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