5869 Need AES CMAC support in KCF+PKCS11
[unleashed.git] / usr / src / lib / pkcs11 / pkcs11_softtoken / common / softAESCrypt.c
blobbc8edcdc4c20b37131bfbd2aded3b5ba7dcfac17
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
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"
40 * Allocate context for the active encryption or decryption operation, and
41 * generate AES key schedule to speed up the operation.
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)
48 size_t size;
49 soft_aes_ctx_t *soft_aes_ctx;
51 soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t));
52 if (soft_aes_ctx == NULL) {
53 return (CKR_HOST_MEMORY);
56 soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0);
58 if (soft_aes_ctx->key_sched == NULL) {
59 free(soft_aes_ctx);
60 return (CKR_HOST_MEMORY);
63 soft_aes_ctx->keysched_len = size;
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;
75 (void) pthread_mutex_unlock(&session_p->session_mutex);
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.
85 if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
86 if (OBJ_KEY_SCHED(key_p) == NULL) {
87 void *ks;
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);
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;
109 (void) pthread_mutex_unlock(&key_p->object_mutex);
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 {
116 * Initialize key schedule for AES. aes_init_keysched()
117 * requires key length in bits.
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 */
128 return (CKR_OK);
133 * soft_aes_encrypt_common()
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
144 * Description:
145 * This function calls the corresponding encrypt routine based
146 * on the mechanism.
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
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)
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;
173 if (mechanism == CKM_AES_CTR)
174 goto do_encryption;
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.
181 * AES allows any input length for C_Encrypt function with the
182 * mechanism CKM_AES_CBC_PAD and for C_EncryptUpdate function.
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;
192 if (!update) {
194 * Called by C_Encrypt
196 if (mechanism == CKM_AES_CBC_PAD) {
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.
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 {
211 * For non-padding mode, the output length will
212 * be same as the input length.
214 out_len = ulDataLen;
218 * If application asks for the length of the output buffer
219 * to hold the ciphertext?
221 if (pEncrypted == NULL) {
222 *pulEncryptedLen = out_len;
223 return (CKR_OK);
226 /* Is the application-supplied buffer large enough? */
227 if (*pulEncryptedLen < out_len) {
228 *pulEncryptedLen = out_len;
229 return (CKR_BUFFER_TOO_SMALL);
232 /* Encrypt pad bytes in a separate operation */
233 if (mechanism == CKM_AES_CBC_PAD) {
234 out_len -= AES_BLOCK_LEN;
237 in_buf = pData;
238 out_buf = pEncrypted;
239 } else {
241 * Called by C_EncryptUpdate
243 * Add the lengths of last remaining data and current
244 * plaintext together to get the total input length.
246 total_len = soft_aes_ctx->remain_len + ulDataLen;
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.
255 out_buf = pEncrypted;
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.
262 if (mechanism == CKM_AES_CMAC) {
263 if (pEncrypted == NULL) {
264 *pulEncryptedLen = ulDataLen;
265 return (CKR_OK);
268 remain = 0;
269 in_buf = pData;
270 goto do_encryption;
273 if ((total_len < AES_BLOCK_LEN) ||
274 ((mechanism == CKM_AES_CBC_PAD) &&
275 (total_len == AES_BLOCK_LEN))) {
276 if (pEncrypted != NULL) {
278 * Save input data and its length in
279 * the remaining buffer of AES context.
281 (void) memcpy(soft_aes_ctx->data +
282 soft_aes_ctx->remain_len, pData, ulDataLen);
283 soft_aes_ctx->remain_len += ulDataLen;
286 /* Set encrypted data length to 0. */
287 *pulEncryptedLen = 0;
288 return (CKR_OK);
291 /* Compute the length of remaing data. */
292 remain = total_len % AES_BLOCK_LEN;
295 * Make sure that the output length is a multiple of
296 * blocksize.
298 out_len = total_len - remain;
301 * If application asks for the length of the output buffer
302 * to hold the ciphertext?
304 if (pEncrypted == NULL) {
305 *pulEncryptedLen = out_len;
306 return (CKR_OK);
309 /* Is the application-supplied buffer large enough? */
310 if (*pulEncryptedLen < out_len) {
311 *pulEncryptedLen = out_len;
312 return (CKR_BUFFER_TOO_SMALL);
315 if (soft_aes_ctx->remain_len != 0) {
317 * Copy last remaining data and current input data
318 * to the output buffer.
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);
326 in_buf = pEncrypted;
327 } else {
328 in_buf = pData;
332 do_encryption:
334 * Begin Encryption now.
336 switch (mechanism) {
338 case CKM_AES_ECB:
341 ulong_t i;
342 uint8_t *tmp_inbuf;
343 uint8_t *tmp_outbuf;
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);
353 if (update) {
355 * For encrypt update, if there is a remaining
356 * data, save it and its length in the context.
358 if (remain != 0)
359 (void) memcpy(soft_aes_ctx->data, pData +
360 (ulDataLen - remain), remain);
361 soft_aes_ctx->remain_len = remain;
364 *pulEncryptedLen = out_len;
366 break;
369 case CKM_AES_CMAC:
370 out_len = ulDataLen;
371 /*FALLTHRU*/
372 case CKM_AES_CBC:
373 case CKM_AES_CBC_PAD:
375 crypto_data_t out;
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;
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);
388 if (rc != 0)
389 goto encrypt_failed;
391 if (update) {
393 * For encrypt update, if there is remaining data,
394 * save it and its length in the context.
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) {
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.
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);
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;
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);
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;
430 rc = cmac_mode_final(soft_aes_ctx->aes_cbc, &out,
431 aes_encrypt_block, aes_xor_block);
434 if (rc == 0) {
435 *pulEncryptedLen = out_len;
436 break;
438 encrypt_failed:
439 *pulEncryptedLen = 0;
440 rv = CKR_FUNCTION_FAILED;
441 goto cleanup;
443 case CKM_AES_CTR:
445 crypto_data_t out;
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;
453 rc = aes_encrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
454 (char *)pData, ulDataLen, &out);
456 if (rc != 0) {
457 *pulEncryptedLen = 0;
458 rv = CKR_FUNCTION_FAILED;
459 goto cleanup;
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.
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);
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
476 *pulEncryptedLen = ulDataLen;
478 } /* end switch */
480 if (update)
481 return (CKR_OK);
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.
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);
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);
502 return (rv);
507 * soft_aes_decrypt_common()
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
518 * Description:
519 * This function calls the corresponding decrypt routine based
520 * on the mechanism.
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
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)
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;
548 if (mechanism == CKM_AES_CTR)
549 goto do_decryption;
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.
556 * AES allows any input length for C_DecryptUpdate function.
558 if (!update) {
560 * Called by C_Decrypt
562 if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) {
563 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
564 goto cleanup;
568 * If application asks for the length of the output buffer
569 * to hold the plaintext?
571 if (pData == NULL) {
572 *pulDataLen = ulEncryptedLen;
573 return (CKR_OK);
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);
582 out_len = ulEncryptedLen;
583 } else {
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.
589 if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) {
590 *pulDataLen = ulEncryptedLen - AES_BLOCK_LEN;
591 return (CKR_BUFFER_TOO_SMALL);
593 out_len = ulEncryptedLen - AES_BLOCK_LEN;
595 in_buf = pEncrypted;
596 out_buf = pData;
597 } else {
599 * Called by C_DecryptUpdate
601 * Add the lengths of last remaining data and current
602 * input data together to get the total input length.
604 total_len = soft_aes_ctx->remain_len + ulEncryptedLen;
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.
613 if ((total_len < AES_BLOCK_LEN) ||
614 ((mechanism == CKM_AES_CBC_PAD) &&
615 (total_len == AES_BLOCK_LEN))) {
616 if (pData != NULL) {
618 * Save input data and its length in
619 * the remaining buffer of AES context.
621 (void) memcpy(soft_aes_ctx->data +
622 soft_aes_ctx->remain_len,
623 pEncrypted, ulEncryptedLen);
624 soft_aes_ctx->remain_len += ulEncryptedLen;
627 /* Set output data length to 0. */
628 *pulDataLen = 0;
629 return (CKR_OK);
632 /* Compute the length of remaing data. */
633 remain = total_len % AES_BLOCK_LEN;
636 * Make sure that the output length is a multiple of
637 * blocksize.
639 out_len = total_len - remain;
641 if (mechanism == CKM_AES_CBC_PAD) {
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.
648 if (remain == 0) {
649 remain = AES_BLOCK_LEN;
650 out_len -= AES_BLOCK_LEN;
655 * If application asks for the length of the output buffer
656 * to hold the plaintext?
658 if (pData == NULL) {
659 *pulDataLen = out_len;
660 return (CKR_OK);
664 * Is the application-supplied buffer large enough?
666 if (*pulDataLen < out_len) {
667 *pulDataLen = out_len;
668 return (CKR_BUFFER_TOO_SMALL);
671 if (soft_aes_ctx->remain_len != 0) {
673 * Copy last remaining data and current input data
674 * to the output buffer.
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);
682 in_buf = pData;
683 } else {
684 in_buf = pEncrypted;
686 out_buf = pData;
689 do_decryption:
691 * Begin Decryption.
693 switch (mechanism) {
695 case CKM_AES_ECB:
698 ulong_t i;
699 uint8_t *tmp_inbuf;
700 uint8_t *tmp_outbuf;
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);
710 if (update) {
712 * For decrypt update, if there is a remaining
713 * data, save it and its length in the context.
715 if (remain != 0)
716 (void) memcpy(soft_aes_ctx->data, pEncrypted +
717 (ulEncryptedLen - remain), remain);
718 soft_aes_ctx->remain_len = remain;
721 *pulDataLen = out_len;
723 break;
726 case CKM_AES_CBC:
727 case CKM_AES_CBC_PAD:
729 crypto_data_t out;
730 CK_ULONG rem_len;
731 uint8_t last_block[AES_BLOCK_LEN];
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;
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);
744 if (rc != 0)
745 goto decrypt_failed;
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;
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);
759 if (rc != 0)
760 goto decrypt_failed;
763 * Remove padding bytes after decryption of
764 * ciphertext block to produce the original
765 * plaintext.
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;
778 } else {
779 *pulDataLen = out_len;
782 if (update) {
784 * For decrypt update, if there is remaining data,
785 * save it and its length in the context.
787 if (remain != 0)
788 (void) memcpy(soft_aes_ctx->data, pEncrypted +
789 (ulEncryptedLen - remain), remain);
790 soft_aes_ctx->remain_len = remain;
793 if (rc == 0)
794 break;
795 decrypt_failed:
796 *pulDataLen = 0;
797 rv = CKR_FUNCTION_FAILED;
798 goto cleanup;
800 case CKM_AES_CTR:
802 crypto_data_t out;
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;
810 rc = aes_decrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
811 (char *)pEncrypted, ulEncryptedLen, &out);
813 if (rc != 0) {
814 *pulDataLen = 0;
815 rv = CKR_FUNCTION_FAILED;
816 goto cleanup;
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.
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;
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
838 *pulDataLen = ulEncryptedLen;
841 } /* end switch */
843 if (update)
844 return (CKR_OK);
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.
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);
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);
865 return (rv);
870 * Allocate and initialize a context for AES CBC mode of operation.
872 void *
873 aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
876 cbc_ctx_t *cbc_ctx;
878 if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
879 return (NULL);
881 cbc_ctx->cbc_keysched = key_sched;
882 cbc_ctx->cbc_keysched_len = size;
884 (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, AES_BLOCK_LEN);
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;
890 return (cbc_ctx);
893 void *
894 aes_cmac_ctx_init(void *key_sched, size_t size)
897 cbc_ctx_t *cbc_ctx;
899 if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
900 return (NULL);
902 cbc_ctx->cbc_keysched = key_sched;
903 cbc_ctx->cbc_keysched_len = size;
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;
909 return (cbc_ctx);
913 * Allocate and initialize a context for AES CTR mode of operation.
915 void *
916 aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param)
919 ctr_ctx_t *ctr_ctx;
920 CK_AES_CTR_PARAMS *pp;
922 /* LINTED: pointer alignment */
923 pp = (CK_AES_CTR_PARAMS *)param;
925 if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
926 return (NULL);
928 ctr_ctx->ctr_keysched = key_sched;
929 ctr_ctx->ctr_keysched_len = size;
931 if (ctr_init_ctx(ctr_ctx, pp->ulCounterBits, pp->cb, aes_copy_block)
932 != CRYPTO_SUCCESS) {
933 free(ctr_ctx);
934 return (NULL);
937 return (ctr_ctx);
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.
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)
949 soft_aes_ctx_t *soft_aes_ctx;
950 CK_MECHANISM encrypt_mech;
951 CK_RV rv;
953 if (key_p->key_type != CKK_AES) {
954 return (CKR_KEY_TYPE_INCONSISTENT);
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);
963 /* initialization vector is zero for AES CMAC */
964 bzero(soft_aes_ctx->ivec, AES_BLOCK_LEN);
966 switch (pMechanism->mechanism) {
968 case CKM_AES_CMAC_GENERAL:
970 if (pMechanism->ulParameterLen !=
971 sizeof (CK_MAC_GENERAL_PARAMS)) {
972 free(soft_aes_ctx);
973 return (CKR_MECHANISM_PARAM_INVALID);
976 if (*(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter >
977 AES_BLOCK_LEN) {
978 free(soft_aes_ctx);
979 return (CKR_MECHANISM_PARAM_INVALID);
982 soft_aes_ctx->mac_len = *((CK_MAC_GENERAL_PARAMS_PTR)
983 pMechanism->pParameter);
985 /*FALLTHRU*/
986 case CKM_AES_CMAC:
989 * For non-general AES MAC, output is always block size
991 if (pMechanism->mechanism == CKM_AES_CMAC) {
992 soft_aes_ctx->mac_len = AES_BLOCK_LEN;
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);
1006 (void) pthread_mutex_lock(&session_p->session_mutex);
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;
1017 (void) pthread_mutex_unlock(&session_p->session_mutex);
1019 break;
1021 return (CKR_OK);
1025 * Called by soft_sign(), soft_sign_final(), soft_verify() or
1026 * soft_verify_final().
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)
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];
1039 if (sign_op) {
1040 soft_aes_ctx_sign_verify =
1041 (soft_aes_ctx_t *)session_p->sign.context;
1043 if (soft_aes_ctx_sign_verify->mac_len == 0) {
1044 *pulSignedLen = 0;
1045 goto clean_exit;
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);
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);
1059 } else {
1060 soft_aes_ctx_sign_verify =
1061 (soft_aes_ctx_t *)session_p->verify.context;
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);
1072 if (rv == CKR_OK) {
1073 *pulSignedLen = soft_aes_ctx_sign_verify->mac_len;
1075 /* the leftmost mac_len bytes of last_block is our MAC */
1076 (void) memcpy(pSigned, last_block, *pulSignedLen);
1079 clean_exit:
1081 (void) pthread_mutex_lock(&session_p->session_mutex);
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;
1091 session_p->encrypt.flags = 0;
1093 (void) pthread_mutex_unlock(&session_p->session_mutex);
1095 if (pEncrypted) {
1096 free(pEncrypted);
1099 return (rv);
1103 * Called by soft_sign_update()
1105 CK_RV
1106 soft_aes_mac_sign_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
1107 CK_ULONG ulPartLen)
1109 CK_BYTE buf[AES_BLOCK_LEN];
1110 CK_ULONG ulEncryptedLen = AES_BLOCK_LEN;
1111 CK_RV rv;
1113 rv = soft_encrypt_update(session_p, pPart, ulPartLen,
1114 buf, &ulEncryptedLen);
1116 return (rv);