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