xref: /freebsd-src/sys/contrib/openzfs/module/icp/algs/sha2/sha2_generic.c (revision 75e1fea68aaa613a20dfdcd0c59dd403aca02c49)
12a58b312SMartin Matuska /*
22a58b312SMartin Matuska  * CDDL HEADER START
32a58b312SMartin Matuska  *
42a58b312SMartin Matuska  * The contents of this file are subject to the terms of the
52a58b312SMartin Matuska  * Common Development and Distribution License (the "License").
62a58b312SMartin Matuska  * You may not use this file except in compliance with the License.
72a58b312SMartin Matuska  *
82a58b312SMartin Matuska  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92a58b312SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
102a58b312SMartin Matuska  * See the License for the specific language governing permissions
112a58b312SMartin Matuska  * and limitations under the License.
122a58b312SMartin Matuska  *
132a58b312SMartin Matuska  * When distributing Covered Code, include this CDDL HEADER in each
142a58b312SMartin Matuska  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152a58b312SMartin Matuska  * If applicable, add the following below this CDDL HEADER, with the
162a58b312SMartin Matuska  * fields enclosed by brackets "[]" replaced with your own identifying
172a58b312SMartin Matuska  * information: Portions Copyright [yyyy] [name of copyright owner]
182a58b312SMartin Matuska  *
192a58b312SMartin Matuska  * CDDL HEADER END
202a58b312SMartin Matuska  */
212a58b312SMartin Matuska 
222a58b312SMartin Matuska /*
232a58b312SMartin Matuska  * Based on public domain code in cppcrypto 0.10.
242a58b312SMartin Matuska  * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
252a58b312SMartin Matuska  */
262a58b312SMartin Matuska 
272a58b312SMartin Matuska #include <sys/zfs_context.h>
282a58b312SMartin Matuska #include <sys/zfs_impl.h>
292a58b312SMartin Matuska #include <sys/sha2.h>
302a58b312SMartin Matuska 
312a58b312SMartin Matuska #include <sha2/sha2_impl.h>
322a58b312SMartin Matuska 
332a58b312SMartin Matuska /*
342a58b312SMartin Matuska  * On i386, gcc brings this for sha512_generic():
352a58b312SMartin Matuska  * error: the frame size of 1040 bytes is larger than 1024
362a58b312SMartin Matuska  */
372a58b312SMartin Matuska #if defined(__GNUC__) && defined(_ILP32)
382a58b312SMartin Matuska #pragma GCC diagnostic ignored "-Wframe-larger-than="
392a58b312SMartin Matuska #endif
402a58b312SMartin Matuska 
412a58b312SMartin Matuska /* SHA256 */
422a58b312SMartin Matuska static const uint32_t SHA256_K[64] = {
432a58b312SMartin Matuska 	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
442a58b312SMartin Matuska 	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
452a58b312SMartin Matuska 	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
462a58b312SMartin Matuska 	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
472a58b312SMartin Matuska 	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
482a58b312SMartin Matuska 	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
492a58b312SMartin Matuska 	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
502a58b312SMartin Matuska 	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
512a58b312SMartin Matuska 	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
522a58b312SMartin Matuska 	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
532a58b312SMartin Matuska 	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
542a58b312SMartin Matuska 	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
552a58b312SMartin Matuska 	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
562a58b312SMartin Matuska 	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
572a58b312SMartin Matuska 	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
582a58b312SMartin Matuska 	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
592a58b312SMartin Matuska };
602a58b312SMartin Matuska 
612a58b312SMartin Matuska #define	Ch(x, y, z)	((z) ^ ((x) & ((y) ^ (z))))
622a58b312SMartin Matuska #define	Maj(x, y, z)	(((y) & (z)) | (((y) | (z)) & (x)))
632a58b312SMartin Matuska 
642a58b312SMartin Matuska #define	rotr32(x, n)	(((x) >> n) | ((x) << (32 - n)))
652a58b312SMartin Matuska #define	sum0(x)		(rotr32((x),  2) ^ rotr32((x), 13) ^ rotr32((x), 22))
662a58b312SMartin Matuska #define	sum1(x)		(rotr32((x),  6) ^ rotr32((x), 11) ^ rotr32((x), 25))
672a58b312SMartin Matuska #define	sigma0(x)	(rotr32((x),  7) ^ rotr32((x), 18) ^ ((x) >> 3))
682a58b312SMartin Matuska #define	sigma1(x)	(rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10))
692a58b312SMartin Matuska 
702a58b312SMartin Matuska #define	WU(j) (W[j & 15] += sigma1(W[(j + 14) & 15]) \
712a58b312SMartin Matuska 	+ W[(j + 9) & 15] + sigma0(W[(j + 1) & 15]))
722a58b312SMartin Matuska 
732a58b312SMartin Matuska #define	COMPRESS(i, j, K) \
742a58b312SMartin Matuska 	T1 = h + sum1(e) + Ch(e, f, g) + K[i + j] + (i? WU(j): W[j]); \
752a58b312SMartin Matuska 	T2 = sum0(a) + Maj(a, b, c); \
762a58b312SMartin Matuska 	h = g, g = f, f = e, e = d + T1; \
772a58b312SMartin Matuska 	d = c, c = b, b = a, a = T1 + T2;
782a58b312SMartin Matuska 
792a58b312SMartin Matuska static void sha256_generic(uint32_t state[8], const void *data, size_t num_blks)
802a58b312SMartin Matuska {
812a58b312SMartin Matuska 	uint64_t blk;
822a58b312SMartin Matuska 
832a58b312SMartin Matuska 	for (blk = 0; blk < num_blks; blk++) {
842a58b312SMartin Matuska 		uint32_t W[16];
852a58b312SMartin Matuska 		uint32_t a, b, c, d, e, f, g, h;
862a58b312SMartin Matuska 		uint32_t T1, T2;
872a58b312SMartin Matuska 		int i;
882a58b312SMartin Matuska 
892a58b312SMartin Matuska 		for (i = 0; i < 16; i++) {
902a58b312SMartin Matuska 			W[i] = BE_32( \
912a58b312SMartin Matuska 			    (((const uint32_t *)(data))[blk * 16 + i]));
922a58b312SMartin Matuska 		}
932a58b312SMartin Matuska 
942a58b312SMartin Matuska 		a = state[0];
952a58b312SMartin Matuska 		b = state[1];
962a58b312SMartin Matuska 		c = state[2];
972a58b312SMartin Matuska 		d = state[3];
982a58b312SMartin Matuska 		e = state[4];
992a58b312SMartin Matuska 		f = state[5];
1002a58b312SMartin Matuska 		g = state[6];
1012a58b312SMartin Matuska 		h = state[7];
1022a58b312SMartin Matuska 
1032a58b312SMartin Matuska 		for (i = 0; i <= 63; i += 16) {
1042a58b312SMartin Matuska 			COMPRESS(i, 0, SHA256_K);
1052a58b312SMartin Matuska 			COMPRESS(i, 1, SHA256_K);
1062a58b312SMartin Matuska 			COMPRESS(i, 2, SHA256_K);
1072a58b312SMartin Matuska 			COMPRESS(i, 3, SHA256_K);
1082a58b312SMartin Matuska 			COMPRESS(i, 4, SHA256_K);
1092a58b312SMartin Matuska 			COMPRESS(i, 5, SHA256_K);
1102a58b312SMartin Matuska 			COMPRESS(i, 6, SHA256_K);
1112a58b312SMartin Matuska 			COMPRESS(i, 7, SHA256_K);
1122a58b312SMartin Matuska 			COMPRESS(i, 8, SHA256_K);
1132a58b312SMartin Matuska 			COMPRESS(i, 9, SHA256_K);
1142a58b312SMartin Matuska 			COMPRESS(i, 10, SHA256_K);
1152a58b312SMartin Matuska 			COMPRESS(i, 11, SHA256_K);
1162a58b312SMartin Matuska 			COMPRESS(i, 12, SHA256_K);
1172a58b312SMartin Matuska 			COMPRESS(i, 13, SHA256_K);
1182a58b312SMartin Matuska 			COMPRESS(i, 14, SHA256_K);
1192a58b312SMartin Matuska 			COMPRESS(i, 15, SHA256_K);
1202a58b312SMartin Matuska 		}
1212a58b312SMartin Matuska 
1222a58b312SMartin Matuska 		state[0] += a;
1232a58b312SMartin Matuska 		state[1] += b;
1242a58b312SMartin Matuska 		state[2] += c;
1252a58b312SMartin Matuska 		state[3] += d;
1262a58b312SMartin Matuska 		state[4] += e;
1272a58b312SMartin Matuska 		state[5] += f;
1282a58b312SMartin Matuska 		state[6] += g;
1292a58b312SMartin Matuska 		state[7] += h;
1302a58b312SMartin Matuska 	}
1312a58b312SMartin Matuska }
1322a58b312SMartin Matuska 
1332a58b312SMartin Matuska #undef sum0
1342a58b312SMartin Matuska #undef sum1
1352a58b312SMartin Matuska #undef sigma0
1362a58b312SMartin Matuska #undef sigma1
1372a58b312SMartin Matuska 
1382a58b312SMartin Matuska #define	rotr64(x, n)	(((x) >> n) | ((x) << (64 - n)))
1392a58b312SMartin Matuska #define	sum0(x)		(rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39))
1402a58b312SMartin Matuska #define	sum1(x)		(rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41))
1412a58b312SMartin Matuska #define	sigma0(x)	(rotr64((x),  1) ^ rotr64((x),  8) ^ ((x) >> 7))
1422a58b312SMartin Matuska #define	sigma1(x)	(rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6))
1432a58b312SMartin Matuska 
1442a58b312SMartin Matuska /* SHA512 */
1452a58b312SMartin Matuska static const uint64_t SHA512_K[80] = {
1462a58b312SMartin Matuska 	0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
1472a58b312SMartin Matuska 	0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
1482a58b312SMartin Matuska 	0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
1492a58b312SMartin Matuska 	0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
1502a58b312SMartin Matuska 	0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
1512a58b312SMartin Matuska 	0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
1522a58b312SMartin Matuska 	0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
1532a58b312SMartin Matuska 	0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
1542a58b312SMartin Matuska 	0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
1552a58b312SMartin Matuska 	0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
1562a58b312SMartin Matuska 	0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
1572a58b312SMartin Matuska 	0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
1582a58b312SMartin Matuska 	0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
1592a58b312SMartin Matuska 	0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
1602a58b312SMartin Matuska 	0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
1612a58b312SMartin Matuska 	0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
1622a58b312SMartin Matuska 	0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
1632a58b312SMartin Matuska 	0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
1642a58b312SMartin Matuska 	0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
1652a58b312SMartin Matuska 	0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
1662a58b312SMartin Matuska 	0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
1672a58b312SMartin Matuska 	0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
1682a58b312SMartin Matuska 	0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
1692a58b312SMartin Matuska 	0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
1702a58b312SMartin Matuska 	0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
1712a58b312SMartin Matuska 	0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
1722a58b312SMartin Matuska 	0x5fcb6fab3ad6faec, 0x6c44198c4a475817
1732a58b312SMartin Matuska };
1742a58b312SMartin Matuska 
1752a58b312SMartin Matuska static void sha512_generic(uint64_t state[8], const void *data, size_t num_blks)
1762a58b312SMartin Matuska {
1772a58b312SMartin Matuska 	uint64_t blk;
1782a58b312SMartin Matuska 
1792a58b312SMartin Matuska 	for (blk = 0; blk < num_blks; blk++) {
1802a58b312SMartin Matuska 		uint64_t W[16];
1812a58b312SMartin Matuska 		uint64_t a, b, c, d, e, f, g, h;
1822a58b312SMartin Matuska 		uint64_t T1, T2;
1832a58b312SMartin Matuska 		int i;
1842a58b312SMartin Matuska 
1852a58b312SMartin Matuska 		for (i = 0; i < 16; i++) {
1862a58b312SMartin Matuska 			W[i] = BE_64( \
1872a58b312SMartin Matuska 			    (((const uint64_t *)(data))[blk * 16 + i]));
1882a58b312SMartin Matuska 		}
1892a58b312SMartin Matuska 
1902a58b312SMartin Matuska 		a = state[0];
1912a58b312SMartin Matuska 		b = state[1];
1922a58b312SMartin Matuska 		c = state[2];
1932a58b312SMartin Matuska 		d = state[3];
1942a58b312SMartin Matuska 		e = state[4];
1952a58b312SMartin Matuska 		f = state[5];
1962a58b312SMartin Matuska 		g = state[6];
1972a58b312SMartin Matuska 		h = state[7];
1982a58b312SMartin Matuska 
1992a58b312SMartin Matuska 		for (i = 0; i <= 79; i += 16) {
2002a58b312SMartin Matuska 			COMPRESS(i, 0, SHA512_K);
2012a58b312SMartin Matuska 			COMPRESS(i, 1, SHA512_K);
2022a58b312SMartin Matuska 			COMPRESS(i, 2, SHA512_K);
2032a58b312SMartin Matuska 			COMPRESS(i, 3, SHA512_K);
2042a58b312SMartin Matuska 			COMPRESS(i, 4, SHA512_K);
2052a58b312SMartin Matuska 			COMPRESS(i, 5, SHA512_K);
2062a58b312SMartin Matuska 			COMPRESS(i, 6, SHA512_K);
2072a58b312SMartin Matuska 			COMPRESS(i, 7, SHA512_K);
2082a58b312SMartin Matuska 			COMPRESS(i, 8, SHA512_K);
2092a58b312SMartin Matuska 			COMPRESS(i, 9, SHA512_K);
2102a58b312SMartin Matuska 			COMPRESS(i, 10, SHA512_K);
2112a58b312SMartin Matuska 			COMPRESS(i, 11, SHA512_K);
2122a58b312SMartin Matuska 			COMPRESS(i, 12, SHA512_K);
2132a58b312SMartin Matuska 			COMPRESS(i, 13, SHA512_K);
2142a58b312SMartin Matuska 			COMPRESS(i, 14, SHA512_K);
2152a58b312SMartin Matuska 			COMPRESS(i, 15, SHA512_K);
2162a58b312SMartin Matuska 		}
2172a58b312SMartin Matuska 		state[0] += a;
2182a58b312SMartin Matuska 		state[1] += b;
2192a58b312SMartin Matuska 		state[2] += c;
2202a58b312SMartin Matuska 		state[3] += d;
2212a58b312SMartin Matuska 		state[4] += e;
2222a58b312SMartin Matuska 		state[5] += f;
2232a58b312SMartin Matuska 		state[6] += g;
2242a58b312SMartin Matuska 		state[7] += h;
2252a58b312SMartin Matuska 	}
2262a58b312SMartin Matuska }
2272a58b312SMartin Matuska 
2282a58b312SMartin Matuska static void sha256_update(sha256_ctx *ctx, const uint8_t *data, size_t len)
2292a58b312SMartin Matuska {
2302a58b312SMartin Matuska 	uint64_t pos = ctx->count[0];
2312a58b312SMartin Matuska 	uint64_t total = ctx->count[1];
2322a58b312SMartin Matuska 	uint8_t *m = ctx->wbuf;
2332a58b312SMartin Matuska 	const sha256_ops_t *ops = ctx->ops;
2342a58b312SMartin Matuska 
2352a58b312SMartin Matuska 	if (pos && pos + len >= 64) {
2362a58b312SMartin Matuska 		memcpy(m + pos, data, 64 - pos);
2372a58b312SMartin Matuska 		ops->transform(ctx->state, m, 1);
2382a58b312SMartin Matuska 		len -= 64 - pos;
2392a58b312SMartin Matuska 		total += (64 - pos) * 8;
2402a58b312SMartin Matuska 		data += 64 - pos;
2412a58b312SMartin Matuska 		pos = 0;
2422a58b312SMartin Matuska 	}
2432a58b312SMartin Matuska 
2442a58b312SMartin Matuska 	if (len >= 64) {
2452a58b312SMartin Matuska 		uint32_t blocks = len / 64;
2462a58b312SMartin Matuska 		uint32_t bytes = blocks * 64;
2472a58b312SMartin Matuska 		ops->transform(ctx->state, data, blocks);
2482a58b312SMartin Matuska 		len -= bytes;
2492a58b312SMartin Matuska 		total += (bytes) * 8;
2502a58b312SMartin Matuska 		data += bytes;
2512a58b312SMartin Matuska 	}
2522a58b312SMartin Matuska 	memcpy(m + pos, data, len);
2532a58b312SMartin Matuska 
2542a58b312SMartin Matuska 	pos += len;
2552a58b312SMartin Matuska 	total += len * 8;
2562a58b312SMartin Matuska 	ctx->count[0] = pos;
2572a58b312SMartin Matuska 	ctx->count[1] = total;
2582a58b312SMartin Matuska }
2592a58b312SMartin Matuska 
2602a58b312SMartin Matuska static void sha512_update(sha512_ctx *ctx, const uint8_t *data, size_t len)
2612a58b312SMartin Matuska {
2622a58b312SMartin Matuska 	uint64_t pos = ctx->count[0];
2632a58b312SMartin Matuska 	uint64_t total = ctx->count[1];
2642a58b312SMartin Matuska 	uint8_t *m = ctx->wbuf;
2652a58b312SMartin Matuska 	const sha512_ops_t *ops = ctx->ops;
2662a58b312SMartin Matuska 
2672a58b312SMartin Matuska 	if (pos && pos + len >= 128) {
2682a58b312SMartin Matuska 		memcpy(m + pos, data, 128 - pos);
2692a58b312SMartin Matuska 		ops->transform(ctx->state, m, 1);
2702a58b312SMartin Matuska 		len -= 128 - pos;
2712a58b312SMartin Matuska 		total += (128 - pos) * 8;
2722a58b312SMartin Matuska 		data += 128 - pos;
2732a58b312SMartin Matuska 		pos = 0;
2742a58b312SMartin Matuska 	}
2752a58b312SMartin Matuska 
2762a58b312SMartin Matuska 	if (len >= 128) {
2772a58b312SMartin Matuska 		uint64_t blocks = len / 128;
2782a58b312SMartin Matuska 		uint64_t bytes = blocks * 128;
2792a58b312SMartin Matuska 		ops->transform(ctx->state, data, blocks);
2802a58b312SMartin Matuska 		len -= bytes;
2812a58b312SMartin Matuska 		total += (bytes) * 8;
2822a58b312SMartin Matuska 		data += bytes;
2832a58b312SMartin Matuska 	}
2842a58b312SMartin Matuska 	memcpy(m + pos, data, len);
2852a58b312SMartin Matuska 
2862a58b312SMartin Matuska 	pos += len;
2872a58b312SMartin Matuska 	total += len * 8;
2882a58b312SMartin Matuska 	ctx->count[0] = pos;
2892a58b312SMartin Matuska 	ctx->count[1] = total;
2902a58b312SMartin Matuska }
2912a58b312SMartin Matuska 
2922a58b312SMartin Matuska static void sha256_final(sha256_ctx *ctx, uint8_t *result, int bits)
2932a58b312SMartin Matuska {
2942a58b312SMartin Matuska 	uint64_t mlen, pos = ctx->count[0];
2952a58b312SMartin Matuska 	uint8_t *m = ctx->wbuf;
2962a58b312SMartin Matuska 	uint32_t *R = (uint32_t *)result;
2972a58b312SMartin Matuska 	const sha256_ops_t *ops = ctx->ops;
2982a58b312SMartin Matuska 
2992a58b312SMartin Matuska 	m[pos++] = 0x80;
3002a58b312SMartin Matuska 	if (pos > 56) {
3012a58b312SMartin Matuska 		memset(m + pos, 0, 64 - pos);
3022a58b312SMartin Matuska 		ops->transform(ctx->state, m, 1);
3032a58b312SMartin Matuska 		pos = 0;
3042a58b312SMartin Matuska 	}
3052a58b312SMartin Matuska 
3062a58b312SMartin Matuska 	memset(m + pos, 0, 64 - pos);
3072a58b312SMartin Matuska 	mlen = BE_64(ctx->count[1]);
3082a58b312SMartin Matuska 	memcpy(m + (64 - 8), &mlen, 64 / 8);
3092a58b312SMartin Matuska 	ops->transform(ctx->state, m, 1);
3102a58b312SMartin Matuska 
3112a58b312SMartin Matuska 	switch (bits) {
3122a58b312SMartin Matuska 	case 224: /* 28 - unused currently /TR */
3132a58b312SMartin Matuska 		R[0] = BE_32(ctx->state[0]);
3142a58b312SMartin Matuska 		R[1] = BE_32(ctx->state[1]);
3152a58b312SMartin Matuska 		R[2] = BE_32(ctx->state[2]);
3162a58b312SMartin Matuska 		R[3] = BE_32(ctx->state[3]);
3172a58b312SMartin Matuska 		R[4] = BE_32(ctx->state[4]);
3182a58b312SMartin Matuska 		R[5] = BE_32(ctx->state[5]);
3192a58b312SMartin Matuska 		R[6] = BE_32(ctx->state[6]);
3202a58b312SMartin Matuska 		break;
3212a58b312SMartin Matuska 	case 256: /* 32 */
3222a58b312SMartin Matuska 		R[0] = BE_32(ctx->state[0]);
3232a58b312SMartin Matuska 		R[1] = BE_32(ctx->state[1]);
3242a58b312SMartin Matuska 		R[2] = BE_32(ctx->state[2]);
3252a58b312SMartin Matuska 		R[3] = BE_32(ctx->state[3]);
3262a58b312SMartin Matuska 		R[4] = BE_32(ctx->state[4]);
3272a58b312SMartin Matuska 		R[5] = BE_32(ctx->state[5]);
3282a58b312SMartin Matuska 		R[6] = BE_32(ctx->state[6]);
3292a58b312SMartin Matuska 		R[7] = BE_32(ctx->state[7]);
3302a58b312SMartin Matuska 		break;
3312a58b312SMartin Matuska 	}
3322a58b312SMartin Matuska 
3332a58b312SMartin Matuska 	memset(ctx, 0, sizeof (*ctx));
3342a58b312SMartin Matuska }
3352a58b312SMartin Matuska 
3362a58b312SMartin Matuska static void sha512_final(sha512_ctx *ctx, uint8_t *result, int bits)
3372a58b312SMartin Matuska {
3382a58b312SMartin Matuska 	uint64_t mlen, pos = ctx->count[0];
3392a58b312SMartin Matuska 	uint8_t *m = ctx->wbuf, *r;
3402a58b312SMartin Matuska 	uint64_t *R = (uint64_t *)result;
3412a58b312SMartin Matuska 	const sha512_ops_t *ops = ctx->ops;
3422a58b312SMartin Matuska 
3432a58b312SMartin Matuska 	m[pos++] = 0x80;
3442a58b312SMartin Matuska 	if (pos > 112) {
3452a58b312SMartin Matuska 		memset(m + pos, 0, 128 - pos);
3462a58b312SMartin Matuska 		ops->transform(ctx->state, m, 1);
3472a58b312SMartin Matuska 		pos = 0;
3482a58b312SMartin Matuska 	}
3492a58b312SMartin Matuska 
3502a58b312SMartin Matuska 	memset(m + pos, 0, 128 - pos);
3512a58b312SMartin Matuska 	mlen = BE_64(ctx->count[1]);
3522a58b312SMartin Matuska 	memcpy(m + (128 - 8), &mlen, 64 / 8);
3532a58b312SMartin Matuska 	ops->transform(ctx->state, m, 1);
3542a58b312SMartin Matuska 
3552a58b312SMartin Matuska 	switch (bits) {
3562a58b312SMartin Matuska 	case 224: /* 28 => 3,5 x 8 */
3572a58b312SMartin Matuska 		r = result + 24;
3582a58b312SMartin Matuska 		R[0] = BE_64(ctx->state[0]);
3592a58b312SMartin Matuska 		R[1] = BE_64(ctx->state[1]);
3602a58b312SMartin Matuska 		R[2] = BE_64(ctx->state[2]);
3612a58b312SMartin Matuska 		/* last 4 bytes are special here */
3622a58b312SMartin Matuska 		*r++ = (uint8_t)(ctx->state[3] >> 56);
3632a58b312SMartin Matuska 		*r++ = (uint8_t)(ctx->state[3] >> 48);
3642a58b312SMartin Matuska 		*r++ = (uint8_t)(ctx->state[3] >> 40);
3652a58b312SMartin Matuska 		*r++ = (uint8_t)(ctx->state[3] >> 32);
3662a58b312SMartin Matuska 		break;
3672a58b312SMartin Matuska 	case 256: /* 32 */
3682a58b312SMartin Matuska 		R[0] = BE_64(ctx->state[0]);
3692a58b312SMartin Matuska 		R[1] = BE_64(ctx->state[1]);
3702a58b312SMartin Matuska 		R[2] = BE_64(ctx->state[2]);
3712a58b312SMartin Matuska 		R[3] = BE_64(ctx->state[3]);
3722a58b312SMartin Matuska 		break;
3732a58b312SMartin Matuska 	case 384: /* 48 */
3742a58b312SMartin Matuska 		R[0] = BE_64(ctx->state[0]);
3752a58b312SMartin Matuska 		R[1] = BE_64(ctx->state[1]);
3762a58b312SMartin Matuska 		R[2] = BE_64(ctx->state[2]);
3772a58b312SMartin Matuska 		R[3] = BE_64(ctx->state[3]);
3782a58b312SMartin Matuska 		R[4] = BE_64(ctx->state[4]);
3792a58b312SMartin Matuska 		R[5] = BE_64(ctx->state[5]);
3802a58b312SMartin Matuska 		break;
3812a58b312SMartin Matuska 	case 512: /* 64 */
3822a58b312SMartin Matuska 		R[0] = BE_64(ctx->state[0]);
3832a58b312SMartin Matuska 		R[1] = BE_64(ctx->state[1]);
3842a58b312SMartin Matuska 		R[2] = BE_64(ctx->state[2]);
3852a58b312SMartin Matuska 		R[3] = BE_64(ctx->state[3]);
3862a58b312SMartin Matuska 		R[4] = BE_64(ctx->state[4]);
3872a58b312SMartin Matuska 		R[5] = BE_64(ctx->state[5]);
3882a58b312SMartin Matuska 		R[6] = BE_64(ctx->state[6]);
3892a58b312SMartin Matuska 		R[7] = BE_64(ctx->state[7]);
3902a58b312SMartin Matuska 		break;
3912a58b312SMartin Matuska 	}
3922a58b312SMartin Matuska 
3932a58b312SMartin Matuska 	memset(ctx, 0, sizeof (*ctx));
3942a58b312SMartin Matuska }
3952a58b312SMartin Matuska 
3962a58b312SMartin Matuska /* SHA2 Init function */
3972a58b312SMartin Matuska void
3982a58b312SMartin Matuska SHA2Init(int algotype, SHA2_CTX *ctx)
3992a58b312SMartin Matuska {
4002a58b312SMartin Matuska 	sha256_ctx *ctx256 = &ctx->sha256;
4012a58b312SMartin Matuska 	sha512_ctx *ctx512 = &ctx->sha512;
4022a58b312SMartin Matuska 
403*75e1fea6SMartin Matuska 	ASSERT3S(algotype, >=, SHA512_HMAC_MECH_INFO_TYPE);
404*75e1fea6SMartin Matuska 	ASSERT3S(algotype, <=, SHA512_256);
4052a58b312SMartin Matuska 
4062a58b312SMartin Matuska 	memset(ctx, 0, sizeof (*ctx));
4072a58b312SMartin Matuska 	ctx->algotype = algotype;
4082a58b312SMartin Matuska 	switch (ctx->algotype) {
409*75e1fea6SMartin Matuska 		case SHA256:
4102a58b312SMartin Matuska 			ctx256->state[0] = 0x6a09e667;
4112a58b312SMartin Matuska 			ctx256->state[1] = 0xbb67ae85;
4122a58b312SMartin Matuska 			ctx256->state[2] = 0x3c6ef372;
4132a58b312SMartin Matuska 			ctx256->state[3] = 0xa54ff53a;
4142a58b312SMartin Matuska 			ctx256->state[4] = 0x510e527f;
4152a58b312SMartin Matuska 			ctx256->state[5] = 0x9b05688c;
4162a58b312SMartin Matuska 			ctx256->state[6] = 0x1f83d9ab;
4172a58b312SMartin Matuska 			ctx256->state[7] = 0x5be0cd19;
4182a58b312SMartin Matuska 			ctx256->count[0] = 0;
4192a58b312SMartin Matuska 			ctx256->ops = sha256_get_ops();
4202a58b312SMartin Matuska 			break;
421*75e1fea6SMartin Matuska 		case SHA512:
4222a58b312SMartin Matuska 		case SHA512_HMAC_MECH_INFO_TYPE:
4232a58b312SMartin Matuska 			ctx512->state[0] = 0x6a09e667f3bcc908ULL;
4242a58b312SMartin Matuska 			ctx512->state[1] = 0xbb67ae8584caa73bULL;
4252a58b312SMartin Matuska 			ctx512->state[2] = 0x3c6ef372fe94f82bULL;
4262a58b312SMartin Matuska 			ctx512->state[3] = 0xa54ff53a5f1d36f1ULL;
4272a58b312SMartin Matuska 			ctx512->state[4] = 0x510e527fade682d1ULL;
4282a58b312SMartin Matuska 			ctx512->state[5] = 0x9b05688c2b3e6c1fULL;
4292a58b312SMartin Matuska 			ctx512->state[6] = 0x1f83d9abfb41bd6bULL;
4302a58b312SMartin Matuska 			ctx512->state[7] = 0x5be0cd19137e2179ULL;
4312a58b312SMartin Matuska 			ctx512->count[0] = 0;
4322a58b312SMartin Matuska 			ctx512->count[1] = 0;
4332a58b312SMartin Matuska 			ctx512->ops = sha512_get_ops();
4342a58b312SMartin Matuska 			break;
435*75e1fea6SMartin Matuska 		case SHA512_256:
4362a58b312SMartin Matuska 			ctx512->state[0] = 0x22312194fc2bf72cULL;
4372a58b312SMartin Matuska 			ctx512->state[1] = 0x9f555fa3c84c64c2ULL;
4382a58b312SMartin Matuska 			ctx512->state[2] = 0x2393b86b6f53b151ULL;
4392a58b312SMartin Matuska 			ctx512->state[3] = 0x963877195940eabdULL;
4402a58b312SMartin Matuska 			ctx512->state[4] = 0x96283ee2a88effe3ULL;
4412a58b312SMartin Matuska 			ctx512->state[5] = 0xbe5e1e2553863992ULL;
4422a58b312SMartin Matuska 			ctx512->state[6] = 0x2b0199fc2c85b8aaULL;
4432a58b312SMartin Matuska 			ctx512->state[7] = 0x0eb72ddc81c52ca2ULL;
4442a58b312SMartin Matuska 			ctx512->count[0] = 0;
4452a58b312SMartin Matuska 			ctx512->count[1] = 0;
4462a58b312SMartin Matuska 			ctx512->ops = sha512_get_ops();
4472a58b312SMartin Matuska 			break;
4482a58b312SMartin Matuska 	}
4492a58b312SMartin Matuska }
4502a58b312SMartin Matuska 
4512a58b312SMartin Matuska /* SHA2 Update function */
4522a58b312SMartin Matuska void
4532a58b312SMartin Matuska SHA2Update(SHA2_CTX *ctx, const void *data, size_t len)
4542a58b312SMartin Matuska {
4552a58b312SMartin Matuska 	/* check for zero input length */
4562a58b312SMartin Matuska 	if (len == 0)
4572a58b312SMartin Matuska 		return;
4582a58b312SMartin Matuska 
4592a58b312SMartin Matuska 	ASSERT3P(data, !=, NULL);
4602a58b312SMartin Matuska 
4612a58b312SMartin Matuska 	switch (ctx->algotype) {
462*75e1fea6SMartin Matuska 		case SHA256:
4632a58b312SMartin Matuska 			sha256_update(&ctx->sha256, data, len);
4642a58b312SMartin Matuska 			break;
465*75e1fea6SMartin Matuska 		case SHA512:
4662a58b312SMartin Matuska 		case SHA512_HMAC_MECH_INFO_TYPE:
4672a58b312SMartin Matuska 			sha512_update(&ctx->sha512, data, len);
4682a58b312SMartin Matuska 			break;
469*75e1fea6SMartin Matuska 		case SHA512_256:
4702a58b312SMartin Matuska 			sha512_update(&ctx->sha512, data, len);
4712a58b312SMartin Matuska 			break;
4722a58b312SMartin Matuska 	}
4732a58b312SMartin Matuska }
4742a58b312SMartin Matuska 
4752a58b312SMartin Matuska /* SHA2Final function */
4762a58b312SMartin Matuska void
4772a58b312SMartin Matuska SHA2Final(void *digest, SHA2_CTX *ctx)
4782a58b312SMartin Matuska {
4792a58b312SMartin Matuska 	switch (ctx->algotype) {
480*75e1fea6SMartin Matuska 		case SHA256:
4812a58b312SMartin Matuska 			sha256_final(&ctx->sha256, digest, 256);
4822a58b312SMartin Matuska 			break;
483*75e1fea6SMartin Matuska 		case SHA512:
4842a58b312SMartin Matuska 		case SHA512_HMAC_MECH_INFO_TYPE:
4852a58b312SMartin Matuska 			sha512_final(&ctx->sha512, digest, 512);
4862a58b312SMartin Matuska 			break;
487*75e1fea6SMartin Matuska 		case SHA512_256:
4882a58b312SMartin Matuska 			sha512_final(&ctx->sha512, digest, 256);
4892a58b312SMartin Matuska 			break;
4902a58b312SMartin Matuska 	}
4912a58b312SMartin Matuska }
4922a58b312SMartin Matuska 
4932a58b312SMartin Matuska /* the generic implementation is always okay */
4942a58b312SMartin Matuska static boolean_t sha2_is_supported(void)
4952a58b312SMartin Matuska {
4962a58b312SMartin Matuska 	return (B_TRUE);
4972a58b312SMartin Matuska }
4982a58b312SMartin Matuska 
4992a58b312SMartin Matuska const sha256_ops_t sha256_generic_impl = {
5002a58b312SMartin Matuska 	.name = "generic",
5012a58b312SMartin Matuska 	.transform = sha256_generic,
5022a58b312SMartin Matuska 	.is_supported = sha2_is_supported
5032a58b312SMartin Matuska };
5042a58b312SMartin Matuska 
5052a58b312SMartin Matuska const sha512_ops_t sha512_generic_impl = {
5062a58b312SMartin Matuska 	.name = "generic",
5072a58b312SMartin Matuska 	.transform = sha512_generic,
5082a58b312SMartin Matuska 	.is_supported = sha2_is_supported
5092a58b312SMartin Matuska };
510