110500SHai-May.Chao@Sun.COM /*
210500SHai-May.Chao@Sun.COM * CDDL HEADER START
310500SHai-May.Chao@Sun.COM *
410500SHai-May.Chao@Sun.COM * The contents of this file are subject to the terms of the
510500SHai-May.Chao@Sun.COM * Common Development and Distribution License (the "License").
610500SHai-May.Chao@Sun.COM * You may not use this file except in compliance with the License.
710500SHai-May.Chao@Sun.COM *
810500SHai-May.Chao@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910500SHai-May.Chao@Sun.COM * or http://www.opensolaris.org/os/licensing.
1010500SHai-May.Chao@Sun.COM * See the License for the specific language governing permissions
1110500SHai-May.Chao@Sun.COM * and limitations under the License.
1210500SHai-May.Chao@Sun.COM *
1310500SHai-May.Chao@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1410500SHai-May.Chao@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510500SHai-May.Chao@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1610500SHai-May.Chao@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1710500SHai-May.Chao@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1810500SHai-May.Chao@Sun.COM *
1910500SHai-May.Chao@Sun.COM * CDDL HEADER END
2010500SHai-May.Chao@Sun.COM */
2110500SHai-May.Chao@Sun.COM /*
22*12929SMisaki.Miyashita@Oracle.COM * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2310500SHai-May.Chao@Sun.COM */
2410500SHai-May.Chao@Sun.COM
2510500SHai-May.Chao@Sun.COM #include <sys/types.h>
2610500SHai-May.Chao@Sun.COM #include <sys/param.h>
2710500SHai-May.Chao@Sun.COM #include <sys/cmn_err.h>
2810500SHai-May.Chao@Sun.COM #include <sys/errno.h>
2910500SHai-May.Chao@Sun.COM #include <sys/kmem.h>
3010500SHai-May.Chao@Sun.COM #include <sys/systm.h>
3110500SHai-May.Chao@Sun.COM #include <sys/crypto/common.h>
3210500SHai-May.Chao@Sun.COM #include <modes/modes.h>
3310500SHai-May.Chao@Sun.COM #define _AES_FIPS_POST
34*12929SMisaki.Miyashita@Oracle.COM #include <fips/fips_test_vectors.h>
3510500SHai-May.Chao@Sun.COM #ifndef _KERNEL
3610500SHai-May.Chao@Sun.COM #include <stdlib.h>
3710500SHai-May.Chao@Sun.COM #include <string.h>
3810500SHai-May.Chao@Sun.COM #include <strings.h>
3910500SHai-May.Chao@Sun.COM #include <stdio.h>
4010500SHai-May.Chao@Sun.COM #include <security/cryptoki.h>
4110500SHai-May.Chao@Sun.COM #include <cryptoutil.h>
4210500SHai-May.Chao@Sun.COM #include "softCrypt.h"
4310500SHai-May.Chao@Sun.COM #else
4410500SHai-May.Chao@Sun.COM #define _AES_IMPL
4510500SHai-May.Chao@Sun.COM #include <aes/aes_impl.h>
4610500SHai-May.Chao@Sun.COM #endif
4710500SHai-May.Chao@Sun.COM
4810500SHai-May.Chao@Sun.COM
4910500SHai-May.Chao@Sun.COM #ifdef _KERNEL
5010500SHai-May.Chao@Sun.COM void *
aes_cbc_ctx_init(void * key_sched,size_t size,uint8_t * ivec)5110500SHai-May.Chao@Sun.COM aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
5210500SHai-May.Chao@Sun.COM {
5310500SHai-May.Chao@Sun.COM
5410500SHai-May.Chao@Sun.COM cbc_ctx_t *cbc_ctx;
5510500SHai-May.Chao@Sun.COM
5610500SHai-May.Chao@Sun.COM if ((cbc_ctx = kmem_zalloc(sizeof (cbc_ctx_t), KM_SLEEP)) == NULL)
5710500SHai-May.Chao@Sun.COM return (NULL);
5810500SHai-May.Chao@Sun.COM
5910500SHai-May.Chao@Sun.COM cbc_ctx->cbc_keysched = key_sched;
6010500SHai-May.Chao@Sun.COM cbc_ctx->cbc_keysched_len = size;
6110500SHai-May.Chao@Sun.COM
6210500SHai-May.Chao@Sun.COM (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, AES_BLOCK_LEN);
6310500SHai-May.Chao@Sun.COM
6410500SHai-May.Chao@Sun.COM cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv;
6510500SHai-May.Chao@Sun.COM cbc_ctx->cbc_flags |= CBC_MODE;
6610500SHai-May.Chao@Sun.COM
6710500SHai-May.Chao@Sun.COM return (cbc_ctx);
6810500SHai-May.Chao@Sun.COM }
6910500SHai-May.Chao@Sun.COM
7010500SHai-May.Chao@Sun.COM /*
7110500SHai-May.Chao@Sun.COM * Allocate and initialize a context for AES CTR mode of operation.
7210500SHai-May.Chao@Sun.COM */
7310500SHai-May.Chao@Sun.COM void *
aes_ctr_ctx_init(void * key_sched,size_t size,uint8_t * param)7410500SHai-May.Chao@Sun.COM aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param)
7510500SHai-May.Chao@Sun.COM {
7610500SHai-May.Chao@Sun.COM
7710500SHai-May.Chao@Sun.COM ctr_ctx_t *ctr_ctx;
7810500SHai-May.Chao@Sun.COM CK_AES_CTR_PARAMS *pp;
7910500SHai-May.Chao@Sun.COM
8010500SHai-May.Chao@Sun.COM /* LINTED: pointer alignment */
8110500SHai-May.Chao@Sun.COM pp = (CK_AES_CTR_PARAMS *)param;
8210500SHai-May.Chao@Sun.COM
8310500SHai-May.Chao@Sun.COM if ((ctr_ctx = kmem_zalloc(sizeof (ctr_ctx_t), KM_SLEEP)) == NULL)
8410500SHai-May.Chao@Sun.COM return (NULL);
8510500SHai-May.Chao@Sun.COM
8610500SHai-May.Chao@Sun.COM ctr_ctx->ctr_keysched = key_sched;
8710500SHai-May.Chao@Sun.COM ctr_ctx->ctr_keysched_len = size;
8810500SHai-May.Chao@Sun.COM
8910500SHai-May.Chao@Sun.COM if (ctr_init_ctx(ctr_ctx, pp->ulCounterBits, pp->cb,
9010500SHai-May.Chao@Sun.COM aes_copy_block) != CRYPTO_SUCCESS) {
9110500SHai-May.Chao@Sun.COM kmem_free(ctr_ctx, sizeof (ctr_ctx_t));
9210500SHai-May.Chao@Sun.COM return (NULL);
9310500SHai-May.Chao@Sun.COM }
9410500SHai-May.Chao@Sun.COM ctr_ctx->ctr_flags |= CTR_MODE;
9510500SHai-May.Chao@Sun.COM
9610500SHai-May.Chao@Sun.COM return (ctr_ctx);
9710500SHai-May.Chao@Sun.COM }
9810500SHai-May.Chao@Sun.COM
9910500SHai-May.Chao@Sun.COM /*
10010500SHai-May.Chao@Sun.COM * Allocate and initialize a context for AES CCM mode of operation.
10110500SHai-May.Chao@Sun.COM */
10210500SHai-May.Chao@Sun.COM void *
aes_ccm_ctx_init(void * key_sched,size_t size,uint8_t * param,boolean_t is_encrypt_init)10310500SHai-May.Chao@Sun.COM aes_ccm_ctx_init(void *key_sched, size_t size, uint8_t *param,
10410500SHai-May.Chao@Sun.COM boolean_t is_encrypt_init)
10510500SHai-May.Chao@Sun.COM {
10610500SHai-May.Chao@Sun.COM
10710500SHai-May.Chao@Sun.COM ccm_ctx_t *ccm_ctx;
10810500SHai-May.Chao@Sun.COM
10910500SHai-May.Chao@Sun.COM if ((ccm_ctx = kmem_zalloc(sizeof (ccm_ctx_t), KM_SLEEP)) == NULL)
11010500SHai-May.Chao@Sun.COM return (NULL);
11110500SHai-May.Chao@Sun.COM
11210500SHai-May.Chao@Sun.COM ccm_ctx->ccm_keysched = key_sched;
11310500SHai-May.Chao@Sun.COM ccm_ctx->ccm_keysched_len = size;
11410500SHai-May.Chao@Sun.COM
11510500SHai-May.Chao@Sun.COM if (ccm_init_ctx(ccm_ctx, (char *)param, KM_SLEEP,
11610500SHai-May.Chao@Sun.COM is_encrypt_init, AES_BLOCK_LEN, aes_encrypt_block,
11710500SHai-May.Chao@Sun.COM aes_xor_block) != CRYPTO_SUCCESS) {
11810500SHai-May.Chao@Sun.COM kmem_free(ccm_ctx, sizeof (ccm_ctx_t));
11910500SHai-May.Chao@Sun.COM return (NULL);
12010500SHai-May.Chao@Sun.COM }
12110500SHai-May.Chao@Sun.COM ccm_ctx->ccm_flags |= CCM_MODE;
12210500SHai-May.Chao@Sun.COM
12310500SHai-May.Chao@Sun.COM return (ccm_ctx);
12410500SHai-May.Chao@Sun.COM }
12510500SHai-May.Chao@Sun.COM
12610500SHai-May.Chao@Sun.COM /*
12710500SHai-May.Chao@Sun.COM * Allocate and initialize a context for AES CCM mode of operation.
12810500SHai-May.Chao@Sun.COM */
12910500SHai-May.Chao@Sun.COM void *
aes_gcm_ctx_init(void * key_sched,size_t size,uint8_t * param)13010500SHai-May.Chao@Sun.COM aes_gcm_ctx_init(void *key_sched, size_t size, uint8_t *param)
13110500SHai-May.Chao@Sun.COM {
13210500SHai-May.Chao@Sun.COM
13310500SHai-May.Chao@Sun.COM gcm_ctx_t *gcm_ctx;
13410500SHai-May.Chao@Sun.COM
13510500SHai-May.Chao@Sun.COM if ((gcm_ctx = kmem_zalloc(sizeof (gcm_ctx_t), KM_SLEEP)) == NULL)
13610500SHai-May.Chao@Sun.COM return (NULL);
13710500SHai-May.Chao@Sun.COM
13810500SHai-May.Chao@Sun.COM gcm_ctx->gcm_keysched = key_sched;
13910500SHai-May.Chao@Sun.COM gcm_ctx->gcm_keysched_len = size;
14010500SHai-May.Chao@Sun.COM
14110500SHai-May.Chao@Sun.COM if (gcm_init_ctx(gcm_ctx, (char *)param, AES_BLOCK_LEN,
14210500SHai-May.Chao@Sun.COM aes_encrypt_block, aes_copy_block,
14310500SHai-May.Chao@Sun.COM aes_xor_block) != CRYPTO_SUCCESS) {
14410500SHai-May.Chao@Sun.COM kmem_free(gcm_ctx, sizeof (gcm_ctx_t));
14510500SHai-May.Chao@Sun.COM return (NULL);
14610500SHai-May.Chao@Sun.COM }
14710500SHai-May.Chao@Sun.COM gcm_ctx->gcm_flags |= GCM_MODE;
14810500SHai-May.Chao@Sun.COM
14910500SHai-May.Chao@Sun.COM return (gcm_ctx);
15010500SHai-May.Chao@Sun.COM }
15110500SHai-May.Chao@Sun.COM
15210500SHai-May.Chao@Sun.COM void *
aes_gmac_ctx_init(void * key_sched,size_t size,uint8_t * param)15310500SHai-May.Chao@Sun.COM aes_gmac_ctx_init(void *key_sched, size_t size, uint8_t *param)
15410500SHai-May.Chao@Sun.COM {
15510500SHai-May.Chao@Sun.COM
15610500SHai-May.Chao@Sun.COM gcm_ctx_t *gcm_ctx;
15710500SHai-May.Chao@Sun.COM
15810500SHai-May.Chao@Sun.COM if ((gcm_ctx = kmem_zalloc(sizeof (gcm_ctx_t), KM_SLEEP)) == NULL)
15910500SHai-May.Chao@Sun.COM return (NULL);
16010500SHai-May.Chao@Sun.COM
16110500SHai-May.Chao@Sun.COM gcm_ctx->gcm_keysched = key_sched;
16210500SHai-May.Chao@Sun.COM gcm_ctx->gcm_keysched_len = size;
16310500SHai-May.Chao@Sun.COM
16410500SHai-May.Chao@Sun.COM if (gmac_init_ctx(gcm_ctx, (char *)param, AES_BLOCK_LEN,
16510500SHai-May.Chao@Sun.COM aes_encrypt_block, aes_copy_block,
16610500SHai-May.Chao@Sun.COM aes_xor_block) != CRYPTO_SUCCESS) {
16710500SHai-May.Chao@Sun.COM kmem_free(gcm_ctx, sizeof (gcm_ctx_t));
16810500SHai-May.Chao@Sun.COM return (NULL);
16910500SHai-May.Chao@Sun.COM }
17010500SHai-May.Chao@Sun.COM gcm_ctx->gcm_flags |= GMAC_MODE;
17110500SHai-May.Chao@Sun.COM
17210500SHai-May.Chao@Sun.COM return (gcm_ctx);
17310500SHai-May.Chao@Sun.COM }
17410500SHai-May.Chao@Sun.COM #endif
17510500SHai-May.Chao@Sun.COM
17610500SHai-May.Chao@Sun.COM
17710500SHai-May.Chao@Sun.COM /*
17810500SHai-May.Chao@Sun.COM * Allocate context for the active encryption or decryption operation, and
17910500SHai-May.Chao@Sun.COM * generate AES key schedule to speed up the operation.
18010500SHai-May.Chao@Sun.COM */
18110500SHai-May.Chao@Sun.COM soft_aes_ctx_t *
18210500SHai-May.Chao@Sun.COM #ifdef _KERNEL
fips_aes_build_context(uint8_t * key,int key_len,uint8_t * iv,aes_mech_type_t mechanism,boolean_t is_encrypt_init)18310500SHai-May.Chao@Sun.COM fips_aes_build_context(uint8_t *key, int key_len, uint8_t *iv,
18410500SHai-May.Chao@Sun.COM aes_mech_type_t mechanism, boolean_t is_encrypt_init)
18510500SHai-May.Chao@Sun.COM #else
18610500SHai-May.Chao@Sun.COM fips_aes_build_context(uint8_t *key, int key_len, uint8_t *iv,
18710500SHai-May.Chao@Sun.COM CK_MECHANISM_TYPE mechanism)
18810500SHai-May.Chao@Sun.COM #endif
18910500SHai-May.Chao@Sun.COM {
19010500SHai-May.Chao@Sun.COM size_t size;
19110500SHai-May.Chao@Sun.COM soft_aes_ctx_t *soft_aes_ctx;
19210500SHai-May.Chao@Sun.COM CK_AES_CTR_PARAMS pp;
19310500SHai-May.Chao@Sun.COM
19410500SHai-May.Chao@Sun.COM #ifdef _KERNEL
19510500SHai-May.Chao@Sun.COM if ((soft_aes_ctx = kmem_zalloc(sizeof (soft_aes_ctx_t),
19610500SHai-May.Chao@Sun.COM KM_SLEEP)) == NULL)
19710500SHai-May.Chao@Sun.COM #else
19810500SHai-May.Chao@Sun.COM if ((soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t)))
19910500SHai-May.Chao@Sun.COM == NULL)
20010500SHai-May.Chao@Sun.COM #endif
20110500SHai-May.Chao@Sun.COM return (NULL);
20210500SHai-May.Chao@Sun.COM
20310500SHai-May.Chao@Sun.COM
20410500SHai-May.Chao@Sun.COM soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0);
20510500SHai-May.Chao@Sun.COM
20610500SHai-May.Chao@Sun.COM if (soft_aes_ctx->key_sched == NULL) {
20710500SHai-May.Chao@Sun.COM #ifdef _KERNEL
20810500SHai-May.Chao@Sun.COM kmem_free(soft_aes_ctx, sizeof (soft_aes_ctx_t));
20910500SHai-May.Chao@Sun.COM #else
21010500SHai-May.Chao@Sun.COM free(soft_aes_ctx);
21110500SHai-May.Chao@Sun.COM #endif
21210500SHai-May.Chao@Sun.COM return (NULL);
21310500SHai-May.Chao@Sun.COM }
21410500SHai-May.Chao@Sun.COM
21510500SHai-May.Chao@Sun.COM soft_aes_ctx->keysched_len = size;
21610500SHai-May.Chao@Sun.COM
21710500SHai-May.Chao@Sun.COM #ifdef __sparcv9
21810500SHai-May.Chao@Sun.COM aes_init_keysched(key, (uint_t)(key_len * 8),
21910500SHai-May.Chao@Sun.COM soft_aes_ctx->key_sched);
22010500SHai-May.Chao@Sun.COM #else /* !__sparcv9 */
22110500SHai-May.Chao@Sun.COM aes_init_keysched(key, (key_len * 8),
22210500SHai-May.Chao@Sun.COM soft_aes_ctx->key_sched);
22310500SHai-May.Chao@Sun.COM #endif /* __sparcv9 */
22410500SHai-May.Chao@Sun.COM
22510500SHai-May.Chao@Sun.COM switch (mechanism) {
22610500SHai-May.Chao@Sun.COM
22710500SHai-May.Chao@Sun.COM case CKM_AES_CBC:
22810500SHai-May.Chao@Sun.COM
22910500SHai-May.Chao@Sun.COM /* Save Initialization Vector (IV) in the context. */
23010500SHai-May.Chao@Sun.COM (void) memcpy(soft_aes_ctx->ivec, iv, AES_BLOCK_LEN);
23110500SHai-May.Chao@Sun.COM /* Allocate a context for AES cipher-block chaining. */
23210500SHai-May.Chao@Sun.COM soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
23310500SHai-May.Chao@Sun.COM soft_aes_ctx->key_sched,
23410500SHai-May.Chao@Sun.COM soft_aes_ctx->keysched_len,
23510500SHai-May.Chao@Sun.COM soft_aes_ctx->ivec);
23610500SHai-May.Chao@Sun.COM break;
23710500SHai-May.Chao@Sun.COM
23810500SHai-May.Chao@Sun.COM case CKM_AES_CTR:
23910500SHai-May.Chao@Sun.COM
24010500SHai-May.Chao@Sun.COM pp.ulCounterBits = 16;
24110500SHai-May.Chao@Sun.COM (void) memcpy(pp.cb, iv, AES_BLOCK_LEN);
24210500SHai-May.Chao@Sun.COM soft_aes_ctx->aes_cbc = aes_ctr_ctx_init(
24310500SHai-May.Chao@Sun.COM soft_aes_ctx->key_sched,
24410500SHai-May.Chao@Sun.COM soft_aes_ctx->keysched_len,
24510500SHai-May.Chao@Sun.COM (uint8_t *)&pp);
24610500SHai-May.Chao@Sun.COM break;
24710500SHai-May.Chao@Sun.COM
24810500SHai-May.Chao@Sun.COM #ifdef _KERNEL
24910500SHai-May.Chao@Sun.COM case AES_CCM_MECH_INFO_TYPE:
25010500SHai-May.Chao@Sun.COM soft_aes_ctx->aes_cbc = aes_ccm_ctx_init(
25110500SHai-May.Chao@Sun.COM soft_aes_ctx->key_sched,
25210500SHai-May.Chao@Sun.COM soft_aes_ctx->keysched_len, iv,
25310500SHai-May.Chao@Sun.COM is_encrypt_init);
25410500SHai-May.Chao@Sun.COM break;
25510500SHai-May.Chao@Sun.COM
25610500SHai-May.Chao@Sun.COM case AES_GCM_MECH_INFO_TYPE:
25710500SHai-May.Chao@Sun.COM soft_aes_ctx->aes_cbc = aes_gcm_ctx_init(
25810500SHai-May.Chao@Sun.COM soft_aes_ctx->key_sched,
25910500SHai-May.Chao@Sun.COM soft_aes_ctx->keysched_len, iv);
26010500SHai-May.Chao@Sun.COM break;
26110500SHai-May.Chao@Sun.COM
26210500SHai-May.Chao@Sun.COM case AES_GMAC_MECH_INFO_TYPE:
26310500SHai-May.Chao@Sun.COM soft_aes_ctx->aes_cbc = aes_gmac_ctx_init(
26410500SHai-May.Chao@Sun.COM soft_aes_ctx->key_sched,
26510500SHai-May.Chao@Sun.COM soft_aes_ctx->keysched_len, iv);
26610500SHai-May.Chao@Sun.COM break;
26710500SHai-May.Chao@Sun.COM #endif
26810500SHai-May.Chao@Sun.COM default:
26910500SHai-May.Chao@Sun.COM return (soft_aes_ctx);
27010500SHai-May.Chao@Sun.COM }
27110500SHai-May.Chao@Sun.COM
27210500SHai-May.Chao@Sun.COM if (soft_aes_ctx->aes_cbc == NULL) {
27310500SHai-May.Chao@Sun.COM bzero(soft_aes_ctx->key_sched,
27410500SHai-May.Chao@Sun.COM soft_aes_ctx->keysched_len);
27510500SHai-May.Chao@Sun.COM #ifdef _KERNEL
27610500SHai-May.Chao@Sun.COM kmem_free(soft_aes_ctx->key_sched, size);
27710500SHai-May.Chao@Sun.COM #else
27810500SHai-May.Chao@Sun.COM free(soft_aes_ctx->key_sched);
27910500SHai-May.Chao@Sun.COM #endif
28010500SHai-May.Chao@Sun.COM return (NULL);
28110500SHai-May.Chao@Sun.COM }
28210500SHai-May.Chao@Sun.COM
28310500SHai-May.Chao@Sun.COM return (soft_aes_ctx);
28410500SHai-May.Chao@Sun.COM }
28510500SHai-May.Chao@Sun.COM
28610500SHai-May.Chao@Sun.COM #ifdef _KERNEL
28710500SHai-May.Chao@Sun.COM void
fips_aes_free_context(soft_aes_ctx_t * soft_aes_ctx)28810500SHai-May.Chao@Sun.COM fips_aes_free_context(soft_aes_ctx_t *soft_aes_ctx)
28910500SHai-May.Chao@Sun.COM {
29010500SHai-May.Chao@Sun.COM
29110500SHai-May.Chao@Sun.COM common_ctx_t *aes_ctx;
29210500SHai-May.Chao@Sun.COM
29310500SHai-May.Chao@Sun.COM aes_ctx = (common_ctx_t *)soft_aes_ctx->aes_cbc;
29410500SHai-May.Chao@Sun.COM
29510500SHai-May.Chao@Sun.COM if (aes_ctx != NULL) {
29610500SHai-May.Chao@Sun.COM bzero(aes_ctx->cc_keysched, aes_ctx->cc_keysched_len);
29710500SHai-May.Chao@Sun.COM kmem_free(aes_ctx->cc_keysched,
29810500SHai-May.Chao@Sun.COM aes_ctx->cc_keysched_len);
29910500SHai-May.Chao@Sun.COM crypto_free_mode_ctx(aes_ctx);
30010500SHai-May.Chao@Sun.COM } else {
30110500SHai-May.Chao@Sun.COM /* ECB MODE */
30210500SHai-May.Chao@Sun.COM bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
30310500SHai-May.Chao@Sun.COM kmem_free(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
30410500SHai-May.Chao@Sun.COM }
30510500SHai-May.Chao@Sun.COM
30610500SHai-May.Chao@Sun.COM kmem_free(soft_aes_ctx, sizeof (soft_aes_ctx_t));
30710500SHai-May.Chao@Sun.COM
30810500SHai-May.Chao@Sun.COM }
30910500SHai-May.Chao@Sun.COM
31010500SHai-May.Chao@Sun.COM #else
31110500SHai-May.Chao@Sun.COM void
fips_aes_free_context(soft_aes_ctx_t * soft_aes_ctx)31210500SHai-May.Chao@Sun.COM fips_aes_free_context(soft_aes_ctx_t *soft_aes_ctx)
31310500SHai-May.Chao@Sun.COM {
31410500SHai-May.Chao@Sun.COM
31510500SHai-May.Chao@Sun.COM common_ctx_t *aes_ctx;
31610500SHai-May.Chao@Sun.COM
31710500SHai-May.Chao@Sun.COM aes_ctx = (common_ctx_t *)soft_aes_ctx->aes_cbc;
31810500SHai-May.Chao@Sun.COM
31910500SHai-May.Chao@Sun.COM if (aes_ctx != NULL) {
32010500SHai-May.Chao@Sun.COM bzero(aes_ctx->cc_keysched, aes_ctx->cc_keysched_len);
32110500SHai-May.Chao@Sun.COM free(aes_ctx->cc_keysched);
32210500SHai-May.Chao@Sun.COM free(soft_aes_ctx->aes_cbc);
32310500SHai-May.Chao@Sun.COM } else {
32410500SHai-May.Chao@Sun.COM /* ECB MODE */
32510500SHai-May.Chao@Sun.COM bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
32610500SHai-May.Chao@Sun.COM free(soft_aes_ctx->key_sched);
32710500SHai-May.Chao@Sun.COM }
32810500SHai-May.Chao@Sun.COM
32910500SHai-May.Chao@Sun.COM free(soft_aes_ctx);
33010500SHai-May.Chao@Sun.COM
33110500SHai-May.Chao@Sun.COM }
33210500SHai-May.Chao@Sun.COM #endif
33310500SHai-May.Chao@Sun.COM
33410500SHai-May.Chao@Sun.COM /*
33510500SHai-May.Chao@Sun.COM * fips_aes_encrypt()
33610500SHai-May.Chao@Sun.COM *
33710500SHai-May.Chao@Sun.COM * Arguments:
33810500SHai-May.Chao@Sun.COM * soft_aes_ctx: pointer to AES context
33910500SHai-May.Chao@Sun.COM * in_buf: pointer to the input data to be encrypted
34010500SHai-May.Chao@Sun.COM * ulDataLen: length of the input data
34110500SHai-May.Chao@Sun.COM * out_buf: pointer to the output data after encryption
34210500SHai-May.Chao@Sun.COM * pulEncryptedLen: pointer to the length of the output data
34310500SHai-May.Chao@Sun.COM * mechanism: CKM_AES_ECB or CKM_AES_CBC
34410500SHai-May.Chao@Sun.COM *
34510500SHai-May.Chao@Sun.COM * Description:
34610500SHai-May.Chao@Sun.COM * This function calls the corresponding low-level encrypt
34710500SHai-May.Chao@Sun.COM * routine based on the mechanism.
34810500SHai-May.Chao@Sun.COM *
34910500SHai-May.Chao@Sun.COM */
35010500SHai-May.Chao@Sun.COM #ifdef _KERNEL
35110500SHai-May.Chao@Sun.COM int
fips_aes_encrypt(soft_aes_ctx_t * soft_aes_ctx,uchar_t * in_buf,ulong_t ulDataLen,uchar_t * out_buf,ulong_t * pulEncryptedLen,aes_mech_type_t mechanism)35210500SHai-May.Chao@Sun.COM fips_aes_encrypt(soft_aes_ctx_t *soft_aes_ctx, uchar_t *in_buf,
35310500SHai-May.Chao@Sun.COM ulong_t ulDataLen, uchar_t *out_buf,
35410500SHai-May.Chao@Sun.COM ulong_t *pulEncryptedLen, aes_mech_type_t mechanism)
35510500SHai-May.Chao@Sun.COM #else
35610500SHai-May.Chao@Sun.COM CK_RV
35710500SHai-May.Chao@Sun.COM fips_aes_encrypt(soft_aes_ctx_t *soft_aes_ctx, CK_BYTE_PTR in_buf,
35810500SHai-May.Chao@Sun.COM CK_ULONG ulDataLen, CK_BYTE_PTR out_buf,
35910500SHai-May.Chao@Sun.COM CK_ULONG_PTR pulEncryptedLen, CK_MECHANISM_TYPE mechanism)
36010500SHai-May.Chao@Sun.COM #endif
36110500SHai-May.Chao@Sun.COM {
36210500SHai-May.Chao@Sun.COM
36310500SHai-May.Chao@Sun.COM int rc = 0;
36410500SHai-May.Chao@Sun.COM CK_RV rv = CKR_OK;
36510500SHai-May.Chao@Sun.COM ulong_t out_len;
36610500SHai-May.Chao@Sun.COM
36710500SHai-May.Chao@Sun.COM /*
36810500SHai-May.Chao@Sun.COM * AES only takes input length that is a multiple of 16-byte
36910500SHai-May.Chao@Sun.COM */
37010500SHai-May.Chao@Sun.COM if ((ulDataLen % AES_BLOCK_LEN) != 0)
37110500SHai-May.Chao@Sun.COM return (CKR_DATA_LEN_RANGE);
37210500SHai-May.Chao@Sun.COM
37310500SHai-May.Chao@Sun.COM /*
37410500SHai-May.Chao@Sun.COM * For non-padding mode, the output length will
37510500SHai-May.Chao@Sun.COM * be same as the input length.
37610500SHai-May.Chao@Sun.COM */
37710500SHai-May.Chao@Sun.COM out_len = ulDataLen;
37810500SHai-May.Chao@Sun.COM
37910500SHai-May.Chao@Sun.COM /*
38010500SHai-May.Chao@Sun.COM * Begin Encryption now.
38110500SHai-May.Chao@Sun.COM */
38210500SHai-May.Chao@Sun.COM switch (mechanism) {
38310500SHai-May.Chao@Sun.COM
38410500SHai-May.Chao@Sun.COM case CKM_AES_ECB:
38510500SHai-May.Chao@Sun.COM {
38610500SHai-May.Chao@Sun.COM
38710500SHai-May.Chao@Sun.COM ulong_t i;
38810500SHai-May.Chao@Sun.COM uint8_t *tmp_inbuf;
38910500SHai-May.Chao@Sun.COM uint8_t *tmp_outbuf;
39010500SHai-May.Chao@Sun.COM
39110500SHai-May.Chao@Sun.COM for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
39210500SHai-May.Chao@Sun.COM tmp_inbuf = &in_buf[i];
39310500SHai-May.Chao@Sun.COM tmp_outbuf = &out_buf[i];
39410500SHai-May.Chao@Sun.COM /* Crunch one block of data for AES. */
39510500SHai-May.Chao@Sun.COM (void) aes_encrypt_block(soft_aes_ctx->key_sched,
39610500SHai-May.Chao@Sun.COM tmp_inbuf, tmp_outbuf);
39710500SHai-May.Chao@Sun.COM }
39810500SHai-May.Chao@Sun.COM
39910500SHai-May.Chao@Sun.COM *pulEncryptedLen = out_len;
40010500SHai-May.Chao@Sun.COM
40110500SHai-May.Chao@Sun.COM break;
40210500SHai-May.Chao@Sun.COM }
40310500SHai-May.Chao@Sun.COM
40410500SHai-May.Chao@Sun.COM case CKM_AES_CBC:
40510500SHai-May.Chao@Sun.COM {
40610500SHai-May.Chao@Sun.COM crypto_data_t out;
40710500SHai-May.Chao@Sun.COM
40810500SHai-May.Chao@Sun.COM out.cd_format = CRYPTO_DATA_RAW;
40910500SHai-May.Chao@Sun.COM out.cd_offset = 0;
41010500SHai-May.Chao@Sun.COM out.cd_length = out_len;
41110500SHai-May.Chao@Sun.COM out.cd_raw.iov_base = (char *)out_buf;
41210500SHai-May.Chao@Sun.COM out.cd_raw.iov_len = out_len;
41310500SHai-May.Chao@Sun.COM
41410500SHai-May.Chao@Sun.COM /* Encrypt multiple blocks of data. */
41510500SHai-May.Chao@Sun.COM rc = aes_encrypt_contiguous_blocks(
41610500SHai-May.Chao@Sun.COM (aes_ctx_t *)soft_aes_ctx->aes_cbc,
41710500SHai-May.Chao@Sun.COM (char *)in_buf, out_len, &out);
41810500SHai-May.Chao@Sun.COM
41910500SHai-May.Chao@Sun.COM if (rc != 0)
42010500SHai-May.Chao@Sun.COM goto encrypt_failed;
42110500SHai-May.Chao@Sun.COM
42210500SHai-May.Chao@Sun.COM if (rc == 0) {
42310500SHai-May.Chao@Sun.COM *pulEncryptedLen = out_len;
42410500SHai-May.Chao@Sun.COM break;
42510500SHai-May.Chao@Sun.COM }
42610500SHai-May.Chao@Sun.COM encrypt_failed:
42710500SHai-May.Chao@Sun.COM *pulEncryptedLen = 0;
42810500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
42910500SHai-May.Chao@Sun.COM }
43010500SHai-May.Chao@Sun.COM
43110500SHai-May.Chao@Sun.COM case CKM_AES_CTR:
43210500SHai-May.Chao@Sun.COM {
43310500SHai-May.Chao@Sun.COM crypto_data_t out;
43410500SHai-May.Chao@Sun.COM
43510500SHai-May.Chao@Sun.COM out.cd_format = CRYPTO_DATA_RAW;
43610500SHai-May.Chao@Sun.COM out.cd_offset = 0;
43710500SHai-May.Chao@Sun.COM out.cd_length = out_len;
43810500SHai-May.Chao@Sun.COM out.cd_raw.iov_base = (char *)out_buf;
43910500SHai-May.Chao@Sun.COM out.cd_raw.iov_len = out_len;
44010500SHai-May.Chao@Sun.COM
44110500SHai-May.Chao@Sun.COM rc = aes_encrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
44210500SHai-May.Chao@Sun.COM (char *)in_buf, out_len, &out);
44310500SHai-May.Chao@Sun.COM
44410500SHai-May.Chao@Sun.COM if (rc != 0) {
44510500SHai-May.Chao@Sun.COM *pulEncryptedLen = 0;
44610500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
44710500SHai-May.Chao@Sun.COM }
44810500SHai-May.Chao@Sun.COM /*
44910500SHai-May.Chao@Sun.COM * Since AES counter mode is a stream cipher, we call
45010500SHai-May.Chao@Sun.COM * aes_counter_final() to pick up any remaining bytes.
45110500SHai-May.Chao@Sun.COM * It is an internal function that does not destroy
45210500SHai-May.Chao@Sun.COM * the context like *normal* final routines.
45310500SHai-May.Chao@Sun.COM */
45410500SHai-May.Chao@Sun.COM if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len
45510500SHai-May.Chao@Sun.COM > 0) {
45610500SHai-May.Chao@Sun.COM rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
45710500SHai-May.Chao@Sun.COM aes_encrypt_block);
45810500SHai-May.Chao@Sun.COM if (rc != 0) {
45910500SHai-May.Chao@Sun.COM *pulEncryptedLen = 0;
46010500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
46110500SHai-May.Chao@Sun.COM }
46210500SHai-May.Chao@Sun.COM }
46310500SHai-May.Chao@Sun.COM
46410500SHai-May.Chao@Sun.COM *pulEncryptedLen = out_len;
46510500SHai-May.Chao@Sun.COM break;
46610500SHai-May.Chao@Sun.COM }
46710500SHai-May.Chao@Sun.COM
46810500SHai-May.Chao@Sun.COM #ifdef _KERNEL
46910500SHai-May.Chao@Sun.COM case AES_CCM_MECH_INFO_TYPE:
47010500SHai-May.Chao@Sun.COM {
47110500SHai-May.Chao@Sun.COM crypto_data_t out;
47210500SHai-May.Chao@Sun.COM size_t saved_length, length_needed;
47310500SHai-May.Chao@Sun.COM aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
47410500SHai-May.Chao@Sun.COM ccm_ctx_t *ccm_ctx = soft_aes_ctx->aes_cbc;
47510500SHai-May.Chao@Sun.COM
47610500SHai-May.Chao@Sun.COM length_needed = ulDataLen + aes_ctx->ac_mac_len;
47710500SHai-May.Chao@Sun.COM
47810500SHai-May.Chao@Sun.COM out.cd_format = CRYPTO_DATA_RAW;
47910500SHai-May.Chao@Sun.COM out.cd_offset = 0;
48010500SHai-May.Chao@Sun.COM out.cd_length = length_needed;
48110500SHai-May.Chao@Sun.COM out.cd_raw.iov_base = (char *)out_buf;
48210500SHai-May.Chao@Sun.COM out.cd_raw.iov_len = length_needed;
48310500SHai-May.Chao@Sun.COM
48410500SHai-May.Chao@Sun.COM saved_length = out.cd_length;
48510500SHai-May.Chao@Sun.COM
48610500SHai-May.Chao@Sun.COM rc = aes_encrypt_contiguous_blocks(aes_ctx,
48710500SHai-May.Chao@Sun.COM (char *)in_buf, ulDataLen, &out);
48810500SHai-May.Chao@Sun.COM
48910500SHai-May.Chao@Sun.COM if (rc != 0) {
49010500SHai-May.Chao@Sun.COM *pulEncryptedLen = 0;
49110500SHai-May.Chao@Sun.COM return (rc);
49210500SHai-May.Chao@Sun.COM }
49310500SHai-May.Chao@Sun.COM
49410500SHai-May.Chao@Sun.COM /*
49510500SHai-May.Chao@Sun.COM * ccm_encrypt_final() will compute the MAC and append
49610500SHai-May.Chao@Sun.COM * it to existing ciphertext. So, need to adjust the left over
49710500SHai-May.Chao@Sun.COM * length value accordingly
49810500SHai-May.Chao@Sun.COM */
49910500SHai-May.Chao@Sun.COM
50010500SHai-May.Chao@Sun.COM /* order of following 2 lines MUST not be reversed */
50110500SHai-May.Chao@Sun.COM out.cd_offset = ccm_ctx->ccm_processed_data_len;
50210500SHai-May.Chao@Sun.COM out.cd_length = saved_length - ccm_ctx->ccm_processed_data_len;
50310500SHai-May.Chao@Sun.COM
50410500SHai-May.Chao@Sun.COM rc = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, &out,
50510500SHai-May.Chao@Sun.COM AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
50610500SHai-May.Chao@Sun.COM
50710500SHai-May.Chao@Sun.COM if (rc != CRYPTO_SUCCESS) {
50810500SHai-May.Chao@Sun.COM *pulEncryptedLen = 0;
50910500SHai-May.Chao@Sun.COM return (rc);
51010500SHai-May.Chao@Sun.COM }
51110500SHai-May.Chao@Sun.COM
51210500SHai-May.Chao@Sun.COM *pulEncryptedLen = length_needed;
51310500SHai-May.Chao@Sun.COM break;
51410500SHai-May.Chao@Sun.COM }
51510500SHai-May.Chao@Sun.COM
51610500SHai-May.Chao@Sun.COM case AES_GCM_MECH_INFO_TYPE:
51710500SHai-May.Chao@Sun.COM {
51810500SHai-May.Chao@Sun.COM crypto_data_t out;
51910500SHai-May.Chao@Sun.COM size_t saved_length, length_needed;
52010500SHai-May.Chao@Sun.COM aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
52110500SHai-May.Chao@Sun.COM gcm_ctx_t *gcm_ctx = soft_aes_ctx->aes_cbc;
52210500SHai-May.Chao@Sun.COM
52310500SHai-May.Chao@Sun.COM /*
52410500SHai-May.Chao@Sun.COM * Output:
52510500SHai-May.Chao@Sun.COM * A ciphertext, denoted C, whose bit length is the same as
52610500SHai-May.Chao@Sun.COM * that of the plaintext.
52710500SHai-May.Chao@Sun.COM * An authentication tag, or tag, for short, denoted T.
52810500SHai-May.Chao@Sun.COM */
52910500SHai-May.Chao@Sun.COM
53010500SHai-May.Chao@Sun.COM length_needed = ulDataLen + aes_ctx->ac_tag_len;
53110500SHai-May.Chao@Sun.COM
53210500SHai-May.Chao@Sun.COM out.cd_format = CRYPTO_DATA_RAW;
53310500SHai-May.Chao@Sun.COM out.cd_offset = 0;
53410500SHai-May.Chao@Sun.COM out.cd_length = length_needed;
53510500SHai-May.Chao@Sun.COM out.cd_raw.iov_base = (char *)out_buf;
53610500SHai-May.Chao@Sun.COM out.cd_raw.iov_len = length_needed;
53710500SHai-May.Chao@Sun.COM
53810500SHai-May.Chao@Sun.COM saved_length = out.cd_length;
53910500SHai-May.Chao@Sun.COM
54010500SHai-May.Chao@Sun.COM rc = aes_encrypt_contiguous_blocks(aes_ctx,
54110500SHai-May.Chao@Sun.COM (char *)in_buf, ulDataLen, &out);
54210500SHai-May.Chao@Sun.COM
54310500SHai-May.Chao@Sun.COM if (rc != 0) {
54410500SHai-May.Chao@Sun.COM *pulEncryptedLen = 0;
54510500SHai-May.Chao@Sun.COM return (rc);
54610500SHai-May.Chao@Sun.COM }
54710500SHai-May.Chao@Sun.COM
54810500SHai-May.Chao@Sun.COM /*
54910500SHai-May.Chao@Sun.COM * ccm_encrypt_final() will compute the MAC and append
55010500SHai-May.Chao@Sun.COM * it to existing ciphertext. So, need to adjust the left over
55110500SHai-May.Chao@Sun.COM * length value accordingly
55210500SHai-May.Chao@Sun.COM */
55310500SHai-May.Chao@Sun.COM
55410500SHai-May.Chao@Sun.COM /* order of following 2 lines MUST not be reversed */
55510500SHai-May.Chao@Sun.COM out.cd_offset = gcm_ctx->gcm_processed_data_len;
55610500SHai-May.Chao@Sun.COM out.cd_length = saved_length - gcm_ctx->gcm_processed_data_len;
55710500SHai-May.Chao@Sun.COM
55810500SHai-May.Chao@Sun.COM rc = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, &out,
55910500SHai-May.Chao@Sun.COM AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
56010500SHai-May.Chao@Sun.COM aes_xor_block);
56110500SHai-May.Chao@Sun.COM
56210500SHai-May.Chao@Sun.COM if (rc != CRYPTO_SUCCESS) {
56310500SHai-May.Chao@Sun.COM *pulEncryptedLen = 0;
56410500SHai-May.Chao@Sun.COM return (rc);
56510500SHai-May.Chao@Sun.COM }
56610500SHai-May.Chao@Sun.COM
56710500SHai-May.Chao@Sun.COM *pulEncryptedLen = length_needed;
56810500SHai-May.Chao@Sun.COM break;
56910500SHai-May.Chao@Sun.COM }
57010500SHai-May.Chao@Sun.COM
57110500SHai-May.Chao@Sun.COM case AES_GMAC_MECH_INFO_TYPE:
57210500SHai-May.Chao@Sun.COM {
57310500SHai-May.Chao@Sun.COM crypto_data_t out;
57410500SHai-May.Chao@Sun.COM size_t length_needed;
57510500SHai-May.Chao@Sun.COM aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
57610500SHai-May.Chao@Sun.COM
57710500SHai-May.Chao@Sun.COM length_needed = aes_ctx->ac_tag_len;
57810500SHai-May.Chao@Sun.COM
57910500SHai-May.Chao@Sun.COM out.cd_format = CRYPTO_DATA_RAW;
58010500SHai-May.Chao@Sun.COM out.cd_offset = 0;
58110500SHai-May.Chao@Sun.COM out.cd_length = length_needed;
58210500SHai-May.Chao@Sun.COM out.cd_raw.iov_base = (char *)out_buf;
58310500SHai-May.Chao@Sun.COM out.cd_raw.iov_len = length_needed;
58410500SHai-May.Chao@Sun.COM
58510500SHai-May.Chao@Sun.COM rc = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, &out,
58610500SHai-May.Chao@Sun.COM AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
58710500SHai-May.Chao@Sun.COM aes_xor_block);
58810500SHai-May.Chao@Sun.COM
58910500SHai-May.Chao@Sun.COM if (rc != CRYPTO_SUCCESS) {
59010500SHai-May.Chao@Sun.COM *pulEncryptedLen = 0;
59110500SHai-May.Chao@Sun.COM return (rc);
59210500SHai-May.Chao@Sun.COM }
59310500SHai-May.Chao@Sun.COM
59410500SHai-May.Chao@Sun.COM *pulEncryptedLen = length_needed;
59510500SHai-May.Chao@Sun.COM break;
59610500SHai-May.Chao@Sun.COM }
59710500SHai-May.Chao@Sun.COM #endif /* _KERNEL */
59810500SHai-May.Chao@Sun.COM } /* end switch */
59910500SHai-May.Chao@Sun.COM
60010500SHai-May.Chao@Sun.COM return (rv);
60110500SHai-May.Chao@Sun.COM }
60210500SHai-May.Chao@Sun.COM
60310500SHai-May.Chao@Sun.COM /*
60410500SHai-May.Chao@Sun.COM * fips_aes_decrypt()
60510500SHai-May.Chao@Sun.COM *
60610500SHai-May.Chao@Sun.COM * Arguments:
60710500SHai-May.Chao@Sun.COM * soft_aes_ctx: pointer to AES context
60810500SHai-May.Chao@Sun.COM * in_buf: pointer to the input data to be decrypted
60910500SHai-May.Chao@Sun.COM * ulEncryptedLen: length of the input data
61010500SHai-May.Chao@Sun.COM * out_buf: pointer to the output data
61110500SHai-May.Chao@Sun.COM * pulDataLen: pointer to the length of the output data
61210500SHai-May.Chao@Sun.COM * mechanism: CKM_AES_ECB or CKM_AES_CBC
61310500SHai-May.Chao@Sun.COM *
61410500SHai-May.Chao@Sun.COM * Description:
61510500SHai-May.Chao@Sun.COM * This function calls the corresponding low-level decrypt
61610500SHai-May.Chao@Sun.COM * function based on the mechanism.
61710500SHai-May.Chao@Sun.COM *
61810500SHai-May.Chao@Sun.COM */
61910500SHai-May.Chao@Sun.COM #ifdef _KERNEL
62010500SHai-May.Chao@Sun.COM int
fips_aes_decrypt(soft_aes_ctx_t * soft_aes_ctx,uchar_t * in_buf,ulong_t ulEncryptedLen,uchar_t * out_buf,ulong_t * pulDataLen,aes_mech_type_t mechanism)62110500SHai-May.Chao@Sun.COM fips_aes_decrypt(soft_aes_ctx_t *soft_aes_ctx, uchar_t *in_buf,
62210500SHai-May.Chao@Sun.COM ulong_t ulEncryptedLen, uchar_t *out_buf,
62310500SHai-May.Chao@Sun.COM ulong_t *pulDataLen, aes_mech_type_t mechanism)
62410500SHai-May.Chao@Sun.COM #else
62510500SHai-May.Chao@Sun.COM CK_RV
62610500SHai-May.Chao@Sun.COM fips_aes_decrypt(soft_aes_ctx_t *soft_aes_ctx, CK_BYTE_PTR in_buf,
62710500SHai-May.Chao@Sun.COM CK_ULONG ulEncryptedLen, CK_BYTE_PTR out_buf,
62810500SHai-May.Chao@Sun.COM CK_ULONG_PTR pulDataLen, CK_MECHANISM_TYPE mechanism)
62910500SHai-May.Chao@Sun.COM #endif
63010500SHai-May.Chao@Sun.COM {
63110500SHai-May.Chao@Sun.COM
63210500SHai-May.Chao@Sun.COM int rc = 0;
63310500SHai-May.Chao@Sun.COM CK_RV rv = CKR_OK;
63410500SHai-May.Chao@Sun.COM ulong_t out_len;
63510500SHai-May.Chao@Sun.COM
63610500SHai-May.Chao@Sun.COM /*
63710500SHai-May.Chao@Sun.COM * AES only takes input length that is a multiple of 16 bytes
63810500SHai-May.Chao@Sun.COM */
63910500SHai-May.Chao@Sun.COM if ((ulEncryptedLen % AES_BLOCK_LEN) != 0)
64010500SHai-May.Chao@Sun.COM return (CKR_ENCRYPTED_DATA_LEN_RANGE);
64110500SHai-May.Chao@Sun.COM
64210500SHai-May.Chao@Sun.COM /*
64310500SHai-May.Chao@Sun.COM * For non-padding mode, the output length will
64410500SHai-May.Chao@Sun.COM * be same as the input length.
64510500SHai-May.Chao@Sun.COM */
64610500SHai-May.Chao@Sun.COM out_len = ulEncryptedLen;
64710500SHai-May.Chao@Sun.COM
64810500SHai-May.Chao@Sun.COM /*
64910500SHai-May.Chao@Sun.COM * Begin Decryption.
65010500SHai-May.Chao@Sun.COM */
65110500SHai-May.Chao@Sun.COM switch (mechanism) {
65210500SHai-May.Chao@Sun.COM
65310500SHai-May.Chao@Sun.COM case CKM_AES_ECB:
65410500SHai-May.Chao@Sun.COM {
65510500SHai-May.Chao@Sun.COM
65610500SHai-May.Chao@Sun.COM ulong_t i;
65710500SHai-May.Chao@Sun.COM uint8_t *tmp_inbuf;
65810500SHai-May.Chao@Sun.COM uint8_t *tmp_outbuf;
65910500SHai-May.Chao@Sun.COM
66010500SHai-May.Chao@Sun.COM for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
66110500SHai-May.Chao@Sun.COM tmp_inbuf = &in_buf[i];
66210500SHai-May.Chao@Sun.COM tmp_outbuf = &out_buf[i];
66310500SHai-May.Chao@Sun.COM /* Crunch one block of data for AES. */
66410500SHai-May.Chao@Sun.COM (void) aes_decrypt_block(soft_aes_ctx->key_sched,
66510500SHai-May.Chao@Sun.COM tmp_inbuf, tmp_outbuf);
66610500SHai-May.Chao@Sun.COM }
66710500SHai-May.Chao@Sun.COM
66810500SHai-May.Chao@Sun.COM *pulDataLen = out_len;
66910500SHai-May.Chao@Sun.COM
67010500SHai-May.Chao@Sun.COM break;
67110500SHai-May.Chao@Sun.COM }
67210500SHai-May.Chao@Sun.COM
67310500SHai-May.Chao@Sun.COM case CKM_AES_CBC:
67410500SHai-May.Chao@Sun.COM {
67510500SHai-May.Chao@Sun.COM crypto_data_t out;
67610500SHai-May.Chao@Sun.COM
67710500SHai-May.Chao@Sun.COM out.cd_format = CRYPTO_DATA_RAW;
67810500SHai-May.Chao@Sun.COM out.cd_offset = 0;
67910500SHai-May.Chao@Sun.COM out.cd_length = out_len;
68010500SHai-May.Chao@Sun.COM out.cd_raw.iov_base = (char *)out_buf;
68110500SHai-May.Chao@Sun.COM out.cd_raw.iov_len = out_len;
68210500SHai-May.Chao@Sun.COM
68310500SHai-May.Chao@Sun.COM /* Decrypt multiple blocks of data. */
68410500SHai-May.Chao@Sun.COM rc = aes_decrypt_contiguous_blocks(
68510500SHai-May.Chao@Sun.COM (aes_ctx_t *)soft_aes_ctx->aes_cbc,
68610500SHai-May.Chao@Sun.COM (char *)in_buf, out_len, &out);
68710500SHai-May.Chao@Sun.COM
68810500SHai-May.Chao@Sun.COM if (rc != 0)
68910500SHai-May.Chao@Sun.COM goto decrypt_failed;
69010500SHai-May.Chao@Sun.COM
69110500SHai-May.Chao@Sun.COM
69210500SHai-May.Chao@Sun.COM *pulDataLen = out_len;
69310500SHai-May.Chao@Sun.COM
69410500SHai-May.Chao@Sun.COM if (rc == 0)
69510500SHai-May.Chao@Sun.COM break;
69610500SHai-May.Chao@Sun.COM decrypt_failed:
69710500SHai-May.Chao@Sun.COM *pulDataLen = 0;
69810500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
69910500SHai-May.Chao@Sun.COM }
70010500SHai-May.Chao@Sun.COM
70110500SHai-May.Chao@Sun.COM case CKM_AES_CTR:
70210500SHai-May.Chao@Sun.COM {
70310500SHai-May.Chao@Sun.COM crypto_data_t out;
70410500SHai-May.Chao@Sun.COM
70510500SHai-May.Chao@Sun.COM out.cd_format = CRYPTO_DATA_RAW;
70610500SHai-May.Chao@Sun.COM out.cd_offset = 0;
70710500SHai-May.Chao@Sun.COM out.cd_length = *pulDataLen;
70810500SHai-May.Chao@Sun.COM out.cd_raw.iov_base = (char *)out_buf;
70910500SHai-May.Chao@Sun.COM out.cd_raw.iov_len = *pulDataLen;
71010500SHai-May.Chao@Sun.COM
71110500SHai-May.Chao@Sun.COM rc = aes_decrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
71210500SHai-May.Chao@Sun.COM (char *)in_buf, out_len, &out);
71310500SHai-May.Chao@Sun.COM
71410500SHai-May.Chao@Sun.COM if (rc != 0) {
71510500SHai-May.Chao@Sun.COM *pulDataLen = 0;
71610500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
71710500SHai-May.Chao@Sun.COM }
71810500SHai-May.Chao@Sun.COM
71910500SHai-May.Chao@Sun.COM /*
72010500SHai-May.Chao@Sun.COM * Since AES counter mode is a stream cipher, we call
72110500SHai-May.Chao@Sun.COM * aes_counter_final() to pick up any remaining bytes.
72210500SHai-May.Chao@Sun.COM * It is an internal function that does not destroy
72310500SHai-May.Chao@Sun.COM * the context like *normal* final routines.
72410500SHai-May.Chao@Sun.COM */
72510500SHai-May.Chao@Sun.COM if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len
72610500SHai-May.Chao@Sun.COM > 0) {
72710500SHai-May.Chao@Sun.COM rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
72810500SHai-May.Chao@Sun.COM aes_encrypt_block);
72910500SHai-May.Chao@Sun.COM
73010500SHai-May.Chao@Sun.COM if (rc == CKR_DATA_LEN_RANGE)
73110500SHai-May.Chao@Sun.COM return (CKR_ENCRYPTED_DATA_LEN_RANGE);
73210500SHai-May.Chao@Sun.COM }
73310500SHai-May.Chao@Sun.COM
73410500SHai-May.Chao@Sun.COM *pulDataLen = out_len;
73510500SHai-May.Chao@Sun.COM break;
73610500SHai-May.Chao@Sun.COM }
73710500SHai-May.Chao@Sun.COM
73810500SHai-May.Chao@Sun.COM #ifdef _KERNEL
73910500SHai-May.Chao@Sun.COM case AES_CCM_MECH_INFO_TYPE:
74010500SHai-May.Chao@Sun.COM {
74110500SHai-May.Chao@Sun.COM crypto_data_t out;
74210500SHai-May.Chao@Sun.COM size_t length_needed;
74310500SHai-May.Chao@Sun.COM aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
74410500SHai-May.Chao@Sun.COM ccm_ctx_t *ccm_ctx = soft_aes_ctx->aes_cbc;
74510500SHai-May.Chao@Sun.COM
74610500SHai-May.Chao@Sun.COM length_needed = ulEncryptedLen + ccm_ctx->ccm_mac_len;
74710500SHai-May.Chao@Sun.COM
74810500SHai-May.Chao@Sun.COM out.cd_format = CRYPTO_DATA_RAW;
74910500SHai-May.Chao@Sun.COM out.cd_offset = 0;
75010500SHai-May.Chao@Sun.COM out.cd_length = ulEncryptedLen;
75110500SHai-May.Chao@Sun.COM out.cd_raw.iov_base = (char *)out_buf;
75210500SHai-May.Chao@Sun.COM out.cd_raw.iov_len = ulEncryptedLen;
75310500SHai-May.Chao@Sun.COM
75410500SHai-May.Chao@Sun.COM rc = aes_decrypt_contiguous_blocks(aes_ctx,
75510500SHai-May.Chao@Sun.COM (char *)in_buf, length_needed, &out);
75610500SHai-May.Chao@Sun.COM
75710500SHai-May.Chao@Sun.COM if (rc != 0) {
75810500SHai-May.Chao@Sun.COM *pulDataLen = 0;
75910500SHai-May.Chao@Sun.COM return (CRYPTO_FAILED);
76010500SHai-May.Chao@Sun.COM }
76110500SHai-May.Chao@Sun.COM
76210500SHai-May.Chao@Sun.COM /* order of following 2 lines MUST not be reversed */
76310500SHai-May.Chao@Sun.COM out.cd_offset = 0;
76410500SHai-May.Chao@Sun.COM out.cd_length = ulEncryptedLen;
76510500SHai-May.Chao@Sun.COM
76610500SHai-May.Chao@Sun.COM rc = ccm_decrypt_final((ccm_ctx_t *)aes_ctx, &out,
76710500SHai-May.Chao@Sun.COM AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
76810500SHai-May.Chao@Sun.COM aes_xor_block);
76910500SHai-May.Chao@Sun.COM
77010500SHai-May.Chao@Sun.COM if (rc != CRYPTO_SUCCESS) {
77110500SHai-May.Chao@Sun.COM *pulDataLen = 0;
77210500SHai-May.Chao@Sun.COM return (CRYPTO_FAILED);
77310500SHai-May.Chao@Sun.COM }
77410500SHai-May.Chao@Sun.COM
77510500SHai-May.Chao@Sun.COM *pulDataLen = ulEncryptedLen;
77610500SHai-May.Chao@Sun.COM
77710500SHai-May.Chao@Sun.COM break;
77810500SHai-May.Chao@Sun.COM }
77910500SHai-May.Chao@Sun.COM
78010500SHai-May.Chao@Sun.COM case AES_GCM_MECH_INFO_TYPE:
78110500SHai-May.Chao@Sun.COM {
78210500SHai-May.Chao@Sun.COM crypto_data_t out;
78310500SHai-May.Chao@Sun.COM size_t length_needed;
78410500SHai-May.Chao@Sun.COM aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
78510500SHai-May.Chao@Sun.COM
78610500SHai-May.Chao@Sun.COM length_needed = ulEncryptedLen + aes_ctx->ac_tag_len;
78710500SHai-May.Chao@Sun.COM
78810500SHai-May.Chao@Sun.COM out.cd_format = CRYPTO_DATA_RAW;
78910500SHai-May.Chao@Sun.COM out.cd_offset = 0;
79010500SHai-May.Chao@Sun.COM out.cd_length = ulEncryptedLen;
79110500SHai-May.Chao@Sun.COM out.cd_raw.iov_base = (char *)out_buf;
79210500SHai-May.Chao@Sun.COM out.cd_raw.iov_len = ulEncryptedLen;
79310500SHai-May.Chao@Sun.COM
79410500SHai-May.Chao@Sun.COM rc = aes_decrypt_contiguous_blocks(aes_ctx,
79510500SHai-May.Chao@Sun.COM (char *)in_buf, length_needed, &out);
79610500SHai-May.Chao@Sun.COM
79710500SHai-May.Chao@Sun.COM if (rc != 0) {
79810500SHai-May.Chao@Sun.COM *pulDataLen = 0;
79910500SHai-May.Chao@Sun.COM return (CRYPTO_FAILED);
80010500SHai-May.Chao@Sun.COM }
80110500SHai-May.Chao@Sun.COM
80210500SHai-May.Chao@Sun.COM /* order of following 2 lines MUST not be reversed */
80310500SHai-May.Chao@Sun.COM out.cd_offset = 0;
80410500SHai-May.Chao@Sun.COM out.cd_length = aes_ctx->ac_tag_len;
80510500SHai-May.Chao@Sun.COM
80610500SHai-May.Chao@Sun.COM rc = gcm_decrypt_final((gcm_ctx_t *)aes_ctx, &out,
80710500SHai-May.Chao@Sun.COM AES_BLOCK_LEN, aes_encrypt_block,
80810500SHai-May.Chao@Sun.COM aes_xor_block);
80910500SHai-May.Chao@Sun.COM
81010500SHai-May.Chao@Sun.COM if (rc != CRYPTO_SUCCESS) {
81110500SHai-May.Chao@Sun.COM *pulDataLen = 0;
81210500SHai-May.Chao@Sun.COM return (CRYPTO_FAILED);
81310500SHai-May.Chao@Sun.COM }
81410500SHai-May.Chao@Sun.COM
81510500SHai-May.Chao@Sun.COM *pulDataLen = ulEncryptedLen;
81610500SHai-May.Chao@Sun.COM
81710500SHai-May.Chao@Sun.COM break;
81810500SHai-May.Chao@Sun.COM }
81910500SHai-May.Chao@Sun.COM
82010500SHai-May.Chao@Sun.COM case AES_GMAC_MECH_INFO_TYPE:
82110500SHai-May.Chao@Sun.COM {
82210500SHai-May.Chao@Sun.COM crypto_data_t out;
82310500SHai-May.Chao@Sun.COM size_t length_needed;
82410500SHai-May.Chao@Sun.COM aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
82510500SHai-May.Chao@Sun.COM
82610500SHai-May.Chao@Sun.COM length_needed = aes_ctx->ac_tag_len;
82710500SHai-May.Chao@Sun.COM
82810500SHai-May.Chao@Sun.COM out.cd_format = CRYPTO_DATA_RAW;
82910500SHai-May.Chao@Sun.COM out.cd_offset = 0;
83010500SHai-May.Chao@Sun.COM out.cd_length = 0;
83110500SHai-May.Chao@Sun.COM out.cd_raw.iov_base = (char *)NULL;
83210500SHai-May.Chao@Sun.COM out.cd_raw.iov_len = 0;
83310500SHai-May.Chao@Sun.COM
83410500SHai-May.Chao@Sun.COM rc = aes_decrypt_contiguous_blocks(aes_ctx,
83510500SHai-May.Chao@Sun.COM (char *)in_buf, length_needed, &out);
83610500SHai-May.Chao@Sun.COM
83710500SHai-May.Chao@Sun.COM if (rc != 0) {
83810500SHai-May.Chao@Sun.COM *pulDataLen = 0;
83910500SHai-May.Chao@Sun.COM return (CRYPTO_FAILED);
84010500SHai-May.Chao@Sun.COM }
84110500SHai-May.Chao@Sun.COM
84210500SHai-May.Chao@Sun.COM /* order of following 2 lines MUST not be reversed */
84310500SHai-May.Chao@Sun.COM out.cd_format = CRYPTO_DATA_RAW;
84410500SHai-May.Chao@Sun.COM out.cd_offset = 0;
84510500SHai-May.Chao@Sun.COM out.cd_length = 0;
84610500SHai-May.Chao@Sun.COM out.cd_raw.iov_base = (char *)NULL;
84710500SHai-May.Chao@Sun.COM out.cd_raw.iov_len = 0;
84810500SHai-May.Chao@Sun.COM
84910500SHai-May.Chao@Sun.COM rc = gcm_decrypt_final((gcm_ctx_t *)aes_ctx, &out,
85010500SHai-May.Chao@Sun.COM AES_BLOCK_LEN, aes_encrypt_block,
85110500SHai-May.Chao@Sun.COM aes_xor_block);
85210500SHai-May.Chao@Sun.COM
85310500SHai-May.Chao@Sun.COM if (rc != CRYPTO_SUCCESS) {
85410500SHai-May.Chao@Sun.COM *pulDataLen = 0;
85510500SHai-May.Chao@Sun.COM return (CRYPTO_FAILED);
85610500SHai-May.Chao@Sun.COM }
85710500SHai-May.Chao@Sun.COM
85810500SHai-May.Chao@Sun.COM *pulDataLen = 0;
85910500SHai-May.Chao@Sun.COM
86010500SHai-May.Chao@Sun.COM break;
86110500SHai-May.Chao@Sun.COM }
86210500SHai-May.Chao@Sun.COM #endif
86310500SHai-May.Chao@Sun.COM } /* end switch */
86410500SHai-May.Chao@Sun.COM
86510500SHai-May.Chao@Sun.COM return (rv);
86610500SHai-May.Chao@Sun.COM }
86710500SHai-May.Chao@Sun.COM
86810500SHai-May.Chao@Sun.COM /* AES self-test for 128-bit, 192-bit, or 256-bit key sizes */
86910500SHai-May.Chao@Sun.COM int
fips_aes_post(int aes_key_size)87010500SHai-May.Chao@Sun.COM fips_aes_post(int aes_key_size)
87110500SHai-May.Chao@Sun.COM {
87210500SHai-May.Chao@Sun.COM uint8_t *aes_ecb_known_ciphertext =
87310500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
87410500SHai-May.Chao@Sun.COM aes_ecb128_known_ciphertext :
87510500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
87610500SHai-May.Chao@Sun.COM aes_ecb192_known_ciphertext :
87710500SHai-May.Chao@Sun.COM aes_ecb256_known_ciphertext;
87810500SHai-May.Chao@Sun.COM
87910500SHai-May.Chao@Sun.COM uint8_t *aes_cbc_known_ciphertext =
88010500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
88110500SHai-May.Chao@Sun.COM aes_cbc128_known_ciphertext :
88210500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
88310500SHai-May.Chao@Sun.COM aes_cbc192_known_ciphertext :
88410500SHai-May.Chao@Sun.COM aes_cbc256_known_ciphertext;
88510500SHai-May.Chao@Sun.COM
88610500SHai-May.Chao@Sun.COM uint8_t *aes_ctr_known_ciphertext =
88710500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
88810500SHai-May.Chao@Sun.COM aes_ctr128_known_ciphertext :
88910500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
89010500SHai-May.Chao@Sun.COM aes_ctr192_known_ciphertext :
89110500SHai-May.Chao@Sun.COM aes_ctr256_known_ciphertext;
89210500SHai-May.Chao@Sun.COM
89310500SHai-May.Chao@Sun.COM uint8_t *aes_ctr_known_key =
89410500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
89510500SHai-May.Chao@Sun.COM aes_ctr128_known_key :
89610500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
89710500SHai-May.Chao@Sun.COM aes_ctr192_known_key :
89810500SHai-May.Chao@Sun.COM aes_ctr256_known_key;
89910500SHai-May.Chao@Sun.COM
90010500SHai-May.Chao@Sun.COM #ifdef _KERNEL
90110500SHai-May.Chao@Sun.COM uint8_t *aes_ccm_known_plaintext =
90210500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
90310500SHai-May.Chao@Sun.COM aes_ccm128_known_plaintext :
90410500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
90510500SHai-May.Chao@Sun.COM aes_ccm192_known_plaintext :
90610500SHai-May.Chao@Sun.COM aes_ccm256_known_plaintext;
90710500SHai-May.Chao@Sun.COM
90810500SHai-May.Chao@Sun.COM uint8_t *aes_ccm_known_ciphertext =
90910500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
91010500SHai-May.Chao@Sun.COM aes_ccm128_known_ciphertext :
91110500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
91210500SHai-May.Chao@Sun.COM aes_ccm192_known_ciphertext :
91310500SHai-May.Chao@Sun.COM aes_ccm256_known_ciphertext;
91410500SHai-May.Chao@Sun.COM
91510500SHai-May.Chao@Sun.COM uint8_t *aes_ccm_known_key =
91610500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
91710500SHai-May.Chao@Sun.COM aes_ccm128_known_key :
91810500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
91910500SHai-May.Chao@Sun.COM aes_ccm192_known_key :
92010500SHai-May.Chao@Sun.COM aes_ccm256_known_key;
92110500SHai-May.Chao@Sun.COM
92210500SHai-May.Chao@Sun.COM uint8_t *aes_ccm_known_adata =
92310500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
92410500SHai-May.Chao@Sun.COM aes_ccm128_known_adata :
92510500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
92610500SHai-May.Chao@Sun.COM aes_ccm192_known_adata :
92710500SHai-May.Chao@Sun.COM aes_ccm256_known_adata;
92810500SHai-May.Chao@Sun.COM
92910500SHai-May.Chao@Sun.COM uint8_t *aes_ccm_known_nonce =
93010500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
93110500SHai-May.Chao@Sun.COM aes_ccm128_known_nonce :
93210500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
93310500SHai-May.Chao@Sun.COM aes_ccm192_known_nonce :
93410500SHai-May.Chao@Sun.COM aes_ccm256_known_nonce;
93510500SHai-May.Chao@Sun.COM
93610500SHai-May.Chao@Sun.COM uint8_t *aes_gcm_known_key =
93710500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
93810500SHai-May.Chao@Sun.COM aes_gcm128_known_key :
93910500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
94010500SHai-May.Chao@Sun.COM aes_gcm192_known_key :
94110500SHai-May.Chao@Sun.COM aes_gcm256_known_key;
94210500SHai-May.Chao@Sun.COM
94310500SHai-May.Chao@Sun.COM uint8_t *aes_gcm_known_iv =
94410500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
94510500SHai-May.Chao@Sun.COM aes_gcm128_known_iv :
94610500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
94710500SHai-May.Chao@Sun.COM aes_gcm192_known_iv :
94810500SHai-May.Chao@Sun.COM aes_gcm256_known_iv;
94910500SHai-May.Chao@Sun.COM
95010500SHai-May.Chao@Sun.COM uint8_t *aes_gcm_known_plaintext =
95110500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
95210500SHai-May.Chao@Sun.COM aes_gcm128_known_plaintext :
95310500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
95410500SHai-May.Chao@Sun.COM aes_gcm192_known_plaintext :
95510500SHai-May.Chao@Sun.COM aes_gcm256_known_plaintext;
95610500SHai-May.Chao@Sun.COM
95710500SHai-May.Chao@Sun.COM uint8_t *aes_gcm_known_ciphertext =
95810500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
95910500SHai-May.Chao@Sun.COM aes_gcm128_known_ciphertext :
96010500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
96110500SHai-May.Chao@Sun.COM aes_gcm192_known_ciphertext :
96210500SHai-May.Chao@Sun.COM aes_gcm256_known_ciphertext;
96310500SHai-May.Chao@Sun.COM
96410500SHai-May.Chao@Sun.COM uint8_t *aes_gcm_known_adata =
96510500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
96610500SHai-May.Chao@Sun.COM aes_gcm128_known_adata :
96710500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
96810500SHai-May.Chao@Sun.COM aes_gcm192_known_adata :
96910500SHai-May.Chao@Sun.COM aes_gcm256_known_adata;
97010500SHai-May.Chao@Sun.COM
97110500SHai-May.Chao@Sun.COM uint8_t *aes_gmac_known_key =
97210500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
97310500SHai-May.Chao@Sun.COM aes_gmac128_known_key :
97410500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
97510500SHai-May.Chao@Sun.COM aes_gmac192_known_key :
97610500SHai-May.Chao@Sun.COM aes_gmac256_known_key;
97710500SHai-May.Chao@Sun.COM
97810500SHai-May.Chao@Sun.COM uint8_t *aes_gmac_known_iv =
97910500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
98010500SHai-May.Chao@Sun.COM aes_gmac128_known_iv :
98110500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
98210500SHai-May.Chao@Sun.COM aes_gmac192_known_iv :
98310500SHai-May.Chao@Sun.COM aes_gmac256_known_iv;
98410500SHai-May.Chao@Sun.COM
98510500SHai-May.Chao@Sun.COM uint8_t *aes_gmac_known_tag =
98610500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
98710500SHai-May.Chao@Sun.COM aes_gmac128_known_tag :
98810500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
98910500SHai-May.Chao@Sun.COM aes_gmac192_known_tag :
99010500SHai-May.Chao@Sun.COM aes_gmac256_known_tag;
99110500SHai-May.Chao@Sun.COM
99210500SHai-May.Chao@Sun.COM uint8_t *aes_gmac_known_adata =
99310500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
99410500SHai-May.Chao@Sun.COM aes_gmac128_known_adata :
99510500SHai-May.Chao@Sun.COM (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
99610500SHai-May.Chao@Sun.COM aes_gmac192_known_adata :
99710500SHai-May.Chao@Sun.COM aes_gmac256_known_adata;
99810500SHai-May.Chao@Sun.COM
99910500SHai-May.Chao@Sun.COM /* AES variables. */
100010500SHai-May.Chao@Sun.COM uint8_t aes_ccm_computed_ciphertext[3*FIPS_AES_ENCRYPT_LENGTH];
100110500SHai-May.Chao@Sun.COM uint8_t aes_ccm_computed_plaintext[2*FIPS_AES_DECRYPT_LENGTH];
100210500SHai-May.Chao@Sun.COM uint8_t aes_gcm_computed_ciphertext[2*FIPS_AES_ENCRYPT_LENGTH];
100310500SHai-May.Chao@Sun.COM uint8_t aes_gcm_computed_plaintext[FIPS_AES_DECRYPT_LENGTH];
100410500SHai-May.Chao@Sun.COM uint8_t aes_gmac_computed_tag[FIPS_AES_ENCRYPT_LENGTH];
100510500SHai-May.Chao@Sun.COM CK_AES_CCM_PARAMS ccm_param;
100610500SHai-May.Chao@Sun.COM CK_AES_GCM_PARAMS gcm_param;
100710500SHai-May.Chao@Sun.COM CK_AES_GMAC_PARAMS gmac_param;
100810500SHai-May.Chao@Sun.COM #endif
100910500SHai-May.Chao@Sun.COM
101010500SHai-May.Chao@Sun.COM uint8_t aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH];
101110500SHai-May.Chao@Sun.COM uint8_t aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH];
101210500SHai-May.Chao@Sun.COM soft_aes_ctx_t *aes_context;
101310500SHai-May.Chao@Sun.COM ulong_t aes_bytes_encrypted;
101410500SHai-May.Chao@Sun.COM ulong_t aes_bytes_decrypted;
101510500SHai-May.Chao@Sun.COM int rv;
101610500SHai-May.Chao@Sun.COM
101710500SHai-May.Chao@Sun.COM /* check if aes_key_size is 128, 192, or 256 bits */
101810500SHai-May.Chao@Sun.COM if ((aes_key_size != FIPS_AES_128_KEY_SIZE) &&
101910500SHai-May.Chao@Sun.COM (aes_key_size != FIPS_AES_192_KEY_SIZE) &&
102010500SHai-May.Chao@Sun.COM (aes_key_size != FIPS_AES_256_KEY_SIZE))
102110500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
102210500SHai-May.Chao@Sun.COM
102310500SHai-May.Chao@Sun.COM /*
102410500SHai-May.Chao@Sun.COM * AES-ECB Known Answer Encryption Test
102510500SHai-May.Chao@Sun.COM */
102610500SHai-May.Chao@Sun.COM #ifdef _KERNEL
102710500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_known_key,
102810500SHai-May.Chao@Sun.COM aes_key_size, NULL, AES_ECB_MECH_INFO_TYPE, B_FALSE);
102910500SHai-May.Chao@Sun.COM #else
103010500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_known_key,
103110500SHai-May.Chao@Sun.COM aes_key_size, NULL, CKM_AES_ECB);
103210500SHai-May.Chao@Sun.COM #endif
103310500SHai-May.Chao@Sun.COM
103410500SHai-May.Chao@Sun.COM if (aes_context == NULL) {
103510500SHai-May.Chao@Sun.COM return (CKR_HOST_MEMORY);
103610500SHai-May.Chao@Sun.COM }
103710500SHai-May.Chao@Sun.COM
103810500SHai-May.Chao@Sun.COM rv = fips_aes_encrypt(aes_context, aes_known_plaintext,
103910500SHai-May.Chao@Sun.COM FIPS_AES_ENCRYPT_LENGTH, aes_computed_ciphertext,
104010500SHai-May.Chao@Sun.COM &aes_bytes_encrypted, CKM_AES_ECB);
104110500SHai-May.Chao@Sun.COM
104210500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
104310500SHai-May.Chao@Sun.COM
104410500SHai-May.Chao@Sun.COM if ((rv != CKR_OK) ||
104510500SHai-May.Chao@Sun.COM (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH) ||
104610500SHai-May.Chao@Sun.COM (memcmp(aes_computed_ciphertext, aes_ecb_known_ciphertext,
104710500SHai-May.Chao@Sun.COM FIPS_AES_ENCRYPT_LENGTH) != 0))
104810500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
104910500SHai-May.Chao@Sun.COM
105010500SHai-May.Chao@Sun.COM /*
105110500SHai-May.Chao@Sun.COM * AES-ECB Known Answer Decryption Test
105210500SHai-May.Chao@Sun.COM */
105310500SHai-May.Chao@Sun.COM #ifdef _KERNEL
105410500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_known_key,
105510500SHai-May.Chao@Sun.COM aes_key_size, NULL, AES_ECB_MECH_INFO_TYPE, B_FALSE);
105610500SHai-May.Chao@Sun.COM #else
105710500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_known_key,
105810500SHai-May.Chao@Sun.COM aes_key_size, NULL, CKM_AES_ECB);
105910500SHai-May.Chao@Sun.COM #endif
106010500SHai-May.Chao@Sun.COM
106110500SHai-May.Chao@Sun.COM if (aes_context == NULL) {
106210500SHai-May.Chao@Sun.COM return (CKR_HOST_MEMORY);
106310500SHai-May.Chao@Sun.COM }
106410500SHai-May.Chao@Sun.COM
106510500SHai-May.Chao@Sun.COM rv = fips_aes_decrypt(aes_context, aes_ecb_known_ciphertext,
106610500SHai-May.Chao@Sun.COM FIPS_AES_DECRYPT_LENGTH, aes_computed_plaintext,
106710500SHai-May.Chao@Sun.COM &aes_bytes_decrypted, CKM_AES_ECB);
106810500SHai-May.Chao@Sun.COM
106910500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
107010500SHai-May.Chao@Sun.COM
107110500SHai-May.Chao@Sun.COM if ((rv != CKR_OK) ||
107210500SHai-May.Chao@Sun.COM (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
107310500SHai-May.Chao@Sun.COM (memcmp(aes_computed_plaintext, aes_known_plaintext,
107410500SHai-May.Chao@Sun.COM FIPS_AES_DECRYPT_LENGTH) != 0))
107510500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
107610500SHai-May.Chao@Sun.COM
107710500SHai-May.Chao@Sun.COM /*
107810500SHai-May.Chao@Sun.COM * AES-CBC Known Answer Encryption Test
107910500SHai-May.Chao@Sun.COM */
108010500SHai-May.Chao@Sun.COM #ifdef _KERNEL
108110500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_known_key,
108210500SHai-May.Chao@Sun.COM aes_key_size, aes_cbc_known_initialization_vector,
108310500SHai-May.Chao@Sun.COM AES_CBC_MECH_INFO_TYPE, B_FALSE);
108410500SHai-May.Chao@Sun.COM #else
108510500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_known_key,
108610500SHai-May.Chao@Sun.COM aes_key_size, aes_cbc_known_initialization_vector,
108710500SHai-May.Chao@Sun.COM CKM_AES_CBC);
108810500SHai-May.Chao@Sun.COM #endif
108910500SHai-May.Chao@Sun.COM
109010500SHai-May.Chao@Sun.COM if (aes_context == NULL) {
109110500SHai-May.Chao@Sun.COM return (CKR_HOST_MEMORY);
109210500SHai-May.Chao@Sun.COM }
109310500SHai-May.Chao@Sun.COM
109410500SHai-May.Chao@Sun.COM rv = fips_aes_encrypt(aes_context, aes_known_plaintext,
109510500SHai-May.Chao@Sun.COM FIPS_AES_ENCRYPT_LENGTH, aes_computed_ciphertext,
109610500SHai-May.Chao@Sun.COM &aes_bytes_encrypted, CKM_AES_CBC);
109710500SHai-May.Chao@Sun.COM
109810500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
109910500SHai-May.Chao@Sun.COM
110010500SHai-May.Chao@Sun.COM if ((rv != CKR_OK) ||
110110500SHai-May.Chao@Sun.COM (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH) ||
110210500SHai-May.Chao@Sun.COM (memcmp(aes_computed_ciphertext, aes_cbc_known_ciphertext,
110310500SHai-May.Chao@Sun.COM FIPS_AES_ENCRYPT_LENGTH) != 0))
110410500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
110510500SHai-May.Chao@Sun.COM
110610500SHai-May.Chao@Sun.COM /*
110710500SHai-May.Chao@Sun.COM * AES-CBC Known Answer Decryption Test
110810500SHai-May.Chao@Sun.COM */
110910500SHai-May.Chao@Sun.COM #ifdef _KERNEL
111010500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_known_key,
111110500SHai-May.Chao@Sun.COM aes_key_size, aes_cbc_known_initialization_vector,
111210500SHai-May.Chao@Sun.COM AES_CBC_MECH_INFO_TYPE, B_FALSE);
111310500SHai-May.Chao@Sun.COM #else
111410500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_known_key,
111510500SHai-May.Chao@Sun.COM aes_key_size, aes_cbc_known_initialization_vector,
111610500SHai-May.Chao@Sun.COM CKM_AES_CBC);
111710500SHai-May.Chao@Sun.COM #endif
111810500SHai-May.Chao@Sun.COM
111910500SHai-May.Chao@Sun.COM if (aes_context == NULL)
112010500SHai-May.Chao@Sun.COM return (CRYPTO_HOST_MEMORY);
112110500SHai-May.Chao@Sun.COM
112210500SHai-May.Chao@Sun.COM rv = fips_aes_decrypt(aes_context, aes_cbc_known_ciphertext,
112310500SHai-May.Chao@Sun.COM FIPS_AES_DECRYPT_LENGTH, aes_computed_plaintext,
112410500SHai-May.Chao@Sun.COM &aes_bytes_decrypted, CKM_AES_CBC);
112510500SHai-May.Chao@Sun.COM
112610500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
112710500SHai-May.Chao@Sun.COM
112810500SHai-May.Chao@Sun.COM if ((rv != CKR_OK) ||
112910500SHai-May.Chao@Sun.COM (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
113010500SHai-May.Chao@Sun.COM (memcmp(aes_computed_plaintext, aes_known_plaintext,
113110500SHai-May.Chao@Sun.COM FIPS_AES_DECRYPT_LENGTH) != 0))
113210500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
113310500SHai-May.Chao@Sun.COM
113410500SHai-May.Chao@Sun.COM /*
113510500SHai-May.Chao@Sun.COM * AES-CTR Known Answer Encryption Test
113610500SHai-May.Chao@Sun.COM */
113710500SHai-May.Chao@Sun.COM #ifdef _KERNEL
113810500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_ctr_known_key,
113910500SHai-May.Chao@Sun.COM aes_key_size, aes_ctr_known_counter,
114010500SHai-May.Chao@Sun.COM AES_CTR_MECH_INFO_TYPE, B_FALSE);
114110500SHai-May.Chao@Sun.COM #else
114210500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_ctr_known_key,
114310500SHai-May.Chao@Sun.COM aes_key_size, aes_ctr_known_counter, CKM_AES_CTR);
114410500SHai-May.Chao@Sun.COM #endif
114510500SHai-May.Chao@Sun.COM
114610500SHai-May.Chao@Sun.COM if (aes_context == NULL) {
114710500SHai-May.Chao@Sun.COM return (CKR_HOST_MEMORY);
114810500SHai-May.Chao@Sun.COM }
114910500SHai-May.Chao@Sun.COM
115010500SHai-May.Chao@Sun.COM rv = fips_aes_encrypt(aes_context, aes_ctr_known_plaintext,
115110500SHai-May.Chao@Sun.COM FIPS_AES_ENCRYPT_LENGTH, aes_computed_ciphertext,
115210500SHai-May.Chao@Sun.COM &aes_bytes_encrypted, CKM_AES_CTR);
115310500SHai-May.Chao@Sun.COM
115410500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
115510500SHai-May.Chao@Sun.COM
115610500SHai-May.Chao@Sun.COM if ((rv != CKR_OK) ||
115710500SHai-May.Chao@Sun.COM (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH) ||
115810500SHai-May.Chao@Sun.COM (memcmp(aes_computed_ciphertext, aes_ctr_known_ciphertext,
115910500SHai-May.Chao@Sun.COM FIPS_AES_ENCRYPT_LENGTH) != 0))
116010500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
116110500SHai-May.Chao@Sun.COM
116210500SHai-May.Chao@Sun.COM /*
116310500SHai-May.Chao@Sun.COM * AES-CTR Known Answer Decryption Test
116410500SHai-May.Chao@Sun.COM */
116510500SHai-May.Chao@Sun.COM #ifdef _KERNEL
116610500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_ctr_known_key,
116710500SHai-May.Chao@Sun.COM aes_key_size, aes_ctr_known_counter,
116810500SHai-May.Chao@Sun.COM AES_CTR_MECH_INFO_TYPE, B_FALSE);
116910500SHai-May.Chao@Sun.COM #else
117010500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_ctr_known_key,
117110500SHai-May.Chao@Sun.COM aes_key_size, aes_ctr_known_counter,
117210500SHai-May.Chao@Sun.COM CKM_AES_CTR);
117310500SHai-May.Chao@Sun.COM #endif
117410500SHai-May.Chao@Sun.COM if (aes_context == NULL) {
117510500SHai-May.Chao@Sun.COM return (CKR_HOST_MEMORY);
117610500SHai-May.Chao@Sun.COM }
117710500SHai-May.Chao@Sun.COM
117810500SHai-May.Chao@Sun.COM rv = fips_aes_decrypt(aes_context, aes_ctr_known_ciphertext,
117910500SHai-May.Chao@Sun.COM FIPS_AES_DECRYPT_LENGTH, aes_computed_plaintext,
118010500SHai-May.Chao@Sun.COM &aes_bytes_decrypted, CKM_AES_CTR);
118110500SHai-May.Chao@Sun.COM
118210500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
118310500SHai-May.Chao@Sun.COM
118410500SHai-May.Chao@Sun.COM if ((rv != CKR_OK) ||
118510500SHai-May.Chao@Sun.COM (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
118610500SHai-May.Chao@Sun.COM (memcmp(aes_computed_plaintext, aes_ctr_known_plaintext,
118710500SHai-May.Chao@Sun.COM FIPS_AES_DECRYPT_LENGTH) != 0))
118810500SHai-May.Chao@Sun.COM return (CKR_DEVICE_ERROR);
118910500SHai-May.Chao@Sun.COM
119010500SHai-May.Chao@Sun.COM /*
119110500SHai-May.Chao@Sun.COM * The following POSTs are only available in Kernel
119210500SHai-May.Chao@Sun.COM *
119310500SHai-May.Chao@Sun.COM * CCM, GCM, and GMAC
119410500SHai-May.Chao@Sun.COM */
119510500SHai-May.Chao@Sun.COM #ifdef _KERNEL
119610500SHai-May.Chao@Sun.COM
119710500SHai-May.Chao@Sun.COM /*
119810500SHai-May.Chao@Sun.COM * AES-CCM Known Answer Encryption Test
119910500SHai-May.Chao@Sun.COM */
120010500SHai-May.Chao@Sun.COM ccm_param.ulMACSize = 16; /* Tlen */
120110500SHai-May.Chao@Sun.COM ccm_param.ulNonceSize = 7; /* Nlen */
120210500SHai-May.Chao@Sun.COM ccm_param.ulAuthDataSize = 30; /* Alen */
120310500SHai-May.Chao@Sun.COM ccm_param.ulDataSize = 32; /* Plen or Clen */
120410500SHai-May.Chao@Sun.COM ccm_param.nonce = aes_ccm_known_nonce;
120510500SHai-May.Chao@Sun.COM ccm_param.authData = aes_ccm_known_adata;
120610500SHai-May.Chao@Sun.COM
120710500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_ccm_known_key,
120810500SHai-May.Chao@Sun.COM aes_key_size, (uint8_t *)&ccm_param,
120910500SHai-May.Chao@Sun.COM AES_CCM_MECH_INFO_TYPE, B_TRUE);
121010500SHai-May.Chao@Sun.COM
121110500SHai-May.Chao@Sun.COM if (aes_context == NULL) {
121210500SHai-May.Chao@Sun.COM return (CRYPTO_HOST_MEMORY);
121310500SHai-May.Chao@Sun.COM }
121410500SHai-May.Chao@Sun.COM
121510500SHai-May.Chao@Sun.COM rv = fips_aes_encrypt(aes_context, aes_ccm_known_plaintext,
121610500SHai-May.Chao@Sun.COM 2*FIPS_AES_ENCRYPT_LENGTH, aes_ccm_computed_ciphertext,
121710500SHai-May.Chao@Sun.COM &aes_bytes_encrypted, AES_CCM_MECH_INFO_TYPE);
121810500SHai-May.Chao@Sun.COM
121910500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
122010500SHai-May.Chao@Sun.COM
122110500SHai-May.Chao@Sun.COM if ((rv != CRYPTO_SUCCESS) ||
122210500SHai-May.Chao@Sun.COM (aes_bytes_encrypted != 3*FIPS_AES_ENCRYPT_LENGTH) ||
122310500SHai-May.Chao@Sun.COM (memcmp(aes_ccm_computed_ciphertext, aes_ccm_known_ciphertext,
122410500SHai-May.Chao@Sun.COM 3*FIPS_AES_ENCRYPT_LENGTH) != 0))
122510500SHai-May.Chao@Sun.COM return (CRYPTO_DEVICE_ERROR);
122610500SHai-May.Chao@Sun.COM
122710500SHai-May.Chao@Sun.COM /*
122810500SHai-May.Chao@Sun.COM * AES-CCM Known Answer Decryption Test
122910500SHai-May.Chao@Sun.COM */
123010500SHai-May.Chao@Sun.COM ccm_param.ulMACSize = 16; /* Tlen */
123110500SHai-May.Chao@Sun.COM ccm_param.ulNonceSize = 7; /* Nlen */
123210500SHai-May.Chao@Sun.COM ccm_param.ulAuthDataSize = 30; /* Alen */
123310500SHai-May.Chao@Sun.COM ccm_param.ulDataSize = 48; /* Plen or Clen */
123410500SHai-May.Chao@Sun.COM ccm_param.nonce = aes_ccm_known_nonce;
123510500SHai-May.Chao@Sun.COM ccm_param.authData = aes_ccm_known_adata;
123610500SHai-May.Chao@Sun.COM
123710500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_ccm_known_key,
123810500SHai-May.Chao@Sun.COM aes_key_size, (uint8_t *)&ccm_param,
123910500SHai-May.Chao@Sun.COM AES_CCM_MECH_INFO_TYPE, B_FALSE);
124010500SHai-May.Chao@Sun.COM
124110500SHai-May.Chao@Sun.COM if (aes_context == NULL) {
124210500SHai-May.Chao@Sun.COM return (CRYPTO_HOST_MEMORY);
124310500SHai-May.Chao@Sun.COM }
124410500SHai-May.Chao@Sun.COM
124510500SHai-May.Chao@Sun.COM rv = fips_aes_decrypt(aes_context, aes_ccm_known_ciphertext,
124610500SHai-May.Chao@Sun.COM 2*FIPS_AES_DECRYPT_LENGTH, aes_ccm_computed_plaintext,
124710500SHai-May.Chao@Sun.COM &aes_bytes_decrypted, AES_CCM_MECH_INFO_TYPE);
124810500SHai-May.Chao@Sun.COM
124910500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
125010500SHai-May.Chao@Sun.COM
125110500SHai-May.Chao@Sun.COM if ((rv != CRYPTO_SUCCESS) ||
125210500SHai-May.Chao@Sun.COM (aes_bytes_decrypted != 2*FIPS_AES_DECRYPT_LENGTH) ||
125310500SHai-May.Chao@Sun.COM (memcmp(aes_ccm_computed_plaintext, aes_ccm_known_plaintext,
125410500SHai-May.Chao@Sun.COM 2*FIPS_AES_DECRYPT_LENGTH) != 0))
125510500SHai-May.Chao@Sun.COM return (CRYPTO_DEVICE_ERROR);
125610500SHai-May.Chao@Sun.COM
125710500SHai-May.Chao@Sun.COM /*
125810500SHai-May.Chao@Sun.COM * AES-GCM Known Answer Encryption Test
125910500SHai-May.Chao@Sun.COM */
126010500SHai-May.Chao@Sun.COM gcm_param.pIv = aes_gcm_known_iv;
126110500SHai-May.Chao@Sun.COM gcm_param.ulIvLen = AES_GMAC_IV_LEN; /* IVlen = 96 bits */
126210500SHai-May.Chao@Sun.COM gcm_param.ulTagBits = AES_GMAC_TAG_BITS; /* Taglen = 128 bits */
126310500SHai-May.Chao@Sun.COM gcm_param.ulAADLen = 16;
126410500SHai-May.Chao@Sun.COM gcm_param.pAAD = aes_gcm_known_adata;
126510500SHai-May.Chao@Sun.COM
126610500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_gcm_known_key,
126710500SHai-May.Chao@Sun.COM aes_key_size, (uint8_t *)&gcm_param,
126810500SHai-May.Chao@Sun.COM AES_GCM_MECH_INFO_TYPE, B_TRUE);
126910500SHai-May.Chao@Sun.COM
127010500SHai-May.Chao@Sun.COM if (aes_context == NULL) {
127110500SHai-May.Chao@Sun.COM return (CRYPTO_HOST_MEMORY);
127210500SHai-May.Chao@Sun.COM }
127310500SHai-May.Chao@Sun.COM
127410500SHai-May.Chao@Sun.COM rv = fips_aes_encrypt(aes_context, aes_gcm_known_plaintext,
127510500SHai-May.Chao@Sun.COM FIPS_AES_ENCRYPT_LENGTH, aes_gcm_computed_ciphertext,
127610500SHai-May.Chao@Sun.COM &aes_bytes_encrypted, AES_GCM_MECH_INFO_TYPE);
127710500SHai-May.Chao@Sun.COM
127810500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
127910500SHai-May.Chao@Sun.COM
128010500SHai-May.Chao@Sun.COM if ((rv != CRYPTO_SUCCESS) ||
128110500SHai-May.Chao@Sun.COM (aes_bytes_encrypted != 2*FIPS_AES_ENCRYPT_LENGTH) ||
128210500SHai-May.Chao@Sun.COM (memcmp(aes_gcm_computed_ciphertext, aes_gcm_known_ciphertext,
128310500SHai-May.Chao@Sun.COM 2*FIPS_AES_ENCRYPT_LENGTH) != 0))
128410500SHai-May.Chao@Sun.COM return (CRYPTO_DEVICE_ERROR);
128510500SHai-May.Chao@Sun.COM
128610500SHai-May.Chao@Sun.COM /*
128710500SHai-May.Chao@Sun.COM * AES-GCM Known Answer Decryption Test
128810500SHai-May.Chao@Sun.COM */
128910500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_gcm_known_key,
129010500SHai-May.Chao@Sun.COM aes_key_size, (uint8_t *)&gcm_param,
129110500SHai-May.Chao@Sun.COM AES_GCM_MECH_INFO_TYPE, B_FALSE);
129210500SHai-May.Chao@Sun.COM
129310500SHai-May.Chao@Sun.COM if (aes_context == NULL) {
129410500SHai-May.Chao@Sun.COM return (CRYPTO_HOST_MEMORY);
129510500SHai-May.Chao@Sun.COM }
129610500SHai-May.Chao@Sun.COM
129710500SHai-May.Chao@Sun.COM rv = fips_aes_decrypt(aes_context, aes_gcm_known_ciphertext,
129810500SHai-May.Chao@Sun.COM FIPS_AES_DECRYPT_LENGTH, aes_gcm_computed_plaintext,
129910500SHai-May.Chao@Sun.COM &aes_bytes_decrypted, AES_GCM_MECH_INFO_TYPE);
130010500SHai-May.Chao@Sun.COM
130110500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
130210500SHai-May.Chao@Sun.COM
130310500SHai-May.Chao@Sun.COM if ((rv != CRYPTO_SUCCESS) ||
130410500SHai-May.Chao@Sun.COM (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
130510500SHai-May.Chao@Sun.COM (memcmp(aes_gcm_computed_plaintext, aes_gcm_known_plaintext,
130610500SHai-May.Chao@Sun.COM FIPS_AES_DECRYPT_LENGTH) != 0))
130710500SHai-May.Chao@Sun.COM return (CRYPTO_DEVICE_ERROR);
130810500SHai-May.Chao@Sun.COM
130910500SHai-May.Chao@Sun.COM /*
131010500SHai-May.Chao@Sun.COM * AES-GMAC Known Answer Encryption Test
131110500SHai-May.Chao@Sun.COM */
131210500SHai-May.Chao@Sun.COM gmac_param.pIv = aes_gmac_known_iv;
131310500SHai-May.Chao@Sun.COM gmac_param.ulAADLen = 16;
131410500SHai-May.Chao@Sun.COM gmac_param.pAAD = aes_gmac_known_adata;
131510500SHai-May.Chao@Sun.COM
131610500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_gmac_known_key,
131710500SHai-May.Chao@Sun.COM aes_key_size, (uint8_t *)&gmac_param,
131810500SHai-May.Chao@Sun.COM AES_GMAC_MECH_INFO_TYPE, B_TRUE);
131910500SHai-May.Chao@Sun.COM
132010500SHai-May.Chao@Sun.COM if (aes_context == NULL) {
132110500SHai-May.Chao@Sun.COM return (CRYPTO_HOST_MEMORY);
132210500SHai-May.Chao@Sun.COM }
132310500SHai-May.Chao@Sun.COM
132410500SHai-May.Chao@Sun.COM rv = fips_aes_encrypt(aes_context, NULL,
132510500SHai-May.Chao@Sun.COM 0, aes_gmac_computed_tag,
132610500SHai-May.Chao@Sun.COM &aes_bytes_encrypted, AES_GMAC_MECH_INFO_TYPE);
132710500SHai-May.Chao@Sun.COM
132810500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
132910500SHai-May.Chao@Sun.COM
133010500SHai-May.Chao@Sun.COM if ((rv != CRYPTO_SUCCESS) ||
133110500SHai-May.Chao@Sun.COM (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH) ||
133210500SHai-May.Chao@Sun.COM (memcmp(aes_gmac_computed_tag, aes_gmac_known_tag,
133310500SHai-May.Chao@Sun.COM FIPS_AES_ENCRYPT_LENGTH) != 0))
133410500SHai-May.Chao@Sun.COM return (CRYPTO_DEVICE_ERROR);
133510500SHai-May.Chao@Sun.COM
133610500SHai-May.Chao@Sun.COM /*
133710500SHai-May.Chao@Sun.COM * AES-GMAC Known Answer Decryption Test
133810500SHai-May.Chao@Sun.COM */
133910500SHai-May.Chao@Sun.COM
134010500SHai-May.Chao@Sun.COM aes_context = fips_aes_build_context(aes_gmac_known_key,
134110500SHai-May.Chao@Sun.COM aes_key_size, (uint8_t *)&gmac_param,
134210500SHai-May.Chao@Sun.COM AES_GMAC_MECH_INFO_TYPE, B_FALSE);
134310500SHai-May.Chao@Sun.COM
134410500SHai-May.Chao@Sun.COM if (aes_context == NULL) {
134510500SHai-May.Chao@Sun.COM return (CRYPTO_HOST_MEMORY);
134610500SHai-May.Chao@Sun.COM }
134710500SHai-May.Chao@Sun.COM
134810500SHai-May.Chao@Sun.COM rv = fips_aes_decrypt(aes_context, aes_gmac_known_tag,
134910500SHai-May.Chao@Sun.COM FIPS_AES_DECRYPT_LENGTH, NULL,
135010500SHai-May.Chao@Sun.COM &aes_bytes_decrypted, AES_GMAC_MECH_INFO_TYPE);
135110500SHai-May.Chao@Sun.COM
135210500SHai-May.Chao@Sun.COM fips_aes_free_context(aes_context);
135310500SHai-May.Chao@Sun.COM
135410500SHai-May.Chao@Sun.COM if ((rv != CRYPTO_SUCCESS) ||
135510500SHai-May.Chao@Sun.COM (aes_bytes_decrypted != 0))
135610500SHai-May.Chao@Sun.COM return (CRYPTO_DEVICE_ERROR);
135710500SHai-May.Chao@Sun.COM
135810500SHai-May.Chao@Sun.COM #endif /* _KERNEL */
135910500SHai-May.Chao@Sun.COM
136010500SHai-May.Chao@Sun.COM return (CRYPTO_SUCCESS);
136110500SHai-May.Chao@Sun.COM }
1362