dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / pkcs11 / pkcs11_softtoken / common / softDecryptUtil.c
blob97520de6a948d840386421589c8388d9d5face2a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <pthread.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <strings.h>
30 #include <sys/types.h>
31 #include <security/cryptoki.h>
32 #include <modes/modes.h>
33 #include <arcfour.h>
34 #include "softSession.h"
35 #include "softObject.h"
36 #include "softOps.h"
37 #include "softCrypt.h"
38 #include "softRSA.h"
41 * Remove padding bytes.
43 CK_RV
44 soft_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len,
45 CK_ULONG *pulDataLen)
47 CK_RV rv;
49 if ((rv = pkcs7_decode(pData, (size_t *)(&padded_len))) != CKR_OK)
50 return (rv);
52 *pulDataLen = padded_len;
53 return (CKR_OK);
58 * soft_decrypt_init()
60 * Arguments:
61 * session_p: pointer to soft_session_t struct
62 * pMechanism: pointer to CK_MECHANISM struct provided by application
63 * key_p: pointer to key soft_object_t struct
65 * Description:
66 * called by C_DecryptInit(). This function calls the corresponding
67 * decrypt init routine based on the mechanism.
69 * Returns:
70 * CKR_OK: success
71 * CKR_HOST_MEMORY: run out of system memory
72 * CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
73 * CKR_MECHANISM_INVALID: invalid mechanism type
74 * CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
75 * with the specified mechanism
77 CK_RV
78 soft_decrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
79 soft_object_t *key_p)
82 CK_RV rv;
84 switch (pMechanism->mechanism) {
86 case CKM_DES_ECB:
88 if (key_p->key_type != CKK_DES) {
89 return (CKR_KEY_TYPE_INCONSISTENT);
92 goto ecb_common;
94 case CKM_DES3_ECB:
96 if ((key_p->key_type != CKK_DES2) &&
97 (key_p->key_type != CKK_DES3)) {
98 return (CKR_KEY_TYPE_INCONSISTENT);
101 ecb_common:
103 return (soft_des_crypt_init_common(session_p, pMechanism,
104 key_p, B_FALSE));
106 case CKM_DES_CBC:
107 case CKM_DES_CBC_PAD:
109 if (key_p->key_type != CKK_DES) {
110 return (CKR_KEY_TYPE_INCONSISTENT);
113 goto cbc_common;
115 case CKM_DES3_CBC:
116 case CKM_DES3_CBC_PAD:
118 soft_des_ctx_t *soft_des_ctx;
120 if ((key_p->key_type != CKK_DES2) &&
121 (key_p->key_type != CKK_DES3)) {
122 return (CKR_KEY_TYPE_INCONSISTENT);
125 cbc_common:
126 if ((pMechanism->pParameter == NULL) ||
127 (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
128 return (CKR_MECHANISM_PARAM_INVALID);
131 rv = soft_des_crypt_init_common(session_p, pMechanism,
132 key_p, B_FALSE);
134 if (rv != CKR_OK)
135 return (rv);
137 (void) pthread_mutex_lock(&session_p->session_mutex);
139 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
140 /* Save Initialization Vector (IV) in the context. */
141 (void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
142 DES_BLOCK_LEN);
144 /* Allocate a context for DES cipher-block chaining. */
145 soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
146 soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
147 soft_des_ctx->ivec, key_p->key_type);
149 if (soft_des_ctx->des_cbc == NULL) {
150 bzero(soft_des_ctx->key_sched,
151 soft_des_ctx->keysched_len);
152 free(soft_des_ctx->key_sched);
153 free(session_p->decrypt.context);
154 session_p->decrypt.context = NULL;
155 (void) pthread_mutex_unlock(&session_p->session_mutex);
156 return (CKR_HOST_MEMORY);
159 (void) pthread_mutex_unlock(&session_p->session_mutex);
161 return (rv);
163 case CKM_AES_ECB:
165 if (key_p->key_type != CKK_AES) {
166 return (CKR_KEY_TYPE_INCONSISTENT);
169 return (soft_aes_crypt_init_common(session_p, pMechanism,
170 key_p, B_FALSE));
172 case CKM_AES_CBC:
173 case CKM_AES_CBC_PAD:
175 soft_aes_ctx_t *soft_aes_ctx;
177 if (key_p->key_type != CKK_AES) {
178 return (CKR_KEY_TYPE_INCONSISTENT);
181 if ((pMechanism->pParameter == NULL) ||
182 (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
183 return (CKR_MECHANISM_PARAM_INVALID);
186 rv = soft_aes_crypt_init_common(session_p, pMechanism,
187 key_p, B_FALSE);
189 if (rv != CKR_OK)
190 return (rv);
192 (void) pthread_mutex_lock(&session_p->session_mutex);
194 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
196 /* Save Initialization Vector (IV) in the context. */
197 (void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
198 AES_BLOCK_LEN);
200 /* Allocate a context for AES cipher-block chaining. */
201 soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
202 soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
203 soft_aes_ctx->ivec);
205 if (soft_aes_ctx->aes_cbc == NULL) {
206 bzero(soft_aes_ctx->key_sched,
207 soft_aes_ctx->keysched_len);
208 free(soft_aes_ctx->key_sched);
209 free(session_p->decrypt.context);
210 session_p->decrypt.context = NULL;
211 (void) pthread_mutex_unlock(&session_p->session_mutex);
212 return (CKR_HOST_MEMORY);
215 (void) pthread_mutex_unlock(&session_p->session_mutex);
217 return (rv);
219 case CKM_AES_CTR:
221 soft_aes_ctx_t *soft_aes_ctx;
223 if (key_p->key_type != CKK_AES) {
224 return (CKR_KEY_TYPE_INCONSISTENT);
227 if (pMechanism->pParameter == NULL ||
228 pMechanism->ulParameterLen != sizeof (CK_AES_CTR_PARAMS)) {
229 return (CKR_MECHANISM_PARAM_INVALID);
232 rv = soft_aes_crypt_init_common(session_p, pMechanism,
233 key_p, B_FALSE);
235 if (rv != CKR_OK)
236 return (rv);
238 (void) pthread_mutex_lock(&session_p->session_mutex);
240 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
241 soft_aes_ctx->aes_cbc = aes_ctr_ctx_init(
242 soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
243 pMechanism->pParameter);
245 if (soft_aes_ctx->aes_cbc == NULL) {
246 bzero(soft_aes_ctx->key_sched,
247 soft_aes_ctx->keysched_len);
248 free(soft_aes_ctx->key_sched);
249 free(session_p->decrypt.context);
250 session_p->decrypt.context = NULL;
251 rv = CKR_HOST_MEMORY;
254 (void) pthread_mutex_unlock(&session_p->session_mutex);
256 return (rv);
258 case CKM_BLOWFISH_CBC:
260 soft_blowfish_ctx_t *soft_blowfish_ctx;
262 if (key_p->key_type != CKK_BLOWFISH)
263 return (CKR_KEY_TYPE_INCONSISTENT);
265 if ((pMechanism->pParameter == NULL) ||
266 (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
267 return (CKR_MECHANISM_PARAM_INVALID);
269 rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
270 key_p, B_FALSE);
272 if (rv != CKR_OK)
273 return (rv);
275 (void) pthread_mutex_lock(&session_p->session_mutex);
277 soft_blowfish_ctx =
278 (soft_blowfish_ctx_t *)session_p->decrypt.context;
280 /* Save Initialization Vector in the context. */
281 (void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
282 BLOWFISH_BLOCK_LEN);
284 /* Allocate a context for CBC */
285 soft_blowfish_ctx->blowfish_cbc =
286 (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
287 soft_blowfish_ctx->keysched_len,
288 soft_blowfish_ctx->ivec);
290 if (soft_blowfish_ctx->blowfish_cbc == NULL) {
291 bzero(soft_blowfish_ctx->key_sched,
292 soft_blowfish_ctx->keysched_len);
293 free(soft_blowfish_ctx->key_sched);
294 free(session_p->decrypt.context = NULL);
295 (void) pthread_mutex_unlock(&session_p->session_mutex);
296 return (CKR_HOST_MEMORY);
299 (void) pthread_mutex_unlock(&session_p->session_mutex);
300 return (rv);
303 case CKM_RC4:
305 if (key_p->key_type != CKK_RC4) {
306 return (CKR_KEY_TYPE_INCONSISTENT);
309 return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
310 B_FALSE));
312 case CKM_RSA_X_509:
313 case CKM_RSA_PKCS:
315 if (key_p->key_type != CKK_RSA) {
316 return (CKR_KEY_TYPE_INCONSISTENT);
319 return (soft_rsa_crypt_init_common(session_p, pMechanism,
320 key_p, B_FALSE));
322 default:
323 return (CKR_MECHANISM_INVALID);
329 * soft_decrypt_common()
331 * Arguments:
332 * session_p: pointer to soft_session_t struct
333 * pEncrypted: pointer to the encrypted data as input
334 * ulEncryptedLen: length of the input data
335 * pData: pointer to the output data contains plaintext
336 * pulDataLen: pointer to the length of the output data
337 * Update: boolean flag indicates caller is soft_decrypt
338 * or soft_decrypt_update
340 * Description:
341 * This function calls the corresponding decrypt routine based
342 * on the mechanism.
344 * Returns:
345 * see soft_decrypt_common().
347 CK_RV
348 soft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
349 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
350 CK_ULONG_PTR pulDataLen, boolean_t Update)
353 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
355 switch (mechanism) {
357 case CKM_DES_ECB:
358 case CKM_DES_CBC:
359 case CKM_DES3_ECB:
360 case CKM_DES3_CBC:
362 if (ulEncryptedLen == 0) {
363 *pulDataLen = 0;
364 return (CKR_OK);
366 /* FALLTHROUGH */
368 case CKM_DES_CBC_PAD:
369 case CKM_DES3_CBC_PAD:
371 return (soft_des_decrypt_common(session_p, pEncrypted,
372 ulEncryptedLen, pData, pulDataLen, Update));
374 case CKM_AES_ECB:
375 case CKM_AES_CBC:
376 case CKM_AES_CTR:
378 if (ulEncryptedLen == 0) {
379 *pulDataLen = 0;
380 return (CKR_OK);
382 /* FALLTHROUGH */
384 case CKM_AES_CBC_PAD:
386 return (soft_aes_decrypt_common(session_p, pEncrypted,
387 ulEncryptedLen, pData, pulDataLen, Update));
389 case CKM_BLOWFISH_CBC:
391 if (ulEncryptedLen == 0) {
392 *pulDataLen = 0;
393 return (CKR_OK);
396 return (soft_blowfish_decrypt_common(session_p, pEncrypted,
397 ulEncryptedLen, pData, pulDataLen, Update));
399 case CKM_RC4:
401 if (ulEncryptedLen == 0) {
402 *pulDataLen = 0;
403 return (CKR_OK);
407 return (soft_arcfour_crypt(&(session_p->decrypt), pEncrypted,
408 ulEncryptedLen, pData, pulDataLen));
410 case CKM_RSA_X_509:
411 case CKM_RSA_PKCS:
413 return (soft_rsa_decrypt_common(session_p, pEncrypted,
414 ulEncryptedLen, pData, pulDataLen, mechanism));
416 default:
417 return (CKR_MECHANISM_INVALID);
424 * soft_decrypt()
426 * Arguments:
427 * session_p: pointer to soft_session_t struct
428 * pEncryptedData: pointer to the encrypted data as input
429 * ulEncryptedDataLen: length of the input data
430 * pData: pointer to the output data contains plaintext
431 * pulDataLen: pointer to the length of the output data
433 * Description:
434 * called by C_Decrypt(). This function calls the soft_decrypt_common
435 * routine.
437 * Returns:
438 * see soft_decrypt_common().
440 CK_RV
441 soft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
442 CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
443 CK_ULONG_PTR pulDataLen)
446 return (soft_decrypt_common(session_p, pEncryptedData,
447 ulEncryptedDataLen, pData, pulDataLen, B_FALSE));
452 * soft_decrypt_update()
454 * Arguments:
455 * session_p: pointer to soft_session_t struct
456 * pEncryptedPart: pointer to the encrypted data as input
457 * ulEncryptedPartLen: length of the input data
458 * pPart: pointer to the output data contains plaintext
459 * pulPartLen: pointer to the length of the output data
461 * Description:
462 * called by C_DecryptUpdate(). This function calls the
463 * soft_decrypt_common routine (with update flag on).
465 * Returns:
466 * see soft_decrypt_common().
468 CK_RV
469 soft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart,
470 CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
471 CK_ULONG_PTR pulPartLen)
473 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
475 switch (mechanism) {
477 case CKM_DES_ECB:
478 case CKM_DES_CBC:
479 case CKM_DES_CBC_PAD:
480 case CKM_DES3_ECB:
481 case CKM_DES3_CBC:
482 case CKM_DES3_CBC_PAD:
483 case CKM_AES_ECB:
484 case CKM_AES_CBC:
485 case CKM_AES_CBC_PAD:
486 case CKM_AES_CTR:
487 case CKM_BLOWFISH_CBC:
488 case CKM_RC4:
490 return (soft_decrypt_common(session_p, pEncryptedPart,
491 ulEncryptedPartLen, pPart, pulPartLen, B_TRUE));
493 default:
494 /* PKCS11: The mechanism only supports single-part operation. */
495 return (CKR_MECHANISM_INVALID);
502 * soft_decrypt_final()
504 * Arguments:
505 * session_p: pointer to soft_session_t struct
506 * pLastPart: pointer to the last recovered data part
507 * pulLastPartLen: pointer to the length of the last recovered data part
509 * Description:
510 * called by C_DecryptFinal().
512 * Returns:
513 * CKR_OK: success
514 * CKR_FUNCTION_FAILED: decrypt final function failed
515 * CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
517 CK_RV
518 soft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
519 CK_ULONG_PTR pulLastPartLen)
522 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
523 CK_ULONG out_len;
524 CK_RV rv = CKR_OK;
525 int rc;
527 (void) pthread_mutex_lock(&session_p->session_mutex);
529 if (session_p->decrypt.context == NULL) {
530 rv = CKR_OPERATION_NOT_INITIALIZED;
531 *pulLastPartLen = 0;
532 goto clean2;
534 switch (mechanism) {
536 case CKM_DES_CBC_PAD:
537 case CKM_DES3_CBC_PAD:
540 soft_des_ctx_t *soft_des_ctx;
542 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
545 * We should have only one block of data left in the
546 * remaining buffer.
548 if (soft_des_ctx->remain_len != DES_BLOCK_LEN) {
549 *pulLastPartLen = 0;
550 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
551 /* Cleanup memory space. */
552 free(soft_des_ctx->des_cbc);
553 bzero(soft_des_ctx->key_sched,
554 soft_des_ctx->keysched_len);
555 free(soft_des_ctx->key_sched);
557 goto clean1;
560 out_len = DES_BLOCK_LEN;
563 * If application asks for the length of the output buffer
564 * to hold the plaintext?
566 if (pLastPart == NULL) {
567 *pulLastPartLen = out_len;
568 rv = CKR_OK;
569 goto clean2;
570 } else {
571 crypto_data_t out;
573 /* Copy remaining data to the output buffer. */
574 (void) memcpy(pLastPart, soft_des_ctx->data,
575 DES_BLOCK_LEN);
577 out.cd_format = CRYPTO_DATA_RAW;
578 out.cd_offset = 0;
579 out.cd_length = DES_BLOCK_LEN;
580 out.cd_raw.iov_base = (char *)pLastPart;
581 out.cd_raw.iov_len = DES_BLOCK_LEN;
583 /* Decrypt final block of data. */
584 rc = des_decrypt_contiguous_blocks(
585 (des_ctx_t *)soft_des_ctx->des_cbc,
586 (char *)pLastPart, DES_BLOCK_LEN, &out);
588 if (rc == 0) {
590 * Remove padding bytes after decryption of
591 * ciphertext block to produce the original
592 * plaintext.
594 rv = soft_remove_pkcs7_padding(pLastPart,
595 DES_BLOCK_LEN, &out_len);
596 if (rv != CKR_OK)
597 *pulLastPartLen = 0;
598 else
599 *pulLastPartLen = out_len;
600 } else {
601 *pulLastPartLen = 0;
602 rv = CKR_FUNCTION_FAILED;
605 /* Cleanup memory space. */
606 free(soft_des_ctx->des_cbc);
607 bzero(soft_des_ctx->key_sched,
608 soft_des_ctx->keysched_len);
609 free(soft_des_ctx->key_sched);
613 break;
616 case CKM_DES_CBC:
617 case CKM_DES_ECB:
618 case CKM_DES3_CBC:
619 case CKM_DES3_ECB:
622 soft_des_ctx_t *soft_des_ctx;
624 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
626 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
627 * so when the final is called, the remaining buffer
628 * should not contain any more data.
630 *pulLastPartLen = 0;
631 if (soft_des_ctx->remain_len != 0) {
632 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
633 } else {
634 if (pLastPart == NULL)
635 goto clean2;
638 /* Cleanup memory space. */
639 free(soft_des_ctx->des_cbc);
640 bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
641 free(soft_des_ctx->key_sched);
643 break;
646 case CKM_AES_CBC_PAD:
649 soft_aes_ctx_t *soft_aes_ctx;
651 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
654 * We should have only one block of data left in the
655 * remaining buffer.
657 if (soft_aes_ctx->remain_len != AES_BLOCK_LEN) {
658 *pulLastPartLen = 0;
659 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
660 /* Cleanup memory space. */
661 free(soft_aes_ctx->aes_cbc);
662 bzero(soft_aes_ctx->key_sched,
663 soft_aes_ctx->keysched_len);
664 free(soft_aes_ctx->key_sched);
666 goto clean1;
669 out_len = AES_BLOCK_LEN;
672 * If application asks for the length of the output buffer
673 * to hold the plaintext?
675 if (pLastPart == NULL) {
676 *pulLastPartLen = out_len;
677 rv = CKR_OK;
678 goto clean2;
679 } else {
680 crypto_data_t out;
682 /* Copy remaining data to the output buffer. */
683 (void) memcpy(pLastPart, soft_aes_ctx->data,
684 AES_BLOCK_LEN);
686 out.cd_format = CRYPTO_DATA_RAW;
687 out.cd_offset = 0;
688 out.cd_length = AES_BLOCK_LEN;
689 out.cd_raw.iov_base = (char *)pLastPart;
690 out.cd_raw.iov_len = AES_BLOCK_LEN;
692 /* Decrypt final block of data. */
693 rc = aes_decrypt_contiguous_blocks(
694 (aes_ctx_t *)soft_aes_ctx->aes_cbc,
695 (char *)pLastPart, AES_BLOCK_LEN, &out);
697 if (rc == 0) {
699 * Remove padding bytes after decryption of
700 * ciphertext block to produce the original
701 * plaintext.
703 rv = soft_remove_pkcs7_padding(pLastPart,
704 AES_BLOCK_LEN, &out_len);
705 if (rv != CKR_OK)
706 *pulLastPartLen = 0;
707 else
708 *pulLastPartLen = out_len;
709 } else {
710 *pulLastPartLen = 0;
711 rv = CKR_FUNCTION_FAILED;
714 /* Cleanup memory space. */
715 free(soft_aes_ctx->aes_cbc);
716 bzero(soft_aes_ctx->key_sched,
717 soft_aes_ctx->keysched_len);
718 free(soft_aes_ctx->key_sched);
722 break;
725 case CKM_AES_CBC:
726 case CKM_AES_ECB:
728 soft_aes_ctx_t *soft_aes_ctx;
730 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
732 * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
733 * so when the final is called, the remaining buffer
734 * should not contain any more data.
736 *pulLastPartLen = 0;
737 if (soft_aes_ctx->remain_len != 0) {
738 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
739 } else {
740 if (pLastPart == NULL)
741 goto clean2;
744 /* Cleanup memory space. */
745 free(soft_aes_ctx->aes_cbc);
746 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
747 free(soft_aes_ctx->key_sched);
749 break;
751 case CKM_AES_CTR:
753 crypto_data_t out;
754 soft_aes_ctx_t *soft_aes_ctx;
755 ctr_ctx_t *ctr_ctx;
756 size_t len;
758 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
759 ctr_ctx = soft_aes_ctx->aes_cbc;
760 len = ctr_ctx->ctr_remainder_len;
761 if (pLastPart == NULL) {
762 *pulLastPartLen = len;
763 goto clean1;
765 if (len > 0) {
766 out.cd_format = CRYPTO_DATA_RAW;
767 out.cd_offset = 0;
768 out.cd_length = len;
769 out.cd_raw.iov_base = (char *)pLastPart;
770 out.cd_raw.iov_len = len;
772 rv = ctr_mode_final(ctr_ctx, &out, aes_encrypt_block);
773 if (rv == CRYPTO_DATA_LEN_RANGE)
774 rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
776 if (rv == CRYPTO_BUFFER_TOO_SMALL) {
777 *pulLastPartLen = len;
778 goto clean1;
781 /* Cleanup memory space. */
782 free(ctr_ctx);
783 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
784 free(soft_aes_ctx->key_sched);
786 break;
788 case CKM_BLOWFISH_CBC:
790 soft_blowfish_ctx_t *soft_blowfish_ctx;
792 soft_blowfish_ctx =
793 (soft_blowfish_ctx_t *)session_p->decrypt.context;
795 *pulLastPartLen = 0;
796 if (soft_blowfish_ctx->remain_len != 0)
797 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
798 else {
799 if (pLastPart == NULL)
800 goto clean2;
803 free(soft_blowfish_ctx->blowfish_cbc);
804 bzero(soft_blowfish_ctx->key_sched,
805 soft_blowfish_ctx->keysched_len);
806 free(soft_blowfish_ctx->key_sched);
808 break;
811 case CKM_RC4:
813 ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context;
814 bzero(key, sizeof (*key));
815 *pulLastPartLen = 0;
816 break;
819 default:
820 /* PKCS11: The mechanism only supports single-part operation. */
821 rv = CKR_MECHANISM_INVALID;
822 break;
825 clean1:
826 free(session_p->decrypt.context);
827 session_p->decrypt.context = NULL;
829 clean2:
830 (void) pthread_mutex_unlock(&session_p->session_mutex);
832 return (rv);