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