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