17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 77c478bd9Sstevel@tonic-gate 87c478bd9Sstevel@tonic-gate /* 97c478bd9Sstevel@tonic-gate * The basic framework for this code came from the reference 107c478bd9Sstevel@tonic-gate * implementation for MD5. That implementation is Copyright (C) 117c478bd9Sstevel@tonic-gate * 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * License to copy and use this software is granted provided that it 147c478bd9Sstevel@tonic-gate * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 157c478bd9Sstevel@tonic-gate * Algorithm" in all material mentioning or referencing this software 167c478bd9Sstevel@tonic-gate * or this function. 177c478bd9Sstevel@tonic-gate * 187c478bd9Sstevel@tonic-gate * License is also granted to make and use derivative works provided 197c478bd9Sstevel@tonic-gate * that such works are identified as "derived from the RSA Data 207c478bd9Sstevel@tonic-gate * Security, Inc. MD5 Message-Digest Algorithm" in all material 217c478bd9Sstevel@tonic-gate * mentioning or referencing the derived work. 227c478bd9Sstevel@tonic-gate * 237c478bd9Sstevel@tonic-gate * RSA Data Security, Inc. makes no representations concerning either 247c478bd9Sstevel@tonic-gate * the merchantability of this software or the suitability of this 257c478bd9Sstevel@tonic-gate * software for any particular purpose. It is provided "as is" 267c478bd9Sstevel@tonic-gate * without express or implied warranty of any kind. 277c478bd9Sstevel@tonic-gate * 287c478bd9Sstevel@tonic-gate * These notices must be retained in any copies of any part of this 297c478bd9Sstevel@tonic-gate * documentation and/or software. 307c478bd9Sstevel@tonic-gate * 317c478bd9Sstevel@tonic-gate * NOTE: Cleaned-up and optimized, version of SHA1, based on the FIPS 180-1 327c478bd9Sstevel@tonic-gate * standard, available at http://www.itl.nist.gov/div897/pubs/fip180-1.htm 337c478bd9Sstevel@tonic-gate * Not as fast as one would like -- further optimizations are encouraged 347c478bd9Sstevel@tonic-gate * and appreciated. 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #include <sys/types.h> 387c478bd9Sstevel@tonic-gate #include <sys/param.h> 397c478bd9Sstevel@tonic-gate #include <sys/systm.h> 407c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 417c478bd9Sstevel@tonic-gate #include <sys/sha1.h> 427c478bd9Sstevel@tonic-gate #include <sys/sha1_consts.h> 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #ifdef _KERNEL 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 477c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 487c478bd9Sstevel@tonic-gate #include <sys/note.h> 497c478bd9Sstevel@tonic-gate #include <sys/crypto/common.h> 507c478bd9Sstevel@tonic-gate #include <sys/crypto/spi.h> 517c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* 547c478bd9Sstevel@tonic-gate * The sha1 module is created with two modlinkages: 557c478bd9Sstevel@tonic-gate * - a modlmisc that allows consumers to directly call the entry points 567c478bd9Sstevel@tonic-gate * SHA1Init, SHA1Update, and SHA1Final. 577c478bd9Sstevel@tonic-gate * - a modlcrypto that allows the module to register with the Kernel 587c478bd9Sstevel@tonic-gate * Cryptographic Framework (KCF) as a software provider for the SHA1 597c478bd9Sstevel@tonic-gate * mechanisms. 607c478bd9Sstevel@tonic-gate */ 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 637c478bd9Sstevel@tonic-gate #ifndef _KERNEL 647c478bd9Sstevel@tonic-gate #include <strings.h> 657c478bd9Sstevel@tonic-gate #include <stdlib.h> 667c478bd9Sstevel@tonic-gate #include <errno.h> 677c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 687c478bd9Sstevel@tonic-gate #endif /* !_KERNEL */ 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate static void Encode(uint8_t *, uint32_t *, size_t); 717c478bd9Sstevel@tonic-gate static void SHA1Transform(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, 727c478bd9Sstevel@tonic-gate SHA1_CTX *, const uint8_t *); 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate static uint8_t PADDING[64] = { 0x80, /* all zeros */ }; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* 777c478bd9Sstevel@tonic-gate * F, G, and H are the basic SHA1 functions. 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate #define F(b, c, d) (((b) & (c)) | ((~b) & (d))) 807c478bd9Sstevel@tonic-gate #define G(b, c, d) ((b) ^ (c) ^ (d)) 817c478bd9Sstevel@tonic-gate #define H(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* 847c478bd9Sstevel@tonic-gate * ROTATE_LEFT rotates x left n bits. 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate #define ROTATE_LEFT(x, n) \ 877c478bd9Sstevel@tonic-gate (((x) << (n)) | ((x) >> ((sizeof (x) * NBBY)-(n)))) 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate #ifdef _KERNEL 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 927c478bd9Sstevel@tonic-gate &mod_miscops, 937c478bd9Sstevel@tonic-gate "SHA1 Message-Digest Algorithm" 947c478bd9Sstevel@tonic-gate }; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate static struct modlcrypto modlcrypto = { 977c478bd9Sstevel@tonic-gate &mod_cryptoops, 987c478bd9Sstevel@tonic-gate "SHA1 Kernel SW Provider %I%" 997c478bd9Sstevel@tonic-gate }; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 1027c478bd9Sstevel@tonic-gate MODREV_1, &modlmisc, &modlcrypto, NULL 1037c478bd9Sstevel@tonic-gate }; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * CSPI information (entry points, provider info, etc.) 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate typedef enum sha1_mech_type { 1107c478bd9Sstevel@tonic-gate SHA1_MECH_INFO_TYPE, /* SUN_CKM_SHA1 */ 1117c478bd9Sstevel@tonic-gate SHA1_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA1_HMAC */ 1127c478bd9Sstevel@tonic-gate SHA1_HMAC_GEN_MECH_INFO_TYPE /* SUN_CKM_SHA1_HMAC_GENERAL */ 1137c478bd9Sstevel@tonic-gate } sha1_mech_type_t; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate #define SHA1_DIGEST_LENGTH 20 /* SHA1 digest length in bytes */ 1167c478bd9Sstevel@tonic-gate #define SHA1_HMAC_BLOCK_SIZE 64 /* SHA1-HMAC block size */ 1177c478bd9Sstevel@tonic-gate #define SHA1_HMAC_MIN_KEY_LEN 8 /* SHA1-HMAC min key length in bits */ 1187c478bd9Sstevel@tonic-gate #define SHA1_HMAC_MAX_KEY_LEN INT_MAX /* SHA1-HMAC max key length in bits */ 1197c478bd9Sstevel@tonic-gate #define SHA1_HMAC_INTS_PER_BLOCK (SHA1_HMAC_BLOCK_SIZE/sizeof (uint32_t)) 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* 1227c478bd9Sstevel@tonic-gate * Context for SHA1 mechanism. 1237c478bd9Sstevel@tonic-gate */ 1247c478bd9Sstevel@tonic-gate typedef struct sha1_ctx { 1257c478bd9Sstevel@tonic-gate sha1_mech_type_t sc_mech_type; /* type of context */ 1267c478bd9Sstevel@tonic-gate SHA1_CTX sc_sha1_ctx; /* SHA1 context */ 1277c478bd9Sstevel@tonic-gate } sha1_ctx_t; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate /* 1307c478bd9Sstevel@tonic-gate * Context for SHA1-HMAC and SHA1-HMAC-GENERAL mechanisms. 1317c478bd9Sstevel@tonic-gate */ 1327c478bd9Sstevel@tonic-gate typedef struct sha1_hmac_ctx { 1337c478bd9Sstevel@tonic-gate sha1_mech_type_t hc_mech_type; /* type of context */ 1347c478bd9Sstevel@tonic-gate uint32_t hc_digest_len; /* digest len in bytes */ 1357c478bd9Sstevel@tonic-gate SHA1_CTX hc_icontext; /* inner SHA1 context */ 1367c478bd9Sstevel@tonic-gate SHA1_CTX hc_ocontext; /* outer SHA1 context */ 1377c478bd9Sstevel@tonic-gate } sha1_hmac_ctx_t; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* 1407c478bd9Sstevel@tonic-gate * Macros to access the SHA1 or SHA1-HMAC contexts from a context passed 1417c478bd9Sstevel@tonic-gate * by KCF to one of the entry points. 1427c478bd9Sstevel@tonic-gate */ 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate #define PROV_SHA1_CTX(ctx) ((sha1_ctx_t *)(ctx)->cc_provider_private) 1457c478bd9Sstevel@tonic-gate #define PROV_SHA1_HMAC_CTX(ctx) ((sha1_hmac_ctx_t *)(ctx)->cc_provider_private) 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate /* to extract the digest length passed as mechanism parameter */ 1487c478bd9Sstevel@tonic-gate #define PROV_SHA1_GET_DIGEST_LEN(m, len) { \ 1497c478bd9Sstevel@tonic-gate if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t))) \ 1507c478bd9Sstevel@tonic-gate (len) = (uint32_t)*((ulong_t *)mechanism->cm_param); \ 1517c478bd9Sstevel@tonic-gate else { \ 1527c478bd9Sstevel@tonic-gate ulong_t tmp_ulong; \ 1537c478bd9Sstevel@tonic-gate bcopy((m)->cm_param, &tmp_ulong, sizeof (ulong_t)); \ 1547c478bd9Sstevel@tonic-gate (len) = (uint32_t)tmp_ulong; \ 1557c478bd9Sstevel@tonic-gate } \ 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate #define PROV_SHA1_DIGEST_KEY(ctx, key, len, digest) { \ 1597c478bd9Sstevel@tonic-gate SHA1Init(ctx); \ 1607c478bd9Sstevel@tonic-gate SHA1Update(ctx, key, len); \ 1617c478bd9Sstevel@tonic-gate SHA1Final(digest, ctx); \ 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * Mechanism info structure passed to KCF during registration. 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate static crypto_mech_info_t sha1_mech_info_tab[] = { 1687c478bd9Sstevel@tonic-gate /* SHA1 */ 1697c478bd9Sstevel@tonic-gate {SUN_CKM_SHA1, SHA1_MECH_INFO_TYPE, 1707c478bd9Sstevel@tonic-gate CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 1717c478bd9Sstevel@tonic-gate 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 1727c478bd9Sstevel@tonic-gate /* SHA1-HMAC */ 1737c478bd9Sstevel@tonic-gate {SUN_CKM_SHA1_HMAC, SHA1_HMAC_MECH_INFO_TYPE, 1747c478bd9Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 1757c478bd9Sstevel@tonic-gate SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN, 1767c478bd9Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 1777c478bd9Sstevel@tonic-gate /* SHA1-HMAC GENERAL */ 1787c478bd9Sstevel@tonic-gate {SUN_CKM_SHA1_HMAC_GENERAL, SHA1_HMAC_GEN_MECH_INFO_TYPE, 1797c478bd9Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 1807c478bd9Sstevel@tonic-gate SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN, 1817c478bd9Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS} 1827c478bd9Sstevel@tonic-gate }; 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate static void sha1_provider_status(crypto_provider_handle_t, uint_t *); 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate static crypto_control_ops_t sha1_control_ops = { 1877c478bd9Sstevel@tonic-gate sha1_provider_status 1887c478bd9Sstevel@tonic-gate }; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate static int sha1_digest_init(crypto_ctx_t *, crypto_mechanism_t *, 1917c478bd9Sstevel@tonic-gate crypto_req_handle_t); 1927c478bd9Sstevel@tonic-gate static int sha1_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 1937c478bd9Sstevel@tonic-gate crypto_req_handle_t); 1947c478bd9Sstevel@tonic-gate static int sha1_digest_update(crypto_ctx_t *, crypto_data_t *, 1957c478bd9Sstevel@tonic-gate crypto_req_handle_t); 1967c478bd9Sstevel@tonic-gate static int sha1_digest_final(crypto_ctx_t *, crypto_data_t *, 1977c478bd9Sstevel@tonic-gate crypto_req_handle_t); 1987c478bd9Sstevel@tonic-gate static int sha1_digest_atomic(crypto_provider_handle_t, crypto_session_id_t, 1997c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_data_t *, crypto_data_t *, 2007c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate static crypto_digest_ops_t sha1_digest_ops = { 2037c478bd9Sstevel@tonic-gate sha1_digest_init, 2047c478bd9Sstevel@tonic-gate sha1_digest, 2057c478bd9Sstevel@tonic-gate sha1_digest_update, 2067c478bd9Sstevel@tonic-gate NULL, 2077c478bd9Sstevel@tonic-gate sha1_digest_final, 2087c478bd9Sstevel@tonic-gate sha1_digest_atomic 2097c478bd9Sstevel@tonic-gate }; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate static int sha1_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, 2127c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 2137c478bd9Sstevel@tonic-gate static int sha1_mac_update(crypto_ctx_t *, crypto_data_t *, 2147c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2157c478bd9Sstevel@tonic-gate static int sha1_mac_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); 2167c478bd9Sstevel@tonic-gate static int sha1_mac_atomic(crypto_provider_handle_t, crypto_session_id_t, 2177c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 2187c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 2197c478bd9Sstevel@tonic-gate static int sha1_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t, 2207c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 2217c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate static crypto_mac_ops_t sha1_mac_ops = { 2247c478bd9Sstevel@tonic-gate sha1_mac_init, 2257c478bd9Sstevel@tonic-gate NULL, 2267c478bd9Sstevel@tonic-gate sha1_mac_update, 2277c478bd9Sstevel@tonic-gate sha1_mac_final, 2287c478bd9Sstevel@tonic-gate sha1_mac_atomic, 2297c478bd9Sstevel@tonic-gate sha1_mac_verify_atomic 2307c478bd9Sstevel@tonic-gate }; 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate static int sha1_create_ctx_template(crypto_provider_handle_t, 2337c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *, 2347c478bd9Sstevel@tonic-gate size_t *, crypto_req_handle_t); 2357c478bd9Sstevel@tonic-gate static int sha1_free_context(crypto_ctx_t *); 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate static crypto_ctx_ops_t sha1_ctx_ops = { 2387c478bd9Sstevel@tonic-gate sha1_create_ctx_template, 2397c478bd9Sstevel@tonic-gate sha1_free_context 2407c478bd9Sstevel@tonic-gate }; 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate static crypto_ops_t sha1_crypto_ops = { 2437c478bd9Sstevel@tonic-gate &sha1_control_ops, 2447c478bd9Sstevel@tonic-gate &sha1_digest_ops, 2457c478bd9Sstevel@tonic-gate NULL, 2467c478bd9Sstevel@tonic-gate &sha1_mac_ops, 2477c478bd9Sstevel@tonic-gate NULL, 2487c478bd9Sstevel@tonic-gate NULL, 2497c478bd9Sstevel@tonic-gate NULL, 2507c478bd9Sstevel@tonic-gate NULL, 2517c478bd9Sstevel@tonic-gate NULL, 2527c478bd9Sstevel@tonic-gate NULL, 2537c478bd9Sstevel@tonic-gate NULL, 2547c478bd9Sstevel@tonic-gate NULL, 2557c478bd9Sstevel@tonic-gate NULL, 2567c478bd9Sstevel@tonic-gate &sha1_ctx_ops 2577c478bd9Sstevel@tonic-gate }; 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate static crypto_provider_info_t sha1_prov_info = { 2607c478bd9Sstevel@tonic-gate CRYPTO_SPI_VERSION_1, 2617c478bd9Sstevel@tonic-gate "SHA1 Software Provider", 2627c478bd9Sstevel@tonic-gate CRYPTO_SW_PROVIDER, 2637c478bd9Sstevel@tonic-gate {&modlinkage}, 2647c478bd9Sstevel@tonic-gate NULL, 2657c478bd9Sstevel@tonic-gate &sha1_crypto_ops, 2667c478bd9Sstevel@tonic-gate sizeof (sha1_mech_info_tab)/sizeof (crypto_mech_info_t), 2677c478bd9Sstevel@tonic-gate sha1_mech_info_tab 2687c478bd9Sstevel@tonic-gate }; 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate static crypto_kcf_provider_handle_t sha1_prov_handle = NULL; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate int 2737c478bd9Sstevel@tonic-gate _init() 2747c478bd9Sstevel@tonic-gate { 2757c478bd9Sstevel@tonic-gate int ret; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate if ((ret = mod_install(&modlinkage)) != 0) 2787c478bd9Sstevel@tonic-gate return (ret); 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /* 2817c478bd9Sstevel@tonic-gate * Register with KCF. If the registration fails, log an 2827c478bd9Sstevel@tonic-gate * error but do not uninstall the module, since the functionality 2837c478bd9Sstevel@tonic-gate * provided by misc/sha1 should still be available. 2847c478bd9Sstevel@tonic-gate */ 2857c478bd9Sstevel@tonic-gate if ((ret = crypto_register_provider(&sha1_prov_info, 2867c478bd9Sstevel@tonic-gate &sha1_prov_handle)) != CRYPTO_SUCCESS) 2877c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "sha1 _init: " 2887c478bd9Sstevel@tonic-gate "crypto_register_provider() failed (0x%x)", ret); 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate return (0); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate int 2947c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 2957c478bd9Sstevel@tonic-gate { 2967c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * SHA1Init() 3037c478bd9Sstevel@tonic-gate * 3047c478bd9Sstevel@tonic-gate * purpose: initializes the sha1 context and begins and sha1 digest operation 3057c478bd9Sstevel@tonic-gate * input: SHA1_CTX * : the context to initializes. 3067c478bd9Sstevel@tonic-gate * output: void 3077c478bd9Sstevel@tonic-gate */ 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate void 3107c478bd9Sstevel@tonic-gate SHA1Init(SHA1_CTX *ctx) 3117c478bd9Sstevel@tonic-gate { 3127c478bd9Sstevel@tonic-gate ctx->count[0] = ctx->count[1] = 0; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * load magic initialization constants. Tell lint 3167c478bd9Sstevel@tonic-gate * that these constants are unsigned by using U. 3177c478bd9Sstevel@tonic-gate */ 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate ctx->state[0] = 0x67452301U; 3207c478bd9Sstevel@tonic-gate ctx->state[1] = 0xefcdab89U; 3217c478bd9Sstevel@tonic-gate ctx->state[2] = 0x98badcfeU; 3227c478bd9Sstevel@tonic-gate ctx->state[3] = 0x10325476U; 3237c478bd9Sstevel@tonic-gate ctx->state[4] = 0xc3d2e1f0U; 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate #ifdef VIS_SHA1 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate #ifdef _KERNEL 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate #include <sys/regset.h> 3327c478bd9Sstevel@tonic-gate #include <sys/vis.h> 333*15b9cbbcSkrishna #include <sys/fpu/fpusystm.h> 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* the alignment for block stores to save fp registers */ 3367c478bd9Sstevel@tonic-gate #define VIS_ALIGN (64) 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate extern int sha1_savefp(kfpu_t *, int); 3397c478bd9Sstevel@tonic-gate extern void sha1_restorefp(kfpu_t *); 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate uint32_t vis_sha1_svfp_threshold = 128; 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate #else /* !_KERNEL */ 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate static boolean_t checked_vis = B_FALSE; 346*15b9cbbcSkrishna static int usevis = 0; 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate static int 3497c478bd9Sstevel@tonic-gate havevis() 3507c478bd9Sstevel@tonic-gate { 3517c478bd9Sstevel@tonic-gate char *buf = NULL; 3527c478bd9Sstevel@tonic-gate char *isa_token; 3537c478bd9Sstevel@tonic-gate char *lasts; 3547c478bd9Sstevel@tonic-gate int ret = 0; 3557c478bd9Sstevel@tonic-gate size_t bufsize = 255; /* UltraSPARC III needs 115 chars */ 3567c478bd9Sstevel@tonic-gate int v9_isa_token, vis_isa_token, isa_token_num; 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate if (checked_vis) { 3597c478bd9Sstevel@tonic-gate return (usevis); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate if ((buf = malloc(bufsize)) == NULL) { 3637c478bd9Sstevel@tonic-gate return (0); 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate if ((ret = sysinfo(SI_ISALIST, buf, bufsize)) == -1) { 3677c478bd9Sstevel@tonic-gate free(buf); 3687c478bd9Sstevel@tonic-gate return (0); 3697c478bd9Sstevel@tonic-gate } else if (ret > bufsize) { 3707c478bd9Sstevel@tonic-gate /* We lost some because our buffer was too small */ 3717c478bd9Sstevel@tonic-gate if ((buf = realloc(buf, bufsize = ret)) == NULL) { 3727c478bd9Sstevel@tonic-gate return (0); 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate if ((ret = sysinfo(SI_ISALIST, buf, bufsize)) == -1) { 3757c478bd9Sstevel@tonic-gate free(buf); 3767c478bd9Sstevel@tonic-gate return (0); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate /* 3817c478bd9Sstevel@tonic-gate * Check the relative posistions of sparcv9 & sparcv9+vis 3827c478bd9Sstevel@tonic-gate * because they are listed in (best) performance order. 3837c478bd9Sstevel@tonic-gate * For example: The Niagara chip reports it has VIS but the 3847c478bd9Sstevel@tonic-gate * SHA1 code runs faster without this optimisation. 3857c478bd9Sstevel@tonic-gate */ 3867c478bd9Sstevel@tonic-gate isa_token = strtok_r(buf, " ", &lasts); 3877c478bd9Sstevel@tonic-gate v9_isa_token = vis_isa_token = -1; 3887c478bd9Sstevel@tonic-gate isa_token_num = 0; 3897c478bd9Sstevel@tonic-gate do { 3907c478bd9Sstevel@tonic-gate if (strcmp(isa_token, "sparcv9") == 0) { 3917c478bd9Sstevel@tonic-gate v9_isa_token = isa_token_num; 3927c478bd9Sstevel@tonic-gate } else if (strcmp(isa_token, "sparcv9+vis") == 0) { 3937c478bd9Sstevel@tonic-gate vis_isa_token = isa_token_num; 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate isa_token_num++; 3967c478bd9Sstevel@tonic-gate } while (isa_token = strtok_r(NULL, " ", &lasts)); 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate if (vis_isa_token != -1 && vis_isa_token < v9_isa_token) 3997c478bd9Sstevel@tonic-gate usevis = 1; 4007c478bd9Sstevel@tonic-gate free(buf); 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate checked_vis = B_TRUE; 4037c478bd9Sstevel@tonic-gate return (usevis); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* 4097c478bd9Sstevel@tonic-gate * VIS SHA-1 consts. 4107c478bd9Sstevel@tonic-gate */ 4117c478bd9Sstevel@tonic-gate static uint64_t VIS[] = { 4124cc1ac68Skrishna 0x8000000080000000ULL, 4134cc1ac68Skrishna 0x0002000200020002ULL, 4144cc1ac68Skrishna 0x5a8279996ed9eba1ULL, 4154cc1ac68Skrishna 0x8f1bbcdcca62c1d6ULL, 4164cc1ac68Skrishna 0x012389ab456789abULL}; 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate extern void SHA1TransformVIS(uint64_t *, uint64_t *, uint32_t *, uint64_t *); 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* 4227c478bd9Sstevel@tonic-gate * SHA1Update() 4237c478bd9Sstevel@tonic-gate * 4247c478bd9Sstevel@tonic-gate * purpose: continues an sha1 digest operation, using the message block 4257c478bd9Sstevel@tonic-gate * to update the context. 4267c478bd9Sstevel@tonic-gate * input: SHA1_CTX * : the context to update 4277c478bd9Sstevel@tonic-gate * uint8_t * : the message block 4287c478bd9Sstevel@tonic-gate * uint32_t : the length of the message block in bytes 4297c478bd9Sstevel@tonic-gate * output: void 4307c478bd9Sstevel@tonic-gate */ 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate void 4337c478bd9Sstevel@tonic-gate SHA1Update(SHA1_CTX *ctx, const uint8_t *input, uint32_t input_len) 4347c478bd9Sstevel@tonic-gate { 4357c478bd9Sstevel@tonic-gate uint32_t i, buf_index, buf_len; 4367c478bd9Sstevel@tonic-gate uint64_t X0[40], input64[8]; 437*15b9cbbcSkrishna #ifdef _KERNEL 438*15b9cbbcSkrishna int usevis = 0; 439*15b9cbbcSkrishna #endif /* _KERNEL */ 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate /* check for noop */ 4427c478bd9Sstevel@tonic-gate if (input_len == 0) 4437c478bd9Sstevel@tonic-gate return; 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate /* compute number of bytes mod 64 */ 4467c478bd9Sstevel@tonic-gate buf_index = (ctx->count[1] >> 3) & 0x3F; 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate /* update number of bits */ 4497c478bd9Sstevel@tonic-gate if ((ctx->count[1] += (input_len << 3)) < (input_len << 3)) 4507c478bd9Sstevel@tonic-gate ctx->count[0]++; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate ctx->count[0] += (input_len >> 29); 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate buf_len = 64 - buf_index; 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* transform as many times as possible */ 4577c478bd9Sstevel@tonic-gate i = 0; 4587c478bd9Sstevel@tonic-gate if (input_len >= buf_len) { 4597c478bd9Sstevel@tonic-gate #ifdef _KERNEL 4607c478bd9Sstevel@tonic-gate uint8_t fpua[sizeof (kfpu_t) + GSR_SIZE + VIS_ALIGN]; 4617c478bd9Sstevel@tonic-gate kfpu_t *fpu; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate uint32_t len = (input_len + buf_index) & ~0x3f; 4647c478bd9Sstevel@tonic-gate int svfp_ok; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate fpu = (kfpu_t *)P2ROUNDUP((uintptr_t)fpua, 64); 4677c478bd9Sstevel@tonic-gate svfp_ok = ((len >= vis_sha1_svfp_threshold) ? 1 : 0); 468*15b9cbbcSkrishna usevis = fpu_exists && sha1_savefp(fpu, svfp_ok); 4697c478bd9Sstevel@tonic-gate #else 4707c478bd9Sstevel@tonic-gate if (!checked_vis) 4717c478bd9Sstevel@tonic-gate usevis = havevis(); 4727c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * general optimization: 4767c478bd9Sstevel@tonic-gate * 4777c478bd9Sstevel@tonic-gate * only do initial bcopy() and SHA1Transform() if 4787c478bd9Sstevel@tonic-gate * buf_index != 0. if buf_index == 0, we're just 4797c478bd9Sstevel@tonic-gate * wasting our time doing the bcopy() since there 4807c478bd9Sstevel@tonic-gate * wasn't any data left over from a previous call to 4817c478bd9Sstevel@tonic-gate * SHA1Update(). 4827c478bd9Sstevel@tonic-gate */ 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate if (buf_index) { 4857c478bd9Sstevel@tonic-gate bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len); 4867c478bd9Sstevel@tonic-gate if (usevis) { 4877c478bd9Sstevel@tonic-gate SHA1TransformVIS(X0, 4887c478bd9Sstevel@tonic-gate (uint64_t *)ctx->buf_un.buf8, 4897c478bd9Sstevel@tonic-gate &ctx->state[0], VIS); 4907c478bd9Sstevel@tonic-gate } else { 4917c478bd9Sstevel@tonic-gate SHA1Transform(ctx->state[0], ctx->state[1], 4927c478bd9Sstevel@tonic-gate ctx->state[2], ctx->state[3], 4937c478bd9Sstevel@tonic-gate ctx->state[4], ctx, ctx->buf_un.buf8); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate i = buf_len; 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate /* 4997c478bd9Sstevel@tonic-gate * VIS SHA-1: uses the VIS 1.0 instructions to accelerate 5007c478bd9Sstevel@tonic-gate * SHA-1 processing. This is achieved by "offloading" the 5017c478bd9Sstevel@tonic-gate * computation of the message schedule (MS) to the VIS units. 5027c478bd9Sstevel@tonic-gate * This allows the VIS computation of the message schedule 5037c478bd9Sstevel@tonic-gate * to be performed in parallel with the standard integer 5047c478bd9Sstevel@tonic-gate * processing of the remainder of the SHA-1 computation. 5057c478bd9Sstevel@tonic-gate * performance by up to around 1.37X, compared to an optimized 5067c478bd9Sstevel@tonic-gate * integer-only implementation. 5077c478bd9Sstevel@tonic-gate * 5087c478bd9Sstevel@tonic-gate * The VIS implementation of SHA1Transform has a different API 5097c478bd9Sstevel@tonic-gate * to the standard integer version: 5107c478bd9Sstevel@tonic-gate * 5117c478bd9Sstevel@tonic-gate * void SHA1TransformVIS( 5127c478bd9Sstevel@tonic-gate * uint64_t *, // Pointer to MS for ith block 5137c478bd9Sstevel@tonic-gate * uint64_t *, // Pointer to ith block of message data 5147c478bd9Sstevel@tonic-gate * uint32_t *, // Pointer to SHA state i.e ctx->state 5157c478bd9Sstevel@tonic-gate * uint64_t *, // Pointer to various VIS constants 5167c478bd9Sstevel@tonic-gate * ) 5177c478bd9Sstevel@tonic-gate * 5187c478bd9Sstevel@tonic-gate * Note: the message data must by 4-byte aligned. 5197c478bd9Sstevel@tonic-gate * 5207c478bd9Sstevel@tonic-gate * Function requires VIS 1.0 support. 5217c478bd9Sstevel@tonic-gate * 5227c478bd9Sstevel@tonic-gate * Handling is provided to deal with arbitrary byte alingment 5237c478bd9Sstevel@tonic-gate * of the input data but the performance gains are reduced 5247c478bd9Sstevel@tonic-gate * for alignments other than 4-bytes. 5257c478bd9Sstevel@tonic-gate */ 5267c478bd9Sstevel@tonic-gate if (usevis) { 5274cc1ac68Skrishna if (((uint64_t)(uintptr_t)(&input[i]) & 0x3)) { 5287c478bd9Sstevel@tonic-gate /* 5297c478bd9Sstevel@tonic-gate * Main processing loop - input misaligned 5307c478bd9Sstevel@tonic-gate */ 5317c478bd9Sstevel@tonic-gate for (; i + 63 < input_len; i += 64) { 5327c478bd9Sstevel@tonic-gate bcopy(&input[i], input64, 64); 5337c478bd9Sstevel@tonic-gate SHA1TransformVIS(X0, input64, 5347c478bd9Sstevel@tonic-gate &ctx->state[0], VIS); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate } else { 5377c478bd9Sstevel@tonic-gate /* 5387c478bd9Sstevel@tonic-gate * Main processing loop - input 8-byte aligned 5397c478bd9Sstevel@tonic-gate */ 5407c478bd9Sstevel@tonic-gate for (; i + 63 < input_len; i += 64) { 5417c478bd9Sstevel@tonic-gate SHA1TransformVIS(X0, 5427c478bd9Sstevel@tonic-gate (uint64_t *)&input[i], 5437c478bd9Sstevel@tonic-gate &ctx->state[0], VIS); 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate #ifdef _KERNEL 5487c478bd9Sstevel@tonic-gate sha1_restorefp(fpu); 5497c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 5507c478bd9Sstevel@tonic-gate } else { 5517c478bd9Sstevel@tonic-gate for (; i + 63 < input_len; i += 64) { 5527c478bd9Sstevel@tonic-gate SHA1Transform(ctx->state[0], ctx->state[1], 5537c478bd9Sstevel@tonic-gate ctx->state[2], ctx->state[3], ctx->state[4], 5547c478bd9Sstevel@tonic-gate ctx, &input[i]); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate /* 5597c478bd9Sstevel@tonic-gate * general optimization: 5607c478bd9Sstevel@tonic-gate * 5617c478bd9Sstevel@tonic-gate * if i and input_len are the same, return now instead 5627c478bd9Sstevel@tonic-gate * of calling bcopy(), since the bcopy() in this case 5637c478bd9Sstevel@tonic-gate * will be an expensive nop. 5647c478bd9Sstevel@tonic-gate */ 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate if (input_len == i) 5677c478bd9Sstevel@tonic-gate return; 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate buf_index = 0; 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate /* buffer remaining input */ 5737c478bd9Sstevel@tonic-gate bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i); 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate #else /* VIS_SHA1 */ 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate void 5797c478bd9Sstevel@tonic-gate SHA1Update(SHA1_CTX *ctx, const uint8_t *input, uint32_t input_len) 5807c478bd9Sstevel@tonic-gate { 5817c478bd9Sstevel@tonic-gate uint32_t i, buf_index, buf_len; 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate /* check for noop */ 5847c478bd9Sstevel@tonic-gate if (input_len == 0) 5857c478bd9Sstevel@tonic-gate return; 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate /* compute number of bytes mod 64 */ 5887c478bd9Sstevel@tonic-gate buf_index = (ctx->count[1] >> 3) & 0x3F; 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate /* update number of bits */ 5917c478bd9Sstevel@tonic-gate if ((ctx->count[1] += (input_len << 3)) < (input_len << 3)) 5927c478bd9Sstevel@tonic-gate ctx->count[0]++; 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate ctx->count[0] += (input_len >> 29); 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate buf_len = 64 - buf_index; 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate /* transform as many times as possible */ 5997c478bd9Sstevel@tonic-gate i = 0; 6007c478bd9Sstevel@tonic-gate if (input_len >= buf_len) { 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate /* 6037c478bd9Sstevel@tonic-gate * general optimization: 6047c478bd9Sstevel@tonic-gate * 6057c478bd9Sstevel@tonic-gate * only do initial bcopy() and SHA1Transform() if 6067c478bd9Sstevel@tonic-gate * buf_index != 0. if buf_index == 0, we're just 6077c478bd9Sstevel@tonic-gate * wasting our time doing the bcopy() since there 6087c478bd9Sstevel@tonic-gate * wasn't any data left over from a previous call to 6097c478bd9Sstevel@tonic-gate * SHA1Update(). 6107c478bd9Sstevel@tonic-gate */ 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate if (buf_index) { 6137c478bd9Sstevel@tonic-gate bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate SHA1Transform(ctx->state[0], ctx->state[1], 6177c478bd9Sstevel@tonic-gate ctx->state[2], ctx->state[3], ctx->state[4], ctx, 6187c478bd9Sstevel@tonic-gate ctx->buf_un.buf8); 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate i = buf_len; 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate for (; i + 63 < input_len; i += 64) 6247c478bd9Sstevel@tonic-gate SHA1Transform(ctx->state[0], ctx->state[1], 6257c478bd9Sstevel@tonic-gate ctx->state[2], ctx->state[3], ctx->state[4], 6267c478bd9Sstevel@tonic-gate ctx, &input[i]); 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate /* 6297c478bd9Sstevel@tonic-gate * general optimization: 6307c478bd9Sstevel@tonic-gate * 6317c478bd9Sstevel@tonic-gate * if i and input_len are the same, return now instead 6327c478bd9Sstevel@tonic-gate * of calling bcopy(), since the bcopy() in this case 6337c478bd9Sstevel@tonic-gate * will be an expensive nop. 6347c478bd9Sstevel@tonic-gate */ 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate if (input_len == i) 6377c478bd9Sstevel@tonic-gate return; 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate buf_index = 0; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate /* buffer remaining input */ 6437c478bd9Sstevel@tonic-gate bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i); 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate #endif /* VIS_SHA1 */ 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate /* 6497c478bd9Sstevel@tonic-gate * SHA1Final() 6507c478bd9Sstevel@tonic-gate * 6517c478bd9Sstevel@tonic-gate * purpose: ends an sha1 digest operation, finalizing the message digest and 6527c478bd9Sstevel@tonic-gate * zeroing the context. 6537c478bd9Sstevel@tonic-gate * input: uint8_t * : a buffer to store the digest in 6547c478bd9Sstevel@tonic-gate * SHA1_CTX * : the context to finalize, save, and zero 6557c478bd9Sstevel@tonic-gate * output: void 6567c478bd9Sstevel@tonic-gate */ 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate void 6597c478bd9Sstevel@tonic-gate SHA1Final(uint8_t *digest, SHA1_CTX *ctx) 6607c478bd9Sstevel@tonic-gate { 6617c478bd9Sstevel@tonic-gate uint8_t bitcount_be[sizeof (ctx->count)]; 6627c478bd9Sstevel@tonic-gate uint32_t index = (ctx->count[1] >> 3) & 0x3f; 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate /* store bit count, big endian */ 6657c478bd9Sstevel@tonic-gate Encode(bitcount_be, ctx->count, sizeof (bitcount_be)); 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate /* pad out to 56 mod 64 */ 6687c478bd9Sstevel@tonic-gate SHA1Update(ctx, PADDING, ((index < 56) ? 56 : 120) - index); 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate /* append length (before padding) */ 6717c478bd9Sstevel@tonic-gate SHA1Update(ctx, bitcount_be, sizeof (bitcount_be)); 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* store state in digest */ 6747c478bd9Sstevel@tonic-gate Encode(digest, ctx->state, sizeof (ctx->state)); 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate /* 6787c478bd9Sstevel@tonic-gate * sparc optimization: 6797c478bd9Sstevel@tonic-gate * 6807c478bd9Sstevel@tonic-gate * on the sparc, we can load big endian 32-bit data easily. note that 6817c478bd9Sstevel@tonic-gate * special care must be taken to ensure the address is 32-bit aligned. 6827c478bd9Sstevel@tonic-gate * in the interest of speed, we don't check to make sure, since 6837c478bd9Sstevel@tonic-gate * careful programming can guarantee this for us. 6847c478bd9Sstevel@tonic-gate */ 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate #if defined(_BIG_ENDIAN) 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate #define LOAD_BIG_32(addr) (*(uint32_t *)(addr)) 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate #else /* little endian -- will work on big endian, but slowly */ 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate #define LOAD_BIG_32(addr) \ 6937c478bd9Sstevel@tonic-gate (((addr)[0] << 24) | ((addr)[1] << 16) | ((addr)[2] << 8) | (addr)[3]) 6947c478bd9Sstevel@tonic-gate #endif 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate /* 6977c478bd9Sstevel@tonic-gate * sparc register window optimization: 6987c478bd9Sstevel@tonic-gate * 6997c478bd9Sstevel@tonic-gate * `a', `b', `c', `d', and `e' are passed into SHA1Transform 7007c478bd9Sstevel@tonic-gate * explicitly since it increases the number of registers available to 7017c478bd9Sstevel@tonic-gate * the compiler. under this scheme, these variables can be held in 7027c478bd9Sstevel@tonic-gate * %i0 - %i4, which leaves more local and out registers available. 7037c478bd9Sstevel@tonic-gate */ 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate /* 7067c478bd9Sstevel@tonic-gate * SHA1Transform() 7077c478bd9Sstevel@tonic-gate * 7087c478bd9Sstevel@tonic-gate * purpose: sha1 transformation -- updates the digest based on `block' 7097c478bd9Sstevel@tonic-gate * input: uint32_t : bytes 1 - 4 of the digest 7107c478bd9Sstevel@tonic-gate * uint32_t : bytes 5 - 8 of the digest 7117c478bd9Sstevel@tonic-gate * uint32_t : bytes 9 - 12 of the digest 7127c478bd9Sstevel@tonic-gate * uint32_t : bytes 12 - 16 of the digest 7137c478bd9Sstevel@tonic-gate * uint32_t : bytes 16 - 20 of the digest 7147c478bd9Sstevel@tonic-gate * SHA1_CTX * : the context to update 7157c478bd9Sstevel@tonic-gate * uint8_t [64]: the block to use to update the digest 7167c478bd9Sstevel@tonic-gate * output: void 7177c478bd9Sstevel@tonic-gate */ 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate void 7207c478bd9Sstevel@tonic-gate SHA1Transform(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, 7217c478bd9Sstevel@tonic-gate SHA1_CTX *ctx, const uint8_t blk[64]) 7227c478bd9Sstevel@tonic-gate { 7237c478bd9Sstevel@tonic-gate /* 7247c478bd9Sstevel@tonic-gate * sparc optimization: 7257c478bd9Sstevel@tonic-gate * 7267c478bd9Sstevel@tonic-gate * while it is somewhat counter-intuitive, on sparc, it is 7277c478bd9Sstevel@tonic-gate * more efficient to place all the constants used in this 7287c478bd9Sstevel@tonic-gate * function in an array and load the values out of the array 7297c478bd9Sstevel@tonic-gate * than to manually load the constants. this is because 7307c478bd9Sstevel@tonic-gate * setting a register to a 32-bit value takes two ops in most 7317c478bd9Sstevel@tonic-gate * cases: a `sethi' and an `or', but loading a 32-bit value 7327c478bd9Sstevel@tonic-gate * from memory only takes one `ld' (or `lduw' on v9). while 7337c478bd9Sstevel@tonic-gate * this increases memory usage, the compiler can find enough 7347c478bd9Sstevel@tonic-gate * other things to do while waiting to keep the pipeline does 7357c478bd9Sstevel@tonic-gate * not stall. additionally, it is likely that many of these 7367c478bd9Sstevel@tonic-gate * constants are cached so that later accesses do not even go 7377c478bd9Sstevel@tonic-gate * out to the bus. 7387c478bd9Sstevel@tonic-gate * 7397c478bd9Sstevel@tonic-gate * this array is declared `static' to keep the compiler from 7407c478bd9Sstevel@tonic-gate * having to bcopy() this array onto the stack frame of 7417c478bd9Sstevel@tonic-gate * SHA1Transform() each time it is called -- which is 7427c478bd9Sstevel@tonic-gate * unacceptably expensive. 7437c478bd9Sstevel@tonic-gate * 7447c478bd9Sstevel@tonic-gate * the `const' is to ensure that callers are good citizens and 7457c478bd9Sstevel@tonic-gate * do not try to munge the array. since these routines are 7467c478bd9Sstevel@tonic-gate * going to be called from inside multithreaded kernelland, 7477c478bd9Sstevel@tonic-gate * this is a good safety check. -- `sha1_consts' will end up in 7487c478bd9Sstevel@tonic-gate * .rodata. 7497c478bd9Sstevel@tonic-gate * 7507c478bd9Sstevel@tonic-gate * unfortunately, loading from an array in this manner hurts 7517c478bd9Sstevel@tonic-gate * performance under intel. so, there is a macro, 7527c478bd9Sstevel@tonic-gate * SHA1_CONST(), used in SHA1Transform(), that either expands to 7537c478bd9Sstevel@tonic-gate * a reference to this array, or to the actual constant, 7547c478bd9Sstevel@tonic-gate * depending on what platform this code is compiled for. 7557c478bd9Sstevel@tonic-gate */ 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate #if defined(__sparc) 7587c478bd9Sstevel@tonic-gate static const uint32_t sha1_consts[] = { 7597c478bd9Sstevel@tonic-gate SHA1_CONST_0, SHA1_CONST_1, SHA1_CONST_2, SHA1_CONST_3, 7607c478bd9Sstevel@tonic-gate }; 7617c478bd9Sstevel@tonic-gate #endif 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate /* 7647c478bd9Sstevel@tonic-gate * general optimization: 7657c478bd9Sstevel@tonic-gate * 7667c478bd9Sstevel@tonic-gate * use individual integers instead of using an array. this is a 7677c478bd9Sstevel@tonic-gate * win, although the amount it wins by seems to vary quite a bit. 7687c478bd9Sstevel@tonic-gate */ 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate uint32_t w_0, w_1, w_2, w_3, w_4, w_5, w_6, w_7; 7717c478bd9Sstevel@tonic-gate uint32_t w_8, w_9, w_10, w_11, w_12, w_13, w_14, w_15; 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate /* 7747c478bd9Sstevel@tonic-gate * sparc optimization: 7757c478bd9Sstevel@tonic-gate * 7767c478bd9Sstevel@tonic-gate * if `block' is already aligned on a 4-byte boundary, use 7777c478bd9Sstevel@tonic-gate * LOAD_BIG_32() directly. otherwise, bcopy() into a 7787c478bd9Sstevel@tonic-gate * buffer that *is* aligned on a 4-byte boundary and then do 7797c478bd9Sstevel@tonic-gate * the LOAD_BIG_32() on that buffer. benchmarks have shown 7807c478bd9Sstevel@tonic-gate * that using the bcopy() is better than loading the bytes 7817c478bd9Sstevel@tonic-gate * individually and doing the endian-swap by hand. 7827c478bd9Sstevel@tonic-gate * 7837c478bd9Sstevel@tonic-gate * even though it's quite tempting to assign to do: 7847c478bd9Sstevel@tonic-gate * 7857c478bd9Sstevel@tonic-gate * blk = bcopy(ctx->buf_un.buf32, blk, sizeof (ctx->buf_un.buf32)); 7867c478bd9Sstevel@tonic-gate * 7877c478bd9Sstevel@tonic-gate * and only have one set of LOAD_BIG_32()'s, the compiler 7887c478bd9Sstevel@tonic-gate * *does not* like that, so please resist the urge. 7897c478bd9Sstevel@tonic-gate */ 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate #if defined(__sparc) 7927c478bd9Sstevel@tonic-gate if ((uintptr_t)blk & 0x3) { /* not 4-byte aligned? */ 7937c478bd9Sstevel@tonic-gate bcopy(blk, ctx->buf_un.buf32, sizeof (ctx->buf_un.buf32)); 7947c478bd9Sstevel@tonic-gate w_15 = LOAD_BIG_32(ctx->buf_un.buf32 + 15); 7957c478bd9Sstevel@tonic-gate w_14 = LOAD_BIG_32(ctx->buf_un.buf32 + 14); 7967c478bd9Sstevel@tonic-gate w_13 = LOAD_BIG_32(ctx->buf_un.buf32 + 13); 7977c478bd9Sstevel@tonic-gate w_12 = LOAD_BIG_32(ctx->buf_un.buf32 + 12); 7987c478bd9Sstevel@tonic-gate w_11 = LOAD_BIG_32(ctx->buf_un.buf32 + 11); 7997c478bd9Sstevel@tonic-gate w_10 = LOAD_BIG_32(ctx->buf_un.buf32 + 10); 8007c478bd9Sstevel@tonic-gate w_9 = LOAD_BIG_32(ctx->buf_un.buf32 + 9); 8017c478bd9Sstevel@tonic-gate w_8 = LOAD_BIG_32(ctx->buf_un.buf32 + 8); 8027c478bd9Sstevel@tonic-gate w_7 = LOAD_BIG_32(ctx->buf_un.buf32 + 7); 8037c478bd9Sstevel@tonic-gate w_6 = LOAD_BIG_32(ctx->buf_un.buf32 + 6); 8047c478bd9Sstevel@tonic-gate w_5 = LOAD_BIG_32(ctx->buf_un.buf32 + 5); 8057c478bd9Sstevel@tonic-gate w_4 = LOAD_BIG_32(ctx->buf_un.buf32 + 4); 8067c478bd9Sstevel@tonic-gate w_3 = LOAD_BIG_32(ctx->buf_un.buf32 + 3); 8077c478bd9Sstevel@tonic-gate w_2 = LOAD_BIG_32(ctx->buf_un.buf32 + 2); 8087c478bd9Sstevel@tonic-gate w_1 = LOAD_BIG_32(ctx->buf_un.buf32 + 1); 8097c478bd9Sstevel@tonic-gate w_0 = LOAD_BIG_32(ctx->buf_un.buf32 + 0); 8107c478bd9Sstevel@tonic-gate } else { 8117c478bd9Sstevel@tonic-gate /*LINTED*/ 8127c478bd9Sstevel@tonic-gate w_15 = LOAD_BIG_32(blk + 60); 8137c478bd9Sstevel@tonic-gate /*LINTED*/ 8147c478bd9Sstevel@tonic-gate w_14 = LOAD_BIG_32(blk + 56); 8157c478bd9Sstevel@tonic-gate /*LINTED*/ 8167c478bd9Sstevel@tonic-gate w_13 = LOAD_BIG_32(blk + 52); 8177c478bd9Sstevel@tonic-gate /*LINTED*/ 8187c478bd9Sstevel@tonic-gate w_12 = LOAD_BIG_32(blk + 48); 8197c478bd9Sstevel@tonic-gate /*LINTED*/ 8207c478bd9Sstevel@tonic-gate w_11 = LOAD_BIG_32(blk + 44); 8217c478bd9Sstevel@tonic-gate /*LINTED*/ 8227c478bd9Sstevel@tonic-gate w_10 = LOAD_BIG_32(blk + 40); 8237c478bd9Sstevel@tonic-gate /*LINTED*/ 8247c478bd9Sstevel@tonic-gate w_9 = LOAD_BIG_32(blk + 36); 8257c478bd9Sstevel@tonic-gate /*LINTED*/ 8267c478bd9Sstevel@tonic-gate w_8 = LOAD_BIG_32(blk + 32); 8277c478bd9Sstevel@tonic-gate /*LINTED*/ 8287c478bd9Sstevel@tonic-gate w_7 = LOAD_BIG_32(blk + 28); 8297c478bd9Sstevel@tonic-gate /*LINTED*/ 8307c478bd9Sstevel@tonic-gate w_6 = LOAD_BIG_32(blk + 24); 8317c478bd9Sstevel@tonic-gate /*LINTED*/ 8327c478bd9Sstevel@tonic-gate w_5 = LOAD_BIG_32(blk + 20); 8337c478bd9Sstevel@tonic-gate /*LINTED*/ 8347c478bd9Sstevel@tonic-gate w_4 = LOAD_BIG_32(blk + 16); 8357c478bd9Sstevel@tonic-gate /*LINTED*/ 8367c478bd9Sstevel@tonic-gate w_3 = LOAD_BIG_32(blk + 12); 8377c478bd9Sstevel@tonic-gate /*LINTED*/ 8387c478bd9Sstevel@tonic-gate w_2 = LOAD_BIG_32(blk + 8); 8397c478bd9Sstevel@tonic-gate /*LINTED*/ 8407c478bd9Sstevel@tonic-gate w_1 = LOAD_BIG_32(blk + 4); 8417c478bd9Sstevel@tonic-gate /*LINTED*/ 8427c478bd9Sstevel@tonic-gate w_0 = LOAD_BIG_32(blk + 0); 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate #else 8457c478bd9Sstevel@tonic-gate w_15 = LOAD_BIG_32(blk + 60); 8467c478bd9Sstevel@tonic-gate w_14 = LOAD_BIG_32(blk + 56); 8477c478bd9Sstevel@tonic-gate w_13 = LOAD_BIG_32(blk + 52); 8487c478bd9Sstevel@tonic-gate w_12 = LOAD_BIG_32(blk + 48); 8497c478bd9Sstevel@tonic-gate w_11 = LOAD_BIG_32(blk + 44); 8507c478bd9Sstevel@tonic-gate w_10 = LOAD_BIG_32(blk + 40); 8517c478bd9Sstevel@tonic-gate w_9 = LOAD_BIG_32(blk + 36); 8527c478bd9Sstevel@tonic-gate w_8 = LOAD_BIG_32(blk + 32); 8537c478bd9Sstevel@tonic-gate w_7 = LOAD_BIG_32(blk + 28); 8547c478bd9Sstevel@tonic-gate w_6 = LOAD_BIG_32(blk + 24); 8557c478bd9Sstevel@tonic-gate w_5 = LOAD_BIG_32(blk + 20); 8567c478bd9Sstevel@tonic-gate w_4 = LOAD_BIG_32(blk + 16); 8577c478bd9Sstevel@tonic-gate w_3 = LOAD_BIG_32(blk + 12); 8587c478bd9Sstevel@tonic-gate w_2 = LOAD_BIG_32(blk + 8); 8597c478bd9Sstevel@tonic-gate w_1 = LOAD_BIG_32(blk + 4); 8607c478bd9Sstevel@tonic-gate w_0 = LOAD_BIG_32(blk + 0); 8617c478bd9Sstevel@tonic-gate #endif 8627c478bd9Sstevel@tonic-gate /* 8637c478bd9Sstevel@tonic-gate * general optimization: 8647c478bd9Sstevel@tonic-gate * 8657c478bd9Sstevel@tonic-gate * even though this approach is described in the standard as 8667c478bd9Sstevel@tonic-gate * being slower algorithmically, it is 30-40% faster than the 8677c478bd9Sstevel@tonic-gate * "faster" version under SPARC, because this version has more 8687c478bd9Sstevel@tonic-gate * of the constraints specified at compile-time and uses fewer 8697c478bd9Sstevel@tonic-gate * variables (and therefore has better register utilization) 8707c478bd9Sstevel@tonic-gate * than its "speedier" brother. (i've tried both, trust me) 8717c478bd9Sstevel@tonic-gate * 8727c478bd9Sstevel@tonic-gate * for either method given in the spec, there is an "assignment" 8737c478bd9Sstevel@tonic-gate * phase where the following takes place: 8747c478bd9Sstevel@tonic-gate * 8757c478bd9Sstevel@tonic-gate * tmp = (main_computation); 8767c478bd9Sstevel@tonic-gate * e = d; d = c; c = rotate_left(b, 30); b = a; a = tmp; 8777c478bd9Sstevel@tonic-gate * 8787c478bd9Sstevel@tonic-gate * we can make the algorithm go faster by not doing this work, 8797c478bd9Sstevel@tonic-gate * but just pretending that `d' is now `e', etc. this works 8807c478bd9Sstevel@tonic-gate * really well and obviates the need for a temporary variable. 8817c478bd9Sstevel@tonic-gate * however, we still explictly perform the rotate action, 8827c478bd9Sstevel@tonic-gate * since it is cheaper on SPARC to do it once than to have to 8837c478bd9Sstevel@tonic-gate * do it over and over again. 8847c478bd9Sstevel@tonic-gate */ 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate /* round 1 */ 8877c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + w_0 + SHA1_CONST(0); /* 0 */ 8887c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + w_1 + SHA1_CONST(0); /* 1 */ 8917c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + w_2 + SHA1_CONST(0); /* 2 */ 8947c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + w_3 + SHA1_CONST(0); /* 3 */ 8977c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + w_4 + SHA1_CONST(0); /* 4 */ 9007c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + w_5 + SHA1_CONST(0); /* 5 */ 9037c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + w_6 + SHA1_CONST(0); /* 6 */ 9067c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + w_7 + SHA1_CONST(0); /* 7 */ 9097c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + w_8 + SHA1_CONST(0); /* 8 */ 9127c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + w_9 + SHA1_CONST(0); /* 9 */ 9157c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + w_10 + SHA1_CONST(0); /* 10 */ 9187c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + w_11 + SHA1_CONST(0); /* 11 */ 9217c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + w_12 + SHA1_CONST(0); /* 12 */ 9247c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + w_13 + SHA1_CONST(0); /* 13 */ 9277c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + w_14 + SHA1_CONST(0); /* 14 */ 9307c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + w_15 + SHA1_CONST(0); /* 15 */ 9337c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate w_0 = ROTATE_LEFT((w_13 ^ w_8 ^ w_2 ^ w_0), 1); /* 16 */ 9367c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + w_0 + SHA1_CONST(0); 9377c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate w_1 = ROTATE_LEFT((w_14 ^ w_9 ^ w_3 ^ w_1), 1); /* 17 */ 9407c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + w_1 + SHA1_CONST(0); 9417c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate w_2 = ROTATE_LEFT((w_15 ^ w_10 ^ w_4 ^ w_2), 1); /* 18 */ 9447c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + w_2 + SHA1_CONST(0); 9457c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 9467c478bd9Sstevel@tonic-gate 9477c478bd9Sstevel@tonic-gate w_3 = ROTATE_LEFT((w_0 ^ w_11 ^ w_5 ^ w_3), 1); /* 19 */ 9487c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + w_3 + SHA1_CONST(0); 9497c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate /* round 2 */ 9527c478bd9Sstevel@tonic-gate w_4 = ROTATE_LEFT((w_1 ^ w_12 ^ w_6 ^ w_4), 1); /* 20 */ 9537c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_4 + SHA1_CONST(1); 9547c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate w_5 = ROTATE_LEFT((w_2 ^ w_13 ^ w_7 ^ w_5), 1); /* 21 */ 9577c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_5 + SHA1_CONST(1); 9587c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate w_6 = ROTATE_LEFT((w_3 ^ w_14 ^ w_8 ^ w_6), 1); /* 22 */ 9617c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_6 + SHA1_CONST(1); 9627c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate w_7 = ROTATE_LEFT((w_4 ^ w_15 ^ w_9 ^ w_7), 1); /* 23 */ 9657c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_7 + SHA1_CONST(1); 9667c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate w_8 = ROTATE_LEFT((w_5 ^ w_0 ^ w_10 ^ w_8), 1); /* 24 */ 9697c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_8 + SHA1_CONST(1); 9707c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate w_9 = ROTATE_LEFT((w_6 ^ w_1 ^ w_11 ^ w_9), 1); /* 25 */ 9737c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_9 + SHA1_CONST(1); 9747c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate w_10 = ROTATE_LEFT((w_7 ^ w_2 ^ w_12 ^ w_10), 1); /* 26 */ 9777c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_10 + SHA1_CONST(1); 9787c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate w_11 = ROTATE_LEFT((w_8 ^ w_3 ^ w_13 ^ w_11), 1); /* 27 */ 9817c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_11 + SHA1_CONST(1); 9827c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate w_12 = ROTATE_LEFT((w_9 ^ w_4 ^ w_14 ^ w_12), 1); /* 28 */ 9857c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_12 + SHA1_CONST(1); 9867c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate w_13 = ROTATE_LEFT((w_10 ^ w_5 ^ w_15 ^ w_13), 1); /* 29 */ 9897c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_13 + SHA1_CONST(1); 9907c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate w_14 = ROTATE_LEFT((w_11 ^ w_6 ^ w_0 ^ w_14), 1); /* 30 */ 9937c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_14 + SHA1_CONST(1); 9947c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate w_15 = ROTATE_LEFT((w_12 ^ w_7 ^ w_1 ^ w_15), 1); /* 31 */ 9977c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_15 + SHA1_CONST(1); 9987c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate w_0 = ROTATE_LEFT((w_13 ^ w_8 ^ w_2 ^ w_0), 1); /* 32 */ 10017c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_0 + SHA1_CONST(1); 10027c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate w_1 = ROTATE_LEFT((w_14 ^ w_9 ^ w_3 ^ w_1), 1); /* 33 */ 10057c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_1 + SHA1_CONST(1); 10067c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate w_2 = ROTATE_LEFT((w_15 ^ w_10 ^ w_4 ^ w_2), 1); /* 34 */ 10097c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_2 + SHA1_CONST(1); 10107c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate w_3 = ROTATE_LEFT((w_0 ^ w_11 ^ w_5 ^ w_3), 1); /* 35 */ 10137c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_3 + SHA1_CONST(1); 10147c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate w_4 = ROTATE_LEFT((w_1 ^ w_12 ^ w_6 ^ w_4), 1); /* 36 */ 10177c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_4 + SHA1_CONST(1); 10187c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate w_5 = ROTATE_LEFT((w_2 ^ w_13 ^ w_7 ^ w_5), 1); /* 37 */ 10217c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_5 + SHA1_CONST(1); 10227c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate w_6 = ROTATE_LEFT((w_3 ^ w_14 ^ w_8 ^ w_6), 1); /* 38 */ 10257c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_6 + SHA1_CONST(1); 10267c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate w_7 = ROTATE_LEFT((w_4 ^ w_15 ^ w_9 ^ w_7), 1); /* 39 */ 10297c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_7 + SHA1_CONST(1); 10307c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate /* round 3 */ 10337c478bd9Sstevel@tonic-gate w_8 = ROTATE_LEFT((w_5 ^ w_0 ^ w_10 ^ w_8), 1); /* 40 */ 10347c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + w_8 + SHA1_CONST(2); 10357c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate w_9 = ROTATE_LEFT((w_6 ^ w_1 ^ w_11 ^ w_9), 1); /* 41 */ 10387c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + w_9 + SHA1_CONST(2); 10397c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate w_10 = ROTATE_LEFT((w_7 ^ w_2 ^ w_12 ^ w_10), 1); /* 42 */ 10427c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + w_10 + SHA1_CONST(2); 10437c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate w_11 = ROTATE_LEFT((w_8 ^ w_3 ^ w_13 ^ w_11), 1); /* 43 */ 10467c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + w_11 + SHA1_CONST(2); 10477c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate w_12 = ROTATE_LEFT((w_9 ^ w_4 ^ w_14 ^ w_12), 1); /* 44 */ 10507c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + w_12 + SHA1_CONST(2); 10517c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate w_13 = ROTATE_LEFT((w_10 ^ w_5 ^ w_15 ^ w_13), 1); /* 45 */ 10547c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + w_13 + SHA1_CONST(2); 10557c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate w_14 = ROTATE_LEFT((w_11 ^ w_6 ^ w_0 ^ w_14), 1); /* 46 */ 10587c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + w_14 + SHA1_CONST(2); 10597c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate w_15 = ROTATE_LEFT((w_12 ^ w_7 ^ w_1 ^ w_15), 1); /* 47 */ 10627c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + w_15 + SHA1_CONST(2); 10637c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate w_0 = ROTATE_LEFT((w_13 ^ w_8 ^ w_2 ^ w_0), 1); /* 48 */ 10667c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + w_0 + SHA1_CONST(2); 10677c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate w_1 = ROTATE_LEFT((w_14 ^ w_9 ^ w_3 ^ w_1), 1); /* 49 */ 10707c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + w_1 + SHA1_CONST(2); 10717c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate w_2 = ROTATE_LEFT((w_15 ^ w_10 ^ w_4 ^ w_2), 1); /* 50 */ 10747c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + w_2 + SHA1_CONST(2); 10757c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate w_3 = ROTATE_LEFT((w_0 ^ w_11 ^ w_5 ^ w_3), 1); /* 51 */ 10787c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + w_3 + SHA1_CONST(2); 10797c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate w_4 = ROTATE_LEFT((w_1 ^ w_12 ^ w_6 ^ w_4), 1); /* 52 */ 10827c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + w_4 + SHA1_CONST(2); 10837c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate w_5 = ROTATE_LEFT((w_2 ^ w_13 ^ w_7 ^ w_5), 1); /* 53 */ 10867c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + w_5 + SHA1_CONST(2); 10877c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate w_6 = ROTATE_LEFT((w_3 ^ w_14 ^ w_8 ^ w_6), 1); /* 54 */ 10907c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + w_6 + SHA1_CONST(2); 10917c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate w_7 = ROTATE_LEFT((w_4 ^ w_15 ^ w_9 ^ w_7), 1); /* 55 */ 10947c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + w_7 + SHA1_CONST(2); 10957c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate w_8 = ROTATE_LEFT((w_5 ^ w_0 ^ w_10 ^ w_8), 1); /* 56 */ 10987c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + w_8 + SHA1_CONST(2); 10997c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate w_9 = ROTATE_LEFT((w_6 ^ w_1 ^ w_11 ^ w_9), 1); /* 57 */ 11027c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + w_9 + SHA1_CONST(2); 11037c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate w_10 = ROTATE_LEFT((w_7 ^ w_2 ^ w_12 ^ w_10), 1); /* 58 */ 11067c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + w_10 + SHA1_CONST(2); 11077c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate w_11 = ROTATE_LEFT((w_8 ^ w_3 ^ w_13 ^ w_11), 1); /* 59 */ 11107c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + w_11 + SHA1_CONST(2); 11117c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate /* round 4 */ 11147c478bd9Sstevel@tonic-gate w_12 = ROTATE_LEFT((w_9 ^ w_4 ^ w_14 ^ w_12), 1); /* 60 */ 11157c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_12 + SHA1_CONST(3); 11167c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate w_13 = ROTATE_LEFT((w_10 ^ w_5 ^ w_15 ^ w_13), 1); /* 61 */ 11197c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_13 + SHA1_CONST(3); 11207c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate w_14 = ROTATE_LEFT((w_11 ^ w_6 ^ w_0 ^ w_14), 1); /* 62 */ 11237c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_14 + SHA1_CONST(3); 11247c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate w_15 = ROTATE_LEFT((w_12 ^ w_7 ^ w_1 ^ w_15), 1); /* 63 */ 11277c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_15 + SHA1_CONST(3); 11287c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate w_0 = ROTATE_LEFT((w_13 ^ w_8 ^ w_2 ^ w_0), 1); /* 64 */ 11317c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_0 + SHA1_CONST(3); 11327c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate w_1 = ROTATE_LEFT((w_14 ^ w_9 ^ w_3 ^ w_1), 1); /* 65 */ 11357c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_1 + SHA1_CONST(3); 11367c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate w_2 = ROTATE_LEFT((w_15 ^ w_10 ^ w_4 ^ w_2), 1); /* 66 */ 11397c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_2 + SHA1_CONST(3); 11407c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate w_3 = ROTATE_LEFT((w_0 ^ w_11 ^ w_5 ^ w_3), 1); /* 67 */ 11437c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_3 + SHA1_CONST(3); 11447c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate w_4 = ROTATE_LEFT((w_1 ^ w_12 ^ w_6 ^ w_4), 1); /* 68 */ 11477c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_4 + SHA1_CONST(3); 11487c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate w_5 = ROTATE_LEFT((w_2 ^ w_13 ^ w_7 ^ w_5), 1); /* 69 */ 11517c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_5 + SHA1_CONST(3); 11527c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate w_6 = ROTATE_LEFT((w_3 ^ w_14 ^ w_8 ^ w_6), 1); /* 70 */ 11557c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_6 + SHA1_CONST(3); 11567c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate w_7 = ROTATE_LEFT((w_4 ^ w_15 ^ w_9 ^ w_7), 1); /* 71 */ 11597c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_7 + SHA1_CONST(3); 11607c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate w_8 = ROTATE_LEFT((w_5 ^ w_0 ^ w_10 ^ w_8), 1); /* 72 */ 11637c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_8 + SHA1_CONST(3); 11647c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate w_9 = ROTATE_LEFT((w_6 ^ w_1 ^ w_11 ^ w_9), 1); /* 73 */ 11677c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_9 + SHA1_CONST(3); 11687c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate w_10 = ROTATE_LEFT((w_7 ^ w_2 ^ w_12 ^ w_10), 1); /* 74 */ 11717c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_10 + SHA1_CONST(3); 11727c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate w_11 = ROTATE_LEFT((w_8 ^ w_3 ^ w_13 ^ w_11), 1); /* 75 */ 11757c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_11 + SHA1_CONST(3); 11767c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate w_12 = ROTATE_LEFT((w_9 ^ w_4 ^ w_14 ^ w_12), 1); /* 76 */ 11797c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_12 + SHA1_CONST(3); 11807c478bd9Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate w_13 = ROTATE_LEFT((w_10 ^ w_5 ^ w_15 ^ w_13), 1); /* 77 */ 11837c478bd9Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_13 + SHA1_CONST(3); 11847c478bd9Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate w_14 = ROTATE_LEFT((w_11 ^ w_6 ^ w_0 ^ w_14), 1); /* 78 */ 11877c478bd9Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_14 + SHA1_CONST(3); 11887c478bd9Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 11897c478bd9Sstevel@tonic-gate 11907c478bd9Sstevel@tonic-gate w_15 = ROTATE_LEFT((w_12 ^ w_7 ^ w_1 ^ w_15), 1); /* 79 */ 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate ctx->state[0] += ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_15 + 11937c478bd9Sstevel@tonic-gate SHA1_CONST(3); 11947c478bd9Sstevel@tonic-gate ctx->state[1] += b; 11957c478bd9Sstevel@tonic-gate ctx->state[2] += ROTATE_LEFT(c, 30); 11967c478bd9Sstevel@tonic-gate ctx->state[3] += d; 11977c478bd9Sstevel@tonic-gate ctx->state[4] += e; 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate /* zeroize sensitive information */ 12007c478bd9Sstevel@tonic-gate w_0 = w_1 = w_2 = w_3 = w_4 = w_5 = w_6 = w_7 = w_8 = 0; 12017c478bd9Sstevel@tonic-gate w_9 = w_10 = w_11 = w_12 = w_13 = w_14 = w_15 = 0; 12027c478bd9Sstevel@tonic-gate } 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate /* 12057c478bd9Sstevel@tonic-gate * devpro compiler optimization: 12067c478bd9Sstevel@tonic-gate * 12077c478bd9Sstevel@tonic-gate * the compiler can generate better code if it knows that `input' and 12087c478bd9Sstevel@tonic-gate * `output' do not point to the same source. there is no portable 12097c478bd9Sstevel@tonic-gate * way to tell the compiler this, but the sun compiler recognizes the 12107c478bd9Sstevel@tonic-gate * `_Restrict' keyword to indicate this condition. use it if possible. 12117c478bd9Sstevel@tonic-gate */ 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate #ifdef __RESTRICT 12147c478bd9Sstevel@tonic-gate #define restrict _Restrict 12157c478bd9Sstevel@tonic-gate #else 12167c478bd9Sstevel@tonic-gate #define restrict /* nothing */ 12177c478bd9Sstevel@tonic-gate #endif 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate /* 12207c478bd9Sstevel@tonic-gate * Encode() 12217c478bd9Sstevel@tonic-gate * 12227c478bd9Sstevel@tonic-gate * purpose: to convert a list of numbers from little endian to big endian 12237c478bd9Sstevel@tonic-gate * input: uint8_t * : place to store the converted big endian numbers 12247c478bd9Sstevel@tonic-gate * uint32_t * : place to get numbers to convert from 12257c478bd9Sstevel@tonic-gate * size_t : the length of the input in bytes 12267c478bd9Sstevel@tonic-gate * output: void 12277c478bd9Sstevel@tonic-gate */ 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate static void 12307c478bd9Sstevel@tonic-gate Encode(uint8_t *restrict output, uint32_t *restrict input, size_t len) 12317c478bd9Sstevel@tonic-gate { 12327c478bd9Sstevel@tonic-gate size_t i, j; 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate #if defined(__sparc) 12357c478bd9Sstevel@tonic-gate if (IS_P2ALIGNED(output, sizeof (uint32_t))) { 12367c478bd9Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4) { 12377c478bd9Sstevel@tonic-gate /* LINTED: pointer alignment */ 12387c478bd9Sstevel@tonic-gate *((uint32_t *)(output + j)) = input[i]; 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate } else { 12417c478bd9Sstevel@tonic-gate #endif /* little endian -- will work on big endian, but slowly */ 12427c478bd9Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4) { 12437c478bd9Sstevel@tonic-gate output[j] = (input[i] >> 24) & 0xff; 12447c478bd9Sstevel@tonic-gate output[j + 1] = (input[i] >> 16) & 0xff; 12457c478bd9Sstevel@tonic-gate output[j + 2] = (input[i] >> 8) & 0xff; 12467c478bd9Sstevel@tonic-gate output[j + 3] = input[i] & 0xff; 12477c478bd9Sstevel@tonic-gate } 12487c478bd9Sstevel@tonic-gate #if defined(__sparc) 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate #endif 12517c478bd9Sstevel@tonic-gate } 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate #ifdef _KERNEL 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate /* 12577c478bd9Sstevel@tonic-gate * KCF software provider control entry points. 12587c478bd9Sstevel@tonic-gate */ 12597c478bd9Sstevel@tonic-gate /* ARGSUSED */ 12607c478bd9Sstevel@tonic-gate static void 12617c478bd9Sstevel@tonic-gate sha1_provider_status(crypto_provider_handle_t provider, uint_t *status) 12627c478bd9Sstevel@tonic-gate { 12637c478bd9Sstevel@tonic-gate *status = CRYPTO_PROVIDER_READY; 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate 12667c478bd9Sstevel@tonic-gate /* 12677c478bd9Sstevel@tonic-gate * KCF software provider digest entry points. 12687c478bd9Sstevel@tonic-gate */ 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate static int 12717c478bd9Sstevel@tonic-gate sha1_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 12727c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 12737c478bd9Sstevel@tonic-gate { 12747c478bd9Sstevel@tonic-gate if (mechanism->cm_type != SHA1_MECH_INFO_TYPE) 12757c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 12767c478bd9Sstevel@tonic-gate 12777c478bd9Sstevel@tonic-gate /* 12787c478bd9Sstevel@tonic-gate * Allocate and initialize SHA1 context. 12797c478bd9Sstevel@tonic-gate */ 12807c478bd9Sstevel@tonic-gate ctx->cc_provider_private = kmem_alloc(sizeof (sha1_ctx_t), 12817c478bd9Sstevel@tonic-gate crypto_kmflag(req)); 12827c478bd9Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 12837c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate PROV_SHA1_CTX(ctx)->sc_mech_type = SHA1_MECH_INFO_TYPE; 12867c478bd9Sstevel@tonic-gate SHA1Init(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx); 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 12897c478bd9Sstevel@tonic-gate } 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate /* 12927c478bd9Sstevel@tonic-gate * Helper SHA1 digest update function for uio data. 12937c478bd9Sstevel@tonic-gate */ 12947c478bd9Sstevel@tonic-gate static int 12957c478bd9Sstevel@tonic-gate sha1_digest_update_uio(SHA1_CTX *sha1_ctx, crypto_data_t *data) 12967c478bd9Sstevel@tonic-gate { 12977c478bd9Sstevel@tonic-gate off_t offset = data->cd_offset; 12987c478bd9Sstevel@tonic-gate size_t length = data->cd_length; 12997c478bd9Sstevel@tonic-gate uint_t vec_idx; 13007c478bd9Sstevel@tonic-gate size_t cur_len; 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate /* we support only kernel buffer */ 13037c478bd9Sstevel@tonic-gate if (data->cd_uio->uio_segflg != UIO_SYSSPACE) 13047c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate /* 13077c478bd9Sstevel@tonic-gate * Jump to the first iovec containing data to be 13087c478bd9Sstevel@tonic-gate * digested. 13097c478bd9Sstevel@tonic-gate */ 13107c478bd9Sstevel@tonic-gate for (vec_idx = 0; vec_idx < data->cd_uio->uio_iovcnt && 13117c478bd9Sstevel@tonic-gate offset >= data->cd_uio->uio_iov[vec_idx].iov_len; 13127c478bd9Sstevel@tonic-gate offset -= data->cd_uio->uio_iov[vec_idx++].iov_len); 13137c478bd9Sstevel@tonic-gate if (vec_idx == data->cd_uio->uio_iovcnt) { 13147c478bd9Sstevel@tonic-gate /* 13157c478bd9Sstevel@tonic-gate * The caller specified an offset that is larger than the 13167c478bd9Sstevel@tonic-gate * total size of the buffers it provided. 13177c478bd9Sstevel@tonic-gate */ 13187c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate /* 13227c478bd9Sstevel@tonic-gate * Now do the digesting on the iovecs. 13237c478bd9Sstevel@tonic-gate */ 13247c478bd9Sstevel@tonic-gate while (vec_idx < data->cd_uio->uio_iovcnt && length > 0) { 13257c478bd9Sstevel@tonic-gate cur_len = MIN(data->cd_uio->uio_iov[vec_idx].iov_len - 13267c478bd9Sstevel@tonic-gate offset, length); 13277c478bd9Sstevel@tonic-gate 13287c478bd9Sstevel@tonic-gate SHA1Update(sha1_ctx, 13297c478bd9Sstevel@tonic-gate (uint8_t *)data->cd_uio->uio_iov[vec_idx].iov_base + offset, 13307c478bd9Sstevel@tonic-gate cur_len); 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate length -= cur_len; 13337c478bd9Sstevel@tonic-gate vec_idx++; 13347c478bd9Sstevel@tonic-gate offset = 0; 13357c478bd9Sstevel@tonic-gate } 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate if (vec_idx == data->cd_uio->uio_iovcnt && length > 0) { 13387c478bd9Sstevel@tonic-gate /* 13397c478bd9Sstevel@tonic-gate * The end of the specified iovec's was reached but 13407c478bd9Sstevel@tonic-gate * the length requested could not be processed, i.e. 13417c478bd9Sstevel@tonic-gate * The caller requested to digest more data than it provided. 13427c478bd9Sstevel@tonic-gate */ 13437c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 13447c478bd9Sstevel@tonic-gate } 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 13477c478bd9Sstevel@tonic-gate } 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate /* 13507c478bd9Sstevel@tonic-gate * Helper SHA1 digest final function for uio data. 13517c478bd9Sstevel@tonic-gate * digest_len is the length of the desired digest. If digest_len 13527c478bd9Sstevel@tonic-gate * is smaller than the default SHA1 digest length, the caller 13537c478bd9Sstevel@tonic-gate * must pass a scratch buffer, digest_scratch, which must 13547c478bd9Sstevel@tonic-gate * be at least SHA1_DIGEST_LENGTH bytes. 13557c478bd9Sstevel@tonic-gate */ 13567c478bd9Sstevel@tonic-gate static int 13577c478bd9Sstevel@tonic-gate sha1_digest_final_uio(SHA1_CTX *sha1_ctx, crypto_data_t *digest, 13587c478bd9Sstevel@tonic-gate ulong_t digest_len, uchar_t *digest_scratch) 13597c478bd9Sstevel@tonic-gate { 13607c478bd9Sstevel@tonic-gate off_t offset = digest->cd_offset; 13617c478bd9Sstevel@tonic-gate uint_t vec_idx; 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate /* we support only kernel buffer */ 13647c478bd9Sstevel@tonic-gate if (digest->cd_uio->uio_segflg != UIO_SYSSPACE) 13657c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate /* 13687c478bd9Sstevel@tonic-gate * Jump to the first iovec containing ptr to the digest to 13697c478bd9Sstevel@tonic-gate * be returned. 13707c478bd9Sstevel@tonic-gate */ 13717c478bd9Sstevel@tonic-gate for (vec_idx = 0; offset >= digest->cd_uio->uio_iov[vec_idx].iov_len && 13727c478bd9Sstevel@tonic-gate vec_idx < digest->cd_uio->uio_iovcnt; 13737c478bd9Sstevel@tonic-gate offset -= digest->cd_uio->uio_iov[vec_idx++].iov_len); 13747c478bd9Sstevel@tonic-gate if (vec_idx == digest->cd_uio->uio_iovcnt) { 13757c478bd9Sstevel@tonic-gate /* 13767c478bd9Sstevel@tonic-gate * The caller specified an offset that is 13777c478bd9Sstevel@tonic-gate * larger than the total size of the buffers 13787c478bd9Sstevel@tonic-gate * it provided. 13797c478bd9Sstevel@tonic-gate */ 13807c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate if (offset + digest_len <= 13847c478bd9Sstevel@tonic-gate digest->cd_uio->uio_iov[vec_idx].iov_len) { 13857c478bd9Sstevel@tonic-gate /* 13867c478bd9Sstevel@tonic-gate * The computed SHA1 digest will fit in the current 13877c478bd9Sstevel@tonic-gate * iovec. 13887c478bd9Sstevel@tonic-gate */ 13897c478bd9Sstevel@tonic-gate if (digest_len != SHA1_DIGEST_LENGTH) { 13907c478bd9Sstevel@tonic-gate /* 13917c478bd9Sstevel@tonic-gate * The caller requested a short digest. Digest 13927c478bd9Sstevel@tonic-gate * into a scratch buffer and return to 13937c478bd9Sstevel@tonic-gate * the user only what was requested. 13947c478bd9Sstevel@tonic-gate */ 13957c478bd9Sstevel@tonic-gate SHA1Final(digest_scratch, sha1_ctx); 13967c478bd9Sstevel@tonic-gate bcopy(digest_scratch, (uchar_t *)digest-> 13977c478bd9Sstevel@tonic-gate cd_uio->uio_iov[vec_idx].iov_base + offset, 13987c478bd9Sstevel@tonic-gate digest_len); 13997c478bd9Sstevel@tonic-gate } else { 14007c478bd9Sstevel@tonic-gate SHA1Final((uchar_t *)digest-> 14017c478bd9Sstevel@tonic-gate cd_uio->uio_iov[vec_idx].iov_base + offset, 14027c478bd9Sstevel@tonic-gate sha1_ctx); 14037c478bd9Sstevel@tonic-gate } 14047c478bd9Sstevel@tonic-gate } else { 14057c478bd9Sstevel@tonic-gate /* 14067c478bd9Sstevel@tonic-gate * The computed digest will be crossing one or more iovec's. 14077c478bd9Sstevel@tonic-gate * This is bad performance-wise but we need to support it. 14087c478bd9Sstevel@tonic-gate * Allocate a small scratch buffer on the stack and 14097c478bd9Sstevel@tonic-gate * copy it piece meal to the specified digest iovec's. 14107c478bd9Sstevel@tonic-gate */ 14117c478bd9Sstevel@tonic-gate uchar_t digest_tmp[SHA1_DIGEST_LENGTH]; 14127c478bd9Sstevel@tonic-gate off_t scratch_offset = 0; 14137c478bd9Sstevel@tonic-gate size_t length = digest_len; 14147c478bd9Sstevel@tonic-gate size_t cur_len; 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate SHA1Final(digest_tmp, sha1_ctx); 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate while (vec_idx < digest->cd_uio->uio_iovcnt && length > 0) { 14197c478bd9Sstevel@tonic-gate cur_len = MIN(digest->cd_uio->uio_iov[vec_idx].iov_len - 14207c478bd9Sstevel@tonic-gate offset, length); 14217c478bd9Sstevel@tonic-gate bcopy(digest_tmp + scratch_offset, 14227c478bd9Sstevel@tonic-gate digest->cd_uio->uio_iov[vec_idx].iov_base + offset, 14237c478bd9Sstevel@tonic-gate cur_len); 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate length -= cur_len; 14267c478bd9Sstevel@tonic-gate vec_idx++; 14277c478bd9Sstevel@tonic-gate scratch_offset += cur_len; 14287c478bd9Sstevel@tonic-gate offset = 0; 14297c478bd9Sstevel@tonic-gate } 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate if (vec_idx == digest->cd_uio->uio_iovcnt && length > 0) { 14327c478bd9Sstevel@tonic-gate /* 14337c478bd9Sstevel@tonic-gate * The end of the specified iovec's was reached but 14347c478bd9Sstevel@tonic-gate * the length requested could not be processed, i.e. 14357c478bd9Sstevel@tonic-gate * The caller requested to digest more data than it 14367c478bd9Sstevel@tonic-gate * provided. 14377c478bd9Sstevel@tonic-gate */ 14387c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 14397c478bd9Sstevel@tonic-gate } 14407c478bd9Sstevel@tonic-gate } 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 14437c478bd9Sstevel@tonic-gate } 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate /* 14467c478bd9Sstevel@tonic-gate * Helper SHA1 digest update for mblk's. 14477c478bd9Sstevel@tonic-gate */ 14487c478bd9Sstevel@tonic-gate static int 14497c478bd9Sstevel@tonic-gate sha1_digest_update_mblk(SHA1_CTX *sha1_ctx, crypto_data_t *data) 14507c478bd9Sstevel@tonic-gate { 14517c478bd9Sstevel@tonic-gate off_t offset = data->cd_offset; 14527c478bd9Sstevel@tonic-gate size_t length = data->cd_length; 14537c478bd9Sstevel@tonic-gate mblk_t *mp; 14547c478bd9Sstevel@tonic-gate size_t cur_len; 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate /* 14577c478bd9Sstevel@tonic-gate * Jump to the first mblk_t containing data to be digested. 14587c478bd9Sstevel@tonic-gate */ 14597c478bd9Sstevel@tonic-gate for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp); 14607c478bd9Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 14617c478bd9Sstevel@tonic-gate if (mp == NULL) { 14627c478bd9Sstevel@tonic-gate /* 14637c478bd9Sstevel@tonic-gate * The caller specified an offset that is larger than the 14647c478bd9Sstevel@tonic-gate * total size of the buffers it provided. 14657c478bd9Sstevel@tonic-gate */ 14667c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate /* 14707c478bd9Sstevel@tonic-gate * Now do the digesting on the mblk chain. 14717c478bd9Sstevel@tonic-gate */ 14727c478bd9Sstevel@tonic-gate while (mp != NULL && length > 0) { 14737c478bd9Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 14747c478bd9Sstevel@tonic-gate SHA1Update(sha1_ctx, mp->b_rptr + offset, cur_len); 14757c478bd9Sstevel@tonic-gate length -= cur_len; 14767c478bd9Sstevel@tonic-gate offset = 0; 14777c478bd9Sstevel@tonic-gate mp = mp->b_cont; 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate if (mp == NULL && length > 0) { 14817c478bd9Sstevel@tonic-gate /* 14827c478bd9Sstevel@tonic-gate * The end of the mblk was reached but the length requested 14837c478bd9Sstevel@tonic-gate * could not be processed, i.e. The caller requested 14847c478bd9Sstevel@tonic-gate * to digest more data than it provided. 14857c478bd9Sstevel@tonic-gate */ 14867c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 14877c478bd9Sstevel@tonic-gate } 14887c478bd9Sstevel@tonic-gate 14897c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 14907c478bd9Sstevel@tonic-gate } 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate /* 14937c478bd9Sstevel@tonic-gate * Helper SHA1 digest final for mblk's. 14947c478bd9Sstevel@tonic-gate * digest_len is the length of the desired digest. If digest_len 14957c478bd9Sstevel@tonic-gate * is smaller than the default SHA1 digest length, the caller 14967c478bd9Sstevel@tonic-gate * must pass a scratch buffer, digest_scratch, which must 14977c478bd9Sstevel@tonic-gate * be at least SHA1_DIGEST_LENGTH bytes. 14987c478bd9Sstevel@tonic-gate */ 14997c478bd9Sstevel@tonic-gate static int 15007c478bd9Sstevel@tonic-gate sha1_digest_final_mblk(SHA1_CTX *sha1_ctx, crypto_data_t *digest, 15017c478bd9Sstevel@tonic-gate ulong_t digest_len, uchar_t *digest_scratch) 15027c478bd9Sstevel@tonic-gate { 15037c478bd9Sstevel@tonic-gate off_t offset = digest->cd_offset; 15047c478bd9Sstevel@tonic-gate mblk_t *mp; 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate /* 15077c478bd9Sstevel@tonic-gate * Jump to the first mblk_t that will be used to store the digest. 15087c478bd9Sstevel@tonic-gate */ 15097c478bd9Sstevel@tonic-gate for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp); 15107c478bd9Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 15117c478bd9Sstevel@tonic-gate if (mp == NULL) { 15127c478bd9Sstevel@tonic-gate /* 15137c478bd9Sstevel@tonic-gate * The caller specified an offset that is larger than the 15147c478bd9Sstevel@tonic-gate * total size of the buffers it provided. 15157c478bd9Sstevel@tonic-gate */ 15167c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 15177c478bd9Sstevel@tonic-gate } 15187c478bd9Sstevel@tonic-gate 15197c478bd9Sstevel@tonic-gate if (offset + digest_len <= MBLKL(mp)) { 15207c478bd9Sstevel@tonic-gate /* 15217c478bd9Sstevel@tonic-gate * The computed SHA1 digest will fit in the current mblk. 15227c478bd9Sstevel@tonic-gate * Do the SHA1Final() in-place. 15237c478bd9Sstevel@tonic-gate */ 15247c478bd9Sstevel@tonic-gate if (digest_len != SHA1_DIGEST_LENGTH) { 15257c478bd9Sstevel@tonic-gate /* 15267c478bd9Sstevel@tonic-gate * The caller requested a short digest. Digest 15277c478bd9Sstevel@tonic-gate * into a scratch buffer and return to 15287c478bd9Sstevel@tonic-gate * the user only what was requested. 15297c478bd9Sstevel@tonic-gate */ 15307c478bd9Sstevel@tonic-gate SHA1Final(digest_scratch, sha1_ctx); 15317c478bd9Sstevel@tonic-gate bcopy(digest_scratch, mp->b_rptr + offset, digest_len); 15327c478bd9Sstevel@tonic-gate } else { 15337c478bd9Sstevel@tonic-gate SHA1Final(mp->b_rptr + offset, sha1_ctx); 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate } else { 15367c478bd9Sstevel@tonic-gate /* 15377c478bd9Sstevel@tonic-gate * The computed digest will be crossing one or more mblk's. 15387c478bd9Sstevel@tonic-gate * This is bad performance-wise but we need to support it. 15397c478bd9Sstevel@tonic-gate * Allocate a small scratch buffer on the stack and 15407c478bd9Sstevel@tonic-gate * copy it piece meal to the specified digest iovec's. 15417c478bd9Sstevel@tonic-gate */ 15427c478bd9Sstevel@tonic-gate uchar_t digest_tmp[SHA1_DIGEST_LENGTH]; 15437c478bd9Sstevel@tonic-gate off_t scratch_offset = 0; 15447c478bd9Sstevel@tonic-gate size_t length = digest_len; 15457c478bd9Sstevel@tonic-gate size_t cur_len; 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate SHA1Final(digest_tmp, sha1_ctx); 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate while (mp != NULL && length > 0) { 15507c478bd9Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 15517c478bd9Sstevel@tonic-gate bcopy(digest_tmp + scratch_offset, 15527c478bd9Sstevel@tonic-gate mp->b_rptr + offset, cur_len); 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate length -= cur_len; 15557c478bd9Sstevel@tonic-gate mp = mp->b_cont; 15567c478bd9Sstevel@tonic-gate scratch_offset += cur_len; 15577c478bd9Sstevel@tonic-gate offset = 0; 15587c478bd9Sstevel@tonic-gate } 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate if (mp == NULL && length > 0) { 15617c478bd9Sstevel@tonic-gate /* 15627c478bd9Sstevel@tonic-gate * The end of the specified mblk was reached but 15637c478bd9Sstevel@tonic-gate * the length requested could not be processed, i.e. 15647c478bd9Sstevel@tonic-gate * The caller requested to digest more data than it 15657c478bd9Sstevel@tonic-gate * provided. 15667c478bd9Sstevel@tonic-gate */ 15677c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 15687c478bd9Sstevel@tonic-gate } 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 15727c478bd9Sstevel@tonic-gate } 15737c478bd9Sstevel@tonic-gate 15747c478bd9Sstevel@tonic-gate /* ARGSUSED */ 15757c478bd9Sstevel@tonic-gate static int 15767c478bd9Sstevel@tonic-gate sha1_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest, 15777c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 15787c478bd9Sstevel@tonic-gate { 15797c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 15807c478bd9Sstevel@tonic-gate 15817c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 15827c478bd9Sstevel@tonic-gate 15837c478bd9Sstevel@tonic-gate /* 15847c478bd9Sstevel@tonic-gate * We need to just return the length needed to store the output. 15857c478bd9Sstevel@tonic-gate * We should not destroy the context for the following cases. 15867c478bd9Sstevel@tonic-gate */ 15877c478bd9Sstevel@tonic-gate if ((digest->cd_length == 0) || 15887c478bd9Sstevel@tonic-gate (digest->cd_length < SHA1_DIGEST_LENGTH)) { 15897c478bd9Sstevel@tonic-gate digest->cd_length = SHA1_DIGEST_LENGTH; 15907c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 15917c478bd9Sstevel@tonic-gate } 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate /* 15947c478bd9Sstevel@tonic-gate * Do the SHA1 update on the specified input data. 15957c478bd9Sstevel@tonic-gate */ 15967c478bd9Sstevel@tonic-gate switch (data->cd_format) { 15977c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 15987c478bd9Sstevel@tonic-gate SHA1Update(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 15997c478bd9Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 16007c478bd9Sstevel@tonic-gate data->cd_length); 16017c478bd9Sstevel@tonic-gate break; 16027c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 16037c478bd9Sstevel@tonic-gate ret = sha1_digest_update_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 16047c478bd9Sstevel@tonic-gate data); 16057c478bd9Sstevel@tonic-gate break; 16067c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 16077c478bd9Sstevel@tonic-gate ret = sha1_digest_update_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 16087c478bd9Sstevel@tonic-gate data); 16097c478bd9Sstevel@tonic-gate break; 16107c478bd9Sstevel@tonic-gate default: 16117c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 16127c478bd9Sstevel@tonic-gate } 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 16157c478bd9Sstevel@tonic-gate /* the update failed, free context and bail */ 16167c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t)); 16177c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 16187c478bd9Sstevel@tonic-gate digest->cd_length = 0; 16197c478bd9Sstevel@tonic-gate return (ret); 16207c478bd9Sstevel@tonic-gate } 16217c478bd9Sstevel@tonic-gate 16227c478bd9Sstevel@tonic-gate /* 16237c478bd9Sstevel@tonic-gate * Do a SHA1 final, must be done separately since the digest 16247c478bd9Sstevel@tonic-gate * type can be different than the input data type. 16257c478bd9Sstevel@tonic-gate */ 16267c478bd9Sstevel@tonic-gate switch (digest->cd_format) { 16277c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 16287c478bd9Sstevel@tonic-gate SHA1Final((unsigned char *)digest->cd_raw.iov_base + 16297c478bd9Sstevel@tonic-gate digest->cd_offset, &PROV_SHA1_CTX(ctx)->sc_sha1_ctx); 16307c478bd9Sstevel@tonic-gate break; 16317c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 16327c478bd9Sstevel@tonic-gate ret = sha1_digest_final_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 16337c478bd9Sstevel@tonic-gate digest, SHA1_DIGEST_LENGTH, NULL); 16347c478bd9Sstevel@tonic-gate break; 16357c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 16367c478bd9Sstevel@tonic-gate ret = sha1_digest_final_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 16377c478bd9Sstevel@tonic-gate digest, SHA1_DIGEST_LENGTH, NULL); 16387c478bd9Sstevel@tonic-gate break; 16397c478bd9Sstevel@tonic-gate default: 16407c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 16417c478bd9Sstevel@tonic-gate } 16427c478bd9Sstevel@tonic-gate 16437c478bd9Sstevel@tonic-gate /* all done, free context and return */ 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 16467c478bd9Sstevel@tonic-gate digest->cd_length = SHA1_DIGEST_LENGTH; 16477c478bd9Sstevel@tonic-gate } else { 16487c478bd9Sstevel@tonic-gate digest->cd_length = 0; 16497c478bd9Sstevel@tonic-gate } 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t)); 16527c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 16537c478bd9Sstevel@tonic-gate return (ret); 16547c478bd9Sstevel@tonic-gate } 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16577c478bd9Sstevel@tonic-gate static int 16587c478bd9Sstevel@tonic-gate sha1_digest_update(crypto_ctx_t *ctx, crypto_data_t *data, 16597c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 16607c478bd9Sstevel@tonic-gate { 16617c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 16627c478bd9Sstevel@tonic-gate 16637c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate /* 16667c478bd9Sstevel@tonic-gate * Do the SHA1 update on the specified input data. 16677c478bd9Sstevel@tonic-gate */ 16687c478bd9Sstevel@tonic-gate switch (data->cd_format) { 16697c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 16707c478bd9Sstevel@tonic-gate SHA1Update(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 16717c478bd9Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 16727c478bd9Sstevel@tonic-gate data->cd_length); 16737c478bd9Sstevel@tonic-gate break; 16747c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 16757c478bd9Sstevel@tonic-gate ret = sha1_digest_update_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 16767c478bd9Sstevel@tonic-gate data); 16777c478bd9Sstevel@tonic-gate break; 16787c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 16797c478bd9Sstevel@tonic-gate ret = sha1_digest_update_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 16807c478bd9Sstevel@tonic-gate data); 16817c478bd9Sstevel@tonic-gate break; 16827c478bd9Sstevel@tonic-gate default: 16837c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 16847c478bd9Sstevel@tonic-gate } 16857c478bd9Sstevel@tonic-gate 16867c478bd9Sstevel@tonic-gate return (ret); 16877c478bd9Sstevel@tonic-gate } 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16907c478bd9Sstevel@tonic-gate static int 16917c478bd9Sstevel@tonic-gate sha1_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest, 16927c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 16937c478bd9Sstevel@tonic-gate { 16947c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate /* 16997c478bd9Sstevel@tonic-gate * We need to just return the length needed to store the output. 17007c478bd9Sstevel@tonic-gate * We should not destroy the context for the following cases. 17017c478bd9Sstevel@tonic-gate */ 17027c478bd9Sstevel@tonic-gate if ((digest->cd_length == 0) || 17037c478bd9Sstevel@tonic-gate (digest->cd_length < SHA1_DIGEST_LENGTH)) { 17047c478bd9Sstevel@tonic-gate digest->cd_length = SHA1_DIGEST_LENGTH; 17057c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 17067c478bd9Sstevel@tonic-gate } 17077c478bd9Sstevel@tonic-gate 17087c478bd9Sstevel@tonic-gate /* 17097c478bd9Sstevel@tonic-gate * Do a SHA1 final. 17107c478bd9Sstevel@tonic-gate */ 17117c478bd9Sstevel@tonic-gate switch (digest->cd_format) { 17127c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 17137c478bd9Sstevel@tonic-gate SHA1Final((unsigned char *)digest->cd_raw.iov_base + 17147c478bd9Sstevel@tonic-gate digest->cd_offset, &PROV_SHA1_CTX(ctx)->sc_sha1_ctx); 17157c478bd9Sstevel@tonic-gate break; 17167c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 17177c478bd9Sstevel@tonic-gate ret = sha1_digest_final_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 17187c478bd9Sstevel@tonic-gate digest, SHA1_DIGEST_LENGTH, NULL); 17197c478bd9Sstevel@tonic-gate break; 17207c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 17217c478bd9Sstevel@tonic-gate ret = sha1_digest_final_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 17227c478bd9Sstevel@tonic-gate digest, SHA1_DIGEST_LENGTH, NULL); 17237c478bd9Sstevel@tonic-gate break; 17247c478bd9Sstevel@tonic-gate default: 17257c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 17267c478bd9Sstevel@tonic-gate } 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate /* all done, free context and return */ 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 17317c478bd9Sstevel@tonic-gate digest->cd_length = SHA1_DIGEST_LENGTH; 17327c478bd9Sstevel@tonic-gate } else { 17337c478bd9Sstevel@tonic-gate digest->cd_length = 0; 17347c478bd9Sstevel@tonic-gate } 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t)); 17377c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate return (ret); 17407c478bd9Sstevel@tonic-gate } 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate /* ARGSUSED */ 17437c478bd9Sstevel@tonic-gate static int 17447c478bd9Sstevel@tonic-gate sha1_digest_atomic(crypto_provider_handle_t provider, 17457c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 17467c478bd9Sstevel@tonic-gate crypto_data_t *data, crypto_data_t *digest, 17477c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 17487c478bd9Sstevel@tonic-gate { 17497c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 17507c478bd9Sstevel@tonic-gate SHA1_CTX sha1_ctx; 17517c478bd9Sstevel@tonic-gate 17527c478bd9Sstevel@tonic-gate if (mechanism->cm_type != SHA1_MECH_INFO_TYPE) 17537c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 17547c478bd9Sstevel@tonic-gate 17557c478bd9Sstevel@tonic-gate /* 17567c478bd9Sstevel@tonic-gate * Do the SHA1 init. 17577c478bd9Sstevel@tonic-gate */ 17587c478bd9Sstevel@tonic-gate SHA1Init(&sha1_ctx); 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate /* 17617c478bd9Sstevel@tonic-gate * Do the SHA1 update on the specified input data. 17627c478bd9Sstevel@tonic-gate */ 17637c478bd9Sstevel@tonic-gate switch (data->cd_format) { 17647c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 17657c478bd9Sstevel@tonic-gate SHA1Update(&sha1_ctx, 17667c478bd9Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 17677c478bd9Sstevel@tonic-gate data->cd_length); 17687c478bd9Sstevel@tonic-gate break; 17697c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 17707c478bd9Sstevel@tonic-gate ret = sha1_digest_update_uio(&sha1_ctx, data); 17717c478bd9Sstevel@tonic-gate break; 17727c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 17737c478bd9Sstevel@tonic-gate ret = sha1_digest_update_mblk(&sha1_ctx, data); 17747c478bd9Sstevel@tonic-gate break; 17757c478bd9Sstevel@tonic-gate default: 17767c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 17777c478bd9Sstevel@tonic-gate } 17787c478bd9Sstevel@tonic-gate 17797c478bd9Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 17807c478bd9Sstevel@tonic-gate /* the update failed, bail */ 17817c478bd9Sstevel@tonic-gate digest->cd_length = 0; 17827c478bd9Sstevel@tonic-gate return (ret); 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate 17857c478bd9Sstevel@tonic-gate /* 17867c478bd9Sstevel@tonic-gate * Do a SHA1 final, must be done separately since the digest 17877c478bd9Sstevel@tonic-gate * type can be different than the input data type. 17887c478bd9Sstevel@tonic-gate */ 17897c478bd9Sstevel@tonic-gate switch (digest->cd_format) { 17907c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 17917c478bd9Sstevel@tonic-gate SHA1Final((unsigned char *)digest->cd_raw.iov_base + 17927c478bd9Sstevel@tonic-gate digest->cd_offset, &sha1_ctx); 17937c478bd9Sstevel@tonic-gate break; 17947c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 17957c478bd9Sstevel@tonic-gate ret = sha1_digest_final_uio(&sha1_ctx, digest, 17967c478bd9Sstevel@tonic-gate SHA1_DIGEST_LENGTH, NULL); 17977c478bd9Sstevel@tonic-gate break; 17987c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 17997c478bd9Sstevel@tonic-gate ret = sha1_digest_final_mblk(&sha1_ctx, digest, 18007c478bd9Sstevel@tonic-gate SHA1_DIGEST_LENGTH, NULL); 18017c478bd9Sstevel@tonic-gate break; 18027c478bd9Sstevel@tonic-gate default: 18037c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 18047c478bd9Sstevel@tonic-gate } 18057c478bd9Sstevel@tonic-gate 18067c478bd9Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 18077c478bd9Sstevel@tonic-gate digest->cd_length = SHA1_DIGEST_LENGTH; 18087c478bd9Sstevel@tonic-gate } else { 18097c478bd9Sstevel@tonic-gate digest->cd_length = 0; 18107c478bd9Sstevel@tonic-gate } 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate return (ret); 18137c478bd9Sstevel@tonic-gate } 18147c478bd9Sstevel@tonic-gate 18157c478bd9Sstevel@tonic-gate /* 18167c478bd9Sstevel@tonic-gate * KCF software provider mac entry points. 18177c478bd9Sstevel@tonic-gate * 18187c478bd9Sstevel@tonic-gate * SHA1 HMAC is: SHA1(key XOR opad, SHA1(key XOR ipad, text)) 18197c478bd9Sstevel@tonic-gate * 18207c478bd9Sstevel@tonic-gate * Init: 18217c478bd9Sstevel@tonic-gate * The initialization routine initializes what we denote 18227c478bd9Sstevel@tonic-gate * as the inner and outer contexts by doing 18237c478bd9Sstevel@tonic-gate * - for inner context: SHA1(key XOR ipad) 18247c478bd9Sstevel@tonic-gate * - for outer context: SHA1(key XOR opad) 18257c478bd9Sstevel@tonic-gate * 18267c478bd9Sstevel@tonic-gate * Update: 18277c478bd9Sstevel@tonic-gate * Each subsequent SHA1 HMAC update will result in an 18287c478bd9Sstevel@tonic-gate * update of the inner context with the specified data. 18297c478bd9Sstevel@tonic-gate * 18307c478bd9Sstevel@tonic-gate * Final: 18317c478bd9Sstevel@tonic-gate * The SHA1 HMAC final will do a SHA1 final operation on the 18327c478bd9Sstevel@tonic-gate * inner context, and the resulting digest will be used 18337c478bd9Sstevel@tonic-gate * as the data for an update on the outer context. Last 18347c478bd9Sstevel@tonic-gate * but not least, a SHA1 final on the outer context will 18357c478bd9Sstevel@tonic-gate * be performed to obtain the SHA1 HMAC digest to return 18367c478bd9Sstevel@tonic-gate * to the user. 18377c478bd9Sstevel@tonic-gate */ 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate /* 18407c478bd9Sstevel@tonic-gate * Initialize a SHA1-HMAC context. 18417c478bd9Sstevel@tonic-gate */ 18427c478bd9Sstevel@tonic-gate static void 18437c478bd9Sstevel@tonic-gate sha1_mac_init_ctx(sha1_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes) 18447c478bd9Sstevel@tonic-gate { 18457c478bd9Sstevel@tonic-gate uint32_t ipad[SHA1_HMAC_INTS_PER_BLOCK]; 18467c478bd9Sstevel@tonic-gate uint32_t opad[SHA1_HMAC_INTS_PER_BLOCK]; 18477c478bd9Sstevel@tonic-gate uint_t i; 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate bzero(ipad, SHA1_HMAC_BLOCK_SIZE); 18507c478bd9Sstevel@tonic-gate bzero(opad, SHA1_HMAC_BLOCK_SIZE); 18517c478bd9Sstevel@tonic-gate 18527c478bd9Sstevel@tonic-gate bcopy(keyval, ipad, length_in_bytes); 18537c478bd9Sstevel@tonic-gate bcopy(keyval, opad, length_in_bytes); 18547c478bd9Sstevel@tonic-gate 18557c478bd9Sstevel@tonic-gate /* XOR key with ipad (0x36) and opad (0x5c) */ 18567c478bd9Sstevel@tonic-gate for (i = 0; i < SHA1_HMAC_INTS_PER_BLOCK; i++) { 18577c478bd9Sstevel@tonic-gate ipad[i] ^= 0x36363636; 18587c478bd9Sstevel@tonic-gate opad[i] ^= 0x5c5c5c5c; 18597c478bd9Sstevel@tonic-gate } 18607c478bd9Sstevel@tonic-gate 18617c478bd9Sstevel@tonic-gate /* perform SHA1 on ipad */ 18627c478bd9Sstevel@tonic-gate SHA1Init(&ctx->hc_icontext); 18637c478bd9Sstevel@tonic-gate SHA1Update(&ctx->hc_icontext, (uint8_t *)ipad, SHA1_HMAC_BLOCK_SIZE); 18647c478bd9Sstevel@tonic-gate 18657c478bd9Sstevel@tonic-gate /* perform SHA1 on opad */ 18667c478bd9Sstevel@tonic-gate SHA1Init(&ctx->hc_ocontext); 18677c478bd9Sstevel@tonic-gate SHA1Update(&ctx->hc_ocontext, (uint8_t *)opad, SHA1_HMAC_BLOCK_SIZE); 18687c478bd9Sstevel@tonic-gate } 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate /* 18717c478bd9Sstevel@tonic-gate */ 18727c478bd9Sstevel@tonic-gate static int 18737c478bd9Sstevel@tonic-gate sha1_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 18747c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, 18757c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 18767c478bd9Sstevel@tonic-gate { 18777c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 18787c478bd9Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE && 18817c478bd9Sstevel@tonic-gate mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE) 18827c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 18857c478bd9Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 18867c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 18877c478bd9Sstevel@tonic-gate 18887c478bd9Sstevel@tonic-gate ctx->cc_provider_private = kmem_alloc(sizeof (sha1_hmac_ctx_t), 18897c478bd9Sstevel@tonic-gate crypto_kmflag(req)); 18907c478bd9Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 18917c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate if (ctx_template != NULL) { 18947c478bd9Sstevel@tonic-gate /* reuse context template */ 18957c478bd9Sstevel@tonic-gate bcopy(ctx_template, PROV_SHA1_HMAC_CTX(ctx), 18967c478bd9Sstevel@tonic-gate sizeof (sha1_hmac_ctx_t)); 18977c478bd9Sstevel@tonic-gate } else { 18987c478bd9Sstevel@tonic-gate /* no context template, compute context */ 18997c478bd9Sstevel@tonic-gate if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) { 19007c478bd9Sstevel@tonic-gate uchar_t digested_key[SHA1_DIGEST_LENGTH]; 19017c478bd9Sstevel@tonic-gate sha1_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private; 19027c478bd9Sstevel@tonic-gate 19037c478bd9Sstevel@tonic-gate /* 19047c478bd9Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 19057c478bd9Sstevel@tonic-gate * The inner context is used since it hasn't been 19067c478bd9Sstevel@tonic-gate * initialized yet. 19077c478bd9Sstevel@tonic-gate */ 19087c478bd9Sstevel@tonic-gate PROV_SHA1_DIGEST_KEY(&hmac_ctx->hc_icontext, 19097c478bd9Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digested_key); 19107c478bd9Sstevel@tonic-gate sha1_mac_init_ctx(PROV_SHA1_HMAC_CTX(ctx), 19117c478bd9Sstevel@tonic-gate digested_key, SHA1_DIGEST_LENGTH); 19127c478bd9Sstevel@tonic-gate } else { 19137c478bd9Sstevel@tonic-gate sha1_mac_init_ctx(PROV_SHA1_HMAC_CTX(ctx), 19147c478bd9Sstevel@tonic-gate key->ck_data, keylen_in_bytes); 19157c478bd9Sstevel@tonic-gate } 19167c478bd9Sstevel@tonic-gate } 19177c478bd9Sstevel@tonic-gate 19187c478bd9Sstevel@tonic-gate /* 19197c478bd9Sstevel@tonic-gate * Get the mechanism parameters, if applicable. 19207c478bd9Sstevel@tonic-gate */ 19217c478bd9Sstevel@tonic-gate PROV_SHA1_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type; 19227c478bd9Sstevel@tonic-gate if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) { 19237c478bd9Sstevel@tonic-gate if (mechanism->cm_param == NULL || 19247c478bd9Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) 19257c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 19267c478bd9Sstevel@tonic-gate PROV_SHA1_GET_DIGEST_LEN(mechanism, 19277c478bd9Sstevel@tonic-gate PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len); 19287c478bd9Sstevel@tonic-gate if (PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len > 19297c478bd9Sstevel@tonic-gate SHA1_DIGEST_LENGTH) 19307c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 19317c478bd9Sstevel@tonic-gate } 19327c478bd9Sstevel@tonic-gate 19337c478bd9Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 19347c478bd9Sstevel@tonic-gate bzero(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t)); 19357c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t)); 19367c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 19377c478bd9Sstevel@tonic-gate } 19387c478bd9Sstevel@tonic-gate 19397c478bd9Sstevel@tonic-gate return (ret); 19407c478bd9Sstevel@tonic-gate } 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate /* ARGSUSED */ 19437c478bd9Sstevel@tonic-gate static int 19447c478bd9Sstevel@tonic-gate sha1_mac_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req) 19457c478bd9Sstevel@tonic-gate { 19467c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 19497c478bd9Sstevel@tonic-gate 19507c478bd9Sstevel@tonic-gate /* 19517c478bd9Sstevel@tonic-gate * Do a SHA1 update of the inner context using the specified 19527c478bd9Sstevel@tonic-gate * data. 19537c478bd9Sstevel@tonic-gate */ 19547c478bd9Sstevel@tonic-gate switch (data->cd_format) { 19557c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 19567c478bd9Sstevel@tonic-gate SHA1Update(&PROV_SHA1_HMAC_CTX(ctx)->hc_icontext, 19577c478bd9Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 19587c478bd9Sstevel@tonic-gate data->cd_length); 19597c478bd9Sstevel@tonic-gate break; 19607c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 19617c478bd9Sstevel@tonic-gate ret = sha1_digest_update_uio( 19627c478bd9Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext, data); 19637c478bd9Sstevel@tonic-gate break; 19647c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 19657c478bd9Sstevel@tonic-gate ret = sha1_digest_update_mblk( 19667c478bd9Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext, data); 19677c478bd9Sstevel@tonic-gate break; 19687c478bd9Sstevel@tonic-gate default: 19697c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 19707c478bd9Sstevel@tonic-gate } 19717c478bd9Sstevel@tonic-gate 19727c478bd9Sstevel@tonic-gate return (ret); 19737c478bd9Sstevel@tonic-gate } 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate /* ARGSUSED */ 19767c478bd9Sstevel@tonic-gate static int 19777c478bd9Sstevel@tonic-gate sha1_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req) 19787c478bd9Sstevel@tonic-gate { 19797c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 19807c478bd9Sstevel@tonic-gate uchar_t digest[SHA1_DIGEST_LENGTH]; 19817c478bd9Sstevel@tonic-gate uint32_t digest_len = SHA1_DIGEST_LENGTH; 19827c478bd9Sstevel@tonic-gate 19837c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 19847c478bd9Sstevel@tonic-gate 19857c478bd9Sstevel@tonic-gate if (PROV_SHA1_HMAC_CTX(ctx)->hc_mech_type == 19867c478bd9Sstevel@tonic-gate SHA1_HMAC_GEN_MECH_INFO_TYPE) 19877c478bd9Sstevel@tonic-gate digest_len = PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len; 19887c478bd9Sstevel@tonic-gate 19897c478bd9Sstevel@tonic-gate /* 19907c478bd9Sstevel@tonic-gate * We need to just return the length needed to store the output. 19917c478bd9Sstevel@tonic-gate * We should not destroy the context for the following cases. 19927c478bd9Sstevel@tonic-gate */ 19937c478bd9Sstevel@tonic-gate if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) { 19947c478bd9Sstevel@tonic-gate mac->cd_length = digest_len; 19957c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 19967c478bd9Sstevel@tonic-gate } 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate /* 19997c478bd9Sstevel@tonic-gate * Do a SHA1 final on the inner context. 20007c478bd9Sstevel@tonic-gate */ 20017c478bd9Sstevel@tonic-gate SHA1Final(digest, &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext); 20027c478bd9Sstevel@tonic-gate 20037c478bd9Sstevel@tonic-gate /* 20047c478bd9Sstevel@tonic-gate * Do a SHA1 update on the outer context, feeding the inner 20057c478bd9Sstevel@tonic-gate * digest as data. 20067c478bd9Sstevel@tonic-gate */ 20077c478bd9Sstevel@tonic-gate SHA1Update(&PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, digest, 20087c478bd9Sstevel@tonic-gate SHA1_DIGEST_LENGTH); 20097c478bd9Sstevel@tonic-gate 20107c478bd9Sstevel@tonic-gate /* 20117c478bd9Sstevel@tonic-gate * Do a SHA1 final on the outer context, storing the computing 20127c478bd9Sstevel@tonic-gate * digest in the users buffer. 20137c478bd9Sstevel@tonic-gate */ 20147c478bd9Sstevel@tonic-gate switch (mac->cd_format) { 20157c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 20167c478bd9Sstevel@tonic-gate if (digest_len != SHA1_DIGEST_LENGTH) { 20177c478bd9Sstevel@tonic-gate /* 20187c478bd9Sstevel@tonic-gate * The caller requested a short digest. Digest 20197c478bd9Sstevel@tonic-gate * into a scratch buffer and return to 20207c478bd9Sstevel@tonic-gate * the user only what was requested. 20217c478bd9Sstevel@tonic-gate */ 20227c478bd9Sstevel@tonic-gate SHA1Final(digest, 20237c478bd9Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext); 20247c478bd9Sstevel@tonic-gate bcopy(digest, (unsigned char *)mac->cd_raw.iov_base + 20257c478bd9Sstevel@tonic-gate mac->cd_offset, digest_len); 20267c478bd9Sstevel@tonic-gate } else { 20277c478bd9Sstevel@tonic-gate SHA1Final((unsigned char *)mac->cd_raw.iov_base + 20287c478bd9Sstevel@tonic-gate mac->cd_offset, 20297c478bd9Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext); 20307c478bd9Sstevel@tonic-gate } 20317c478bd9Sstevel@tonic-gate break; 20327c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 20337c478bd9Sstevel@tonic-gate ret = sha1_digest_final_uio( 20347c478bd9Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, mac, 20357c478bd9Sstevel@tonic-gate digest_len, digest); 20367c478bd9Sstevel@tonic-gate break; 20377c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 20387c478bd9Sstevel@tonic-gate ret = sha1_digest_final_mblk( 20397c478bd9Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, mac, 20407c478bd9Sstevel@tonic-gate digest_len, digest); 20417c478bd9Sstevel@tonic-gate break; 20427c478bd9Sstevel@tonic-gate default: 20437c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 20447c478bd9Sstevel@tonic-gate } 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 20477c478bd9Sstevel@tonic-gate mac->cd_length = digest_len; 20487c478bd9Sstevel@tonic-gate } else { 20497c478bd9Sstevel@tonic-gate mac->cd_length = 0; 20507c478bd9Sstevel@tonic-gate } 20517c478bd9Sstevel@tonic-gate 20527c478bd9Sstevel@tonic-gate bzero(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t)); 20537c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t)); 20547c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 20557c478bd9Sstevel@tonic-gate 20567c478bd9Sstevel@tonic-gate return (ret); 20577c478bd9Sstevel@tonic-gate } 20587c478bd9Sstevel@tonic-gate 20597c478bd9Sstevel@tonic-gate #define SHA1_MAC_UPDATE(data, ctx, ret) { \ 20607c478bd9Sstevel@tonic-gate switch (data->cd_format) { \ 20617c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: \ 20627c478bd9Sstevel@tonic-gate SHA1Update(&(ctx).hc_icontext, \ 20637c478bd9Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + \ 20647c478bd9Sstevel@tonic-gate data->cd_offset, data->cd_length); \ 20657c478bd9Sstevel@tonic-gate break; \ 20667c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: \ 20677c478bd9Sstevel@tonic-gate ret = sha1_digest_update_uio(&(ctx).hc_icontext, data); \ 20687c478bd9Sstevel@tonic-gate break; \ 20697c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: \ 20707c478bd9Sstevel@tonic-gate ret = sha1_digest_update_mblk(&(ctx).hc_icontext, \ 20717c478bd9Sstevel@tonic-gate data); \ 20727c478bd9Sstevel@tonic-gate break; \ 20737c478bd9Sstevel@tonic-gate default: \ 20747c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; \ 20757c478bd9Sstevel@tonic-gate } \ 20767c478bd9Sstevel@tonic-gate } 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate /* ARGSUSED */ 20797c478bd9Sstevel@tonic-gate static int 20807c478bd9Sstevel@tonic-gate sha1_mac_atomic(crypto_provider_handle_t provider, 20817c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 20827c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 20837c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 20847c478bd9Sstevel@tonic-gate { 20857c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 20867c478bd9Sstevel@tonic-gate uchar_t digest[SHA1_DIGEST_LENGTH]; 20877c478bd9Sstevel@tonic-gate sha1_hmac_ctx_t sha1_hmac_ctx; 20887c478bd9Sstevel@tonic-gate uint32_t digest_len = SHA1_DIGEST_LENGTH; 20897c478bd9Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 20907c478bd9Sstevel@tonic-gate 20917c478bd9Sstevel@tonic-gate if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE && 20927c478bd9Sstevel@tonic-gate mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE) 20937c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 20947c478bd9Sstevel@tonic-gate 20957c478bd9Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 20967c478bd9Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 20977c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 20987c478bd9Sstevel@tonic-gate 20997c478bd9Sstevel@tonic-gate if (ctx_template != NULL) { 21007c478bd9Sstevel@tonic-gate /* reuse context template */ 21017c478bd9Sstevel@tonic-gate bcopy(ctx_template, &sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 21027c478bd9Sstevel@tonic-gate } else { 21037c478bd9Sstevel@tonic-gate /* no context template, initialize context */ 21047c478bd9Sstevel@tonic-gate if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) { 21057c478bd9Sstevel@tonic-gate /* 21067c478bd9Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 21077c478bd9Sstevel@tonic-gate * The inner context is used since it hasn't been 21087c478bd9Sstevel@tonic-gate * initialized yet. 21097c478bd9Sstevel@tonic-gate */ 21107c478bd9Sstevel@tonic-gate PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx.hc_icontext, 21117c478bd9Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digest); 21127c478bd9Sstevel@tonic-gate sha1_mac_init_ctx(&sha1_hmac_ctx, digest, 21137c478bd9Sstevel@tonic-gate SHA1_DIGEST_LENGTH); 21147c478bd9Sstevel@tonic-gate } else { 21157c478bd9Sstevel@tonic-gate sha1_mac_init_ctx(&sha1_hmac_ctx, key->ck_data, 21167c478bd9Sstevel@tonic-gate keylen_in_bytes); 21177c478bd9Sstevel@tonic-gate } 21187c478bd9Sstevel@tonic-gate } 21197c478bd9Sstevel@tonic-gate 21207c478bd9Sstevel@tonic-gate /* get the mechanism parameters, if applicable */ 21217c478bd9Sstevel@tonic-gate if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) { 21227c478bd9Sstevel@tonic-gate if (mechanism->cm_param == NULL || 21237c478bd9Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) { 21247c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 21257c478bd9Sstevel@tonic-gate goto bail; 21267c478bd9Sstevel@tonic-gate } 21277c478bd9Sstevel@tonic-gate PROV_SHA1_GET_DIGEST_LEN(mechanism, digest_len); 21287c478bd9Sstevel@tonic-gate if (digest_len > SHA1_DIGEST_LENGTH) { 21297c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 21307c478bd9Sstevel@tonic-gate goto bail; 21317c478bd9Sstevel@tonic-gate } 21327c478bd9Sstevel@tonic-gate } 21337c478bd9Sstevel@tonic-gate 21347c478bd9Sstevel@tonic-gate /* do a SHA1 update of the inner context using the specified data */ 21357c478bd9Sstevel@tonic-gate SHA1_MAC_UPDATE(data, sha1_hmac_ctx, ret); 21367c478bd9Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) 21377c478bd9Sstevel@tonic-gate /* the update failed, free context and bail */ 21387c478bd9Sstevel@tonic-gate goto bail; 21397c478bd9Sstevel@tonic-gate 21407c478bd9Sstevel@tonic-gate /* 21417c478bd9Sstevel@tonic-gate * Do a SHA1 final on the inner context. 21427c478bd9Sstevel@tonic-gate */ 21437c478bd9Sstevel@tonic-gate SHA1Final(digest, &sha1_hmac_ctx.hc_icontext); 21447c478bd9Sstevel@tonic-gate 21457c478bd9Sstevel@tonic-gate /* 21467c478bd9Sstevel@tonic-gate * Do an SHA1 update on the outer context, feeding the inner 21477c478bd9Sstevel@tonic-gate * digest as data. 21487c478bd9Sstevel@tonic-gate */ 21497c478bd9Sstevel@tonic-gate SHA1Update(&sha1_hmac_ctx.hc_ocontext, digest, SHA1_DIGEST_LENGTH); 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate /* 21527c478bd9Sstevel@tonic-gate * Do a SHA1 final on the outer context, storing the computed 21537c478bd9Sstevel@tonic-gate * digest in the users buffer. 21547c478bd9Sstevel@tonic-gate */ 21557c478bd9Sstevel@tonic-gate switch (mac->cd_format) { 21567c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 21577c478bd9Sstevel@tonic-gate if (digest_len != SHA1_DIGEST_LENGTH) { 21587c478bd9Sstevel@tonic-gate /* 21597c478bd9Sstevel@tonic-gate * The caller requested a short digest. Digest 21607c478bd9Sstevel@tonic-gate * into a scratch buffer and return to 21617c478bd9Sstevel@tonic-gate * the user only what was requested. 21627c478bd9Sstevel@tonic-gate */ 21637c478bd9Sstevel@tonic-gate SHA1Final(digest, &sha1_hmac_ctx.hc_ocontext); 21647c478bd9Sstevel@tonic-gate bcopy(digest, (unsigned char *)mac->cd_raw.iov_base + 21657c478bd9Sstevel@tonic-gate mac->cd_offset, digest_len); 21667c478bd9Sstevel@tonic-gate } else { 21677c478bd9Sstevel@tonic-gate SHA1Final((unsigned char *)mac->cd_raw.iov_base + 21687c478bd9Sstevel@tonic-gate mac->cd_offset, &sha1_hmac_ctx.hc_ocontext); 21697c478bd9Sstevel@tonic-gate } 21707c478bd9Sstevel@tonic-gate break; 21717c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 21727c478bd9Sstevel@tonic-gate ret = sha1_digest_final_uio(&sha1_hmac_ctx.hc_ocontext, mac, 21737c478bd9Sstevel@tonic-gate digest_len, digest); 21747c478bd9Sstevel@tonic-gate break; 21757c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 21767c478bd9Sstevel@tonic-gate ret = sha1_digest_final_mblk(&sha1_hmac_ctx.hc_ocontext, mac, 21777c478bd9Sstevel@tonic-gate digest_len, digest); 21787c478bd9Sstevel@tonic-gate break; 21797c478bd9Sstevel@tonic-gate default: 21807c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 21817c478bd9Sstevel@tonic-gate } 21827c478bd9Sstevel@tonic-gate 21837c478bd9Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 21847c478bd9Sstevel@tonic-gate mac->cd_length = digest_len; 21857c478bd9Sstevel@tonic-gate } else { 21867c478bd9Sstevel@tonic-gate mac->cd_length = 0; 21877c478bd9Sstevel@tonic-gate } 21887c478bd9Sstevel@tonic-gate /* Extra paranoia: zeroize the context on the stack */ 21897c478bd9Sstevel@tonic-gate bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 21907c478bd9Sstevel@tonic-gate 21917c478bd9Sstevel@tonic-gate return (ret); 21927c478bd9Sstevel@tonic-gate bail: 21937c478bd9Sstevel@tonic-gate bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 21947c478bd9Sstevel@tonic-gate mac->cd_length = 0; 21957c478bd9Sstevel@tonic-gate return (ret); 21967c478bd9Sstevel@tonic-gate } 21977c478bd9Sstevel@tonic-gate 21987c478bd9Sstevel@tonic-gate /* ARGSUSED */ 21997c478bd9Sstevel@tonic-gate static int 22007c478bd9Sstevel@tonic-gate sha1_mac_verify_atomic(crypto_provider_handle_t provider, 22017c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 22027c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 22037c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 22047c478bd9Sstevel@tonic-gate { 22057c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 22067c478bd9Sstevel@tonic-gate uchar_t digest[SHA1_DIGEST_LENGTH]; 22077c478bd9Sstevel@tonic-gate sha1_hmac_ctx_t sha1_hmac_ctx; 22087c478bd9Sstevel@tonic-gate uint32_t digest_len = SHA1_DIGEST_LENGTH; 22097c478bd9Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 22107c478bd9Sstevel@tonic-gate 22117c478bd9Sstevel@tonic-gate if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE && 22127c478bd9Sstevel@tonic-gate mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE) 22137c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 22147c478bd9Sstevel@tonic-gate 22157c478bd9Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 22167c478bd9Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 22177c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 22187c478bd9Sstevel@tonic-gate 22197c478bd9Sstevel@tonic-gate if (ctx_template != NULL) { 22207c478bd9Sstevel@tonic-gate /* reuse context template */ 22217c478bd9Sstevel@tonic-gate bcopy(ctx_template, &sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 22227c478bd9Sstevel@tonic-gate } else { 22237c478bd9Sstevel@tonic-gate /* no context template, initialize context */ 22247c478bd9Sstevel@tonic-gate if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) { 22257c478bd9Sstevel@tonic-gate /* 22267c478bd9Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 22277c478bd9Sstevel@tonic-gate * The inner context is used since it hasn't been 22287c478bd9Sstevel@tonic-gate * initialized yet. 22297c478bd9Sstevel@tonic-gate */ 22307c478bd9Sstevel@tonic-gate PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx.hc_icontext, 22317c478bd9Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digest); 22327c478bd9Sstevel@tonic-gate sha1_mac_init_ctx(&sha1_hmac_ctx, digest, 22337c478bd9Sstevel@tonic-gate SHA1_DIGEST_LENGTH); 22347c478bd9Sstevel@tonic-gate } else { 22357c478bd9Sstevel@tonic-gate sha1_mac_init_ctx(&sha1_hmac_ctx, key->ck_data, 22367c478bd9Sstevel@tonic-gate keylen_in_bytes); 22377c478bd9Sstevel@tonic-gate } 22387c478bd9Sstevel@tonic-gate } 22397c478bd9Sstevel@tonic-gate 22407c478bd9Sstevel@tonic-gate /* get the mechanism parameters, if applicable */ 22417c478bd9Sstevel@tonic-gate if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) { 22427c478bd9Sstevel@tonic-gate if (mechanism->cm_param == NULL || 22437c478bd9Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) { 22447c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 22457c478bd9Sstevel@tonic-gate goto bail; 22467c478bd9Sstevel@tonic-gate } 22477c478bd9Sstevel@tonic-gate PROV_SHA1_GET_DIGEST_LEN(mechanism, digest_len); 22487c478bd9Sstevel@tonic-gate if (digest_len > SHA1_DIGEST_LENGTH) { 22497c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 22507c478bd9Sstevel@tonic-gate goto bail; 22517c478bd9Sstevel@tonic-gate } 22527c478bd9Sstevel@tonic-gate } 22537c478bd9Sstevel@tonic-gate 22547c478bd9Sstevel@tonic-gate if (mac->cd_length != digest_len) { 22557c478bd9Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 22567c478bd9Sstevel@tonic-gate goto bail; 22577c478bd9Sstevel@tonic-gate } 22587c478bd9Sstevel@tonic-gate 22597c478bd9Sstevel@tonic-gate /* do a SHA1 update of the inner context using the specified data */ 22607c478bd9Sstevel@tonic-gate SHA1_MAC_UPDATE(data, sha1_hmac_ctx, ret); 22617c478bd9Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) 22627c478bd9Sstevel@tonic-gate /* the update failed, free context and bail */ 22637c478bd9Sstevel@tonic-gate goto bail; 22647c478bd9Sstevel@tonic-gate 22657c478bd9Sstevel@tonic-gate /* do a SHA1 final on the inner context */ 22667c478bd9Sstevel@tonic-gate SHA1Final(digest, &sha1_hmac_ctx.hc_icontext); 22677c478bd9Sstevel@tonic-gate 22687c478bd9Sstevel@tonic-gate /* 22697c478bd9Sstevel@tonic-gate * Do an SHA1 update on the outer context, feeding the inner 22707c478bd9Sstevel@tonic-gate * digest as data. 22717c478bd9Sstevel@tonic-gate */ 22727c478bd9Sstevel@tonic-gate SHA1Update(&sha1_hmac_ctx.hc_ocontext, digest, SHA1_DIGEST_LENGTH); 22737c478bd9Sstevel@tonic-gate 22747c478bd9Sstevel@tonic-gate /* 22757c478bd9Sstevel@tonic-gate * Do a SHA1 final on the outer context, storing the computed 22767c478bd9Sstevel@tonic-gate * digest in the users buffer. 22777c478bd9Sstevel@tonic-gate */ 22787c478bd9Sstevel@tonic-gate SHA1Final(digest, &sha1_hmac_ctx.hc_ocontext); 22797c478bd9Sstevel@tonic-gate 22807c478bd9Sstevel@tonic-gate /* 22817c478bd9Sstevel@tonic-gate * Compare the computed digest against the expected digest passed 22827c478bd9Sstevel@tonic-gate * as argument. 22837c478bd9Sstevel@tonic-gate */ 22847c478bd9Sstevel@tonic-gate 22857c478bd9Sstevel@tonic-gate switch (mac->cd_format) { 22867c478bd9Sstevel@tonic-gate 22877c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 22887c478bd9Sstevel@tonic-gate if (bcmp(digest, (unsigned char *)mac->cd_raw.iov_base + 22897c478bd9Sstevel@tonic-gate mac->cd_offset, digest_len) != 0) 22907c478bd9Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 22917c478bd9Sstevel@tonic-gate break; 22927c478bd9Sstevel@tonic-gate 22937c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: { 22947c478bd9Sstevel@tonic-gate off_t offset = mac->cd_offset; 22957c478bd9Sstevel@tonic-gate uint_t vec_idx; 22967c478bd9Sstevel@tonic-gate off_t scratch_offset = 0; 22977c478bd9Sstevel@tonic-gate size_t length = digest_len; 22987c478bd9Sstevel@tonic-gate size_t cur_len; 22997c478bd9Sstevel@tonic-gate 23007c478bd9Sstevel@tonic-gate /* we support only kernel buffer */ 23017c478bd9Sstevel@tonic-gate if (mac->cd_uio->uio_segflg != UIO_SYSSPACE) 23027c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gate /* jump to the first iovec containing the expected digest */ 23057c478bd9Sstevel@tonic-gate for (vec_idx = 0; 23067c478bd9Sstevel@tonic-gate offset >= mac->cd_uio->uio_iov[vec_idx].iov_len && 23077c478bd9Sstevel@tonic-gate vec_idx < mac->cd_uio->uio_iovcnt; 23087c478bd9Sstevel@tonic-gate offset -= mac->cd_uio->uio_iov[vec_idx++].iov_len); 23097c478bd9Sstevel@tonic-gate if (vec_idx == mac->cd_uio->uio_iovcnt) { 23107c478bd9Sstevel@tonic-gate /* 23117c478bd9Sstevel@tonic-gate * The caller specified an offset that is 23127c478bd9Sstevel@tonic-gate * larger than the total size of the buffers 23137c478bd9Sstevel@tonic-gate * it provided. 23147c478bd9Sstevel@tonic-gate */ 23157c478bd9Sstevel@tonic-gate ret = CRYPTO_DATA_LEN_RANGE; 23167c478bd9Sstevel@tonic-gate break; 23177c478bd9Sstevel@tonic-gate } 23187c478bd9Sstevel@tonic-gate 23197c478bd9Sstevel@tonic-gate /* do the comparison of computed digest vs specified one */ 23207c478bd9Sstevel@tonic-gate while (vec_idx < mac->cd_uio->uio_iovcnt && length > 0) { 23217c478bd9Sstevel@tonic-gate cur_len = MIN(mac->cd_uio->uio_iov[vec_idx].iov_len - 23227c478bd9Sstevel@tonic-gate offset, length); 23237c478bd9Sstevel@tonic-gate 23247c478bd9Sstevel@tonic-gate if (bcmp(digest + scratch_offset, 23257c478bd9Sstevel@tonic-gate mac->cd_uio->uio_iov[vec_idx].iov_base + offset, 23267c478bd9Sstevel@tonic-gate cur_len) != 0) { 23277c478bd9Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 23287c478bd9Sstevel@tonic-gate break; 23297c478bd9Sstevel@tonic-gate } 23307c478bd9Sstevel@tonic-gate 23317c478bd9Sstevel@tonic-gate length -= cur_len; 23327c478bd9Sstevel@tonic-gate vec_idx++; 23337c478bd9Sstevel@tonic-gate scratch_offset += cur_len; 23347c478bd9Sstevel@tonic-gate offset = 0; 23357c478bd9Sstevel@tonic-gate } 23367c478bd9Sstevel@tonic-gate break; 23377c478bd9Sstevel@tonic-gate } 23387c478bd9Sstevel@tonic-gate 23397c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: { 23407c478bd9Sstevel@tonic-gate off_t offset = mac->cd_offset; 23417c478bd9Sstevel@tonic-gate mblk_t *mp; 23427c478bd9Sstevel@tonic-gate off_t scratch_offset = 0; 23437c478bd9Sstevel@tonic-gate size_t length = digest_len; 23447c478bd9Sstevel@tonic-gate size_t cur_len; 23457c478bd9Sstevel@tonic-gate 23467c478bd9Sstevel@tonic-gate /* jump to the first mblk_t containing the expected digest */ 23477c478bd9Sstevel@tonic-gate for (mp = mac->cd_mp; mp != NULL && offset >= MBLKL(mp); 23487c478bd9Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 23497c478bd9Sstevel@tonic-gate if (mp == NULL) { 23507c478bd9Sstevel@tonic-gate /* 23517c478bd9Sstevel@tonic-gate * The caller specified an offset that is larger than 23527c478bd9Sstevel@tonic-gate * the total size of the buffers it provided. 23537c478bd9Sstevel@tonic-gate */ 23547c478bd9Sstevel@tonic-gate ret = CRYPTO_DATA_LEN_RANGE; 23557c478bd9Sstevel@tonic-gate break; 23567c478bd9Sstevel@tonic-gate } 23577c478bd9Sstevel@tonic-gate 23587c478bd9Sstevel@tonic-gate while (mp != NULL && length > 0) { 23597c478bd9Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 23607c478bd9Sstevel@tonic-gate if (bcmp(digest + scratch_offset, 23617c478bd9Sstevel@tonic-gate mp->b_rptr + offset, cur_len) != 0) { 23627c478bd9Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 23637c478bd9Sstevel@tonic-gate break; 23647c478bd9Sstevel@tonic-gate } 23657c478bd9Sstevel@tonic-gate 23667c478bd9Sstevel@tonic-gate length -= cur_len; 23677c478bd9Sstevel@tonic-gate mp = mp->b_cont; 23687c478bd9Sstevel@tonic-gate scratch_offset += cur_len; 23697c478bd9Sstevel@tonic-gate offset = 0; 23707c478bd9Sstevel@tonic-gate } 23717c478bd9Sstevel@tonic-gate break; 23727c478bd9Sstevel@tonic-gate } 23737c478bd9Sstevel@tonic-gate 23747c478bd9Sstevel@tonic-gate default: 23757c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 23767c478bd9Sstevel@tonic-gate } 23777c478bd9Sstevel@tonic-gate 23787c478bd9Sstevel@tonic-gate bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 23797c478bd9Sstevel@tonic-gate return (ret); 23807c478bd9Sstevel@tonic-gate bail: 23817c478bd9Sstevel@tonic-gate bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 23827c478bd9Sstevel@tonic-gate mac->cd_length = 0; 23837c478bd9Sstevel@tonic-gate return (ret); 23847c478bd9Sstevel@tonic-gate } 23857c478bd9Sstevel@tonic-gate 23867c478bd9Sstevel@tonic-gate /* 23877c478bd9Sstevel@tonic-gate * KCF software provider context management entry points. 23887c478bd9Sstevel@tonic-gate */ 23897c478bd9Sstevel@tonic-gate 23907c478bd9Sstevel@tonic-gate /* ARGSUSED */ 23917c478bd9Sstevel@tonic-gate static int 23927c478bd9Sstevel@tonic-gate sha1_create_ctx_template(crypto_provider_handle_t provider, 23937c478bd9Sstevel@tonic-gate crypto_mechanism_t *mechanism, crypto_key_t *key, 23947c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size, 23957c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 23967c478bd9Sstevel@tonic-gate { 23977c478bd9Sstevel@tonic-gate sha1_hmac_ctx_t *sha1_hmac_ctx_tmpl; 23987c478bd9Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 23997c478bd9Sstevel@tonic-gate 24007c478bd9Sstevel@tonic-gate if ((mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE) && 24017c478bd9Sstevel@tonic-gate (mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE)) { 24027c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 24037c478bd9Sstevel@tonic-gate } 24047c478bd9Sstevel@tonic-gate 24057c478bd9Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 24067c478bd9Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 24077c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 24087c478bd9Sstevel@tonic-gate 24097c478bd9Sstevel@tonic-gate /* 24107c478bd9Sstevel@tonic-gate * Allocate and initialize SHA1 context. 24117c478bd9Sstevel@tonic-gate */ 24127c478bd9Sstevel@tonic-gate sha1_hmac_ctx_tmpl = kmem_alloc(sizeof (sha1_hmac_ctx_t), 24137c478bd9Sstevel@tonic-gate crypto_kmflag(req)); 24147c478bd9Sstevel@tonic-gate if (sha1_hmac_ctx_tmpl == NULL) 24157c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 24167c478bd9Sstevel@tonic-gate 24177c478bd9Sstevel@tonic-gate if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) { 24187c478bd9Sstevel@tonic-gate uchar_t digested_key[SHA1_DIGEST_LENGTH]; 24197c478bd9Sstevel@tonic-gate 24207c478bd9Sstevel@tonic-gate /* 24217c478bd9Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 24227c478bd9Sstevel@tonic-gate * The inner context is used since it hasn't been 24237c478bd9Sstevel@tonic-gate * initialized yet. 24247c478bd9Sstevel@tonic-gate */ 24257c478bd9Sstevel@tonic-gate PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx_tmpl->hc_icontext, 24267c478bd9Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digested_key); 24277c478bd9Sstevel@tonic-gate sha1_mac_init_ctx(sha1_hmac_ctx_tmpl, digested_key, 24287c478bd9Sstevel@tonic-gate SHA1_DIGEST_LENGTH); 24297c478bd9Sstevel@tonic-gate } else { 24307c478bd9Sstevel@tonic-gate sha1_mac_init_ctx(sha1_hmac_ctx_tmpl, key->ck_data, 24317c478bd9Sstevel@tonic-gate keylen_in_bytes); 24327c478bd9Sstevel@tonic-gate } 24337c478bd9Sstevel@tonic-gate 24347c478bd9Sstevel@tonic-gate sha1_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type; 24357c478bd9Sstevel@tonic-gate *ctx_template = (crypto_spi_ctx_template_t)sha1_hmac_ctx_tmpl; 24367c478bd9Sstevel@tonic-gate *ctx_template_size = sizeof (sha1_hmac_ctx_t); 24377c478bd9Sstevel@tonic-gate 24387c478bd9Sstevel@tonic-gate 24397c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 24407c478bd9Sstevel@tonic-gate } 24417c478bd9Sstevel@tonic-gate 24427c478bd9Sstevel@tonic-gate static int 24437c478bd9Sstevel@tonic-gate sha1_free_context(crypto_ctx_t *ctx) 24447c478bd9Sstevel@tonic-gate { 24457c478bd9Sstevel@tonic-gate uint_t ctx_len; 24467c478bd9Sstevel@tonic-gate sha1_mech_type_t mech_type; 24477c478bd9Sstevel@tonic-gate 24487c478bd9Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 24497c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 24507c478bd9Sstevel@tonic-gate 24517c478bd9Sstevel@tonic-gate /* 24527c478bd9Sstevel@tonic-gate * We have to free either SHA1 or SHA1-HMAC contexts, which 24537c478bd9Sstevel@tonic-gate * have different lengths. 24547c478bd9Sstevel@tonic-gate */ 24557c478bd9Sstevel@tonic-gate 24567c478bd9Sstevel@tonic-gate mech_type = PROV_SHA1_CTX(ctx)->sc_mech_type; 24577c478bd9Sstevel@tonic-gate if (mech_type == SHA1_MECH_INFO_TYPE) 24587c478bd9Sstevel@tonic-gate ctx_len = sizeof (sha1_ctx_t); 24597c478bd9Sstevel@tonic-gate else { 24607c478bd9Sstevel@tonic-gate ASSERT(mech_type == SHA1_HMAC_MECH_INFO_TYPE || 24617c478bd9Sstevel@tonic-gate mech_type == SHA1_HMAC_GEN_MECH_INFO_TYPE); 24627c478bd9Sstevel@tonic-gate ctx_len = sizeof (sha1_hmac_ctx_t); 24637c478bd9Sstevel@tonic-gate } 24647c478bd9Sstevel@tonic-gate 24657c478bd9Sstevel@tonic-gate bzero(ctx->cc_provider_private, ctx_len); 24667c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, ctx_len); 24677c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 24687c478bd9Sstevel@tonic-gate 24697c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 24707c478bd9Sstevel@tonic-gate } 24717c478bd9Sstevel@tonic-gate 24727c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 2473