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