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