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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 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 <blowfish_impl.h> 44 #include <blowfish_cbc_crypt.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 %I%" 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 /* 208 * Register with KCF. If the registration fails, return error. 209 */ 210 if ((ret = crypto_register_provider(&blowfish_prov_info, 211 &blowfish_prov_handle)) != CRYPTO_SUCCESS) { 212 cmn_err(CE_WARN, "%s _init: crypto_register_provider() " 213 "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret); 214 return (EACCES); 215 } 216 217 if ((ret = mod_install(&modlinkage)) != 0) { 218 int rv; 219 220 ASSERT(blowfish_prov_handle != NULL); 221 /* We should not return if the unregister returns busy. */ 222 while ((rv = crypto_unregister_provider(blowfish_prov_handle)) 223 == CRYPTO_BUSY) { 224 cmn_err(CE_WARN, 225 "%s _init: crypto_unregister_provider() " 226 "failed (0x%x). Retrying.", 227 CRYPTO_PROVIDER_NAME, rv); 228 /* wait 10 seconds and try again */ 229 delay(10 * drv_usectohz(1000000)); 230 } 231 } 232 233 return (ret); 234 } 235 236 int 237 _fini(void) 238 { 239 int ret; 240 241 /* 242 * Unregister from KCF if previous registration succeeded. 243 */ 244 if (blowfish_prov_handle != NULL) { 245 if ((ret = crypto_unregister_provider(blowfish_prov_handle)) != 246 CRYPTO_SUCCESS) { 247 cmn_err(CE_WARN, 248 "%s _fini: crypto_unregister_provider() " 249 "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret); 250 return (EBUSY); 251 } 252 blowfish_prov_handle = NULL; 253 } 254 255 return (mod_remove(&modlinkage)); 256 } 257 258 int 259 _info(struct modinfo *modinfop) 260 { 261 return (mod_info(&modlinkage, modinfop)); 262 } 263 264 /* 265 * Initialize key schedules for blowfish 266 */ 267 static int 268 init_keysched(crypto_key_t *key, void *keysched) 269 { 270 /* EXPORT DELETE START */ 271 /* 272 * Only keys by value are supported by this module. 273 */ 274 switch (key->ck_format) { 275 case CRYPTO_KEY_RAW: 276 if (key->ck_length < BLOWFISH_MINBITS || 277 key->ck_length > BLOWFISH_MAXBITS) { 278 return (CRYPTO_KEY_SIZE_RANGE); 279 } 280 break; 281 default: 282 return (CRYPTO_KEY_TYPE_INCONSISTENT); 283 } 284 285 blowfish_init_keysched(key->ck_data, key->ck_length, keysched); 286 /* EXPORT DELETE END */ 287 return (CRYPTO_SUCCESS); 288 } 289 290 /* 291 * KCF software provider control entry points. 292 */ 293 /* ARGSUSED */ 294 static void 295 blowfish_provider_status(crypto_provider_handle_t provider, uint_t *status) 296 { 297 *status = CRYPTO_PROVIDER_READY; 298 } 299 300 /* 301 * KCF software provider encrypt entry points. 302 */ 303 static int 304 blowfish_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 305 crypto_key_t *key, crypto_spi_ctx_template_t template, 306 crypto_req_handle_t req) 307 { 308 309 /* EXPORT DELETE START */ 310 311 blowfish_ctx_t *blowfish_ctx; 312 int rv; 313 int kmflag; 314 315 /* 316 * Only keys by value are supported by this module. 317 */ 318 if (key->ck_format != CRYPTO_KEY_RAW) { 319 return (CRYPTO_KEY_TYPE_INCONSISTENT); 320 } 321 322 if (!BLOWFISH_VALID_MECH(mechanism)) 323 return (CRYPTO_MECHANISM_INVALID); 324 325 if (mechanism->cm_param != NULL && 326 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 327 return (CRYPTO_MECHANISM_PARAM_INVALID); 328 329 /* 330 * Allocate a blowfish context. 331 */ 332 kmflag = crypto_kmflag(req); 333 blowfish_ctx = kmem_zalloc(sizeof (blowfish_ctx_t), kmflag); 334 if (blowfish_ctx == NULL) 335 return (CRYPTO_HOST_MEMORY); 336 337 rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism, 338 key, kmflag); 339 if (rv != CRYPTO_SUCCESS) { 340 kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t)); 341 return (rv); 342 } 343 344 ctx->cc_provider_private = blowfish_ctx; 345 346 /* EXPORT DELETE END */ 347 348 return (CRYPTO_SUCCESS); 349 } 350 351 /* 352 * Helper blowfish encrypt update function for iov input data. 353 */ 354 static int 355 blowfish_cipher_update_iov(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input, 356 crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t, 357 crypto_data_t *)) 358 { 359 if (input->cd_miscdata != NULL) { 360 if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) { 361 /* LINTED: pointer alignment */ 362 blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata; 363 } else { 364 uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0]; 365 uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 366 367 BLOWFISH_COPY_BLOCK(miscdata8, iv8); 368 } 369 } 370 371 if (input->cd_raw.iov_len < input->cd_length) 372 return (CRYPTO_ARGUMENTS_BAD); 373 374 return (cipher)(blowfish_ctx, input->cd_raw.iov_base + input->cd_offset, 375 input->cd_length, (input == output) ? NULL : output); 376 } 377 378 /* 379 * Helper blowfish encrypt update function for uio input data. 380 */ 381 static int 382 blowfish_cipher_update_uio(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input, 383 crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t, 384 crypto_data_t *)) 385 { 386 uio_t *uiop = input->cd_uio; 387 off_t offset = input->cd_offset; 388 size_t length = input->cd_length; 389 uint_t vec_idx; 390 size_t cur_len; 391 392 if (input->cd_miscdata != NULL) { 393 if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) { 394 /*LINTED: pointer alignment */ 395 blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata; 396 } else { 397 uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0]; 398 uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 399 400 BLOWFISH_COPY_BLOCK(miscdata8, iv8); 401 } 402 } 403 404 if (input->cd_uio->uio_segflg != UIO_SYSSPACE) { 405 return (CRYPTO_ARGUMENTS_BAD); 406 } 407 408 /* 409 * Jump to the first iovec containing data to be 410 * processed. 411 */ 412 for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && 413 offset >= uiop->uio_iov[vec_idx].iov_len; 414 offset -= uiop->uio_iov[vec_idx++].iov_len); 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 if (mp == NULL) { 482 /* 483 * The caller specified an offset that is larger than the 484 * total size of the buffers it provided. 485 */ 486 return (CRYPTO_DATA_LEN_RANGE); 487 } 488 489 /* 490 * Now do the processing on the mblk chain. 491 */ 492 while (mp != NULL && length > 0) { 493 cur_len = MIN(MBLKL(mp) - offset, length); 494 (cipher)(blowfish_ctx, (char *)(mp->b_rptr + offset), cur_len, 495 (input == output) ? NULL : output); 496 497 length -= cur_len; 498 offset = 0; 499 mp = mp->b_cont; 500 } 501 502 if (mp == NULL && length > 0) { 503 /* 504 * The end of the mblk was reached but the length requested 505 * could not be processed, i.e. The caller requested 506 * to digest more data than it provided. 507 */ 508 return (CRYPTO_DATA_LEN_RANGE); 509 } 510 511 return (CRYPTO_SUCCESS); 512 } 513 514 /* ARGSUSED */ 515 static int 516 blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext, 517 crypto_data_t *ciphertext, crypto_req_handle_t req) 518 { 519 int ret; 520 521 /* EXPORT DELETE START */ 522 523 blowfish_ctx_t *blowfish_ctx; 524 525 /* 526 * Plaintext must be a multiple of blowfish block size. 527 * This test only works for non-padded mechanisms 528 * when blocksize is 2^N. 529 */ 530 if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 531 return (CRYPTO_DATA_LEN_RANGE); 532 533 ASSERT(ctx->cc_provider_private != NULL); 534 blowfish_ctx = ctx->cc_provider_private; 535 536 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 537 538 /* 539 * We need to just return the length needed to store the output. 540 * We should not destroy the context for the following case. 541 */ 542 if (ciphertext->cd_length < plaintext->cd_length) { 543 ciphertext->cd_length = plaintext->cd_length; 544 return (CRYPTO_BUFFER_TOO_SMALL); 545 } 546 547 /* 548 * Do an update on the specified input data. 549 */ 550 ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, req); 551 ASSERT(blowfish_ctx->bc_remainder_len == 0); 552 (void) blowfish_free_context(ctx); 553 554 /* EXPORT DELETE END */ 555 556 /* LINTED */ 557 return (ret); 558 } 559 560 /* ARGSUSED */ 561 static int 562 blowfish_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 563 crypto_data_t *plaintext, crypto_req_handle_t req) 564 { 565 int ret; 566 567 /* EXPORT DELETE START */ 568 569 blowfish_ctx_t *blowfish_ctx; 570 571 /* 572 * Ciphertext must be a multiple of blowfish block size. 573 * This test only works for non-padded mechanisms 574 * when blocksize is 2^N. 575 */ 576 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 577 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 578 579 ASSERT(ctx->cc_provider_private != NULL); 580 blowfish_ctx = ctx->cc_provider_private; 581 582 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 583 584 /* 585 * We need to just return the length needed to store the output. 586 * We should not destroy the context for the following case. 587 */ 588 if (plaintext->cd_length < ciphertext->cd_length) { 589 plaintext->cd_length = ciphertext->cd_length; 590 return (CRYPTO_BUFFER_TOO_SMALL); 591 } 592 593 /* 594 * Do an update on the specified input data. 595 */ 596 ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, req); 597 ASSERT(blowfish_ctx->bc_remainder_len == 0); 598 (void) blowfish_free_context(ctx); 599 600 /* EXPORT DELETE END */ 601 602 /* LINTED */ 603 return (ret); 604 } 605 606 /* ARGSUSED */ 607 static int 608 blowfish_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext, 609 crypto_data_t *ciphertext, crypto_req_handle_t req) 610 { 611 off_t saved_offset; 612 size_t saved_length, out_len; 613 int ret = CRYPTO_SUCCESS; 614 615 ASSERT(ctx->cc_provider_private != NULL); 616 617 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 618 619 /* compute number of bytes that will hold the ciphertext */ 620 out_len = 621 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 622 out_len += plaintext->cd_length; 623 out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 624 625 /* return length needed to store the output */ 626 if (ciphertext->cd_length < out_len) { 627 ciphertext->cd_length = out_len; 628 return (CRYPTO_BUFFER_TOO_SMALL); 629 } 630 631 saved_offset = ciphertext->cd_offset; 632 saved_length = ciphertext->cd_length; 633 634 /* 635 * Do the blowfish update on the specified input data. 636 */ 637 switch (plaintext->cd_format) { 638 case CRYPTO_DATA_RAW: 639 ret = blowfish_cipher_update_iov(ctx->cc_provider_private, 640 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 641 break; 642 case CRYPTO_DATA_UIO: 643 ret = blowfish_cipher_update_uio(ctx->cc_provider_private, 644 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 645 break; 646 case CRYPTO_DATA_MBLK: 647 ret = blowfish_cipher_update_mp(ctx->cc_provider_private, 648 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 649 break; 650 default: 651 ret = CRYPTO_ARGUMENTS_BAD; 652 } 653 654 if (ret == CRYPTO_SUCCESS) { 655 if (plaintext != ciphertext) 656 ciphertext->cd_length = 657 ciphertext->cd_offset - saved_offset; 658 } else { 659 ciphertext->cd_length = saved_length; 660 } 661 ciphertext->cd_offset = saved_offset; 662 663 return (ret); 664 } 665 666 /* ARGSUSED */ 667 static int 668 blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 669 crypto_data_t *plaintext, crypto_req_handle_t req) 670 { 671 off_t saved_offset; 672 size_t saved_length, out_len; 673 int ret = CRYPTO_SUCCESS; 674 675 ASSERT(ctx->cc_provider_private != NULL); 676 677 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 678 679 /* compute number of bytes that will hold the plaintext */ 680 out_len = 681 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 682 out_len += ciphertext->cd_length; 683 out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 684 685 /* return length needed to store the output */ 686 if (plaintext->cd_length < out_len) { 687 plaintext->cd_length = out_len; 688 return (CRYPTO_BUFFER_TOO_SMALL); 689 } 690 691 saved_offset = plaintext->cd_offset; 692 saved_length = plaintext->cd_length; 693 694 /* 695 * Do the blowfish update on the specified input data. 696 */ 697 switch (ciphertext->cd_format) { 698 case CRYPTO_DATA_RAW: 699 ret = blowfish_cipher_update_iov(ctx->cc_provider_private, 700 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 701 break; 702 case CRYPTO_DATA_UIO: 703 ret = blowfish_cipher_update_uio(ctx->cc_provider_private, 704 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 705 break; 706 case CRYPTO_DATA_MBLK: 707 ret = blowfish_cipher_update_mp(ctx->cc_provider_private, 708 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 709 break; 710 default: 711 ret = CRYPTO_ARGUMENTS_BAD; 712 } 713 714 if (ret == CRYPTO_SUCCESS) { 715 if (ciphertext != plaintext) 716 plaintext->cd_length = 717 plaintext->cd_offset - saved_offset; 718 } else { 719 plaintext->cd_length = saved_length; 720 } 721 plaintext->cd_offset = saved_offset; 722 723 return (ret); 724 } 725 726 /* ARGSUSED */ 727 static int 728 blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 729 crypto_req_handle_t req) 730 { 731 732 /* EXPORT DELETE START */ 733 734 blowfish_ctx_t *blowfish_ctx; 735 736 ASSERT(ctx->cc_provider_private != NULL); 737 blowfish_ctx = ctx->cc_provider_private; 738 739 /* 740 * There must be no unprocessed data. 741 * This happens if the length of the last data is 742 * not a multiple of the BLOWFISH block length. 743 */ 744 if (blowfish_ctx->bc_remainder_len > 0) 745 return (CRYPTO_DATA_LEN_RANGE); 746 747 (void) blowfish_free_context(ctx); 748 data->cd_length = 0; 749 750 /* EXPORT DELETE END */ 751 752 return (CRYPTO_SUCCESS); 753 } 754 755 /* ARGSUSED */ 756 static int 757 blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 758 crypto_req_handle_t req) 759 { 760 761 /* EXPORT DELETE START */ 762 763 blowfish_ctx_t *blowfish_ctx; 764 765 ASSERT(ctx->cc_provider_private != NULL); 766 blowfish_ctx = ctx->cc_provider_private; 767 768 /* 769 * There must be no unprocessed ciphertext. 770 * This happens if the length of the last ciphertext is 771 * not a multiple of the BLOWFISH block length. 772 */ 773 if (blowfish_ctx->bc_remainder_len > 0) 774 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 775 776 (void) blowfish_free_context(ctx); 777 data->cd_length = 0; 778 779 /* EXPORT DELETE END */ 780 781 return (CRYPTO_SUCCESS); 782 } 783 784 /* ARGSUSED */ 785 static int 786 blowfish_encrypt_atomic(crypto_provider_handle_t provider, 787 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 788 crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext, 789 crypto_spi_ctx_template_t template, crypto_req_handle_t req) 790 { 791 blowfish_ctx_t blowfish_ctx; /* on the stack */ 792 off_t saved_offset; 793 size_t saved_length; 794 int ret; 795 796 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 797 798 /* 799 * Plaintext must be a multiple of blowfish block size. 800 * This test only works for non-padded mechanisms 801 * when blocksize is 2^N. 802 */ 803 if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 804 return (CRYPTO_DATA_LEN_RANGE); 805 806 /* return length needed to store the output */ 807 if (ciphertext->cd_length < plaintext->cd_length) { 808 ciphertext->cd_length = plaintext->cd_length; 809 return (CRYPTO_BUFFER_TOO_SMALL); 810 } 811 812 if (!BLOWFISH_VALID_MECH(mechanism)) 813 return (CRYPTO_MECHANISM_INVALID); 814 815 if (mechanism->cm_param_len != 0 && 816 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 817 return (CRYPTO_MECHANISM_PARAM_INVALID); 818 819 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 820 821 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 822 key, crypto_kmflag(req)); 823 if (ret != CRYPTO_SUCCESS) 824 return (ret); 825 826 saved_offset = ciphertext->cd_offset; 827 saved_length = ciphertext->cd_length; 828 829 /* 830 * Do an update on the specified input data. 831 */ 832 switch (plaintext->cd_format) { 833 case CRYPTO_DATA_RAW: 834 ret = blowfish_cipher_update_iov(&blowfish_ctx, 835 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 836 break; 837 case CRYPTO_DATA_UIO: 838 ret = blowfish_cipher_update_uio(&blowfish_ctx, 839 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 840 break; 841 case CRYPTO_DATA_MBLK: 842 ret = blowfish_cipher_update_mp(&blowfish_ctx, 843 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 844 break; 845 default: 846 ret = CRYPTO_ARGUMENTS_BAD; 847 } 848 849 if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 850 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 851 kmem_free(blowfish_ctx.bc_keysched, 852 blowfish_ctx.bc_keysched_len); 853 } 854 855 if (ret == CRYPTO_SUCCESS) { 856 ASSERT(blowfish_ctx.bc_remainder_len == 0); 857 if (plaintext != ciphertext) 858 ciphertext->cd_length = 859 ciphertext->cd_offset - saved_offset; 860 } else { 861 ciphertext->cd_length = saved_length; 862 } 863 ciphertext->cd_offset = saved_offset; 864 865 return (ret); 866 } 867 868 /* ARGSUSED */ 869 static int 870 blowfish_decrypt_atomic(crypto_provider_handle_t provider, 871 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 872 crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext, 873 crypto_spi_ctx_template_t template, crypto_req_handle_t req) 874 { 875 blowfish_ctx_t blowfish_ctx; /* on the stack */ 876 off_t saved_offset; 877 size_t saved_length; 878 int ret; 879 880 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 881 882 /* 883 * Ciphertext must be a multiple of blowfish block size. 884 * This test only works for non-padded mechanisms 885 * when blocksize is 2^N. 886 */ 887 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 888 return (CRYPTO_DATA_LEN_RANGE); 889 890 /* return length needed to store the output */ 891 if (plaintext->cd_length < ciphertext->cd_length) { 892 plaintext->cd_length = ciphertext->cd_length; 893 return (CRYPTO_BUFFER_TOO_SMALL); 894 } 895 896 if (!BLOWFISH_VALID_MECH(mechanism)) 897 return (CRYPTO_MECHANISM_INVALID); 898 899 if (mechanism->cm_param_len != 0 && 900 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 901 return (CRYPTO_MECHANISM_PARAM_INVALID); 902 903 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 904 905 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 906 key, crypto_kmflag(req)); 907 if (ret != CRYPTO_SUCCESS) 908 return (ret); 909 910 saved_offset = plaintext->cd_offset; 911 saved_length = plaintext->cd_length; 912 913 /* 914 * Do an update on the specified input data. 915 */ 916 switch (ciphertext->cd_format) { 917 case CRYPTO_DATA_RAW: 918 ret = blowfish_cipher_update_iov(&blowfish_ctx, 919 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 920 break; 921 case CRYPTO_DATA_UIO: 922 ret = blowfish_cipher_update_uio(&blowfish_ctx, 923 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 924 break; 925 case CRYPTO_DATA_MBLK: 926 ret = blowfish_cipher_update_mp(&blowfish_ctx, 927 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 928 break; 929 default: 930 ret = CRYPTO_ARGUMENTS_BAD; 931 } 932 933 if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 934 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 935 kmem_free(blowfish_ctx.bc_keysched, 936 blowfish_ctx.bc_keysched_len); 937 } 938 939 if (ret == CRYPTO_SUCCESS) { 940 ASSERT(blowfish_ctx.bc_remainder_len == 0); 941 if (ciphertext != plaintext) 942 plaintext->cd_length = 943 plaintext->cd_offset - saved_offset; 944 } else { 945 plaintext->cd_length = saved_length; 946 } 947 plaintext->cd_offset = saved_offset; 948 949 return (ret); 950 } 951 952 /* 953 * KCF software provider context template entry points. 954 */ 955 /* ARGSUSED */ 956 static int 957 blowfish_create_ctx_template(crypto_provider_handle_t provider, 958 crypto_mechanism_t *mechanism, crypto_key_t *key, 959 crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req) 960 { 961 962 /* EXPORT DELETE START */ 963 964 void *keysched; 965 size_t size; 966 int rv; 967 968 if (!BLOWFISH_VALID_MECH(mechanism)) 969 return (CRYPTO_MECHANISM_INVALID); 970 971 if ((keysched = blowfish_alloc_keysched(&size, 972 crypto_kmflag(req))) == NULL) { 973 return (CRYPTO_HOST_MEMORY); 974 } 975 976 /* 977 * Initialize key schedule. Key length information is stored 978 * in the key. 979 */ 980 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) { 981 bzero(keysched, size); 982 kmem_free(keysched, size); 983 return (rv); 984 } 985 986 *tmpl = keysched; 987 *tmpl_size = size; 988 989 /* EXPORT DELETE END */ 990 991 return (CRYPTO_SUCCESS); 992 } 993 994 /* ARGSUSED */ 995 static int 996 blowfish_free_context(crypto_ctx_t *ctx) 997 { 998 blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private; 999 1000 if (blowfish_ctx != NULL) { 1001 if (blowfish_ctx->bc_flags & 1002 BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 1003 ASSERT(blowfish_ctx->bc_keysched_len != 0); 1004 bzero(blowfish_ctx->bc_keysched, 1005 blowfish_ctx->bc_keysched_len); 1006 kmem_free(blowfish_ctx->bc_keysched, 1007 blowfish_ctx->bc_keysched_len); 1008 } 1009 kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t)); 1010 ctx->cc_provider_private = NULL; 1011 } 1012 1013 return (CRYPTO_SUCCESS); 1014 } 1015 1016 /* ARGSUSED */ 1017 static int 1018 blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx, 1019 crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism, 1020 crypto_key_t *key, int kmflag) 1021 { 1022 int rv = CRYPTO_SUCCESS; 1023 1024 /* EXPORT DELETE START */ 1025 1026 void *keysched; 1027 size_t size; 1028 1029 if (template == NULL) { 1030 if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL) 1031 return (CRYPTO_HOST_MEMORY); 1032 /* 1033 * Initialize key schedule. 1034 * Key length is stored in the key. 1035 */ 1036 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) 1037 kmem_free(keysched, size); 1038 1039 blowfish_ctx->bc_flags = BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE; 1040 blowfish_ctx->bc_keysched_len = size; 1041 } else { 1042 keysched = template; 1043 } 1044 1045 if (mechanism->cm_type == BLOWFISH_CBC_MECH_INFO_TYPE) { 1046 /* 1047 * Copy IV into BLOWFISH context. 1048 * 1049 * If cm_param == NULL then the IV comes from the 1050 * cd_miscdata field in the crypto_data structure. 1051 */ 1052 if (mechanism->cm_param != NULL) { 1053 ASSERT(mechanism->cm_param_len == BLOWFISH_BLOCK_LEN); 1054 if (IS_P2ALIGNED(mechanism->cm_param, 1055 sizeof (uint64_t))) { 1056 /* LINTED: pointer alignment */ 1057 blowfish_ctx->bc_iv = 1058 *(uint64_t *)mechanism->cm_param; 1059 } else { 1060 uint8_t *iv8; 1061 uint8_t *p8; 1062 iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 1063 p8 = (uint8_t *)&mechanism->cm_param[0]; 1064 1065 BLOWFISH_COPY_BLOCK(p8, iv8); 1066 } 1067 } 1068 1069 blowfish_ctx->bc_lastp = (uint8_t *)&blowfish_ctx->bc_iv; 1070 blowfish_ctx->bc_flags |= BLOWFISH_CBC_MODE; 1071 } 1072 blowfish_ctx->bc_keysched = keysched; 1073 1074 /* EXPORT DELETE END */ 1075 1076 return (rv); 1077 } 1078