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