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