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