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