17c478bd9Sstevel@tonic-gate /* 2*673007c6Sdarrenm * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 77c478bd9Sstevel@tonic-gate 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * The basic framework for this code came from the reference 117c478bd9Sstevel@tonic-gate * implementation for MD5. That implementation is Copyright (C) 127c478bd9Sstevel@tonic-gate * 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * License to copy and use this software is granted provided that it 157c478bd9Sstevel@tonic-gate * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 167c478bd9Sstevel@tonic-gate * Algorithm" in all material mentioning or referencing this software 177c478bd9Sstevel@tonic-gate * or this function. 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * License is also granted to make and use derivative works provided 207c478bd9Sstevel@tonic-gate * that such works are identified as "derived from the RSA Data 217c478bd9Sstevel@tonic-gate * Security, Inc. MD5 Message-Digest Algorithm" in all material 227c478bd9Sstevel@tonic-gate * mentioning or referencing the derived work. 237c478bd9Sstevel@tonic-gate * 247c478bd9Sstevel@tonic-gate * RSA Data Security, Inc. makes no representations concerning either 257c478bd9Sstevel@tonic-gate * the merchantability of this software or the suitability of this 267c478bd9Sstevel@tonic-gate * software for any particular purpose. It is provided "as is" 277c478bd9Sstevel@tonic-gate * without express or implied warranty of any kind. 287c478bd9Sstevel@tonic-gate * 297c478bd9Sstevel@tonic-gate * These notices must be retained in any copies of any part of this 307c478bd9Sstevel@tonic-gate * documentation and/or software. 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * NOTE: Cleaned-up and optimized, version of SHA2, based on the FIPS 180-2 337c478bd9Sstevel@tonic-gate * standard, available at http://www.itl.nist.gov/div897/pubs/fip180-2.htm 347c478bd9Sstevel@tonic-gate * Not as fast as one would like -- further optimizations are encouraged 357c478bd9Sstevel@tonic-gate * and appreciated. 367c478bd9Sstevel@tonic-gate */ 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include <sys/types.h> 397c478bd9Sstevel@tonic-gate #include <sys/param.h> 407c478bd9Sstevel@tonic-gate #include <sys/systm.h> 417c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 427c478bd9Sstevel@tonic-gate #include <sys/sha2.h> 437c478bd9Sstevel@tonic-gate #include <sys/sha2_consts.h> 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #ifdef _KERNEL 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 487c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 497c478bd9Sstevel@tonic-gate #include <sys/crypto/common.h> 507c478bd9Sstevel@tonic-gate #include <sys/crypto/spi.h> 517c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* 547c478bd9Sstevel@tonic-gate * The sha2 module is created with two modlinkages: 557c478bd9Sstevel@tonic-gate * - a modlmisc that allows consumers to directly call the entry points 567c478bd9Sstevel@tonic-gate * SHA2Init, SHA2Update, and SHA2Final. 577c478bd9Sstevel@tonic-gate * - a modlcrypto that allows the module to register with the Kernel 587c478bd9Sstevel@tonic-gate * Cryptographic Framework (KCF) as a software provider for the SHA2 597c478bd9Sstevel@tonic-gate * mechanisms. 607c478bd9Sstevel@tonic-gate */ 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #else 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #include <strings.h> 657c478bd9Sstevel@tonic-gate #include <stdlib.h> 667c478bd9Sstevel@tonic-gate #include <errno.h> 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate #endif /* !_KERNEL */ 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate static void Encode(uint8_t *, uint32_t *, size_t); 717c478bd9Sstevel@tonic-gate static void Encode64(uint8_t *, uint64_t *, size_t); 727c478bd9Sstevel@tonic-gate static void SHA256Transform(SHA2_CTX *, const uint8_t *); 737c478bd9Sstevel@tonic-gate static void SHA512Transform(SHA2_CTX *, const uint8_t *); 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate static uint8_t PADDING[128] = { 0x80, /* all zeros */ }; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* Ch and Maj are the basic SHA2 functions. */ 787c478bd9Sstevel@tonic-gate #define Ch(b, c, d) (((b) & (c)) ^ ((~b) & (d))) 797c478bd9Sstevel@tonic-gate #define Maj(b, c, d) (((b) & (c)) ^ ((b) & (d)) ^ ((c) & (d))) 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate /* Rotates x right n bits. */ 827c478bd9Sstevel@tonic-gate #define ROTR(x, n) \ 837c478bd9Sstevel@tonic-gate (((x) >> (n)) | ((x) << ((sizeof (x) * NBBY)-(n)))) 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate /* Shift x right n bits */ 867c478bd9Sstevel@tonic-gate #define SHR(x, n) ((x) >> (n)) 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* SHA256 Functions */ 897c478bd9Sstevel@tonic-gate #define BIGSIGMA0_256(x) (ROTR((x), 2) ^ ROTR((x), 13) ^ ROTR((x), 22)) 907c478bd9Sstevel@tonic-gate #define BIGSIGMA1_256(x) (ROTR((x), 6) ^ ROTR((x), 11) ^ ROTR((x), 25)) 917c478bd9Sstevel@tonic-gate #define SIGMA0_256(x) (ROTR((x), 7) ^ ROTR((x), 18) ^ SHR((x), 3)) 927c478bd9Sstevel@tonic-gate #define SIGMA1_256(x) (ROTR((x), 17) ^ ROTR((x), 19) ^ SHR((x), 10)) 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate #define SHA256ROUND(a, b, c, d, e, f, g, h, i, w) \ 957c478bd9Sstevel@tonic-gate T1 = h + BIGSIGMA1_256(e) + Ch(e, f, g) + SHA256_CONST(i) + w; \ 967c478bd9Sstevel@tonic-gate d += T1; \ 977c478bd9Sstevel@tonic-gate T2 = BIGSIGMA0_256(a) + Maj(a, b, c); \ 987c478bd9Sstevel@tonic-gate h = T1 + T2 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* SHA384/512 Functions */ 1017c478bd9Sstevel@tonic-gate #define BIGSIGMA0(x) (ROTR((x), 28) ^ ROTR((x), 34) ^ ROTR((x), 39)) 1027c478bd9Sstevel@tonic-gate #define BIGSIGMA1(x) (ROTR((x), 14) ^ ROTR((x), 18) ^ ROTR((x), 41)) 1037c478bd9Sstevel@tonic-gate #define SIGMA0(x) (ROTR((x), 1) ^ ROTR((x), 8) ^ SHR((x), 7)) 1047c478bd9Sstevel@tonic-gate #define SIGMA1(x) (ROTR((x), 19) ^ ROTR((x), 61) ^ SHR((x), 6)) 1057c478bd9Sstevel@tonic-gate #define SHA512ROUND(a, b, c, d, e, f, g, h, i, w) \ 1067c478bd9Sstevel@tonic-gate T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + SHA512_CONST(i) + w; \ 1077c478bd9Sstevel@tonic-gate d += T1; \ 1087c478bd9Sstevel@tonic-gate T2 = BIGSIGMA0(a) + Maj(a, b, c); \ 1097c478bd9Sstevel@tonic-gate h = T1 + T2 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate #ifdef _KERNEL 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 1147c478bd9Sstevel@tonic-gate &mod_miscops, 1157c478bd9Sstevel@tonic-gate "SHA2 Message-Digest Algorithm" 1167c478bd9Sstevel@tonic-gate }; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate static struct modlcrypto modlcrypto = { 1197c478bd9Sstevel@tonic-gate &mod_cryptoops, 1207c478bd9Sstevel@tonic-gate "SHA2 Kernel SW Provider %I%" 1217c478bd9Sstevel@tonic-gate }; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 1247c478bd9Sstevel@tonic-gate MODREV_1, &modlmisc, &modlcrypto, NULL 1257c478bd9Sstevel@tonic-gate }; 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate /* 1287c478bd9Sstevel@tonic-gate * CSPI information (entry points, provider info, etc.) 1297c478bd9Sstevel@tonic-gate */ 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * List of support mechanisms in this module. 1357c478bd9Sstevel@tonic-gate * 1367c478bd9Sstevel@tonic-gate * It is important to note that in the module, division or modulus calculations 1377c478bd9Sstevel@tonic-gate * are used on the enumerated type to determine which mechanism is being used; 1387c478bd9Sstevel@tonic-gate * therefore, changing the order or additional mechanisms should be done 1397c478bd9Sstevel@tonic-gate * carefully 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate typedef enum sha2_mech_type { 1427c478bd9Sstevel@tonic-gate SHA256_MECH_INFO_TYPE, /* SUN_CKM_SHA256 */ 1437c478bd9Sstevel@tonic-gate SHA256_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC */ 1447c478bd9Sstevel@tonic-gate SHA256_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC_GENERAL */ 1457c478bd9Sstevel@tonic-gate SHA384_MECH_INFO_TYPE, /* SUN_CKM_SHA384 */ 1467c478bd9Sstevel@tonic-gate SHA384_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC */ 1477c478bd9Sstevel@tonic-gate SHA384_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC_GENERAL */ 1487c478bd9Sstevel@tonic-gate SHA512_MECH_INFO_TYPE, /* SUN_CKM_SHA512 */ 1497c478bd9Sstevel@tonic-gate SHA512_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC */ 1507c478bd9Sstevel@tonic-gate SHA512_HMAC_GEN_MECH_INFO_TYPE /* SUN_CKM_SHA512_HMAC_GENERAL */ 1517c478bd9Sstevel@tonic-gate } sha2_mech_type_t; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate #ifdef _KERNEL 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * Context for SHA2 mechanism. 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate typedef struct sha2_ctx { 1607c478bd9Sstevel@tonic-gate sha2_mech_type_t sc_mech_type; /* type of context */ 1617c478bd9Sstevel@tonic-gate SHA2_CTX sc_sha2_ctx; /* SHA2 context */ 1627c478bd9Sstevel@tonic-gate } sha2_ctx_t; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * Context for SHA2 HMAC and HMAC GENERAL mechanisms. 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate typedef struct sha2_hmac_ctx { 1687c478bd9Sstevel@tonic-gate sha2_mech_type_t hc_mech_type; /* type of context */ 1697c478bd9Sstevel@tonic-gate uint32_t hc_digest_len; /* digest len in bytes */ 1707c478bd9Sstevel@tonic-gate SHA2_CTX hc_icontext; /* inner SHA2 context */ 1717c478bd9Sstevel@tonic-gate SHA2_CTX hc_ocontext; /* outer SHA2 context */ 1727c478bd9Sstevel@tonic-gate } sha2_hmac_ctx_t; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* 1757c478bd9Sstevel@tonic-gate * Macros to access the SHA2 or SHA2-HMAC contexts from a context passed 1767c478bd9Sstevel@tonic-gate * by KCF to one of the entry points. 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate #define PROV_SHA2_CTX(ctx) ((sha2_ctx_t *)(ctx)->cc_provider_private) 1807c478bd9Sstevel@tonic-gate #define PROV_SHA2_HMAC_CTX(ctx) ((sha2_hmac_ctx_t *)(ctx)->cc_provider_private) 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* to extract the digest length passed as mechanism parameter */ 1837c478bd9Sstevel@tonic-gate #define PROV_SHA2_GET_DIGEST_LEN(m, len) { \ 1847c478bd9Sstevel@tonic-gate if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t))) \ 1857c478bd9Sstevel@tonic-gate (len) = (uint32_t)*((ulong_t *)(m)->cm_param); \ 1867c478bd9Sstevel@tonic-gate else { \ 1877c478bd9Sstevel@tonic-gate ulong_t tmp_ulong; \ 1887c478bd9Sstevel@tonic-gate bcopy((m)->cm_param, &tmp_ulong, sizeof (ulong_t)); \ 1897c478bd9Sstevel@tonic-gate (len) = (uint32_t)tmp_ulong; \ 1907c478bd9Sstevel@tonic-gate } \ 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate #define PROV_SHA2_DIGEST_KEY(mech, ctx, key, len, digest) { \ 1947c478bd9Sstevel@tonic-gate SHA2Init(mech, ctx); \ 1957c478bd9Sstevel@tonic-gate SHA2Update(ctx, key, len); \ 1967c478bd9Sstevel@tonic-gate SHA2Final(digest, ctx); \ 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate /* 2007c478bd9Sstevel@tonic-gate * Mechanism info structure passed to KCF during registration. 2017c478bd9Sstevel@tonic-gate */ 2027c478bd9Sstevel@tonic-gate static crypto_mech_info_t sha2_mech_info_tab[] = { 2037c478bd9Sstevel@tonic-gate /* SHA256 */ 2047c478bd9Sstevel@tonic-gate {SUN_CKM_SHA256, SHA256_MECH_INFO_TYPE, 2057c478bd9Sstevel@tonic-gate CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 2067c478bd9Sstevel@tonic-gate 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2077c478bd9Sstevel@tonic-gate /* SHA256-HMAC */ 2087c478bd9Sstevel@tonic-gate {SUN_CKM_SHA256_HMAC, SHA256_HMAC_MECH_INFO_TYPE, 2097c478bd9Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2107c478bd9Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2117c478bd9Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2127c478bd9Sstevel@tonic-gate /* SHA256-HMAC GENERAL */ 2137c478bd9Sstevel@tonic-gate {SUN_CKM_SHA256_HMAC_GENERAL, SHA256_HMAC_GEN_MECH_INFO_TYPE, 2147c478bd9Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2157c478bd9Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2167c478bd9Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2177c478bd9Sstevel@tonic-gate /* SHA384 */ 2187c478bd9Sstevel@tonic-gate {SUN_CKM_SHA384, SHA384_MECH_INFO_TYPE, 2197c478bd9Sstevel@tonic-gate CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 2207c478bd9Sstevel@tonic-gate 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2217c478bd9Sstevel@tonic-gate /* SHA384-HMAC */ 2227c478bd9Sstevel@tonic-gate {SUN_CKM_SHA384_HMAC, SHA384_HMAC_MECH_INFO_TYPE, 2237c478bd9Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2247c478bd9Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2257c478bd9Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2267c478bd9Sstevel@tonic-gate /* SHA384-HMAC GENERAL */ 2277c478bd9Sstevel@tonic-gate {SUN_CKM_SHA384_HMAC_GENERAL, SHA384_HMAC_GEN_MECH_INFO_TYPE, 2287c478bd9Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2297c478bd9Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2307c478bd9Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2317c478bd9Sstevel@tonic-gate /* SHA512 */ 2327c478bd9Sstevel@tonic-gate {SUN_CKM_SHA512, SHA512_MECH_INFO_TYPE, 2337c478bd9Sstevel@tonic-gate CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 2347c478bd9Sstevel@tonic-gate 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2357c478bd9Sstevel@tonic-gate /* SHA512-HMAC */ 2367c478bd9Sstevel@tonic-gate {SUN_CKM_SHA512_HMAC, SHA512_HMAC_MECH_INFO_TYPE, 2377c478bd9Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2387c478bd9Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2397c478bd9Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS}, 2407c478bd9Sstevel@tonic-gate /* SHA512-HMAC GENERAL */ 2417c478bd9Sstevel@tonic-gate {SUN_CKM_SHA512_HMAC_GENERAL, SHA512_HMAC_GEN_MECH_INFO_TYPE, 2427c478bd9Sstevel@tonic-gate CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 2437c478bd9Sstevel@tonic-gate SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN, 2447c478bd9Sstevel@tonic-gate CRYPTO_KEYSIZE_UNIT_IN_BITS} 2457c478bd9Sstevel@tonic-gate }; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate void SHA2Init(uint64_t, SHA2_CTX *); 2487c478bd9Sstevel@tonic-gate void SHA2Update(SHA2_CTX *, const uint8_t *, uint32_t); 2497c478bd9Sstevel@tonic-gate void SHA2Final(uint8_t *, SHA2_CTX *); 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate static void sha2_provider_status(crypto_provider_handle_t, uint_t *); 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate static crypto_control_ops_t sha2_control_ops = { 2547c478bd9Sstevel@tonic-gate sha2_provider_status 2557c478bd9Sstevel@tonic-gate }; 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate static int sha2_digest_init(crypto_ctx_t *, crypto_mechanism_t *, 2587c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2597c478bd9Sstevel@tonic-gate static int sha2_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 2607c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2617c478bd9Sstevel@tonic-gate static int sha2_digest_update(crypto_ctx_t *, crypto_data_t *, 2627c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2637c478bd9Sstevel@tonic-gate static int sha2_digest_final(crypto_ctx_t *, crypto_data_t *, 2647c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2657c478bd9Sstevel@tonic-gate static int sha2_digest_atomic(crypto_provider_handle_t, crypto_session_id_t, 2667c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_data_t *, crypto_data_t *, 2677c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate static crypto_digest_ops_t sha2_digest_ops = { 2707c478bd9Sstevel@tonic-gate sha2_digest_init, 2717c478bd9Sstevel@tonic-gate sha2_digest, 2727c478bd9Sstevel@tonic-gate sha2_digest_update, 2737c478bd9Sstevel@tonic-gate NULL, 2747c478bd9Sstevel@tonic-gate sha2_digest_final, 2757c478bd9Sstevel@tonic-gate sha2_digest_atomic 2767c478bd9Sstevel@tonic-gate }; 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate static int sha2_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, 2797c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 2807c478bd9Sstevel@tonic-gate static int sha2_mac_update(crypto_ctx_t *, crypto_data_t *, 2817c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2827c478bd9Sstevel@tonic-gate static int sha2_mac_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); 2837c478bd9Sstevel@tonic-gate static int sha2_mac_atomic(crypto_provider_handle_t, crypto_session_id_t, 2847c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 2857c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 2867c478bd9Sstevel@tonic-gate static int sha2_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t, 2877c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 2887c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate static crypto_mac_ops_t sha2_mac_ops = { 2917c478bd9Sstevel@tonic-gate sha2_mac_init, 2927c478bd9Sstevel@tonic-gate NULL, 2937c478bd9Sstevel@tonic-gate sha2_mac_update, 2947c478bd9Sstevel@tonic-gate sha2_mac_final, 2957c478bd9Sstevel@tonic-gate sha2_mac_atomic, 2967c478bd9Sstevel@tonic-gate sha2_mac_verify_atomic 2977c478bd9Sstevel@tonic-gate }; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate static int sha2_create_ctx_template(crypto_provider_handle_t, 3007c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *, 3017c478bd9Sstevel@tonic-gate size_t *, crypto_req_handle_t); 3027c478bd9Sstevel@tonic-gate static int sha2_free_context(crypto_ctx_t *); 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate static crypto_ctx_ops_t sha2_ctx_ops = { 3057c478bd9Sstevel@tonic-gate sha2_create_ctx_template, 3067c478bd9Sstevel@tonic-gate sha2_free_context 3077c478bd9Sstevel@tonic-gate }; 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate static crypto_ops_t sha2_crypto_ops = { 3107c478bd9Sstevel@tonic-gate &sha2_control_ops, 3117c478bd9Sstevel@tonic-gate &sha2_digest_ops, 3127c478bd9Sstevel@tonic-gate NULL, 3137c478bd9Sstevel@tonic-gate &sha2_mac_ops, 3147c478bd9Sstevel@tonic-gate NULL, 3157c478bd9Sstevel@tonic-gate NULL, 3167c478bd9Sstevel@tonic-gate NULL, 3177c478bd9Sstevel@tonic-gate NULL, 3187c478bd9Sstevel@tonic-gate NULL, 3197c478bd9Sstevel@tonic-gate NULL, 3207c478bd9Sstevel@tonic-gate NULL, 3217c478bd9Sstevel@tonic-gate NULL, 3227c478bd9Sstevel@tonic-gate NULL, 3237c478bd9Sstevel@tonic-gate &sha2_ctx_ops 3247c478bd9Sstevel@tonic-gate }; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate static crypto_provider_info_t sha2_prov_info = { 3277c478bd9Sstevel@tonic-gate CRYPTO_SPI_VERSION_1, 3287c478bd9Sstevel@tonic-gate "SHA2 Software Provider", 3297c478bd9Sstevel@tonic-gate CRYPTO_SW_PROVIDER, 3307c478bd9Sstevel@tonic-gate {&modlinkage}, 3317c478bd9Sstevel@tonic-gate NULL, 3327c478bd9Sstevel@tonic-gate &sha2_crypto_ops, 3337c478bd9Sstevel@tonic-gate sizeof (sha2_mech_info_tab)/sizeof (crypto_mech_info_t), 3347c478bd9Sstevel@tonic-gate sha2_mech_info_tab 3357c478bd9Sstevel@tonic-gate }; 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate static crypto_kcf_provider_handle_t sha2_prov_handle = NULL; 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate int 3407c478bd9Sstevel@tonic-gate _init() 3417c478bd9Sstevel@tonic-gate { 3427c478bd9Sstevel@tonic-gate int ret; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate if ((ret = mod_install(&modlinkage)) != 0) 3457c478bd9Sstevel@tonic-gate return (ret); 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * Register with KCF. If the registration fails, log an 3497c478bd9Sstevel@tonic-gate * error but do not uninstall the module, since the functionality 3507c478bd9Sstevel@tonic-gate * provided by misc/sha2 should still be available. 3517c478bd9Sstevel@tonic-gate */ 3527c478bd9Sstevel@tonic-gate if ((ret = crypto_register_provider(&sha2_prov_info, 3537c478bd9Sstevel@tonic-gate &sha2_prov_handle)) != CRYPTO_SUCCESS) 3547c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "sha2 _init: " 3557c478bd9Sstevel@tonic-gate "crypto_register_provider() failed (0x%x)", ret); 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate return (0); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate int 3617c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 3627c478bd9Sstevel@tonic-gate { 3637c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate /* 3707c478bd9Sstevel@tonic-gate * sparc optimization: 3717c478bd9Sstevel@tonic-gate * 3727c478bd9Sstevel@tonic-gate * on the sparc, we can load big endian 32-bit data easily. note that 3737c478bd9Sstevel@tonic-gate * special care must be taken to ensure the address is 32-bit aligned. 3747c478bd9Sstevel@tonic-gate * in the interest of speed, we don't check to make sure, since 3757c478bd9Sstevel@tonic-gate * careful programming can guarantee this for us. 3767c478bd9Sstevel@tonic-gate */ 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate #if defined(_BIG_ENDIAN) 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate #define LOAD_BIG_32(addr) (*(uint32_t *)(addr)) 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate #else /* little endian -- will work on big endian, but slowly */ 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate #define LOAD_BIG_32(addr) \ 3857c478bd9Sstevel@tonic-gate (((addr)[0] << 24) | ((addr)[1] << 16) | ((addr)[2] << 8) | (addr)[3]) 3867c478bd9Sstevel@tonic-gate #endif 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate #if defined(_BIG_ENDIAN) 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate #define LOAD_BIG_64(addr) (*(uint64_t *)(addr)) 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate #else /* little endian -- will work on big endian, but slowly */ 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate #define LOAD_BIG_64(addr) \ 3967c478bd9Sstevel@tonic-gate (((uint64_t)(addr)[0] << 56) | ((uint64_t)(addr)[1] << 48) | \ 3977c478bd9Sstevel@tonic-gate ((uint64_t)(addr)[2] << 40) | ((uint64_t)(addr)[3] << 32) | \ 3987c478bd9Sstevel@tonic-gate ((uint64_t)(addr)[4] << 24) | ((uint64_t)(addr)[5] << 16) | \ 3997c478bd9Sstevel@tonic-gate ((uint64_t)(addr)[6] << 8) | (uint64_t)(addr)[7]) 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate #endif 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate /* SHA256 Transform */ 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate static void 4077c478bd9Sstevel@tonic-gate SHA256Transform(SHA2_CTX *ctx, const uint8_t *blk) 4087c478bd9Sstevel@tonic-gate { 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate uint32_t a = ctx->state.s32[0]; 4117c478bd9Sstevel@tonic-gate uint32_t b = ctx->state.s32[1]; 4127c478bd9Sstevel@tonic-gate uint32_t c = ctx->state.s32[2]; 4137c478bd9Sstevel@tonic-gate uint32_t d = ctx->state.s32[3]; 4147c478bd9Sstevel@tonic-gate uint32_t e = ctx->state.s32[4]; 4157c478bd9Sstevel@tonic-gate uint32_t f = ctx->state.s32[5]; 4167c478bd9Sstevel@tonic-gate uint32_t g = ctx->state.s32[6]; 4177c478bd9Sstevel@tonic-gate uint32_t h = ctx->state.s32[7]; 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate uint32_t w0, w1, w2, w3, w4, w5, w6, w7; 4207c478bd9Sstevel@tonic-gate uint32_t w8, w9, w10, w11, w12, w13, w14, w15; 4217c478bd9Sstevel@tonic-gate uint32_t T1, T2; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate #if defined(__sparc) 4247c478bd9Sstevel@tonic-gate static const uint32_t sha256_consts[] = { 4257c478bd9Sstevel@tonic-gate SHA256_CONST_0, SHA256_CONST_1, SHA256_CONST_2, 4267c478bd9Sstevel@tonic-gate SHA256_CONST_3, SHA256_CONST_4, SHA256_CONST_5, 4277c478bd9Sstevel@tonic-gate SHA256_CONST_6, SHA256_CONST_7, SHA256_CONST_8, 4287c478bd9Sstevel@tonic-gate SHA256_CONST_9, SHA256_CONST_10, SHA256_CONST_11, 4297c478bd9Sstevel@tonic-gate SHA256_CONST_12, SHA256_CONST_13, SHA256_CONST_14, 4307c478bd9Sstevel@tonic-gate SHA256_CONST_15, SHA256_CONST_16, SHA256_CONST_17, 4317c478bd9Sstevel@tonic-gate SHA256_CONST_18, SHA256_CONST_19, SHA256_CONST_20, 4327c478bd9Sstevel@tonic-gate SHA256_CONST_21, SHA256_CONST_22, SHA256_CONST_23, 4337c478bd9Sstevel@tonic-gate SHA256_CONST_24, SHA256_CONST_25, SHA256_CONST_26, 4347c478bd9Sstevel@tonic-gate SHA256_CONST_27, SHA256_CONST_28, SHA256_CONST_29, 4357c478bd9Sstevel@tonic-gate SHA256_CONST_30, SHA256_CONST_31, SHA256_CONST_32, 4367c478bd9Sstevel@tonic-gate SHA256_CONST_33, SHA256_CONST_34, SHA256_CONST_35, 4377c478bd9Sstevel@tonic-gate SHA256_CONST_36, SHA256_CONST_37, SHA256_CONST_38, 4387c478bd9Sstevel@tonic-gate SHA256_CONST_39, SHA256_CONST_40, SHA256_CONST_41, 4397c478bd9Sstevel@tonic-gate SHA256_CONST_42, SHA256_CONST_43, SHA256_CONST_44, 4407c478bd9Sstevel@tonic-gate SHA256_CONST_45, SHA256_CONST_46, SHA256_CONST_47, 4417c478bd9Sstevel@tonic-gate SHA256_CONST_48, SHA256_CONST_49, SHA256_CONST_50, 4427c478bd9Sstevel@tonic-gate SHA256_CONST_51, SHA256_CONST_52, SHA256_CONST_53, 4437c478bd9Sstevel@tonic-gate SHA256_CONST_54, SHA256_CONST_55, SHA256_CONST_56, 4447c478bd9Sstevel@tonic-gate SHA256_CONST_57, SHA256_CONST_58, SHA256_CONST_59, 4457c478bd9Sstevel@tonic-gate SHA256_CONST_60, SHA256_CONST_61, SHA256_CONST_62, 4467c478bd9Sstevel@tonic-gate SHA256_CONST_63 4477c478bd9Sstevel@tonic-gate }; 4487c478bd9Sstevel@tonic-gate #endif 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate if ((uintptr_t)blk & 0x3) { /* not 4-byte aligned? */ 4517c478bd9Sstevel@tonic-gate bcopy(blk, ctx->buf_un.buf32, sizeof (ctx->buf_un.buf32)); 4527c478bd9Sstevel@tonic-gate blk = (uint8_t *)ctx->buf_un.buf32; 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 455f66d273dSizick #if defined(__sparc) 456f66d273dSizick /*LINTED*/ 457f66d273dSizick w0 = LOAD_BIG_32(blk + 4 * 0); 458f66d273dSizick SHA256ROUND(a, b, c, d, e, f, g, h, 0, w0); 459f66d273dSizick /*LINTED*/ 460f66d273dSizick w1 = LOAD_BIG_32(blk + 4 * 1); 461f66d273dSizick SHA256ROUND(h, a, b, c, d, e, f, g, 1, w1); 462f66d273dSizick /*LINTED*/ 463f66d273dSizick w2 = LOAD_BIG_32(blk + 4 * 2); 464f66d273dSizick SHA256ROUND(g, h, a, b, c, d, e, f, 2, w2); 465f66d273dSizick /*LINTED*/ 466f66d273dSizick w3 = LOAD_BIG_32(blk + 4 * 3); 467f66d273dSizick SHA256ROUND(f, g, h, a, b, c, d, e, 3, w3); 468f66d273dSizick /*LINTED*/ 469f66d273dSizick w4 = LOAD_BIG_32(blk + 4 * 4); 470f66d273dSizick SHA256ROUND(e, f, g, h, a, b, c, d, 4, w4); 471f66d273dSizick /*LINTED*/ 472f66d273dSizick w5 = LOAD_BIG_32(blk + 4 * 5); 473f66d273dSizick SHA256ROUND(d, e, f, g, h, a, b, c, 5, w5); 474f66d273dSizick /*LINTED*/ 475f66d273dSizick w6 = LOAD_BIG_32(blk + 4 * 6); 476f66d273dSizick SHA256ROUND(c, d, e, f, g, h, a, b, 6, w6); 477f66d273dSizick /*LINTED*/ 478f66d273dSizick w7 = LOAD_BIG_32(blk + 4 * 7); 479f66d273dSizick SHA256ROUND(b, c, d, e, f, g, h, a, 7, w7); 480f66d273dSizick /*LINTED*/ 481f66d273dSizick w8 = LOAD_BIG_32(blk + 4 * 8); 482f66d273dSizick SHA256ROUND(a, b, c, d, e, f, g, h, 8, w8); 483f66d273dSizick /*LINTED*/ 484f66d273dSizick w9 = LOAD_BIG_32(blk + 4 * 9); 485f66d273dSizick SHA256ROUND(h, a, b, c, d, e, f, g, 9, w9); 486f66d273dSizick /*LINTED*/ 487f66d273dSizick w10 = LOAD_BIG_32(blk + 4 * 10); 488f66d273dSizick SHA256ROUND(g, h, a, b, c, d, e, f, 10, w10); 489f66d273dSizick /*LINTED*/ 490f66d273dSizick w11 = LOAD_BIG_32(blk + 4 * 11); 491f66d273dSizick SHA256ROUND(f, g, h, a, b, c, d, e, 11, w11); 492f66d273dSizick /*LINTED*/ 493f66d273dSizick w12 = LOAD_BIG_32(blk + 4 * 12); 494f66d273dSizick SHA256ROUND(e, f, g, h, a, b, c, d, 12, w12); 495f66d273dSizick /*LINTED*/ 496f66d273dSizick w13 = LOAD_BIG_32(blk + 4 * 13); 497f66d273dSizick SHA256ROUND(d, e, f, g, h, a, b, c, 13, w13); 498f66d273dSizick /*LINTED*/ 499f66d273dSizick w14 = LOAD_BIG_32(blk + 4 * 14); 500f66d273dSizick SHA256ROUND(c, d, e, f, g, h, a, b, 14, w14); 501f66d273dSizick /*LINTED*/ 502f66d273dSizick w15 = LOAD_BIG_32(blk + 4 * 15); 503f66d273dSizick SHA256ROUND(b, c, d, e, f, g, h, a, 15, w15); 504f66d273dSizick 505f66d273dSizick #else 506f66d273dSizick 5077c478bd9Sstevel@tonic-gate w0 = LOAD_BIG_32(blk + 4 * 0); 5087c478bd9Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 0, w0); 5097c478bd9Sstevel@tonic-gate w1 = LOAD_BIG_32(blk + 4 * 1); 5107c478bd9Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 1, w1); 5117c478bd9Sstevel@tonic-gate w2 = LOAD_BIG_32(blk + 4 * 2); 5127c478bd9Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 2, w2); 5137c478bd9Sstevel@tonic-gate w3 = LOAD_BIG_32(blk + 4 * 3); 5147c478bd9Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 3, w3); 5157c478bd9Sstevel@tonic-gate w4 = LOAD_BIG_32(blk + 4 * 4); 5167c478bd9Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 4, w4); 5177c478bd9Sstevel@tonic-gate w5 = LOAD_BIG_32(blk + 4 * 5); 5187c478bd9Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 5, w5); 5197c478bd9Sstevel@tonic-gate w6 = LOAD_BIG_32(blk + 4 * 6); 5207c478bd9Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 6, w6); 5217c478bd9Sstevel@tonic-gate w7 = LOAD_BIG_32(blk + 4 * 7); 5227c478bd9Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 7, w7); 5237c478bd9Sstevel@tonic-gate w8 = LOAD_BIG_32(blk + 4 * 8); 5247c478bd9Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 8, w8); 5257c478bd9Sstevel@tonic-gate w9 = LOAD_BIG_32(blk + 4 * 9); 5267c478bd9Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 9, w9); 5277c478bd9Sstevel@tonic-gate w10 = LOAD_BIG_32(blk + 4 * 10); 5287c478bd9Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 10, w10); 5297c478bd9Sstevel@tonic-gate w11 = LOAD_BIG_32(blk + 4 * 11); 5307c478bd9Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 11, w11); 5317c478bd9Sstevel@tonic-gate w12 = LOAD_BIG_32(blk + 4 * 12); 5327c478bd9Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 12, w12); 5337c478bd9Sstevel@tonic-gate w13 = LOAD_BIG_32(blk + 4 * 13); 5347c478bd9Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 13, w13); 5357c478bd9Sstevel@tonic-gate w14 = LOAD_BIG_32(blk + 4 * 14); 5367c478bd9Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 14, w14); 5377c478bd9Sstevel@tonic-gate w15 = LOAD_BIG_32(blk + 4 * 15); 5387c478bd9Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 15, w15); 5397c478bd9Sstevel@tonic-gate 540f66d273dSizick #endif 541f66d273dSizick 5427c478bd9Sstevel@tonic-gate w0 = SIGMA1_256(w14) + w9 + SIGMA0_256(w1) + w0; 5437c478bd9Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 16, w0); 5447c478bd9Sstevel@tonic-gate w1 = SIGMA1_256(w15) + w10 + SIGMA0_256(w2) + w1; 5457c478bd9Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 17, w1); 5467c478bd9Sstevel@tonic-gate w2 = SIGMA1_256(w0) + w11 + SIGMA0_256(w3) + w2; 5477c478bd9Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 18, w2); 5487c478bd9Sstevel@tonic-gate w3 = SIGMA1_256(w1) + w12 + SIGMA0_256(w4) + w3; 5497c478bd9Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 19, w3); 5507c478bd9Sstevel@tonic-gate w4 = SIGMA1_256(w2) + w13 + SIGMA0_256(w5) + w4; 5517c478bd9Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 20, w4); 5527c478bd9Sstevel@tonic-gate w5 = SIGMA1_256(w3) + w14 + SIGMA0_256(w6) + w5; 5537c478bd9Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 21, w5); 5547c478bd9Sstevel@tonic-gate w6 = SIGMA1_256(w4) + w15 + SIGMA0_256(w7) + w6; 5557c478bd9Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 22, w6); 5567c478bd9Sstevel@tonic-gate w7 = SIGMA1_256(w5) + w0 + SIGMA0_256(w8) + w7; 5577c478bd9Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 23, w7); 5587c478bd9Sstevel@tonic-gate w8 = SIGMA1_256(w6) + w1 + SIGMA0_256(w9) + w8; 5597c478bd9Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 24, w8); 5607c478bd9Sstevel@tonic-gate w9 = SIGMA1_256(w7) + w2 + SIGMA0_256(w10) + w9; 5617c478bd9Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 25, w9); 5627c478bd9Sstevel@tonic-gate w10 = SIGMA1_256(w8) + w3 + SIGMA0_256(w11) + w10; 5637c478bd9Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 26, w10); 5647c478bd9Sstevel@tonic-gate w11 = SIGMA1_256(w9) + w4 + SIGMA0_256(w12) + w11; 5657c478bd9Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 27, w11); 5667c478bd9Sstevel@tonic-gate w12 = SIGMA1_256(w10) + w5 + SIGMA0_256(w13) + w12; 5677c478bd9Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 28, w12); 5687c478bd9Sstevel@tonic-gate w13 = SIGMA1_256(w11) + w6 + SIGMA0_256(w14) + w13; 5697c478bd9Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 29, w13); 5707c478bd9Sstevel@tonic-gate w14 = SIGMA1_256(w12) + w7 + SIGMA0_256(w15) + w14; 5717c478bd9Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 30, w14); 5727c478bd9Sstevel@tonic-gate w15 = SIGMA1_256(w13) + w8 + SIGMA0_256(w0) + w15; 5737c478bd9Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 31, w15); 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate w0 = SIGMA1_256(w14) + w9 + SIGMA0_256(w1) + w0; 5767c478bd9Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 32, w0); 5777c478bd9Sstevel@tonic-gate w1 = SIGMA1_256(w15) + w10 + SIGMA0_256(w2) + w1; 5787c478bd9Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 33, w1); 5797c478bd9Sstevel@tonic-gate w2 = SIGMA1_256(w0) + w11 + SIGMA0_256(w3) + w2; 5807c478bd9Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 34, w2); 5817c478bd9Sstevel@tonic-gate w3 = SIGMA1_256(w1) + w12 + SIGMA0_256(w4) + w3; 5827c478bd9Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 35, w3); 5837c478bd9Sstevel@tonic-gate w4 = SIGMA1_256(w2) + w13 + SIGMA0_256(w5) + w4; 5847c478bd9Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 36, w4); 5857c478bd9Sstevel@tonic-gate w5 = SIGMA1_256(w3) + w14 + SIGMA0_256(w6) + w5; 5867c478bd9Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 37, w5); 5877c478bd9Sstevel@tonic-gate w6 = SIGMA1_256(w4) + w15 + SIGMA0_256(w7) + w6; 5887c478bd9Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 38, w6); 5897c478bd9Sstevel@tonic-gate w7 = SIGMA1_256(w5) + w0 + SIGMA0_256(w8) + w7; 5907c478bd9Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 39, w7); 5917c478bd9Sstevel@tonic-gate w8 = SIGMA1_256(w6) + w1 + SIGMA0_256(w9) + w8; 5927c478bd9Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 40, w8); 5937c478bd9Sstevel@tonic-gate w9 = SIGMA1_256(w7) + w2 + SIGMA0_256(w10) + w9; 5947c478bd9Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 41, w9); 5957c478bd9Sstevel@tonic-gate w10 = SIGMA1_256(w8) + w3 + SIGMA0_256(w11) + w10; 5967c478bd9Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 42, w10); 5977c478bd9Sstevel@tonic-gate w11 = SIGMA1_256(w9) + w4 + SIGMA0_256(w12) + w11; 5987c478bd9Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 43, w11); 5997c478bd9Sstevel@tonic-gate w12 = SIGMA1_256(w10) + w5 + SIGMA0_256(w13) + w12; 6007c478bd9Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 44, w12); 6017c478bd9Sstevel@tonic-gate w13 = SIGMA1_256(w11) + w6 + SIGMA0_256(w14) + w13; 6027c478bd9Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 45, w13); 6037c478bd9Sstevel@tonic-gate w14 = SIGMA1_256(w12) + w7 + SIGMA0_256(w15) + w14; 6047c478bd9Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 46, w14); 6057c478bd9Sstevel@tonic-gate w15 = SIGMA1_256(w13) + w8 + SIGMA0_256(w0) + w15; 6067c478bd9Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 47, w15); 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate w0 = SIGMA1_256(w14) + w9 + SIGMA0_256(w1) + w0; 6097c478bd9Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 48, w0); 6107c478bd9Sstevel@tonic-gate w1 = SIGMA1_256(w15) + w10 + SIGMA0_256(w2) + w1; 6117c478bd9Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 49, w1); 6127c478bd9Sstevel@tonic-gate w2 = SIGMA1_256(w0) + w11 + SIGMA0_256(w3) + w2; 6137c478bd9Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 50, w2); 6147c478bd9Sstevel@tonic-gate w3 = SIGMA1_256(w1) + w12 + SIGMA0_256(w4) + w3; 6157c478bd9Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 51, w3); 6167c478bd9Sstevel@tonic-gate w4 = SIGMA1_256(w2) + w13 + SIGMA0_256(w5) + w4; 6177c478bd9Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 52, w4); 6187c478bd9Sstevel@tonic-gate w5 = SIGMA1_256(w3) + w14 + SIGMA0_256(w6) + w5; 6197c478bd9Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 53, w5); 6207c478bd9Sstevel@tonic-gate w6 = SIGMA1_256(w4) + w15 + SIGMA0_256(w7) + w6; 6217c478bd9Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 54, w6); 6227c478bd9Sstevel@tonic-gate w7 = SIGMA1_256(w5) + w0 + SIGMA0_256(w8) + w7; 6237c478bd9Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 55, w7); 6247c478bd9Sstevel@tonic-gate w8 = SIGMA1_256(w6) + w1 + SIGMA0_256(w9) + w8; 6257c478bd9Sstevel@tonic-gate SHA256ROUND(a, b, c, d, e, f, g, h, 56, w8); 6267c478bd9Sstevel@tonic-gate w9 = SIGMA1_256(w7) + w2 + SIGMA0_256(w10) + w9; 6277c478bd9Sstevel@tonic-gate SHA256ROUND(h, a, b, c, d, e, f, g, 57, w9); 6287c478bd9Sstevel@tonic-gate w10 = SIGMA1_256(w8) + w3 + SIGMA0_256(w11) + w10; 6297c478bd9Sstevel@tonic-gate SHA256ROUND(g, h, a, b, c, d, e, f, 58, w10); 6307c478bd9Sstevel@tonic-gate w11 = SIGMA1_256(w9) + w4 + SIGMA0_256(w12) + w11; 6317c478bd9Sstevel@tonic-gate SHA256ROUND(f, g, h, a, b, c, d, e, 59, w11); 6327c478bd9Sstevel@tonic-gate w12 = SIGMA1_256(w10) + w5 + SIGMA0_256(w13) + w12; 6337c478bd9Sstevel@tonic-gate SHA256ROUND(e, f, g, h, a, b, c, d, 60, w12); 6347c478bd9Sstevel@tonic-gate w13 = SIGMA1_256(w11) + w6 + SIGMA0_256(w14) + w13; 6357c478bd9Sstevel@tonic-gate SHA256ROUND(d, e, f, g, h, a, b, c, 61, w13); 6367c478bd9Sstevel@tonic-gate w14 = SIGMA1_256(w12) + w7 + SIGMA0_256(w15) + w14; 6377c478bd9Sstevel@tonic-gate SHA256ROUND(c, d, e, f, g, h, a, b, 62, w14); 6387c478bd9Sstevel@tonic-gate w15 = SIGMA1_256(w13) + w8 + SIGMA0_256(w0) + w15; 6397c478bd9Sstevel@tonic-gate SHA256ROUND(b, c, d, e, f, g, h, a, 63, w15); 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate ctx->state.s32[0] += a; 6427c478bd9Sstevel@tonic-gate ctx->state.s32[1] += b; 6437c478bd9Sstevel@tonic-gate ctx->state.s32[2] += c; 6447c478bd9Sstevel@tonic-gate ctx->state.s32[3] += d; 6457c478bd9Sstevel@tonic-gate ctx->state.s32[4] += e; 6467c478bd9Sstevel@tonic-gate ctx->state.s32[5] += f; 6477c478bd9Sstevel@tonic-gate ctx->state.s32[6] += g; 6487c478bd9Sstevel@tonic-gate ctx->state.s32[7] += h; 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate /* SHA384 and SHA512 Transform */ 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate static void 6557c478bd9Sstevel@tonic-gate SHA512Transform(SHA2_CTX *ctx, const uint8_t *blk) 6567c478bd9Sstevel@tonic-gate { 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate uint64_t a = ctx->state.s64[0]; 6597c478bd9Sstevel@tonic-gate uint64_t b = ctx->state.s64[1]; 6607c478bd9Sstevel@tonic-gate uint64_t c = ctx->state.s64[2]; 6617c478bd9Sstevel@tonic-gate uint64_t d = ctx->state.s64[3]; 6627c478bd9Sstevel@tonic-gate uint64_t e = ctx->state.s64[4]; 6637c478bd9Sstevel@tonic-gate uint64_t f = ctx->state.s64[5]; 6647c478bd9Sstevel@tonic-gate uint64_t g = ctx->state.s64[6]; 6657c478bd9Sstevel@tonic-gate uint64_t h = ctx->state.s64[7]; 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate uint64_t w0, w1, w2, w3, w4, w5, w6, w7; 6687c478bd9Sstevel@tonic-gate uint64_t w8, w9, w10, w11, w12, w13, w14, w15; 6697c478bd9Sstevel@tonic-gate uint64_t T1, T2; 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate #if defined(__sparc) 6727c478bd9Sstevel@tonic-gate static const uint64_t sha512_consts[] = { 6737c478bd9Sstevel@tonic-gate SHA512_CONST_0, SHA512_CONST_1, SHA512_CONST_2, 6747c478bd9Sstevel@tonic-gate SHA512_CONST_3, SHA512_CONST_4, SHA512_CONST_5, 6757c478bd9Sstevel@tonic-gate SHA512_CONST_6, SHA512_CONST_7, SHA512_CONST_8, 6767c478bd9Sstevel@tonic-gate SHA512_CONST_9, SHA512_CONST_10, SHA512_CONST_11, 6777c478bd9Sstevel@tonic-gate SHA512_CONST_12, SHA512_CONST_13, SHA512_CONST_14, 6787c478bd9Sstevel@tonic-gate SHA512_CONST_15, SHA512_CONST_16, SHA512_CONST_17, 6797c478bd9Sstevel@tonic-gate SHA512_CONST_18, SHA512_CONST_19, SHA512_CONST_20, 6807c478bd9Sstevel@tonic-gate SHA512_CONST_21, SHA512_CONST_22, SHA512_CONST_23, 6817c478bd9Sstevel@tonic-gate SHA512_CONST_24, SHA512_CONST_25, SHA512_CONST_26, 6827c478bd9Sstevel@tonic-gate SHA512_CONST_27, SHA512_CONST_28, SHA512_CONST_29, 6837c478bd9Sstevel@tonic-gate SHA512_CONST_30, SHA512_CONST_31, SHA512_CONST_32, 6847c478bd9Sstevel@tonic-gate SHA512_CONST_33, SHA512_CONST_34, SHA512_CONST_35, 6857c478bd9Sstevel@tonic-gate SHA512_CONST_36, SHA512_CONST_37, SHA512_CONST_38, 6867c478bd9Sstevel@tonic-gate SHA512_CONST_39, SHA512_CONST_40, SHA512_CONST_41, 6877c478bd9Sstevel@tonic-gate SHA512_CONST_42, SHA512_CONST_43, SHA512_CONST_44, 6887c478bd9Sstevel@tonic-gate SHA512_CONST_45, SHA512_CONST_46, SHA512_CONST_47, 6897c478bd9Sstevel@tonic-gate SHA512_CONST_48, SHA512_CONST_49, SHA512_CONST_50, 6907c478bd9Sstevel@tonic-gate SHA512_CONST_51, SHA512_CONST_52, SHA512_CONST_53, 6917c478bd9Sstevel@tonic-gate SHA512_CONST_54, SHA512_CONST_55, SHA512_CONST_56, 6927c478bd9Sstevel@tonic-gate SHA512_CONST_57, SHA512_CONST_58, SHA512_CONST_59, 6937c478bd9Sstevel@tonic-gate SHA512_CONST_60, SHA512_CONST_61, SHA512_CONST_62, 6947c478bd9Sstevel@tonic-gate SHA512_CONST_63, SHA512_CONST_64, SHA512_CONST_65, 6957c478bd9Sstevel@tonic-gate SHA512_CONST_66, SHA512_CONST_67, SHA512_CONST_68, 6967c478bd9Sstevel@tonic-gate SHA512_CONST_69, SHA512_CONST_70, SHA512_CONST_71, 6977c478bd9Sstevel@tonic-gate SHA512_CONST_72, SHA512_CONST_73, SHA512_CONST_74, 6987c478bd9Sstevel@tonic-gate SHA512_CONST_75, SHA512_CONST_76, SHA512_CONST_77, 6997c478bd9Sstevel@tonic-gate SHA512_CONST_78, SHA512_CONST_79 7007c478bd9Sstevel@tonic-gate }; 7017c478bd9Sstevel@tonic-gate #endif 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate if ((uintptr_t)blk & 0x7) { /* not 8-byte aligned? */ 7057c478bd9Sstevel@tonic-gate bcopy(blk, ctx->buf_un.buf64, sizeof (ctx->buf_un.buf64)); 7067c478bd9Sstevel@tonic-gate blk = (uint8_t *)ctx->buf_un.buf64; 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate 709f66d273dSizick #if defined(__sparc) 710f66d273dSizick /*LINTED*/ 711f66d273dSizick w0 = LOAD_BIG_64(blk + 8 * 0); 712f66d273dSizick SHA512ROUND(a, b, c, d, e, f, g, h, 0, w0); 713f66d273dSizick /*LINTED*/ 714f66d273dSizick w1 = LOAD_BIG_64(blk + 8 * 1); 715f66d273dSizick SHA512ROUND(h, a, b, c, d, e, f, g, 1, w1); 716f66d273dSizick /*LINTED*/ 717f66d273dSizick w2 = LOAD_BIG_64(blk + 8 * 2); 718f66d273dSizick SHA512ROUND(g, h, a, b, c, d, e, f, 2, w2); 719f66d273dSizick /*LINTED*/ 720f66d273dSizick w3 = LOAD_BIG_64(blk + 8 * 3); 721f66d273dSizick SHA512ROUND(f, g, h, a, b, c, d, e, 3, w3); 722f66d273dSizick /*LINTED*/ 723f66d273dSizick w4 = LOAD_BIG_64(blk + 8 * 4); 724f66d273dSizick SHA512ROUND(e, f, g, h, a, b, c, d, 4, w4); 725f66d273dSizick /*LINTED*/ 726f66d273dSizick w5 = LOAD_BIG_64(blk + 8 * 5); 727f66d273dSizick SHA512ROUND(d, e, f, g, h, a, b, c, 5, w5); 728f66d273dSizick /*LINTED*/ 729f66d273dSizick w6 = LOAD_BIG_64(blk + 8 * 6); 730f66d273dSizick SHA512ROUND(c, d, e, f, g, h, a, b, 6, w6); 731f66d273dSizick /*LINTED*/ 732f66d273dSizick w7 = LOAD_BIG_64(blk + 8 * 7); 733f66d273dSizick SHA512ROUND(b, c, d, e, f, g, h, a, 7, w7); 734f66d273dSizick /*LINTED*/ 735f66d273dSizick w8 = LOAD_BIG_64(blk + 8 * 8); 736f66d273dSizick SHA512ROUND(a, b, c, d, e, f, g, h, 8, w8); 737f66d273dSizick /*LINTED*/ 738f66d273dSizick w9 = LOAD_BIG_64(blk + 8 * 9); 739f66d273dSizick SHA512ROUND(h, a, b, c, d, e, f, g, 9, w9); 740f66d273dSizick /*LINTED*/ 741f66d273dSizick w10 = LOAD_BIG_64(blk + 8 * 10); 742f66d273dSizick SHA512ROUND(g, h, a, b, c, d, e, f, 10, w10); 743f66d273dSizick /*LINTED*/ 744f66d273dSizick w11 = LOAD_BIG_64(blk + 8 * 11); 745f66d273dSizick SHA512ROUND(f, g, h, a, b, c, d, e, 11, w11); 746f66d273dSizick /*LINTED*/ 747f66d273dSizick w12 = LOAD_BIG_64(blk + 8 * 12); 748f66d273dSizick SHA512ROUND(e, f, g, h, a, b, c, d, 12, w12); 749f66d273dSizick /*LINTED*/ 750f66d273dSizick w13 = LOAD_BIG_64(blk + 8 * 13); 751f66d273dSizick SHA512ROUND(d, e, f, g, h, a, b, c, 13, w13); 752f66d273dSizick /*LINTED*/ 753f66d273dSizick w14 = LOAD_BIG_64(blk + 8 * 14); 754f66d273dSizick SHA512ROUND(c, d, e, f, g, h, a, b, 14, w14); 755f66d273dSizick /*LINTED*/ 756f66d273dSizick w15 = LOAD_BIG_64(blk + 8 * 15); 757f66d273dSizick SHA512ROUND(b, c, d, e, f, g, h, a, 15, w15); 758f66d273dSizick 759f66d273dSizick #else 760f66d273dSizick 7617c478bd9Sstevel@tonic-gate w0 = LOAD_BIG_64(blk + 8 * 0); 7627c478bd9Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 0, w0); 7637c478bd9Sstevel@tonic-gate w1 = LOAD_BIG_64(blk + 8 * 1); 7647c478bd9Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 1, w1); 7657c478bd9Sstevel@tonic-gate w2 = LOAD_BIG_64(blk + 8 * 2); 7667c478bd9Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 2, w2); 7677c478bd9Sstevel@tonic-gate w3 = LOAD_BIG_64(blk + 8 * 3); 7687c478bd9Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 3, w3); 7697c478bd9Sstevel@tonic-gate w4 = LOAD_BIG_64(blk + 8 * 4); 7707c478bd9Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 4, w4); 7717c478bd9Sstevel@tonic-gate w5 = LOAD_BIG_64(blk + 8 * 5); 7727c478bd9Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 5, w5); 7737c478bd9Sstevel@tonic-gate w6 = LOAD_BIG_64(blk + 8 * 6); 7747c478bd9Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 6, w6); 7757c478bd9Sstevel@tonic-gate w7 = LOAD_BIG_64(blk + 8 * 7); 7767c478bd9Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 7, w7); 7777c478bd9Sstevel@tonic-gate w8 = LOAD_BIG_64(blk + 8 * 8); 7787c478bd9Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 8, w8); 7797c478bd9Sstevel@tonic-gate w9 = LOAD_BIG_64(blk + 8 * 9); 7807c478bd9Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 9, w9); 7817c478bd9Sstevel@tonic-gate w10 = LOAD_BIG_64(blk + 8 * 10); 7827c478bd9Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 10, w10); 7837c478bd9Sstevel@tonic-gate w11 = LOAD_BIG_64(blk + 8 * 11); 7847c478bd9Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 11, w11); 7857c478bd9Sstevel@tonic-gate w12 = LOAD_BIG_64(blk + 8 * 12); 7867c478bd9Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 12, w12); 7877c478bd9Sstevel@tonic-gate w13 = LOAD_BIG_64(blk + 8 * 13); 7887c478bd9Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 13, w13); 7897c478bd9Sstevel@tonic-gate w14 = LOAD_BIG_64(blk + 8 * 14); 7907c478bd9Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 14, w14); 7917c478bd9Sstevel@tonic-gate w15 = LOAD_BIG_64(blk + 8 * 15); 7927c478bd9Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 15, w15); 7937c478bd9Sstevel@tonic-gate 794f66d273dSizick #endif 795f66d273dSizick 7967c478bd9Sstevel@tonic-gate w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0; 7977c478bd9Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 16, w0); 7987c478bd9Sstevel@tonic-gate w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1; 7997c478bd9Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 17, w1); 8007c478bd9Sstevel@tonic-gate w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2; 8017c478bd9Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 18, w2); 8027c478bd9Sstevel@tonic-gate w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3; 8037c478bd9Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 19, w3); 8047c478bd9Sstevel@tonic-gate w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4; 8057c478bd9Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 20, w4); 8067c478bd9Sstevel@tonic-gate w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5; 8077c478bd9Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 21, w5); 8087c478bd9Sstevel@tonic-gate w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6; 8097c478bd9Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 22, w6); 8107c478bd9Sstevel@tonic-gate w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7; 8117c478bd9Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 23, w7); 8127c478bd9Sstevel@tonic-gate w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8; 8137c478bd9Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 24, w8); 8147c478bd9Sstevel@tonic-gate w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9; 8157c478bd9Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 25, w9); 8167c478bd9Sstevel@tonic-gate w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10; 8177c478bd9Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 26, w10); 8187c478bd9Sstevel@tonic-gate w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11; 8197c478bd9Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 27, w11); 8207c478bd9Sstevel@tonic-gate w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12; 8217c478bd9Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 28, w12); 8227c478bd9Sstevel@tonic-gate w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13; 8237c478bd9Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 29, w13); 8247c478bd9Sstevel@tonic-gate w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14; 8257c478bd9Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 30, w14); 8267c478bd9Sstevel@tonic-gate w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15; 8277c478bd9Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 31, w15); 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0; 8307c478bd9Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 32, w0); 8317c478bd9Sstevel@tonic-gate w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1; 8327c478bd9Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 33, w1); 8337c478bd9Sstevel@tonic-gate w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2; 8347c478bd9Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 34, w2); 8357c478bd9Sstevel@tonic-gate w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3; 8367c478bd9Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 35, w3); 8377c478bd9Sstevel@tonic-gate w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4; 8387c478bd9Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 36, w4); 8397c478bd9Sstevel@tonic-gate w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5; 8407c478bd9Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 37, w5); 8417c478bd9Sstevel@tonic-gate w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6; 8427c478bd9Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 38, w6); 8437c478bd9Sstevel@tonic-gate w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7; 8447c478bd9Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 39, w7); 8457c478bd9Sstevel@tonic-gate w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8; 8467c478bd9Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 40, w8); 8477c478bd9Sstevel@tonic-gate w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9; 8487c478bd9Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 41, w9); 8497c478bd9Sstevel@tonic-gate w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10; 8507c478bd9Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 42, w10); 8517c478bd9Sstevel@tonic-gate w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11; 8527c478bd9Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 43, w11); 8537c478bd9Sstevel@tonic-gate w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12; 8547c478bd9Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 44, w12); 8557c478bd9Sstevel@tonic-gate w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13; 8567c478bd9Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 45, w13); 8577c478bd9Sstevel@tonic-gate w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14; 8587c478bd9Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 46, w14); 8597c478bd9Sstevel@tonic-gate w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15; 8607c478bd9Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 47, w15); 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0; 8637c478bd9Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 48, w0); 8647c478bd9Sstevel@tonic-gate w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1; 8657c478bd9Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 49, w1); 8667c478bd9Sstevel@tonic-gate w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2; 8677c478bd9Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 50, w2); 8687c478bd9Sstevel@tonic-gate w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3; 8697c478bd9Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 51, w3); 8707c478bd9Sstevel@tonic-gate w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4; 8717c478bd9Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 52, w4); 8727c478bd9Sstevel@tonic-gate w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5; 8737c478bd9Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 53, w5); 8747c478bd9Sstevel@tonic-gate w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6; 8757c478bd9Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 54, w6); 8767c478bd9Sstevel@tonic-gate w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7; 8777c478bd9Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 55, w7); 8787c478bd9Sstevel@tonic-gate w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8; 8797c478bd9Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 56, w8); 8807c478bd9Sstevel@tonic-gate w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9; 8817c478bd9Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 57, w9); 8827c478bd9Sstevel@tonic-gate w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10; 8837c478bd9Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 58, w10); 8847c478bd9Sstevel@tonic-gate w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11; 8857c478bd9Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 59, w11); 8867c478bd9Sstevel@tonic-gate w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12; 8877c478bd9Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 60, w12); 8887c478bd9Sstevel@tonic-gate w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13; 8897c478bd9Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 61, w13); 8907c478bd9Sstevel@tonic-gate w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14; 8917c478bd9Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 62, w14); 8927c478bd9Sstevel@tonic-gate w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15; 8937c478bd9Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 63, w15); 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0; 8967c478bd9Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 64, w0); 8977c478bd9Sstevel@tonic-gate w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1; 8987c478bd9Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 65, w1); 8997c478bd9Sstevel@tonic-gate w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2; 9007c478bd9Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 66, w2); 9017c478bd9Sstevel@tonic-gate w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3; 9027c478bd9Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 67, w3); 9037c478bd9Sstevel@tonic-gate w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4; 9047c478bd9Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 68, w4); 9057c478bd9Sstevel@tonic-gate w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5; 9067c478bd9Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 69, w5); 9077c478bd9Sstevel@tonic-gate w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6; 9087c478bd9Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 70, w6); 9097c478bd9Sstevel@tonic-gate w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7; 9107c478bd9Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 71, w7); 9117c478bd9Sstevel@tonic-gate w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8; 9127c478bd9Sstevel@tonic-gate SHA512ROUND(a, b, c, d, e, f, g, h, 72, w8); 9137c478bd9Sstevel@tonic-gate w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9; 9147c478bd9Sstevel@tonic-gate SHA512ROUND(h, a, b, c, d, e, f, g, 73, w9); 9157c478bd9Sstevel@tonic-gate w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10; 9167c478bd9Sstevel@tonic-gate SHA512ROUND(g, h, a, b, c, d, e, f, 74, w10); 9177c478bd9Sstevel@tonic-gate w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11; 9187c478bd9Sstevel@tonic-gate SHA512ROUND(f, g, h, a, b, c, d, e, 75, w11); 9197c478bd9Sstevel@tonic-gate w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12; 9207c478bd9Sstevel@tonic-gate SHA512ROUND(e, f, g, h, a, b, c, d, 76, w12); 9217c478bd9Sstevel@tonic-gate w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13; 9227c478bd9Sstevel@tonic-gate SHA512ROUND(d, e, f, g, h, a, b, c, 77, w13); 9237c478bd9Sstevel@tonic-gate w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14; 9247c478bd9Sstevel@tonic-gate SHA512ROUND(c, d, e, f, g, h, a, b, 78, w14); 9257c478bd9Sstevel@tonic-gate w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15; 9267c478bd9Sstevel@tonic-gate SHA512ROUND(b, c, d, e, f, g, h, a, 79, w15); 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate ctx->state.s64[0] += a; 9297c478bd9Sstevel@tonic-gate ctx->state.s64[1] += b; 9307c478bd9Sstevel@tonic-gate ctx->state.s64[2] += c; 9317c478bd9Sstevel@tonic-gate ctx->state.s64[3] += d; 9327c478bd9Sstevel@tonic-gate ctx->state.s64[4] += e; 9337c478bd9Sstevel@tonic-gate ctx->state.s64[5] += f; 9347c478bd9Sstevel@tonic-gate ctx->state.s64[6] += g; 9357c478bd9Sstevel@tonic-gate ctx->state.s64[7] += h; 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate /* 9417c478bd9Sstevel@tonic-gate * devpro compiler optimization: 9427c478bd9Sstevel@tonic-gate * 9437c478bd9Sstevel@tonic-gate * the compiler can generate better code if it knows that `input' and 9447c478bd9Sstevel@tonic-gate * `output' do not point to the same source. there is no portable 9457c478bd9Sstevel@tonic-gate * way to tell the compiler this, but the sun compiler recognizes the 9467c478bd9Sstevel@tonic-gate * `_Restrict' keyword to indicate this condition. use it if possible. 9477c478bd9Sstevel@tonic-gate */ 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate #ifdef __RESTRICT 9507c478bd9Sstevel@tonic-gate #define restrict _Restrict 9517c478bd9Sstevel@tonic-gate #else 9527c478bd9Sstevel@tonic-gate #define restrict /* nothing */ 9537c478bd9Sstevel@tonic-gate #endif 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate /* 9567c478bd9Sstevel@tonic-gate * Encode() 9577c478bd9Sstevel@tonic-gate * 9587c478bd9Sstevel@tonic-gate * purpose: to convert a list of numbers from little endian to big endian 9597c478bd9Sstevel@tonic-gate * input: uint8_t * : place to store the converted big endian numbers 9607c478bd9Sstevel@tonic-gate * uint32_t * : place to get numbers to convert from 9617c478bd9Sstevel@tonic-gate * size_t : the length of the input in bytes 9627c478bd9Sstevel@tonic-gate * output: void 9637c478bd9Sstevel@tonic-gate */ 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate static void 9667c478bd9Sstevel@tonic-gate Encode(uint8_t *restrict output, uint32_t *restrict input, size_t len) 9677c478bd9Sstevel@tonic-gate { 9687c478bd9Sstevel@tonic-gate size_t i, j; 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate #if defined(__sparc) 9717c478bd9Sstevel@tonic-gate if (IS_P2ALIGNED(output, sizeof (uint32_t))) { 9727c478bd9Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4) { 9737c478bd9Sstevel@tonic-gate /* LINTED: pointer alignment */ 9747c478bd9Sstevel@tonic-gate *((uint32_t *)(output + j)) = input[i]; 9757c478bd9Sstevel@tonic-gate } 9767c478bd9Sstevel@tonic-gate } else { 9777c478bd9Sstevel@tonic-gate #endif /* little endian -- will work on big endian, but slowly */ 9787c478bd9Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4) { 9797c478bd9Sstevel@tonic-gate output[j] = (input[i] >> 24) & 0xff; 9807c478bd9Sstevel@tonic-gate output[j + 1] = (input[i] >> 16) & 0xff; 9817c478bd9Sstevel@tonic-gate output[j + 2] = (input[i] >> 8) & 0xff; 9827c478bd9Sstevel@tonic-gate output[j + 3] = input[i] & 0xff; 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate #if defined(__sparc) 9857c478bd9Sstevel@tonic-gate } 9867c478bd9Sstevel@tonic-gate #endif 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate static void 9907c478bd9Sstevel@tonic-gate Encode64(uint8_t *restrict output, uint64_t *restrict input, size_t len) 9917c478bd9Sstevel@tonic-gate { 9927c478bd9Sstevel@tonic-gate size_t i, j; 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate #if defined(__sparc) 9957c478bd9Sstevel@tonic-gate if (IS_P2ALIGNED(output, sizeof (uint64_t))) { 9967c478bd9Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 8) { 9977c478bd9Sstevel@tonic-gate /* LINTED: pointer alignment */ 9987c478bd9Sstevel@tonic-gate *((uint64_t *)(output + j)) = input[i]; 9997c478bd9Sstevel@tonic-gate } 10007c478bd9Sstevel@tonic-gate } else { 10017c478bd9Sstevel@tonic-gate #endif /* little endian -- will work on big endian, but slowly */ 10027c478bd9Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 8) { 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate output[j] = (input[i] >> 56) & 0xff; 10057c478bd9Sstevel@tonic-gate output[j + 1] = (input[i] >> 48) & 0xff; 10067c478bd9Sstevel@tonic-gate output[j + 2] = (input[i] >> 40) & 0xff; 10077c478bd9Sstevel@tonic-gate output[j + 3] = (input[i] >> 32) & 0xff; 10087c478bd9Sstevel@tonic-gate output[j + 4] = (input[i] >> 24) & 0xff; 10097c478bd9Sstevel@tonic-gate output[j + 5] = (input[i] >> 16) & 0xff; 10107c478bd9Sstevel@tonic-gate output[j + 6] = (input[i] >> 8) & 0xff; 10117c478bd9Sstevel@tonic-gate output[j + 7] = input[i] & 0xff; 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate #if defined(__sparc) 10147c478bd9Sstevel@tonic-gate } 10157c478bd9Sstevel@tonic-gate #endif 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate #ifdef _KERNEL 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate /* 10227c478bd9Sstevel@tonic-gate * KCF software provider control entry points. 10237c478bd9Sstevel@tonic-gate */ 10247c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10257c478bd9Sstevel@tonic-gate static void 10267c478bd9Sstevel@tonic-gate sha2_provider_status(crypto_provider_handle_t provider, uint_t *status) 10277c478bd9Sstevel@tonic-gate { 10287c478bd9Sstevel@tonic-gate *status = CRYPTO_PROVIDER_READY; 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate /* 10327c478bd9Sstevel@tonic-gate * KCF software provider digest entry points. 10337c478bd9Sstevel@tonic-gate */ 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate static int 10367c478bd9Sstevel@tonic-gate sha2_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 10377c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 10387c478bd9Sstevel@tonic-gate { 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* 10417c478bd9Sstevel@tonic-gate * Allocate and initialize SHA2 context. 10427c478bd9Sstevel@tonic-gate */ 10437c478bd9Sstevel@tonic-gate ctx->cc_provider_private = kmem_alloc(sizeof (sha2_ctx_t), 10447c478bd9Sstevel@tonic-gate crypto_kmflag(req)); 10457c478bd9Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 10467c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate PROV_SHA2_CTX(ctx)->sc_mech_type = mechanism->cm_type; 10497c478bd9Sstevel@tonic-gate SHA2Init(mechanism->cm_type, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx); 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate /* 10557c478bd9Sstevel@tonic-gate * Helper SHA2 digest update function for uio data. 10567c478bd9Sstevel@tonic-gate */ 10577c478bd9Sstevel@tonic-gate static int 10587c478bd9Sstevel@tonic-gate sha2_digest_update_uio(SHA2_CTX *sha2_ctx, crypto_data_t *data) 10597c478bd9Sstevel@tonic-gate { 10607c478bd9Sstevel@tonic-gate off_t offset = data->cd_offset; 10617c478bd9Sstevel@tonic-gate size_t length = data->cd_length; 10627c478bd9Sstevel@tonic-gate uint_t vec_idx; 10637c478bd9Sstevel@tonic-gate size_t cur_len; 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate /* we support only kernel buffer */ 10667c478bd9Sstevel@tonic-gate if (data->cd_uio->uio_segflg != UIO_SYSSPACE) 10677c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate /* 10707c478bd9Sstevel@tonic-gate * Jump to the first iovec containing data to be 10717c478bd9Sstevel@tonic-gate * digested. 10727c478bd9Sstevel@tonic-gate */ 10737c478bd9Sstevel@tonic-gate for (vec_idx = 0; vec_idx < data->cd_uio->uio_iovcnt && 10747c478bd9Sstevel@tonic-gate offset >= data->cd_uio->uio_iov[vec_idx].iov_len; 10757c478bd9Sstevel@tonic-gate offset -= data->cd_uio->uio_iov[vec_idx++].iov_len); 10767c478bd9Sstevel@tonic-gate if (vec_idx == data->cd_uio->uio_iovcnt) { 10777c478bd9Sstevel@tonic-gate /* 10787c478bd9Sstevel@tonic-gate * The caller specified an offset that is larger than the 10797c478bd9Sstevel@tonic-gate * total size of the buffers it provided. 10807c478bd9Sstevel@tonic-gate */ 10817c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate /* 10857c478bd9Sstevel@tonic-gate * Now do the digesting on the iovecs. 10867c478bd9Sstevel@tonic-gate */ 10877c478bd9Sstevel@tonic-gate while (vec_idx < data->cd_uio->uio_iovcnt && length > 0) { 10887c478bd9Sstevel@tonic-gate cur_len = MIN(data->cd_uio->uio_iov[vec_idx].iov_len - 10897c478bd9Sstevel@tonic-gate offset, length); 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate SHA2Update(sha2_ctx, (uint8_t *)data->cd_uio-> 10927c478bd9Sstevel@tonic-gate uio_iov[vec_idx].iov_base + offset, cur_len); 10937c478bd9Sstevel@tonic-gate length -= cur_len; 10947c478bd9Sstevel@tonic-gate vec_idx++; 10957c478bd9Sstevel@tonic-gate offset = 0; 10967c478bd9Sstevel@tonic-gate } 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate if (vec_idx == data->cd_uio->uio_iovcnt && length > 0) { 10997c478bd9Sstevel@tonic-gate /* 11007c478bd9Sstevel@tonic-gate * The end of the specified iovec's was reached but 11017c478bd9Sstevel@tonic-gate * the length requested could not be processed, i.e. 11027c478bd9Sstevel@tonic-gate * The caller requested to digest more data than it provided. 11037c478bd9Sstevel@tonic-gate */ 11047c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate /* 11117c478bd9Sstevel@tonic-gate * Helper SHA2 digest final function for uio data. 11127c478bd9Sstevel@tonic-gate * digest_len is the length of the desired digest. If digest_len 11137c478bd9Sstevel@tonic-gate * is smaller than the default SHA2 digest length, the caller 11147c478bd9Sstevel@tonic-gate * must pass a scratch buffer, digest_scratch, which must 11157c478bd9Sstevel@tonic-gate * be at least the algorithm's digest length bytes. 11167c478bd9Sstevel@tonic-gate */ 11177c478bd9Sstevel@tonic-gate static int 11187c478bd9Sstevel@tonic-gate sha2_digest_final_uio(SHA2_CTX *sha2_ctx, crypto_data_t *digest, 11197c478bd9Sstevel@tonic-gate ulong_t digest_len, uchar_t *digest_scratch) 11207c478bd9Sstevel@tonic-gate { 11217c478bd9Sstevel@tonic-gate off_t offset = digest->cd_offset; 11227c478bd9Sstevel@tonic-gate uint_t vec_idx; 11237c478bd9Sstevel@tonic-gate 11247c478bd9Sstevel@tonic-gate /* we support only kernel buffer */ 11257c478bd9Sstevel@tonic-gate if (digest->cd_uio->uio_segflg != UIO_SYSSPACE) 11267c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate /* 11297c478bd9Sstevel@tonic-gate * Jump to the first iovec containing ptr to the digest to 11307c478bd9Sstevel@tonic-gate * be returned. 11317c478bd9Sstevel@tonic-gate */ 11327c478bd9Sstevel@tonic-gate for (vec_idx = 0; offset >= digest->cd_uio->uio_iov[vec_idx].iov_len && 11337c478bd9Sstevel@tonic-gate vec_idx < digest->cd_uio->uio_iovcnt; 11347c478bd9Sstevel@tonic-gate offset -= digest->cd_uio->uio_iov[vec_idx++].iov_len); 11357c478bd9Sstevel@tonic-gate if (vec_idx == digest->cd_uio->uio_iovcnt) { 11367c478bd9Sstevel@tonic-gate /* 11377c478bd9Sstevel@tonic-gate * The caller specified an offset that is 11387c478bd9Sstevel@tonic-gate * larger than the total size of the buffers 11397c478bd9Sstevel@tonic-gate * it provided. 11407c478bd9Sstevel@tonic-gate */ 11417c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate if (offset + digest_len <= 11457c478bd9Sstevel@tonic-gate digest->cd_uio->uio_iov[vec_idx].iov_len) { 11467c478bd9Sstevel@tonic-gate /* 11477c478bd9Sstevel@tonic-gate * The computed SHA2 digest will fit in the current 11487c478bd9Sstevel@tonic-gate * iovec. 11497c478bd9Sstevel@tonic-gate */ 11507c478bd9Sstevel@tonic-gate if (((sha2_ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) && 11517c478bd9Sstevel@tonic-gate (digest_len != SHA256_DIGEST_LENGTH)) || 11527c478bd9Sstevel@tonic-gate ((sha2_ctx->algotype > SHA256_HMAC_GEN_MECH_INFO_TYPE) && 11537c478bd9Sstevel@tonic-gate (digest_len != SHA512_DIGEST_LENGTH))) { 11547c478bd9Sstevel@tonic-gate /* 11557c478bd9Sstevel@tonic-gate * The caller requested a short digest. Digest 11567c478bd9Sstevel@tonic-gate * into a scratch buffer and return to 11577c478bd9Sstevel@tonic-gate * the user only what was requested. 11587c478bd9Sstevel@tonic-gate */ 11597c478bd9Sstevel@tonic-gate SHA2Final(digest_scratch, sha2_ctx); 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate bcopy(digest_scratch, (uchar_t *)digest-> 11627c478bd9Sstevel@tonic-gate cd_uio->uio_iov[vec_idx].iov_base + offset, 11637c478bd9Sstevel@tonic-gate digest_len); 11647c478bd9Sstevel@tonic-gate } else { 11657c478bd9Sstevel@tonic-gate SHA2Final((uchar_t *)digest-> 11667c478bd9Sstevel@tonic-gate cd_uio->uio_iov[vec_idx].iov_base + offset, 11677c478bd9Sstevel@tonic-gate sha2_ctx); 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate } else { 11717c478bd9Sstevel@tonic-gate /* 11727c478bd9Sstevel@tonic-gate * The computed digest will be crossing one or more iovec's. 11737c478bd9Sstevel@tonic-gate * This is bad performance-wise but we need to support it. 11747c478bd9Sstevel@tonic-gate * Allocate a small scratch buffer on the stack and 11757c478bd9Sstevel@tonic-gate * copy it piece meal to the specified digest iovec's. 11767c478bd9Sstevel@tonic-gate */ 11777c478bd9Sstevel@tonic-gate uchar_t digest_tmp[SHA512_DIGEST_LENGTH]; 11787c478bd9Sstevel@tonic-gate off_t scratch_offset = 0; 11797c478bd9Sstevel@tonic-gate size_t length = digest_len; 11807c478bd9Sstevel@tonic-gate size_t cur_len; 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate SHA2Final(digest_tmp, sha2_ctx); 11837c478bd9Sstevel@tonic-gate 11847c478bd9Sstevel@tonic-gate while (vec_idx < digest->cd_uio->uio_iovcnt && length > 0) { 11857c478bd9Sstevel@tonic-gate cur_len = 11867c478bd9Sstevel@tonic-gate MIN(digest->cd_uio->uio_iov[vec_idx].iov_len - 11877c478bd9Sstevel@tonic-gate offset, length); 11887c478bd9Sstevel@tonic-gate bcopy(digest_tmp + scratch_offset, 11897c478bd9Sstevel@tonic-gate digest->cd_uio->uio_iov[vec_idx].iov_base + offset, 11907c478bd9Sstevel@tonic-gate cur_len); 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate length -= cur_len; 11937c478bd9Sstevel@tonic-gate vec_idx++; 11947c478bd9Sstevel@tonic-gate scratch_offset += cur_len; 11957c478bd9Sstevel@tonic-gate offset = 0; 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate if (vec_idx == digest->cd_uio->uio_iovcnt && length > 0) { 11997c478bd9Sstevel@tonic-gate /* 12007c478bd9Sstevel@tonic-gate * The end of the specified iovec's was reached but 12017c478bd9Sstevel@tonic-gate * the length requested could not be processed, i.e. 12027c478bd9Sstevel@tonic-gate * The caller requested to digest more data than it 12037c478bd9Sstevel@tonic-gate * provided. 12047c478bd9Sstevel@tonic-gate */ 12057c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 12067c478bd9Sstevel@tonic-gate } 12077c478bd9Sstevel@tonic-gate } 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate /* 12137c478bd9Sstevel@tonic-gate * Helper SHA2 digest update for mblk's. 12147c478bd9Sstevel@tonic-gate */ 12157c478bd9Sstevel@tonic-gate static int 12167c478bd9Sstevel@tonic-gate sha2_digest_update_mblk(SHA2_CTX *sha2_ctx, crypto_data_t *data) 12177c478bd9Sstevel@tonic-gate { 12187c478bd9Sstevel@tonic-gate off_t offset = data->cd_offset; 12197c478bd9Sstevel@tonic-gate size_t length = data->cd_length; 12207c478bd9Sstevel@tonic-gate mblk_t *mp; 12217c478bd9Sstevel@tonic-gate size_t cur_len; 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate /* 12247c478bd9Sstevel@tonic-gate * Jump to the first mblk_t containing data to be digested. 12257c478bd9Sstevel@tonic-gate */ 12267c478bd9Sstevel@tonic-gate for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp); 12277c478bd9Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 12287c478bd9Sstevel@tonic-gate if (mp == NULL) { 12297c478bd9Sstevel@tonic-gate /* 12307c478bd9Sstevel@tonic-gate * The caller specified an offset that is larger than the 12317c478bd9Sstevel@tonic-gate * total size of the buffers it provided. 12327c478bd9Sstevel@tonic-gate */ 12337c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 12347c478bd9Sstevel@tonic-gate } 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate /* 12377c478bd9Sstevel@tonic-gate * Now do the digesting on the mblk chain. 12387c478bd9Sstevel@tonic-gate */ 12397c478bd9Sstevel@tonic-gate while (mp != NULL && length > 0) { 12407c478bd9Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 12417c478bd9Sstevel@tonic-gate SHA2Update(sha2_ctx, mp->b_rptr + offset, cur_len); 12427c478bd9Sstevel@tonic-gate length -= cur_len; 12437c478bd9Sstevel@tonic-gate offset = 0; 12447c478bd9Sstevel@tonic-gate mp = mp->b_cont; 12457c478bd9Sstevel@tonic-gate } 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate if (mp == NULL && length > 0) { 12487c478bd9Sstevel@tonic-gate /* 12497c478bd9Sstevel@tonic-gate * The end of the mblk was reached but the length requested 12507c478bd9Sstevel@tonic-gate * could not be processed, i.e. The caller requested 12517c478bd9Sstevel@tonic-gate * to digest more data than it provided. 12527c478bd9Sstevel@tonic-gate */ 12537c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate 12597c478bd9Sstevel@tonic-gate /* 12607c478bd9Sstevel@tonic-gate * Helper SHA2 digest final for mblk's. 12617c478bd9Sstevel@tonic-gate * digest_len is the length of the desired digest. If digest_len 12627c478bd9Sstevel@tonic-gate * is smaller than the default SHA2 digest length, the caller 12637c478bd9Sstevel@tonic-gate * must pass a scratch buffer, digest_scratch, which must 12647c478bd9Sstevel@tonic-gate * be at least the algorithm's digest length bytes. 12657c478bd9Sstevel@tonic-gate */ 12667c478bd9Sstevel@tonic-gate static int 12677c478bd9Sstevel@tonic-gate sha2_digest_final_mblk(SHA2_CTX *sha2_ctx, crypto_data_t *digest, 12687c478bd9Sstevel@tonic-gate ulong_t digest_len, uchar_t *digest_scratch) 12697c478bd9Sstevel@tonic-gate { 12707c478bd9Sstevel@tonic-gate off_t offset = digest->cd_offset; 12717c478bd9Sstevel@tonic-gate mblk_t *mp; 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate /* 12747c478bd9Sstevel@tonic-gate * Jump to the first mblk_t that will be used to store the digest. 12757c478bd9Sstevel@tonic-gate */ 12767c478bd9Sstevel@tonic-gate for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp); 12777c478bd9Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 12787c478bd9Sstevel@tonic-gate if (mp == NULL) { 12797c478bd9Sstevel@tonic-gate /* 12807c478bd9Sstevel@tonic-gate * The caller specified an offset that is larger than the 12817c478bd9Sstevel@tonic-gate * total size of the buffers it provided. 12827c478bd9Sstevel@tonic-gate */ 12837c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 12847c478bd9Sstevel@tonic-gate } 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate if (offset + digest_len <= MBLKL(mp)) { 12877c478bd9Sstevel@tonic-gate /* 12887c478bd9Sstevel@tonic-gate * The computed SHA2 digest will fit in the current mblk. 12897c478bd9Sstevel@tonic-gate * Do the SHA2Final() in-place. 12907c478bd9Sstevel@tonic-gate */ 12917c478bd9Sstevel@tonic-gate if (((sha2_ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) && 12927c478bd9Sstevel@tonic-gate (digest_len != SHA256_DIGEST_LENGTH)) || 12937c478bd9Sstevel@tonic-gate ((sha2_ctx->algotype > SHA256_HMAC_GEN_MECH_INFO_TYPE) && 12947c478bd9Sstevel@tonic-gate (digest_len != SHA512_DIGEST_LENGTH))) { 12957c478bd9Sstevel@tonic-gate /* 12967c478bd9Sstevel@tonic-gate * The caller requested a short digest. Digest 12977c478bd9Sstevel@tonic-gate * into a scratch buffer and return to 12987c478bd9Sstevel@tonic-gate * the user only what was requested. 12997c478bd9Sstevel@tonic-gate */ 13007c478bd9Sstevel@tonic-gate SHA2Final(digest_scratch, sha2_ctx); 13017c478bd9Sstevel@tonic-gate bcopy(digest_scratch, mp->b_rptr + offset, digest_len); 13027c478bd9Sstevel@tonic-gate } else { 13037c478bd9Sstevel@tonic-gate SHA2Final(mp->b_rptr + offset, sha2_ctx); 13047c478bd9Sstevel@tonic-gate } 13057c478bd9Sstevel@tonic-gate } else { 13067c478bd9Sstevel@tonic-gate /* 13077c478bd9Sstevel@tonic-gate * The computed digest will be crossing one or more mblk's. 13087c478bd9Sstevel@tonic-gate * This is bad performance-wise but we need to support it. 13097c478bd9Sstevel@tonic-gate * Allocate a small scratch buffer on the stack and 13107c478bd9Sstevel@tonic-gate * copy it piece meal to the specified digest iovec's. 13117c478bd9Sstevel@tonic-gate */ 13127c478bd9Sstevel@tonic-gate uchar_t digest_tmp[SHA512_DIGEST_LENGTH]; 13137c478bd9Sstevel@tonic-gate off_t scratch_offset = 0; 13147c478bd9Sstevel@tonic-gate size_t length = digest_len; 13157c478bd9Sstevel@tonic-gate size_t cur_len; 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate SHA2Final(digest_tmp, sha2_ctx); 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate while (mp != NULL && length > 0) { 13207c478bd9Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 13217c478bd9Sstevel@tonic-gate bcopy(digest_tmp + scratch_offset, 13227c478bd9Sstevel@tonic-gate mp->b_rptr + offset, cur_len); 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate length -= cur_len; 13257c478bd9Sstevel@tonic-gate mp = mp->b_cont; 13267c478bd9Sstevel@tonic-gate scratch_offset += cur_len; 13277c478bd9Sstevel@tonic-gate offset = 0; 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate if (mp == NULL && length > 0) { 13317c478bd9Sstevel@tonic-gate /* 13327c478bd9Sstevel@tonic-gate * The end of the specified mblk was reached but 13337c478bd9Sstevel@tonic-gate * the length requested could not be processed, i.e. 13347c478bd9Sstevel@tonic-gate * The caller requested to digest more data than it 13357c478bd9Sstevel@tonic-gate * provided. 13367c478bd9Sstevel@tonic-gate */ 13377c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate } 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate /* ARGSUSED */ 13457c478bd9Sstevel@tonic-gate static int 13467c478bd9Sstevel@tonic-gate sha2_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest, 13477c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 13487c478bd9Sstevel@tonic-gate { 13497c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 13507c478bd9Sstevel@tonic-gate uint_t sha_digest_len; 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate switch (PROV_SHA2_CTX(ctx)->sc_mech_type) { 13557c478bd9Sstevel@tonic-gate case SHA256_MECH_INFO_TYPE: 13567c478bd9Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 13577c478bd9Sstevel@tonic-gate break; 13587c478bd9Sstevel@tonic-gate case SHA384_MECH_INFO_TYPE: 13597c478bd9Sstevel@tonic-gate sha_digest_len = SHA384_DIGEST_LENGTH; 13607c478bd9Sstevel@tonic-gate break; 13617c478bd9Sstevel@tonic-gate case SHA512_MECH_INFO_TYPE: 13627c478bd9Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 13637c478bd9Sstevel@tonic-gate break; 13647c478bd9Sstevel@tonic-gate default: 13657c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 13667c478bd9Sstevel@tonic-gate } 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate /* 13697c478bd9Sstevel@tonic-gate * We need to just return the length needed to store the output. 13707c478bd9Sstevel@tonic-gate * We should not destroy the context for the following cases. 13717c478bd9Sstevel@tonic-gate */ 13727c478bd9Sstevel@tonic-gate if ((digest->cd_length == 0) || 13737c478bd9Sstevel@tonic-gate (digest->cd_length < sha_digest_len)) { 13747c478bd9Sstevel@tonic-gate digest->cd_length = sha_digest_len; 13757c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 13767c478bd9Sstevel@tonic-gate } 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate /* 13797c478bd9Sstevel@tonic-gate * Do the SHA2 update on the specified input data. 13807c478bd9Sstevel@tonic-gate */ 13817c478bd9Sstevel@tonic-gate switch (data->cd_format) { 13827c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 13837c478bd9Sstevel@tonic-gate SHA2Update(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 13847c478bd9Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 13857c478bd9Sstevel@tonic-gate data->cd_length); 13867c478bd9Sstevel@tonic-gate break; 13877c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 13887c478bd9Sstevel@tonic-gate ret = sha2_digest_update_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 13897c478bd9Sstevel@tonic-gate data); 13907c478bd9Sstevel@tonic-gate break; 13917c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 13927c478bd9Sstevel@tonic-gate ret = sha2_digest_update_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 13937c478bd9Sstevel@tonic-gate data); 13947c478bd9Sstevel@tonic-gate break; 13957c478bd9Sstevel@tonic-gate default: 13967c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 13977c478bd9Sstevel@tonic-gate } 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 14007c478bd9Sstevel@tonic-gate /* the update failed, free context and bail */ 14017c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t)); 14027c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 14037c478bd9Sstevel@tonic-gate digest->cd_length = 0; 14047c478bd9Sstevel@tonic-gate return (ret); 14057c478bd9Sstevel@tonic-gate } 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate /* 14087c478bd9Sstevel@tonic-gate * Do a SHA2 final, must be done separately since the digest 14097c478bd9Sstevel@tonic-gate * type can be different than the input data type. 14107c478bd9Sstevel@tonic-gate */ 14117c478bd9Sstevel@tonic-gate switch (digest->cd_format) { 14127c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 14137c478bd9Sstevel@tonic-gate SHA2Final((unsigned char *)digest->cd_raw.iov_base + 14147c478bd9Sstevel@tonic-gate digest->cd_offset, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx); 14157c478bd9Sstevel@tonic-gate break; 14167c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 14177c478bd9Sstevel@tonic-gate ret = sha2_digest_final_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 14187c478bd9Sstevel@tonic-gate digest, sha_digest_len, NULL); 14197c478bd9Sstevel@tonic-gate break; 14207c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 14217c478bd9Sstevel@tonic-gate ret = sha2_digest_final_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 14227c478bd9Sstevel@tonic-gate digest, sha_digest_len, NULL); 14237c478bd9Sstevel@tonic-gate break; 14247c478bd9Sstevel@tonic-gate default: 14257c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate /* all done, free context and return */ 14297c478bd9Sstevel@tonic-gate 1430f66d273dSizick if (ret == CRYPTO_SUCCESS) 14317c478bd9Sstevel@tonic-gate digest->cd_length = sha_digest_len; 1432f66d273dSizick else 14337c478bd9Sstevel@tonic-gate digest->cd_length = 0; 14347c478bd9Sstevel@tonic-gate 14357c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t)); 14367c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 14377c478bd9Sstevel@tonic-gate return (ret); 14387c478bd9Sstevel@tonic-gate } 14397c478bd9Sstevel@tonic-gate 14407c478bd9Sstevel@tonic-gate /* ARGSUSED */ 14417c478bd9Sstevel@tonic-gate static int 14427c478bd9Sstevel@tonic-gate sha2_digest_update(crypto_ctx_t *ctx, crypto_data_t *data, 14437c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 14447c478bd9Sstevel@tonic-gate { 14457c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate /* 14507c478bd9Sstevel@tonic-gate * Do the SHA2 update on the specified input data. 14517c478bd9Sstevel@tonic-gate */ 14527c478bd9Sstevel@tonic-gate switch (data->cd_format) { 14537c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 14547c478bd9Sstevel@tonic-gate SHA2Update(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 14557c478bd9Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 14567c478bd9Sstevel@tonic-gate data->cd_length); 14577c478bd9Sstevel@tonic-gate break; 14587c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 14597c478bd9Sstevel@tonic-gate ret = sha2_digest_update_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 14607c478bd9Sstevel@tonic-gate data); 14617c478bd9Sstevel@tonic-gate break; 14627c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 14637c478bd9Sstevel@tonic-gate ret = sha2_digest_update_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 14647c478bd9Sstevel@tonic-gate data); 14657c478bd9Sstevel@tonic-gate break; 14667c478bd9Sstevel@tonic-gate default: 14677c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 14687c478bd9Sstevel@tonic-gate } 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate return (ret); 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate /* ARGSUSED */ 14747c478bd9Sstevel@tonic-gate static int 14757c478bd9Sstevel@tonic-gate sha2_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest, 14767c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 14777c478bd9Sstevel@tonic-gate { 14787c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 14797c478bd9Sstevel@tonic-gate uint_t sha_digest_len; 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 14827c478bd9Sstevel@tonic-gate 14837c478bd9Sstevel@tonic-gate switch (PROV_SHA2_CTX(ctx)->sc_mech_type) { 14847c478bd9Sstevel@tonic-gate case SHA256_MECH_INFO_TYPE: 14857c478bd9Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 14867c478bd9Sstevel@tonic-gate break; 14877c478bd9Sstevel@tonic-gate case SHA384_MECH_INFO_TYPE: 14887c478bd9Sstevel@tonic-gate sha_digest_len = SHA384_DIGEST_LENGTH; 14897c478bd9Sstevel@tonic-gate break; 14907c478bd9Sstevel@tonic-gate case SHA512_MECH_INFO_TYPE: 14917c478bd9Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 14927c478bd9Sstevel@tonic-gate break; 14937c478bd9Sstevel@tonic-gate default: 14947c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 14957c478bd9Sstevel@tonic-gate } 14967c478bd9Sstevel@tonic-gate 14977c478bd9Sstevel@tonic-gate /* 14987c478bd9Sstevel@tonic-gate * We need to just return the length needed to store the output. 14997c478bd9Sstevel@tonic-gate * We should not destroy the context for the following cases. 15007c478bd9Sstevel@tonic-gate */ 15017c478bd9Sstevel@tonic-gate if ((digest->cd_length == 0) || 15027c478bd9Sstevel@tonic-gate (digest->cd_length < sha_digest_len)) { 15037c478bd9Sstevel@tonic-gate digest->cd_length = sha_digest_len; 15047c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 15057c478bd9Sstevel@tonic-gate } 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate /* 15087c478bd9Sstevel@tonic-gate * Do a SHA2 final. 15097c478bd9Sstevel@tonic-gate */ 15107c478bd9Sstevel@tonic-gate switch (digest->cd_format) { 15117c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 15127c478bd9Sstevel@tonic-gate SHA2Final((unsigned char *)digest->cd_raw.iov_base + 15137c478bd9Sstevel@tonic-gate digest->cd_offset, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx); 15147c478bd9Sstevel@tonic-gate break; 15157c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 15167c478bd9Sstevel@tonic-gate ret = sha2_digest_final_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 15177c478bd9Sstevel@tonic-gate digest, sha_digest_len, NULL); 15187c478bd9Sstevel@tonic-gate break; 15197c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 15207c478bd9Sstevel@tonic-gate ret = sha2_digest_final_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx, 15217c478bd9Sstevel@tonic-gate digest, sha_digest_len, NULL); 15227c478bd9Sstevel@tonic-gate break; 15237c478bd9Sstevel@tonic-gate default: 15247c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 15257c478bd9Sstevel@tonic-gate } 15267c478bd9Sstevel@tonic-gate 15277c478bd9Sstevel@tonic-gate /* all done, free context and return */ 15287c478bd9Sstevel@tonic-gate 1529f66d273dSizick if (ret == CRYPTO_SUCCESS) 15307c478bd9Sstevel@tonic-gate digest->cd_length = sha_digest_len; 1531f66d273dSizick else 15327c478bd9Sstevel@tonic-gate digest->cd_length = 0; 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t)); 15357c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate return (ret); 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate /* ARGSUSED */ 15417c478bd9Sstevel@tonic-gate static int 15427c478bd9Sstevel@tonic-gate sha2_digest_atomic(crypto_provider_handle_t provider, 15437c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 15447c478bd9Sstevel@tonic-gate crypto_data_t *data, crypto_data_t *digest, 15457c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 15467c478bd9Sstevel@tonic-gate { 15477c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 15487c478bd9Sstevel@tonic-gate SHA2_CTX sha2_ctx; 15497c478bd9Sstevel@tonic-gate uint32_t sha_digest_len; 15507c478bd9Sstevel@tonic-gate 15517c478bd9Sstevel@tonic-gate /* 15527c478bd9Sstevel@tonic-gate * Do the SHA inits. 15537c478bd9Sstevel@tonic-gate */ 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate SHA2Init(mechanism->cm_type, &sha2_ctx); 15567c478bd9Sstevel@tonic-gate 15577c478bd9Sstevel@tonic-gate switch (data->cd_format) { 15587c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 15597c478bd9Sstevel@tonic-gate SHA2Update(&sha2_ctx, (uint8_t *)data-> 15607c478bd9Sstevel@tonic-gate cd_raw.iov_base + data->cd_offset, data->cd_length); 15617c478bd9Sstevel@tonic-gate break; 15627c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 15637c478bd9Sstevel@tonic-gate ret = sha2_digest_update_uio(&sha2_ctx, data); 15647c478bd9Sstevel@tonic-gate break; 15657c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 15667c478bd9Sstevel@tonic-gate ret = sha2_digest_update_mblk(&sha2_ctx, data); 15677c478bd9Sstevel@tonic-gate break; 15687c478bd9Sstevel@tonic-gate default: 15697c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 15707c478bd9Sstevel@tonic-gate } 15717c478bd9Sstevel@tonic-gate 15727c478bd9Sstevel@tonic-gate /* 15737c478bd9Sstevel@tonic-gate * Do the SHA updates on the specified input data. 15747c478bd9Sstevel@tonic-gate */ 15757c478bd9Sstevel@tonic-gate 15767c478bd9Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 15777c478bd9Sstevel@tonic-gate /* the update failed, bail */ 15787c478bd9Sstevel@tonic-gate digest->cd_length = 0; 15797c478bd9Sstevel@tonic-gate return (ret); 15807c478bd9Sstevel@tonic-gate } 15817c478bd9Sstevel@tonic-gate 15827c478bd9Sstevel@tonic-gate if (mechanism->cm_type <= SHA256_HMAC_GEN_MECH_INFO_TYPE) 15837c478bd9Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 15847c478bd9Sstevel@tonic-gate else 15857c478bd9Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate /* 15887c478bd9Sstevel@tonic-gate * Do a SHA2 final, must be done separately since the digest 15897c478bd9Sstevel@tonic-gate * type can be different than the input data type. 15907c478bd9Sstevel@tonic-gate */ 15917c478bd9Sstevel@tonic-gate switch (digest->cd_format) { 15927c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 15937c478bd9Sstevel@tonic-gate SHA2Final((unsigned char *)digest->cd_raw.iov_base + 15947c478bd9Sstevel@tonic-gate digest->cd_offset, &sha2_ctx); 15957c478bd9Sstevel@tonic-gate break; 15967c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 15977c478bd9Sstevel@tonic-gate ret = sha2_digest_final_uio(&sha2_ctx, digest, 15987c478bd9Sstevel@tonic-gate sha_digest_len, NULL); 15997c478bd9Sstevel@tonic-gate break; 16007c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 16017c478bd9Sstevel@tonic-gate ret = sha2_digest_final_mblk(&sha2_ctx, digest, 16027c478bd9Sstevel@tonic-gate sha_digest_len, NULL); 16037c478bd9Sstevel@tonic-gate break; 16047c478bd9Sstevel@tonic-gate default: 16057c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate 1608f66d273dSizick if (ret == CRYPTO_SUCCESS) 16097c478bd9Sstevel@tonic-gate digest->cd_length = sha_digest_len; 1610f66d273dSizick else 16117c478bd9Sstevel@tonic-gate digest->cd_length = 0; 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate return (ret); 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate /* 16177c478bd9Sstevel@tonic-gate * KCF software provider mac entry points. 16187c478bd9Sstevel@tonic-gate * 16197c478bd9Sstevel@tonic-gate * SHA2 HMAC is: SHA2(key XOR opad, SHA2(key XOR ipad, text)) 16207c478bd9Sstevel@tonic-gate * 16217c478bd9Sstevel@tonic-gate * Init: 16227c478bd9Sstevel@tonic-gate * The initialization routine initializes what we denote 16237c478bd9Sstevel@tonic-gate * as the inner and outer contexts by doing 16247c478bd9Sstevel@tonic-gate * - for inner context: SHA2(key XOR ipad) 16257c478bd9Sstevel@tonic-gate * - for outer context: SHA2(key XOR opad) 16267c478bd9Sstevel@tonic-gate * 16277c478bd9Sstevel@tonic-gate * Update: 16287c478bd9Sstevel@tonic-gate * Each subsequent SHA2 HMAC update will result in an 16297c478bd9Sstevel@tonic-gate * update of the inner context with the specified data. 16307c478bd9Sstevel@tonic-gate * 16317c478bd9Sstevel@tonic-gate * Final: 16327c478bd9Sstevel@tonic-gate * The SHA2 HMAC final will do a SHA2 final operation on the 16337c478bd9Sstevel@tonic-gate * inner context, and the resulting digest will be used 16347c478bd9Sstevel@tonic-gate * as the data for an update on the outer context. Last 16357c478bd9Sstevel@tonic-gate * but not least, a SHA2 final on the outer context will 16367c478bd9Sstevel@tonic-gate * be performed to obtain the SHA2 HMAC digest to return 16377c478bd9Sstevel@tonic-gate * to the user. 16387c478bd9Sstevel@tonic-gate */ 16397c478bd9Sstevel@tonic-gate 16407c478bd9Sstevel@tonic-gate /* 16417c478bd9Sstevel@tonic-gate * Initialize a SHA2-HMAC context. 16427c478bd9Sstevel@tonic-gate */ 16437c478bd9Sstevel@tonic-gate static void 16447c478bd9Sstevel@tonic-gate sha2_mac_init_ctx(sha2_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes) 16457c478bd9Sstevel@tonic-gate { 16467c478bd9Sstevel@tonic-gate uint64_t ipad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)]; 16477c478bd9Sstevel@tonic-gate uint64_t opad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)]; 16487c478bd9Sstevel@tonic-gate int i, block_size, blocks_per_int64; 16497c478bd9Sstevel@tonic-gate 16507c478bd9Sstevel@tonic-gate /* Determine the block size */ 16517c478bd9Sstevel@tonic-gate if (ctx->hc_mech_type <= SHA256_HMAC_GEN_MECH_INFO_TYPE) { 16527c478bd9Sstevel@tonic-gate block_size = SHA256_HMAC_BLOCK_SIZE; 16537c478bd9Sstevel@tonic-gate blocks_per_int64 = SHA256_HMAC_BLOCK_SIZE / sizeof (uint64_t); 16547c478bd9Sstevel@tonic-gate } else { 16557c478bd9Sstevel@tonic-gate block_size = SHA512_HMAC_BLOCK_SIZE; 16567c478bd9Sstevel@tonic-gate blocks_per_int64 = SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t); 16577c478bd9Sstevel@tonic-gate } 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate (void) bzero(ipad, block_size); 16607c478bd9Sstevel@tonic-gate (void) bzero(opad, block_size); 16617c478bd9Sstevel@tonic-gate (void) bcopy(keyval, ipad, length_in_bytes); 16627c478bd9Sstevel@tonic-gate (void) bcopy(keyval, opad, length_in_bytes); 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate /* XOR key with ipad (0x36) and opad (0x5c) */ 16657c478bd9Sstevel@tonic-gate for (i = 0; i < blocks_per_int64; i ++) { 16667c478bd9Sstevel@tonic-gate ipad[i] ^= 0x3636363636363636; 16677c478bd9Sstevel@tonic-gate opad[i] ^= 0x5c5c5c5c5c5c5c5c; 16687c478bd9Sstevel@tonic-gate } 16697c478bd9Sstevel@tonic-gate 16707c478bd9Sstevel@tonic-gate /* perform SHA2 on ipad */ 16717c478bd9Sstevel@tonic-gate SHA2Init(ctx->hc_mech_type, &ctx->hc_icontext); 16727c478bd9Sstevel@tonic-gate SHA2Update(&ctx->hc_icontext, (uint8_t *)ipad, block_size); 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate /* perform SHA2 on opad */ 16757c478bd9Sstevel@tonic-gate SHA2Init(ctx->hc_mech_type, &ctx->hc_ocontext); 16767c478bd9Sstevel@tonic-gate SHA2Update(&ctx->hc_ocontext, (uint8_t *)opad, block_size); 16777c478bd9Sstevel@tonic-gate 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate /* 16817c478bd9Sstevel@tonic-gate */ 16827c478bd9Sstevel@tonic-gate static int 16837c478bd9Sstevel@tonic-gate sha2_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 16847c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, 16857c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 16867c478bd9Sstevel@tonic-gate { 16877c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 16887c478bd9Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 16897c478bd9Sstevel@tonic-gate uint_t sha_digest_len, sha_hmac_block_size; 16907c478bd9Sstevel@tonic-gate 16917c478bd9Sstevel@tonic-gate /* 16927c478bd9Sstevel@tonic-gate * Set the digest length and block size to values approriate to the 16937c478bd9Sstevel@tonic-gate * mechanism 16947c478bd9Sstevel@tonic-gate */ 16957c478bd9Sstevel@tonic-gate switch (mechanism->cm_type) { 16967c478bd9Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 16977c478bd9Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 16987c478bd9Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 16997c478bd9Sstevel@tonic-gate sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE; 17007c478bd9Sstevel@tonic-gate break; 17017c478bd9Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 17027c478bd9Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 17037c478bd9Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 17047c478bd9Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 17057c478bd9Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 17067c478bd9Sstevel@tonic-gate sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 17077c478bd9Sstevel@tonic-gate break; 17087c478bd9Sstevel@tonic-gate default: 17097c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 17107c478bd9Sstevel@tonic-gate } 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 17137c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 17147c478bd9Sstevel@tonic-gate 17157c478bd9Sstevel@tonic-gate ctx->cc_provider_private = kmem_alloc(sizeof (sha2_hmac_ctx_t), 17167c478bd9Sstevel@tonic-gate crypto_kmflag(req)); 17177c478bd9Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 17187c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate if (ctx_template != NULL) { 17217c478bd9Sstevel@tonic-gate /* reuse context template */ 17227c478bd9Sstevel@tonic-gate bcopy(ctx_template, PROV_SHA2_HMAC_CTX(ctx), 17237c478bd9Sstevel@tonic-gate sizeof (sha2_hmac_ctx_t)); 17247c478bd9Sstevel@tonic-gate } else { 17257c478bd9Sstevel@tonic-gate /* no context template, compute context */ 17267c478bd9Sstevel@tonic-gate if (keylen_in_bytes > sha_hmac_block_size) { 17277c478bd9Sstevel@tonic-gate uchar_t digested_key[SHA512_DIGEST_LENGTH]; 17287c478bd9Sstevel@tonic-gate sha2_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private; 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate /* 17317c478bd9Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 17327c478bd9Sstevel@tonic-gate * The inner context is used since it hasn't been 17337c478bd9Sstevel@tonic-gate * initialized yet. 17347c478bd9Sstevel@tonic-gate */ 17357c478bd9Sstevel@tonic-gate PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 17367c478bd9Sstevel@tonic-gate &hmac_ctx->hc_icontext, 17377c478bd9Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digested_key); 17387c478bd9Sstevel@tonic-gate sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx), 17397c478bd9Sstevel@tonic-gate digested_key, sha_digest_len); 17407c478bd9Sstevel@tonic-gate } else { 17417c478bd9Sstevel@tonic-gate sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx), 17427c478bd9Sstevel@tonic-gate key->ck_data, keylen_in_bytes); 17437c478bd9Sstevel@tonic-gate } 17447c478bd9Sstevel@tonic-gate } 17457c478bd9Sstevel@tonic-gate 17467c478bd9Sstevel@tonic-gate /* 17477c478bd9Sstevel@tonic-gate * Get the mechanism parameters, if applicable. 17487c478bd9Sstevel@tonic-gate */ 17497c478bd9Sstevel@tonic-gate PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type; 17507c478bd9Sstevel@tonic-gate if (mechanism->cm_type % 3 == 2) { 17517c478bd9Sstevel@tonic-gate if (mechanism->cm_param == NULL || 17527c478bd9Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) 17537c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 17547c478bd9Sstevel@tonic-gate PROV_SHA2_GET_DIGEST_LEN(mechanism, 17557c478bd9Sstevel@tonic-gate PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len); 17567c478bd9Sstevel@tonic-gate if (PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len > sha_digest_len) 17577c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 17587c478bd9Sstevel@tonic-gate } 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 17617c478bd9Sstevel@tonic-gate bzero(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t)); 17627c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t)); 17637c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 17647c478bd9Sstevel@tonic-gate } 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate return (ret); 17677c478bd9Sstevel@tonic-gate } 17687c478bd9Sstevel@tonic-gate 17697c478bd9Sstevel@tonic-gate /* ARGSUSED */ 17707c478bd9Sstevel@tonic-gate static int 17717c478bd9Sstevel@tonic-gate sha2_mac_update(crypto_ctx_t *ctx, crypto_data_t *data, 17727c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 17737c478bd9Sstevel@tonic-gate { 17747c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate /* 17797c478bd9Sstevel@tonic-gate * Do a SHA2 update of the inner context using the specified 17807c478bd9Sstevel@tonic-gate * data. 17817c478bd9Sstevel@tonic-gate */ 17827c478bd9Sstevel@tonic-gate switch (data->cd_format) { 17837c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 17847c478bd9Sstevel@tonic-gate SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, 17857c478bd9Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 17867c478bd9Sstevel@tonic-gate data->cd_length); 17877c478bd9Sstevel@tonic-gate break; 17887c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 17897c478bd9Sstevel@tonic-gate ret = sha2_digest_update_uio( 17907c478bd9Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, data); 17917c478bd9Sstevel@tonic-gate break; 17927c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 17937c478bd9Sstevel@tonic-gate ret = sha2_digest_update_mblk( 17947c478bd9Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, data); 17957c478bd9Sstevel@tonic-gate break; 17967c478bd9Sstevel@tonic-gate default: 17977c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 17987c478bd9Sstevel@tonic-gate } 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate return (ret); 18017c478bd9Sstevel@tonic-gate } 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate /* ARGSUSED */ 18047c478bd9Sstevel@tonic-gate static int 18057c478bd9Sstevel@tonic-gate sha2_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req) 18067c478bd9Sstevel@tonic-gate { 18077c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 18087c478bd9Sstevel@tonic-gate uchar_t digest[SHA512_DIGEST_LENGTH]; 18097c478bd9Sstevel@tonic-gate uint32_t digest_len, sha_digest_len; 18107c478bd9Sstevel@tonic-gate 18117c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 18127c478bd9Sstevel@tonic-gate 18137c478bd9Sstevel@tonic-gate /* Set the digest lengths to values approriate to the mechanism */ 18147c478bd9Sstevel@tonic-gate switch (PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type) { 18157c478bd9Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 18167c478bd9Sstevel@tonic-gate sha_digest_len = digest_len = SHA256_DIGEST_LENGTH; 18177c478bd9Sstevel@tonic-gate break; 18187c478bd9Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 18197c478bd9Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 18207c478bd9Sstevel@tonic-gate sha_digest_len = digest_len = SHA512_DIGEST_LENGTH; 18217c478bd9Sstevel@tonic-gate break; 18227c478bd9Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 18237c478bd9Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 18247c478bd9Sstevel@tonic-gate digest_len = PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len; 18257c478bd9Sstevel@tonic-gate break; 18267c478bd9Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 18277c478bd9Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 18287c478bd9Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 18297c478bd9Sstevel@tonic-gate digest_len = PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len; 18307c478bd9Sstevel@tonic-gate break; 18317c478bd9Sstevel@tonic-gate } 18327c478bd9Sstevel@tonic-gate 18337c478bd9Sstevel@tonic-gate /* 18347c478bd9Sstevel@tonic-gate * We need to just return the length needed to store the output. 18357c478bd9Sstevel@tonic-gate * We should not destroy the context for the following cases. 18367c478bd9Sstevel@tonic-gate */ 18377c478bd9Sstevel@tonic-gate if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) { 18387c478bd9Sstevel@tonic-gate mac->cd_length = digest_len; 18397c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 18407c478bd9Sstevel@tonic-gate } 18417c478bd9Sstevel@tonic-gate 18427c478bd9Sstevel@tonic-gate /* 18437c478bd9Sstevel@tonic-gate * Do a SHA2 final on the inner context. 18447c478bd9Sstevel@tonic-gate */ 18457c478bd9Sstevel@tonic-gate SHA2Final(digest, &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext); 18467c478bd9Sstevel@tonic-gate 18477c478bd9Sstevel@tonic-gate /* 18487c478bd9Sstevel@tonic-gate * Do a SHA2 update on the outer context, feeding the inner 18497c478bd9Sstevel@tonic-gate * digest as data. 18507c478bd9Sstevel@tonic-gate */ 18517c478bd9Sstevel@tonic-gate SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, digest, 18527c478bd9Sstevel@tonic-gate sha_digest_len); 18537c478bd9Sstevel@tonic-gate 18547c478bd9Sstevel@tonic-gate /* 18557c478bd9Sstevel@tonic-gate * Do a SHA2 final on the outer context, storing the computing 18567c478bd9Sstevel@tonic-gate * digest in the users buffer. 18577c478bd9Sstevel@tonic-gate */ 18587c478bd9Sstevel@tonic-gate switch (mac->cd_format) { 18597c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 18607c478bd9Sstevel@tonic-gate if (digest_len != sha_digest_len) { 18617c478bd9Sstevel@tonic-gate /* 18627c478bd9Sstevel@tonic-gate * The caller requested a short digest. Digest 18637c478bd9Sstevel@tonic-gate * into a scratch buffer and return to 18647c478bd9Sstevel@tonic-gate * the user only what was requested. 18657c478bd9Sstevel@tonic-gate */ 18667c478bd9Sstevel@tonic-gate SHA2Final(digest, 18677c478bd9Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext); 18687c478bd9Sstevel@tonic-gate bcopy(digest, (unsigned char *)mac->cd_raw.iov_base + 18697c478bd9Sstevel@tonic-gate mac->cd_offset, digest_len); 18707c478bd9Sstevel@tonic-gate } else { 18717c478bd9Sstevel@tonic-gate SHA2Final((unsigned char *)mac->cd_raw.iov_base + 18727c478bd9Sstevel@tonic-gate mac->cd_offset, 18737c478bd9Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext); 18747c478bd9Sstevel@tonic-gate } 18757c478bd9Sstevel@tonic-gate break; 18767c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 18777c478bd9Sstevel@tonic-gate ret = sha2_digest_final_uio( 18787c478bd9Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, mac, 18797c478bd9Sstevel@tonic-gate digest_len, digest); 18807c478bd9Sstevel@tonic-gate break; 18817c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 18827c478bd9Sstevel@tonic-gate ret = sha2_digest_final_mblk( 18837c478bd9Sstevel@tonic-gate &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, mac, 18847c478bd9Sstevel@tonic-gate digest_len, digest); 18857c478bd9Sstevel@tonic-gate break; 18867c478bd9Sstevel@tonic-gate default: 18877c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 18887c478bd9Sstevel@tonic-gate } 18897c478bd9Sstevel@tonic-gate 1890f66d273dSizick if (ret == CRYPTO_SUCCESS) 18917c478bd9Sstevel@tonic-gate mac->cd_length = digest_len; 1892f66d273dSizick else 18937c478bd9Sstevel@tonic-gate mac->cd_length = 0; 18947c478bd9Sstevel@tonic-gate 1895f66d273dSizick bzero(&PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, sizeof (sha2_hmac_ctx_t)); 18967c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t)); 18977c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 18987c478bd9Sstevel@tonic-gate 18997c478bd9Sstevel@tonic-gate return (ret); 19007c478bd9Sstevel@tonic-gate } 19017c478bd9Sstevel@tonic-gate 19027c478bd9Sstevel@tonic-gate #define SHA2_MAC_UPDATE(data, ctx, ret) { \ 19037c478bd9Sstevel@tonic-gate switch (data->cd_format) { \ 19047c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: \ 19057c478bd9Sstevel@tonic-gate SHA2Update(&(ctx).hc_icontext, \ 19067c478bd9Sstevel@tonic-gate (uint8_t *)data->cd_raw.iov_base + \ 19077c478bd9Sstevel@tonic-gate data->cd_offset, data->cd_length); \ 19087c478bd9Sstevel@tonic-gate break; \ 19097c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: \ 19107c478bd9Sstevel@tonic-gate ret = sha2_digest_update_uio(&(ctx).hc_icontext, data); \ 19117c478bd9Sstevel@tonic-gate break; \ 19127c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: \ 19137c478bd9Sstevel@tonic-gate ret = sha2_digest_update_mblk(&(ctx).hc_icontext, \ 19147c478bd9Sstevel@tonic-gate data); \ 19157c478bd9Sstevel@tonic-gate break; \ 19167c478bd9Sstevel@tonic-gate default: \ 19177c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; \ 19187c478bd9Sstevel@tonic-gate } \ 19197c478bd9Sstevel@tonic-gate } 19207c478bd9Sstevel@tonic-gate 19217c478bd9Sstevel@tonic-gate /* ARGSUSED */ 19227c478bd9Sstevel@tonic-gate static int 19237c478bd9Sstevel@tonic-gate sha2_mac_atomic(crypto_provider_handle_t provider, 19247c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 19257c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 19267c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 19277c478bd9Sstevel@tonic-gate { 19287c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 19297c478bd9Sstevel@tonic-gate uchar_t digest[SHA512_DIGEST_LENGTH]; 19307c478bd9Sstevel@tonic-gate sha2_hmac_ctx_t sha2_hmac_ctx; 19317c478bd9Sstevel@tonic-gate uint32_t sha_digest_len, digest_len, sha_hmac_block_size; 19327c478bd9Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 19337c478bd9Sstevel@tonic-gate 19347c478bd9Sstevel@tonic-gate /* 19357c478bd9Sstevel@tonic-gate * Set the digest length and block size to values approriate to the 19367c478bd9Sstevel@tonic-gate * mechanism 19377c478bd9Sstevel@tonic-gate */ 19387c478bd9Sstevel@tonic-gate switch (mechanism->cm_type) { 19397c478bd9Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 19407c478bd9Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 19417c478bd9Sstevel@tonic-gate sha_digest_len = digest_len = SHA256_DIGEST_LENGTH; 19427c478bd9Sstevel@tonic-gate sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE; 19437c478bd9Sstevel@tonic-gate break; 19447c478bd9Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 19457c478bd9Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 19467c478bd9Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 19477c478bd9Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 19487c478bd9Sstevel@tonic-gate sha_digest_len = digest_len = SHA512_DIGEST_LENGTH; 19497c478bd9Sstevel@tonic-gate sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 19507c478bd9Sstevel@tonic-gate break; 19517c478bd9Sstevel@tonic-gate default: 19527c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 19537c478bd9Sstevel@tonic-gate } 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 19567c478bd9Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 19577c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 19587c478bd9Sstevel@tonic-gate 19597c478bd9Sstevel@tonic-gate if (ctx_template != NULL) { 19607c478bd9Sstevel@tonic-gate /* reuse context template */ 19617c478bd9Sstevel@tonic-gate bcopy(ctx_template, &sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t)); 19627c478bd9Sstevel@tonic-gate } else { 19637c478bd9Sstevel@tonic-gate sha2_hmac_ctx.hc_mech_type = mechanism->cm_type; 19647c478bd9Sstevel@tonic-gate /* no context template, initialize context */ 19657c478bd9Sstevel@tonic-gate if (keylen_in_bytes > sha_hmac_block_size) { 19667c478bd9Sstevel@tonic-gate /* 19677c478bd9Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 19687c478bd9Sstevel@tonic-gate * The inner context is used since it hasn't been 19697c478bd9Sstevel@tonic-gate * initialized yet. 19707c478bd9Sstevel@tonic-gate */ 19717c478bd9Sstevel@tonic-gate PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 19727c478bd9Sstevel@tonic-gate &sha2_hmac_ctx.hc_icontext, 19737c478bd9Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digest); 19747c478bd9Sstevel@tonic-gate sha2_mac_init_ctx(&sha2_hmac_ctx, digest, 19757c478bd9Sstevel@tonic-gate sha_digest_len); 19767c478bd9Sstevel@tonic-gate } else { 19777c478bd9Sstevel@tonic-gate sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data, 19787c478bd9Sstevel@tonic-gate keylen_in_bytes); 19797c478bd9Sstevel@tonic-gate } 19807c478bd9Sstevel@tonic-gate } 19817c478bd9Sstevel@tonic-gate 19827c478bd9Sstevel@tonic-gate /* get the mechanism parameters, if applicable */ 19837c478bd9Sstevel@tonic-gate if ((mechanism->cm_type % 3) == 2) { 19847c478bd9Sstevel@tonic-gate if (mechanism->cm_param == NULL || 19857c478bd9Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) { 19867c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 19877c478bd9Sstevel@tonic-gate goto bail; 19887c478bd9Sstevel@tonic-gate } 19897c478bd9Sstevel@tonic-gate PROV_SHA2_GET_DIGEST_LEN(mechanism, digest_len); 19907c478bd9Sstevel@tonic-gate if (digest_len > sha_digest_len) { 19917c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 19927c478bd9Sstevel@tonic-gate goto bail; 19937c478bd9Sstevel@tonic-gate } 19947c478bd9Sstevel@tonic-gate } 19957c478bd9Sstevel@tonic-gate 19967c478bd9Sstevel@tonic-gate /* do a SHA2 update of the inner context using the specified data */ 19977c478bd9Sstevel@tonic-gate SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret); 19987c478bd9Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) 19997c478bd9Sstevel@tonic-gate /* the update failed, free context and bail */ 20007c478bd9Sstevel@tonic-gate goto bail; 20017c478bd9Sstevel@tonic-gate 20027c478bd9Sstevel@tonic-gate /* 20037c478bd9Sstevel@tonic-gate * Do a SHA2 final on the inner context. 20047c478bd9Sstevel@tonic-gate */ 20057c478bd9Sstevel@tonic-gate SHA2Final(digest, &sha2_hmac_ctx.hc_icontext); 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate /* 20087c478bd9Sstevel@tonic-gate * Do an SHA2 update on the outer context, feeding the inner 20097c478bd9Sstevel@tonic-gate * digest as data. 20107c478bd9Sstevel@tonic-gate * 20117c478bd9Sstevel@tonic-gate * Make sure that SHA384 is handled special because 20127c478bd9Sstevel@tonic-gate * it cannot feed a 60-byte inner hash to the outer 20137c478bd9Sstevel@tonic-gate */ 20147c478bd9Sstevel@tonic-gate if (mechanism->cm_type == SHA384_HMAC_MECH_INFO_TYPE || 20157c478bd9Sstevel@tonic-gate mechanism->cm_type == SHA384_HMAC_GEN_MECH_INFO_TYPE) 20167c478bd9Sstevel@tonic-gate SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, 20177c478bd9Sstevel@tonic-gate SHA384_DIGEST_LENGTH); 20187c478bd9Sstevel@tonic-gate else 20197c478bd9Sstevel@tonic-gate SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len); 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate /* 20227c478bd9Sstevel@tonic-gate * Do a SHA2 final on the outer context, storing the computed 20237c478bd9Sstevel@tonic-gate * digest in the users buffer. 20247c478bd9Sstevel@tonic-gate */ 20257c478bd9Sstevel@tonic-gate switch (mac->cd_format) { 20267c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 20277c478bd9Sstevel@tonic-gate if (digest_len != sha_digest_len) { 20287c478bd9Sstevel@tonic-gate /* 20297c478bd9Sstevel@tonic-gate * The caller requested a short digest. Digest 20307c478bd9Sstevel@tonic-gate * into a scratch buffer and return to 20317c478bd9Sstevel@tonic-gate * the user only what was requested. 20327c478bd9Sstevel@tonic-gate */ 20337c478bd9Sstevel@tonic-gate SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext); 20347c478bd9Sstevel@tonic-gate bcopy(digest, (unsigned char *)mac->cd_raw.iov_base + 20357c478bd9Sstevel@tonic-gate mac->cd_offset, digest_len); 20367c478bd9Sstevel@tonic-gate } else { 20377c478bd9Sstevel@tonic-gate SHA2Final((unsigned char *)mac->cd_raw.iov_base + 20387c478bd9Sstevel@tonic-gate mac->cd_offset, &sha2_hmac_ctx.hc_ocontext); 20397c478bd9Sstevel@tonic-gate } 20407c478bd9Sstevel@tonic-gate break; 20417c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 20427c478bd9Sstevel@tonic-gate ret = sha2_digest_final_uio(&sha2_hmac_ctx.hc_ocontext, mac, 20437c478bd9Sstevel@tonic-gate digest_len, digest); 20447c478bd9Sstevel@tonic-gate break; 20457c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 20467c478bd9Sstevel@tonic-gate ret = sha2_digest_final_mblk(&sha2_hmac_ctx.hc_ocontext, mac, 20477c478bd9Sstevel@tonic-gate digest_len, digest); 20487c478bd9Sstevel@tonic-gate break; 20497c478bd9Sstevel@tonic-gate default: 20507c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 20517c478bd9Sstevel@tonic-gate } 20527c478bd9Sstevel@tonic-gate 20537c478bd9Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 20547c478bd9Sstevel@tonic-gate mac->cd_length = digest_len; 2055f66d273dSizick return (CRYPTO_SUCCESS); 20567c478bd9Sstevel@tonic-gate } 20577c478bd9Sstevel@tonic-gate bail: 20587c478bd9Sstevel@tonic-gate bzero(&sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t)); 20597c478bd9Sstevel@tonic-gate mac->cd_length = 0; 20607c478bd9Sstevel@tonic-gate return (ret); 20617c478bd9Sstevel@tonic-gate } 20627c478bd9Sstevel@tonic-gate 20637c478bd9Sstevel@tonic-gate /* ARGSUSED */ 20647c478bd9Sstevel@tonic-gate static int 20657c478bd9Sstevel@tonic-gate sha2_mac_verify_atomic(crypto_provider_handle_t provider, 20667c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 20677c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 20687c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 20697c478bd9Sstevel@tonic-gate { 20707c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 20717c478bd9Sstevel@tonic-gate uchar_t digest[SHA512_DIGEST_LENGTH]; 20727c478bd9Sstevel@tonic-gate sha2_hmac_ctx_t sha2_hmac_ctx; 20737c478bd9Sstevel@tonic-gate uint32_t sha_digest_len, digest_len, sha_hmac_block_size; 20747c478bd9Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 20757c478bd9Sstevel@tonic-gate 20767c478bd9Sstevel@tonic-gate /* 20777c478bd9Sstevel@tonic-gate * Set the digest length and block size to values approriate to the 20787c478bd9Sstevel@tonic-gate * mechanism 20797c478bd9Sstevel@tonic-gate */ 20807c478bd9Sstevel@tonic-gate switch (mechanism->cm_type) { 20817c478bd9Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 20827c478bd9Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 20837c478bd9Sstevel@tonic-gate sha_digest_len = digest_len = SHA256_DIGEST_LENGTH; 20847c478bd9Sstevel@tonic-gate sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE; 20857c478bd9Sstevel@tonic-gate break; 20867c478bd9Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 20877c478bd9Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 20887c478bd9Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 20897c478bd9Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 20907c478bd9Sstevel@tonic-gate sha_digest_len = digest_len = SHA512_DIGEST_LENGTH; 20917c478bd9Sstevel@tonic-gate sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 20927c478bd9Sstevel@tonic-gate break; 20937c478bd9Sstevel@tonic-gate default: 20947c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 20957c478bd9Sstevel@tonic-gate } 20967c478bd9Sstevel@tonic-gate 20977c478bd9Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 20987c478bd9Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 20997c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 21007c478bd9Sstevel@tonic-gate 21017c478bd9Sstevel@tonic-gate if (ctx_template != NULL) { 21027c478bd9Sstevel@tonic-gate /* reuse context template */ 21037c478bd9Sstevel@tonic-gate bcopy(ctx_template, &sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t)); 21047c478bd9Sstevel@tonic-gate } else { 21057c478bd9Sstevel@tonic-gate /* no context template, initialize context */ 21067c478bd9Sstevel@tonic-gate if (keylen_in_bytes > sha_hmac_block_size) { 21077c478bd9Sstevel@tonic-gate /* 21087c478bd9Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 21097c478bd9Sstevel@tonic-gate * The inner context is used since it hasn't been 21107c478bd9Sstevel@tonic-gate * initialized yet. 21117c478bd9Sstevel@tonic-gate */ 21127c478bd9Sstevel@tonic-gate PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 21137c478bd9Sstevel@tonic-gate &sha2_hmac_ctx.hc_icontext, 21147c478bd9Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digest); 21157c478bd9Sstevel@tonic-gate sha2_mac_init_ctx(&sha2_hmac_ctx, digest, 21167c478bd9Sstevel@tonic-gate sha_digest_len); 21177c478bd9Sstevel@tonic-gate } else { 21187c478bd9Sstevel@tonic-gate sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data, 21197c478bd9Sstevel@tonic-gate keylen_in_bytes); 21207c478bd9Sstevel@tonic-gate } 21217c478bd9Sstevel@tonic-gate } 21227c478bd9Sstevel@tonic-gate 21237c478bd9Sstevel@tonic-gate /* get the mechanism parameters, if applicable */ 21247c478bd9Sstevel@tonic-gate if (mechanism->cm_type % 3 == 2) { 21257c478bd9Sstevel@tonic-gate if (mechanism->cm_param == NULL || 21267c478bd9Sstevel@tonic-gate mechanism->cm_param_len != sizeof (ulong_t)) { 21277c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 21287c478bd9Sstevel@tonic-gate goto bail; 21297c478bd9Sstevel@tonic-gate } 21307c478bd9Sstevel@tonic-gate PROV_SHA2_GET_DIGEST_LEN(mechanism, digest_len); 21317c478bd9Sstevel@tonic-gate if (digest_len > sha_digest_len) { 21327c478bd9Sstevel@tonic-gate ret = CRYPTO_MECHANISM_PARAM_INVALID; 21337c478bd9Sstevel@tonic-gate goto bail; 21347c478bd9Sstevel@tonic-gate } 21357c478bd9Sstevel@tonic-gate } 21367c478bd9Sstevel@tonic-gate 21377c478bd9Sstevel@tonic-gate if (mac->cd_length != digest_len) { 21387c478bd9Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 21397c478bd9Sstevel@tonic-gate goto bail; 21407c478bd9Sstevel@tonic-gate } 21417c478bd9Sstevel@tonic-gate 21427c478bd9Sstevel@tonic-gate /* do a SHA2 update of the inner context using the specified data */ 21437c478bd9Sstevel@tonic-gate SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret); 21447c478bd9Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) 21457c478bd9Sstevel@tonic-gate /* the update failed, free context and bail */ 21467c478bd9Sstevel@tonic-gate goto bail; 21477c478bd9Sstevel@tonic-gate 21487c478bd9Sstevel@tonic-gate /* do a SHA2 final on the inner context */ 21497c478bd9Sstevel@tonic-gate SHA2Final(digest, &sha2_hmac_ctx.hc_icontext); 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate /* 21527c478bd9Sstevel@tonic-gate * Do an SHA2 update on the outer context, feeding the inner 21537c478bd9Sstevel@tonic-gate * digest as data. 21547c478bd9Sstevel@tonic-gate */ 21557c478bd9Sstevel@tonic-gate SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len); 21567c478bd9Sstevel@tonic-gate 21577c478bd9Sstevel@tonic-gate /* 21587c478bd9Sstevel@tonic-gate * Do a SHA2 final on the outer context, storing the computed 21597c478bd9Sstevel@tonic-gate * digest in the users buffer. 21607c478bd9Sstevel@tonic-gate */ 21617c478bd9Sstevel@tonic-gate SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext); 21627c478bd9Sstevel@tonic-gate 21637c478bd9Sstevel@tonic-gate /* 21647c478bd9Sstevel@tonic-gate * Compare the computed digest against the expected digest passed 21657c478bd9Sstevel@tonic-gate * as argument. 21667c478bd9Sstevel@tonic-gate */ 21677c478bd9Sstevel@tonic-gate 21687c478bd9Sstevel@tonic-gate switch (mac->cd_format) { 21697c478bd9Sstevel@tonic-gate 21707c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 21717c478bd9Sstevel@tonic-gate if (bcmp(digest, (unsigned char *)mac->cd_raw.iov_base + 21727c478bd9Sstevel@tonic-gate mac->cd_offset, digest_len) != 0) 21737c478bd9Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 21747c478bd9Sstevel@tonic-gate break; 21757c478bd9Sstevel@tonic-gate 21767c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: { 21777c478bd9Sstevel@tonic-gate off_t offset = mac->cd_offset; 21787c478bd9Sstevel@tonic-gate uint_t vec_idx; 21797c478bd9Sstevel@tonic-gate off_t scratch_offset = 0; 21807c478bd9Sstevel@tonic-gate size_t length = digest_len; 21817c478bd9Sstevel@tonic-gate size_t cur_len; 21827c478bd9Sstevel@tonic-gate 21837c478bd9Sstevel@tonic-gate /* we support only kernel buffer */ 21847c478bd9Sstevel@tonic-gate if (mac->cd_uio->uio_segflg != UIO_SYSSPACE) 21857c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 21867c478bd9Sstevel@tonic-gate 21877c478bd9Sstevel@tonic-gate /* jump to the first iovec containing the expected digest */ 21887c478bd9Sstevel@tonic-gate for (vec_idx = 0; 21897c478bd9Sstevel@tonic-gate offset >= mac->cd_uio->uio_iov[vec_idx].iov_len && 21907c478bd9Sstevel@tonic-gate vec_idx < mac->cd_uio->uio_iovcnt; 21917c478bd9Sstevel@tonic-gate offset -= mac->cd_uio->uio_iov[vec_idx++].iov_len); 21927c478bd9Sstevel@tonic-gate if (vec_idx == mac->cd_uio->uio_iovcnt) { 21937c478bd9Sstevel@tonic-gate /* 21947c478bd9Sstevel@tonic-gate * The caller specified an offset that is 21957c478bd9Sstevel@tonic-gate * larger than the total size of the buffers 21967c478bd9Sstevel@tonic-gate * it provided. 21977c478bd9Sstevel@tonic-gate */ 21987c478bd9Sstevel@tonic-gate ret = CRYPTO_DATA_LEN_RANGE; 21997c478bd9Sstevel@tonic-gate break; 22007c478bd9Sstevel@tonic-gate } 22017c478bd9Sstevel@tonic-gate 22027c478bd9Sstevel@tonic-gate /* do the comparison of computed digest vs specified one */ 22037c478bd9Sstevel@tonic-gate while (vec_idx < mac->cd_uio->uio_iovcnt && length > 0) { 22047c478bd9Sstevel@tonic-gate cur_len = MIN(mac->cd_uio->uio_iov[vec_idx].iov_len - 22057c478bd9Sstevel@tonic-gate offset, length); 22067c478bd9Sstevel@tonic-gate 22077c478bd9Sstevel@tonic-gate if (bcmp(digest + scratch_offset, 22087c478bd9Sstevel@tonic-gate mac->cd_uio->uio_iov[vec_idx].iov_base + offset, 22097c478bd9Sstevel@tonic-gate cur_len) != 0) { 22107c478bd9Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 22117c478bd9Sstevel@tonic-gate break; 22127c478bd9Sstevel@tonic-gate } 22137c478bd9Sstevel@tonic-gate 22147c478bd9Sstevel@tonic-gate length -= cur_len; 22157c478bd9Sstevel@tonic-gate vec_idx++; 22167c478bd9Sstevel@tonic-gate scratch_offset += cur_len; 22177c478bd9Sstevel@tonic-gate offset = 0; 22187c478bd9Sstevel@tonic-gate } 22197c478bd9Sstevel@tonic-gate break; 22207c478bd9Sstevel@tonic-gate } 22217c478bd9Sstevel@tonic-gate 22227c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: { 22237c478bd9Sstevel@tonic-gate off_t offset = mac->cd_offset; 22247c478bd9Sstevel@tonic-gate mblk_t *mp; 22257c478bd9Sstevel@tonic-gate off_t scratch_offset = 0; 22267c478bd9Sstevel@tonic-gate size_t length = digest_len; 22277c478bd9Sstevel@tonic-gate size_t cur_len; 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate /* jump to the first mblk_t containing the expected digest */ 22307c478bd9Sstevel@tonic-gate for (mp = mac->cd_mp; mp != NULL && offset >= MBLKL(mp); 22317c478bd9Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 22327c478bd9Sstevel@tonic-gate if (mp == NULL) { 22337c478bd9Sstevel@tonic-gate /* 22347c478bd9Sstevel@tonic-gate * The caller specified an offset that is larger than 22357c478bd9Sstevel@tonic-gate * the total size of the buffers it provided. 22367c478bd9Sstevel@tonic-gate */ 22377c478bd9Sstevel@tonic-gate ret = CRYPTO_DATA_LEN_RANGE; 22387c478bd9Sstevel@tonic-gate break; 22397c478bd9Sstevel@tonic-gate } 22407c478bd9Sstevel@tonic-gate 22417c478bd9Sstevel@tonic-gate while (mp != NULL && length > 0) { 22427c478bd9Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 22437c478bd9Sstevel@tonic-gate if (bcmp(digest + scratch_offset, 22447c478bd9Sstevel@tonic-gate mp->b_rptr + offset, cur_len) != 0) { 22457c478bd9Sstevel@tonic-gate ret = CRYPTO_INVALID_MAC; 22467c478bd9Sstevel@tonic-gate break; 22477c478bd9Sstevel@tonic-gate } 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate length -= cur_len; 22507c478bd9Sstevel@tonic-gate mp = mp->b_cont; 22517c478bd9Sstevel@tonic-gate scratch_offset += cur_len; 22527c478bd9Sstevel@tonic-gate offset = 0; 22537c478bd9Sstevel@tonic-gate } 22547c478bd9Sstevel@tonic-gate break; 22557c478bd9Sstevel@tonic-gate } 22567c478bd9Sstevel@tonic-gate 22577c478bd9Sstevel@tonic-gate default: 22587c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 22597c478bd9Sstevel@tonic-gate } 22607c478bd9Sstevel@tonic-gate 22617c478bd9Sstevel@tonic-gate return (ret); 22627c478bd9Sstevel@tonic-gate bail: 22637c478bd9Sstevel@tonic-gate bzero(&sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t)); 22647c478bd9Sstevel@tonic-gate mac->cd_length = 0; 22657c478bd9Sstevel@tonic-gate return (ret); 22667c478bd9Sstevel@tonic-gate } 22677c478bd9Sstevel@tonic-gate 22687c478bd9Sstevel@tonic-gate /* 22697c478bd9Sstevel@tonic-gate * KCF software provider context management entry points. 22707c478bd9Sstevel@tonic-gate */ 22717c478bd9Sstevel@tonic-gate 22727c478bd9Sstevel@tonic-gate /* ARGSUSED */ 22737c478bd9Sstevel@tonic-gate static int 22747c478bd9Sstevel@tonic-gate sha2_create_ctx_template(crypto_provider_handle_t provider, 22757c478bd9Sstevel@tonic-gate crypto_mechanism_t *mechanism, crypto_key_t *key, 22767c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size, 22777c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 22787c478bd9Sstevel@tonic-gate { 22797c478bd9Sstevel@tonic-gate sha2_hmac_ctx_t *sha2_hmac_ctx_tmpl; 22807c478bd9Sstevel@tonic-gate uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 22817c478bd9Sstevel@tonic-gate uint32_t sha_digest_len, sha_hmac_block_size; 22827c478bd9Sstevel@tonic-gate 22837c478bd9Sstevel@tonic-gate /* 22847c478bd9Sstevel@tonic-gate * Set the digest length and block size to values approriate to the 22857c478bd9Sstevel@tonic-gate * mechanism 22867c478bd9Sstevel@tonic-gate */ 22877c478bd9Sstevel@tonic-gate switch (mechanism->cm_type) { 22887c478bd9Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 22897c478bd9Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 22907c478bd9Sstevel@tonic-gate sha_digest_len = SHA256_DIGEST_LENGTH; 22917c478bd9Sstevel@tonic-gate sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE; 22927c478bd9Sstevel@tonic-gate break; 22937c478bd9Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 22947c478bd9Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 22957c478bd9Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 22967c478bd9Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 22977c478bd9Sstevel@tonic-gate sha_digest_len = SHA512_DIGEST_LENGTH; 22987c478bd9Sstevel@tonic-gate sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 22997c478bd9Sstevel@tonic-gate break; 23007c478bd9Sstevel@tonic-gate default: 23017c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 23027c478bd9Sstevel@tonic-gate } 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gate /* Add support for key by attributes (RFE 4706552) */ 23057c478bd9Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 23067c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 23077c478bd9Sstevel@tonic-gate 23087c478bd9Sstevel@tonic-gate /* 23097c478bd9Sstevel@tonic-gate * Allocate and initialize SHA2 context. 23107c478bd9Sstevel@tonic-gate */ 23117c478bd9Sstevel@tonic-gate sha2_hmac_ctx_tmpl = kmem_alloc(sizeof (sha2_hmac_ctx_t), 23127c478bd9Sstevel@tonic-gate crypto_kmflag(req)); 23137c478bd9Sstevel@tonic-gate if (sha2_hmac_ctx_tmpl == NULL) 23147c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 23157c478bd9Sstevel@tonic-gate 23167c478bd9Sstevel@tonic-gate sha2_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type; 23177c478bd9Sstevel@tonic-gate 23187c478bd9Sstevel@tonic-gate if (keylen_in_bytes > sha_hmac_block_size) { 23197c478bd9Sstevel@tonic-gate uchar_t digested_key[SHA512_DIGEST_LENGTH]; 23207c478bd9Sstevel@tonic-gate 23217c478bd9Sstevel@tonic-gate /* 23227c478bd9Sstevel@tonic-gate * Hash the passed-in key to get a smaller key. 23237c478bd9Sstevel@tonic-gate * The inner context is used since it hasn't been 23247c478bd9Sstevel@tonic-gate * initialized yet. 23257c478bd9Sstevel@tonic-gate */ 23267c478bd9Sstevel@tonic-gate PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 23277c478bd9Sstevel@tonic-gate &sha2_hmac_ctx_tmpl->hc_icontext, 23287c478bd9Sstevel@tonic-gate key->ck_data, keylen_in_bytes, digested_key); 23297c478bd9Sstevel@tonic-gate sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, digested_key, 23307c478bd9Sstevel@tonic-gate sha_digest_len); 23317c478bd9Sstevel@tonic-gate } else { 23327c478bd9Sstevel@tonic-gate sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, key->ck_data, 23337c478bd9Sstevel@tonic-gate keylen_in_bytes); 23347c478bd9Sstevel@tonic-gate } 23357c478bd9Sstevel@tonic-gate 23367c478bd9Sstevel@tonic-gate *ctx_template = (crypto_spi_ctx_template_t)sha2_hmac_ctx_tmpl; 23377c478bd9Sstevel@tonic-gate *ctx_template_size = sizeof (sha2_hmac_ctx_t); 23387c478bd9Sstevel@tonic-gate 23397c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 23407c478bd9Sstevel@tonic-gate } 23417c478bd9Sstevel@tonic-gate 23427c478bd9Sstevel@tonic-gate static int 23437c478bd9Sstevel@tonic-gate sha2_free_context(crypto_ctx_t *ctx) 23447c478bd9Sstevel@tonic-gate { 23457c478bd9Sstevel@tonic-gate uint_t ctx_len; 23467c478bd9Sstevel@tonic-gate 23477c478bd9Sstevel@tonic-gate if (ctx->cc_provider_private == NULL) 23487c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 23497c478bd9Sstevel@tonic-gate 23507c478bd9Sstevel@tonic-gate /* 23517c478bd9Sstevel@tonic-gate * We have to free either SHA2 or SHA2-HMAC contexts, which 23527c478bd9Sstevel@tonic-gate * have different lengths. 23537c478bd9Sstevel@tonic-gate * 23547c478bd9Sstevel@tonic-gate * Note: Below is dependent on the mechanism ordering. 23557c478bd9Sstevel@tonic-gate */ 23567c478bd9Sstevel@tonic-gate 23577c478bd9Sstevel@tonic-gate if (PROV_SHA2_CTX(ctx)->sc_mech_type % 3 == 0) 23587c478bd9Sstevel@tonic-gate ctx_len = sizeof (sha2_ctx_t); 23597c478bd9Sstevel@tonic-gate else 23607c478bd9Sstevel@tonic-gate ctx_len = sizeof (sha2_hmac_ctx_t); 23617c478bd9Sstevel@tonic-gate 23627c478bd9Sstevel@tonic-gate bzero(ctx->cc_provider_private, ctx_len); 23637c478bd9Sstevel@tonic-gate kmem_free(ctx->cc_provider_private, ctx_len); 23647c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 23657c478bd9Sstevel@tonic-gate 23667c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 23677c478bd9Sstevel@tonic-gate } 23687c478bd9Sstevel@tonic-gate 23697c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 23707c478bd9Sstevel@tonic-gate 23717c478bd9Sstevel@tonic-gate void 23727c478bd9Sstevel@tonic-gate SHA2Init(uint64_t mech, SHA2_CTX *ctx) 23737c478bd9Sstevel@tonic-gate { 23747c478bd9Sstevel@tonic-gate 23757c478bd9Sstevel@tonic-gate switch (mech) { 23767c478bd9Sstevel@tonic-gate case SHA256_MECH_INFO_TYPE: 23777c478bd9Sstevel@tonic-gate case SHA256_HMAC_MECH_INFO_TYPE: 23787c478bd9Sstevel@tonic-gate case SHA256_HMAC_GEN_MECH_INFO_TYPE: 23797c478bd9Sstevel@tonic-gate ctx->state.s32[0] = 0x6a09e667U; 23807c478bd9Sstevel@tonic-gate ctx->state.s32[1] = 0xbb67ae85U; 23817c478bd9Sstevel@tonic-gate ctx->state.s32[2] = 0x3c6ef372U; 23827c478bd9Sstevel@tonic-gate ctx->state.s32[3] = 0xa54ff53aU; 23837c478bd9Sstevel@tonic-gate ctx->state.s32[4] = 0x510e527fU; 23847c478bd9Sstevel@tonic-gate ctx->state.s32[5] = 0x9b05688cU; 23857c478bd9Sstevel@tonic-gate ctx->state.s32[6] = 0x1f83d9abU; 23867c478bd9Sstevel@tonic-gate ctx->state.s32[7] = 0x5be0cd19U; 23877c478bd9Sstevel@tonic-gate break; 23887c478bd9Sstevel@tonic-gate case SHA384_MECH_INFO_TYPE: 23897c478bd9Sstevel@tonic-gate case SHA384_HMAC_MECH_INFO_TYPE: 23907c478bd9Sstevel@tonic-gate case SHA384_HMAC_GEN_MECH_INFO_TYPE: 23917c478bd9Sstevel@tonic-gate ctx->state.s64[0] = 0xcbbb9d5dc1059ed8ULL; 23927c478bd9Sstevel@tonic-gate ctx->state.s64[1] = 0x629a292a367cd507ULL; 23937c478bd9Sstevel@tonic-gate ctx->state.s64[2] = 0x9159015a3070dd17ULL; 23947c478bd9Sstevel@tonic-gate ctx->state.s64[3] = 0x152fecd8f70e5939ULL; 23957c478bd9Sstevel@tonic-gate ctx->state.s64[4] = 0x67332667ffc00b31ULL; 23967c478bd9Sstevel@tonic-gate ctx->state.s64[5] = 0x8eb44a8768581511ULL; 23977c478bd9Sstevel@tonic-gate ctx->state.s64[6] = 0xdb0c2e0d64f98fa7ULL; 23987c478bd9Sstevel@tonic-gate ctx->state.s64[7] = 0x47b5481dbefa4fa4ULL; 23997c478bd9Sstevel@tonic-gate break; 24007c478bd9Sstevel@tonic-gate case SHA512_MECH_INFO_TYPE: 24017c478bd9Sstevel@tonic-gate case SHA512_HMAC_MECH_INFO_TYPE: 24027c478bd9Sstevel@tonic-gate case SHA512_HMAC_GEN_MECH_INFO_TYPE: 24037c478bd9Sstevel@tonic-gate ctx->state.s64[0] = 0x6a09e667f3bcc908ULL; 24047c478bd9Sstevel@tonic-gate ctx->state.s64[1] = 0xbb67ae8584caa73bULL; 24057c478bd9Sstevel@tonic-gate ctx->state.s64[2] = 0x3c6ef372fe94f82bULL; 24067c478bd9Sstevel@tonic-gate ctx->state.s64[3] = 0xa54ff53a5f1d36f1ULL; 24077c478bd9Sstevel@tonic-gate ctx->state.s64[4] = 0x510e527fade682d1ULL; 24087c478bd9Sstevel@tonic-gate ctx->state.s64[5] = 0x9b05688c2b3e6c1fULL; 24097c478bd9Sstevel@tonic-gate ctx->state.s64[6] = 0x1f83d9abfb41bd6bULL; 24107c478bd9Sstevel@tonic-gate ctx->state.s64[7] = 0x5be0cd19137e2179ULL; 24117c478bd9Sstevel@tonic-gate break; 24127c478bd9Sstevel@tonic-gate #ifdef _KERNEL 24137c478bd9Sstevel@tonic-gate default: 24147c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "sha2_init: " 24157c478bd9Sstevel@tonic-gate "failed to find a supported algorithm: 0x%x", 24167c478bd9Sstevel@tonic-gate (uint32_t)mech); 24177c478bd9Sstevel@tonic-gate 24187c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 24197c478bd9Sstevel@tonic-gate } 24207c478bd9Sstevel@tonic-gate 24217c478bd9Sstevel@tonic-gate ctx->algotype = mech; 24227c478bd9Sstevel@tonic-gate ctx->count.c64[0] = ctx->count.c64[1] = 0; 24237c478bd9Sstevel@tonic-gate } 24247c478bd9Sstevel@tonic-gate 24257c478bd9Sstevel@tonic-gate /* 24267c478bd9Sstevel@tonic-gate * SHA2Update() 24277c478bd9Sstevel@tonic-gate * 24287c478bd9Sstevel@tonic-gate * purpose: continues an sha2 digest operation, using the message block 24297c478bd9Sstevel@tonic-gate * to update the context. 24307c478bd9Sstevel@tonic-gate * input: SHA2_CTX * : the context to update 24317c478bd9Sstevel@tonic-gate * uint8_t * : the message block 24327c478bd9Sstevel@tonic-gate * uint32_t : the length of the message block in bytes 24337c478bd9Sstevel@tonic-gate * output: void 24347c478bd9Sstevel@tonic-gate */ 24357c478bd9Sstevel@tonic-gate 24367c478bd9Sstevel@tonic-gate void 24377c478bd9Sstevel@tonic-gate SHA2Update(SHA2_CTX *ctx, const uint8_t *input, uint32_t input_len) 24387c478bd9Sstevel@tonic-gate { 24397c478bd9Sstevel@tonic-gate uint32_t i, buf_index, buf_len, buf_limit; 24407c478bd9Sstevel@tonic-gate 24417c478bd9Sstevel@tonic-gate /* check for noop */ 24427c478bd9Sstevel@tonic-gate if (input_len == 0) 24437c478bd9Sstevel@tonic-gate return; 24447c478bd9Sstevel@tonic-gate 24457c478bd9Sstevel@tonic-gate if (ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) { 24467c478bd9Sstevel@tonic-gate buf_limit = 64; 24477c478bd9Sstevel@tonic-gate 24487c478bd9Sstevel@tonic-gate /* compute number of bytes mod 64 */ 24497c478bd9Sstevel@tonic-gate buf_index = (ctx->count.c32[1] >> 3) & 0x3F; 24507c478bd9Sstevel@tonic-gate 24517c478bd9Sstevel@tonic-gate /* update number of bits */ 24527c478bd9Sstevel@tonic-gate if ((ctx->count.c32[1] += (input_len << 3)) < (input_len << 3)) 24537c478bd9Sstevel@tonic-gate ctx->count.c32[0]++; 24547c478bd9Sstevel@tonic-gate 24557c478bd9Sstevel@tonic-gate ctx->count.c32[0] += (input_len >> 29); 24567c478bd9Sstevel@tonic-gate 24577c478bd9Sstevel@tonic-gate } else { 24587c478bd9Sstevel@tonic-gate buf_limit = 128; 24597c478bd9Sstevel@tonic-gate 24607c478bd9Sstevel@tonic-gate /* compute number of bytes mod 128 */ 24617c478bd9Sstevel@tonic-gate buf_index = (ctx->count.c64[1] >> 3) & 0x7F; 24627c478bd9Sstevel@tonic-gate 24637c478bd9Sstevel@tonic-gate /* update number of bits */ 24647c478bd9Sstevel@tonic-gate if ((ctx->count.c64[1] += (input_len << 3)) < (input_len << 3)) 24657c478bd9Sstevel@tonic-gate ctx->count.c64[0]++; 24667c478bd9Sstevel@tonic-gate 24677c478bd9Sstevel@tonic-gate ctx->count.c64[0] += (input_len >> 29); 24687c478bd9Sstevel@tonic-gate } 24697c478bd9Sstevel@tonic-gate 24707c478bd9Sstevel@tonic-gate buf_len = buf_limit - buf_index; 24717c478bd9Sstevel@tonic-gate 24727c478bd9Sstevel@tonic-gate /* transform as many times as possible */ 24737c478bd9Sstevel@tonic-gate i = 0; 24747c478bd9Sstevel@tonic-gate if (input_len >= buf_len) { 24757c478bd9Sstevel@tonic-gate 24767c478bd9Sstevel@tonic-gate /* 24777c478bd9Sstevel@tonic-gate * general optimization: 24787c478bd9Sstevel@tonic-gate * 24797c478bd9Sstevel@tonic-gate * only do initial bcopy() and SHA2Transform() if 24807c478bd9Sstevel@tonic-gate * buf_index != 0. if buf_index == 0, we're just 24817c478bd9Sstevel@tonic-gate * wasting our time doing the bcopy() since there 24827c478bd9Sstevel@tonic-gate * wasn't any data left over from a previous call to 24837c478bd9Sstevel@tonic-gate * SHA2Update(). 24847c478bd9Sstevel@tonic-gate */ 24857c478bd9Sstevel@tonic-gate if (buf_index) { 24867c478bd9Sstevel@tonic-gate bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len); 24877c478bd9Sstevel@tonic-gate if (ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) 24887c478bd9Sstevel@tonic-gate SHA256Transform(ctx, ctx->buf_un.buf8); 24897c478bd9Sstevel@tonic-gate else 24907c478bd9Sstevel@tonic-gate SHA512Transform(ctx, ctx->buf_un.buf8); 24917c478bd9Sstevel@tonic-gate 24927c478bd9Sstevel@tonic-gate i = buf_len; 24937c478bd9Sstevel@tonic-gate } 24947c478bd9Sstevel@tonic-gate 24957c478bd9Sstevel@tonic-gate 24967c478bd9Sstevel@tonic-gate for (; i + buf_limit - 1 < input_len; i += buf_limit) { 24977c478bd9Sstevel@tonic-gate if (ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) 24987c478bd9Sstevel@tonic-gate SHA256Transform(ctx, &input[i]); 24997c478bd9Sstevel@tonic-gate else 25007c478bd9Sstevel@tonic-gate SHA512Transform(ctx, &input[i]); 25017c478bd9Sstevel@tonic-gate } 25027c478bd9Sstevel@tonic-gate 25037c478bd9Sstevel@tonic-gate /* 25047c478bd9Sstevel@tonic-gate * general optimization: 25057c478bd9Sstevel@tonic-gate * 25067c478bd9Sstevel@tonic-gate * if i and input_len are the same, return now instead 25077c478bd9Sstevel@tonic-gate * of calling bcopy(), since the bcopy() in this case 25087c478bd9Sstevel@tonic-gate * will be an expensive nop. 25097c478bd9Sstevel@tonic-gate */ 25107c478bd9Sstevel@tonic-gate 25117c478bd9Sstevel@tonic-gate if (input_len == i) 25127c478bd9Sstevel@tonic-gate return; 25137c478bd9Sstevel@tonic-gate 25147c478bd9Sstevel@tonic-gate buf_index = 0; 25157c478bd9Sstevel@tonic-gate } 25167c478bd9Sstevel@tonic-gate 25177c478bd9Sstevel@tonic-gate /* buffer remaining input */ 25187c478bd9Sstevel@tonic-gate bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i); 25197c478bd9Sstevel@tonic-gate } 25207c478bd9Sstevel@tonic-gate 25217c478bd9Sstevel@tonic-gate 25227c478bd9Sstevel@tonic-gate /* 25237c478bd9Sstevel@tonic-gate * SHA2Final() 25247c478bd9Sstevel@tonic-gate * 25257c478bd9Sstevel@tonic-gate * purpose: ends an sha2 digest operation, finalizing the message digest and 25267c478bd9Sstevel@tonic-gate * zeroing the context. 25277c478bd9Sstevel@tonic-gate * input: uint8_t * : a buffer to store the digest in 25287c478bd9Sstevel@tonic-gate * SHA2_CTX * : the context to finalize, save, and zero 25297c478bd9Sstevel@tonic-gate * output: void 25307c478bd9Sstevel@tonic-gate */ 25317c478bd9Sstevel@tonic-gate 25327c478bd9Sstevel@tonic-gate 25337c478bd9Sstevel@tonic-gate void 25347c478bd9Sstevel@tonic-gate SHA2Final(uint8_t *digest, SHA2_CTX *ctx) 25357c478bd9Sstevel@tonic-gate { 25367c478bd9Sstevel@tonic-gate uint8_t bitcount_be[sizeof (ctx->count.c32)]; 25377c478bd9Sstevel@tonic-gate uint8_t bitcount_be64[sizeof (ctx->count.c64)]; 25387c478bd9Sstevel@tonic-gate uint32_t index; 25397c478bd9Sstevel@tonic-gate 25407c478bd9Sstevel@tonic-gate 25417c478bd9Sstevel@tonic-gate if (ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) { 25427c478bd9Sstevel@tonic-gate index = (ctx->count.c32[1] >> 3) & 0x3f; 25437c478bd9Sstevel@tonic-gate Encode(bitcount_be, ctx->count.c32, sizeof (bitcount_be)); 25447c478bd9Sstevel@tonic-gate SHA2Update(ctx, PADDING, ((index < 56) ? 56 : 120) - index); 25457c478bd9Sstevel@tonic-gate SHA2Update(ctx, bitcount_be, sizeof (bitcount_be)); 25467c478bd9Sstevel@tonic-gate Encode(digest, ctx->state.s32, sizeof (ctx->state.s32)); 25477c478bd9Sstevel@tonic-gate 25487c478bd9Sstevel@tonic-gate } else { 25497c478bd9Sstevel@tonic-gate index = (ctx->count.c64[1] >> 3) & 0x7f; 25507c478bd9Sstevel@tonic-gate Encode64(bitcount_be64, ctx->count.c64, 25517c478bd9Sstevel@tonic-gate sizeof (bitcount_be64)); 25527c478bd9Sstevel@tonic-gate SHA2Update(ctx, PADDING, ((index < 112) ? 112 : 240) - index); 25537c478bd9Sstevel@tonic-gate SHA2Update(ctx, bitcount_be64, sizeof (bitcount_be64)); 25547c478bd9Sstevel@tonic-gate if (ctx->algotype <= SHA384_HMAC_GEN_MECH_INFO_TYPE) { 25557c478bd9Sstevel@tonic-gate ctx->state.s64[6] = ctx->state.s64[7] = 0; 25567c478bd9Sstevel@tonic-gate Encode64(digest, ctx->state.s64, 25577c478bd9Sstevel@tonic-gate sizeof (uint64_t) * 6); 25587c478bd9Sstevel@tonic-gate } else 25597c478bd9Sstevel@tonic-gate Encode64(digest, ctx->state.s64, 25607c478bd9Sstevel@tonic-gate sizeof (ctx->state.s64)); 25617c478bd9Sstevel@tonic-gate } 2562*673007c6Sdarrenm 2563*673007c6Sdarrenm /* zeroize sensitive information */ 2564*673007c6Sdarrenm bzero(ctx, sizeof (*ctx)); 25657c478bd9Sstevel@tonic-gate } 2566