xref: /titanic_52/usr/src/lib/pkcs11/pkcs11_softtoken/common/softEncryptUtil.c (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <pthread.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <sys/types.h>
34 #include <security/cryptoki.h>
35 #include <des_cbc_crypt.h>
36 #include <aes_cbc_crypt.h>
37 #include <arcfour.h>
38 #include "softSession.h"
39 #include "softObject.h"
40 #include "softOps.h"
41 #include "softCrypt.h"
42 #include "softRSA.h"
43 
44 /*
45  * Add padding bytes with the value of length of padding.
46  */
47 void
48 soft_add_pkcs7_padding(CK_BYTE *buf, int block_size, CK_ULONG data_len)
49 {
50 
51 	ulong_t i, pad_len;
52 	CK_BYTE pad_value;
53 
54 	pad_len = block_size - (data_len % block_size);
55 	pad_value = (CK_BYTE)pad_len;
56 
57 	for (i = 0; i < pad_len; i++)
58 		buf[i] = pad_value;
59 }
60 
61 /*
62  * Perform encrypt init operation internally for the support of
63  * CKM_DES_MAC and CKM_DES_MAC_GENERAL
64  *
65  * This function is called with the session being held, and without
66  * its mutex taken.
67  */
68 CK_RV
69 soft_encrypt_init_internal(soft_session_t *session_p, CK_MECHANISM_PTR
70 	pMechanism, soft_object_t *key_p)
71 {
72 	CK_RV rv;
73 
74 	(void) pthread_mutex_lock(&session_p->session_mutex);
75 
76 	/* Check to see if encrypt operation is already active */
77 	if (session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE) {
78 		(void) pthread_mutex_unlock(&session_p->session_mutex);
79 		return (CKR_OPERATION_ACTIVE);
80 	}
81 
82 	session_p->encrypt.flags = CRYPTO_OPERATION_ACTIVE;
83 
84 	(void) pthread_mutex_unlock(&session_p->session_mutex);
85 
86 	rv = soft_encrypt_init(session_p, pMechanism, key_p);
87 
88 	if (rv != CKR_OK) {
89 		(void) pthread_mutex_lock(&session_p->session_mutex);
90 		session_p->encrypt.flags &= ~CRYPTO_OPERATION_ACTIVE;
91 		(void) pthread_mutex_unlock(&session_p->session_mutex);
92 	}
93 
94 	return (rv);
95 }
96 
97 /*
98  * soft_encrypt_init()
99  *
100  * Arguments:
101  *	session_p:	pointer to soft_session_t struct
102  *	pMechanism:	pointer to CK_MECHANISM struct provided by application
103  *	key_p:		pointer to key soft_object_t struct
104  *
105  * Description:
106  *	called by C_EncryptInit(). This function calls the corresponding
107  *	encrypt init routine based on the mechanism.
108  *
109  * Returns:
110  *	CKR_OK: success
111  *	CKR_HOST_MEMORY: run out of system memory
112  *	CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
113  *	CKR_MECHANISM_INVALID: invalid mechanism type
114  *	CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
115  *		with the specified mechanism
116  */
117 CK_RV
118 soft_encrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
119     soft_object_t *key_p)
120 {
121 
122 	CK_RV rv;
123 
124 	switch (pMechanism->mechanism) {
125 
126 	case CKM_DES_ECB:
127 
128 		if (key_p->key_type != CKK_DES) {
129 			return (CKR_KEY_TYPE_INCONSISTENT);
130 		}
131 		goto ecb_common;
132 
133 	case CKM_DES3_ECB:
134 
135 		if ((key_p->key_type != CKK_DES2) &&
136 		    (key_p->key_type != CKK_DES3)) {
137 			return (CKR_KEY_TYPE_INCONSISTENT);
138 		}
139 
140 ecb_common:
141 		return (soft_des_crypt_init_common(session_p, pMechanism,
142 		    key_p, B_TRUE));
143 
144 	case CKM_DES_CBC:
145 	case CKM_DES_CBC_PAD:
146 
147 		if (key_p->key_type != CKK_DES) {
148 			return (CKR_KEY_TYPE_INCONSISTENT);
149 		}
150 
151 		goto cbc_common;
152 
153 	case CKM_DES3_CBC:
154 	case CKM_DES3_CBC_PAD:
155 	{
156 
157 		soft_des_ctx_t *soft_des_ctx;
158 
159 		if ((key_p->key_type != CKK_DES2) &&
160 		    (key_p->key_type != CKK_DES3)) {
161 			return (CKR_KEY_TYPE_INCONSISTENT);
162 		}
163 
164 cbc_common:
165 		if ((pMechanism->pParameter == NULL) ||
166 		    (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
167 			return (CKR_MECHANISM_PARAM_INVALID);
168 		}
169 
170 		rv = soft_des_crypt_init_common(session_p, pMechanism,
171 		    key_p, B_TRUE);
172 
173 		if (rv != CKR_OK)
174 			return (rv);
175 
176 		(void) pthread_mutex_lock(&session_p->session_mutex);
177 
178 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
179 		/* Copy Initialization Vector (IV) into the context. */
180 		(void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
181 		    DES_BLOCK_LEN);
182 
183 		/* Allocate a context for DES cipher-block chaining. */
184 		soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
185 		    soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
186 		    soft_des_ctx->ivec, key_p->key_type);
187 
188 		if (soft_des_ctx->des_cbc == NULL) {
189 			bzero(soft_des_ctx->key_sched,
190 			    soft_des_ctx->keysched_len);
191 			free(soft_des_ctx->key_sched);
192 			free(session_p->encrypt.context);
193 			session_p->encrypt.context = NULL;
194 			rv = CKR_HOST_MEMORY;
195 		}
196 
197 		(void) pthread_mutex_unlock(&session_p->session_mutex);
198 
199 		return (rv);
200 	}
201 	case CKM_AES_ECB:
202 
203 		if (key_p->key_type != CKK_AES) {
204 			return (CKR_KEY_TYPE_INCONSISTENT);
205 		}
206 
207 		return (soft_aes_crypt_init_common(session_p, pMechanism,
208 		    key_p, B_TRUE));
209 
210 	case CKM_AES_CBC:
211 	case CKM_AES_CBC_PAD:
212 	{
213 		soft_aes_ctx_t *soft_aes_ctx;
214 
215 		if (key_p->key_type != CKK_AES) {
216 			return (CKR_KEY_TYPE_INCONSISTENT);
217 		}
218 
219 		if ((pMechanism->pParameter == NULL) ||
220 		    (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
221 			return (CKR_MECHANISM_PARAM_INVALID);
222 		}
223 
224 		rv = soft_aes_crypt_init_common(session_p, pMechanism,
225 		    key_p, B_TRUE);
226 
227 		if (rv != CKR_OK)
228 			return (rv);
229 
230 		(void) pthread_mutex_lock(&session_p->session_mutex);
231 
232 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
233 		/* Copy Initialization Vector (IV) into the context. */
234 		(void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
235 		    AES_BLOCK_LEN);
236 
237 		/* Allocate a context for AES cipher-block chaining. */
238 		soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
239 		    soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
240 		    soft_aes_ctx->ivec);
241 
242 		if (soft_aes_ctx->aes_cbc == NULL) {
243 			bzero(soft_aes_ctx->key_sched,
244 			    soft_aes_ctx->keysched_len);
245 			free(soft_aes_ctx->key_sched);
246 			free(session_p->encrypt.context);
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_RC4:
256 
257 		if (key_p->key_type != CKK_RC4) {
258 			return (CKR_KEY_TYPE_INCONSISTENT);
259 		}
260 
261 		return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
262 		    B_TRUE));
263 
264 	case CKM_RSA_X_509:
265 	case CKM_RSA_PKCS:
266 
267 		if (key_p->key_type != CKK_RSA) {
268 			return (CKR_KEY_TYPE_INCONSISTENT);
269 		}
270 
271 		return (soft_rsa_crypt_init_common(session_p, pMechanism,
272 		    key_p, B_TRUE));
273 
274 	default:
275 		return (CKR_MECHANISM_INVALID);
276 	}
277 }
278 
279 
280 /*
281  * soft_encrypt_common()
282  *
283  * Arguments:
284  *      session_p:	pointer to soft_session_t struct
285  *	pData:		pointer to the input data to be encrypted
286  *	ulDataLen:	length of the input data
287  *	pEncrypted:	pointer to the output data after encryption
288  *	pulEncryptedLen: pointer to the length of the output data
289  *	update:		boolean flag indicates caller is soft_encrypt
290  *			or soft_encrypt_update
291  *
292  * Description:
293  *      This function calls the corresponding encrypt routine based
294  *	on the mechanism.
295  *
296  * Returns:
297  *	see corresponding encrypt routine.
298  */
299 CK_RV
300 soft_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
301     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
302     CK_ULONG_PTR pulEncryptedLen, boolean_t update)
303 {
304 
305 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
306 
307 	switch (mechanism) {
308 
309 	case CKM_DES_ECB:
310 	case CKM_DES_CBC:
311 	case CKM_DES_CBC_PAD:
312 	case CKM_DES3_ECB:
313 	case CKM_DES3_CBC:
314 	case CKM_DES3_CBC_PAD:
315 
316 		return (soft_des_encrypt_common(session_p, pData,
317 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
318 
319 	case CKM_AES_ECB:
320 	case CKM_AES_CBC:
321 	case CKM_AES_CBC_PAD:
322 
323 		return (soft_aes_encrypt_common(session_p, pData,
324 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
325 
326 	case CKM_RC4:
327 	{
328 		ARCFour_key *keystream = session_p->encrypt.context;
329 		CK_RV rv;
330 
331 		rv = soft_arcfour_crypt(&(session_p->encrypt), pData,
332 		    ulDataLen, pEncrypted, pulEncryptedLen);
333 		if ((rv == CKR_OK) && (pEncrypted != NULL)) {
334 			bzero(keystream, sizeof (*keystream));
335 			free(keystream);
336 			session_p->encrypt.context = NULL;
337 		}
338 		return (rv);
339 	}
340 
341 	case CKM_RSA_X_509:
342 	case CKM_RSA_PKCS:
343 
344 		return (soft_rsa_encrypt_common(session_p, pData,
345 		    ulDataLen, pEncrypted, pulEncryptedLen, mechanism));
346 
347 	default:
348 		return (CKR_MECHANISM_INVALID);
349 	}
350 }
351 
352 
353 /*
354  * soft_encrypt()
355  *
356  * Arguments:
357  *      session_p:	pointer to soft_session_t struct
358  *	pData:		pointer to the input data to be encrypted
359  *	ulDataLen:	length of the input data
360  *	pEncryptedData:	pointer to the output data after encryption
361  *	pulEncryptedDataLen: pointer to the length of the output data
362  *
363  * Description:
364  *      called by C_Encrypt(). This function calls the soft_encrypt_common
365  *	routine.
366  *
367  * Returns:
368  *	see soft_encrypt_common().
369  */
370 CK_RV
371 soft_encrypt(soft_session_t *session_p, CK_BYTE_PTR pData,
372     CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
373     CK_ULONG_PTR pulEncryptedDataLen)
374 {
375 
376 	return (soft_encrypt_common(session_p, pData, ulDataLen,
377 	    pEncryptedData, pulEncryptedDataLen, B_FALSE));
378 }
379 
380 
381 /*
382  * soft_encrypt_update()
383  *
384  * Arguments:
385  *      session_p:	pointer to soft_session_t struct
386  *      pPart:		pointer to the input data to be digested
387  *      ulPartLen:	length of the input data
388  *	pEncryptedPart:	pointer to the ciphertext
389  *	pulEncryptedPartLen: pointer to the length of the ciphertext
390  *
391  * Description:
392  *      called by C_EncryptUpdate(). This function calls the
393  *	soft_encrypt_common routine (with update flag on).
394  *
395  * Returns:
396  *	see soft_encrypt_common().
397  */
398 CK_RV
399 soft_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
400 	CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
401 	CK_ULONG_PTR pulEncryptedPartLen)
402 {
403 
404 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
405 
406 	switch (mechanism) {
407 
408 	case CKM_DES_ECB:
409 	case CKM_DES_CBC:
410 	case CKM_DES_CBC_PAD:
411 	case CKM_DES3_ECB:
412 	case CKM_DES3_CBC:
413 	case CKM_DES3_CBC_PAD:
414 	case CKM_AES_ECB:
415 	case CKM_AES_CBC:
416 	case CKM_AES_CBC_PAD:
417 
418 		return (soft_encrypt_common(session_p, pPart, ulPartLen,
419 		    pEncryptedPart, pulEncryptedPartLen, B_TRUE));
420 
421 	case CKM_RC4:
422 
423 		return (soft_arcfour_crypt(&(session_p->encrypt), pPart,
424 		    ulPartLen, pEncryptedPart, pulEncryptedPartLen));
425 
426 	default:
427 		/* PKCS11: The mechanism only supports single-part operation. */
428 		return (CKR_MECHANISM_INVALID);
429 	}
430 }
431 
432 
433 /*
434  * soft_encrypt_final()
435  *
436  * Arguments:
437  *      session_p:		pointer to soft_session_t struct
438  *      pLastEncryptedPart:	pointer to the last encrypted data part
439  *      pulLastEncryptedPartLen: pointer to the length of the last
440  *				encrypted data part
441  *
442  * Description:
443  *      called by C_EncryptFinal().
444  *
445  * Returns:
446  *	CKR_OK: success
447  *	CKR_FUNCTION_FAILED: encrypt final function failed
448  *	CKR_DATA_LEN_RANGE: remaining buffer contains bad length
449  */
450 CK_RV
451 soft_encrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastEncryptedPart,
452 	CK_ULONG_PTR pulLastEncryptedPartLen)
453 {
454 
455 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
456 	CK_ULONG out_len;
457 	CK_RV rv = CKR_OK;
458 	int rc;
459 
460 	(void) pthread_mutex_lock(&session_p->session_mutex);
461 
462 	if (session_p->encrypt.context == NULL) {
463 		rv = CKR_OPERATION_NOT_INITIALIZED;
464 		*pulLastEncryptedPartLen = 0;
465 		goto clean1;
466 	}
467 	switch (mechanism) {
468 
469 	case CKM_DES_CBC_PAD:
470 	case CKM_DES3_CBC_PAD:
471 	{
472 		soft_des_ctx_t *soft_des_ctx;
473 
474 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
475 		/*
476 		 * For CKM_DES_CBC_PAD, compute output length with
477 		 * padding. If the remaining buffer has one block
478 		 * of data, then output length will be two blocksize of
479 		 * ciphertext. If the remaining buffer has less than
480 		 * one block of data, then output length will be
481 		 * one blocksize.
482 		 */
483 		if (soft_des_ctx->remain_len == DES_BLOCK_LEN)
484 			out_len = 2 * DES_BLOCK_LEN;
485 		else
486 			out_len = DES_BLOCK_LEN;
487 
488 		if (pLastEncryptedPart == NULL) {
489 			/*
490 			 * Application asks for the length of the output
491 			 * buffer to hold the ciphertext.
492 			 */
493 			*pulLastEncryptedPartLen = out_len;
494 			goto clean1;
495 		} else {
496 			crypto_data_t out;
497 
498 			/* Copy remaining data to the output buffer. */
499 			(void) memcpy(pLastEncryptedPart, soft_des_ctx->data,
500 			    soft_des_ctx->remain_len);
501 
502 			/*
503 			 * Add padding bytes prior to encrypt final.
504 			 */
505 			soft_add_pkcs7_padding(pLastEncryptedPart +
506 			    soft_des_ctx->remain_len, DES_BLOCK_LEN,
507 			    soft_des_ctx->remain_len);
508 
509 			out.cd_format = CRYPTO_DATA_RAW;
510 			out.cd_offset = 0;
511 			out.cd_length = out_len;
512 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
513 			out.cd_raw.iov_len = out_len;
514 
515 			/* Encrypt multiple blocks of data. */
516 			rc = des_encrypt_contiguous_blocks(
517 			    (des_ctx_t *)soft_des_ctx->des_cbc,
518 			    (char *)pLastEncryptedPart, out_len, &out);
519 
520 			if (rc == 0) {
521 				*pulLastEncryptedPartLen = out_len;
522 			} else {
523 				*pulLastEncryptedPartLen = 0;
524 				rv = CKR_FUNCTION_FAILED;
525 			}
526 
527 			/* Cleanup memory space. */
528 			free(soft_des_ctx->des_cbc);
529 			bzero(soft_des_ctx->key_sched,
530 			    soft_des_ctx->keysched_len);
531 			free(soft_des_ctx->key_sched);
532 		}
533 
534 		break;
535 	}
536 	case CKM_DES_CBC:
537 	case CKM_DES_ECB:
538 	case CKM_DES3_CBC:
539 	case CKM_DES3_ECB:
540 	{
541 
542 		soft_des_ctx_t *soft_des_ctx;
543 
544 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
545 		/*
546 		 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
547 		 * so when the final is called, the remaining buffer
548 		 * should not contain any more data.
549 		 */
550 		*pulLastEncryptedPartLen = 0;
551 		if (soft_des_ctx->remain_len != 0) {
552 			rv = CKR_DATA_LEN_RANGE;
553 		} else {
554 			if (pLastEncryptedPart == NULL)
555 				goto clean1;
556 		}
557 
558 		/* Cleanup memory space. */
559 		free(soft_des_ctx->des_cbc);
560 		bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
561 		free(soft_des_ctx->key_sched);
562 
563 		break;
564 	}
565 	case CKM_AES_CBC_PAD:
566 	{
567 		soft_aes_ctx_t *soft_aes_ctx;
568 
569 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
570 		/*
571 		 * For CKM_AES_CBC_PAD, compute output length with
572 		 * padding. If the remaining buffer has one block
573 		 * of data, then output length will be two blocksize of
574 		 * ciphertext. If the remaining buffer has less than
575 		 * one block of data, then output length will be
576 		 * one blocksize.
577 		 */
578 		if (soft_aes_ctx->remain_len == AES_BLOCK_LEN)
579 			out_len = 2 * AES_BLOCK_LEN;
580 		else
581 			out_len = AES_BLOCK_LEN;
582 
583 		if (pLastEncryptedPart == NULL) {
584 			/*
585 			 * Application asks for the length of the output
586 			 * buffer to hold the ciphertext.
587 			 */
588 			*pulLastEncryptedPartLen = out_len;
589 			goto clean1;
590 		} else {
591 			crypto_data_t out;
592 
593 			/* Copy remaining data to the output buffer. */
594 			(void) memcpy(pLastEncryptedPart, soft_aes_ctx->data,
595 			    soft_aes_ctx->remain_len);
596 
597 			/*
598 			 * Add padding bytes prior to encrypt final.
599 			 */
600 			soft_add_pkcs7_padding(pLastEncryptedPart +
601 			    soft_aes_ctx->remain_len, AES_BLOCK_LEN,
602 			    soft_aes_ctx->remain_len);
603 
604 			out.cd_format = CRYPTO_DATA_RAW;
605 			out.cd_offset = 0;
606 			out.cd_length = out_len;
607 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
608 			out.cd_raw.iov_len = out_len;
609 
610 			/* Encrypt multiple blocks of data. */
611 			rc = aes_encrypt_contiguous_blocks(
612 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
613 			    (char *)pLastEncryptedPart, out_len, &out);
614 
615 			if (rc == 0) {
616 				*pulLastEncryptedPartLen = out_len;
617 			} else {
618 				*pulLastEncryptedPartLen = 0;
619 				rv = CKR_FUNCTION_FAILED;
620 			}
621 
622 			/* Cleanup memory space. */
623 			free(soft_aes_ctx->aes_cbc);
624 			bzero(soft_aes_ctx->key_sched,
625 			    soft_aes_ctx->keysched_len);
626 			free(soft_aes_ctx->key_sched);
627 		}
628 
629 		break;
630 	}
631 	case CKM_AES_CBC:
632 	case CKM_AES_ECB:
633 	{
634 
635 		soft_aes_ctx_t *soft_aes_ctx;
636 
637 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
638 		/*
639 		 * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
640 		 * so when the final is called, the remaining buffer
641 		 * should not contain any more data.
642 		 */
643 		*pulLastEncryptedPartLen = 0;
644 		if (soft_aes_ctx->remain_len != 0) {
645 			rv = CKR_DATA_LEN_RANGE;
646 		} else {
647 			if (pLastEncryptedPart == NULL)
648 				goto clean1;
649 		}
650 
651 		/* Cleanup memory space. */
652 		free(soft_aes_ctx->aes_cbc);
653 		bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
654 		free(soft_aes_ctx->key_sched);
655 
656 		break;
657 	}
658 
659 	case CKM_RC4:
660 	{
661 		ARCFour_key *key = (ARCFour_key *)session_p->encrypt.context;
662 		bzero(key, sizeof (*key));
663 		*pulLastEncryptedPartLen = 0;
664 		break;
665 	}
666 	default:
667 		/* PKCS11: The mechanism only supports single-part operation. */
668 		rv = CKR_MECHANISM_INVALID;
669 		break;
670 	}
671 
672 	free(session_p->encrypt.context);
673 	session_p->encrypt.context = NULL;
674 clean1:
675 	(void) pthread_mutex_unlock(&session_p->session_mutex);
676 
677 	return (rv);
678 }
679 
680 /*
681  * This function frees the allocated active crypto context and the
682  * lower level of allocated struct as needed.
683  * This function is called by the 1st tier of encrypt/decrypt routines
684  * or by the 2nd tier of session close routine. Since the 1st tier
685  * caller will always call this function without locking the session
686  * mutex and the 2nd tier caller will call with the lock, we add the
687  * third parameter "lock_held" to distiguish this case.
688  */
689 void
690 soft_crypt_cleanup(soft_session_t *session_p, boolean_t encrypt,
691 	boolean_t lock_held)
692 {
693 
694 	crypto_active_op_t *active_op;
695 	boolean_t lock_true = B_TRUE;
696 
697 	if (!lock_held)
698 		(void) pthread_mutex_lock(&session_p->session_mutex);
699 
700 	active_op = (encrypt) ? &(session_p->encrypt) : &(session_p->decrypt);
701 
702 	switch (active_op->mech.mechanism) {
703 
704 	case CKM_DES_CBC_PAD:
705 	case CKM_DES3_CBC_PAD:
706 	case CKM_DES_CBC:
707 	case CKM_DES_ECB:
708 	case CKM_DES3_CBC:
709 	case CKM_DES3_ECB:
710 	{
711 
712 		soft_des_ctx_t *soft_des_ctx =
713 		    (soft_des_ctx_t *)active_op->context;
714 		des_ctx_t *des_ctx;
715 
716 		if (soft_des_ctx != NULL) {
717 			des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
718 			if (des_ctx != NULL) {
719 				bzero(des_ctx->dc_keysched,
720 				    des_ctx->dc_keysched_len);
721 				free(soft_des_ctx->des_cbc);
722 			}
723 			bzero(soft_des_ctx->key_sched,
724 			    soft_des_ctx->keysched_len);
725 			free(soft_des_ctx->key_sched);
726 		}
727 		break;
728 	}
729 
730 	case CKM_AES_CBC_PAD:
731 	case CKM_AES_CBC:
732 	case CKM_AES_ECB:
733 	{
734 		soft_aes_ctx_t *soft_aes_ctx =
735 		    (soft_aes_ctx_t *)active_op->context;
736 		aes_ctx_t *aes_ctx;
737 
738 		if (soft_aes_ctx != NULL) {
739 			aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
740 			if (aes_ctx != NULL) {
741 				bzero(aes_ctx->ac_keysched,
742 				    aes_ctx->ac_keysched_len);
743 				free(soft_aes_ctx->aes_cbc);
744 			}
745 			bzero(soft_aes_ctx->key_sched,
746 			    soft_aes_ctx->keysched_len);
747 			free(soft_aes_ctx->key_sched);
748 		}
749 		break;
750 	}
751 
752 	case CKM_RC4:
753 	{
754 		ARCFour_key *key = (ARCFour_key *)active_op->context;
755 
756 		if (key != NULL)
757 			bzero(key, sizeof (*key));
758 		break;
759 	}
760 
761 	case CKM_RSA_X_509:
762 	case CKM_RSA_PKCS:
763 		break;
764 
765 	} /* switch */
766 
767 	if (active_op->context != NULL) {
768 		free(active_op->context);
769 		active_op->context = NULL;
770 	}
771 
772 	active_op->flags = 0;
773 
774 	if (!lock_held)
775 		SES_REFRELE(session_p, lock_true);
776 }
777