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