1 /* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Cleaned-up and optimized version of MD5, based on the reference 8 * implementation provided in RFC 1321. See RSA Copyright information 9 * below. 10 * 11 * NOTE: All compiler data was gathered with SC4.2, and verified with SC5.x, 12 * as used to build Solaris 2.7. Hopefully the compiler behavior won't 13 * change for the worse in subsequent Solaris builds. 14 */ 15 16 #pragma ident "%Z%%M% %I% %E% SMI" 17 18 /* 19 * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm 20 */ 21 22 /* 23 * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 24 * rights reserved. 25 * 26 * License to copy and use this software is granted provided that it 27 * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 28 * Algorithm" in all material mentioning or referencing this software 29 * or this function. 30 * 31 * License is also granted to make and use derivative works provided 32 * that such works are identified as "derived from the RSA Data 33 * Security, Inc. MD5 Message-Digest Algorithm" in all material 34 * mentioning or referencing the derived work. 35 * 36 * RSA Data Security, Inc. makes no representations concerning either 37 * the merchantability of this software or the suitability of this 38 * software for any particular purpose. It is provided "as is" 39 * without express or implied warranty of any kind. 40 * 41 * These notices must be retained in any copies of any part of this 42 * documentation and/or software. 43 */ 44 45 #include <sys/types.h> 46 #include <sys/md5.h> 47 #include <sys/md5_consts.h> /* MD5_CONST() optimization */ 48 #include "md5_byteswap.h" 49 #if !defined(_KERNEL) || defined(_BOOT) 50 #include <strings.h> 51 #endif /* !_KERNEL || _BOOT */ 52 53 #if defined(_KERNEL) && !defined(_BOOT) 54 55 /* 56 * In kernel module, the md5 module is created with two modlinkages: 57 * - a modlmisc that allows consumers to directly call the entry points 58 * MD5Init, MD5Update, and MD5Final. 59 * - a modlcrypto that allows the module to register with the Kernel 60 * Cryptographic Framework (KCF) as a software provider for the MD5 61 * mechanisms. 62 */ 63 64 #include <sys/systm.h> 65 #include <sys/modctl.h> 66 #include <sys/cmn_err.h> 67 #include <sys/ddi.h> 68 #include <sys/crypto/common.h> 69 #include <sys/crypto/spi.h> 70 #include <sys/sysmacros.h> 71 #include <sys/strsun.h> 72 #include <sys/note.h> 73 74 extern struct mod_ops mod_miscops; 75 extern struct mod_ops mod_cryptoops; 76 77 /* 78 * Module linkage information for the kernel. 79 */ 80 81 static struct modlmisc modlmisc = { 82 &mod_miscops, 83 "MD5 Message-Digest Algorithm" 84 }; 85 86 static struct modlcrypto modlcrypto = { 87 &mod_cryptoops, 88 "MD5 Kernel SW Provider 1.23" 89 }; 90 91 static struct modlinkage modlinkage = { 92 MODREV_1, 93 (void *)&modlmisc, 94 (void *)&modlcrypto, 95 NULL 96 }; 97 98 /* 99 * CSPI information (entry points, provider info, etc.) 100 */ 101 102 typedef enum md5_mech_type { 103 MD5_MECH_INFO_TYPE, /* SUN_CKM_MD5 */ 104 MD5_HMAC_MECH_INFO_TYPE, /* SUN_CKM_MD5_HMAC */ 105 MD5_HMAC_GEN_MECH_INFO_TYPE /* SUN_CKM_MD5_HMAC_GENERAL */ 106 } md5_mech_type_t; 107 108 #define MD5_DIGEST_LENGTH 16 /* MD5 digest length in bytes */ 109 #define MD5_HMAC_BLOCK_SIZE 64 /* MD5 block size */ 110 #define MD5_HMAC_MIN_KEY_LEN 8 /* MD5-HMAC min key length in bits */ 111 #define MD5_HMAC_MAX_KEY_LEN INT_MAX /* MD5-HMAC max key length in bits */ 112 #define MD5_HMAC_INTS_PER_BLOCK (MD5_HMAC_BLOCK_SIZE/sizeof (uint32_t)) 113 114 /* 115 * Context for MD5 mechanism. 116 */ 117 typedef struct md5_ctx { 118 md5_mech_type_t mc_mech_type; /* type of context */ 119 MD5_CTX mc_md5_ctx; /* MD5 context */ 120 } md5_ctx_t; 121 122 /* 123 * Context for MD5-HMAC and MD5-HMAC-GENERAL mechanisms. 124 */ 125 typedef struct md5_hmac_ctx { 126 md5_mech_type_t hc_mech_type; /* type of context */ 127 uint32_t hc_digest_len; /* digest len in bytes */ 128 MD5_CTX hc_icontext; /* inner MD5 context */ 129 MD5_CTX hc_ocontext; /* outer MD5 context */ 130 } md5_hmac_ctx_t; 131 132 /* 133 * Macros to access the MD5 or MD5-HMAC contexts from a context passed 134 * by KCF to one of the entry points. 135 */ 136 137 #define PROV_MD5_CTX(ctx) ((md5_ctx_t *)(ctx)->cc_provider_private) 138 #define PROV_MD5_HMAC_CTX(ctx) ((md5_hmac_ctx_t *)(ctx)->cc_provider_private) 139 /* to extract the digest length passed as mechanism parameter */ 140 141 #define PROV_MD5_GET_DIGEST_LEN(m, len) { \ 142 if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t))) \ 143 (len) = (uint32_t)*((ulong_t *)mechanism->cm_param); \ 144 else { \ 145 ulong_t tmp_ulong; \ 146 bcopy((m)->cm_param, &tmp_ulong, sizeof (ulong_t)); \ 147 (len) = (uint32_t)tmp_ulong; \ 148 } \ 149 } 150 151 #define PROV_MD5_DIGEST_KEY(ctx, key, len, digest) { \ 152 MD5Init(ctx); \ 153 MD5Update(ctx, key, len); \ 154 MD5Final(digest, ctx); \ 155 } 156 157 /* 158 * Mechanism info structure passed to KCF during registration. 159 */ 160 static crypto_mech_info_t md5_mech_info_tab[] = { 161 /* MD5 */ 162 {SUN_CKM_MD5, MD5_MECH_INFO_TYPE, 163 CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 164 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 165 /* MD5-HMAC */ 166 {SUN_CKM_MD5_HMAC, MD5_HMAC_MECH_INFO_TYPE, 167 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 168 MD5_HMAC_MIN_KEY_LEN, MD5_HMAC_MAX_KEY_LEN, 169 CRYPTO_KEYSIZE_UNIT_IN_BITS}, 170 /* MD5-HMAC GENERAL */ 171 {SUN_CKM_MD5_HMAC_GENERAL, MD5_HMAC_GEN_MECH_INFO_TYPE, 172 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 173 MD5_HMAC_MIN_KEY_LEN, MD5_HMAC_MAX_KEY_LEN, 174 CRYPTO_KEYSIZE_UNIT_IN_BITS} 175 }; 176 177 static void md5_provider_status(crypto_provider_handle_t, uint_t *); 178 179 static crypto_control_ops_t md5_control_ops = { 180 md5_provider_status 181 }; 182 183 static int md5_digest_init(crypto_ctx_t *, crypto_mechanism_t *, 184 crypto_req_handle_t); 185 static int md5_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 186 crypto_req_handle_t); 187 static int md5_digest_update(crypto_ctx_t *, crypto_data_t *, 188 crypto_req_handle_t); 189 static int md5_digest_final(crypto_ctx_t *, crypto_data_t *, 190 crypto_req_handle_t); 191 static int md5_digest_atomic(crypto_provider_handle_t, crypto_session_id_t, 192 crypto_mechanism_t *, crypto_data_t *, crypto_data_t *, 193 crypto_req_handle_t); 194 195 static crypto_digest_ops_t md5_digest_ops = { 196 md5_digest_init, 197 md5_digest, 198 md5_digest_update, 199 NULL, 200 md5_digest_final, 201 md5_digest_atomic 202 }; 203 204 static int md5_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, 205 crypto_spi_ctx_template_t, crypto_req_handle_t); 206 static int md5_mac_update(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); 207 static int md5_mac_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); 208 static int md5_mac_atomic(crypto_provider_handle_t, crypto_session_id_t, 209 crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 210 crypto_spi_ctx_template_t, crypto_req_handle_t); 211 static int md5_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t, 212 crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 213 crypto_spi_ctx_template_t, crypto_req_handle_t); 214 215 static crypto_mac_ops_t md5_mac_ops = { 216 md5_mac_init, 217 NULL, 218 md5_mac_update, 219 md5_mac_final, 220 md5_mac_atomic, 221 md5_mac_verify_atomic 222 }; 223 224 static int md5_create_ctx_template(crypto_provider_handle_t, 225 crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *, 226 size_t *, crypto_req_handle_t); 227 static int md5_free_context(crypto_ctx_t *); 228 229 static crypto_ctx_ops_t md5_ctx_ops = { 230 md5_create_ctx_template, 231 md5_free_context 232 }; 233 234 static crypto_ops_t md5_crypto_ops = { 235 &md5_control_ops, 236 &md5_digest_ops, 237 NULL, 238 &md5_mac_ops, 239 NULL, 240 NULL, 241 NULL, 242 NULL, 243 NULL, 244 NULL, 245 NULL, 246 NULL, 247 NULL, 248 &md5_ctx_ops 249 }; 250 251 static crypto_provider_info_t md5_prov_info = { 252 CRYPTO_SPI_VERSION_1, 253 "MD5 Software Provider", 254 CRYPTO_SW_PROVIDER, 255 {&modlinkage}, 256 NULL, 257 &md5_crypto_ops, 258 sizeof (md5_mech_info_tab)/sizeof (crypto_mech_info_t), 259 md5_mech_info_tab 260 }; 261 262 static crypto_kcf_provider_handle_t md5_prov_handle = NULL; 263 264 int 265 _init(void) 266 { 267 int ret; 268 269 if ((ret = mod_install(&modlinkage)) != 0) 270 return (ret); 271 272 /* 273 * Register with KCF. If the registration fails, log an 274 * error but do not uninstall the module, since the functionality 275 * provided by misc/md5 should still be available. 276 */ 277 if ((ret = crypto_register_provider(&md5_prov_info, 278 &md5_prov_handle)) != CRYPTO_SUCCESS) 279 cmn_err(CE_WARN, "md5 _init: " 280 "crypto_register_provider() failed (0x%x)", ret); 281 282 return (0); 283 } 284 285 int 286 _fini(void) 287 { 288 int ret; 289 290 /* 291 * Unregister from KCF if previous registration succeeded. 292 */ 293 if (md5_prov_handle != NULL) { 294 if ((ret = crypto_unregister_provider(md5_prov_handle)) != 295 CRYPTO_SUCCESS) { 296 cmn_err(CE_WARN, "md5 _fini: " 297 "crypto_unregister_provider() failed (0x%x)", ret); 298 return (EBUSY); 299 } 300 md5_prov_handle = NULL; 301 } 302 303 return (mod_remove(&modlinkage)); 304 } 305 306 int 307 _info(struct modinfo *modinfop) 308 { 309 return (mod_info(&modlinkage, modinfop)); 310 } 311 #endif /* _KERNEL && !_BOOT */ 312 313 static void Encode(uint8_t *, uint32_t *, size_t); 314 static void MD5Transform(uint32_t, uint32_t, uint32_t, uint32_t, MD5_CTX *, 315 const uint8_t [64]); 316 317 static uint8_t PADDING[64] = { 0x80, /* all zeros */ }; 318 319 /* 320 * F, G, H and I are the basic MD5 functions. 321 */ 322 #define F(b, c, d) (((b) & (c)) | ((~b) & (d))) 323 #define G(b, c, d) (((b) & (d)) | ((c) & (~d))) 324 #define H(b, c, d) ((b) ^ (c) ^ (d)) 325 #define I(b, c, d) ((c) ^ ((b) | (~d))) 326 327 /* 328 * ROTATE_LEFT rotates x left n bits. 329 */ 330 #define ROTATE_LEFT(x, n) \ 331 (((x) << (n)) | ((x) >> ((sizeof (x) << 3) - (n)))) 332 333 /* 334 * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 335 * Rotation is separate from addition to prevent recomputation. 336 */ 337 338 #define FF(a, b, c, d, x, s, ac) { \ 339 (a) += F((b), (c), (d)) + (x) + ((unsigned long long)(ac)); \ 340 (a) = ROTATE_LEFT((a), (s)); \ 341 (a) += (b); \ 342 } 343 344 #define GG(a, b, c, d, x, s, ac) { \ 345 (a) += G((b), (c), (d)) + (x) + ((unsigned long long)(ac)); \ 346 (a) = ROTATE_LEFT((a), (s)); \ 347 (a) += (b); \ 348 } 349 350 #define HH(a, b, c, d, x, s, ac) { \ 351 (a) += H((b), (c), (d)) + (x) + ((unsigned long long)(ac)); \ 352 (a) = ROTATE_LEFT((a), (s)); \ 353 (a) += (b); \ 354 } 355 356 #define II(a, b, c, d, x, s, ac) { \ 357 (a) += I((b), (c), (d)) + (x) + ((unsigned long long)(ac)); \ 358 (a) = ROTATE_LEFT((a), (s)); \ 359 (a) += (b); \ 360 } 361 362 /* 363 * Loading 32-bit constants on a RISC is expensive since it involves both a 364 * `sethi' and an `or'. thus, we instead have the compiler generate `ld's to 365 * load the constants from an array called `md5_consts'. however, on intel 366 * (and other CISC processors), it is cheaper to load the constant 367 * directly. thus, the c code in MD5Transform() uses the macro MD5_CONST() 368 * which either expands to a constant or an array reference, depending on the 369 * architecture the code is being compiled for. 370 * 371 * Right now, i386 and amd64 are the CISC exceptions. 372 * If we get another CISC ISA, we'll have to change the ifdef. 373 */ 374 375 #if defined(__i386) || defined(__amd64) 376 377 #define MD5_CONST(x) (MD5_CONST_ ## x) 378 #define MD5_CONST_e(x) MD5_CONST(x) 379 #define MD5_CONST_o(x) MD5_CONST(x) 380 381 #else 382 /* 383 * sparc/RISC optimization: 384 * 385 * while it is somewhat counter-intuitive, on sparc (and presumably other RISC 386 * machines), it is more efficient to place all the constants used in this 387 * function in an array and load the values out of the array than to manually 388 * load the constants. this is because setting a register to a 32-bit value 389 * takes two ops in most cases: a `sethi' and an `or', but loading a 32-bit 390 * value from memory only takes one `ld' (or `lduw' on v9). while this 391 * increases memory usage, the compiler can find enough other things to do 392 * while waiting to keep the pipeline does not stall. additionally, it is 393 * likely that many of these constants are cached so that later accesses do 394 * not even go out to the bus. 395 * 396 * this array is declared `static' to keep the compiler from having to 397 * bcopy() this array onto the stack frame of MD5Transform() each time it is 398 * called -- which is unacceptably expensive. 399 * 400 * the `const' is to ensure that callers are good citizens and do not try to 401 * munge the array. since these routines are going to be called from inside 402 * multithreaded kernelland, this is a good safety check. -- `constants' will 403 * end up in .rodata. 404 * 405 * unfortunately, loading from an array in this manner hurts performance under 406 * intel (and presumably other CISC machines). so, there is a macro, 407 * MD5_CONST(), used in MD5Transform(), that either expands to a reference to 408 * this array, or to the actual constant, depending on what platform this code 409 * is compiled for. 410 */ 411 412 #ifdef sun4v 413 414 /* 415 * Going to load these consts in 8B chunks, so need to enforce 8B alignment 416 */ 417 418 /* CSTYLED */ 419 #pragma align 64 (md5_consts) 420 421 #endif /* sun4v */ 422 423 static const uint32_t md5_consts[] = { 424 MD5_CONST_0, MD5_CONST_1, MD5_CONST_2, MD5_CONST_3, 425 MD5_CONST_4, MD5_CONST_5, MD5_CONST_6, MD5_CONST_7, 426 MD5_CONST_8, MD5_CONST_9, MD5_CONST_10, MD5_CONST_11, 427 MD5_CONST_12, MD5_CONST_13, MD5_CONST_14, MD5_CONST_15, 428 MD5_CONST_16, MD5_CONST_17, MD5_CONST_18, MD5_CONST_19, 429 MD5_CONST_20, MD5_CONST_21, MD5_CONST_22, MD5_CONST_23, 430 MD5_CONST_24, MD5_CONST_25, MD5_CONST_26, MD5_CONST_27, 431 MD5_CONST_28, MD5_CONST_29, MD5_CONST_30, MD5_CONST_31, 432 MD5_CONST_32, MD5_CONST_33, MD5_CONST_34, MD5_CONST_35, 433 MD5_CONST_36, MD5_CONST_37, MD5_CONST_38, MD5_CONST_39, 434 MD5_CONST_40, MD5_CONST_41, MD5_CONST_42, MD5_CONST_43, 435 MD5_CONST_44, MD5_CONST_45, MD5_CONST_46, MD5_CONST_47, 436 MD5_CONST_48, MD5_CONST_49, MD5_CONST_50, MD5_CONST_51, 437 MD5_CONST_52, MD5_CONST_53, MD5_CONST_54, MD5_CONST_55, 438 MD5_CONST_56, MD5_CONST_57, MD5_CONST_58, MD5_CONST_59, 439 MD5_CONST_60, MD5_CONST_61, MD5_CONST_62, MD5_CONST_63 440 }; 441 442 443 #ifdef sun4v 444 /* 445 * To reduce the number of loads, load consts in 64-bit 446 * chunks and then split. 447 * 448 * No need to mask upper 32-bits, as just interested in 449 * low 32-bits (saves an & operation and means that this 450 * optimization doesn't increases the icount. 451 */ 452 #define MD5_CONST_e(x) (md5_consts64[x/2] >> 32) 453 #define MD5_CONST_o(x) (md5_consts64[x/2]) 454 455 #else 456 457 #define MD5_CONST_e(x) (md5_consts[x]) 458 #define MD5_CONST_o(x) (md5_consts[x]) 459 460 #endif /* sun4v */ 461 462 #endif 463 464 /* 465 * MD5Init() 466 * 467 * purpose: initializes the md5 context and begins and md5 digest operation 468 * input: MD5_CTX * : the context to initialize. 469 * output: void 470 */ 471 472 void 473 MD5Init(MD5_CTX *ctx) 474 { 475 ctx->count[0] = ctx->count[1] = 0; 476 477 /* load magic initialization constants */ 478 ctx->state[0] = MD5_INIT_CONST_1; 479 ctx->state[1] = MD5_INIT_CONST_2; 480 ctx->state[2] = MD5_INIT_CONST_3; 481 ctx->state[3] = MD5_INIT_CONST_4; 482 } 483 484 /* 485 * MD5Update() 486 * 487 * purpose: continues an md5 digest operation, using the message block 488 * to update the context. 489 * input: MD5_CTX * : the context to update 490 * uint8_t * : the message block 491 * uint32_t : the length of the message block in bytes 492 * output: void 493 * 494 * MD5 crunches in 64-byte blocks. All numeric constants here are related to 495 * that property of MD5. 496 */ 497 498 void 499 MD5Update(MD5_CTX *ctx, const void *inpp, unsigned int input_len) 500 { 501 uint32_t i, buf_index, buf_len; 502 #ifdef sun4v 503 uint32_t old_asi; 504 #endif /* sun4v */ 505 const unsigned char *input = (const unsigned char *)inpp; 506 507 /* compute (number of bytes computed so far) mod 64 */ 508 buf_index = (ctx->count[0] >> 3) & 0x3F; 509 510 /* update number of bits hashed into this MD5 computation so far */ 511 if ((ctx->count[0] += (input_len << 3)) < (input_len << 3)) 512 ctx->count[1]++; 513 ctx->count[1] += (input_len >> 29); 514 515 buf_len = 64 - buf_index; 516 517 /* transform as many times as possible */ 518 i = 0; 519 if (input_len >= buf_len) { 520 521 /* 522 * general optimization: 523 * 524 * only do initial bcopy() and MD5Transform() if 525 * buf_index != 0. if buf_index == 0, we're just 526 * wasting our time doing the bcopy() since there 527 * wasn't any data left over from a previous call to 528 * MD5Update(). 529 */ 530 531 #ifdef sun4v 532 /* 533 * For N1 use %asi register. However, costly to repeatedly set 534 * in MD5Transform. Therefore, set once here. 535 * Should probably restore the old value afterwards... 536 */ 537 old_asi = get_little(); 538 set_little(0x88); 539 #endif /* sun4v */ 540 541 if (buf_index) { 542 bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len); 543 544 MD5Transform(ctx->state[0], ctx->state[1], 545 ctx->state[2], ctx->state[3], ctx, 546 ctx->buf_un.buf8); 547 548 i = buf_len; 549 } 550 551 for (; i + 63 < input_len; i += 64) 552 MD5Transform(ctx->state[0], ctx->state[1], 553 ctx->state[2], ctx->state[3], ctx, &input[i]); 554 555 556 #ifdef sun4v 557 /* 558 * Restore old %ASI value 559 */ 560 set_little(old_asi); 561 #endif /* sun4v */ 562 563 /* 564 * general optimization: 565 * 566 * if i and input_len are the same, return now instead 567 * of calling bcopy(), since the bcopy() in this 568 * case will be an expensive nop. 569 */ 570 571 if (input_len == i) 572 return; 573 574 buf_index = 0; 575 } 576 577 /* buffer remaining input */ 578 bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i); 579 } 580 581 /* 582 * MD5Final() 583 * 584 * purpose: ends an md5 digest operation, finalizing the message digest and 585 * zeroing the context. 586 * input: uint8_t * : a buffer to store the digest in 587 * MD5_CTX * : the context to finalize, save, and zero 588 * output: void 589 */ 590 591 void 592 MD5Final(unsigned char *digest, MD5_CTX *ctx) 593 { 594 uint8_t bitcount_le[sizeof (ctx->count)]; 595 uint32_t index = (ctx->count[0] >> 3) & 0x3f; 596 597 /* store bit count, little endian */ 598 Encode(bitcount_le, ctx->count, sizeof (bitcount_le)); 599 600 /* pad out to 56 mod 64 */ 601 MD5Update(ctx, PADDING, ((index < 56) ? 56 : 120) - index); 602 603 /* append length (before padding) */ 604 MD5Update(ctx, bitcount_le, sizeof (bitcount_le)); 605 606 /* store state in digest */ 607 Encode(digest, ctx->state, sizeof (ctx->state)); 608 609 /* zeroize sensitive information */ 610 bzero(ctx, sizeof (*ctx)); 611 } 612 613 #ifndef _KERNEL 614 615 void 616 md5_calc(unsigned char *output, unsigned char *input, unsigned int inlen) 617 { 618 MD5_CTX context; 619 620 MD5Init(&context); 621 MD5Update(&context, input, inlen); 622 MD5Final(output, &context); 623 } 624 625 #endif /* !_KERNEL */ 626 627 /* 628 * sparc register window optimization: 629 * 630 * `a', `b', `c', and `d' are passed into MD5Transform explicitly 631 * since it increases the number of registers available to the 632 * compiler. under this scheme, these variables can be held in 633 * %i0 - %i3, which leaves more local and out registers available. 634 */ 635 636 /* 637 * MD5Transform() 638 * 639 * purpose: md5 transformation -- updates the digest based on `block' 640 * input: uint32_t : bytes 1 - 4 of the digest 641 * uint32_t : bytes 5 - 8 of the digest 642 * uint32_t : bytes 9 - 12 of the digest 643 * uint32_t : bytes 12 - 16 of the digest 644 * MD5_CTX * : the context to update 645 * uint8_t [64]: the block to use to update the digest 646 * output: void 647 */ 648 649 static void 650 MD5Transform(uint32_t a, uint32_t b, uint32_t c, uint32_t d, 651 MD5_CTX *ctx, const uint8_t block[64]) 652 { 653 /* 654 * general optimization: 655 * 656 * use individual integers instead of using an array. this is a 657 * win, although the amount it wins by seems to vary quite a bit. 658 */ 659 660 register uint32_t x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7; 661 register uint32_t x_8, x_9, x_10, x_11, x_12, x_13, x_14, x_15; 662 #ifdef sun4v 663 unsigned long long *md5_consts64; 664 665 md5_consts64 = (unsigned long long *) md5_consts; 666 #endif /* sun4v */ 667 668 /* 669 * general optimization: 670 * 671 * the compiler (at least SC4.2/5.x) generates better code if 672 * variable use is localized. in this case, swapping the integers in 673 * this order allows `x_0 'to be swapped nearest to its first use in 674 * FF(), and likewise for `x_1' and up. note that the compiler 675 * prefers this to doing each swap right before the FF() that 676 * uses it. 677 */ 678 679 /* 680 * sparc v9/v8plus optimization: 681 * 682 * if `block' is already aligned on a 4-byte boundary, use the 683 * optimized load_little_32() directly. otherwise, bcopy() 684 * into a buffer that *is* aligned on a 4-byte boundary and 685 * then do the load_little_32() on that buffer. benchmarks 686 * have shown that using the bcopy() is better than loading 687 * the bytes individually and doing the endian-swap by hand. 688 * 689 * even though it's quite tempting to assign to do: 690 * 691 * blk = bcopy(blk, ctx->buf_un.buf32, sizeof (ctx->buf_un.buf32)); 692 * 693 * and only have one set of LOAD_LITTLE_32()'s, the compiler (at least 694 * SC4.2/5.x) *does not* like that, so please resist the urge. 695 */ 696 697 #ifdef _MD5_CHECK_ALIGNMENT 698 if ((uintptr_t)block & 0x3) { /* not 4-byte aligned? */ 699 bcopy(block, ctx->buf_un.buf32, sizeof (ctx->buf_un.buf32)); 700 701 #ifdef sun4v 702 x_15 = LOAD_LITTLE_32_f(ctx->buf_un.buf32); 703 x_14 = LOAD_LITTLE_32_e(ctx->buf_un.buf32); 704 x_13 = LOAD_LITTLE_32_d(ctx->buf_un.buf32); 705 x_12 = LOAD_LITTLE_32_c(ctx->buf_un.buf32); 706 x_11 = LOAD_LITTLE_32_b(ctx->buf_un.buf32); 707 x_10 = LOAD_LITTLE_32_a(ctx->buf_un.buf32); 708 x_9 = LOAD_LITTLE_32_9(ctx->buf_un.buf32); 709 x_8 = LOAD_LITTLE_32_8(ctx->buf_un.buf32); 710 x_7 = LOAD_LITTLE_32_7(ctx->buf_un.buf32); 711 x_6 = LOAD_LITTLE_32_6(ctx->buf_un.buf32); 712 x_5 = LOAD_LITTLE_32_5(ctx->buf_un.buf32); 713 x_4 = LOAD_LITTLE_32_4(ctx->buf_un.buf32); 714 x_3 = LOAD_LITTLE_32_3(ctx->buf_un.buf32); 715 x_2 = LOAD_LITTLE_32_2(ctx->buf_un.buf32); 716 x_1 = LOAD_LITTLE_32_1(ctx->buf_un.buf32); 717 x_0 = LOAD_LITTLE_32_0(ctx->buf_un.buf32); 718 #else 719 x_15 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 15); 720 x_14 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 14); 721 x_13 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 13); 722 x_12 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 12); 723 x_11 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 11); 724 x_10 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 10); 725 x_9 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 9); 726 x_8 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 8); 727 x_7 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 7); 728 x_6 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 6); 729 x_5 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 5); 730 x_4 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 4); 731 x_3 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 3); 732 x_2 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 2); 733 x_1 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 1); 734 x_0 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 0); 735 #endif /* sun4v */ 736 } else 737 #endif 738 { 739 740 #ifdef sun4v 741 x_15 = LOAD_LITTLE_32_f(block); 742 x_14 = LOAD_LITTLE_32_e(block); 743 x_13 = LOAD_LITTLE_32_d(block); 744 x_12 = LOAD_LITTLE_32_c(block); 745 x_11 = LOAD_LITTLE_32_b(block); 746 x_10 = LOAD_LITTLE_32_a(block); 747 x_9 = LOAD_LITTLE_32_9(block); 748 x_8 = LOAD_LITTLE_32_8(block); 749 x_7 = LOAD_LITTLE_32_7(block); 750 x_6 = LOAD_LITTLE_32_6(block); 751 x_5 = LOAD_LITTLE_32_5(block); 752 x_4 = LOAD_LITTLE_32_4(block); 753 x_3 = LOAD_LITTLE_32_3(block); 754 x_2 = LOAD_LITTLE_32_2(block); 755 x_1 = LOAD_LITTLE_32_1(block); 756 x_0 = LOAD_LITTLE_32_0(block); 757 #else 758 x_15 = LOAD_LITTLE_32(block + 60); 759 x_14 = LOAD_LITTLE_32(block + 56); 760 x_13 = LOAD_LITTLE_32(block + 52); 761 x_12 = LOAD_LITTLE_32(block + 48); 762 x_11 = LOAD_LITTLE_32(block + 44); 763 x_10 = LOAD_LITTLE_32(block + 40); 764 x_9 = LOAD_LITTLE_32(block + 36); 765 x_8 = LOAD_LITTLE_32(block + 32); 766 x_7 = LOAD_LITTLE_32(block + 28); 767 x_6 = LOAD_LITTLE_32(block + 24); 768 x_5 = LOAD_LITTLE_32(block + 20); 769 x_4 = LOAD_LITTLE_32(block + 16); 770 x_3 = LOAD_LITTLE_32(block + 12); 771 x_2 = LOAD_LITTLE_32(block + 8); 772 x_1 = LOAD_LITTLE_32(block + 4); 773 x_0 = LOAD_LITTLE_32(block + 0); 774 #endif /* sun4v */ 775 } 776 777 /* round 1 */ 778 FF(a, b, c, d, x_0, MD5_SHIFT_11, MD5_CONST_e(0)); /* 1 */ 779 FF(d, a, b, c, x_1, MD5_SHIFT_12, MD5_CONST_o(1)); /* 2 */ 780 FF(c, d, a, b, x_2, MD5_SHIFT_13, MD5_CONST_e(2)); /* 3 */ 781 FF(b, c, d, a, x_3, MD5_SHIFT_14, MD5_CONST_o(3)); /* 4 */ 782 FF(a, b, c, d, x_4, MD5_SHIFT_11, MD5_CONST_e(4)); /* 5 */ 783 FF(d, a, b, c, x_5, MD5_SHIFT_12, MD5_CONST_o(5)); /* 6 */ 784 FF(c, d, a, b, x_6, MD5_SHIFT_13, MD5_CONST_e(6)); /* 7 */ 785 FF(b, c, d, a, x_7, MD5_SHIFT_14, MD5_CONST_o(7)); /* 8 */ 786 FF(a, b, c, d, x_8, MD5_SHIFT_11, MD5_CONST_e(8)); /* 9 */ 787 FF(d, a, b, c, x_9, MD5_SHIFT_12, MD5_CONST_o(9)); /* 10 */ 788 FF(c, d, a, b, x_10, MD5_SHIFT_13, MD5_CONST_e(10)); /* 11 */ 789 FF(b, c, d, a, x_11, MD5_SHIFT_14, MD5_CONST_o(11)); /* 12 */ 790 FF(a, b, c, d, x_12, MD5_SHIFT_11, MD5_CONST_e(12)); /* 13 */ 791 FF(d, a, b, c, x_13, MD5_SHIFT_12, MD5_CONST_o(13)); /* 14 */ 792 FF(c, d, a, b, x_14, MD5_SHIFT_13, MD5_CONST_e(14)); /* 15 */ 793 FF(b, c, d, a, x_15, MD5_SHIFT_14, MD5_CONST_o(15)); /* 16 */ 794 795 /* round 2 */ 796 GG(a, b, c, d, x_1, MD5_SHIFT_21, MD5_CONST_e(16)); /* 17 */ 797 GG(d, a, b, c, x_6, MD5_SHIFT_22, MD5_CONST_o(17)); /* 18 */ 798 GG(c, d, a, b, x_11, MD5_SHIFT_23, MD5_CONST_e(18)); /* 19 */ 799 GG(b, c, d, a, x_0, MD5_SHIFT_24, MD5_CONST_o(19)); /* 20 */ 800 GG(a, b, c, d, x_5, MD5_SHIFT_21, MD5_CONST_e(20)); /* 21 */ 801 GG(d, a, b, c, x_10, MD5_SHIFT_22, MD5_CONST_o(21)); /* 22 */ 802 GG(c, d, a, b, x_15, MD5_SHIFT_23, MD5_CONST_e(22)); /* 23 */ 803 GG(b, c, d, a, x_4, MD5_SHIFT_24, MD5_CONST_o(23)); /* 24 */ 804 GG(a, b, c, d, x_9, MD5_SHIFT_21, MD5_CONST_e(24)); /* 25 */ 805 GG(d, a, b, c, x_14, MD5_SHIFT_22, MD5_CONST_o(25)); /* 26 */ 806 GG(c, d, a, b, x_3, MD5_SHIFT_23, MD5_CONST_e(26)); /* 27 */ 807 GG(b, c, d, a, x_8, MD5_SHIFT_24, MD5_CONST_o(27)); /* 28 */ 808 GG(a, b, c, d, x_13, MD5_SHIFT_21, MD5_CONST_e(28)); /* 29 */ 809 GG(d, a, b, c, x_2, MD5_SHIFT_22, MD5_CONST_o(29)); /* 30 */ 810 GG(c, d, a, b, x_7, MD5_SHIFT_23, MD5_CONST_e(30)); /* 31 */ 811 GG(b, c, d, a, x_12, MD5_SHIFT_24, MD5_CONST_o(31)); /* 32 */ 812 813 /* round 3 */ 814 HH(a, b, c, d, x_5, MD5_SHIFT_31, MD5_CONST_e(32)); /* 33 */ 815 HH(d, a, b, c, x_8, MD5_SHIFT_32, MD5_CONST_o(33)); /* 34 */ 816 HH(c, d, a, b, x_11, MD5_SHIFT_33, MD5_CONST_e(34)); /* 35 */ 817 HH(b, c, d, a, x_14, MD5_SHIFT_34, MD5_CONST_o(35)); /* 36 */ 818 HH(a, b, c, d, x_1, MD5_SHIFT_31, MD5_CONST_e(36)); /* 37 */ 819 HH(d, a, b, c, x_4, MD5_SHIFT_32, MD5_CONST_o(37)); /* 38 */ 820 HH(c, d, a, b, x_7, MD5_SHIFT_33, MD5_CONST_e(38)); /* 39 */ 821 HH(b, c, d, a, x_10, MD5_SHIFT_34, MD5_CONST_o(39)); /* 40 */ 822 HH(a, b, c, d, x_13, MD5_SHIFT_31, MD5_CONST_e(40)); /* 41 */ 823 HH(d, a, b, c, x_0, MD5_SHIFT_32, MD5_CONST_o(41)); /* 42 */ 824 HH(c, d, a, b, x_3, MD5_SHIFT_33, MD5_CONST_e(42)); /* 43 */ 825 HH(b, c, d, a, x_6, MD5_SHIFT_34, MD5_CONST_o(43)); /* 44 */ 826 HH(a, b, c, d, x_9, MD5_SHIFT_31, MD5_CONST_e(44)); /* 45 */ 827 HH(d, a, b, c, x_12, MD5_SHIFT_32, MD5_CONST_o(45)); /* 46 */ 828 HH(c, d, a, b, x_15, MD5_SHIFT_33, MD5_CONST_e(46)); /* 47 */ 829 HH(b, c, d, a, x_2, MD5_SHIFT_34, MD5_CONST_o(47)); /* 48 */ 830 831 /* round 4 */ 832 II(a, b, c, d, x_0, MD5_SHIFT_41, MD5_CONST_e(48)); /* 49 */ 833 II(d, a, b, c, x_7, MD5_SHIFT_42, MD5_CONST_o(49)); /* 50 */ 834 II(c, d, a, b, x_14, MD5_SHIFT_43, MD5_CONST_e(50)); /* 51 */ 835 II(b, c, d, a, x_5, MD5_SHIFT_44, MD5_CONST_o(51)); /* 52 */ 836 II(a, b, c, d, x_12, MD5_SHIFT_41, MD5_CONST_e(52)); /* 53 */ 837 II(d, a, b, c, x_3, MD5_SHIFT_42, MD5_CONST_o(53)); /* 54 */ 838 II(c, d, a, b, x_10, MD5_SHIFT_43, MD5_CONST_e(54)); /* 55 */ 839 II(b, c, d, a, x_1, MD5_SHIFT_44, MD5_CONST_o(55)); /* 56 */ 840 II(a, b, c, d, x_8, MD5_SHIFT_41, MD5_CONST_e(56)); /* 57 */ 841 II(d, a, b, c, x_15, MD5_SHIFT_42, MD5_CONST_o(57)); /* 58 */ 842 II(c, d, a, b, x_6, MD5_SHIFT_43, MD5_CONST_e(58)); /* 59 */ 843 II(b, c, d, a, x_13, MD5_SHIFT_44, MD5_CONST_o(59)); /* 60 */ 844 II(a, b, c, d, x_4, MD5_SHIFT_41, MD5_CONST_e(60)); /* 61 */ 845 II(d, a, b, c, x_11, MD5_SHIFT_42, MD5_CONST_o(61)); /* 62 */ 846 II(c, d, a, b, x_2, MD5_SHIFT_43, MD5_CONST_e(62)); /* 63 */ 847 II(b, c, d, a, x_9, MD5_SHIFT_44, MD5_CONST_o(63)); /* 64 */ 848 849 ctx->state[0] += a; 850 ctx->state[1] += b; 851 ctx->state[2] += c; 852 ctx->state[3] += d; 853 854 /* 855 * zeroize sensitive information -- compiler will optimize 856 * this out if everything is kept in registers 857 */ 858 859 x_0 = x_1 = x_2 = x_3 = x_4 = x_5 = x_6 = x_7 = x_8 = 0; 860 x_9 = x_10 = x_11 = x_12 = x_13 = x_14 = x_15 = 0; 861 } 862 863 /* 864 * devpro compiler optimization: 865 * 866 * the compiler can generate better code if it knows that `input' and 867 * `output' do not point to the same source. there is no portable 868 * way to tell the compiler this, but the devpro compiler recognizes the 869 * `_Restrict' keyword to indicate this condition. use it if possible. 870 */ 871 872 #if defined(__RESTRICT) && !defined(__GNUC__) 873 #define restrict _Restrict 874 #else 875 #define restrict /* nothing */ 876 #endif 877 878 /* 879 * Encode() 880 * 881 * purpose: to convert a list of numbers from big endian to little endian 882 * input: uint8_t * : place to store the converted little endian numbers 883 * uint32_t * : place to get numbers to convert from 884 * size_t : the length of the input in bytes 885 * output: void 886 */ 887 888 static void 889 Encode(uint8_t *restrict output, uint32_t *restrict input, size_t input_len) 890 { 891 size_t i, j; 892 893 for (i = 0, j = 0; j < input_len; i++, j += sizeof (uint32_t)) { 894 895 #ifdef _LITTLE_ENDIAN 896 897 #ifdef _MD5_CHECK_ALIGNMENT 898 if ((uintptr_t)output & 0x3) /* Not 4-byte aligned */ 899 bcopy(input + i, output + j, 4); 900 else *(uint32_t *)(output + j) = input[i]; 901 #else 902 *(uint32_t *)(output + j) = input[i]; 903 #endif /* _MD5_CHECK_ALIGNMENT */ 904 905 #else /* big endian -- will work on little endian, but slowly */ 906 907 output[j] = input[i] & 0xff; 908 output[j + 1] = (input[i] >> 8) & 0xff; 909 output[j + 2] = (input[i] >> 16) & 0xff; 910 output[j + 3] = (input[i] >> 24) & 0xff; 911 #endif 912 } 913 } 914 915 #if defined(_KERNEL) && !defined(_BOOT) 916 917 /* 918 * KCF software provider control entry points. 919 */ 920 /* ARGSUSED */ 921 static void 922 md5_provider_status(crypto_provider_handle_t provider, uint_t *status) 923 { 924 *status = CRYPTO_PROVIDER_READY; 925 } 926 927 /* 928 * KCF software provider digest entry points. 929 */ 930 931 static int 932 md5_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 933 crypto_req_handle_t req) 934 { 935 if (mechanism->cm_type != MD5_MECH_INFO_TYPE) 936 return (CRYPTO_MECHANISM_INVALID); 937 938 /* 939 * Allocate and initialize MD5 context. 940 */ 941 ctx->cc_provider_private = kmem_alloc(sizeof (md5_ctx_t), 942 crypto_kmflag(req)); 943 if (ctx->cc_provider_private == NULL) 944 return (CRYPTO_HOST_MEMORY); 945 946 PROV_MD5_CTX(ctx)->mc_mech_type = MD5_MECH_INFO_TYPE; 947 MD5Init(&PROV_MD5_CTX(ctx)->mc_md5_ctx); 948 949 return (CRYPTO_SUCCESS); 950 } 951 952 /* 953 * Helper MD5 digest update function for uio data. 954 */ 955 static int 956 md5_digest_update_uio(MD5_CTX *md5_ctx, crypto_data_t *data) 957 { 958 off_t offset = data->cd_offset; 959 size_t length = data->cd_length; 960 uint_t vec_idx; 961 size_t cur_len; 962 963 /* we support only kernel buffer */ 964 if (data->cd_uio->uio_segflg != UIO_SYSSPACE) 965 return (CRYPTO_ARGUMENTS_BAD); 966 967 /* 968 * Jump to the first iovec containing data to be 969 * digested. 970 */ 971 for (vec_idx = 0; vec_idx < data->cd_uio->uio_iovcnt && 972 offset >= data->cd_uio->uio_iov[vec_idx].iov_len; 973 offset -= data->cd_uio->uio_iov[vec_idx++].iov_len); 974 if (vec_idx == data->cd_uio->uio_iovcnt) { 975 /* 976 * The caller specified an offset that is larger than the 977 * total size of the buffers it provided. 978 */ 979 return (CRYPTO_DATA_LEN_RANGE); 980 } 981 982 /* 983 * Now do the digesting on the iovecs. 984 */ 985 while (vec_idx < data->cd_uio->uio_iovcnt && length > 0) { 986 cur_len = MIN(data->cd_uio->uio_iov[vec_idx].iov_len - 987 offset, length); 988 989 MD5Update(md5_ctx, data->cd_uio->uio_iov[vec_idx].iov_base + 990 offset, cur_len); 991 992 length -= cur_len; 993 vec_idx++; 994 offset = 0; 995 } 996 997 if (vec_idx == data->cd_uio->uio_iovcnt && length > 0) { 998 /* 999 * The end of the specified iovec's was reached but 1000 * the length requested could not be processed, i.e. 1001 * The caller requested to digest more data than it provided. 1002 */ 1003 return (CRYPTO_DATA_LEN_RANGE); 1004 } 1005 1006 return (CRYPTO_SUCCESS); 1007 } 1008 1009 /* 1010 * Helper MD5 digest final function for uio data. 1011 * digest_len is the length of the desired digest. If digest_len 1012 * is smaller than the default MD5 digest length, the caller 1013 * must pass a scratch buffer, digest_scratch, which must 1014 * be at least MD5_DIGEST_LENGTH bytes. 1015 */ 1016 static int 1017 md5_digest_final_uio(MD5_CTX *md5_ctx, crypto_data_t *digest, 1018 ulong_t digest_len, uchar_t *digest_scratch) 1019 { 1020 off_t offset = digest->cd_offset; 1021 uint_t vec_idx; 1022 1023 /* we support only kernel buffer */ 1024 if (digest->cd_uio->uio_segflg != UIO_SYSSPACE) 1025 return (CRYPTO_ARGUMENTS_BAD); 1026 1027 /* 1028 * Jump to the first iovec containing ptr to the digest to 1029 * be returned. 1030 */ 1031 for (vec_idx = 0; offset >= digest->cd_uio->uio_iov[vec_idx].iov_len && 1032 vec_idx < digest->cd_uio->uio_iovcnt; 1033 offset -= digest->cd_uio->uio_iov[vec_idx++].iov_len); 1034 if (vec_idx == digest->cd_uio->uio_iovcnt) { 1035 /* 1036 * The caller specified an offset that is 1037 * larger than the total size of the buffers 1038 * it provided. 1039 */ 1040 return (CRYPTO_DATA_LEN_RANGE); 1041 } 1042 1043 if (offset + digest_len <= 1044 digest->cd_uio->uio_iov[vec_idx].iov_len) { 1045 /* 1046 * The computed MD5 digest will fit in the current 1047 * iovec. 1048 */ 1049 if (digest_len != MD5_DIGEST_LENGTH) { 1050 /* 1051 * The caller requested a short digest. Digest 1052 * into a scratch buffer and return to 1053 * the user only what was requested. 1054 */ 1055 MD5Final(digest_scratch, md5_ctx); 1056 bcopy(digest_scratch, (uchar_t *)digest-> 1057 cd_uio->uio_iov[vec_idx].iov_base + offset, 1058 digest_len); 1059 } else { 1060 MD5Final((uchar_t *)digest-> 1061 cd_uio->uio_iov[vec_idx].iov_base + offset, 1062 md5_ctx); 1063 } 1064 } else { 1065 /* 1066 * The computed digest will be crossing one or more iovec's. 1067 * This is bad performance-wise but we need to support it. 1068 * Allocate a small scratch buffer on the stack and 1069 * copy it piece meal to the specified digest iovec's. 1070 */ 1071 uchar_t digest_tmp[MD5_DIGEST_LENGTH]; 1072 off_t scratch_offset = 0; 1073 size_t length = digest_len; 1074 size_t cur_len; 1075 1076 MD5Final(digest_tmp, md5_ctx); 1077 1078 while (vec_idx < digest->cd_uio->uio_iovcnt && length > 0) { 1079 cur_len = MIN(digest->cd_uio->uio_iov[vec_idx].iov_len - 1080 offset, length); 1081 bcopy(digest_tmp + scratch_offset, 1082 digest->cd_uio->uio_iov[vec_idx].iov_base + offset, 1083 cur_len); 1084 1085 length -= cur_len; 1086 vec_idx++; 1087 scratch_offset += cur_len; 1088 offset = 0; 1089 } 1090 1091 if (vec_idx == digest->cd_uio->uio_iovcnt && length > 0) { 1092 /* 1093 * The end of the specified iovec's was reached but 1094 * the length requested could not be processed, i.e. 1095 * The caller requested to digest more data than it 1096 * provided. 1097 */ 1098 return (CRYPTO_DATA_LEN_RANGE); 1099 } 1100 } 1101 1102 return (CRYPTO_SUCCESS); 1103 } 1104 1105 /* 1106 * Helper MD5 digest update for mblk's. 1107 */ 1108 static int 1109 md5_digest_update_mblk(MD5_CTX *md5_ctx, crypto_data_t *data) 1110 { 1111 off_t offset = data->cd_offset; 1112 size_t length = data->cd_length; 1113 mblk_t *mp; 1114 size_t cur_len; 1115 1116 /* 1117 * Jump to the first mblk_t containing data to be digested. 1118 */ 1119 for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp); 1120 offset -= MBLKL(mp), mp = mp->b_cont); 1121 if (mp == NULL) { 1122 /* 1123 * The caller specified an offset that is larger than the 1124 * total size of the buffers it provided. 1125 */ 1126 return (CRYPTO_DATA_LEN_RANGE); 1127 } 1128 1129 /* 1130 * Now do the digesting on the mblk chain. 1131 */ 1132 while (mp != NULL && length > 0) { 1133 cur_len = MIN(MBLKL(mp) - offset, length); 1134 MD5Update(md5_ctx, mp->b_rptr + offset, cur_len); 1135 length -= cur_len; 1136 offset = 0; 1137 mp = mp->b_cont; 1138 } 1139 1140 if (mp == NULL && length > 0) { 1141 /* 1142 * The end of the mblk was reached but the length requested 1143 * could not be processed, i.e. The caller requested 1144 * to digest more data than it provided. 1145 */ 1146 return (CRYPTO_DATA_LEN_RANGE); 1147 } 1148 1149 return (CRYPTO_SUCCESS); 1150 } 1151 1152 /* 1153 * Helper MD5 digest final for mblk's. 1154 * digest_len is the length of the desired digest. If digest_len 1155 * is smaller than the default MD5 digest length, the caller 1156 * must pass a scratch buffer, digest_scratch, which must 1157 * be at least MD5_DIGEST_LENGTH bytes. 1158 */ 1159 static int 1160 md5_digest_final_mblk(MD5_CTX *md5_ctx, crypto_data_t *digest, 1161 ulong_t digest_len, uchar_t *digest_scratch) 1162 { 1163 off_t offset = digest->cd_offset; 1164 mblk_t *mp; 1165 1166 /* 1167 * Jump to the first mblk_t that will be used to store the digest. 1168 */ 1169 for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp); 1170 offset -= MBLKL(mp), mp = mp->b_cont); 1171 if (mp == NULL) { 1172 /* 1173 * The caller specified an offset that is larger than the 1174 * total size of the buffers it provided. 1175 */ 1176 return (CRYPTO_DATA_LEN_RANGE); 1177 } 1178 1179 if (offset + digest_len <= MBLKL(mp)) { 1180 /* 1181 * The computed MD5 digest will fit in the current mblk. 1182 * Do the MD5Final() in-place. 1183 */ 1184 if (digest_len != MD5_DIGEST_LENGTH) { 1185 /* 1186 * The caller requested a short digest. Digest 1187 * into a scratch buffer and return to 1188 * the user only what was requested. 1189 */ 1190 MD5Final(digest_scratch, md5_ctx); 1191 bcopy(digest_scratch, mp->b_rptr + offset, digest_len); 1192 } else { 1193 MD5Final(mp->b_rptr + offset, md5_ctx); 1194 } 1195 } else { 1196 /* 1197 * The computed digest will be crossing one or more mblk's. 1198 * This is bad performance-wise but we need to support it. 1199 * Allocate a small scratch buffer on the stack and 1200 * copy it piece meal to the specified digest iovec's. 1201 */ 1202 uchar_t digest_tmp[MD5_DIGEST_LENGTH]; 1203 off_t scratch_offset = 0; 1204 size_t length = digest_len; 1205 size_t cur_len; 1206 1207 MD5Final(digest_tmp, md5_ctx); 1208 1209 while (mp != NULL && length > 0) { 1210 cur_len = MIN(MBLKL(mp) - offset, length); 1211 bcopy(digest_tmp + scratch_offset, 1212 mp->b_rptr + offset, cur_len); 1213 1214 length -= cur_len; 1215 mp = mp->b_cont; 1216 scratch_offset += cur_len; 1217 offset = 0; 1218 } 1219 1220 if (mp == NULL && length > 0) { 1221 /* 1222 * The end of the specified mblk was reached but 1223 * the length requested could not be processed, i.e. 1224 * The caller requested to digest more data than it 1225 * provided. 1226 */ 1227 return (CRYPTO_DATA_LEN_RANGE); 1228 } 1229 } 1230 1231 return (CRYPTO_SUCCESS); 1232 } 1233 1234 /* ARGSUSED */ 1235 static int 1236 md5_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest, 1237 crypto_req_handle_t req) 1238 { 1239 int ret = CRYPTO_SUCCESS; 1240 1241 ASSERT(ctx->cc_provider_private != NULL); 1242 1243 /* 1244 * We need to just return the length needed to store the output. 1245 * We should not destroy the context for the following cases. 1246 */ 1247 if ((digest->cd_length == 0) || 1248 (digest->cd_length < MD5_DIGEST_LENGTH)) { 1249 digest->cd_length = MD5_DIGEST_LENGTH; 1250 return (CRYPTO_BUFFER_TOO_SMALL); 1251 } 1252 1253 /* 1254 * Do the MD5 update on the specified input data. 1255 */ 1256 switch (data->cd_format) { 1257 case CRYPTO_DATA_RAW: 1258 MD5Update(&PROV_MD5_CTX(ctx)->mc_md5_ctx, 1259 data->cd_raw.iov_base + data->cd_offset, 1260 data->cd_length); 1261 break; 1262 case CRYPTO_DATA_UIO: 1263 ret = md5_digest_update_uio(&PROV_MD5_CTX(ctx)->mc_md5_ctx, 1264 data); 1265 break; 1266 case CRYPTO_DATA_MBLK: 1267 ret = md5_digest_update_mblk(&PROV_MD5_CTX(ctx)->mc_md5_ctx, 1268 data); 1269 break; 1270 default: 1271 ret = CRYPTO_ARGUMENTS_BAD; 1272 } 1273 1274 if (ret != CRYPTO_SUCCESS) { 1275 /* the update failed, free context and bail */ 1276 kmem_free(ctx->cc_provider_private, sizeof (md5_ctx_t)); 1277 ctx->cc_provider_private = NULL; 1278 digest->cd_length = 0; 1279 return (ret); 1280 } 1281 1282 /* 1283 * Do an MD5 final, must be done separately since the digest 1284 * type can be different than the input data type. 1285 */ 1286 switch (digest->cd_format) { 1287 case CRYPTO_DATA_RAW: 1288 MD5Final((unsigned char *)digest->cd_raw.iov_base + 1289 digest->cd_offset, &PROV_MD5_CTX(ctx)->mc_md5_ctx); 1290 break; 1291 case CRYPTO_DATA_UIO: 1292 ret = md5_digest_final_uio(&PROV_MD5_CTX(ctx)->mc_md5_ctx, 1293 digest, MD5_DIGEST_LENGTH, NULL); 1294 break; 1295 case CRYPTO_DATA_MBLK: 1296 ret = md5_digest_final_mblk(&PROV_MD5_CTX(ctx)->mc_md5_ctx, 1297 digest, MD5_DIGEST_LENGTH, NULL); 1298 break; 1299 default: 1300 ret = CRYPTO_ARGUMENTS_BAD; 1301 } 1302 1303 /* all done, free context and return */ 1304 1305 if (ret == CRYPTO_SUCCESS) { 1306 digest->cd_length = MD5_DIGEST_LENGTH; 1307 } else { 1308 digest->cd_length = 0; 1309 } 1310 1311 kmem_free(ctx->cc_provider_private, sizeof (md5_ctx_t)); 1312 ctx->cc_provider_private = NULL; 1313 return (ret); 1314 } 1315 1316 /* ARGSUSED */ 1317 static int 1318 md5_digest_update(crypto_ctx_t *ctx, crypto_data_t *data, 1319 crypto_req_handle_t req) 1320 { 1321 int ret = CRYPTO_SUCCESS; 1322 1323 ASSERT(ctx->cc_provider_private != NULL); 1324 1325 /* 1326 * Do the MD5 update on the specified input data. 1327 */ 1328 switch (data->cd_format) { 1329 case CRYPTO_DATA_RAW: 1330 MD5Update(&PROV_MD5_CTX(ctx)->mc_md5_ctx, 1331 data->cd_raw.iov_base + data->cd_offset, 1332 data->cd_length); 1333 break; 1334 case CRYPTO_DATA_UIO: 1335 ret = md5_digest_update_uio(&PROV_MD5_CTX(ctx)->mc_md5_ctx, 1336 data); 1337 break; 1338 case CRYPTO_DATA_MBLK: 1339 ret = md5_digest_update_mblk(&PROV_MD5_CTX(ctx)->mc_md5_ctx, 1340 data); 1341 break; 1342 default: 1343 ret = CRYPTO_ARGUMENTS_BAD; 1344 } 1345 1346 return (ret); 1347 } 1348 1349 /* ARGSUSED */ 1350 static int 1351 md5_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest, 1352 crypto_req_handle_t req) 1353 { 1354 int ret = CRYPTO_SUCCESS; 1355 1356 ASSERT(ctx->cc_provider_private != NULL); 1357 1358 /* 1359 * We need to just return the length needed to store the output. 1360 * We should not destroy the context for the following cases. 1361 */ 1362 if ((digest->cd_length == 0) || 1363 (digest->cd_length < MD5_DIGEST_LENGTH)) { 1364 digest->cd_length = MD5_DIGEST_LENGTH; 1365 return (CRYPTO_BUFFER_TOO_SMALL); 1366 } 1367 1368 /* 1369 * Do an MD5 final. 1370 */ 1371 switch (digest->cd_format) { 1372 case CRYPTO_DATA_RAW: 1373 MD5Final((unsigned char *)digest->cd_raw.iov_base + 1374 digest->cd_offset, &PROV_MD5_CTX(ctx)->mc_md5_ctx); 1375 break; 1376 case CRYPTO_DATA_UIO: 1377 ret = md5_digest_final_uio(&PROV_MD5_CTX(ctx)->mc_md5_ctx, 1378 digest, MD5_DIGEST_LENGTH, NULL); 1379 break; 1380 case CRYPTO_DATA_MBLK: 1381 ret = md5_digest_final_mblk(&PROV_MD5_CTX(ctx)->mc_md5_ctx, 1382 digest, MD5_DIGEST_LENGTH, NULL); 1383 break; 1384 default: 1385 ret = CRYPTO_ARGUMENTS_BAD; 1386 } 1387 1388 /* all done, free context and return */ 1389 1390 if (ret == CRYPTO_SUCCESS) { 1391 digest->cd_length = MD5_DIGEST_LENGTH; 1392 } else { 1393 digest->cd_length = 0; 1394 } 1395 1396 kmem_free(ctx->cc_provider_private, sizeof (md5_ctx_t)); 1397 ctx->cc_provider_private = NULL; 1398 1399 return (ret); 1400 } 1401 1402 /* ARGSUSED */ 1403 static int 1404 md5_digest_atomic(crypto_provider_handle_t provider, 1405 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 1406 crypto_data_t *data, crypto_data_t *digest, 1407 crypto_req_handle_t req) 1408 { 1409 int ret = CRYPTO_SUCCESS; 1410 MD5_CTX md5_ctx; 1411 1412 if (mechanism->cm_type != MD5_MECH_INFO_TYPE) 1413 return (CRYPTO_MECHANISM_INVALID); 1414 1415 /* 1416 * Do the MD5 init. 1417 */ 1418 MD5Init(&md5_ctx); 1419 1420 /* 1421 * Do the MD5 update on the specified input data. 1422 */ 1423 switch (data->cd_format) { 1424 case CRYPTO_DATA_RAW: 1425 MD5Update(&md5_ctx, data->cd_raw.iov_base + data->cd_offset, 1426 data->cd_length); 1427 break; 1428 case CRYPTO_DATA_UIO: 1429 ret = md5_digest_update_uio(&md5_ctx, data); 1430 break; 1431 case CRYPTO_DATA_MBLK: 1432 ret = md5_digest_update_mblk(&md5_ctx, data); 1433 break; 1434 default: 1435 ret = CRYPTO_ARGUMENTS_BAD; 1436 } 1437 1438 if (ret != CRYPTO_SUCCESS) { 1439 /* the update failed, bail */ 1440 digest->cd_length = 0; 1441 return (ret); 1442 } 1443 1444 /* 1445 * Do an MD5 final, must be done separately since the digest 1446 * type can be different than the input data type. 1447 */ 1448 switch (digest->cd_format) { 1449 case CRYPTO_DATA_RAW: 1450 MD5Final((unsigned char *)digest->cd_raw.iov_base + 1451 digest->cd_offset, &md5_ctx); 1452 break; 1453 case CRYPTO_DATA_UIO: 1454 ret = md5_digest_final_uio(&md5_ctx, digest, 1455 MD5_DIGEST_LENGTH, NULL); 1456 break; 1457 case CRYPTO_DATA_MBLK: 1458 ret = md5_digest_final_mblk(&md5_ctx, digest, 1459 MD5_DIGEST_LENGTH, NULL); 1460 break; 1461 default: 1462 ret = CRYPTO_ARGUMENTS_BAD; 1463 } 1464 1465 if (ret == CRYPTO_SUCCESS) { 1466 digest->cd_length = MD5_DIGEST_LENGTH; 1467 } else { 1468 digest->cd_length = 0; 1469 } 1470 1471 return (ret); 1472 } 1473 1474 /* 1475 * KCF software provider mac entry points. 1476 * 1477 * MD5 HMAC is: MD5(key XOR opad, MD5(key XOR ipad, text)) 1478 * 1479 * Init: 1480 * The initialization routine initializes what we denote 1481 * as the inner and outer contexts by doing 1482 * - for inner context: MD5(key XOR ipad) 1483 * - for outer context: MD5(key XOR opad) 1484 * 1485 * Update: 1486 * Each subsequent MD5 HMAC update will result in an 1487 * update of the inner context with the specified data. 1488 * 1489 * Final: 1490 * The MD5 HMAC final will do a MD5 final operation on the 1491 * inner context, and the resulting digest will be used 1492 * as the data for an update on the outer context. Last 1493 * but not least, an MD5 final on the outer context will 1494 * be performed to obtain the MD5 HMAC digest to return 1495 * to the user. 1496 */ 1497 1498 /* 1499 * Initialize a MD5-HMAC context. 1500 */ 1501 static void 1502 md5_mac_init_ctx(md5_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes) 1503 { 1504 uint32_t ipad[MD5_HMAC_INTS_PER_BLOCK]; 1505 uint32_t opad[MD5_HMAC_INTS_PER_BLOCK]; 1506 uint_t i; 1507 1508 bzero(ipad, MD5_HMAC_BLOCK_SIZE); 1509 bzero(opad, MD5_HMAC_BLOCK_SIZE); 1510 1511 bcopy(keyval, ipad, length_in_bytes); 1512 bcopy(keyval, opad, length_in_bytes); 1513 1514 /* XOR key with ipad (0x36) and opad (0x5c) */ 1515 for (i = 0; i < MD5_HMAC_INTS_PER_BLOCK; i++) { 1516 ipad[i] ^= 0x36363636; 1517 opad[i] ^= 0x5c5c5c5c; 1518 } 1519 1520 /* perform MD5 on ipad */ 1521 MD5Init(&ctx->hc_icontext); 1522 MD5Update(&ctx->hc_icontext, ipad, MD5_HMAC_BLOCK_SIZE); 1523 1524 /* perform MD5 on opad */ 1525 MD5Init(&ctx->hc_ocontext); 1526 MD5Update(&ctx->hc_ocontext, opad, MD5_HMAC_BLOCK_SIZE); 1527 } 1528 1529 /* 1530 * Initializes a multi-part MAC operation. 1531 */ 1532 static int 1533 md5_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 1534 crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, 1535 crypto_req_handle_t req) 1536 { 1537 int ret = CRYPTO_SUCCESS; 1538 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 1539 1540 if (mechanism->cm_type != MD5_HMAC_MECH_INFO_TYPE && 1541 mechanism->cm_type != MD5_HMAC_GEN_MECH_INFO_TYPE) 1542 return (CRYPTO_MECHANISM_INVALID); 1543 1544 /* Add support for key by attributes (RFE 4706552) */ 1545 if (key->ck_format != CRYPTO_KEY_RAW) 1546 return (CRYPTO_ARGUMENTS_BAD); 1547 1548 ctx->cc_provider_private = kmem_alloc(sizeof (md5_hmac_ctx_t), 1549 crypto_kmflag(req)); 1550 if (ctx->cc_provider_private == NULL) 1551 return (CRYPTO_HOST_MEMORY); 1552 1553 if (ctx_template != NULL) { 1554 /* reuse context template */ 1555 bcopy(ctx_template, PROV_MD5_HMAC_CTX(ctx), 1556 sizeof (md5_hmac_ctx_t)); 1557 } else { 1558 /* no context template, compute context */ 1559 if (keylen_in_bytes > MD5_HMAC_BLOCK_SIZE) { 1560 uchar_t digested_key[MD5_DIGEST_LENGTH]; 1561 md5_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private; 1562 1563 /* 1564 * Hash the passed-in key to get a smaller key. 1565 * The inner context is used since it hasn't been 1566 * initialized yet. 1567 */ 1568 PROV_MD5_DIGEST_KEY(&hmac_ctx->hc_icontext, 1569 key->ck_data, keylen_in_bytes, digested_key); 1570 md5_mac_init_ctx(PROV_MD5_HMAC_CTX(ctx), 1571 digested_key, MD5_DIGEST_LENGTH); 1572 } else { 1573 md5_mac_init_ctx(PROV_MD5_HMAC_CTX(ctx), 1574 key->ck_data, keylen_in_bytes); 1575 } 1576 } 1577 1578 /* 1579 * Get the mechanism parameters, if applicable. 1580 */ 1581 PROV_MD5_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type; 1582 if (mechanism->cm_type == MD5_HMAC_GEN_MECH_INFO_TYPE) { 1583 if (mechanism->cm_param == NULL || 1584 mechanism->cm_param_len != sizeof (ulong_t)) 1585 ret = CRYPTO_MECHANISM_PARAM_INVALID; 1586 PROV_MD5_GET_DIGEST_LEN(mechanism, 1587 PROV_MD5_HMAC_CTX(ctx)->hc_digest_len); 1588 if (PROV_MD5_HMAC_CTX(ctx)->hc_digest_len > 1589 MD5_DIGEST_LENGTH) 1590 ret = CRYPTO_MECHANISM_PARAM_INVALID; 1591 } 1592 1593 if (ret != CRYPTO_SUCCESS) { 1594 bzero(ctx->cc_provider_private, sizeof (md5_hmac_ctx_t)); 1595 kmem_free(ctx->cc_provider_private, sizeof (md5_hmac_ctx_t)); 1596 ctx->cc_provider_private = NULL; 1597 } 1598 1599 return (ret); 1600 } 1601 1602 1603 /* ARGSUSED */ 1604 static int 1605 md5_mac_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req) 1606 { 1607 int ret = CRYPTO_SUCCESS; 1608 1609 ASSERT(ctx->cc_provider_private != NULL); 1610 1611 /* 1612 * Do an MD5 update of the inner context using the specified 1613 * data. 1614 */ 1615 switch (data->cd_format) { 1616 case CRYPTO_DATA_RAW: 1617 MD5Update(&PROV_MD5_HMAC_CTX(ctx)->hc_icontext, 1618 data->cd_raw.iov_base + data->cd_offset, 1619 data->cd_length); 1620 break; 1621 case CRYPTO_DATA_UIO: 1622 ret = md5_digest_update_uio( 1623 &PROV_MD5_HMAC_CTX(ctx)->hc_icontext, data); 1624 break; 1625 case CRYPTO_DATA_MBLK: 1626 ret = md5_digest_update_mblk( 1627 &PROV_MD5_HMAC_CTX(ctx)->hc_icontext, data); 1628 break; 1629 default: 1630 ret = CRYPTO_ARGUMENTS_BAD; 1631 } 1632 1633 return (ret); 1634 } 1635 1636 /* ARGSUSED */ 1637 static int 1638 md5_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req) 1639 { 1640 int ret = CRYPTO_SUCCESS; 1641 uchar_t digest[MD5_DIGEST_LENGTH]; 1642 uint32_t digest_len = MD5_DIGEST_LENGTH; 1643 1644 ASSERT(ctx->cc_provider_private != NULL); 1645 1646 if (PROV_MD5_HMAC_CTX(ctx)->hc_mech_type == MD5_HMAC_GEN_MECH_INFO_TYPE) 1647 digest_len = PROV_MD5_HMAC_CTX(ctx)->hc_digest_len; 1648 1649 /* 1650 * We need to just return the length needed to store the output. 1651 * We should not destroy the context for the following cases. 1652 */ 1653 if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) { 1654 mac->cd_length = digest_len; 1655 return (CRYPTO_BUFFER_TOO_SMALL); 1656 } 1657 1658 /* 1659 * Do an MD5 final on the inner context. 1660 */ 1661 MD5Final(digest, &PROV_MD5_HMAC_CTX(ctx)->hc_icontext); 1662 1663 /* 1664 * Do an MD5 update on the outer context, feeding the inner 1665 * digest as data. 1666 */ 1667 MD5Update(&PROV_MD5_HMAC_CTX(ctx)->hc_ocontext, digest, 1668 MD5_DIGEST_LENGTH); 1669 1670 /* 1671 * Do an MD5 final on the outer context, storing the computing 1672 * digest in the users buffer. 1673 */ 1674 switch (mac->cd_format) { 1675 case CRYPTO_DATA_RAW: 1676 if (digest_len != MD5_DIGEST_LENGTH) { 1677 /* 1678 * The caller requested a short digest. Digest 1679 * into a scratch buffer and return to 1680 * the user only what was requested. 1681 */ 1682 MD5Final(digest, 1683 &PROV_MD5_HMAC_CTX(ctx)->hc_ocontext); 1684 bcopy(digest, (unsigned char *)mac->cd_raw.iov_base + 1685 mac->cd_offset, digest_len); 1686 } else { 1687 MD5Final((unsigned char *)mac->cd_raw.iov_base + 1688 mac->cd_offset, 1689 &PROV_MD5_HMAC_CTX(ctx)->hc_ocontext); 1690 } 1691 break; 1692 case CRYPTO_DATA_UIO: 1693 ret = md5_digest_final_uio( 1694 &PROV_MD5_HMAC_CTX(ctx)->hc_ocontext, mac, 1695 digest_len, digest); 1696 break; 1697 case CRYPTO_DATA_MBLK: 1698 ret = md5_digest_final_mblk( 1699 &PROV_MD5_HMAC_CTX(ctx)->hc_ocontext, mac, 1700 digest_len, digest); 1701 break; 1702 default: 1703 ret = CRYPTO_ARGUMENTS_BAD; 1704 } 1705 1706 if (ret == CRYPTO_SUCCESS) { 1707 mac->cd_length = digest_len; 1708 } else { 1709 mac->cd_length = 0; 1710 } 1711 1712 bzero(ctx->cc_provider_private, sizeof (md5_hmac_ctx_t)); 1713 kmem_free(ctx->cc_provider_private, sizeof (md5_hmac_ctx_t)); 1714 ctx->cc_provider_private = NULL; 1715 1716 return (ret); 1717 } 1718 1719 #define MD5_MAC_UPDATE(data, ctx, ret) { \ 1720 switch (data->cd_format) { \ 1721 case CRYPTO_DATA_RAW: \ 1722 MD5Update(&(ctx).hc_icontext, \ 1723 data->cd_raw.iov_base + data->cd_offset, \ 1724 data->cd_length); \ 1725 break; \ 1726 case CRYPTO_DATA_UIO: \ 1727 ret = md5_digest_update_uio(&(ctx).hc_icontext, data); \ 1728 break; \ 1729 case CRYPTO_DATA_MBLK: \ 1730 ret = md5_digest_update_mblk(&(ctx).hc_icontext, \ 1731 data); \ 1732 break; \ 1733 default: \ 1734 ret = CRYPTO_ARGUMENTS_BAD; \ 1735 } \ 1736 } 1737 1738 1739 /* ARGSUSED */ 1740 static int 1741 md5_mac_atomic(crypto_provider_handle_t provider, 1742 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 1743 crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 1744 crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 1745 { 1746 int ret = CRYPTO_SUCCESS; 1747 uchar_t digest[MD5_DIGEST_LENGTH]; 1748 md5_hmac_ctx_t md5_hmac_ctx; 1749 uint32_t digest_len = MD5_DIGEST_LENGTH; 1750 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 1751 1752 if (mechanism->cm_type != MD5_HMAC_MECH_INFO_TYPE && 1753 mechanism->cm_type != MD5_HMAC_GEN_MECH_INFO_TYPE) 1754 return (CRYPTO_MECHANISM_INVALID); 1755 1756 /* Add support for key by attributes (RFE 4706552) */ 1757 if (key->ck_format != CRYPTO_KEY_RAW) 1758 return (CRYPTO_ARGUMENTS_BAD); 1759 1760 if (ctx_template != NULL) { 1761 /* reuse context template */ 1762 bcopy(ctx_template, &md5_hmac_ctx, sizeof (md5_hmac_ctx_t)); 1763 } else { 1764 /* no context template, compute context */ 1765 if (keylen_in_bytes > MD5_HMAC_BLOCK_SIZE) { 1766 /* 1767 * Hash the passed-in key to get a smaller key. 1768 * The inner context is used since it hasn't been 1769 * initialized yet. 1770 */ 1771 PROV_MD5_DIGEST_KEY(&md5_hmac_ctx.hc_icontext, 1772 key->ck_data, keylen_in_bytes, digest); 1773 md5_mac_init_ctx(&md5_hmac_ctx, digest, 1774 MD5_DIGEST_LENGTH); 1775 } else { 1776 md5_mac_init_ctx(&md5_hmac_ctx, key->ck_data, 1777 keylen_in_bytes); 1778 } 1779 } 1780 1781 /* 1782 * Get the mechanism parameters, if applicable. 1783 */ 1784 if (mechanism->cm_type == MD5_HMAC_GEN_MECH_INFO_TYPE) { 1785 if (mechanism->cm_param == NULL || 1786 mechanism->cm_param_len != sizeof (ulong_t)) { 1787 ret = CRYPTO_MECHANISM_PARAM_INVALID; 1788 goto bail; 1789 } 1790 PROV_MD5_GET_DIGEST_LEN(mechanism, digest_len); 1791 if (digest_len > MD5_DIGEST_LENGTH) { 1792 ret = CRYPTO_MECHANISM_PARAM_INVALID; 1793 goto bail; 1794 } 1795 } 1796 1797 /* do an MD5 update of the inner context using the specified data */ 1798 MD5_MAC_UPDATE(data, md5_hmac_ctx, ret); 1799 if (ret != CRYPTO_SUCCESS) 1800 /* the update failed, free context and bail */ 1801 goto bail; 1802 1803 /* do an MD5 final on the inner context */ 1804 MD5Final(digest, &md5_hmac_ctx.hc_icontext); 1805 1806 /* 1807 * Do an MD5 update on the outer context, feeding the inner 1808 * digest as data. 1809 */ 1810 MD5Update(&md5_hmac_ctx.hc_ocontext, digest, MD5_DIGEST_LENGTH); 1811 1812 /* 1813 * Do an MD5 final on the outer context, storing the computed 1814 * digest in the users buffer. 1815 */ 1816 switch (mac->cd_format) { 1817 case CRYPTO_DATA_RAW: 1818 if (digest_len != MD5_DIGEST_LENGTH) { 1819 /* 1820 * The caller requested a short digest. Digest 1821 * into a scratch buffer and return to 1822 * the user only what was requested. 1823 */ 1824 MD5Final(digest, &md5_hmac_ctx.hc_ocontext); 1825 bcopy(digest, (unsigned char *)mac->cd_raw.iov_base + 1826 mac->cd_offset, digest_len); 1827 } else { 1828 MD5Final((unsigned char *)mac->cd_raw.iov_base + 1829 mac->cd_offset, &md5_hmac_ctx.hc_ocontext); 1830 } 1831 break; 1832 case CRYPTO_DATA_UIO: 1833 ret = md5_digest_final_uio(&md5_hmac_ctx.hc_ocontext, mac, 1834 digest_len, digest); 1835 break; 1836 case CRYPTO_DATA_MBLK: 1837 ret = md5_digest_final_mblk(&md5_hmac_ctx.hc_ocontext, mac, 1838 digest_len, digest); 1839 break; 1840 default: 1841 ret = CRYPTO_ARGUMENTS_BAD; 1842 } 1843 1844 if (ret == CRYPTO_SUCCESS) { 1845 mac->cd_length = digest_len; 1846 } else { 1847 mac->cd_length = 0; 1848 } 1849 /* Extra paranoia: zeroizing the local context on the stack */ 1850 bzero(&md5_hmac_ctx, sizeof (md5_hmac_ctx_t)); 1851 1852 return (ret); 1853 bail: 1854 bzero(&md5_hmac_ctx, sizeof (md5_hmac_ctx_t)); 1855 mac->cd_length = 0; 1856 return (ret); 1857 } 1858 1859 /* ARGSUSED */ 1860 static int 1861 md5_mac_verify_atomic(crypto_provider_handle_t provider, 1862 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 1863 crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 1864 crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 1865 { 1866 int ret = CRYPTO_SUCCESS; 1867 uchar_t digest[MD5_DIGEST_LENGTH]; 1868 md5_hmac_ctx_t md5_hmac_ctx; 1869 uint32_t digest_len = MD5_DIGEST_LENGTH; 1870 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 1871 1872 if (mechanism->cm_type != MD5_HMAC_MECH_INFO_TYPE && 1873 mechanism->cm_type != MD5_HMAC_GEN_MECH_INFO_TYPE) 1874 return (CRYPTO_MECHANISM_INVALID); 1875 1876 /* Add support for key by attributes (RFE 4706552) */ 1877 if (key->ck_format != CRYPTO_KEY_RAW) 1878 return (CRYPTO_ARGUMENTS_BAD); 1879 1880 if (ctx_template != NULL) { 1881 /* reuse context template */ 1882 bcopy(ctx_template, &md5_hmac_ctx, sizeof (md5_hmac_ctx_t)); 1883 } else { 1884 /* no context template, compute context */ 1885 if (keylen_in_bytes > MD5_HMAC_BLOCK_SIZE) { 1886 /* 1887 * Hash the passed-in key to get a smaller key. 1888 * The inner context is used since it hasn't been 1889 * initialized yet. 1890 */ 1891 PROV_MD5_DIGEST_KEY(&md5_hmac_ctx.hc_icontext, 1892 key->ck_data, keylen_in_bytes, digest); 1893 md5_mac_init_ctx(&md5_hmac_ctx, digest, 1894 MD5_DIGEST_LENGTH); 1895 } else { 1896 md5_mac_init_ctx(&md5_hmac_ctx, key->ck_data, 1897 keylen_in_bytes); 1898 } 1899 } 1900 1901 /* 1902 * Get the mechanism parameters, if applicable. 1903 */ 1904 if (mechanism->cm_type == MD5_HMAC_GEN_MECH_INFO_TYPE) { 1905 if (mechanism->cm_param == NULL || 1906 mechanism->cm_param_len != sizeof (ulong_t)) { 1907 ret = CRYPTO_MECHANISM_PARAM_INVALID; 1908 goto bail; 1909 } 1910 PROV_MD5_GET_DIGEST_LEN(mechanism, digest_len); 1911 if (digest_len > MD5_DIGEST_LENGTH) { 1912 ret = CRYPTO_MECHANISM_PARAM_INVALID; 1913 goto bail; 1914 } 1915 } 1916 1917 if (mac->cd_length != digest_len) { 1918 ret = CRYPTO_INVALID_MAC; 1919 goto bail; 1920 } 1921 1922 /* do an MD5 update of the inner context using the specified data */ 1923 MD5_MAC_UPDATE(data, md5_hmac_ctx, ret); 1924 if (ret != CRYPTO_SUCCESS) 1925 /* the update failed, free context and bail */ 1926 goto bail; 1927 1928 /* do an MD5 final on the inner context */ 1929 MD5Final(digest, &md5_hmac_ctx.hc_icontext); 1930 1931 /* 1932 * Do an MD5 update on the outer context, feeding the inner 1933 * digest as data. 1934 */ 1935 MD5Update(&md5_hmac_ctx.hc_ocontext, digest, MD5_DIGEST_LENGTH); 1936 1937 /* 1938 * Do an MD5 final on the outer context, storing the computed 1939 * digest in the local digest buffer. 1940 */ 1941 MD5Final(digest, &md5_hmac_ctx.hc_ocontext); 1942 1943 /* 1944 * Compare the computed digest against the expected digest passed 1945 * as argument. 1946 */ 1947 switch (mac->cd_format) { 1948 1949 case CRYPTO_DATA_RAW: 1950 if (bcmp(digest, (unsigned char *)mac->cd_raw.iov_base + 1951 mac->cd_offset, digest_len) != 0) 1952 ret = CRYPTO_INVALID_MAC; 1953 break; 1954 1955 case CRYPTO_DATA_UIO: { 1956 off_t offset = mac->cd_offset; 1957 uint_t vec_idx; 1958 off_t scratch_offset = 0; 1959 size_t length = digest_len; 1960 size_t cur_len; 1961 1962 /* we support only kernel buffer */ 1963 if (mac->cd_uio->uio_segflg != UIO_SYSSPACE) 1964 return (CRYPTO_ARGUMENTS_BAD); 1965 1966 /* jump to the first iovec containing the expected digest */ 1967 for (vec_idx = 0; 1968 offset >= mac->cd_uio->uio_iov[vec_idx].iov_len && 1969 vec_idx < mac->cd_uio->uio_iovcnt; 1970 offset -= mac->cd_uio->uio_iov[vec_idx++].iov_len); 1971 if (vec_idx == mac->cd_uio->uio_iovcnt) { 1972 /* 1973 * The caller specified an offset that is 1974 * larger than the total size of the buffers 1975 * it provided. 1976 */ 1977 ret = CRYPTO_DATA_LEN_RANGE; 1978 break; 1979 } 1980 1981 /* do the comparison of computed digest vs specified one */ 1982 while (vec_idx < mac->cd_uio->uio_iovcnt && length > 0) { 1983 cur_len = MIN(mac->cd_uio->uio_iov[vec_idx].iov_len - 1984 offset, length); 1985 1986 if (bcmp(digest + scratch_offset, 1987 mac->cd_uio->uio_iov[vec_idx].iov_base + offset, 1988 cur_len) != 0) { 1989 ret = CRYPTO_INVALID_MAC; 1990 break; 1991 } 1992 1993 length -= cur_len; 1994 vec_idx++; 1995 scratch_offset += cur_len; 1996 offset = 0; 1997 } 1998 break; 1999 } 2000 2001 case CRYPTO_DATA_MBLK: { 2002 off_t offset = mac->cd_offset; 2003 mblk_t *mp; 2004 off_t scratch_offset = 0; 2005 size_t length = digest_len; 2006 size_t cur_len; 2007 2008 /* jump to the first mblk_t containing the expected digest */ 2009 for (mp = mac->cd_mp; mp != NULL && offset >= MBLKL(mp); 2010 offset -= MBLKL(mp), mp = mp->b_cont); 2011 if (mp == NULL) { 2012 /* 2013 * The caller specified an offset that is larger than 2014 * the total size of the buffers it provided. 2015 */ 2016 ret = CRYPTO_DATA_LEN_RANGE; 2017 break; 2018 } 2019 2020 while (mp != NULL && length > 0) { 2021 cur_len = MIN(MBLKL(mp) - offset, length); 2022 if (bcmp(digest + scratch_offset, 2023 mp->b_rptr + offset, cur_len) != 0) { 2024 ret = CRYPTO_INVALID_MAC; 2025 break; 2026 } 2027 2028 length -= cur_len; 2029 mp = mp->b_cont; 2030 scratch_offset += cur_len; 2031 offset = 0; 2032 } 2033 break; 2034 } 2035 2036 default: 2037 ret = CRYPTO_ARGUMENTS_BAD; 2038 } 2039 2040 bzero(&md5_hmac_ctx, sizeof (md5_hmac_ctx_t)); 2041 return (ret); 2042 bail: 2043 bzero(&md5_hmac_ctx, sizeof (md5_hmac_ctx_t)); 2044 mac->cd_length = 0; 2045 return (ret); 2046 } 2047 2048 /* 2049 * KCF software provider context management entry points. 2050 */ 2051 2052 /* ARGSUSED */ 2053 static int 2054 md5_create_ctx_template(crypto_provider_handle_t provider, 2055 crypto_mechanism_t *mechanism, crypto_key_t *key, 2056 crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size, 2057 crypto_req_handle_t req) 2058 { 2059 md5_hmac_ctx_t *md5_hmac_ctx_tmpl; 2060 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 2061 2062 if ((mechanism->cm_type != MD5_HMAC_MECH_INFO_TYPE) && 2063 (mechanism->cm_type != MD5_HMAC_GEN_MECH_INFO_TYPE)) 2064 return (CRYPTO_MECHANISM_INVALID); 2065 2066 /* Add support for key by attributes (RFE 4706552) */ 2067 if (key->ck_format != CRYPTO_KEY_RAW) 2068 return (CRYPTO_ARGUMENTS_BAD); 2069 2070 /* 2071 * Allocate and initialize MD5 context. 2072 */ 2073 md5_hmac_ctx_tmpl = kmem_alloc(sizeof (md5_hmac_ctx_t), 2074 crypto_kmflag(req)); 2075 if (md5_hmac_ctx_tmpl == NULL) 2076 return (CRYPTO_HOST_MEMORY); 2077 2078 if (keylen_in_bytes > MD5_HMAC_BLOCK_SIZE) { 2079 uchar_t digested_key[MD5_DIGEST_LENGTH]; 2080 2081 /* 2082 * Hash the passed-in key to get a smaller key. 2083 * The inner context is used since it hasn't been 2084 * initialized yet. 2085 */ 2086 PROV_MD5_DIGEST_KEY(&md5_hmac_ctx_tmpl->hc_icontext, 2087 key->ck_data, keylen_in_bytes, digested_key); 2088 md5_mac_init_ctx(md5_hmac_ctx_tmpl, digested_key, 2089 MD5_DIGEST_LENGTH); 2090 } else { 2091 md5_mac_init_ctx(md5_hmac_ctx_tmpl, key->ck_data, 2092 keylen_in_bytes); 2093 } 2094 2095 md5_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type; 2096 *ctx_template = (crypto_spi_ctx_template_t)md5_hmac_ctx_tmpl; 2097 *ctx_template_size = sizeof (md5_hmac_ctx_t); 2098 2099 return (CRYPTO_SUCCESS); 2100 } 2101 2102 static int 2103 md5_free_context(crypto_ctx_t *ctx) 2104 { 2105 uint_t ctx_len; 2106 md5_mech_type_t mech_type; 2107 2108 if (ctx->cc_provider_private == NULL) 2109 return (CRYPTO_SUCCESS); 2110 2111 /* 2112 * We have to free either MD5 or MD5-HMAC contexts, which 2113 * have different lengths. 2114 */ 2115 2116 mech_type = PROV_MD5_CTX(ctx)->mc_mech_type; 2117 if (mech_type == MD5_MECH_INFO_TYPE) 2118 ctx_len = sizeof (md5_ctx_t); 2119 else { 2120 ASSERT(mech_type == MD5_HMAC_MECH_INFO_TYPE || 2121 mech_type == MD5_HMAC_GEN_MECH_INFO_TYPE); 2122 ctx_len = sizeof (md5_hmac_ctx_t); 2123 } 2124 2125 bzero(ctx->cc_provider_private, ctx_len); 2126 kmem_free(ctx->cc_provider_private, ctx_len); 2127 ctx->cc_provider_private = NULL; 2128 2129 return (CRYPTO_SUCCESS); 2130 } 2131 2132 #endif /* _KERNEL && !_BOOT */ 2133