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