xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c (revision bea83d026ee1bd1b2a2419e1d0232f107a5d7d9b)
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 <aes_cbc_crypt.h>
35 #include <aes_impl.h>
36 #include "softSession.h"
37 #include "softObject.h"
38 #include "softCrypt.h"
39 
40 /*
41  * Allocate context for the active encryption or decryption operation, and
42  * generate AES key schedule to speed up the operation.
43  */
44 CK_RV
45 soft_aes_crypt_init_common(soft_session_t *session_p,
46     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
47     boolean_t encrypt)
48 {
49 	size_t size;
50 	soft_aes_ctx_t *soft_aes_ctx;
51 
52 	soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t));
53 	if (soft_aes_ctx == NULL) {
54 		return (CKR_HOST_MEMORY);
55 	}
56 
57 	soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0);
58 
59 	if (soft_aes_ctx->key_sched == NULL) {
60 		free(soft_aes_ctx);
61 		return (CKR_HOST_MEMORY);
62 	}
63 
64 	soft_aes_ctx->keysched_len = size;
65 
66 	(void) pthread_mutex_lock(&session_p->session_mutex);
67 	if (encrypt) {
68 		/* Called by C_EncryptInit. */
69 		session_p->encrypt.context = soft_aes_ctx;
70 		session_p->encrypt.mech.mechanism = pMechanism->mechanism;
71 	} else {
72 		/* Called by C_DecryptInit. */
73 		session_p->decrypt.context = soft_aes_ctx;
74 		session_p->decrypt.mech.mechanism = pMechanism->mechanism;
75 	}
76 	(void) pthread_mutex_unlock(&session_p->session_mutex);
77 
78 	/*
79 	 * If this is a non-sensitive key and it does NOT have
80 	 * a key schedule yet, then allocate one and expand it.
81 	 * Otherwise, if it's a non-sensitive key, and it DOES have
82 	 * a key schedule already attached to it, just copy the
83 	 * pre-expanded schedule to the context and avoid the
84 	 * extra key schedule expansion operation.
85 	 */
86 	if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
87 		if (OBJ_KEY_SCHED(key_p) == NULL) {
88 			void *ks;
89 
90 			(void) pthread_mutex_lock(&key_p->object_mutex);
91 			if (OBJ_KEY_SCHED(key_p) == NULL) {
92 				ks = aes_alloc_keysched(&size, 0);
93 				if (ks == NULL) {
94 					(void) pthread_mutex_unlock(
95 					    &key_p->object_mutex);
96 					free(soft_aes_ctx);
97 					return (CKR_HOST_MEMORY);
98 				}
99 #ifdef	__sparcv9
100 				/* LINTED */
101 				aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
102 				    (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
103 #else	/* !__sparcv9 */
104 				aes_init_keysched(OBJ_SEC_VALUE(key_p),
105 				    (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
106 #endif	/* __sparcv9 */
107 				OBJ_KEY_SCHED_LEN(key_p) = size;
108 				OBJ_KEY_SCHED(key_p) = ks;
109 			}
110 			(void) pthread_mutex_unlock(&key_p->object_mutex);
111 		}
112 		(void) memcpy(soft_aes_ctx->key_sched, OBJ_KEY_SCHED(key_p),
113 		    OBJ_KEY_SCHED_LEN(key_p));
114 		soft_aes_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
115 	} else {
116 		/*
117 		 * Initialize key schedule for AES. aes_init_keysched()
118 		 * requires key length in bits.
119 		 */
120 #ifdef	__sparcv9
121 		/* LINTED */
122 		aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
123 		    (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched);
124 #else	/* !__sparcv9 */
125 		aes_init_keysched(OBJ_SEC_VALUE(key_p),
126 		    (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched);
127 #endif	/* __sparcv9 */
128 	}
129 	return (CKR_OK);
130 }
131 
132 
133 /*
134  * soft_aes_encrypt_common()
135  *
136  * Arguments:
137  *      session_p:	pointer to soft_session_t struct
138  *	pData:		pointer to the input data to be encrypted
139  *	ulDataLen:	length of the input data
140  *	pEncrypted:	pointer to the output data after encryption
141  *	pulEncryptedLen: pointer to the length of the output data
142  *	update:		boolean flag indicates caller is soft_encrypt
143  *			or soft_encrypt_update
144  *
145  * Description:
146  *      This function calls the corresponding encrypt routine based
147  *	on the mechanism.
148  *
149  * Returns:
150  *      CKR_OK: success
151  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
152  *			      is too small
153  *	CKR_FUNCTION_FAILED: encrypt function failed
154  *	CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
155  */
156 CK_RV
157 soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
158     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
159     CK_ULONG_PTR pulEncryptedLen, boolean_t update)
160 {
161 
162 	int rc = 0;
163 	CK_RV rv = CKR_OK;
164 	soft_aes_ctx_t *soft_aes_ctx =
165 	    (soft_aes_ctx_t *)session_p->encrypt.context;
166 	aes_ctx_t *aes_ctx;
167 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
168 	CK_BYTE *in_buf = NULL;
169 	CK_BYTE *out_buf = NULL;
170 	CK_ULONG out_len;
171 	CK_ULONG total_len;
172 	CK_ULONG remain;
173 
174 	/*
175 	 * AES only takes input length that is a multiple of blocksize
176 	 * for C_Encrypt function with the mechanism CKM_AES_ECB or
177 	 * CKM_AES_CBC.
178 	 *
179 	 * AES allows any input length for C_Encrypt function with the
180 	 * mechanism CKM_AES_CBC_PAD and for C_EncryptUpdate function.
181 	 */
182 	if ((!update) && (mechanism != CKM_AES_CBC_PAD)) {
183 		if ((ulDataLen % AES_BLOCK_LEN) != 0) {
184 			rv = CKR_DATA_LEN_RANGE;
185 			goto cleanup;
186 		}
187 	}
188 
189 	if (!update) {
190 		/*
191 		 * Called by C_Encrypt
192 		 */
193 		if (mechanism == CKM_AES_CBC_PAD) {
194 			/*
195 			 * For CKM_AES_CBC_PAD, compute output length to
196 			 * count for the padding. If the length of input
197 			 * data is a multiple of blocksize, then make output
198 			 * length to be the sum of the input length and
199 			 * one blocksize. Otherwise, output length will
200 			 * be rounded up to the next multiple of blocksize.
201 			 */
202 			out_len = AES_BLOCK_LEN *
203 			    (ulDataLen / AES_BLOCK_LEN + 1);
204 		} else {
205 			/*
206 			 * For non-padding mode, the output length will
207 			 * be same as the input length.
208 			 */
209 			out_len = ulDataLen;
210 		}
211 
212 		/*
213 		 * If application asks for the length of the output buffer
214 		 * to hold the ciphertext?
215 		 */
216 		if (pEncrypted == NULL) {
217 			*pulEncryptedLen = out_len;
218 			return (CKR_OK);
219 		}
220 
221 		/* Is the application-supplied buffer large enough? */
222 		if (*pulEncryptedLen < out_len) {
223 			*pulEncryptedLen = out_len;
224 			return (CKR_BUFFER_TOO_SMALL);
225 		}
226 
227 		/* Encrypt pad bytes in a separate operation */
228 		if (mechanism == CKM_AES_CBC_PAD) {
229 			out_len -= AES_BLOCK_LEN;
230 		}
231 
232 		in_buf = pData;
233 		out_buf = pEncrypted;
234 	} else {
235 		/*
236 		 * Called by C_EncryptUpdate
237 		 *
238 		 * Add the lengths of last remaining data and current
239 		 * plaintext together to get the total input length.
240 		 */
241 		total_len = soft_aes_ctx->remain_len + ulDataLen;
242 
243 		/*
244 		 * If the total input length is less than one blocksize,
245 		 * or if the total input length is just one blocksize and
246 		 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
247 		 * encryption until when more data comes in next
248 		 * C_EncryptUpdate or when C_EncryptFinal is called.
249 		 */
250 		if ((total_len < AES_BLOCK_LEN) ||
251 		    ((mechanism == CKM_AES_CBC_PAD) &&
252 		    (total_len == AES_BLOCK_LEN))) {
253 			if (pEncrypted != NULL) {
254 				/*
255 				 * Save input data and its length in
256 				 * the remaining buffer of AES context.
257 				 */
258 				(void) memcpy(soft_aes_ctx->data +
259 				    soft_aes_ctx->remain_len, pData, ulDataLen);
260 				soft_aes_ctx->remain_len += ulDataLen;
261 			}
262 
263 			/* Set encrypted data length to 0. */
264 			*pulEncryptedLen = 0;
265 			return (CKR_OK);
266 		}
267 
268 		/* Compute the length of remaing data. */
269 		remain = total_len % AES_BLOCK_LEN;
270 
271 		/*
272 		 * Make sure that the output length is a multiple of
273 		 * blocksize.
274 		 */
275 		out_len = total_len - remain;
276 
277 		/*
278 		 * If application asks for the length of the output buffer
279 		 * to hold the ciphertext?
280 		 */
281 		if (pEncrypted == NULL) {
282 			*pulEncryptedLen = out_len;
283 			return (CKR_OK);
284 		}
285 
286 		/* Is the application-supplied buffer large enough? */
287 		if (*pulEncryptedLen < out_len) {
288 			*pulEncryptedLen = out_len;
289 			return (CKR_BUFFER_TOO_SMALL);
290 		}
291 
292 		if (soft_aes_ctx->remain_len != 0) {
293 			/*
294 			 * Copy last remaining data and current input data
295 			 * to the output buffer.
296 			 */
297 			(void) memmove(pEncrypted + soft_aes_ctx->remain_len,
298 			    pData, out_len - soft_aes_ctx->remain_len);
299 			(void) memcpy(pEncrypted, soft_aes_ctx->data,
300 			    soft_aes_ctx->remain_len);
301 			bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
302 
303 			in_buf = pEncrypted;
304 		} else {
305 			in_buf = pData;
306 		}
307 		out_buf = pEncrypted;
308 	}
309 
310 	/*
311 	 * Begin Encryption now.
312 	 */
313 	switch (mechanism) {
314 
315 	case CKM_AES_ECB:
316 	{
317 
318 		ulong_t i;
319 		uint8_t *tmp_inbuf;
320 		uint8_t *tmp_outbuf;
321 
322 		for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
323 			tmp_inbuf = &in_buf[i];
324 			tmp_outbuf = &out_buf[i];
325 			/* Crunch one block of data for AES. */
326 			aes_encrypt_block(soft_aes_ctx->key_sched,
327 			    tmp_inbuf, tmp_outbuf);
328 		}
329 
330 		if (update) {
331 			/*
332 			 * For encrypt update, if there is a remaining
333 			 * data, save it and its length in the context.
334 			 */
335 			if (remain != 0)
336 				(void) memcpy(soft_aes_ctx->data, pData +
337 				    (ulDataLen - remain), remain);
338 			soft_aes_ctx->remain_len = remain;
339 		}
340 
341 		*pulEncryptedLen = out_len;
342 
343 		break;
344 	}
345 
346 	case CKM_AES_CBC:
347 	case CKM_AES_CBC_PAD:
348 	{
349 		crypto_data_t out;
350 
351 		out.cd_format = CRYPTO_DATA_RAW;
352 		out.cd_offset = 0;
353 		out.cd_length = out_len;
354 		out.cd_raw.iov_base = (char *)out_buf;
355 		out.cd_raw.iov_len = out_len;
356 
357 		/* Encrypt multiple blocks of data. */
358 		rc = aes_encrypt_contiguous_blocks(
359 		    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
360 		    (char *)in_buf, out_len, &out);
361 
362 		if (rc != 0)
363 			goto encrypt_failed;
364 
365 		if (update) {
366 			/*
367 			 * For encrypt update, if there is remaining data,
368 			 * save it and its length in the context.
369 			 */
370 			if (remain != 0)
371 				(void) memcpy(soft_aes_ctx->data, pData +
372 				    (ulDataLen - remain), remain);
373 			soft_aes_ctx->remain_len = remain;
374 		} else if (mechanism == CKM_AES_CBC_PAD) {
375 			/*
376 			 * Save the remainder of the input
377 			 * block in a temporary block because
378 			 * we dont want to overrun the buffer
379 			 * by tacking on pad bytes.
380 			 */
381 			CK_BYTE tmpblock[AES_BLOCK_LEN];
382 			(void) memcpy(tmpblock, in_buf + out_len,
383 			    ulDataLen - out_len);
384 			soft_add_pkcs7_padding(tmpblock +
385 			    (ulDataLen - out_len),
386 			    AES_BLOCK_LEN, ulDataLen - out_len);
387 
388 			out.cd_offset = out_len;
389 			out.cd_length = AES_BLOCK_LEN;
390 			out.cd_raw.iov_base = (char *)out_buf;
391 			out.cd_raw.iov_len = out_len + AES_BLOCK_LEN;
392 
393 			/* Encrypt last block containing pad bytes. */
394 			rc = aes_encrypt_contiguous_blocks(
395 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
396 			    (char *)tmpblock, AES_BLOCK_LEN, &out);
397 
398 			out_len += AES_BLOCK_LEN;
399 		}
400 
401 		if (rc == 0) {
402 			*pulEncryptedLen = out_len;
403 			break;
404 		}
405 encrypt_failed:
406 		*pulEncryptedLen = 0;
407 		rv = CKR_FUNCTION_FAILED;
408 		goto cleanup;
409 	}
410 	} /* end switch */
411 
412 	if (update)
413 		return (CKR_OK);
414 
415 	/*
416 	 * The following code will be executed if the caller is
417 	 * soft_encrypt() or an error occurred. The encryption
418 	 * operation will be terminated so we need to do some cleanup.
419 	 */
420 cleanup:
421 	(void) pthread_mutex_lock(&session_p->session_mutex);
422 	aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
423 	if (aes_ctx != NULL) {
424 		bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
425 		free(soft_aes_ctx->aes_cbc);
426 	}
427 
428 	bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
429 	free(soft_aes_ctx->key_sched);
430 	free(session_p->encrypt.context);
431 	session_p->encrypt.context = NULL;
432 	(void) pthread_mutex_unlock(&session_p->session_mutex);
433 
434 	return (rv);
435 }
436 
437 
438 /*
439  * soft_aes_decrypt_common()
440  *
441  * Arguments:
442  *      session_p:	pointer to soft_session_t struct
443  *	pEncrypted:	pointer to the input data to be decrypted
444  *	ulEncryptedLen:	length of the input data
445  *	pData:		pointer to the output data
446  *	pulDataLen:	pointer to the length of the output data
447  *	Update:		boolean flag indicates caller is soft_decrypt
448  *			or soft_decrypt_update
449  *
450  * Description:
451  *      This function calls the corresponding decrypt routine based
452  *	on the mechanism.
453  *
454  * Returns:
455  *      CKR_OK: success
456  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
457  *			      is too small
458  *	CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
459  *				      of blocksize
460  *	CKR_FUNCTION_FAILED: decrypt function failed
461  */
462 CK_RV
463 soft_aes_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
464     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
465     CK_ULONG_PTR pulDataLen, boolean_t update)
466 {
467 
468 	int rc = 0;
469 	CK_RV rv = CKR_OK;
470 	soft_aes_ctx_t *soft_aes_ctx =
471 	    (soft_aes_ctx_t *)session_p->decrypt.context;
472 	aes_ctx_t *aes_ctx;
473 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
474 	CK_BYTE *in_buf = NULL;
475 	CK_BYTE *out_buf = NULL;
476 	CK_ULONG out_len;
477 	CK_ULONG total_len;
478 	CK_ULONG remain;
479 
480 	/*
481 	 * AES only takes input length that is a multiple of 16 bytes
482 	 * for C_Decrypt function with the mechanism CKM_AES_ECB,
483 	 * CKM_AES_CBC or CKM_AES_CBC_PAD.
484 	 *
485 	 * AES allows any input length for C_DecryptUpdate function.
486 	 */
487 	if (!update) {
488 		/*
489 		 * Called by C_Decrypt
490 		 */
491 		if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) {
492 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
493 			goto cleanup;
494 		}
495 
496 		/*
497 		 * If application asks for the length of the output buffer
498 		 * to hold the plaintext?
499 		 */
500 		if (pData == NULL) {
501 			*pulDataLen = ulEncryptedLen;
502 			return (CKR_OK);
503 		}
504 
505 		/* Is the application-supplied buffer large enough? */
506 		if (mechanism != CKM_AES_CBC_PAD) {
507 			if (*pulDataLen < ulEncryptedLen) {
508 				*pulDataLen = ulEncryptedLen;
509 				return (CKR_BUFFER_TOO_SMALL);
510 			}
511 			out_len = ulEncryptedLen;
512 		} else {
513 			/*
514 			 * For CKM_AES_CBC_PAD, we don't know how
515 			 * many bytes for padding at this time, so
516 			 * we'd assume one block was padded.
517 			 */
518 			if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) {
519 				*pulDataLen = ulEncryptedLen - AES_BLOCK_LEN;
520 				return (CKR_BUFFER_TOO_SMALL);
521 			}
522 			out_len = ulEncryptedLen - AES_BLOCK_LEN;
523 		}
524 		in_buf = pEncrypted;
525 		out_buf = pData;
526 	} else {
527 		/*
528 		 *  Called by C_DecryptUpdate
529 		 *
530 		 * Add the lengths of last remaining data and current
531 		 * input data together to get the total input length.
532 		 */
533 		total_len = soft_aes_ctx->remain_len + ulEncryptedLen;
534 
535 		/*
536 		 * If the total input length is less than one blocksize,
537 		 * or if the total input length is just one blocksize and
538 		 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
539 		 * decryption until when more data comes in next
540 		 * C_DecryptUpdate or when C_DecryptFinal is called.
541 		 */
542 		if ((total_len < AES_BLOCK_LEN) ||
543 		    ((mechanism == CKM_AES_CBC_PAD) &&
544 		    (total_len == AES_BLOCK_LEN))) {
545 			if (pData != NULL) {
546 				/*
547 				 * Save input data and its length in
548 				 * the remaining buffer of AES context.
549 				 */
550 				(void) memcpy(soft_aes_ctx->data +
551 				    soft_aes_ctx->remain_len,
552 				    pEncrypted, ulEncryptedLen);
553 				soft_aes_ctx->remain_len += ulEncryptedLen;
554 			}
555 
556 			/* Set output data length to 0. */
557 			*pulDataLen = 0;
558 			return (CKR_OK);
559 		}
560 
561 		/* Compute the length of remaing data. */
562 		remain = total_len % AES_BLOCK_LEN;
563 
564 		/*
565 		 * Make sure that the output length is a multiple of
566 		 * blocksize.
567 		 */
568 		out_len = total_len - remain;
569 
570 		if (mechanism == CKM_AES_CBC_PAD) {
571 			/*
572 			 * If the input data length is a multiple of
573 			 * blocksize, then save the last block of input
574 			 * data in the remaining buffer. C_DecryptFinal
575 			 * will handle this last block of data.
576 			 */
577 			if (remain == 0) {
578 				remain = AES_BLOCK_LEN;
579 				out_len -= AES_BLOCK_LEN;
580 			}
581 		}
582 
583 		/*
584 		 * If application asks for the length of the output buffer
585 		 * to hold the plaintext?
586 		 */
587 		if (pData == NULL) {
588 			*pulDataLen = out_len;
589 			return (CKR_OK);
590 		}
591 
592 		/*
593 		 * Is the application-supplied buffer large enough?
594 		 */
595 		if (*pulDataLen < out_len) {
596 			*pulDataLen = out_len;
597 			return (CKR_BUFFER_TOO_SMALL);
598 		}
599 
600 		if (soft_aes_ctx->remain_len != 0) {
601 			/*
602 			 * Copy last remaining data and current input data
603 			 * to the output buffer.
604 			 */
605 			(void) memmove(pData + soft_aes_ctx->remain_len,
606 			    pEncrypted, out_len - soft_aes_ctx->remain_len);
607 			(void) memcpy(pData, soft_aes_ctx->data,
608 			    soft_aes_ctx->remain_len);
609 			bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
610 
611 			in_buf = pData;
612 		} else {
613 			in_buf = pEncrypted;
614 		}
615 		out_buf = pData;
616 	}
617 
618 	/*
619 	 * Begin Decryption.
620 	 */
621 	switch (mechanism) {
622 
623 	case CKM_AES_ECB:
624 	{
625 
626 		ulong_t i;
627 		uint8_t *tmp_inbuf;
628 		uint8_t *tmp_outbuf;
629 
630 		for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
631 			tmp_inbuf = &in_buf[i];
632 			tmp_outbuf = &out_buf[i];
633 			/* Crunch one block of data for AES. */
634 			aes_decrypt_block(soft_aes_ctx->key_sched,
635 			    tmp_inbuf, tmp_outbuf);
636 		}
637 
638 		if (update) {
639 			/*
640 			 * For decrypt update, if there is a remaining
641 			 * data, save it and its length in the context.
642 			 */
643 			if (remain != 0)
644 				(void) memcpy(soft_aes_ctx->data, pEncrypted +
645 				    (ulEncryptedLen - remain), remain);
646 			soft_aes_ctx->remain_len = remain;
647 		}
648 
649 		*pulDataLen = out_len;
650 
651 		break;
652 	}
653 
654 	case CKM_AES_CBC:
655 	case CKM_AES_CBC_PAD:
656 	{
657 		crypto_data_t out;
658 		CK_ULONG rem_len;
659 		uint8_t last_block[AES_BLOCK_LEN];
660 
661 		out.cd_format = CRYPTO_DATA_RAW;
662 		out.cd_offset = 0;
663 		out.cd_length = out_len;
664 		out.cd_raw.iov_base = (char *)out_buf;
665 		out.cd_raw.iov_len = out_len;
666 
667 		/* Decrypt multiple blocks of data. */
668 		rc = aes_decrypt_contiguous_blocks(
669 		    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
670 		    (char *)in_buf, out_len, &out);
671 
672 		if (rc != 0)
673 			goto decrypt_failed;
674 
675 		if ((mechanism == CKM_AES_CBC_PAD) && (!update)) {
676 			/* Decrypt last block containing pad bytes. */
677 			out.cd_offset = 0;
678 			out.cd_length = AES_BLOCK_LEN;
679 			out.cd_raw.iov_base = (char *)last_block;
680 			out.cd_raw.iov_len = AES_BLOCK_LEN;
681 
682 			/* Decrypt last block containing pad bytes. */
683 			rc = aes_decrypt_contiguous_blocks(
684 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
685 			    (char *)in_buf + out_len, AES_BLOCK_LEN, &out);
686 
687 			if (rc != 0)
688 				goto decrypt_failed;
689 
690 			/*
691 			 * Remove padding bytes after decryption of
692 			 * ciphertext block to produce the original
693 			 * plaintext.
694 			 */
695 			rv = soft_remove_pkcs7_padding(last_block,
696 			    AES_BLOCK_LEN, &rem_len, AES_BLOCK_LEN);
697 			if (rv == CKR_OK) {
698 				if (rem_len != 0)
699 					(void) memcpy(out_buf + out_len,
700 					    last_block, rem_len);
701 				*pulDataLen = out_len + rem_len;
702 			} else {
703 				*pulDataLen = 0;
704 				goto cleanup;
705 			}
706 		} else {
707 			*pulDataLen = out_len;
708 		}
709 
710 		if (update) {
711 			/*
712 			 * For decrypt update, if there is remaining data,
713 			 * save it and its length in the context.
714 			 */
715 			if (remain != 0)
716 				(void) memcpy(soft_aes_ctx->data, pEncrypted +
717 				    (ulEncryptedLen - remain), remain);
718 			soft_aes_ctx->remain_len = remain;
719 		}
720 
721 		if (rc == 0)
722 			break;
723 decrypt_failed:
724 		*pulDataLen = 0;
725 		rv = CKR_FUNCTION_FAILED;
726 		goto cleanup;
727 	}
728 	} /* end switch */
729 
730 	if (update)
731 		return (CKR_OK);
732 
733 	/*
734 	 * The following code will be executed if the caller is
735 	 * soft_decrypt() or an error occurred. The decryption
736 	 * operation will be terminated so we need to do some cleanup.
737 	 */
738 cleanup:
739 	(void) pthread_mutex_lock(&session_p->session_mutex);
740 	aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
741 	if (aes_ctx != NULL) {
742 		bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
743 		free(soft_aes_ctx->aes_cbc);
744 	}
745 
746 	bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
747 	free(soft_aes_ctx->key_sched);
748 	free(session_p->decrypt.context);
749 	session_p->decrypt.context = NULL;
750 	(void) pthread_mutex_unlock(&session_p->session_mutex);
751 
752 	return (rv);
753 }
754 
755 
756 /*
757  * Allocate and initialize a context for AES CBC mode of operation.
758  */
759 void *
760 aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
761 {
762 
763 	aes_ctx_t *aes_ctx;
764 
765 	if ((aes_ctx = calloc(1, sizeof (aes_ctx_t))) == NULL)
766 		return (NULL);
767 
768 	aes_ctx->ac_keysched = key_sched;
769 
770 	(void) memcpy(&aes_ctx->ac_iv[0], ivec, AES_BLOCK_LEN);
771 
772 	aes_ctx->ac_lastp = (uint8_t *)aes_ctx->ac_iv;
773 	aes_ctx->ac_keysched_len = size;
774 	aes_ctx->ac_flags |= AES_CBC_MODE;
775 
776 	return ((void *)aes_ctx);
777 
778 }
779