xref: /freebsd/sys/contrib/openzfs/tests/unit/test_sha2.c (revision 22649d4dba730d46244fd2dff4fd174903c8379f)
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