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 2007 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 <blowfish_impl.h> 43 #include <blowfish_cbc_crypt.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 /* 329 * Allocate a blowfish context. 330 */ 331 kmflag = crypto_kmflag(req); 332 blowfish_ctx = kmem_zalloc(sizeof (blowfish_ctx_t), kmflag); 333 if (blowfish_ctx == NULL) 334 return (CRYPTO_HOST_MEMORY); 335 336 rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism, 337 key, kmflag); 338 if (rv != CRYPTO_SUCCESS) { 339 kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t)); 340 return (rv); 341 } 342 343 ctx->cc_provider_private = blowfish_ctx; 344 345 /* EXPORT DELETE END */ 346 347 return (CRYPTO_SUCCESS); 348 } 349 350 /* 351 * Helper blowfish encrypt update function for iov input data. 352 */ 353 static int 354 blowfish_cipher_update_iov(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input, 355 crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t, 356 crypto_data_t *)) 357 { 358 if (input->cd_miscdata != NULL) { 359 if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) { 360 /* LINTED: pointer alignment */ 361 blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata; 362 } else { 363 uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0]; 364 uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 365 366 BLOWFISH_COPY_BLOCK(miscdata8, iv8); 367 } 368 } 369 370 if (input->cd_raw.iov_len < input->cd_length) 371 return (CRYPTO_ARGUMENTS_BAD); 372 373 return (cipher)(blowfish_ctx, input->cd_raw.iov_base + input->cd_offset, 374 input->cd_length, (input == output) ? NULL : output); 375 } 376 377 /* 378 * Helper blowfish encrypt update function for uio input data. 379 */ 380 static int 381 blowfish_cipher_update_uio(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input, 382 crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t, 383 crypto_data_t *)) 384 { 385 uio_t *uiop = input->cd_uio; 386 off_t offset = input->cd_offset; 387 size_t length = input->cd_length; 388 uint_t vec_idx; 389 size_t cur_len; 390 391 if (input->cd_miscdata != NULL) { 392 if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) { 393 /*LINTED: pointer alignment */ 394 blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata; 395 } else { 396 uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0]; 397 uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 398 399 BLOWFISH_COPY_BLOCK(miscdata8, iv8); 400 } 401 } 402 403 if (input->cd_uio->uio_segflg != UIO_SYSSPACE) { 404 return (CRYPTO_ARGUMENTS_BAD); 405 } 406 407 /* 408 * Jump to the first iovec containing data to be 409 * processed. 410 */ 411 for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && 412 offset >= uiop->uio_iov[vec_idx].iov_len; 413 offset -= uiop->uio_iov[vec_idx++].iov_len) 414 ; 415 if (vec_idx == uiop->uio_iovcnt) { 416 /* 417 * The caller specified an offset that is larger than the 418 * total size of the buffers it provided. 419 */ 420 return (CRYPTO_DATA_LEN_RANGE); 421 } 422 423 /* 424 * Now process the iovecs. 425 */ 426 while (vec_idx < uiop->uio_iovcnt && length > 0) { 427 cur_len = MIN(uiop->uio_iov[vec_idx].iov_len - 428 offset, length); 429 430 (cipher)(blowfish_ctx, uiop->uio_iov[vec_idx].iov_base + 431 offset, cur_len, (input == output) ? NULL : output); 432 433 length -= cur_len; 434 vec_idx++; 435 offset = 0; 436 } 437 438 if (vec_idx == uiop->uio_iovcnt && length > 0) { 439 /* 440 * The end of the specified iovec's was reached but 441 * the length requested could not be processed, i.e. 442 * The caller requested to digest more data than it provided. 443 */ 444 445 return (CRYPTO_DATA_LEN_RANGE); 446 } 447 448 return (CRYPTO_SUCCESS); 449 } 450 451 /* 452 * Helper blowfish encrypt update function for mblk input data. 453 */ 454 static int 455 blowfish_cipher_update_mp(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input, 456 crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t, 457 crypto_data_t *)) 458 { 459 off_t offset = input->cd_offset; 460 size_t length = input->cd_length; 461 mblk_t *mp; 462 size_t cur_len; 463 464 if (input->cd_miscdata != NULL) { 465 if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) { 466 /*LINTED: pointer alignment */ 467 blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata; 468 } else { 469 uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0]; 470 uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 471 472 BLOWFISH_COPY_BLOCK(miscdata8, iv8); 473 } 474 } 475 476 /* 477 * Jump to the first mblk_t containing data to be processed. 478 */ 479 for (mp = input->cd_mp; mp != NULL && offset >= MBLKL(mp); 480 offset -= MBLKL(mp), mp = mp->b_cont) 481 ; 482 if (mp == NULL) { 483 /* 484 * The caller specified an offset that is larger than the 485 * total size of the buffers it provided. 486 */ 487 return (CRYPTO_DATA_LEN_RANGE); 488 } 489 490 /* 491 * Now do the processing on the mblk chain. 492 */ 493 while (mp != NULL && length > 0) { 494 cur_len = MIN(MBLKL(mp) - offset, length); 495 (cipher)(blowfish_ctx, (char *)(mp->b_rptr + offset), cur_len, 496 (input == output) ? NULL : output); 497 498 length -= cur_len; 499 offset = 0; 500 mp = mp->b_cont; 501 } 502 503 if (mp == NULL && length > 0) { 504 /* 505 * The end of the mblk was reached but the length requested 506 * could not be processed, i.e. The caller requested 507 * to digest more data than it provided. 508 */ 509 return (CRYPTO_DATA_LEN_RANGE); 510 } 511 512 return (CRYPTO_SUCCESS); 513 } 514 515 /* ARGSUSED */ 516 static int 517 blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext, 518 crypto_data_t *ciphertext, crypto_req_handle_t req) 519 { 520 int ret; 521 522 /* EXPORT DELETE START */ 523 524 blowfish_ctx_t *blowfish_ctx; 525 526 /* 527 * Plaintext must be a multiple of blowfish block size. 528 * This test only works for non-padded mechanisms 529 * when blocksize is 2^N. 530 */ 531 if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 532 return (CRYPTO_DATA_LEN_RANGE); 533 534 ASSERT(ctx->cc_provider_private != NULL); 535 blowfish_ctx = ctx->cc_provider_private; 536 537 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 538 539 /* 540 * We need to just return the length needed to store the output. 541 * We should not destroy the context for the following case. 542 */ 543 if (ciphertext->cd_length < plaintext->cd_length) { 544 ciphertext->cd_length = plaintext->cd_length; 545 return (CRYPTO_BUFFER_TOO_SMALL); 546 } 547 548 /* 549 * Do an update on the specified input data. 550 */ 551 ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, req); 552 ASSERT(blowfish_ctx->bc_remainder_len == 0); 553 (void) blowfish_free_context(ctx); 554 555 /* EXPORT DELETE END */ 556 557 /* LINTED */ 558 return (ret); 559 } 560 561 /* ARGSUSED */ 562 static int 563 blowfish_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 564 crypto_data_t *plaintext, crypto_req_handle_t req) 565 { 566 int ret; 567 568 /* EXPORT DELETE START */ 569 570 blowfish_ctx_t *blowfish_ctx; 571 572 /* 573 * Ciphertext must be a multiple of blowfish block size. 574 * This test only works for non-padded mechanisms 575 * when blocksize is 2^N. 576 */ 577 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 578 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 579 580 ASSERT(ctx->cc_provider_private != NULL); 581 blowfish_ctx = ctx->cc_provider_private; 582 583 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 584 585 /* 586 * We need to just return the length needed to store the output. 587 * We should not destroy the context for the following case. 588 */ 589 if (plaintext->cd_length < ciphertext->cd_length) { 590 plaintext->cd_length = ciphertext->cd_length; 591 return (CRYPTO_BUFFER_TOO_SMALL); 592 } 593 594 /* 595 * Do an update on the specified input data. 596 */ 597 ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, req); 598 ASSERT(blowfish_ctx->bc_remainder_len == 0); 599 (void) blowfish_free_context(ctx); 600 601 /* EXPORT DELETE END */ 602 603 /* LINTED */ 604 return (ret); 605 } 606 607 /* ARGSUSED */ 608 static int 609 blowfish_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext, 610 crypto_data_t *ciphertext, crypto_req_handle_t req) 611 { 612 off_t saved_offset; 613 size_t saved_length, out_len; 614 int ret = CRYPTO_SUCCESS; 615 616 ASSERT(ctx->cc_provider_private != NULL); 617 618 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 619 620 /* compute number of bytes that will hold the ciphertext */ 621 out_len = 622 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 623 out_len += plaintext->cd_length; 624 out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 625 626 /* return length needed to store the output */ 627 if (ciphertext->cd_length < out_len) { 628 ciphertext->cd_length = out_len; 629 return (CRYPTO_BUFFER_TOO_SMALL); 630 } 631 632 saved_offset = ciphertext->cd_offset; 633 saved_length = ciphertext->cd_length; 634 635 /* 636 * Do the blowfish update on the specified input data. 637 */ 638 switch (plaintext->cd_format) { 639 case CRYPTO_DATA_RAW: 640 ret = blowfish_cipher_update_iov(ctx->cc_provider_private, 641 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 642 break; 643 case CRYPTO_DATA_UIO: 644 ret = blowfish_cipher_update_uio(ctx->cc_provider_private, 645 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 646 break; 647 case CRYPTO_DATA_MBLK: 648 ret = blowfish_cipher_update_mp(ctx->cc_provider_private, 649 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 650 break; 651 default: 652 ret = CRYPTO_ARGUMENTS_BAD; 653 } 654 655 if (ret == CRYPTO_SUCCESS) { 656 if (plaintext != ciphertext) 657 ciphertext->cd_length = 658 ciphertext->cd_offset - saved_offset; 659 } else { 660 ciphertext->cd_length = saved_length; 661 } 662 ciphertext->cd_offset = saved_offset; 663 664 return (ret); 665 } 666 667 /* ARGSUSED */ 668 static int 669 blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 670 crypto_data_t *plaintext, crypto_req_handle_t req) 671 { 672 off_t saved_offset; 673 size_t saved_length, out_len; 674 int ret = CRYPTO_SUCCESS; 675 676 ASSERT(ctx->cc_provider_private != NULL); 677 678 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 679 680 /* compute number of bytes that will hold the plaintext */ 681 out_len = 682 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 683 out_len += ciphertext->cd_length; 684 out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 685 686 /* return length needed to store the output */ 687 if (plaintext->cd_length < out_len) { 688 plaintext->cd_length = out_len; 689 return (CRYPTO_BUFFER_TOO_SMALL); 690 } 691 692 saved_offset = plaintext->cd_offset; 693 saved_length = plaintext->cd_length; 694 695 /* 696 * Do the blowfish update on the specified input data. 697 */ 698 switch (ciphertext->cd_format) { 699 case CRYPTO_DATA_RAW: 700 ret = blowfish_cipher_update_iov(ctx->cc_provider_private, 701 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 702 break; 703 case CRYPTO_DATA_UIO: 704 ret = blowfish_cipher_update_uio(ctx->cc_provider_private, 705 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 706 break; 707 case CRYPTO_DATA_MBLK: 708 ret = blowfish_cipher_update_mp(ctx->cc_provider_private, 709 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 710 break; 711 default: 712 ret = CRYPTO_ARGUMENTS_BAD; 713 } 714 715 if (ret == CRYPTO_SUCCESS) { 716 if (ciphertext != plaintext) 717 plaintext->cd_length = 718 plaintext->cd_offset - saved_offset; 719 } else { 720 plaintext->cd_length = saved_length; 721 } 722 plaintext->cd_offset = saved_offset; 723 724 return (ret); 725 } 726 727 /* ARGSUSED */ 728 static int 729 blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 730 crypto_req_handle_t req) 731 { 732 733 /* EXPORT DELETE START */ 734 735 blowfish_ctx_t *blowfish_ctx; 736 737 ASSERT(ctx->cc_provider_private != NULL); 738 blowfish_ctx = ctx->cc_provider_private; 739 740 /* 741 * There must be no unprocessed data. 742 * This happens if the length of the last data is 743 * not a multiple of the BLOWFISH block length. 744 */ 745 if (blowfish_ctx->bc_remainder_len > 0) 746 return (CRYPTO_DATA_LEN_RANGE); 747 748 (void) blowfish_free_context(ctx); 749 data->cd_length = 0; 750 751 /* EXPORT DELETE END */ 752 753 return (CRYPTO_SUCCESS); 754 } 755 756 /* ARGSUSED */ 757 static int 758 blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 759 crypto_req_handle_t req) 760 { 761 762 /* EXPORT DELETE START */ 763 764 blowfish_ctx_t *blowfish_ctx; 765 766 ASSERT(ctx->cc_provider_private != NULL); 767 blowfish_ctx = ctx->cc_provider_private; 768 769 /* 770 * There must be no unprocessed ciphertext. 771 * This happens if the length of the last ciphertext is 772 * not a multiple of the BLOWFISH block length. 773 */ 774 if (blowfish_ctx->bc_remainder_len > 0) 775 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 776 777 (void) blowfish_free_context(ctx); 778 data->cd_length = 0; 779 780 /* EXPORT DELETE END */ 781 782 return (CRYPTO_SUCCESS); 783 } 784 785 /* ARGSUSED */ 786 static int 787 blowfish_encrypt_atomic(crypto_provider_handle_t provider, 788 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 789 crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext, 790 crypto_spi_ctx_template_t template, crypto_req_handle_t req) 791 { 792 blowfish_ctx_t blowfish_ctx; /* on the stack */ 793 off_t saved_offset; 794 size_t saved_length; 795 int ret; 796 797 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 798 799 /* 800 * Plaintext must be a multiple of blowfish block size. 801 * This test only works for non-padded mechanisms 802 * when blocksize is 2^N. 803 */ 804 if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 805 return (CRYPTO_DATA_LEN_RANGE); 806 807 /* return length needed to store the output */ 808 if (ciphertext->cd_length < plaintext->cd_length) { 809 ciphertext->cd_length = plaintext->cd_length; 810 return (CRYPTO_BUFFER_TOO_SMALL); 811 } 812 813 if (!BLOWFISH_VALID_MECH(mechanism)) 814 return (CRYPTO_MECHANISM_INVALID); 815 816 if (mechanism->cm_param_len != 0 && 817 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 818 return (CRYPTO_MECHANISM_PARAM_INVALID); 819 820 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 821 822 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 823 key, crypto_kmflag(req)); 824 if (ret != CRYPTO_SUCCESS) 825 return (ret); 826 827 saved_offset = ciphertext->cd_offset; 828 saved_length = ciphertext->cd_length; 829 830 /* 831 * Do an update on the specified input data. 832 */ 833 switch (plaintext->cd_format) { 834 case CRYPTO_DATA_RAW: 835 ret = blowfish_cipher_update_iov(&blowfish_ctx, 836 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 837 break; 838 case CRYPTO_DATA_UIO: 839 ret = blowfish_cipher_update_uio(&blowfish_ctx, 840 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 841 break; 842 case CRYPTO_DATA_MBLK: 843 ret = blowfish_cipher_update_mp(&blowfish_ctx, 844 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 845 break; 846 default: 847 ret = CRYPTO_ARGUMENTS_BAD; 848 } 849 850 if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 851 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 852 kmem_free(blowfish_ctx.bc_keysched, 853 blowfish_ctx.bc_keysched_len); 854 } 855 856 if (ret == CRYPTO_SUCCESS) { 857 ASSERT(blowfish_ctx.bc_remainder_len == 0); 858 if (plaintext != ciphertext) 859 ciphertext->cd_length = 860 ciphertext->cd_offset - saved_offset; 861 } else { 862 ciphertext->cd_length = saved_length; 863 } 864 ciphertext->cd_offset = saved_offset; 865 866 return (ret); 867 } 868 869 /* ARGSUSED */ 870 static int 871 blowfish_decrypt_atomic(crypto_provider_handle_t provider, 872 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 873 crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext, 874 crypto_spi_ctx_template_t template, crypto_req_handle_t req) 875 { 876 blowfish_ctx_t blowfish_ctx; /* on the stack */ 877 off_t saved_offset; 878 size_t saved_length; 879 int ret; 880 881 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 882 883 /* 884 * Ciphertext must be a multiple of blowfish block size. 885 * This test only works for non-padded mechanisms 886 * when blocksize is 2^N. 887 */ 888 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 889 return (CRYPTO_DATA_LEN_RANGE); 890 891 /* return length needed to store the output */ 892 if (plaintext->cd_length < ciphertext->cd_length) { 893 plaintext->cd_length = ciphertext->cd_length; 894 return (CRYPTO_BUFFER_TOO_SMALL); 895 } 896 897 if (!BLOWFISH_VALID_MECH(mechanism)) 898 return (CRYPTO_MECHANISM_INVALID); 899 900 if (mechanism->cm_param_len != 0 && 901 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 902 return (CRYPTO_MECHANISM_PARAM_INVALID); 903 904 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 905 906 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 907 key, crypto_kmflag(req)); 908 if (ret != CRYPTO_SUCCESS) 909 return (ret); 910 911 saved_offset = plaintext->cd_offset; 912 saved_length = plaintext->cd_length; 913 914 /* 915 * Do an update on the specified input data. 916 */ 917 switch (ciphertext->cd_format) { 918 case CRYPTO_DATA_RAW: 919 ret = blowfish_cipher_update_iov(&blowfish_ctx, 920 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 921 break; 922 case CRYPTO_DATA_UIO: 923 ret = blowfish_cipher_update_uio(&blowfish_ctx, 924 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 925 break; 926 case CRYPTO_DATA_MBLK: 927 ret = blowfish_cipher_update_mp(&blowfish_ctx, 928 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 929 break; 930 default: 931 ret = CRYPTO_ARGUMENTS_BAD; 932 } 933 934 if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 935 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 936 kmem_free(blowfish_ctx.bc_keysched, 937 blowfish_ctx.bc_keysched_len); 938 } 939 940 if (ret == CRYPTO_SUCCESS) { 941 ASSERT(blowfish_ctx.bc_remainder_len == 0); 942 if (ciphertext != plaintext) 943 plaintext->cd_length = 944 plaintext->cd_offset - saved_offset; 945 } else { 946 plaintext->cd_length = saved_length; 947 } 948 plaintext->cd_offset = saved_offset; 949 950 return (ret); 951 } 952 953 /* 954 * KCF software provider context template entry points. 955 */ 956 /* ARGSUSED */ 957 static int 958 blowfish_create_ctx_template(crypto_provider_handle_t provider, 959 crypto_mechanism_t *mechanism, crypto_key_t *key, 960 crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req) 961 { 962 963 /* EXPORT DELETE START */ 964 965 void *keysched; 966 size_t size; 967 int rv; 968 969 if (!BLOWFISH_VALID_MECH(mechanism)) 970 return (CRYPTO_MECHANISM_INVALID); 971 972 if ((keysched = blowfish_alloc_keysched(&size, 973 crypto_kmflag(req))) == NULL) { 974 return (CRYPTO_HOST_MEMORY); 975 } 976 977 /* 978 * Initialize key schedule. Key length information is stored 979 * in the key. 980 */ 981 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) { 982 bzero(keysched, size); 983 kmem_free(keysched, size); 984 return (rv); 985 } 986 987 *tmpl = keysched; 988 *tmpl_size = size; 989 990 /* EXPORT DELETE END */ 991 992 return (CRYPTO_SUCCESS); 993 } 994 995 /* ARGSUSED */ 996 static int 997 blowfish_free_context(crypto_ctx_t *ctx) 998 { 999 blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private; 1000 1001 if (blowfish_ctx != NULL) { 1002 if (blowfish_ctx->bc_flags & 1003 BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 1004 ASSERT(blowfish_ctx->bc_keysched_len != 0); 1005 bzero(blowfish_ctx->bc_keysched, 1006 blowfish_ctx->bc_keysched_len); 1007 kmem_free(blowfish_ctx->bc_keysched, 1008 blowfish_ctx->bc_keysched_len); 1009 } 1010 kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t)); 1011 ctx->cc_provider_private = NULL; 1012 } 1013 1014 return (CRYPTO_SUCCESS); 1015 } 1016 1017 /* ARGSUSED */ 1018 static int 1019 blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx, 1020 crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism, 1021 crypto_key_t *key, int kmflag) 1022 { 1023 int rv = CRYPTO_SUCCESS; 1024 1025 /* EXPORT DELETE START */ 1026 1027 void *keysched; 1028 size_t size; 1029 1030 if (template == NULL) { 1031 if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL) 1032 return (CRYPTO_HOST_MEMORY); 1033 /* 1034 * Initialize key schedule. 1035 * Key length is stored in the key. 1036 */ 1037 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) 1038 kmem_free(keysched, size); 1039 1040 blowfish_ctx->bc_flags = BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE; 1041 blowfish_ctx->bc_keysched_len = size; 1042 } else { 1043 keysched = template; 1044 } 1045 1046 if (mechanism->cm_type == BLOWFISH_CBC_MECH_INFO_TYPE) { 1047 /* 1048 * Copy IV into BLOWFISH context. 1049 * 1050 * If cm_param == NULL then the IV comes from the 1051 * cd_miscdata field in the crypto_data structure. 1052 */ 1053 if (mechanism->cm_param != NULL) { 1054 ASSERT(mechanism->cm_param_len == BLOWFISH_BLOCK_LEN); 1055 if (IS_P2ALIGNED(mechanism->cm_param, 1056 sizeof (uint64_t))) { 1057 /* LINTED: pointer alignment */ 1058 blowfish_ctx->bc_iv = 1059 *(uint64_t *)mechanism->cm_param; 1060 } else { 1061 uint8_t *iv8; 1062 uint8_t *p8; 1063 iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 1064 p8 = (uint8_t *)&mechanism->cm_param[0]; 1065 1066 BLOWFISH_COPY_BLOCK(p8, iv8); 1067 } 1068 } 1069 1070 blowfish_ctx->bc_lastp = (uint8_t *)&blowfish_ctx->bc_iv; 1071 blowfish_ctx->bc_flags |= BLOWFISH_CBC_MODE; 1072 } 1073 blowfish_ctx->bc_keysched = keysched; 1074 1075 /* EXPORT DELETE END */ 1076 1077 return (rv); 1078 } 1079