xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softEncryptUtil.c (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
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 		return (soft_aes_crypt_init_common(session_p, pMechanism,
201 		    key_p, B_TRUE));
202 
203 	case CKM_RC4:
204 
205 		if (key_p->key_type != CKK_RC4) {
206 			return (CKR_KEY_TYPE_INCONSISTENT);
207 		}
208 
209 		return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
210 		    B_TRUE));
211 
212 	case CKM_RSA_X_509:
213 	case CKM_RSA_PKCS:
214 
215 		if (key_p->key_type != CKK_RSA) {
216 			return (CKR_KEY_TYPE_INCONSISTENT);
217 		}
218 
219 		return (soft_rsa_crypt_init_common(session_p, pMechanism,
220 		    key_p, B_TRUE));
221 
222 	case CKM_BLOWFISH_CBC:
223 	{
224 		soft_blowfish_ctx_t *soft_blowfish_ctx;
225 
226 		if (key_p->key_type != CKK_BLOWFISH)
227 			return (CKR_KEY_TYPE_INCONSISTENT);
228 
229 		if ((pMechanism->pParameter == NULL) ||
230 		    (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
231 			return (CKR_MECHANISM_PARAM_INVALID);
232 
233 		rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
234 		    key_p, B_TRUE);
235 
236 		if (rv != CKR_OK)
237 			return (rv);
238 
239 		(void) pthread_mutex_lock(&session_p->session_mutex);
240 
241 		soft_blowfish_ctx =
242 		    (soft_blowfish_ctx_t *)session_p->encrypt.context;
243 		/* Copy Initialization Vector (IV) into the context. */
244 		(void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
245 		    BLOWFISH_BLOCK_LEN);
246 
247 		/* Allocate a context for Blowfish cipher-block chaining */
248 		soft_blowfish_ctx->blowfish_cbc =
249 		    (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
250 		    soft_blowfish_ctx->keysched_len,
251 		    soft_blowfish_ctx->ivec);
252 
253 		if (soft_blowfish_ctx->blowfish_cbc == NULL) {
254 			freezero(soft_blowfish_ctx->key_sched,
255 			    soft_blowfish_ctx->keysched_len);
256 			freezero(session_p->encrypt.context,
257 			    sizeof (soft_blowfish_ctx_t));
258 			session_p->encrypt.context = NULL;
259 			rv = CKR_HOST_MEMORY;
260 		}
261 
262 		(void) pthread_mutex_unlock(&session_p->session_mutex);
263 
264 		return (rv);
265 	}
266 	default:
267 		return (CKR_MECHANISM_INVALID);
268 	}
269 }
270 
271 
272 /*
273  * soft_encrypt_common()
274  *
275  * Arguments:
276  *      session_p:	pointer to soft_session_t struct
277  *	pData:		pointer to the input data to be encrypted
278  *	ulDataLen:	length of the input data
279  *	pEncrypted:	pointer to the output data after encryption
280  *	pulEncryptedLen: pointer to the length of the output data
281  *	update:		boolean flag indicates caller is soft_encrypt
282  *			or soft_encrypt_update
283  *
284  * Description:
285  *      This function calls the corresponding encrypt routine based
286  *	on the mechanism.
287  *
288  * Returns:
289  *	see corresponding encrypt routine.
290  */
291 CK_RV
292 soft_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
293     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
294     CK_ULONG_PTR pulEncryptedLen, boolean_t update)
295 {
296 
297 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
298 
299 	switch (mechanism) {
300 
301 	case CKM_DES_ECB:
302 	case CKM_DES_CBC:
303 	case CKM_DES3_ECB:
304 	case CKM_DES3_CBC:
305 
306 		if (ulDataLen == 0) {
307 			*pulEncryptedLen = 0;
308 			return (CKR_OK);
309 		}
310 		/* FALLTHROUGH */
311 
312 	case CKM_DES_CBC_PAD:
313 	case CKM_DES3_CBC_PAD:
314 
315 		return (soft_des_encrypt_common(session_p, pData,
316 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
317 
318 	case CKM_AES_ECB:
319 	case CKM_AES_CBC:
320 	case CKM_AES_CTR:
321 	case CKM_AES_CCM:
322 	case CKM_AES_CMAC:
323 	case CKM_AES_CBC_PAD:
324 	case CKM_AES_GCM:
325 		if (update) {
326 			return (soft_aes_encrypt_update(session_p, pData,
327 			    ulDataLen, pEncrypted, pulEncryptedLen));
328 		} else {
329 			return (soft_aes_encrypt(session_p, pData,
330 			    ulDataLen, pEncrypted, pulEncryptedLen));
331 		}
332 
333 	case CKM_BLOWFISH_CBC:
334 
335 		if (ulDataLen == 0) {
336 			*pulEncryptedLen = 0;
337 			return (CKR_OK);
338 		}
339 
340 		return (soft_blowfish_encrypt_common(session_p, pData,
341 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
342 
343 	case CKM_RC4:
344 
345 		if (ulDataLen == 0) {
346 			*pulEncryptedLen = 0;
347 			return (CKR_OK);
348 		}
349 
350 		return (soft_arcfour_crypt(&(session_p->encrypt), pData,
351 		    ulDataLen, pEncrypted, pulEncryptedLen));
352 
353 	case CKM_RSA_X_509:
354 	case CKM_RSA_PKCS:
355 
356 		return (soft_rsa_encrypt_common(session_p, pData,
357 		    ulDataLen, pEncrypted, pulEncryptedLen, mechanism));
358 
359 	default:
360 		return (CKR_MECHANISM_INVALID);
361 	}
362 }
363 
364 
365 /*
366  * soft_encrypt()
367  *
368  * Arguments:
369  *      session_p:	pointer to soft_session_t struct
370  *	pData:		pointer to the input data to be encrypted
371  *	ulDataLen:	length of the input data
372  *	pEncryptedData:	pointer to the output data after encryption
373  *	pulEncryptedDataLen: pointer to the length of the output data
374  *
375  * Description:
376  *      called by C_Encrypt(). This function calls the soft_encrypt_common
377  *	routine.
378  *
379  * Returns:
380  *	see soft_encrypt_common().
381  */
382 CK_RV
383 soft_encrypt(soft_session_t *session_p, CK_BYTE_PTR pData,
384     CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
385     CK_ULONG_PTR pulEncryptedDataLen)
386 {
387 	return (soft_encrypt_common(session_p, pData, ulDataLen,
388 	    pEncryptedData, pulEncryptedDataLen, B_FALSE));
389 }
390 
391 
392 /*
393  * soft_encrypt_update()
394  *
395  * Arguments:
396  *      session_p:	pointer to soft_session_t struct
397  *      pPart:		pointer to the input data to be digested
398  *      ulPartLen:	length of the input data
399  *	pEncryptedPart:	pointer to the ciphertext
400  *	pulEncryptedPartLen: pointer to the length of the ciphertext
401  *
402  * Description:
403  *      called by C_EncryptUpdate(). This function calls the
404  *	soft_encrypt_common routine (with update flag on).
405  *
406  * Returns:
407  *	see soft_encrypt_common().
408  */
409 CK_RV
410 soft_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
411     CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
412     CK_ULONG_PTR pulEncryptedPartLen)
413 {
414 
415 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
416 
417 	switch (mechanism) {
418 
419 	case CKM_DES_ECB:
420 	case CKM_DES_CBC:
421 	case CKM_DES_CBC_PAD:
422 	case CKM_DES3_ECB:
423 	case CKM_DES3_CBC:
424 	case CKM_DES3_CBC_PAD:
425 	case CKM_AES_ECB:
426 	case CKM_AES_CBC:
427 	case CKM_AES_CBC_PAD:
428 	case CKM_AES_CMAC:
429 	case CKM_AES_CTR:
430 	case CKM_AES_GCM:
431 	case CKM_AES_CCM:
432 	case CKM_BLOWFISH_CBC:
433 	case CKM_RC4:
434 
435 		return (soft_encrypt_common(session_p, pPart, ulPartLen,
436 		    pEncryptedPart, pulEncryptedPartLen, B_TRUE));
437 
438 	default:
439 		/* PKCS11: The mechanism only supports single-part operation. */
440 		return (CKR_MECHANISM_INVALID);
441 	}
442 }
443 
444 
445 /*
446  * soft_encrypt_final()
447  *
448  * Arguments:
449  *      session_p:		pointer to soft_session_t struct
450  *      pLastEncryptedPart:	pointer to the last encrypted data part
451  *      pulLastEncryptedPartLen: pointer to the length of the last
452  *				encrypted data part
453  *
454  * Description:
455  *      called by C_EncryptFinal().
456  *
457  * Returns:
458  *	CKR_OK: success
459  *	CKR_FUNCTION_FAILED: encrypt final function failed
460  *	CKR_DATA_LEN_RANGE: remaining buffer contains bad length
461  */
462 CK_RV
463 soft_encrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastEncryptedPart,
464     CK_ULONG_PTR pulLastEncryptedPartLen)
465 {
466 
467 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
468 	CK_ULONG out_len;
469 	CK_RV rv = CKR_OK;
470 	int rc;
471 
472 	(void) pthread_mutex_lock(&session_p->session_mutex);
473 
474 	if (session_p->encrypt.context == NULL) {
475 		rv = CKR_OPERATION_NOT_INITIALIZED;
476 		*pulLastEncryptedPartLen = 0;
477 		goto clean1;
478 	}
479 	switch (mechanism) {
480 
481 	case CKM_DES_CBC_PAD:
482 	case CKM_DES3_CBC_PAD:
483 	{
484 		soft_des_ctx_t *soft_des_ctx;
485 
486 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
487 		/*
488 		 * For CKM_DES_CBC_PAD, compute output length with
489 		 * padding. If the remaining buffer has one block
490 		 * of data, then output length will be two blocksize of
491 		 * ciphertext. If the remaining buffer has less than
492 		 * one block of data, then output length will be
493 		 * one blocksize.
494 		 */
495 		if (soft_des_ctx->remain_len == DES_BLOCK_LEN)
496 			out_len = 2 * DES_BLOCK_LEN;
497 		else
498 			out_len = DES_BLOCK_LEN;
499 
500 		if (pLastEncryptedPart == NULL) {
501 			/*
502 			 * Application asks for the length of the output
503 			 * buffer to hold the ciphertext.
504 			 */
505 			*pulLastEncryptedPartLen = out_len;
506 			goto clean1;
507 		} else {
508 			crypto_data_t out;
509 
510 			/* Copy remaining data to the output buffer. */
511 			(void) memcpy(pLastEncryptedPart, soft_des_ctx->data,
512 			    soft_des_ctx->remain_len);
513 
514 			/*
515 			 * Add padding bytes prior to encrypt final.
516 			 */
517 			soft_add_pkcs7_padding(pLastEncryptedPart +
518 			    soft_des_ctx->remain_len, DES_BLOCK_LEN,
519 			    soft_des_ctx->remain_len);
520 
521 			out.cd_format = CRYPTO_DATA_RAW;
522 			out.cd_offset = 0;
523 			out.cd_length = out_len;
524 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
525 			out.cd_raw.iov_len = out_len;
526 
527 			/* Encrypt multiple blocks of data. */
528 			rc = des_encrypt_contiguous_blocks(
529 			    (des_ctx_t *)soft_des_ctx->des_cbc,
530 			    (char *)pLastEncryptedPart, out_len, &out);
531 
532 			if (rc == 0) {
533 				*pulLastEncryptedPartLen = out_len;
534 			} else {
535 				*pulLastEncryptedPartLen = 0;
536 				rv = CKR_FUNCTION_FAILED;
537 			}
538 
539 			/* Cleanup memory space. */
540 			free(soft_des_ctx->des_cbc);
541 			freezero(soft_des_ctx->key_sched,
542 			    soft_des_ctx->keysched_len);
543 		}
544 
545 		break;
546 	}
547 	case CKM_DES_CBC:
548 	case CKM_DES_ECB:
549 	case CKM_DES3_CBC:
550 	case CKM_DES3_ECB:
551 	{
552 
553 		soft_des_ctx_t *soft_des_ctx;
554 
555 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
556 		/*
557 		 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
558 		 * so when the final is called, the remaining buffer
559 		 * should not contain any more data.
560 		 */
561 		*pulLastEncryptedPartLen = 0;
562 		if (soft_des_ctx->remain_len != 0) {
563 			rv = CKR_DATA_LEN_RANGE;
564 		} else {
565 			if (pLastEncryptedPart == NULL)
566 				goto clean1;
567 		}
568 
569 		/* Cleanup memory space. */
570 		free(soft_des_ctx->des_cbc);
571 		freezero(soft_des_ctx->key_sched,
572 		    soft_des_ctx->keysched_len);
573 
574 		break;
575 	}
576 	case CKM_AES_CBC_PAD:
577 	case CKM_AES_CMAC:
578 	case CKM_AES_CBC:
579 	case CKM_AES_ECB:
580 	case CKM_AES_CTR:
581 	case CKM_AES_CCM:
582 	case CKM_AES_GCM:
583 		rv = soft_aes_encrypt_final(session_p, pLastEncryptedPart,
584 		    pulLastEncryptedPartLen);
585 		break;
586 
587 	case CKM_BLOWFISH_CBC:
588 	{
589 		soft_blowfish_ctx_t *soft_blowfish_ctx;
590 
591 		soft_blowfish_ctx =
592 		    (soft_blowfish_ctx_t *)session_p->encrypt.context;
593 		/*
594 		 * CKM_BLOWFISH_CBC does not do any padding, so when the
595 		 * final is called, the remaining buffer should not contain
596 		 * any more data
597 		 */
598 		*pulLastEncryptedPartLen = 0;
599 		if (soft_blowfish_ctx->remain_len != 0)
600 			rv = CKR_DATA_LEN_RANGE;
601 		else {
602 			if (pLastEncryptedPart == NULL)
603 				goto clean1;
604 		}
605 
606 		free(soft_blowfish_ctx->blowfish_cbc);
607 		freezero(soft_blowfish_ctx->key_sched,
608 		    soft_blowfish_ctx->keysched_len);
609 		break;
610 	}
611 
612 	case CKM_RC4:
613 	{
614 		ARCFour_key *key = (ARCFour_key *)session_p->encrypt.context;
615 		/* Remaining data size is always zero for RC4. */
616 		*pulLastEncryptedPartLen = 0;
617 		if (pLastEncryptedPart == NULL)
618 			goto clean1;
619 		explicit_bzero(key, sizeof (*key));
620 		break;
621 	}
622 	default:
623 		/* PKCS11: The mechanism only supports single-part operation. */
624 		rv = CKR_MECHANISM_INVALID;
625 		break;
626 	}
627 
628 	free(session_p->encrypt.context);
629 	session_p->encrypt.context = NULL;
630 clean1:
631 	(void) pthread_mutex_unlock(&session_p->session_mutex);
632 
633 	return (rv);
634 }
635 
636 /*
637  * This function frees the allocated active crypto context and the
638  * lower level of allocated struct as needed.
639  * This function is called by the 1st tier of encrypt/decrypt routines
640  * or by the 2nd tier of session close routine. Since the 1st tier
641  * caller will always call this function without locking the session
642  * mutex and the 2nd tier caller will call with the lock, we add the
643  * third parameter "lock_held" to distinguish this case.
644  */
645 void
646 soft_crypt_cleanup(soft_session_t *session_p, boolean_t encrypt,
647     boolean_t lock_held)
648 {
649 
650 	crypto_active_op_t *active_op;
651 	boolean_t lock_true = B_TRUE;
652 
653 	if (!lock_held)
654 		(void) pthread_mutex_lock(&session_p->session_mutex);
655 
656 	active_op = (encrypt) ? &(session_p->encrypt) : &(session_p->decrypt);
657 
658 	switch (active_op->mech.mechanism) {
659 
660 	case CKM_DES_CBC_PAD:
661 	case CKM_DES3_CBC_PAD:
662 	case CKM_DES_CBC:
663 	case CKM_DES_ECB:
664 	case CKM_DES3_CBC:
665 	case CKM_DES3_ECB:
666 	{
667 
668 		soft_des_ctx_t *soft_des_ctx =
669 		    (soft_des_ctx_t *)active_op->context;
670 		des_ctx_t *des_ctx;
671 
672 		if (soft_des_ctx != NULL) {
673 			des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
674 			if (des_ctx != NULL) {
675 				explicit_bzero(des_ctx->dc_keysched,
676 				    des_ctx->dc_keysched_len);
677 				free(soft_des_ctx->des_cbc);
678 			}
679 			freezero(soft_des_ctx->key_sched,
680 			    soft_des_ctx->keysched_len);
681 		}
682 		break;
683 	}
684 
685 	case CKM_AES_CBC_PAD:
686 	case CKM_AES_CBC:
687 	case CKM_AES_CMAC:
688 	case CKM_AES_ECB:
689 	case CKM_AES_GCM:
690 	case CKM_AES_CCM:
691 	case CKM_AES_CTR:
692 		soft_aes_free_ctx(active_op->context);
693 		active_op->context = NULL;
694 		break;
695 
696 	case CKM_BLOWFISH_CBC:
697 	{
698 		soft_blowfish_ctx_t *soft_blowfish_ctx =
699 		    (soft_blowfish_ctx_t *)active_op->context;
700 		blowfish_ctx_t *blowfish_ctx;
701 
702 		if (soft_blowfish_ctx != NULL) {
703 			blowfish_ctx =
704 			    (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
705 			if (blowfish_ctx != NULL) {
706 				explicit_bzero(blowfish_ctx->bc_keysched,
707 				    blowfish_ctx->bc_keysched_len);
708 				free(soft_blowfish_ctx->blowfish_cbc);
709 			}
710 
711 			freezero(soft_blowfish_ctx->key_sched,
712 			    soft_blowfish_ctx->keysched_len);
713 		}
714 		break;
715 	}
716 
717 	case CKM_RC4:
718 	{
719 		ARCFour_key *key = (ARCFour_key *)active_op->context;
720 
721 		if (key != NULL)
722 			explicit_bzero(key, sizeof (*key));
723 		break;
724 	}
725 
726 	case CKM_RSA_X_509:
727 	case CKM_RSA_PKCS:
728 	{
729 		soft_rsa_ctx_t *rsa_ctx =
730 		    (soft_rsa_ctx_t *)active_op->context;
731 
732 		if (rsa_ctx != NULL)
733 			if (rsa_ctx->key != NULL) {
734 				soft_cleanup_object(rsa_ctx->key);
735 				free(rsa_ctx->key);
736 			}
737 
738 		break;
739 	}
740 
741 	} /* switch */
742 
743 	if (active_op->context != NULL) {
744 		free(active_op->context);
745 		active_op->context = NULL;
746 	}
747 
748 	active_op->flags = 0;
749 
750 	if (!lock_held)
751 		SES_REFRELE(session_p, lock_true);
752 }
753