xref: /openbsd-src/regress/lib/libcrypto/sha/sha_test.c (revision 3374c67d44f9b75b98444cbf63020f777792342e)
1 /*	$OpenBSD: sha_test.c,v 1.4 2022/09/02 13:23:05 tb Exp $ */
2 /*
3  * Copyright (c) 2022 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 
24 struct 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 
31 static 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 
308 struct sha_repetition_test {
309 	const int algorithm;
310 	const uint8_t in;
311 	const size_t in_repetitions;
312 	const uint8_t out[EVP_MAX_MD_SIZE];
313 };
314 
315 static const struct sha_repetition_test sha_repetition_tests[] = {
316 	/* SHA-1 */
317 	{
318 		.algorithm = NID_sha1,
319 		.in = 'a',
320 		.in_repetitions = 1000000,
321 		.out = {
322 			0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, 0xa4,
323 			0xf6, 0x1e, 0xeb, 0x2b, 0xdb, 0xad, 0x27, 0x31,
324 			0x65, 0x34, 0x01, 0x6f,
325 		}
326 	},
327 
328 	/* SHA-224 */
329 	{
330 		.algorithm = NID_sha224,
331 		.in = 'a',
332 		.in_repetitions = 1000000,
333 		.out = {
334 			0x20, 0x79, 0x46, 0x55, 0x98, 0x0c, 0x91, 0xd8,
335 			0xbb, 0xb4, 0xc1, 0xea, 0x97, 0x61, 0x8a, 0x4b,
336 			0xf0, 0x3f, 0x42, 0x58, 0x19, 0x48, 0xb2, 0xee,
337 			0x4e, 0xe7, 0xad, 0x67,
338 		}
339 	},
340 
341 	/* SHA-256 */
342 	{
343 		.algorithm = NID_sha256,
344 		.in = 'a',
345 		.in_repetitions = 1000000,
346 		.out = {
347 			0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92,
348 			0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67,
349 			0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e,
350 			0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0,
351 		}
352 	},
353 
354 	/* SHA-384 */
355 	{
356 		.algorithm = NID_sha384,
357 		.in = 'a',
358 		.in_repetitions = 1000000,
359 		.out = {
360 			0x9d, 0x0e, 0x18, 0x09, 0x71, 0x64, 0x74, 0xcb,
361 			0x08, 0x6e, 0x83, 0x4e, 0x31, 0x0a, 0x4a, 0x1c,
362 			0xed, 0x14, 0x9e, 0x9c, 0x00, 0xf2, 0x48, 0x52,
363 			0x79, 0x72, 0xce, 0xc5, 0x70, 0x4c, 0x2a, 0x5b,
364 			0x07, 0xb8, 0xb3, 0xdc, 0x38, 0xec, 0xc4, 0xeb,
365 			0xae, 0x97, 0xdd, 0xd8, 0x7f, 0x3d, 0x89, 0x85,
366 		}
367 	},
368 
369 	/* SHA-512 */
370 	{
371 		.algorithm = NID_sha512,
372 		.in = 'a',
373 		.in_repetitions = 1000000,
374 		.out = {
375 			0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64,
376 			0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63,
377 			0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28,
378 			0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb,
379 			0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a,
380 			0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b,
381 			0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e,
382 			0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b,
383 		}
384 	},
385 };
386 
387 #define N_SHA_TESTS (sizeof(sha_tests) / sizeof(sha_tests[0]))
388 #define N_SHA_REPETITION_TESTS (sizeof(sha_repetition_tests) / sizeof(sha_repetition_tests[0]))
389 
390 typedef unsigned char *(*sha_hash_func)(const unsigned char *, size_t,
391     unsigned char *);
392 
393 static int
394 sha_hash_from_algorithm(int algorithm, const char **out_label,
395     sha_hash_func *out_func, const EVP_MD **out_md, size_t *out_len)
396 {
397 	const char *label;
398 	sha_hash_func sha_func;
399 	const EVP_MD *md;
400 	size_t len;
401 
402 	switch (algorithm) {
403 	case NID_sha1:
404 		label = SN_sha1;
405 		sha_func = SHA1;
406 		md = EVP_sha1();
407 		len = SHA_DIGEST_LENGTH;
408 		break;
409 	case NID_sha224:
410 		label = SN_sha224;
411 		sha_func = SHA224;
412 		md = EVP_sha224();
413 		len = SHA224_DIGEST_LENGTH;
414 		break;
415 	case NID_sha256:
416 		label = SN_sha256;
417 		sha_func = SHA256;
418 		md = EVP_sha256();
419 		len = SHA256_DIGEST_LENGTH;
420 		break;
421 	case NID_sha384:
422 		label = SN_sha384;
423 		sha_func = SHA384;
424 		md = EVP_sha384();
425 		len = SHA384_DIGEST_LENGTH;
426 		break;
427 	case NID_sha512:
428 		label = SN_sha512;
429 		sha_func = SHA512;
430 		md = EVP_sha512();
431 		len = SHA512_DIGEST_LENGTH;
432 		break;
433 	default:
434 		fprintf(stderr, "FAIL: unknown algorithm (%d)\n",
435 		    algorithm);
436 		return 0;
437 	}
438 
439 	if (out_label != NULL)
440 		*out_label = label;
441 	if (out_func != NULL)
442 		*out_func = sha_func;
443 	if (out_md != NULL)
444 		*out_md = md;
445 	if (out_len != NULL)
446 		*out_len = len;
447 
448 	return 1;
449 }
450 
451 static int
452 sha_test(void)
453 {
454 	sha_hash_func sha_func;
455 	const struct sha_test *st;
456 	EVP_MD_CTX *hash = NULL;
457 	const EVP_MD *md;
458 	uint8_t out[EVP_MAX_MD_SIZE];
459 	size_t in_len, out_len;
460 	size_t i;
461 	const char *label;
462 	int failed = 1;
463 
464 	if ((hash = EVP_MD_CTX_new()) == NULL) {
465 		fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n");
466 		goto failed;
467 	}
468 
469 	for (i = 0; i < N_SHA_TESTS; i++) {
470 		st = &sha_tests[i];
471 		if (!sha_hash_from_algorithm(st->algorithm, &label, &sha_func,
472 		    &md, &out_len))
473 			goto failed;
474 
475 		/* Digest */
476 		memset(out, 0, sizeof(out));
477 		sha_func(st->in, st->in_len, out);
478 		if (memcmp(st->out, out, out_len) != 0) {
479 			fprintf(stderr, "FAIL (%s): mismatch\n", label);
480 			goto failed;
481 		}
482 
483 		/* EVP single-shot digest */
484 		memset(out, 0, sizeof(out));
485 		if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) {
486 			fprintf(stderr, "FAIL (%s): EVP_Digest failed\n",
487 			    label);
488 			goto failed;
489 		}
490 
491 		if (memcmp(st->out, out, out_len) != 0) {
492 			fprintf(stderr, "FAIL (%s): EVP single-shot mismatch\n",
493 			    label);
494 			goto failed;
495 		}
496 
497 		/* EVP digest */
498 		memset(out, 0, sizeof(out));
499 		if (!EVP_DigestInit_ex(hash, md, NULL)) {
500 			fprintf(stderr, "FAIL (%s): EVP_DigestInit_ex failed\n",
501 			    label);
502 			goto failed;
503 		}
504 
505 		in_len = st->in_len / 2;
506 		if (!EVP_DigestUpdate(hash, st->in, in_len)) {
507 			fprintf(stderr,
508 			    "FAIL (%s): EVP_DigestUpdate first half failed\n",
509 			    label);
510 			goto failed;
511 		}
512 
513 		if (!EVP_DigestUpdate(hash, st->in + in_len,
514 		    st->in_len - in_len)) {
515 			fprintf(stderr,
516 			    "FAIL (%s): EVP_DigestUpdate second half failed\n",
517 			    label);
518 			goto failed;
519 		}
520 
521 		if (!EVP_DigestFinal_ex(hash, out, NULL)) {
522 			fprintf(stderr,
523 			    "FAIL (%s): EVP_DigestFinal_ex failed\n",
524 			    label);
525 			goto failed;
526 		}
527 
528 		if (memcmp(st->out, out, out_len) != 0) {
529 			fprintf(stderr, "FAIL (%s): EVP mismatch\n", label);
530 			goto failed;
531 		}
532 	}
533 
534 	failed = 0;
535 
536  failed:
537 	EVP_MD_CTX_free(hash);
538 	return failed;
539 }
540 
541 static int
542 sha_repetition_test(void)
543 {
544 	const struct sha_repetition_test *st;
545 	EVP_MD_CTX *hash = NULL;
546 	const EVP_MD *md;
547 	uint8_t buf[1024];
548 	uint8_t out[EVP_MAX_MD_SIZE];
549 	size_t out_len, part_len;
550 	size_t i, j;
551 	const char *label;
552 	int failed = 1;
553 
554 	if ((hash = EVP_MD_CTX_new()) == NULL) {
555 		fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n");
556 		goto failed;
557 	}
558 
559 	for (i = 0; i < N_SHA_REPETITION_TESTS; i++) {
560 		st = &sha_repetition_tests[i];
561 		if (!sha_hash_from_algorithm(st->algorithm, &label, NULL, &md,
562 		    &out_len))
563 			goto failed;
564 
565 		/* EVP digest */
566 		if (!EVP_DigestInit_ex(hash, md, NULL)) {
567 			fprintf(stderr,
568 			    "FAIL (%s): EVP_DigestInit_ex failed\n",
569 			    label);
570 			goto failed;
571 		}
572 
573 		memset(buf, st->in, sizeof(buf));
574 
575 		for (j = 0; j < st->in_repetitions;) {
576 			part_len = arc4random_uniform(sizeof(buf));
577 			if (part_len > st->in_repetitions - j)
578 				part_len = st->in_repetitions - j;
579 
580 			if (!EVP_DigestUpdate(hash, buf, part_len)) {
581 				fprintf(stderr,
582 				    "FAIL (%s): EVP_DigestUpdate failed\n",
583 				    label);
584 				goto failed;
585 			}
586 
587 			j += part_len;
588 		}
589 
590 		if (!EVP_DigestFinal_ex(hash, out, NULL)) {
591 			fprintf(stderr,
592 			    "FAIL (%s): EVP_DigestFinal_ex failed\n",
593 			    label);
594 			goto failed;
595 		}
596 
597 		if (memcmp(st->out, out, out_len) != 0) {
598 			fprintf(stderr, "FAIL (%s): EVP mismatch\n", label);
599 			goto failed;
600 		}
601 	}
602 
603 	failed = 0;
604 
605  failed:
606 	EVP_MD_CTX_free(hash);
607 	return failed;
608 }
609 
610 int
611 main(int argc, char **argv)
612 {
613 	int failed = 0;
614 
615 	failed |= sha_test();
616 	failed |= sha_repetition_test();
617 
618 	return failed;
619 }
620