xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softEncryptUtil.c (revision e153cda9f9660e385e8f468253f80e59f5d454d7)
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 2015 Nexenta Systems, Inc.  All rights reserved.
25  * Copyright (c) 2018, Joyent, Inc.
26  */
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  * Add padding bytes with the value of length of padding.
44  */
45 void
46 soft_add_pkcs7_padding(CK_BYTE *buf, int block_size, CK_ULONG data_len)
47 {
48 	(void) pkcs7_encode(NULL, data_len, buf, block_size, block_size);
49 }
50 
51 /*
52  * Perform encrypt init operation internally for the support of
53  * CKM_AES and CKM_DES MAC operations.
54  *
55  * This function is called with the session being held, and without
56  * its mutex taken.
57  */
58 CK_RV
59 soft_encrypt_init_internal(soft_session_t *session_p, CK_MECHANISM_PTR
60     pMechanism, soft_object_t *key_p)
61 {
62 	CK_RV rv;
63 
64 	(void) pthread_mutex_lock(&session_p->session_mutex);
65 
66 	/* Check to see if encrypt operation is already active */
67 	if (session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE) {
68 		(void) pthread_mutex_unlock(&session_p->session_mutex);
69 		return (CKR_OPERATION_ACTIVE);
70 	}
71 
72 	session_p->encrypt.flags = CRYPTO_OPERATION_ACTIVE;
73 
74 	(void) pthread_mutex_unlock(&session_p->session_mutex);
75 
76 	rv = soft_encrypt_init(session_p, pMechanism, key_p);
77 
78 	if (rv != CKR_OK) {
79 		(void) pthread_mutex_lock(&session_p->session_mutex);
80 		session_p->encrypt.flags &= ~CRYPTO_OPERATION_ACTIVE;
81 		(void) pthread_mutex_unlock(&session_p->session_mutex);
82 	}
83 
84 	return (rv);
85 }
86 
87 /*
88  * soft_encrypt_init()
89  *
90  * Arguments:
91  *	session_p:	pointer to soft_session_t struct
92  *	pMechanism:	pointer to CK_MECHANISM struct provided by application
93  *	key_p:		pointer to key soft_object_t struct
94  *
95  * Description:
96  *	called by C_EncryptInit(). This function calls the corresponding
97  *	encrypt init routine based on the mechanism.
98  *
99  * Returns:
100  *	CKR_OK: success
101  *	CKR_HOST_MEMORY: run out of system memory
102  *	CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
103  *	CKR_MECHANISM_INVALID: invalid mechanism type
104  *	CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
105  *		with the specified mechanism
106  */
107 CK_RV
108 soft_encrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
109     soft_object_t *key_p)
110 {
111 
112 	CK_RV rv;
113 
114 	switch (pMechanism->mechanism) {
115 
116 	case CKM_DES_ECB:
117 
118 		if (key_p->key_type != CKK_DES) {
119 			return (CKR_KEY_TYPE_INCONSISTENT);
120 		}
121 		goto ecb_common;
122 
123 	case CKM_DES3_ECB:
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 ecb_common:
131 		return (soft_des_crypt_init_common(session_p, pMechanism,
132 		    key_p, B_TRUE));
133 
134 	case CKM_DES_CBC:
135 	case CKM_DES_CBC_PAD:
136 
137 		if (key_p->key_type != CKK_DES) {
138 			return (CKR_KEY_TYPE_INCONSISTENT);
139 		}
140 
141 		goto cbc_common;
142 
143 	case CKM_DES3_CBC:
144 	case CKM_DES3_CBC_PAD:
145 	{
146 
147 		soft_des_ctx_t *soft_des_ctx;
148 
149 		if ((key_p->key_type != CKK_DES2) &&
150 		    (key_p->key_type != CKK_DES3)) {
151 			return (CKR_KEY_TYPE_INCONSISTENT);
152 		}
153 
154 cbc_common:
155 		if ((pMechanism->pParameter == NULL) ||
156 		    (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
157 			return (CKR_MECHANISM_PARAM_INVALID);
158 		}
159 
160 		rv = soft_des_crypt_init_common(session_p, pMechanism,
161 		    key_p, B_TRUE);
162 
163 		if (rv != CKR_OK)
164 			return (rv);
165 
166 		(void) pthread_mutex_lock(&session_p->session_mutex);
167 
168 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
169 		/* Copy Initialization Vector (IV) into the context. */
170 		(void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
171 		    DES_BLOCK_LEN);
172 
173 		/* Allocate a context for DES cipher-block chaining. */
174 		soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
175 		    soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
176 		    soft_des_ctx->ivec, key_p->key_type);
177 
178 		if (soft_des_ctx->des_cbc == NULL) {
179 			freezero(soft_des_ctx->key_sched,
180 			    soft_des_ctx->keysched_len);
181 			freezero(session_p->encrypt.context,
182 			    sizeof (soft_des_ctx_t));
183 			session_p->encrypt.context = NULL;
184 			rv = CKR_HOST_MEMORY;
185 		}
186 
187 		(void) pthread_mutex_unlock(&session_p->session_mutex);
188 
189 		return (rv);
190 	}
191 	case CKM_AES_ECB:
192 
193 		if (key_p->key_type != CKK_AES) {
194 			return (CKR_KEY_TYPE_INCONSISTENT);
195 		}
196 
197 		return (soft_aes_crypt_init_common(session_p, pMechanism,
198 		    key_p, B_TRUE));
199 
200 	case CKM_AES_CBC:
201 	case CKM_AES_CBC_PAD:
202 		if ((pMechanism->pParameter == NULL) ||
203 		    (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
204 			return (CKR_MECHANISM_PARAM_INVALID);
205 		}
206 	/* FALLTHRU */
207 	case CKM_AES_CMAC:
208 	{
209 		soft_aes_ctx_t *soft_aes_ctx;
210 
211 		if (key_p->key_type != CKK_AES) {
212 			return (CKR_KEY_TYPE_INCONSISTENT);
213 		}
214 
215 
216 		rv = soft_aes_crypt_init_common(session_p, pMechanism,
217 		    key_p, B_TRUE);
218 
219 		if (rv != CKR_OK)
220 			return (rv);
221 
222 		(void) pthread_mutex_lock(&session_p->session_mutex);
223 
224 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
225 		/* Copy Initialization Vector (IV) into the context. */
226 		if (pMechanism->mechanism == CKM_AES_CMAC) {
227 			(void) bzero(soft_aes_ctx->ivec, AES_BLOCK_LEN);
228 			/* Allocate a context for AES cipher-block chaining. */
229 			soft_aes_ctx->aes_cbc = (void *)aes_cmac_ctx_init(
230 			    soft_aes_ctx->key_sched,
231 			    soft_aes_ctx->keysched_len);
232 		} else {
233 			(void) memcpy(soft_aes_ctx->ivec,
234 			    pMechanism->pParameter,
235 			    AES_BLOCK_LEN);
236 			/* Allocate a context for AES cipher-block chaining. */
237 			soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
238 			    soft_aes_ctx->key_sched,
239 			    soft_aes_ctx->keysched_len,
240 			    soft_aes_ctx->ivec);
241 		}
242 		if (soft_aes_ctx->aes_cbc == NULL) {
243 			freezero(soft_aes_ctx->key_sched,
244 			    soft_aes_ctx->keysched_len);
245 			freezero(session_p->encrypt.context,
246 			    sizeof (soft_aes_ctx_t));
247 			session_p->encrypt.context = NULL;
248 			rv = CKR_HOST_MEMORY;
249 		}
250 
251 		(void) pthread_mutex_unlock(&session_p->session_mutex);
252 
253 		return (rv);
254 	}
255 	case CKM_AES_CTR:
256 	{
257 		soft_aes_ctx_t *soft_aes_ctx;
258 
259 		if (key_p->key_type != CKK_AES) {
260 			return (CKR_KEY_TYPE_INCONSISTENT);
261 		}
262 
263 		if (pMechanism->pParameter == NULL ||
264 		    pMechanism->ulParameterLen != sizeof (CK_AES_CTR_PARAMS)) {
265 			return (CKR_MECHANISM_PARAM_INVALID);
266 		}
267 
268 		rv = soft_aes_crypt_init_common(session_p, pMechanism,
269 		    key_p, B_TRUE);
270 
271 		if (rv != CKR_OK)
272 			return (rv);
273 
274 		(void) pthread_mutex_lock(&session_p->session_mutex);
275 
276 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
277 		soft_aes_ctx->aes_cbc = aes_ctr_ctx_init(
278 		    soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
279 		    pMechanism->pParameter);
280 
281 		if (soft_aes_ctx->aes_cbc == NULL) {
282 			freezero(soft_aes_ctx->key_sched,
283 			    soft_aes_ctx->keysched_len);
284 			freezero(session_p->encrypt.context,
285 			    sizeof (soft_aes_ctx_t));
286 			session_p->encrypt.context = NULL;
287 			rv = CKR_HOST_MEMORY;
288 		}
289 
290 		(void) pthread_mutex_unlock(&session_p->session_mutex);
291 
292 		return (rv);
293 	}
294 	case CKM_RC4:
295 
296 		if (key_p->key_type != CKK_RC4) {
297 			return (CKR_KEY_TYPE_INCONSISTENT);
298 		}
299 
300 		return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
301 		    B_TRUE));
302 
303 	case CKM_RSA_X_509:
304 	case CKM_RSA_PKCS:
305 
306 		if (key_p->key_type != CKK_RSA) {
307 			return (CKR_KEY_TYPE_INCONSISTENT);
308 		}
309 
310 		return (soft_rsa_crypt_init_common(session_p, pMechanism,
311 		    key_p, B_TRUE));
312 
313 	case CKM_BLOWFISH_CBC:
314 	{
315 		soft_blowfish_ctx_t *soft_blowfish_ctx;
316 
317 		if (key_p->key_type != CKK_BLOWFISH)
318 			return (CKR_KEY_TYPE_INCONSISTENT);
319 
320 		if ((pMechanism->pParameter == NULL) ||
321 		    (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
322 			return (CKR_MECHANISM_PARAM_INVALID);
323 
324 		rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
325 		    key_p, B_TRUE);
326 
327 		if (rv != CKR_OK)
328 			return (rv);
329 
330 		(void) pthread_mutex_lock(&session_p->session_mutex);
331 
332 		soft_blowfish_ctx =
333 		    (soft_blowfish_ctx_t *)session_p->encrypt.context;
334 		/* Copy Initialization Vector (IV) into the context. */
335 		(void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
336 		    BLOWFISH_BLOCK_LEN);
337 
338 		/* Allocate a context for Blowfish cipher-block chaining */
339 		soft_blowfish_ctx->blowfish_cbc =
340 		    (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
341 		    soft_blowfish_ctx->keysched_len,
342 		    soft_blowfish_ctx->ivec);
343 
344 		if (soft_blowfish_ctx->blowfish_cbc == NULL) {
345 			freezero(soft_blowfish_ctx->key_sched,
346 			    soft_blowfish_ctx->keysched_len);
347 			freezero(session_p->encrypt.context,
348 			    sizeof (soft_blowfish_ctx_t));
349 			session_p->encrypt.context = NULL;
350 			rv = CKR_HOST_MEMORY;
351 		}
352 
353 		(void) pthread_mutex_unlock(&session_p->session_mutex);
354 
355 		return (rv);
356 	}
357 	default:
358 		return (CKR_MECHANISM_INVALID);
359 	}
360 }
361 
362 
363 /*
364  * soft_encrypt_common()
365  *
366  * Arguments:
367  *      session_p:	pointer to soft_session_t struct
368  *	pData:		pointer to the input data to be encrypted
369  *	ulDataLen:	length of the input data
370  *	pEncrypted:	pointer to the output data after encryption
371  *	pulEncryptedLen: pointer to the length of the output data
372  *	update:		boolean flag indicates caller is soft_encrypt
373  *			or soft_encrypt_update
374  *
375  * Description:
376  *      This function calls the corresponding encrypt routine based
377  *	on the mechanism.
378  *
379  * Returns:
380  *	see corresponding encrypt routine.
381  */
382 CK_RV
383 soft_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
384     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
385     CK_ULONG_PTR pulEncryptedLen, boolean_t update)
386 {
387 
388 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
389 
390 	switch (mechanism) {
391 
392 	case CKM_DES_ECB:
393 	case CKM_DES_CBC:
394 	case CKM_DES3_ECB:
395 	case CKM_DES3_CBC:
396 
397 		if (ulDataLen == 0) {
398 			*pulEncryptedLen = 0;
399 			return (CKR_OK);
400 		}
401 		/* FALLTHROUGH */
402 
403 	case CKM_DES_CBC_PAD:
404 	case CKM_DES3_CBC_PAD:
405 
406 		return (soft_des_encrypt_common(session_p, pData,
407 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
408 
409 	case CKM_AES_ECB:
410 	case CKM_AES_CBC:
411 	case CKM_AES_CTR:
412 
413 		if (ulDataLen == 0) {
414 			*pulEncryptedLen = 0;
415 			return (CKR_OK);
416 		}
417 		/* FALLTHROUGH */
418 
419 	case CKM_AES_CMAC:
420 	case CKM_AES_CBC_PAD:
421 
422 		return (soft_aes_encrypt_common(session_p, pData,
423 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
424 
425 	case CKM_BLOWFISH_CBC:
426 
427 		if (ulDataLen == 0) {
428 			*pulEncryptedLen = 0;
429 			return (CKR_OK);
430 		}
431 
432 		return (soft_blowfish_encrypt_common(session_p, pData,
433 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
434 
435 	case CKM_RC4:
436 
437 		if (ulDataLen == 0) {
438 			*pulEncryptedLen = 0;
439 			return (CKR_OK);
440 		}
441 
442 		return (soft_arcfour_crypt(&(session_p->encrypt), pData,
443 		    ulDataLen, pEncrypted, pulEncryptedLen));
444 
445 	case CKM_RSA_X_509:
446 	case CKM_RSA_PKCS:
447 
448 		return (soft_rsa_encrypt_common(session_p, pData,
449 		    ulDataLen, pEncrypted, pulEncryptedLen, mechanism));
450 
451 	default:
452 		return (CKR_MECHANISM_INVALID);
453 	}
454 }
455 
456 
457 /*
458  * soft_encrypt()
459  *
460  * Arguments:
461  *      session_p:	pointer to soft_session_t struct
462  *	pData:		pointer to the input data to be encrypted
463  *	ulDataLen:	length of the input data
464  *	pEncryptedData:	pointer to the output data after encryption
465  *	pulEncryptedDataLen: pointer to the length of the output data
466  *
467  * Description:
468  *      called by C_Encrypt(). This function calls the soft_encrypt_common
469  *	routine.
470  *
471  * Returns:
472  *	see soft_encrypt_common().
473  */
474 CK_RV
475 soft_encrypt(soft_session_t *session_p, CK_BYTE_PTR pData,
476     CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
477     CK_ULONG_PTR pulEncryptedDataLen)
478 {
479 
480 	return (soft_encrypt_common(session_p, pData, ulDataLen,
481 	    pEncryptedData, pulEncryptedDataLen, B_FALSE));
482 }
483 
484 
485 /*
486  * soft_encrypt_update()
487  *
488  * Arguments:
489  *      session_p:	pointer to soft_session_t struct
490  *      pPart:		pointer to the input data to be digested
491  *      ulPartLen:	length of the input data
492  *	pEncryptedPart:	pointer to the ciphertext
493  *	pulEncryptedPartLen: pointer to the length of the ciphertext
494  *
495  * Description:
496  *      called by C_EncryptUpdate(). This function calls the
497  *	soft_encrypt_common routine (with update flag on).
498  *
499  * Returns:
500  *	see soft_encrypt_common().
501  */
502 CK_RV
503 soft_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
504     CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
505     CK_ULONG_PTR pulEncryptedPartLen)
506 {
507 
508 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
509 
510 	switch (mechanism) {
511 
512 	case CKM_DES_ECB:
513 	case CKM_DES_CBC:
514 	case CKM_DES_CBC_PAD:
515 	case CKM_DES3_ECB:
516 	case CKM_DES3_CBC:
517 	case CKM_DES3_CBC_PAD:
518 	case CKM_AES_ECB:
519 	case CKM_AES_CBC:
520 	case CKM_AES_CBC_PAD:
521 	case CKM_AES_CMAC:
522 	case CKM_AES_CTR:
523 	case CKM_BLOWFISH_CBC:
524 	case CKM_RC4:
525 
526 		return (soft_encrypt_common(session_p, pPart, ulPartLen,
527 		    pEncryptedPart, pulEncryptedPartLen, B_TRUE));
528 
529 	default:
530 		/* PKCS11: The mechanism only supports single-part operation. */
531 		return (CKR_MECHANISM_INVALID);
532 	}
533 }
534 
535 
536 /*
537  * soft_encrypt_final()
538  *
539  * Arguments:
540  *      session_p:		pointer to soft_session_t struct
541  *      pLastEncryptedPart:	pointer to the last encrypted data part
542  *      pulLastEncryptedPartLen: pointer to the length of the last
543  *				encrypted data part
544  *
545  * Description:
546  *      called by C_EncryptFinal().
547  *
548  * Returns:
549  *	CKR_OK: success
550  *	CKR_FUNCTION_FAILED: encrypt final function failed
551  *	CKR_DATA_LEN_RANGE: remaining buffer contains bad length
552  */
553 CK_RV
554 soft_encrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastEncryptedPart,
555     CK_ULONG_PTR pulLastEncryptedPartLen)
556 {
557 
558 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
559 	CK_ULONG out_len;
560 	CK_RV rv = CKR_OK;
561 	int rc;
562 
563 	(void) pthread_mutex_lock(&session_p->session_mutex);
564 
565 	if (session_p->encrypt.context == NULL) {
566 		rv = CKR_OPERATION_NOT_INITIALIZED;
567 		*pulLastEncryptedPartLen = 0;
568 		goto clean1;
569 	}
570 	switch (mechanism) {
571 
572 	case CKM_DES_CBC_PAD:
573 	case CKM_DES3_CBC_PAD:
574 	{
575 		soft_des_ctx_t *soft_des_ctx;
576 
577 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
578 		/*
579 		 * For CKM_DES_CBC_PAD, compute output length with
580 		 * padding. If the remaining buffer has one block
581 		 * of data, then output length will be two blocksize of
582 		 * ciphertext. If the remaining buffer has less than
583 		 * one block of data, then output length will be
584 		 * one blocksize.
585 		 */
586 		if (soft_des_ctx->remain_len == DES_BLOCK_LEN)
587 			out_len = 2 * DES_BLOCK_LEN;
588 		else
589 			out_len = DES_BLOCK_LEN;
590 
591 		if (pLastEncryptedPart == NULL) {
592 			/*
593 			 * Application asks for the length of the output
594 			 * buffer to hold the ciphertext.
595 			 */
596 			*pulLastEncryptedPartLen = out_len;
597 			goto clean1;
598 		} else {
599 			crypto_data_t out;
600 
601 			/* Copy remaining data to the output buffer. */
602 			(void) memcpy(pLastEncryptedPart, soft_des_ctx->data,
603 			    soft_des_ctx->remain_len);
604 
605 			/*
606 			 * Add padding bytes prior to encrypt final.
607 			 */
608 			soft_add_pkcs7_padding(pLastEncryptedPart +
609 			    soft_des_ctx->remain_len, DES_BLOCK_LEN,
610 			    soft_des_ctx->remain_len);
611 
612 			out.cd_format = CRYPTO_DATA_RAW;
613 			out.cd_offset = 0;
614 			out.cd_length = out_len;
615 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
616 			out.cd_raw.iov_len = out_len;
617 
618 			/* Encrypt multiple blocks of data. */
619 			rc = des_encrypt_contiguous_blocks(
620 			    (des_ctx_t *)soft_des_ctx->des_cbc,
621 			    (char *)pLastEncryptedPart, out_len, &out);
622 
623 			if (rc == 0) {
624 				*pulLastEncryptedPartLen = out_len;
625 			} else {
626 				*pulLastEncryptedPartLen = 0;
627 				rv = CKR_FUNCTION_FAILED;
628 			}
629 
630 			/* Cleanup memory space. */
631 			free(soft_des_ctx->des_cbc);
632 			freezero(soft_des_ctx->key_sched,
633 			    soft_des_ctx->keysched_len);
634 		}
635 
636 		break;
637 	}
638 	case CKM_DES_CBC:
639 	case CKM_DES_ECB:
640 	case CKM_DES3_CBC:
641 	case CKM_DES3_ECB:
642 	{
643 
644 		soft_des_ctx_t *soft_des_ctx;
645 
646 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
647 		/*
648 		 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
649 		 * so when the final is called, the remaining buffer
650 		 * should not contain any more data.
651 		 */
652 		*pulLastEncryptedPartLen = 0;
653 		if (soft_des_ctx->remain_len != 0) {
654 			rv = CKR_DATA_LEN_RANGE;
655 		} else {
656 			if (pLastEncryptedPart == NULL)
657 				goto clean1;
658 		}
659 
660 		/* Cleanup memory space. */
661 		free(soft_des_ctx->des_cbc);
662 		freezero(soft_des_ctx->key_sched,
663 		    soft_des_ctx->keysched_len);
664 
665 		break;
666 	}
667 	case CKM_AES_CBC_PAD:
668 	{
669 		soft_aes_ctx_t *soft_aes_ctx;
670 
671 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
672 		/*
673 		 * For CKM_AES_CBC_PAD, compute output length with
674 		 * padding. If the remaining buffer has one block
675 		 * of data, then output length will be two blocksize of
676 		 * ciphertext. If the remaining buffer has less than
677 		 * one block of data, then output length will be
678 		 * one blocksize.
679 		 */
680 		if (soft_aes_ctx->remain_len == AES_BLOCK_LEN)
681 			out_len = 2 * AES_BLOCK_LEN;
682 		else
683 			out_len = AES_BLOCK_LEN;
684 
685 		if (pLastEncryptedPart == NULL) {
686 			/*
687 			 * Application asks for the length of the output
688 			 * buffer to hold the ciphertext.
689 			 */
690 			*pulLastEncryptedPartLen = out_len;
691 			goto clean1;
692 		} else {
693 			crypto_data_t out;
694 
695 			/* Copy remaining data to the output buffer. */
696 			(void) memcpy(pLastEncryptedPart, soft_aes_ctx->data,
697 			    soft_aes_ctx->remain_len);
698 
699 			/*
700 			 * Add padding bytes prior to encrypt final.
701 			 */
702 			soft_add_pkcs7_padding(pLastEncryptedPart +
703 			    soft_aes_ctx->remain_len, AES_BLOCK_LEN,
704 			    soft_aes_ctx->remain_len);
705 
706 			out.cd_format = CRYPTO_DATA_RAW;
707 			out.cd_offset = 0;
708 			out.cd_length = out_len;
709 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
710 			out.cd_raw.iov_len = out_len;
711 
712 			/* Encrypt multiple blocks of data. */
713 			rc = aes_encrypt_contiguous_blocks(
714 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
715 			    (char *)pLastEncryptedPart, out_len, &out);
716 
717 			if (rc == 0) {
718 				*pulLastEncryptedPartLen = out_len;
719 			} else {
720 				*pulLastEncryptedPartLen = 0;
721 				rv = CKR_FUNCTION_FAILED;
722 			}
723 
724 			/* Cleanup memory space. */
725 			free(soft_aes_ctx->aes_cbc);
726 			freezero(soft_aes_ctx->key_sched,
727 			    soft_aes_ctx->keysched_len);
728 		}
729 
730 		break;
731 	}
732 	case CKM_AES_CMAC:
733 	{
734 		soft_aes_ctx_t *soft_aes_ctx;
735 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
736 
737 		if (pLastEncryptedPart == NULL) {
738 			/*
739 			 * Application asks for the length of the output
740 			 * buffer to hold the ciphertext.
741 			 */
742 			*pulLastEncryptedPartLen = AES_BLOCK_LEN;
743 			goto clean1;
744 		} else {
745 			crypto_data_t out;
746 
747 			out.cd_format = CRYPTO_DATA_RAW;
748 			out.cd_offset = 0;
749 			out.cd_length = AES_BLOCK_LEN;
750 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
751 			out.cd_raw.iov_len = AES_BLOCK_LEN;
752 
753 			rc = cmac_mode_final(soft_aes_ctx->aes_cbc, &out,
754 			    aes_encrypt_block, aes_xor_block);
755 
756 			if (rc == 0) {
757 				*pulLastEncryptedPartLen = AES_BLOCK_LEN;
758 			} else {
759 				*pulLastEncryptedPartLen = 0;
760 				rv = CKR_FUNCTION_FAILED;
761 			}
762 
763 			/* Cleanup memory space. */
764 			free(soft_aes_ctx->aes_cbc);
765 			freezero(soft_aes_ctx->key_sched,
766 			    soft_aes_ctx->keysched_len);
767 		}
768 
769 		break;
770 	}
771 	case CKM_AES_CBC:
772 	case CKM_AES_ECB:
773 	{
774 		soft_aes_ctx_t *soft_aes_ctx;
775 
776 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
777 		/*
778 		 * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
779 		 * so when the final is called, the remaining buffer
780 		 * should not contain any more data.
781 		 */
782 		*pulLastEncryptedPartLen = 0;
783 		if (soft_aes_ctx->remain_len != 0) {
784 			rv = CKR_DATA_LEN_RANGE;
785 		} else {
786 			if (pLastEncryptedPart == NULL)
787 				goto clean1;
788 		}
789 
790 		/* Cleanup memory space. */
791 		free(soft_aes_ctx->aes_cbc);
792 		freezero(soft_aes_ctx->key_sched,
793 		    soft_aes_ctx->keysched_len);
794 
795 		break;
796 	}
797 	case CKM_AES_CTR:
798 	{
799 		crypto_data_t out;
800 		soft_aes_ctx_t *soft_aes_ctx;
801 		ctr_ctx_t *ctr_ctx;
802 		size_t len;
803 
804 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
805 		ctr_ctx = soft_aes_ctx->aes_cbc;
806 		len = ctr_ctx->ctr_remainder_len;
807 
808 		if (pLastEncryptedPart == NULL) {
809 			*pulLastEncryptedPartLen = len;
810 			goto clean1;
811 		}
812 		if (len > 0) {
813 			out.cd_format = CRYPTO_DATA_RAW;
814 			out.cd_offset = 0;
815 			out.cd_length = len;
816 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
817 			out.cd_raw.iov_len = len;
818 
819 			rv = ctr_mode_final(ctr_ctx, &out, aes_encrypt_block);
820 		}
821 		if (rv == CRYPTO_BUFFER_TOO_SMALL) {
822 			*pulLastEncryptedPartLen = len;
823 			goto clean1;
824 		}
825 
826 		/* Cleanup memory space. */
827 		free(ctr_ctx);
828 		freezero(soft_aes_ctx->key_sched,
829 		    soft_aes_ctx->keysched_len);
830 
831 		break;
832 	}
833 	case CKM_BLOWFISH_CBC:
834 	{
835 		soft_blowfish_ctx_t *soft_blowfish_ctx;
836 
837 		soft_blowfish_ctx =
838 		    (soft_blowfish_ctx_t *)session_p->encrypt.context;
839 		/*
840 		 * CKM_BLOWFISH_CBC does not do any padding, so when the
841 		 * final is called, the remaining buffer should not contain
842 		 * any more data
843 		 */
844 		*pulLastEncryptedPartLen = 0;
845 		if (soft_blowfish_ctx->remain_len != 0)
846 			rv = CKR_DATA_LEN_RANGE;
847 		else {
848 			if (pLastEncryptedPart == NULL)
849 				goto clean1;
850 		}
851 
852 		free(soft_blowfish_ctx->blowfish_cbc);
853 		freezero(soft_blowfish_ctx->key_sched,
854 		    soft_blowfish_ctx->keysched_len);
855 		break;
856 	}
857 
858 	case CKM_RC4:
859 	{
860 		ARCFour_key *key = (ARCFour_key *)session_p->encrypt.context;
861 		/* Remaining data size is always zero for RC4. */
862 		*pulLastEncryptedPartLen = 0;
863 		if (pLastEncryptedPart == NULL)
864 			goto clean1;
865 		explicit_bzero(key, sizeof (*key));
866 		break;
867 	}
868 	default:
869 		/* PKCS11: The mechanism only supports single-part operation. */
870 		rv = CKR_MECHANISM_INVALID;
871 		break;
872 	}
873 
874 	free(session_p->encrypt.context);
875 	session_p->encrypt.context = NULL;
876 clean1:
877 	(void) pthread_mutex_unlock(&session_p->session_mutex);
878 
879 	return (rv);
880 }
881 
882 /*
883  * This function frees the allocated active crypto context and the
884  * lower level of allocated struct as needed.
885  * This function is called by the 1st tier of encrypt/decrypt routines
886  * or by the 2nd tier of session close routine. Since the 1st tier
887  * caller will always call this function without locking the session
888  * mutex and the 2nd tier caller will call with the lock, we add the
889  * third parameter "lock_held" to distinguish this case.
890  */
891 void
892 soft_crypt_cleanup(soft_session_t *session_p, boolean_t encrypt,
893     boolean_t lock_held)
894 {
895 
896 	crypto_active_op_t *active_op;
897 	boolean_t lock_true = B_TRUE;
898 
899 	if (!lock_held)
900 		(void) pthread_mutex_lock(&session_p->session_mutex);
901 
902 	active_op = (encrypt) ? &(session_p->encrypt) : &(session_p->decrypt);
903 
904 	switch (active_op->mech.mechanism) {
905 
906 	case CKM_DES_CBC_PAD:
907 	case CKM_DES3_CBC_PAD:
908 	case CKM_DES_CBC:
909 	case CKM_DES_ECB:
910 	case CKM_DES3_CBC:
911 	case CKM_DES3_ECB:
912 	{
913 
914 		soft_des_ctx_t *soft_des_ctx =
915 		    (soft_des_ctx_t *)active_op->context;
916 		des_ctx_t *des_ctx;
917 
918 		if (soft_des_ctx != NULL) {
919 			des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
920 			if (des_ctx != NULL) {
921 				explicit_bzero(des_ctx->dc_keysched,
922 				    des_ctx->dc_keysched_len);
923 				free(soft_des_ctx->des_cbc);
924 			}
925 			freezero(soft_des_ctx->key_sched,
926 			    soft_des_ctx->keysched_len);
927 		}
928 		break;
929 	}
930 
931 	case CKM_AES_CBC_PAD:
932 	case CKM_AES_CBC:
933 	case CKM_AES_CMAC:
934 	case CKM_AES_ECB:
935 	{
936 		soft_aes_ctx_t *soft_aes_ctx =
937 		    (soft_aes_ctx_t *)active_op->context;
938 		aes_ctx_t *aes_ctx;
939 
940 		if (soft_aes_ctx != NULL) {
941 			aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
942 			if (aes_ctx != NULL) {
943 				explicit_bzero(aes_ctx->ac_keysched,
944 				    aes_ctx->ac_keysched_len);
945 				free(soft_aes_ctx->aes_cbc);
946 			}
947 			freezero(soft_aes_ctx->key_sched,
948 			    soft_aes_ctx->keysched_len);
949 		}
950 		break;
951 	}
952 
953 	case CKM_BLOWFISH_CBC:
954 	{
955 		soft_blowfish_ctx_t *soft_blowfish_ctx =
956 		    (soft_blowfish_ctx_t *)active_op->context;
957 		blowfish_ctx_t *blowfish_ctx;
958 
959 		if (soft_blowfish_ctx != NULL) {
960 			blowfish_ctx =
961 			    (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
962 			if (blowfish_ctx != NULL) {
963 				explicit_bzero(blowfish_ctx->bc_keysched,
964 				    blowfish_ctx->bc_keysched_len);
965 				free(soft_blowfish_ctx->blowfish_cbc);
966 			}
967 
968 			freezero(soft_blowfish_ctx->key_sched,
969 			    soft_blowfish_ctx->keysched_len);
970 		}
971 		break;
972 	}
973 
974 	case CKM_RC4:
975 	{
976 		ARCFour_key *key = (ARCFour_key *)active_op->context;
977 
978 		if (key != NULL)
979 			explicit_bzero(key, sizeof (*key));
980 		break;
981 	}
982 
983 	case CKM_RSA_X_509:
984 	case CKM_RSA_PKCS:
985 	{
986 		soft_rsa_ctx_t *rsa_ctx =
987 		    (soft_rsa_ctx_t *)active_op->context;
988 
989 		if (rsa_ctx != NULL)
990 			if (rsa_ctx->key != NULL) {
991 				soft_cleanup_object(rsa_ctx->key);
992 				free(rsa_ctx->key);
993 			}
994 
995 		break;
996 	}
997 
998 	} /* switch */
999 
1000 	if (active_op->context != NULL) {
1001 		free(active_op->context);
1002 		active_op->context = NULL;
1003 	}
1004 
1005 	active_op->flags = 0;
1006 
1007 	if (!lock_held)
1008 		SES_REFRELE(session_p, lock_true);
1009 }
1010