xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c (revision bf5d9f18edeb77c14df996d367853599bdd43fd1)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
25  */
26 
27 #include <pthread.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <sys/types.h>
32 #include <security/cryptoki.h>
33 #include <aes_impl.h>
34 #include "softSession.h"
35 #include "softObject.h"
36 #include "softCrypt.h"
37 #include "softOps.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 	    (mechanism != CKM_AES_CMAC)) {
186 		if ((ulDataLen % AES_BLOCK_LEN) != 0) {
187 			rv = CKR_DATA_LEN_RANGE;
188 			goto cleanup;
189 		}
190 	}
191 
192 	if (!update) {
193 		/*
194 		 * Called by C_Encrypt
195 		 */
196 		if (mechanism == CKM_AES_CBC_PAD) {
197 			/*
198 			 * For CKM_AES_CBC_PAD, compute output length to
199 			 * count for the padding. If the length of input
200 			 * data is a multiple of blocksize, then make output
201 			 * length to be the sum of the input length and
202 			 * one blocksize. Otherwise, output length will
203 			 * be rounded up to the next multiple of blocksize.
204 			 */
205 			out_len = AES_BLOCK_LEN *
206 			    (ulDataLen / AES_BLOCK_LEN + 1);
207 		} else if (mechanism == CKM_AES_CMAC) {
208 			out_len = AES_BLOCK_LEN;
209 		} else {
210 			/*
211 			 * For non-padding mode, the output length will
212 			 * be same as the input length.
213 			 */
214 			out_len = ulDataLen;
215 		}
216 
217 		/*
218 		 * If application asks for the length of the output buffer
219 		 * to hold the ciphertext?
220 		 */
221 		if (pEncrypted == NULL) {
222 			*pulEncryptedLen = out_len;
223 			return (CKR_OK);
224 		}
225 
226 		/* Is the application-supplied buffer large enough? */
227 		if (*pulEncryptedLen < out_len) {
228 			*pulEncryptedLen = out_len;
229 			return (CKR_BUFFER_TOO_SMALL);
230 		}
231 
232 		/* Encrypt pad bytes in a separate operation */
233 		if (mechanism == CKM_AES_CBC_PAD) {
234 			out_len -= AES_BLOCK_LEN;
235 		}
236 
237 		in_buf = pData;
238 		out_buf = pEncrypted;
239 	} else {
240 		/*
241 		 * Called by C_EncryptUpdate
242 		 *
243 		 * Add the lengths of last remaining data and current
244 		 * plaintext together to get the total input length.
245 		 */
246 		total_len = soft_aes_ctx->remain_len + ulDataLen;
247 
248 		/*
249 		 * If the total input length is less than one blocksize,
250 		 * or if the total input length is just one blocksize and
251 		 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
252 		 * encryption until when more data comes in next
253 		 * C_EncryptUpdate or when C_EncryptFinal is called.
254 		 */
255 		out_buf = pEncrypted;
256 
257 		/*
258 		 * We prefer to let the underlying implementation of CMAC handle
259 		 * the storing of extra bytes, and no data is output until
260 		 * *_final, so skip that part of the following validation.
261 		 */
262 		if (mechanism == CKM_AES_CMAC) {
263 			if (pEncrypted == NULL) {
264 				*pulEncryptedLen = ulDataLen;
265 				return (CKR_OK);
266 			}
267 
268 			remain = 0;
269 			in_buf = pData;
270 			goto do_encryption;
271 		}
272 
273 		if ((total_len < AES_BLOCK_LEN) ||
274 		    ((mechanism == CKM_AES_CBC_PAD) &&
275 		    (total_len == AES_BLOCK_LEN))) {
276 			if (pEncrypted != NULL) {
277 				/*
278 				 * Save input data and its length in
279 				 * the remaining buffer of AES context.
280 				 */
281 				(void) memcpy(soft_aes_ctx->data +
282 				    soft_aes_ctx->remain_len, pData, ulDataLen);
283 				soft_aes_ctx->remain_len += ulDataLen;
284 			}
285 
286 			/* Set encrypted data length to 0. */
287 			*pulEncryptedLen = 0;
288 			return (CKR_OK);
289 		}
290 
291 		/* Compute the length of remaing data. */
292 		remain = total_len % AES_BLOCK_LEN;
293 
294 		/*
295 		 * Make sure that the output length is a multiple of
296 		 * blocksize.
297 		 */
298 		out_len = total_len - remain;
299 
300 		/*
301 		 * If application asks for the length of the output buffer
302 		 * to hold the ciphertext?
303 		 */
304 		if (pEncrypted == NULL) {
305 			*pulEncryptedLen = out_len;
306 			return (CKR_OK);
307 		}
308 
309 		/* Is the application-supplied buffer large enough? */
310 		if (*pulEncryptedLen < out_len) {
311 			*pulEncryptedLen = out_len;
312 			return (CKR_BUFFER_TOO_SMALL);
313 		}
314 
315 		if (soft_aes_ctx->remain_len != 0) {
316 			/*
317 			 * Copy last remaining data and current input data
318 			 * to the output buffer.
319 			 */
320 			(void) memmove(pEncrypted + soft_aes_ctx->remain_len,
321 			    pData, out_len - soft_aes_ctx->remain_len);
322 			(void) memcpy(pEncrypted, soft_aes_ctx->data,
323 			    soft_aes_ctx->remain_len);
324 			bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
325 
326 			in_buf = pEncrypted;
327 		} else {
328 			in_buf = pData;
329 		}
330 	}
331 
332 do_encryption:
333 	/*
334 	 * Begin Encryption now.
335 	 */
336 	switch (mechanism) {
337 
338 	case CKM_AES_ECB:
339 	{
340 
341 		ulong_t i;
342 		uint8_t *tmp_inbuf;
343 		uint8_t *tmp_outbuf;
344 
345 		for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
346 			tmp_inbuf = &in_buf[i];
347 			tmp_outbuf = &out_buf[i];
348 			/* Crunch one block of data for AES. */
349 			(void) aes_encrypt_block(soft_aes_ctx->key_sched,
350 			    tmp_inbuf, tmp_outbuf);
351 		}
352 
353 		if (update) {
354 			/*
355 			 * For encrypt update, if there is a remaining
356 			 * data, save it and its length in the context.
357 			 */
358 			if (remain != 0)
359 				(void) memcpy(soft_aes_ctx->data, pData +
360 				    (ulDataLen - remain), remain);
361 			soft_aes_ctx->remain_len = remain;
362 		}
363 
364 		*pulEncryptedLen = out_len;
365 
366 		break;
367 	}
368 
369 	case CKM_AES_CMAC:
370 		out_len = ulDataLen;
371 		/*FALLTHRU*/
372 	case CKM_AES_CBC:
373 	case CKM_AES_CBC_PAD:
374 	{
375 		crypto_data_t out;
376 
377 		out.cd_format = CRYPTO_DATA_RAW;
378 		out.cd_offset = 0;
379 		out.cd_length = out_len;
380 		out.cd_raw.iov_base = (char *)out_buf;
381 		out.cd_raw.iov_len = out_len;
382 
383 		/* Encrypt multiple blocks of data. */
384 		rc = aes_encrypt_contiguous_blocks(
385 		    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
386 		    (char *)in_buf, out_len, &out);
387 
388 		if (rc != 0)
389 			goto encrypt_failed;
390 
391 		if (update) {
392 			/*
393 			 * For encrypt update, if there is remaining data,
394 			 * save it and its length in the context.
395 			 */
396 			if (remain != 0)
397 				(void) memcpy(soft_aes_ctx->data, pData +
398 				    (ulDataLen - remain), remain);
399 			soft_aes_ctx->remain_len = remain;
400 		} else if (mechanism == CKM_AES_CBC_PAD) {
401 			/*
402 			 * Save the remainder of the input
403 			 * block in a temporary block because
404 			 * we dont want to overrun the buffer
405 			 * by tacking on pad bytes.
406 			 */
407 			CK_BYTE tmpblock[AES_BLOCK_LEN];
408 			(void) memcpy(tmpblock, in_buf + out_len,
409 			    ulDataLen - out_len);
410 			soft_add_pkcs7_padding(tmpblock +
411 			    (ulDataLen - out_len),
412 			    AES_BLOCK_LEN, ulDataLen - out_len);
413 
414 			out.cd_offset = out_len;
415 			out.cd_length = AES_BLOCK_LEN;
416 			out.cd_raw.iov_base = (char *)out_buf;
417 			out.cd_raw.iov_len = out_len + AES_BLOCK_LEN;
418 
419 			/* Encrypt last block containing pad bytes. */
420 			rc = aes_encrypt_contiguous_blocks(
421 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
422 			    (char *)tmpblock, AES_BLOCK_LEN, &out);
423 
424 			out_len += AES_BLOCK_LEN;
425 		} else if (mechanism == CKM_AES_CMAC) {
426 			out.cd_length = AES_BLOCK_LEN;
427 			out.cd_raw.iov_base = (char *)out_buf;
428 			out.cd_raw.iov_len = AES_BLOCK_LEN;
429 
430 			rc = cmac_mode_final(soft_aes_ctx->aes_cbc, &out,
431 			    aes_encrypt_block, aes_xor_block);
432 		}
433 
434 		if (rc == 0) {
435 			*pulEncryptedLen = out_len;
436 			break;
437 		}
438 encrypt_failed:
439 		*pulEncryptedLen = 0;
440 		rv = CKR_FUNCTION_FAILED;
441 		goto cleanup;
442 	}
443 	case CKM_AES_CTR:
444 	{
445 		crypto_data_t out;
446 
447 		out.cd_format = CRYPTO_DATA_RAW;
448 		out.cd_offset = 0;
449 		out.cd_length = *pulEncryptedLen;
450 		out.cd_raw.iov_base = (char *)pEncrypted;
451 		out.cd_raw.iov_len = *pulEncryptedLen;
452 
453 		rc = aes_encrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
454 		    (char *)pData, ulDataLen, &out);
455 
456 		if (rc != 0) {
457 			*pulEncryptedLen = 0;
458 			rv = CKR_FUNCTION_FAILED;
459 			goto cleanup;
460 		}
461 		/*
462 		 * Since AES counter mode is a stream cipher, we call
463 		 * aes_counter_final() to pick up any remaining bytes.
464 		 * It is an internal function that does not destroy
465 		 * the context like *normal* final routines.
466 		 */
467 		if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len > 0)
468 			rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
469 			    aes_encrypt_block);
470 
471 		/*
472 		 * Even though success means we've encrypted all of the input,
473 		 * we should still behave like the other functions and return
474 		 * the encrypted length in pulEncryptedLen
475 		 */
476 		*pulEncryptedLen = ulDataLen;
477 	}
478 	} /* end switch */
479 
480 	if (update)
481 		return (CKR_OK);
482 
483 	/*
484 	 * The following code will be executed if the caller is
485 	 * soft_encrypt() or an error occurred. The encryption
486 	 * operation will be terminated so we need to do some cleanup.
487 	 */
488 cleanup:
489 	(void) pthread_mutex_lock(&session_p->session_mutex);
490 	aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
491 	if (aes_ctx != NULL) {
492 		bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
493 		free(soft_aes_ctx->aes_cbc);
494 	}
495 
496 	bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
497 	free(soft_aes_ctx->key_sched);
498 	free(session_p->encrypt.context);
499 	session_p->encrypt.context = NULL;
500 	(void) pthread_mutex_unlock(&session_p->session_mutex);
501 
502 	return (rv);
503 }
504 
505 
506 /*
507  * soft_aes_decrypt_common()
508  *
509  * Arguments:
510  *      session_p:	pointer to soft_session_t struct
511  *	pEncrypted:	pointer to the input data to be decrypted
512  *	ulEncryptedLen:	length of the input data
513  *	pData:		pointer to the output data
514  *	pulDataLen:	pointer to the length of the output data
515  *	Update:		boolean flag indicates caller is soft_decrypt
516  *			or soft_decrypt_update
517  *
518  * Description:
519  *      This function calls the corresponding decrypt routine based
520  *	on the mechanism.
521  *
522  * Returns:
523  *      CKR_OK: success
524  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
525  *			      is too small
526  *	CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
527  *				      of blocksize
528  *	CKR_FUNCTION_FAILED: decrypt function failed
529  */
530 CK_RV
531 soft_aes_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
532     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
533     CK_ULONG_PTR pulDataLen, boolean_t update)
534 {
535 
536 	int rc = 0;
537 	CK_RV rv = CKR_OK;
538 	soft_aes_ctx_t *soft_aes_ctx =
539 	    (soft_aes_ctx_t *)session_p->decrypt.context;
540 	aes_ctx_t *aes_ctx;
541 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
542 	CK_BYTE *in_buf = NULL;
543 	CK_BYTE *out_buf = NULL;
544 	CK_ULONG out_len;
545 	CK_ULONG total_len;
546 	CK_ULONG remain;
547 
548 	if (mechanism == CKM_AES_CTR)
549 		goto do_decryption;
550 
551 	/*
552 	 * AES only takes input length that is a multiple of 16 bytes
553 	 * for C_Decrypt function with the mechanism CKM_AES_ECB,
554 	 * CKM_AES_CBC or CKM_AES_CBC_PAD.
555 	 *
556 	 * AES allows any input length for C_DecryptUpdate function.
557 	 */
558 	if (!update) {
559 		/*
560 		 * Called by C_Decrypt
561 		 */
562 		if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) {
563 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
564 			goto cleanup;
565 		}
566 
567 		/*
568 		 * If application asks for the length of the output buffer
569 		 * to hold the plaintext?
570 		 */
571 		if (pData == NULL) {
572 			*pulDataLen = ulEncryptedLen;
573 			return (CKR_OK);
574 		}
575 
576 		/* Is the application-supplied buffer large enough? */
577 		if (mechanism != CKM_AES_CBC_PAD) {
578 			if (*pulDataLen < ulEncryptedLen) {
579 				*pulDataLen = ulEncryptedLen;
580 				return (CKR_BUFFER_TOO_SMALL);
581 			}
582 			out_len = ulEncryptedLen;
583 		} else {
584 			/*
585 			 * For CKM_AES_CBC_PAD, we don't know how
586 			 * many bytes for padding at this time, so
587 			 * we'd assume one block was padded.
588 			 */
589 			if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) {
590 				*pulDataLen = ulEncryptedLen - AES_BLOCK_LEN;
591 				return (CKR_BUFFER_TOO_SMALL);
592 			}
593 			out_len = ulEncryptedLen - AES_BLOCK_LEN;
594 		}
595 		in_buf = pEncrypted;
596 		out_buf = pData;
597 	} else {
598 		/*
599 		 *  Called by C_DecryptUpdate
600 		 *
601 		 * Add the lengths of last remaining data and current
602 		 * input data together to get the total input length.
603 		 */
604 		total_len = soft_aes_ctx->remain_len + ulEncryptedLen;
605 
606 		/*
607 		 * If the total input length is less than one blocksize,
608 		 * or if the total input length is just one blocksize and
609 		 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
610 		 * decryption until when more data comes in next
611 		 * C_DecryptUpdate or when C_DecryptFinal is called.
612 		 */
613 		if ((total_len < AES_BLOCK_LEN) ||
614 		    ((mechanism == CKM_AES_CBC_PAD) &&
615 		    (total_len == AES_BLOCK_LEN))) {
616 			if (pData != NULL) {
617 				/*
618 				 * Save input data and its length in
619 				 * the remaining buffer of AES context.
620 				 */
621 				(void) memcpy(soft_aes_ctx->data +
622 				    soft_aes_ctx->remain_len,
623 				    pEncrypted, ulEncryptedLen);
624 				soft_aes_ctx->remain_len += ulEncryptedLen;
625 			}
626 
627 			/* Set output data length to 0. */
628 			*pulDataLen = 0;
629 			return (CKR_OK);
630 		}
631 
632 		/* Compute the length of remaing data. */
633 		remain = total_len % AES_BLOCK_LEN;
634 
635 		/*
636 		 * Make sure that the output length is a multiple of
637 		 * blocksize.
638 		 */
639 		out_len = total_len - remain;
640 
641 		if (mechanism == CKM_AES_CBC_PAD) {
642 			/*
643 			 * If the input data length is a multiple of
644 			 * blocksize, then save the last block of input
645 			 * data in the remaining buffer. C_DecryptFinal
646 			 * will handle this last block of data.
647 			 */
648 			if (remain == 0) {
649 				remain = AES_BLOCK_LEN;
650 				out_len -= AES_BLOCK_LEN;
651 			}
652 		}
653 
654 		/*
655 		 * If application asks for the length of the output buffer
656 		 * to hold the plaintext?
657 		 */
658 		if (pData == NULL) {
659 			*pulDataLen = out_len;
660 			return (CKR_OK);
661 		}
662 
663 		/*
664 		 * Is the application-supplied buffer large enough?
665 		 */
666 		if (*pulDataLen < out_len) {
667 			*pulDataLen = out_len;
668 			return (CKR_BUFFER_TOO_SMALL);
669 		}
670 
671 		if (soft_aes_ctx->remain_len != 0) {
672 			/*
673 			 * Copy last remaining data and current input data
674 			 * to the output buffer.
675 			 */
676 			(void) memmove(pData + soft_aes_ctx->remain_len,
677 			    pEncrypted, out_len - soft_aes_ctx->remain_len);
678 			(void) memcpy(pData, soft_aes_ctx->data,
679 			    soft_aes_ctx->remain_len);
680 			bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
681 
682 			in_buf = pData;
683 		} else {
684 			in_buf = pEncrypted;
685 		}
686 		out_buf = pData;
687 	}
688 
689 do_decryption:
690 	/*
691 	 * Begin Decryption.
692 	 */
693 	switch (mechanism) {
694 
695 	case CKM_AES_ECB:
696 	{
697 
698 		ulong_t i;
699 		uint8_t *tmp_inbuf;
700 		uint8_t *tmp_outbuf;
701 
702 		for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
703 			tmp_inbuf = &in_buf[i];
704 			tmp_outbuf = &out_buf[i];
705 			/* Crunch one block of data for AES. */
706 			(void) aes_decrypt_block(soft_aes_ctx->key_sched,
707 			    tmp_inbuf, tmp_outbuf);
708 		}
709 
710 		if (update) {
711 			/*
712 			 * For decrypt update, if there is a remaining
713 			 * data, 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 		*pulDataLen = out_len;
722 
723 		break;
724 	}
725 
726 	case CKM_AES_CBC:
727 	case CKM_AES_CBC_PAD:
728 	{
729 		crypto_data_t out;
730 		CK_ULONG rem_len;
731 		uint8_t last_block[AES_BLOCK_LEN];
732 
733 		out.cd_format = CRYPTO_DATA_RAW;
734 		out.cd_offset = 0;
735 		out.cd_length = out_len;
736 		out.cd_raw.iov_base = (char *)out_buf;
737 		out.cd_raw.iov_len = out_len;
738 
739 		/* Decrypt multiple blocks of data. */
740 		rc = aes_decrypt_contiguous_blocks(
741 		    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
742 		    (char *)in_buf, out_len, &out);
743 
744 		if (rc != 0)
745 			goto decrypt_failed;
746 
747 		if ((mechanism == CKM_AES_CBC_PAD) && (!update)) {
748 			/* Decrypt last block containing pad bytes. */
749 			out.cd_offset = 0;
750 			out.cd_length = AES_BLOCK_LEN;
751 			out.cd_raw.iov_base = (char *)last_block;
752 			out.cd_raw.iov_len = AES_BLOCK_LEN;
753 
754 			/* Decrypt last block containing pad bytes. */
755 			rc = aes_decrypt_contiguous_blocks(
756 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
757 			    (char *)in_buf + out_len, AES_BLOCK_LEN, &out);
758 
759 			if (rc != 0)
760 				goto decrypt_failed;
761 
762 			/*
763 			 * Remove padding bytes after decryption of
764 			 * ciphertext block to produce the original
765 			 * plaintext.
766 			 */
767 			rv = soft_remove_pkcs7_padding(last_block,
768 			    AES_BLOCK_LEN, &rem_len);
769 			if (rv == CKR_OK) {
770 				if (rem_len != 0)
771 					(void) memcpy(out_buf + out_len,
772 					    last_block, rem_len);
773 				*pulDataLen = out_len + rem_len;
774 			} else {
775 				*pulDataLen = 0;
776 				goto cleanup;
777 			}
778 		} else {
779 			*pulDataLen = out_len;
780 		}
781 
782 		if (update) {
783 			/*
784 			 * For decrypt update, if there is remaining data,
785 			 * save it and its length in the context.
786 			 */
787 			if (remain != 0)
788 				(void) memcpy(soft_aes_ctx->data, pEncrypted +
789 				    (ulEncryptedLen - remain), remain);
790 			soft_aes_ctx->remain_len = remain;
791 		}
792 
793 		if (rc == 0)
794 			break;
795 decrypt_failed:
796 		*pulDataLen = 0;
797 		rv = CKR_FUNCTION_FAILED;
798 		goto cleanup;
799 	}
800 	case CKM_AES_CTR:
801 	{
802 		crypto_data_t out;
803 
804 		out.cd_format = CRYPTO_DATA_RAW;
805 		out.cd_offset = 0;
806 		out.cd_length = *pulDataLen;
807 		out.cd_raw.iov_base = (char *)pData;
808 		out.cd_raw.iov_len = *pulDataLen;
809 
810 		rc = aes_decrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
811 		    (char *)pEncrypted, ulEncryptedLen, &out);
812 
813 		if (rc != 0) {
814 			*pulDataLen = 0;
815 			rv = CKR_FUNCTION_FAILED;
816 			goto cleanup;
817 		}
818 
819 		/*
820 		 * Since AES counter mode is a stream cipher, we call
821 		 * aes_counter_final() to pick up any remaining bytes.
822 		 * It is an internal function that does not destroy
823 		 * the context like *normal* final routines.
824 		 */
825 		if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len
826 		    > 0) {
827 			rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
828 			    aes_encrypt_block);
829 			if (rc == CRYPTO_DATA_LEN_RANGE)
830 				rc = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
831 		}
832 
833 		/*
834 		 * Even though success means we've decrypted all of the input,
835 		 * we should still behave like the other functions and return
836 		 * the decrypted length in pulDataLen
837 		 */
838 		*pulDataLen = ulEncryptedLen;
839 
840 	}
841 	} /* end switch */
842 
843 	if (update)
844 		return (CKR_OK);
845 
846 	/*
847 	 * The following code will be executed if the caller is
848 	 * soft_decrypt() or an error occurred. The decryption
849 	 * operation will be terminated so we need to do some cleanup.
850 	 */
851 cleanup:
852 	(void) pthread_mutex_lock(&session_p->session_mutex);
853 	aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
854 	if (aes_ctx != NULL) {
855 		bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
856 		free(soft_aes_ctx->aes_cbc);
857 	}
858 
859 	bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
860 	free(soft_aes_ctx->key_sched);
861 	free(session_p->decrypt.context);
862 	session_p->decrypt.context = NULL;
863 	(void) pthread_mutex_unlock(&session_p->session_mutex);
864 
865 	return (rv);
866 }
867 
868 
869 /*
870  * Allocate and initialize a context for AES CBC mode of operation.
871  */
872 void *
873 aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
874 {
875 
876 	cbc_ctx_t *cbc_ctx;
877 
878 	if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
879 		return (NULL);
880 
881 	cbc_ctx->cbc_keysched = key_sched;
882 	cbc_ctx->cbc_keysched_len = size;
883 
884 	(void) memcpy(&cbc_ctx->cbc_iv[0], ivec, AES_BLOCK_LEN);
885 
886 	cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv;
887 	cbc_ctx->cbc_flags |= CBC_MODE;
888 	cbc_ctx->max_remain = AES_BLOCK_LEN;
889 
890 	return (cbc_ctx);
891 }
892 
893 void *
894 aes_cmac_ctx_init(void *key_sched, size_t size)
895 {
896 
897 	cbc_ctx_t *cbc_ctx;
898 
899 	if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
900 		return (NULL);
901 
902 	cbc_ctx->cbc_keysched = key_sched;
903 	cbc_ctx->cbc_keysched_len = size;
904 
905 	cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv;
906 	cbc_ctx->cbc_flags |= CMAC_MODE;
907 	cbc_ctx->max_remain = AES_BLOCK_LEN + 1;
908 
909 	return (cbc_ctx);
910 }
911 
912 /*
913  * Allocate and initialize a context for AES CTR mode of operation.
914  */
915 void *
916 aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param)
917 {
918 
919 	ctr_ctx_t *ctr_ctx;
920 	CK_AES_CTR_PARAMS *pp;
921 
922 	/* LINTED: pointer alignment */
923 	pp = (CK_AES_CTR_PARAMS *)param;
924 
925 	if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
926 		return (NULL);
927 
928 	ctr_ctx->ctr_keysched = key_sched;
929 	ctr_ctx->ctr_keysched_len = size;
930 
931 	if (ctr_init_ctx(ctr_ctx, pp->ulCounterBits, pp->cb, aes_copy_block)
932 	    != CRYPTO_SUCCESS) {
933 		free(ctr_ctx);
934 		return (NULL);
935 	}
936 
937 	return (ctr_ctx);
938 }
939 
940 /*
941  * Allocate and initialize AES contexts for both signing and encrypting,
942  * saving both context pointers in the session struct. For general-length AES
943  * MAC, check the length in the parameter to see if it is in the right range.
944  */
945 CK_RV
946 soft_aes_sign_verify_init_common(soft_session_t *session_p,
947     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t sign_op)
948 {
949 	soft_aes_ctx_t	*soft_aes_ctx;
950 	CK_MECHANISM	encrypt_mech;
951 	CK_RV rv;
952 
953 	if (key_p->key_type != CKK_AES) {
954 		return (CKR_KEY_TYPE_INCONSISTENT);
955 	}
956 
957 	/* allocate memory for the sign/verify context */
958 	soft_aes_ctx = malloc(sizeof (soft_aes_ctx_t));
959 	if (soft_aes_ctx == NULL) {
960 		return (CKR_HOST_MEMORY);
961 	}
962 
963 	/* initialization vector is zero for AES CMAC */
964 	bzero(soft_aes_ctx->ivec, AES_BLOCK_LEN);
965 
966 	switch (pMechanism->mechanism) {
967 
968 	case CKM_AES_CMAC_GENERAL:
969 
970 		if (pMechanism->ulParameterLen !=
971 		    sizeof (CK_MAC_GENERAL_PARAMS)) {
972 			free(soft_aes_ctx);
973 			return (CKR_MECHANISM_PARAM_INVALID);
974 		}
975 
976 		if (*(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter >
977 		    AES_BLOCK_LEN) {
978 			free(soft_aes_ctx);
979 			return (CKR_MECHANISM_PARAM_INVALID);
980 		}
981 
982 		soft_aes_ctx->mac_len = *((CK_MAC_GENERAL_PARAMS_PTR)
983 		    pMechanism->pParameter);
984 
985 		/*FALLTHRU*/
986 	case CKM_AES_CMAC:
987 
988 		/*
989 		 * For non-general AES MAC, output is always block size
990 		 */
991 		if (pMechanism->mechanism == CKM_AES_CMAC) {
992 			soft_aes_ctx->mac_len = AES_BLOCK_LEN;
993 		}
994 
995 		/* allocate a context for AES encryption */
996 		encrypt_mech.mechanism = CKM_AES_CMAC;
997 		encrypt_mech.pParameter = (void *)soft_aes_ctx->ivec;
998 		encrypt_mech.ulParameterLen = AES_BLOCK_LEN;
999 		rv = soft_encrypt_init_internal(session_p, &encrypt_mech,
1000 		    key_p);
1001 		if (rv != CKR_OK) {
1002 			free(soft_aes_ctx);
1003 			return (rv);
1004 		}
1005 
1006 		(void) pthread_mutex_lock(&session_p->session_mutex);
1007 
1008 		if (sign_op) {
1009 			session_p->sign.context = soft_aes_ctx;
1010 			session_p->sign.mech.mechanism = pMechanism->mechanism;
1011 		} else {
1012 			session_p->verify.context = soft_aes_ctx;
1013 			session_p->verify.mech.mechanism =
1014 			    pMechanism->mechanism;
1015 		}
1016 
1017 		(void) pthread_mutex_unlock(&session_p->session_mutex);
1018 
1019 		break;
1020 	}
1021 	return (CKR_OK);
1022 }
1023 
1024 /*
1025  * Called by soft_sign(), soft_sign_final(), soft_verify() or
1026  * soft_verify_final().
1027  */
1028 CK_RV
1029 soft_aes_sign_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
1030     CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, CK_ULONG_PTR pulSignedLen,
1031     boolean_t sign_op, boolean_t Final)
1032 {
1033 	soft_aes_ctx_t		*soft_aes_ctx_sign_verify;
1034 	CK_RV			rv;
1035 	CK_BYTE			*pEncrypted = NULL;
1036 	CK_ULONG		ulEncryptedLen = AES_BLOCK_LEN;
1037 	CK_BYTE			last_block[AES_BLOCK_LEN];
1038 
1039 	if (sign_op) {
1040 		soft_aes_ctx_sign_verify =
1041 		    (soft_aes_ctx_t *)session_p->sign.context;
1042 
1043 		if (soft_aes_ctx_sign_verify->mac_len == 0) {
1044 			*pulSignedLen = 0;
1045 			goto clean_exit;
1046 		}
1047 
1048 		/* Application asks for the length of the output buffer. */
1049 		if (pSigned == NULL) {
1050 			*pulSignedLen = soft_aes_ctx_sign_verify->mac_len;
1051 			return (CKR_OK);
1052 		}
1053 
1054 		/* Is the application-supplied buffer large enough? */
1055 		if (*pulSignedLen < soft_aes_ctx_sign_verify->mac_len) {
1056 			*pulSignedLen = soft_aes_ctx_sign_verify->mac_len;
1057 			return (CKR_BUFFER_TOO_SMALL);
1058 		}
1059 	} else {
1060 		soft_aes_ctx_sign_verify =
1061 		    (soft_aes_ctx_t *)session_p->verify.context;
1062 	}
1063 
1064 	if (Final) {
1065 		rv = soft_encrypt_final(session_p, last_block,
1066 		    &ulEncryptedLen);
1067 	} else {
1068 		rv = soft_encrypt(session_p, pData, ulDataLen,
1069 		    last_block, &ulEncryptedLen);
1070 	}
1071 
1072 	if (rv == CKR_OK) {
1073 		*pulSignedLen = soft_aes_ctx_sign_verify->mac_len;
1074 
1075 		/* the leftmost mac_len bytes of last_block is our MAC */
1076 		(void) memcpy(pSigned, last_block, *pulSignedLen);
1077 	}
1078 
1079 clean_exit:
1080 
1081 	(void) pthread_mutex_lock(&session_p->session_mutex);
1082 
1083 	/* soft_encrypt_common() has freed the encrypt context */
1084 	if (sign_op) {
1085 		free(session_p->sign.context);
1086 		session_p->sign.context = NULL;
1087 	} else {
1088 		free(session_p->verify.context);
1089 		session_p->verify.context = NULL;
1090 	}
1091 	session_p->encrypt.flags = 0;
1092 
1093 	(void) pthread_mutex_unlock(&session_p->session_mutex);
1094 
1095 	if (pEncrypted) {
1096 		free(pEncrypted);
1097 	}
1098 
1099 	return (rv);
1100 }
1101 
1102 /*
1103  * Called by soft_sign_update()
1104  */
1105 CK_RV
1106 soft_aes_mac_sign_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
1107     CK_ULONG ulPartLen)
1108 {
1109 	CK_BYTE		buf[AES_BLOCK_LEN];
1110 	CK_ULONG	ulEncryptedLen = AES_BLOCK_LEN;
1111 	CK_RV		rv;
1112 
1113 	rv = soft_encrypt_update(session_p, pPart, ulPartLen,
1114 	    buf, &ulEncryptedLen);
1115 
1116 	return (rv);
1117 }
1118