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