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