xref: /onnv-gate/usr/src/common/crypto/fips/fips_des_util.c (revision 10500:a10fbcfc2f21)
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 *
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
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
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 *
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
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 	}
242 }
243 #endif
244 
245 /*
246  * fips_des_encrypt()
247  *
248  * Arguments:
249  *	soft_des_ctx:	pointer to DES context
250  *	in_buf:		pointer to the input data to be encrypted
251  *	ulDataLen:	length of the input data
252  *	out_buf:	pointer to the output data after encryption
253  *	pulEncryptedLen: pointer to the length of the output data
254  *	mechanism:	CKM_DES_ECB, CKM_DES3_ECB, CKM_DES_CBC, CKM_DES3_CBC
255  *
256  * Description:
257  *	This function calls the corresponding DES low-level encrypt
258  *	routine based on the mechanism.
259  *
260  */
261 #ifndef _KERNEL
262 CK_RV
263 fips_des_encrypt(soft_des_ctx_t *soft_des_ctx, CK_BYTE_PTR in_buf,
264 	CK_ULONG ulDataLen, CK_BYTE_PTR out_buf,
265 	CK_ULONG_PTR pulEncryptedLen, CK_MECHANISM_TYPE mechanism)
266 #else
267 int
268 fips_des_encrypt(des_ctx_t *des_ctx, uint8_t *in_buf,
269 	ulong_t ulDataLen, uint8_t *out_buf,
270 	ulong_t *pulEncryptedLen, des_mech_type_t mechanism)
271 #endif
272 {
273 
274 	CK_RV rv = CKR_OK;
275 	int rc = 0;
276 	ulong_t out_len;
277 
278 	/*
279 	 * DES only takes input length that is a multiple of blocksize
280 	 * with the mechanism CKM_DES<n>_ECB or CKM_DES<n>_CBC.
281 	 */
282 	if ((ulDataLen % DES_BLOCK_LEN) != 0) {
283 		return (CKR_DATA_LEN_RANGE);
284 	}
285 
286 	/*
287 	 * For non-padding mode, the output length will
288 	 * be same as the input length.
289 	 */
290 	out_len = ulDataLen;
291 
292 	/*
293 	 * Begin Encryption now.
294 	 */
295 	switch (mechanism) {
296 	case CKM_DES_ECB:
297 	case CKM_DES3_ECB:
298 	{
299 
300 		ulong_t i;
301 		uint8_t *tmp_inbuf;
302 		uint8_t *tmp_outbuf;
303 
304 		for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
305 			tmp_inbuf = &in_buf[i];
306 			tmp_outbuf = &out_buf[i];
307 			/* Crunch one block of data for DES. */
308 #ifndef _KERNEL
309 			if (soft_des_ctx->key_type == CKK_DES)
310 				(void) des_crunch_block(
311 				    soft_des_ctx->key_sched,
312 				    tmp_inbuf, tmp_outbuf, B_FALSE);
313 			else
314 				(void) des3_crunch_block(
315 				    soft_des_ctx->key_sched,
316 				    tmp_inbuf, tmp_outbuf, B_FALSE);
317 #else
318 			if (mechanism == DES_ECB_MECH_INFO_TYPE)
319 				(void) des_crunch_block(des_ctx->dc_keysched,
320 				    tmp_inbuf, tmp_outbuf, B_FALSE);
321 			else
322 				(void) des3_crunch_block(des_ctx->dc_keysched,
323 				    tmp_inbuf, tmp_outbuf, B_FALSE);
324 #endif
325 		}
326 
327 		*pulEncryptedLen = out_len;
328 		break;
329 	}
330 
331 	case CKM_DES_CBC:
332 	case CKM_DES3_CBC:
333 	{
334 		crypto_data_t out;
335 
336 		out.cd_format =  CRYPTO_DATA_RAW;
337 		out.cd_offset = 0;
338 		out.cd_length = out_len;
339 		out.cd_raw.iov_base = (char *)out_buf;
340 		out.cd_raw.iov_len = out_len;
341 
342 		/* Encrypt multiple blocks of data. */
343 		rc = des_encrypt_contiguous_blocks(
344 #ifndef _KERNEL
345 		    (des_ctx_t *)soft_des_ctx->des_cbc,
346 #else
347 			des_ctx,
348 #endif
349 		    (char *)in_buf, out_len, &out);
350 
351 		if (rc != 0)
352 			goto encrypt_failed;
353 
354 		if (rc == 0) {
355 			*pulEncryptedLen = out_len;
356 			break;
357 		}
358 encrypt_failed:
359 		*pulEncryptedLen = 0;
360 
361 		return (CKR_DEVICE_ERROR);
362 
363 	}
364 	} /* end switch */
365 
366 	return (rv);
367 }
368 
369 /*
370  * fips_des_decrypt()
371  *
372  * Arguments:
373  *	soft_des_ctx:	pointer to DES context
374  *	in_buf:	pointer to the input data to be decrypted
375  *	ulEncryptedLen:	length of the input data
376  *	out_buf:	pointer to the output data
377  *	pulDataLen:	pointer to the length of the output data
378  *	mechanism:	CKM_DES_ECB, CKM_DES3_ECB, CKM_DES_CBC, CKM_DES3_CBC
379  *
380  * Description:
381  *      This function calls the corresponding DES low-level decrypt
382  *	function based on the mechanism.
383  *
384  */
385 #ifndef _KERNEL
386 CK_RV
387 fips_des_decrypt(soft_des_ctx_t *soft_des_ctx, CK_BYTE_PTR in_buf,
388 	CK_ULONG ulEncryptedLen, CK_BYTE_PTR out_buf,
389 	CK_ULONG_PTR pulDataLen, CK_MECHANISM_TYPE mechanism)
390 #else
391 int
392 fips_des_decrypt(des_ctx_t *des_ctx, uint8_t *in_buf,
393 	ulong_t ulEncryptedLen, uint8_t *out_buf,
394 	ulong_t *pulDataLen, des_mech_type_t mechanism)
395 #endif
396 {
397 
398 	CK_RV rv = CKR_OK;
399 	int rc = 0;
400 	ulong_t out_len;
401 
402 	/*
403 	 * DES only takes input length that is a multiple of 8 bytes
404 	 * with the mechanism CKM_DES<n>_ECB, CKM_DES<n>_CBC or
405 	 * CKM_DES<n>_CBC_PAD.
406 	 */
407 	if ((ulEncryptedLen % DES_BLOCK_LEN) != 0) {
408 		return (CKR_DATA_LEN_RANGE);
409 	}
410 
411 	/* Set output length same as input length. */
412 	out_len = ulEncryptedLen;
413 
414 	/*
415 	 * Begin Decryption.
416 	 */
417 	switch (mechanism) {
418 	case CKM_DES_ECB:
419 	case CKM_DES3_ECB:
420 	{
421 		uint8_t *tmp_inbuf;
422 		uint8_t *tmp_outbuf;
423 		ulong_t i;
424 
425 		for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
426 			tmp_inbuf = &in_buf[i];
427 			tmp_outbuf = &out_buf[i];
428 			/* Crunch one block of data for DES. */
429 #ifndef _KERNEL
430 			if (soft_des_ctx->key_type == CKK_DES)
431 				(void) des_crunch_block(
432 				    soft_des_ctx->key_sched,
433 				    tmp_inbuf, tmp_outbuf, B_TRUE);
434 			else
435 				(void) des3_crunch_block(
436 				    soft_des_ctx->key_sched,
437 				    tmp_inbuf, tmp_outbuf, B_TRUE);
438 #else
439 			if (mechanism == DES_ECB_MECH_INFO_TYPE)
440 				(void) des_crunch_block(des_ctx->dc_keysched,
441 				    tmp_inbuf, tmp_outbuf, B_TRUE);
442 			else
443 				(void) des3_crunch_block(des_ctx->dc_keysched,
444 				    tmp_inbuf, tmp_outbuf, B_TRUE);
445 #endif
446 		}
447 
448 		*pulDataLen = out_len;
449 		break;
450 	}
451 
452 	case CKM_DES_CBC:
453 	case CKM_DES3_CBC:
454 	{
455 		crypto_data_t out;
456 		out.cd_format =  CRYPTO_DATA_RAW;
457 		out.cd_offset = 0;
458 		out.cd_length = out_len;
459 		out.cd_raw.iov_base = (char *)out_buf;
460 		out.cd_raw.iov_len = out_len;
461 
462 		/* Decrypt multiple blocks of data. */
463 		rc = des_decrypt_contiguous_blocks(
464 #ifndef _KERNEL
465 		    (des_ctx_t *)soft_des_ctx->des_cbc,
466 #else
467 		    des_ctx,
468 #endif
469 		    (char *)in_buf, out_len, &out);
470 
471 		if (rc != 0)
472 			goto decrypt_failed;
473 
474 		*pulDataLen = out_len;
475 
476 		if (rc == 0)
477 			break;
478 decrypt_failed:
479 		*pulDataLen = 0;
480 
481 		return (CKR_DEVICE_ERROR);
482 
483 	}
484 	} /* end switch */
485 
486 	return (rv);
487 }
488 
489 /*
490  * DES3 Power-On SelfTest(s).
491  */
492 int
493 fips_des3_post(void)
494 {
495 
496 	/* DES3 Known Key. */
497 	static uint8_t des3_known_key[] = { "ANSI Triple-DES Key Data" };
498 
499 	/* DES3-CBC Known Initialization Vector (64-bits). */
500 	static uint8_t des3_cbc_known_iv[] = { "Security" };
501 
502 	/* DES3 Known Plaintext (64-bits). */
503 	static uint8_t des3_ecb_known_plaintext[] = { "Solaris!" };
504 	static uint8_t des3_cbc_known_plaintext[] = { "Solaris!" };
505 
506 	/* DES3 Known Ciphertext (64-bits). */
507 	static uint8_t des3_ecb_known_ciphertext[] = {
508 		0x17, 0x0d, 0x1f, 0x13, 0xd3, 0xa0, 0x3a, 0x63
509 	};
510 
511 	static uint8_t des3_cbc_known_ciphertext[] = {
512 		0x7f, 0x62, 0x44, 0xb3, 0xf8, 0x77, 0xf8, 0xf8
513 	};
514 
515 	/* DES3 variables. */
516 	uint8_t des3_computed_ciphertext[FIPS_DES3_ENCRYPT_LENGTH];
517 	uint8_t des3_computed_plaintext[FIPS_DES3_DECRYPT_LENGTH];
518 
519 #ifdef _KERNEL
520 	des_ctx_t *des3_context;
521 #else
522 	soft_des_ctx_t *des3_context;
523 #endif
524 
525 	ulong_t des3_bytes_encrypted;
526 	ulong_t des3_bytes_decrypted;
527 	int rv;
528 
529 	/*
530 	 * DES3 ECB Known Answer Encryption Test
531 	 */
532 #ifdef _KERNEL
533 	des3_context = des_build_context(des3_known_key, NULL,
534 	    DES3_ECB_MECH_INFO_TYPE);
535 #else
536 	des3_context = des_build_context(des3_known_key, NULL,
537 	    CKK_DES3, CKM_DES3_ECB);
538 #endif
539 
540 	if (des3_context == NULL)
541 		return (CKR_HOST_MEMORY);
542 
543 #ifdef _KERNEL
544 	rv = fips_des_encrypt(des3_context, des3_ecb_known_plaintext,
545 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
546 	    &des3_bytes_encrypted, DES3_ECB_MECH_INFO_TYPE);
547 #else
548 	rv = fips_des_encrypt(des3_context, des3_ecb_known_plaintext,
549 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
550 	    &des3_bytes_encrypted, CKM_DES3_ECB);
551 #endif
552 
553 	fips_des_free_context(des3_context);
554 
555 	if ((rv != CRYPTO_SUCCESS) ||
556 	    (des3_bytes_encrypted != FIPS_DES3_ENCRYPT_LENGTH) ||
557 	    (memcmp(des3_computed_ciphertext, des3_ecb_known_ciphertext,
558 	    FIPS_DES3_ENCRYPT_LENGTH) != 0))
559 		return (CKR_DEVICE_ERROR);
560 
561 	/*
562 	 * DES3 ECB Known Answer Decryption Test
563 	 */
564 #ifdef _KERNEL
565 	des3_context = des_build_context(des3_known_key, NULL,
566 	    DES3_ECB_MECH_INFO_TYPE);
567 #else
568 	des3_context = des_build_context(des3_known_key, NULL,
569 	    CKK_DES3, CKM_DES3_ECB);
570 #endif
571 
572 	if (des3_context == NULL)
573 		return (CKR_HOST_MEMORY);
574 
575 #ifdef _KERNEL
576 	rv = fips_des_decrypt(des3_context, des3_ecb_known_ciphertext,
577 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
578 	    &des3_bytes_decrypted, DES3_ECB_MECH_INFO_TYPE);
579 #else
580 	rv = fips_des_decrypt(des3_context, des3_ecb_known_ciphertext,
581 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
582 	    &des3_bytes_decrypted, CKM_DES3_ECB);
583 #endif
584 
585 	fips_des_free_context(des3_context);
586 
587 	if ((rv != CRYPTO_SUCCESS) ||
588 	    (des3_bytes_decrypted != FIPS_DES3_DECRYPT_LENGTH) ||
589 	    (memcmp(des3_computed_plaintext, des3_ecb_known_plaintext,
590 	    FIPS_DES3_DECRYPT_LENGTH) != 0))
591 		return (CKR_DEVICE_ERROR);
592 
593 	/*
594 	 * DES3 CBC Known Answer Encryption Test
595 	 */
596 #ifdef _KERNEL
597 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
598 	    DES3_CBC_MECH_INFO_TYPE);
599 #else
600 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
601 	    CKK_DES3, CKM_DES3_CBC);
602 #endif
603 
604 	if (des3_context == NULL)
605 		return (CKR_HOST_MEMORY);
606 
607 #ifdef _KERNEL
608 	rv = fips_des_encrypt(des3_context, des3_cbc_known_plaintext,
609 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
610 	    &des3_bytes_encrypted, DES3_CBC_MECH_INFO_TYPE);
611 #else
612 	rv = fips_des_encrypt(des3_context, des3_cbc_known_plaintext,
613 	    FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
614 	    &des3_bytes_encrypted, CKM_DES3_CBC);
615 #endif
616 
617 	fips_des_free_context(des3_context);
618 
619 	if ((rv != CRYPTO_SUCCESS) ||
620 	    (des3_bytes_encrypted != FIPS_DES3_ENCRYPT_LENGTH) ||
621 	    (memcmp(des3_computed_ciphertext, des3_cbc_known_ciphertext,
622 	    FIPS_DES3_ENCRYPT_LENGTH) != 0))
623 		return (CKR_DEVICE_ERROR);
624 
625 	/*
626 	 * DES3 CBC Known Answer Decryption Test
627 	 */
628 #ifdef _KERNEL
629 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
630 	    DES3_CBC_MECH_INFO_TYPE);
631 #else
632 	des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
633 	    CKK_DES3, CKM_DES3_CBC);
634 #endif
635 
636 	if (des3_context == NULL)
637 		return (CKR_HOST_MEMORY);
638 
639 #ifdef _KERNEL
640 	rv = fips_des_decrypt(des3_context, des3_cbc_known_ciphertext,
641 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
642 	    &des3_bytes_decrypted, DES3_CBC_MECH_INFO_TYPE);
643 #else
644 	rv = fips_des_decrypt(des3_context, des3_cbc_known_ciphertext,
645 	    FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
646 	    &des3_bytes_decrypted, CKM_DES3_CBC);
647 #endif
648 
649 	fips_des_free_context(des3_context);
650 
651 	if ((rv != CRYPTO_SUCCESS) ||
652 	    (des3_bytes_decrypted != FIPS_DES3_DECRYPT_LENGTH) ||
653 	    (memcmp(des3_computed_plaintext, des3_cbc_known_plaintext,
654 	    FIPS_DES3_DECRYPT_LENGTH) != 0))
655 		return (CKR_DEVICE_ERROR);
656 
657 	return (CKR_OK);
658 }
659