1/*	$OpenBSD: sha_test.c,v 1.6 2023/07/19 15:11:42 joshua Exp $ */
2/*
3 * Copyright (c) 2022, 2023 Joshua Sing <joshua@hypera.dev>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <openssl/evp.h>
19#include <openssl/sha.h>
20
21#include <stdint.h>
22#include <string.h>
23
24struct sha_test {
25	const int algorithm;
26	const uint8_t in[128];
27	const size_t in_len;
28	const uint8_t out[EVP_MAX_MD_SIZE];
29};
30
31static const struct sha_test sha_tests[] = {
32	/* SHA-1 */
33	{
34		.algorithm = NID_sha1,
35		.in = "abc",
36		.in_len = 3,
37		.out = {
38			0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
39			0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
40			0x9c, 0xd0, 0xd8, 0x9d,
41		},
42	},
43	{
44		.algorithm = NID_sha1,
45		.in = "",
46		.in_len = 0,
47		.out = {
48			0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
49			0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
50			0xaf, 0xd8, 0x07, 0x09,
51		},
52	},
53	{
54		.algorithm = NID_sha1,
55		.in =
56		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
57		    "mnopnopq",
58		.in_len = 56,
59		.out = {
60			0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e,
61			0xba, 0xae, 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5,
62			0xe5, 0x46, 0x70, 0xf1,
63		},
64	},
65	{
66		.algorithm = NID_sha1,
67		.in =
68		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
69		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
70		    "mnopqrstnopqrstu",
71		.in_len = 112,
72		.out = {
73			0xa4, 0x9b, 0x24, 0x46, 0xa0, 0x2c, 0x64, 0x5b,
74			0xf4, 0x19, 0xf9, 0x95, 0xb6, 0x70, 0x91, 0x25,
75			0x3a, 0x04, 0xa2, 0x59,
76		},
77	},
78
79	/* SHA-224 */
80	{
81		.algorithm = NID_sha224,
82		.in = "abc",
83		.in_len = 3,
84		.out = {
85			0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, 0x22,
86			0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, 0x55, 0xb3,
87			0x2a, 0xad, 0xbc, 0xe4, 0xbd, 0xa0, 0xb3, 0xf7,
88			0xe3, 0x6c, 0x9d, 0xa7,
89		},
90	},
91	{
92		.algorithm = NID_sha224,
93		.in = "",
94		.in_len = 0,
95		.out = {
96			0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9,
97			0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4,
98			0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a,
99			0xc5, 0xb3, 0xe4, 0x2f,
100		},
101	},
102	{
103		.algorithm = NID_sha224,
104		.in =
105		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
106		    "mnopnopq",
107		.in_len = 56,
108		.out = {
109			0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, 0xcc,
110			0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, 0x01, 0x50,
111			0xb0, 0xc6, 0x45, 0x5c, 0xb4, 0xf5, 0x8b, 0x19,
112			0x52, 0x52, 0x25, 0x25,
113		},
114	},
115	{
116		.algorithm = NID_sha224,
117		.in =
118		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
119		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
120		    "mnopqrstnopqrstu",
121		.in_len = 112,
122		.out = {
123			0xc9, 0x7c, 0xa9, 0xa5, 0x59, 0x85, 0x0c, 0xe9,
124			0x7a, 0x04, 0xa9, 0x6d, 0xef, 0x6d, 0x99, 0xa9,
125			0xe0, 0xe0, 0xe2, 0xab, 0x14, 0xe6, 0xb8, 0xdf,
126			0x26, 0x5f, 0xc0, 0xb3,
127		},
128	},
129
130	/* SHA-256 */
131	{
132		.algorithm = NID_sha256,
133		.in = "abc",
134		.in_len = 3,
135		.out = {
136			0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
137			0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
138			0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
139			0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
140		},
141	},
142	{
143		.algorithm = NID_sha256,
144		.in = "",
145		.in_len = 0,
146		.out = {
147			0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
148			0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
149			0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
150			0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
151		},
152	},
153	{
154		.algorithm = NID_sha256,
155		.in =
156		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
157		    "mnopnopq",
158		.in_len = 56,
159		.out = {
160			0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
161			0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
162			0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
163			0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
164		},
165	},
166	{
167		.algorithm = NID_sha256,
168		.in =
169		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
170		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
171		    "mnopqrstnopqrstu",
172		.in_len = 112,
173		.out = {
174			0xcf, 0x5b, 0x16, 0xa7, 0x78, 0xaf, 0x83, 0x80,
175			0x03, 0x6c, 0xe5, 0x9e, 0x7b, 0x04, 0x92, 0x37,
176			0x0b, 0x24, 0x9b, 0x11, 0xe8, 0xf0, 0x7a, 0x51,
177			0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1,
178		},
179	},
180
181	/* SHA-384 */
182	{
183		.algorithm = NID_sha384,
184		.in = "abc",
185		.in_len = 3,
186		.out = {
187			0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
188			0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
189			0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
190			0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
191			0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
192			0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7,
193		},
194	},
195	{
196		.algorithm = NID_sha384,
197		.in = "",
198		.in_len = 0,
199		.out = {
200			0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38,
201			0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
202			0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43,
203			0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
204			0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb,
205			0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b,
206		},
207	},
208	{
209		.algorithm = NID_sha384,
210		.in =
211		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
212		    "mnopnopq",
213		.in_len = 56,
214		.out = {
215			0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39,
216			0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39,
217			0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab,
218			0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6,
219			0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f,
220			0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b,
221		},
222	},
223	{
224		.algorithm = NID_sha384,
225		.in =
226		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
227		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
228		    "mnopqrstnopqrstu",
229		.in_len = 112,
230		.out = {
231			0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
232			0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
233			0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
234			0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
235			0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
236			0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39,
237		},
238	},
239
240	/* SHA-512 */
241	{
242		.algorithm = NID_sha512,
243		.in = "abc",
244		.in_len = 3,
245		.out = {
246			0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
247			0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
248			0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
249			0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
250			0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
251			0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
252			0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
253			0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,
254		},
255	},
256	{
257		.algorithm = NID_sha512,
258		.in = "",
259		.in_len = 0,
260		.out = {
261			0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
262			0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
263			0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
264			0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
265			0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
266			0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
267			0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
268			0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e,
269		},
270	},
271	{
272		.algorithm = NID_sha512,
273		.in =
274		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
275		    "mnopnopq",
276		.in_len = 56,
277		.out = {
278			0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a,
279			0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16,
280			0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8,
281			0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35,
282			0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9,
283			0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0,
284			0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03,
285			0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45,
286		},
287	},
288	{
289		.algorithm = NID_sha512,
290		.in =
291		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
292		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
293		    "mnopqrstnopqrstu",
294		.in_len = 112,
295		.out = {
296			0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
297			0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
298			0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
299			0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
300			0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
301			0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
302			0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
303			0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09,
304		},
305	},
306
307	/* SHA3-224 */
308	{
309		.algorithm = NID_sha3_224,
310		.in = "abc",
311		.in_len = 3,
312		.out = {
313			0xe6, 0x42, 0x82, 0x4c, 0x3f, 0x8c, 0xf2, 0x4a,
314			0xd0, 0x92, 0x34, 0xee, 0x7d, 0x3c, 0x76, 0x6f,
315			0xc9, 0xa3, 0xa5, 0x16, 0x8d, 0x0c, 0x94, 0xad,
316			0x73, 0xb4, 0x6f, 0xdf,
317		},
318	},
319	{
320		.algorithm = NID_sha3_224,
321		.in = "",
322		.in_len = 0,
323		.out = {
324			0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7,
325			0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab,
326			0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f,
327			0x5b, 0x5a, 0x6b, 0xc7,
328		},
329	},
330	{
331		.algorithm = NID_sha3_224,
332		.in =
333		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
334		    "mnopnopq",
335		.in_len = 56,
336		.out = {
337			0x8a, 0x24, 0x10, 0x8b, 0x15, 0x4a, 0xda, 0x21,
338			0xc9, 0xfd, 0x55, 0x74, 0x49, 0x44, 0x79, 0xba,
339			0x5c, 0x7e, 0x7a, 0xb7, 0x6e, 0xf2, 0x64, 0xea,
340			0xd0, 0xfc, 0xce, 0x33,
341		},
342	},
343	{
344		.algorithm = NID_sha3_224,
345		.in =
346		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
347		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
348		    "mnopqrstnopqrstu",
349		.in_len = 112,
350		.out = {
351			0x54, 0x3e, 0x68, 0x68, 0xe1, 0x66, 0x6c, 0x1a,
352			0x64, 0x36, 0x30, 0xdf, 0x77, 0x36, 0x7a, 0xe5,
353			0xa6, 0x2a, 0x85, 0x07, 0x0a, 0x51, 0xc1, 0x4c,
354			0xbf, 0x66, 0x5c, 0xbc,
355		},
356	},
357
358	/* SHA3-256 */
359	{
360		.algorithm = NID_sha3_256,
361		.in = "abc",
362		.in_len = 3,
363		.out = {
364			0x3a, 0x98, 0x5d, 0xa7, 0x4f, 0xe2, 0x25, 0xb2,
365			0x04, 0x5c, 0x17, 0x2d, 0x6b, 0xd3, 0x90, 0xbd,
366			0x85, 0x5f, 0x08, 0x6e, 0x3e, 0x9d, 0x52, 0x5b,
367			0x46, 0xbf, 0xe2, 0x45, 0x11, 0x43, 0x15, 0x32,
368		},
369	},
370	{
371		.algorithm = NID_sha3_256,
372		.in = "",
373		.in_len = 0,
374		.out = {
375			0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66,
376			0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62,
377			0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa,
378			0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a,
379		},
380	},
381	{
382		.algorithm = NID_sha3_256,
383		.in =
384		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
385		    "mnopnopq",
386		.in_len = 56,
387		.out = {
388			0x41, 0xc0, 0xdb, 0xa2, 0xa9, 0xd6, 0x24, 0x08,
389			0x49, 0x10, 0x03, 0x76, 0xa8, 0x23, 0x5e, 0x2c,
390			0x82, 0xe1, 0xb9, 0x99, 0x8a, 0x99, 0x9e, 0x21,
391			0xdb, 0x32, 0xdd, 0x97, 0x49, 0x6d, 0x33, 0x76,
392		},
393	},
394	{
395		.algorithm = NID_sha3_256,
396		.in =
397		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
398		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
399		    "mnopqrstnopqrstu",
400		.in_len = 112,
401		.out = {
402			0x91, 0x6f, 0x60, 0x61, 0xfe, 0x87, 0x97, 0x41,
403			0xca, 0x64, 0x69, 0xb4, 0x39, 0x71, 0xdf, 0xdb,
404			0x28, 0xb1, 0xa3, 0x2d, 0xc3, 0x6c, 0xb3, 0x25,
405			0x4e, 0x81, 0x2b, 0xe2, 0x7a, 0xad, 0x1d, 0x18,
406		},
407	},
408
409	/* SHA3-384 */
410	{
411		.algorithm = NID_sha3_384,
412		.in = "abc",
413		.in_len = 3,
414		.out = {
415			0xec, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6f, 0xc9,
416			0x26, 0x45, 0x9f, 0x58, 0xe2, 0xc6, 0xad, 0x8d,
417			0xf9, 0xb4, 0x73, 0xcb, 0x0f, 0xc0, 0x8c, 0x25,
418			0x96, 0xda, 0x7c, 0xf0, 0xe4, 0x9b, 0xe4, 0xb2,
419			0x98, 0xd8, 0x8c, 0xea, 0x92, 0x7a, 0xc7, 0xf5,
420			0x39, 0xf1, 0xed, 0xf2, 0x28, 0x37, 0x6d, 0x25,
421		},
422	},
423	{
424		.algorithm = NID_sha3_384,
425		.in = "",
426		.in_len = 0,
427		.out = {
428			0x0c, 0x63, 0xa7, 0x5b, 0x84, 0x5e, 0x4f, 0x7d,
429			0x01, 0x10, 0x7d, 0x85, 0x2e, 0x4c, 0x24, 0x85,
430			0xc5, 0x1a, 0x50, 0xaa, 0xaa, 0x94, 0xfc, 0x61,
431			0x99, 0x5e, 0x71, 0xbb, 0xee, 0x98, 0x3a, 0x2a,
432			0xc3, 0x71, 0x38, 0x31, 0x26, 0x4a, 0xdb, 0x47,
433			0xfb, 0x6b, 0xd1, 0xe0, 0x58, 0xd5, 0xf0, 0x04,
434		},
435	},
436	{
437		.algorithm = NID_sha3_384,
438		.in =
439		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
440		    "mnopnopq",
441		.in_len = 56,
442		.out = {
443			0x99, 0x1c, 0x66, 0x57, 0x55, 0xeb, 0x3a, 0x4b,
444			0x6b, 0xbd, 0xfb, 0x75, 0xc7, 0x8a, 0x49, 0x2e,
445			0x8c, 0x56, 0xa2, 0x2c, 0x5c, 0x4d, 0x7e, 0x42,
446			0x9b, 0xfd, 0xbc, 0x32, 0xb9, 0xd4, 0xad, 0x5a,
447			0xa0, 0x4a, 0x1f, 0x07, 0x6e, 0x62, 0xfe, 0xa1,
448			0x9e, 0xef, 0x51, 0xac, 0xd0, 0x65, 0x7c, 0x22,
449		},
450	},
451	{
452		.algorithm = NID_sha3_384,
453		.in =
454		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
455		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
456		    "mnopqrstnopqrstu",
457		.in_len = 112,
458		.out = {
459			0x79, 0x40, 0x7d, 0x3b, 0x59, 0x16, 0xb5, 0x9c,
460			0x3e, 0x30, 0xb0, 0x98, 0x22, 0x97, 0x47, 0x91,
461			0xc3, 0x13, 0xfb, 0x9e, 0xcc, 0x84, 0x9e, 0x40,
462			0x6f, 0x23, 0x59, 0x2d, 0x04, 0xf6, 0x25, 0xdc,
463			0x8c, 0x70, 0x9b, 0x98, 0xb4, 0x3b, 0x38, 0x52,
464			0xb3, 0x37, 0x21, 0x61, 0x79, 0xaa, 0x7f, 0xc7,
465		},
466	},
467
468	/* SHA3-512 */
469	{
470		.algorithm = NID_sha3_512,
471		.in = "abc",
472		.in_len = 3,
473		.out = {
474			0xb7, 0x51, 0x85, 0x0b, 0x1a, 0x57, 0x16, 0x8a,
475			0x56, 0x93, 0xcd, 0x92, 0x4b, 0x6b, 0x09, 0x6e,
476			0x08, 0xf6, 0x21, 0x82, 0x74, 0x44, 0xf7, 0x0d,
477			0x88, 0x4f, 0x5d, 0x02, 0x40, 0xd2, 0x71, 0x2e,
478			0x10, 0xe1, 0x16, 0xe9, 0x19, 0x2a, 0xf3, 0xc9,
479			0x1a, 0x7e, 0xc5, 0x76, 0x47, 0xe3, 0x93, 0x40,
480			0x57, 0x34, 0x0b, 0x4c, 0xf4, 0x08, 0xd5, 0xa5,
481			0x65, 0x92, 0xf8, 0x27, 0x4e, 0xec, 0x53, 0xf0,
482		},
483	},
484	{
485		.algorithm = NID_sha3_512,
486		.in = "",
487		.in_len = 0,
488		.out = {
489			0xa6, 0x9f, 0x73, 0xcc, 0xa2, 0x3a, 0x9a, 0xc5,
490			0xc8, 0xb5, 0x67, 0xdc, 0x18, 0x5a, 0x75, 0x6e,
491			0x97, 0xc9, 0x82, 0x16, 0x4f, 0xe2, 0x58, 0x59,
492			0xe0, 0xd1, 0xdc, 0xc1, 0x47, 0x5c, 0x80, 0xa6,
493			0x15, 0xb2, 0x12, 0x3a, 0xf1, 0xf5, 0xf9, 0x4c,
494			0x11, 0xe3, 0xe9, 0x40, 0x2c, 0x3a, 0xc5, 0x58,
495			0xf5, 0x00, 0x19, 0x9d, 0x95, 0xb6, 0xd3, 0xe3,
496			0x01, 0x75, 0x85, 0x86, 0x28, 0x1d, 0xcd, 0x26,
497		},
498	},
499	{
500		.algorithm = NID_sha3_512,
501		.in =
502		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
503		    "mnopnopq",
504		.in_len = 56,
505		.out = {
506			0x04, 0xa3, 0x71, 0xe8, 0x4e, 0xcf, 0xb5, 0xb8,
507			0xb7, 0x7c, 0xb4, 0x86, 0x10, 0xfc, 0xa8, 0x18,
508			0x2d, 0xd4, 0x57, 0xce, 0x6f, 0x32, 0x6a, 0x0f,
509			0xd3, 0xd7, 0xec, 0x2f, 0x1e, 0x91, 0x63, 0x6d,
510			0xee, 0x69, 0x1f, 0xbe, 0x0c, 0x98, 0x53, 0x02,
511			0xba, 0x1b, 0x0d, 0x8d, 0xc7, 0x8c, 0x08, 0x63,
512			0x46, 0xb5, 0x33, 0xb4, 0x9c, 0x03, 0x0d, 0x99,
513			0xa2, 0x7d, 0xaf, 0x11, 0x39, 0xd6, 0xe7, 0x5e,
514		},
515	},
516	{
517		.algorithm = NID_sha3_512,
518		.in =
519		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
520		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
521		    "mnopqrstnopqrstu",
522		.in_len = 112,
523		.out = {
524			0xaf, 0xeb, 0xb2, 0xef, 0x54, 0x2e, 0x65, 0x79,
525			0xc5, 0x0c, 0xad, 0x06, 0xd2, 0xe5, 0x78, 0xf9,
526			0xf8, 0xdd, 0x68, 0x81, 0xd7, 0xdc, 0x82, 0x4d,
527			0x26, 0x36, 0x0f, 0xee, 0xbf, 0x18, 0xa4, 0xfa,
528			0x73, 0xe3, 0x26, 0x11, 0x22, 0x94, 0x8e, 0xfc,
529			0xfd, 0x49, 0x2e, 0x74, 0xe8, 0x2e, 0x21, 0x89,
530			0xed, 0x0f, 0xb4, 0x40, 0xd1, 0x87, 0xf3, 0x82,
531			0x27, 0x0c, 0xb4, 0x55, 0xf2, 0x1d, 0xd1, 0x85,
532		},
533	},
534};
535
536struct sha_repetition_test {
537	const int algorithm;
538	const uint8_t in;
539	const size_t in_repetitions;
540	const uint8_t out[EVP_MAX_MD_SIZE];
541};
542
543static const struct sha_repetition_test sha_repetition_tests[] = {
544	/* SHA-1 */
545	{
546		.algorithm = NID_sha1,
547		.in = 'a',
548		.in_repetitions = 1000000,
549		.out = {
550			0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, 0xa4,
551			0xf6, 0x1e, 0xeb, 0x2b, 0xdb, 0xad, 0x27, 0x31,
552			0x65, 0x34, 0x01, 0x6f,
553		},
554	},
555
556	/* SHA-224 */
557	{
558		.algorithm = NID_sha224,
559		.in = 'a',
560		.in_repetitions = 1000000,
561		.out = {
562			0x20, 0x79, 0x46, 0x55, 0x98, 0x0c, 0x91, 0xd8,
563			0xbb, 0xb4, 0xc1, 0xea, 0x97, 0x61, 0x8a, 0x4b,
564			0xf0, 0x3f, 0x42, 0x58, 0x19, 0x48, 0xb2, 0xee,
565			0x4e, 0xe7, 0xad, 0x67,
566		},
567	},
568
569	/* SHA-256 */
570	{
571		.algorithm = NID_sha256,
572		.in = 'a',
573		.in_repetitions = 1000000,
574		.out = {
575			0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92,
576			0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67,
577			0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e,
578			0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0,
579		},
580	},
581
582	/* SHA-384 */
583	{
584		.algorithm = NID_sha384,
585		.in = 'a',
586		.in_repetitions = 1000000,
587		.out = {
588			0x9d, 0x0e, 0x18, 0x09, 0x71, 0x64, 0x74, 0xcb,
589			0x08, 0x6e, 0x83, 0x4e, 0x31, 0x0a, 0x4a, 0x1c,
590			0xed, 0x14, 0x9e, 0x9c, 0x00, 0xf2, 0x48, 0x52,
591			0x79, 0x72, 0xce, 0xc5, 0x70, 0x4c, 0x2a, 0x5b,
592			0x07, 0xb8, 0xb3, 0xdc, 0x38, 0xec, 0xc4, 0xeb,
593			0xae, 0x97, 0xdd, 0xd8, 0x7f, 0x3d, 0x89, 0x85,
594		},
595	},
596
597	/* SHA-512 */
598	{
599		.algorithm = NID_sha512,
600		.in = 'a',
601		.in_repetitions = 1000000,
602		.out = {
603			0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64,
604			0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63,
605			0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28,
606			0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb,
607			0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a,
608			0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b,
609			0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e,
610			0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b,
611		},
612	},
613
614	/* SHA3-224 */
615	{
616		.algorithm = NID_sha3_224,
617		.in = 'a',
618		.in_repetitions = 1000000,
619		.out = {
620			0xd6, 0x93, 0x35, 0xb9, 0x33, 0x25, 0x19, 0x2e,
621			0x51, 0x6a, 0x91, 0x2e, 0x6d, 0x19, 0xa1, 0x5c,
622			0xb5, 0x1c, 0x6e, 0xd5, 0xc1, 0x52, 0x43, 0xe7,
623			0xa7, 0xfd, 0x65, 0x3c,
624		},
625	},
626
627	/* SHA3-256 */
628	{
629		.algorithm = NID_sha3_256,
630		.in = 'a',
631		.in_repetitions = 1000000,
632		.out = {
633			0x5c, 0x88, 0x75, 0xae, 0x47, 0x4a, 0x36, 0x34,
634			0xba, 0x4f, 0xd5, 0x5e, 0xc8, 0x5b, 0xff, 0xd6,
635			0x61, 0xf3, 0x2a, 0xca, 0x75, 0xc6, 0xd6, 0x99,
636			0xd0, 0xcd, 0xcb, 0x6c, 0x11, 0x58, 0x91, 0xc1,
637		},
638	},
639
640	/* SHA3-384 */
641	{
642		.algorithm = NID_sha3_384,
643		.in = 'a',
644		.in_repetitions = 1000000,
645		.out = {
646			0xee, 0xe9, 0xe2, 0x4d, 0x78, 0xc1, 0x85, 0x53,
647			0x37, 0x98, 0x34, 0x51, 0xdf, 0x97, 0xc8, 0xad,
648			0x9e, 0xed, 0xf2, 0x56, 0xc6, 0x33, 0x4f, 0x8e,
649			0x94, 0x8d, 0x25, 0x2d, 0x5e, 0x0e, 0x76, 0x84,
650			0x7a, 0xa0, 0x77, 0x4d, 0xdb, 0x90, 0xa8, 0x42,
651			0x19, 0x0d, 0x2c, 0x55, 0x8b, 0x4b, 0x83, 0x40,
652		},
653	},
654
655	/* SHA3-512 */
656	{
657		.algorithm = NID_sha3_512,
658		.in = 'a',
659		.in_repetitions = 1000000,
660		.out = {
661			0x3c, 0x3a, 0x87, 0x6d, 0xa1, 0x40, 0x34, 0xab,
662			0x60, 0x62, 0x7c, 0x07, 0x7b, 0xb9, 0x8f, 0x7e,
663			0x12, 0x0a, 0x2a, 0x53, 0x70, 0x21, 0x2d, 0xff,
664			0xb3, 0x38, 0x5a, 0x18, 0xd4, 0xf3, 0x88, 0x59,
665			0xed, 0x31, 0x1d, 0x0a, 0x9d, 0x51, 0x41, 0xce,
666			0x9c, 0xc5, 0xc6, 0x6e, 0xe6, 0x89, 0xb2, 0x66,
667			0xa8, 0xaa, 0x18, 0xac, 0xe8, 0x28, 0x2a, 0x0e,
668			0x0d, 0xb5, 0x96, 0xc9, 0x0b, 0x0a, 0x7b, 0x87,
669		},
670	},
671};
672
673#define N_SHA_TESTS (sizeof(sha_tests) / sizeof(sha_tests[0]))
674#define N_SHA_REPETITION_TESTS (sizeof(sha_repetition_tests) / sizeof(sha_repetition_tests[0]))
675
676typedef unsigned char *(*sha_hash_func)(const unsigned char *, size_t,
677    unsigned char *);
678
679static int
680sha_hash_from_algorithm(int algorithm, const char **out_label,
681    sha_hash_func *out_func, const EVP_MD **out_md, size_t *out_len)
682{
683	const char *label;
684	sha_hash_func sha_func;
685	const EVP_MD *md;
686	size_t len;
687
688	switch (algorithm) {
689	case NID_sha1:
690		label = SN_sha1;
691		sha_func = SHA1;
692		md = EVP_sha1();
693		len = SHA_DIGEST_LENGTH;
694		break;
695	case NID_sha224:
696		label = SN_sha224;
697		sha_func = SHA224;
698		md = EVP_sha224();
699		len = SHA224_DIGEST_LENGTH;
700		break;
701	case NID_sha256:
702		label = SN_sha256;
703		sha_func = SHA256;
704		md = EVP_sha256();
705		len = SHA256_DIGEST_LENGTH;
706		break;
707	case NID_sha384:
708		label = SN_sha384;
709		sha_func = SHA384;
710		md = EVP_sha384();
711		len = SHA384_DIGEST_LENGTH;
712		break;
713	case NID_sha512:
714		label = SN_sha512;
715		sha_func = SHA512;
716		md = EVP_sha512();
717		len = SHA512_DIGEST_LENGTH;
718		break;
719	case NID_sha3_224:
720		label = SN_sha3_224;
721		sha_func = NULL;
722		md = EVP_sha3_224();
723		len = 224 / 8;
724		break;
725	case NID_sha3_256:
726		label = SN_sha3_256;
727		sha_func = NULL;
728		md = EVP_sha3_256();
729		len = 256 / 8;
730		break;
731	case NID_sha3_384:
732		label = SN_sha3_384;
733		sha_func = NULL;
734		md = EVP_sha3_384();
735		len = 384 / 8;
736		break;
737	case NID_sha3_512:
738		label = SN_sha3_512;
739		sha_func = NULL;
740		md = EVP_sha3_512();
741		len = 512 / 8;
742		break;
743	default:
744		fprintf(stderr, "FAIL: unknown algorithm (%d)\n",
745		    algorithm);
746		return 0;
747	}
748
749	if (out_label != NULL)
750		*out_label = label;
751	if (out_func != NULL)
752		*out_func = sha_func;
753	if (out_md != NULL)
754		*out_md = md;
755	if (out_len != NULL)
756		*out_len = len;
757
758	return 1;
759}
760
761static int
762sha_test(void)
763{
764	sha_hash_func sha_func;
765	const struct sha_test *st;
766	EVP_MD_CTX *hash = NULL;
767	const EVP_MD *md;
768	uint8_t out[EVP_MAX_MD_SIZE];
769	size_t in_len, out_len;
770	size_t i;
771	const char *label;
772	int failed = 1;
773
774	if ((hash = EVP_MD_CTX_new()) == NULL) {
775		fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n");
776		goto failed;
777	}
778
779	for (i = 0; i < N_SHA_TESTS; i++) {
780		st = &sha_tests[i];
781		if (!sha_hash_from_algorithm(st->algorithm, &label, &sha_func,
782		    &md, &out_len))
783			goto failed;
784
785		/* Digest */
786		if (sha_func != NULL) {
787			memset(out, 0, sizeof(out));
788			sha_func(st->in, st->in_len, out);
789			if (memcmp(st->out, out, out_len) != 0) {
790				fprintf(stderr, "FAIL (%s:%zu): mismatch\n",
791				    label, i);
792				goto failed;
793			}
794		}
795
796		/* EVP single-shot digest */
797		memset(out, 0, sizeof(out));
798		if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) {
799			fprintf(stderr, "FAIL (%s:%zu): EVP_Digest failed\n",
800			    label, i);
801			goto failed;
802		}
803
804		if (memcmp(st->out, out, out_len) != 0) {
805			fprintf(stderr,
806			    "FAIL (%s:%zu): EVP single-shot mismatch\n",
807			    label, i);
808			goto failed;
809		}
810
811		/* EVP digest */
812		memset(out, 0, sizeof(out));
813		if (!EVP_DigestInit_ex(hash, md, NULL)) {
814			fprintf(stderr,
815			    "FAIL (%s:%zu): EVP_DigestInit_ex failed\n",
816			    label, i);
817			goto failed;
818		}
819
820		in_len = st->in_len / 2;
821		if (!EVP_DigestUpdate(hash, st->in, in_len)) {
822			fprintf(stderr,
823			    "FAIL (%s:%zu): EVP_DigestUpdate first half "
824			    "failed\n", label, i);
825			goto failed;
826		}
827
828		if (!EVP_DigestUpdate(hash, st->in + in_len,
829		    st->in_len - in_len)) {
830			fprintf(stderr,
831			    "FAIL (%s:%zu): EVP_DigestUpdate second half "
832			    "failed\n", label, i);
833			goto failed;
834		}
835
836		if (!EVP_DigestFinal_ex(hash, out, NULL)) {
837			fprintf(stderr,
838			    "FAIL (%s:%zu): EVP_DigestFinal_ex failed\n",
839			    label, i);
840			goto failed;
841		}
842
843		if (memcmp(st->out, out, out_len) != 0) {
844			fprintf(stderr, "FAIL (%s:%zu): EVP mismatch\n",
845			    label, i);
846			goto failed;
847		}
848	}
849
850	failed = 0;
851
852 failed:
853	EVP_MD_CTX_free(hash);
854	return failed;
855}
856
857static int
858sha_repetition_test(void)
859{
860	const struct sha_repetition_test *st;
861	EVP_MD_CTX *hash = NULL;
862	const EVP_MD *md;
863	uint8_t buf[1024];
864	uint8_t out[EVP_MAX_MD_SIZE];
865	size_t out_len, part_len;
866	size_t i, j;
867	const char *label;
868	int failed = 1;
869
870	if ((hash = EVP_MD_CTX_new()) == NULL) {
871		fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n");
872		goto failed;
873	}
874
875	for (i = 0; i < N_SHA_REPETITION_TESTS; i++) {
876		st = &sha_repetition_tests[i];
877		if (!sha_hash_from_algorithm(st->algorithm, &label, NULL, &md,
878		    &out_len))
879			goto failed;
880
881		/* EVP digest */
882		if (!EVP_DigestInit_ex(hash, md, NULL)) {
883			fprintf(stderr,
884			    "FAIL (%s:%zu): EVP_DigestInit_ex failed\n",
885			    label, i);
886			goto failed;
887		}
888
889		memset(buf, st->in, sizeof(buf));
890
891		for (j = 0; j < st->in_repetitions;) {
892			part_len = arc4random_uniform(sizeof(buf));
893			if (part_len > st->in_repetitions - j)
894				part_len = st->in_repetitions - j;
895
896			if (!EVP_DigestUpdate(hash, buf, part_len)) {
897				fprintf(stderr,
898				    "FAIL (%s:%zu): EVP_DigestUpdate failed\n",
899				    label, i);
900				goto failed;
901			}
902
903			j += part_len;
904		}
905
906		if (!EVP_DigestFinal_ex(hash, out, NULL)) {
907			fprintf(stderr,
908			    "FAIL (%s:%zu): EVP_DigestFinal_ex failed\n",
909			    label, i);
910			goto failed;
911		}
912
913		if (memcmp(st->out, out, out_len) != 0) {
914			fprintf(stderr, "FAIL (%s:%zu): EVP mismatch\n",
915			    label, i);
916			goto failed;
917		}
918	}
919
920	failed = 0;
921
922 failed:
923	EVP_MD_CTX_free(hash);
924	return failed;
925}
926
927int
928main(int argc, char **argv)
929{
930	int failed = 0;
931
932	failed |= sha_test();
933	failed |= sha_repetition_test();
934
935	return failed;
936}
937