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