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