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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
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 <des_cbc_crypt.h>
35 #include <aes_cbc_crypt.h>
36 #include <blowfish_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 	case CKM_BLOWFISH_CBC:
275 	{
276 		soft_blowfish_ctx_t *soft_blowfish_ctx;
277 
278 		if (key_p->key_type != CKK_BLOWFISH)
279 			return (CKR_KEY_TYPE_INCONSISTENT);
280 
281 		if ((pMechanism->pParameter == NULL) ||
282 		    (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
283 			return (CKR_MECHANISM_PARAM_INVALID);
284 
285 		rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
286 		    key_p, B_TRUE);
287 
288 		if (rv != CKR_OK)
289 			return (rv);
290 
291 		(void) pthread_mutex_lock(&session_p->session_mutex);
292 
293 		soft_blowfish_ctx =
294 		    (soft_blowfish_ctx_t *)session_p->encrypt.context;
295 		/* Copy Initialization Vector (IV) into the context. */
296 		(void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
297 		    BLOWFISH_BLOCK_LEN);
298 
299 		/* Allocate a context for Blowfish cipher-block chaining */
300 		soft_blowfish_ctx->blowfish_cbc =
301 		    (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
302 			soft_blowfish_ctx->keysched_len,
303 			soft_blowfish_ctx->ivec);
304 
305 		if (soft_blowfish_ctx->blowfish_cbc == NULL) {
306 			bzero(soft_blowfish_ctx->key_sched,
307 			    soft_blowfish_ctx->keysched_len);
308 			free(soft_blowfish_ctx->key_sched);
309 			free(session_p->encrypt.context);
310 			session_p->encrypt.context = NULL;
311 			rv = CKR_HOST_MEMORY;
312 		}
313 
314 		(void) pthread_mutex_unlock(&session_p->session_mutex);
315 
316 		return (rv);
317 	}
318 	default:
319 		return (CKR_MECHANISM_INVALID);
320 	}
321 }
322 
323 
324 /*
325  * soft_encrypt_common()
326  *
327  * Arguments:
328  *      session_p:	pointer to soft_session_t struct
329  *	pData:		pointer to the input data to be encrypted
330  *	ulDataLen:	length of the input data
331  *	pEncrypted:	pointer to the output data after encryption
332  *	pulEncryptedLen: pointer to the length of the output data
333  *	update:		boolean flag indicates caller is soft_encrypt
334  *			or soft_encrypt_update
335  *
336  * Description:
337  *      This function calls the corresponding encrypt routine based
338  *	on the mechanism.
339  *
340  * Returns:
341  *	see corresponding encrypt routine.
342  */
343 CK_RV
344 soft_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
345     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
346     CK_ULONG_PTR pulEncryptedLen, boolean_t update)
347 {
348 
349 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
350 
351 	switch (mechanism) {
352 
353 	case CKM_DES_ECB:
354 	case CKM_DES_CBC:
355 	case CKM_DES3_ECB:
356 	case CKM_DES3_CBC:
357 
358 		if (ulDataLen == 0) {
359 			*pulEncryptedLen = 0;
360 			return (CKR_OK);
361 		}
362 		/* FALLTHROUGH */
363 
364 	case CKM_DES_CBC_PAD:
365 	case CKM_DES3_CBC_PAD:
366 
367 		return (soft_des_encrypt_common(session_p, pData,
368 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
369 
370 	case CKM_AES_ECB:
371 	case CKM_AES_CBC:
372 
373 		if (ulDataLen == 0) {
374 			*pulEncryptedLen = 0;
375 			return (CKR_OK);
376 		}
377 		/* FALLTHROUGH */
378 
379 	case CKM_AES_CBC_PAD:
380 
381 		return (soft_aes_encrypt_common(session_p, pData,
382 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
383 
384 	case CKM_BLOWFISH_CBC:
385 
386 		if (ulDataLen == 0) {
387 			*pulEncryptedLen = 0;
388 			return (CKR_OK);
389 		}
390 
391 		return (soft_blowfish_encrypt_common(session_p, pData,
392 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
393 
394 	case CKM_RC4:
395 
396 		if (ulDataLen == 0) {
397 			*pulEncryptedLen = 0;
398 			return (CKR_OK);
399 		}
400 
401 		return (soft_arcfour_crypt(&(session_p->encrypt), pData,
402 		    ulDataLen, pEncrypted, pulEncryptedLen));
403 
404 	case CKM_RSA_X_509:
405 	case CKM_RSA_PKCS:
406 
407 		return (soft_rsa_encrypt_common(session_p, pData,
408 		    ulDataLen, pEncrypted, pulEncryptedLen, mechanism));
409 
410 	default:
411 		return (CKR_MECHANISM_INVALID);
412 	}
413 }
414 
415 
416 /*
417  * soft_encrypt()
418  *
419  * Arguments:
420  *      session_p:	pointer to soft_session_t struct
421  *	pData:		pointer to the input data to be encrypted
422  *	ulDataLen:	length of the input data
423  *	pEncryptedData:	pointer to the output data after encryption
424  *	pulEncryptedDataLen: pointer to the length of the output data
425  *
426  * Description:
427  *      called by C_Encrypt(). This function calls the soft_encrypt_common
428  *	routine.
429  *
430  * Returns:
431  *	see soft_encrypt_common().
432  */
433 CK_RV
434 soft_encrypt(soft_session_t *session_p, CK_BYTE_PTR pData,
435     CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
436     CK_ULONG_PTR pulEncryptedDataLen)
437 {
438 
439 	return (soft_encrypt_common(session_p, pData, ulDataLen,
440 	    pEncryptedData, pulEncryptedDataLen, B_FALSE));
441 }
442 
443 
444 /*
445  * soft_encrypt_update()
446  *
447  * Arguments:
448  *      session_p:	pointer to soft_session_t struct
449  *      pPart:		pointer to the input data to be digested
450  *      ulPartLen:	length of the input data
451  *	pEncryptedPart:	pointer to the ciphertext
452  *	pulEncryptedPartLen: pointer to the length of the ciphertext
453  *
454  * Description:
455  *      called by C_EncryptUpdate(). This function calls the
456  *	soft_encrypt_common routine (with update flag on).
457  *
458  * Returns:
459  *	see soft_encrypt_common().
460  */
461 CK_RV
462 soft_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
463 	CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
464 	CK_ULONG_PTR pulEncryptedPartLen)
465 {
466 
467 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
468 
469 	switch (mechanism) {
470 
471 	case CKM_DES_ECB:
472 	case CKM_DES_CBC:
473 	case CKM_DES_CBC_PAD:
474 	case CKM_DES3_ECB:
475 	case CKM_DES3_CBC:
476 	case CKM_DES3_CBC_PAD:
477 	case CKM_AES_ECB:
478 	case CKM_AES_CBC:
479 	case CKM_AES_CBC_PAD:
480 	case CKM_BLOWFISH_CBC:
481 	case CKM_RC4:
482 
483 		return (soft_encrypt_common(session_p, pPart, ulPartLen,
484 		    pEncryptedPart, pulEncryptedPartLen, B_TRUE));
485 
486 	default:
487 		/* PKCS11: The mechanism only supports single-part operation. */
488 		return (CKR_MECHANISM_INVALID);
489 	}
490 }
491 
492 
493 /*
494  * soft_encrypt_final()
495  *
496  * Arguments:
497  *      session_p:		pointer to soft_session_t struct
498  *      pLastEncryptedPart:	pointer to the last encrypted data part
499  *      pulLastEncryptedPartLen: pointer to the length of the last
500  *				encrypted data part
501  *
502  * Description:
503  *      called by C_EncryptFinal().
504  *
505  * Returns:
506  *	CKR_OK: success
507  *	CKR_FUNCTION_FAILED: encrypt final function failed
508  *	CKR_DATA_LEN_RANGE: remaining buffer contains bad length
509  */
510 CK_RV
511 soft_encrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastEncryptedPart,
512 	CK_ULONG_PTR pulLastEncryptedPartLen)
513 {
514 
515 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
516 	CK_ULONG out_len;
517 	CK_RV rv = CKR_OK;
518 	int rc;
519 
520 	(void) pthread_mutex_lock(&session_p->session_mutex);
521 
522 	if (session_p->encrypt.context == NULL) {
523 		rv = CKR_OPERATION_NOT_INITIALIZED;
524 		*pulLastEncryptedPartLen = 0;
525 		goto clean1;
526 	}
527 	switch (mechanism) {
528 
529 	case CKM_DES_CBC_PAD:
530 	case CKM_DES3_CBC_PAD:
531 	{
532 		soft_des_ctx_t *soft_des_ctx;
533 
534 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
535 		/*
536 		 * For CKM_DES_CBC_PAD, compute output length with
537 		 * padding. If the remaining buffer has one block
538 		 * of data, then output length will be two blocksize of
539 		 * ciphertext. If the remaining buffer has less than
540 		 * one block of data, then output length will be
541 		 * one blocksize.
542 		 */
543 		if (soft_des_ctx->remain_len == DES_BLOCK_LEN)
544 			out_len = 2 * DES_BLOCK_LEN;
545 		else
546 			out_len = DES_BLOCK_LEN;
547 
548 		if (pLastEncryptedPart == NULL) {
549 			/*
550 			 * Application asks for the length of the output
551 			 * buffer to hold the ciphertext.
552 			 */
553 			*pulLastEncryptedPartLen = out_len;
554 			goto clean1;
555 		} else {
556 			crypto_data_t out;
557 
558 			/* Copy remaining data to the output buffer. */
559 			(void) memcpy(pLastEncryptedPart, soft_des_ctx->data,
560 			    soft_des_ctx->remain_len);
561 
562 			/*
563 			 * Add padding bytes prior to encrypt final.
564 			 */
565 			soft_add_pkcs7_padding(pLastEncryptedPart +
566 			    soft_des_ctx->remain_len, DES_BLOCK_LEN,
567 			    soft_des_ctx->remain_len);
568 
569 			out.cd_format = CRYPTO_DATA_RAW;
570 			out.cd_offset = 0;
571 			out.cd_length = out_len;
572 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
573 			out.cd_raw.iov_len = out_len;
574 
575 			/* Encrypt multiple blocks of data. */
576 			rc = des_encrypt_contiguous_blocks(
577 			    (des_ctx_t *)soft_des_ctx->des_cbc,
578 			    (char *)pLastEncryptedPart, out_len, &out);
579 
580 			if (rc == 0) {
581 				*pulLastEncryptedPartLen = out_len;
582 			} else {
583 				*pulLastEncryptedPartLen = 0;
584 				rv = CKR_FUNCTION_FAILED;
585 			}
586 
587 			/* Cleanup memory space. */
588 			free(soft_des_ctx->des_cbc);
589 			bzero(soft_des_ctx->key_sched,
590 			    soft_des_ctx->keysched_len);
591 			free(soft_des_ctx->key_sched);
592 		}
593 
594 		break;
595 	}
596 	case CKM_DES_CBC:
597 	case CKM_DES_ECB:
598 	case CKM_DES3_CBC:
599 	case CKM_DES3_ECB:
600 	{
601 
602 		soft_des_ctx_t *soft_des_ctx;
603 
604 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
605 		/*
606 		 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
607 		 * so when the final is called, the remaining buffer
608 		 * should not contain any more data.
609 		 */
610 		*pulLastEncryptedPartLen = 0;
611 		if (soft_des_ctx->remain_len != 0) {
612 			rv = CKR_DATA_LEN_RANGE;
613 		} else {
614 			if (pLastEncryptedPart == NULL)
615 				goto clean1;
616 		}
617 
618 		/* Cleanup memory space. */
619 		free(soft_des_ctx->des_cbc);
620 		bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
621 		free(soft_des_ctx->key_sched);
622 
623 		break;
624 	}
625 	case CKM_AES_CBC_PAD:
626 	{
627 		soft_aes_ctx_t *soft_aes_ctx;
628 
629 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
630 		/*
631 		 * For CKM_AES_CBC_PAD, compute output length with
632 		 * padding. If the remaining buffer has one block
633 		 * of data, then output length will be two blocksize of
634 		 * ciphertext. If the remaining buffer has less than
635 		 * one block of data, then output length will be
636 		 * one blocksize.
637 		 */
638 		if (soft_aes_ctx->remain_len == AES_BLOCK_LEN)
639 			out_len = 2 * AES_BLOCK_LEN;
640 		else
641 			out_len = AES_BLOCK_LEN;
642 
643 		if (pLastEncryptedPart == NULL) {
644 			/*
645 			 * Application asks for the length of the output
646 			 * buffer to hold the ciphertext.
647 			 */
648 			*pulLastEncryptedPartLen = out_len;
649 			goto clean1;
650 		} else {
651 			crypto_data_t out;
652 
653 			/* Copy remaining data to the output buffer. */
654 			(void) memcpy(pLastEncryptedPart, soft_aes_ctx->data,
655 			    soft_aes_ctx->remain_len);
656 
657 			/*
658 			 * Add padding bytes prior to encrypt final.
659 			 */
660 			soft_add_pkcs7_padding(pLastEncryptedPart +
661 			    soft_aes_ctx->remain_len, AES_BLOCK_LEN,
662 			    soft_aes_ctx->remain_len);
663 
664 			out.cd_format = CRYPTO_DATA_RAW;
665 			out.cd_offset = 0;
666 			out.cd_length = out_len;
667 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
668 			out.cd_raw.iov_len = out_len;
669 
670 			/* Encrypt multiple blocks of data. */
671 			rc = aes_encrypt_contiguous_blocks(
672 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
673 			    (char *)pLastEncryptedPart, out_len, &out);
674 
675 			if (rc == 0) {
676 				*pulLastEncryptedPartLen = out_len;
677 			} else {
678 				*pulLastEncryptedPartLen = 0;
679 				rv = CKR_FUNCTION_FAILED;
680 			}
681 
682 			/* Cleanup memory space. */
683 			free(soft_aes_ctx->aes_cbc);
684 			bzero(soft_aes_ctx->key_sched,
685 			    soft_aes_ctx->keysched_len);
686 			free(soft_aes_ctx->key_sched);
687 		}
688 
689 		break;
690 	}
691 	case CKM_AES_CBC:
692 	case CKM_AES_ECB:
693 	{
694 
695 		soft_aes_ctx_t *soft_aes_ctx;
696 
697 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
698 		/*
699 		 * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
700 		 * so when the final is called, the remaining buffer
701 		 * should not contain any more data.
702 		 */
703 		*pulLastEncryptedPartLen = 0;
704 		if (soft_aes_ctx->remain_len != 0) {
705 			rv = CKR_DATA_LEN_RANGE;
706 		} else {
707 			if (pLastEncryptedPart == NULL)
708 				goto clean1;
709 		}
710 
711 		/* Cleanup memory space. */
712 		free(soft_aes_ctx->aes_cbc);
713 		bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
714 		free(soft_aes_ctx->key_sched);
715 
716 		break;
717 	}
718 
719 	case CKM_BLOWFISH_CBC:
720 	{
721 		soft_blowfish_ctx_t *soft_blowfish_ctx;
722 
723 		soft_blowfish_ctx =
724 		    (soft_blowfish_ctx_t *)session_p->encrypt.context;
725 		/*
726 		 * CKM_BLOWFISH_CBC does not do any padding, so when the
727 		 * final is called, the remaining buffer should not contain
728 		 * any more data
729 		 */
730 		*pulLastEncryptedPartLen = 0;
731 		if (soft_blowfish_ctx->remain_len != 0)
732 			rv = CKR_DATA_LEN_RANGE;
733 		else {
734 			if (pLastEncryptedPart == NULL)
735 				goto clean1;
736 		}
737 
738 		free(soft_blowfish_ctx->blowfish_cbc);
739 		bzero(soft_blowfish_ctx->key_sched,
740 		    soft_blowfish_ctx->keysched_len);
741 		free(soft_blowfish_ctx->key_sched);
742 		break;
743 	}
744 
745 	case CKM_RC4:
746 	{
747 		ARCFour_key *key = (ARCFour_key *)session_p->encrypt.context;
748 		bzero(key, sizeof (*key));
749 		*pulLastEncryptedPartLen = 0;
750 		break;
751 	}
752 	default:
753 		/* PKCS11: The mechanism only supports single-part operation. */
754 		rv = CKR_MECHANISM_INVALID;
755 		break;
756 	}
757 
758 	free(session_p->encrypt.context);
759 	session_p->encrypt.context = NULL;
760 clean1:
761 	(void) pthread_mutex_unlock(&session_p->session_mutex);
762 
763 	return (rv);
764 }
765 
766 /*
767  * This function frees the allocated active crypto context and the
768  * lower level of allocated struct as needed.
769  * This function is called by the 1st tier of encrypt/decrypt routines
770  * or by the 2nd tier of session close routine. Since the 1st tier
771  * caller will always call this function without locking the session
772  * mutex and the 2nd tier caller will call with the lock, we add the
773  * third parameter "lock_held" to distiguish this case.
774  */
775 void
776 soft_crypt_cleanup(soft_session_t *session_p, boolean_t encrypt,
777 	boolean_t lock_held)
778 {
779 
780 	crypto_active_op_t *active_op;
781 	boolean_t lock_true = B_TRUE;
782 
783 	if (!lock_held)
784 		(void) pthread_mutex_lock(&session_p->session_mutex);
785 
786 	active_op = (encrypt) ? &(session_p->encrypt) : &(session_p->decrypt);
787 
788 	switch (active_op->mech.mechanism) {
789 
790 	case CKM_DES_CBC_PAD:
791 	case CKM_DES3_CBC_PAD:
792 	case CKM_DES_CBC:
793 	case CKM_DES_ECB:
794 	case CKM_DES3_CBC:
795 	case CKM_DES3_ECB:
796 	{
797 
798 		soft_des_ctx_t *soft_des_ctx =
799 		    (soft_des_ctx_t *)active_op->context;
800 		des_ctx_t *des_ctx;
801 
802 		if (soft_des_ctx != NULL) {
803 			des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
804 			if (des_ctx != NULL) {
805 				bzero(des_ctx->dc_keysched,
806 				    des_ctx->dc_keysched_len);
807 				free(soft_des_ctx->des_cbc);
808 			}
809 			bzero(soft_des_ctx->key_sched,
810 			    soft_des_ctx->keysched_len);
811 			free(soft_des_ctx->key_sched);
812 		}
813 		break;
814 	}
815 
816 	case CKM_AES_CBC_PAD:
817 	case CKM_AES_CBC:
818 	case CKM_AES_ECB:
819 	{
820 		soft_aes_ctx_t *soft_aes_ctx =
821 		    (soft_aes_ctx_t *)active_op->context;
822 		aes_ctx_t *aes_ctx;
823 
824 		if (soft_aes_ctx != NULL) {
825 			aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
826 			if (aes_ctx != NULL) {
827 				bzero(aes_ctx->ac_keysched,
828 				    aes_ctx->ac_keysched_len);
829 				free(soft_aes_ctx->aes_cbc);
830 			}
831 			bzero(soft_aes_ctx->key_sched,
832 			    soft_aes_ctx->keysched_len);
833 			free(soft_aes_ctx->key_sched);
834 		}
835 		break;
836 	}
837 
838 	case CKM_BLOWFISH_CBC:
839 	{
840 		soft_blowfish_ctx_t *soft_blowfish_ctx =
841 		    (soft_blowfish_ctx_t *)active_op->context;
842 		blowfish_ctx_t *blowfish_ctx;
843 
844 		if (soft_blowfish_ctx != NULL) {
845 			blowfish_ctx =
846 			    (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
847 			if (blowfish_ctx != NULL) {
848 				bzero(blowfish_ctx->bc_keysched,
849 				    blowfish_ctx->bc_keysched_len);
850 				free(soft_blowfish_ctx->blowfish_cbc);
851 			}
852 
853 			bzero(soft_blowfish_ctx->key_sched,
854 			    soft_blowfish_ctx->keysched_len);
855 			free(soft_blowfish_ctx->key_sched);
856 		}
857 		break;
858 	}
859 
860 	case CKM_RC4:
861 	{
862 		ARCFour_key *key = (ARCFour_key *)active_op->context;
863 
864 		if (key != NULL)
865 			bzero(key, sizeof (*key));
866 		break;
867 	}
868 
869 	case CKM_RSA_X_509:
870 	case CKM_RSA_PKCS:
871 	{
872 		soft_rsa_ctx_t *rsa_ctx =
873 		    (soft_rsa_ctx_t *)active_op->context;
874 
875 		if (rsa_ctx != NULL)
876 			if (rsa_ctx->key != NULL) {
877 				soft_cleanup_object(rsa_ctx->key);
878 				free(rsa_ctx->key);
879 			}
880 
881 		break;
882 	}
883 
884 	} /* switch */
885 
886 	if (active_op->context != NULL) {
887 		free(active_op->context);
888 		active_op->context = NULL;
889 	}
890 
891 	active_op->flags = 0;
892 
893 	if (!lock_held)
894 		SES_REFRELE(session_p, lock_true);
895 }
896