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