10Sstevel@tonic-gate /* 2*1551Sdarrenm * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 70Sstevel@tonic-gate 80Sstevel@tonic-gate 90Sstevel@tonic-gate /* 100Sstevel@tonic-gate * The basic framework for this code came from the reference 110Sstevel@tonic-gate * implementation for MD5. That implementation is Copyright (C) 120Sstevel@tonic-gate * 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * License to copy and use this software is granted provided that it 150Sstevel@tonic-gate * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 160Sstevel@tonic-gate * Algorithm" in all material mentioning or referencing this software 170Sstevel@tonic-gate * or this function. 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * License is also granted to make and use derivative works provided 200Sstevel@tonic-gate * that such works are identified as "derived from the RSA Data 210Sstevel@tonic-gate * Security, Inc. MD5 Message-Digest Algorithm" in all material 220Sstevel@tonic-gate * mentioning or referencing the derived work. 230Sstevel@tonic-gate * 240Sstevel@tonic-gate * RSA Data Security, Inc. makes no representations concerning either 250Sstevel@tonic-gate * the merchantability of this software or the suitability of this 260Sstevel@tonic-gate * software for any particular purpose. It is provided "as is" 270Sstevel@tonic-gate * without express or implied warranty of any kind. 280Sstevel@tonic-gate * 290Sstevel@tonic-gate * These notices must be retained in any copies of any part of this 300Sstevel@tonic-gate * documentation and/or software. 310Sstevel@tonic-gate * 320Sstevel@tonic-gate * NOTE: Cleaned-up and optimized, version of SHA2, based on the FIPS 180-2 330Sstevel@tonic-gate * standard, available at http://www.itl.nist.gov/div897/pubs/fip180-2.htm 340Sstevel@tonic-gate * Not as fast as one would like -- further optimizations are encouraged 350Sstevel@tonic-gate * and appreciated. 360Sstevel@tonic-gate */ 370Sstevel@tonic-gate 380Sstevel@tonic-gate #include <sys/types.h> 390Sstevel@tonic-gate #include <sys/param.h> 400Sstevel@tonic-gate #include <sys/systm.h> 410Sstevel@tonic-gate #include <sys/sysmacros.h> 420Sstevel@tonic-gate #include <sys/sha2.h> 430Sstevel@tonic-gate #include <sys/sha2_consts.h> 440Sstevel@tonic-gate 450Sstevel@tonic-gate #ifdef _KERNEL 460Sstevel@tonic-gate 470Sstevel@tonic-gate #include <sys/modctl.h> 480Sstevel@tonic-gate #include <sys/cmn_err.h> 490Sstevel@tonic-gate #include <sys/crypto/common.h> 500Sstevel@tonic-gate #include <sys/crypto/spi.h> 510Sstevel@tonic-gate #include <sys/strsun.h> 520Sstevel@tonic-gate 530Sstevel@tonic-gate /* 540Sstevel@tonic-gate * The sha2 module is created with two modlinkages: 550Sstevel@tonic-gate * - a modlmisc that allows consumers to directly call the entry points 560Sstevel@tonic-gate * SHA2Init, SHA2Update, and SHA2Final. 570Sstevel@tonic-gate * - a modlcrypto that allows the module to register with the Kernel 580Sstevel@tonic-gate * Cryptographic Framework (KCF) as a software provider for the SHA2 590Sstevel@tonic-gate * mechanisms. 600Sstevel@tonic-gate */ 610Sstevel@tonic-gate 620Sstevel@tonic-gate #else 630Sstevel@tonic-gate 640Sstevel@tonic-gate #include <strings.h> 650Sstevel@tonic-gate #include <stdlib.h> 660Sstevel@tonic-gate #include <errno.h> 670Sstevel@tonic-gate 680Sstevel@tonic-gate #endif /* !_KERNEL */ 690Sstevel@tonic-gate 700Sstevel@tonic-gate static void Encode(uint8_t *, uint32_t *, size_t); 710Sstevel@tonic-gate static void Encode64(uint8_t *, uint64_t *, size_t); 720Sstevel@tonic-gate static void SHA256Transform(SHA2_CTX *, const uint8_t *); 730Sstevel@tonic-gate static void SHA512Transform(SHA2_CTX *, const uint8_t *); 740Sstevel@tonic-gate 750Sstevel@tonic-gate static uint8_t PADDING[128] = { 0x80, /* all zeros */ }; 760Sstevel@tonic-gate 770Sstevel@tonic-gate /* Ch and Maj are the basic SHA2 functions. */ 780Sstevel@tonic-gate #define Ch(b, c, d) (((b) & (c)) ^ ((~b) & (d))) 790Sstevel@tonic-gate #define Maj(b, c, d) (((b) & (c)) ^ ((b) & (d)) ^ ((c) & (d))) 800Sstevel@tonic-gate 810Sstevel@tonic-gate /* Rotates x right n bits. */ 820Sstevel@tonic-gate #define ROTR(x, n) \ 830Sstevel@tonic-gate (((x) >> (n)) | ((x) << ((sizeof (x) * NBBY)-(n)))) 840Sstevel@tonic-gate 850Sstevel@tonic-gate /* Shift x right n bits */ 860Sstevel@tonic-gate #define SHR(x, n) ((x) >> (n)) 870Sstevel@tonic-gate 880Sstevel@tonic-gate /* SHA256 Functions */ 890Sstevel@tonic-gate #define BIGSIGMA0_256(x) (ROTR((x), 2) ^ ROTR((x), 13) ^ ROTR((x), 22)) 900Sstevel@tonic-gate #define BIGSIGMA1_256(x) (ROTR((x), 6) ^ ROTR((x), 11) ^ ROTR((x), 25)) 910Sstevel@tonic-gate #define SIGMA0_256(x) (ROTR((x), 7) ^ ROTR((x), 18) ^ SHR((x), 3)) 920Sstevel@tonic-gate #define SIGMA1_256(x) (ROTR((x), 17) ^ ROTR((x), 19) ^ SHR((x), 10)) 930Sstevel@tonic-gate 940Sstevel@tonic-gate #define SHA256ROUND(a, b, c, d, e, f, g, h, i, w) \ 950Sstevel@tonic-gate T1 = h + BIGSIGMA1_256(e) + Ch(e, f, g) + SHA256_CONST(i) + w; \ 960Sstevel@tonic-gate d += T1; \ 970Sstevel@tonic-gate T2 = BIGSIGMA0_256(a) + Maj(a, b, c); \ 980Sstevel@tonic-gate h = T1 + T2 990Sstevel@tonic-gate 1000Sstevel@tonic-gate /* SHA384/512 Functions */ 1010Sstevel@tonic-gate #define BIGSIGMA0(x) (ROTR((x), 28) ^ ROTR((x), 34) ^ ROTR((x), 39)) 1020Sstevel@tonic-gate #define BIGSIGMA1(x) (ROTR((x), 14) ^ ROTR((x), 18) ^ ROTR((x), 41)) 1030Sstevel@tonic-gate #define SIGMA0(x) (ROTR((x), 1) ^ ROTR((x), 8) ^ SHR((x), 7)) 1040Sstevel@tonic-gate #define SIGMA1(x) (ROTR((x), 19) ^ ROTR((x), 61) ^ SHR((x), 6)) 1050Sstevel@tonic-gate #define SHA512ROUND(a, b, c, d, e, f, g, h, i, w) \ 1060Sstevel@tonic-gate T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + SHA512_CONST(i) + w; \ 1070Sstevel@tonic-gate d += T1; \ 1080Sstevel@tonic-gate T2 = BIGSIGMA0(a) + Maj(a, b, c); \ 1090Sstevel@tonic-gate h = T1 + T2 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate #ifdef _KERNEL 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate static struct modlmisc modlmisc = { 1140Sstevel@tonic-gate &mod_miscops, 1150Sstevel@tonic-gate "SHA2 Message-Digest Algorithm" 1160Sstevel@tonic-gate }; 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate static struct modlcrypto modlcrypto = { 1190Sstevel@tonic-gate &mod_cryptoops, 1200Sstevel@tonic-gate "SHA2 Kernel SW Provider %I%" 1210Sstevel@tonic-gate }; 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate static struct modlinkage modlinkage = { 1240Sstevel@tonic-gate MODREV_1, &modlmisc, &modlcrypto, NULL 1250Sstevel@tonic-gate }; 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate /* 1280Sstevel@tonic-gate * CSPI information (entry points, provider info, etc.) 1290Sstevel@tonic-gate */ 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate #endif /* _KERNEL */ 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* 1340Sstevel@tonic-gate * List of support mechanisms in this module. 1350Sstevel@tonic-gate * 1360Sstevel@tonic-gate * It is important to note that in the module, division or modulus calculations 1370Sstevel@tonic-gate * are used on the enumerated type to determine which mechanism is being used; 1380Sstevel@tonic-gate * therefore, changing the order or additional mechanisms should be done 1390Sstevel@tonic-gate * carefully 1400Sstevel@tonic-gate */ 1410Sstevel@tonic-gate typedef enum sha2_mech_type { 1420Sstevel@tonic-gate SHA256_MECH_INFO_TYPE, /* SUN_CKM_SHA256 */ 1430Sstevel@tonic-gate SHA256_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC */ 1440Sstevel@tonic-gate SHA256_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC_GENERAL */ 1450Sstevel@tonic-gate SHA384_MECH_INFO_TYPE, /* SUN_CKM_SHA384 */ 1460Sstevel@tonic-gate SHA384_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC */ 1470Sstevel@tonic-gate SHA384_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC_GENERAL */ 1480Sstevel@tonic-gate SHA512_MECH_INFO_TYPE, /* SUN_CKM_SHA512 */ 1490Sstevel@tonic-gate SHA512_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC */ 1500Sstevel@tonic-gate SHA512_HMAC_GEN_MECH_INFO_TYPE /* SUN_CKM_SHA512_HMAC_GENERAL */ 1510Sstevel@tonic-gate } sha2_mech_type_t; 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate #ifdef _KERNEL 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate /* 1570Sstevel@tonic-gate * Context for SHA2 mechanism. 1580Sstevel@tonic-gate */ 1590Sstevel@tonic-gate typedef struct sha2_ctx { 1600Sstevel@tonic-gate sha2_mech_type_t sc_mech_type; /* type of context */ 1610Sstevel@tonic-gate SHA2_CTX sc_sha2_ctx; /* SHA2 context */ 1620Sstevel@tonic-gate } sha2_ctx_t; 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate /* 1650Sstevel@tonic-gate * Context for SHA2 HMAC and HMAC GENERAL mechanisms. 1660Sstevel@tonic-gate */ 1670Sstevel@tonic-gate typedef struct sha2_hmac_ctx { 1680Sstevel@tonic-gate sha2_mech_type_t hc_mech_type; /* type of context */ 1690Sstevel@tonic-gate uint32_t hc_digest_len; /* digest len in bytes */ 1700Sstevel@tonic-gate SHA2_CTX hc_icontext; /* inner SHA2 context */ 1710Sstevel@tonic-gate SHA2_CTX hc_ocontext; /* outer SHA2 context */ 1720Sstevel@tonic-gate } sha2_hmac_ctx_t; 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate /* 1750Sstevel@tonic-gate * Macros to access the SHA2 or SHA2-HMAC contexts from a context passed 1760Sstevel@tonic-gate * by KCF to one of the entry points. 1770Sstevel@tonic-gate */ 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate #define PROV_SHA2_CTX(ctx) ((sha2_ctx_t *)(ctx)->cc_provider_private) 1800Sstevel@tonic-gate #define PROV_SHA2_HMAC_CTX(ctx) ((sha2_hmac_ctx_t *)(ctx)->cc_provider_private) 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate /* to extract the digest length passed as mechanism parameter */ 1830Sstevel@tonic-gate #define PROV_SHA2_GET_DIGEST_LEN(m, len) { \ 1840Sstevel@tonic-gate if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t))) \ 1850Sstevel@tonic-gate (len) = (uint32_t)*((ulong_t *)(m)->cm_param); \ 1860Sstevel@tonic-gate else { \ 1870Sstevel@tonic-gate ulong_t tmp_ulong; \ 1880Sstevel@tonic-gate bcopy((m)->cm_param, &tmp_ulong, sizeof (ulong_t)); \ 1890Sstevel@tonic-gate (len) = (uint32_t)tmp_ulong; \ 1900Sstevel@tonic-gate } \ 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate #define PROV_SHA2_DIGEST_KEY(mech, ctx, key, len, digest) { \ 1940Sstevel@tonic-gate SHA2Init(mech, ctx); \ 1950Sstevel@tonic-gate SHA2Update(ctx, key, len); \ 1960Sstevel@tonic-gate SHA2Final(digest, ctx); \ 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate /* 2000Sstevel@tonic-gate * Mechanism info structure passed to KCF during registration. 2010Sstevel@tonic-gate */ 2020Sstevel@tonic-gate static crypto_mech_info_t sha2_mech_info_tab[] = { 2030Sstevel@tonic-gate /* SHA256 */ 2040Sstevel@tonic-gate {SUN_CKM_SHA256, SHA256_MECH_INFO_TYPE, 2050Sstevel@tonic-gate CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 2060Sstevel@tonic-gate 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2070Sstevel@tonic-gate /* SHA256-HMAC */ 2080Sstevel@tonic-gate {SUN_CKM_SHA256_HMAC, SHA256_HMAC_MECH_INFO_TYPE, 2090Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2100Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2110Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2120Sstevel@tonic-gate /* SHA256-HMAC GENERAL */ 2130Sstevel@tonic-gate {SUN_CKM_SHA256_HMAC_GENERAL, SHA256_HMAC_GEN_MECH_INFO_TYPE, 2140Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2150Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2160Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2170Sstevel@tonic-gate /* SHA384 */ 2180Sstevel@tonic-gate {SUN_CKM_SHA384, SHA384_MECH_INFO_TYPE, 2190Sstevel@tonic-gate CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 2200Sstevel@tonic-gate 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2210Sstevel@tonic-gate /* SHA384-HMAC */ 2220Sstevel@tonic-gate {SUN_CKM_SHA384_HMAC, SHA384_HMAC_MECH_INFO_TYPE, 2230Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2240Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2250Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2260Sstevel@tonic-gate /* SHA384-HMAC GENERAL */ 2270Sstevel@tonic-gate {SUN_CKM_SHA384_HMAC_GENERAL, SHA384_HMAC_GEN_MECH_INFO_TYPE, 2280Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2290Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2300Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2310Sstevel@tonic-gate /* SHA512 */ 2320Sstevel@tonic-gate {SUN_CKM_SHA512, SHA512_MECH_INFO_TYPE, 2330Sstevel@tonic-gate CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 2340Sstevel@tonic-gate 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2350Sstevel@tonic-gate /* SHA512-HMAC */ 2360Sstevel@tonic-gate {SUN_CKM_SHA512_HMAC, SHA512_HMAC_MECH_INFO_TYPE, 2370Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2380Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2390Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2400Sstevel@tonic-gate /* SHA512-HMAC GENERAL */ 2410Sstevel@tonic-gate {SUN_CKM_SHA512_HMAC_GENERAL, SHA512_HMAC_GEN_MECH_INFO_TYPE, 2420Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2430Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2440Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS} 2450Sstevel@tonic-gate }; 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate void SHA2Init(uint64_t, SHA2_CTX *); 2480Sstevel@tonic-gate void SHA2Update(SHA2_CTX *, const uint8_t *, uint32_t); 2490Sstevel@tonic-gate void SHA2Final(uint8_t *, SHA2_CTX *); 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate static void sha2_provider_status(crypto_provider_handle_t, uint_t *); 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate static crypto_control_ops_t sha2_control_ops = { 2540Sstevel@tonic-gate sha2_provider_status 2550Sstevel@tonic-gate }; 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate static int sha2_digest_init(crypto_ctx_t *, crypto_mechanism_t *, 2580Sstevel@tonic-gate crypto_req_handle_t); 2590Sstevel@tonic-gate static int sha2_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 2600Sstevel@tonic-gate crypto_req_handle_t); 2610Sstevel@tonic-gate static int sha2_digest_update(crypto_ctx_t *, crypto_data_t *, 2620Sstevel@tonic-gate crypto_req_handle_t); 2630Sstevel@tonic-gate static int sha2_digest_final(crypto_ctx_t *, crypto_data_t *, 2640Sstevel@tonic-gate crypto_req_handle_t); 2650Sstevel@tonic-gate static int sha2_digest_atomic(crypto_provider_handle_t, crypto_session_id_t, 2660Sstevel@tonic-gate crypto_mechanism_t *, crypto_data_t *, crypto_data_t *, 2670Sstevel@tonic-gate crypto_req_handle_t); 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate static crypto_digest_ops_t sha2_digest_ops = { 2700Sstevel@tonic-gate sha2_digest_init, 2710Sstevel@tonic-gate sha2_digest, 2720Sstevel@tonic-gate sha2_digest_update, 2730Sstevel@tonic-gate NULL, 2740Sstevel@tonic-gate sha2_digest_final, 2750Sstevel@tonic-gate sha2_digest_atomic 2760Sstevel@tonic-gate }; 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate static int sha2_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, 2790Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 2800Sstevel@tonic-gate static int sha2_mac_update(crypto_ctx_t *, crypto_data_t *, 2810Sstevel@tonic-gate crypto_req_handle_t); 2820Sstevel@tonic-gate static int sha2_mac_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); 2830Sstevel@tonic-gate static int sha2_mac_atomic(crypto_provider_handle_t, crypto_session_id_t, 2840Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 2850Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 2860Sstevel@tonic-gate static int sha2_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t, 2870Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 2880Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate static crypto_mac_ops_t sha2_mac_ops = { 2910Sstevel@tonic-gate sha2_mac_init, 2920Sstevel@tonic-gate NULL, 2930Sstevel@tonic-gate sha2_mac_update, 2940Sstevel@tonic-gate sha2_mac_final, 2950Sstevel@tonic-gate sha2_mac_atomic, 2960Sstevel@tonic-gate sha2_mac_verify_atomic 2970Sstevel@tonic-gate }; 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate static int sha2_create_ctx_template(crypto_provider_handle_t, 3000Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *, 3010Sstevel@tonic-gate size_t *, crypto_req_handle_t); 3020Sstevel@tonic-gate static int sha2_free_context(crypto_ctx_t *); 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate static crypto_ctx_ops_t sha2_ctx_ops = { 3050Sstevel@tonic-gate sha2_create_ctx_template, 3060Sstevel@tonic-gate sha2_free_context 3070Sstevel@tonic-gate }; 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate static crypto_ops_t sha2_crypto_ops = { 3100Sstevel@tonic-gate &sha2_control_ops, 3110Sstevel@tonic-gate &sha2_digest_ops, 3120Sstevel@tonic-gate NULL, 3130Sstevel@tonic-gate &sha2_mac_ops, 3140Sstevel@tonic-gate NULL, 3150Sstevel@tonic-gate NULL, 3160Sstevel@tonic-gate NULL, 3170Sstevel@tonic-gate NULL, 3180Sstevel@tonic-gate NULL, 3190Sstevel@tonic-gate NULL, 3200Sstevel@tonic-gate NULL, 3210Sstevel@tonic-gate NULL, 3220Sstevel@tonic-gate NULL, 3230Sstevel@tonic-gate &sha2_ctx_ops 3240Sstevel@tonic-gate }; 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate static crypto_provider_info_t sha2_prov_info = { 3270Sstevel@tonic-gate CRYPTO_SPI_VERSION_1, 3280Sstevel@tonic-gate "SHA2 Software Provider", 3290Sstevel@tonic-gate CRYPTO_SW_PROVIDER, 3300Sstevel@tonic-gate {&modlinkage}, 3310Sstevel@tonic-gate NULL, 3320Sstevel@tonic-gate &sha2_crypto_ops, 3330Sstevel@tonic-gate sizeof (sha2_mech_info_tab)/sizeof (crypto_mech_info_t), 3340Sstevel@tonic-gate sha2_mech_info_tab 3350Sstevel@tonic-gate }; 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate static crypto_kcf_provider_handle_t sha2_prov_handle = NULL; 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate int 3400Sstevel@tonic-gate _init() 3410Sstevel@tonic-gate { 3420Sstevel@tonic-gate int ret; 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate if ((ret = mod_install(&modlinkage)) != 0) 3450Sstevel@tonic-gate return (ret); 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* 3480Sstevel@tonic-gate * Register with KCF. If the registration fails, log an 3490Sstevel@tonic-gate * error but do not uninstall the module, since the functionality 3500Sstevel@tonic-gate * provided by misc/sha2 should still be available. 3510Sstevel@tonic-gate */ 3520Sstevel@tonic-gate if ((ret = crypto_register_provider(&sha2_prov_info, 3530Sstevel@tonic-gate &sha2_prov_handle)) != CRYPTO_SUCCESS) 3540Sstevel@tonic-gate cmn_err(CE_WARN, "sha2 _init: " 3550Sstevel@tonic-gate "crypto_register_provider() failed (0x%x)", ret); 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate return (0); 3580Sstevel@tonic-gate } 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate int 3610Sstevel@tonic-gate _info(struct modinfo *modinfop) 3620Sstevel@tonic-gate { 3630Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate #endif /* _KERNEL */ 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate /* 3700Sstevel@tonic-gate * sparc optimization: 3710Sstevel@tonic-gate * 3720Sstevel@tonic-gate * on the sparc, we can load big endian 32-bit data easily. note that 3730Sstevel@tonic-gate * special care must be taken to ensure the address is 32-bit aligned. 3740Sstevel@tonic-gate * in the interest of speed, we don't check to make sure, since 3750Sstevel@tonic-gate * careful programming can guarantee this for us. 3760Sstevel@tonic-gate */ 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate #if defined(_BIG_ENDIAN) 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate #define LOAD_BIG_32(addr) (*(uint32_t *)(addr)) 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate #else /* little endian -- will work on big endian, but slowly */ 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate #define LOAD_BIG_32(addr) \ 3850Sstevel@tonic-gate (((addr)[0] << 24) | ((addr)[1] << 16) | ((addr)[2] << 8) | (addr)[3]) 3860Sstevel@tonic-gate #endif 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate #if defined(_BIG_ENDIAN) 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate #define LOAD_BIG_64(addr) (*(uint64_t *)(addr)) 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate #else /* little endian -- will work on big endian, but slowly */ 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate #define LOAD_BIG_64(addr) \ 3960Sstevel@tonic-gate (((uint64_t)(addr)[0] << 56) | ((uint64_t)(addr)[1] << 48) | \ 3970Sstevel@tonic-gate ((uint64_t)(addr)[2] << 40) | ((uint64_t)(addr)[3] << 32) | \ 3980Sstevel@tonic-gate ((uint64_t)(addr)[4] << 24) | ((uint64_t)(addr)[5] << 16) | \ 3990Sstevel@tonic-gate ((uint64_t)(addr)[6] << 8) | (uint64_t)(addr)[7]) 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate #endif 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate /* SHA256 Transform */ 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate static void 4070Sstevel@tonic-gate SHA256Transform(SHA2_CTX *ctx, const uint8_t *blk) 4080Sstevel@tonic-gate { 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate uint32_t a = ctx->state.s32[0]; 4110Sstevel@tonic-gate uint32_t b = ctx->state.s32[1]; 4120Sstevel@tonic-gate uint32_t c = ctx->state.s32[2]; 4130Sstevel@tonic-gate uint32_t d = ctx->state.s32[3]; 4140Sstevel@tonic-gate uint32_t e = ctx->state.s32[4]; 4150Sstevel@tonic-gate uint32_t f = ctx->state.s32[5]; 4160Sstevel@tonic-gate uint32_t g = ctx->state.s32[6]; 4170Sstevel@tonic-gate uint32_t h = ctx->state.s32[7]; 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate uint32_t w0, w1, w2, w3, w4, w5, w6, w7; 4200Sstevel@tonic-gate uint32_t w8, w9, w10, w11, w12, w13, w14, w15; 4210Sstevel@tonic-gate uint32_t T1, T2; 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate #if defined(__sparc) 4240Sstevel@tonic-gate static const uint32_t sha256_consts[] = { 4250Sstevel@tonic-gate SHA256_CONST_0, SHA256_CONST_1, SHA256_CONST_2, 4260Sstevel@tonic-gate SHA256_CONST_3, SHA256_CONST_4, SHA256_CONST_5, 4270Sstevel@tonic-gate SHA256_CONST_6, SHA256_CONST_7, SHA256_CONST_8, 4280Sstevel@tonic-gate SHA256_CONST_9, SHA256_CONST_10, SHA256_CONST_11, 4290Sstevel@tonic-gate SHA256_CONST_12, SHA256_CONST_13, SHA256_CONST_14, 4300Sstevel@tonic-gate SHA256_CONST_15, SHA256_CONST_16, SHA256_CONST_17, 4310Sstevel@tonic-gate SHA256_CONST_18, SHA256_CONST_19, SHA256_CONST_20, 4320Sstevel@tonic-gate SHA256_CONST_21, SHA256_CONST_22, SHA256_CONST_23, 4330Sstevel@tonic-gate SHA256_CONST_24, SHA256_CONST_25, SHA256_CONST_26, 4340Sstevel@tonic-gate SHA256_CONST_27, SHA256_CONST_28, SHA256_CONST_29, 4350Sstevel@tonic-gate SHA256_CONST_30, SHA256_CONST_31, SHA256_CONST_32, 4360Sstevel@tonic-gate SHA256_CONST_33, SHA256_CONST_34, SHA256_CONST_35, 4370Sstevel@tonic-gate SHA256_CONST_36, SHA256_CONST_37, SHA256_CONST_38, 4380Sstevel@tonic-gate SHA256_CONST_39, SHA256_CONST_40, SHA256_CONST_41, 4390Sstevel@tonic-gate SHA256_CONST_42, SHA256_CONST_43, SHA256_CONST_44, 4400Sstevel@tonic-gate SHA256_CONST_45, SHA256_CONST_46, SHA256_CONST_47, 4410Sstevel@tonic-gate SHA256_CONST_48, SHA256_CONST_49, SHA256_CONST_50, 4420Sstevel@tonic-gate SHA256_CONST_51, SHA256_CONST_52, SHA256_CONST_53, 4430Sstevel@tonic-gate SHA256_CONST_54, SHA256_CONST_55, SHA256_CONST_56, 4440Sstevel@tonic-gate SHA256_CONST_57, SHA256_CONST_58, SHA256_CONST_59, 4450Sstevel@tonic-gate SHA256_CONST_60, SHA256_CONST_61, SHA256_CONST_62, 4460Sstevel@tonic-gate SHA256_CONST_63 4470Sstevel@tonic-gate }; 4480Sstevel@tonic-gate #endif 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate if ((uintptr_t)blk & 0x3) { /* not 4-byte aligned? */ 4510Sstevel@tonic-gate bcopy(blk, ctx->buf_un.buf32, sizeof (ctx->buf_un.buf32)); 4520Sstevel@tonic-gate blk = (uint8_t *)ctx->buf_un.buf32; 4530Sstevel@tonic-gate } 4540Sstevel@tonic-gate 455676Sizick #if defined(__sparc) 456676Sizick /*LINTED*/ 457676Sizick w0 = LOAD_BIG_32(blk + 4 * 0); 458676Sizick SHA256ROUND(a, b, c, d, e, f, g, h, 0, w0); 459676Sizick /*LINTED*/ 460676Sizick w1 = LOAD_BIG_32(blk + 4 * 1); 461676Sizick SHA256ROUND(h, a, b, c, d, e, f, g, 1, w1); 462676Sizick /*LINTED*/ 463676Sizick w2 = LOAD_BIG_32(blk + 4 * 2); 464676Sizick SHA256ROUND(g, h, a, b, c, d, e, f, 2, w2); 465676Sizick /*LINTED*/ 466676Sizick w3 = LOAD_BIG_32(blk + 4 * 3); 467676Sizick SHA256ROUND(f, g, h, a, b, c, d, e, 3, w3); 468676Sizick /*LINTED*/ 469676Sizick w4 = LOAD_BIG_32(blk + 4 * 4); 470676Sizick SHA256ROUND(e, f, g, h, a, b, c, d, 4, w4); 471676Sizick /*LINTED*/ 472676Sizick w5 = LOAD_BIG_32(blk + 4 * 5); 473676Sizick SHA256ROUND(d, e, f, g, h, a, b, c, 5, w5); 474676Sizick /*LINTED*/ 475676Sizick w6 = LOAD_BIG_32(blk + 4 * 6); 476676Sizick SHA256ROUND(c, d, e, f, g, h, a, b, 6, w6); 477676Sizick /*LINTED*/ 478676Sizick w7 = LOAD_BIG_32(blk + 4 * 7); 479676Sizick SHA256ROUND(b, c, d, e, f, g, h, a, 7, w7); 480676Sizick /*LINTED*/ 481676Sizick w8 = LOAD_BIG_32(blk + 4 * 8); 482676Sizick SHA256ROUND(a, b, c, d, e, f, g, h, 8, w8); 483676Sizick /*LINTED*/ 484676Sizick w9 = LOAD_BIG_32(blk + 4 * 9); 485676Sizick SHA256ROUND(h, a, b, c, d, e, f, g, 9, w9); 486676Sizick /*LINTED*/ 487676Sizick w10 = LOAD_BIG_32(blk + 4 * 10); 488676Sizick SHA256ROUND(g, h, a, b, c, d, e, f, 10, w10); 489676Sizick /*LINTED*/ 490676Sizick w11 = LOAD_BIG_32(blk + 4 * 11); 491676Sizick SHA256ROUND(f, g, h, a, b, c, d, e, 11, w11); 492676Sizick /*LINTED*/ 493676Sizick w12 = LOAD_BIG_32(blk + 4 * 12); 494676Sizick SHA256ROUND(e, f, g, h, a, b, c, d, 12, w12); 495676Sizick /*LINTED*/ 496676Sizick w13 = LOAD_BIG_32(blk + 4 * 13); 497676Sizick SHA256ROUND(d, e, f, g, h, a, b, c, 13, w13); 498676Sizick /*LINTED*/ 499676Sizick w14 = LOAD_BIG_32(blk + 4 * 14); 500676Sizick SHA256ROUND(c, d, e, f, g, h, a, b, 14, w14); 501676Sizick /*LINTED*/ 502676Sizick w15 = LOAD_BIG_32(blk + 4 * 15); 503676Sizick SHA256ROUND(b, c, d, e, f, g, h, a, 15, w15); 504676Sizick 505676Sizick #else 506676Sizick 5070Sstevel@tonic-gate w0 = LOAD_BIG_32(blk + 4 * 0); 5080Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 0, w0); 5090Sstevel@tonic-gate w1 = LOAD_BIG_32(blk + 4 * 1); 5100Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 1, w1); 5110Sstevel@tonic-gate w2 = LOAD_BIG_32(blk + 4 * 2); 5120Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 2, w2); 5130Sstevel@tonic-gate w3 = LOAD_BIG_32(blk + 4 * 3); 5140Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 3, w3); 5150Sstevel@tonic-gate w4 = LOAD_BIG_32(blk + 4 * 4); 5160Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 4, w4); 5170Sstevel@tonic-gate w5 = LOAD_BIG_32(blk + 4 * 5); 5180Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 5, w5); 5190Sstevel@tonic-gate w6 = LOAD_BIG_32(blk + 4 * 6); 5200Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 6, w6); 5210Sstevel@tonic-gate w7 = LOAD_BIG_32(blk + 4 * 7); 5220Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 7, w7); 5230Sstevel@tonic-gate w8 = LOAD_BIG_32(blk + 4 * 8); 5240Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 8, w8); 5250Sstevel@tonic-gate w9 = LOAD_BIG_32(blk + 4 * 9); 5260Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 9, w9); 5270Sstevel@tonic-gate w10 = LOAD_BIG_32(blk + 4 * 10); 5280Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 10, w10); 5290Sstevel@tonic-gate w11 = LOAD_BIG_32(blk + 4 * 11); 5300Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 11, w11); 5310Sstevel@tonic-gate w12 = LOAD_BIG_32(blk + 4 * 12); 5320Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 12, w12); 5330Sstevel@tonic-gate w13 = LOAD_BIG_32(blk + 4 * 13); 5340Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 13, w13); 5350Sstevel@tonic-gate w14 = LOAD_BIG_32(blk + 4 * 14); 5360Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 14, w14); 5370Sstevel@tonic-gate w15 = LOAD_BIG_32(blk + 4 * 15); 5380Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 15, w15); 5390Sstevel@tonic-gate 540676Sizick #endif 541676Sizick 5420Sstevel@tonic-gate w0 = SIGMA1_256(w14) + w9 + SIGMA0_256(w1) + w0; 5430Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 16, w0); 5440Sstevel@tonic-gate w1 = SIGMA1_256(w15) + w10 + SIGMA0_256(w2) + w1; 5450Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 17, w1); 5460Sstevel@tonic-gate w2 = SIGMA1_256(w0) + w11 + SIGMA0_256(w3) + w2; 5470Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 18, w2); 5480Sstevel@tonic-gate w3 = SIGMA1_256(w1) + w12 + SIGMA0_256(w4) + w3; 5490Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 19, w3); 5500Sstevel@tonic-gate w4 = SIGMA1_256(w2) + w13 + SIGMA0_256(w5) + w4; 5510Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 20, w4); 5520Sstevel@tonic-gate w5 = SIGMA1_256(w3) + w14 + SIGMA0_256(w6) + w5; 5530Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 21, w5); 5540Sstevel@tonic-gate w6 = SIGMA1_256(w4) + w15 + SIGMA0_256(w7) + w6; 5550Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 22, w6); 5560Sstevel@tonic-gate w7 = SIGMA1_256(w5) + w0 + SIGMA0_256(w8) + w7; 5570Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 23, w7); 5580Sstevel@tonic-gate w8 = SIGMA1_256(w6) + w1 + SIGMA0_256(w9) + w8; 5590Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 24, w8); 5600Sstevel@tonic-gate w9 = SIGMA1_256(w7) + w2 + SIGMA0_256(w10) + w9; 5610Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 25, w9); 5620Sstevel@tonic-gate w10 = SIGMA1_256(w8) + w3 + SIGMA0_256(w11) + w10; 5630Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 26, w10); 5640Sstevel@tonic-gate w11 = SIGMA1_256(w9) + w4 + SIGMA0_256(w12) + w11; 5650Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 27, w11); 5660Sstevel@tonic-gate w12 = SIGMA1_256(w10) + w5 + SIGMA0_256(w13) + w12; 5670Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 28, w12); 5680Sstevel@tonic-gate w13 = SIGMA1_256(w11) + w6 + SIGMA0_256(w14) + w13; 5690Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 29, w13); 5700Sstevel@tonic-gate w14 = SIGMA1_256(w12) + w7 + SIGMA0_256(w15) + w14; 5710Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 30, w14); 5720Sstevel@tonic-gate w15 = SIGMA1_256(w13) + w8 + SIGMA0_256(w0) + w15; 5730Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 31, w15); 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate w0 = SIGMA1_256(w14) + w9 + SIGMA0_256(w1) + w0; 5760Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 32, w0); 5770Sstevel@tonic-gate w1 = SIGMA1_256(w15) + w10 + SIGMA0_256(w2) + w1; 5780Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 33, w1); 5790Sstevel@tonic-gate w2 = SIGMA1_256(w0) + w11 + SIGMA0_256(w3) + w2; 5800Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 34, w2); 5810Sstevel@tonic-gate w3 = SIGMA1_256(w1) + w12 + SIGMA0_256(w4) + w3; 5820Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 35, w3); 5830Sstevel@tonic-gate w4 = SIGMA1_256(w2) + w13 + SIGMA0_256(w5) + w4; 5840Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 36, w4); 5850Sstevel@tonic-gate w5 = SIGMA1_256(w3) + w14 + SIGMA0_256(w6) + w5; 5860Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 37, w5); 5870Sstevel@tonic-gate w6 = SIGMA1_256(w4) + w15 + SIGMA0_256(w7) + w6; 5880Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 38, w6); 5890Sstevel@tonic-gate w7 = SIGMA1_256(w5) + w0 + SIGMA0_256(w8) + w7; 5900Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 39, w7); 5910Sstevel@tonic-gate w8 = SIGMA1_256(w6) + w1 + SIGMA0_256(w9) + w8; 5920Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 40, w8); 5930Sstevel@tonic-gate w9 = SIGMA1_256(w7) + w2 + SIGMA0_256(w10) + w9; 5940Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 41, w9); 5950Sstevel@tonic-gate w10 = SIGMA1_256(w8) + w3 + SIGMA0_256(w11) + w10; 5960Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 42, w10); 5970Sstevel@tonic-gate w11 = SIGMA1_256(w9) + w4 + SIGMA0_256(w12) + w11; 5980Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 43, w11); 5990Sstevel@tonic-gate w12 = SIGMA1_256(w10) + w5 + SIGMA0_256(w13) + w12; 6000Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 44, w12); 6010Sstevel@tonic-gate w13 = SIGMA1_256(w11) + w6 + SIGMA0_256(w14) + w13; 6020Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 45, w13); 6030Sstevel@tonic-gate w14 = SIGMA1_256(w12) + w7 + SIGMA0_256(w15) + w14; 6040Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 46, w14); 6050Sstevel@tonic-gate w15 = SIGMA1_256(w13) + w8 + SIGMA0_256(w0) + w15; 6060Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 47, w15); 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate w0 = SIGMA1_256(w14) + w9 + SIGMA0_256(w1) + w0; 6090Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 48, w0); 6100Sstevel@tonic-gate w1 = SIGMA1_256(w15) + w10 + SIGMA0_256(w2) + w1; 6110Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 49, w1); 6120Sstevel@tonic-gate w2 = SIGMA1_256(w0) + w11 + SIGMA0_256(w3) + w2; 6130Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 50, w2); 6140Sstevel@tonic-gate w3 = SIGMA1_256(w1) + w12 + SIGMA0_256(w4) + w3; 6150Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 51, w3); 6160Sstevel@tonic-gate w4 = SIGMA1_256(w2) + w13 + SIGMA0_256(w5) + w4; 6170Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 52, w4); 6180Sstevel@tonic-gate w5 = SIGMA1_256(w3) + w14 + SIGMA0_256(w6) + w5; 6190Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 53, w5); 6200Sstevel@tonic-gate w6 = SIGMA1_256(w4) + w15 + SIGMA0_256(w7) + w6; 6210Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 54, w6); 6220Sstevel@tonic-gate w7 = SIGMA1_256(w5) + w0 + SIGMA0_256(w8) + w7; 6230Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 55, w7); 6240Sstevel@tonic-gate w8 = SIGMA1_256(w6) + w1 + SIGMA0_256(w9) + w8; 6250Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 56, w8); 6260Sstevel@tonic-gate w9 = SIGMA1_256(w7) + w2 + SIGMA0_256(w10) + w9; 6270Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 57, w9); 6280Sstevel@tonic-gate w10 = SIGMA1_256(w8) + w3 + SIGMA0_256(w11) + w10; 6290Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 58, w10); 6300Sstevel@tonic-gate w11 = SIGMA1_256(w9) + w4 + SIGMA0_256(w12) + w11; 6310Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 59, w11); 6320Sstevel@tonic-gate w12 = SIGMA1_256(w10) + w5 + SIGMA0_256(w13) + w12; 6330Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 60, w12); 6340Sstevel@tonic-gate w13 = SIGMA1_256(w11) + w6 + SIGMA0_256(w14) + w13; 6350Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 61, w13); 6360Sstevel@tonic-gate w14 = SIGMA1_256(w12) + w7 + SIGMA0_256(w15) + w14; 6370Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 62, w14); 6380Sstevel@tonic-gate w15 = SIGMA1_256(w13) + w8 + SIGMA0_256(w0) + w15; 6390Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 63, w15); 6400Sstevel@tonic-gate 6410Sstevel@tonic-gate ctx->state.s32[0] += a; 6420Sstevel@tonic-gate ctx->state.s32[1] += b; 6430Sstevel@tonic-gate ctx->state.s32[2] += c; 6440Sstevel@tonic-gate ctx->state.s32[3] += d; 6450Sstevel@tonic-gate ctx->state.s32[4] += e; 6460Sstevel@tonic-gate ctx->state.s32[5] += f; 6470Sstevel@tonic-gate ctx->state.s32[6] += g; 6480Sstevel@tonic-gate ctx->state.s32[7] += h; 6490Sstevel@tonic-gate } 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate /* SHA384 and SHA512 Transform */ 6530Sstevel@tonic-gate 6540Sstevel@tonic-gate static void 6550Sstevel@tonic-gate SHA512Transform(SHA2_CTX *ctx, const uint8_t *blk) 6560Sstevel@tonic-gate { 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate uint64_t a = ctx->state.s64[0]; 6590Sstevel@tonic-gate uint64_t b = ctx->state.s64[1]; 6600Sstevel@tonic-gate uint64_t c = ctx->state.s64[2]; 6610Sstevel@tonic-gate uint64_t d = ctx->state.s64[3]; 6620Sstevel@tonic-gate uint64_t e = ctx->state.s64[4]; 6630Sstevel@tonic-gate uint64_t f = ctx->state.s64[5]; 6640Sstevel@tonic-gate uint64_t g = ctx->state.s64[6]; 6650Sstevel@tonic-gate uint64_t h = ctx->state.s64[7]; 6660Sstevel@tonic-gate 6670Sstevel@tonic-gate uint64_t w0, w1, w2, w3, w4, w5, w6, w7; 6680Sstevel@tonic-gate uint64_t w8, w9, w10, w11, w12, w13, w14, w15; 6690Sstevel@tonic-gate uint64_t T1, T2; 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate #if defined(__sparc) 6720Sstevel@tonic-gate static const uint64_t sha512_consts[] = { 6730Sstevel@tonic-gate SHA512_CONST_0, SHA512_CONST_1, SHA512_CONST_2, 6740Sstevel@tonic-gate SHA512_CONST_3, SHA512_CONST_4, SHA512_CONST_5, 6750Sstevel@tonic-gate SHA512_CONST_6, SHA512_CONST_7, SHA512_CONST_8, 6760Sstevel@tonic-gate SHA512_CONST_9, SHA512_CONST_10, SHA512_CONST_11, 6770Sstevel@tonic-gate SHA512_CONST_12, SHA512_CONST_13, SHA512_CONST_14, 6780Sstevel@tonic-gate SHA512_CONST_15, SHA512_CONST_16, SHA512_CONST_17, 6790Sstevel@tonic-gate SHA512_CONST_18, SHA512_CONST_19, SHA512_CONST_20, 6800Sstevel@tonic-gate SHA512_CONST_21, SHA512_CONST_22, SHA512_CONST_23, 6810Sstevel@tonic-gate SHA512_CONST_24, SHA512_CONST_25, SHA512_CONST_26, 6820Sstevel@tonic-gate SHA512_CONST_27, SHA512_CONST_28, SHA512_CONST_29, 6830Sstevel@tonic-gate SHA512_CONST_30, SHA512_CONST_31, SHA512_CONST_32, 6840Sstevel@tonic-gate SHA512_CONST_33, SHA512_CONST_34, SHA512_CONST_35, 6850Sstevel@tonic-gate SHA512_CONST_36, SHA512_CONST_37, SHA512_CONST_38, 6860Sstevel@tonic-gate SHA512_CONST_39, SHA512_CONST_40, SHA512_CONST_41, 6870Sstevel@tonic-gate SHA512_CONST_42, SHA512_CONST_43, SHA512_CONST_44, 6880Sstevel@tonic-gate SHA512_CONST_45, SHA512_CONST_46, SHA512_CONST_47, 6890Sstevel@tonic-gate SHA512_CONST_48, SHA512_CONST_49, SHA512_CONST_50, 6900Sstevel@tonic-gate SHA512_CONST_51, SHA512_CONST_52, SHA512_CONST_53, 6910Sstevel@tonic-gate SHA512_CONST_54, SHA512_CONST_55, SHA512_CONST_56, 6920Sstevel@tonic-gate SHA512_CONST_57, SHA512_CONST_58, SHA512_CONST_59, 6930Sstevel@tonic-gate SHA512_CONST_60, SHA512_CONST_61, SHA512_CONST_62, 6940Sstevel@tonic-gate SHA512_CONST_63, SHA512_CONST_64, SHA512_CONST_65, 6950Sstevel@tonic-gate SHA512_CONST_66, SHA512_CONST_67, SHA512_CONST_68, 6960Sstevel@tonic-gate SHA512_CONST_69, SHA512_CONST_70, SHA512_CONST_71, 6970Sstevel@tonic-gate SHA512_CONST_72, SHA512_CONST_73, SHA512_CONST_74, 6980Sstevel@tonic-gate SHA512_CONST_75, SHA512_CONST_76, SHA512_CONST_77, 6990Sstevel@tonic-gate SHA512_CONST_78, SHA512_CONST_79 7000Sstevel@tonic-gate }; 7010Sstevel@tonic-gate #endif 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate 7040Sstevel@tonic-gate if ((uintptr_t)blk & 0x7) { /* not 8-byte aligned? */ 7050Sstevel@tonic-gate bcopy(blk, ctx->buf_un.buf64, sizeof (ctx->buf_un.buf64)); 7060Sstevel@tonic-gate blk = (uint8_t *)ctx->buf_un.buf64; 7070Sstevel@tonic-gate } 7080Sstevel@tonic-gate 709676Sizick #if defined(__sparc) 710676Sizick /*LINTED*/ 711676Sizick w0 = LOAD_BIG_64(blk + 8 * 0); 712676Sizick SHA512ROUND(a, b, c, d, e, f, g, h, 0, w0); 713676Sizick /*LINTED*/ 714676Sizick w1 = LOAD_BIG_64(blk + 8 * 1); 715676Sizick SHA512ROUND(h, a, b, c, d, e, f, g, 1, w1); 716676Sizick /*LINTED*/ 717676Sizick w2 = LOAD_BIG_64(blk + 8 * 2); 718676Sizick SHA512ROUND(g, h, a, b, c, d, e, f, 2, w2); 719676Sizick /*LINTED*/ 720676Sizick w3 = LOAD_BIG_64(blk + 8 * 3); 721676Sizick SHA512ROUND(f, g, h, a, b, c, d, e, 3, w3); 722676Sizick /*LINTED*/ 723676Sizick w4 = LOAD_BIG_64(blk + 8 * 4); 724676Sizick SHA512ROUND(e, f, g, h, a, b, c, d, 4, w4); 725676Sizick /*LINTED*/ 726676Sizick w5 = LOAD_BIG_64(blk + 8 * 5); 727676Sizick SHA512ROUND(d, e, f, g, h, a, b, c, 5, w5); 728676Sizick /*LINTED*/ 729676Sizick w6 = LOAD_BIG_64(blk + 8 * 6); 730676Sizick SHA512ROUND(c, d, e, f, g, h, a, b, 6, w6); 731676Sizick /*LINTED*/ 732676Sizick w7 = LOAD_BIG_64(blk + 8 * 7); 733676Sizick SHA512ROUND(b, c, d, e, f, g, h, a, 7, w7); 734676Sizick /*LINTED*/ 735676Sizick w8 = LOAD_BIG_64(blk + 8 * 8); 736676Sizick SHA512ROUND(a, b, c, d, e, f, g, h, 8, w8); 737676Sizick /*LINTED*/ 738676Sizick w9 = LOAD_BIG_64(blk + 8 * 9); 739676Sizick SHA512ROUND(h, a, b, c, d, e, f, g, 9, w9); 740676Sizick /*LINTED*/ 741676Sizick w10 = LOAD_BIG_64(blk + 8 * 10); 742676Sizick SHA512ROUND(g, h, a, b, c, d, e, f, 10, w10); 743676Sizick /*LINTED*/ 744676Sizick w11 = LOAD_BIG_64(blk + 8 * 11); 745676Sizick SHA512ROUND(f, g, h, a, b, c, d, e, 11, w11); 746676Sizick /*LINTED*/ 747676Sizick w12 = LOAD_BIG_64(blk + 8 * 12); 748676Sizick SHA512ROUND(e, f, g, h, a, b, c, d, 12, w12); 749676Sizick /*LINTED*/ 750676Sizick w13 = LOAD_BIG_64(blk + 8 * 13); 751676Sizick SHA512ROUND(d, e, f, g, h, a, b, c, 13, w13); 752676Sizick /*LINTED*/ 753676Sizick w14 = LOAD_BIG_64(blk + 8 * 14); 754676Sizick SHA512ROUND(c, d, e, f, g, h, a, b, 14, w14); 755676Sizick /*LINTED*/ 756676Sizick w15 = LOAD_BIG_64(blk + 8 * 15); 757676Sizick SHA512ROUND(b, c, d, e, f, g, h, a, 15, w15); 758676Sizick 759676Sizick #else 760676Sizick 7610Sstevel@tonic-gate w0 = LOAD_BIG_64(blk + 8 * 0); 7620Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 0, w0); 7630Sstevel@tonic-gate w1 = LOAD_BIG_64(blk + 8 * 1); 7640Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 1, w1); 7650Sstevel@tonic-gate w2 = LOAD_BIG_64(blk + 8 * 2); 7660Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 2, w2); 7670Sstevel@tonic-gate w3 = LOAD_BIG_64(blk + 8 * 3); 7680Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 3, w3); 7690Sstevel@tonic-gate w4 = LOAD_BIG_64(blk + 8 * 4); 7700Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 4, w4); 7710Sstevel@tonic-gate w5 = LOAD_BIG_64(blk + 8 * 5); 7720Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 5, w5); 7730Sstevel@tonic-gate w6 = LOAD_BIG_64(blk + 8 * 6); 7740Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 6, w6); 7750Sstevel@tonic-gate w7 = LOAD_BIG_64(blk + 8 * 7); 7760Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 7, w7); 7770Sstevel@tonic-gate w8 = LOAD_BIG_64(blk + 8 * 8); 7780Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 8, w8); 7790Sstevel@tonic-gate w9 = LOAD_BIG_64(blk + 8 * 9); 7800Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 9, w9); 7810Sstevel@tonic-gate w10 = LOAD_BIG_64(blk + 8 * 10); 7820Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 10, w10); 7830Sstevel@tonic-gate w11 = LOAD_BIG_64(blk + 8 * 11); 7840Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 11, w11); 7850Sstevel@tonic-gate w12 = LOAD_BIG_64(blk + 8 * 12); 7860Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 12, w12); 7870Sstevel@tonic-gate w13 = LOAD_BIG_64(blk + 8 * 13); 7880Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 13, w13); 7890Sstevel@tonic-gate w14 = LOAD_BIG_64(blk + 8 * 14); 7900Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 14, w14); 7910Sstevel@tonic-gate w15 = LOAD_BIG_64(blk + 8 * 15); 7920Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 15, w15); 7930Sstevel@tonic-gate 794676Sizick #endif 795676Sizick 7960Sstevel@tonic-gate w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0; 7970Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 16, w0); 7980Sstevel@tonic-gate w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1; 7990Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 17, w1); 8000Sstevel@tonic-gate w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2; 8010Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 18, w2); 8020Sstevel@tonic-gate w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3; 8030Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 19, w3); 8040Sstevel@tonic-gate w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4; 8050Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 20, w4); 8060Sstevel@tonic-gate w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5; 8070Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 21, w5); 8080Sstevel@tonic-gate w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6; 8090Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 22, w6); 8100Sstevel@tonic-gate w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7; 8110Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 23, w7); 8120Sstevel@tonic-gate w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8; 8130Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 24, w8); 8140Sstevel@tonic-gate w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9; 8150Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 25, w9); 8160Sstevel@tonic-gate w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10; 8170Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 26, w10); 8180Sstevel@tonic-gate w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11; 8190Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 27, w11); 8200Sstevel@tonic-gate w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12; 8210Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 28, w12); 8220Sstevel@tonic-gate w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13; 8230Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 29, w13); 8240Sstevel@tonic-gate w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14; 8250Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 30, w14); 8260Sstevel@tonic-gate w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15; 8270Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 31, w15); 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0; 8300Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 32, w0); 8310Sstevel@tonic-gate w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1; 8320Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 33, w1); 8330Sstevel@tonic-gate w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2; 8340Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 34, w2); 8350Sstevel@tonic-gate w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3; 8360Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 35, w3); 8370Sstevel@tonic-gate w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4; 8380Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 36, w4); 8390Sstevel@tonic-gate w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5; 8400Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 37, w5); 8410Sstevel@tonic-gate w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6; 8420Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 38, w6); 8430Sstevel@tonic-gate w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7; 8440Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 39, w7); 8450Sstevel@tonic-gate w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8; 8460Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 40, w8); 8470Sstevel@tonic-gate w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9; 8480Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 41, w9); 8490Sstevel@tonic-gate w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10; 8500Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 42, w10); 8510Sstevel@tonic-gate w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11; 8520Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 43, w11); 8530Sstevel@tonic-gate w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12; 8540Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 44, w12); 8550Sstevel@tonic-gate w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13; 8560Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 45, w13); 8570Sstevel@tonic-gate w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14; 8580Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 46, w14); 8590Sstevel@tonic-gate w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15; 8600Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 47, w15); 8610Sstevel@tonic-gate 8620Sstevel@tonic-gate w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0; 8630Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 48, w0); 8640Sstevel@tonic-gate w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1; 8650Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 49, w1); 8660Sstevel@tonic-gate w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2; 8670Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 50, w2); 8680Sstevel@tonic-gate w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3; 8690Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 51, w3); 8700Sstevel@tonic-gate w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4; 8710Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 52, w4); 8720Sstevel@tonic-gate w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5; 8730Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 53, w5); 8740Sstevel@tonic-gate w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6; 8750Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 54, w6); 8760Sstevel@tonic-gate w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7; 8770Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 55, w7); 8780Sstevel@tonic-gate w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8; 8790Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 56, w8); 8800Sstevel@tonic-gate w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9; 8810Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 57, w9); 8820Sstevel@tonic-gate w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10; 8830Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 58, w10); 8840Sstevel@tonic-gate w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11; 8850Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 59, w11); 8860Sstevel@tonic-gate w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12; 8870Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 60, w12); 8880Sstevel@tonic-gate w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13; 8890Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 61, w13); 8900Sstevel@tonic-gate w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14; 8910Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 62, w14); 8920Sstevel@tonic-gate w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15; 8930Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 63, w15); 8940Sstevel@tonic-gate 8950Sstevel@tonic-gate w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0; 8960Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 64, w0); 8970Sstevel@tonic-gate w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1; 8980Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 65, w1); 8990Sstevel@tonic-gate w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2; 9000Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 66, w2); 9010Sstevel@tonic-gate w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3; 9020Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 67, w3); 9030Sstevel@tonic-gate w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4; 9040Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 68, w4); 9050Sstevel@tonic-gate w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5; 9060Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 69, w5); 9070Sstevel@tonic-gate w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6; 9080Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 70, w6); 9090Sstevel@tonic-gate w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7; 9100Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 71, w7); 9110Sstevel@tonic-gate w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8; 9120Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 72, w8); 9130Sstevel@tonic-gate w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9; 9140Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 73, w9); 9150Sstevel@tonic-gate w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10; 9160Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 74, w10); 9170Sstevel@tonic-gate w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11; 9180Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 75, w11); 9190Sstevel@tonic-gate w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12; 9200Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 76, w12); 9210Sstevel@tonic-gate w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13; 9220Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 77, w13); 9230Sstevel@tonic-gate w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14; 9240Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 78, w14); 9250Sstevel@tonic-gate w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15; 9260Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 79, w15); 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate ctx->state.s64[0] += a; 9290Sstevel@tonic-gate ctx->state.s64[1] += b; 9300Sstevel@tonic-gate ctx->state.s64[2] += c; 9310Sstevel@tonic-gate ctx->state.s64[3] += d; 9320Sstevel@tonic-gate ctx->state.s64[4] += e; 9330Sstevel@tonic-gate ctx->state.s64[5] += f; 9340Sstevel@tonic-gate ctx->state.s64[6] += g; 9350Sstevel@tonic-gate ctx->state.s64[7] += h; 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate } 9380Sstevel@tonic-gate 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate /* 9410Sstevel@tonic-gate * devpro compiler optimization: 9420Sstevel@tonic-gate * 9430Sstevel@tonic-gate * the compiler can generate better code if it knows that `input' and 9440Sstevel@tonic-gate * `output' do not point to the same source. there is no portable 9450Sstevel@tonic-gate * way to tell the compiler this, but the sun compiler recognizes the 9460Sstevel@tonic-gate * `_Restrict' keyword to indicate this condition. use it if possible. 9470Sstevel@tonic-gate */ 9480Sstevel@tonic-gate 9490Sstevel@tonic-gate #ifdef __RESTRICT 9500Sstevel@tonic-gate #define restrict _Restrict 9510Sstevel@tonic-gate #else 9520Sstevel@tonic-gate #define restrict /* nothing */ 9530Sstevel@tonic-gate #endif 9540Sstevel@tonic-gate 9550Sstevel@tonic-gate /* 9560Sstevel@tonic-gate * Encode() 9570Sstevel@tonic-gate * 9580Sstevel@tonic-gate * purpose: to convert a list of numbers from little endian to big endian 9590Sstevel@tonic-gate * input: uint8_t * : place to store the converted big endian numbers 9600Sstevel@tonic-gate * uint32_t * : place to get numbers to convert from 9610Sstevel@tonic-gate * size_t : the length of the input in bytes 9620Sstevel@tonic-gate * output: void 9630Sstevel@tonic-gate */ 9640Sstevel@tonic-gate 9650Sstevel@tonic-gate static void 9660Sstevel@tonic-gate Encode(uint8_t *restrict output, uint32_t *restrict input, size_t len) 9670Sstevel@tonic-gate { 9680Sstevel@tonic-gate size_t i, j; 9690Sstevel@tonic-gate 9700Sstevel@tonic-gate #if defined(__sparc) 9710Sstevel@tonic-gate if (IS_P2ALIGNED(output, sizeof (uint32_t))) { 9720Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4) { 9730Sstevel@tonic-gate /* LINTED: pointer alignment */ 9740Sstevel@tonic-gate *((uint32_t *)(output + j)) = input[i]; 9750Sstevel@tonic-gate } 9760Sstevel@tonic-gate } else { 9770Sstevel@tonic-gate #endif /* little endian -- will work on big endian, but slowly */ 9780Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4) { 9790Sstevel@tonic-gate output[j] = (input[i] >> 24) & 0xff; 9800Sstevel@tonic-gate output[j + 1] = (input[i] >> 16) & 0xff; 9810Sstevel@tonic-gate output[j + 2] = (input[i] >> 8) & 0xff; 9820Sstevel@tonic-gate output[j + 3] = input[i] & 0xff; 9830Sstevel@tonic-gate } 9840Sstevel@tonic-gate #if defined(__sparc) 9850Sstevel@tonic-gate } 9860Sstevel@tonic-gate #endif 9870Sstevel@tonic-gate } 9880Sstevel@tonic-gate 9890Sstevel@tonic-gate static void 9900Sstevel@tonic-gate Encode64(uint8_t *restrict output, uint64_t *restrict input, size_t len) 9910Sstevel@tonic-gate { 9920Sstevel@tonic-gate size_t i, j; 9930Sstevel@tonic-gate 9940Sstevel@tonic-gate #if defined(__sparc) 9950Sstevel@tonic-gate if (IS_P2ALIGNED(output, sizeof (uint64_t))) { 9960Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 8) { 9970Sstevel@tonic-gate /* LINTED: pointer alignment */ 9980Sstevel@tonic-gate *((uint64_t *)(output + j)) = input[i]; 9990Sstevel@tonic-gate } 10000Sstevel@tonic-gate } else { 10010Sstevel@tonic-gate #endif /* little endian -- will work on big endian, but slowly */ 10020Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 8) { 10030Sstevel@tonic-gate 10040Sstevel@tonic-gate output[j] = (input[i] >> 56) & 0xff; 10050Sstevel@tonic-gate output[j + 1] = (input[i] >> 48) & 0xff; 10060Sstevel@tonic-gate output[j + 2] = (input[i] >> 40) & 0xff; 10070Sstevel@tonic-gate output[j + 3] = (input[i] >> 32) & 0xff; 10080Sstevel@tonic-gate output[j + 4] = (input[i] >> 24) & 0xff; 10090Sstevel@tonic-gate output[j + 5] = (input[i] >> 16) & 0xff; 10100Sstevel@tonic-gate output[j + 6] = (input[i] >> 8) & 0xff; 10110Sstevel@tonic-gate output[j + 7] = input[i] & 0xff; 10120Sstevel@tonic-gate } 10130Sstevel@tonic-gate #if defined(__sparc) 10140Sstevel@tonic-gate } 10150Sstevel@tonic-gate #endif 10160Sstevel@tonic-gate } 10170Sstevel@tonic-gate 10180Sstevel@tonic-gate 10190Sstevel@tonic-gate #ifdef _KERNEL 10200Sstevel@tonic-gate 10210Sstevel@tonic-gate /* 10220Sstevel@tonic-gate * KCF software provider control entry points. 10230Sstevel@tonic-gate */ 10240Sstevel@tonic-gate /* ARGSUSED */ 10250Sstevel@tonic-gate static void 10260Sstevel@tonic-gate sha2_provider_status(crypto_provider_handle_t provider, uint_t *status) 10270Sstevel@tonic-gate { 10280Sstevel@tonic-gate *status = CRYPTO_PROVIDER_READY; 10290Sstevel@tonic-gate } 10300Sstevel@tonic-gate 10310Sstevel@tonic-gate /* 10320Sstevel@tonic-gate * KCF software provider digest entry points. 10330Sstevel@tonic-gate */ 10340Sstevel@tonic-gate 10350Sstevel@tonic-gate static int 10360Sstevel@tonic-gate sha2_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 10370Sstevel@tonic-gate crypto_req_handle_t req) 10380Sstevel@tonic-gate { 10390Sstevel@tonic-gate 10400Sstevel@tonic-gate /* 10410Sstevel@tonic-gate * Allocate and initialize SHA2 context. 10420Sstevel@tonic-gate */ 10430Sstevel@tonic-gate ctx->cc_provider_private = kmem_alloc(sizeof (sha2_ctx_t), 10440Sstevel@tonic-gate crypto_kmflag(req)); 10450Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 10460Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 10470Sstevel@tonic-gate 10480Sstevel@tonic-gate PROV_SHA2_CTX(ctx)->sc_mech_type = mechanism->cm_type; 10490Sstevel@tonic-gate SHA2Init(mechanism->cm_type, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx); 10500Sstevel@tonic-gate 10510Sstevel@tonic-gate return (CRYPTO_SUCCESS); 10520Sstevel@tonic-gate } 10530Sstevel@tonic-gate 10540Sstevel@tonic-gate /* 10550Sstevel@tonic-gate * Helper SHA2 digest update function for uio data. 10560Sstevel@tonic-gate */ 10570Sstevel@tonic-gate static int 10580Sstevel@tonic-gate sha2_digest_update_uio(SHA2_CTX *sha2_ctx, crypto_data_t *data) 10590Sstevel@tonic-gate { 10600Sstevel@tonic-gate off_t offset = data->cd_offset; 10610Sstevel@tonic-gate size_t length = data->cd_length; 10620Sstevel@tonic-gate uint_t vec_idx; 10630Sstevel@tonic-gate size_t cur_len; 10640Sstevel@tonic-gate 10650Sstevel@tonic-gate /* we support only kernel buffer */ 10660Sstevel@tonic-gate if (data->cd_uio->uio_segflg != UIO_SYSSPACE) 10670Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 10680Sstevel@tonic-gate 10690Sstevel@tonic-gate /* 10700Sstevel@tonic-gate * Jump to the first iovec containing data to be 10710Sstevel@tonic-gate * digested. 10720Sstevel@tonic-gate */ 10730Sstevel@tonic-gate for (vec_idx = 0; vec_idx < data->cd_uio->uio_iovcnt && 10740Sstevel@tonic-gate offset >= data->cd_uio->uio_iov[vec_idx].iov_len; 10750Sstevel@tonic-gate offset -= data->cd_uio->uio_iov[vec_idx++].iov_len); 10760Sstevel@tonic-gate if (vec_idx == data->cd_uio->uio_iovcnt) { 10770Sstevel@tonic-gate /* 10780Sstevel@tonic-gate * The caller specified an offset that is larger than the 10790Sstevel@tonic-gate * total size of the buffers it provided. 10800Sstevel@tonic-gate */ 10810Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 10820Sstevel@tonic-gate } 10830Sstevel@tonic-gate 10840Sstevel@tonic-gate /* 10850Sstevel@tonic-gate * Now do the digesting on the iovecs. 10860Sstevel@tonic-gate */ 10870Sstevel@tonic-gate while (vec_idx < data->cd_uio->uio_iovcnt && length > 0) { 10880Sstevel@tonic-gate cur_len = MIN(data->cd_uio->uio_iov[vec_idx].iov_len - 10890Sstevel@tonic-gate offset, length); 10900Sstevel@tonic-gate 10910Sstevel@tonic-gate SHA2Update(sha2_ctx, (uint8_t *)data->cd_uio-> 10920Sstevel@tonic-gate uio_iov[vec_idx].iov_base + offset, cur_len); 10930Sstevel@tonic-gate length -= cur_len; 10940Sstevel@tonic-gate vec_idx++; 10950Sstevel@tonic-gate offset = 0; 10960Sstevel@tonic-gate } 10970Sstevel@tonic-gate 10980Sstevel@tonic-gate if (vec_idx == data->cd_uio->uio_iovcnt && length > 0) { 10990Sstevel@tonic-gate /* 11000Sstevel@tonic-gate * The end of the specified iovec's was reached but 11010Sstevel@tonic-gate * the length requested could not be processed, i.e. 11020Sstevel@tonic-gate * The caller requested to digest more data than it provided. 11030Sstevel@tonic-gate */ 11040Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 11050Sstevel@tonic-gate } 11060Sstevel@tonic-gate 11070Sstevel@tonic-gate return (CRYPTO_SUCCESS); 11080Sstevel@tonic-gate } 11090Sstevel@tonic-gate 11100Sstevel@tonic-gate /* 11110Sstevel@tonic-gate * Helper SHA2 digest final function for uio data. 11120Sstevel@tonic-gate * digest_len is the length of the desired digest. If digest_len 11130Sstevel@tonic-gate * is smaller than the default SHA2 digest length, the caller 11140Sstevel@tonic-gate * must pass a scratch buffer, digest_scratch, which must 11150Sstevel@tonic-gate * be at least the algorithm's digest length bytes. 11160Sstevel@tonic-gate */ 11170Sstevel@tonic-gate static int 11180Sstevel@tonic-gate sha2_digest_final_uio(SHA2_CTX *sha2_ctx, crypto_data_t *digest, 11190Sstevel@tonic-gate ulong_t digest_len, uchar_t *digest_scratch) 11200Sstevel@tonic-gate { 11210Sstevel@tonic-gate off_t offset = digest->cd_offset; 11220Sstevel@tonic-gate uint_t vec_idx; 11230Sstevel@tonic-gate 11240Sstevel@tonic-gate /* we support only kernel buffer */ 11250Sstevel@tonic-gate if (digest->cd_uio->uio_segflg != UIO_SYSSPACE) 11260Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 11270Sstevel@tonic-gate 11280Sstevel@tonic-gate /* 11290Sstevel@tonic-gate * Jump to the first iovec containing ptr to the digest to 11300Sstevel@tonic-gate * be returned. 11310Sstevel@tonic-gate */ 11320Sstevel@tonic-gate for (vec_idx = 0; offset >= digest->cd_uio->uio_iov[vec_idx].iov_len && 11330Sstevel@tonic-gate vec_idx < digest->cd_uio->uio_iovcnt; 11340Sstevel@tonic-gate offset -= digest->cd_uio->uio_iov[vec_idx++].iov_len); 11350Sstevel@tonic-gate if (vec_idx == digest->cd_uio->uio_iovcnt) { 11360Sstevel@tonic-gate /* 11370Sstevel@tonic-gate * The caller specified an offset that is 11380Sstevel@tonic-gate * larger than the total size of the buffers 11390Sstevel@tonic-gate * it provided. 11400Sstevel@tonic-gate */ 11410Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 11420Sstevel@tonic-gate } 11430Sstevel@tonic-gate 11440Sstevel@tonic-gate if (offset + digest_len <= 11450Sstevel@tonic-gate digest->cd_uio->uio_iov[vec_idx].iov_len) { 11460Sstevel@tonic-gate /* 11470Sstevel@tonic-gate * The computed SHA2 digest will fit in the current 11480Sstevel@tonic-gate * iovec. 11490Sstevel@tonic-gate */ 11500Sstevel@tonic-gate if (((sha2_ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) && 11510Sstevel@tonic-gate (digest_len != SHA256_DIGEST_LENGTH)) || 11520Sstevel@tonic-gate ((sha2_ctx->algotype > SHA256_HMAC_GEN_MECH_INFO_TYPE) && 11530Sstevel@tonic-gate (digest_len != SHA512_DIGEST_LENGTH))) { 11540Sstevel@tonic-gate /* 11550Sstevel@tonic-gate * The caller requested a short digest. Digest 11560Sstevel@tonic-gate * into a scratch buffer and return to 11570Sstevel@tonic-gate * the user only what was requested. 11580Sstevel@tonic-gate */ 11590Sstevel@tonic-gate SHA2Final(digest_scratch, sha2_ctx); 11600Sstevel@tonic-gate 11610Sstevel@tonic-gate bcopy(digest_scratch, (uchar_t *)digest-> 11620Sstevel@tonic-gate cd_uio->uio_iov[vec_idx].iov_base + offset, 11630Sstevel@tonic-gate digest_len); 11640Sstevel@tonic-gate } else { 11650Sstevel@tonic-gate SHA2Final((uchar_t *)digest-> 11660Sstevel@tonic-gate cd_uio->uio_iov[vec_idx].iov_base + offset, 11670Sstevel@tonic-gate sha2_ctx); 11680Sstevel@tonic-gate 11690Sstevel@tonic-gate } 11700Sstevel@tonic-gate } else { 11710Sstevel@tonic-gate /* 11720Sstevel@tonic-gate * The computed digest will be crossing one or more iovec's. 11730Sstevel@tonic-gate * This is bad performance-wise but we need to support it. 11740Sstevel@tonic-gate * Allocate a small scratch buffer on the stack and 11750Sstevel@tonic-gate * copy it piece meal to the specified digest iovec's. 11760Sstevel@tonic-gate */ 11770Sstevel@tonic-gate uchar_t digest_tmp[SHA512_DIGEST_LENGTH]; 11780Sstevel@tonic-gate off_t scratch_offset = 0; 11790Sstevel@tonic-gate size_t length = digest_len; 11800Sstevel@tonic-gate size_t cur_len; 11810Sstevel@tonic-gate 11820Sstevel@tonic-gate SHA2Final(digest_tmp, sha2_ctx); 11830Sstevel@tonic-gate 11840Sstevel@tonic-gate while (vec_idx < digest->cd_uio->uio_iovcnt && length > 0) { 11850Sstevel@tonic-gate cur_len = 11860Sstevel@tonic-gate MIN(digest->cd_uio->uio_iov[vec_idx].iov_len - 11870Sstevel@tonic-gate offset, length); 11880Sstevel@tonic-gate bcopy(digest_tmp + scratch_offset, 11890Sstevel@tonic-gate digest->cd_uio->uio_iov[vec_idx].iov_base + offset, 11900Sstevel@tonic-gate cur_len); 11910Sstevel@tonic-gate 11920Sstevel@tonic-gate length -= cur_len; 11930Sstevel@tonic-gate vec_idx++; 11940Sstevel@tonic-gate scratch_offset += cur_len; 11950Sstevel@tonic-gate offset = 0; 11960Sstevel@tonic-gate } 11970Sstevel@tonic-gate 11980Sstevel@tonic-gate if (vec_idx == digest->cd_uio->uio_iovcnt && length > 0) { 11990Sstevel@tonic-gate /* 12000Sstevel@tonic-gate * The end of the specified iovec's was reached but 12010Sstevel@tonic-gate * the length requested could not be processed, i.e. 12020Sstevel@tonic-gate * The caller requested to digest more data than it 12030Sstevel@tonic-gate * provided. 12040Sstevel@tonic-gate */ 12050Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 12060Sstevel@tonic-gate } 12070Sstevel@tonic-gate } 12080Sstevel@tonic-gate 12090Sstevel@tonic-gate return (CRYPTO_SUCCESS); 12100Sstevel@tonic-gate } 12110Sstevel@tonic-gate 12120Sstevel@tonic-gate /* 12130Sstevel@tonic-gate * Helper SHA2 digest update for mblk's. 12140Sstevel@tonic-gate */ 12150Sstevel@tonic-gate static int 12160Sstevel@tonic-gate sha2_digest_update_mblk(SHA2_CTX *sha2_ctx, crypto_data_t *data) 12170Sstevel@tonic-gate { 12180Sstevel@tonic-gate off_t offset = data->cd_offset; 12190Sstevel@tonic-gate size_t length = data->cd_length; 12200Sstevel@tonic-gate mblk_t *mp; 12210Sstevel@tonic-gate size_t cur_len; 12220Sstevel@tonic-gate 12230Sstevel@tonic-gate /* 12240Sstevel@tonic-gate * Jump to the first mblk_t containing data to be digested. 12250Sstevel@tonic-gate */ 12260Sstevel@tonic-gate for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp); 12270Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 12280Sstevel@tonic-gate if (mp == NULL) { 12290Sstevel@tonic-gate /* 12300Sstevel@tonic-gate * The caller specified an offset that is larger than the 12310Sstevel@tonic-gate * total size of the buffers it provided. 12320Sstevel@tonic-gate */ 12330Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 12340Sstevel@tonic-gate } 12350Sstevel@tonic-gate 12360Sstevel@tonic-gate /* 12370Sstevel@tonic-gate * Now do the digesting on the mblk chain. 12380Sstevel@tonic-gate */ 12390Sstevel@tonic-gate while (mp != NULL && length > 0) { 12400Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 12410Sstevel@tonic-gate SHA2Update(sha2_ctx, mp->b_rptr + offset, cur_len); 12420Sstevel@tonic-gate length -= cur_len; 12430Sstevel@tonic-gate offset = 0; 12440Sstevel@tonic-gate mp = mp->b_cont; 12450Sstevel@tonic-gate } 12460Sstevel@tonic-gate 12470Sstevel@tonic-gate if (mp == NULL && length > 0) { 12480Sstevel@tonic-gate /* 12490Sstevel@tonic-gate * The end of the mblk was reached but the length requested 12500Sstevel@tonic-gate * could not be processed, i.e. The caller requested 12510Sstevel@tonic-gate * to digest more data than it provided. 12520Sstevel@tonic-gate */ 12530Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 12540Sstevel@tonic-gate } 12550Sstevel@tonic-gate 12560Sstevel@tonic-gate return (CRYPTO_SUCCESS); 12570Sstevel@tonic-gate } 12580Sstevel@tonic-gate 12590Sstevel@tonic-gate /* 12600Sstevel@tonic-gate * Helper SHA2 digest final for mblk's. 12610Sstevel@tonic-gate * digest_len is the length of the desired digest. If digest_len 12620Sstevel@tonic-gate * is smaller than the default SHA2 digest length, the caller 12630Sstevel@tonic-gate * must pass a scratch buffer, digest_scratch, which must 12640Sstevel@tonic-gate * be at least the algorithm's digest length bytes. 12650Sstevel@tonic-gate */ 12660Sstevel@tonic-gate static int 12670Sstevel@tonic-gate sha2_digest_final_mblk(SHA2_CTX *sha2_ctx, crypto_data_t *digest, 12680Sstevel@tonic-gate ulong_t digest_len, uchar_t *digest_scratch) 12690Sstevel@tonic-gate { 12700Sstevel@tonic-gate off_t offset = digest->cd_offset; 12710Sstevel@tonic-gate mblk_t *mp; 12720Sstevel@tonic-gate 12730Sstevel@tonic-gate /* 12740Sstevel@tonic-gate * Jump to the first mblk_t that will be used to store the digest. 12750Sstevel@tonic-gate */ 12760Sstevel@tonic-gate for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp); 12770Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 12780Sstevel@tonic-gate if (mp == NULL) { 12790Sstevel@tonic-gate /* 12800Sstevel@tonic-gate * The caller specified an offset that is larger than the 12810Sstevel@tonic-gate * total size of the buffers it provided. 12820Sstevel@tonic-gate */ 12830Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 12840Sstevel@tonic-gate } 12850Sstevel@tonic-gate 12860Sstevel@tonic-gate if (offset + digest_len <= MBLKL(mp)) { 12870Sstevel@tonic-gate /* 12880Sstevel@tonic-gate * The computed SHA2 digest will fit in the current mblk. 12890Sstevel@tonic-gate * Do the SHA2Final() in-place. 12900Sstevel@tonic-gate */ 12910Sstevel@tonic-gate if (((sha2_ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) && 12920Sstevel@tonic-gate (digest_len != SHA256_DIGEST_LENGTH)) || 12930Sstevel@tonic-gate ((sha2_ctx->algotype > SHA256_HMAC_GEN_MECH_INFO_TYPE) && 12940Sstevel@tonic-gate (digest_len != SHA512_DIGEST_LENGTH))) { 12950Sstevel@tonic-gate /* 12960Sstevel@tonic-gate * The caller requested a short digest. Digest 12970Sstevel@tonic-gate * into a scratch buffer and return to 12980Sstevel@tonic-gate * the user only what was requested. 12990Sstevel@tonic-gate */ 13000Sstevel@tonic-gate SHA2Final(digest_scratch, sha2_ctx); 13010Sstevel@tonic-gate bcopy(digest_scratch, mp->b_rptr + offset, digest_len); 13020Sstevel@tonic-gate } else { 13030Sstevel@tonic-gate SHA2Final(mp->b_rptr + offset, sha2_ctx); 13040Sstevel@tonic-gate } 13050Sstevel@tonic-gate } else { 13060Sstevel@tonic-gate /* 13070Sstevel@tonic-gate * The computed digest will be crossing one or more mblk's. 13080Sstevel@tonic-gate * This is bad performance-wise but we need to support it. 13090Sstevel@tonic-gate * Allocate a small scratch buffer on the stack and 13100Sstevel@tonic-gate * copy it piece meal to the specified digest iovec's. 13110Sstevel@tonic-gate */ 13120Sstevel@tonic-gate uchar_t digest_tmp[SHA512_DIGEST_LENGTH]; 13130Sstevel@tonic-gate off_t scratch_offset = 0; 13140Sstevel@tonic-gate size_t length = digest_len; 13150Sstevel@tonic-gate size_t cur_len; 13160Sstevel@tonic-gate 13170Sstevel@tonic-gate SHA2Final(digest_tmp, sha2_ctx); 13180Sstevel@tonic-gate 13190Sstevel@tonic-gate while (mp != NULL && length > 0) { 13200Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 13210Sstevel@tonic-gate bcopy(digest_tmp + scratch_offset, 13220Sstevel@tonic-gate mp->b_rptr + offset, cur_len); 13230Sstevel@tonic-gate 13240Sstevel@tonic-gate length -= cur_len; 13250Sstevel@tonic-gate mp = mp->b_cont; 13260Sstevel@tonic-gate scratch_offset += cur_len; 13270Sstevel@tonic-gate offset = 0; 13280Sstevel@tonic-gate } 13290Sstevel@tonic-gate 13300Sstevel@tonic-gate if (mp == NULL && length > 0) { 13310Sstevel@tonic-gate /* 13320Sstevel@tonic-gate * The end of the specified mblk was reached but 13330Sstevel@tonic-gate * the length requested could not be processed, i.e. 13340Sstevel@tonic-gate * The caller requested to digest more data than it 13350Sstevel@tonic-gate * provided. 13360Sstevel@tonic-gate */ 13370Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 13380Sstevel@tonic-gate } 13390Sstevel@tonic-gate } 13400Sstevel@tonic-gate 13410Sstevel@tonic-gate return (CRYPTO_SUCCESS); 13420Sstevel@tonic-gate } 13430Sstevel@tonic-gate 13440Sstevel@tonic-gate /* ARGSUSED */ 13450Sstevel@tonic-gate static int 13460Sstevel@tonic-gate sha2_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest, 13470Sstevel@tonic-gate crypto_req_handle_t req) 13480Sstevel@tonic-gate { 13490Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 13500Sstevel@tonic-gate uint_t sha_digest_len; 13510Sstevel@tonic-gate 13520Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 13530Sstevel@tonic-gate 13540Sstevel@tonic-gate switch (PROV_SHA2_CTX(ctx)->sc_mech_type) { 13550Sstevel@tonic-gate case SHA256_MECH_INFO_TYPE: 13560Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 13570Sstevel@tonic-gate break; 13580Sstevel@tonic-gate case SHA384_MECH_INFO_TYPE: 13590Sstevel@tonic-gate sha_digest_len = SHA384_DIGEST_LENGTH; 13600Sstevel@tonic-gate break; 13610Sstevel@tonic-gate case SHA512_MECH_INFO_TYPE: 13620Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 13630Sstevel@tonic-gate break; 13640Sstevel@tonic-gate default: 13650Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 13660Sstevel@tonic-gate } 13670Sstevel@tonic-gate 13680Sstevel@tonic-gate /* 13690Sstevel@tonic-gate * We need to just return the length needed to store the output. 13700Sstevel@tonic-gate * We should not destroy the context for the following cases. 13710Sstevel@tonic-gate */ 13720Sstevel@tonic-gate if ((digest->cd_length == 0) || 13730Sstevel@tonic-gate (digest->cd_length < sha_digest_len)) { 13740Sstevel@tonic-gate digest->cd_length = sha_digest_len; 13750Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 13760Sstevel@tonic-gate } 13770Sstevel@tonic-gate 13780Sstevel@tonic-gate /* 13790Sstevel@tonic-gate * Do the SHA2 update on the specified input data. 13800Sstevel@tonic-gate */ 13810Sstevel@tonic-gate switch (data->cd_format) { 13820Sstevel@tonic-gate case CRYPTO_DATA_RAW: 13830Sstevel@tonic-gate SHA2Update(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 13840Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 13850Sstevel@tonic-gate data->cd_length); 13860Sstevel@tonic-gate break; 13870Sstevel@tonic-gate case CRYPTO_DATA_UIO: 13880Sstevel@tonic-gate ret = sha2_digest_update_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 13890Sstevel@tonic-gate data); 13900Sstevel@tonic-gate break; 13910Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 13920Sstevel@tonic-gate ret = sha2_digest_update_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 13930Sstevel@tonic-gate data); 13940Sstevel@tonic-gate break; 13950Sstevel@tonic-gate default: 13960Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 13970Sstevel@tonic-gate } 13980Sstevel@tonic-gate 13990Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 14000Sstevel@tonic-gate /* the update failed, free context and bail */ 14010Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t)); 14020Sstevel@tonic-gate ctx->cc_provider_private = NULL; 14030Sstevel@tonic-gate digest->cd_length = 0; 14040Sstevel@tonic-gate return (ret); 14050Sstevel@tonic-gate } 14060Sstevel@tonic-gate 14070Sstevel@tonic-gate /* 14080Sstevel@tonic-gate * Do a SHA2 final, must be done separately since the digest 14090Sstevel@tonic-gate * type can be different than the input data type. 14100Sstevel@tonic-gate */ 14110Sstevel@tonic-gate switch (digest->cd_format) { 14120Sstevel@tonic-gate case CRYPTO_DATA_RAW: 14130Sstevel@tonic-gate SHA2Final((unsigned char *)digest->cd_raw.iov_base + 14140Sstevel@tonic-gate digest->cd_offset, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx); 14150Sstevel@tonic-gate break; 14160Sstevel@tonic-gate case CRYPTO_DATA_UIO: 14170Sstevel@tonic-gate ret = sha2_digest_final_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 14180Sstevel@tonic-gate digest, sha_digest_len, NULL); 14190Sstevel@tonic-gate break; 14200Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 14210Sstevel@tonic-gate ret = sha2_digest_final_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 14220Sstevel@tonic-gate digest, sha_digest_len, NULL); 14230Sstevel@tonic-gate break; 14240Sstevel@tonic-gate default: 14250Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 14260Sstevel@tonic-gate } 14270Sstevel@tonic-gate 14280Sstevel@tonic-gate /* all done, free context and return */ 14290Sstevel@tonic-gate 1430676Sizick if (ret == CRYPTO_SUCCESS) 14310Sstevel@tonic-gate digest->cd_length = sha_digest_len; 1432676Sizick else 14330Sstevel@tonic-gate digest->cd_length = 0; 14340Sstevel@tonic-gate 14350Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t)); 14360Sstevel@tonic-gate ctx->cc_provider_private = NULL; 14370Sstevel@tonic-gate return (ret); 14380Sstevel@tonic-gate } 14390Sstevel@tonic-gate 14400Sstevel@tonic-gate /* ARGSUSED */ 14410Sstevel@tonic-gate static int 14420Sstevel@tonic-gate sha2_digest_update(crypto_ctx_t *ctx, crypto_data_t *data, 14430Sstevel@tonic-gate crypto_req_handle_t req) 14440Sstevel@tonic-gate { 14450Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 14480Sstevel@tonic-gate 14490Sstevel@tonic-gate /* 14500Sstevel@tonic-gate * Do the SHA2 update on the specified input data. 14510Sstevel@tonic-gate */ 14520Sstevel@tonic-gate switch (data->cd_format) { 14530Sstevel@tonic-gate case CRYPTO_DATA_RAW: 14540Sstevel@tonic-gate SHA2Update(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 14550Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 14560Sstevel@tonic-gate data->cd_length); 14570Sstevel@tonic-gate break; 14580Sstevel@tonic-gate case CRYPTO_DATA_UIO: 14590Sstevel@tonic-gate ret = sha2_digest_update_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 14600Sstevel@tonic-gate data); 14610Sstevel@tonic-gate break; 14620Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 14630Sstevel@tonic-gate ret = sha2_digest_update_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 14640Sstevel@tonic-gate data); 14650Sstevel@tonic-gate break; 14660Sstevel@tonic-gate default: 14670Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 14680Sstevel@tonic-gate } 14690Sstevel@tonic-gate 14700Sstevel@tonic-gate return (ret); 14710Sstevel@tonic-gate } 14720Sstevel@tonic-gate 14730Sstevel@tonic-gate /* ARGSUSED */ 14740Sstevel@tonic-gate static int 14750Sstevel@tonic-gate sha2_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest, 14760Sstevel@tonic-gate crypto_req_handle_t req) 14770Sstevel@tonic-gate { 14780Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 14790Sstevel@tonic-gate uint_t sha_digest_len; 14800Sstevel@tonic-gate 14810Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 14820Sstevel@tonic-gate 14830Sstevel@tonic-gate switch (PROV_SHA2_CTX(ctx)->sc_mech_type) { 14840Sstevel@tonic-gate case SHA256_MECH_INFO_TYPE: 14850Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 14860Sstevel@tonic-gate break; 14870Sstevel@tonic-gate case SHA384_MECH_INFO_TYPE: 14880Sstevel@tonic-gate sha_digest_len = SHA384_DIGEST_LENGTH; 14890Sstevel@tonic-gate break; 14900Sstevel@tonic-gate case SHA512_MECH_INFO_TYPE: 14910Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 14920Sstevel@tonic-gate break; 14930Sstevel@tonic-gate default: 14940Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 14950Sstevel@tonic-gate } 14960Sstevel@tonic-gate 14970Sstevel@tonic-gate /* 14980Sstevel@tonic-gate * We need to just return the length needed to store the output. 14990Sstevel@tonic-gate * We should not destroy the context for the following cases. 15000Sstevel@tonic-gate */ 15010Sstevel@tonic-gate if ((digest->cd_length == 0) || 15020Sstevel@tonic-gate (digest->cd_length < sha_digest_len)) { 15030Sstevel@tonic-gate digest->cd_length = sha_digest_len; 15040Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 15050Sstevel@tonic-gate } 15060Sstevel@tonic-gate 15070Sstevel@tonic-gate /* 15080Sstevel@tonic-gate * Do a SHA2 final. 15090Sstevel@tonic-gate */ 15100Sstevel@tonic-gate switch (digest->cd_format) { 15110Sstevel@tonic-gate case CRYPTO_DATA_RAW: 15120Sstevel@tonic-gate SHA2Final((unsigned char *)digest->cd_raw.iov_base + 15130Sstevel@tonic-gate digest->cd_offset, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx); 15140Sstevel@tonic-gate break; 15150Sstevel@tonic-gate case CRYPTO_DATA_UIO: 15160Sstevel@tonic-gate ret = sha2_digest_final_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 15170Sstevel@tonic-gate digest, sha_digest_len, NULL); 15180Sstevel@tonic-gate break; 15190Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 15200Sstevel@tonic-gate ret = sha2_digest_final_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 15210Sstevel@tonic-gate digest, sha_digest_len, NULL); 15220Sstevel@tonic-gate break; 15230Sstevel@tonic-gate default: 15240Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 15250Sstevel@tonic-gate } 15260Sstevel@tonic-gate 15270Sstevel@tonic-gate /* all done, free context and return */ 15280Sstevel@tonic-gate 1529676Sizick if (ret == CRYPTO_SUCCESS) 15300Sstevel@tonic-gate digest->cd_length = sha_digest_len; 1531676Sizick else 15320Sstevel@tonic-gate digest->cd_length = 0; 15330Sstevel@tonic-gate 15340Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t)); 15350Sstevel@tonic-gate ctx->cc_provider_private = NULL; 15360Sstevel@tonic-gate 15370Sstevel@tonic-gate return (ret); 15380Sstevel@tonic-gate } 15390Sstevel@tonic-gate 15400Sstevel@tonic-gate /* ARGSUSED */ 15410Sstevel@tonic-gate static int 15420Sstevel@tonic-gate sha2_digest_atomic(crypto_provider_handle_t provider, 15430Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 15440Sstevel@tonic-gate crypto_data_t *data, crypto_data_t *digest, 15450Sstevel@tonic-gate crypto_req_handle_t req) 15460Sstevel@tonic-gate { 15470Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 15480Sstevel@tonic-gate SHA2_CTX sha2_ctx; 15490Sstevel@tonic-gate uint32_t sha_digest_len; 15500Sstevel@tonic-gate 15510Sstevel@tonic-gate /* 15520Sstevel@tonic-gate * Do the SHA inits. 15530Sstevel@tonic-gate */ 15540Sstevel@tonic-gate 15550Sstevel@tonic-gate SHA2Init(mechanism->cm_type, &sha2_ctx); 15560Sstevel@tonic-gate 15570Sstevel@tonic-gate switch (data->cd_format) { 15580Sstevel@tonic-gate case CRYPTO_DATA_RAW: 15590Sstevel@tonic-gate SHA2Update(&sha2_ctx, (uint8_t *)data-> 15600Sstevel@tonic-gate cd_raw.iov_base + data->cd_offset, data->cd_length); 15610Sstevel@tonic-gate break; 15620Sstevel@tonic-gate case CRYPTO_DATA_UIO: 15630Sstevel@tonic-gate ret = sha2_digest_update_uio(&sha2_ctx, data); 15640Sstevel@tonic-gate break; 15650Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 15660Sstevel@tonic-gate ret = sha2_digest_update_mblk(&sha2_ctx, data); 15670Sstevel@tonic-gate break; 15680Sstevel@tonic-gate default: 15690Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 15700Sstevel@tonic-gate } 15710Sstevel@tonic-gate 15720Sstevel@tonic-gate /* 15730Sstevel@tonic-gate * Do the SHA updates on the specified input data. 15740Sstevel@tonic-gate */ 15750Sstevel@tonic-gate 15760Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 15770Sstevel@tonic-gate /* the update failed, bail */ 15780Sstevel@tonic-gate digest->cd_length = 0; 15790Sstevel@tonic-gate return (ret); 15800Sstevel@tonic-gate } 15810Sstevel@tonic-gate 15820Sstevel@tonic-gate if (mechanism->cm_type <= SHA256_HMAC_GEN_MECH_INFO_TYPE) 15830Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 15840Sstevel@tonic-gate else 15850Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 15860Sstevel@tonic-gate 15870Sstevel@tonic-gate /* 15880Sstevel@tonic-gate * Do a SHA2 final, must be done separately since the digest 15890Sstevel@tonic-gate * type can be different than the input data type. 15900Sstevel@tonic-gate */ 15910Sstevel@tonic-gate switch (digest->cd_format) { 15920Sstevel@tonic-gate case CRYPTO_DATA_RAW: 15930Sstevel@tonic-gate SHA2Final((unsigned char *)digest->cd_raw.iov_base + 15940Sstevel@tonic-gate digest->cd_offset, &sha2_ctx); 15950Sstevel@tonic-gate break; 15960Sstevel@tonic-gate case CRYPTO_DATA_UIO: 15970Sstevel@tonic-gate ret = sha2_digest_final_uio(&sha2_ctx, digest, 15980Sstevel@tonic-gate sha_digest_len, NULL); 15990Sstevel@tonic-gate break; 16000Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 16010Sstevel@tonic-gate ret = sha2_digest_final_mblk(&sha2_ctx, digest, 16020Sstevel@tonic-gate sha_digest_len, NULL); 16030Sstevel@tonic-gate break; 16040Sstevel@tonic-gate default: 16050Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 16060Sstevel@tonic-gate } 16070Sstevel@tonic-gate 1608676Sizick if (ret == CRYPTO_SUCCESS) 16090Sstevel@tonic-gate digest->cd_length = sha_digest_len; 1610676Sizick else 16110Sstevel@tonic-gate digest->cd_length = 0; 16120Sstevel@tonic-gate 16130Sstevel@tonic-gate return (ret); 16140Sstevel@tonic-gate } 16150Sstevel@tonic-gate 16160Sstevel@tonic-gate /* 16170Sstevel@tonic-gate * KCF software provider mac entry points. 16180Sstevel@tonic-gate * 16190Sstevel@tonic-gate * SHA2 HMAC is: SHA2(key XOR opad, SHA2(key XOR ipad, text)) 16200Sstevel@tonic-gate * 16210Sstevel@tonic-gate * Init: 16220Sstevel@tonic-gate * The initialization routine initializes what we denote 16230Sstevel@tonic-gate * as the inner and outer contexts by doing 16240Sstevel@tonic-gate * - for inner context: SHA2(key XOR ipad) 16250Sstevel@tonic-gate * - for outer context: SHA2(key XOR opad) 16260Sstevel@tonic-gate * 16270Sstevel@tonic-gate * Update: 16280Sstevel@tonic-gate * Each subsequent SHA2 HMAC update will result in an 16290Sstevel@tonic-gate * update of the inner context with the specified data. 16300Sstevel@tonic-gate * 16310Sstevel@tonic-gate * Final: 16320Sstevel@tonic-gate * The SHA2 HMAC final will do a SHA2 final operation on the 16330Sstevel@tonic-gate * inner context, and the resulting digest will be used 16340Sstevel@tonic-gate * as the data for an update on the outer context. Last 16350Sstevel@tonic-gate * but not least, a SHA2 final on the outer context will 16360Sstevel@tonic-gate * be performed to obtain the SHA2 HMAC digest to return 16370Sstevel@tonic-gate * to the user. 16380Sstevel@tonic-gate */ 16390Sstevel@tonic-gate 16400Sstevel@tonic-gate /* 16410Sstevel@tonic-gate * Initialize a SHA2-HMAC context. 16420Sstevel@tonic-gate */ 16430Sstevel@tonic-gate static void 16440Sstevel@tonic-gate sha2_mac_init_ctx(sha2_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes) 16450Sstevel@tonic-gate { 16460Sstevel@tonic-gate uint64_t ipad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)]; 16470Sstevel@tonic-gate uint64_t opad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)]; 16480Sstevel@tonic-gate int i, block_size, blocks_per_int64; 16490Sstevel@tonic-gate 16500Sstevel@tonic-gate /* Determine the block size */ 16510Sstevel@tonic-gate if (ctx->hc_mech_type <= SHA256_HMAC_GEN_MECH_INFO_TYPE) { 16520Sstevel@tonic-gate block_size = SHA256_HMAC_BLOCK_SIZE; 16530Sstevel@tonic-gate blocks_per_int64 = SHA256_HMAC_BLOCK_SIZE / sizeof (uint64_t); 16540Sstevel@tonic-gate } else { 16550Sstevel@tonic-gate block_size = SHA512_HMAC_BLOCK_SIZE; 16560Sstevel@tonic-gate blocks_per_int64 = SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t); 16570Sstevel@tonic-gate } 16580Sstevel@tonic-gate 16590Sstevel@tonic-gate (void) bzero(ipad, block_size); 16600Sstevel@tonic-gate (void) bzero(opad, block_size); 16610Sstevel@tonic-gate (void) bcopy(keyval, ipad, length_in_bytes); 16620Sstevel@tonic-gate (void) bcopy(keyval, opad, length_in_bytes); 16630Sstevel@tonic-gate 16640Sstevel@tonic-gate /* XOR key with ipad (0x36) and opad (0x5c) */ 16650Sstevel@tonic-gate for (i = 0; i < blocks_per_int64; i ++) { 16660Sstevel@tonic-gate ipad[i] ^= 0x3636363636363636; 16670Sstevel@tonic-gate opad[i] ^= 0x5c5c5c5c5c5c5c5c; 16680Sstevel@tonic-gate } 16690Sstevel@tonic-gate 16700Sstevel@tonic-gate /* perform SHA2 on ipad */ 16710Sstevel@tonic-gate SHA2Init(ctx->hc_mech_type, &ctx->hc_icontext); 16720Sstevel@tonic-gate SHA2Update(&ctx->hc_icontext, (uint8_t *)ipad, block_size); 16730Sstevel@tonic-gate 16740Sstevel@tonic-gate /* perform SHA2 on opad */ 16750Sstevel@tonic-gate SHA2Init(ctx->hc_mech_type, &ctx->hc_ocontext); 16760Sstevel@tonic-gate SHA2Update(&ctx->hc_ocontext, (uint8_t *)opad, block_size); 16770Sstevel@tonic-gate 16780Sstevel@tonic-gate } 16790Sstevel@tonic-gate 16800Sstevel@tonic-gate /* 16810Sstevel@tonic-gate */ 16820Sstevel@tonic-gate static int 16830Sstevel@tonic-gate sha2_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 16840Sstevel@tonic-gate crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, 16850Sstevel@tonic-gate crypto_req_handle_t req) 16860Sstevel@tonic-gate { 16870Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 16880Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 16890Sstevel@tonic-gate uint_t sha_digest_len, sha_hmac_block_size; 16900Sstevel@tonic-gate 16910Sstevel@tonic-gate /* 16920Sstevel@tonic-gate * Set the digest length and block size to values approriate to the 16930Sstevel@tonic-gate * mechanism 16940Sstevel@tonic-gate */ 16950Sstevel@tonic-gate switch (mechanism->cm_type) { 16960Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 16970Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 16980Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 16990Sstevel@tonic-gate sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE; 17000Sstevel@tonic-gate break; 17010Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 17020Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 17030Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 17040Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 17050Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 17060Sstevel@tonic-gate sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 17070Sstevel@tonic-gate break; 17080Sstevel@tonic-gate default: 17090Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 17100Sstevel@tonic-gate } 17110Sstevel@tonic-gate 17120Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 17130Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 17140Sstevel@tonic-gate 17150Sstevel@tonic-gate ctx->cc_provider_private = kmem_alloc(sizeof (sha2_hmac_ctx_t), 17160Sstevel@tonic-gate crypto_kmflag(req)); 17170Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 17180Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 17190Sstevel@tonic-gate 17200Sstevel@tonic-gate if (ctx_template != NULL) { 17210Sstevel@tonic-gate /* reuse context template */ 17220Sstevel@tonic-gate bcopy(ctx_template, PROV_SHA2_HMAC_CTX(ctx), 17230Sstevel@tonic-gate sizeof (sha2_hmac_ctx_t)); 17240Sstevel@tonic-gate } else { 17250Sstevel@tonic-gate /* no context template, compute context */ 17260Sstevel@tonic-gate if (keylen_in_bytes > sha_hmac_block_size) { 17270Sstevel@tonic-gate uchar_t digested_key[SHA512_DIGEST_LENGTH]; 17280Sstevel@tonic-gate sha2_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private; 17290Sstevel@tonic-gate 17300Sstevel@tonic-gate /* 17310Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 17320Sstevel@tonic-gate * The inner context is used since it hasn't been 17330Sstevel@tonic-gate * initialized yet. 17340Sstevel@tonic-gate */ 17350Sstevel@tonic-gate PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 17360Sstevel@tonic-gate &hmac_ctx->hc_icontext, 17370Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digested_key); 17380Sstevel@tonic-gate sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx), 17390Sstevel@tonic-gate digested_key, sha_digest_len); 17400Sstevel@tonic-gate } else { 17410Sstevel@tonic-gate sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx), 17420Sstevel@tonic-gate key->ck_data, keylen_in_bytes); 17430Sstevel@tonic-gate } 17440Sstevel@tonic-gate } 17450Sstevel@tonic-gate 17460Sstevel@tonic-gate /* 17470Sstevel@tonic-gate * Get the mechanism parameters, if applicable. 17480Sstevel@tonic-gate */ 17490Sstevel@tonic-gate PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type; 17500Sstevel@tonic-gate if (mechanism->cm_type % 3 == 2) { 17510Sstevel@tonic-gate if (mechanism->cm_param == NULL || 17520Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) 17530Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 17540Sstevel@tonic-gate PROV_SHA2_GET_DIGEST_LEN(mechanism, 17550Sstevel@tonic-gate PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len); 17560Sstevel@tonic-gate if (PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len > sha_digest_len) 17570Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 17580Sstevel@tonic-gate } 17590Sstevel@tonic-gate 17600Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 17610Sstevel@tonic-gate bzero(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t)); 17620Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t)); 17630Sstevel@tonic-gate ctx->cc_provider_private = NULL; 17640Sstevel@tonic-gate } 17650Sstevel@tonic-gate 17660Sstevel@tonic-gate return (ret); 17670Sstevel@tonic-gate } 17680Sstevel@tonic-gate 17690Sstevel@tonic-gate /* ARGSUSED */ 17700Sstevel@tonic-gate static int 17710Sstevel@tonic-gate sha2_mac_update(crypto_ctx_t *ctx, crypto_data_t *data, 17720Sstevel@tonic-gate crypto_req_handle_t req) 17730Sstevel@tonic-gate { 17740Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 17750Sstevel@tonic-gate 17760Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 17770Sstevel@tonic-gate 17780Sstevel@tonic-gate /* 17790Sstevel@tonic-gate * Do a SHA2 update of the inner context using the specified 17800Sstevel@tonic-gate * data. 17810Sstevel@tonic-gate */ 17820Sstevel@tonic-gate switch (data->cd_format) { 17830Sstevel@tonic-gate case CRYPTO_DATA_RAW: 17840Sstevel@tonic-gate SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, 17850Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 17860Sstevel@tonic-gate data->cd_length); 17870Sstevel@tonic-gate break; 17880Sstevel@tonic-gate case CRYPTO_DATA_UIO: 17890Sstevel@tonic-gate ret = sha2_digest_update_uio( 17900Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, data); 17910Sstevel@tonic-gate break; 17920Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 17930Sstevel@tonic-gate ret = sha2_digest_update_mblk( 17940Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, data); 17950Sstevel@tonic-gate break; 17960Sstevel@tonic-gate default: 17970Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 17980Sstevel@tonic-gate } 17990Sstevel@tonic-gate 18000Sstevel@tonic-gate return (ret); 18010Sstevel@tonic-gate } 18020Sstevel@tonic-gate 18030Sstevel@tonic-gate /* ARGSUSED */ 18040Sstevel@tonic-gate static int 18050Sstevel@tonic-gate sha2_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req) 18060Sstevel@tonic-gate { 18070Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 18080Sstevel@tonic-gate uchar_t digest[SHA512_DIGEST_LENGTH]; 18090Sstevel@tonic-gate uint32_t digest_len, sha_digest_len; 18100Sstevel@tonic-gate 18110Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 18120Sstevel@tonic-gate 18130Sstevel@tonic-gate /* Set the digest lengths to values approriate to the mechanism */ 18140Sstevel@tonic-gate switch (PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type) { 18150Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 18160Sstevel@tonic-gate sha_digest_len = digest_len = SHA256_DIGEST_LENGTH; 18170Sstevel@tonic-gate break; 18180Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 18190Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 18200Sstevel@tonic-gate sha_digest_len = digest_len = SHA512_DIGEST_LENGTH; 18210Sstevel@tonic-gate break; 18220Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 18230Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 18240Sstevel@tonic-gate digest_len = PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len; 18250Sstevel@tonic-gate break; 18260Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 18270Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 18280Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 18290Sstevel@tonic-gate digest_len = PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len; 18300Sstevel@tonic-gate break; 18310Sstevel@tonic-gate } 18320Sstevel@tonic-gate 18330Sstevel@tonic-gate /* 18340Sstevel@tonic-gate * We need to just return the length needed to store the output. 18350Sstevel@tonic-gate * We should not destroy the context for the following cases. 18360Sstevel@tonic-gate */ 18370Sstevel@tonic-gate if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) { 18380Sstevel@tonic-gate mac->cd_length = digest_len; 18390Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 18400Sstevel@tonic-gate } 18410Sstevel@tonic-gate 18420Sstevel@tonic-gate /* 18430Sstevel@tonic-gate * Do a SHA2 final on the inner context. 18440Sstevel@tonic-gate */ 18450Sstevel@tonic-gate SHA2Final(digest, &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext); 18460Sstevel@tonic-gate 18470Sstevel@tonic-gate /* 18480Sstevel@tonic-gate * Do a SHA2 update on the outer context, feeding the inner 18490Sstevel@tonic-gate * digest as data. 18500Sstevel@tonic-gate */ 18510Sstevel@tonic-gate SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, digest, 18520Sstevel@tonic-gate sha_digest_len); 18530Sstevel@tonic-gate 18540Sstevel@tonic-gate /* 18550Sstevel@tonic-gate * Do a SHA2 final on the outer context, storing the computing 18560Sstevel@tonic-gate * digest in the users buffer. 18570Sstevel@tonic-gate */ 18580Sstevel@tonic-gate switch (mac->cd_format) { 18590Sstevel@tonic-gate case CRYPTO_DATA_RAW: 18600Sstevel@tonic-gate if (digest_len != sha_digest_len) { 18610Sstevel@tonic-gate /* 18620Sstevel@tonic-gate * The caller requested a short digest. Digest 18630Sstevel@tonic-gate * into a scratch buffer and return to 18640Sstevel@tonic-gate * the user only what was requested. 18650Sstevel@tonic-gate */ 18660Sstevel@tonic-gate SHA2Final(digest, 18670Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext); 18680Sstevel@tonic-gate bcopy(digest, (unsigned char *)mac->cd_raw.iov_base + 18690Sstevel@tonic-gate mac->cd_offset, digest_len); 18700Sstevel@tonic-gate } else { 18710Sstevel@tonic-gate SHA2Final((unsigned char *)mac->cd_raw.iov_base + 18720Sstevel@tonic-gate mac->cd_offset, 18730Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext); 18740Sstevel@tonic-gate } 18750Sstevel@tonic-gate break; 18760Sstevel@tonic-gate case CRYPTO_DATA_UIO: 18770Sstevel@tonic-gate ret = sha2_digest_final_uio( 18780Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, mac, 18790Sstevel@tonic-gate digest_len, digest); 18800Sstevel@tonic-gate break; 18810Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 18820Sstevel@tonic-gate ret = sha2_digest_final_mblk( 18830Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, mac, 18840Sstevel@tonic-gate digest_len, digest); 18850Sstevel@tonic-gate break; 18860Sstevel@tonic-gate default: 18870Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 18880Sstevel@tonic-gate } 18890Sstevel@tonic-gate 1890676Sizick if (ret == CRYPTO_SUCCESS) 18910Sstevel@tonic-gate mac->cd_length = digest_len; 1892676Sizick else 18930Sstevel@tonic-gate mac->cd_length = 0; 18940Sstevel@tonic-gate 1895676Sizick bzero(&PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, sizeof (sha2_hmac_ctx_t)); 18960Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t)); 18970Sstevel@tonic-gate ctx->cc_provider_private = NULL; 18980Sstevel@tonic-gate 18990Sstevel@tonic-gate return (ret); 19000Sstevel@tonic-gate } 19010Sstevel@tonic-gate 19020Sstevel@tonic-gate #define SHA2_MAC_UPDATE(data, ctx, ret) { \ 19030Sstevel@tonic-gate switch (data->cd_format) { \ 19040Sstevel@tonic-gate case CRYPTO_DATA_RAW: \ 19050Sstevel@tonic-gate SHA2Update(&(ctx).hc_icontext, \ 19060Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + \ 19070Sstevel@tonic-gate data->cd_offset, data->cd_length); \ 19080Sstevel@tonic-gate break; \ 19090Sstevel@tonic-gate case CRYPTO_DATA_UIO: \ 19100Sstevel@tonic-gate ret = sha2_digest_update_uio(&(ctx).hc_icontext, data); \ 19110Sstevel@tonic-gate break; \ 19120Sstevel@tonic-gate case CRYPTO_DATA_MBLK: \ 19130Sstevel@tonic-gate ret = sha2_digest_update_mblk(&(ctx).hc_icontext, \ 19140Sstevel@tonic-gate data); \ 19150Sstevel@tonic-gate break; \ 19160Sstevel@tonic-gate default: \ 19170Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; \ 19180Sstevel@tonic-gate } \ 19190Sstevel@tonic-gate } 19200Sstevel@tonic-gate 19210Sstevel@tonic-gate /* ARGSUSED */ 19220Sstevel@tonic-gate static int 19230Sstevel@tonic-gate sha2_mac_atomic(crypto_provider_handle_t provider, 19240Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 19250Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 19260Sstevel@tonic-gate crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 19270Sstevel@tonic-gate { 19280Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 19290Sstevel@tonic-gate uchar_t digest[SHA512_DIGEST_LENGTH]; 19300Sstevel@tonic-gate sha2_hmac_ctx_t sha2_hmac_ctx; 19310Sstevel@tonic-gate uint32_t sha_digest_len, digest_len, sha_hmac_block_size; 19320Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 19330Sstevel@tonic-gate 19340Sstevel@tonic-gate /* 19350Sstevel@tonic-gate * Set the digest length and block size to values approriate to the 19360Sstevel@tonic-gate * mechanism 19370Sstevel@tonic-gate */ 19380Sstevel@tonic-gate switch (mechanism->cm_type) { 19390Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 19400Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 19410Sstevel@tonic-gate sha_digest_len = digest_len = SHA256_DIGEST_LENGTH; 19420Sstevel@tonic-gate sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE; 19430Sstevel@tonic-gate break; 19440Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 19450Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 19460Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 19470Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 19480Sstevel@tonic-gate sha_digest_len = digest_len = SHA512_DIGEST_LENGTH; 19490Sstevel@tonic-gate sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 19500Sstevel@tonic-gate break; 19510Sstevel@tonic-gate default: 19520Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 19530Sstevel@tonic-gate } 19540Sstevel@tonic-gate 19550Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 19560Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 19570Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 19580Sstevel@tonic-gate 19590Sstevel@tonic-gate if (ctx_template != NULL) { 19600Sstevel@tonic-gate /* reuse context template */ 19610Sstevel@tonic-gate bcopy(ctx_template, &sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t)); 19620Sstevel@tonic-gate } else { 19630Sstevel@tonic-gate sha2_hmac_ctx.hc_mech_type = mechanism->cm_type; 19640Sstevel@tonic-gate /* no context template, initialize context */ 19650Sstevel@tonic-gate if (keylen_in_bytes > sha_hmac_block_size) { 19660Sstevel@tonic-gate /* 19670Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 19680Sstevel@tonic-gate * The inner context is used since it hasn't been 19690Sstevel@tonic-gate * initialized yet. 19700Sstevel@tonic-gate */ 19710Sstevel@tonic-gate PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 19720Sstevel@tonic-gate &sha2_hmac_ctx.hc_icontext, 19730Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digest); 19740Sstevel@tonic-gate sha2_mac_init_ctx(&sha2_hmac_ctx, digest, 19750Sstevel@tonic-gate sha_digest_len); 19760Sstevel@tonic-gate } else { 19770Sstevel@tonic-gate sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data, 19780Sstevel@tonic-gate keylen_in_bytes); 19790Sstevel@tonic-gate } 19800Sstevel@tonic-gate } 19810Sstevel@tonic-gate 19820Sstevel@tonic-gate /* get the mechanism parameters, if applicable */ 19830Sstevel@tonic-gate if ((mechanism->cm_type % 3) == 2) { 19840Sstevel@tonic-gate if (mechanism->cm_param == NULL || 19850Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) { 19860Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 19870Sstevel@tonic-gate goto bail; 19880Sstevel@tonic-gate } 19890Sstevel@tonic-gate PROV_SHA2_GET_DIGEST_LEN(mechanism, digest_len); 19900Sstevel@tonic-gate if (digest_len > sha_digest_len) { 19910Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 19920Sstevel@tonic-gate goto bail; 19930Sstevel@tonic-gate } 19940Sstevel@tonic-gate } 19950Sstevel@tonic-gate 19960Sstevel@tonic-gate /* do a SHA2 update of the inner context using the specified data */ 19970Sstevel@tonic-gate SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret); 19980Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) 19990Sstevel@tonic-gate /* the update failed, free context and bail */ 20000Sstevel@tonic-gate goto bail; 20010Sstevel@tonic-gate 20020Sstevel@tonic-gate /* 20030Sstevel@tonic-gate * Do a SHA2 final on the inner context. 20040Sstevel@tonic-gate */ 20050Sstevel@tonic-gate SHA2Final(digest, &sha2_hmac_ctx.hc_icontext); 20060Sstevel@tonic-gate 20070Sstevel@tonic-gate /* 20080Sstevel@tonic-gate * Do an SHA2 update on the outer context, feeding the inner 20090Sstevel@tonic-gate * digest as data. 20100Sstevel@tonic-gate * 20110Sstevel@tonic-gate * Make sure that SHA384 is handled special because 20120Sstevel@tonic-gate * it cannot feed a 60-byte inner hash to the outer 20130Sstevel@tonic-gate */ 20140Sstevel@tonic-gate if (mechanism->cm_type == SHA384_HMAC_MECH_INFO_TYPE || 20150Sstevel@tonic-gate mechanism->cm_type == SHA384_HMAC_GEN_MECH_INFO_TYPE) 20160Sstevel@tonic-gate SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, 20170Sstevel@tonic-gate SHA384_DIGEST_LENGTH); 20180Sstevel@tonic-gate else 20190Sstevel@tonic-gate SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len); 20200Sstevel@tonic-gate 20210Sstevel@tonic-gate /* 20220Sstevel@tonic-gate * Do a SHA2 final on the outer context, storing the computed 20230Sstevel@tonic-gate * digest in the users buffer. 20240Sstevel@tonic-gate */ 20250Sstevel@tonic-gate switch (mac->cd_format) { 20260Sstevel@tonic-gate case CRYPTO_DATA_RAW: 20270Sstevel@tonic-gate if (digest_len != sha_digest_len) { 20280Sstevel@tonic-gate /* 20290Sstevel@tonic-gate * The caller requested a short digest. Digest 20300Sstevel@tonic-gate * into a scratch buffer and return to 20310Sstevel@tonic-gate * the user only what was requested. 20320Sstevel@tonic-gate */ 20330Sstevel@tonic-gate SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext); 20340Sstevel@tonic-gate bcopy(digest, (unsigned char *)mac->cd_raw.iov_base + 20350Sstevel@tonic-gate mac->cd_offset, digest_len); 20360Sstevel@tonic-gate } else { 20370Sstevel@tonic-gate SHA2Final((unsigned char *)mac->cd_raw.iov_base + 20380Sstevel@tonic-gate mac->cd_offset, &sha2_hmac_ctx.hc_ocontext); 20390Sstevel@tonic-gate } 20400Sstevel@tonic-gate break; 20410Sstevel@tonic-gate case CRYPTO_DATA_UIO: 20420Sstevel@tonic-gate ret = sha2_digest_final_uio(&sha2_hmac_ctx.hc_ocontext, mac, 20430Sstevel@tonic-gate digest_len, digest); 20440Sstevel@tonic-gate break; 20450Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 20460Sstevel@tonic-gate ret = sha2_digest_final_mblk(&sha2_hmac_ctx.hc_ocontext, mac, 20470Sstevel@tonic-gate digest_len, digest); 20480Sstevel@tonic-gate break; 20490Sstevel@tonic-gate default: 20500Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 20510Sstevel@tonic-gate } 20520Sstevel@tonic-gate 20530Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 20540Sstevel@tonic-gate mac->cd_length = digest_len; 2055676Sizick return (CRYPTO_SUCCESS); 20560Sstevel@tonic-gate } 20570Sstevel@tonic-gate bail: 20580Sstevel@tonic-gate bzero(&sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t)); 20590Sstevel@tonic-gate mac->cd_length = 0; 20600Sstevel@tonic-gate return (ret); 20610Sstevel@tonic-gate } 20620Sstevel@tonic-gate 20630Sstevel@tonic-gate /* ARGSUSED */ 20640Sstevel@tonic-gate static int 20650Sstevel@tonic-gate sha2_mac_verify_atomic(crypto_provider_handle_t provider, 20660Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 20670Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 20680Sstevel@tonic-gate crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 20690Sstevel@tonic-gate { 20700Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 20710Sstevel@tonic-gate uchar_t digest[SHA512_DIGEST_LENGTH]; 20720Sstevel@tonic-gate sha2_hmac_ctx_t sha2_hmac_ctx; 20730Sstevel@tonic-gate uint32_t sha_digest_len, digest_len, sha_hmac_block_size; 20740Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 20750Sstevel@tonic-gate 20760Sstevel@tonic-gate /* 20770Sstevel@tonic-gate * Set the digest length and block size to values approriate to the 20780Sstevel@tonic-gate * mechanism 20790Sstevel@tonic-gate */ 20800Sstevel@tonic-gate switch (mechanism->cm_type) { 20810Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 20820Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 20830Sstevel@tonic-gate sha_digest_len = digest_len = SHA256_DIGEST_LENGTH; 20840Sstevel@tonic-gate sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE; 20850Sstevel@tonic-gate break; 20860Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 20870Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 20880Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 20890Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 20900Sstevel@tonic-gate sha_digest_len = digest_len = SHA512_DIGEST_LENGTH; 20910Sstevel@tonic-gate sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 20920Sstevel@tonic-gate break; 20930Sstevel@tonic-gate default: 20940Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 20950Sstevel@tonic-gate } 20960Sstevel@tonic-gate 20970Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 20980Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 20990Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 21000Sstevel@tonic-gate 21010Sstevel@tonic-gate if (ctx_template != NULL) { 21020Sstevel@tonic-gate /* reuse context template */ 21030Sstevel@tonic-gate bcopy(ctx_template, &sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t)); 21040Sstevel@tonic-gate } else { 21050Sstevel@tonic-gate /* no context template, initialize context */ 21060Sstevel@tonic-gate if (keylen_in_bytes > sha_hmac_block_size) { 21070Sstevel@tonic-gate /* 21080Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 21090Sstevel@tonic-gate * The inner context is used since it hasn't been 21100Sstevel@tonic-gate * initialized yet. 21110Sstevel@tonic-gate */ 21120Sstevel@tonic-gate PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 21130Sstevel@tonic-gate &sha2_hmac_ctx.hc_icontext, 21140Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digest); 21150Sstevel@tonic-gate sha2_mac_init_ctx(&sha2_hmac_ctx, digest, 21160Sstevel@tonic-gate sha_digest_len); 21170Sstevel@tonic-gate } else { 21180Sstevel@tonic-gate sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data, 21190Sstevel@tonic-gate keylen_in_bytes); 21200Sstevel@tonic-gate } 21210Sstevel@tonic-gate } 21220Sstevel@tonic-gate 21230Sstevel@tonic-gate /* get the mechanism parameters, if applicable */ 21240Sstevel@tonic-gate if (mechanism->cm_type % 3 == 2) { 21250Sstevel@tonic-gate if (mechanism->cm_param == NULL || 21260Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) { 21270Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 21280Sstevel@tonic-gate goto bail; 21290Sstevel@tonic-gate } 21300Sstevel@tonic-gate PROV_SHA2_GET_DIGEST_LEN(mechanism, digest_len); 21310Sstevel@tonic-gate if (digest_len > sha_digest_len) { 21320Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 21330Sstevel@tonic-gate goto bail; 21340Sstevel@tonic-gate } 21350Sstevel@tonic-gate } 21360Sstevel@tonic-gate 21370Sstevel@tonic-gate if (mac->cd_length != digest_len) { 21380Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 21390Sstevel@tonic-gate goto bail; 21400Sstevel@tonic-gate } 21410Sstevel@tonic-gate 21420Sstevel@tonic-gate /* do a SHA2 update of the inner context using the specified data */ 21430Sstevel@tonic-gate SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret); 21440Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) 21450Sstevel@tonic-gate /* the update failed, free context and bail */ 21460Sstevel@tonic-gate goto bail; 21470Sstevel@tonic-gate 21480Sstevel@tonic-gate /* do a SHA2 final on the inner context */ 21490Sstevel@tonic-gate SHA2Final(digest, &sha2_hmac_ctx.hc_icontext); 21500Sstevel@tonic-gate 21510Sstevel@tonic-gate /* 21520Sstevel@tonic-gate * Do an SHA2 update on the outer context, feeding the inner 21530Sstevel@tonic-gate * digest as data. 21540Sstevel@tonic-gate */ 21550Sstevel@tonic-gate SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len); 21560Sstevel@tonic-gate 21570Sstevel@tonic-gate /* 21580Sstevel@tonic-gate * Do a SHA2 final on the outer context, storing the computed 21590Sstevel@tonic-gate * digest in the users buffer. 21600Sstevel@tonic-gate */ 21610Sstevel@tonic-gate SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext); 21620Sstevel@tonic-gate 21630Sstevel@tonic-gate /* 21640Sstevel@tonic-gate * Compare the computed digest against the expected digest passed 21650Sstevel@tonic-gate * as argument. 21660Sstevel@tonic-gate */ 21670Sstevel@tonic-gate 21680Sstevel@tonic-gate switch (mac->cd_format) { 21690Sstevel@tonic-gate 21700Sstevel@tonic-gate case CRYPTO_DATA_RAW: 21710Sstevel@tonic-gate if (bcmp(digest, (unsigned char *)mac->cd_raw.iov_base + 21720Sstevel@tonic-gate mac->cd_offset, digest_len) != 0) 21730Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 21740Sstevel@tonic-gate break; 21750Sstevel@tonic-gate 21760Sstevel@tonic-gate case CRYPTO_DATA_UIO: { 21770Sstevel@tonic-gate off_t offset = mac->cd_offset; 21780Sstevel@tonic-gate uint_t vec_idx; 21790Sstevel@tonic-gate off_t scratch_offset = 0; 21800Sstevel@tonic-gate size_t length = digest_len; 21810Sstevel@tonic-gate size_t cur_len; 21820Sstevel@tonic-gate 21830Sstevel@tonic-gate /* we support only kernel buffer */ 21840Sstevel@tonic-gate if (mac->cd_uio->uio_segflg != UIO_SYSSPACE) 21850Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 21860Sstevel@tonic-gate 21870Sstevel@tonic-gate /* jump to the first iovec containing the expected digest */ 21880Sstevel@tonic-gate for (vec_idx = 0; 21890Sstevel@tonic-gate offset >= mac->cd_uio->uio_iov[vec_idx].iov_len && 21900Sstevel@tonic-gate vec_idx < mac->cd_uio->uio_iovcnt; 21910Sstevel@tonic-gate offset -= mac->cd_uio->uio_iov[vec_idx++].iov_len); 21920Sstevel@tonic-gate if (vec_idx == mac->cd_uio->uio_iovcnt) { 21930Sstevel@tonic-gate /* 21940Sstevel@tonic-gate * The caller specified an offset that is 21950Sstevel@tonic-gate * larger than the total size of the buffers 21960Sstevel@tonic-gate * it provided. 21970Sstevel@tonic-gate */ 21980Sstevel@tonic-gate ret = CRYPTO_DATA_LEN_RANGE; 21990Sstevel@tonic-gate break; 22000Sstevel@tonic-gate } 22010Sstevel@tonic-gate 22020Sstevel@tonic-gate /* do the comparison of computed digest vs specified one */ 22030Sstevel@tonic-gate while (vec_idx < mac->cd_uio->uio_iovcnt && length > 0) { 22040Sstevel@tonic-gate cur_len = MIN(mac->cd_uio->uio_iov[vec_idx].iov_len - 22050Sstevel@tonic-gate offset, length); 22060Sstevel@tonic-gate 22070Sstevel@tonic-gate if (bcmp(digest + scratch_offset, 22080Sstevel@tonic-gate mac->cd_uio->uio_iov[vec_idx].iov_base + offset, 22090Sstevel@tonic-gate cur_len) != 0) { 22100Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 22110Sstevel@tonic-gate break; 22120Sstevel@tonic-gate } 22130Sstevel@tonic-gate 22140Sstevel@tonic-gate length -= cur_len; 22150Sstevel@tonic-gate vec_idx++; 22160Sstevel@tonic-gate scratch_offset += cur_len; 22170Sstevel@tonic-gate offset = 0; 22180Sstevel@tonic-gate } 22190Sstevel@tonic-gate break; 22200Sstevel@tonic-gate } 22210Sstevel@tonic-gate 22220Sstevel@tonic-gate case CRYPTO_DATA_MBLK: { 22230Sstevel@tonic-gate off_t offset = mac->cd_offset; 22240Sstevel@tonic-gate mblk_t *mp; 22250Sstevel@tonic-gate off_t scratch_offset = 0; 22260Sstevel@tonic-gate size_t length = digest_len; 22270Sstevel@tonic-gate size_t cur_len; 22280Sstevel@tonic-gate 22290Sstevel@tonic-gate /* jump to the first mblk_t containing the expected digest */ 22300Sstevel@tonic-gate for (mp = mac->cd_mp; mp != NULL && offset >= MBLKL(mp); 22310Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 22320Sstevel@tonic-gate if (mp == NULL) { 22330Sstevel@tonic-gate /* 22340Sstevel@tonic-gate * The caller specified an offset that is larger than 22350Sstevel@tonic-gate * the total size of the buffers it provided. 22360Sstevel@tonic-gate */ 22370Sstevel@tonic-gate ret = CRYPTO_DATA_LEN_RANGE; 22380Sstevel@tonic-gate break; 22390Sstevel@tonic-gate } 22400Sstevel@tonic-gate 22410Sstevel@tonic-gate while (mp != NULL && length > 0) { 22420Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 22430Sstevel@tonic-gate if (bcmp(digest + scratch_offset, 22440Sstevel@tonic-gate mp->b_rptr + offset, cur_len) != 0) { 22450Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 22460Sstevel@tonic-gate break; 22470Sstevel@tonic-gate } 22480Sstevel@tonic-gate 22490Sstevel@tonic-gate length -= cur_len; 22500Sstevel@tonic-gate mp = mp->b_cont; 22510Sstevel@tonic-gate scratch_offset += cur_len; 22520Sstevel@tonic-gate offset = 0; 22530Sstevel@tonic-gate } 22540Sstevel@tonic-gate break; 22550Sstevel@tonic-gate } 22560Sstevel@tonic-gate 22570Sstevel@tonic-gate default: 22580Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 22590Sstevel@tonic-gate } 22600Sstevel@tonic-gate 22610Sstevel@tonic-gate return (ret); 22620Sstevel@tonic-gate bail: 22630Sstevel@tonic-gate bzero(&sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t)); 22640Sstevel@tonic-gate mac->cd_length = 0; 22650Sstevel@tonic-gate return (ret); 22660Sstevel@tonic-gate } 22670Sstevel@tonic-gate 22680Sstevel@tonic-gate /* 22690Sstevel@tonic-gate * KCF software provider context management entry points. 22700Sstevel@tonic-gate */ 22710Sstevel@tonic-gate 22720Sstevel@tonic-gate /* ARGSUSED */ 22730Sstevel@tonic-gate static int 22740Sstevel@tonic-gate sha2_create_ctx_template(crypto_provider_handle_t provider, 22750Sstevel@tonic-gate crypto_mechanism_t *mechanism, crypto_key_t *key, 22760Sstevel@tonic-gate crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size, 22770Sstevel@tonic-gate crypto_req_handle_t req) 22780Sstevel@tonic-gate { 22790Sstevel@tonic-gate sha2_hmac_ctx_t *sha2_hmac_ctx_tmpl; 22800Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 22810Sstevel@tonic-gate uint32_t sha_digest_len, sha_hmac_block_size; 22820Sstevel@tonic-gate 22830Sstevel@tonic-gate /* 22840Sstevel@tonic-gate * Set the digest length and block size to values approriate to the 22850Sstevel@tonic-gate * mechanism 22860Sstevel@tonic-gate */ 22870Sstevel@tonic-gate switch (mechanism->cm_type) { 22880Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 22890Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 22900Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 22910Sstevel@tonic-gate sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE; 22920Sstevel@tonic-gate break; 22930Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 22940Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 22950Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 22960Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 22970Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 22980Sstevel@tonic-gate sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 22990Sstevel@tonic-gate break; 23000Sstevel@tonic-gate default: 23010Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 23020Sstevel@tonic-gate } 23030Sstevel@tonic-gate 23040Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 23050Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 23060Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 23070Sstevel@tonic-gate 23080Sstevel@tonic-gate /* 23090Sstevel@tonic-gate * Allocate and initialize SHA2 context. 23100Sstevel@tonic-gate */ 23110Sstevel@tonic-gate sha2_hmac_ctx_tmpl = kmem_alloc(sizeof (sha2_hmac_ctx_t), 23120Sstevel@tonic-gate crypto_kmflag(req)); 23130Sstevel@tonic-gate if (sha2_hmac_ctx_tmpl == NULL) 23140Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 23150Sstevel@tonic-gate 23160Sstevel@tonic-gate sha2_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type; 23170Sstevel@tonic-gate 23180Sstevel@tonic-gate if (keylen_in_bytes > sha_hmac_block_size) { 23190Sstevel@tonic-gate uchar_t digested_key[SHA512_DIGEST_LENGTH]; 23200Sstevel@tonic-gate 23210Sstevel@tonic-gate /* 23220Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 23230Sstevel@tonic-gate * The inner context is used since it hasn't been 23240Sstevel@tonic-gate * initialized yet. 23250Sstevel@tonic-gate */ 23260Sstevel@tonic-gate PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 23270Sstevel@tonic-gate &sha2_hmac_ctx_tmpl->hc_icontext, 23280Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digested_key); 23290Sstevel@tonic-gate sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, digested_key, 23300Sstevel@tonic-gate sha_digest_len); 23310Sstevel@tonic-gate } else { 23320Sstevel@tonic-gate sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, key->ck_data, 23330Sstevel@tonic-gate keylen_in_bytes); 23340Sstevel@tonic-gate } 23350Sstevel@tonic-gate 23360Sstevel@tonic-gate *ctx_template = (crypto_spi_ctx_template_t)sha2_hmac_ctx_tmpl; 23370Sstevel@tonic-gate *ctx_template_size = sizeof (sha2_hmac_ctx_t); 23380Sstevel@tonic-gate 23390Sstevel@tonic-gate return (CRYPTO_SUCCESS); 23400Sstevel@tonic-gate } 23410Sstevel@tonic-gate 23420Sstevel@tonic-gate static int 23430Sstevel@tonic-gate sha2_free_context(crypto_ctx_t *ctx) 23440Sstevel@tonic-gate { 23450Sstevel@tonic-gate uint_t ctx_len; 23460Sstevel@tonic-gate 23470Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 23480Sstevel@tonic-gate return (CRYPTO_SUCCESS); 23490Sstevel@tonic-gate 23500Sstevel@tonic-gate /* 23510Sstevel@tonic-gate * We have to free either SHA2 or SHA2-HMAC contexts, which 23520Sstevel@tonic-gate * have different lengths. 23530Sstevel@tonic-gate * 23540Sstevel@tonic-gate * Note: Below is dependent on the mechanism ordering. 23550Sstevel@tonic-gate */ 23560Sstevel@tonic-gate 23570Sstevel@tonic-gate if (PROV_SHA2_CTX(ctx)->sc_mech_type % 3 == 0) 23580Sstevel@tonic-gate ctx_len = sizeof (sha2_ctx_t); 23590Sstevel@tonic-gate else 23600Sstevel@tonic-gate ctx_len = sizeof (sha2_hmac_ctx_t); 23610Sstevel@tonic-gate 23620Sstevel@tonic-gate bzero(ctx->cc_provider_private, ctx_len); 23630Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, ctx_len); 23640Sstevel@tonic-gate ctx->cc_provider_private = NULL; 23650Sstevel@tonic-gate 23660Sstevel@tonic-gate return (CRYPTO_SUCCESS); 23670Sstevel@tonic-gate } 23680Sstevel@tonic-gate 23690Sstevel@tonic-gate #endif /* _KERNEL */ 23700Sstevel@tonic-gate 23710Sstevel@tonic-gate void 23720Sstevel@tonic-gate SHA2Init(uint64_t mech, SHA2_CTX *ctx) 23730Sstevel@tonic-gate { 23740Sstevel@tonic-gate 23750Sstevel@tonic-gate switch (mech) { 23760Sstevel@tonic-gate case SHA256_MECH_INFO_TYPE: 23770Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 23780Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 23790Sstevel@tonic-gate ctx->state.s32[0] = 0x6a09e667U; 23800Sstevel@tonic-gate ctx->state.s32[1] = 0xbb67ae85U; 23810Sstevel@tonic-gate ctx->state.s32[2] = 0x3c6ef372U; 23820Sstevel@tonic-gate ctx->state.s32[3] = 0xa54ff53aU; 23830Sstevel@tonic-gate ctx->state.s32[4] = 0x510e527fU; 23840Sstevel@tonic-gate ctx->state.s32[5] = 0x9b05688cU; 23850Sstevel@tonic-gate ctx->state.s32[6] = 0x1f83d9abU; 23860Sstevel@tonic-gate ctx->state.s32[7] = 0x5be0cd19U; 23870Sstevel@tonic-gate break; 23880Sstevel@tonic-gate case SHA384_MECH_INFO_TYPE: 23890Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 23900Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 23910Sstevel@tonic-gate ctx->state.s64[0] = 0xcbbb9d5dc1059ed8ULL; 23920Sstevel@tonic-gate ctx->state.s64[1] = 0x629a292a367cd507ULL; 23930Sstevel@tonic-gate ctx->state.s64[2] = 0x9159015a3070dd17ULL; 23940Sstevel@tonic-gate ctx->state.s64[3] = 0x152fecd8f70e5939ULL; 23950Sstevel@tonic-gate ctx->state.s64[4] = 0x67332667ffc00b31ULL; 23960Sstevel@tonic-gate ctx->state.s64[5] = 0x8eb44a8768581511ULL; 23970Sstevel@tonic-gate ctx->state.s64[6] = 0xdb0c2e0d64f98fa7ULL; 23980Sstevel@tonic-gate ctx->state.s64[7] = 0x47b5481dbefa4fa4ULL; 23990Sstevel@tonic-gate break; 24000Sstevel@tonic-gate case SHA512_MECH_INFO_TYPE: 24010Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 24020Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 24030Sstevel@tonic-gate ctx->state.s64[0] = 0x6a09e667f3bcc908ULL; 24040Sstevel@tonic-gate ctx->state.s64[1] = 0xbb67ae8584caa73bULL; 24050Sstevel@tonic-gate ctx->state.s64[2] = 0x3c6ef372fe94f82bULL; 24060Sstevel@tonic-gate ctx->state.s64[3] = 0xa54ff53a5f1d36f1ULL; 24070Sstevel@tonic-gate ctx->state.s64[4] = 0x510e527fade682d1ULL; 24080Sstevel@tonic-gate ctx->state.s64[5] = 0x9b05688c2b3e6c1fULL; 24090Sstevel@tonic-gate ctx->state.s64[6] = 0x1f83d9abfb41bd6bULL; 24100Sstevel@tonic-gate ctx->state.s64[7] = 0x5be0cd19137e2179ULL; 24110Sstevel@tonic-gate break; 24120Sstevel@tonic-gate #ifdef _KERNEL 24130Sstevel@tonic-gate default: 24140Sstevel@tonic-gate cmn_err(CE_WARN, "sha2_init: " 24150Sstevel@tonic-gate "failed to find a supported algorithm: 0x%x", 24160Sstevel@tonic-gate (uint32_t)mech); 24170Sstevel@tonic-gate 24180Sstevel@tonic-gate #endif /* _KERNEL */ 24190Sstevel@tonic-gate } 24200Sstevel@tonic-gate 24210Sstevel@tonic-gate ctx->algotype = mech; 24220Sstevel@tonic-gate ctx->count.c64[0] = ctx->count.c64[1] = 0; 24230Sstevel@tonic-gate } 24240Sstevel@tonic-gate 24250Sstevel@tonic-gate /* 24260Sstevel@tonic-gate * SHA2Update() 24270Sstevel@tonic-gate * 24280Sstevel@tonic-gate * purpose: continues an sha2 digest operation, using the message block 24290Sstevel@tonic-gate * to update the context. 24300Sstevel@tonic-gate * input: SHA2_CTX * : the context to update 24310Sstevel@tonic-gate * uint8_t * : the message block 24320Sstevel@tonic-gate * uint32_t : the length of the message block in bytes 24330Sstevel@tonic-gate * output: void 24340Sstevel@tonic-gate */ 24350Sstevel@tonic-gate 24360Sstevel@tonic-gate void 24370Sstevel@tonic-gate SHA2Update(SHA2_CTX *ctx, const uint8_t *input, uint32_t input_len) 24380Sstevel@tonic-gate { 24390Sstevel@tonic-gate uint32_t i, buf_index, buf_len, buf_limit; 24400Sstevel@tonic-gate 24410Sstevel@tonic-gate /* check for noop */ 24420Sstevel@tonic-gate if (input_len == 0) 24430Sstevel@tonic-gate return; 24440Sstevel@tonic-gate 24450Sstevel@tonic-gate if (ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) { 24460Sstevel@tonic-gate buf_limit = 64; 24470Sstevel@tonic-gate 24480Sstevel@tonic-gate /* compute number of bytes mod 64 */ 24490Sstevel@tonic-gate buf_index = (ctx->count.c32[1] >> 3) & 0x3F; 24500Sstevel@tonic-gate 24510Sstevel@tonic-gate /* update number of bits */ 24520Sstevel@tonic-gate if ((ctx->count.c32[1] += (input_len << 3)) < (input_len << 3)) 24530Sstevel@tonic-gate ctx->count.c32[0]++; 24540Sstevel@tonic-gate 24550Sstevel@tonic-gate ctx->count.c32[0] += (input_len >> 29); 24560Sstevel@tonic-gate 24570Sstevel@tonic-gate } else { 24580Sstevel@tonic-gate buf_limit = 128; 24590Sstevel@tonic-gate 24600Sstevel@tonic-gate /* compute number of bytes mod 128 */ 24610Sstevel@tonic-gate buf_index = (ctx->count.c64[1] >> 3) & 0x7F; 24620Sstevel@tonic-gate 24630Sstevel@tonic-gate /* update number of bits */ 24640Sstevel@tonic-gate if ((ctx->count.c64[1] += (input_len << 3)) < (input_len << 3)) 24650Sstevel@tonic-gate ctx->count.c64[0]++; 24660Sstevel@tonic-gate 24670Sstevel@tonic-gate ctx->count.c64[0] += (input_len >> 29); 24680Sstevel@tonic-gate } 24690Sstevel@tonic-gate 24700Sstevel@tonic-gate buf_len = buf_limit - buf_index; 24710Sstevel@tonic-gate 24720Sstevel@tonic-gate /* transform as many times as possible */ 24730Sstevel@tonic-gate i = 0; 24740Sstevel@tonic-gate if (input_len >= buf_len) { 24750Sstevel@tonic-gate 24760Sstevel@tonic-gate /* 24770Sstevel@tonic-gate * general optimization: 24780Sstevel@tonic-gate * 24790Sstevel@tonic-gate * only do initial bcopy() and SHA2Transform() if 24800Sstevel@tonic-gate * buf_index != 0. if buf_index == 0, we're just 24810Sstevel@tonic-gate * wasting our time doing the bcopy() since there 24820Sstevel@tonic-gate * wasn't any data left over from a previous call to 24830Sstevel@tonic-gate * SHA2Update(). 24840Sstevel@tonic-gate */ 24850Sstevel@tonic-gate if (buf_index) { 24860Sstevel@tonic-gate bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len); 24870Sstevel@tonic-gate if (ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) 24880Sstevel@tonic-gate SHA256Transform(ctx, ctx->buf_un.buf8); 24890Sstevel@tonic-gate else 24900Sstevel@tonic-gate SHA512Transform(ctx, ctx->buf_un.buf8); 24910Sstevel@tonic-gate 24920Sstevel@tonic-gate i = buf_len; 24930Sstevel@tonic-gate } 24940Sstevel@tonic-gate 24950Sstevel@tonic-gate 24960Sstevel@tonic-gate for (; i + buf_limit - 1 < input_len; i += buf_limit) { 24970Sstevel@tonic-gate if (ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) 24980Sstevel@tonic-gate SHA256Transform(ctx, &input[i]); 24990Sstevel@tonic-gate else 25000Sstevel@tonic-gate SHA512Transform(ctx, &input[i]); 25010Sstevel@tonic-gate } 25020Sstevel@tonic-gate 25030Sstevel@tonic-gate /* 25040Sstevel@tonic-gate * general optimization: 25050Sstevel@tonic-gate * 25060Sstevel@tonic-gate * if i and input_len are the same, return now instead 25070Sstevel@tonic-gate * of calling bcopy(), since the bcopy() in this case 25080Sstevel@tonic-gate * will be an expensive nop. 25090Sstevel@tonic-gate */ 25100Sstevel@tonic-gate 25110Sstevel@tonic-gate if (input_len == i) 25120Sstevel@tonic-gate return; 25130Sstevel@tonic-gate 25140Sstevel@tonic-gate buf_index = 0; 25150Sstevel@tonic-gate } 25160Sstevel@tonic-gate 25170Sstevel@tonic-gate /* buffer remaining input */ 25180Sstevel@tonic-gate bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i); 25190Sstevel@tonic-gate } 25200Sstevel@tonic-gate 25210Sstevel@tonic-gate 25220Sstevel@tonic-gate /* 25230Sstevel@tonic-gate * SHA2Final() 25240Sstevel@tonic-gate * 25250Sstevel@tonic-gate * purpose: ends an sha2 digest operation, finalizing the message digest and 25260Sstevel@tonic-gate * zeroing the context. 25270Sstevel@tonic-gate * input: uint8_t * : a buffer to store the digest in 25280Sstevel@tonic-gate * SHA2_CTX * : the context to finalize, save, and zero 25290Sstevel@tonic-gate * output: void 25300Sstevel@tonic-gate */ 25310Sstevel@tonic-gate 25320Sstevel@tonic-gate 25330Sstevel@tonic-gate void 25340Sstevel@tonic-gate SHA2Final(uint8_t *digest, SHA2_CTX *ctx) 25350Sstevel@tonic-gate { 25360Sstevel@tonic-gate uint8_t bitcount_be[sizeof (ctx->count.c32)]; 25370Sstevel@tonic-gate uint8_t bitcount_be64[sizeof (ctx->count.c64)]; 25380Sstevel@tonic-gate uint32_t index; 25390Sstevel@tonic-gate 25400Sstevel@tonic-gate 25410Sstevel@tonic-gate if (ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) { 25420Sstevel@tonic-gate index = (ctx->count.c32[1] >> 3) & 0x3f; 25430Sstevel@tonic-gate Encode(bitcount_be, ctx->count.c32, sizeof (bitcount_be)); 25440Sstevel@tonic-gate SHA2Update(ctx, PADDING, ((index < 56) ? 56 : 120) - index); 25450Sstevel@tonic-gate SHA2Update(ctx, bitcount_be, sizeof (bitcount_be)); 25460Sstevel@tonic-gate Encode(digest, ctx->state.s32, sizeof (ctx->state.s32)); 25470Sstevel@tonic-gate 25480Sstevel@tonic-gate } else { 25490Sstevel@tonic-gate index = (ctx->count.c64[1] >> 3) & 0x7f; 25500Sstevel@tonic-gate Encode64(bitcount_be64, ctx->count.c64, 25510Sstevel@tonic-gate sizeof (bitcount_be64)); 25520Sstevel@tonic-gate SHA2Update(ctx, PADDING, ((index < 112) ? 112 : 240) - index); 25530Sstevel@tonic-gate SHA2Update(ctx, bitcount_be64, sizeof (bitcount_be64)); 25540Sstevel@tonic-gate if (ctx->algotype <= SHA384_HMAC_GEN_MECH_INFO_TYPE) { 25550Sstevel@tonic-gate ctx->state.s64[6] = ctx->state.s64[7] = 0; 25560Sstevel@tonic-gate Encode64(digest, ctx->state.s64, 25570Sstevel@tonic-gate sizeof (uint64_t) * 6); 25580Sstevel@tonic-gate } else 25590Sstevel@tonic-gate Encode64(digest, ctx->state.s64, 25600Sstevel@tonic-gate sizeof (ctx->state.s64)); 25610Sstevel@tonic-gate } 2562*1551Sdarrenm 2563*1551Sdarrenm /* zeroize sensitive information */ 2564*1551Sdarrenm bzero(ctx, sizeof (*ctx)); 25650Sstevel@tonic-gate } 2566