dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / pkcs11 / pkcs11_softtoken / common / softAESCrypt.c
blob60343360dc11f36c199f55048b9cd40da4770575
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.
26 #include <pthread.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <strings.h>
30 #include <sys/types.h>
31 #include <security/cryptoki.h>
32 #include "softSession.h"
33 #include "softObject.h"
34 #include "softCrypt.h"
35 #include <aes_impl.h>
38 * Allocate context for the active encryption or decryption operation, and
39 * generate AES key schedule to speed up the operation.
41 CK_RV
42 soft_aes_crypt_init_common(soft_session_t *session_p,
43 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
44 boolean_t encrypt)
46 size_t size;
47 soft_aes_ctx_t *soft_aes_ctx;
49 soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t));
50 if (soft_aes_ctx == NULL) {
51 return (CKR_HOST_MEMORY);
54 soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0);
56 if (soft_aes_ctx->key_sched == NULL) {
57 free(soft_aes_ctx);
58 return (CKR_HOST_MEMORY);
61 soft_aes_ctx->keysched_len = size;
63 (void) pthread_mutex_lock(&session_p->session_mutex);
64 if (encrypt) {
65 /* Called by C_EncryptInit. */
66 session_p->encrypt.context = soft_aes_ctx;
67 session_p->encrypt.mech.mechanism = pMechanism->mechanism;
68 } else {
69 /* Called by C_DecryptInit. */
70 session_p->decrypt.context = soft_aes_ctx;
71 session_p->decrypt.mech.mechanism = pMechanism->mechanism;
73 (void) pthread_mutex_unlock(&session_p->session_mutex);
76 * If this is a non-sensitive key and it does NOT have
77 * a key schedule yet, then allocate one and expand it.
78 * Otherwise, if it's a non-sensitive key, and it DOES have
79 * a key schedule already attached to it, just copy the
80 * pre-expanded schedule to the context and avoid the
81 * extra key schedule expansion operation.
83 if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
84 if (OBJ_KEY_SCHED(key_p) == NULL) {
85 void *ks;
87 (void) pthread_mutex_lock(&key_p->object_mutex);
88 if (OBJ_KEY_SCHED(key_p) == NULL) {
89 ks = aes_alloc_keysched(&size, 0);
90 if (ks == NULL) {
91 (void) pthread_mutex_unlock(
92 &key_p->object_mutex);
93 free(soft_aes_ctx);
94 return (CKR_HOST_MEMORY);
96 aes_init_keysched(OBJ_SEC_VALUE(key_p),
97 (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
98 OBJ_KEY_SCHED_LEN(key_p) = size;
99 OBJ_KEY_SCHED(key_p) = ks;
101 (void) pthread_mutex_unlock(&key_p->object_mutex);
103 (void) memcpy(soft_aes_ctx->key_sched, OBJ_KEY_SCHED(key_p),
104 OBJ_KEY_SCHED_LEN(key_p));
105 soft_aes_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
106 } else {
108 * Initialize key schedule for AES. aes_init_keysched()
109 * requires key length in bits.
111 aes_init_keysched(OBJ_SEC_VALUE(key_p),
112 (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched);
114 return (CKR_OK);
119 * soft_aes_encrypt_common()
121 * Arguments:
122 * session_p: pointer to soft_session_t struct
123 * pData: pointer to the input data to be encrypted
124 * ulDataLen: length of the input data
125 * pEncrypted: pointer to the output data after encryption
126 * pulEncryptedLen: pointer to the length of the output data
127 * update: boolean flag indicates caller is soft_encrypt
128 * or soft_encrypt_update
130 * Description:
131 * This function calls the corresponding encrypt routine based
132 * on the mechanism.
134 * Returns:
135 * CKR_OK: success
136 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
137 * is too small
138 * CKR_FUNCTION_FAILED: encrypt function failed
139 * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
141 CK_RV
142 soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
143 CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
144 CK_ULONG_PTR pulEncryptedLen, boolean_t update)
147 int rc = 0;
148 CK_RV rv = CKR_OK;
149 soft_aes_ctx_t *soft_aes_ctx =
150 (soft_aes_ctx_t *)session_p->encrypt.context;
151 aes_ctx_t *aes_ctx;
152 CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
153 CK_BYTE *in_buf = NULL;
154 CK_BYTE *out_buf = NULL;
155 CK_ULONG out_len;
156 CK_ULONG total_len;
157 CK_ULONG remain;
159 if (mechanism == CKM_AES_CTR)
160 goto do_encryption;
163 * AES only takes input length that is a multiple of blocksize
164 * for C_Encrypt function with the mechanism CKM_AES_ECB or
165 * CKM_AES_CBC.
167 * AES allows any input length for C_Encrypt function with the
168 * mechanism CKM_AES_CBC_PAD and for C_EncryptUpdate function.
170 if ((!update) && (mechanism != CKM_AES_CBC_PAD)) {
171 if ((ulDataLen % AES_BLOCK_LEN) != 0) {
172 rv = CKR_DATA_LEN_RANGE;
173 goto cleanup;
177 if (!update) {
179 * Called by C_Encrypt
181 if (mechanism == CKM_AES_CBC_PAD) {
183 * For CKM_AES_CBC_PAD, compute output length to
184 * count for the padding. If the length of input
185 * data is a multiple of blocksize, then make output
186 * length to be the sum of the input length and
187 * one blocksize. Otherwise, output length will
188 * be rounded up to the next multiple of blocksize.
190 out_len = AES_BLOCK_LEN *
191 (ulDataLen / AES_BLOCK_LEN + 1);
192 } else {
194 * For non-padding mode, the output length will
195 * be same as the input length.
197 out_len = ulDataLen;
201 * If application asks for the length of the output buffer
202 * to hold the ciphertext?
204 if (pEncrypted == NULL) {
205 *pulEncryptedLen = out_len;
206 return (CKR_OK);
209 /* Is the application-supplied buffer large enough? */
210 if (*pulEncryptedLen < out_len) {
211 *pulEncryptedLen = out_len;
212 return (CKR_BUFFER_TOO_SMALL);
215 /* Encrypt pad bytes in a separate operation */
216 if (mechanism == CKM_AES_CBC_PAD) {
217 out_len -= AES_BLOCK_LEN;
220 in_buf = pData;
221 out_buf = pEncrypted;
222 } else {
224 * Called by C_EncryptUpdate
226 * Add the lengths of last remaining data and current
227 * plaintext together to get the total input length.
229 total_len = soft_aes_ctx->remain_len + ulDataLen;
232 * If the total input length is less than one blocksize,
233 * or if the total input length is just one blocksize and
234 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
235 * encryption until when more data comes in next
236 * C_EncryptUpdate or when C_EncryptFinal is called.
238 if ((total_len < AES_BLOCK_LEN) ||
239 ((mechanism == CKM_AES_CBC_PAD) &&
240 (total_len == AES_BLOCK_LEN))) {
241 if (pEncrypted != NULL) {
243 * Save input data and its length in
244 * the remaining buffer of AES context.
246 (void) memcpy(soft_aes_ctx->data +
247 soft_aes_ctx->remain_len, pData, ulDataLen);
248 soft_aes_ctx->remain_len += ulDataLen;
251 /* Set encrypted data length to 0. */
252 *pulEncryptedLen = 0;
253 return (CKR_OK);
256 /* Compute the length of remaing data. */
257 remain = total_len % AES_BLOCK_LEN;
260 * Make sure that the output length is a multiple of
261 * blocksize.
263 out_len = total_len - remain;
266 * If application asks for the length of the output buffer
267 * to hold the ciphertext?
269 if (pEncrypted == NULL) {
270 *pulEncryptedLen = out_len;
271 return (CKR_OK);
274 /* Is the application-supplied buffer large enough? */
275 if (*pulEncryptedLen < out_len) {
276 *pulEncryptedLen = out_len;
277 return (CKR_BUFFER_TOO_SMALL);
280 if (soft_aes_ctx->remain_len != 0) {
282 * Copy last remaining data and current input data
283 * to the output buffer.
285 (void) memmove(pEncrypted + soft_aes_ctx->remain_len,
286 pData, out_len - soft_aes_ctx->remain_len);
287 (void) memcpy(pEncrypted, soft_aes_ctx->data,
288 soft_aes_ctx->remain_len);
289 bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
291 in_buf = pEncrypted;
292 } else {
293 in_buf = pData;
295 out_buf = pEncrypted;
298 do_encryption:
300 * Begin Encryption now.
302 switch (mechanism) {
304 case CKM_AES_ECB:
307 ulong_t i;
308 uint8_t *tmp_inbuf;
309 uint8_t *tmp_outbuf;
311 for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
312 tmp_inbuf = &in_buf[i];
313 tmp_outbuf = &out_buf[i];
314 /* Crunch one block of data for AES. */
315 (void) aes_encrypt_block(soft_aes_ctx->key_sched,
316 tmp_inbuf, tmp_outbuf);
319 if (update) {
321 * For encrypt update, if there is a remaining
322 * data, save it and its length in the context.
324 if (remain != 0)
325 (void) memcpy(soft_aes_ctx->data, pData +
326 (ulDataLen - remain), remain);
327 soft_aes_ctx->remain_len = remain;
330 *pulEncryptedLen = out_len;
332 break;
335 case CKM_AES_CBC:
336 case CKM_AES_CBC_PAD:
338 crypto_data_t out;
340 out.cd_format = CRYPTO_DATA_RAW;
341 out.cd_offset = 0;
342 out.cd_length = out_len;
343 out.cd_raw.iov_base = (char *)out_buf;
344 out.cd_raw.iov_len = out_len;
346 /* Encrypt multiple blocks of data. */
347 rc = aes_encrypt_contiguous_blocks(
348 (aes_ctx_t *)soft_aes_ctx->aes_cbc,
349 (char *)in_buf, out_len, &out);
351 if (rc != 0)
352 goto encrypt_failed;
354 if (update) {
356 * For encrypt update, if there is remaining data,
357 * save it and its length in the context.
359 if (remain != 0)
360 (void) memcpy(soft_aes_ctx->data, pData +
361 (ulDataLen - remain), remain);
362 soft_aes_ctx->remain_len = remain;
363 } else if (mechanism == CKM_AES_CBC_PAD) {
365 * Save the remainder of the input
366 * block in a temporary block because
367 * we dont want to overrun the buffer
368 * by tacking on pad bytes.
370 CK_BYTE tmpblock[AES_BLOCK_LEN];
371 (void) memcpy(tmpblock, in_buf + out_len,
372 ulDataLen - out_len);
373 soft_add_pkcs7_padding(tmpblock +
374 (ulDataLen - out_len),
375 AES_BLOCK_LEN, ulDataLen - out_len);
377 out.cd_offset = out_len;
378 out.cd_length = AES_BLOCK_LEN;
379 out.cd_raw.iov_base = (char *)out_buf;
380 out.cd_raw.iov_len = out_len + AES_BLOCK_LEN;
382 /* Encrypt last block containing pad bytes. */
383 rc = aes_encrypt_contiguous_blocks(
384 (aes_ctx_t *)soft_aes_ctx->aes_cbc,
385 (char *)tmpblock, AES_BLOCK_LEN, &out);
387 out_len += AES_BLOCK_LEN;
390 if (rc == 0) {
391 *pulEncryptedLen = out_len;
392 break;
394 encrypt_failed:
395 *pulEncryptedLen = 0;
396 rv = CKR_FUNCTION_FAILED;
397 goto cleanup;
399 case CKM_AES_CTR:
401 crypto_data_t out;
403 out.cd_format = CRYPTO_DATA_RAW;
404 out.cd_offset = 0;
405 out.cd_length = *pulEncryptedLen;
406 out.cd_raw.iov_base = (char *)pEncrypted;
407 out.cd_raw.iov_len = *pulEncryptedLen;
409 rc = aes_encrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
410 (char *)pData, ulDataLen, &out);
412 if (rc != 0) {
413 *pulEncryptedLen = 0;
414 rv = CKR_FUNCTION_FAILED;
415 goto cleanup;
418 * Since AES counter mode is a stream cipher, we call
419 * aes_counter_final() to pick up any remaining bytes.
420 * It is an internal function that does not destroy
421 * the context like *normal* final routines.
423 if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len > 0)
424 rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
425 aes_encrypt_block);
427 } /* end switch */
429 if (update)
430 return (CKR_OK);
433 * The following code will be executed if the caller is
434 * soft_encrypt() or an error occurred. The encryption
435 * operation will be terminated so we need to do some cleanup.
437 cleanup:
438 (void) pthread_mutex_lock(&session_p->session_mutex);
439 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
440 if (aes_ctx != NULL) {
441 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
442 free(soft_aes_ctx->aes_cbc);
445 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
446 free(soft_aes_ctx->key_sched);
447 free(session_p->encrypt.context);
448 session_p->encrypt.context = NULL;
449 (void) pthread_mutex_unlock(&session_p->session_mutex);
451 return (rv);
456 * soft_aes_decrypt_common()
458 * Arguments:
459 * session_p: pointer to soft_session_t struct
460 * pEncrypted: pointer to the input data to be decrypted
461 * ulEncryptedLen: length of the input data
462 * pData: pointer to the output data
463 * pulDataLen: pointer to the length of the output data
464 * Update: boolean flag indicates caller is soft_decrypt
465 * or soft_decrypt_update
467 * Description:
468 * This function calls the corresponding decrypt routine based
469 * on the mechanism.
471 * Returns:
472 * CKR_OK: success
473 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
474 * is too small
475 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
476 * of blocksize
477 * CKR_FUNCTION_FAILED: decrypt function failed
479 CK_RV
480 soft_aes_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
481 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
482 CK_ULONG_PTR pulDataLen, boolean_t update)
485 int rc = 0;
486 CK_RV rv = CKR_OK;
487 soft_aes_ctx_t *soft_aes_ctx =
488 (soft_aes_ctx_t *)session_p->decrypt.context;
489 aes_ctx_t *aes_ctx;
490 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
491 CK_BYTE *in_buf = NULL;
492 CK_BYTE *out_buf = NULL;
493 CK_ULONG out_len;
494 CK_ULONG total_len;
495 CK_ULONG remain;
497 if (mechanism == CKM_AES_CTR)
498 goto do_decryption;
501 * AES only takes input length that is a multiple of 16 bytes
502 * for C_Decrypt function with the mechanism CKM_AES_ECB,
503 * CKM_AES_CBC or CKM_AES_CBC_PAD.
505 * AES allows any input length for C_DecryptUpdate function.
507 if (!update) {
509 * Called by C_Decrypt
511 if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) {
512 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
513 goto cleanup;
517 * If application asks for the length of the output buffer
518 * to hold the plaintext?
520 if (pData == NULL) {
521 *pulDataLen = ulEncryptedLen;
522 return (CKR_OK);
525 /* Is the application-supplied buffer large enough? */
526 if (mechanism != CKM_AES_CBC_PAD) {
527 if (*pulDataLen < ulEncryptedLen) {
528 *pulDataLen = ulEncryptedLen;
529 return (CKR_BUFFER_TOO_SMALL);
531 out_len = ulEncryptedLen;
532 } else {
534 * For CKM_AES_CBC_PAD, we don't know how
535 * many bytes for padding at this time, so
536 * we'd assume one block was padded.
538 if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) {
539 *pulDataLen = ulEncryptedLen - AES_BLOCK_LEN;
540 return (CKR_BUFFER_TOO_SMALL);
542 out_len = ulEncryptedLen - AES_BLOCK_LEN;
544 in_buf = pEncrypted;
545 out_buf = pData;
546 } else {
548 * Called by C_DecryptUpdate
550 * Add the lengths of last remaining data and current
551 * input data together to get the total input length.
553 total_len = soft_aes_ctx->remain_len + ulEncryptedLen;
556 * If the total input length is less than one blocksize,
557 * or if the total input length is just one blocksize and
558 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
559 * decryption until when more data comes in next
560 * C_DecryptUpdate or when C_DecryptFinal is called.
562 if ((total_len < AES_BLOCK_LEN) ||
563 ((mechanism == CKM_AES_CBC_PAD) &&
564 (total_len == AES_BLOCK_LEN))) {
565 if (pData != NULL) {
567 * Save input data and its length in
568 * the remaining buffer of AES context.
570 (void) memcpy(soft_aes_ctx->data +
571 soft_aes_ctx->remain_len,
572 pEncrypted, ulEncryptedLen);
573 soft_aes_ctx->remain_len += ulEncryptedLen;
576 /* Set output data length to 0. */
577 *pulDataLen = 0;
578 return (CKR_OK);
581 /* Compute the length of remaing data. */
582 remain = total_len % AES_BLOCK_LEN;
585 * Make sure that the output length is a multiple of
586 * blocksize.
588 out_len = total_len - remain;
590 if (mechanism == CKM_AES_CBC_PAD) {
592 * If the input data length is a multiple of
593 * blocksize, then save the last block of input
594 * data in the remaining buffer. C_DecryptFinal
595 * will handle this last block of data.
597 if (remain == 0) {
598 remain = AES_BLOCK_LEN;
599 out_len -= AES_BLOCK_LEN;
604 * If application asks for the length of the output buffer
605 * to hold the plaintext?
607 if (pData == NULL) {
608 *pulDataLen = out_len;
609 return (CKR_OK);
613 * Is the application-supplied buffer large enough?
615 if (*pulDataLen < out_len) {
616 *pulDataLen = out_len;
617 return (CKR_BUFFER_TOO_SMALL);
620 if (soft_aes_ctx->remain_len != 0) {
622 * Copy last remaining data and current input data
623 * to the output buffer.
625 (void) memmove(pData + soft_aes_ctx->remain_len,
626 pEncrypted, out_len - soft_aes_ctx->remain_len);
627 (void) memcpy(pData, soft_aes_ctx->data,
628 soft_aes_ctx->remain_len);
629 bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
631 in_buf = pData;
632 } else {
633 in_buf = pEncrypted;
635 out_buf = pData;
638 do_decryption:
640 * Begin Decryption.
642 switch (mechanism) {
644 case CKM_AES_ECB:
647 ulong_t i;
648 uint8_t *tmp_inbuf;
649 uint8_t *tmp_outbuf;
651 for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
652 tmp_inbuf = &in_buf[i];
653 tmp_outbuf = &out_buf[i];
654 /* Crunch one block of data for AES. */
655 (void) aes_decrypt_block(soft_aes_ctx->key_sched,
656 tmp_inbuf, tmp_outbuf);
659 if (update) {
661 * For decrypt update, if there is a remaining
662 * data, save it and its length in the context.
664 if (remain != 0)
665 (void) memcpy(soft_aes_ctx->data, pEncrypted +
666 (ulEncryptedLen - remain), remain);
667 soft_aes_ctx->remain_len = remain;
670 *pulDataLen = out_len;
672 break;
675 case CKM_AES_CBC:
676 case CKM_AES_CBC_PAD:
678 crypto_data_t out;
679 CK_ULONG rem_len;
680 uint8_t last_block[AES_BLOCK_LEN];
682 out.cd_format = CRYPTO_DATA_RAW;
683 out.cd_offset = 0;
684 out.cd_length = out_len;
685 out.cd_raw.iov_base = (char *)out_buf;
686 out.cd_raw.iov_len = out_len;
688 /* Decrypt multiple blocks of data. */
689 rc = aes_decrypt_contiguous_blocks(
690 (aes_ctx_t *)soft_aes_ctx->aes_cbc,
691 (char *)in_buf, out_len, &out);
693 if (rc != 0)
694 goto decrypt_failed;
696 if ((mechanism == CKM_AES_CBC_PAD) && (!update)) {
697 /* Decrypt last block containing pad bytes. */
698 out.cd_offset = 0;
699 out.cd_length = AES_BLOCK_LEN;
700 out.cd_raw.iov_base = (char *)last_block;
701 out.cd_raw.iov_len = AES_BLOCK_LEN;
703 /* Decrypt last block containing pad bytes. */
704 rc = aes_decrypt_contiguous_blocks(
705 (aes_ctx_t *)soft_aes_ctx->aes_cbc,
706 (char *)in_buf + out_len, AES_BLOCK_LEN, &out);
708 if (rc != 0)
709 goto decrypt_failed;
712 * Remove padding bytes after decryption of
713 * ciphertext block to produce the original
714 * plaintext.
716 rv = soft_remove_pkcs7_padding(last_block,
717 AES_BLOCK_LEN, &rem_len);
718 if (rv == CKR_OK) {
719 if (rem_len != 0)
720 (void) memcpy(out_buf + out_len,
721 last_block, rem_len);
722 *pulDataLen = out_len + rem_len;
723 } else {
724 *pulDataLen = 0;
725 goto cleanup;
727 } else {
728 *pulDataLen = out_len;
731 if (update) {
733 * For decrypt update, if there is remaining data,
734 * save it and its length in the context.
736 if (remain != 0)
737 (void) memcpy(soft_aes_ctx->data, pEncrypted +
738 (ulEncryptedLen - remain), remain);
739 soft_aes_ctx->remain_len = remain;
742 if (rc == 0)
743 break;
744 decrypt_failed:
745 *pulDataLen = 0;
746 rv = CKR_FUNCTION_FAILED;
747 goto cleanup;
749 case CKM_AES_CTR:
751 crypto_data_t out;
753 out.cd_format = CRYPTO_DATA_RAW;
754 out.cd_offset = 0;
755 out.cd_length = *pulDataLen;
756 out.cd_raw.iov_base = (char *)pData;
757 out.cd_raw.iov_len = *pulDataLen;
759 rc = aes_decrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
760 (char *)pEncrypted, ulEncryptedLen, &out);
762 if (rc != 0) {
763 *pulDataLen = 0;
764 rv = CKR_FUNCTION_FAILED;
765 goto cleanup;
769 * Since AES counter mode is a stream cipher, we call
770 * aes_counter_final() to pick up any remaining bytes.
771 * It is an internal function that does not destroy
772 * the context like *normal* final routines.
774 if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len
775 > 0) {
776 rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
777 aes_encrypt_block);
778 if (rc == CRYPTO_DATA_LEN_RANGE)
779 rc = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
782 } /* end switch */
784 if (update)
785 return (CKR_OK);
788 * The following code will be executed if the caller is
789 * soft_decrypt() or an error occurred. The decryption
790 * operation will be terminated so we need to do some cleanup.
792 cleanup:
793 (void) pthread_mutex_lock(&session_p->session_mutex);
794 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
795 if (aes_ctx != NULL) {
796 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
797 free(soft_aes_ctx->aes_cbc);
800 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
801 free(soft_aes_ctx->key_sched);
802 free(session_p->decrypt.context);
803 session_p->decrypt.context = NULL;
804 (void) pthread_mutex_unlock(&session_p->session_mutex);
806 return (rv);
811 * Allocate and initialize a context for AES CBC mode of operation.
813 void *
814 aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
817 cbc_ctx_t *cbc_ctx;
819 if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
820 return (NULL);
822 cbc_ctx->cbc_keysched = key_sched;
823 cbc_ctx->cbc_keysched_len = size;
825 (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, AES_BLOCK_LEN);
827 cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv;
828 cbc_ctx->cbc_flags |= CBC_MODE;
830 return (cbc_ctx);
834 * Allocate and initialize a context for AES CTR mode of operation.
836 void *
837 aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param)
840 ctr_ctx_t *ctr_ctx;
841 CK_AES_CTR_PARAMS *pp;
843 /* LINTED: pointer alignment */
844 pp = (CK_AES_CTR_PARAMS *)param;
846 if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
847 return (NULL);
849 ctr_ctx->ctr_keysched = key_sched;
850 ctr_ctx->ctr_keysched_len = size;
852 if (ctr_init_ctx(ctr_ctx, pp->ulCounterBits, pp->cb, aes_copy_block)
853 != CRYPTO_SUCCESS) {
854 free(ctr_ctx);
855 return (NULL);
858 return (ctr_ctx);