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 .co_control_ops = &blowfish_control_ops, 170 .co_digest_ops = NULL, 171 .co_cipher_ops = &blowfish_cipher_ops, 172 .co_mac_ops = NULL, 173 .co_sign_ops = NULL, 174 .co_verify_ops = NULL, 175 .co_dual_ops = NULL, 176 .co_dual_cipher_mac_ops = NULL, 177 .co_random_ops = NULL, 178 .co_session_ops = NULL, 179 .co_object_ops = NULL, 180 .co_key_ops = NULL, 181 .co_provider_ops = NULL, 182 .co_ctx_ops = &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 /* 244 * Only keys by value are supported by this module. 245 */ 246 switch (key->ck_format) { 247 case CRYPTO_KEY_RAW: 248 if (key->ck_length < BLOWFISH_MINBITS || 249 key->ck_length > BLOWFISH_MAXBITS) { 250 return (CRYPTO_KEY_SIZE_RANGE); 251 } 252 break; 253 default: 254 return (CRYPTO_KEY_TYPE_INCONSISTENT); 255 } 256 257 blowfish_init_keysched(key->ck_data, key->ck_length, keysched); 258 return (CRYPTO_SUCCESS); 259 } 260 261 /* 262 * KCF software provider control entry points. 263 */ 264 /* ARGSUSED */ 265 static void 266 blowfish_provider_status(crypto_provider_handle_t provider, uint_t *status) 267 { 268 *status = CRYPTO_PROVIDER_READY; 269 } 270 271 /* 272 * KCF software provider encrypt entry points. 273 */ 274 static int 275 blowfish_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 276 crypto_key_t *key, crypto_spi_ctx_template_t template, 277 crypto_req_handle_t req) 278 { 279 blowfish_ctx_t *blowfish_ctx; 280 int rv; 281 int kmflag; 282 283 /* 284 * Only keys by value are supported by this module. 285 */ 286 if (key->ck_format != CRYPTO_KEY_RAW) { 287 return (CRYPTO_KEY_TYPE_INCONSISTENT); 288 } 289 290 if (!BLOWFISH_VALID_MECH(mechanism)) 291 return (CRYPTO_MECHANISM_INVALID); 292 293 if (mechanism->cm_param != NULL && 294 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 295 return (CRYPTO_MECHANISM_PARAM_INVALID); 296 297 kmflag = crypto_kmflag(req); 298 switch (mechanism->cm_type) { 299 case BLOWFISH_ECB_MECH_INFO_TYPE: 300 blowfish_ctx = ecb_alloc_ctx(kmflag); 301 break; 302 case BLOWFISH_CBC_MECH_INFO_TYPE: 303 blowfish_ctx = cbc_alloc_ctx(kmflag); 304 break; 305 } 306 if (blowfish_ctx == NULL) 307 return (CRYPTO_HOST_MEMORY); 308 309 rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism, 310 key, kmflag); 311 if (rv != CRYPTO_SUCCESS) { 312 crypto_free_mode_ctx(blowfish_ctx); 313 return (rv); 314 } 315 316 ctx->cc_provider_private = blowfish_ctx; 317 318 return (CRYPTO_SUCCESS); 319 } 320 321 static void 322 blowfish_copy_block64(uint8_t *in, uint64_t *out) 323 { 324 if (IS_P2ALIGNED(in, sizeof (uint64_t))) { 325 /* LINTED: pointer alignment */ 326 out[0] = *(uint64_t *)&in[0]; 327 } else { 328 uint8_t *iv8 = (uint8_t *)&out[0]; 329 330 BLOWFISH_COPY_BLOCK(in, iv8); 331 } 332 } 333 334 /* ARGSUSED */ 335 static int 336 blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext, 337 crypto_data_t *ciphertext, crypto_req_handle_t req) 338 { 339 int ret; 340 341 blowfish_ctx_t *blowfish_ctx; 342 343 /* 344 * Plaintext must be a multiple of blowfish block size. 345 * This test only works for non-padded mechanisms 346 * when blocksize is 2^N. 347 */ 348 if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 349 return (CRYPTO_DATA_LEN_RANGE); 350 351 ASSERT(ctx->cc_provider_private != NULL); 352 blowfish_ctx = ctx->cc_provider_private; 353 354 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 355 356 /* 357 * We need to just return the length needed to store the output. 358 * We should not destroy the context for the following case. 359 */ 360 if (ciphertext->cd_length < plaintext->cd_length) { 361 ciphertext->cd_length = plaintext->cd_length; 362 return (CRYPTO_BUFFER_TOO_SMALL); 363 } 364 365 /* 366 * Do an update on the specified input data. 367 */ 368 ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, req); 369 ASSERT(blowfish_ctx->bc_remainder_len == 0); 370 (void) blowfish_free_context(ctx); 371 372 /* LINTED */ 373 return (ret); 374 } 375 376 /* ARGSUSED */ 377 static int 378 blowfish_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 379 crypto_data_t *plaintext, crypto_req_handle_t req) 380 { 381 int ret; 382 383 blowfish_ctx_t *blowfish_ctx; 384 385 /* 386 * Ciphertext must be a multiple of blowfish block size. 387 * This test only works for non-padded mechanisms 388 * when blocksize is 2^N. 389 */ 390 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 391 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 392 393 ASSERT(ctx->cc_provider_private != NULL); 394 blowfish_ctx = ctx->cc_provider_private; 395 396 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 397 398 /* 399 * We need to just return the length needed to store the output. 400 * We should not destroy the context for the following case. 401 */ 402 if (plaintext->cd_length < ciphertext->cd_length) { 403 plaintext->cd_length = ciphertext->cd_length; 404 return (CRYPTO_BUFFER_TOO_SMALL); 405 } 406 407 /* 408 * Do an update on the specified input data. 409 */ 410 ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, req); 411 ASSERT(blowfish_ctx->bc_remainder_len == 0); 412 (void) blowfish_free_context(ctx); 413 414 /* LINTED */ 415 return (ret); 416 } 417 418 /* ARGSUSED */ 419 static int 420 blowfish_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext, 421 crypto_data_t *ciphertext, crypto_req_handle_t req) 422 { 423 off_t saved_offset; 424 size_t saved_length, out_len; 425 int ret = CRYPTO_SUCCESS; 426 427 ASSERT(ctx->cc_provider_private != NULL); 428 429 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 430 431 /* compute number of bytes that will hold the ciphertext */ 432 out_len = 433 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 434 out_len += plaintext->cd_length; 435 out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 436 437 /* return length needed to store the output */ 438 if (ciphertext->cd_length < out_len) { 439 ciphertext->cd_length = out_len; 440 return (CRYPTO_BUFFER_TOO_SMALL); 441 } 442 443 saved_offset = ciphertext->cd_offset; 444 saved_length = ciphertext->cd_length; 445 446 /* 447 * Do the blowfish update on the specified input data. 448 */ 449 switch (plaintext->cd_format) { 450 case CRYPTO_DATA_RAW: 451 ret = crypto_update_iov(ctx->cc_provider_private, 452 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 453 blowfish_copy_block64); 454 break; 455 case CRYPTO_DATA_UIO: 456 ret = crypto_update_uio(ctx->cc_provider_private, 457 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 458 blowfish_copy_block64); 459 break; 460 case CRYPTO_DATA_MBLK: 461 ret = crypto_update_mp(ctx->cc_provider_private, 462 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 463 blowfish_copy_block64); 464 break; 465 default: 466 ret = CRYPTO_ARGUMENTS_BAD; 467 } 468 469 if (ret == CRYPTO_SUCCESS) { 470 if (plaintext != ciphertext) 471 ciphertext->cd_length = 472 ciphertext->cd_offset - saved_offset; 473 } else { 474 ciphertext->cd_length = saved_length; 475 } 476 ciphertext->cd_offset = saved_offset; 477 478 return (ret); 479 } 480 481 /* ARGSUSED */ 482 static int 483 blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 484 crypto_data_t *plaintext, crypto_req_handle_t req) 485 { 486 off_t saved_offset; 487 size_t saved_length, out_len; 488 int ret = CRYPTO_SUCCESS; 489 490 ASSERT(ctx->cc_provider_private != NULL); 491 492 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 493 494 /* compute number of bytes that will hold the plaintext */ 495 out_len = 496 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 497 out_len += ciphertext->cd_length; 498 out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 499 500 /* return length needed to store the output */ 501 if (plaintext->cd_length < out_len) { 502 plaintext->cd_length = out_len; 503 return (CRYPTO_BUFFER_TOO_SMALL); 504 } 505 506 saved_offset = plaintext->cd_offset; 507 saved_length = plaintext->cd_length; 508 509 /* 510 * Do the blowfish update on the specified input data. 511 */ 512 switch (ciphertext->cd_format) { 513 case CRYPTO_DATA_RAW: 514 ret = crypto_update_iov(ctx->cc_provider_private, 515 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 516 blowfish_copy_block64); 517 break; 518 case CRYPTO_DATA_UIO: 519 ret = crypto_update_uio(ctx->cc_provider_private, 520 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 521 blowfish_copy_block64); 522 break; 523 case CRYPTO_DATA_MBLK: 524 ret = crypto_update_mp(ctx->cc_provider_private, 525 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 526 blowfish_copy_block64); 527 break; 528 default: 529 ret = CRYPTO_ARGUMENTS_BAD; 530 } 531 532 if (ret == CRYPTO_SUCCESS) { 533 if (ciphertext != plaintext) 534 plaintext->cd_length = 535 plaintext->cd_offset - saved_offset; 536 } else { 537 plaintext->cd_length = saved_length; 538 } 539 plaintext->cd_offset = saved_offset; 540 541 return (ret); 542 } 543 544 /* ARGSUSED */ 545 static int 546 blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 547 crypto_req_handle_t req) 548 { 549 blowfish_ctx_t *blowfish_ctx; 550 551 ASSERT(ctx->cc_provider_private != NULL); 552 blowfish_ctx = ctx->cc_provider_private; 553 554 /* 555 * There must be no unprocessed data. 556 * This happens if the length of the last data is 557 * not a multiple of the BLOWFISH block length. 558 */ 559 if (blowfish_ctx->bc_remainder_len > 0) 560 return (CRYPTO_DATA_LEN_RANGE); 561 562 (void) blowfish_free_context(ctx); 563 data->cd_length = 0; 564 565 return (CRYPTO_SUCCESS); 566 } 567 568 /* ARGSUSED */ 569 static int 570 blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 571 crypto_req_handle_t req) 572 { 573 blowfish_ctx_t *blowfish_ctx; 574 575 ASSERT(ctx->cc_provider_private != NULL); 576 blowfish_ctx = ctx->cc_provider_private; 577 578 /* 579 * There must be no unprocessed ciphertext. 580 * This happens if the length of the last ciphertext is 581 * not a multiple of the BLOWFISH block length. 582 */ 583 if (blowfish_ctx->bc_remainder_len > 0) 584 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 585 586 (void) blowfish_free_context(ctx); 587 data->cd_length = 0; 588 589 return (CRYPTO_SUCCESS); 590 } 591 592 /* ARGSUSED */ 593 static int 594 blowfish_encrypt_atomic(crypto_provider_handle_t provider, 595 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 596 crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext, 597 crypto_spi_ctx_template_t template, crypto_req_handle_t req) 598 { 599 blowfish_ctx_t blowfish_ctx; /* on the stack */ 600 off_t saved_offset; 601 size_t saved_length; 602 int ret; 603 604 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 605 606 /* 607 * Plaintext must be a multiple of blowfish block size. 608 * This test only works for non-padded mechanisms 609 * when blocksize is 2^N. 610 */ 611 if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 612 return (CRYPTO_DATA_LEN_RANGE); 613 614 /* return length needed to store the output */ 615 if (ciphertext->cd_length < plaintext->cd_length) { 616 ciphertext->cd_length = plaintext->cd_length; 617 return (CRYPTO_BUFFER_TOO_SMALL); 618 } 619 620 if (!BLOWFISH_VALID_MECH(mechanism)) 621 return (CRYPTO_MECHANISM_INVALID); 622 623 if (mechanism->cm_param_len != 0 && 624 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 625 return (CRYPTO_MECHANISM_PARAM_INVALID); 626 627 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 628 629 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 630 key, crypto_kmflag(req)); 631 if (ret != CRYPTO_SUCCESS) 632 return (ret); 633 634 saved_offset = ciphertext->cd_offset; 635 saved_length = ciphertext->cd_length; 636 637 /* 638 * Do an update on the specified input data. 639 */ 640 switch (plaintext->cd_format) { 641 case CRYPTO_DATA_RAW: 642 ret = crypto_update_iov(&blowfish_ctx, 643 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 644 blowfish_copy_block64); 645 break; 646 case CRYPTO_DATA_UIO: 647 ret = crypto_update_uio(&blowfish_ctx, 648 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 649 blowfish_copy_block64); 650 break; 651 case CRYPTO_DATA_MBLK: 652 ret = crypto_update_mp((void *)&blowfish_ctx, 653 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks, 654 blowfish_copy_block64); 655 break; 656 default: 657 ret = CRYPTO_ARGUMENTS_BAD; 658 } 659 660 if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 661 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 662 kmem_free(blowfish_ctx.bc_keysched, 663 blowfish_ctx.bc_keysched_len); 664 } 665 666 if (ret == CRYPTO_SUCCESS) { 667 ASSERT(blowfish_ctx.bc_remainder_len == 0); 668 if (plaintext != ciphertext) 669 ciphertext->cd_length = 670 ciphertext->cd_offset - saved_offset; 671 } else { 672 ciphertext->cd_length = saved_length; 673 } 674 ciphertext->cd_offset = saved_offset; 675 676 return (ret); 677 } 678 679 /* ARGSUSED */ 680 static int 681 blowfish_decrypt_atomic(crypto_provider_handle_t provider, 682 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 683 crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext, 684 crypto_spi_ctx_template_t template, crypto_req_handle_t req) 685 { 686 blowfish_ctx_t blowfish_ctx; /* on the stack */ 687 off_t saved_offset; 688 size_t saved_length; 689 int ret; 690 691 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 692 693 /* 694 * Ciphertext must be a multiple of blowfish block size. 695 * This test only works for non-padded mechanisms 696 * when blocksize is 2^N. 697 */ 698 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 699 return (CRYPTO_DATA_LEN_RANGE); 700 701 /* return length needed to store the output */ 702 if (plaintext->cd_length < ciphertext->cd_length) { 703 plaintext->cd_length = ciphertext->cd_length; 704 return (CRYPTO_BUFFER_TOO_SMALL); 705 } 706 707 if (!BLOWFISH_VALID_MECH(mechanism)) 708 return (CRYPTO_MECHANISM_INVALID); 709 710 if (mechanism->cm_param_len != 0 && 711 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 712 return (CRYPTO_MECHANISM_PARAM_INVALID); 713 714 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 715 716 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 717 key, crypto_kmflag(req)); 718 if (ret != CRYPTO_SUCCESS) 719 return (ret); 720 721 saved_offset = plaintext->cd_offset; 722 saved_length = plaintext->cd_length; 723 724 /* 725 * Do an update on the specified input data. 726 */ 727 switch (ciphertext->cd_format) { 728 case CRYPTO_DATA_RAW: 729 ret = crypto_update_iov(&blowfish_ctx, 730 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 731 blowfish_copy_block64); 732 break; 733 case CRYPTO_DATA_UIO: 734 ret = crypto_update_uio(&blowfish_ctx, 735 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 736 blowfish_copy_block64); 737 break; 738 case CRYPTO_DATA_MBLK: 739 ret = crypto_update_mp(&blowfish_ctx, 740 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks, 741 blowfish_copy_block64); 742 break; 743 default: 744 ret = CRYPTO_ARGUMENTS_BAD; 745 } 746 747 if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 748 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 749 kmem_free(blowfish_ctx.bc_keysched, 750 blowfish_ctx.bc_keysched_len); 751 } 752 753 if (ret == CRYPTO_SUCCESS) { 754 ASSERT(blowfish_ctx.bc_remainder_len == 0); 755 if (ciphertext != plaintext) 756 plaintext->cd_length = 757 plaintext->cd_offset - saved_offset; 758 } else { 759 plaintext->cd_length = saved_length; 760 } 761 plaintext->cd_offset = saved_offset; 762 763 return (ret); 764 } 765 766 /* 767 * KCF software provider context template entry points. 768 */ 769 /* ARGSUSED */ 770 static int 771 blowfish_create_ctx_template(crypto_provider_handle_t provider, 772 crypto_mechanism_t *mechanism, crypto_key_t *key, 773 crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req) 774 { 775 void *keysched; 776 size_t size; 777 int rv; 778 779 if (!BLOWFISH_VALID_MECH(mechanism)) 780 return (CRYPTO_MECHANISM_INVALID); 781 782 if ((keysched = blowfish_alloc_keysched(&size, 783 crypto_kmflag(req))) == NULL) { 784 return (CRYPTO_HOST_MEMORY); 785 } 786 787 /* 788 * Initialize key schedule. Key length information is stored 789 * in the key. 790 */ 791 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) { 792 bzero(keysched, size); 793 kmem_free(keysched, size); 794 return (rv); 795 } 796 797 *tmpl = keysched; 798 *tmpl_size = size; 799 800 return (CRYPTO_SUCCESS); 801 } 802 803 /* ARGSUSED */ 804 static int 805 blowfish_free_context(crypto_ctx_t *ctx) 806 { 807 blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private; 808 809 if (blowfish_ctx != NULL) { 810 if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 811 ASSERT(blowfish_ctx->bc_keysched_len != 0); 812 bzero(blowfish_ctx->bc_keysched, 813 blowfish_ctx->bc_keysched_len); 814 kmem_free(blowfish_ctx->bc_keysched, 815 blowfish_ctx->bc_keysched_len); 816 } 817 crypto_free_mode_ctx(blowfish_ctx); 818 ctx->cc_provider_private = NULL; 819 } 820 821 return (CRYPTO_SUCCESS); 822 } 823 824 /* ARGSUSED */ 825 static int 826 blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx, 827 crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism, 828 crypto_key_t *key, int kmflag) 829 { 830 int rv = CRYPTO_SUCCESS; 831 832 void *keysched; 833 size_t size; 834 835 if (template == NULL) { 836 if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL) 837 return (CRYPTO_HOST_MEMORY); 838 /* 839 * Initialize key schedule. 840 * Key length is stored in the key. 841 */ 842 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) 843 kmem_free(keysched, size); 844 845 blowfish_ctx->bc_flags |= PROVIDER_OWNS_KEY_SCHEDULE; 846 blowfish_ctx->bc_keysched_len = size; 847 } else { 848 keysched = template; 849 } 850 blowfish_ctx->bc_keysched = keysched; 851 852 switch (mechanism->cm_type) { 853 case BLOWFISH_CBC_MECH_INFO_TYPE: 854 rv = cbc_init_ctx((cbc_ctx_t *)blowfish_ctx, 855 mechanism->cm_param, mechanism->cm_param_len, 856 BLOWFISH_BLOCK_LEN, blowfish_copy_block64); 857 break; 858 case BLOWFISH_ECB_MECH_INFO_TYPE: 859 blowfish_ctx->bc_flags |= ECB_MODE; 860 } 861 862 if (rv != CRYPTO_SUCCESS) { 863 if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 864 bzero(keysched, size); 865 kmem_free(keysched, size); 866 } 867 } 868 869 return (rv); 870 }