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