xref: /titanic_50/usr/src/lib/pkcs11/pkcs11_softtoken/common/softDecryptUtil.c (revision 80868c5387b92f32fe0e8ea709e36cb535287e03)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <pthread.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <sys/types.h>
34 #include <security/cryptoki.h>
35 #include <des_cbc_crypt.h>
36 #include <aes_cbc_crypt.h>
37 #include <blowfish_cbc_crypt.h>
38 #include <arcfour.h>
39 #include "softSession.h"
40 #include "softObject.h"
41 #include "softOps.h"
42 #include "softCrypt.h"
43 #include "softRSA.h"
44 
45 
46 /*
47  * Remove padding bytes.
48  */
49 CK_RV
50 soft_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len,
51     CK_ULONG *pulDataLen, int block_size)
52 {
53 
54 	CK_BYTE  pad_value;
55 
56 	pad_value = pData[padded_len - 1];
57 
58 
59 	/* Make sure there is a valid padding value. */
60 	if ((pad_value == 0) || (pad_value > block_size))
61 	    return (CKR_ENCRYPTED_DATA_INVALID);
62 
63 	*pulDataLen = padded_len - pad_value;
64 	return (CKR_OK);
65 }
66 
67 
68 /*
69  * soft_decrypt_init()
70  *
71  * Arguments:
72  *	session_p:	pointer to soft_session_t struct
73  *	pMechanism:	pointer to CK_MECHANISM struct provided by application
74  *	key_p:		pointer to key soft_object_t struct
75  *
76  * Description:
77  *	called by C_DecryptInit(). This function calls the corresponding
78  *	decrypt init routine based on the mechanism.
79  *
80  * Returns:
81  *	CKR_OK: success
82  *	CKR_HOST_MEMORY: run out of system memory
83  *	CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
84  *	CKR_MECHANISM_INVALID: invalid mechanism type
85  *	CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
86  *				   with the specified mechanism
87  */
88 CK_RV
89 soft_decrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
90     soft_object_t *key_p)
91 {
92 
93 	CK_RV rv;
94 
95 	switch (pMechanism->mechanism) {
96 
97 	case CKM_DES_ECB:
98 
99 		if (key_p->key_type != CKK_DES) {
100 			return (CKR_KEY_TYPE_INCONSISTENT);
101 		}
102 
103 		goto ecb_common;
104 
105 	case CKM_DES3_ECB:
106 
107 		if ((key_p->key_type != CKK_DES2) &&
108 		    (key_p->key_type != CKK_DES3)) {
109 			return (CKR_KEY_TYPE_INCONSISTENT);
110 		}
111 
112 ecb_common:
113 
114 		return (soft_des_crypt_init_common(session_p, pMechanism,
115 		    key_p, B_FALSE));
116 
117 	case CKM_DES_CBC:
118 	case CKM_DES_CBC_PAD:
119 
120 		if (key_p->key_type != CKK_DES) {
121 			return (CKR_KEY_TYPE_INCONSISTENT);
122 		}
123 
124 		goto cbc_common;
125 
126 	case CKM_DES3_CBC:
127 	case CKM_DES3_CBC_PAD:
128 	{
129 		soft_des_ctx_t *soft_des_ctx;
130 
131 		if ((key_p->key_type != CKK_DES2) &&
132 		    (key_p->key_type != CKK_DES3)) {
133 			return (CKR_KEY_TYPE_INCONSISTENT);
134 		}
135 
136 cbc_common:
137 		if ((pMechanism->pParameter == NULL) ||
138 		    (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
139 			return (CKR_MECHANISM_PARAM_INVALID);
140 		}
141 
142 		rv = soft_des_crypt_init_common(session_p, pMechanism,
143 		    key_p, B_FALSE);
144 
145 		if (rv != CKR_OK)
146 			return (rv);
147 
148 		(void) pthread_mutex_lock(&session_p->session_mutex);
149 
150 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
151 		/* Save Initialization Vector (IV) in the context. */
152 		(void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
153 		    DES_BLOCK_LEN);
154 
155 		/* Allocate a context for DES cipher-block chaining. */
156 		soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
157 		    soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
158 		    soft_des_ctx->ivec, key_p->key_type);
159 
160 		if (soft_des_ctx->des_cbc == NULL) {
161 			bzero(soft_des_ctx->key_sched,
162 			    soft_des_ctx->keysched_len);
163 			free(soft_des_ctx->key_sched);
164 			free(session_p->decrypt.context);
165 			session_p->decrypt.context = NULL;
166 			(void) pthread_mutex_unlock(&session_p->session_mutex);
167 			return (CKR_HOST_MEMORY);
168 		}
169 
170 		(void) pthread_mutex_unlock(&session_p->session_mutex);
171 
172 		return (rv);
173 	}
174 	case CKM_AES_ECB:
175 
176 		if (key_p->key_type != CKK_AES) {
177 			return (CKR_KEY_TYPE_INCONSISTENT);
178 		}
179 
180 		return (soft_aes_crypt_init_common(session_p, pMechanism,
181 		    key_p, B_FALSE));
182 
183 	case CKM_AES_CBC:
184 	case CKM_AES_CBC_PAD:
185 	{
186 		soft_aes_ctx_t *soft_aes_ctx;
187 
188 		if (key_p->key_type != CKK_AES) {
189 			return (CKR_KEY_TYPE_INCONSISTENT);
190 		}
191 
192 		if ((pMechanism->pParameter == NULL) ||
193 		    (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
194 			return (CKR_MECHANISM_PARAM_INVALID);
195 		}
196 
197 		rv = soft_aes_crypt_init_common(session_p, pMechanism,
198 		    key_p, B_FALSE);
199 
200 		if (rv != CKR_OK)
201 			return (rv);
202 
203 		(void) pthread_mutex_lock(&session_p->session_mutex);
204 
205 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
206 
207 		/* Save Initialization Vector (IV) in the context. */
208 		(void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
209 		    AES_BLOCK_LEN);
210 
211 		/* Allocate a context for AES cipher-block chaining. */
212 		soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
213 		    soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
214 		    soft_aes_ctx->ivec);
215 
216 		if (soft_aes_ctx->aes_cbc == NULL) {
217 			bzero(soft_aes_ctx->key_sched,
218 			    soft_aes_ctx->keysched_len);
219 			free(soft_aes_ctx->key_sched);
220 			free(session_p->decrypt.context);
221 			session_p->decrypt.context = NULL;
222 			(void) pthread_mutex_unlock(&session_p->session_mutex);
223 			return (CKR_HOST_MEMORY);
224 		}
225 
226 		(void) pthread_mutex_unlock(&session_p->session_mutex);
227 
228 		return (rv);
229 	}
230 
231 	case CKM_BLOWFISH_CBC:
232 	{
233 		soft_blowfish_ctx_t *soft_blowfish_ctx;
234 
235 		if (key_p->key_type != CKK_BLOWFISH)
236 			return (CKR_KEY_TYPE_INCONSISTENT);
237 
238 		if ((pMechanism->pParameter == NULL) ||
239 		    (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
240 			return (CKR_MECHANISM_PARAM_INVALID);
241 
242 		rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
243 		    key_p, B_FALSE);
244 
245 		if (rv != CKR_OK)
246 			return (rv);
247 
248 		(void) pthread_mutex_lock(&session_p->session_mutex);
249 
250 		soft_blowfish_ctx =
251 		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
252 
253 		/* Save Initialization Vector in the context. */
254 		(void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
255 		    BLOWFISH_BLOCK_LEN);
256 
257 		/* Allocate a context for CBC */
258 		soft_blowfish_ctx->blowfish_cbc =
259 		    (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
260 			soft_blowfish_ctx->keysched_len,
261 			soft_blowfish_ctx->ivec);
262 
263 		if (soft_blowfish_ctx->blowfish_cbc == NULL) {
264 			bzero(soft_blowfish_ctx->key_sched,
265 			    soft_blowfish_ctx->keysched_len);
266 			free(soft_blowfish_ctx->key_sched);
267 			free(session_p->decrypt.context = NULL);
268 			(void) pthread_mutex_unlock(&session_p->session_mutex);
269 			return (CKR_HOST_MEMORY);
270 		}
271 
272 		(void) pthread_mutex_unlock(&session_p->session_mutex);
273 		return (rv);
274 	}
275 
276 	case CKM_RC4:
277 
278 		if (key_p->key_type != CKK_RC4) {
279 			return (CKR_KEY_TYPE_INCONSISTENT);
280 		}
281 
282 		return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
283 		    B_FALSE));
284 
285 	case CKM_RSA_X_509:
286 	case CKM_RSA_PKCS:
287 
288 		if (key_p->key_type != CKK_RSA) {
289 			return (CKR_KEY_TYPE_INCONSISTENT);
290 		}
291 
292 		return (soft_rsa_crypt_init_common(session_p, pMechanism,
293 		    key_p, B_FALSE));
294 
295 	default:
296 		return (CKR_MECHANISM_INVALID);
297 	}
298 }
299 
300 
301 /*
302  * soft_decrypt_common()
303  *
304  * Arguments:
305  *      session_p:	pointer to soft_session_t struct
306  *	pEncrypted:	pointer to the encrypted data as input
307  *	ulEncryptedLen:	length of the input data
308  *	pData:		pointer to the output data contains plaintext
309  *	pulDataLen:	pointer to the length of the output data
310  *	Update:		boolean flag indicates caller is soft_decrypt
311  *			or soft_decrypt_update
312  *
313  * Description:
314  *      This function calls the corresponding decrypt routine based
315  *	on the mechanism.
316  *
317  * Returns:
318  *	see soft_decrypt_common().
319  */
320 CK_RV
321 soft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
322     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
323     CK_ULONG_PTR pulDataLen, boolean_t Update)
324 {
325 
326 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
327 
328 	switch (mechanism) {
329 
330 	case CKM_DES_ECB:
331 	case CKM_DES_CBC:
332 	case CKM_DES_CBC_PAD:
333 	case CKM_DES3_ECB:
334 	case CKM_DES3_CBC:
335 	case CKM_DES3_CBC_PAD:
336 
337 		return (soft_des_decrypt_common(session_p, pEncrypted,
338 		    ulEncryptedLen, pData, pulDataLen, Update));
339 
340 	case CKM_AES_ECB:
341 	case CKM_AES_CBC:
342 	case CKM_AES_CBC_PAD:
343 
344 		return (soft_aes_decrypt_common(session_p, pEncrypted,
345 		    ulEncryptedLen, pData, pulDataLen, Update));
346 
347 	case CKM_BLOWFISH_CBC:
348 
349 		return (soft_blowfish_decrypt_common(session_p, pEncrypted,
350 		    ulEncryptedLen, pData, pulDataLen, Update));
351 
352 	case CKM_RC4:
353 	{
354 		ARCFour_key *keystream = session_p->decrypt.context;
355 		CK_RV rv;
356 
357 		rv = soft_arcfour_crypt(&(session_p->decrypt), pEncrypted,
358 		    ulEncryptedLen, pData, pulDataLen);
359 
360 		if ((rv == CKR_OK) && (pData != NULL)) {
361 			bzero(keystream, sizeof (*keystream));
362 			free(keystream);
363 			session_p->decrypt.context = NULL;
364 		}
365 		return (rv);
366 	}
367 
368 	case CKM_RSA_X_509:
369 	case CKM_RSA_PKCS:
370 
371 		return (soft_rsa_decrypt_common(session_p, pEncrypted,
372 		    ulEncryptedLen, pData, pulDataLen, mechanism));
373 
374 	default:
375 		return (CKR_MECHANISM_INVALID);
376 
377 	}
378 }
379 
380 
381 /*
382  * soft_decrypt()
383  *
384  * Arguments:
385  *      session_p:	pointer to soft_session_t struct
386  *	pEncryptedData: pointer to the encrypted data as input
387  *	ulEncryptedDataLen: length of the input data
388  *	pData:		pointer to the output data contains plaintext
389  *	pulDataLen:	pointer to the length of the output data
390  *
391  * Description:
392  *      called by C_Decrypt(). This function calls the soft_decrypt_common
393  *	routine.
394  *
395  * Returns:
396  *	see soft_decrypt_common().
397  */
398 CK_RV
399 soft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
400     CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
401     CK_ULONG_PTR pulDataLen)
402 {
403 
404 	return (soft_decrypt_common(session_p, pEncryptedData,
405 	    ulEncryptedDataLen, pData, pulDataLen, B_FALSE));
406 }
407 
408 
409 /*
410  * soft_decrypt_update()
411  *
412  * Arguments:
413  *      session_p:	pointer to soft_session_t struct
414  *	pEncryptedPart: pointer to the encrypted data as input
415  *	ulEncryptedPartLen: length of the input data
416  *	pPart:          pointer to the output data contains plaintext
417  *	pulPartLen:     pointer to the length of the output data
418  *
419  * Description:
420  *      called by C_DecryptUpdate(). This function calls the
421  *	soft_decrypt_common routine (with update flag on).
422  *
423  * Returns:
424  *	see soft_decrypt_common().
425  */
426 CK_RV
427 soft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart,
428 	CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
429 	CK_ULONG_PTR pulPartLen)
430 {
431 
432 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
433 
434 	switch (mechanism) {
435 
436 	case CKM_DES_ECB:
437 	case CKM_DES_CBC:
438 	case CKM_DES_CBC_PAD:
439 	case CKM_DES3_ECB:
440 	case CKM_DES3_CBC:
441 	case CKM_DES3_CBC_PAD:
442 	case CKM_AES_ECB:
443 	case CKM_AES_CBC:
444 	case CKM_AES_CBC_PAD:
445 	case CKM_BLOWFISH_CBC:
446 
447 		return (soft_decrypt_common(session_p, pEncryptedPart,
448 		    ulEncryptedPartLen, pPart, pulPartLen, B_TRUE));
449 
450 	case CKM_RC4:
451 
452 		return (soft_arcfour_crypt(&(session_p->decrypt),
453 		    pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen));
454 
455 	default:
456 		/* PKCS11: The mechanism only supports single-part operation. */
457 		return (CKR_MECHANISM_INVALID);
458 	}
459 
460 }
461 
462 
463 /*
464  * soft_decrypt_final()
465  *
466  * Arguments:
467  *      session_p:	pointer to soft_session_t struct
468  *      pLastPart:	pointer to the last recovered data part
469  *      pulLastPartLen:	pointer to the length of the last recovered data part
470  *
471  * Description:
472  *      called by C_DecryptFinal().
473  *
474  * Returns:
475  *	CKR_OK: success
476  *	CKR_FUNCTION_FAILED: decrypt final function failed
477  *	CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
478  */
479 CK_RV
480 soft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
481 	CK_ULONG_PTR pulLastPartLen)
482 {
483 
484 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
485 	CK_ULONG out_len;
486 	CK_RV rv = CKR_OK;
487 	int rc;
488 
489 	(void) pthread_mutex_lock(&session_p->session_mutex);
490 
491 	if (session_p->decrypt.context == NULL) {
492 		rv = CKR_OPERATION_NOT_INITIALIZED;
493 		*pulLastPartLen = 0;
494 		goto clean2;
495 	}
496 	switch (mechanism) {
497 
498 	case CKM_DES_CBC_PAD:
499 	case CKM_DES3_CBC_PAD:
500 	{
501 
502 		soft_des_ctx_t *soft_des_ctx;
503 
504 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
505 
506 		/*
507 		 * We should have only one block of data left in the
508 		 * remaining buffer.
509 		 */
510 		if (soft_des_ctx->remain_len != DES_BLOCK_LEN) {
511 			*pulLastPartLen = 0;
512 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
513 			/* Cleanup memory space. */
514 			free(soft_des_ctx->des_cbc);
515 			bzero(soft_des_ctx->key_sched,
516 			    soft_des_ctx->keysched_len);
517 			free(soft_des_ctx->key_sched);
518 
519 			goto clean1;
520 		}
521 
522 		out_len = DES_BLOCK_LEN;
523 
524 		/*
525 		 * If application asks for the length of the output buffer
526 		 * to hold the plaintext?
527 		 */
528 		if (pLastPart == NULL) {
529 			*pulLastPartLen = out_len;
530 			rv = CKR_OK;
531 			goto clean2;
532 		} else {
533 			crypto_data_t out;
534 
535 			/* Copy remaining data to the output buffer. */
536 			(void) memcpy(pLastPart, soft_des_ctx->data,
537 			    DES_BLOCK_LEN);
538 
539 			out.cd_format = CRYPTO_DATA_RAW;
540 			out.cd_offset = 0;
541 			out.cd_length = DES_BLOCK_LEN;
542 			out.cd_raw.iov_base = (char *)pLastPart;
543 			out.cd_raw.iov_len = DES_BLOCK_LEN;
544 
545 			/* Decrypt final block of data. */
546 			rc = des_decrypt_contiguous_blocks(
547 			    (des_ctx_t *)soft_des_ctx->des_cbc,
548 			    (char *)pLastPart, DES_BLOCK_LEN, &out);
549 
550 			if (rc == 0) {
551 				/*
552 				 * Remove padding bytes after decryption of
553 				 * ciphertext block to produce the original
554 				 * plaintext.
555 				 */
556 				rv = soft_remove_pkcs7_padding(pLastPart,
557 				    DES_BLOCK_LEN, &out_len, DES_BLOCK_LEN);
558 				if (rv != CKR_OK)
559 					*pulLastPartLen = 0;
560 				else
561 					*pulLastPartLen = out_len;
562 			} else {
563 				*pulLastPartLen = 0;
564 				rv = CKR_FUNCTION_FAILED;
565 			}
566 
567 			/* Cleanup memory space. */
568 			free(soft_des_ctx->des_cbc);
569 			bzero(soft_des_ctx->key_sched,
570 			    soft_des_ctx->keysched_len);
571 			free(soft_des_ctx->key_sched);
572 
573 		}
574 
575 		break;
576 	}
577 
578 	case CKM_DES_CBC:
579 	case CKM_DES_ECB:
580 	case CKM_DES3_CBC:
581 	case CKM_DES3_ECB:
582 	{
583 
584 		soft_des_ctx_t *soft_des_ctx;
585 
586 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
587 		/*
588 		 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
589 		 * so when the final is called, the remaining buffer
590 		 * should not contain any more data.
591 		 */
592 		*pulLastPartLen = 0;
593 		if (soft_des_ctx->remain_len != 0) {
594 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
595 		} else {
596 			if (pLastPart == NULL)
597 				goto clean2;
598 		}
599 
600 		/* Cleanup memory space. */
601 		free(soft_des_ctx->des_cbc);
602 		bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
603 		free(soft_des_ctx->key_sched);
604 
605 		break;
606 	}
607 
608 	case CKM_AES_CBC_PAD:
609 	{
610 
611 		soft_aes_ctx_t *soft_aes_ctx;
612 
613 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
614 
615 		/*
616 		 * We should have only one block of data left in the
617 		 * remaining buffer.
618 		 */
619 		if (soft_aes_ctx->remain_len != AES_BLOCK_LEN) {
620 			*pulLastPartLen = 0;
621 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
622 			/* Cleanup memory space. */
623 			free(soft_aes_ctx->aes_cbc);
624 			bzero(soft_aes_ctx->key_sched,
625 			    soft_aes_ctx->keysched_len);
626 			free(soft_aes_ctx->key_sched);
627 
628 			goto clean1;
629 		}
630 
631 		out_len = AES_BLOCK_LEN;
632 
633 		/*
634 		 * If application asks for the length of the output buffer
635 		 * to hold the plaintext?
636 		 */
637 		if (pLastPart == NULL) {
638 			*pulLastPartLen = out_len;
639 			rv = CKR_OK;
640 			goto clean2;
641 		} else {
642 			crypto_data_t out;
643 
644 			/* Copy remaining data to the output buffer. */
645 			(void) memcpy(pLastPart, soft_aes_ctx->data,
646 			    AES_BLOCK_LEN);
647 
648 			out.cd_format = CRYPTO_DATA_RAW;
649 			out.cd_offset = 0;
650 			out.cd_length = AES_BLOCK_LEN;
651 			out.cd_raw.iov_base = (char *)pLastPart;
652 			out.cd_raw.iov_len = AES_BLOCK_LEN;
653 
654 			/* Decrypt final block of data. */
655 			rc = aes_decrypt_contiguous_blocks(
656 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
657 			    (char *)pLastPart, AES_BLOCK_LEN, &out);
658 
659 			if (rc == 0) {
660 				/*
661 				 * Remove padding bytes after decryption of
662 				 * ciphertext block to produce the original
663 				 * plaintext.
664 				 */
665 				rv = soft_remove_pkcs7_padding(pLastPart,
666 				    AES_BLOCK_LEN, &out_len, AES_BLOCK_LEN);
667 				if (rv != CKR_OK)
668 					*pulLastPartLen = 0;
669 				else
670 					*pulLastPartLen = out_len;
671 			} else {
672 				*pulLastPartLen = 0;
673 				rv = CKR_FUNCTION_FAILED;
674 			}
675 
676 			/* Cleanup memory space. */
677 			free(soft_aes_ctx->aes_cbc);
678 			bzero(soft_aes_ctx->key_sched,
679 			    soft_aes_ctx->keysched_len);
680 			free(soft_aes_ctx->key_sched);
681 
682 		}
683 
684 		break;
685 	}
686 
687 	case CKM_AES_CBC:
688 	case CKM_AES_ECB:
689 	{
690 		soft_aes_ctx_t *soft_aes_ctx;
691 
692 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
693 		/*
694 		 * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
695 		 * so when the final is called, the remaining buffer
696 		 * should not contain any more data.
697 		 */
698 		*pulLastPartLen = 0;
699 		if (soft_aes_ctx->remain_len != 0) {
700 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
701 		} else {
702 			if (pLastPart == NULL)
703 				goto clean2;
704 		}
705 
706 		/* Cleanup memory space. */
707 		free(soft_aes_ctx->aes_cbc);
708 		bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
709 		free(soft_aes_ctx->key_sched);
710 
711 		break;
712 	}
713 
714 	case CKM_BLOWFISH_CBC:
715 	{
716 		soft_blowfish_ctx_t *soft_blowfish_ctx;
717 
718 		soft_blowfish_ctx =
719 		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
720 
721 		*pulLastPartLen = 0;
722 		if (soft_blowfish_ctx->remain_len != 0)
723 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
724 		else {
725 			if (pLastPart == NULL)
726 				goto clean2;
727 		}
728 
729 		free(soft_blowfish_ctx->blowfish_cbc);
730 		bzero(soft_blowfish_ctx->key_sched,
731 		    soft_blowfish_ctx->keysched_len);
732 		free(soft_blowfish_ctx->key_sched);
733 
734 		break;
735 	}
736 
737 	case CKM_RC4:
738 	{
739 		ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context;
740 		bzero(key, sizeof (*key));
741 		*pulLastPartLen = 0;
742 		break;
743 	}
744 
745 	default:
746 		/* PKCS11: The mechanism only supports single-part operation. */
747 		rv = CKR_MECHANISM_INVALID;
748 		break;
749 	}
750 
751 clean1:
752 	free(session_p->decrypt.context);
753 	session_p->decrypt.context = NULL;
754 
755 clean2:
756 	(void) pthread_mutex_unlock(&session_p->session_mutex);
757 
758 	return (rv);
759 
760 }
761