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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Blowfish provider for the Kernel Cryptographic Framework (KCF) 30 */ 31 32 #include <sys/types.h> 33 #include <sys/systm.h> 34 #include <sys/modctl.h> 35 #include <sys/cmn_err.h> 36 #include <sys/ddi.h> 37 #include <sys/crypto/common.h> 38 #include <sys/crypto/spi.h> 39 #include <sys/sysmacros.h> 40 #include <sys/strsun.h> 41 #include <sys/note.h> 42 #include <modes/modes.h> 43 #include <blowfish/blowfish_impl.h> 44 45 extern struct mod_ops mod_cryptoops; 46 47 /* 48 * Module linkage information for the kernel. 49 */ 50 static struct modlcrypto modlcrypto = { 51 &mod_cryptoops, 52 "Blowfish Kernel SW Provider" 53 }; 54 55 static struct modlinkage modlinkage = { 56 MODREV_1, 57 (void *)&modlcrypto, 58 NULL 59 }; 60 61 /* 62 * CSPI information (entry points, provider info, etc.) 63 */ 64 typedef enum blowfish_mech_type { 65 BLOWFISH_ECB_MECH_INFO_TYPE, /* SUN_CKM_BLOWFISH_ECB */ 66 BLOWFISH_CBC_MECH_INFO_TYPE /* SUN_CKM_BLOWFISH_CBC */ 67 } blowfish_mech_type_t; 68 69 70 #define BLOWFISH_COPY_BLOCK(src, dst) \ 71 (dst)[0] = (src)[0]; \ 72 (dst)[1] = (src)[1]; \ 73 (dst)[2] = (src)[2]; \ 74 (dst)[3] = (src)[3]; \ 75 (dst)[4] = (src)[4]; \ 76 (dst)[5] = (src)[5]; \ 77 (dst)[6] = (src)[6]; \ 78 (dst)[7] = (src)[7] 79 80 #define BLOWFISH_XOR_BLOCK(src, dst) \ 81 (dst)[0] ^= (src)[0]; \ 82 (dst)[1] ^= (src)[1]; \ 83 (dst)[2] ^= (src)[2]; \ 84 (dst)[3] ^= (src)[3]; \ 85 (dst)[4] ^= (src)[4]; \ 86 (dst)[5] ^= (src)[5]; \ 87 (dst)[6] ^= (src)[6]; \ 88 (dst)[7] ^= (src)[7] 89 90 /* 91 * Mechanism info structure passed to KCF during registration. 92 */ 93 94 static crypto_mech_info_t blowfish_mech_info_tab[] = { 95 /* BLOWFISH_ECB */ 96 {SUN_CKM_BLOWFISH_ECB, BLOWFISH_ECB_MECH_INFO_TYPE, 97 CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 98 CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC, 99 BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 100 /* BLOWFISH_CBC */ 101 {SUN_CKM_BLOWFISH_CBC, BLOWFISH_CBC_MECH_INFO_TYPE, 102 CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 103 CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC, 104 BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS} 105 }; 106 107 #define BLOWFISH_VALID_MECH(mech) \ 108 (((mech)->cm_type == BLOWFISH_ECB_MECH_INFO_TYPE || \ 109 (mech)->cm_type == BLOWFISH_CBC_MECH_INFO_TYPE) ? 1 : 0) 110 111 /* operations are in-place if the output buffer is NULL */ 112 #define BLOWFISH_ARG_INPLACE(input, output) \ 113 if ((output) == NULL) \ 114 (output) = (input); 115 116 static void blowfish_provider_status(crypto_provider_handle_t, uint_t *); 117 118 static crypto_control_ops_t blowfish_control_ops = { 119 blowfish_provider_status 120 }; 121 122 static int blowfish_common_init(crypto_ctx_t *, crypto_mechanism_t *, 123 crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 124 static int blowfish_common_init_ctx(blowfish_ctx_t *, 125 crypto_spi_ctx_template_t *, crypto_mechanism_t *, crypto_key_t *, int); 126 static int blowfish_encrypt_final(crypto_ctx_t *, crypto_data_t *, 127 crypto_req_handle_t); 128 static int blowfish_decrypt_final(crypto_ctx_t *, crypto_data_t *, 129 crypto_req_handle_t); 130 131 static int blowfish_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 132 crypto_req_handle_t); 133 static int blowfish_encrypt_update(crypto_ctx_t *, crypto_data_t *, 134 crypto_data_t *, crypto_req_handle_t); 135 static int blowfish_encrypt_atomic(crypto_provider_handle_t, 136 crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 137 crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 138 139 static int blowfish_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 140 crypto_req_handle_t); 141 static int blowfish_decrypt_update(crypto_ctx_t *, crypto_data_t *, 142 crypto_data_t *, crypto_req_handle_t); 143 static int blowfish_decrypt_atomic(crypto_provider_handle_t, 144 crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 145 crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 146 147 static crypto_cipher_ops_t blowfish_cipher_ops = { 148 blowfish_common_init, 149 blowfish_encrypt, 150 blowfish_encrypt_update, 151 blowfish_encrypt_final, 152 blowfish_encrypt_atomic, 153 blowfish_common_init, 154 blowfish_decrypt, 155 blowfish_decrypt_update, 156 blowfish_decrypt_final, 157 blowfish_decrypt_atomic 158 }; 159 160 static int blowfish_create_ctx_template(crypto_provider_handle_t, 161 crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *, 162 size_t *, crypto_req_handle_t); 163 static int blowfish_free_context(crypto_ctx_t *); 164 165 static crypto_ctx_ops_t blowfish_ctx_ops = { 166 blowfish_create_ctx_template, 167 blowfish_free_context 168 }; 169 170 static crypto_ops_t blowfish_crypto_ops = { 171 &blowfish_control_ops, 172 NULL, 173 &blowfish_cipher_ops, 174 NULL, 175 NULL, 176 NULL, 177 NULL, 178 NULL, 179 NULL, 180 NULL, 181 NULL, 182 NULL, 183 NULL, 184 &blowfish_ctx_ops 185 }; 186 187 static crypto_provider_info_t blowfish_prov_info = { 188 CRYPTO_SPI_VERSION_1, 189 "Blowfish Software Provider", 190 CRYPTO_SW_PROVIDER, 191 {&modlinkage}, 192 NULL, 193 &blowfish_crypto_ops, 194 sizeof (blowfish_mech_info_tab)/sizeof (crypto_mech_info_t), 195 blowfish_mech_info_tab 196 }; 197 198 199 static crypto_kcf_provider_handle_t blowfish_prov_handle = NULL; 200 201 int 202 _init(void) 203 { 204 int ret; 205 206 /* 207 * Register with KCF. If the registration fails, return error. 208 */ 209 if ((ret = crypto_register_provider(&blowfish_prov_info, 210 &blowfish_prov_handle)) != CRYPTO_SUCCESS) { 211 cmn_err(CE_WARN, "%s _init: crypto_register_provider() " 212 "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret); 213 return (EACCES); 214 } 215 216 if ((ret = mod_install(&modlinkage)) != 0) { 217 int rv; 218 219 ASSERT(blowfish_prov_handle != NULL); 220 /* We should not return if the unregister returns busy. */ 221 while ((rv = crypto_unregister_provider(blowfish_prov_handle)) 222 == CRYPTO_BUSY) { 223 cmn_err(CE_WARN, 224 "%s _init: crypto_unregister_provider() " 225 "failed (0x%x). Retrying.", 226 CRYPTO_PROVIDER_NAME, rv); 227 /* wait 10 seconds and try again */ 228 delay(10 * drv_usectohz(1000000)); 229 } 230 } 231 232 return (ret); 233 } 234 235 int 236 _fini(void) 237 { 238 int ret; 239 240 /* 241 * Unregister from KCF if previous registration succeeded. 242 */ 243 if (blowfish_prov_handle != NULL) { 244 if ((ret = crypto_unregister_provider(blowfish_prov_handle)) != 245 CRYPTO_SUCCESS) { 246 cmn_err(CE_WARN, 247 "%s _fini: crypto_unregister_provider() " 248 "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret); 249 return (EBUSY); 250 } 251 blowfish_prov_handle = NULL; 252 } 253 254 return (mod_remove(&modlinkage)); 255 } 256 257 int 258 _info(struct modinfo *modinfop) 259 { 260 return (mod_info(&modlinkage, modinfop)); 261 } 262 263 /* 264 * Initialize key schedules for blowfish 265 */ 266 static int 267 init_keysched(crypto_key_t *key, void *keysched) 268 { 269 /* EXPORT DELETE START */ 270 /* 271 * Only keys by value are supported by this module. 272 */ 273 switch (key->ck_format) { 274 case CRYPTO_KEY_RAW: 275 if (key->ck_length < BLOWFISH_MINBITS || 276 key->ck_length > BLOWFISH_MAXBITS) { 277 return (CRYPTO_KEY_SIZE_RANGE); 278 } 279 break; 280 default: 281 return (CRYPTO_KEY_TYPE_INCONSISTENT); 282 } 283 284 blowfish_init_keysched(key->ck_data, key->ck_length, keysched); 285 /* EXPORT DELETE END */ 286 return (CRYPTO_SUCCESS); 287 } 288 289 /* 290 * KCF software provider control entry points. 291 */ 292 /* ARGSUSED */ 293 static void 294 blowfish_provider_status(crypto_provider_handle_t provider, uint_t *status) 295 { 296 *status = CRYPTO_PROVIDER_READY; 297 } 298 299 /* 300 * KCF software provider encrypt entry points. 301 */ 302 static int 303 blowfish_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 304 crypto_key_t *key, crypto_spi_ctx_template_t template, 305 crypto_req_handle_t req) 306 { 307 308 /* EXPORT DELETE START */ 309 310 blowfish_ctx_t *blowfish_ctx; 311 int rv; 312 int kmflag; 313 314 /* 315 * Only keys by value are supported by this module. 316 */ 317 if (key->ck_format != CRYPTO_KEY_RAW) { 318 return (CRYPTO_KEY_TYPE_INCONSISTENT); 319 } 320 321 if (!BLOWFISH_VALID_MECH(mechanism)) 322 return (CRYPTO_MECHANISM_INVALID); 323 324 if (mechanism->cm_param != NULL && 325 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 326 return (CRYPTO_MECHANISM_PARAM_INVALID); 327 328 kmflag = crypto_kmflag(req); 329 switch (mechanism->cm_type) { 330 case BLOWFISH_ECB_MECH_INFO_TYPE: 331 blowfish_ctx = ecb_alloc_ctx(kmflag); 332 break; 333 case BLOWFISH_CBC_MECH_INFO_TYPE: 334 blowfish_ctx = cbc_alloc_ctx(kmflag); 335 break; 336 } 337 if (blowfish_ctx == NULL) 338 return (CRYPTO_HOST_MEMORY); 339 340 rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism, 341 key, kmflag); 342 if (rv != CRYPTO_SUCCESS) { 343 crypto_free_mode_ctx(blowfish_ctx); 344 return (rv); 345 } 346 347 ctx->cc_provider_private = blowfish_ctx; 348 349 /* EXPORT DELETE END */ 350 351 return (CRYPTO_SUCCESS); 352 } 353 354 static void 355 blowfish_copy_block64(uint8_t *in, uint64_t *out) 356 { 357 if (IS_P2ALIGNED(in, sizeof (uint64_t))) { 358 /* LINTED: pointer alignment */ 359 out[0] = *(uint64_t *)&in[0]; 360 } else { 361 uint8_t *iv8 = (uint8_t *)&out[0]; 362 363 BLOWFISH_COPY_BLOCK(in, iv8); 364 } 365 } 366 367 /* ARGSUSED */ 368 static int 369 blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext, 370 crypto_data_t *ciphertext, crypto_req_handle_t req) 371 { 372 int ret; 373 374 /* EXPORT DELETE START */ 375 376 blowfish_ctx_t *blowfish_ctx; 377 378 /* 379 * Plaintext must be a multiple of blowfish block size. 380 * This test only works for non-padded mechanisms 381 * when blocksize is 2^N. 382 */ 383 if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 384 return (CRYPTO_DATA_LEN_RANGE); 385 386 ASSERT(ctx->cc_provider_private != NULL); 387 blowfish_ctx = ctx->cc_provider_private; 388 389 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 390 391 /* 392 * We need to just return the length needed to store the output. 393 * We should not destroy the context for the following case. 394 */ 395 if (ciphertext->cd_length < plaintext->cd_length) { 396 ciphertext->cd_length = plaintext->cd_length; 397 return (CRYPTO_BUFFER_TOO_SMALL); 398 } 399 400 /* 401 * Do an update on the specified input data. 402 */ 403 ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, req); 404 ASSERT(blowfish_ctx->bc_remainder_len == 0); 405 (void) blowfish_free_context(ctx); 406 407 /* EXPORT DELETE END */ 408 409 /* LINTED */ 410 return (ret); 411 } 412 413 /* ARGSUSED */ 414 static int 415 blowfish_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 416 crypto_data_t *plaintext, crypto_req_handle_t req) 417 { 418 int ret; 419 420 /* EXPORT DELETE START */ 421 422 blowfish_ctx_t *blowfish_ctx; 423 424 /* 425 * Ciphertext must be a multiple of blowfish block size. 426 * This test only works for non-padded mechanisms 427 * when blocksize is 2^N. 428 */ 429 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 430 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 431 432 ASSERT(ctx->cc_provider_private != NULL); 433 blowfish_ctx = ctx->cc_provider_private; 434 435 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 436 437 /* 438 * We need to just return the length needed to store the output. 439 * We should not destroy the context for the following case. 440 */ 441 if (plaintext->cd_length < ciphertext->cd_length) { 442 plaintext->cd_length = ciphertext->cd_length; 443 return (CRYPTO_BUFFER_TOO_SMALL); 444 } 445 446 /* 447 * Do an update on the specified input data. 448 */ 449 ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, req); 450 ASSERT(blowfish_ctx->bc_remainder_len == 0); 451 (void) blowfish_free_context(ctx); 452 453 /* EXPORT DELETE END */ 454 455 /* LINTED */ 456 return (ret); 457 } 458 459 /* ARGSUSED */ 460 static int 461 blowfish_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext, 462 crypto_data_t *ciphertext, crypto_req_handle_t req) 463 { 464 off_t saved_offset; 465 size_t saved_length, out_len; 466 int ret = CRYPTO_SUCCESS; 467 468 ASSERT(ctx->cc_provider_private != NULL); 469 470 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 471 472 /* compute number of bytes that will hold the ciphertext */ 473 out_len = 474 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 475 out_len += plaintext->cd_length; 476 out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 477 478 /* return length needed to store the output */ 479 if (ciphertext->cd_length < out_len) { 480 ciphertext->cd_length = out_len; 481 return (CRYPTO_BUFFER_TOO_SMALL); 482 } 483 484 saved_offset = ciphertext->cd_offset; 485 saved_length = ciphertext->cd_length; 486 487 /* 488 * Do the blowfish update on the specified input data. 489 */ 490 switch (plaintext->cd_format) { 491 case CRYPTO_DATA_RAW: 492 ret = crypto_update_iov(ctx->cc_provider_private, 493 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 494 blowfish_copy_block64); 495 break; 496 case CRYPTO_DATA_UIO: 497 ret = crypto_update_uio(ctx->cc_provider_private, 498 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 499 blowfish_copy_block64); 500 break; 501 case CRYPTO_DATA_MBLK: 502 ret = crypto_update_mp(ctx->cc_provider_private, 503 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 504 blowfish_copy_block64); 505 break; 506 default: 507 ret = CRYPTO_ARGUMENTS_BAD; 508 } 509 510 if (ret == CRYPTO_SUCCESS) { 511 if (plaintext != ciphertext) 512 ciphertext->cd_length = 513 ciphertext->cd_offset - saved_offset; 514 } else { 515 ciphertext->cd_length = saved_length; 516 } 517 ciphertext->cd_offset = saved_offset; 518 519 return (ret); 520 } 521 522 /* ARGSUSED */ 523 static int 524 blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 525 crypto_data_t *plaintext, crypto_req_handle_t req) 526 { 527 off_t saved_offset; 528 size_t saved_length, out_len; 529 int ret = CRYPTO_SUCCESS; 530 531 ASSERT(ctx->cc_provider_private != NULL); 532 533 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 534 535 /* compute number of bytes that will hold the plaintext */ 536 out_len = 537 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 538 out_len += ciphertext->cd_length; 539 out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 540 541 /* return length needed to store the output */ 542 if (plaintext->cd_length < out_len) { 543 plaintext->cd_length = out_len; 544 return (CRYPTO_BUFFER_TOO_SMALL); 545 } 546 547 saved_offset = plaintext->cd_offset; 548 saved_length = plaintext->cd_length; 549 550 /* 551 * Do the blowfish update on the specified input data. 552 */ 553 switch (ciphertext->cd_format) { 554 case CRYPTO_DATA_RAW: 555 ret = crypto_update_iov(ctx->cc_provider_private, 556 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 557 blowfish_copy_block64); 558 break; 559 case CRYPTO_DATA_UIO: 560 ret = crypto_update_uio(ctx->cc_provider_private, 561 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 562 blowfish_copy_block64); 563 break; 564 case CRYPTO_DATA_MBLK: 565 ret = crypto_update_mp(ctx->cc_provider_private, 566 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 567 blowfish_copy_block64); 568 break; 569 default: 570 ret = CRYPTO_ARGUMENTS_BAD; 571 } 572 573 if (ret == CRYPTO_SUCCESS) { 574 if (ciphertext != plaintext) 575 plaintext->cd_length = 576 plaintext->cd_offset - saved_offset; 577 } else { 578 plaintext->cd_length = saved_length; 579 } 580 plaintext->cd_offset = saved_offset; 581 582 return (ret); 583 } 584 585 /* ARGSUSED */ 586 static int 587 blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 588 crypto_req_handle_t req) 589 { 590 591 /* EXPORT DELETE START */ 592 593 blowfish_ctx_t *blowfish_ctx; 594 595 ASSERT(ctx->cc_provider_private != NULL); 596 blowfish_ctx = ctx->cc_provider_private; 597 598 /* 599 * There must be no unprocessed data. 600 * This happens if the length of the last data is 601 * not a multiple of the BLOWFISH block length. 602 */ 603 if (blowfish_ctx->bc_remainder_len > 0) 604 return (CRYPTO_DATA_LEN_RANGE); 605 606 (void) blowfish_free_context(ctx); 607 data->cd_length = 0; 608 609 /* EXPORT DELETE END */ 610 611 return (CRYPTO_SUCCESS); 612 } 613 614 /* ARGSUSED */ 615 static int 616 blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 617 crypto_req_handle_t req) 618 { 619 620 /* EXPORT DELETE START */ 621 622 blowfish_ctx_t *blowfish_ctx; 623 624 ASSERT(ctx->cc_provider_private != NULL); 625 blowfish_ctx = ctx->cc_provider_private; 626 627 /* 628 * There must be no unprocessed ciphertext. 629 * This happens if the length of the last ciphertext is 630 * not a multiple of the BLOWFISH block length. 631 */ 632 if (blowfish_ctx->bc_remainder_len > 0) 633 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 634 635 (void) blowfish_free_context(ctx); 636 data->cd_length = 0; 637 638 /* EXPORT DELETE END */ 639 640 return (CRYPTO_SUCCESS); 641 } 642 643 /* ARGSUSED */ 644 static int 645 blowfish_encrypt_atomic(crypto_provider_handle_t provider, 646 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 647 crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext, 648 crypto_spi_ctx_template_t template, crypto_req_handle_t req) 649 { 650 blowfish_ctx_t blowfish_ctx; /* on the stack */ 651 off_t saved_offset; 652 size_t saved_length; 653 int ret; 654 655 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 656 657 /* 658 * Plaintext must be a multiple of blowfish block size. 659 * This test only works for non-padded mechanisms 660 * when blocksize is 2^N. 661 */ 662 if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 663 return (CRYPTO_DATA_LEN_RANGE); 664 665 /* return length needed to store the output */ 666 if (ciphertext->cd_length < plaintext->cd_length) { 667 ciphertext->cd_length = plaintext->cd_length; 668 return (CRYPTO_BUFFER_TOO_SMALL); 669 } 670 671 if (!BLOWFISH_VALID_MECH(mechanism)) 672 return (CRYPTO_MECHANISM_INVALID); 673 674 if (mechanism->cm_param_len != 0 && 675 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 676 return (CRYPTO_MECHANISM_PARAM_INVALID); 677 678 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 679 680 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 681 key, crypto_kmflag(req)); 682 if (ret != CRYPTO_SUCCESS) 683 return (ret); 684 685 saved_offset = ciphertext->cd_offset; 686 saved_length = ciphertext->cd_length; 687 688 /* 689 * Do an update on the specified input data. 690 */ 691 switch (plaintext->cd_format) { 692 case CRYPTO_DATA_RAW: 693 ret = crypto_update_iov(&blowfish_ctx, 694 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 695 blowfish_copy_block64); 696 break; 697 case CRYPTO_DATA_UIO: 698 ret = crypto_update_uio(&blowfish_ctx, 699 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 700 blowfish_copy_block64); 701 break; 702 case CRYPTO_DATA_MBLK: 703 ret = crypto_update_mp((void *)&blowfish_ctx, 704 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 705 blowfish_copy_block64); 706 break; 707 default: 708 ret = CRYPTO_ARGUMENTS_BAD; 709 } 710 711 if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 712 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 713 kmem_free(blowfish_ctx.bc_keysched, 714 blowfish_ctx.bc_keysched_len); 715 } 716 717 if (ret == CRYPTO_SUCCESS) { 718 ASSERT(blowfish_ctx.bc_remainder_len == 0); 719 if (plaintext != ciphertext) 720 ciphertext->cd_length = 721 ciphertext->cd_offset - saved_offset; 722 } else { 723 ciphertext->cd_length = saved_length; 724 } 725 ciphertext->cd_offset = saved_offset; 726 727 return (ret); 728 } 729 730 /* ARGSUSED */ 731 static int 732 blowfish_decrypt_atomic(crypto_provider_handle_t provider, 733 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 734 crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext, 735 crypto_spi_ctx_template_t template, crypto_req_handle_t req) 736 { 737 blowfish_ctx_t blowfish_ctx; /* on the stack */ 738 off_t saved_offset; 739 size_t saved_length; 740 int ret; 741 742 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 743 744 /* 745 * Ciphertext must be a multiple of blowfish block size. 746 * This test only works for non-padded mechanisms 747 * when blocksize is 2^N. 748 */ 749 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 750 return (CRYPTO_DATA_LEN_RANGE); 751 752 /* return length needed to store the output */ 753 if (plaintext->cd_length < ciphertext->cd_length) { 754 plaintext->cd_length = ciphertext->cd_length; 755 return (CRYPTO_BUFFER_TOO_SMALL); 756 } 757 758 if (!BLOWFISH_VALID_MECH(mechanism)) 759 return (CRYPTO_MECHANISM_INVALID); 760 761 if (mechanism->cm_param_len != 0 && 762 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 763 return (CRYPTO_MECHANISM_PARAM_INVALID); 764 765 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 766 767 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 768 key, crypto_kmflag(req)); 769 if (ret != CRYPTO_SUCCESS) 770 return (ret); 771 772 saved_offset = plaintext->cd_offset; 773 saved_length = plaintext->cd_length; 774 775 /* 776 * Do an update on the specified input data. 777 */ 778 switch (ciphertext->cd_format) { 779 case CRYPTO_DATA_RAW: 780 ret = crypto_update_iov(&blowfish_ctx, 781 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 782 blowfish_copy_block64); 783 break; 784 case CRYPTO_DATA_UIO: 785 ret = crypto_update_uio(&blowfish_ctx, 786 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 787 blowfish_copy_block64); 788 break; 789 case CRYPTO_DATA_MBLK: 790 ret = crypto_update_mp(&blowfish_ctx, 791 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 792 blowfish_copy_block64); 793 break; 794 default: 795 ret = CRYPTO_ARGUMENTS_BAD; 796 } 797 798 if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 799 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 800 kmem_free(blowfish_ctx.bc_keysched, 801 blowfish_ctx.bc_keysched_len); 802 } 803 804 if (ret == CRYPTO_SUCCESS) { 805 ASSERT(blowfish_ctx.bc_remainder_len == 0); 806 if (ciphertext != plaintext) 807 plaintext->cd_length = 808 plaintext->cd_offset - saved_offset; 809 } else { 810 plaintext->cd_length = saved_length; 811 } 812 plaintext->cd_offset = saved_offset; 813 814 return (ret); 815 } 816 817 /* 818 * KCF software provider context template entry points. 819 */ 820 /* ARGSUSED */ 821 static int 822 blowfish_create_ctx_template(crypto_provider_handle_t provider, 823 crypto_mechanism_t *mechanism, crypto_key_t *key, 824 crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req) 825 { 826 827 /* EXPORT DELETE START */ 828 829 void *keysched; 830 size_t size; 831 int rv; 832 833 if (!BLOWFISH_VALID_MECH(mechanism)) 834 return (CRYPTO_MECHANISM_INVALID); 835 836 if ((keysched = blowfish_alloc_keysched(&size, 837 crypto_kmflag(req))) == NULL) { 838 return (CRYPTO_HOST_MEMORY); 839 } 840 841 /* 842 * Initialize key schedule. Key length information is stored 843 * in the key. 844 */ 845 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) { 846 bzero(keysched, size); 847 kmem_free(keysched, size); 848 return (rv); 849 } 850 851 *tmpl = keysched; 852 *tmpl_size = size; 853 854 /* EXPORT DELETE END */ 855 856 return (CRYPTO_SUCCESS); 857 } 858 859 /* ARGSUSED */ 860 static int 861 blowfish_free_context(crypto_ctx_t *ctx) 862 { 863 blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private; 864 865 if (blowfish_ctx != NULL) { 866 if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 867 ASSERT(blowfish_ctx->bc_keysched_len != 0); 868 bzero(blowfish_ctx->bc_keysched, 869 blowfish_ctx->bc_keysched_len); 870 kmem_free(blowfish_ctx->bc_keysched, 871 blowfish_ctx->bc_keysched_len); 872 } 873 crypto_free_mode_ctx(blowfish_ctx); 874 ctx->cc_provider_private = NULL; 875 } 876 877 return (CRYPTO_SUCCESS); 878 } 879 880 /* ARGSUSED */ 881 static int 882 blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx, 883 crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism, 884 crypto_key_t *key, int kmflag) 885 { 886 int rv = CRYPTO_SUCCESS; 887 888 /* EXPORT DELETE START */ 889 890 void *keysched; 891 size_t size; 892 893 if (template == NULL) { 894 if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL) 895 return (CRYPTO_HOST_MEMORY); 896 /* 897 * Initialize key schedule. 898 * Key length is stored in the key. 899 */ 900 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) 901 kmem_free(keysched, size); 902 903 blowfish_ctx->bc_flags |= PROVIDER_OWNS_KEY_SCHEDULE; 904 blowfish_ctx->bc_keysched_len = size; 905 } else { 906 keysched = template; 907 } 908 blowfish_ctx->bc_keysched = keysched; 909 910 switch (mechanism->cm_type) { 911 case BLOWFISH_CBC_MECH_INFO_TYPE: 912 rv = cbc_init_ctx((cbc_ctx_t *)blowfish_ctx, 913 mechanism->cm_param, mechanism->cm_param_len, 914 BLOWFISH_BLOCK_LEN, blowfish_copy_block64); 915 break; 916 case BLOWFISH_ECB_MECH_INFO_TYPE: 917 blowfish_ctx->bc_flags |= ECB_MODE; 918 } 919 920 if (rv != CRYPTO_SUCCESS) { 921 if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 922 bzero(keysched, size); 923 kmem_free(keysched, size); 924 } 925 } 926 927 /* EXPORT DELETE END */ 928 929 return (rv); 930 } 931