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