xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c (revision 89b2a9fbeabf42fa54594df0e5927bcc50a07cc9)
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 #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 "softSession.h"
33 #include "softObject.h"
34 #include "softCrypt.h"
35 #include <aes_impl.h>
36 
37 /*
38  * Allocate context for the active encryption or decryption operation, and
39  * generate AES key schedule to speed up the operation.
40  */
41 CK_RV
42 soft_aes_crypt_init_common(soft_session_t *session_p,
43     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
44     boolean_t encrypt)
45 {
46 	size_t size;
47 	soft_aes_ctx_t *soft_aes_ctx;
48 
49 	soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t));
50 	if (soft_aes_ctx == NULL) {
51 		return (CKR_HOST_MEMORY);
52 	}
53 
54 	soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0);
55 
56 	if (soft_aes_ctx->key_sched == NULL) {
57 		free(soft_aes_ctx);
58 		return (CKR_HOST_MEMORY);
59 	}
60 
61 	soft_aes_ctx->keysched_len = size;
62 
63 	(void) pthread_mutex_lock(&session_p->session_mutex);
64 	if (encrypt) {
65 		/* Called by C_EncryptInit. */
66 		session_p->encrypt.context = soft_aes_ctx;
67 		session_p->encrypt.mech.mechanism = pMechanism->mechanism;
68 	} else {
69 		/* Called by C_DecryptInit. */
70 		session_p->decrypt.context = soft_aes_ctx;
71 		session_p->decrypt.mech.mechanism = pMechanism->mechanism;
72 	}
73 	(void) pthread_mutex_unlock(&session_p->session_mutex);
74 
75 	/*
76 	 * If this is a non-sensitive key and it does NOT have
77 	 * a key schedule yet, then allocate one and expand it.
78 	 * Otherwise, if it's a non-sensitive key, and it DOES have
79 	 * a key schedule already attached to it, just copy the
80 	 * pre-expanded schedule to the context and avoid the
81 	 * extra key schedule expansion operation.
82 	 */
83 	if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
84 		if (OBJ_KEY_SCHED(key_p) == NULL) {
85 			void *ks;
86 
87 			(void) pthread_mutex_lock(&key_p->object_mutex);
88 			if (OBJ_KEY_SCHED(key_p) == NULL) {
89 				ks = aes_alloc_keysched(&size, 0);
90 				if (ks == NULL) {
91 					(void) pthread_mutex_unlock(
92 					    &key_p->object_mutex);
93 					free(soft_aes_ctx);
94 					return (CKR_HOST_MEMORY);
95 				}
96 #ifdef	__sparcv9
97 				/* LINTED */
98 				aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
99 				    (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
100 #else	/* !__sparcv9 */
101 				aes_init_keysched(OBJ_SEC_VALUE(key_p),
102 				    (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
103 #endif	/* __sparcv9 */
104 				OBJ_KEY_SCHED_LEN(key_p) = size;
105 				OBJ_KEY_SCHED(key_p) = ks;
106 			}
107 			(void) pthread_mutex_unlock(&key_p->object_mutex);
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), soft_aes_ctx->key_sched);
121 #else	/* !__sparcv9 */
122 		aes_init_keysched(OBJ_SEC_VALUE(key_p),
123 		    (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched);
124 #endif	/* __sparcv9 */
125 	}
126 	return (CKR_OK);
127 }
128 
129 
130 /*
131  * soft_aes_encrypt_common()
132  *
133  * Arguments:
134  *      session_p:	pointer to soft_session_t struct
135  *	pData:		pointer to the input data to be encrypted
136  *	ulDataLen:	length of the input data
137  *	pEncrypted:	pointer to the output data after encryption
138  *	pulEncryptedLen: pointer to the length of the output data
139  *	update:		boolean flag indicates caller is soft_encrypt
140  *			or soft_encrypt_update
141  *
142  * Description:
143  *      This function calls the corresponding encrypt routine based
144  *	on the mechanism.
145  *
146  * Returns:
147  *      CKR_OK: success
148  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
149  *			      is too small
150  *	CKR_FUNCTION_FAILED: encrypt function failed
151  *	CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
152  */
153 CK_RV
154 soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
155     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
156     CK_ULONG_PTR pulEncryptedLen, boolean_t update)
157 {
158 
159 	int rc = 0;
160 	CK_RV rv = CKR_OK;
161 	soft_aes_ctx_t *soft_aes_ctx =
162 	    (soft_aes_ctx_t *)session_p->encrypt.context;
163 	aes_ctx_t *aes_ctx;
164 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
165 	CK_BYTE *in_buf = NULL;
166 	CK_BYTE *out_buf = NULL;
167 	CK_ULONG out_len;
168 	CK_ULONG total_len;
169 	CK_ULONG remain;
170 
171 	if (mechanism == CKM_AES_CTR)
172 		goto do_encryption;
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 do_encryption:
311 	/*
312 	 * Begin Encryption now.
313 	 */
314 	switch (mechanism) {
315 
316 	case CKM_AES_ECB:
317 	{
318 
319 		ulong_t i;
320 		uint8_t *tmp_inbuf;
321 		uint8_t *tmp_outbuf;
322 
323 		for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
324 			tmp_inbuf = &in_buf[i];
325 			tmp_outbuf = &out_buf[i];
326 			/* Crunch one block of data for AES. */
327 			(void) aes_encrypt_block(soft_aes_ctx->key_sched,
328 			    tmp_inbuf, tmp_outbuf);
329 		}
330 
331 		if (update) {
332 			/*
333 			 * For encrypt update, if there is a remaining
334 			 * data, save it and its length in the context.
335 			 */
336 			if (remain != 0)
337 				(void) memcpy(soft_aes_ctx->data, pData +
338 				    (ulDataLen - remain), remain);
339 			soft_aes_ctx->remain_len = remain;
340 		}
341 
342 		*pulEncryptedLen = out_len;
343 
344 		break;
345 	}
346 
347 	case CKM_AES_CBC:
348 	case CKM_AES_CBC_PAD:
349 	{
350 		crypto_data_t out;
351 
352 		out.cd_format = CRYPTO_DATA_RAW;
353 		out.cd_offset = 0;
354 		out.cd_length = out_len;
355 		out.cd_raw.iov_base = (char *)out_buf;
356 		out.cd_raw.iov_len = out_len;
357 
358 		/* Encrypt multiple blocks of data. */
359 		rc = aes_encrypt_contiguous_blocks(
360 		    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
361 		    (char *)in_buf, out_len, &out);
362 
363 		if (rc != 0)
364 			goto encrypt_failed;
365 
366 		if (update) {
367 			/*
368 			 * For encrypt update, if there is remaining data,
369 			 * save it and its length in the context.
370 			 */
371 			if (remain != 0)
372 				(void) memcpy(soft_aes_ctx->data, pData +
373 				    (ulDataLen - remain), remain);
374 			soft_aes_ctx->remain_len = remain;
375 		} else if (mechanism == CKM_AES_CBC_PAD) {
376 			/*
377 			 * Save the remainder of the input
378 			 * block in a temporary block because
379 			 * we dont want to overrun the buffer
380 			 * by tacking on pad bytes.
381 			 */
382 			CK_BYTE tmpblock[AES_BLOCK_LEN];
383 			(void) memcpy(tmpblock, in_buf + out_len,
384 			    ulDataLen - out_len);
385 			soft_add_pkcs7_padding(tmpblock +
386 			    (ulDataLen - out_len),
387 			    AES_BLOCK_LEN, ulDataLen - out_len);
388 
389 			out.cd_offset = out_len;
390 			out.cd_length = AES_BLOCK_LEN;
391 			out.cd_raw.iov_base = (char *)out_buf;
392 			out.cd_raw.iov_len = out_len + AES_BLOCK_LEN;
393 
394 			/* Encrypt last block containing pad bytes. */
395 			rc = aes_encrypt_contiguous_blocks(
396 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
397 			    (char *)tmpblock, AES_BLOCK_LEN, &out);
398 
399 			out_len += AES_BLOCK_LEN;
400 		}
401 
402 		if (rc == 0) {
403 			*pulEncryptedLen = out_len;
404 			break;
405 		}
406 encrypt_failed:
407 		*pulEncryptedLen = 0;
408 		rv = CKR_FUNCTION_FAILED;
409 		goto cleanup;
410 	}
411 	case CKM_AES_CTR:
412 	{
413 		crypto_data_t out;
414 
415 		out.cd_format = CRYPTO_DATA_RAW;
416 		out.cd_offset = 0;
417 		out.cd_length = *pulEncryptedLen;
418 		out.cd_raw.iov_base = (char *)pEncrypted;
419 		out.cd_raw.iov_len = *pulEncryptedLen;
420 
421 		rc = aes_encrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
422 		    (char *)pData, ulDataLen, &out);
423 
424 		if (rc != 0) {
425 			*pulEncryptedLen = 0;
426 			rv = CKR_FUNCTION_FAILED;
427 			goto cleanup;
428 		}
429 		/*
430 		 * Since AES counter mode is a stream cipher, we call
431 		 * aes_counter_final() to pick up any remaining bytes.
432 		 * It is an internal function that does not destroy
433 		 * the context like *normal* final routines.
434 		 */
435 		if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len > 0)
436 			rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
437 			    aes_encrypt_block);
438 	}
439 	} /* end switch */
440 
441 	if (update)
442 		return (CKR_OK);
443 
444 	/*
445 	 * The following code will be executed if the caller is
446 	 * soft_encrypt() or an error occurred. The encryption
447 	 * operation will be terminated so we need to do some cleanup.
448 	 */
449 cleanup:
450 	(void) pthread_mutex_lock(&session_p->session_mutex);
451 	aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
452 	if (aes_ctx != NULL) {
453 		bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
454 		free(soft_aes_ctx->aes_cbc);
455 	}
456 
457 	bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
458 	free(soft_aes_ctx->key_sched);
459 	free(session_p->encrypt.context);
460 	session_p->encrypt.context = NULL;
461 	(void) pthread_mutex_unlock(&session_p->session_mutex);
462 
463 	return (rv);
464 }
465 
466 
467 /*
468  * soft_aes_decrypt_common()
469  *
470  * Arguments:
471  *      session_p:	pointer to soft_session_t struct
472  *	pEncrypted:	pointer to the input data to be decrypted
473  *	ulEncryptedLen:	length of the input data
474  *	pData:		pointer to the output data
475  *	pulDataLen:	pointer to the length of the output data
476  *	Update:		boolean flag indicates caller is soft_decrypt
477  *			or soft_decrypt_update
478  *
479  * Description:
480  *      This function calls the corresponding decrypt routine based
481  *	on the mechanism.
482  *
483  * Returns:
484  *      CKR_OK: success
485  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
486  *			      is too small
487  *	CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
488  *				      of blocksize
489  *	CKR_FUNCTION_FAILED: decrypt function failed
490  */
491 CK_RV
492 soft_aes_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
493     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
494     CK_ULONG_PTR pulDataLen, boolean_t update)
495 {
496 
497 	int rc = 0;
498 	CK_RV rv = CKR_OK;
499 	soft_aes_ctx_t *soft_aes_ctx =
500 	    (soft_aes_ctx_t *)session_p->decrypt.context;
501 	aes_ctx_t *aes_ctx;
502 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
503 	CK_BYTE *in_buf = NULL;
504 	CK_BYTE *out_buf = NULL;
505 	CK_ULONG out_len;
506 	CK_ULONG total_len;
507 	CK_ULONG remain;
508 
509 	if (mechanism == CKM_AES_CTR)
510 		goto do_decryption;
511 
512 	/*
513 	 * AES only takes input length that is a multiple of 16 bytes
514 	 * for C_Decrypt function with the mechanism CKM_AES_ECB,
515 	 * CKM_AES_CBC or CKM_AES_CBC_PAD.
516 	 *
517 	 * AES allows any input length for C_DecryptUpdate function.
518 	 */
519 	if (!update) {
520 		/*
521 		 * Called by C_Decrypt
522 		 */
523 		if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) {
524 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
525 			goto cleanup;
526 		}
527 
528 		/*
529 		 * If application asks for the length of the output buffer
530 		 * to hold the plaintext?
531 		 */
532 		if (pData == NULL) {
533 			*pulDataLen = ulEncryptedLen;
534 			return (CKR_OK);
535 		}
536 
537 		/* Is the application-supplied buffer large enough? */
538 		if (mechanism != CKM_AES_CBC_PAD) {
539 			if (*pulDataLen < ulEncryptedLen) {
540 				*pulDataLen = ulEncryptedLen;
541 				return (CKR_BUFFER_TOO_SMALL);
542 			}
543 			out_len = ulEncryptedLen;
544 		} else {
545 			/*
546 			 * For CKM_AES_CBC_PAD, we don't know how
547 			 * many bytes for padding at this time, so
548 			 * we'd assume one block was padded.
549 			 */
550 			if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) {
551 				*pulDataLen = ulEncryptedLen - AES_BLOCK_LEN;
552 				return (CKR_BUFFER_TOO_SMALL);
553 			}
554 			out_len = ulEncryptedLen - AES_BLOCK_LEN;
555 		}
556 		in_buf = pEncrypted;
557 		out_buf = pData;
558 	} else {
559 		/*
560 		 *  Called by C_DecryptUpdate
561 		 *
562 		 * Add the lengths of last remaining data and current
563 		 * input data together to get the total input length.
564 		 */
565 		total_len = soft_aes_ctx->remain_len + ulEncryptedLen;
566 
567 		/*
568 		 * If the total input length is less than one blocksize,
569 		 * or if the total input length is just one blocksize and
570 		 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
571 		 * decryption until when more data comes in next
572 		 * C_DecryptUpdate or when C_DecryptFinal is called.
573 		 */
574 		if ((total_len < AES_BLOCK_LEN) ||
575 		    ((mechanism == CKM_AES_CBC_PAD) &&
576 		    (total_len == AES_BLOCK_LEN))) {
577 			if (pData != NULL) {
578 				/*
579 				 * Save input data and its length in
580 				 * the remaining buffer of AES context.
581 				 */
582 				(void) memcpy(soft_aes_ctx->data +
583 				    soft_aes_ctx->remain_len,
584 				    pEncrypted, ulEncryptedLen);
585 				soft_aes_ctx->remain_len += ulEncryptedLen;
586 			}
587 
588 			/* Set output data length to 0. */
589 			*pulDataLen = 0;
590 			return (CKR_OK);
591 		}
592 
593 		/* Compute the length of remaing data. */
594 		remain = total_len % AES_BLOCK_LEN;
595 
596 		/*
597 		 * Make sure that the output length is a multiple of
598 		 * blocksize.
599 		 */
600 		out_len = total_len - remain;
601 
602 		if (mechanism == CKM_AES_CBC_PAD) {
603 			/*
604 			 * If the input data length is a multiple of
605 			 * blocksize, then save the last block of input
606 			 * data in the remaining buffer. C_DecryptFinal
607 			 * will handle this last block of data.
608 			 */
609 			if (remain == 0) {
610 				remain = AES_BLOCK_LEN;
611 				out_len -= AES_BLOCK_LEN;
612 			}
613 		}
614 
615 		/*
616 		 * If application asks for the length of the output buffer
617 		 * to hold the plaintext?
618 		 */
619 		if (pData == NULL) {
620 			*pulDataLen = out_len;
621 			return (CKR_OK);
622 		}
623 
624 		/*
625 		 * Is the application-supplied buffer large enough?
626 		 */
627 		if (*pulDataLen < out_len) {
628 			*pulDataLen = out_len;
629 			return (CKR_BUFFER_TOO_SMALL);
630 		}
631 
632 		if (soft_aes_ctx->remain_len != 0) {
633 			/*
634 			 * Copy last remaining data and current input data
635 			 * to the output buffer.
636 			 */
637 			(void) memmove(pData + soft_aes_ctx->remain_len,
638 			    pEncrypted, out_len - soft_aes_ctx->remain_len);
639 			(void) memcpy(pData, soft_aes_ctx->data,
640 			    soft_aes_ctx->remain_len);
641 			bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
642 
643 			in_buf = pData;
644 		} else {
645 			in_buf = pEncrypted;
646 		}
647 		out_buf = pData;
648 	}
649 
650 do_decryption:
651 	/*
652 	 * Begin Decryption.
653 	 */
654 	switch (mechanism) {
655 
656 	case CKM_AES_ECB:
657 	{
658 
659 		ulong_t i;
660 		uint8_t *tmp_inbuf;
661 		uint8_t *tmp_outbuf;
662 
663 		for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
664 			tmp_inbuf = &in_buf[i];
665 			tmp_outbuf = &out_buf[i];
666 			/* Crunch one block of data for AES. */
667 			(void) aes_decrypt_block(soft_aes_ctx->key_sched,
668 			    tmp_inbuf, tmp_outbuf);
669 		}
670 
671 		if (update) {
672 			/*
673 			 * For decrypt update, if there is a remaining
674 			 * data, save it and its length in the context.
675 			 */
676 			if (remain != 0)
677 				(void) memcpy(soft_aes_ctx->data, pEncrypted +
678 				    (ulEncryptedLen - remain), remain);
679 			soft_aes_ctx->remain_len = remain;
680 		}
681 
682 		*pulDataLen = out_len;
683 
684 		break;
685 	}
686 
687 	case CKM_AES_CBC:
688 	case CKM_AES_CBC_PAD:
689 	{
690 		crypto_data_t out;
691 		CK_ULONG rem_len;
692 		uint8_t last_block[AES_BLOCK_LEN];
693 
694 		out.cd_format = CRYPTO_DATA_RAW;
695 		out.cd_offset = 0;
696 		out.cd_length = out_len;
697 		out.cd_raw.iov_base = (char *)out_buf;
698 		out.cd_raw.iov_len = out_len;
699 
700 		/* Decrypt multiple blocks of data. */
701 		rc = aes_decrypt_contiguous_blocks(
702 		    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
703 		    (char *)in_buf, out_len, &out);
704 
705 		if (rc != 0)
706 			goto decrypt_failed;
707 
708 		if ((mechanism == CKM_AES_CBC_PAD) && (!update)) {
709 			/* Decrypt last block containing pad bytes. */
710 			out.cd_offset = 0;
711 			out.cd_length = AES_BLOCK_LEN;
712 			out.cd_raw.iov_base = (char *)last_block;
713 			out.cd_raw.iov_len = AES_BLOCK_LEN;
714 
715 			/* Decrypt last block containing pad bytes. */
716 			rc = aes_decrypt_contiguous_blocks(
717 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
718 			    (char *)in_buf + out_len, AES_BLOCK_LEN, &out);
719 
720 			if (rc != 0)
721 				goto decrypt_failed;
722 
723 			/*
724 			 * Remove padding bytes after decryption of
725 			 * ciphertext block to produce the original
726 			 * plaintext.
727 			 */
728 			rv = soft_remove_pkcs7_padding(last_block,
729 			    AES_BLOCK_LEN, &rem_len, AES_BLOCK_LEN);
730 			if (rv == CKR_OK) {
731 				if (rem_len != 0)
732 					(void) memcpy(out_buf + out_len,
733 					    last_block, rem_len);
734 				*pulDataLen = out_len + rem_len;
735 			} else {
736 				*pulDataLen = 0;
737 				goto cleanup;
738 			}
739 		} else {
740 			*pulDataLen = out_len;
741 		}
742 
743 		if (update) {
744 			/*
745 			 * For decrypt update, if there is remaining data,
746 			 * save it and its length in the context.
747 			 */
748 			if (remain != 0)
749 				(void) memcpy(soft_aes_ctx->data, pEncrypted +
750 				    (ulEncryptedLen - remain), remain);
751 			soft_aes_ctx->remain_len = remain;
752 		}
753 
754 		if (rc == 0)
755 			break;
756 decrypt_failed:
757 		*pulDataLen = 0;
758 		rv = CKR_FUNCTION_FAILED;
759 		goto cleanup;
760 	}
761 	case CKM_AES_CTR:
762 	{
763 		crypto_data_t out;
764 
765 		out.cd_format = CRYPTO_DATA_RAW;
766 		out.cd_offset = 0;
767 		out.cd_length = *pulDataLen;
768 		out.cd_raw.iov_base = (char *)pData;
769 		out.cd_raw.iov_len = *pulDataLen;
770 
771 		rc = aes_decrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
772 		    (char *)pEncrypted, ulEncryptedLen, &out);
773 
774 		if (rc != 0) {
775 			*pulDataLen = 0;
776 			rv = CKR_FUNCTION_FAILED;
777 			goto cleanup;
778 		}
779 
780 		/*
781 		 * Since AES counter mode is a stream cipher, we call
782 		 * aes_counter_final() to pick up any remaining bytes.
783 		 * It is an internal function that does not destroy
784 		 * the context like *normal* final routines.
785 		 */
786 		if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len
787 		    > 0) {
788 			rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
789 			    aes_encrypt_block);
790 			if (rc == CRYPTO_DATA_LEN_RANGE)
791 				rc = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
792 		}
793 	}
794 	} /* end switch */
795 
796 	if (update)
797 		return (CKR_OK);
798 
799 	/*
800 	 * The following code will be executed if the caller is
801 	 * soft_decrypt() or an error occurred. The decryption
802 	 * operation will be terminated so we need to do some cleanup.
803 	 */
804 cleanup:
805 	(void) pthread_mutex_lock(&session_p->session_mutex);
806 	aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
807 	if (aes_ctx != NULL) {
808 		bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
809 		free(soft_aes_ctx->aes_cbc);
810 	}
811 
812 	bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
813 	free(soft_aes_ctx->key_sched);
814 	free(session_p->decrypt.context);
815 	session_p->decrypt.context = NULL;
816 	(void) pthread_mutex_unlock(&session_p->session_mutex);
817 
818 	return (rv);
819 }
820 
821 
822 /*
823  * Allocate and initialize a context for AES CBC mode of operation.
824  */
825 void *
826 aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
827 {
828 
829 	cbc_ctx_t *cbc_ctx;
830 
831 	if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
832 		return (NULL);
833 
834 	cbc_ctx->cbc_keysched = key_sched;
835 	cbc_ctx->cbc_keysched_len = size;
836 
837 	(void) memcpy(&cbc_ctx->cbc_iv[0], ivec, AES_BLOCK_LEN);
838 
839 	cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv;
840 	cbc_ctx->cbc_flags |= CBC_MODE;
841 
842 	return (cbc_ctx);
843 }
844 
845 /*
846  * Allocate and initialize a context for AES CTR mode of operation.
847  */
848 void *
849 aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param)
850 {
851 
852 	ctr_ctx_t *ctr_ctx;
853 	CK_AES_CTR_PARAMS *pp;
854 
855 	/* LINTED: pointer alignment */
856 	pp = (CK_AES_CTR_PARAMS *)param;
857 
858 	if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
859 		return (NULL);
860 
861 	ctr_ctx->ctr_keysched = key_sched;
862 	ctr_ctx->ctr_keysched_len = size;
863 
864 	if (ctr_init_ctx(ctr_ctx, pp->ulCounterBits, pp->cb, aes_copy_block)
865 	    != CRYPTO_SUCCESS) {
866 		free(ctr_ctx);
867 		return (NULL);
868 	}
869 
870 	return (ctr_ctx);
871 }
872