xref: /onnv-gate/usr/src/common/crypto/fips/fips_aes_util.c (revision 12929:f2051cc42292)
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