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