1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * The basic framework for this code came from the reference 31*0Sstevel@tonic-gate * implementation for MD5. That implementation is Copyright (C) 32*0Sstevel@tonic-gate * 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. 33*0Sstevel@tonic-gate * 34*0Sstevel@tonic-gate * License to copy and use this software is granted provided that it 35*0Sstevel@tonic-gate * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 36*0Sstevel@tonic-gate * Algorithm" in all material mentioning or referencing this software 37*0Sstevel@tonic-gate * or this function. 38*0Sstevel@tonic-gate * 39*0Sstevel@tonic-gate * License is also granted to make and use derivative works provided 40*0Sstevel@tonic-gate * that such works are identified as "derived from the RSA Data 41*0Sstevel@tonic-gate * Security, Inc. MD5 Message-Digest Algorithm" in all material 42*0Sstevel@tonic-gate * mentioning or referencing the derived work. 43*0Sstevel@tonic-gate * 44*0Sstevel@tonic-gate * RSA Data Security, Inc. makes no representations concerning either 45*0Sstevel@tonic-gate * the merchantability of this software or the suitability of this 46*0Sstevel@tonic-gate * software for any particular purpose. It is provided "as is" 47*0Sstevel@tonic-gate * without express or implied warranty of any kind. 48*0Sstevel@tonic-gate * 49*0Sstevel@tonic-gate * These notices must be retained in any copies of any part of this 50*0Sstevel@tonic-gate * documentation and/or software. 51*0Sstevel@tonic-gate * 52*0Sstevel@tonic-gate * NOTE: Cleaned-up and optimized, version of SHA1, based on the FIPS 180-1 53*0Sstevel@tonic-gate * standard, available at http://www.itl.nist.gov/div897/pubs/fip180-1.htm 54*0Sstevel@tonic-gate * Not as fast as one would like -- further optimizations are encouraged 55*0Sstevel@tonic-gate * and appreciated. 56*0Sstevel@tonic-gate */ 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate #include <sys/types.h> 59*0Sstevel@tonic-gate #include <sys/param.h> 60*0Sstevel@tonic-gate #include <sys/systm.h> 61*0Sstevel@tonic-gate #include <sys/sysmacros.h> 62*0Sstevel@tonic-gate #include <sys/sha1.h> 63*0Sstevel@tonic-gate #include <sys/sha1_consts.h> 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate #ifdef _KERNEL 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate #include <sys/modctl.h> 68*0Sstevel@tonic-gate #include <sys/cmn_err.h> 69*0Sstevel@tonic-gate #include <sys/note.h> 70*0Sstevel@tonic-gate #include <sys/crypto/common.h> 71*0Sstevel@tonic-gate #include <sys/crypto/spi.h> 72*0Sstevel@tonic-gate #include <sys/strsun.h> 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate /* 75*0Sstevel@tonic-gate * The sha1 module is created with two modlinkages: 76*0Sstevel@tonic-gate * - a modlmisc that allows consumers to directly call the entry points 77*0Sstevel@tonic-gate * SHA1Init, SHA1Update, and SHA1Final. 78*0Sstevel@tonic-gate * - a modlcrypto that allows the module to register with the Kernel 79*0Sstevel@tonic-gate * Cryptographic Framework (KCF) as a software provider for the SHA1 80*0Sstevel@tonic-gate * mechanisms. 81*0Sstevel@tonic-gate */ 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate #endif /* _KERNEL */ 84*0Sstevel@tonic-gate #ifndef _KERNEL 85*0Sstevel@tonic-gate #include <strings.h> 86*0Sstevel@tonic-gate #include <stdlib.h> 87*0Sstevel@tonic-gate #include <errno.h> 88*0Sstevel@tonic-gate #include <sys/systeminfo.h> 89*0Sstevel@tonic-gate #endif /* !_KERNEL */ 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate static void Encode(uint8_t *, uint32_t *, size_t); 92*0Sstevel@tonic-gate static void SHA1Transform(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, 93*0Sstevel@tonic-gate SHA1_CTX *, const uint8_t *); 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate static uint8_t PADDING[64] = { 0x80, /* all zeros */ }; 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate /* 98*0Sstevel@tonic-gate * F, G, and H are the basic SHA1 functions. 99*0Sstevel@tonic-gate */ 100*0Sstevel@tonic-gate #define F(b, c, d) (((b) & (c)) | ((~b) & (d))) 101*0Sstevel@tonic-gate #define G(b, c, d) ((b) ^ (c) ^ (d)) 102*0Sstevel@tonic-gate #define H(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate /* 105*0Sstevel@tonic-gate * ROTATE_LEFT rotates x left n bits. 106*0Sstevel@tonic-gate */ 107*0Sstevel@tonic-gate #define ROTATE_LEFT(x, n) \ 108*0Sstevel@tonic-gate (((x) << (n)) | ((x) >> ((sizeof (x) * NBBY)-(n)))) 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate #ifdef _KERNEL 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate static struct modlmisc modlmisc = { 113*0Sstevel@tonic-gate &mod_miscops, 114*0Sstevel@tonic-gate "SHA1 Message-Digest Algorithm" 115*0Sstevel@tonic-gate }; 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate static struct modlcrypto modlcrypto = { 118*0Sstevel@tonic-gate &mod_cryptoops, 119*0Sstevel@tonic-gate "SHA1 Kernel SW Provider %I%" 120*0Sstevel@tonic-gate }; 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate static struct modlinkage modlinkage = { 123*0Sstevel@tonic-gate MODREV_1, &modlmisc, &modlcrypto, NULL 124*0Sstevel@tonic-gate }; 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate /* 127*0Sstevel@tonic-gate * CSPI information (entry points, provider info, etc.) 128*0Sstevel@tonic-gate */ 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate typedef enum sha1_mech_type { 131*0Sstevel@tonic-gate SHA1_MECH_INFO_TYPE, /* SUN_CKM_SHA1 */ 132*0Sstevel@tonic-gate SHA1_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA1_HMAC */ 133*0Sstevel@tonic-gate SHA1_HMAC_GEN_MECH_INFO_TYPE /* SUN_CKM_SHA1_HMAC_GENERAL */ 134*0Sstevel@tonic-gate } sha1_mech_type_t; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate #define SHA1_DIGEST_LENGTH 20 /* SHA1 digest length in bytes */ 137*0Sstevel@tonic-gate #define SHA1_HMAC_BLOCK_SIZE 64 /* SHA1-HMAC block size */ 138*0Sstevel@tonic-gate #define SHA1_HMAC_MIN_KEY_LEN 8 /* SHA1-HMAC min key length in bits */ 139*0Sstevel@tonic-gate #define SHA1_HMAC_MAX_KEY_LEN INT_MAX /* SHA1-HMAC max key length in bits */ 140*0Sstevel@tonic-gate #define SHA1_HMAC_INTS_PER_BLOCK (SHA1_HMAC_BLOCK_SIZE/sizeof (uint32_t)) 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate /* 143*0Sstevel@tonic-gate * Context for SHA1 mechanism. 144*0Sstevel@tonic-gate */ 145*0Sstevel@tonic-gate typedef struct sha1_ctx { 146*0Sstevel@tonic-gate sha1_mech_type_t sc_mech_type; /* type of context */ 147*0Sstevel@tonic-gate SHA1_CTX sc_sha1_ctx; /* SHA1 context */ 148*0Sstevel@tonic-gate } sha1_ctx_t; 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate /* 151*0Sstevel@tonic-gate * Context for SHA1-HMAC and SHA1-HMAC-GENERAL mechanisms. 152*0Sstevel@tonic-gate */ 153*0Sstevel@tonic-gate typedef struct sha1_hmac_ctx { 154*0Sstevel@tonic-gate sha1_mech_type_t hc_mech_type; /* type of context */ 155*0Sstevel@tonic-gate uint32_t hc_digest_len; /* digest len in bytes */ 156*0Sstevel@tonic-gate SHA1_CTX hc_icontext; /* inner SHA1 context */ 157*0Sstevel@tonic-gate SHA1_CTX hc_ocontext; /* outer SHA1 context */ 158*0Sstevel@tonic-gate } sha1_hmac_ctx_t; 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* 161*0Sstevel@tonic-gate * Macros to access the SHA1 or SHA1-HMAC contexts from a context passed 162*0Sstevel@tonic-gate * by KCF to one of the entry points. 163*0Sstevel@tonic-gate */ 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate #define PROV_SHA1_CTX(ctx) ((sha1_ctx_t *)(ctx)->cc_provider_private) 166*0Sstevel@tonic-gate #define PROV_SHA1_HMAC_CTX(ctx) ((sha1_hmac_ctx_t *)(ctx)->cc_provider_private) 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate /* to extract the digest length passed as mechanism parameter */ 169*0Sstevel@tonic-gate #define PROV_SHA1_GET_DIGEST_LEN(m, len) { \ 170*0Sstevel@tonic-gate if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t))) \ 171*0Sstevel@tonic-gate (len) = (uint32_t)*((ulong_t *)mechanism->cm_param); \ 172*0Sstevel@tonic-gate else { \ 173*0Sstevel@tonic-gate ulong_t tmp_ulong; \ 174*0Sstevel@tonic-gate bcopy((m)->cm_param, &tmp_ulong, sizeof (ulong_t)); \ 175*0Sstevel@tonic-gate (len) = (uint32_t)tmp_ulong; \ 176*0Sstevel@tonic-gate } \ 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate #define PROV_SHA1_DIGEST_KEY(ctx, key, len, digest) { \ 180*0Sstevel@tonic-gate SHA1Init(ctx); \ 181*0Sstevel@tonic-gate SHA1Update(ctx, key, len); \ 182*0Sstevel@tonic-gate SHA1Final(digest, ctx); \ 183*0Sstevel@tonic-gate } 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate /* 186*0Sstevel@tonic-gate * Mechanism info structure passed to KCF during registration. 187*0Sstevel@tonic-gate */ 188*0Sstevel@tonic-gate static crypto_mech_info_t sha1_mech_info_tab[] = { 189*0Sstevel@tonic-gate /* SHA1 */ 190*0Sstevel@tonic-gate {SUN_CKM_SHA1, SHA1_MECH_INFO_TYPE, 191*0Sstevel@tonic-gate CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 192*0Sstevel@tonic-gate 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 193*0Sstevel@tonic-gate /* SHA1-HMAC */ 194*0Sstevel@tonic-gate {SUN_CKM_SHA1_HMAC, SHA1_HMAC_MECH_INFO_TYPE, 195*0Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 196*0Sstevel@tonic-gate SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN, 197*0Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 198*0Sstevel@tonic-gate /* SHA1-HMAC GENERAL */ 199*0Sstevel@tonic-gate {SUN_CKM_SHA1_HMAC_GENERAL, SHA1_HMAC_GEN_MECH_INFO_TYPE, 200*0Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 201*0Sstevel@tonic-gate SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN, 202*0Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS} 203*0Sstevel@tonic-gate }; 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate static void sha1_provider_status(crypto_provider_handle_t, uint_t *); 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate static crypto_control_ops_t sha1_control_ops = { 208*0Sstevel@tonic-gate sha1_provider_status 209*0Sstevel@tonic-gate }; 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate static int sha1_digest_init(crypto_ctx_t *, crypto_mechanism_t *, 212*0Sstevel@tonic-gate crypto_req_handle_t); 213*0Sstevel@tonic-gate static int sha1_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 214*0Sstevel@tonic-gate crypto_req_handle_t); 215*0Sstevel@tonic-gate static int sha1_digest_update(crypto_ctx_t *, crypto_data_t *, 216*0Sstevel@tonic-gate crypto_req_handle_t); 217*0Sstevel@tonic-gate static int sha1_digest_final(crypto_ctx_t *, crypto_data_t *, 218*0Sstevel@tonic-gate crypto_req_handle_t); 219*0Sstevel@tonic-gate static int sha1_digest_atomic(crypto_provider_handle_t, crypto_session_id_t, 220*0Sstevel@tonic-gate crypto_mechanism_t *, crypto_data_t *, crypto_data_t *, 221*0Sstevel@tonic-gate crypto_req_handle_t); 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate static crypto_digest_ops_t sha1_digest_ops = { 224*0Sstevel@tonic-gate sha1_digest_init, 225*0Sstevel@tonic-gate sha1_digest, 226*0Sstevel@tonic-gate sha1_digest_update, 227*0Sstevel@tonic-gate NULL, 228*0Sstevel@tonic-gate sha1_digest_final, 229*0Sstevel@tonic-gate sha1_digest_atomic 230*0Sstevel@tonic-gate }; 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate static int sha1_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, 233*0Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 234*0Sstevel@tonic-gate static int sha1_mac_update(crypto_ctx_t *, crypto_data_t *, 235*0Sstevel@tonic-gate crypto_req_handle_t); 236*0Sstevel@tonic-gate static int sha1_mac_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); 237*0Sstevel@tonic-gate static int sha1_mac_atomic(crypto_provider_handle_t, crypto_session_id_t, 238*0Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 239*0Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 240*0Sstevel@tonic-gate static int sha1_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t, 241*0Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 242*0Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate static crypto_mac_ops_t sha1_mac_ops = { 245*0Sstevel@tonic-gate sha1_mac_init, 246*0Sstevel@tonic-gate NULL, 247*0Sstevel@tonic-gate sha1_mac_update, 248*0Sstevel@tonic-gate sha1_mac_final, 249*0Sstevel@tonic-gate sha1_mac_atomic, 250*0Sstevel@tonic-gate sha1_mac_verify_atomic 251*0Sstevel@tonic-gate }; 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate static int sha1_create_ctx_template(crypto_provider_handle_t, 254*0Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *, 255*0Sstevel@tonic-gate size_t *, crypto_req_handle_t); 256*0Sstevel@tonic-gate static int sha1_free_context(crypto_ctx_t *); 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate static crypto_ctx_ops_t sha1_ctx_ops = { 259*0Sstevel@tonic-gate sha1_create_ctx_template, 260*0Sstevel@tonic-gate sha1_free_context 261*0Sstevel@tonic-gate }; 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate static crypto_ops_t sha1_crypto_ops = { 264*0Sstevel@tonic-gate &sha1_control_ops, 265*0Sstevel@tonic-gate &sha1_digest_ops, 266*0Sstevel@tonic-gate NULL, 267*0Sstevel@tonic-gate &sha1_mac_ops, 268*0Sstevel@tonic-gate NULL, 269*0Sstevel@tonic-gate NULL, 270*0Sstevel@tonic-gate NULL, 271*0Sstevel@tonic-gate NULL, 272*0Sstevel@tonic-gate NULL, 273*0Sstevel@tonic-gate NULL, 274*0Sstevel@tonic-gate NULL, 275*0Sstevel@tonic-gate NULL, 276*0Sstevel@tonic-gate NULL, 277*0Sstevel@tonic-gate &sha1_ctx_ops 278*0Sstevel@tonic-gate }; 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate static crypto_provider_info_t sha1_prov_info = { 281*0Sstevel@tonic-gate CRYPTO_SPI_VERSION_1, 282*0Sstevel@tonic-gate "SHA1 Software Provider", 283*0Sstevel@tonic-gate CRYPTO_SW_PROVIDER, 284*0Sstevel@tonic-gate {&modlinkage}, 285*0Sstevel@tonic-gate NULL, 286*0Sstevel@tonic-gate &sha1_crypto_ops, 287*0Sstevel@tonic-gate sizeof (sha1_mech_info_tab)/sizeof (crypto_mech_info_t), 288*0Sstevel@tonic-gate sha1_mech_info_tab 289*0Sstevel@tonic-gate }; 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate static crypto_kcf_provider_handle_t sha1_prov_handle = NULL; 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate int 294*0Sstevel@tonic-gate _init() 295*0Sstevel@tonic-gate { 296*0Sstevel@tonic-gate int ret; 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate if ((ret = mod_install(&modlinkage)) != 0) 299*0Sstevel@tonic-gate return (ret); 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate /* 302*0Sstevel@tonic-gate * Register with KCF. If the registration fails, log an 303*0Sstevel@tonic-gate * error but do not uninstall the module, since the functionality 304*0Sstevel@tonic-gate * provided by misc/sha1 should still be available. 305*0Sstevel@tonic-gate */ 306*0Sstevel@tonic-gate if ((ret = crypto_register_provider(&sha1_prov_info, 307*0Sstevel@tonic-gate &sha1_prov_handle)) != CRYPTO_SUCCESS) 308*0Sstevel@tonic-gate cmn_err(CE_WARN, "sha1 _init: " 309*0Sstevel@tonic-gate "crypto_register_provider() failed (0x%x)", ret); 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate return (0); 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate int 315*0Sstevel@tonic-gate _info(struct modinfo *modinfop) 316*0Sstevel@tonic-gate { 317*0Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 318*0Sstevel@tonic-gate } 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate #endif /* _KERNEL */ 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate /* 323*0Sstevel@tonic-gate * SHA1Init() 324*0Sstevel@tonic-gate * 325*0Sstevel@tonic-gate * purpose: initializes the sha1 context and begins and sha1 digest operation 326*0Sstevel@tonic-gate * input: SHA1_CTX * : the context to initializes. 327*0Sstevel@tonic-gate * output: void 328*0Sstevel@tonic-gate */ 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate void 331*0Sstevel@tonic-gate SHA1Init(SHA1_CTX *ctx) 332*0Sstevel@tonic-gate { 333*0Sstevel@tonic-gate ctx->count[0] = ctx->count[1] = 0; 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* 336*0Sstevel@tonic-gate * load magic initialization constants. Tell lint 337*0Sstevel@tonic-gate * that these constants are unsigned by using U. 338*0Sstevel@tonic-gate */ 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate ctx->state[0] = 0x67452301U; 341*0Sstevel@tonic-gate ctx->state[1] = 0xefcdab89U; 342*0Sstevel@tonic-gate ctx->state[2] = 0x98badcfeU; 343*0Sstevel@tonic-gate ctx->state[3] = 0x10325476U; 344*0Sstevel@tonic-gate ctx->state[4] = 0xc3d2e1f0U; 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate #ifdef VIS_SHA1 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate static int usevis = 0; 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate #ifdef _KERNEL 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate #include <sys/regset.h> 354*0Sstevel@tonic-gate #include <sys/vis.h> 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate /* the alignment for block stores to save fp registers */ 357*0Sstevel@tonic-gate #define VIS_ALIGN (64) 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate extern int sha1_savefp(kfpu_t *, int); 360*0Sstevel@tonic-gate extern void sha1_restorefp(kfpu_t *); 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate uint32_t vis_sha1_svfp_threshold = 128; 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate #else /* !_KERNEL */ 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate static boolean_t checked_vis = B_FALSE; 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate static int 369*0Sstevel@tonic-gate havevis() 370*0Sstevel@tonic-gate { 371*0Sstevel@tonic-gate char *buf = NULL; 372*0Sstevel@tonic-gate char *isa_token; 373*0Sstevel@tonic-gate char *lasts; 374*0Sstevel@tonic-gate int ret = 0; 375*0Sstevel@tonic-gate size_t bufsize = 255; /* UltraSPARC III needs 115 chars */ 376*0Sstevel@tonic-gate int v9_isa_token, vis_isa_token, isa_token_num; 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate if (checked_vis) { 379*0Sstevel@tonic-gate return (usevis); 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate if ((buf = malloc(bufsize)) == NULL) { 383*0Sstevel@tonic-gate return (0); 384*0Sstevel@tonic-gate } 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate if ((ret = sysinfo(SI_ISALIST, buf, bufsize)) == -1) { 387*0Sstevel@tonic-gate free(buf); 388*0Sstevel@tonic-gate return (0); 389*0Sstevel@tonic-gate } else if (ret > bufsize) { 390*0Sstevel@tonic-gate /* We lost some because our buffer was too small */ 391*0Sstevel@tonic-gate if ((buf = realloc(buf, bufsize = ret)) == NULL) { 392*0Sstevel@tonic-gate return (0); 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate if ((ret = sysinfo(SI_ISALIST, buf, bufsize)) == -1) { 395*0Sstevel@tonic-gate free(buf); 396*0Sstevel@tonic-gate return (0); 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate /* 401*0Sstevel@tonic-gate * Check the relative posistions of sparcv9 & sparcv9+vis 402*0Sstevel@tonic-gate * because they are listed in (best) performance order. 403*0Sstevel@tonic-gate * For example: The Niagara chip reports it has VIS but the 404*0Sstevel@tonic-gate * SHA1 code runs faster without this optimisation. 405*0Sstevel@tonic-gate */ 406*0Sstevel@tonic-gate isa_token = strtok_r(buf, " ", &lasts); 407*0Sstevel@tonic-gate v9_isa_token = vis_isa_token = -1; 408*0Sstevel@tonic-gate isa_token_num = 0; 409*0Sstevel@tonic-gate do { 410*0Sstevel@tonic-gate if (strcmp(isa_token, "sparcv9") == 0) { 411*0Sstevel@tonic-gate v9_isa_token = isa_token_num; 412*0Sstevel@tonic-gate } else if (strcmp(isa_token, "sparcv9+vis") == 0) { 413*0Sstevel@tonic-gate vis_isa_token = isa_token_num; 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate isa_token_num++; 416*0Sstevel@tonic-gate } while (isa_token = strtok_r(NULL, " ", &lasts)); 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate if (vis_isa_token != -1 && vis_isa_token < v9_isa_token) 419*0Sstevel@tonic-gate usevis = 1; 420*0Sstevel@tonic-gate free(buf); 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate checked_vis = B_TRUE; 423*0Sstevel@tonic-gate return (usevis); 424*0Sstevel@tonic-gate } 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate #endif /* _KERNEL */ 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate /* 429*0Sstevel@tonic-gate * VIS SHA-1 consts. 430*0Sstevel@tonic-gate */ 431*0Sstevel@tonic-gate static uint64_t VIS[] = { 432*0Sstevel@tonic-gate 0x8000000080000000, 433*0Sstevel@tonic-gate 0x0002000200020002, 434*0Sstevel@tonic-gate 0x5a8279996ed9eba1, 435*0Sstevel@tonic-gate 0x8f1bbcdcca62c1d6, 436*0Sstevel@tonic-gate 0x012389ab456789ab}; 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate extern void SHA1TransformVIS(uint64_t *, uint64_t *, uint32_t *, uint64_t *); 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate /* 442*0Sstevel@tonic-gate * SHA1Update() 443*0Sstevel@tonic-gate * 444*0Sstevel@tonic-gate * purpose: continues an sha1 digest operation, using the message block 445*0Sstevel@tonic-gate * to update the context. 446*0Sstevel@tonic-gate * input: SHA1_CTX * : the context to update 447*0Sstevel@tonic-gate * uint8_t * : the message block 448*0Sstevel@tonic-gate * uint32_t : the length of the message block in bytes 449*0Sstevel@tonic-gate * output: void 450*0Sstevel@tonic-gate */ 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate void 453*0Sstevel@tonic-gate SHA1Update(SHA1_CTX *ctx, const uint8_t *input, uint32_t input_len) 454*0Sstevel@tonic-gate { 455*0Sstevel@tonic-gate uint32_t i, buf_index, buf_len; 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate uint64_t X0[40], input64[8]; 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate /* check for noop */ 460*0Sstevel@tonic-gate if (input_len == 0) 461*0Sstevel@tonic-gate return; 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate /* compute number of bytes mod 64 */ 464*0Sstevel@tonic-gate buf_index = (ctx->count[1] >> 3) & 0x3F; 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate /* update number of bits */ 467*0Sstevel@tonic-gate if ((ctx->count[1] += (input_len << 3)) < (input_len << 3)) 468*0Sstevel@tonic-gate ctx->count[0]++; 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate ctx->count[0] += (input_len >> 29); 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate buf_len = 64 - buf_index; 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate /* transform as many times as possible */ 475*0Sstevel@tonic-gate i = 0; 476*0Sstevel@tonic-gate if (input_len >= buf_len) { 477*0Sstevel@tonic-gate #ifdef _KERNEL 478*0Sstevel@tonic-gate uint8_t fpua[sizeof (kfpu_t) + GSR_SIZE + VIS_ALIGN]; 479*0Sstevel@tonic-gate kfpu_t *fpu; 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate uint32_t len = (input_len + buf_index) & ~0x3f; 482*0Sstevel@tonic-gate int svfp_ok; 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate fpu = (kfpu_t *)P2ROUNDUP((uintptr_t)fpua, 64); 485*0Sstevel@tonic-gate svfp_ok = ((len >= vis_sha1_svfp_threshold) ? 1 : 0); 486*0Sstevel@tonic-gate usevis = sha1_savefp(fpu, svfp_ok); 487*0Sstevel@tonic-gate #else 488*0Sstevel@tonic-gate if (!checked_vis) 489*0Sstevel@tonic-gate usevis = havevis(); 490*0Sstevel@tonic-gate #endif /* _KERNEL */ 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate /* 493*0Sstevel@tonic-gate * general optimization: 494*0Sstevel@tonic-gate * 495*0Sstevel@tonic-gate * only do initial bcopy() and SHA1Transform() if 496*0Sstevel@tonic-gate * buf_index != 0. if buf_index == 0, we're just 497*0Sstevel@tonic-gate * wasting our time doing the bcopy() since there 498*0Sstevel@tonic-gate * wasn't any data left over from a previous call to 499*0Sstevel@tonic-gate * SHA1Update(). 500*0Sstevel@tonic-gate */ 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate if (buf_index) { 503*0Sstevel@tonic-gate bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len); 504*0Sstevel@tonic-gate if (usevis) { 505*0Sstevel@tonic-gate SHA1TransformVIS(X0, 506*0Sstevel@tonic-gate (uint64_t *)ctx->buf_un.buf8, 507*0Sstevel@tonic-gate &ctx->state[0], VIS); 508*0Sstevel@tonic-gate } else { 509*0Sstevel@tonic-gate SHA1Transform(ctx->state[0], ctx->state[1], 510*0Sstevel@tonic-gate ctx->state[2], ctx->state[3], 511*0Sstevel@tonic-gate ctx->state[4], ctx, ctx->buf_un.buf8); 512*0Sstevel@tonic-gate } 513*0Sstevel@tonic-gate i = buf_len; 514*0Sstevel@tonic-gate } 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate /* 517*0Sstevel@tonic-gate * VIS SHA-1: uses the VIS 1.0 instructions to accelerate 518*0Sstevel@tonic-gate * SHA-1 processing. This is achieved by "offloading" the 519*0Sstevel@tonic-gate * computation of the message schedule (MS) to the VIS units. 520*0Sstevel@tonic-gate * This allows the VIS computation of the message schedule 521*0Sstevel@tonic-gate * to be performed in parallel with the standard integer 522*0Sstevel@tonic-gate * processing of the remainder of the SHA-1 computation. 523*0Sstevel@tonic-gate * performance by up to around 1.37X, compared to an optimized 524*0Sstevel@tonic-gate * integer-only implementation. 525*0Sstevel@tonic-gate * 526*0Sstevel@tonic-gate * The VIS implementation of SHA1Transform has a different API 527*0Sstevel@tonic-gate * to the standard integer version: 528*0Sstevel@tonic-gate * 529*0Sstevel@tonic-gate * void SHA1TransformVIS( 530*0Sstevel@tonic-gate * uint64_t *, // Pointer to MS for ith block 531*0Sstevel@tonic-gate * uint64_t *, // Pointer to ith block of message data 532*0Sstevel@tonic-gate * uint32_t *, // Pointer to SHA state i.e ctx->state 533*0Sstevel@tonic-gate * uint64_t *, // Pointer to various VIS constants 534*0Sstevel@tonic-gate * ) 535*0Sstevel@tonic-gate * 536*0Sstevel@tonic-gate * Note: the message data must by 4-byte aligned. 537*0Sstevel@tonic-gate * 538*0Sstevel@tonic-gate * Function requires VIS 1.0 support. 539*0Sstevel@tonic-gate * 540*0Sstevel@tonic-gate * Handling is provided to deal with arbitrary byte alingment 541*0Sstevel@tonic-gate * of the input data but the performance gains are reduced 542*0Sstevel@tonic-gate * for alignments other than 4-bytes. 543*0Sstevel@tonic-gate */ 544*0Sstevel@tonic-gate if (usevis) { 545*0Sstevel@tonic-gate if (((uint64_t)(&input[i]) & 0x3)) { 546*0Sstevel@tonic-gate /* 547*0Sstevel@tonic-gate * Main processing loop - input misaligned 548*0Sstevel@tonic-gate */ 549*0Sstevel@tonic-gate for (; i + 63 < input_len; i += 64) { 550*0Sstevel@tonic-gate bcopy(&input[i], input64, 64); 551*0Sstevel@tonic-gate SHA1TransformVIS(X0, input64, 552*0Sstevel@tonic-gate &ctx->state[0], VIS); 553*0Sstevel@tonic-gate } 554*0Sstevel@tonic-gate } else { 555*0Sstevel@tonic-gate /* 556*0Sstevel@tonic-gate * Main processing loop - input 8-byte aligned 557*0Sstevel@tonic-gate */ 558*0Sstevel@tonic-gate for (; i + 63 < input_len; i += 64) { 559*0Sstevel@tonic-gate SHA1TransformVIS(X0, 560*0Sstevel@tonic-gate (uint64_t *)&input[i], 561*0Sstevel@tonic-gate &ctx->state[0], VIS); 562*0Sstevel@tonic-gate } 563*0Sstevel@tonic-gate 564*0Sstevel@tonic-gate } 565*0Sstevel@tonic-gate #ifdef _KERNEL 566*0Sstevel@tonic-gate sha1_restorefp(fpu); 567*0Sstevel@tonic-gate #endif /* _KERNEL */ 568*0Sstevel@tonic-gate } else { 569*0Sstevel@tonic-gate for (; i + 63 < input_len; i += 64) { 570*0Sstevel@tonic-gate SHA1Transform(ctx->state[0], ctx->state[1], 571*0Sstevel@tonic-gate ctx->state[2], ctx->state[3], ctx->state[4], 572*0Sstevel@tonic-gate ctx, &input[i]); 573*0Sstevel@tonic-gate } 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate /* 577*0Sstevel@tonic-gate * general optimization: 578*0Sstevel@tonic-gate * 579*0Sstevel@tonic-gate * if i and input_len are the same, return now instead 580*0Sstevel@tonic-gate * of calling bcopy(), since the bcopy() in this case 581*0Sstevel@tonic-gate * will be an expensive nop. 582*0Sstevel@tonic-gate */ 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate if (input_len == i) 585*0Sstevel@tonic-gate return; 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate buf_index = 0; 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate /* buffer remaining input */ 591*0Sstevel@tonic-gate bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i); 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate #else /* VIS_SHA1 */ 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate void 597*0Sstevel@tonic-gate SHA1Update(SHA1_CTX *ctx, const uint8_t *input, uint32_t input_len) 598*0Sstevel@tonic-gate { 599*0Sstevel@tonic-gate uint32_t i, buf_index, buf_len; 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate /* check for noop */ 602*0Sstevel@tonic-gate if (input_len == 0) 603*0Sstevel@tonic-gate return; 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate /* compute number of bytes mod 64 */ 606*0Sstevel@tonic-gate buf_index = (ctx->count[1] >> 3) & 0x3F; 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate /* update number of bits */ 609*0Sstevel@tonic-gate if ((ctx->count[1] += (input_len << 3)) < (input_len << 3)) 610*0Sstevel@tonic-gate ctx->count[0]++; 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate ctx->count[0] += (input_len >> 29); 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate buf_len = 64 - buf_index; 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate /* transform as many times as possible */ 617*0Sstevel@tonic-gate i = 0; 618*0Sstevel@tonic-gate if (input_len >= buf_len) { 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate /* 621*0Sstevel@tonic-gate * general optimization: 622*0Sstevel@tonic-gate * 623*0Sstevel@tonic-gate * only do initial bcopy() and SHA1Transform() if 624*0Sstevel@tonic-gate * buf_index != 0. if buf_index == 0, we're just 625*0Sstevel@tonic-gate * wasting our time doing the bcopy() since there 626*0Sstevel@tonic-gate * wasn't any data left over from a previous call to 627*0Sstevel@tonic-gate * SHA1Update(). 628*0Sstevel@tonic-gate */ 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate if (buf_index) { 631*0Sstevel@tonic-gate bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len); 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate SHA1Transform(ctx->state[0], ctx->state[1], 635*0Sstevel@tonic-gate ctx->state[2], ctx->state[3], ctx->state[4], ctx, 636*0Sstevel@tonic-gate ctx->buf_un.buf8); 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate i = buf_len; 639*0Sstevel@tonic-gate } 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate for (; i + 63 < input_len; i += 64) 642*0Sstevel@tonic-gate SHA1Transform(ctx->state[0], ctx->state[1], 643*0Sstevel@tonic-gate ctx->state[2], ctx->state[3], ctx->state[4], 644*0Sstevel@tonic-gate ctx, &input[i]); 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate /* 647*0Sstevel@tonic-gate * general optimization: 648*0Sstevel@tonic-gate * 649*0Sstevel@tonic-gate * if i and input_len are the same, return now instead 650*0Sstevel@tonic-gate * of calling bcopy(), since the bcopy() in this case 651*0Sstevel@tonic-gate * will be an expensive nop. 652*0Sstevel@tonic-gate */ 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate if (input_len == i) 655*0Sstevel@tonic-gate return; 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate buf_index = 0; 658*0Sstevel@tonic-gate } 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate /* buffer remaining input */ 661*0Sstevel@tonic-gate bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i); 662*0Sstevel@tonic-gate } 663*0Sstevel@tonic-gate 664*0Sstevel@tonic-gate #endif /* VIS_SHA1 */ 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate /* 667*0Sstevel@tonic-gate * SHA1Final() 668*0Sstevel@tonic-gate * 669*0Sstevel@tonic-gate * purpose: ends an sha1 digest operation, finalizing the message digest and 670*0Sstevel@tonic-gate * zeroing the context. 671*0Sstevel@tonic-gate * input: uint8_t * : a buffer to store the digest in 672*0Sstevel@tonic-gate * SHA1_CTX * : the context to finalize, save, and zero 673*0Sstevel@tonic-gate * output: void 674*0Sstevel@tonic-gate */ 675*0Sstevel@tonic-gate 676*0Sstevel@tonic-gate void 677*0Sstevel@tonic-gate SHA1Final(uint8_t *digest, SHA1_CTX *ctx) 678*0Sstevel@tonic-gate { 679*0Sstevel@tonic-gate uint8_t bitcount_be[sizeof (ctx->count)]; 680*0Sstevel@tonic-gate uint32_t index = (ctx->count[1] >> 3) & 0x3f; 681*0Sstevel@tonic-gate 682*0Sstevel@tonic-gate /* store bit count, big endian */ 683*0Sstevel@tonic-gate Encode(bitcount_be, ctx->count, sizeof (bitcount_be)); 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate /* pad out to 56 mod 64 */ 686*0Sstevel@tonic-gate SHA1Update(ctx, PADDING, ((index < 56) ? 56 : 120) - index); 687*0Sstevel@tonic-gate 688*0Sstevel@tonic-gate /* append length (before padding) */ 689*0Sstevel@tonic-gate SHA1Update(ctx, bitcount_be, sizeof (bitcount_be)); 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate /* store state in digest */ 692*0Sstevel@tonic-gate Encode(digest, ctx->state, sizeof (ctx->state)); 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate 695*0Sstevel@tonic-gate /* 696*0Sstevel@tonic-gate * sparc optimization: 697*0Sstevel@tonic-gate * 698*0Sstevel@tonic-gate * on the sparc, we can load big endian 32-bit data easily. note that 699*0Sstevel@tonic-gate * special care must be taken to ensure the address is 32-bit aligned. 700*0Sstevel@tonic-gate * in the interest of speed, we don't check to make sure, since 701*0Sstevel@tonic-gate * careful programming can guarantee this for us. 702*0Sstevel@tonic-gate */ 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate #if defined(_BIG_ENDIAN) 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate #define LOAD_BIG_32(addr) (*(uint32_t *)(addr)) 707*0Sstevel@tonic-gate 708*0Sstevel@tonic-gate #else /* little endian -- will work on big endian, but slowly */ 709*0Sstevel@tonic-gate 710*0Sstevel@tonic-gate #define LOAD_BIG_32(addr) \ 711*0Sstevel@tonic-gate (((addr)[0] << 24) | ((addr)[1] << 16) | ((addr)[2] << 8) | (addr)[3]) 712*0Sstevel@tonic-gate #endif 713*0Sstevel@tonic-gate 714*0Sstevel@tonic-gate /* 715*0Sstevel@tonic-gate * sparc register window optimization: 716*0Sstevel@tonic-gate * 717*0Sstevel@tonic-gate * `a', `b', `c', `d', and `e' are passed into SHA1Transform 718*0Sstevel@tonic-gate * explicitly since it increases the number of registers available to 719*0Sstevel@tonic-gate * the compiler. under this scheme, these variables can be held in 720*0Sstevel@tonic-gate * %i0 - %i4, which leaves more local and out registers available. 721*0Sstevel@tonic-gate */ 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate /* 724*0Sstevel@tonic-gate * SHA1Transform() 725*0Sstevel@tonic-gate * 726*0Sstevel@tonic-gate * purpose: sha1 transformation -- updates the digest based on `block' 727*0Sstevel@tonic-gate * input: uint32_t : bytes 1 - 4 of the digest 728*0Sstevel@tonic-gate * uint32_t : bytes 5 - 8 of the digest 729*0Sstevel@tonic-gate * uint32_t : bytes 9 - 12 of the digest 730*0Sstevel@tonic-gate * uint32_t : bytes 12 - 16 of the digest 731*0Sstevel@tonic-gate * uint32_t : bytes 16 - 20 of the digest 732*0Sstevel@tonic-gate * SHA1_CTX * : the context to update 733*0Sstevel@tonic-gate * uint8_t [64]: the block to use to update the digest 734*0Sstevel@tonic-gate * output: void 735*0Sstevel@tonic-gate */ 736*0Sstevel@tonic-gate 737*0Sstevel@tonic-gate void 738*0Sstevel@tonic-gate SHA1Transform(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, 739*0Sstevel@tonic-gate SHA1_CTX *ctx, const uint8_t blk[64]) 740*0Sstevel@tonic-gate { 741*0Sstevel@tonic-gate /* 742*0Sstevel@tonic-gate * sparc optimization: 743*0Sstevel@tonic-gate * 744*0Sstevel@tonic-gate * while it is somewhat counter-intuitive, on sparc, it is 745*0Sstevel@tonic-gate * more efficient to place all the constants used in this 746*0Sstevel@tonic-gate * function in an array and load the values out of the array 747*0Sstevel@tonic-gate * than to manually load the constants. this is because 748*0Sstevel@tonic-gate * setting a register to a 32-bit value takes two ops in most 749*0Sstevel@tonic-gate * cases: a `sethi' and an `or', but loading a 32-bit value 750*0Sstevel@tonic-gate * from memory only takes one `ld' (or `lduw' on v9). while 751*0Sstevel@tonic-gate * this increases memory usage, the compiler can find enough 752*0Sstevel@tonic-gate * other things to do while waiting to keep the pipeline does 753*0Sstevel@tonic-gate * not stall. additionally, it is likely that many of these 754*0Sstevel@tonic-gate * constants are cached so that later accesses do not even go 755*0Sstevel@tonic-gate * out to the bus. 756*0Sstevel@tonic-gate * 757*0Sstevel@tonic-gate * this array is declared `static' to keep the compiler from 758*0Sstevel@tonic-gate * having to bcopy() this array onto the stack frame of 759*0Sstevel@tonic-gate * SHA1Transform() each time it is called -- which is 760*0Sstevel@tonic-gate * unacceptably expensive. 761*0Sstevel@tonic-gate * 762*0Sstevel@tonic-gate * the `const' is to ensure that callers are good citizens and 763*0Sstevel@tonic-gate * do not try to munge the array. since these routines are 764*0Sstevel@tonic-gate * going to be called from inside multithreaded kernelland, 765*0Sstevel@tonic-gate * this is a good safety check. -- `sha1_consts' will end up in 766*0Sstevel@tonic-gate * .rodata. 767*0Sstevel@tonic-gate * 768*0Sstevel@tonic-gate * unfortunately, loading from an array in this manner hurts 769*0Sstevel@tonic-gate * performance under intel. so, there is a macro, 770*0Sstevel@tonic-gate * SHA1_CONST(), used in SHA1Transform(), that either expands to 771*0Sstevel@tonic-gate * a reference to this array, or to the actual constant, 772*0Sstevel@tonic-gate * depending on what platform this code is compiled for. 773*0Sstevel@tonic-gate */ 774*0Sstevel@tonic-gate 775*0Sstevel@tonic-gate #if defined(__sparc) 776*0Sstevel@tonic-gate static const uint32_t sha1_consts[] = { 777*0Sstevel@tonic-gate SHA1_CONST_0, SHA1_CONST_1, SHA1_CONST_2, SHA1_CONST_3, 778*0Sstevel@tonic-gate }; 779*0Sstevel@tonic-gate #endif 780*0Sstevel@tonic-gate 781*0Sstevel@tonic-gate /* 782*0Sstevel@tonic-gate * general optimization: 783*0Sstevel@tonic-gate * 784*0Sstevel@tonic-gate * use individual integers instead of using an array. this is a 785*0Sstevel@tonic-gate * win, although the amount it wins by seems to vary quite a bit. 786*0Sstevel@tonic-gate */ 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gate uint32_t w_0, w_1, w_2, w_3, w_4, w_5, w_6, w_7; 789*0Sstevel@tonic-gate uint32_t w_8, w_9, w_10, w_11, w_12, w_13, w_14, w_15; 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate /* 792*0Sstevel@tonic-gate * sparc optimization: 793*0Sstevel@tonic-gate * 794*0Sstevel@tonic-gate * if `block' is already aligned on a 4-byte boundary, use 795*0Sstevel@tonic-gate * LOAD_BIG_32() directly. otherwise, bcopy() into a 796*0Sstevel@tonic-gate * buffer that *is* aligned on a 4-byte boundary and then do 797*0Sstevel@tonic-gate * the LOAD_BIG_32() on that buffer. benchmarks have shown 798*0Sstevel@tonic-gate * that using the bcopy() is better than loading the bytes 799*0Sstevel@tonic-gate * individually and doing the endian-swap by hand. 800*0Sstevel@tonic-gate * 801*0Sstevel@tonic-gate * even though it's quite tempting to assign to do: 802*0Sstevel@tonic-gate * 803*0Sstevel@tonic-gate * blk = bcopy(ctx->buf_un.buf32, blk, sizeof (ctx->buf_un.buf32)); 804*0Sstevel@tonic-gate * 805*0Sstevel@tonic-gate * and only have one set of LOAD_BIG_32()'s, the compiler 806*0Sstevel@tonic-gate * *does not* like that, so please resist the urge. 807*0Sstevel@tonic-gate */ 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate #if defined(__sparc) 810*0Sstevel@tonic-gate if ((uintptr_t)blk & 0x3) { /* not 4-byte aligned? */ 811*0Sstevel@tonic-gate bcopy(blk, ctx->buf_un.buf32, sizeof (ctx->buf_un.buf32)); 812*0Sstevel@tonic-gate w_15 = LOAD_BIG_32(ctx->buf_un.buf32 + 15); 813*0Sstevel@tonic-gate w_14 = LOAD_BIG_32(ctx->buf_un.buf32 + 14); 814*0Sstevel@tonic-gate w_13 = LOAD_BIG_32(ctx->buf_un.buf32 + 13); 815*0Sstevel@tonic-gate w_12 = LOAD_BIG_32(ctx->buf_un.buf32 + 12); 816*0Sstevel@tonic-gate w_11 = LOAD_BIG_32(ctx->buf_un.buf32 + 11); 817*0Sstevel@tonic-gate w_10 = LOAD_BIG_32(ctx->buf_un.buf32 + 10); 818*0Sstevel@tonic-gate w_9 = LOAD_BIG_32(ctx->buf_un.buf32 + 9); 819*0Sstevel@tonic-gate w_8 = LOAD_BIG_32(ctx->buf_un.buf32 + 8); 820*0Sstevel@tonic-gate w_7 = LOAD_BIG_32(ctx->buf_un.buf32 + 7); 821*0Sstevel@tonic-gate w_6 = LOAD_BIG_32(ctx->buf_un.buf32 + 6); 822*0Sstevel@tonic-gate w_5 = LOAD_BIG_32(ctx->buf_un.buf32 + 5); 823*0Sstevel@tonic-gate w_4 = LOAD_BIG_32(ctx->buf_un.buf32 + 4); 824*0Sstevel@tonic-gate w_3 = LOAD_BIG_32(ctx->buf_un.buf32 + 3); 825*0Sstevel@tonic-gate w_2 = LOAD_BIG_32(ctx->buf_un.buf32 + 2); 826*0Sstevel@tonic-gate w_1 = LOAD_BIG_32(ctx->buf_un.buf32 + 1); 827*0Sstevel@tonic-gate w_0 = LOAD_BIG_32(ctx->buf_un.buf32 + 0); 828*0Sstevel@tonic-gate } else { 829*0Sstevel@tonic-gate /*LINTED*/ 830*0Sstevel@tonic-gate w_15 = LOAD_BIG_32(blk + 60); 831*0Sstevel@tonic-gate /*LINTED*/ 832*0Sstevel@tonic-gate w_14 = LOAD_BIG_32(blk + 56); 833*0Sstevel@tonic-gate /*LINTED*/ 834*0Sstevel@tonic-gate w_13 = LOAD_BIG_32(blk + 52); 835*0Sstevel@tonic-gate /*LINTED*/ 836*0Sstevel@tonic-gate w_12 = LOAD_BIG_32(blk + 48); 837*0Sstevel@tonic-gate /*LINTED*/ 838*0Sstevel@tonic-gate w_11 = LOAD_BIG_32(blk + 44); 839*0Sstevel@tonic-gate /*LINTED*/ 840*0Sstevel@tonic-gate w_10 = LOAD_BIG_32(blk + 40); 841*0Sstevel@tonic-gate /*LINTED*/ 842*0Sstevel@tonic-gate w_9 = LOAD_BIG_32(blk + 36); 843*0Sstevel@tonic-gate /*LINTED*/ 844*0Sstevel@tonic-gate w_8 = LOAD_BIG_32(blk + 32); 845*0Sstevel@tonic-gate /*LINTED*/ 846*0Sstevel@tonic-gate w_7 = LOAD_BIG_32(blk + 28); 847*0Sstevel@tonic-gate /*LINTED*/ 848*0Sstevel@tonic-gate w_6 = LOAD_BIG_32(blk + 24); 849*0Sstevel@tonic-gate /*LINTED*/ 850*0Sstevel@tonic-gate w_5 = LOAD_BIG_32(blk + 20); 851*0Sstevel@tonic-gate /*LINTED*/ 852*0Sstevel@tonic-gate w_4 = LOAD_BIG_32(blk + 16); 853*0Sstevel@tonic-gate /*LINTED*/ 854*0Sstevel@tonic-gate w_3 = LOAD_BIG_32(blk + 12); 855*0Sstevel@tonic-gate /*LINTED*/ 856*0Sstevel@tonic-gate w_2 = LOAD_BIG_32(blk + 8); 857*0Sstevel@tonic-gate /*LINTED*/ 858*0Sstevel@tonic-gate w_1 = LOAD_BIG_32(blk + 4); 859*0Sstevel@tonic-gate /*LINTED*/ 860*0Sstevel@tonic-gate w_0 = LOAD_BIG_32(blk + 0); 861*0Sstevel@tonic-gate } 862*0Sstevel@tonic-gate #else 863*0Sstevel@tonic-gate w_15 = LOAD_BIG_32(blk + 60); 864*0Sstevel@tonic-gate w_14 = LOAD_BIG_32(blk + 56); 865*0Sstevel@tonic-gate w_13 = LOAD_BIG_32(blk + 52); 866*0Sstevel@tonic-gate w_12 = LOAD_BIG_32(blk + 48); 867*0Sstevel@tonic-gate w_11 = LOAD_BIG_32(blk + 44); 868*0Sstevel@tonic-gate w_10 = LOAD_BIG_32(blk + 40); 869*0Sstevel@tonic-gate w_9 = LOAD_BIG_32(blk + 36); 870*0Sstevel@tonic-gate w_8 = LOAD_BIG_32(blk + 32); 871*0Sstevel@tonic-gate w_7 = LOAD_BIG_32(blk + 28); 872*0Sstevel@tonic-gate w_6 = LOAD_BIG_32(blk + 24); 873*0Sstevel@tonic-gate w_5 = LOAD_BIG_32(blk + 20); 874*0Sstevel@tonic-gate w_4 = LOAD_BIG_32(blk + 16); 875*0Sstevel@tonic-gate w_3 = LOAD_BIG_32(blk + 12); 876*0Sstevel@tonic-gate w_2 = LOAD_BIG_32(blk + 8); 877*0Sstevel@tonic-gate w_1 = LOAD_BIG_32(blk + 4); 878*0Sstevel@tonic-gate w_0 = LOAD_BIG_32(blk + 0); 879*0Sstevel@tonic-gate #endif 880*0Sstevel@tonic-gate /* 881*0Sstevel@tonic-gate * general optimization: 882*0Sstevel@tonic-gate * 883*0Sstevel@tonic-gate * even though this approach is described in the standard as 884*0Sstevel@tonic-gate * being slower algorithmically, it is 30-40% faster than the 885*0Sstevel@tonic-gate * "faster" version under SPARC, because this version has more 886*0Sstevel@tonic-gate * of the constraints specified at compile-time and uses fewer 887*0Sstevel@tonic-gate * variables (and therefore has better register utilization) 888*0Sstevel@tonic-gate * than its "speedier" brother. (i've tried both, trust me) 889*0Sstevel@tonic-gate * 890*0Sstevel@tonic-gate * for either method given in the spec, there is an "assignment" 891*0Sstevel@tonic-gate * phase where the following takes place: 892*0Sstevel@tonic-gate * 893*0Sstevel@tonic-gate * tmp = (main_computation); 894*0Sstevel@tonic-gate * e = d; d = c; c = rotate_left(b, 30); b = a; a = tmp; 895*0Sstevel@tonic-gate * 896*0Sstevel@tonic-gate * we can make the algorithm go faster by not doing this work, 897*0Sstevel@tonic-gate * but just pretending that `d' is now `e', etc. this works 898*0Sstevel@tonic-gate * really well and obviates the need for a temporary variable. 899*0Sstevel@tonic-gate * however, we still explictly perform the rotate action, 900*0Sstevel@tonic-gate * since it is cheaper on SPARC to do it once than to have to 901*0Sstevel@tonic-gate * do it over and over again. 902*0Sstevel@tonic-gate */ 903*0Sstevel@tonic-gate 904*0Sstevel@tonic-gate /* round 1 */ 905*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + w_0 + SHA1_CONST(0); /* 0 */ 906*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 907*0Sstevel@tonic-gate 908*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + w_1 + SHA1_CONST(0); /* 1 */ 909*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 910*0Sstevel@tonic-gate 911*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + w_2 + SHA1_CONST(0); /* 2 */ 912*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 913*0Sstevel@tonic-gate 914*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + w_3 + SHA1_CONST(0); /* 3 */ 915*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 916*0Sstevel@tonic-gate 917*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + w_4 + SHA1_CONST(0); /* 4 */ 918*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 919*0Sstevel@tonic-gate 920*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + w_5 + SHA1_CONST(0); /* 5 */ 921*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 922*0Sstevel@tonic-gate 923*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + w_6 + SHA1_CONST(0); /* 6 */ 924*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 925*0Sstevel@tonic-gate 926*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + w_7 + SHA1_CONST(0); /* 7 */ 927*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 928*0Sstevel@tonic-gate 929*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + w_8 + SHA1_CONST(0); /* 8 */ 930*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 931*0Sstevel@tonic-gate 932*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + w_9 + SHA1_CONST(0); /* 9 */ 933*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 934*0Sstevel@tonic-gate 935*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + w_10 + SHA1_CONST(0); /* 10 */ 936*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 937*0Sstevel@tonic-gate 938*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + w_11 + SHA1_CONST(0); /* 11 */ 939*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 940*0Sstevel@tonic-gate 941*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + w_12 + SHA1_CONST(0); /* 12 */ 942*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 943*0Sstevel@tonic-gate 944*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + w_13 + SHA1_CONST(0); /* 13 */ 945*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 946*0Sstevel@tonic-gate 947*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + w_14 + SHA1_CONST(0); /* 14 */ 948*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + F(b, c, d) + e + w_15 + SHA1_CONST(0); /* 15 */ 951*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 952*0Sstevel@tonic-gate 953*0Sstevel@tonic-gate w_0 = ROTATE_LEFT((w_13 ^ w_8 ^ w_2 ^ w_0), 1); /* 16 */ 954*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + F(a, b, c) + d + w_0 + SHA1_CONST(0); 955*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 956*0Sstevel@tonic-gate 957*0Sstevel@tonic-gate w_1 = ROTATE_LEFT((w_14 ^ w_9 ^ w_3 ^ w_1), 1); /* 17 */ 958*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + F(e, a, b) + c + w_1 + SHA1_CONST(0); 959*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 960*0Sstevel@tonic-gate 961*0Sstevel@tonic-gate w_2 = ROTATE_LEFT((w_15 ^ w_10 ^ w_4 ^ w_2), 1); /* 18 */ 962*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + F(d, e, a) + b + w_2 + SHA1_CONST(0); 963*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 964*0Sstevel@tonic-gate 965*0Sstevel@tonic-gate w_3 = ROTATE_LEFT((w_0 ^ w_11 ^ w_5 ^ w_3), 1); /* 19 */ 966*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + F(c, d, e) + a + w_3 + SHA1_CONST(0); 967*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 968*0Sstevel@tonic-gate 969*0Sstevel@tonic-gate /* round 2 */ 970*0Sstevel@tonic-gate w_4 = ROTATE_LEFT((w_1 ^ w_12 ^ w_6 ^ w_4), 1); /* 20 */ 971*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_4 + SHA1_CONST(1); 972*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 973*0Sstevel@tonic-gate 974*0Sstevel@tonic-gate w_5 = ROTATE_LEFT((w_2 ^ w_13 ^ w_7 ^ w_5), 1); /* 21 */ 975*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_5 + SHA1_CONST(1); 976*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gate w_6 = ROTATE_LEFT((w_3 ^ w_14 ^ w_8 ^ w_6), 1); /* 22 */ 979*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_6 + SHA1_CONST(1); 980*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 981*0Sstevel@tonic-gate 982*0Sstevel@tonic-gate w_7 = ROTATE_LEFT((w_4 ^ w_15 ^ w_9 ^ w_7), 1); /* 23 */ 983*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_7 + SHA1_CONST(1); 984*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 985*0Sstevel@tonic-gate 986*0Sstevel@tonic-gate w_8 = ROTATE_LEFT((w_5 ^ w_0 ^ w_10 ^ w_8), 1); /* 24 */ 987*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_8 + SHA1_CONST(1); 988*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 989*0Sstevel@tonic-gate 990*0Sstevel@tonic-gate w_9 = ROTATE_LEFT((w_6 ^ w_1 ^ w_11 ^ w_9), 1); /* 25 */ 991*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_9 + SHA1_CONST(1); 992*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 993*0Sstevel@tonic-gate 994*0Sstevel@tonic-gate w_10 = ROTATE_LEFT((w_7 ^ w_2 ^ w_12 ^ w_10), 1); /* 26 */ 995*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_10 + SHA1_CONST(1); 996*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 997*0Sstevel@tonic-gate 998*0Sstevel@tonic-gate w_11 = ROTATE_LEFT((w_8 ^ w_3 ^ w_13 ^ w_11), 1); /* 27 */ 999*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_11 + SHA1_CONST(1); 1000*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 1001*0Sstevel@tonic-gate 1002*0Sstevel@tonic-gate w_12 = ROTATE_LEFT((w_9 ^ w_4 ^ w_14 ^ w_12), 1); /* 28 */ 1003*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_12 + SHA1_CONST(1); 1004*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 1005*0Sstevel@tonic-gate 1006*0Sstevel@tonic-gate w_13 = ROTATE_LEFT((w_10 ^ w_5 ^ w_15 ^ w_13), 1); /* 29 */ 1007*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_13 + SHA1_CONST(1); 1008*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 1009*0Sstevel@tonic-gate 1010*0Sstevel@tonic-gate w_14 = ROTATE_LEFT((w_11 ^ w_6 ^ w_0 ^ w_14), 1); /* 30 */ 1011*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_14 + SHA1_CONST(1); 1012*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 1013*0Sstevel@tonic-gate 1014*0Sstevel@tonic-gate w_15 = ROTATE_LEFT((w_12 ^ w_7 ^ w_1 ^ w_15), 1); /* 31 */ 1015*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_15 + SHA1_CONST(1); 1016*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate w_0 = ROTATE_LEFT((w_13 ^ w_8 ^ w_2 ^ w_0), 1); /* 32 */ 1019*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_0 + SHA1_CONST(1); 1020*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 1021*0Sstevel@tonic-gate 1022*0Sstevel@tonic-gate w_1 = ROTATE_LEFT((w_14 ^ w_9 ^ w_3 ^ w_1), 1); /* 33 */ 1023*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_1 + SHA1_CONST(1); 1024*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 1025*0Sstevel@tonic-gate 1026*0Sstevel@tonic-gate w_2 = ROTATE_LEFT((w_15 ^ w_10 ^ w_4 ^ w_2), 1); /* 34 */ 1027*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_2 + SHA1_CONST(1); 1028*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 1029*0Sstevel@tonic-gate 1030*0Sstevel@tonic-gate w_3 = ROTATE_LEFT((w_0 ^ w_11 ^ w_5 ^ w_3), 1); /* 35 */ 1031*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_3 + SHA1_CONST(1); 1032*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 1033*0Sstevel@tonic-gate 1034*0Sstevel@tonic-gate w_4 = ROTATE_LEFT((w_1 ^ w_12 ^ w_6 ^ w_4), 1); /* 36 */ 1035*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_4 + SHA1_CONST(1); 1036*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 1037*0Sstevel@tonic-gate 1038*0Sstevel@tonic-gate w_5 = ROTATE_LEFT((w_2 ^ w_13 ^ w_7 ^ w_5), 1); /* 37 */ 1039*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_5 + SHA1_CONST(1); 1040*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 1041*0Sstevel@tonic-gate 1042*0Sstevel@tonic-gate w_6 = ROTATE_LEFT((w_3 ^ w_14 ^ w_8 ^ w_6), 1); /* 38 */ 1043*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_6 + SHA1_CONST(1); 1044*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 1045*0Sstevel@tonic-gate 1046*0Sstevel@tonic-gate w_7 = ROTATE_LEFT((w_4 ^ w_15 ^ w_9 ^ w_7), 1); /* 39 */ 1047*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_7 + SHA1_CONST(1); 1048*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 1049*0Sstevel@tonic-gate 1050*0Sstevel@tonic-gate /* round 3 */ 1051*0Sstevel@tonic-gate w_8 = ROTATE_LEFT((w_5 ^ w_0 ^ w_10 ^ w_8), 1); /* 40 */ 1052*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + w_8 + SHA1_CONST(2); 1053*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 1054*0Sstevel@tonic-gate 1055*0Sstevel@tonic-gate w_9 = ROTATE_LEFT((w_6 ^ w_1 ^ w_11 ^ w_9), 1); /* 41 */ 1056*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + w_9 + SHA1_CONST(2); 1057*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 1058*0Sstevel@tonic-gate 1059*0Sstevel@tonic-gate w_10 = ROTATE_LEFT((w_7 ^ w_2 ^ w_12 ^ w_10), 1); /* 42 */ 1060*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + w_10 + SHA1_CONST(2); 1061*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 1062*0Sstevel@tonic-gate 1063*0Sstevel@tonic-gate w_11 = ROTATE_LEFT((w_8 ^ w_3 ^ w_13 ^ w_11), 1); /* 43 */ 1064*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + w_11 + SHA1_CONST(2); 1065*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 1066*0Sstevel@tonic-gate 1067*0Sstevel@tonic-gate w_12 = ROTATE_LEFT((w_9 ^ w_4 ^ w_14 ^ w_12), 1); /* 44 */ 1068*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + w_12 + SHA1_CONST(2); 1069*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 1070*0Sstevel@tonic-gate 1071*0Sstevel@tonic-gate w_13 = ROTATE_LEFT((w_10 ^ w_5 ^ w_15 ^ w_13), 1); /* 45 */ 1072*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + w_13 + SHA1_CONST(2); 1073*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate w_14 = ROTATE_LEFT((w_11 ^ w_6 ^ w_0 ^ w_14), 1); /* 46 */ 1076*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + w_14 + SHA1_CONST(2); 1077*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 1078*0Sstevel@tonic-gate 1079*0Sstevel@tonic-gate w_15 = ROTATE_LEFT((w_12 ^ w_7 ^ w_1 ^ w_15), 1); /* 47 */ 1080*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + w_15 + SHA1_CONST(2); 1081*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 1082*0Sstevel@tonic-gate 1083*0Sstevel@tonic-gate w_0 = ROTATE_LEFT((w_13 ^ w_8 ^ w_2 ^ w_0), 1); /* 48 */ 1084*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + w_0 + SHA1_CONST(2); 1085*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 1086*0Sstevel@tonic-gate 1087*0Sstevel@tonic-gate w_1 = ROTATE_LEFT((w_14 ^ w_9 ^ w_3 ^ w_1), 1); /* 49 */ 1088*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + w_1 + SHA1_CONST(2); 1089*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 1090*0Sstevel@tonic-gate 1091*0Sstevel@tonic-gate w_2 = ROTATE_LEFT((w_15 ^ w_10 ^ w_4 ^ w_2), 1); /* 50 */ 1092*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + w_2 + SHA1_CONST(2); 1093*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 1094*0Sstevel@tonic-gate 1095*0Sstevel@tonic-gate w_3 = ROTATE_LEFT((w_0 ^ w_11 ^ w_5 ^ w_3), 1); /* 51 */ 1096*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + w_3 + SHA1_CONST(2); 1097*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate w_4 = ROTATE_LEFT((w_1 ^ w_12 ^ w_6 ^ w_4), 1); /* 52 */ 1100*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + w_4 + SHA1_CONST(2); 1101*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 1102*0Sstevel@tonic-gate 1103*0Sstevel@tonic-gate w_5 = ROTATE_LEFT((w_2 ^ w_13 ^ w_7 ^ w_5), 1); /* 53 */ 1104*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + w_5 + SHA1_CONST(2); 1105*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 1106*0Sstevel@tonic-gate 1107*0Sstevel@tonic-gate w_6 = ROTATE_LEFT((w_3 ^ w_14 ^ w_8 ^ w_6), 1); /* 54 */ 1108*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + w_6 + SHA1_CONST(2); 1109*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 1110*0Sstevel@tonic-gate 1111*0Sstevel@tonic-gate w_7 = ROTATE_LEFT((w_4 ^ w_15 ^ w_9 ^ w_7), 1); /* 55 */ 1112*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + H(b, c, d) + e + w_7 + SHA1_CONST(2); 1113*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 1114*0Sstevel@tonic-gate 1115*0Sstevel@tonic-gate w_8 = ROTATE_LEFT((w_5 ^ w_0 ^ w_10 ^ w_8), 1); /* 56 */ 1116*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + H(a, b, c) + d + w_8 + SHA1_CONST(2); 1117*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 1118*0Sstevel@tonic-gate 1119*0Sstevel@tonic-gate w_9 = ROTATE_LEFT((w_6 ^ w_1 ^ w_11 ^ w_9), 1); /* 57 */ 1120*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + H(e, a, b) + c + w_9 + SHA1_CONST(2); 1121*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gate w_10 = ROTATE_LEFT((w_7 ^ w_2 ^ w_12 ^ w_10), 1); /* 58 */ 1124*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + H(d, e, a) + b + w_10 + SHA1_CONST(2); 1125*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 1126*0Sstevel@tonic-gate 1127*0Sstevel@tonic-gate w_11 = ROTATE_LEFT((w_8 ^ w_3 ^ w_13 ^ w_11), 1); /* 59 */ 1128*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + H(c, d, e) + a + w_11 + SHA1_CONST(2); 1129*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 1130*0Sstevel@tonic-gate 1131*0Sstevel@tonic-gate /* round 4 */ 1132*0Sstevel@tonic-gate w_12 = ROTATE_LEFT((w_9 ^ w_4 ^ w_14 ^ w_12), 1); /* 60 */ 1133*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_12 + SHA1_CONST(3); 1134*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 1135*0Sstevel@tonic-gate 1136*0Sstevel@tonic-gate w_13 = ROTATE_LEFT((w_10 ^ w_5 ^ w_15 ^ w_13), 1); /* 61 */ 1137*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_13 + SHA1_CONST(3); 1138*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 1139*0Sstevel@tonic-gate 1140*0Sstevel@tonic-gate w_14 = ROTATE_LEFT((w_11 ^ w_6 ^ w_0 ^ w_14), 1); /* 62 */ 1141*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_14 + SHA1_CONST(3); 1142*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 1143*0Sstevel@tonic-gate 1144*0Sstevel@tonic-gate w_15 = ROTATE_LEFT((w_12 ^ w_7 ^ w_1 ^ w_15), 1); /* 63 */ 1145*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_15 + SHA1_CONST(3); 1146*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 1147*0Sstevel@tonic-gate 1148*0Sstevel@tonic-gate w_0 = ROTATE_LEFT((w_13 ^ w_8 ^ w_2 ^ w_0), 1); /* 64 */ 1149*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_0 + SHA1_CONST(3); 1150*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 1151*0Sstevel@tonic-gate 1152*0Sstevel@tonic-gate w_1 = ROTATE_LEFT((w_14 ^ w_9 ^ w_3 ^ w_1), 1); /* 65 */ 1153*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_1 + SHA1_CONST(3); 1154*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate w_2 = ROTATE_LEFT((w_15 ^ w_10 ^ w_4 ^ w_2), 1); /* 66 */ 1157*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_2 + SHA1_CONST(3); 1158*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 1159*0Sstevel@tonic-gate 1160*0Sstevel@tonic-gate w_3 = ROTATE_LEFT((w_0 ^ w_11 ^ w_5 ^ w_3), 1); /* 67 */ 1161*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_3 + SHA1_CONST(3); 1162*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 1163*0Sstevel@tonic-gate 1164*0Sstevel@tonic-gate w_4 = ROTATE_LEFT((w_1 ^ w_12 ^ w_6 ^ w_4), 1); /* 68 */ 1165*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_4 + SHA1_CONST(3); 1166*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 1167*0Sstevel@tonic-gate 1168*0Sstevel@tonic-gate w_5 = ROTATE_LEFT((w_2 ^ w_13 ^ w_7 ^ w_5), 1); /* 69 */ 1169*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_5 + SHA1_CONST(3); 1170*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 1171*0Sstevel@tonic-gate 1172*0Sstevel@tonic-gate w_6 = ROTATE_LEFT((w_3 ^ w_14 ^ w_8 ^ w_6), 1); /* 70 */ 1173*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_6 + SHA1_CONST(3); 1174*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 1175*0Sstevel@tonic-gate 1176*0Sstevel@tonic-gate w_7 = ROTATE_LEFT((w_4 ^ w_15 ^ w_9 ^ w_7), 1); /* 71 */ 1177*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_7 + SHA1_CONST(3); 1178*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 1179*0Sstevel@tonic-gate 1180*0Sstevel@tonic-gate w_8 = ROTATE_LEFT((w_5 ^ w_0 ^ w_10 ^ w_8), 1); /* 72 */ 1181*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_8 + SHA1_CONST(3); 1182*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 1183*0Sstevel@tonic-gate 1184*0Sstevel@tonic-gate w_9 = ROTATE_LEFT((w_6 ^ w_1 ^ w_11 ^ w_9), 1); /* 73 */ 1185*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_9 + SHA1_CONST(3); 1186*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 1187*0Sstevel@tonic-gate 1188*0Sstevel@tonic-gate w_10 = ROTATE_LEFT((w_7 ^ w_2 ^ w_12 ^ w_10), 1); /* 74 */ 1189*0Sstevel@tonic-gate a = ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_10 + SHA1_CONST(3); 1190*0Sstevel@tonic-gate c = ROTATE_LEFT(c, 30); 1191*0Sstevel@tonic-gate 1192*0Sstevel@tonic-gate w_11 = ROTATE_LEFT((w_8 ^ w_3 ^ w_13 ^ w_11), 1); /* 75 */ 1193*0Sstevel@tonic-gate e = ROTATE_LEFT(a, 5) + G(b, c, d) + e + w_11 + SHA1_CONST(3); 1194*0Sstevel@tonic-gate b = ROTATE_LEFT(b, 30); 1195*0Sstevel@tonic-gate 1196*0Sstevel@tonic-gate w_12 = ROTATE_LEFT((w_9 ^ w_4 ^ w_14 ^ w_12), 1); /* 76 */ 1197*0Sstevel@tonic-gate d = ROTATE_LEFT(e, 5) + G(a, b, c) + d + w_12 + SHA1_CONST(3); 1198*0Sstevel@tonic-gate a = ROTATE_LEFT(a, 30); 1199*0Sstevel@tonic-gate 1200*0Sstevel@tonic-gate w_13 = ROTATE_LEFT((w_10 ^ w_5 ^ w_15 ^ w_13), 1); /* 77 */ 1201*0Sstevel@tonic-gate c = ROTATE_LEFT(d, 5) + G(e, a, b) + c + w_13 + SHA1_CONST(3); 1202*0Sstevel@tonic-gate e = ROTATE_LEFT(e, 30); 1203*0Sstevel@tonic-gate 1204*0Sstevel@tonic-gate w_14 = ROTATE_LEFT((w_11 ^ w_6 ^ w_0 ^ w_14), 1); /* 78 */ 1205*0Sstevel@tonic-gate b = ROTATE_LEFT(c, 5) + G(d, e, a) + b + w_14 + SHA1_CONST(3); 1206*0Sstevel@tonic-gate d = ROTATE_LEFT(d, 30); 1207*0Sstevel@tonic-gate 1208*0Sstevel@tonic-gate w_15 = ROTATE_LEFT((w_12 ^ w_7 ^ w_1 ^ w_15), 1); /* 79 */ 1209*0Sstevel@tonic-gate 1210*0Sstevel@tonic-gate ctx->state[0] += ROTATE_LEFT(b, 5) + G(c, d, e) + a + w_15 + 1211*0Sstevel@tonic-gate SHA1_CONST(3); 1212*0Sstevel@tonic-gate ctx->state[1] += b; 1213*0Sstevel@tonic-gate ctx->state[2] += ROTATE_LEFT(c, 30); 1214*0Sstevel@tonic-gate ctx->state[3] += d; 1215*0Sstevel@tonic-gate ctx->state[4] += e; 1216*0Sstevel@tonic-gate 1217*0Sstevel@tonic-gate /* zeroize sensitive information */ 1218*0Sstevel@tonic-gate w_0 = w_1 = w_2 = w_3 = w_4 = w_5 = w_6 = w_7 = w_8 = 0; 1219*0Sstevel@tonic-gate w_9 = w_10 = w_11 = w_12 = w_13 = w_14 = w_15 = 0; 1220*0Sstevel@tonic-gate } 1221*0Sstevel@tonic-gate 1222*0Sstevel@tonic-gate /* 1223*0Sstevel@tonic-gate * devpro compiler optimization: 1224*0Sstevel@tonic-gate * 1225*0Sstevel@tonic-gate * the compiler can generate better code if it knows that `input' and 1226*0Sstevel@tonic-gate * `output' do not point to the same source. there is no portable 1227*0Sstevel@tonic-gate * way to tell the compiler this, but the sun compiler recognizes the 1228*0Sstevel@tonic-gate * `_Restrict' keyword to indicate this condition. use it if possible. 1229*0Sstevel@tonic-gate */ 1230*0Sstevel@tonic-gate 1231*0Sstevel@tonic-gate #ifdef __RESTRICT 1232*0Sstevel@tonic-gate #define restrict _Restrict 1233*0Sstevel@tonic-gate #else 1234*0Sstevel@tonic-gate #define restrict /* nothing */ 1235*0Sstevel@tonic-gate #endif 1236*0Sstevel@tonic-gate 1237*0Sstevel@tonic-gate /* 1238*0Sstevel@tonic-gate * Encode() 1239*0Sstevel@tonic-gate * 1240*0Sstevel@tonic-gate * purpose: to convert a list of numbers from little endian to big endian 1241*0Sstevel@tonic-gate * input: uint8_t * : place to store the converted big endian numbers 1242*0Sstevel@tonic-gate * uint32_t * : place to get numbers to convert from 1243*0Sstevel@tonic-gate * size_t : the length of the input in bytes 1244*0Sstevel@tonic-gate * output: void 1245*0Sstevel@tonic-gate */ 1246*0Sstevel@tonic-gate 1247*0Sstevel@tonic-gate static void 1248*0Sstevel@tonic-gate Encode(uint8_t *restrict output, uint32_t *restrict input, size_t len) 1249*0Sstevel@tonic-gate { 1250*0Sstevel@tonic-gate size_t i, j; 1251*0Sstevel@tonic-gate 1252*0Sstevel@tonic-gate #if defined(__sparc) 1253*0Sstevel@tonic-gate if (IS_P2ALIGNED(output, sizeof (uint32_t))) { 1254*0Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4) { 1255*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1256*0Sstevel@tonic-gate *((uint32_t *)(output + j)) = input[i]; 1257*0Sstevel@tonic-gate } 1258*0Sstevel@tonic-gate } else { 1259*0Sstevel@tonic-gate #endif /* little endian -- will work on big endian, but slowly */ 1260*0Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4) { 1261*0Sstevel@tonic-gate output[j] = (input[i] >> 24) & 0xff; 1262*0Sstevel@tonic-gate output[j + 1] = (input[i] >> 16) & 0xff; 1263*0Sstevel@tonic-gate output[j + 2] = (input[i] >> 8) & 0xff; 1264*0Sstevel@tonic-gate output[j + 3] = input[i] & 0xff; 1265*0Sstevel@tonic-gate } 1266*0Sstevel@tonic-gate #if defined(__sparc) 1267*0Sstevel@tonic-gate } 1268*0Sstevel@tonic-gate #endif 1269*0Sstevel@tonic-gate } 1270*0Sstevel@tonic-gate 1271*0Sstevel@tonic-gate 1272*0Sstevel@tonic-gate #ifdef _KERNEL 1273*0Sstevel@tonic-gate 1274*0Sstevel@tonic-gate /* 1275*0Sstevel@tonic-gate * KCF software provider control entry points. 1276*0Sstevel@tonic-gate */ 1277*0Sstevel@tonic-gate /* ARGSUSED */ 1278*0Sstevel@tonic-gate static void 1279*0Sstevel@tonic-gate sha1_provider_status(crypto_provider_handle_t provider, uint_t *status) 1280*0Sstevel@tonic-gate { 1281*0Sstevel@tonic-gate *status = CRYPTO_PROVIDER_READY; 1282*0Sstevel@tonic-gate } 1283*0Sstevel@tonic-gate 1284*0Sstevel@tonic-gate /* 1285*0Sstevel@tonic-gate * KCF software provider digest entry points. 1286*0Sstevel@tonic-gate */ 1287*0Sstevel@tonic-gate 1288*0Sstevel@tonic-gate static int 1289*0Sstevel@tonic-gate sha1_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 1290*0Sstevel@tonic-gate crypto_req_handle_t req) 1291*0Sstevel@tonic-gate { 1292*0Sstevel@tonic-gate if (mechanism->cm_type != SHA1_MECH_INFO_TYPE) 1293*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 1294*0Sstevel@tonic-gate 1295*0Sstevel@tonic-gate /* 1296*0Sstevel@tonic-gate * Allocate and initialize SHA1 context. 1297*0Sstevel@tonic-gate */ 1298*0Sstevel@tonic-gate ctx->cc_provider_private = kmem_alloc(sizeof (sha1_ctx_t), 1299*0Sstevel@tonic-gate crypto_kmflag(req)); 1300*0Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 1301*0Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 1302*0Sstevel@tonic-gate 1303*0Sstevel@tonic-gate PROV_SHA1_CTX(ctx)->sc_mech_type = SHA1_MECH_INFO_TYPE; 1304*0Sstevel@tonic-gate SHA1Init(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx); 1305*0Sstevel@tonic-gate 1306*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 1307*0Sstevel@tonic-gate } 1308*0Sstevel@tonic-gate 1309*0Sstevel@tonic-gate /* 1310*0Sstevel@tonic-gate * Helper SHA1 digest update function for uio data. 1311*0Sstevel@tonic-gate */ 1312*0Sstevel@tonic-gate static int 1313*0Sstevel@tonic-gate sha1_digest_update_uio(SHA1_CTX *sha1_ctx, crypto_data_t *data) 1314*0Sstevel@tonic-gate { 1315*0Sstevel@tonic-gate off_t offset = data->cd_offset; 1316*0Sstevel@tonic-gate size_t length = data->cd_length; 1317*0Sstevel@tonic-gate uint_t vec_idx; 1318*0Sstevel@tonic-gate size_t cur_len; 1319*0Sstevel@tonic-gate 1320*0Sstevel@tonic-gate /* we support only kernel buffer */ 1321*0Sstevel@tonic-gate if (data->cd_uio->uio_segflg != UIO_SYSSPACE) 1322*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 1323*0Sstevel@tonic-gate 1324*0Sstevel@tonic-gate /* 1325*0Sstevel@tonic-gate * Jump to the first iovec containing data to be 1326*0Sstevel@tonic-gate * digested. 1327*0Sstevel@tonic-gate */ 1328*0Sstevel@tonic-gate for (vec_idx = 0; vec_idx < data->cd_uio->uio_iovcnt && 1329*0Sstevel@tonic-gate offset >= data->cd_uio->uio_iov[vec_idx].iov_len; 1330*0Sstevel@tonic-gate offset -= data->cd_uio->uio_iov[vec_idx++].iov_len); 1331*0Sstevel@tonic-gate if (vec_idx == data->cd_uio->uio_iovcnt) { 1332*0Sstevel@tonic-gate /* 1333*0Sstevel@tonic-gate * The caller specified an offset that is larger than the 1334*0Sstevel@tonic-gate * total size of the buffers it provided. 1335*0Sstevel@tonic-gate */ 1336*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 1337*0Sstevel@tonic-gate } 1338*0Sstevel@tonic-gate 1339*0Sstevel@tonic-gate /* 1340*0Sstevel@tonic-gate * Now do the digesting on the iovecs. 1341*0Sstevel@tonic-gate */ 1342*0Sstevel@tonic-gate while (vec_idx < data->cd_uio->uio_iovcnt && length > 0) { 1343*0Sstevel@tonic-gate cur_len = MIN(data->cd_uio->uio_iov[vec_idx].iov_len - 1344*0Sstevel@tonic-gate offset, length); 1345*0Sstevel@tonic-gate 1346*0Sstevel@tonic-gate SHA1Update(sha1_ctx, 1347*0Sstevel@tonic-gate (uint8_t *)data->cd_uio->uio_iov[vec_idx].iov_base + offset, 1348*0Sstevel@tonic-gate cur_len); 1349*0Sstevel@tonic-gate 1350*0Sstevel@tonic-gate length -= cur_len; 1351*0Sstevel@tonic-gate vec_idx++; 1352*0Sstevel@tonic-gate offset = 0; 1353*0Sstevel@tonic-gate } 1354*0Sstevel@tonic-gate 1355*0Sstevel@tonic-gate if (vec_idx == data->cd_uio->uio_iovcnt && length > 0) { 1356*0Sstevel@tonic-gate /* 1357*0Sstevel@tonic-gate * The end of the specified iovec's was reached but 1358*0Sstevel@tonic-gate * the length requested could not be processed, i.e. 1359*0Sstevel@tonic-gate * The caller requested to digest more data than it provided. 1360*0Sstevel@tonic-gate */ 1361*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 1362*0Sstevel@tonic-gate } 1363*0Sstevel@tonic-gate 1364*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 1365*0Sstevel@tonic-gate } 1366*0Sstevel@tonic-gate 1367*0Sstevel@tonic-gate /* 1368*0Sstevel@tonic-gate * Helper SHA1 digest final function for uio data. 1369*0Sstevel@tonic-gate * digest_len is the length of the desired digest. If digest_len 1370*0Sstevel@tonic-gate * is smaller than the default SHA1 digest length, the caller 1371*0Sstevel@tonic-gate * must pass a scratch buffer, digest_scratch, which must 1372*0Sstevel@tonic-gate * be at least SHA1_DIGEST_LENGTH bytes. 1373*0Sstevel@tonic-gate */ 1374*0Sstevel@tonic-gate static int 1375*0Sstevel@tonic-gate sha1_digest_final_uio(SHA1_CTX *sha1_ctx, crypto_data_t *digest, 1376*0Sstevel@tonic-gate ulong_t digest_len, uchar_t *digest_scratch) 1377*0Sstevel@tonic-gate { 1378*0Sstevel@tonic-gate off_t offset = digest->cd_offset; 1379*0Sstevel@tonic-gate uint_t vec_idx; 1380*0Sstevel@tonic-gate 1381*0Sstevel@tonic-gate /* we support only kernel buffer */ 1382*0Sstevel@tonic-gate if (digest->cd_uio->uio_segflg != UIO_SYSSPACE) 1383*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate /* 1386*0Sstevel@tonic-gate * Jump to the first iovec containing ptr to the digest to 1387*0Sstevel@tonic-gate * be returned. 1388*0Sstevel@tonic-gate */ 1389*0Sstevel@tonic-gate for (vec_idx = 0; offset >= digest->cd_uio->uio_iov[vec_idx].iov_len && 1390*0Sstevel@tonic-gate vec_idx < digest->cd_uio->uio_iovcnt; 1391*0Sstevel@tonic-gate offset -= digest->cd_uio->uio_iov[vec_idx++].iov_len); 1392*0Sstevel@tonic-gate if (vec_idx == digest->cd_uio->uio_iovcnt) { 1393*0Sstevel@tonic-gate /* 1394*0Sstevel@tonic-gate * The caller specified an offset that is 1395*0Sstevel@tonic-gate * larger than the total size of the buffers 1396*0Sstevel@tonic-gate * it provided. 1397*0Sstevel@tonic-gate */ 1398*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 1399*0Sstevel@tonic-gate } 1400*0Sstevel@tonic-gate 1401*0Sstevel@tonic-gate if (offset + digest_len <= 1402*0Sstevel@tonic-gate digest->cd_uio->uio_iov[vec_idx].iov_len) { 1403*0Sstevel@tonic-gate /* 1404*0Sstevel@tonic-gate * The computed SHA1 digest will fit in the current 1405*0Sstevel@tonic-gate * iovec. 1406*0Sstevel@tonic-gate */ 1407*0Sstevel@tonic-gate if (digest_len != SHA1_DIGEST_LENGTH) { 1408*0Sstevel@tonic-gate /* 1409*0Sstevel@tonic-gate * The caller requested a short digest. Digest 1410*0Sstevel@tonic-gate * into a scratch buffer and return to 1411*0Sstevel@tonic-gate * the user only what was requested. 1412*0Sstevel@tonic-gate */ 1413*0Sstevel@tonic-gate SHA1Final(digest_scratch, sha1_ctx); 1414*0Sstevel@tonic-gate bcopy(digest_scratch, (uchar_t *)digest-> 1415*0Sstevel@tonic-gate cd_uio->uio_iov[vec_idx].iov_base + offset, 1416*0Sstevel@tonic-gate digest_len); 1417*0Sstevel@tonic-gate } else { 1418*0Sstevel@tonic-gate SHA1Final((uchar_t *)digest-> 1419*0Sstevel@tonic-gate cd_uio->uio_iov[vec_idx].iov_base + offset, 1420*0Sstevel@tonic-gate sha1_ctx); 1421*0Sstevel@tonic-gate } 1422*0Sstevel@tonic-gate } else { 1423*0Sstevel@tonic-gate /* 1424*0Sstevel@tonic-gate * The computed digest will be crossing one or more iovec's. 1425*0Sstevel@tonic-gate * This is bad performance-wise but we need to support it. 1426*0Sstevel@tonic-gate * Allocate a small scratch buffer on the stack and 1427*0Sstevel@tonic-gate * copy it piece meal to the specified digest iovec's. 1428*0Sstevel@tonic-gate */ 1429*0Sstevel@tonic-gate uchar_t digest_tmp[SHA1_DIGEST_LENGTH]; 1430*0Sstevel@tonic-gate off_t scratch_offset = 0; 1431*0Sstevel@tonic-gate size_t length = digest_len; 1432*0Sstevel@tonic-gate size_t cur_len; 1433*0Sstevel@tonic-gate 1434*0Sstevel@tonic-gate SHA1Final(digest_tmp, sha1_ctx); 1435*0Sstevel@tonic-gate 1436*0Sstevel@tonic-gate while (vec_idx < digest->cd_uio->uio_iovcnt && length > 0) { 1437*0Sstevel@tonic-gate cur_len = MIN(digest->cd_uio->uio_iov[vec_idx].iov_len - 1438*0Sstevel@tonic-gate offset, length); 1439*0Sstevel@tonic-gate bcopy(digest_tmp + scratch_offset, 1440*0Sstevel@tonic-gate digest->cd_uio->uio_iov[vec_idx].iov_base + offset, 1441*0Sstevel@tonic-gate cur_len); 1442*0Sstevel@tonic-gate 1443*0Sstevel@tonic-gate length -= cur_len; 1444*0Sstevel@tonic-gate vec_idx++; 1445*0Sstevel@tonic-gate scratch_offset += cur_len; 1446*0Sstevel@tonic-gate offset = 0; 1447*0Sstevel@tonic-gate } 1448*0Sstevel@tonic-gate 1449*0Sstevel@tonic-gate if (vec_idx == digest->cd_uio->uio_iovcnt && length > 0) { 1450*0Sstevel@tonic-gate /* 1451*0Sstevel@tonic-gate * The end of the specified iovec's was reached but 1452*0Sstevel@tonic-gate * the length requested could not be processed, i.e. 1453*0Sstevel@tonic-gate * The caller requested to digest more data than it 1454*0Sstevel@tonic-gate * provided. 1455*0Sstevel@tonic-gate */ 1456*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 1457*0Sstevel@tonic-gate } 1458*0Sstevel@tonic-gate } 1459*0Sstevel@tonic-gate 1460*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 1461*0Sstevel@tonic-gate } 1462*0Sstevel@tonic-gate 1463*0Sstevel@tonic-gate /* 1464*0Sstevel@tonic-gate * Helper SHA1 digest update for mblk's. 1465*0Sstevel@tonic-gate */ 1466*0Sstevel@tonic-gate static int 1467*0Sstevel@tonic-gate sha1_digest_update_mblk(SHA1_CTX *sha1_ctx, crypto_data_t *data) 1468*0Sstevel@tonic-gate { 1469*0Sstevel@tonic-gate off_t offset = data->cd_offset; 1470*0Sstevel@tonic-gate size_t length = data->cd_length; 1471*0Sstevel@tonic-gate mblk_t *mp; 1472*0Sstevel@tonic-gate size_t cur_len; 1473*0Sstevel@tonic-gate 1474*0Sstevel@tonic-gate /* 1475*0Sstevel@tonic-gate * Jump to the first mblk_t containing data to be digested. 1476*0Sstevel@tonic-gate */ 1477*0Sstevel@tonic-gate for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp); 1478*0Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 1479*0Sstevel@tonic-gate if (mp == NULL) { 1480*0Sstevel@tonic-gate /* 1481*0Sstevel@tonic-gate * The caller specified an offset that is larger than the 1482*0Sstevel@tonic-gate * total size of the buffers it provided. 1483*0Sstevel@tonic-gate */ 1484*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 1485*0Sstevel@tonic-gate } 1486*0Sstevel@tonic-gate 1487*0Sstevel@tonic-gate /* 1488*0Sstevel@tonic-gate * Now do the digesting on the mblk chain. 1489*0Sstevel@tonic-gate */ 1490*0Sstevel@tonic-gate while (mp != NULL && length > 0) { 1491*0Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 1492*0Sstevel@tonic-gate SHA1Update(sha1_ctx, mp->b_rptr + offset, cur_len); 1493*0Sstevel@tonic-gate length -= cur_len; 1494*0Sstevel@tonic-gate offset = 0; 1495*0Sstevel@tonic-gate mp = mp->b_cont; 1496*0Sstevel@tonic-gate } 1497*0Sstevel@tonic-gate 1498*0Sstevel@tonic-gate if (mp == NULL && length > 0) { 1499*0Sstevel@tonic-gate /* 1500*0Sstevel@tonic-gate * The end of the mblk was reached but the length requested 1501*0Sstevel@tonic-gate * could not be processed, i.e. The caller requested 1502*0Sstevel@tonic-gate * to digest more data than it provided. 1503*0Sstevel@tonic-gate */ 1504*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 1505*0Sstevel@tonic-gate } 1506*0Sstevel@tonic-gate 1507*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 1508*0Sstevel@tonic-gate } 1509*0Sstevel@tonic-gate 1510*0Sstevel@tonic-gate /* 1511*0Sstevel@tonic-gate * Helper SHA1 digest final for mblk's. 1512*0Sstevel@tonic-gate * digest_len is the length of the desired digest. If digest_len 1513*0Sstevel@tonic-gate * is smaller than the default SHA1 digest length, the caller 1514*0Sstevel@tonic-gate * must pass a scratch buffer, digest_scratch, which must 1515*0Sstevel@tonic-gate * be at least SHA1_DIGEST_LENGTH bytes. 1516*0Sstevel@tonic-gate */ 1517*0Sstevel@tonic-gate static int 1518*0Sstevel@tonic-gate sha1_digest_final_mblk(SHA1_CTX *sha1_ctx, crypto_data_t *digest, 1519*0Sstevel@tonic-gate ulong_t digest_len, uchar_t *digest_scratch) 1520*0Sstevel@tonic-gate { 1521*0Sstevel@tonic-gate off_t offset = digest->cd_offset; 1522*0Sstevel@tonic-gate mblk_t *mp; 1523*0Sstevel@tonic-gate 1524*0Sstevel@tonic-gate /* 1525*0Sstevel@tonic-gate * Jump to the first mblk_t that will be used to store the digest. 1526*0Sstevel@tonic-gate */ 1527*0Sstevel@tonic-gate for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp); 1528*0Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 1529*0Sstevel@tonic-gate if (mp == NULL) { 1530*0Sstevel@tonic-gate /* 1531*0Sstevel@tonic-gate * The caller specified an offset that is larger than the 1532*0Sstevel@tonic-gate * total size of the buffers it provided. 1533*0Sstevel@tonic-gate */ 1534*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 1535*0Sstevel@tonic-gate } 1536*0Sstevel@tonic-gate 1537*0Sstevel@tonic-gate if (offset + digest_len <= MBLKL(mp)) { 1538*0Sstevel@tonic-gate /* 1539*0Sstevel@tonic-gate * The computed SHA1 digest will fit in the current mblk. 1540*0Sstevel@tonic-gate * Do the SHA1Final() in-place. 1541*0Sstevel@tonic-gate */ 1542*0Sstevel@tonic-gate if (digest_len != SHA1_DIGEST_LENGTH) { 1543*0Sstevel@tonic-gate /* 1544*0Sstevel@tonic-gate * The caller requested a short digest. Digest 1545*0Sstevel@tonic-gate * into a scratch buffer and return to 1546*0Sstevel@tonic-gate * the user only what was requested. 1547*0Sstevel@tonic-gate */ 1548*0Sstevel@tonic-gate SHA1Final(digest_scratch, sha1_ctx); 1549*0Sstevel@tonic-gate bcopy(digest_scratch, mp->b_rptr + offset, digest_len); 1550*0Sstevel@tonic-gate } else { 1551*0Sstevel@tonic-gate SHA1Final(mp->b_rptr + offset, sha1_ctx); 1552*0Sstevel@tonic-gate } 1553*0Sstevel@tonic-gate } else { 1554*0Sstevel@tonic-gate /* 1555*0Sstevel@tonic-gate * The computed digest will be crossing one or more mblk's. 1556*0Sstevel@tonic-gate * This is bad performance-wise but we need to support it. 1557*0Sstevel@tonic-gate * Allocate a small scratch buffer on the stack and 1558*0Sstevel@tonic-gate * copy it piece meal to the specified digest iovec's. 1559*0Sstevel@tonic-gate */ 1560*0Sstevel@tonic-gate uchar_t digest_tmp[SHA1_DIGEST_LENGTH]; 1561*0Sstevel@tonic-gate off_t scratch_offset = 0; 1562*0Sstevel@tonic-gate size_t length = digest_len; 1563*0Sstevel@tonic-gate size_t cur_len; 1564*0Sstevel@tonic-gate 1565*0Sstevel@tonic-gate SHA1Final(digest_tmp, sha1_ctx); 1566*0Sstevel@tonic-gate 1567*0Sstevel@tonic-gate while (mp != NULL && length > 0) { 1568*0Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 1569*0Sstevel@tonic-gate bcopy(digest_tmp + scratch_offset, 1570*0Sstevel@tonic-gate mp->b_rptr + offset, cur_len); 1571*0Sstevel@tonic-gate 1572*0Sstevel@tonic-gate length -= cur_len; 1573*0Sstevel@tonic-gate mp = mp->b_cont; 1574*0Sstevel@tonic-gate scratch_offset += cur_len; 1575*0Sstevel@tonic-gate offset = 0; 1576*0Sstevel@tonic-gate } 1577*0Sstevel@tonic-gate 1578*0Sstevel@tonic-gate if (mp == NULL && length > 0) { 1579*0Sstevel@tonic-gate /* 1580*0Sstevel@tonic-gate * The end of the specified mblk was reached but 1581*0Sstevel@tonic-gate * the length requested could not be processed, i.e. 1582*0Sstevel@tonic-gate * The caller requested to digest more data than it 1583*0Sstevel@tonic-gate * provided. 1584*0Sstevel@tonic-gate */ 1585*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 1586*0Sstevel@tonic-gate } 1587*0Sstevel@tonic-gate } 1588*0Sstevel@tonic-gate 1589*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 1590*0Sstevel@tonic-gate } 1591*0Sstevel@tonic-gate 1592*0Sstevel@tonic-gate /* ARGSUSED */ 1593*0Sstevel@tonic-gate static int 1594*0Sstevel@tonic-gate sha1_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest, 1595*0Sstevel@tonic-gate crypto_req_handle_t req) 1596*0Sstevel@tonic-gate { 1597*0Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 1598*0Sstevel@tonic-gate 1599*0Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 1600*0Sstevel@tonic-gate 1601*0Sstevel@tonic-gate /* 1602*0Sstevel@tonic-gate * We need to just return the length needed to store the output. 1603*0Sstevel@tonic-gate * We should not destroy the context for the following cases. 1604*0Sstevel@tonic-gate */ 1605*0Sstevel@tonic-gate if ((digest->cd_length == 0) || 1606*0Sstevel@tonic-gate (digest->cd_length < SHA1_DIGEST_LENGTH)) { 1607*0Sstevel@tonic-gate digest->cd_length = SHA1_DIGEST_LENGTH; 1608*0Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 1609*0Sstevel@tonic-gate } 1610*0Sstevel@tonic-gate 1611*0Sstevel@tonic-gate /* 1612*0Sstevel@tonic-gate * Do the SHA1 update on the specified input data. 1613*0Sstevel@tonic-gate */ 1614*0Sstevel@tonic-gate switch (data->cd_format) { 1615*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 1616*0Sstevel@tonic-gate SHA1Update(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 1617*0Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 1618*0Sstevel@tonic-gate data->cd_length); 1619*0Sstevel@tonic-gate break; 1620*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 1621*0Sstevel@tonic-gate ret = sha1_digest_update_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 1622*0Sstevel@tonic-gate data); 1623*0Sstevel@tonic-gate break; 1624*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 1625*0Sstevel@tonic-gate ret = sha1_digest_update_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 1626*0Sstevel@tonic-gate data); 1627*0Sstevel@tonic-gate break; 1628*0Sstevel@tonic-gate default: 1629*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 1630*0Sstevel@tonic-gate } 1631*0Sstevel@tonic-gate 1632*0Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 1633*0Sstevel@tonic-gate /* the update failed, free context and bail */ 1634*0Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t)); 1635*0Sstevel@tonic-gate ctx->cc_provider_private = NULL; 1636*0Sstevel@tonic-gate digest->cd_length = 0; 1637*0Sstevel@tonic-gate return (ret); 1638*0Sstevel@tonic-gate } 1639*0Sstevel@tonic-gate 1640*0Sstevel@tonic-gate /* 1641*0Sstevel@tonic-gate * Do a SHA1 final, must be done separately since the digest 1642*0Sstevel@tonic-gate * type can be different than the input data type. 1643*0Sstevel@tonic-gate */ 1644*0Sstevel@tonic-gate switch (digest->cd_format) { 1645*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 1646*0Sstevel@tonic-gate SHA1Final((unsigned char *)digest->cd_raw.iov_base + 1647*0Sstevel@tonic-gate digest->cd_offset, &PROV_SHA1_CTX(ctx)->sc_sha1_ctx); 1648*0Sstevel@tonic-gate break; 1649*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 1650*0Sstevel@tonic-gate ret = sha1_digest_final_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 1651*0Sstevel@tonic-gate digest, SHA1_DIGEST_LENGTH, NULL); 1652*0Sstevel@tonic-gate break; 1653*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 1654*0Sstevel@tonic-gate ret = sha1_digest_final_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 1655*0Sstevel@tonic-gate digest, SHA1_DIGEST_LENGTH, NULL); 1656*0Sstevel@tonic-gate break; 1657*0Sstevel@tonic-gate default: 1658*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 1659*0Sstevel@tonic-gate } 1660*0Sstevel@tonic-gate 1661*0Sstevel@tonic-gate /* all done, free context and return */ 1662*0Sstevel@tonic-gate 1663*0Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 1664*0Sstevel@tonic-gate digest->cd_length = SHA1_DIGEST_LENGTH; 1665*0Sstevel@tonic-gate } else { 1666*0Sstevel@tonic-gate digest->cd_length = 0; 1667*0Sstevel@tonic-gate } 1668*0Sstevel@tonic-gate 1669*0Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t)); 1670*0Sstevel@tonic-gate ctx->cc_provider_private = NULL; 1671*0Sstevel@tonic-gate return (ret); 1672*0Sstevel@tonic-gate } 1673*0Sstevel@tonic-gate 1674*0Sstevel@tonic-gate /* ARGSUSED */ 1675*0Sstevel@tonic-gate static int 1676*0Sstevel@tonic-gate sha1_digest_update(crypto_ctx_t *ctx, crypto_data_t *data, 1677*0Sstevel@tonic-gate crypto_req_handle_t req) 1678*0Sstevel@tonic-gate { 1679*0Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 1680*0Sstevel@tonic-gate 1681*0Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 1682*0Sstevel@tonic-gate 1683*0Sstevel@tonic-gate /* 1684*0Sstevel@tonic-gate * Do the SHA1 update on the specified input data. 1685*0Sstevel@tonic-gate */ 1686*0Sstevel@tonic-gate switch (data->cd_format) { 1687*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 1688*0Sstevel@tonic-gate SHA1Update(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 1689*0Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 1690*0Sstevel@tonic-gate data->cd_length); 1691*0Sstevel@tonic-gate break; 1692*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 1693*0Sstevel@tonic-gate ret = sha1_digest_update_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 1694*0Sstevel@tonic-gate data); 1695*0Sstevel@tonic-gate break; 1696*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 1697*0Sstevel@tonic-gate ret = sha1_digest_update_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 1698*0Sstevel@tonic-gate data); 1699*0Sstevel@tonic-gate break; 1700*0Sstevel@tonic-gate default: 1701*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 1702*0Sstevel@tonic-gate } 1703*0Sstevel@tonic-gate 1704*0Sstevel@tonic-gate return (ret); 1705*0Sstevel@tonic-gate } 1706*0Sstevel@tonic-gate 1707*0Sstevel@tonic-gate /* ARGSUSED */ 1708*0Sstevel@tonic-gate static int 1709*0Sstevel@tonic-gate sha1_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest, 1710*0Sstevel@tonic-gate crypto_req_handle_t req) 1711*0Sstevel@tonic-gate { 1712*0Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 1713*0Sstevel@tonic-gate 1714*0Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 1715*0Sstevel@tonic-gate 1716*0Sstevel@tonic-gate /* 1717*0Sstevel@tonic-gate * We need to just return the length needed to store the output. 1718*0Sstevel@tonic-gate * We should not destroy the context for the following cases. 1719*0Sstevel@tonic-gate */ 1720*0Sstevel@tonic-gate if ((digest->cd_length == 0) || 1721*0Sstevel@tonic-gate (digest->cd_length < SHA1_DIGEST_LENGTH)) { 1722*0Sstevel@tonic-gate digest->cd_length = SHA1_DIGEST_LENGTH; 1723*0Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 1724*0Sstevel@tonic-gate } 1725*0Sstevel@tonic-gate 1726*0Sstevel@tonic-gate /* 1727*0Sstevel@tonic-gate * Do a SHA1 final. 1728*0Sstevel@tonic-gate */ 1729*0Sstevel@tonic-gate switch (digest->cd_format) { 1730*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 1731*0Sstevel@tonic-gate SHA1Final((unsigned char *)digest->cd_raw.iov_base + 1732*0Sstevel@tonic-gate digest->cd_offset, &PROV_SHA1_CTX(ctx)->sc_sha1_ctx); 1733*0Sstevel@tonic-gate break; 1734*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 1735*0Sstevel@tonic-gate ret = sha1_digest_final_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 1736*0Sstevel@tonic-gate digest, SHA1_DIGEST_LENGTH, NULL); 1737*0Sstevel@tonic-gate break; 1738*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 1739*0Sstevel@tonic-gate ret = sha1_digest_final_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx, 1740*0Sstevel@tonic-gate digest, SHA1_DIGEST_LENGTH, NULL); 1741*0Sstevel@tonic-gate break; 1742*0Sstevel@tonic-gate default: 1743*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 1744*0Sstevel@tonic-gate } 1745*0Sstevel@tonic-gate 1746*0Sstevel@tonic-gate /* all done, free context and return */ 1747*0Sstevel@tonic-gate 1748*0Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 1749*0Sstevel@tonic-gate digest->cd_length = SHA1_DIGEST_LENGTH; 1750*0Sstevel@tonic-gate } else { 1751*0Sstevel@tonic-gate digest->cd_length = 0; 1752*0Sstevel@tonic-gate } 1753*0Sstevel@tonic-gate 1754*0Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t)); 1755*0Sstevel@tonic-gate ctx->cc_provider_private = NULL; 1756*0Sstevel@tonic-gate 1757*0Sstevel@tonic-gate return (ret); 1758*0Sstevel@tonic-gate } 1759*0Sstevel@tonic-gate 1760*0Sstevel@tonic-gate /* ARGSUSED */ 1761*0Sstevel@tonic-gate static int 1762*0Sstevel@tonic-gate sha1_digest_atomic(crypto_provider_handle_t provider, 1763*0Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 1764*0Sstevel@tonic-gate crypto_data_t *data, crypto_data_t *digest, 1765*0Sstevel@tonic-gate crypto_req_handle_t req) 1766*0Sstevel@tonic-gate { 1767*0Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 1768*0Sstevel@tonic-gate SHA1_CTX sha1_ctx; 1769*0Sstevel@tonic-gate 1770*0Sstevel@tonic-gate if (mechanism->cm_type != SHA1_MECH_INFO_TYPE) 1771*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 1772*0Sstevel@tonic-gate 1773*0Sstevel@tonic-gate /* 1774*0Sstevel@tonic-gate * Do the SHA1 init. 1775*0Sstevel@tonic-gate */ 1776*0Sstevel@tonic-gate SHA1Init(&sha1_ctx); 1777*0Sstevel@tonic-gate 1778*0Sstevel@tonic-gate /* 1779*0Sstevel@tonic-gate * Do the SHA1 update on the specified input data. 1780*0Sstevel@tonic-gate */ 1781*0Sstevel@tonic-gate switch (data->cd_format) { 1782*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 1783*0Sstevel@tonic-gate SHA1Update(&sha1_ctx, 1784*0Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 1785*0Sstevel@tonic-gate data->cd_length); 1786*0Sstevel@tonic-gate break; 1787*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 1788*0Sstevel@tonic-gate ret = sha1_digest_update_uio(&sha1_ctx, data); 1789*0Sstevel@tonic-gate break; 1790*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 1791*0Sstevel@tonic-gate ret = sha1_digest_update_mblk(&sha1_ctx, data); 1792*0Sstevel@tonic-gate break; 1793*0Sstevel@tonic-gate default: 1794*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 1795*0Sstevel@tonic-gate } 1796*0Sstevel@tonic-gate 1797*0Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 1798*0Sstevel@tonic-gate /* the update failed, bail */ 1799*0Sstevel@tonic-gate digest->cd_length = 0; 1800*0Sstevel@tonic-gate return (ret); 1801*0Sstevel@tonic-gate } 1802*0Sstevel@tonic-gate 1803*0Sstevel@tonic-gate /* 1804*0Sstevel@tonic-gate * Do a SHA1 final, must be done separately since the digest 1805*0Sstevel@tonic-gate * type can be different than the input data type. 1806*0Sstevel@tonic-gate */ 1807*0Sstevel@tonic-gate switch (digest->cd_format) { 1808*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 1809*0Sstevel@tonic-gate SHA1Final((unsigned char *)digest->cd_raw.iov_base + 1810*0Sstevel@tonic-gate digest->cd_offset, &sha1_ctx); 1811*0Sstevel@tonic-gate break; 1812*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 1813*0Sstevel@tonic-gate ret = sha1_digest_final_uio(&sha1_ctx, digest, 1814*0Sstevel@tonic-gate SHA1_DIGEST_LENGTH, NULL); 1815*0Sstevel@tonic-gate break; 1816*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 1817*0Sstevel@tonic-gate ret = sha1_digest_final_mblk(&sha1_ctx, digest, 1818*0Sstevel@tonic-gate SHA1_DIGEST_LENGTH, NULL); 1819*0Sstevel@tonic-gate break; 1820*0Sstevel@tonic-gate default: 1821*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 1822*0Sstevel@tonic-gate } 1823*0Sstevel@tonic-gate 1824*0Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 1825*0Sstevel@tonic-gate digest->cd_length = SHA1_DIGEST_LENGTH; 1826*0Sstevel@tonic-gate } else { 1827*0Sstevel@tonic-gate digest->cd_length = 0; 1828*0Sstevel@tonic-gate } 1829*0Sstevel@tonic-gate 1830*0Sstevel@tonic-gate return (ret); 1831*0Sstevel@tonic-gate } 1832*0Sstevel@tonic-gate 1833*0Sstevel@tonic-gate /* 1834*0Sstevel@tonic-gate * KCF software provider mac entry points. 1835*0Sstevel@tonic-gate * 1836*0Sstevel@tonic-gate * SHA1 HMAC is: SHA1(key XOR opad, SHA1(key XOR ipad, text)) 1837*0Sstevel@tonic-gate * 1838*0Sstevel@tonic-gate * Init: 1839*0Sstevel@tonic-gate * The initialization routine initializes what we denote 1840*0Sstevel@tonic-gate * as the inner and outer contexts by doing 1841*0Sstevel@tonic-gate * - for inner context: SHA1(key XOR ipad) 1842*0Sstevel@tonic-gate * - for outer context: SHA1(key XOR opad) 1843*0Sstevel@tonic-gate * 1844*0Sstevel@tonic-gate * Update: 1845*0Sstevel@tonic-gate * Each subsequent SHA1 HMAC update will result in an 1846*0Sstevel@tonic-gate * update of the inner context with the specified data. 1847*0Sstevel@tonic-gate * 1848*0Sstevel@tonic-gate * Final: 1849*0Sstevel@tonic-gate * The SHA1 HMAC final will do a SHA1 final operation on the 1850*0Sstevel@tonic-gate * inner context, and the resulting digest will be used 1851*0Sstevel@tonic-gate * as the data for an update on the outer context. Last 1852*0Sstevel@tonic-gate * but not least, a SHA1 final on the outer context will 1853*0Sstevel@tonic-gate * be performed to obtain the SHA1 HMAC digest to return 1854*0Sstevel@tonic-gate * to the user. 1855*0Sstevel@tonic-gate */ 1856*0Sstevel@tonic-gate 1857*0Sstevel@tonic-gate /* 1858*0Sstevel@tonic-gate * Initialize a SHA1-HMAC context. 1859*0Sstevel@tonic-gate */ 1860*0Sstevel@tonic-gate static void 1861*0Sstevel@tonic-gate sha1_mac_init_ctx(sha1_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes) 1862*0Sstevel@tonic-gate { 1863*0Sstevel@tonic-gate uint32_t ipad[SHA1_HMAC_INTS_PER_BLOCK]; 1864*0Sstevel@tonic-gate uint32_t opad[SHA1_HMAC_INTS_PER_BLOCK]; 1865*0Sstevel@tonic-gate uint_t i; 1866*0Sstevel@tonic-gate 1867*0Sstevel@tonic-gate bzero(ipad, SHA1_HMAC_BLOCK_SIZE); 1868*0Sstevel@tonic-gate bzero(opad, SHA1_HMAC_BLOCK_SIZE); 1869*0Sstevel@tonic-gate 1870*0Sstevel@tonic-gate bcopy(keyval, ipad, length_in_bytes); 1871*0Sstevel@tonic-gate bcopy(keyval, opad, length_in_bytes); 1872*0Sstevel@tonic-gate 1873*0Sstevel@tonic-gate /* XOR key with ipad (0x36) and opad (0x5c) */ 1874*0Sstevel@tonic-gate for (i = 0; i < SHA1_HMAC_INTS_PER_BLOCK; i++) { 1875*0Sstevel@tonic-gate ipad[i] ^= 0x36363636; 1876*0Sstevel@tonic-gate opad[i] ^= 0x5c5c5c5c; 1877*0Sstevel@tonic-gate } 1878*0Sstevel@tonic-gate 1879*0Sstevel@tonic-gate /* perform SHA1 on ipad */ 1880*0Sstevel@tonic-gate SHA1Init(&ctx->hc_icontext); 1881*0Sstevel@tonic-gate SHA1Update(&ctx->hc_icontext, (uint8_t *)ipad, SHA1_HMAC_BLOCK_SIZE); 1882*0Sstevel@tonic-gate 1883*0Sstevel@tonic-gate /* perform SHA1 on opad */ 1884*0Sstevel@tonic-gate SHA1Init(&ctx->hc_ocontext); 1885*0Sstevel@tonic-gate SHA1Update(&ctx->hc_ocontext, (uint8_t *)opad, SHA1_HMAC_BLOCK_SIZE); 1886*0Sstevel@tonic-gate } 1887*0Sstevel@tonic-gate 1888*0Sstevel@tonic-gate /* 1889*0Sstevel@tonic-gate */ 1890*0Sstevel@tonic-gate static int 1891*0Sstevel@tonic-gate sha1_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 1892*0Sstevel@tonic-gate crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, 1893*0Sstevel@tonic-gate crypto_req_handle_t req) 1894*0Sstevel@tonic-gate { 1895*0Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 1896*0Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 1897*0Sstevel@tonic-gate 1898*0Sstevel@tonic-gate if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE && 1899*0Sstevel@tonic-gate mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE) 1900*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 1901*0Sstevel@tonic-gate 1902*0Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 1903*0Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 1904*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 1905*0Sstevel@tonic-gate 1906*0Sstevel@tonic-gate ctx->cc_provider_private = kmem_alloc(sizeof (sha1_hmac_ctx_t), 1907*0Sstevel@tonic-gate crypto_kmflag(req)); 1908*0Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 1909*0Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 1910*0Sstevel@tonic-gate 1911*0Sstevel@tonic-gate if (ctx_template != NULL) { 1912*0Sstevel@tonic-gate /* reuse context template */ 1913*0Sstevel@tonic-gate bcopy(ctx_template, PROV_SHA1_HMAC_CTX(ctx), 1914*0Sstevel@tonic-gate sizeof (sha1_hmac_ctx_t)); 1915*0Sstevel@tonic-gate } else { 1916*0Sstevel@tonic-gate /* no context template, compute context */ 1917*0Sstevel@tonic-gate if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) { 1918*0Sstevel@tonic-gate uchar_t digested_key[SHA1_DIGEST_LENGTH]; 1919*0Sstevel@tonic-gate sha1_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private; 1920*0Sstevel@tonic-gate 1921*0Sstevel@tonic-gate /* 1922*0Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 1923*0Sstevel@tonic-gate * The inner context is used since it hasn't been 1924*0Sstevel@tonic-gate * initialized yet. 1925*0Sstevel@tonic-gate */ 1926*0Sstevel@tonic-gate PROV_SHA1_DIGEST_KEY(&hmac_ctx->hc_icontext, 1927*0Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digested_key); 1928*0Sstevel@tonic-gate sha1_mac_init_ctx(PROV_SHA1_HMAC_CTX(ctx), 1929*0Sstevel@tonic-gate digested_key, SHA1_DIGEST_LENGTH); 1930*0Sstevel@tonic-gate } else { 1931*0Sstevel@tonic-gate sha1_mac_init_ctx(PROV_SHA1_HMAC_CTX(ctx), 1932*0Sstevel@tonic-gate key->ck_data, keylen_in_bytes); 1933*0Sstevel@tonic-gate } 1934*0Sstevel@tonic-gate } 1935*0Sstevel@tonic-gate 1936*0Sstevel@tonic-gate /* 1937*0Sstevel@tonic-gate * Get the mechanism parameters, if applicable. 1938*0Sstevel@tonic-gate */ 1939*0Sstevel@tonic-gate PROV_SHA1_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type; 1940*0Sstevel@tonic-gate if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) { 1941*0Sstevel@tonic-gate if (mechanism->cm_param == NULL || 1942*0Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) 1943*0Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 1944*0Sstevel@tonic-gate PROV_SHA1_GET_DIGEST_LEN(mechanism, 1945*0Sstevel@tonic-gate PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len); 1946*0Sstevel@tonic-gate if (PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len > 1947*0Sstevel@tonic-gate SHA1_DIGEST_LENGTH) 1948*0Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 1949*0Sstevel@tonic-gate } 1950*0Sstevel@tonic-gate 1951*0Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 1952*0Sstevel@tonic-gate bzero(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t)); 1953*0Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t)); 1954*0Sstevel@tonic-gate ctx->cc_provider_private = NULL; 1955*0Sstevel@tonic-gate } 1956*0Sstevel@tonic-gate 1957*0Sstevel@tonic-gate return (ret); 1958*0Sstevel@tonic-gate } 1959*0Sstevel@tonic-gate 1960*0Sstevel@tonic-gate /* ARGSUSED */ 1961*0Sstevel@tonic-gate static int 1962*0Sstevel@tonic-gate sha1_mac_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req) 1963*0Sstevel@tonic-gate { 1964*0Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 1965*0Sstevel@tonic-gate 1966*0Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 1967*0Sstevel@tonic-gate 1968*0Sstevel@tonic-gate /* 1969*0Sstevel@tonic-gate * Do a SHA1 update of the inner context using the specified 1970*0Sstevel@tonic-gate * data. 1971*0Sstevel@tonic-gate */ 1972*0Sstevel@tonic-gate switch (data->cd_format) { 1973*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 1974*0Sstevel@tonic-gate SHA1Update(&PROV_SHA1_HMAC_CTX(ctx)->hc_icontext, 1975*0Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 1976*0Sstevel@tonic-gate data->cd_length); 1977*0Sstevel@tonic-gate break; 1978*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 1979*0Sstevel@tonic-gate ret = sha1_digest_update_uio( 1980*0Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext, data); 1981*0Sstevel@tonic-gate break; 1982*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 1983*0Sstevel@tonic-gate ret = sha1_digest_update_mblk( 1984*0Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext, data); 1985*0Sstevel@tonic-gate break; 1986*0Sstevel@tonic-gate default: 1987*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 1988*0Sstevel@tonic-gate } 1989*0Sstevel@tonic-gate 1990*0Sstevel@tonic-gate return (ret); 1991*0Sstevel@tonic-gate } 1992*0Sstevel@tonic-gate 1993*0Sstevel@tonic-gate /* ARGSUSED */ 1994*0Sstevel@tonic-gate static int 1995*0Sstevel@tonic-gate sha1_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req) 1996*0Sstevel@tonic-gate { 1997*0Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 1998*0Sstevel@tonic-gate uchar_t digest[SHA1_DIGEST_LENGTH]; 1999*0Sstevel@tonic-gate uint32_t digest_len = SHA1_DIGEST_LENGTH; 2000*0Sstevel@tonic-gate 2001*0Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 2002*0Sstevel@tonic-gate 2003*0Sstevel@tonic-gate if (PROV_SHA1_HMAC_CTX(ctx)->hc_mech_type == 2004*0Sstevel@tonic-gate SHA1_HMAC_GEN_MECH_INFO_TYPE) 2005*0Sstevel@tonic-gate digest_len = PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len; 2006*0Sstevel@tonic-gate 2007*0Sstevel@tonic-gate /* 2008*0Sstevel@tonic-gate * We need to just return the length needed to store the output. 2009*0Sstevel@tonic-gate * We should not destroy the context for the following cases. 2010*0Sstevel@tonic-gate */ 2011*0Sstevel@tonic-gate if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) { 2012*0Sstevel@tonic-gate mac->cd_length = digest_len; 2013*0Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 2014*0Sstevel@tonic-gate } 2015*0Sstevel@tonic-gate 2016*0Sstevel@tonic-gate /* 2017*0Sstevel@tonic-gate * Do a SHA1 final on the inner context. 2018*0Sstevel@tonic-gate */ 2019*0Sstevel@tonic-gate SHA1Final(digest, &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext); 2020*0Sstevel@tonic-gate 2021*0Sstevel@tonic-gate /* 2022*0Sstevel@tonic-gate * Do a SHA1 update on the outer context, feeding the inner 2023*0Sstevel@tonic-gate * digest as data. 2024*0Sstevel@tonic-gate */ 2025*0Sstevel@tonic-gate SHA1Update(&PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, digest, 2026*0Sstevel@tonic-gate SHA1_DIGEST_LENGTH); 2027*0Sstevel@tonic-gate 2028*0Sstevel@tonic-gate /* 2029*0Sstevel@tonic-gate * Do a SHA1 final on the outer context, storing the computing 2030*0Sstevel@tonic-gate * digest in the users buffer. 2031*0Sstevel@tonic-gate */ 2032*0Sstevel@tonic-gate switch (mac->cd_format) { 2033*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 2034*0Sstevel@tonic-gate if (digest_len != SHA1_DIGEST_LENGTH) { 2035*0Sstevel@tonic-gate /* 2036*0Sstevel@tonic-gate * The caller requested a short digest. Digest 2037*0Sstevel@tonic-gate * into a scratch buffer and return to 2038*0Sstevel@tonic-gate * the user only what was requested. 2039*0Sstevel@tonic-gate */ 2040*0Sstevel@tonic-gate SHA1Final(digest, 2041*0Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext); 2042*0Sstevel@tonic-gate bcopy(digest, (unsigned char *)mac->cd_raw.iov_base + 2043*0Sstevel@tonic-gate mac->cd_offset, digest_len); 2044*0Sstevel@tonic-gate } else { 2045*0Sstevel@tonic-gate SHA1Final((unsigned char *)mac->cd_raw.iov_base + 2046*0Sstevel@tonic-gate mac->cd_offset, 2047*0Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext); 2048*0Sstevel@tonic-gate } 2049*0Sstevel@tonic-gate break; 2050*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 2051*0Sstevel@tonic-gate ret = sha1_digest_final_uio( 2052*0Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, mac, 2053*0Sstevel@tonic-gate digest_len, digest); 2054*0Sstevel@tonic-gate break; 2055*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 2056*0Sstevel@tonic-gate ret = sha1_digest_final_mblk( 2057*0Sstevel@tonic-gate &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, mac, 2058*0Sstevel@tonic-gate digest_len, digest); 2059*0Sstevel@tonic-gate break; 2060*0Sstevel@tonic-gate default: 2061*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 2062*0Sstevel@tonic-gate } 2063*0Sstevel@tonic-gate 2064*0Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 2065*0Sstevel@tonic-gate mac->cd_length = digest_len; 2066*0Sstevel@tonic-gate } else { 2067*0Sstevel@tonic-gate mac->cd_length = 0; 2068*0Sstevel@tonic-gate } 2069*0Sstevel@tonic-gate 2070*0Sstevel@tonic-gate bzero(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t)); 2071*0Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t)); 2072*0Sstevel@tonic-gate ctx->cc_provider_private = NULL; 2073*0Sstevel@tonic-gate 2074*0Sstevel@tonic-gate return (ret); 2075*0Sstevel@tonic-gate } 2076*0Sstevel@tonic-gate 2077*0Sstevel@tonic-gate #define SHA1_MAC_UPDATE(data, ctx, ret) { \ 2078*0Sstevel@tonic-gate switch (data->cd_format) { \ 2079*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: \ 2080*0Sstevel@tonic-gate SHA1Update(&(ctx).hc_icontext, \ 2081*0Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + \ 2082*0Sstevel@tonic-gate data->cd_offset, data->cd_length); \ 2083*0Sstevel@tonic-gate break; \ 2084*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: \ 2085*0Sstevel@tonic-gate ret = sha1_digest_update_uio(&(ctx).hc_icontext, data); \ 2086*0Sstevel@tonic-gate break; \ 2087*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: \ 2088*0Sstevel@tonic-gate ret = sha1_digest_update_mblk(&(ctx).hc_icontext, \ 2089*0Sstevel@tonic-gate data); \ 2090*0Sstevel@tonic-gate break; \ 2091*0Sstevel@tonic-gate default: \ 2092*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; \ 2093*0Sstevel@tonic-gate } \ 2094*0Sstevel@tonic-gate } 2095*0Sstevel@tonic-gate 2096*0Sstevel@tonic-gate /* ARGSUSED */ 2097*0Sstevel@tonic-gate static int 2098*0Sstevel@tonic-gate sha1_mac_atomic(crypto_provider_handle_t provider, 2099*0Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 2100*0Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 2101*0Sstevel@tonic-gate crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 2102*0Sstevel@tonic-gate { 2103*0Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 2104*0Sstevel@tonic-gate uchar_t digest[SHA1_DIGEST_LENGTH]; 2105*0Sstevel@tonic-gate sha1_hmac_ctx_t sha1_hmac_ctx; 2106*0Sstevel@tonic-gate uint32_t digest_len = SHA1_DIGEST_LENGTH; 2107*0Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 2108*0Sstevel@tonic-gate 2109*0Sstevel@tonic-gate if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE && 2110*0Sstevel@tonic-gate mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE) 2111*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 2112*0Sstevel@tonic-gate 2113*0Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 2114*0Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 2115*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 2116*0Sstevel@tonic-gate 2117*0Sstevel@tonic-gate if (ctx_template != NULL) { 2118*0Sstevel@tonic-gate /* reuse context template */ 2119*0Sstevel@tonic-gate bcopy(ctx_template, &sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 2120*0Sstevel@tonic-gate } else { 2121*0Sstevel@tonic-gate /* no context template, initialize context */ 2122*0Sstevel@tonic-gate if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) { 2123*0Sstevel@tonic-gate /* 2124*0Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 2125*0Sstevel@tonic-gate * The inner context is used since it hasn't been 2126*0Sstevel@tonic-gate * initialized yet. 2127*0Sstevel@tonic-gate */ 2128*0Sstevel@tonic-gate PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx.hc_icontext, 2129*0Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digest); 2130*0Sstevel@tonic-gate sha1_mac_init_ctx(&sha1_hmac_ctx, digest, 2131*0Sstevel@tonic-gate SHA1_DIGEST_LENGTH); 2132*0Sstevel@tonic-gate } else { 2133*0Sstevel@tonic-gate sha1_mac_init_ctx(&sha1_hmac_ctx, key->ck_data, 2134*0Sstevel@tonic-gate keylen_in_bytes); 2135*0Sstevel@tonic-gate } 2136*0Sstevel@tonic-gate } 2137*0Sstevel@tonic-gate 2138*0Sstevel@tonic-gate /* get the mechanism parameters, if applicable */ 2139*0Sstevel@tonic-gate if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) { 2140*0Sstevel@tonic-gate if (mechanism->cm_param == NULL || 2141*0Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) { 2142*0Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 2143*0Sstevel@tonic-gate goto bail; 2144*0Sstevel@tonic-gate } 2145*0Sstevel@tonic-gate PROV_SHA1_GET_DIGEST_LEN(mechanism, digest_len); 2146*0Sstevel@tonic-gate if (digest_len > SHA1_DIGEST_LENGTH) { 2147*0Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 2148*0Sstevel@tonic-gate goto bail; 2149*0Sstevel@tonic-gate } 2150*0Sstevel@tonic-gate } 2151*0Sstevel@tonic-gate 2152*0Sstevel@tonic-gate /* do a SHA1 update of the inner context using the specified data */ 2153*0Sstevel@tonic-gate SHA1_MAC_UPDATE(data, sha1_hmac_ctx, ret); 2154*0Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) 2155*0Sstevel@tonic-gate /* the update failed, free context and bail */ 2156*0Sstevel@tonic-gate goto bail; 2157*0Sstevel@tonic-gate 2158*0Sstevel@tonic-gate /* 2159*0Sstevel@tonic-gate * Do a SHA1 final on the inner context. 2160*0Sstevel@tonic-gate */ 2161*0Sstevel@tonic-gate SHA1Final(digest, &sha1_hmac_ctx.hc_icontext); 2162*0Sstevel@tonic-gate 2163*0Sstevel@tonic-gate /* 2164*0Sstevel@tonic-gate * Do an SHA1 update on the outer context, feeding the inner 2165*0Sstevel@tonic-gate * digest as data. 2166*0Sstevel@tonic-gate */ 2167*0Sstevel@tonic-gate SHA1Update(&sha1_hmac_ctx.hc_ocontext, digest, SHA1_DIGEST_LENGTH); 2168*0Sstevel@tonic-gate 2169*0Sstevel@tonic-gate /* 2170*0Sstevel@tonic-gate * Do a SHA1 final on the outer context, storing the computed 2171*0Sstevel@tonic-gate * digest in the users buffer. 2172*0Sstevel@tonic-gate */ 2173*0Sstevel@tonic-gate switch (mac->cd_format) { 2174*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 2175*0Sstevel@tonic-gate if (digest_len != SHA1_DIGEST_LENGTH) { 2176*0Sstevel@tonic-gate /* 2177*0Sstevel@tonic-gate * The caller requested a short digest. Digest 2178*0Sstevel@tonic-gate * into a scratch buffer and return to 2179*0Sstevel@tonic-gate * the user only what was requested. 2180*0Sstevel@tonic-gate */ 2181*0Sstevel@tonic-gate SHA1Final(digest, &sha1_hmac_ctx.hc_ocontext); 2182*0Sstevel@tonic-gate bcopy(digest, (unsigned char *)mac->cd_raw.iov_base + 2183*0Sstevel@tonic-gate mac->cd_offset, digest_len); 2184*0Sstevel@tonic-gate } else { 2185*0Sstevel@tonic-gate SHA1Final((unsigned char *)mac->cd_raw.iov_base + 2186*0Sstevel@tonic-gate mac->cd_offset, &sha1_hmac_ctx.hc_ocontext); 2187*0Sstevel@tonic-gate } 2188*0Sstevel@tonic-gate break; 2189*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 2190*0Sstevel@tonic-gate ret = sha1_digest_final_uio(&sha1_hmac_ctx.hc_ocontext, mac, 2191*0Sstevel@tonic-gate digest_len, digest); 2192*0Sstevel@tonic-gate break; 2193*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 2194*0Sstevel@tonic-gate ret = sha1_digest_final_mblk(&sha1_hmac_ctx.hc_ocontext, mac, 2195*0Sstevel@tonic-gate digest_len, digest); 2196*0Sstevel@tonic-gate break; 2197*0Sstevel@tonic-gate default: 2198*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 2199*0Sstevel@tonic-gate } 2200*0Sstevel@tonic-gate 2201*0Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 2202*0Sstevel@tonic-gate mac->cd_length = digest_len; 2203*0Sstevel@tonic-gate } else { 2204*0Sstevel@tonic-gate mac->cd_length = 0; 2205*0Sstevel@tonic-gate } 2206*0Sstevel@tonic-gate /* Extra paranoia: zeroize the context on the stack */ 2207*0Sstevel@tonic-gate bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 2208*0Sstevel@tonic-gate 2209*0Sstevel@tonic-gate return (ret); 2210*0Sstevel@tonic-gate bail: 2211*0Sstevel@tonic-gate bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 2212*0Sstevel@tonic-gate mac->cd_length = 0; 2213*0Sstevel@tonic-gate return (ret); 2214*0Sstevel@tonic-gate } 2215*0Sstevel@tonic-gate 2216*0Sstevel@tonic-gate /* ARGSUSED */ 2217*0Sstevel@tonic-gate static int 2218*0Sstevel@tonic-gate sha1_mac_verify_atomic(crypto_provider_handle_t provider, 2219*0Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 2220*0Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 2221*0Sstevel@tonic-gate crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 2222*0Sstevel@tonic-gate { 2223*0Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 2224*0Sstevel@tonic-gate uchar_t digest[SHA1_DIGEST_LENGTH]; 2225*0Sstevel@tonic-gate sha1_hmac_ctx_t sha1_hmac_ctx; 2226*0Sstevel@tonic-gate uint32_t digest_len = SHA1_DIGEST_LENGTH; 2227*0Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 2228*0Sstevel@tonic-gate 2229*0Sstevel@tonic-gate if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE && 2230*0Sstevel@tonic-gate mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE) 2231*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 2232*0Sstevel@tonic-gate 2233*0Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 2234*0Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 2235*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 2236*0Sstevel@tonic-gate 2237*0Sstevel@tonic-gate if (ctx_template != NULL) { 2238*0Sstevel@tonic-gate /* reuse context template */ 2239*0Sstevel@tonic-gate bcopy(ctx_template, &sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 2240*0Sstevel@tonic-gate } else { 2241*0Sstevel@tonic-gate /* no context template, initialize context */ 2242*0Sstevel@tonic-gate if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) { 2243*0Sstevel@tonic-gate /* 2244*0Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 2245*0Sstevel@tonic-gate * The inner context is used since it hasn't been 2246*0Sstevel@tonic-gate * initialized yet. 2247*0Sstevel@tonic-gate */ 2248*0Sstevel@tonic-gate PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx.hc_icontext, 2249*0Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digest); 2250*0Sstevel@tonic-gate sha1_mac_init_ctx(&sha1_hmac_ctx, digest, 2251*0Sstevel@tonic-gate SHA1_DIGEST_LENGTH); 2252*0Sstevel@tonic-gate } else { 2253*0Sstevel@tonic-gate sha1_mac_init_ctx(&sha1_hmac_ctx, key->ck_data, 2254*0Sstevel@tonic-gate keylen_in_bytes); 2255*0Sstevel@tonic-gate } 2256*0Sstevel@tonic-gate } 2257*0Sstevel@tonic-gate 2258*0Sstevel@tonic-gate /* get the mechanism parameters, if applicable */ 2259*0Sstevel@tonic-gate if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) { 2260*0Sstevel@tonic-gate if (mechanism->cm_param == NULL || 2261*0Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) { 2262*0Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 2263*0Sstevel@tonic-gate goto bail; 2264*0Sstevel@tonic-gate } 2265*0Sstevel@tonic-gate PROV_SHA1_GET_DIGEST_LEN(mechanism, digest_len); 2266*0Sstevel@tonic-gate if (digest_len > SHA1_DIGEST_LENGTH) { 2267*0Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 2268*0Sstevel@tonic-gate goto bail; 2269*0Sstevel@tonic-gate } 2270*0Sstevel@tonic-gate } 2271*0Sstevel@tonic-gate 2272*0Sstevel@tonic-gate if (mac->cd_length != digest_len) { 2273*0Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 2274*0Sstevel@tonic-gate goto bail; 2275*0Sstevel@tonic-gate } 2276*0Sstevel@tonic-gate 2277*0Sstevel@tonic-gate /* do a SHA1 update of the inner context using the specified data */ 2278*0Sstevel@tonic-gate SHA1_MAC_UPDATE(data, sha1_hmac_ctx, ret); 2279*0Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) 2280*0Sstevel@tonic-gate /* the update failed, free context and bail */ 2281*0Sstevel@tonic-gate goto bail; 2282*0Sstevel@tonic-gate 2283*0Sstevel@tonic-gate /* do a SHA1 final on the inner context */ 2284*0Sstevel@tonic-gate SHA1Final(digest, &sha1_hmac_ctx.hc_icontext); 2285*0Sstevel@tonic-gate 2286*0Sstevel@tonic-gate /* 2287*0Sstevel@tonic-gate * Do an SHA1 update on the outer context, feeding the inner 2288*0Sstevel@tonic-gate * digest as data. 2289*0Sstevel@tonic-gate */ 2290*0Sstevel@tonic-gate SHA1Update(&sha1_hmac_ctx.hc_ocontext, digest, SHA1_DIGEST_LENGTH); 2291*0Sstevel@tonic-gate 2292*0Sstevel@tonic-gate /* 2293*0Sstevel@tonic-gate * Do a SHA1 final on the outer context, storing the computed 2294*0Sstevel@tonic-gate * digest in the users buffer. 2295*0Sstevel@tonic-gate */ 2296*0Sstevel@tonic-gate SHA1Final(digest, &sha1_hmac_ctx.hc_ocontext); 2297*0Sstevel@tonic-gate 2298*0Sstevel@tonic-gate /* 2299*0Sstevel@tonic-gate * Compare the computed digest against the expected digest passed 2300*0Sstevel@tonic-gate * as argument. 2301*0Sstevel@tonic-gate */ 2302*0Sstevel@tonic-gate 2303*0Sstevel@tonic-gate switch (mac->cd_format) { 2304*0Sstevel@tonic-gate 2305*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 2306*0Sstevel@tonic-gate if (bcmp(digest, (unsigned char *)mac->cd_raw.iov_base + 2307*0Sstevel@tonic-gate mac->cd_offset, digest_len) != 0) 2308*0Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 2309*0Sstevel@tonic-gate break; 2310*0Sstevel@tonic-gate 2311*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: { 2312*0Sstevel@tonic-gate off_t offset = mac->cd_offset; 2313*0Sstevel@tonic-gate uint_t vec_idx; 2314*0Sstevel@tonic-gate off_t scratch_offset = 0; 2315*0Sstevel@tonic-gate size_t length = digest_len; 2316*0Sstevel@tonic-gate size_t cur_len; 2317*0Sstevel@tonic-gate 2318*0Sstevel@tonic-gate /* we support only kernel buffer */ 2319*0Sstevel@tonic-gate if (mac->cd_uio->uio_segflg != UIO_SYSSPACE) 2320*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 2321*0Sstevel@tonic-gate 2322*0Sstevel@tonic-gate /* jump to the first iovec containing the expected digest */ 2323*0Sstevel@tonic-gate for (vec_idx = 0; 2324*0Sstevel@tonic-gate offset >= mac->cd_uio->uio_iov[vec_idx].iov_len && 2325*0Sstevel@tonic-gate vec_idx < mac->cd_uio->uio_iovcnt; 2326*0Sstevel@tonic-gate offset -= mac->cd_uio->uio_iov[vec_idx++].iov_len); 2327*0Sstevel@tonic-gate if (vec_idx == mac->cd_uio->uio_iovcnt) { 2328*0Sstevel@tonic-gate /* 2329*0Sstevel@tonic-gate * The caller specified an offset that is 2330*0Sstevel@tonic-gate * larger than the total size of the buffers 2331*0Sstevel@tonic-gate * it provided. 2332*0Sstevel@tonic-gate */ 2333*0Sstevel@tonic-gate ret = CRYPTO_DATA_LEN_RANGE; 2334*0Sstevel@tonic-gate break; 2335*0Sstevel@tonic-gate } 2336*0Sstevel@tonic-gate 2337*0Sstevel@tonic-gate /* do the comparison of computed digest vs specified one */ 2338*0Sstevel@tonic-gate while (vec_idx < mac->cd_uio->uio_iovcnt && length > 0) { 2339*0Sstevel@tonic-gate cur_len = MIN(mac->cd_uio->uio_iov[vec_idx].iov_len - 2340*0Sstevel@tonic-gate offset, length); 2341*0Sstevel@tonic-gate 2342*0Sstevel@tonic-gate if (bcmp(digest + scratch_offset, 2343*0Sstevel@tonic-gate mac->cd_uio->uio_iov[vec_idx].iov_base + offset, 2344*0Sstevel@tonic-gate cur_len) != 0) { 2345*0Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 2346*0Sstevel@tonic-gate break; 2347*0Sstevel@tonic-gate } 2348*0Sstevel@tonic-gate 2349*0Sstevel@tonic-gate length -= cur_len; 2350*0Sstevel@tonic-gate vec_idx++; 2351*0Sstevel@tonic-gate scratch_offset += cur_len; 2352*0Sstevel@tonic-gate offset = 0; 2353*0Sstevel@tonic-gate } 2354*0Sstevel@tonic-gate break; 2355*0Sstevel@tonic-gate } 2356*0Sstevel@tonic-gate 2357*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: { 2358*0Sstevel@tonic-gate off_t offset = mac->cd_offset; 2359*0Sstevel@tonic-gate mblk_t *mp; 2360*0Sstevel@tonic-gate off_t scratch_offset = 0; 2361*0Sstevel@tonic-gate size_t length = digest_len; 2362*0Sstevel@tonic-gate size_t cur_len; 2363*0Sstevel@tonic-gate 2364*0Sstevel@tonic-gate /* jump to the first mblk_t containing the expected digest */ 2365*0Sstevel@tonic-gate for (mp = mac->cd_mp; mp != NULL && offset >= MBLKL(mp); 2366*0Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 2367*0Sstevel@tonic-gate if (mp == NULL) { 2368*0Sstevel@tonic-gate /* 2369*0Sstevel@tonic-gate * The caller specified an offset that is larger than 2370*0Sstevel@tonic-gate * the total size of the buffers it provided. 2371*0Sstevel@tonic-gate */ 2372*0Sstevel@tonic-gate ret = CRYPTO_DATA_LEN_RANGE; 2373*0Sstevel@tonic-gate break; 2374*0Sstevel@tonic-gate } 2375*0Sstevel@tonic-gate 2376*0Sstevel@tonic-gate while (mp != NULL && length > 0) { 2377*0Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 2378*0Sstevel@tonic-gate if (bcmp(digest + scratch_offset, 2379*0Sstevel@tonic-gate mp->b_rptr + offset, cur_len) != 0) { 2380*0Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 2381*0Sstevel@tonic-gate break; 2382*0Sstevel@tonic-gate } 2383*0Sstevel@tonic-gate 2384*0Sstevel@tonic-gate length -= cur_len; 2385*0Sstevel@tonic-gate mp = mp->b_cont; 2386*0Sstevel@tonic-gate scratch_offset += cur_len; 2387*0Sstevel@tonic-gate offset = 0; 2388*0Sstevel@tonic-gate } 2389*0Sstevel@tonic-gate break; 2390*0Sstevel@tonic-gate } 2391*0Sstevel@tonic-gate 2392*0Sstevel@tonic-gate default: 2393*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 2394*0Sstevel@tonic-gate } 2395*0Sstevel@tonic-gate 2396*0Sstevel@tonic-gate bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 2397*0Sstevel@tonic-gate return (ret); 2398*0Sstevel@tonic-gate bail: 2399*0Sstevel@tonic-gate bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t)); 2400*0Sstevel@tonic-gate mac->cd_length = 0; 2401*0Sstevel@tonic-gate return (ret); 2402*0Sstevel@tonic-gate } 2403*0Sstevel@tonic-gate 2404*0Sstevel@tonic-gate /* 2405*0Sstevel@tonic-gate * KCF software provider context management entry points. 2406*0Sstevel@tonic-gate */ 2407*0Sstevel@tonic-gate 2408*0Sstevel@tonic-gate /* ARGSUSED */ 2409*0Sstevel@tonic-gate static int 2410*0Sstevel@tonic-gate sha1_create_ctx_template(crypto_provider_handle_t provider, 2411*0Sstevel@tonic-gate crypto_mechanism_t *mechanism, crypto_key_t *key, 2412*0Sstevel@tonic-gate crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size, 2413*0Sstevel@tonic-gate crypto_req_handle_t req) 2414*0Sstevel@tonic-gate { 2415*0Sstevel@tonic-gate sha1_hmac_ctx_t *sha1_hmac_ctx_tmpl; 2416*0Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 2417*0Sstevel@tonic-gate 2418*0Sstevel@tonic-gate if ((mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE) && 2419*0Sstevel@tonic-gate (mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE)) { 2420*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 2421*0Sstevel@tonic-gate } 2422*0Sstevel@tonic-gate 2423*0Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 2424*0Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 2425*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 2426*0Sstevel@tonic-gate 2427*0Sstevel@tonic-gate /* 2428*0Sstevel@tonic-gate * Allocate and initialize SHA1 context. 2429*0Sstevel@tonic-gate */ 2430*0Sstevel@tonic-gate sha1_hmac_ctx_tmpl = kmem_alloc(sizeof (sha1_hmac_ctx_t), 2431*0Sstevel@tonic-gate crypto_kmflag(req)); 2432*0Sstevel@tonic-gate if (sha1_hmac_ctx_tmpl == NULL) 2433*0Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 2434*0Sstevel@tonic-gate 2435*0Sstevel@tonic-gate if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) { 2436*0Sstevel@tonic-gate uchar_t digested_key[SHA1_DIGEST_LENGTH]; 2437*0Sstevel@tonic-gate 2438*0Sstevel@tonic-gate /* 2439*0Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 2440*0Sstevel@tonic-gate * The inner context is used since it hasn't been 2441*0Sstevel@tonic-gate * initialized yet. 2442*0Sstevel@tonic-gate */ 2443*0Sstevel@tonic-gate PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx_tmpl->hc_icontext, 2444*0Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digested_key); 2445*0Sstevel@tonic-gate sha1_mac_init_ctx(sha1_hmac_ctx_tmpl, digested_key, 2446*0Sstevel@tonic-gate SHA1_DIGEST_LENGTH); 2447*0Sstevel@tonic-gate } else { 2448*0Sstevel@tonic-gate sha1_mac_init_ctx(sha1_hmac_ctx_tmpl, key->ck_data, 2449*0Sstevel@tonic-gate keylen_in_bytes); 2450*0Sstevel@tonic-gate } 2451*0Sstevel@tonic-gate 2452*0Sstevel@tonic-gate sha1_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type; 2453*0Sstevel@tonic-gate *ctx_template = (crypto_spi_ctx_template_t)sha1_hmac_ctx_tmpl; 2454*0Sstevel@tonic-gate *ctx_template_size = sizeof (sha1_hmac_ctx_t); 2455*0Sstevel@tonic-gate 2456*0Sstevel@tonic-gate 2457*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 2458*0Sstevel@tonic-gate } 2459*0Sstevel@tonic-gate 2460*0Sstevel@tonic-gate static int 2461*0Sstevel@tonic-gate sha1_free_context(crypto_ctx_t *ctx) 2462*0Sstevel@tonic-gate { 2463*0Sstevel@tonic-gate uint_t ctx_len; 2464*0Sstevel@tonic-gate sha1_mech_type_t mech_type; 2465*0Sstevel@tonic-gate 2466*0Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 2467*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 2468*0Sstevel@tonic-gate 2469*0Sstevel@tonic-gate /* 2470*0Sstevel@tonic-gate * We have to free either SHA1 or SHA1-HMAC contexts, which 2471*0Sstevel@tonic-gate * have different lengths. 2472*0Sstevel@tonic-gate */ 2473*0Sstevel@tonic-gate 2474*0Sstevel@tonic-gate mech_type = PROV_SHA1_CTX(ctx)->sc_mech_type; 2475*0Sstevel@tonic-gate if (mech_type == SHA1_MECH_INFO_TYPE) 2476*0Sstevel@tonic-gate ctx_len = sizeof (sha1_ctx_t); 2477*0Sstevel@tonic-gate else { 2478*0Sstevel@tonic-gate ASSERT(mech_type == SHA1_HMAC_MECH_INFO_TYPE || 2479*0Sstevel@tonic-gate mech_type == SHA1_HMAC_GEN_MECH_INFO_TYPE); 2480*0Sstevel@tonic-gate ctx_len = sizeof (sha1_hmac_ctx_t); 2481*0Sstevel@tonic-gate } 2482*0Sstevel@tonic-gate 2483*0Sstevel@tonic-gate bzero(ctx->cc_provider_private, ctx_len); 2484*0Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, ctx_len); 2485*0Sstevel@tonic-gate ctx->cc_provider_private = NULL; 2486*0Sstevel@tonic-gate 2487*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 2488*0Sstevel@tonic-gate } 2489*0Sstevel@tonic-gate 2490*0Sstevel@tonic-gate #endif /* _KERNEL */ 2491