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