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