xref: /onnv-gate/usr/src/common/crypto/fips/fips_des_util.c (revision 10979:00cad6413daf)
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 /*
2210500SHai-May.Chao@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2310500SHai-May.Chao@Sun.COM  * Use is subject to license terms.
2410500SHai-May.Chao@Sun.COM  */
2510500SHai-May.Chao@Sun.COM 
2610500SHai-May.Chao@Sun.COM #include <sys/types.h>
2710500SHai-May.Chao@Sun.COM #include <sys/errno.h>
2810500SHai-May.Chao@Sun.COM #include <sys/kmem.h>
2910500SHai-May.Chao@Sun.COM #include <sys/systm.h>
3010500SHai-May.Chao@Sun.COM #include <sys/crypto/common.h>
3110500SHai-May.Chao@Sun.COM #include <sys/cmn_err.h>
3210500SHai-May.Chao@Sun.COM #include <modes/modes.h>
3310500SHai-May.Chao@Sun.COM #define	_DES_FIPS_POST
3410500SHai-May.Chao@Sun.COM #ifndef _KERNEL
3510500SHai-May.Chao@Sun.COM #include <stdlib.h>
3610500SHai-May.Chao@Sun.COM #include <string.h>
3710500SHai-May.Chao@Sun.COM #include <strings.h>
3810500SHai-May.Chao@Sun.COM #include <stdio.h>
3910500SHai-May.Chao@Sun.COM #include <security/cryptoki.h>
4010500SHai-May.Chao@Sun.COM #include <cryptoutil.h>
4110500SHai-May.Chao@Sun.COM #include "softCrypt.h"
4210500SHai-May.Chao@Sun.COM #else
4310500SHai-May.Chao@Sun.COM #define	_DES_IMPL
4410500SHai-May.Chao@Sun.COM #include <des/des_impl.h>
4510500SHai-May.Chao@Sun.COM #endif
4610500SHai-May.Chao@Sun.COM 
4710500SHai-May.Chao@Sun.COM #ifndef _KERNEL
4810500SHai-May.Chao@Sun.COM /*
4910500SHai-May.Chao@Sun.COM  * Allocate context for the DES encryption or decryption operation, and
5010500SHai-May.Chao@Sun.COM  * generate DES or DES3 key schedule to speed up the operation.
5110500SHai-May.Chao@Sun.COM  */
5210500SHai-May.Chao@Sun.COM soft_des_ctx_t *
des_build_context(uint8_t * key,uint8_t * iv,CK_KEY_TYPE key_type,CK_MECHANISM_TYPE mechanism)5310500SHai-May.Chao@Sun.COM des_build_context(uint8_t *key, uint8_t *iv, CK_KEY_TYPE key_type,
5410500SHai-May.Chao@Sun.COM 	CK_MECHANISM_TYPE mechanism)
5510500SHai-May.Chao@Sun.COM {
5610500SHai-May.Chao@Sun.COM 
5710500SHai-May.Chao@Sun.COM 	size_t size;
5810500SHai-May.Chao@Sun.COM 	soft_des_ctx_t *soft_des_ctx;
5910500SHai-May.Chao@Sun.COM 
6010500SHai-May.Chao@Sun.COM 	soft_des_ctx = calloc(1, sizeof (soft_des_ctx_t));
6110500SHai-May.Chao@Sun.COM 	if (soft_des_ctx == NULL) {
6210500SHai-May.Chao@Sun.COM 		return (NULL);
6310500SHai-May.Chao@Sun.COM 	}
6410500SHai-May.Chao@Sun.COM 
6510500SHai-May.Chao@Sun.COM 	/* Allocate key schedule for DES or DES3 based on key type. */
6610500SHai-May.Chao@Sun.COM 	if (key_type == CKK_DES) {
6710500SHai-May.Chao@Sun.COM 		soft_des_ctx->key_sched = des_alloc_keysched(&size, DES, 0);
6810500SHai-May.Chao@Sun.COM 		if (soft_des_ctx->key_sched == NULL) {
6910500SHai-May.Chao@Sun.COM 			free(soft_des_ctx);
7010500SHai-May.Chao@Sun.COM 			return (NULL);
7110500SHai-May.Chao@Sun.COM 		}
7210500SHai-May.Chao@Sun.COM 		des_init_keysched(key, DES, soft_des_ctx->key_sched);
7310500SHai-May.Chao@Sun.COM 	} else {
7410500SHai-May.Chao@Sun.COM 		soft_des_ctx->key_sched = des_alloc_keysched(&size, DES3, 0);
7510500SHai-May.Chao@Sun.COM 		if (soft_des_ctx->key_sched == NULL) {
7610500SHai-May.Chao@Sun.COM 			free(soft_des_ctx);
7710500SHai-May.Chao@Sun.COM 			return (NULL);
7810500SHai-May.Chao@Sun.COM 		}
7910500SHai-May.Chao@Sun.COM 		des_init_keysched(key, DES3, soft_des_ctx->key_sched);
8010500SHai-May.Chao@Sun.COM 	}
8110500SHai-May.Chao@Sun.COM 
8210500SHai-May.Chao@Sun.COM 	soft_des_ctx->keysched_len = size;
8310500SHai-May.Chao@Sun.COM 	soft_des_ctx->key_type = key_type;
8410500SHai-May.Chao@Sun.COM 
8510500SHai-May.Chao@Sun.COM 	if ((mechanism == CKM_DES_CBC) || (mechanism == CKM_DES3_CBC)) {
8610500SHai-May.Chao@Sun.COM 		/* Save Initialization Vector (IV) in the context. */
8710500SHai-May.Chao@Sun.COM 		(void) memcpy(soft_des_ctx->ivec, iv, DES_BLOCK_LEN);
8810500SHai-May.Chao@Sun.COM 
8910500SHai-May.Chao@Sun.COM 		/* Allocate a context for DES cipher-block chaining. */
9010500SHai-May.Chao@Sun.COM 		soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
9110500SHai-May.Chao@Sun.COM 		    soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
9210500SHai-May.Chao@Sun.COM 		    soft_des_ctx->ivec, soft_des_ctx->key_type);
9310500SHai-May.Chao@Sun.COM 
9410500SHai-May.Chao@Sun.COM 		if (soft_des_ctx->des_cbc == NULL) {
9510500SHai-May.Chao@Sun.COM 			bzero(soft_des_ctx->key_sched,
9610500SHai-May.Chao@Sun.COM 			    soft_des_ctx->keysched_len);
9710500SHai-May.Chao@Sun.COM 			free(soft_des_ctx->key_sched);
9810500SHai-May.Chao@Sun.COM 			return (NULL);
9910500SHai-May.Chao@Sun.COM 		}
10010500SHai-May.Chao@Sun.COM 	}
10110500SHai-May.Chao@Sun.COM 
10210500SHai-May.Chao@Sun.COM 	return (soft_des_ctx);
10310500SHai-May.Chao@Sun.COM }
10410500SHai-May.Chao@Sun.COM 
10510500SHai-May.Chao@Sun.COM /*
10610500SHai-May.Chao@Sun.COM  * Free the DES context.
10710500SHai-May.Chao@Sun.COM  */
10810500SHai-May.Chao@Sun.COM void
fips_des_free_context(soft_des_ctx_t * soft_des_ctx)10910500SHai-May.Chao@Sun.COM fips_des_free_context(soft_des_ctx_t *soft_des_ctx)
11010500SHai-May.Chao@Sun.COM {
11110500SHai-May.Chao@Sun.COM 
11210500SHai-May.Chao@Sun.COM 	des_ctx_t *des_ctx;
11310500SHai-May.Chao@Sun.COM 
11410500SHai-May.Chao@Sun.COM 	des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
11510500SHai-May.Chao@Sun.COM 	if (des_ctx != NULL) {
11610500SHai-May.Chao@Sun.COM 		bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len);
11710500SHai-May.Chao@Sun.COM 		free(soft_des_ctx->des_cbc);
11810500SHai-May.Chao@Sun.COM 	}
11910500SHai-May.Chao@Sun.COM 
12010500SHai-May.Chao@Sun.COM 	bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
12110500SHai-May.Chao@Sun.COM 	free(soft_des_ctx->key_sched);
12210500SHai-May.Chao@Sun.COM 	free(soft_des_ctx);
12310500SHai-May.Chao@Sun.COM }
12410500SHai-May.Chao@Sun.COM #else
12510500SHai-May.Chao@Sun.COM 
12610500SHai-May.Chao@Sun.COM static void
des_copy_block64(uint8_t * in,uint64_t * out)12710500SHai-May.Chao@Sun.COM des_copy_block64(uint8_t *in, uint64_t *out)
12810500SHai-May.Chao@Sun.COM {
12910500SHai-May.Chao@Sun.COM 	if (IS_P2ALIGNED(in, sizeof (uint64_t))) {
13010500SHai-May.Chao@Sun.COM 		/* LINTED: pointer alignment */
13110500SHai-May.Chao@Sun.COM 		out[0] = *(uint64_t *)&in[0];
13210500SHai-May.Chao@Sun.COM 	} else {
13310500SHai-May.Chao@Sun.COM 		uint64_t tmp64;
13410500SHai-May.Chao@Sun.COM 
13510500SHai-May.Chao@Sun.COM #ifdef _BIG_ENDIAN
13610500SHai-May.Chao@Sun.COM 		tmp64 = (((uint64_t)in[0] << 56) |
13710500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[1] << 48) |
13810500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[2] << 40) |
13910500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[3] << 32) |
14010500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[4] << 24) |
14110500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[5] << 16) |
14210500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[6] << 8) |
14310500SHai-May.Chao@Sun.COM 		    (uint64_t)in[7]);
14410500SHai-May.Chao@Sun.COM #else
14510500SHai-May.Chao@Sun.COM 		tmp64 = (((uint64_t)in[7] << 56) |
14610500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[6] << 48) |
14710500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[5] << 40) |
14810500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[4] << 32) |
14910500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[3] << 24) |
15010500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[2] << 16) |
15110500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[1] << 8) |
15210500SHai-May.Chao@Sun.COM 		    (uint64_t)in[0]);
15310500SHai-May.Chao@Sun.COM #endif /* _BIG_ENDIAN */
15410500SHai-May.Chao@Sun.COM 
15510500SHai-May.Chao@Sun.COM 		out[0] = tmp64;
15610500SHai-May.Chao@Sun.COM 	}
15710500SHai-May.Chao@Sun.COM }
15810500SHai-May.Chao@Sun.COM 
15910500SHai-May.Chao@Sun.COM des_ctx_t *
des_build_context(uint8_t * key,uint8_t * iv,des_mech_type_t mech_type)16010500SHai-May.Chao@Sun.COM des_build_context(uint8_t *key, uint8_t *iv,
16110500SHai-May.Chao@Sun.COM 	des_mech_type_t mech_type)
16210500SHai-May.Chao@Sun.COM {
16310500SHai-May.Chao@Sun.COM 	int rv = CRYPTO_SUCCESS;
16410500SHai-May.Chao@Sun.COM 	void *keysched;
16510500SHai-May.Chao@Sun.COM 	size_t size;
16610500SHai-May.Chao@Sun.COM 	des_ctx_t *des_ctx = NULL;
16710500SHai-May.Chao@Sun.COM 	des_strength_t strength;
16810500SHai-May.Chao@Sun.COM 
16910500SHai-May.Chao@Sun.COM 	switch (mech_type) {
17010500SHai-May.Chao@Sun.COM 	case DES_ECB_MECH_INFO_TYPE:
17110500SHai-May.Chao@Sun.COM 		des_ctx = ecb_alloc_ctx(KM_SLEEP);
17210500SHai-May.Chao@Sun.COM 		/* FALLTHRU */
17310500SHai-May.Chao@Sun.COM 	case DES_CBC_MECH_INFO_TYPE:
17410500SHai-May.Chao@Sun.COM 		strength = DES;
17510500SHai-May.Chao@Sun.COM 		if (des_ctx == NULL)
17610500SHai-May.Chao@Sun.COM 			des_ctx = cbc_alloc_ctx(KM_SLEEP);
17710500SHai-May.Chao@Sun.COM 		break;
17810500SHai-May.Chao@Sun.COM 	case DES3_ECB_MECH_INFO_TYPE:
17910500SHai-May.Chao@Sun.COM 		des_ctx = ecb_alloc_ctx(KM_SLEEP);
18010500SHai-May.Chao@Sun.COM 		/* FALLTHRU */
18110500SHai-May.Chao@Sun.COM 	case DES3_CBC_MECH_INFO_TYPE:
18210500SHai-May.Chao@Sun.COM 		strength = DES3;
18310500SHai-May.Chao@Sun.COM 		if (des_ctx == NULL)
18410500SHai-May.Chao@Sun.COM 			des_ctx = cbc_alloc_ctx(KM_SLEEP);
18510500SHai-May.Chao@Sun.COM 		break;
18610500SHai-May.Chao@Sun.COM 	default:
18710500SHai-May.Chao@Sun.COM 		return (NULL);
18810500SHai-May.Chao@Sun.COM 	}
18910500SHai-May.Chao@Sun.COM 
19010500SHai-May.Chao@Sun.COM 	if ((keysched = des_alloc_keysched(&size, strength,
19110500SHai-May.Chao@Sun.COM 	    KM_SLEEP)) == NULL)
19210500SHai-May.Chao@Sun.COM 		return (NULL);
19310500SHai-May.Chao@Sun.COM 
19410500SHai-May.Chao@Sun.COM 	/*
19510500SHai-May.Chao@Sun.COM 	 * Initialize key schedule.
19610500SHai-May.Chao@Sun.COM 	 * Key length is stored in the key.
19710500SHai-May.Chao@Sun.COM 	 */
19810500SHai-May.Chao@Sun.COM 	des_init_keysched(key, strength, keysched);
19910500SHai-May.Chao@Sun.COM 
20010500SHai-May.Chao@Sun.COM 	des_ctx->dc_flags |= PROVIDER_OWNS_KEY_SCHEDULE;
20110500SHai-May.Chao@Sun.COM 	des_ctx->dc_keysched_len = size;
20210500SHai-May.Chao@Sun.COM 	des_ctx->dc_keysched = keysched;
20310500SHai-May.Chao@Sun.COM 
20410500SHai-May.Chao@Sun.COM 	if (strength == DES3) {
20510500SHai-May.Chao@Sun.COM 		des_ctx->dc_flags |= DES3_STRENGTH;
20610500SHai-May.Chao@Sun.COM 	}
20710500SHai-May.Chao@Sun.COM 
20810500SHai-May.Chao@Sun.COM 	switch (mech_type) {
20910500SHai-May.Chao@Sun.COM 	case DES_CBC_MECH_INFO_TYPE:
21010500SHai-May.Chao@Sun.COM 	case DES3_CBC_MECH_INFO_TYPE:
21110500SHai-May.Chao@Sun.COM 		/* Save Initialization Vector (IV) in the context. */
21210500SHai-May.Chao@Sun.COM 		rv = cbc_init_ctx((cbc_ctx_t *)des_ctx, (char *)iv,
21310500SHai-May.Chao@Sun.COM 		    DES_BLOCK_LEN, DES_BLOCK_LEN, des_copy_block64);
21410500SHai-May.Chao@Sun.COM 		break;
21510500SHai-May.Chao@Sun.COM 	case DES_ECB_MECH_INFO_TYPE:
21610500SHai-May.Chao@Sun.COM 	case DES3_ECB_MECH_INFO_TYPE:
21710500SHai-May.Chao@Sun.COM 		des_ctx->dc_flags |= ECB_MODE;
21810500SHai-May.Chao@Sun.COM 	}
21910500SHai-May.Chao@Sun.COM 
22010500SHai-May.Chao@Sun.COM 	if (rv != CRYPTO_SUCCESS) {
22110500SHai-May.Chao@Sun.COM 		if (des_ctx->dc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
22210500SHai-May.Chao@Sun.COM 			bzero(keysched, size);
22310500SHai-May.Chao@Sun.COM 			kmem_free(keysched, size);
22410500SHai-May.Chao@Sun.COM 		}
22510500SHai-May.Chao@Sun.COM 	}
22610500SHai-May.Chao@Sun.COM 
22710500SHai-May.Chao@Sun.COM 	return (des_ctx);
22810500SHai-May.Chao@Sun.COM }
22910500SHai-May.Chao@Sun.COM 
23010500SHai-May.Chao@Sun.COM void
fips_des_free_context(des_ctx_t * des_ctx)23110500SHai-May.Chao@Sun.COM fips_des_free_context(des_ctx_t *des_ctx)
23210500SHai-May.Chao@Sun.COM {
23310500SHai-May.Chao@Sun.COM 
23410500SHai-May.Chao@Sun.COM 	if (des_ctx != NULL) {
23510500SHai-May.Chao@Sun.COM 		if (des_ctx->dc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
23610500SHai-May.Chao@Sun.COM 			ASSERT(des_ctx->dc_keysched_len != 0);
23710500SHai-May.Chao@Sun.COM 			bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len);
23810500SHai-May.Chao@Sun.COM 			kmem_free(des_ctx->dc_keysched,
23910500SHai-May.Chao@Sun.COM 			    des_ctx->dc_keysched_len);
24010500SHai-May.Chao@Sun.COM 		}
241*10979SHai-May.Chao@Sun.COM 		bzero(des_ctx, sizeof (des_ctx_t));
242*10979SHai-May.Chao@Sun.COM 		kmem_free(des_ctx, sizeof (des_ctx_t));
24310500SHai-May.Chao@Sun.COM 	}
24410500SHai-May.Chao@Sun.COM }
24510500SHai-May.Chao@Sun.COM #endif
24610500SHai-May.Chao@Sun.COM 
24710500SHai-May.Chao@Sun.COM /*
24810500SHai-May.Chao@Sun.COM  * fips_des_encrypt()
24910500SHai-May.Chao@Sun.COM  *
25010500SHai-May.Chao@Sun.COM  * Arguments:
25110500SHai-May.Chao@Sun.COM  *	soft_des_ctx:	pointer to DES context
25210500SHai-May.Chao@Sun.COM  *	in_buf:		pointer to the input data to be encrypted
25310500SHai-May.Chao@Sun.COM  *	ulDataLen:	length of the input data
25410500SHai-May.Chao@Sun.COM  *	out_buf:	pointer to the output data after encryption
25510500SHai-May.Chao@Sun.COM  *	pulEncryptedLen: pointer to the length of the output data
25610500SHai-May.Chao@Sun.COM  *	mechanism:	CKM_DES_ECB, CKM_DES3_ECB, CKM_DES_CBC, CKM_DES3_CBC
25710500SHai-May.Chao@Sun.COM  *
25810500SHai-May.Chao@Sun.COM  * Description:
25910500SHai-May.Chao@Sun.COM  *	This function calls the corresponding DES low-level encrypt
26010500SHai-May.Chao@Sun.COM  *	routine based on the mechanism.
26110500SHai-May.Chao@Sun.COM  *
26210500SHai-May.Chao@Sun.COM  */
26310500SHai-May.Chao@Sun.COM #ifndef _KERNEL
26410500SHai-May.Chao@Sun.COM CK_RV
fips_des_encrypt(soft_des_ctx_t * soft_des_ctx,CK_BYTE_PTR in_buf,CK_ULONG ulDataLen,CK_BYTE_PTR out_buf,CK_ULONG_PTR pulEncryptedLen,CK_MECHANISM_TYPE mechanism)26510500SHai-May.Chao@Sun.COM fips_des_encrypt(soft_des_ctx_t *soft_des_ctx, CK_BYTE_PTR in_buf,
26610500SHai-May.Chao@Sun.COM 	CK_ULONG ulDataLen, CK_BYTE_PTR out_buf,
26710500SHai-May.Chao@Sun.COM 	CK_ULONG_PTR pulEncryptedLen, CK_MECHANISM_TYPE mechanism)
26810500SHai-May.Chao@Sun.COM #else
26910500SHai-May.Chao@Sun.COM int
27010500SHai-May.Chao@Sun.COM fips_des_encrypt(des_ctx_t *des_ctx, uint8_t *in_buf,
27110500SHai-May.Chao@Sun.COM 	ulong_t ulDataLen, uint8_t *out_buf,
27210500SHai-May.Chao@Sun.COM 	ulong_t *pulEncryptedLen, des_mech_type_t mechanism)
27310500SHai-May.Chao@Sun.COM #endif
27410500SHai-May.Chao@Sun.COM {
27510500SHai-May.Chao@Sun.COM 
27610500SHai-May.Chao@Sun.COM 	CK_RV rv = CKR_OK;
27710500SHai-May.Chao@Sun.COM 	int rc = 0;
27810500SHai-May.Chao@Sun.COM 	ulong_t out_len;
27910500SHai-May.Chao@Sun.COM 
28010500SHai-May.Chao@Sun.COM 	/*
28110500SHai-May.Chao@Sun.COM 	 * DES only takes input length that is a multiple of blocksize
28210500SHai-May.Chao@Sun.COM 	 * with the mechanism CKM_DES<n>_ECB or CKM_DES<n>_CBC.
28310500SHai-May.Chao@Sun.COM 	 */
28410500SHai-May.Chao@Sun.COM 	if ((ulDataLen % DES_BLOCK_LEN) != 0) {
28510500SHai-May.Chao@Sun.COM 		return (CKR_DATA_LEN_RANGE);
28610500SHai-May.Chao@Sun.COM 	}
28710500SHai-May.Chao@Sun.COM 
28810500SHai-May.Chao@Sun.COM 	/*
28910500SHai-May.Chao@Sun.COM 	 * For non-padding mode, the output length will
29010500SHai-May.Chao@Sun.COM 	 * be same as the input length.
29110500SHai-May.Chao@Sun.COM 	 */
29210500SHai-May.Chao@Sun.COM 	out_len = ulDataLen;
29310500SHai-May.Chao@Sun.COM 
29410500SHai-May.Chao@Sun.COM 	/*
29510500SHai-May.Chao@Sun.COM 	 * Begin Encryption now.
29610500SHai-May.Chao@Sun.COM 	 */
29710500SHai-May.Chao@Sun.COM 	switch (mechanism) {
29810500SHai-May.Chao@Sun.COM 	case CKM_DES_ECB:
29910500SHai-May.Chao@Sun.COM 	case CKM_DES3_ECB:
30010500SHai-May.Chao@Sun.COM 	{
30110500SHai-May.Chao@Sun.COM 
30210500SHai-May.Chao@Sun.COM 		ulong_t i;
30310500SHai-May.Chao@Sun.COM 		uint8_t *tmp_inbuf;
30410500SHai-May.Chao@Sun.COM 		uint8_t *tmp_outbuf;
30510500SHai-May.Chao@Sun.COM 
30610500SHai-May.Chao@Sun.COM 		for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
30710500SHai-May.Chao@Sun.COM 			tmp_inbuf = &in_buf[i];
30810500SHai-May.Chao@Sun.COM 			tmp_outbuf = &out_buf[i];
30910500SHai-May.Chao@Sun.COM 			/* Crunch one block of data for DES. */
31010500SHai-May.Chao@Sun.COM #ifndef _KERNEL
31110500SHai-May.Chao@Sun.COM 			if (soft_des_ctx->key_type == CKK_DES)
31210500SHai-May.Chao@Sun.COM 				(void) des_crunch_block(
31310500SHai-May.Chao@Sun.COM 				    soft_des_ctx->key_sched,
31410500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_FALSE);
31510500SHai-May.Chao@Sun.COM 			else
31610500SHai-May.Chao@Sun.COM 				(void) des3_crunch_block(
31710500SHai-May.Chao@Sun.COM 				    soft_des_ctx->key_sched,
31810500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_FALSE);
31910500SHai-May.Chao@Sun.COM #else
32010500SHai-May.Chao@Sun.COM 			if (mechanism == DES_ECB_MECH_INFO_TYPE)
32110500SHai-May.Chao@Sun.COM 				(void) des_crunch_block(des_ctx->dc_keysched,
32210500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_FALSE);
32310500SHai-May.Chao@Sun.COM 			else
32410500SHai-May.Chao@Sun.COM 				(void) des3_crunch_block(des_ctx->dc_keysched,
32510500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_FALSE);
32610500SHai-May.Chao@Sun.COM #endif
32710500SHai-May.Chao@Sun.COM 		}
32810500SHai-May.Chao@Sun.COM 
32910500SHai-May.Chao@Sun.COM 		*pulEncryptedLen = out_len;
33010500SHai-May.Chao@Sun.COM 		break;
33110500SHai-May.Chao@Sun.COM 	}
33210500SHai-May.Chao@Sun.COM 
33310500SHai-May.Chao@Sun.COM 	case CKM_DES_CBC:
33410500SHai-May.Chao@Sun.COM 	case CKM_DES3_CBC:
33510500SHai-May.Chao@Sun.COM 	{
33610500SHai-May.Chao@Sun.COM 		crypto_data_t out;
33710500SHai-May.Chao@Sun.COM 
33810500SHai-May.Chao@Sun.COM 		out.cd_format =  CRYPTO_DATA_RAW;
33910500SHai-May.Chao@Sun.COM 		out.cd_offset = 0;
34010500SHai-May.Chao@Sun.COM 		out.cd_length = out_len;
34110500SHai-May.Chao@Sun.COM 		out.cd_raw.iov_base = (char *)out_buf;
34210500SHai-May.Chao@Sun.COM 		out.cd_raw.iov_len = out_len;
34310500SHai-May.Chao@Sun.COM 
34410500SHai-May.Chao@Sun.COM 		/* Encrypt multiple blocks of data. */
34510500SHai-May.Chao@Sun.COM 		rc = des_encrypt_contiguous_blocks(
34610500SHai-May.Chao@Sun.COM #ifndef _KERNEL
34710500SHai-May.Chao@Sun.COM 		    (des_ctx_t *)soft_des_ctx->des_cbc,
34810500SHai-May.Chao@Sun.COM #else
34910500SHai-May.Chao@Sun.COM 			des_ctx,
35010500SHai-May.Chao@Sun.COM #endif
35110500SHai-May.Chao@Sun.COM 		    (char *)in_buf, out_len, &out);
35210500SHai-May.Chao@Sun.COM 
35310500SHai-May.Chao@Sun.COM 		if (rc != 0)
35410500SHai-May.Chao@Sun.COM 			goto encrypt_failed;
35510500SHai-May.Chao@Sun.COM 
35610500SHai-May.Chao@Sun.COM 		if (rc == 0) {
35710500SHai-May.Chao@Sun.COM 			*pulEncryptedLen = out_len;
35810500SHai-May.Chao@Sun.COM 			break;
35910500SHai-May.Chao@Sun.COM 		}
36010500SHai-May.Chao@Sun.COM encrypt_failed:
36110500SHai-May.Chao@Sun.COM 		*pulEncryptedLen = 0;
36210500SHai-May.Chao@Sun.COM 
36310500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
36410500SHai-May.Chao@Sun.COM 
36510500SHai-May.Chao@Sun.COM 	}
36610500SHai-May.Chao@Sun.COM 	} /* end switch */
36710500SHai-May.Chao@Sun.COM 
36810500SHai-May.Chao@Sun.COM 	return (rv);
36910500SHai-May.Chao@Sun.COM }
37010500SHai-May.Chao@Sun.COM 
37110500SHai-May.Chao@Sun.COM /*
37210500SHai-May.Chao@Sun.COM  * fips_des_decrypt()
37310500SHai-May.Chao@Sun.COM  *
37410500SHai-May.Chao@Sun.COM  * Arguments:
37510500SHai-May.Chao@Sun.COM  *	soft_des_ctx:	pointer to DES context
37610500SHai-May.Chao@Sun.COM  *	in_buf:	pointer to the input data to be decrypted
37710500SHai-May.Chao@Sun.COM  *	ulEncryptedLen:	length of the input data
37810500SHai-May.Chao@Sun.COM  *	out_buf:	pointer to the output data
37910500SHai-May.Chao@Sun.COM  *	pulDataLen:	pointer to the length of the output data
38010500SHai-May.Chao@Sun.COM  *	mechanism:	CKM_DES_ECB, CKM_DES3_ECB, CKM_DES_CBC, CKM_DES3_CBC
38110500SHai-May.Chao@Sun.COM  *
38210500SHai-May.Chao@Sun.COM  * Description:
38310500SHai-May.Chao@Sun.COM  *      This function calls the corresponding DES low-level decrypt
38410500SHai-May.Chao@Sun.COM  *	function based on the mechanism.
38510500SHai-May.Chao@Sun.COM  *
38610500SHai-May.Chao@Sun.COM  */
38710500SHai-May.Chao@Sun.COM #ifndef _KERNEL
38810500SHai-May.Chao@Sun.COM CK_RV
fips_des_decrypt(soft_des_ctx_t * soft_des_ctx,CK_BYTE_PTR in_buf,CK_ULONG ulEncryptedLen,CK_BYTE_PTR out_buf,CK_ULONG_PTR pulDataLen,CK_MECHANISM_TYPE mechanism)38910500SHai-May.Chao@Sun.COM fips_des_decrypt(soft_des_ctx_t *soft_des_ctx, CK_BYTE_PTR in_buf,
39010500SHai-May.Chao@Sun.COM 	CK_ULONG ulEncryptedLen, CK_BYTE_PTR out_buf,
39110500SHai-May.Chao@Sun.COM 	CK_ULONG_PTR pulDataLen, CK_MECHANISM_TYPE mechanism)
39210500SHai-May.Chao@Sun.COM #else
39310500SHai-May.Chao@Sun.COM int
39410500SHai-May.Chao@Sun.COM fips_des_decrypt(des_ctx_t *des_ctx, uint8_t *in_buf,
39510500SHai-May.Chao@Sun.COM 	ulong_t ulEncryptedLen, uint8_t *out_buf,
39610500SHai-May.Chao@Sun.COM 	ulong_t *pulDataLen, des_mech_type_t mechanism)
39710500SHai-May.Chao@Sun.COM #endif
39810500SHai-May.Chao@Sun.COM {
39910500SHai-May.Chao@Sun.COM 
40010500SHai-May.Chao@Sun.COM 	CK_RV rv = CKR_OK;
40110500SHai-May.Chao@Sun.COM 	int rc = 0;
40210500SHai-May.Chao@Sun.COM 	ulong_t out_len;
40310500SHai-May.Chao@Sun.COM 
40410500SHai-May.Chao@Sun.COM 	/*
40510500SHai-May.Chao@Sun.COM 	 * DES only takes input length that is a multiple of 8 bytes
40610500SHai-May.Chao@Sun.COM 	 * with the mechanism CKM_DES<n>_ECB, CKM_DES<n>_CBC or
40710500SHai-May.Chao@Sun.COM 	 * CKM_DES<n>_CBC_PAD.
40810500SHai-May.Chao@Sun.COM 	 */
40910500SHai-May.Chao@Sun.COM 	if ((ulEncryptedLen % DES_BLOCK_LEN) != 0) {
41010500SHai-May.Chao@Sun.COM 		return (CKR_DATA_LEN_RANGE);
41110500SHai-May.Chao@Sun.COM 	}
41210500SHai-May.Chao@Sun.COM 
41310500SHai-May.Chao@Sun.COM 	/* Set output length same as input length. */
41410500SHai-May.Chao@Sun.COM 	out_len = ulEncryptedLen;
41510500SHai-May.Chao@Sun.COM 
41610500SHai-May.Chao@Sun.COM 	/*
41710500SHai-May.Chao@Sun.COM 	 * Begin Decryption.
41810500SHai-May.Chao@Sun.COM 	 */
41910500SHai-May.Chao@Sun.COM 	switch (mechanism) {
42010500SHai-May.Chao@Sun.COM 	case CKM_DES_ECB:
42110500SHai-May.Chao@Sun.COM 	case CKM_DES3_ECB:
42210500SHai-May.Chao@Sun.COM 	{
42310500SHai-May.Chao@Sun.COM 		uint8_t *tmp_inbuf;
42410500SHai-May.Chao@Sun.COM 		uint8_t *tmp_outbuf;
42510500SHai-May.Chao@Sun.COM 		ulong_t i;
42610500SHai-May.Chao@Sun.COM 
42710500SHai-May.Chao@Sun.COM 		for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
42810500SHai-May.Chao@Sun.COM 			tmp_inbuf = &in_buf[i];
42910500SHai-May.Chao@Sun.COM 			tmp_outbuf = &out_buf[i];
43010500SHai-May.Chao@Sun.COM 			/* Crunch one block of data for DES. */
43110500SHai-May.Chao@Sun.COM #ifndef _KERNEL
43210500SHai-May.Chao@Sun.COM 			if (soft_des_ctx->key_type == CKK_DES)
43310500SHai-May.Chao@Sun.COM 				(void) des_crunch_block(
43410500SHai-May.Chao@Sun.COM 				    soft_des_ctx->key_sched,
43510500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_TRUE);
43610500SHai-May.Chao@Sun.COM 			else
43710500SHai-May.Chao@Sun.COM 				(void) des3_crunch_block(
43810500SHai-May.Chao@Sun.COM 				    soft_des_ctx->key_sched,
43910500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_TRUE);
44010500SHai-May.Chao@Sun.COM #else
44110500SHai-May.Chao@Sun.COM 			if (mechanism == DES_ECB_MECH_INFO_TYPE)
44210500SHai-May.Chao@Sun.COM 				(void) des_crunch_block(des_ctx->dc_keysched,
44310500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_TRUE);
44410500SHai-May.Chao@Sun.COM 			else
44510500SHai-May.Chao@Sun.COM 				(void) des3_crunch_block(des_ctx->dc_keysched,
44610500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_TRUE);
44710500SHai-May.Chao@Sun.COM #endif
44810500SHai-May.Chao@Sun.COM 		}
44910500SHai-May.Chao@Sun.COM 
45010500SHai-May.Chao@Sun.COM 		*pulDataLen = out_len;
45110500SHai-May.Chao@Sun.COM 		break;
45210500SHai-May.Chao@Sun.COM 	}
45310500SHai-May.Chao@Sun.COM 
45410500SHai-May.Chao@Sun.COM 	case CKM_DES_CBC:
45510500SHai-May.Chao@Sun.COM 	case CKM_DES3_CBC:
45610500SHai-May.Chao@Sun.COM 	{
45710500SHai-May.Chao@Sun.COM 		crypto_data_t out;
45810500SHai-May.Chao@Sun.COM 		out.cd_format =  CRYPTO_DATA_RAW;
45910500SHai-May.Chao@Sun.COM 		out.cd_offset = 0;
46010500SHai-May.Chao@Sun.COM 		out.cd_length = out_len;
46110500SHai-May.Chao@Sun.COM 		out.cd_raw.iov_base = (char *)out_buf;
46210500SHai-May.Chao@Sun.COM 		out.cd_raw.iov_len = out_len;
46310500SHai-May.Chao@Sun.COM 
46410500SHai-May.Chao@Sun.COM 		/* Decrypt multiple blocks of data. */
46510500SHai-May.Chao@Sun.COM 		rc = des_decrypt_contiguous_blocks(
46610500SHai-May.Chao@Sun.COM #ifndef _KERNEL
46710500SHai-May.Chao@Sun.COM 		    (des_ctx_t *)soft_des_ctx->des_cbc,
46810500SHai-May.Chao@Sun.COM #else
46910500SHai-May.Chao@Sun.COM 		    des_ctx,
47010500SHai-May.Chao@Sun.COM #endif
47110500SHai-May.Chao@Sun.COM 		    (char *)in_buf, out_len, &out);
47210500SHai-May.Chao@Sun.COM 
47310500SHai-May.Chao@Sun.COM 		if (rc != 0)
47410500SHai-May.Chao@Sun.COM 			goto decrypt_failed;
47510500SHai-May.Chao@Sun.COM 
47610500SHai-May.Chao@Sun.COM 		*pulDataLen = out_len;
47710500SHai-May.Chao@Sun.COM 
47810500SHai-May.Chao@Sun.COM 		if (rc == 0)
47910500SHai-May.Chao@Sun.COM 			break;
48010500SHai-May.Chao@Sun.COM decrypt_failed:
48110500SHai-May.Chao@Sun.COM 		*pulDataLen = 0;
48210500SHai-May.Chao@Sun.COM 
48310500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
48410500SHai-May.Chao@Sun.COM 
48510500SHai-May.Chao@Sun.COM 	}
48610500SHai-May.Chao@Sun.COM 	} /* end switch */
48710500SHai-May.Chao@Sun.COM 
48810500SHai-May.Chao@Sun.COM 	return (rv);
48910500SHai-May.Chao@Sun.COM }
49010500SHai-May.Chao@Sun.COM 
49110500SHai-May.Chao@Sun.COM /*
49210500SHai-May.Chao@Sun.COM  * DES3 Power-On SelfTest(s).
49310500SHai-May.Chao@Sun.COM  */
49410500SHai-May.Chao@Sun.COM int
fips_des3_post(void)49510500SHai-May.Chao@Sun.COM fips_des3_post(void)
49610500SHai-May.Chao@Sun.COM {
49710500SHai-May.Chao@Sun.COM 
49810500SHai-May.Chao@Sun.COM 	/* DES3 Known Key. */
49910500SHai-May.Chao@Sun.COM 	static uint8_t des3_known_key[] = { "ANSI Triple-DES Key Data" };
50010500SHai-May.Chao@Sun.COM 
50110500SHai-May.Chao@Sun.COM 	/* DES3-CBC Known Initialization Vector (64-bits). */
50210500SHai-May.Chao@Sun.COM 	static uint8_t des3_cbc_known_iv[] = { "Security" };
50310500SHai-May.Chao@Sun.COM 
50410500SHai-May.Chao@Sun.COM 	/* DES3 Known Plaintext (64-bits). */
50510500SHai-May.Chao@Sun.COM 	static uint8_t des3_ecb_known_plaintext[] = { "Solaris!" };
50610500SHai-May.Chao@Sun.COM 	static uint8_t des3_cbc_known_plaintext[] = { "Solaris!" };
50710500SHai-May.Chao@Sun.COM 
50810500SHai-May.Chao@Sun.COM 	/* DES3 Known Ciphertext (64-bits). */
50910500SHai-May.Chao@Sun.COM 	static uint8_t des3_ecb_known_ciphertext[] = {
51010500SHai-May.Chao@Sun.COM 		0x17, 0x0d, 0x1f, 0x13, 0xd3, 0xa0, 0x3a, 0x63
51110500SHai-May.Chao@Sun.COM 	};
51210500SHai-May.Chao@Sun.COM 
51310500SHai-May.Chao@Sun.COM 	static uint8_t des3_cbc_known_ciphertext[] = {
51410500SHai-May.Chao@Sun.COM 		0x7f, 0x62, 0x44, 0xb3, 0xf8, 0x77, 0xf8, 0xf8
51510500SHai-May.Chao@Sun.COM 	};
51610500SHai-May.Chao@Sun.COM 
51710500SHai-May.Chao@Sun.COM 	/* DES3 variables. */
51810500SHai-May.Chao@Sun.COM 	uint8_t des3_computed_ciphertext[FIPS_DES3_ENCRYPT_LENGTH];
51910500SHai-May.Chao@Sun.COM 	uint8_t des3_computed_plaintext[FIPS_DES3_DECRYPT_LENGTH];
52010500SHai-May.Chao@Sun.COM 
52110500SHai-May.Chao@Sun.COM #ifdef _KERNEL
52210500SHai-May.Chao@Sun.COM 	des_ctx_t *des3_context;
52310500SHai-May.Chao@Sun.COM #else
52410500SHai-May.Chao@Sun.COM 	soft_des_ctx_t *des3_context;
52510500SHai-May.Chao@Sun.COM #endif
52610500SHai-May.Chao@Sun.COM 
52710500SHai-May.Chao@Sun.COM 	ulong_t des3_bytes_encrypted;
52810500SHai-May.Chao@Sun.COM 	ulong_t des3_bytes_decrypted;
52910500SHai-May.Chao@Sun.COM 	int rv;
53010500SHai-May.Chao@Sun.COM 
53110500SHai-May.Chao@Sun.COM 	/*
53210500SHai-May.Chao@Sun.COM 	 * DES3 ECB Known Answer Encryption Test
53310500SHai-May.Chao@Sun.COM 	 */
53410500SHai-May.Chao@Sun.COM #ifdef _KERNEL
53510500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, NULL,
53610500SHai-May.Chao@Sun.COM 	    DES3_ECB_MECH_INFO_TYPE);
53710500SHai-May.Chao@Sun.COM #else
53810500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, NULL,
53910500SHai-May.Chao@Sun.COM 	    CKK_DES3, CKM_DES3_ECB);
54010500SHai-May.Chao@Sun.COM #endif
54110500SHai-May.Chao@Sun.COM 
54210500SHai-May.Chao@Sun.COM 	if (des3_context == NULL)
54310500SHai-May.Chao@Sun.COM 		return (CKR_HOST_MEMORY);
54410500SHai-May.Chao@Sun.COM 
54510500SHai-May.Chao@Sun.COM #ifdef _KERNEL
54610500SHai-May.Chao@Sun.COM 	rv = fips_des_encrypt(des3_context, des3_ecb_known_plaintext,
54710500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
54810500SHai-May.Chao@Sun.COM 	    &des3_bytes_encrypted, DES3_ECB_MECH_INFO_TYPE);
54910500SHai-May.Chao@Sun.COM #else
55010500SHai-May.Chao@Sun.COM 	rv = fips_des_encrypt(des3_context, des3_ecb_known_plaintext,
55110500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
55210500SHai-May.Chao@Sun.COM 	    &des3_bytes_encrypted, CKM_DES3_ECB);
55310500SHai-May.Chao@Sun.COM #endif
55410500SHai-May.Chao@Sun.COM 
55510500SHai-May.Chao@Sun.COM 	fips_des_free_context(des3_context);
55610500SHai-May.Chao@Sun.COM 
55710500SHai-May.Chao@Sun.COM 	if ((rv != CRYPTO_SUCCESS) ||
55810500SHai-May.Chao@Sun.COM 	    (des3_bytes_encrypted != FIPS_DES3_ENCRYPT_LENGTH) ||
55910500SHai-May.Chao@Sun.COM 	    (memcmp(des3_computed_ciphertext, des3_ecb_known_ciphertext,
56010500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH) != 0))
56110500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
56210500SHai-May.Chao@Sun.COM 
56310500SHai-May.Chao@Sun.COM 	/*
56410500SHai-May.Chao@Sun.COM 	 * DES3 ECB Known Answer Decryption Test
56510500SHai-May.Chao@Sun.COM 	 */
56610500SHai-May.Chao@Sun.COM #ifdef _KERNEL
56710500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, NULL,
56810500SHai-May.Chao@Sun.COM 	    DES3_ECB_MECH_INFO_TYPE);
56910500SHai-May.Chao@Sun.COM #else
57010500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, NULL,
57110500SHai-May.Chao@Sun.COM 	    CKK_DES3, CKM_DES3_ECB);
57210500SHai-May.Chao@Sun.COM #endif
57310500SHai-May.Chao@Sun.COM 
57410500SHai-May.Chao@Sun.COM 	if (des3_context == NULL)
57510500SHai-May.Chao@Sun.COM 		return (CKR_HOST_MEMORY);
57610500SHai-May.Chao@Sun.COM 
57710500SHai-May.Chao@Sun.COM #ifdef _KERNEL
57810500SHai-May.Chao@Sun.COM 	rv = fips_des_decrypt(des3_context, des3_ecb_known_ciphertext,
57910500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
58010500SHai-May.Chao@Sun.COM 	    &des3_bytes_decrypted, DES3_ECB_MECH_INFO_TYPE);
58110500SHai-May.Chao@Sun.COM #else
58210500SHai-May.Chao@Sun.COM 	rv = fips_des_decrypt(des3_context, des3_ecb_known_ciphertext,
58310500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
58410500SHai-May.Chao@Sun.COM 	    &des3_bytes_decrypted, CKM_DES3_ECB);
58510500SHai-May.Chao@Sun.COM #endif
58610500SHai-May.Chao@Sun.COM 
58710500SHai-May.Chao@Sun.COM 	fips_des_free_context(des3_context);
58810500SHai-May.Chao@Sun.COM 
58910500SHai-May.Chao@Sun.COM 	if ((rv != CRYPTO_SUCCESS) ||
59010500SHai-May.Chao@Sun.COM 	    (des3_bytes_decrypted != FIPS_DES3_DECRYPT_LENGTH) ||
59110500SHai-May.Chao@Sun.COM 	    (memcmp(des3_computed_plaintext, des3_ecb_known_plaintext,
59210500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH) != 0))
59310500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
59410500SHai-May.Chao@Sun.COM 
59510500SHai-May.Chao@Sun.COM 	/*
59610500SHai-May.Chao@Sun.COM 	 * DES3 CBC Known Answer Encryption Test
59710500SHai-May.Chao@Sun.COM 	 */
59810500SHai-May.Chao@Sun.COM #ifdef _KERNEL
59910500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
60010500SHai-May.Chao@Sun.COM 	    DES3_CBC_MECH_INFO_TYPE);
60110500SHai-May.Chao@Sun.COM #else
60210500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
60310500SHai-May.Chao@Sun.COM 	    CKK_DES3, CKM_DES3_CBC);
60410500SHai-May.Chao@Sun.COM #endif
60510500SHai-May.Chao@Sun.COM 
60610500SHai-May.Chao@Sun.COM 	if (des3_context == NULL)
60710500SHai-May.Chao@Sun.COM 		return (CKR_HOST_MEMORY);
60810500SHai-May.Chao@Sun.COM 
60910500SHai-May.Chao@Sun.COM #ifdef _KERNEL
61010500SHai-May.Chao@Sun.COM 	rv = fips_des_encrypt(des3_context, des3_cbc_known_plaintext,
61110500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
61210500SHai-May.Chao@Sun.COM 	    &des3_bytes_encrypted, DES3_CBC_MECH_INFO_TYPE);
61310500SHai-May.Chao@Sun.COM #else
61410500SHai-May.Chao@Sun.COM 	rv = fips_des_encrypt(des3_context, des3_cbc_known_plaintext,
61510500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
61610500SHai-May.Chao@Sun.COM 	    &des3_bytes_encrypted, CKM_DES3_CBC);
61710500SHai-May.Chao@Sun.COM #endif
61810500SHai-May.Chao@Sun.COM 
61910500SHai-May.Chao@Sun.COM 	fips_des_free_context(des3_context);
62010500SHai-May.Chao@Sun.COM 
62110500SHai-May.Chao@Sun.COM 	if ((rv != CRYPTO_SUCCESS) ||
62210500SHai-May.Chao@Sun.COM 	    (des3_bytes_encrypted != FIPS_DES3_ENCRYPT_LENGTH) ||
62310500SHai-May.Chao@Sun.COM 	    (memcmp(des3_computed_ciphertext, des3_cbc_known_ciphertext,
62410500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH) != 0))
62510500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
62610500SHai-May.Chao@Sun.COM 
62710500SHai-May.Chao@Sun.COM 	/*
62810500SHai-May.Chao@Sun.COM 	 * DES3 CBC Known Answer Decryption Test
62910500SHai-May.Chao@Sun.COM 	 */
63010500SHai-May.Chao@Sun.COM #ifdef _KERNEL
63110500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
63210500SHai-May.Chao@Sun.COM 	    DES3_CBC_MECH_INFO_TYPE);
63310500SHai-May.Chao@Sun.COM #else
63410500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
63510500SHai-May.Chao@Sun.COM 	    CKK_DES3, CKM_DES3_CBC);
63610500SHai-May.Chao@Sun.COM #endif
63710500SHai-May.Chao@Sun.COM 
63810500SHai-May.Chao@Sun.COM 	if (des3_context == NULL)
63910500SHai-May.Chao@Sun.COM 		return (CKR_HOST_MEMORY);
64010500SHai-May.Chao@Sun.COM 
64110500SHai-May.Chao@Sun.COM #ifdef _KERNEL
64210500SHai-May.Chao@Sun.COM 	rv = fips_des_decrypt(des3_context, des3_cbc_known_ciphertext,
64310500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
64410500SHai-May.Chao@Sun.COM 	    &des3_bytes_decrypted, DES3_CBC_MECH_INFO_TYPE);
64510500SHai-May.Chao@Sun.COM #else
64610500SHai-May.Chao@Sun.COM 	rv = fips_des_decrypt(des3_context, des3_cbc_known_ciphertext,
64710500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
64810500SHai-May.Chao@Sun.COM 	    &des3_bytes_decrypted, CKM_DES3_CBC);
64910500SHai-May.Chao@Sun.COM #endif
65010500SHai-May.Chao@Sun.COM 
65110500SHai-May.Chao@Sun.COM 	fips_des_free_context(des3_context);
65210500SHai-May.Chao@Sun.COM 
65310500SHai-May.Chao@Sun.COM 	if ((rv != CRYPTO_SUCCESS) ||
65410500SHai-May.Chao@Sun.COM 	    (des3_bytes_decrypted != FIPS_DES3_DECRYPT_LENGTH) ||
65510500SHai-May.Chao@Sun.COM 	    (memcmp(des3_computed_plaintext, des3_cbc_known_plaintext,
65610500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH) != 0))
65710500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
65810500SHai-May.Chao@Sun.COM 
65910500SHai-May.Chao@Sun.COM 	return (CKR_OK);
66010500SHai-May.Chao@Sun.COM }
661