md5.c (673007c6) | md5.c (734b6a94) |
---|---|
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. | 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 --- 23 unchanged lines hidden (view full) --- 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 | 10 */ 11 12#pragma ident "%Z%%M% %I% %E% SMI" 13 14/* 15 * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm 16 */ 17 --- 23 unchanged lines hidden (view full) --- 41#include <sys/types.h> 42#include <sys/md5.h> 43#include <sys/md5_consts.h> /* MD5_CONST() optimization */ 44#include "md5_byteswap.h" 45#if !defined(_KERNEL) || defined(_BOOT) 46#include <strings.h> 47#endif /* !_KERNEL || _BOOT */ 48 |
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 | 49#ifdef _KERNEL |
64#include <sys/systm.h> | 50#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> | 51#endif /* _KERNEL */ |
73 | 52 |
74extern struct mod_ops mod_miscops; 75extern struct mod_ops mod_cryptoops; 76 77/* 78 * Module linkage information for the kernel. 79 */ 80 81static struct modlmisc modlmisc = { 82 &mod_miscops, 83 "MD5 Message-Digest Algorithm" 84}; 85 86static struct modlcrypto modlcrypto = { 87 &mod_cryptoops, 88 "MD5 Kernel SW Provider 1.23" 89}; 90 91static 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 102typedef 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 */ 117typedef 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 */ 125typedef 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 */ 160static 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 177static void md5_provider_status(crypto_provider_handle_t, uint_t *); 178 179static crypto_control_ops_t md5_control_ops = { 180 md5_provider_status 181}; 182 183static int md5_digest_init(crypto_ctx_t *, crypto_mechanism_t *, 184 crypto_req_handle_t); 185static int md5_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 186 crypto_req_handle_t); 187static int md5_digest_update(crypto_ctx_t *, crypto_data_t *, 188 crypto_req_handle_t); 189static int md5_digest_final(crypto_ctx_t *, crypto_data_t *, 190 crypto_req_handle_t); 191static 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 195static 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 204static int md5_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, 205 crypto_spi_ctx_template_t, crypto_req_handle_t); 206static int md5_mac_update(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); 207static int md5_mac_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); 208static 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); 211static 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 215static 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 224static 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); 227static int md5_free_context(crypto_ctx_t *); 228 229static crypto_ctx_ops_t md5_ctx_ops = { 230 md5_create_ctx_template, 231 md5_free_context 232}; 233 234static 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 251static 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 262static crypto_kcf_provider_handle_t md5_prov_handle = NULL; 263 264int 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 285int 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 306int 307_info(struct modinfo *modinfop) 308{ 309 return (mod_info(&modlinkage, modinfop)); 310} 311#endif /* _KERNEL && !_BOOT */ 312 313static void Encode(uint8_t *, uint32_t *, size_t); | 53static void Encode(uint8_t *, const uint32_t *, size_t); |
314static void MD5Transform(uint32_t, uint32_t, uint32_t, uint32_t, MD5_CTX *, 315 const uint8_t [64]); 316 317static uint8_t PADDING[64] = { 0x80, /* all zeros */ }; 318 319/* 320 * F, G, H and I are the basic MD5 functions. 321 */ --- 335 unchanged lines hidden (view full) --- 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 | 54static void MD5Transform(uint32_t, uint32_t, uint32_t, uint32_t, MD5_CTX *, 55 const uint8_t [64]); 56 57static uint8_t PADDING[64] = { 0x80, /* all zeros */ }; 58 59/* 60 * F, G, H and I are the basic MD5 functions. 61 */ --- 335 unchanged lines hidden (view full) --- 397 * win, although the amount it wins by seems to vary quite a bit. 398 */ 399 400 register uint32_t x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7; 401 register uint32_t x_8, x_9, x_10, x_11, x_12, x_13, x_14, x_15; 402#ifdef sun4v 403 unsigned long long *md5_consts64; 404 |
405 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
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 --- 60 unchanged lines hidden (view full) --- 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 | 406 md5_consts64 = (unsigned long long *) md5_consts; 407#endif /* sun4v */ 408 409 /* 410 * general optimization: 411 * 412 * the compiler (at least SC4.2/5.x) generates better code if 413 * variable use is localized. in this case, swapping the integers in --- 60 unchanged lines hidden (view full) --- 474 x_1 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 1); 475 x_0 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 0); 476#endif /* sun4v */ 477 } else 478#endif 479 { 480 481#ifdef sun4v |
482 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
741 x_15 = LOAD_LITTLE_32_f(block); | 483 x_15 = LOAD_LITTLE_32_f(block); |
484 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
742 x_14 = LOAD_LITTLE_32_e(block); | 485 x_14 = LOAD_LITTLE_32_e(block); |
486 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
743 x_13 = LOAD_LITTLE_32_d(block); | 487 x_13 = LOAD_LITTLE_32_d(block); |
488 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
744 x_12 = LOAD_LITTLE_32_c(block); | 489 x_12 = LOAD_LITTLE_32_c(block); |
490 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
745 x_11 = LOAD_LITTLE_32_b(block); | 491 x_11 = LOAD_LITTLE_32_b(block); |
492 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
746 x_10 = LOAD_LITTLE_32_a(block); | 493 x_10 = LOAD_LITTLE_32_a(block); |
494 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
747 x_9 = LOAD_LITTLE_32_9(block); | 495 x_9 = LOAD_LITTLE_32_9(block); |
496 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
748 x_8 = LOAD_LITTLE_32_8(block); | 497 x_8 = LOAD_LITTLE_32_8(block); |
498 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
749 x_7 = LOAD_LITTLE_32_7(block); | 499 x_7 = LOAD_LITTLE_32_7(block); |
500 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
750 x_6 = LOAD_LITTLE_32_6(block); | 501 x_6 = LOAD_LITTLE_32_6(block); |
502 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
751 x_5 = LOAD_LITTLE_32_5(block); | 503 x_5 = LOAD_LITTLE_32_5(block); |
504 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
752 x_4 = LOAD_LITTLE_32_4(block); | 505 x_4 = LOAD_LITTLE_32_4(block); |
506 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
753 x_3 = LOAD_LITTLE_32_3(block); | 507 x_3 = LOAD_LITTLE_32_3(block); |
508 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
754 x_2 = LOAD_LITTLE_32_2(block); | 509 x_2 = LOAD_LITTLE_32_2(block); |
510 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
755 x_1 = LOAD_LITTLE_32_1(block); | 511 x_1 = LOAD_LITTLE_32_1(block); |
512 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
756 x_0 = LOAD_LITTLE_32_0(block); 757#else | 513 x_0 = LOAD_LITTLE_32_0(block); 514#else |
515 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
758 x_15 = LOAD_LITTLE_32(block + 60); | 516 x_15 = LOAD_LITTLE_32(block + 60); |
517 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
759 x_14 = LOAD_LITTLE_32(block + 56); | 518 x_14 = LOAD_LITTLE_32(block + 56); |
519 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
760 x_13 = LOAD_LITTLE_32(block + 52); | 520 x_13 = LOAD_LITTLE_32(block + 52); |
521 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
761 x_12 = LOAD_LITTLE_32(block + 48); | 522 x_12 = LOAD_LITTLE_32(block + 48); |
523 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
762 x_11 = LOAD_LITTLE_32(block + 44); | 524 x_11 = LOAD_LITTLE_32(block + 44); |
525 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
763 x_10 = LOAD_LITTLE_32(block + 40); | 526 x_10 = LOAD_LITTLE_32(block + 40); |
527 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
764 x_9 = LOAD_LITTLE_32(block + 36); | 528 x_9 = LOAD_LITTLE_32(block + 36); |
529 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
765 x_8 = LOAD_LITTLE_32(block + 32); | 530 x_8 = LOAD_LITTLE_32(block + 32); |
531 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
766 x_7 = LOAD_LITTLE_32(block + 28); | 532 x_7 = LOAD_LITTLE_32(block + 28); |
533 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
767 x_6 = LOAD_LITTLE_32(block + 24); | 534 x_6 = LOAD_LITTLE_32(block + 24); |
535 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
768 x_5 = LOAD_LITTLE_32(block + 20); | 536 x_5 = LOAD_LITTLE_32(block + 20); |
537 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
769 x_4 = LOAD_LITTLE_32(block + 16); | 538 x_4 = LOAD_LITTLE_32(block + 16); |
539 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
770 x_3 = LOAD_LITTLE_32(block + 12); | 540 x_3 = LOAD_LITTLE_32(block + 12); |
541 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
771 x_2 = LOAD_LITTLE_32(block + 8); | 542 x_2 = LOAD_LITTLE_32(block + 8); |
543 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
772 x_1 = LOAD_LITTLE_32(block + 4); | 544 x_1 = LOAD_LITTLE_32(block + 4); |
545 /* LINTED E_BAD_PTR_CAST_ALIGN */ |
|
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 */ --- 75 unchanged lines hidden (view full) --- 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/* | 546 x_0 = LOAD_LITTLE_32(block + 0); 547#endif /* sun4v */ 548 } 549 550 /* round 1 */ 551 FF(a, b, c, d, x_0, MD5_SHIFT_11, MD5_CONST_e(0)); /* 1 */ 552 FF(d, a, b, c, x_1, MD5_SHIFT_12, MD5_CONST_o(1)); /* 2 */ 553 FF(c, d, a, b, x_2, MD5_SHIFT_13, MD5_CONST_e(2)); /* 3 */ --- 75 unchanged lines hidden (view full) --- 629 * this out if everything is kept in registers 630 */ 631 632 x_0 = x_1 = x_2 = x_3 = x_4 = x_5 = x_6 = x_7 = x_8 = 0; 633 x_9 = x_10 = x_11 = x_12 = x_13 = x_14 = x_15 = 0; 634} 635 636/* |
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 888static void | 637 * Encode() 638 * 639 * purpose: to convert a list of numbers from big endian to little endian 640 * input: uint8_t * : place to store the converted little endian numbers 641 * uint32_t * : place to get numbers to convert from 642 * size_t : the length of the input in bytes 643 * output: void 644 */ 645 646static void |
889Encode(uint8_t *restrict output, uint32_t *restrict input, size_t input_len) | 647Encode(uint8_t *_RESTRICT_KYWD output, const uint32_t *_RESTRICT_KYWD input, 648 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 | 649{ 650 size_t i, j; 651 652 for (i = 0, j = 0; j < input_len; i++, j += sizeof (uint32_t)) { 653 654#ifdef _LITTLE_ENDIAN 655 656#ifdef _MD5_CHECK_ALIGNMENT 657 if ((uintptr_t)output & 0x3) /* Not 4-byte aligned */ 658 bcopy(input + i, output + j, 4); 659 else *(uint32_t *)(output + j) = input[i]; 660#else |
661 /*LINTED E_BAD_PTR_CAST_ALIGN*/ |
|
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} | 662 *(uint32_t *)(output + j) = input[i]; 663#endif /* _MD5_CHECK_ALIGNMENT */ 664 665#else /* big endian -- will work on little endian, but slowly */ 666 667 output[j] = input[i] & 0xff; 668 output[j + 1] = (input[i] >> 8) & 0xff; 669 output[j + 2] = (input[i] >> 16) & 0xff; 670 output[j + 3] = (input[i] >> 24) & 0xff; 671#endif 672 } 673} |
914 915#if defined(_KERNEL) && !defined(_BOOT) 916 917/* 918 * KCF software provider control entry points. 919 */ 920/* ARGSUSED */ 921static void 922md5_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 931static int 932md5_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 */ 955static int 956md5_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 */ 1016static int 1017md5_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 */ 1108static int 1109md5_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 */ 1159static int 1160md5_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 */ 1235static int 1236md5_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 */ 1317static int 1318md5_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 */ 1350static int 1351md5_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 */ 1403static int 1404md5_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 */ 1501static void 1502md5_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 */ 1532static int 1533md5_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 */ 1604static int 1605md5_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 */ 1637static int 1638md5_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 */ 1740static int 1741md5_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); 1853bail: 1854 bzero(&md5_hmac_ctx, sizeof (md5_hmac_ctx_t)); 1855 mac->cd_length = 0; 1856 return (ret); 1857} 1858 1859/* ARGSUSED */ 1860static int 1861md5_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); 2042bail: 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 */ 2053static int 2054md5_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 2102static int 2103md5_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 */ | |