9642 PKCS#11 softtoken should use explicit_bzero
[unleashed.git] / usr / src / lib / pkcs11 / pkcs11_softtoken / common / softDecryptUtil.c
blob27b8edf8944e69c8bb7850db4df9acac98f5684e
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.
24 * Copyright (c) 2018, Joyent, Inc.
27 #include <pthread.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <sys/types.h>
32 #include <security/cryptoki.h>
33 #include <modes/modes.h>
34 #include <arcfour.h>
35 #include "softSession.h"
36 #include "softObject.h"
37 #include "softOps.h"
38 #include "softCrypt.h"
39 #include "softRSA.h"
42 * Remove padding bytes.
44 CK_RV
45 soft_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len,
46 CK_ULONG *pulDataLen)
48 CK_RV rv;
50 #ifdef __sparcv9
51 if ((rv = pkcs7_decode(pData, (&padded_len))) != CKR_OK)
52 #else /* !__sparcv9 */
53 if ((rv = pkcs7_decode(pData, (size_t *)(&padded_len))) != CKR_OK)
54 #endif /* __sparcv9 */
55 return (rv);
57 *pulDataLen = padded_len;
58 return (CKR_OK);
63 * soft_decrypt_init()
65 * Arguments:
66 * session_p: pointer to soft_session_t struct
67 * pMechanism: pointer to CK_MECHANISM struct provided by application
68 * key_p: pointer to key soft_object_t struct
70 * Description:
71 * called by C_DecryptInit(). This function calls the corresponding
72 * decrypt init routine based on the mechanism.
74 * Returns:
75 * CKR_OK: success
76 * CKR_HOST_MEMORY: run out of system memory
77 * CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
78 * CKR_MECHANISM_INVALID: invalid mechanism type
79 * CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
80 * with the specified mechanism
82 CK_RV
83 soft_decrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
84 soft_object_t *key_p)
87 CK_RV rv;
89 switch (pMechanism->mechanism) {
91 case CKM_DES_ECB:
93 if (key_p->key_type != CKK_DES) {
94 return (CKR_KEY_TYPE_INCONSISTENT);
97 goto ecb_common;
99 case CKM_DES3_ECB:
101 if ((key_p->key_type != CKK_DES2) &&
102 (key_p->key_type != CKK_DES3)) {
103 return (CKR_KEY_TYPE_INCONSISTENT);
106 ecb_common:
108 return (soft_des_crypt_init_common(session_p, pMechanism,
109 key_p, B_FALSE));
111 case CKM_DES_CBC:
112 case CKM_DES_CBC_PAD:
114 if (key_p->key_type != CKK_DES) {
115 return (CKR_KEY_TYPE_INCONSISTENT);
118 goto cbc_common;
120 case CKM_DES3_CBC:
121 case CKM_DES3_CBC_PAD:
123 soft_des_ctx_t *soft_des_ctx;
125 if ((key_p->key_type != CKK_DES2) &&
126 (key_p->key_type != CKK_DES3)) {
127 return (CKR_KEY_TYPE_INCONSISTENT);
130 cbc_common:
131 if ((pMechanism->pParameter == NULL) ||
132 (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
133 return (CKR_MECHANISM_PARAM_INVALID);
136 rv = soft_des_crypt_init_common(session_p, pMechanism,
137 key_p, B_FALSE);
139 if (rv != CKR_OK)
140 return (rv);
142 (void) pthread_mutex_lock(&session_p->session_mutex);
144 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
145 /* Save Initialization Vector (IV) in the context. */
146 (void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
147 DES_BLOCK_LEN);
149 /* Allocate a context for DES cipher-block chaining. */
150 soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
151 soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
152 soft_des_ctx->ivec, key_p->key_type);
154 if (soft_des_ctx->des_cbc == NULL) {
155 freezero(soft_des_ctx->key_sched,
156 soft_des_ctx->keysched_len);
157 freezero(session_p->decrypt.context,
158 sizeof (soft_des_ctx_t));
159 session_p->decrypt.context = NULL;
160 (void) pthread_mutex_unlock(&session_p->session_mutex);
161 return (CKR_HOST_MEMORY);
164 (void) pthread_mutex_unlock(&session_p->session_mutex);
166 return (rv);
168 case CKM_AES_ECB:
170 if (key_p->key_type != CKK_AES) {
171 return (CKR_KEY_TYPE_INCONSISTENT);
174 return (soft_aes_crypt_init_common(session_p, pMechanism,
175 key_p, B_FALSE));
177 case CKM_AES_CBC:
178 case CKM_AES_CBC_PAD:
180 soft_aes_ctx_t *soft_aes_ctx;
182 if (key_p->key_type != CKK_AES) {
183 return (CKR_KEY_TYPE_INCONSISTENT);
186 if ((pMechanism->pParameter == NULL) ||
187 (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
188 return (CKR_MECHANISM_PARAM_INVALID);
191 rv = soft_aes_crypt_init_common(session_p, pMechanism,
192 key_p, B_FALSE);
194 if (rv != CKR_OK)
195 return (rv);
197 (void) pthread_mutex_lock(&session_p->session_mutex);
199 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
201 /* Save Initialization Vector (IV) in the context. */
202 (void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
203 AES_BLOCK_LEN);
205 /* Allocate a context for AES cipher-block chaining. */
206 soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
207 soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
208 soft_aes_ctx->ivec);
210 if (soft_aes_ctx->aes_cbc == NULL) {
211 freezero(soft_aes_ctx->key_sched,
212 soft_aes_ctx->keysched_len);
213 freezero(session_p->decrypt.context,
214 sizeof (soft_aes_ctx_t));
215 session_p->decrypt.context = NULL;
216 (void) pthread_mutex_unlock(&session_p->session_mutex);
217 return (CKR_HOST_MEMORY);
220 (void) pthread_mutex_unlock(&session_p->session_mutex);
222 return (rv);
224 case CKM_AES_CTR:
226 soft_aes_ctx_t *soft_aes_ctx;
228 if (key_p->key_type != CKK_AES) {
229 return (CKR_KEY_TYPE_INCONSISTENT);
232 if (pMechanism->pParameter == NULL ||
233 pMechanism->ulParameterLen != sizeof (CK_AES_CTR_PARAMS)) {
234 return (CKR_MECHANISM_PARAM_INVALID);
237 rv = soft_aes_crypt_init_common(session_p, pMechanism,
238 key_p, B_FALSE);
240 if (rv != CKR_OK)
241 return (rv);
243 (void) pthread_mutex_lock(&session_p->session_mutex);
245 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
246 soft_aes_ctx->aes_cbc = aes_ctr_ctx_init(
247 soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
248 pMechanism->pParameter);
250 if (soft_aes_ctx->aes_cbc == NULL) {
251 freezero(soft_aes_ctx->key_sched,
252 soft_aes_ctx->keysched_len);
253 freezero(session_p->decrypt.context,
254 sizeof (soft_aes_ctx_t));
255 session_p->decrypt.context = NULL;
256 rv = CKR_HOST_MEMORY;
259 (void) pthread_mutex_unlock(&session_p->session_mutex);
261 return (rv);
263 case CKM_BLOWFISH_CBC:
265 soft_blowfish_ctx_t *soft_blowfish_ctx;
267 if (key_p->key_type != CKK_BLOWFISH)
268 return (CKR_KEY_TYPE_INCONSISTENT);
270 if ((pMechanism->pParameter == NULL) ||
271 (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
272 return (CKR_MECHANISM_PARAM_INVALID);
274 rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
275 key_p, B_FALSE);
277 if (rv != CKR_OK)
278 return (rv);
280 (void) pthread_mutex_lock(&session_p->session_mutex);
282 soft_blowfish_ctx =
283 (soft_blowfish_ctx_t *)session_p->decrypt.context;
285 /* Save Initialization Vector in the context. */
286 (void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
287 BLOWFISH_BLOCK_LEN);
289 /* Allocate a context for CBC */
290 soft_blowfish_ctx->blowfish_cbc =
291 (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
292 soft_blowfish_ctx->keysched_len,
293 soft_blowfish_ctx->ivec);
295 if (soft_blowfish_ctx->blowfish_cbc == NULL) {
296 freezero(soft_blowfish_ctx->key_sched,
297 soft_blowfish_ctx->keysched_len);
298 freezero(session_p->decrypt.context,
299 sizeof (soft_blowfish_ctx_t));
300 session_p->decrypt.context = NULL;
301 (void) pthread_mutex_unlock(&session_p->session_mutex);
302 return (CKR_HOST_MEMORY);
305 (void) pthread_mutex_unlock(&session_p->session_mutex);
306 return (rv);
309 case CKM_RC4:
311 if (key_p->key_type != CKK_RC4) {
312 return (CKR_KEY_TYPE_INCONSISTENT);
315 return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
316 B_FALSE));
318 case CKM_RSA_X_509:
319 case CKM_RSA_PKCS:
321 if (key_p->key_type != CKK_RSA) {
322 return (CKR_KEY_TYPE_INCONSISTENT);
325 return (soft_rsa_crypt_init_common(session_p, pMechanism,
326 key_p, B_FALSE));
328 default:
329 return (CKR_MECHANISM_INVALID);
335 * soft_decrypt_common()
337 * Arguments:
338 * session_p: pointer to soft_session_t struct
339 * pEncrypted: pointer to the encrypted data as input
340 * ulEncryptedLen: length of the input data
341 * pData: pointer to the output data contains plaintext
342 * pulDataLen: pointer to the length of the output data
343 * Update: boolean flag indicates caller is soft_decrypt
344 * or soft_decrypt_update
346 * Description:
347 * This function calls the corresponding decrypt routine based
348 * on the mechanism.
350 * Returns:
351 * see soft_decrypt_common().
353 CK_RV
354 soft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
355 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
356 CK_ULONG_PTR pulDataLen, boolean_t Update)
359 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
361 switch (mechanism) {
363 case CKM_DES_ECB:
364 case CKM_DES_CBC:
365 case CKM_DES3_ECB:
366 case CKM_DES3_CBC:
368 if (ulEncryptedLen == 0) {
369 *pulDataLen = 0;
370 return (CKR_OK);
372 /* FALLTHROUGH */
374 case CKM_DES_CBC_PAD:
375 case CKM_DES3_CBC_PAD:
377 return (soft_des_decrypt_common(session_p, pEncrypted,
378 ulEncryptedLen, pData, pulDataLen, Update));
380 case CKM_AES_ECB:
381 case CKM_AES_CBC:
382 case CKM_AES_CTR:
384 if (ulEncryptedLen == 0) {
385 *pulDataLen = 0;
386 return (CKR_OK);
388 /* FALLTHROUGH */
390 case CKM_AES_CBC_PAD:
392 return (soft_aes_decrypt_common(session_p, pEncrypted,
393 ulEncryptedLen, pData, pulDataLen, Update));
395 case CKM_BLOWFISH_CBC:
397 if (ulEncryptedLen == 0) {
398 *pulDataLen = 0;
399 return (CKR_OK);
402 return (soft_blowfish_decrypt_common(session_p, pEncrypted,
403 ulEncryptedLen, pData, pulDataLen, Update));
405 case CKM_RC4:
407 if (ulEncryptedLen == 0) {
408 *pulDataLen = 0;
409 return (CKR_OK);
413 return (soft_arcfour_crypt(&(session_p->decrypt), pEncrypted,
414 ulEncryptedLen, pData, pulDataLen));
416 case CKM_RSA_X_509:
417 case CKM_RSA_PKCS:
419 return (soft_rsa_decrypt_common(session_p, pEncrypted,
420 ulEncryptedLen, pData, pulDataLen, mechanism));
422 default:
423 return (CKR_MECHANISM_INVALID);
430 * soft_decrypt()
432 * Arguments:
433 * session_p: pointer to soft_session_t struct
434 * pEncryptedData: pointer to the encrypted data as input
435 * ulEncryptedDataLen: length of the input data
436 * pData: pointer to the output data contains plaintext
437 * pulDataLen: pointer to the length of the output data
439 * Description:
440 * called by C_Decrypt(). This function calls the soft_decrypt_common
441 * routine.
443 * Returns:
444 * see soft_decrypt_common().
446 CK_RV
447 soft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
448 CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
449 CK_ULONG_PTR pulDataLen)
452 return (soft_decrypt_common(session_p, pEncryptedData,
453 ulEncryptedDataLen, pData, pulDataLen, B_FALSE));
458 * soft_decrypt_update()
460 * Arguments:
461 * session_p: pointer to soft_session_t struct
462 * pEncryptedPart: pointer to the encrypted data as input
463 * ulEncryptedPartLen: length of the input data
464 * pPart: pointer to the output data contains plaintext
465 * pulPartLen: pointer to the length of the output data
467 * Description:
468 * called by C_DecryptUpdate(). This function calls the
469 * soft_decrypt_common routine (with update flag on).
471 * Returns:
472 * see soft_decrypt_common().
474 CK_RV
475 soft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart,
476 CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
478 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
480 switch (mechanism) {
482 case CKM_DES_ECB:
483 case CKM_DES_CBC:
484 case CKM_DES_CBC_PAD:
485 case CKM_DES3_ECB:
486 case CKM_DES3_CBC:
487 case CKM_DES3_CBC_PAD:
488 case CKM_AES_ECB:
489 case CKM_AES_CBC:
490 case CKM_AES_CBC_PAD:
491 case CKM_AES_CTR:
492 case CKM_BLOWFISH_CBC:
493 case CKM_RC4:
495 return (soft_decrypt_common(session_p, pEncryptedPart,
496 ulEncryptedPartLen, pPart, pulPartLen, B_TRUE));
498 default:
499 /* PKCS11: The mechanism only supports single-part operation. */
500 return (CKR_MECHANISM_INVALID);
507 * soft_decrypt_final()
509 * Arguments:
510 * session_p: pointer to soft_session_t struct
511 * pLastPart: pointer to the last recovered data part
512 * pulLastPartLen: pointer to the length of the last recovered data part
514 * Description:
515 * called by C_DecryptFinal().
517 * Returns:
518 * CKR_OK: success
519 * CKR_FUNCTION_FAILED: decrypt final function failed
520 * CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
522 CK_RV
523 soft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
524 CK_ULONG_PTR pulLastPartLen)
527 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
528 CK_ULONG out_len;
529 CK_RV rv = CKR_OK;
530 int rc;
532 (void) pthread_mutex_lock(&session_p->session_mutex);
534 if (session_p->decrypt.context == NULL) {
535 rv = CKR_OPERATION_NOT_INITIALIZED;
536 *pulLastPartLen = 0;
537 goto clean2;
539 switch (mechanism) {
541 case CKM_DES_CBC_PAD:
542 case CKM_DES3_CBC_PAD:
545 soft_des_ctx_t *soft_des_ctx;
547 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
550 * We should have only one block of data left in the
551 * remaining buffer.
553 if (soft_des_ctx->remain_len != DES_BLOCK_LEN) {
554 *pulLastPartLen = 0;
555 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
556 /* Cleanup memory space. */
557 free(soft_des_ctx->des_cbc);
558 freezero(soft_des_ctx->key_sched,
559 soft_des_ctx->keysched_len);
561 goto clean1;
564 out_len = DES_BLOCK_LEN;
567 * If application asks for the length of the output buffer
568 * to hold the plaintext?
570 if (pLastPart == NULL) {
571 *pulLastPartLen = out_len;
572 rv = CKR_OK;
573 goto clean2;
574 } else {
575 crypto_data_t out;
577 /* Copy remaining data to the output buffer. */
578 (void) memcpy(pLastPart, soft_des_ctx->data,
579 DES_BLOCK_LEN);
581 out.cd_format = CRYPTO_DATA_RAW;
582 out.cd_offset = 0;
583 out.cd_length = DES_BLOCK_LEN;
584 out.cd_raw.iov_base = (char *)pLastPart;
585 out.cd_raw.iov_len = DES_BLOCK_LEN;
587 /* Decrypt final block of data. */
588 rc = des_decrypt_contiguous_blocks(
589 (des_ctx_t *)soft_des_ctx->des_cbc,
590 (char *)pLastPart, DES_BLOCK_LEN, &out);
592 if (rc == 0) {
594 * Remove padding bytes after decryption of
595 * ciphertext block to produce the original
596 * plaintext.
598 rv = soft_remove_pkcs7_padding(pLastPart,
599 DES_BLOCK_LEN, &out_len);
600 if (rv != CKR_OK)
601 *pulLastPartLen = 0;
602 else
603 *pulLastPartLen = out_len;
604 } else {
605 *pulLastPartLen = 0;
606 rv = CKR_FUNCTION_FAILED;
609 /* Cleanup memory space. */
610 free(soft_des_ctx->des_cbc);
611 freezero(soft_des_ctx->key_sched,
612 soft_des_ctx->keysched_len);
616 break;
619 case CKM_DES_CBC:
620 case CKM_DES_ECB:
621 case CKM_DES3_CBC:
622 case CKM_DES3_ECB:
625 soft_des_ctx_t *soft_des_ctx;
627 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
629 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
630 * so when the final is called, the remaining buffer
631 * should not contain any more data.
633 *pulLastPartLen = 0;
634 if (soft_des_ctx->remain_len != 0) {
635 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
636 } else {
637 if (pLastPart == NULL)
638 goto clean2;
641 /* Cleanup memory space. */
642 free(soft_des_ctx->des_cbc);
643 freezero(soft_des_ctx->key_sched,
644 soft_des_ctx->keysched_len);
646 break;
649 case CKM_AES_CBC_PAD:
652 soft_aes_ctx_t *soft_aes_ctx;
654 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
657 * We should have only one block of data left in the
658 * remaining buffer.
660 if (soft_aes_ctx->remain_len != AES_BLOCK_LEN) {
661 *pulLastPartLen = 0;
662 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
663 /* Cleanup memory space. */
664 free(soft_aes_ctx->aes_cbc);
665 freezero(soft_aes_ctx->key_sched,
666 soft_aes_ctx->keysched_len);
668 goto clean1;
671 out_len = AES_BLOCK_LEN;
674 * If application asks for the length of the output buffer
675 * to hold the plaintext?
677 if (pLastPart == NULL) {
678 *pulLastPartLen = out_len;
679 rv = CKR_OK;
680 goto clean2;
681 } else {
682 crypto_data_t out;
684 /* Copy remaining data to the output buffer. */
685 (void) memcpy(pLastPart, soft_aes_ctx->data,
686 AES_BLOCK_LEN);
688 out.cd_format = CRYPTO_DATA_RAW;
689 out.cd_offset = 0;
690 out.cd_length = AES_BLOCK_LEN;
691 out.cd_raw.iov_base = (char *)pLastPart;
692 out.cd_raw.iov_len = AES_BLOCK_LEN;
694 /* Decrypt final block of data. */
695 rc = aes_decrypt_contiguous_blocks(
696 (aes_ctx_t *)soft_aes_ctx->aes_cbc,
697 (char *)pLastPart, AES_BLOCK_LEN, &out);
699 if (rc == 0) {
701 * Remove padding bytes after decryption of
702 * ciphertext block to produce the original
703 * plaintext.
705 rv = soft_remove_pkcs7_padding(pLastPart,
706 AES_BLOCK_LEN, &out_len);
707 if (rv != CKR_OK)
708 *pulLastPartLen = 0;
709 else
710 *pulLastPartLen = out_len;
711 } else {
712 *pulLastPartLen = 0;
713 rv = CKR_FUNCTION_FAILED;
716 /* Cleanup memory space. */
717 free(soft_aes_ctx->aes_cbc);
718 freezero(soft_aes_ctx->key_sched,
719 soft_aes_ctx->keysched_len);
723 break;
726 case CKM_AES_CBC:
727 case CKM_AES_ECB:
729 soft_aes_ctx_t *soft_aes_ctx;
731 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
733 * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
734 * so when the final is called, the remaining buffer
735 * should not contain any more data.
737 *pulLastPartLen = 0;
738 if (soft_aes_ctx->remain_len != 0) {
739 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
740 } else {
741 if (pLastPart == NULL)
742 goto clean2;
745 /* Cleanup memory space. */
746 free(soft_aes_ctx->aes_cbc);
747 freezero(soft_aes_ctx->key_sched,
748 soft_aes_ctx->keysched_len);
750 break;
752 case CKM_AES_CTR:
754 crypto_data_t out;
755 soft_aes_ctx_t *soft_aes_ctx;
756 ctr_ctx_t *ctr_ctx;
757 size_t len;
759 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
760 ctr_ctx = soft_aes_ctx->aes_cbc;
761 len = ctr_ctx->ctr_remainder_len;
762 if (pLastPart == NULL) {
763 *pulLastPartLen = len;
764 goto clean1;
766 if (len > 0) {
767 out.cd_format = CRYPTO_DATA_RAW;
768 out.cd_offset = 0;
769 out.cd_length = len;
770 out.cd_raw.iov_base = (char *)pLastPart;
771 out.cd_raw.iov_len = len;
773 rv = ctr_mode_final(ctr_ctx, &out, aes_encrypt_block);
774 if (rv == CRYPTO_DATA_LEN_RANGE)
775 rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
777 if (rv == CRYPTO_BUFFER_TOO_SMALL) {
778 *pulLastPartLen = len;
779 goto clean1;
782 /* Cleanup memory space. */
783 free(ctr_ctx);
784 freezero(soft_aes_ctx->key_sched,
785 soft_aes_ctx->keysched_len);
787 break;
789 case CKM_BLOWFISH_CBC:
791 soft_blowfish_ctx_t *soft_blowfish_ctx;
793 soft_blowfish_ctx =
794 (soft_blowfish_ctx_t *)session_p->decrypt.context;
796 *pulLastPartLen = 0;
797 if (soft_blowfish_ctx->remain_len != 0)
798 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
799 else {
800 if (pLastPart == NULL)
801 goto clean2;
804 free(soft_blowfish_ctx->blowfish_cbc);
805 freezero(soft_blowfish_ctx->key_sched,
806 soft_blowfish_ctx->keysched_len);
808 break;
811 case CKM_RC4:
813 ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context;
814 explicit_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);