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