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