xref: /onnv-gate/usr/src/common/crypto/fips/fips_des_util.c (revision 10500:a10fbcfc2f21)
1*10500SHai-May.Chao@Sun.COM /*
2*10500SHai-May.Chao@Sun.COM  * CDDL HEADER START
3*10500SHai-May.Chao@Sun.COM  *
4*10500SHai-May.Chao@Sun.COM  * The contents of this file are subject to the terms of the
5*10500SHai-May.Chao@Sun.COM  * Common Development and Distribution License (the "License").
6*10500SHai-May.Chao@Sun.COM  * You may not use this file except in compliance with the License.
7*10500SHai-May.Chao@Sun.COM  *
8*10500SHai-May.Chao@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10500SHai-May.Chao@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*10500SHai-May.Chao@Sun.COM  * See the License for the specific language governing permissions
11*10500SHai-May.Chao@Sun.COM  * and limitations under the License.
12*10500SHai-May.Chao@Sun.COM  *
13*10500SHai-May.Chao@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*10500SHai-May.Chao@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10500SHai-May.Chao@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*10500SHai-May.Chao@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*10500SHai-May.Chao@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*10500SHai-May.Chao@Sun.COM  *
19*10500SHai-May.Chao@Sun.COM  * CDDL HEADER END
20*10500SHai-May.Chao@Sun.COM  */
21*10500SHai-May.Chao@Sun.COM /*
22*10500SHai-May.Chao@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*10500SHai-May.Chao@Sun.COM  * Use is subject to license terms.
24*10500SHai-May.Chao@Sun.COM  */
25*10500SHai-May.Chao@Sun.COM 
26*10500SHai-May.Chao@Sun.COM #include <sys/types.h>
27*10500SHai-May.Chao@Sun.COM #include <sys/errno.h>
28*10500SHai-May.Chao@Sun.COM #include <sys/kmem.h>
29*10500SHai-May.Chao@Sun.COM #include <sys/systm.h>
30*10500SHai-May.Chao@Sun.COM #include <sys/crypto/common.h>
31*10500SHai-May.Chao@Sun.COM #include <sys/cmn_err.h>
32*10500SHai-May.Chao@Sun.COM #include <modes/modes.h>
33*10500SHai-May.Chao@Sun.COM #define	_DES_FIPS_POST
34*10500SHai-May.Chao@Sun.COM #ifndef _KERNEL
35*10500SHai-May.Chao@Sun.COM #include <stdlib.h>
36*10500SHai-May.Chao@Sun.COM #include <string.h>
37*10500SHai-May.Chao@Sun.COM #include <strings.h>
38*10500SHai-May.Chao@Sun.COM #include <stdio.h>
39*10500SHai-May.Chao@Sun.COM #include <security/cryptoki.h>
40*10500SHai-May.Chao@Sun.COM #include <cryptoutil.h>
41*10500SHai-May.Chao@Sun.COM #include "softCrypt.h"
42*10500SHai-May.Chao@Sun.COM #else
43*10500SHai-May.Chao@Sun.COM #define	_DES_IMPL
44*10500SHai-May.Chao@Sun.COM #include <des/des_impl.h>
45*10500SHai-May.Chao@Sun.COM #endif
46*10500SHai-May.Chao@Sun.COM 
47*10500SHai-May.Chao@Sun.COM #ifndef _KERNEL
48*10500SHai-May.Chao@Sun.COM /*
49*10500SHai-May.Chao@Sun.COM  * Allocate context for the DES encryption or decryption operation, and
50*10500SHai-May.Chao@Sun.COM  * generate DES or DES3 key schedule to speed up the operation.
51*10500SHai-May.Chao@Sun.COM  */
52*10500SHai-May.Chao@Sun.COM soft_des_ctx_t *
53*10500SHai-May.Chao@Sun.COM des_build_context(uint8_t *key, uint8_t *iv, CK_KEY_TYPE key_type,
54*10500SHai-May.Chao@Sun.COM 	CK_MECHANISM_TYPE mechanism)
55*10500SHai-May.Chao@Sun.COM {
56*10500SHai-May.Chao@Sun.COM 
57*10500SHai-May.Chao@Sun.COM 	size_t size;
58*10500SHai-May.Chao@Sun.COM 	soft_des_ctx_t *soft_des_ctx;
59*10500SHai-May.Chao@Sun.COM 
60*10500SHai-May.Chao@Sun.COM 	soft_des_ctx = calloc(1, sizeof (soft_des_ctx_t));
61*10500SHai-May.Chao@Sun.COM 	if (soft_des_ctx == NULL) {
62*10500SHai-May.Chao@Sun.COM 		return (NULL);
63*10500SHai-May.Chao@Sun.COM 	}
64*10500SHai-May.Chao@Sun.COM 
65*10500SHai-May.Chao@Sun.COM 	/* Allocate key schedule for DES or DES3 based on key type. */
66*10500SHai-May.Chao@Sun.COM 	if (key_type == CKK_DES) {
67*10500SHai-May.Chao@Sun.COM 		soft_des_ctx->key_sched = des_alloc_keysched(&size, DES, 0);
68*10500SHai-May.Chao@Sun.COM 		if (soft_des_ctx->key_sched == NULL) {
69*10500SHai-May.Chao@Sun.COM 			free(soft_des_ctx);
70*10500SHai-May.Chao@Sun.COM 			return (NULL);
71*10500SHai-May.Chao@Sun.COM 		}
72*10500SHai-May.Chao@Sun.COM 		des_init_keysched(key, DES, soft_des_ctx->key_sched);
73*10500SHai-May.Chao@Sun.COM 	} else {
74*10500SHai-May.Chao@Sun.COM 		soft_des_ctx->key_sched = des_alloc_keysched(&size, DES3, 0);
75*10500SHai-May.Chao@Sun.COM 		if (soft_des_ctx->key_sched == NULL) {
76*10500SHai-May.Chao@Sun.COM 			free(soft_des_ctx);
77*10500SHai-May.Chao@Sun.COM 			return (NULL);
78*10500SHai-May.Chao@Sun.COM 		}
79*10500SHai-May.Chao@Sun.COM 		des_init_keysched(key, DES3, soft_des_ctx->key_sched);
80*10500SHai-May.Chao@Sun.COM 	}
81*10500SHai-May.Chao@Sun.COM 
82*10500SHai-May.Chao@Sun.COM 	soft_des_ctx->keysched_len = size;
83*10500SHai-May.Chao@Sun.COM 	soft_des_ctx->key_type = key_type;
84*10500SHai-May.Chao@Sun.COM 
85*10500SHai-May.Chao@Sun.COM 	if ((mechanism == CKM_DES_CBC) || (mechanism == CKM_DES3_CBC)) {
86*10500SHai-May.Chao@Sun.COM 		/* Save Initialization Vector (IV) in the context. */
87*10500SHai-May.Chao@Sun.COM 		(void) memcpy(soft_des_ctx->ivec, iv, DES_BLOCK_LEN);
88*10500SHai-May.Chao@Sun.COM 
89*10500SHai-May.Chao@Sun.COM 		/* Allocate a context for DES cipher-block chaining. */
90*10500SHai-May.Chao@Sun.COM 		soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
91*10500SHai-May.Chao@Sun.COM 		    soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
92*10500SHai-May.Chao@Sun.COM 		    soft_des_ctx->ivec, soft_des_ctx->key_type);
93*10500SHai-May.Chao@Sun.COM 
94*10500SHai-May.Chao@Sun.COM 		if (soft_des_ctx->des_cbc == NULL) {
95*10500SHai-May.Chao@Sun.COM 			bzero(soft_des_ctx->key_sched,
96*10500SHai-May.Chao@Sun.COM 			    soft_des_ctx->keysched_len);
97*10500SHai-May.Chao@Sun.COM 			free(soft_des_ctx->key_sched);
98*10500SHai-May.Chao@Sun.COM 			return (NULL);
99*10500SHai-May.Chao@Sun.COM 		}
100*10500SHai-May.Chao@Sun.COM 	}
101*10500SHai-May.Chao@Sun.COM 
102*10500SHai-May.Chao@Sun.COM 	return (soft_des_ctx);
103*10500SHai-May.Chao@Sun.COM }
104*10500SHai-May.Chao@Sun.COM 
105*10500SHai-May.Chao@Sun.COM /*
106*10500SHai-May.Chao@Sun.COM  * Free the DES context.
107*10500SHai-May.Chao@Sun.COM  */
108*10500SHai-May.Chao@Sun.COM void
109*10500SHai-May.Chao@Sun.COM fips_des_free_context(soft_des_ctx_t *soft_des_ctx)
110*10500SHai-May.Chao@Sun.COM {
111*10500SHai-May.Chao@Sun.COM 
112*10500SHai-May.Chao@Sun.COM 	des_ctx_t *des_ctx;
113*10500SHai-May.Chao@Sun.COM 
114*10500SHai-May.Chao@Sun.COM 	des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
115*10500SHai-May.Chao@Sun.COM 	if (des_ctx != NULL) {
116*10500SHai-May.Chao@Sun.COM 		bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len);
117*10500SHai-May.Chao@Sun.COM 		free(soft_des_ctx->des_cbc);
118*10500SHai-May.Chao@Sun.COM 	}
119*10500SHai-May.Chao@Sun.COM 
120*10500SHai-May.Chao@Sun.COM 	bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
121*10500SHai-May.Chao@Sun.COM 	free(soft_des_ctx->key_sched);
122*10500SHai-May.Chao@Sun.COM 	free(soft_des_ctx);
123*10500SHai-May.Chao@Sun.COM }
124*10500SHai-May.Chao@Sun.COM #else
125*10500SHai-May.Chao@Sun.COM 
126*10500SHai-May.Chao@Sun.COM static void
127*10500SHai-May.Chao@Sun.COM des_copy_block64(uint8_t *in, uint64_t *out)
128*10500SHai-May.Chao@Sun.COM {
129*10500SHai-May.Chao@Sun.COM 	if (IS_P2ALIGNED(in, sizeof (uint64_t))) {
130*10500SHai-May.Chao@Sun.COM 		/* LINTED: pointer alignment */
131*10500SHai-May.Chao@Sun.COM 		out[0] = *(uint64_t *)&in[0];
132*10500SHai-May.Chao@Sun.COM 	} else {
133*10500SHai-May.Chao@Sun.COM 		uint64_t tmp64;
134*10500SHai-May.Chao@Sun.COM 
135*10500SHai-May.Chao@Sun.COM #ifdef _BIG_ENDIAN
136*10500SHai-May.Chao@Sun.COM 		tmp64 = (((uint64_t)in[0] << 56) |
137*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[1] << 48) |
138*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[2] << 40) |
139*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[3] << 32) |
140*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[4] << 24) |
141*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[5] << 16) |
142*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[6] << 8) |
143*10500SHai-May.Chao@Sun.COM 		    (uint64_t)in[7]);
144*10500SHai-May.Chao@Sun.COM #else
145*10500SHai-May.Chao@Sun.COM 		tmp64 = (((uint64_t)in[7] << 56) |
146*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[6] << 48) |
147*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[5] << 40) |
148*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[4] << 32) |
149*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[3] << 24) |
150*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[2] << 16) |
151*10500SHai-May.Chao@Sun.COM 		    ((uint64_t)in[1] << 8) |
152*10500SHai-May.Chao@Sun.COM 		    (uint64_t)in[0]);
153*10500SHai-May.Chao@Sun.COM #endif /* _BIG_ENDIAN */
154*10500SHai-May.Chao@Sun.COM 
155*10500SHai-May.Chao@Sun.COM 		out[0] = tmp64;
156*10500SHai-May.Chao@Sun.COM 	}
157*10500SHai-May.Chao@Sun.COM }
158*10500SHai-May.Chao@Sun.COM 
159*10500SHai-May.Chao@Sun.COM des_ctx_t *
160*10500SHai-May.Chao@Sun.COM des_build_context(uint8_t *key, uint8_t *iv,
161*10500SHai-May.Chao@Sun.COM 	des_mech_type_t mech_type)
162*10500SHai-May.Chao@Sun.COM {
163*10500SHai-May.Chao@Sun.COM 	int rv = CRYPTO_SUCCESS;
164*10500SHai-May.Chao@Sun.COM 	void *keysched;
165*10500SHai-May.Chao@Sun.COM 	size_t size;
166*10500SHai-May.Chao@Sun.COM 	des_ctx_t *des_ctx = NULL;
167*10500SHai-May.Chao@Sun.COM 	des_strength_t strength;
168*10500SHai-May.Chao@Sun.COM 
169*10500SHai-May.Chao@Sun.COM 	switch (mech_type) {
170*10500SHai-May.Chao@Sun.COM 	case DES_ECB_MECH_INFO_TYPE:
171*10500SHai-May.Chao@Sun.COM 		des_ctx = ecb_alloc_ctx(KM_SLEEP);
172*10500SHai-May.Chao@Sun.COM 		/* FALLTHRU */
173*10500SHai-May.Chao@Sun.COM 	case DES_CBC_MECH_INFO_TYPE:
174*10500SHai-May.Chao@Sun.COM 		strength = DES;
175*10500SHai-May.Chao@Sun.COM 		if (des_ctx == NULL)
176*10500SHai-May.Chao@Sun.COM 			des_ctx = cbc_alloc_ctx(KM_SLEEP);
177*10500SHai-May.Chao@Sun.COM 		break;
178*10500SHai-May.Chao@Sun.COM 	case DES3_ECB_MECH_INFO_TYPE:
179*10500SHai-May.Chao@Sun.COM 		des_ctx = ecb_alloc_ctx(KM_SLEEP);
180*10500SHai-May.Chao@Sun.COM 		/* FALLTHRU */
181*10500SHai-May.Chao@Sun.COM 	case DES3_CBC_MECH_INFO_TYPE:
182*10500SHai-May.Chao@Sun.COM 		strength = DES3;
183*10500SHai-May.Chao@Sun.COM 		if (des_ctx == NULL)
184*10500SHai-May.Chao@Sun.COM 			des_ctx = cbc_alloc_ctx(KM_SLEEP);
185*10500SHai-May.Chao@Sun.COM 		break;
186*10500SHai-May.Chao@Sun.COM 	default:
187*10500SHai-May.Chao@Sun.COM 		return (NULL);
188*10500SHai-May.Chao@Sun.COM 	}
189*10500SHai-May.Chao@Sun.COM 
190*10500SHai-May.Chao@Sun.COM 	if ((keysched = des_alloc_keysched(&size, strength,
191*10500SHai-May.Chao@Sun.COM 	    KM_SLEEP)) == NULL)
192*10500SHai-May.Chao@Sun.COM 		return (NULL);
193*10500SHai-May.Chao@Sun.COM 
194*10500SHai-May.Chao@Sun.COM 	/*
195*10500SHai-May.Chao@Sun.COM 	 * Initialize key schedule.
196*10500SHai-May.Chao@Sun.COM 	 * Key length is stored in the key.
197*10500SHai-May.Chao@Sun.COM 	 */
198*10500SHai-May.Chao@Sun.COM 	des_init_keysched(key, strength, keysched);
199*10500SHai-May.Chao@Sun.COM 
200*10500SHai-May.Chao@Sun.COM 	des_ctx->dc_flags |= PROVIDER_OWNS_KEY_SCHEDULE;
201*10500SHai-May.Chao@Sun.COM 	des_ctx->dc_keysched_len = size;
202*10500SHai-May.Chao@Sun.COM 	des_ctx->dc_keysched = keysched;
203*10500SHai-May.Chao@Sun.COM 
204*10500SHai-May.Chao@Sun.COM 	if (strength == DES3) {
205*10500SHai-May.Chao@Sun.COM 		des_ctx->dc_flags |= DES3_STRENGTH;
206*10500SHai-May.Chao@Sun.COM 	}
207*10500SHai-May.Chao@Sun.COM 
208*10500SHai-May.Chao@Sun.COM 	switch (mech_type) {
209*10500SHai-May.Chao@Sun.COM 	case DES_CBC_MECH_INFO_TYPE:
210*10500SHai-May.Chao@Sun.COM 	case DES3_CBC_MECH_INFO_TYPE:
211*10500SHai-May.Chao@Sun.COM 		/* Save Initialization Vector (IV) in the context. */
212*10500SHai-May.Chao@Sun.COM 		rv = cbc_init_ctx((cbc_ctx_t *)des_ctx, (char *)iv,
213*10500SHai-May.Chao@Sun.COM 		    DES_BLOCK_LEN, DES_BLOCK_LEN, des_copy_block64);
214*10500SHai-May.Chao@Sun.COM 		break;
215*10500SHai-May.Chao@Sun.COM 	case DES_ECB_MECH_INFO_TYPE:
216*10500SHai-May.Chao@Sun.COM 	case DES3_ECB_MECH_INFO_TYPE:
217*10500SHai-May.Chao@Sun.COM 		des_ctx->dc_flags |= ECB_MODE;
218*10500SHai-May.Chao@Sun.COM 	}
219*10500SHai-May.Chao@Sun.COM 
220*10500SHai-May.Chao@Sun.COM 	if (rv != CRYPTO_SUCCESS) {
221*10500SHai-May.Chao@Sun.COM 		if (des_ctx->dc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
222*10500SHai-May.Chao@Sun.COM 			bzero(keysched, size);
223*10500SHai-May.Chao@Sun.COM 			kmem_free(keysched, size);
224*10500SHai-May.Chao@Sun.COM 		}
225*10500SHai-May.Chao@Sun.COM 	}
226*10500SHai-May.Chao@Sun.COM 
227*10500SHai-May.Chao@Sun.COM 	return (des_ctx);
228*10500SHai-May.Chao@Sun.COM }
229*10500SHai-May.Chao@Sun.COM 
230*10500SHai-May.Chao@Sun.COM void
231*10500SHai-May.Chao@Sun.COM fips_des_free_context(des_ctx_t *des_ctx)
232*10500SHai-May.Chao@Sun.COM {
233*10500SHai-May.Chao@Sun.COM 
234*10500SHai-May.Chao@Sun.COM 	if (des_ctx != NULL) {
235*10500SHai-May.Chao@Sun.COM 		if (des_ctx->dc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
236*10500SHai-May.Chao@Sun.COM 			ASSERT(des_ctx->dc_keysched_len != 0);
237*10500SHai-May.Chao@Sun.COM 			bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len);
238*10500SHai-May.Chao@Sun.COM 			kmem_free(des_ctx->dc_keysched,
239*10500SHai-May.Chao@Sun.COM 			    des_ctx->dc_keysched_len);
240*10500SHai-May.Chao@Sun.COM 		}
241*10500SHai-May.Chao@Sun.COM 	}
242*10500SHai-May.Chao@Sun.COM }
243*10500SHai-May.Chao@Sun.COM #endif
244*10500SHai-May.Chao@Sun.COM 
245*10500SHai-May.Chao@Sun.COM /*
246*10500SHai-May.Chao@Sun.COM  * fips_des_encrypt()
247*10500SHai-May.Chao@Sun.COM  *
248*10500SHai-May.Chao@Sun.COM  * Arguments:
249*10500SHai-May.Chao@Sun.COM  *	soft_des_ctx:	pointer to DES context
250*10500SHai-May.Chao@Sun.COM  *	in_buf:		pointer to the input data to be encrypted
251*10500SHai-May.Chao@Sun.COM  *	ulDataLen:	length of the input data
252*10500SHai-May.Chao@Sun.COM  *	out_buf:	pointer to the output data after encryption
253*10500SHai-May.Chao@Sun.COM  *	pulEncryptedLen: pointer to the length of the output data
254*10500SHai-May.Chao@Sun.COM  *	mechanism:	CKM_DES_ECB, CKM_DES3_ECB, CKM_DES_CBC, CKM_DES3_CBC
255*10500SHai-May.Chao@Sun.COM  *
256*10500SHai-May.Chao@Sun.COM  * Description:
257*10500SHai-May.Chao@Sun.COM  *	This function calls the corresponding DES low-level encrypt
258*10500SHai-May.Chao@Sun.COM  *	routine based on the mechanism.
259*10500SHai-May.Chao@Sun.COM  *
260*10500SHai-May.Chao@Sun.COM  */
261*10500SHai-May.Chao@Sun.COM #ifndef _KERNEL
262*10500SHai-May.Chao@Sun.COM CK_RV
263*10500SHai-May.Chao@Sun.COM fips_des_encrypt(soft_des_ctx_t *soft_des_ctx, CK_BYTE_PTR in_buf,
264*10500SHai-May.Chao@Sun.COM 	CK_ULONG ulDataLen, CK_BYTE_PTR out_buf,
265*10500SHai-May.Chao@Sun.COM 	CK_ULONG_PTR pulEncryptedLen, CK_MECHANISM_TYPE mechanism)
266*10500SHai-May.Chao@Sun.COM #else
267*10500SHai-May.Chao@Sun.COM int
268*10500SHai-May.Chao@Sun.COM fips_des_encrypt(des_ctx_t *des_ctx, uint8_t *in_buf,
269*10500SHai-May.Chao@Sun.COM 	ulong_t ulDataLen, uint8_t *out_buf,
270*10500SHai-May.Chao@Sun.COM 	ulong_t *pulEncryptedLen, des_mech_type_t mechanism)
271*10500SHai-May.Chao@Sun.COM #endif
272*10500SHai-May.Chao@Sun.COM {
273*10500SHai-May.Chao@Sun.COM 
274*10500SHai-May.Chao@Sun.COM 	CK_RV rv = CKR_OK;
275*10500SHai-May.Chao@Sun.COM 	int rc = 0;
276*10500SHai-May.Chao@Sun.COM 	ulong_t out_len;
277*10500SHai-May.Chao@Sun.COM 
278*10500SHai-May.Chao@Sun.COM 	/*
279*10500SHai-May.Chao@Sun.COM 	 * DES only takes input length that is a multiple of blocksize
280*10500SHai-May.Chao@Sun.COM 	 * with the mechanism CKM_DES<n>_ECB or CKM_DES<n>_CBC.
281*10500SHai-May.Chao@Sun.COM 	 */
282*10500SHai-May.Chao@Sun.COM 	if ((ulDataLen % DES_BLOCK_LEN) != 0) {
283*10500SHai-May.Chao@Sun.COM 		return (CKR_DATA_LEN_RANGE);
284*10500SHai-May.Chao@Sun.COM 	}
285*10500SHai-May.Chao@Sun.COM 
286*10500SHai-May.Chao@Sun.COM 	/*
287*10500SHai-May.Chao@Sun.COM 	 * For non-padding mode, the output length will
288*10500SHai-May.Chao@Sun.COM 	 * be same as the input length.
289*10500SHai-May.Chao@Sun.COM 	 */
290*10500SHai-May.Chao@Sun.COM 	out_len = ulDataLen;
291*10500SHai-May.Chao@Sun.COM 
292*10500SHai-May.Chao@Sun.COM 	/*
293*10500SHai-May.Chao@Sun.COM 	 * Begin Encryption now.
294*10500SHai-May.Chao@Sun.COM 	 */
295*10500SHai-May.Chao@Sun.COM 	switch (mechanism) {
296*10500SHai-May.Chao@Sun.COM 	case CKM_DES_ECB:
297*10500SHai-May.Chao@Sun.COM 	case CKM_DES3_ECB:
298*10500SHai-May.Chao@Sun.COM 	{
299*10500SHai-May.Chao@Sun.COM 
300*10500SHai-May.Chao@Sun.COM 		ulong_t i;
301*10500SHai-May.Chao@Sun.COM 		uint8_t *tmp_inbuf;
302*10500SHai-May.Chao@Sun.COM 		uint8_t *tmp_outbuf;
303*10500SHai-May.Chao@Sun.COM 
304*10500SHai-May.Chao@Sun.COM 		for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
305*10500SHai-May.Chao@Sun.COM 			tmp_inbuf = &in_buf[i];
306*10500SHai-May.Chao@Sun.COM 			tmp_outbuf = &out_buf[i];
307*10500SHai-May.Chao@Sun.COM 			/* Crunch one block of data for DES. */
308*10500SHai-May.Chao@Sun.COM #ifndef _KERNEL
309*10500SHai-May.Chao@Sun.COM 			if (soft_des_ctx->key_type == CKK_DES)
310*10500SHai-May.Chao@Sun.COM 				(void) des_crunch_block(
311*10500SHai-May.Chao@Sun.COM 				    soft_des_ctx->key_sched,
312*10500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_FALSE);
313*10500SHai-May.Chao@Sun.COM 			else
314*10500SHai-May.Chao@Sun.COM 				(void) des3_crunch_block(
315*10500SHai-May.Chao@Sun.COM 				    soft_des_ctx->key_sched,
316*10500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_FALSE);
317*10500SHai-May.Chao@Sun.COM #else
318*10500SHai-May.Chao@Sun.COM 			if (mechanism == DES_ECB_MECH_INFO_TYPE)
319*10500SHai-May.Chao@Sun.COM 				(void) des_crunch_block(des_ctx->dc_keysched,
320*10500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_FALSE);
321*10500SHai-May.Chao@Sun.COM 			else
322*10500SHai-May.Chao@Sun.COM 				(void) des3_crunch_block(des_ctx->dc_keysched,
323*10500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_FALSE);
324*10500SHai-May.Chao@Sun.COM #endif
325*10500SHai-May.Chao@Sun.COM 		}
326*10500SHai-May.Chao@Sun.COM 
327*10500SHai-May.Chao@Sun.COM 		*pulEncryptedLen = out_len;
328*10500SHai-May.Chao@Sun.COM 		break;
329*10500SHai-May.Chao@Sun.COM 	}
330*10500SHai-May.Chao@Sun.COM 
331*10500SHai-May.Chao@Sun.COM 	case CKM_DES_CBC:
332*10500SHai-May.Chao@Sun.COM 	case CKM_DES3_CBC:
333*10500SHai-May.Chao@Sun.COM 	{
334*10500SHai-May.Chao@Sun.COM 		crypto_data_t out;
335*10500SHai-May.Chao@Sun.COM 
336*10500SHai-May.Chao@Sun.COM 		out.cd_format =  CRYPTO_DATA_RAW;
337*10500SHai-May.Chao@Sun.COM 		out.cd_offset = 0;
338*10500SHai-May.Chao@Sun.COM 		out.cd_length = out_len;
339*10500SHai-May.Chao@Sun.COM 		out.cd_raw.iov_base = (char *)out_buf;
340*10500SHai-May.Chao@Sun.COM 		out.cd_raw.iov_len = out_len;
341*10500SHai-May.Chao@Sun.COM 
342*10500SHai-May.Chao@Sun.COM 		/* Encrypt multiple blocks of data. */
343*10500SHai-May.Chao@Sun.COM 		rc = des_encrypt_contiguous_blocks(
344*10500SHai-May.Chao@Sun.COM #ifndef _KERNEL
345*10500SHai-May.Chao@Sun.COM 		    (des_ctx_t *)soft_des_ctx->des_cbc,
346*10500SHai-May.Chao@Sun.COM #else
347*10500SHai-May.Chao@Sun.COM 			des_ctx,
348*10500SHai-May.Chao@Sun.COM #endif
349*10500SHai-May.Chao@Sun.COM 		    (char *)in_buf, out_len, &out);
350*10500SHai-May.Chao@Sun.COM 
351*10500SHai-May.Chao@Sun.COM 		if (rc != 0)
352*10500SHai-May.Chao@Sun.COM 			goto encrypt_failed;
353*10500SHai-May.Chao@Sun.COM 
354*10500SHai-May.Chao@Sun.COM 		if (rc == 0) {
355*10500SHai-May.Chao@Sun.COM 			*pulEncryptedLen = out_len;
356*10500SHai-May.Chao@Sun.COM 			break;
357*10500SHai-May.Chao@Sun.COM 		}
358*10500SHai-May.Chao@Sun.COM encrypt_failed:
359*10500SHai-May.Chao@Sun.COM 		*pulEncryptedLen = 0;
360*10500SHai-May.Chao@Sun.COM 
361*10500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
362*10500SHai-May.Chao@Sun.COM 
363*10500SHai-May.Chao@Sun.COM 	}
364*10500SHai-May.Chao@Sun.COM 	} /* end switch */
365*10500SHai-May.Chao@Sun.COM 
366*10500SHai-May.Chao@Sun.COM 	return (rv);
367*10500SHai-May.Chao@Sun.COM }
368*10500SHai-May.Chao@Sun.COM 
369*10500SHai-May.Chao@Sun.COM /*
370*10500SHai-May.Chao@Sun.COM  * fips_des_decrypt()
371*10500SHai-May.Chao@Sun.COM  *
372*10500SHai-May.Chao@Sun.COM  * Arguments:
373*10500SHai-May.Chao@Sun.COM  *	soft_des_ctx:	pointer to DES context
374*10500SHai-May.Chao@Sun.COM  *	in_buf:	pointer to the input data to be decrypted
375*10500SHai-May.Chao@Sun.COM  *	ulEncryptedLen:	length of the input data
376*10500SHai-May.Chao@Sun.COM  *	out_buf:	pointer to the output data
377*10500SHai-May.Chao@Sun.COM  *	pulDataLen:	pointer to the length of the output data
378*10500SHai-May.Chao@Sun.COM  *	mechanism:	CKM_DES_ECB, CKM_DES3_ECB, CKM_DES_CBC, CKM_DES3_CBC
379*10500SHai-May.Chao@Sun.COM  *
380*10500SHai-May.Chao@Sun.COM  * Description:
381*10500SHai-May.Chao@Sun.COM  *      This function calls the corresponding DES low-level decrypt
382*10500SHai-May.Chao@Sun.COM  *	function based on the mechanism.
383*10500SHai-May.Chao@Sun.COM  *
384*10500SHai-May.Chao@Sun.COM  */
385*10500SHai-May.Chao@Sun.COM #ifndef _KERNEL
386*10500SHai-May.Chao@Sun.COM CK_RV
387*10500SHai-May.Chao@Sun.COM fips_des_decrypt(soft_des_ctx_t *soft_des_ctx, CK_BYTE_PTR in_buf,
388*10500SHai-May.Chao@Sun.COM 	CK_ULONG ulEncryptedLen, CK_BYTE_PTR out_buf,
389*10500SHai-May.Chao@Sun.COM 	CK_ULONG_PTR pulDataLen, CK_MECHANISM_TYPE mechanism)
390*10500SHai-May.Chao@Sun.COM #else
391*10500SHai-May.Chao@Sun.COM int
392*10500SHai-May.Chao@Sun.COM fips_des_decrypt(des_ctx_t *des_ctx, uint8_t *in_buf,
393*10500SHai-May.Chao@Sun.COM 	ulong_t ulEncryptedLen, uint8_t *out_buf,
394*10500SHai-May.Chao@Sun.COM 	ulong_t *pulDataLen, des_mech_type_t mechanism)
395*10500SHai-May.Chao@Sun.COM #endif
396*10500SHai-May.Chao@Sun.COM {
397*10500SHai-May.Chao@Sun.COM 
398*10500SHai-May.Chao@Sun.COM 	CK_RV rv = CKR_OK;
399*10500SHai-May.Chao@Sun.COM 	int rc = 0;
400*10500SHai-May.Chao@Sun.COM 	ulong_t out_len;
401*10500SHai-May.Chao@Sun.COM 
402*10500SHai-May.Chao@Sun.COM 	/*
403*10500SHai-May.Chao@Sun.COM 	 * DES only takes input length that is a multiple of 8 bytes
404*10500SHai-May.Chao@Sun.COM 	 * with the mechanism CKM_DES<n>_ECB, CKM_DES<n>_CBC or
405*10500SHai-May.Chao@Sun.COM 	 * CKM_DES<n>_CBC_PAD.
406*10500SHai-May.Chao@Sun.COM 	 */
407*10500SHai-May.Chao@Sun.COM 	if ((ulEncryptedLen % DES_BLOCK_LEN) != 0) {
408*10500SHai-May.Chao@Sun.COM 		return (CKR_DATA_LEN_RANGE);
409*10500SHai-May.Chao@Sun.COM 	}
410*10500SHai-May.Chao@Sun.COM 
411*10500SHai-May.Chao@Sun.COM 	/* Set output length same as input length. */
412*10500SHai-May.Chao@Sun.COM 	out_len = ulEncryptedLen;
413*10500SHai-May.Chao@Sun.COM 
414*10500SHai-May.Chao@Sun.COM 	/*
415*10500SHai-May.Chao@Sun.COM 	 * Begin Decryption.
416*10500SHai-May.Chao@Sun.COM 	 */
417*10500SHai-May.Chao@Sun.COM 	switch (mechanism) {
418*10500SHai-May.Chao@Sun.COM 	case CKM_DES_ECB:
419*10500SHai-May.Chao@Sun.COM 	case CKM_DES3_ECB:
420*10500SHai-May.Chao@Sun.COM 	{
421*10500SHai-May.Chao@Sun.COM 		uint8_t *tmp_inbuf;
422*10500SHai-May.Chao@Sun.COM 		uint8_t *tmp_outbuf;
423*10500SHai-May.Chao@Sun.COM 		ulong_t i;
424*10500SHai-May.Chao@Sun.COM 
425*10500SHai-May.Chao@Sun.COM 		for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
426*10500SHai-May.Chao@Sun.COM 			tmp_inbuf = &in_buf[i];
427*10500SHai-May.Chao@Sun.COM 			tmp_outbuf = &out_buf[i];
428*10500SHai-May.Chao@Sun.COM 			/* Crunch one block of data for DES. */
429*10500SHai-May.Chao@Sun.COM #ifndef _KERNEL
430*10500SHai-May.Chao@Sun.COM 			if (soft_des_ctx->key_type == CKK_DES)
431*10500SHai-May.Chao@Sun.COM 				(void) des_crunch_block(
432*10500SHai-May.Chao@Sun.COM 				    soft_des_ctx->key_sched,
433*10500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_TRUE);
434*10500SHai-May.Chao@Sun.COM 			else
435*10500SHai-May.Chao@Sun.COM 				(void) des3_crunch_block(
436*10500SHai-May.Chao@Sun.COM 				    soft_des_ctx->key_sched,
437*10500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_TRUE);
438*10500SHai-May.Chao@Sun.COM #else
439*10500SHai-May.Chao@Sun.COM 			if (mechanism == DES_ECB_MECH_INFO_TYPE)
440*10500SHai-May.Chao@Sun.COM 				(void) des_crunch_block(des_ctx->dc_keysched,
441*10500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_TRUE);
442*10500SHai-May.Chao@Sun.COM 			else
443*10500SHai-May.Chao@Sun.COM 				(void) des3_crunch_block(des_ctx->dc_keysched,
444*10500SHai-May.Chao@Sun.COM 				    tmp_inbuf, tmp_outbuf, B_TRUE);
445*10500SHai-May.Chao@Sun.COM #endif
446*10500SHai-May.Chao@Sun.COM 		}
447*10500SHai-May.Chao@Sun.COM 
448*10500SHai-May.Chao@Sun.COM 		*pulDataLen = out_len;
449*10500SHai-May.Chao@Sun.COM 		break;
450*10500SHai-May.Chao@Sun.COM 	}
451*10500SHai-May.Chao@Sun.COM 
452*10500SHai-May.Chao@Sun.COM 	case CKM_DES_CBC:
453*10500SHai-May.Chao@Sun.COM 	case CKM_DES3_CBC:
454*10500SHai-May.Chao@Sun.COM 	{
455*10500SHai-May.Chao@Sun.COM 		crypto_data_t out;
456*10500SHai-May.Chao@Sun.COM 		out.cd_format =  CRYPTO_DATA_RAW;
457*10500SHai-May.Chao@Sun.COM 		out.cd_offset = 0;
458*10500SHai-May.Chao@Sun.COM 		out.cd_length = out_len;
459*10500SHai-May.Chao@Sun.COM 		out.cd_raw.iov_base = (char *)out_buf;
460*10500SHai-May.Chao@Sun.COM 		out.cd_raw.iov_len = out_len;
461*10500SHai-May.Chao@Sun.COM 
462*10500SHai-May.Chao@Sun.COM 		/* Decrypt multiple blocks of data. */
463*10500SHai-May.Chao@Sun.COM 		rc = des_decrypt_contiguous_blocks(
464*10500SHai-May.Chao@Sun.COM #ifndef _KERNEL
465*10500SHai-May.Chao@Sun.COM 		    (des_ctx_t *)soft_des_ctx->des_cbc,
466*10500SHai-May.Chao@Sun.COM #else
467*10500SHai-May.Chao@Sun.COM 		    des_ctx,
468*10500SHai-May.Chao@Sun.COM #endif
469*10500SHai-May.Chao@Sun.COM 		    (char *)in_buf, out_len, &out);
470*10500SHai-May.Chao@Sun.COM 
471*10500SHai-May.Chao@Sun.COM 		if (rc != 0)
472*10500SHai-May.Chao@Sun.COM 			goto decrypt_failed;
473*10500SHai-May.Chao@Sun.COM 
474*10500SHai-May.Chao@Sun.COM 		*pulDataLen = out_len;
475*10500SHai-May.Chao@Sun.COM 
476*10500SHai-May.Chao@Sun.COM 		if (rc == 0)
477*10500SHai-May.Chao@Sun.COM 			break;
478*10500SHai-May.Chao@Sun.COM decrypt_failed:
479*10500SHai-May.Chao@Sun.COM 		*pulDataLen = 0;
480*10500SHai-May.Chao@Sun.COM 
481*10500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
482*10500SHai-May.Chao@Sun.COM 
483*10500SHai-May.Chao@Sun.COM 	}
484*10500SHai-May.Chao@Sun.COM 	} /* end switch */
485*10500SHai-May.Chao@Sun.COM 
486*10500SHai-May.Chao@Sun.COM 	return (rv);
487*10500SHai-May.Chao@Sun.COM }
488*10500SHai-May.Chao@Sun.COM 
489*10500SHai-May.Chao@Sun.COM /*
490*10500SHai-May.Chao@Sun.COM  * DES3 Power-On SelfTest(s).
491*10500SHai-May.Chao@Sun.COM  */
492*10500SHai-May.Chao@Sun.COM int
493*10500SHai-May.Chao@Sun.COM fips_des3_post(void)
494*10500SHai-May.Chao@Sun.COM {
495*10500SHai-May.Chao@Sun.COM 
496*10500SHai-May.Chao@Sun.COM 	/* DES3 Known Key. */
497*10500SHai-May.Chao@Sun.COM 	static uint8_t des3_known_key[] = { "ANSI Triple-DES Key Data" };
498*10500SHai-May.Chao@Sun.COM 
499*10500SHai-May.Chao@Sun.COM 	/* DES3-CBC Known Initialization Vector (64-bits). */
500*10500SHai-May.Chao@Sun.COM 	static uint8_t des3_cbc_known_iv[] = { "Security" };
501*10500SHai-May.Chao@Sun.COM 
502*10500SHai-May.Chao@Sun.COM 	/* DES3 Known Plaintext (64-bits). */
503*10500SHai-May.Chao@Sun.COM 	static uint8_t des3_ecb_known_plaintext[] = { "Solaris!" };
504*10500SHai-May.Chao@Sun.COM 	static uint8_t des3_cbc_known_plaintext[] = { "Solaris!" };
505*10500SHai-May.Chao@Sun.COM 
506*10500SHai-May.Chao@Sun.COM 	/* DES3 Known Ciphertext (64-bits). */
507*10500SHai-May.Chao@Sun.COM 	static uint8_t des3_ecb_known_ciphertext[] = {
508*10500SHai-May.Chao@Sun.COM 		0x17, 0x0d, 0x1f, 0x13, 0xd3, 0xa0, 0x3a, 0x63
509*10500SHai-May.Chao@Sun.COM 	};
510*10500SHai-May.Chao@Sun.COM 
511*10500SHai-May.Chao@Sun.COM 	static uint8_t des3_cbc_known_ciphertext[] = {
512*10500SHai-May.Chao@Sun.COM 		0x7f, 0x62, 0x44, 0xb3, 0xf8, 0x77, 0xf8, 0xf8
513*10500SHai-May.Chao@Sun.COM 	};
514*10500SHai-May.Chao@Sun.COM 
515*10500SHai-May.Chao@Sun.COM 	/* DES3 variables. */
516*10500SHai-May.Chao@Sun.COM 	uint8_t des3_computed_ciphertext[FIPS_DES3_ENCRYPT_LENGTH];
517*10500SHai-May.Chao@Sun.COM 	uint8_t des3_computed_plaintext[FIPS_DES3_DECRYPT_LENGTH];
518*10500SHai-May.Chao@Sun.COM 
519*10500SHai-May.Chao@Sun.COM #ifdef _KERNEL
520*10500SHai-May.Chao@Sun.COM 	des_ctx_t *des3_context;
521*10500SHai-May.Chao@Sun.COM #else
522*10500SHai-May.Chao@Sun.COM 	soft_des_ctx_t *des3_context;
523*10500SHai-May.Chao@Sun.COM #endif
524*10500SHai-May.Chao@Sun.COM 
525*10500SHai-May.Chao@Sun.COM 	ulong_t des3_bytes_encrypted;
526*10500SHai-May.Chao@Sun.COM 	ulong_t des3_bytes_decrypted;
527*10500SHai-May.Chao@Sun.COM 	int rv;
528*10500SHai-May.Chao@Sun.COM 
529*10500SHai-May.Chao@Sun.COM 	/*
530*10500SHai-May.Chao@Sun.COM 	 * DES3 ECB Known Answer Encryption Test
531*10500SHai-May.Chao@Sun.COM 	 */
532*10500SHai-May.Chao@Sun.COM #ifdef _KERNEL
533*10500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, NULL,
534*10500SHai-May.Chao@Sun.COM 	    DES3_ECB_MECH_INFO_TYPE);
535*10500SHai-May.Chao@Sun.COM #else
536*10500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, NULL,
537*10500SHai-May.Chao@Sun.COM 	    CKK_DES3, CKM_DES3_ECB);
538*10500SHai-May.Chao@Sun.COM #endif
539*10500SHai-May.Chao@Sun.COM 
540*10500SHai-May.Chao@Sun.COM 	if (des3_context == NULL)
541*10500SHai-May.Chao@Sun.COM 		return (CKR_HOST_MEMORY);
542*10500SHai-May.Chao@Sun.COM 
543*10500SHai-May.Chao@Sun.COM #ifdef _KERNEL
544*10500SHai-May.Chao@Sun.COM 	rv = fips_des_encrypt(des3_context, des3_ecb_known_plaintext,
545*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
546*10500SHai-May.Chao@Sun.COM 	    &des3_bytes_encrypted, DES3_ECB_MECH_INFO_TYPE);
547*10500SHai-May.Chao@Sun.COM #else
548*10500SHai-May.Chao@Sun.COM 	rv = fips_des_encrypt(des3_context, des3_ecb_known_plaintext,
549*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
550*10500SHai-May.Chao@Sun.COM 	    &des3_bytes_encrypted, CKM_DES3_ECB);
551*10500SHai-May.Chao@Sun.COM #endif
552*10500SHai-May.Chao@Sun.COM 
553*10500SHai-May.Chao@Sun.COM 	fips_des_free_context(des3_context);
554*10500SHai-May.Chao@Sun.COM 
555*10500SHai-May.Chao@Sun.COM 	if ((rv != CRYPTO_SUCCESS) ||
556*10500SHai-May.Chao@Sun.COM 	    (des3_bytes_encrypted != FIPS_DES3_ENCRYPT_LENGTH) ||
557*10500SHai-May.Chao@Sun.COM 	    (memcmp(des3_computed_ciphertext, des3_ecb_known_ciphertext,
558*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH) != 0))
559*10500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
560*10500SHai-May.Chao@Sun.COM 
561*10500SHai-May.Chao@Sun.COM 	/*
562*10500SHai-May.Chao@Sun.COM 	 * DES3 ECB Known Answer Decryption Test
563*10500SHai-May.Chao@Sun.COM 	 */
564*10500SHai-May.Chao@Sun.COM #ifdef _KERNEL
565*10500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, NULL,
566*10500SHai-May.Chao@Sun.COM 	    DES3_ECB_MECH_INFO_TYPE);
567*10500SHai-May.Chao@Sun.COM #else
568*10500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, NULL,
569*10500SHai-May.Chao@Sun.COM 	    CKK_DES3, CKM_DES3_ECB);
570*10500SHai-May.Chao@Sun.COM #endif
571*10500SHai-May.Chao@Sun.COM 
572*10500SHai-May.Chao@Sun.COM 	if (des3_context == NULL)
573*10500SHai-May.Chao@Sun.COM 		return (CKR_HOST_MEMORY);
574*10500SHai-May.Chao@Sun.COM 
575*10500SHai-May.Chao@Sun.COM #ifdef _KERNEL
576*10500SHai-May.Chao@Sun.COM 	rv = fips_des_decrypt(des3_context, des3_ecb_known_ciphertext,
577*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
578*10500SHai-May.Chao@Sun.COM 	    &des3_bytes_decrypted, DES3_ECB_MECH_INFO_TYPE);
579*10500SHai-May.Chao@Sun.COM #else
580*10500SHai-May.Chao@Sun.COM 	rv = fips_des_decrypt(des3_context, des3_ecb_known_ciphertext,
581*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
582*10500SHai-May.Chao@Sun.COM 	    &des3_bytes_decrypted, CKM_DES3_ECB);
583*10500SHai-May.Chao@Sun.COM #endif
584*10500SHai-May.Chao@Sun.COM 
585*10500SHai-May.Chao@Sun.COM 	fips_des_free_context(des3_context);
586*10500SHai-May.Chao@Sun.COM 
587*10500SHai-May.Chao@Sun.COM 	if ((rv != CRYPTO_SUCCESS) ||
588*10500SHai-May.Chao@Sun.COM 	    (des3_bytes_decrypted != FIPS_DES3_DECRYPT_LENGTH) ||
589*10500SHai-May.Chao@Sun.COM 	    (memcmp(des3_computed_plaintext, des3_ecb_known_plaintext,
590*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH) != 0))
591*10500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
592*10500SHai-May.Chao@Sun.COM 
593*10500SHai-May.Chao@Sun.COM 	/*
594*10500SHai-May.Chao@Sun.COM 	 * DES3 CBC Known Answer Encryption Test
595*10500SHai-May.Chao@Sun.COM 	 */
596*10500SHai-May.Chao@Sun.COM #ifdef _KERNEL
597*10500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
598*10500SHai-May.Chao@Sun.COM 	    DES3_CBC_MECH_INFO_TYPE);
599*10500SHai-May.Chao@Sun.COM #else
600*10500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
601*10500SHai-May.Chao@Sun.COM 	    CKK_DES3, CKM_DES3_CBC);
602*10500SHai-May.Chao@Sun.COM #endif
603*10500SHai-May.Chao@Sun.COM 
604*10500SHai-May.Chao@Sun.COM 	if (des3_context == NULL)
605*10500SHai-May.Chao@Sun.COM 		return (CKR_HOST_MEMORY);
606*10500SHai-May.Chao@Sun.COM 
607*10500SHai-May.Chao@Sun.COM #ifdef _KERNEL
608*10500SHai-May.Chao@Sun.COM 	rv = fips_des_encrypt(des3_context, des3_cbc_known_plaintext,
609*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
610*10500SHai-May.Chao@Sun.COM 	    &des3_bytes_encrypted, DES3_CBC_MECH_INFO_TYPE);
611*10500SHai-May.Chao@Sun.COM #else
612*10500SHai-May.Chao@Sun.COM 	rv = fips_des_encrypt(des3_context, des3_cbc_known_plaintext,
613*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
614*10500SHai-May.Chao@Sun.COM 	    &des3_bytes_encrypted, CKM_DES3_CBC);
615*10500SHai-May.Chao@Sun.COM #endif
616*10500SHai-May.Chao@Sun.COM 
617*10500SHai-May.Chao@Sun.COM 	fips_des_free_context(des3_context);
618*10500SHai-May.Chao@Sun.COM 
619*10500SHai-May.Chao@Sun.COM 	if ((rv != CRYPTO_SUCCESS) ||
620*10500SHai-May.Chao@Sun.COM 	    (des3_bytes_encrypted != FIPS_DES3_ENCRYPT_LENGTH) ||
621*10500SHai-May.Chao@Sun.COM 	    (memcmp(des3_computed_ciphertext, des3_cbc_known_ciphertext,
622*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_ENCRYPT_LENGTH) != 0))
623*10500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
624*10500SHai-May.Chao@Sun.COM 
625*10500SHai-May.Chao@Sun.COM 	/*
626*10500SHai-May.Chao@Sun.COM 	 * DES3 CBC Known Answer Decryption Test
627*10500SHai-May.Chao@Sun.COM 	 */
628*10500SHai-May.Chao@Sun.COM #ifdef _KERNEL
629*10500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
630*10500SHai-May.Chao@Sun.COM 	    DES3_CBC_MECH_INFO_TYPE);
631*10500SHai-May.Chao@Sun.COM #else
632*10500SHai-May.Chao@Sun.COM 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
633*10500SHai-May.Chao@Sun.COM 	    CKK_DES3, CKM_DES3_CBC);
634*10500SHai-May.Chao@Sun.COM #endif
635*10500SHai-May.Chao@Sun.COM 
636*10500SHai-May.Chao@Sun.COM 	if (des3_context == NULL)
637*10500SHai-May.Chao@Sun.COM 		return (CKR_HOST_MEMORY);
638*10500SHai-May.Chao@Sun.COM 
639*10500SHai-May.Chao@Sun.COM #ifdef _KERNEL
640*10500SHai-May.Chao@Sun.COM 	rv = fips_des_decrypt(des3_context, des3_cbc_known_ciphertext,
641*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
642*10500SHai-May.Chao@Sun.COM 	    &des3_bytes_decrypted, DES3_CBC_MECH_INFO_TYPE);
643*10500SHai-May.Chao@Sun.COM #else
644*10500SHai-May.Chao@Sun.COM 	rv = fips_des_decrypt(des3_context, des3_cbc_known_ciphertext,
645*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
646*10500SHai-May.Chao@Sun.COM 	    &des3_bytes_decrypted, CKM_DES3_CBC);
647*10500SHai-May.Chao@Sun.COM #endif
648*10500SHai-May.Chao@Sun.COM 
649*10500SHai-May.Chao@Sun.COM 	fips_des_free_context(des3_context);
650*10500SHai-May.Chao@Sun.COM 
651*10500SHai-May.Chao@Sun.COM 	if ((rv != CRYPTO_SUCCESS) ||
652*10500SHai-May.Chao@Sun.COM 	    (des3_bytes_decrypted != FIPS_DES3_DECRYPT_LENGTH) ||
653*10500SHai-May.Chao@Sun.COM 	    (memcmp(des3_computed_plaintext, des3_cbc_known_plaintext,
654*10500SHai-May.Chao@Sun.COM 	    FIPS_DES3_DECRYPT_LENGTH) != 0))
655*10500SHai-May.Chao@Sun.COM 		return (CKR_DEVICE_ERROR);
656*10500SHai-May.Chao@Sun.COM 
657*10500SHai-May.Chao@Sun.COM 	return (CKR_OK);
658*10500SHai-May.Chao@Sun.COM }
659