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 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 %I%" 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 BF_ECB_MECH_INFO_TYPE, /* SUN_CKM_BF_ECB */ 66 BF_CBC_MECH_INFO_TYPE /* SUN_CKM_BF_CBC */ 67 } blowfish_mech_type_t; 68 69 /* 70 * bc_keysched: Pointer to key schedule. 71 * 72 * bc_keysched_len: Length of the key schedule. 73 * 74 * bc_remainder: This is for residual data, i.e. data that can't 75 * be processed because there are too few bytes. 76 * Must wait until more data arrives. 77 * 78 * bc_remainder_len: Number of bytes in bc_remainder. 79 * 80 * bc_iv: Scratch buffer that sometimes contains the IV. 81 * 82 * bc_lastblock: Scratch buffer. 83 * 84 * bc_lastp: Pointer to previous block of ciphertext. 85 * 86 * bc_copy_to: Pointer to where encrypted residual data needs 87 * to be copied. 88 * 89 * bc_flags: BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE 90 * When a context is freed, it is necessary 91 * to know whether the key schedule was allocated 92 * by the caller, or by blowfish_common_init(). 93 * If allocated by the latter, then it needs to be freed. 94 * 95 * BLOWFISH_CBC_MODE 96 * If flag is not set, the mode is BLOWFISH_ECB_MODE. 97 * 98 */ 99 typedef struct blowfish_ctx { 100 void *bc_keysched; 101 size_t bc_keysched_len; 102 uint64_t bc_iv; 103 uint64_t bc_lastblock; 104 uint64_t bc_remainder; 105 size_t bc_remainder_len; 106 uint8_t *bc_lastp; 107 uint8_t *bc_copy_to; 108 uint32_t bc_flags; 109 } blowfish_ctx_t; 110 111 #define BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE 0x00000001 112 #define BLOWFISH_CBC_MODE 0x00000002 113 114 #define BLOWFISH_COPY_BLOCK(src, dst) \ 115 (dst)[0] = (src)[0]; \ 116 (dst)[1] = (src)[1]; \ 117 (dst)[2] = (src)[2]; \ 118 (dst)[3] = (src)[3]; \ 119 (dst)[4] = (src)[4]; \ 120 (dst)[5] = (src)[5]; \ 121 (dst)[6] = (src)[6]; \ 122 (dst)[7] = (src)[7] 123 124 #define BLOWFISH_XOR_BLOCK(src, dst) \ 125 (dst)[0] ^= (src)[0]; \ 126 (dst)[1] ^= (src)[1]; \ 127 (dst)[2] ^= (src)[2]; \ 128 (dst)[3] ^= (src)[3]; \ 129 (dst)[4] ^= (src)[4]; \ 130 (dst)[5] ^= (src)[5]; \ 131 (dst)[6] ^= (src)[6]; \ 132 (dst)[7] ^= (src)[7] 133 134 /* 135 * Mechanism info structure passed to KCF during registration. 136 */ 137 138 static crypto_mech_info_t blowfish_mech_info_tab[] = { 139 /* BLOWFISH_ECB */ 140 {SUN_CKM_BF_ECB, BF_ECB_MECH_INFO_TYPE, 141 CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 142 CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC, 143 BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 144 /* BLOWFISH_CBC */ 145 {SUN_CKM_BF_CBC, BF_CBC_MECH_INFO_TYPE, 146 CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 147 CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC, 148 BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS} 149 }; 150 151 #define BLOWFISH_VALID_MECH(mech) \ 152 (((mech)->cm_type == BF_ECB_MECH_INFO_TYPE || \ 153 (mech)->cm_type == BF_CBC_MECH_INFO_TYPE) ? 1 : 0) 154 155 /* operations are in-place if the output buffer is NULL */ 156 #define BLOWFISH_ARG_INPLACE(input, output) \ 157 if ((output) == NULL) \ 158 (output) = (input); 159 160 static void blowfish_provider_status(crypto_provider_handle_t, uint_t *); 161 162 static crypto_control_ops_t blowfish_control_ops = { 163 blowfish_provider_status 164 }; 165 166 static int blowfish_common_init(crypto_ctx_t *, crypto_mechanism_t *, 167 crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 168 static int blowfish_common_init_ctx(blowfish_ctx_t *, 169 crypto_spi_ctx_template_t *, crypto_mechanism_t *, crypto_key_t *, int); 170 static int blowfish_encrypt_final(crypto_ctx_t *, crypto_data_t *, 171 crypto_req_handle_t); 172 static int blowfish_decrypt_final(crypto_ctx_t *, crypto_data_t *, 173 crypto_req_handle_t); 174 175 static int blowfish_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 176 crypto_req_handle_t); 177 static int blowfish_encrypt_update(crypto_ctx_t *, crypto_data_t *, 178 crypto_data_t *, crypto_req_handle_t); 179 static int blowfish_encrypt_atomic(crypto_provider_handle_t, 180 crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 181 crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 182 183 static int blowfish_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 184 crypto_req_handle_t); 185 static int blowfish_decrypt_update(crypto_ctx_t *, crypto_data_t *, 186 crypto_data_t *, crypto_req_handle_t); 187 static int blowfish_decrypt_atomic(crypto_provider_handle_t, 188 crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 189 crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 190 191 static crypto_cipher_ops_t blowfish_cipher_ops = { 192 blowfish_common_init, 193 blowfish_encrypt, 194 blowfish_encrypt_update, 195 blowfish_encrypt_final, 196 blowfish_encrypt_atomic, 197 blowfish_common_init, 198 blowfish_decrypt, 199 blowfish_decrypt_update, 200 blowfish_decrypt_final, 201 blowfish_decrypt_atomic 202 }; 203 204 static int blowfish_create_ctx_template(crypto_provider_handle_t, 205 crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *, 206 size_t *, crypto_req_handle_t); 207 static int blowfish_free_context(crypto_ctx_t *); 208 209 static crypto_ctx_ops_t blowfish_ctx_ops = { 210 blowfish_create_ctx_template, 211 blowfish_free_context 212 }; 213 214 static crypto_ops_t blowfish_crypto_ops = { 215 &blowfish_control_ops, 216 NULL, 217 &blowfish_cipher_ops, 218 NULL, 219 NULL, 220 NULL, 221 NULL, 222 NULL, 223 NULL, 224 NULL, 225 NULL, 226 NULL, 227 NULL, 228 &blowfish_ctx_ops 229 }; 230 231 static crypto_provider_info_t blowfish_prov_info = { 232 CRYPTO_SPI_VERSION_1, 233 "Blowfish Software Provider", 234 CRYPTO_SW_PROVIDER, 235 {&modlinkage}, 236 NULL, 237 &blowfish_crypto_ops, 238 sizeof (blowfish_mech_info_tab)/sizeof (crypto_mech_info_t), 239 blowfish_mech_info_tab 240 }; 241 242 static int blowfish_encrypt_contiguous_blocks(blowfish_ctx_t *, char *, size_t, 243 crypto_data_t *); 244 static int blowfish_decrypt_contiguous_blocks(blowfish_ctx_t *, char *, size_t, 245 crypto_data_t *); 246 247 static crypto_kcf_provider_handle_t blowfish_prov_handle = NULL; 248 249 int 250 _init(void) 251 { 252 int ret; 253 254 /* 255 * Register with KCF. If the registration fails, return error. 256 */ 257 if ((ret = crypto_register_provider(&blowfish_prov_info, 258 &blowfish_prov_handle)) != CRYPTO_SUCCESS) { 259 cmn_err(CE_WARN, "%s _init: crypto_register_provider() " 260 "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret); 261 return (EACCES); 262 } 263 264 if ((ret = mod_install(&modlinkage)) != 0) { 265 int rv; 266 267 ASSERT(blowfish_prov_handle != NULL); 268 /* We should not return if the unregister returns busy. */ 269 while ((rv = crypto_unregister_provider(blowfish_prov_handle)) 270 == CRYPTO_BUSY) { 271 cmn_err(CE_WARN, 272 "%s _init: crypto_unregister_provider() " 273 "failed (0x%x). Retrying.", 274 CRYPTO_PROVIDER_NAME, rv); 275 /* wait 10 seconds and try again */ 276 delay(10 * drv_usectohz(1000000)); 277 } 278 } 279 280 return (ret); 281 } 282 283 int 284 _fini(void) 285 { 286 int ret; 287 288 /* 289 * Unregister from KCF if previous registration succeeded. 290 */ 291 if (blowfish_prov_handle != NULL) { 292 if ((ret = crypto_unregister_provider(blowfish_prov_handle)) != 293 CRYPTO_SUCCESS) { 294 cmn_err(CE_WARN, 295 "%s _fini: crypto_unregister_provider() " 296 "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret); 297 return (EBUSY); 298 } 299 blowfish_prov_handle = NULL; 300 } 301 302 return (mod_remove(&modlinkage)); 303 } 304 305 int 306 _info(struct modinfo *modinfop) 307 { 308 return (mod_info(&modlinkage, modinfop)); 309 } 310 311 /* 312 * Initialize key schedules for blowfish 313 */ 314 static int 315 init_keysched(crypto_key_t *key, void *keysched) 316 { 317 /* EXPORT DELETE START */ 318 /* 319 * Only keys by value are supported by this module. 320 */ 321 switch (key->ck_format) { 322 case CRYPTO_KEY_RAW: 323 if (key->ck_length < BLOWFISH_MINBITS || 324 key->ck_length > BLOWFISH_MAXBITS) { 325 return (CRYPTO_KEY_SIZE_RANGE); 326 } 327 break; 328 default: 329 return (CRYPTO_KEY_TYPE_INCONSISTENT); 330 } 331 332 blowfish_init_keysched(key->ck_data, key->ck_length, keysched); 333 /* EXPORT DELETE END */ 334 return (CRYPTO_SUCCESS); 335 } 336 337 /* 338 * KCF software provider control entry points. 339 */ 340 /* ARGSUSED */ 341 static void 342 blowfish_provider_status(crypto_provider_handle_t provider, uint_t *status) 343 { 344 *status = CRYPTO_PROVIDER_READY; 345 } 346 347 /* 348 * KCF software provider encrypt entry points. 349 */ 350 static int 351 blowfish_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 352 crypto_key_t *key, crypto_spi_ctx_template_t template, 353 crypto_req_handle_t req) 354 { 355 356 /* EXPORT DELETE START */ 357 358 blowfish_ctx_t *blowfish_ctx; 359 int rv; 360 int kmflag; 361 362 /* 363 * Only keys by value are supported by this module. 364 */ 365 if (key->ck_format != CRYPTO_KEY_RAW) { 366 return (CRYPTO_KEY_TYPE_INCONSISTENT); 367 } 368 369 if (!BLOWFISH_VALID_MECH(mechanism)) 370 return (CRYPTO_MECHANISM_INVALID); 371 372 if (mechanism->cm_param != NULL && 373 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 374 return (CRYPTO_MECHANISM_PARAM_INVALID); 375 376 /* 377 * Allocate a blowfish context. 378 */ 379 kmflag = crypto_kmflag(req); 380 blowfish_ctx = kmem_zalloc(sizeof (blowfish_ctx_t), kmflag); 381 if (blowfish_ctx == NULL) 382 return (CRYPTO_HOST_MEMORY); 383 384 rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism, 385 key, kmflag); 386 if (rv != CRYPTO_SUCCESS) { 387 kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t)); 388 return (rv); 389 } 390 391 ctx->cc_provider_private = blowfish_ctx; 392 393 /* EXPORT DELETE END */ 394 395 return (CRYPTO_SUCCESS); 396 } 397 398 /* 399 * Helper blowfish encrypt update function for iov input data. 400 */ 401 static int 402 blowfish_cipher_update_iov(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input, 403 crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t, 404 crypto_data_t *)) 405 { 406 if (input->cd_miscdata != NULL) { 407 if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) { 408 /* LINTED: pointer alignment */ 409 blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata; 410 } else { 411 uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0]; 412 uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 413 414 BLOWFISH_COPY_BLOCK(miscdata8, iv8); 415 } 416 } 417 418 if (input->cd_raw.iov_len < input->cd_length) 419 return (CRYPTO_ARGUMENTS_BAD); 420 421 return (cipher)(blowfish_ctx, input->cd_raw.iov_base + input->cd_offset, 422 input->cd_length, (input == output) ? NULL : output); 423 } 424 425 /* 426 * Helper blowfish encrypt update function for uio input data. 427 */ 428 static int 429 blowfish_cipher_update_uio(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input, 430 crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t, 431 crypto_data_t *)) 432 { 433 uio_t *uiop = input->cd_uio; 434 off_t offset = input->cd_offset; 435 size_t length = input->cd_length; 436 uint_t vec_idx; 437 size_t cur_len; 438 439 if (input->cd_miscdata != NULL) { 440 if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) { 441 /*LINTED: pointer alignment */ 442 blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata; 443 } else { 444 uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0]; 445 uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 446 447 BLOWFISH_COPY_BLOCK(miscdata8, iv8); 448 } 449 } 450 451 if (input->cd_uio->uio_segflg != UIO_SYSSPACE) { 452 return (CRYPTO_ARGUMENTS_BAD); 453 } 454 455 /* 456 * Jump to the first iovec containing data to be 457 * processed. 458 */ 459 for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && 460 offset >= uiop->uio_iov[vec_idx].iov_len; 461 offset -= uiop->uio_iov[vec_idx++].iov_len); 462 if (vec_idx == uiop->uio_iovcnt) { 463 /* 464 * The caller specified an offset that is larger than the 465 * total size of the buffers it provided. 466 */ 467 return (CRYPTO_DATA_LEN_RANGE); 468 } 469 470 /* 471 * Now process the iovecs. 472 */ 473 while (vec_idx < uiop->uio_iovcnt && length > 0) { 474 cur_len = MIN(uiop->uio_iov[vec_idx].iov_len - 475 offset, length); 476 477 (cipher)(blowfish_ctx, uiop->uio_iov[vec_idx].iov_base + 478 offset, cur_len, (input == output) ? NULL : output); 479 480 length -= cur_len; 481 vec_idx++; 482 offset = 0; 483 } 484 485 if (vec_idx == uiop->uio_iovcnt && length > 0) { 486 /* 487 * The end of the specified iovec's was reached but 488 * the length requested could not be processed, i.e. 489 * The caller requested to digest more data than it provided. 490 */ 491 492 return (CRYPTO_DATA_LEN_RANGE); 493 } 494 495 return (CRYPTO_SUCCESS); 496 } 497 498 /* 499 * Helper blowfish encrypt update function for mblk input data. 500 */ 501 static int 502 blowfish_cipher_update_mp(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input, 503 crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t, 504 crypto_data_t *)) 505 { 506 off_t offset = input->cd_offset; 507 size_t length = input->cd_length; 508 mblk_t *mp; 509 size_t cur_len; 510 511 if (input->cd_miscdata != NULL) { 512 if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) { 513 /*LINTED: pointer alignment */ 514 blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata; 515 } else { 516 uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0]; 517 uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 518 519 BLOWFISH_COPY_BLOCK(miscdata8, iv8); 520 } 521 } 522 523 /* 524 * Jump to the first mblk_t containing data to be processed. 525 */ 526 for (mp = input->cd_mp; mp != NULL && offset >= MBLKL(mp); 527 offset -= MBLKL(mp), mp = mp->b_cont); 528 if (mp == NULL) { 529 /* 530 * The caller specified an offset that is larger than the 531 * total size of the buffers it provided. 532 */ 533 return (CRYPTO_DATA_LEN_RANGE); 534 } 535 536 /* 537 * Now do the processing on the mblk chain. 538 */ 539 while (mp != NULL && length > 0) { 540 cur_len = MIN(MBLKL(mp) - offset, length); 541 (cipher)(blowfish_ctx, (char *)(mp->b_rptr + offset), cur_len, 542 (input == output) ? NULL : output); 543 544 length -= cur_len; 545 offset = 0; 546 mp = mp->b_cont; 547 } 548 549 if (mp == NULL && length > 0) { 550 /* 551 * The end of the mblk was reached but the length requested 552 * could not be processed, i.e. The caller requested 553 * to digest more data than it provided. 554 */ 555 return (CRYPTO_DATA_LEN_RANGE); 556 } 557 558 return (CRYPTO_SUCCESS); 559 } 560 561 /* ARGSUSED */ 562 static int 563 blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext, 564 crypto_data_t *ciphertext, crypto_req_handle_t req) 565 { 566 int ret; 567 568 /* EXPORT DELETE START */ 569 570 blowfish_ctx_t *blowfish_ctx; 571 572 /* 573 * Plaintext 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 ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 578 return (CRYPTO_DATA_LEN_RANGE); 579 580 ASSERT(ctx->cc_provider_private != NULL); 581 blowfish_ctx = ctx->cc_provider_private; 582 583 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 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 (ciphertext->cd_length < plaintext->cd_length) { 590 ciphertext->cd_length = plaintext->cd_length; 591 return (CRYPTO_BUFFER_TOO_SMALL); 592 } 593 594 /* 595 * Do an update on the specified input data. 596 */ 597 ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, 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_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 610 crypto_data_t *plaintext, crypto_req_handle_t req) 611 { 612 int ret; 613 614 /* EXPORT DELETE START */ 615 616 blowfish_ctx_t *blowfish_ctx; 617 618 /* 619 * Ciphertext must be a multiple of blowfish block size. 620 * This test only works for non-padded mechanisms 621 * when blocksize is 2^N. 622 */ 623 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 624 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 625 626 ASSERT(ctx->cc_provider_private != NULL); 627 blowfish_ctx = ctx->cc_provider_private; 628 629 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 630 631 /* 632 * We need to just return the length needed to store the output. 633 * We should not destroy the context for the following case. 634 */ 635 if (plaintext->cd_length < ciphertext->cd_length) { 636 plaintext->cd_length = ciphertext->cd_length; 637 return (CRYPTO_BUFFER_TOO_SMALL); 638 } 639 640 /* 641 * Do an update on the specified input data. 642 */ 643 ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, req); 644 ASSERT(blowfish_ctx->bc_remainder_len == 0); 645 (void) blowfish_free_context(ctx); 646 647 /* EXPORT DELETE END */ 648 649 /* LINTED */ 650 return (ret); 651 } 652 653 /* ARGSUSED */ 654 static int 655 blowfish_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext, 656 crypto_data_t *ciphertext, crypto_req_handle_t req) 657 { 658 off_t saved_offset; 659 size_t saved_length, out_len; 660 int ret = CRYPTO_SUCCESS; 661 662 ASSERT(ctx->cc_provider_private != NULL); 663 664 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 665 666 /* compute number of bytes that will hold the ciphertext */ 667 out_len = 668 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 669 out_len += plaintext->cd_length; 670 out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 671 672 /* return length needed to store the output */ 673 if (ciphertext->cd_length < out_len) { 674 ciphertext->cd_length = out_len; 675 return (CRYPTO_BUFFER_TOO_SMALL); 676 } 677 678 saved_offset = ciphertext->cd_offset; 679 saved_length = ciphertext->cd_length; 680 681 /* 682 * Do the blowfish update on the specified input data. 683 */ 684 switch (plaintext->cd_format) { 685 case CRYPTO_DATA_RAW: 686 ret = blowfish_cipher_update_iov(ctx->cc_provider_private, 687 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 688 break; 689 case CRYPTO_DATA_UIO: 690 ret = blowfish_cipher_update_uio(ctx->cc_provider_private, 691 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 692 break; 693 case CRYPTO_DATA_MBLK: 694 ret = blowfish_cipher_update_mp(ctx->cc_provider_private, 695 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 696 break; 697 default: 698 ret = CRYPTO_ARGUMENTS_BAD; 699 } 700 701 if (ret == CRYPTO_SUCCESS) { 702 if (plaintext != ciphertext) 703 ciphertext->cd_length = 704 ciphertext->cd_offset - saved_offset; 705 } else { 706 ciphertext->cd_length = saved_length; 707 } 708 ciphertext->cd_offset = saved_offset; 709 710 return (ret); 711 } 712 713 /* ARGSUSED */ 714 static int 715 blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 716 crypto_data_t *plaintext, crypto_req_handle_t req) 717 { 718 off_t saved_offset; 719 size_t saved_length, out_len; 720 int ret = CRYPTO_SUCCESS; 721 722 ASSERT(ctx->cc_provider_private != NULL); 723 724 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 725 726 /* compute number of bytes that will hold the plaintext */ 727 out_len = 728 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 729 out_len += ciphertext->cd_length; 730 out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 731 732 /* return length needed to store the output */ 733 if (plaintext->cd_length < out_len) { 734 plaintext->cd_length = out_len; 735 return (CRYPTO_BUFFER_TOO_SMALL); 736 } 737 738 saved_offset = plaintext->cd_offset; 739 saved_length = plaintext->cd_length; 740 741 /* 742 * Do the blowfish update on the specified input data. 743 */ 744 switch (ciphertext->cd_format) { 745 case CRYPTO_DATA_RAW: 746 ret = blowfish_cipher_update_iov(ctx->cc_provider_private, 747 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 748 break; 749 case CRYPTO_DATA_UIO: 750 ret = blowfish_cipher_update_uio(ctx->cc_provider_private, 751 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 752 break; 753 case CRYPTO_DATA_MBLK: 754 ret = blowfish_cipher_update_mp(ctx->cc_provider_private, 755 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 756 break; 757 default: 758 ret = CRYPTO_ARGUMENTS_BAD; 759 } 760 761 if (ret == CRYPTO_SUCCESS) { 762 if (ciphertext != plaintext) 763 plaintext->cd_length = 764 plaintext->cd_offset - saved_offset; 765 } else { 766 plaintext->cd_length = saved_length; 767 } 768 plaintext->cd_offset = saved_offset; 769 770 return (ret); 771 } 772 773 /* ARGSUSED */ 774 static int 775 blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 776 crypto_req_handle_t req) 777 { 778 779 /* EXPORT DELETE START */ 780 781 blowfish_ctx_t *blowfish_ctx; 782 783 ASSERT(ctx->cc_provider_private != NULL); 784 blowfish_ctx = ctx->cc_provider_private; 785 786 /* 787 * There must be no unprocessed data. 788 * This happens if the length of the last data is 789 * not a multiple of the BLOWFISH block length. 790 */ 791 if (blowfish_ctx->bc_remainder_len > 0) 792 return (CRYPTO_DATA_LEN_RANGE); 793 794 (void) blowfish_free_context(ctx); 795 data->cd_length = 0; 796 797 /* EXPORT DELETE END */ 798 799 return (CRYPTO_SUCCESS); 800 } 801 802 /* ARGSUSED */ 803 static int 804 blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 805 crypto_req_handle_t req) 806 { 807 808 /* EXPORT DELETE START */ 809 810 blowfish_ctx_t *blowfish_ctx; 811 812 ASSERT(ctx->cc_provider_private != NULL); 813 blowfish_ctx = ctx->cc_provider_private; 814 815 /* 816 * There must be no unprocessed ciphertext. 817 * This happens if the length of the last ciphertext is 818 * not a multiple of the BLOWFISH block length. 819 */ 820 if (blowfish_ctx->bc_remainder_len > 0) 821 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 822 823 (void) blowfish_free_context(ctx); 824 data->cd_length = 0; 825 826 /* EXPORT DELETE END */ 827 828 return (CRYPTO_SUCCESS); 829 } 830 831 /* ARGSUSED */ 832 static int 833 blowfish_encrypt_atomic(crypto_provider_handle_t provider, 834 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 835 crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext, 836 crypto_spi_ctx_template_t template, crypto_req_handle_t req) 837 { 838 blowfish_ctx_t blowfish_ctx; /* on the stack */ 839 off_t saved_offset; 840 size_t saved_length; 841 int ret; 842 843 BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 844 845 /* 846 * Plaintext must be a multiple of blowfish block size. 847 * This test only works for non-padded mechanisms 848 * when blocksize is 2^N. 849 */ 850 if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 851 return (CRYPTO_DATA_LEN_RANGE); 852 853 /* return length needed to store the output */ 854 if (ciphertext->cd_length < plaintext->cd_length) { 855 ciphertext->cd_length = plaintext->cd_length; 856 return (CRYPTO_BUFFER_TOO_SMALL); 857 } 858 859 if (!BLOWFISH_VALID_MECH(mechanism)) 860 return (CRYPTO_MECHANISM_INVALID); 861 862 if (mechanism->cm_param_len != 0 && 863 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 864 return (CRYPTO_MECHANISM_PARAM_INVALID); 865 866 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 867 868 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 869 key, crypto_kmflag(req)); 870 if (ret != CRYPTO_SUCCESS) 871 return (ret); 872 873 saved_offset = ciphertext->cd_offset; 874 saved_length = ciphertext->cd_length; 875 876 /* 877 * Do an update on the specified input data. 878 */ 879 switch (plaintext->cd_format) { 880 case CRYPTO_DATA_RAW: 881 ret = blowfish_cipher_update_iov(&blowfish_ctx, 882 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 883 break; 884 case CRYPTO_DATA_UIO: 885 ret = blowfish_cipher_update_uio(&blowfish_ctx, 886 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 887 break; 888 case CRYPTO_DATA_MBLK: 889 ret = blowfish_cipher_update_mp(&blowfish_ctx, 890 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 891 break; 892 default: 893 ret = CRYPTO_ARGUMENTS_BAD; 894 } 895 896 if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 897 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 898 kmem_free(blowfish_ctx.bc_keysched, 899 blowfish_ctx.bc_keysched_len); 900 } 901 902 if (ret == CRYPTO_SUCCESS) { 903 ASSERT(blowfish_ctx.bc_remainder_len == 0); 904 if (plaintext != ciphertext) 905 ciphertext->cd_length = 906 ciphertext->cd_offset - saved_offset; 907 } else { 908 ciphertext->cd_length = saved_length; 909 } 910 ciphertext->cd_offset = saved_offset; 911 912 return (ret); 913 } 914 915 /* ARGSUSED */ 916 static int 917 blowfish_decrypt_atomic(crypto_provider_handle_t provider, 918 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 919 crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext, 920 crypto_spi_ctx_template_t template, crypto_req_handle_t req) 921 { 922 blowfish_ctx_t blowfish_ctx; /* on the stack */ 923 off_t saved_offset; 924 size_t saved_length; 925 int ret; 926 927 BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 928 929 /* 930 * Ciphertext must be a multiple of blowfish block size. 931 * This test only works for non-padded mechanisms 932 * when blocksize is 2^N. 933 */ 934 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 935 return (CRYPTO_DATA_LEN_RANGE); 936 937 /* return length needed to store the output */ 938 if (plaintext->cd_length < ciphertext->cd_length) { 939 plaintext->cd_length = ciphertext->cd_length; 940 return (CRYPTO_BUFFER_TOO_SMALL); 941 } 942 943 if (!BLOWFISH_VALID_MECH(mechanism)) 944 return (CRYPTO_MECHANISM_INVALID); 945 946 if (mechanism->cm_param_len != 0 && 947 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 948 return (CRYPTO_MECHANISM_PARAM_INVALID); 949 950 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 951 952 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 953 key, crypto_kmflag(req)); 954 if (ret != CRYPTO_SUCCESS) 955 return (ret); 956 957 saved_offset = plaintext->cd_offset; 958 saved_length = plaintext->cd_length; 959 960 /* 961 * Do an update on the specified input data. 962 */ 963 switch (ciphertext->cd_format) { 964 case CRYPTO_DATA_RAW: 965 ret = blowfish_cipher_update_iov(&blowfish_ctx, 966 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 967 break; 968 case CRYPTO_DATA_UIO: 969 ret = blowfish_cipher_update_uio(&blowfish_ctx, 970 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 971 break; 972 case CRYPTO_DATA_MBLK: 973 ret = blowfish_cipher_update_mp(&blowfish_ctx, 974 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 975 break; 976 default: 977 ret = CRYPTO_ARGUMENTS_BAD; 978 } 979 980 if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 981 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 982 kmem_free(blowfish_ctx.bc_keysched, 983 blowfish_ctx.bc_keysched_len); 984 } 985 986 if (ret == CRYPTO_SUCCESS) { 987 ASSERT(blowfish_ctx.bc_remainder_len == 0); 988 if (ciphertext != plaintext) 989 plaintext->cd_length = 990 plaintext->cd_offset - saved_offset; 991 } else { 992 plaintext->cd_length = saved_length; 993 } 994 plaintext->cd_offset = saved_offset; 995 996 return (ret); 997 } 998 999 /* 1000 * KCF software provider context template entry points. 1001 */ 1002 /* ARGSUSED */ 1003 static int 1004 blowfish_create_ctx_template(crypto_provider_handle_t provider, 1005 crypto_mechanism_t *mechanism, crypto_key_t *key, 1006 crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req) 1007 { 1008 1009 /* EXPORT DELETE START */ 1010 1011 void *keysched; 1012 size_t size; 1013 int rv; 1014 1015 if (!BLOWFISH_VALID_MECH(mechanism)) 1016 return (CRYPTO_MECHANISM_INVALID); 1017 1018 if ((keysched = blowfish_alloc_keysched(&size, 1019 crypto_kmflag(req))) == NULL) { 1020 return (CRYPTO_HOST_MEMORY); 1021 } 1022 1023 /* 1024 * Initialize key schedule. Key length information is stored 1025 * in the key. 1026 */ 1027 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) { 1028 bzero(keysched, size); 1029 kmem_free(keysched, size); 1030 return (rv); 1031 } 1032 1033 *tmpl = keysched; 1034 *tmpl_size = size; 1035 1036 /* EXPORT DELETE END */ 1037 1038 return (CRYPTO_SUCCESS); 1039 } 1040 1041 /* ARGSUSED */ 1042 static int 1043 blowfish_free_context(crypto_ctx_t *ctx) 1044 { 1045 blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private; 1046 1047 if (blowfish_ctx != NULL) { 1048 if (blowfish_ctx->bc_flags & 1049 BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 1050 ASSERT(blowfish_ctx->bc_keysched_len != 0); 1051 bzero(blowfish_ctx->bc_keysched, 1052 blowfish_ctx->bc_keysched_len); 1053 kmem_free(blowfish_ctx->bc_keysched, 1054 blowfish_ctx->bc_keysched_len); 1055 } 1056 kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t)); 1057 ctx->cc_provider_private = NULL; 1058 } 1059 1060 return (CRYPTO_SUCCESS); 1061 } 1062 1063 /* 1064 * Initialize by setting iov_or_mp to point to the current iovec or mp, 1065 * and by setting current_offset to an offset within the current iovec or mp . 1066 */ 1067 static void 1068 blowfish_init_ptrs(crypto_data_t *out, void **iov_or_mp, 1069 offset_t *current_offset) 1070 { 1071 offset_t offset; 1072 1073 switch (out->cd_format) { 1074 case CRYPTO_DATA_RAW: 1075 *current_offset = out->cd_offset; 1076 break; 1077 1078 case CRYPTO_DATA_UIO: { 1079 uio_t *uiop = out->cd_uio; 1080 uint_t vec_idx; 1081 1082 offset = out->cd_offset; 1083 for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && 1084 offset >= uiop->uio_iov[vec_idx].iov_len; 1085 offset -= uiop->uio_iov[vec_idx++].iov_len); 1086 1087 *current_offset = offset; 1088 *iov_or_mp = (void *)(uintptr_t)vec_idx; 1089 break; 1090 } 1091 1092 case CRYPTO_DATA_MBLK: { 1093 mblk_t *mp; 1094 1095 offset = out->cd_offset; 1096 for (mp = out->cd_mp; mp != NULL && offset >= MBLKL(mp); 1097 offset -= MBLKL(mp), mp = mp->b_cont); 1098 1099 *current_offset = offset; 1100 *iov_or_mp = mp; 1101 break; 1102 1103 } 1104 } /* end switch */ 1105 } 1106 1107 /* 1108 * Get pointers for where in the output to copy a block of encrypted or 1109 * decrypted data. The iov_or_mp argument stores a pointer to the current 1110 * iovec or mp, and offset stores an offset into the current iovec or mp. 1111 */ 1112 static void 1113 blowfish_get_ptrs(crypto_data_t *out, void **iov_or_mp, 1114 offset_t *current_offset, uint8_t **out_data_1, size_t *out_data_1_len, 1115 uint8_t **out_data_2) 1116 { 1117 offset_t offset; 1118 1119 switch (out->cd_format) { 1120 case CRYPTO_DATA_RAW: { 1121 iovec_t *iov; 1122 1123 offset = *current_offset; 1124 iov = &out->cd_raw; 1125 if ((offset + BLOWFISH_BLOCK_LEN) <= iov->iov_len) { 1126 /* one BLOWFISH block fits */ 1127 *out_data_1 = (uint8_t *)iov->iov_base + offset; 1128 *out_data_1_len = BLOWFISH_BLOCK_LEN; 1129 *out_data_2 = NULL; 1130 *current_offset = offset + BLOWFISH_BLOCK_LEN; 1131 } 1132 break; 1133 } 1134 1135 case CRYPTO_DATA_UIO: { 1136 uio_t *uio = out->cd_uio; 1137 iovec_t *iov; 1138 offset_t offset; 1139 uint_t vec_idx; 1140 uint8_t *p; 1141 1142 offset = *current_offset; 1143 vec_idx = (uint_t)(uintptr_t)(*iov_or_mp); 1144 iov = &uio->uio_iov[vec_idx]; 1145 p = (uint8_t *)iov->iov_base + offset; 1146 *out_data_1 = p; 1147 1148 if (offset + BLOWFISH_BLOCK_LEN <= iov->iov_len) { 1149 /* can fit one BLOWFISH block into this iov */ 1150 *out_data_1_len = BLOWFISH_BLOCK_LEN; 1151 *out_data_2 = NULL; 1152 *current_offset = offset + BLOWFISH_BLOCK_LEN; 1153 } else { 1154 /* one BLOWFISH block spans two iovecs */ 1155 *out_data_1_len = iov->iov_len - offset; 1156 if (vec_idx == uio->uio_iovcnt) 1157 return; 1158 vec_idx++; 1159 iov = &uio->uio_iov[vec_idx]; 1160 *out_data_2 = (uint8_t *)iov->iov_base; 1161 *current_offset = BLOWFISH_BLOCK_LEN - *out_data_1_len; 1162 } 1163 *iov_or_mp = (void *)(uintptr_t)vec_idx; 1164 break; 1165 } 1166 1167 case CRYPTO_DATA_MBLK: { 1168 mblk_t *mp; 1169 uint8_t *p; 1170 1171 offset = *current_offset; 1172 mp = (mblk_t *)*iov_or_mp; 1173 p = mp->b_rptr + offset; 1174 *out_data_1 = p; 1175 if ((p + BLOWFISH_BLOCK_LEN) <= mp->b_wptr) { 1176 /* can fit one BLOWFISH block into this mblk */ 1177 *out_data_1_len = BLOWFISH_BLOCK_LEN; 1178 *out_data_2 = NULL; 1179 *current_offset = offset + BLOWFISH_BLOCK_LEN; 1180 } else { 1181 /* one BLOWFISH block spans two mblks */ 1182 *out_data_1_len = mp->b_wptr - p; 1183 if ((mp = mp->b_cont) == NULL) 1184 return; 1185 *out_data_2 = mp->b_rptr; 1186 *current_offset = BLOWFISH_BLOCK_LEN - *out_data_1_len; 1187 } 1188 *iov_or_mp = mp; 1189 break; 1190 } 1191 } /* end switch */ 1192 } 1193 1194 /* 1195 * Encrypt multiple blocks of data. 1196 */ 1197 static int 1198 blowfish_encrypt_contiguous_blocks(blowfish_ctx_t *ctx, char *data, 1199 size_t length, crypto_data_t *out) 1200 { 1201 /* EXPORT DELETE START */ 1202 size_t remainder = length; 1203 size_t need; 1204 uint8_t *datap = (uint8_t *)data; 1205 uint8_t *blockp; 1206 uint8_t *lastp; 1207 uint32_t tmp[2]; 1208 void *iov_or_mp; 1209 offset_t offset; 1210 uint8_t *out_data_1; 1211 uint8_t *out_data_2; 1212 size_t out_data_1_len; 1213 1214 if (length + ctx->bc_remainder_len < BLOWFISH_BLOCK_LEN) { 1215 /* accumulate bytes here and return */ 1216 bcopy(datap, 1217 (uint8_t *)&ctx->bc_remainder + ctx->bc_remainder_len, 1218 length); 1219 ctx->bc_remainder_len += length; 1220 ctx->bc_copy_to = datap; 1221 return (0); 1222 } 1223 1224 lastp = (uint8_t *)&ctx->bc_iv; 1225 if (out != NULL) 1226 blowfish_init_ptrs(out, &iov_or_mp, &offset); 1227 1228 do { 1229 /* Unprocessed data from last call. */ 1230 if (ctx->bc_remainder_len > 0) { 1231 need = BLOWFISH_BLOCK_LEN - ctx->bc_remainder_len; 1232 1233 if (need > remainder) 1234 return (1); 1235 1236 bcopy(datap, &((uint8_t *)&ctx->bc_remainder) 1237 [ctx->bc_remainder_len], need); 1238 1239 blockp = (uint8_t *)&ctx->bc_remainder; 1240 } else { 1241 blockp = datap; 1242 } 1243 1244 /* don't write on the plaintext */ 1245 if (out != NULL) { 1246 if (IS_P2ALIGNED(blockp, sizeof (uint32_t))) { 1247 /* LINTED: pointer alignment */ 1248 tmp[0] = *(uint32_t *)blockp; 1249 /* LINTED: pointer alignment */ 1250 tmp[1] = *(uint32_t *)&blockp[4]; 1251 } else { 1252 #ifdef _BIG_ENDIAN 1253 tmp[0] = (((uint32_t)blockp[0] << 24) | 1254 ((uint32_t)blockp[1] << 16) | 1255 ((uint32_t)blockp[2] << 8) | 1256 (uint32_t)blockp[3]); 1257 1258 tmp[1] = (((uint32_t)blockp[4] << 24) | 1259 ((uint32_t)blockp[5] << 16) | 1260 ((uint32_t)blockp[6] << 8) | 1261 (uint32_t)blockp[7]); 1262 #else 1263 tmp[0] = (((uint32_t)blockp[7] << 24) | 1264 ((uint32_t)blockp[6] << 16) | 1265 ((uint32_t)blockp[5] << 8) | 1266 (uint32_t)blockp[4]); 1267 1268 tmp[1] = (((uint32_t)blockp[3] << 24) | 1269 ((uint32_t)blockp[2] << 16) | 1270 ((uint32_t)blockp[1] << 8) | 1271 (uint32_t)blockp[0]); 1272 #endif /* _BIG_ENDIAN */ 1273 } 1274 blockp = (uint8_t *)tmp; 1275 } 1276 1277 if (ctx->bc_flags & BLOWFISH_CBC_MODE) { 1278 /* 1279 * XOR the previous cipher block or IV with the 1280 * current clear block. Check for alignment. 1281 */ 1282 if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) && 1283 IS_P2ALIGNED(lastp, sizeof (uint32_t))) { 1284 /* LINTED: pointer alignment */ 1285 *(uint32_t *)&blockp[0] ^= 1286 /* LINTED: pointer alignment */ 1287 *(uint32_t *)&lastp[0]; 1288 /* LINTED: pointer alignment */ 1289 *(uint32_t *)&blockp[4] ^= 1290 /* LINTED: pointer alignment */ 1291 *(uint32_t *)&lastp[4]; 1292 } else { 1293 BLOWFISH_XOR_BLOCK(lastp, blockp); 1294 } 1295 } 1296 1297 if (out == NULL) { 1298 blowfish_encrypt_block(ctx->bc_keysched, blockp, 1299 blockp); 1300 1301 ctx->bc_lastp = blockp; 1302 lastp = blockp; 1303 1304 if (ctx->bc_remainder_len > 0) { 1305 bcopy(blockp, ctx->bc_copy_to, 1306 ctx->bc_remainder_len); 1307 bcopy(blockp + ctx->bc_remainder_len, datap, 1308 need); 1309 } 1310 } else { 1311 blowfish_encrypt_block(ctx->bc_keysched, blockp, lastp); 1312 blowfish_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 1313 &out_data_1_len, &out_data_2); 1314 1315 /* copy block to where it belongs */ 1316 bcopy(lastp, out_data_1, out_data_1_len); 1317 if (out_data_2 != NULL) { 1318 bcopy(lastp + out_data_1_len, out_data_2, 1319 BLOWFISH_BLOCK_LEN - out_data_1_len); 1320 } 1321 1322 /* update offset */ 1323 out->cd_offset += BLOWFISH_BLOCK_LEN; 1324 } 1325 1326 /* Update pointer to next block of data to be processed. */ 1327 if (ctx->bc_remainder_len != 0) { 1328 datap += need; 1329 ctx->bc_remainder_len = 0; 1330 } else { 1331 datap += BLOWFISH_BLOCK_LEN; 1332 } 1333 1334 remainder = (size_t)&data[length] - (size_t)datap; 1335 1336 /* Incomplete last block. */ 1337 if (remainder > 0 && remainder < BLOWFISH_BLOCK_LEN) { 1338 bcopy(datap, &ctx->bc_remainder, remainder); 1339 ctx->bc_remainder_len = remainder; 1340 ctx->bc_copy_to = datap; 1341 goto out; 1342 } 1343 ctx->bc_copy_to = NULL; 1344 1345 } while (remainder > 0); 1346 1347 out: 1348 if (ctx->bc_lastp != NULL) { 1349 if (IS_P2ALIGNED(ctx->bc_lastp, sizeof (uint32_t))) { 1350 uint8_t *iv8 = (uint8_t *)&ctx->bc_iv; 1351 uint8_t *last8 = (uint8_t *)ctx->bc_lastp; 1352 1353 /* LINTED: pointer alignment */ 1354 *(uint32_t *)iv8 = *(uint32_t *)last8; 1355 /* LINTED: pointer alignment */ 1356 *(uint32_t *)&iv8[4] = *(uint32_t *)&last8[4]; 1357 } else { 1358 uint8_t *iv8 = (uint8_t *)&ctx->bc_iv; 1359 uint8_t *last8 = ctx->bc_lastp; 1360 1361 BLOWFISH_COPY_BLOCK(last8, iv8); 1362 } 1363 ctx->bc_lastp = (uint8_t *)&ctx->bc_iv; 1364 } 1365 /* EXPORT DELETE END */ 1366 1367 return (0); 1368 } 1369 1370 #define OTHER(a, ctx) \ 1371 (((a) == &(ctx)->bc_lastblock) ? &(ctx)->bc_iv : &(ctx)->bc_lastblock) 1372 1373 static int 1374 blowfish_decrypt_contiguous_blocks(blowfish_ctx_t *ctx, char *data, 1375 size_t length, crypto_data_t *out) 1376 { 1377 /* EXPORT DELETE START */ 1378 size_t remainder = length; 1379 size_t need; 1380 uint8_t *datap = (uint8_t *)data; 1381 uint8_t *blockp; 1382 uint8_t *lastp; 1383 uint32_t tmp[2]; 1384 void *iov_or_mp; 1385 offset_t offset; 1386 uint8_t *out_data_1; 1387 uint8_t *out_data_2; 1388 size_t out_data_1_len; 1389 1390 if (length + ctx->bc_remainder_len < BLOWFISH_BLOCK_LEN) { 1391 /* accumulate bytes here and return */ 1392 bcopy(datap, 1393 (uint8_t *)&ctx->bc_remainder + ctx->bc_remainder_len, 1394 length); 1395 ctx->bc_remainder_len += length; 1396 ctx->bc_copy_to = datap; 1397 return (0); 1398 } 1399 1400 lastp = ctx->bc_lastp; 1401 if (out != NULL) 1402 blowfish_init_ptrs(out, &iov_or_mp, &offset); 1403 1404 do { 1405 /* Unprocessed data from last call. */ 1406 if (ctx->bc_remainder_len > 0) { 1407 need = BLOWFISH_BLOCK_LEN - ctx->bc_remainder_len; 1408 1409 if (need > remainder) 1410 return (1); 1411 1412 bcopy(datap, &((uint8_t *)&ctx->bc_remainder) 1413 [ctx->bc_remainder_len], need); 1414 1415 blockp = (uint8_t *)&ctx->bc_remainder; 1416 } else { 1417 blockp = datap; 1418 } 1419 1420 if (ctx->bc_flags & BLOWFISH_CBC_MODE) { 1421 1422 /* Save current ciphertext block */ 1423 if (IS_P2ALIGNED(blockp, sizeof (uint32_t))) { 1424 uint32_t *tmp32; 1425 1426 /* LINTED: pointer alignment */ 1427 tmp32 = (uint32_t *)OTHER((uint64_t *)lastp, 1428 ctx); 1429 1430 /* LINTED: pointer alignment */ 1431 *tmp32++ = *(uint32_t *)blockp; 1432 /* LINTED: pointer alignment */ 1433 *tmp32++ = *(uint32_t *)&blockp[4]; 1434 } else { 1435 uint8_t *tmp8; 1436 tmp8 = (uint8_t *)OTHER((uint64_t *)lastp, ctx); 1437 1438 BLOWFISH_COPY_BLOCK(blockp, tmp8); 1439 } 1440 } 1441 1442 if (out != NULL) { 1443 blowfish_decrypt_block(ctx->bc_keysched, blockp, 1444 (uint8_t *)tmp); 1445 blockp = (uint8_t *)tmp; 1446 } else { 1447 blowfish_decrypt_block(ctx->bc_keysched, blockp, 1448 blockp); 1449 } 1450 1451 if (ctx->bc_flags & BLOWFISH_CBC_MODE) { 1452 /* 1453 * XOR the previous cipher block or IV with the 1454 * currently decrypted block. Check for alignment. 1455 */ 1456 if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) && 1457 IS_P2ALIGNED(lastp, sizeof (uint32_t))) { 1458 /* LINTED: pointer alignment */ 1459 *(uint32_t *)blockp ^= *(uint32_t *)lastp; 1460 /* LINTED: pointer alignment */ 1461 *(uint32_t *)&blockp[4] ^= 1462 /* LINTED: pointer alignment */ 1463 *(uint32_t *)&lastp[4]; 1464 } else { 1465 BLOWFISH_XOR_BLOCK(lastp, blockp); 1466 } 1467 1468 /* LINTED: pointer alignment */ 1469 lastp = (uint8_t *)OTHER((uint64_t *)lastp, ctx); 1470 } 1471 1472 if (out != NULL) { 1473 blowfish_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 1474 &out_data_1_len, &out_data_2); 1475 /* copy temporary block to where it belongs */ 1476 bcopy(&tmp, out_data_1, out_data_1_len); 1477 if (out_data_2 != NULL) { 1478 bcopy((uint8_t *)&tmp + out_data_1_len, 1479 out_data_2, 1480 BLOWFISH_BLOCK_LEN - out_data_1_len); 1481 } 1482 1483 /* update offset */ 1484 out->cd_offset += BLOWFISH_BLOCK_LEN; 1485 } else if (ctx->bc_remainder_len > 0) { 1486 /* copy temporary block to where it belongs */ 1487 bcopy(blockp, ctx->bc_copy_to, ctx->bc_remainder_len); 1488 bcopy(blockp + ctx->bc_remainder_len, datap, need); 1489 } 1490 1491 /* Update pointer to next block of data to be processed. */ 1492 if (ctx->bc_remainder_len != 0) { 1493 datap += need; 1494 ctx->bc_remainder_len = 0; 1495 } else { 1496 datap += BLOWFISH_BLOCK_LEN; 1497 } 1498 1499 remainder = (size_t)&data[length] - (size_t)datap; 1500 1501 /* Incomplete last block. */ 1502 if (remainder > 0 && remainder < BLOWFISH_BLOCK_LEN) { 1503 bcopy(datap, (uchar_t *)&ctx->bc_remainder, remainder); 1504 ctx->bc_remainder_len = remainder; 1505 ctx->bc_lastp = lastp; 1506 ctx->bc_copy_to = datap; 1507 return (0); 1508 } 1509 ctx->bc_copy_to = NULL; 1510 1511 } while (remainder > 0); 1512 1513 ctx->bc_lastp = lastp; 1514 /* EXPORT DELETE END */ 1515 return (0); 1516 } 1517 1518 /* ARGSUSED */ 1519 static int 1520 blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx, 1521 crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism, 1522 crypto_key_t *key, int kmflag) 1523 { 1524 int rv = CRYPTO_SUCCESS; 1525 1526 /* EXPORT DELETE START */ 1527 1528 void *keysched; 1529 size_t size; 1530 1531 if (template == NULL) { 1532 if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL) 1533 return (CRYPTO_HOST_MEMORY); 1534 /* 1535 * Initialize key schedule. 1536 * Key length is stored in the key. 1537 */ 1538 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) 1539 kmem_free(keysched, size); 1540 1541 blowfish_ctx->bc_flags = BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE; 1542 blowfish_ctx->bc_keysched_len = size; 1543 } else { 1544 keysched = template; 1545 } 1546 1547 if (mechanism->cm_type == BF_CBC_MECH_INFO_TYPE) { 1548 /* 1549 * Copy IV into BLOWFISH context. 1550 * 1551 * If cm_param == NULL then the IV comes from the 1552 * cd_miscdata field in the crypto_data structure. 1553 */ 1554 if (mechanism->cm_param != NULL) { 1555 ASSERT(mechanism->cm_param_len == BLOWFISH_BLOCK_LEN); 1556 if (IS_P2ALIGNED(mechanism->cm_param, 1557 sizeof (uint64_t))) { 1558 /* LINTED: pointer alignment */ 1559 blowfish_ctx->bc_iv = 1560 *(uint64_t *)mechanism->cm_param; 1561 } else { 1562 uint8_t *iv8; 1563 uint8_t *p8; 1564 iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 1565 p8 = (uint8_t *)&mechanism->cm_param[0]; 1566 1567 BLOWFISH_COPY_BLOCK(p8, iv8); 1568 } 1569 } 1570 1571 blowfish_ctx->bc_lastp = (uint8_t *)&blowfish_ctx->bc_iv; 1572 blowfish_ctx->bc_flags |= BLOWFISH_CBC_MODE; 1573 } 1574 blowfish_ctx->bc_keysched = keysched; 1575 1576 /* EXPORT DELETE END */ 1577 1578 return (rv); 1579 } 1580