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