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]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
31 #include <sys/types.h>
32 #include <security/cryptoki.h>
34 #include "softSession.h"
35 #include "softObject.h"
36 #include "softCrypt.h"
40 * Allocate context for the active encryption or decryption operation, and
41 * generate AES key schedule to speed up the operation.
44 soft_aes_crypt_init_common(soft_session_t
*session_p
,
45 CK_MECHANISM_PTR pMechanism
, soft_object_t
*key_p
,
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
) {
60 return (CKR_HOST_MEMORY
);
63 soft_aes_ctx
->keysched_len
= size
;
65 (void) pthread_mutex_lock(&session_p
->session_mutex
);
67 /* Called by C_EncryptInit. */
68 session_p
->encrypt
.context
= soft_aes_ctx
;
69 session_p
->encrypt
.mech
.mechanism
= pMechanism
->mechanism
;
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
) {
89 (void) pthread_mutex_lock(&key_p
->object_mutex
);
90 if (OBJ_KEY_SCHED(key_p
) == NULL
) {
91 ks
= aes_alloc_keysched(&size
, 0);
93 (void) pthread_mutex_unlock(
94 &key_p
->object_mutex
);
96 return (CKR_HOST_MEMORY
);
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
);
116 * Initialize key schedule for AES. aes_init_keysched()
117 * requires key length in bits.
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 */
133 * soft_aes_encrypt_common()
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
145 * This function calls the corresponding encrypt routine based
150 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
152 * CKR_FUNCTION_FAILED: encrypt function failed
153 * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
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
)
163 soft_aes_ctx_t
*soft_aes_ctx
=
164 (soft_aes_ctx_t
*)session_p
->encrypt
.context
;
166 CK_MECHANISM_TYPE mechanism
= session_p
->encrypt
.mech
.mechanism
;
167 CK_BYTE
*in_buf
= NULL
;
168 CK_BYTE
*out_buf
= NULL
;
173 if (mechanism
== CKM_AES_CTR
)
177 * AES only takes input length that is a multiple of blocksize
178 * for C_Encrypt function with the mechanism CKM_AES_ECB or
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
;
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
;
211 * For non-padding mode, the output length will
212 * be same as the input length.
218 * If application asks for the length of the output buffer
219 * to hold the ciphertext?
221 if (pEncrypted
== NULL
) {
222 *pulEncryptedLen
= out_len
;
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
;
238 out_buf
= pEncrypted
;
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
;
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;
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
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
;
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
);
334 * Begin Encryption now.
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
);
355 * For encrypt update, if there is a remaining
356 * data, save it and its length in the context.
359 (void) memcpy(soft_aes_ctx
->data
, pData
+
360 (ulDataLen
- remain
), remain
);
361 soft_aes_ctx
->remain_len
= remain
;
364 *pulEncryptedLen
= out_len
;
373 case CKM_AES_CBC_PAD
:
377 out
.cd_format
= CRYPTO_DATA_RAW
;
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
);
393 * For encrypt update, if there is remaining data,
394 * save it and its length in the context.
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
);
435 *pulEncryptedLen
= out_len
;
439 *pulEncryptedLen
= 0;
440 rv
= CKR_FUNCTION_FAILED
;
447 out
.cd_format
= CRYPTO_DATA_RAW
;
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
);
457 *pulEncryptedLen
= 0;
458 rv
= CKR_FUNCTION_FAILED
;
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
,
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
;
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.
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
);
507 * soft_aes_decrypt_common()
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
519 * This function calls the corresponding decrypt routine based
524 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
526 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
528 * CKR_FUNCTION_FAILED: decrypt function failed
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
)
538 soft_aes_ctx_t
*soft_aes_ctx
=
539 (soft_aes_ctx_t
*)session_p
->decrypt
.context
;
541 CK_MECHANISM_TYPE mechanism
= session_p
->decrypt
.mech
.mechanism
;
542 CK_BYTE
*in_buf
= NULL
;
543 CK_BYTE
*out_buf
= NULL
;
548 if (mechanism
== CKM_AES_CTR
)
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.
560 * Called by C_Decrypt
562 if ((ulEncryptedLen
% AES_BLOCK_LEN
) != 0) {
563 rv
= CKR_ENCRYPTED_DATA_LEN_RANGE
;
568 * If application asks for the length of the output buffer
569 * to hold the plaintext?
572 *pulDataLen
= ulEncryptedLen
;
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
;
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
;
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
))) {
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. */
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
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.
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?
659 *pulDataLen
= out_len
;
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
);
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
);
712 * For decrypt update, if there is a remaining
713 * data, save it and its length in the context.
716 (void) memcpy(soft_aes_ctx
->data
, pEncrypted
+
717 (ulEncryptedLen
- remain
), remain
);
718 soft_aes_ctx
->remain_len
= remain
;
721 *pulDataLen
= out_len
;
727 case CKM_AES_CBC_PAD
:
731 uint8_t last_block
[AES_BLOCK_LEN
];
733 out
.cd_format
= CRYPTO_DATA_RAW
;
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
);
747 if ((mechanism
== CKM_AES_CBC_PAD
) && (!update
)) {
748 /* Decrypt last block containing pad bytes. */
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
);
763 * Remove padding bytes after decryption of
764 * ciphertext block to produce the original
767 rv
= soft_remove_pkcs7_padding(last_block
,
768 AES_BLOCK_LEN
, &rem_len
);
771 (void) memcpy(out_buf
+ out_len
,
772 last_block
, rem_len
);
773 *pulDataLen
= out_len
+ rem_len
;
779 *pulDataLen
= out_len
;
784 * For decrypt update, if there is remaining data,
785 * save it and its length in the context.
788 (void) memcpy(soft_aes_ctx
->data
, pEncrypted
+
789 (ulEncryptedLen
- remain
), remain
);
790 soft_aes_ctx
->remain_len
= remain
;
797 rv
= CKR_FUNCTION_FAILED
;
804 out
.cd_format
= CRYPTO_DATA_RAW
;
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
);
815 rv
= CKR_FUNCTION_FAILED
;
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
827 rc
= ctr_mode_final(soft_aes_ctx
->aes_cbc
, &out
,
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
;
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.
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
);
870 * Allocate and initialize a context for AES CBC mode of operation.
873 aes_cbc_ctx_init(void *key_sched
, size_t size
, uint8_t *ivec
)
878 if ((cbc_ctx
= calloc(1, sizeof (cbc_ctx_t
))) == 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
;
894 aes_cmac_ctx_init(void *key_sched
, size_t size
)
899 if ((cbc_ctx
= calloc(1, sizeof (cbc_ctx_t
))) == 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;
913 * Allocate and initialize a context for AES CTR mode of operation.
916 aes_ctr_ctx_init(void *key_sched
, size_t size
, uint8_t *param
)
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
)
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
)
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.
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
;
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
)) {
973 return (CKR_MECHANISM_PARAM_INVALID
);
976 if (*(CK_MAC_GENERAL_PARAMS
*)pMechanism
->pParameter
>
979 return (CKR_MECHANISM_PARAM_INVALID
);
982 soft_aes_ctx
->mac_len
= *((CK_MAC_GENERAL_PARAMS_PTR
)
983 pMechanism
->pParameter
);
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
,
1006 (void) pthread_mutex_lock(&session_p
->session_mutex
);
1009 session_p
->sign
.context
= soft_aes_ctx
;
1010 session_p
->sign
.mech
.mechanism
= pMechanism
->mechanism
;
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
);
1025 * Called by soft_sign(), soft_sign_final(), soft_verify() or
1026 * soft_verify_final().
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
;
1035 CK_BYTE
*pEncrypted
= NULL
;
1036 CK_ULONG ulEncryptedLen
= AES_BLOCK_LEN
;
1037 CK_BYTE last_block
[AES_BLOCK_LEN
];
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) {
1048 /* Application asks for the length of the output buffer. */
1049 if (pSigned
== NULL
) {
1050 *pulSignedLen
= soft_aes_ctx_sign_verify
->mac_len
;
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
);
1060 soft_aes_ctx_sign_verify
=
1061 (soft_aes_ctx_t
*)session_p
->verify
.context
;
1065 rv
= soft_encrypt_final(session_p
, last_block
,
1068 rv
= soft_encrypt(session_p
, pData
, ulDataLen
,
1069 last_block
, &ulEncryptedLen
);
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
);
1081 (void) pthread_mutex_lock(&session_p
->session_mutex
);
1083 /* soft_encrypt_common() has freed the encrypt context */
1085 free(session_p
->sign
.context
);
1086 session_p
->sign
.context
= NULL
;
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
);
1103 * Called by soft_sign_update()
1106 soft_aes_mac_sign_verify_update(soft_session_t
*session_p
, CK_BYTE_PTR pPart
,
1109 CK_BYTE buf
[AES_BLOCK_LEN
];
1110 CK_ULONG ulEncryptedLen
= AES_BLOCK_LEN
;
1113 rv
= soft_encrypt_update(session_p
, pPart
, ulPartLen
,
1114 buf
, &ulEncryptedLen
);