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