1*22649d4dSMartin Matuska // SPDX-License-Identifier: CDDL-1.0
2*22649d4dSMartin Matuska /*
3*22649d4dSMartin Matuska * This file and its contents are supplied under the terms of the
4*22649d4dSMartin Matuska * Common Development and Distribution License ("CDDL"), version 1.0.
5*22649d4dSMartin Matuska * You may only use this file in accordance with the terms of version
6*22649d4dSMartin Matuska * 1.0 of the CDDL.
7*22649d4dSMartin Matuska *
8*22649d4dSMartin Matuska * A full copy of the text of the CDDL should have accompanied this
9*22649d4dSMartin Matuska * source. A copy of the CDDL is also available via the Internet at
10*22649d4dSMartin Matuska * https://opensource.org/license/CDDL-1.0.
11*22649d4dSMartin Matuska */
12*22649d4dSMartin Matuska
13*22649d4dSMartin Matuska /*
14*22649d4dSMartin Matuska * Copyright (c) 2026, Christos Longros.
15*22649d4dSMartin Matuska */
16*22649d4dSMartin Matuska
17*22649d4dSMartin Matuska #include <string.h>
18*22649d4dSMartin Matuska
19*22649d4dSMartin Matuska #include <sys/types.h>
20*22649d4dSMartin Matuska #include <sys/sha2.h>
21*22649d4dSMartin Matuska #include <sys/zfs_impl.h>
22*22649d4dSMartin Matuska
23*22649d4dSMartin Matuska #include "unit.h"
24*22649d4dSMartin Matuska
25*22649d4dSMartin Matuska /* ========== */
26*22649d4dSMartin Matuska
27*22649d4dSMartin Matuska #define DATA_SIZE 8192
28*22649d4dSMartin Matuska
29*22649d4dSMartin Matuska static uint8_t databuf[DATA_SIZE] __attribute__((aligned(64)));
30*22649d4dSMartin Matuska
31*22649d4dSMartin Matuska static void
fill_data(void)32*22649d4dSMartin Matuska fill_data(void)
33*22649d4dSMartin Matuska {
34*22649d4dSMartin Matuska for (size_t i = 0; i < DATA_SIZE; i++)
35*22649d4dSMartin Matuska databuf[i] = (uint8_t)i;
36*22649d4dSMartin Matuska }
37*22649d4dSMartin Matuska
38*22649d4dSMartin Matuska static void
hash_buf(int algotype,const void * buf,size_t len,uint8_t * digest)39*22649d4dSMartin Matuska hash_buf(int algotype, const void *buf, size_t len, uint8_t *digest)
40*22649d4dSMartin Matuska {
41*22649d4dSMartin Matuska SHA2_CTX ctx;
42*22649d4dSMartin Matuska
43*22649d4dSMartin Matuska SHA2Init(algotype, &ctx);
44*22649d4dSMartin Matuska SHA2Update(&ctx, buf, len);
45*22649d4dSMartin Matuska SHA2Final(digest, &ctx);
46*22649d4dSMartin Matuska }
47*22649d4dSMartin Matuska
48*22649d4dSMartin Matuska /* ========== */
49*22649d4dSMartin Matuska
50*22649d4dSMartin Matuska /*
51*22649d4dSMartin Matuska * Test messages and digests from:
52*22649d4dSMartin Matuska * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
53*22649d4dSMartin Matuska */
54*22649d4dSMartin Matuska
55*22649d4dSMartin Matuska static const char *test_msg0 = "abc";
56*22649d4dSMartin Matuska static const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklm"
57*22649d4dSMartin Matuska "nlmnomnopnopq";
58*22649d4dSMartin Matuska static const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfgh"
59*22649d4dSMartin Matuska "ijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
60*22649d4dSMartin Matuska
61*22649d4dSMartin Matuska static const uint8_t sha256_test_digests[][32] = {
62*22649d4dSMartin Matuska {
63*22649d4dSMartin Matuska /* for test_msg0 */
64*22649d4dSMartin Matuska 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
65*22649d4dSMartin Matuska 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
66*22649d4dSMartin Matuska 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
67*22649d4dSMartin Matuska 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD
68*22649d4dSMartin Matuska },
69*22649d4dSMartin Matuska {
70*22649d4dSMartin Matuska /* for test_msg1 */
71*22649d4dSMartin Matuska 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
72*22649d4dSMartin Matuska 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
73*22649d4dSMartin Matuska 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
74*22649d4dSMartin Matuska 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1
75*22649d4dSMartin Matuska }
76*22649d4dSMartin Matuska /* no test vector for test_msg2 */
77*22649d4dSMartin Matuska };
78*22649d4dSMartin Matuska
79*22649d4dSMartin Matuska static const uint8_t sha512_test_digests[][64] = {
80*22649d4dSMartin Matuska {
81*22649d4dSMartin Matuska /* for test_msg0 */
82*22649d4dSMartin Matuska 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
83*22649d4dSMartin Matuska 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
84*22649d4dSMartin Matuska 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
85*22649d4dSMartin Matuska 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
86*22649d4dSMartin Matuska 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
87*22649d4dSMartin Matuska 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
88*22649d4dSMartin Matuska 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
89*22649d4dSMartin Matuska 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F
90*22649d4dSMartin Matuska },
91*22649d4dSMartin Matuska {
92*22649d4dSMartin Matuska /* no test vector for test_msg1 */
93*22649d4dSMartin Matuska 0
94*22649d4dSMartin Matuska },
95*22649d4dSMartin Matuska {
96*22649d4dSMartin Matuska /* for test_msg2 */
97*22649d4dSMartin Matuska 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
98*22649d4dSMartin Matuska 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
99*22649d4dSMartin Matuska 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
100*22649d4dSMartin Matuska 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
101*22649d4dSMartin Matuska 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
102*22649d4dSMartin Matuska 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
103*22649d4dSMartin Matuska 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
104*22649d4dSMartin Matuska 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09
105*22649d4dSMartin Matuska }
106*22649d4dSMartin Matuska };
107*22649d4dSMartin Matuska
108*22649d4dSMartin Matuska static const uint8_t sha512_256_test_digests[][32] = {
109*22649d4dSMartin Matuska {
110*22649d4dSMartin Matuska /* for test_msg0 */
111*22649d4dSMartin Matuska 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9,
112*22649d4dSMartin Matuska 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB,
113*22649d4dSMartin Matuska 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46,
114*22649d4dSMartin Matuska 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23
115*22649d4dSMartin Matuska },
116*22649d4dSMartin Matuska {
117*22649d4dSMartin Matuska /* no test vector for test_msg1 */
118*22649d4dSMartin Matuska 0
119*22649d4dSMartin Matuska },
120*22649d4dSMartin Matuska {
121*22649d4dSMartin Matuska /* for test_msg2 */
122*22649d4dSMartin Matuska 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8,
123*22649d4dSMartin Matuska 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE,
124*22649d4dSMartin Matuska 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14,
125*22649d4dSMartin Matuska 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A
126*22649d4dSMartin Matuska }
127*22649d4dSMartin Matuska };
128*22649d4dSMartin Matuska
129*22649d4dSMartin Matuska /* one million repetitions of 'a' */
130*22649d4dSMartin Matuska
131*22649d4dSMartin Matuska static const uint8_t sha256_million_digest[32] = {
132*22649d4dSMartin Matuska 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
133*22649d4dSMartin Matuska 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
134*22649d4dSMartin Matuska 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
135*22649d4dSMartin Matuska 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0
136*22649d4dSMartin Matuska };
137*22649d4dSMartin Matuska
138*22649d4dSMartin Matuska static const uint8_t sha512_million_digest[64] = {
139*22649d4dSMartin Matuska 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
140*22649d4dSMartin Matuska 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
141*22649d4dSMartin Matuska 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
142*22649d4dSMartin Matuska 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
143*22649d4dSMartin Matuska 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
144*22649d4dSMartin Matuska 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
145*22649d4dSMartin Matuska 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
146*22649d4dSMartin Matuska 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B
147*22649d4dSMartin Matuska };
148*22649d4dSMartin Matuska
149*22649d4dSMartin Matuska /*
150*22649d4dSMartin Matuska * Monte Carlo seeds and COUNT = 0 checkpoints from the NIST CAVP
151*22649d4dSMartin Matuska * byte-oriented test vectors (shabytetestvectors).
152*22649d4dSMartin Matuska */
153*22649d4dSMartin Matuska
154*22649d4dSMartin Matuska static const uint8_t sha256_monte_carlo_seed[32] = {
155*22649d4dSMartin Matuska 0x6D, 0x1E, 0x72, 0xAD, 0x03, 0xDD, 0xEB, 0x5D,
156*22649d4dSMartin Matuska 0xE8, 0x91, 0xE5, 0x72, 0xE2, 0x39, 0x6F, 0x8D,
157*22649d4dSMartin Matuska 0xA0, 0x15, 0xD8, 0x99, 0xEF, 0x0E, 0x79, 0x50,
158*22649d4dSMartin Matuska 0x31, 0x52, 0xD6, 0x01, 0x0A, 0x3F, 0xE6, 0x91
159*22649d4dSMartin Matuska };
160*22649d4dSMartin Matuska
161*22649d4dSMartin Matuska static const uint8_t sha256_monte_carlo_digest[32] = {
162*22649d4dSMartin Matuska 0xE9, 0x3C, 0x33, 0x0A, 0xE5, 0x44, 0x77, 0x38,
163*22649d4dSMartin Matuska 0xC8, 0xAA, 0x85, 0xD7, 0x1A, 0x6C, 0x80, 0xF2,
164*22649d4dSMartin Matuska 0xA5, 0x83, 0x81, 0xD0, 0x58, 0x72, 0xD2, 0x6B,
165*22649d4dSMartin Matuska 0xDD, 0x39, 0xF1, 0xFC, 0xD4, 0xF2, 0xB7, 0x88
166*22649d4dSMartin Matuska };
167*22649d4dSMartin Matuska
168*22649d4dSMartin Matuska static const uint8_t sha512_monte_carlo_seed[64] = {
169*22649d4dSMartin Matuska 0x5C, 0x33, 0x7D, 0xE5, 0xCA, 0xF3, 0x5D, 0x18,
170*22649d4dSMartin Matuska 0xED, 0x90, 0xB5, 0xCD, 0xDF, 0xCE, 0x00, 0x1C,
171*22649d4dSMartin Matuska 0xA1, 0xB8, 0xEE, 0x86, 0x02, 0xF3, 0x67, 0xE7,
172*22649d4dSMartin Matuska 0xC2, 0x4C, 0xCC, 0xA6, 0xF8, 0x93, 0x80, 0x2F,
173*22649d4dSMartin Matuska 0xB1, 0xAC, 0xA7, 0xA3, 0xDA, 0xE3, 0x2D, 0xCD,
174*22649d4dSMartin Matuska 0x60, 0x80, 0x0A, 0x59, 0x95, 0x9B, 0xC5, 0x40,
175*22649d4dSMartin Matuska 0xD6, 0x32, 0x37, 0x87, 0x6B, 0x79, 0x92, 0x29,
176*22649d4dSMartin Matuska 0xAE, 0x71, 0xA2, 0x52, 0x6F, 0xBC, 0x52, 0xCD
177*22649d4dSMartin Matuska };
178*22649d4dSMartin Matuska
179*22649d4dSMartin Matuska static const uint8_t sha512_monte_carlo_digest[64] = {
180*22649d4dSMartin Matuska 0xAD, 0xA6, 0x9A, 0xDD, 0x00, 0x71, 0xB7, 0x94,
181*22649d4dSMartin Matuska 0x46, 0x3C, 0x88, 0x06, 0xA1, 0x77, 0x32, 0x67,
182*22649d4dSMartin Matuska 0x35, 0xFA, 0x62, 0x4B, 0x68, 0xAB, 0x7B, 0xCA,
183*22649d4dSMartin Matuska 0xB2, 0x38, 0x8B, 0x92, 0x76, 0xC0, 0x36, 0xE4,
184*22649d4dSMartin Matuska 0xEA, 0xAF, 0xF8, 0x73, 0x33, 0xE8, 0x3C, 0x81,
185*22649d4dSMartin Matuska 0xC0, 0xBC, 0xA0, 0x35, 0x9D, 0x4A, 0xEE, 0xBC,
186*22649d4dSMartin Matuska 0xBC, 0xFD, 0x31, 0x4C, 0x06, 0x30, 0xE0, 0xC2,
187*22649d4dSMartin Matuska 0xAF, 0x68, 0xC1, 0xFB, 0x19, 0xCC, 0x47, 0x0E
188*22649d4dSMartin Matuska };
189*22649d4dSMartin Matuska
190*22649d4dSMartin Matuska static const uint8_t sha512_256_monte_carlo_seed[32] = {
191*22649d4dSMartin Matuska 0xF4, 0x1E, 0xCE, 0x26, 0x13, 0xE4, 0x57, 0x39,
192*22649d4dSMartin Matuska 0x15, 0x69, 0x6B, 0x5A, 0xDC, 0xD5, 0x1C, 0xA3,
193*22649d4dSMartin Matuska 0x28, 0xBE, 0x3B, 0xF5, 0x66, 0xA9, 0xCA, 0x99,
194*22649d4dSMartin Matuska 0xC9, 0xCE, 0xB0, 0x27, 0x9C, 0x1C, 0xB0, 0xA7
195*22649d4dSMartin Matuska };
196*22649d4dSMartin Matuska
197*22649d4dSMartin Matuska static const uint8_t sha512_256_monte_carlo_digest[32] = {
198*22649d4dSMartin Matuska 0xB1, 0xD9, 0x7A, 0x65, 0x36, 0x89, 0x6A, 0xA0,
199*22649d4dSMartin Matuska 0x10, 0x98, 0xFB, 0x2B, 0x9E, 0x15, 0xD8, 0x69,
200*22649d4dSMartin Matuska 0x26, 0x21, 0xC8, 0x40, 0x77, 0x05, 0x1F, 0xC1,
201*22649d4dSMartin Matuska 0xF7, 0x0A, 0x8A, 0x48, 0xBA, 0xA6, 0xDF, 0xAF
202*22649d4dSMartin Matuska };
203*22649d4dSMartin Matuska
204*22649d4dSMartin Matuska static MunitResult
test_sha256_known(const MunitParameter params[],void * data)205*22649d4dSMartin Matuska test_sha256_known(const MunitParameter params[], void *data)
206*22649d4dSMartin Matuska {
207*22649d4dSMartin Matuska (void) params, (void) data;
208*22649d4dSMartin Matuska uint8_t digest[SHA256_DIGEST_LENGTH];
209*22649d4dSMartin Matuska
210*22649d4dSMartin Matuska hash_buf(SHA256, test_msg0, strlen(test_msg0), digest);
211*22649d4dSMartin Matuska munit_assert_memory_equal(sizeof (digest), digest,
212*22649d4dSMartin Matuska sha256_test_digests[0]);
213*22649d4dSMartin Matuska
214*22649d4dSMartin Matuska hash_buf(SHA256, test_msg1, strlen(test_msg1), digest);
215*22649d4dSMartin Matuska munit_assert_memory_equal(sizeof (digest), digest,
216*22649d4dSMartin Matuska sha256_test_digests[1]);
217*22649d4dSMartin Matuska
218*22649d4dSMartin Matuska return (MUNIT_OK);
219*22649d4dSMartin Matuska }
220*22649d4dSMartin Matuska
221*22649d4dSMartin Matuska static MunitResult
test_sha512_known(const MunitParameter params[],void * data)222*22649d4dSMartin Matuska test_sha512_known(const MunitParameter params[], void *data)
223*22649d4dSMartin Matuska {
224*22649d4dSMartin Matuska (void) params, (void) data;
225*22649d4dSMartin Matuska uint8_t digest[SHA512_DIGEST_LENGTH];
226*22649d4dSMartin Matuska
227*22649d4dSMartin Matuska hash_buf(SHA512, test_msg0, strlen(test_msg0), digest);
228*22649d4dSMartin Matuska munit_assert_memory_equal(sizeof (digest), digest,
229*22649d4dSMartin Matuska sha512_test_digests[0]);
230*22649d4dSMartin Matuska
231*22649d4dSMartin Matuska hash_buf(SHA512, test_msg2, strlen(test_msg2), digest);
232*22649d4dSMartin Matuska munit_assert_memory_equal(sizeof (digest), digest,
233*22649d4dSMartin Matuska sha512_test_digests[2]);
234*22649d4dSMartin Matuska
235*22649d4dSMartin Matuska return (MUNIT_OK);
236*22649d4dSMartin Matuska }
237*22649d4dSMartin Matuska
238*22649d4dSMartin Matuska static MunitResult
test_sha512_256_known(const MunitParameter params[],void * data)239*22649d4dSMartin Matuska test_sha512_256_known(const MunitParameter params[], void *data)
240*22649d4dSMartin Matuska {
241*22649d4dSMartin Matuska (void) params, (void) data;
242*22649d4dSMartin Matuska uint8_t digest[SHA512_256_DIGEST_LENGTH];
243*22649d4dSMartin Matuska
244*22649d4dSMartin Matuska hash_buf(SHA512_256, test_msg0, strlen(test_msg0), digest);
245*22649d4dSMartin Matuska munit_assert_memory_equal(sizeof (digest), digest,
246*22649d4dSMartin Matuska sha512_256_test_digests[0]);
247*22649d4dSMartin Matuska
248*22649d4dSMartin Matuska hash_buf(SHA512_256, test_msg2, strlen(test_msg2), digest);
249*22649d4dSMartin Matuska munit_assert_memory_equal(sizeof (digest), digest,
250*22649d4dSMartin Matuska sha512_256_test_digests[2]);
251*22649d4dSMartin Matuska
252*22649d4dSMartin Matuska return (MUNIT_OK);
253*22649d4dSMartin Matuska }
254*22649d4dSMartin Matuska
255*22649d4dSMartin Matuska static MunitResult
test_million(const MunitParameter params[],void * data)256*22649d4dSMartin Matuska test_million(const MunitParameter params[], void *data)
257*22649d4dSMartin Matuska {
258*22649d4dSMartin Matuska (void) params, (void) data;
259*22649d4dSMartin Matuska static uint8_t buf[1000000];
260*22649d4dSMartin Matuska uint8_t digest[SHA512_DIGEST_LENGTH];
261*22649d4dSMartin Matuska
262*22649d4dSMartin Matuska memset(buf, 'a', sizeof (buf));
263*22649d4dSMartin Matuska
264*22649d4dSMartin Matuska hash_buf(SHA256, buf, sizeof (buf), digest);
265*22649d4dSMartin Matuska munit_assert_memory_equal(SHA256_DIGEST_LENGTH, digest,
266*22649d4dSMartin Matuska sha256_million_digest);
267*22649d4dSMartin Matuska
268*22649d4dSMartin Matuska hash_buf(SHA512, buf, sizeof (buf), digest);
269*22649d4dSMartin Matuska munit_assert_memory_equal(SHA512_DIGEST_LENGTH, digest,
270*22649d4dSMartin Matuska sha512_million_digest);
271*22649d4dSMartin Matuska
272*22649d4dSMartin Matuska return (MUNIT_OK);
273*22649d4dSMartin Matuska }
274*22649d4dSMartin Matuska
275*22649d4dSMartin Matuska /* SHAVS chain MD[i] = SHA(MD[i-3] || MD[i-2] || MD[i-1]), 1000 rounds. */
276*22649d4dSMartin Matuska static MunitResult
test_monte_carlo(const MunitParameter params[],void * data)277*22649d4dSMartin Matuska test_monte_carlo(const MunitParameter params[], void *data)
278*22649d4dSMartin Matuska {
279*22649d4dSMartin Matuska (void) params, (void) data;
280*22649d4dSMartin Matuska
281*22649d4dSMartin Matuska static const int algos[] = { SHA256, SHA512, SHA512_256 };
282*22649d4dSMartin Matuska static const size_t diglens[] = { SHA256_DIGEST_LENGTH,
283*22649d4dSMartin Matuska SHA512_DIGEST_LENGTH, SHA512_256_DIGEST_LENGTH };
284*22649d4dSMartin Matuska static const uint8_t *const seeds[] = { sha256_monte_carlo_seed,
285*22649d4dSMartin Matuska sha512_monte_carlo_seed, sha512_256_monte_carlo_seed };
286*22649d4dSMartin Matuska static const uint8_t *const known[] = { sha256_monte_carlo_digest,
287*22649d4dSMartin Matuska sha512_monte_carlo_digest, sha512_256_monte_carlo_digest };
288*22649d4dSMartin Matuska
289*22649d4dSMartin Matuska for (size_t a = 0; a < ARRAY_SIZE(algos); a++) {
290*22649d4dSMartin Matuska uint8_t msg[3 * SHA512_DIGEST_LENGTH];
291*22649d4dSMartin Matuska uint8_t digest[SHA512_DIGEST_LENGTH];
292*22649d4dSMartin Matuska size_t diglen = diglens[a];
293*22649d4dSMartin Matuska
294*22649d4dSMartin Matuska for (int m = 0; m < 3; m++)
295*22649d4dSMartin Matuska memcpy(msg + m * diglen, seeds[a], diglen);
296*22649d4dSMartin Matuska
297*22649d4dSMartin Matuska for (int i = 0; i < 1000; i++) {
298*22649d4dSMartin Matuska hash_buf(algos[a], msg, 3 * diglen, digest);
299*22649d4dSMartin Matuska memmove(msg, msg + diglen, 2 * diglen);
300*22649d4dSMartin Matuska memcpy(msg + 2 * diglen, digest, diglen);
301*22649d4dSMartin Matuska }
302*22649d4dSMartin Matuska
303*22649d4dSMartin Matuska munit_assert_memory_equal(diglen, digest, known[a]);
304*22649d4dSMartin Matuska }
305*22649d4dSMartin Matuska
306*22649d4dSMartin Matuska return (MUNIT_OK);
307*22649d4dSMartin Matuska }
308*22649d4dSMartin Matuska
309*22649d4dSMartin Matuska /*
310*22649d4dSMartin Matuska * Split updates across the 64- and 128-byte message block boundaries
311*22649d4dSMartin Matuska * must produce the same digest as a single update.
312*22649d4dSMartin Matuska */
313*22649d4dSMartin Matuska static MunitResult
test_incremental(const MunitParameter params[],void * data)314*22649d4dSMartin Matuska test_incremental(const MunitParameter params[], void *data)
315*22649d4dSMartin Matuska {
316*22649d4dSMartin Matuska (void) params, (void) data;
317*22649d4dSMartin Matuska fill_data();
318*22649d4dSMartin Matuska
319*22649d4dSMartin Matuska static const int algos[] = { SHA256, SHA512, SHA512_256 };
320*22649d4dSMartin Matuska static const size_t diglens[] = { SHA256_DIGEST_LENGTH,
321*22649d4dSMartin Matuska SHA512_DIGEST_LENGTH, SHA512_256_DIGEST_LENGTH };
322*22649d4dSMartin Matuska static const size_t chunks[] = { 1, 63, 64, 65, 127, 128, 129, 1000 };
323*22649d4dSMartin Matuska
324*22649d4dSMartin Matuska for (size_t a = 0; a < ARRAY_SIZE(algos); a++) {
325*22649d4dSMartin Matuska uint8_t once[SHA512_DIGEST_LENGTH];
326*22649d4dSMartin Matuska uint8_t split[SHA512_DIGEST_LENGTH];
327*22649d4dSMartin Matuska SHA2_CTX ctx;
328*22649d4dSMartin Matuska size_t off = 0;
329*22649d4dSMartin Matuska
330*22649d4dSMartin Matuska hash_buf(algos[a], databuf, DATA_SIZE, once);
331*22649d4dSMartin Matuska
332*22649d4dSMartin Matuska SHA2Init(algos[a], &ctx);
333*22649d4dSMartin Matuska for (size_t c = 0; c < ARRAY_SIZE(chunks); c++) {
334*22649d4dSMartin Matuska SHA2Update(&ctx, databuf + off, chunks[c]);
335*22649d4dSMartin Matuska off += chunks[c];
336*22649d4dSMartin Matuska }
337*22649d4dSMartin Matuska SHA2Update(&ctx, databuf + off, DATA_SIZE - off);
338*22649d4dSMartin Matuska SHA2Final(split, &ctx);
339*22649d4dSMartin Matuska
340*22649d4dSMartin Matuska munit_assert_memory_equal(diglens[a], once, split);
341*22649d4dSMartin Matuska }
342*22649d4dSMartin Matuska
343*22649d4dSMartin Matuska return (MUNIT_OK);
344*22649d4dSMartin Matuska }
345*22649d4dSMartin Matuska
346*22649d4dSMartin Matuska /*
347*22649d4dSMartin Matuska * Every supported implementation must reproduce the known answer and
348*22649d4dSMartin Matuska * compute the same digest for a multi-block message.
349*22649d4dSMartin Matuska */
350*22649d4dSMartin Matuska static MunitResult
test_impls(const MunitParameter params[],void * data)351*22649d4dSMartin Matuska test_impls(const MunitParameter params[], void *data)
352*22649d4dSMartin Matuska {
353*22649d4dSMartin Matuska (void) params, (void) data;
354*22649d4dSMartin Matuska fill_data();
355*22649d4dSMartin Matuska
356*22649d4dSMartin Matuska static const char *const algos[] = { "sha256", "sha512" };
357*22649d4dSMartin Matuska static const int algotypes[] = { SHA256, SHA512 };
358*22649d4dSMartin Matuska static const uint8_t *const known[] = { sha256_test_digests[0],
359*22649d4dSMartin Matuska sha512_test_digests[0] };
360*22649d4dSMartin Matuska static const size_t diglens[] = { SHA256_DIGEST_LENGTH,
361*22649d4dSMartin Matuska SHA512_DIGEST_LENGTH };
362*22649d4dSMartin Matuska
363*22649d4dSMartin Matuska for (size_t a = 0; a < ARRAY_SIZE(algos); a++) {
364*22649d4dSMartin Matuska const zfs_impl_t *ops = zfs_impl_get_ops(algos[a]);
365*22649d4dSMartin Matuska uint8_t ref[SHA512_DIGEST_LENGTH];
366*22649d4dSMartin Matuska uint8_t digest[SHA512_DIGEST_LENGTH];
367*22649d4dSMartin Matuska uint32_t saved;
368*22649d4dSMartin Matuska
369*22649d4dSMartin Matuska unit_true(ops != NULL);
370*22649d4dSMartin Matuska saved = ops->getid();
371*22649d4dSMartin Matuska
372*22649d4dSMartin Matuska for (uint32_t id = 0; id < ops->getcnt(); id++) {
373*22649d4dSMartin Matuska ops->setid(id);
374*22649d4dSMartin Matuska
375*22649d4dSMartin Matuska hash_buf(algotypes[a], test_msg0, strlen(test_msg0),
376*22649d4dSMartin Matuska digest);
377*22649d4dSMartin Matuska munit_assert_memory_equal(diglens[a], digest,
378*22649d4dSMartin Matuska known[a]);
379*22649d4dSMartin Matuska
380*22649d4dSMartin Matuska hash_buf(algotypes[a], databuf, DATA_SIZE, digest);
381*22649d4dSMartin Matuska if (id == 0)
382*22649d4dSMartin Matuska memcpy(ref, digest, diglens[a]);
383*22649d4dSMartin Matuska else
384*22649d4dSMartin Matuska munit_assert_memory_equal(diglens[a],
385*22649d4dSMartin Matuska ref, digest);
386*22649d4dSMartin Matuska }
387*22649d4dSMartin Matuska
388*22649d4dSMartin Matuska ops->setid(saved);
389*22649d4dSMartin Matuska }
390*22649d4dSMartin Matuska
391*22649d4dSMartin Matuska return (MUNIT_OK);
392*22649d4dSMartin Matuska }
393*22649d4dSMartin Matuska
394*22649d4dSMartin Matuska /* ========== */
395*22649d4dSMartin Matuska
396*22649d4dSMartin Matuska static const MunitTest sha2_tests[] = {
397*22649d4dSMartin Matuska UNIT_TEST("sha256_known", test_sha256_known),
398*22649d4dSMartin Matuska UNIT_TEST("sha512_known", test_sha512_known),
399*22649d4dSMartin Matuska UNIT_TEST("sha512_256_known", test_sha512_256_known),
400*22649d4dSMartin Matuska UNIT_TEST("million", test_million),
401*22649d4dSMartin Matuska UNIT_TEST("monte_carlo", test_monte_carlo),
402*22649d4dSMartin Matuska UNIT_TEST("incremental", test_incremental),
403*22649d4dSMartin Matuska UNIT_TEST("impls", test_impls),
404*22649d4dSMartin Matuska { 0 },
405*22649d4dSMartin Matuska };
406*22649d4dSMartin Matuska
407*22649d4dSMartin Matuska static const MunitSuite sha2_test_suite = {
408*22649d4dSMartin Matuska "sha2.",
409*22649d4dSMartin Matuska sha2_tests,
410*22649d4dSMartin Matuska NULL,
411*22649d4dSMartin Matuska 1,
412*22649d4dSMartin Matuska MUNIT_SUITE_OPTION_NONE,
413*22649d4dSMartin Matuska };
414*22649d4dSMartin Matuska
415*22649d4dSMartin Matuska int
main(int argc,char ** argv)416*22649d4dSMartin Matuska main(int argc, char **argv)
417*22649d4dSMartin Matuska {
418*22649d4dSMartin Matuska return (munit_suite_main(&sha2_test_suite, NULL, argc, argv));
419*22649d4dSMartin Matuska }
420