xref: /openbsd-src/regress/lib/libcrypto/sha/sha_test.c (revision 55e6bb006c4feedf4443043c9ffb01bc7e2ec48a)
1 /*	$OpenBSD: sha_test.c,v 1.1 2022/09/01 14:02:41 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 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
105 		    "mnopnopq",
106 		.in_len = 56,
107 		.out = {
108 			0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, 0xcc,
109 			0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, 0x01, 0x50,
110 			0xb0, 0xc6, 0x45, 0x5c, 0xb4, 0xf5, 0x8b, 0x19,
111 			0x52, 0x52, 0x25, 0x25,
112 		}
113 	},
114 	{
115 		.algorithm = NID_sha224,
116 		.in =
117 		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
118 		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
119 		    "mnopqrstnopqrstu",
120 		.in_len = 112,
121 		.out = {
122 			0xc9, 0x7c, 0xa9, 0xa5, 0x59, 0x85, 0x0c, 0xe9,
123 			0x7a, 0x04, 0xa9, 0x6d, 0xef, 0x6d, 0x99, 0xa9,
124 			0xe0, 0xe0, 0xe2, 0xab, 0x14, 0xe6, 0xb8, 0xdf,
125 			0x26, 0x5f, 0xc0, 0xb3,
126 		}
127 	},
128 
129 	/* SHA-256 */
130 	{
131 		.algorithm = NID_sha256,
132 		.in = "abc",
133 		.in_len = 3,
134 		.out = {
135 			0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
136 			0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
137 			0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
138 			0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
139 		}
140 	},
141 	{
142 		.algorithm = NID_sha256,
143 		.in = "",
144 		.in_len = 0,
145 		.out = {
146 			0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
147 			0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
148 			0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
149 			0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
150 		}
151 	},
152 	{
153 		.algorithm = NID_sha256,
154 		.in =
155 		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
156 		    "mnopnopq",
157 		.in_len = 56,
158 		.out = {
159 			0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
160 			0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
161 			0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
162 			0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
163 		}
164 	},
165 	{
166 		.algorithm = NID_sha256,
167 		.in =
168 		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
169 		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
170 		    "mnopqrstnopqrstu",
171 		.in_len = 112,
172 		.out = {
173 			0xcf, 0x5b, 0x16, 0xa7, 0x78, 0xaf, 0x83, 0x80,
174 			0x03, 0x6c, 0xe5, 0x9e, 0x7b, 0x04, 0x92, 0x37,
175 			0x0b, 0x24, 0x9b, 0x11, 0xe8, 0xf0, 0x7a, 0x51,
176 			0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1,
177 		}
178 	},
179 
180 	/* SHA-384 */
181 	{
182 		.algorithm = NID_sha384,
183 		.in = "abc",
184 		.in_len = 3,
185 		.out = {
186 			0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
187 			0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
188 			0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
189 			0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
190 			0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
191 			0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7,
192 		}
193 	},
194 	{
195 		.algorithm = NID_sha384,
196 		.in = "",
197 		.in_len = 0,
198 		.out = {
199 			0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38,
200 			0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
201 			0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43,
202 			0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
203 			0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb,
204 			0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b,
205 		}
206 	},
207 	{
208 		.algorithm = NID_sha384,
209 		.in =
210 		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
211 		    "mnopnopq",
212 		.in_len = 56,
213 		.out = {
214 			0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39,
215 			0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39,
216 			0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab,
217 			0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6,
218 			0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f,
219 			0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b,
220 		}
221 	},
222 	{
223 		.algorithm = NID_sha384,
224 		.in =
225 		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
226 		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
227 		    "mnopqrstnopqrstu",
228 		.in_len = 112,
229 		.out = {
230 			0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
231 			0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
232 			0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
233 			0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
234 			0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
235 			0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39,
236 		}
237 	},
238 
239 	/* SHA-512 */
240 	{
241 		.algorithm = NID_sha512,
242 		.in = "abc",
243 		.in_len = 3,
244 		.out = {
245 			0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
246 			0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
247 			0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
248 			0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
249 			0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
250 			0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
251 			0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
252 			0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,
253 		}
254 	},
255 	{
256 		.algorithm = NID_sha512,
257 		.in = "",
258 		.in_len = 0,
259 		.out = {
260 			0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
261 			0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
262 			0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
263 			0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
264 			0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
265 			0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
266 			0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
267 			0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e,
268 		}
269 	},
270 	{
271 		.algorithm = NID_sha512,
272 		.in =
273 		    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno"
274 		    "mnopnopq",
275 		.in_len = 56,
276 		.out = {
277 			0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a,
278 			0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16,
279 			0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8,
280 			0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35,
281 			0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9,
282 			0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0,
283 			0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03,
284 			0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45,
285 		}
286 	},
287 	{
288 		.algorithm = NID_sha512,
289 		.in =
290 		    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm"
291 		    "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
292 		    "mnopqrstnopqrstu",
293 		.in_len = 112,
294 		.out = {
295 			0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
296 			0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
297 			0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
298 			0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
299 			0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
300 			0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
301 			0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
302 			0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09,
303 		}
304 	},
305 };
306 
307 #define N_SHA_TESTS (sizeof(sha_tests) / sizeof(sha_tests[0]))
308 
309 static int
310 sha_test(void)
311 {
312 	unsigned char *(*sha_func)(const unsigned char *, size_t, unsigned char *);
313 	struct sha_test *st;
314 	EVP_MD_CTX *hash = NULL;
315 	const EVP_MD *md;
316 	uint8_t out[EVP_MAX_MD_SIZE];
317 	size_t in_len, out_len;
318 	size_t i;
319 	const char *label;
320 	int failed = 1;
321 
322 	if ((hash = EVP_MD_CTX_new()) == NULL) {
323 		fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n");
324 		goto failed;
325 	}
326 
327 	for (i = 0; i < N_SHA_TESTS; i++) {
328 		st = &sha_tests[i];
329 		switch (st->algorithm) {
330 		case NID_sha1:
331 			sha_func = SHA1;
332 			md = EVP_sha1();
333 			out_len = SHA_DIGEST_LENGTH;
334 			label = SN_sha1;
335 			break;
336 		case NID_sha224:
337 			sha_func = SHA224;
338 			md = EVP_sha224();
339 			out_len = SHA224_DIGEST_LENGTH;
340 			label = SN_sha224;
341 			break;
342 		case NID_sha256:
343 			sha_func = SHA256;
344 			md = EVP_sha256();
345 			out_len = SHA256_DIGEST_LENGTH;
346 			label = SN_sha256;
347 			break;
348 		case NID_sha384:
349 			sha_func = SHA384;
350 			md = EVP_sha384();
351 			out_len = SHA384_DIGEST_LENGTH;
352 			label = SN_sha384;
353 			break;
354 		case NID_sha512:
355 			sha_func = SHA512;
356 			md = EVP_sha512();
357 			out_len = SHA512_DIGEST_LENGTH;
358 			label = SN_sha512;
359 			break;
360 		default:
361 			fprintf(stderr, "FAIL: unknown algorithm (%d)\n",
362 			    st->algorithm);
363 			goto failed;
364 		}
365 
366 		/* Digest */
367 		memset(out, 0, sizeof(out));
368 		sha_func(st->in, st->in_len, out);
369 		if (memcmp(st->out, out, out_len) != 0) {
370 			fprintf(stderr, "FAIL (%s): mismatch\n", label);
371 			goto failed;
372 		}
373 
374 		/* EVP single-shot digest */
375 		memset(out, 0, sizeof(out));
376 		if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) {
377 			fprintf(stderr, "FAIL (%s): EVP_Digest failed\n", label);
378 			goto failed;
379 		}
380 
381 		if (memcmp(st->out, out, out_len) != 0) {
382 			fprintf(stderr, "FAIL (%s): EVP single-shot mismatch\n",
383 			    label);
384 			goto failed;
385 		}
386 
387 		/* EVP digest */
388 		memset(out, 0, sizeof(out));
389 		if (!EVP_DigestInit_ex(hash, md, NULL)) {
390 			fprintf(stderr, "FAIL (%s): EVP_DigestInit_ex failed\n",
391 			    label);
392 			goto failed;
393 		}
394 
395 		in_len = st->in_len / 2;
396 		if (!EVP_DigestUpdate(hash, st->in, in_len)) {
397 			fprintf(stderr,
398 			    "FAIL (%s): EVP_DigestUpdate first half failed\n",
399 			    label);
400 			goto failed;
401 		}
402 
403 		if (!EVP_DigestUpdate(hash, st->in + in_len,
404 		    st->in_len - in_len)) {
405 			fprintf(stderr,
406 			    "FAIL (%s): EVP_DigestUpdate second half failed\n",
407 			    label);
408 			goto failed;
409 		}
410 
411 		if (!EVP_DigestFinal_ex(hash, out, NULL)) {
412 			fprintf(stderr,
413 			    "FAIL (%s): EVP_DigestFinal_ex failed\n",
414 			    label);
415 			goto failed;
416 		}
417 
418 		if (memcmp(st->out, out, out_len) != 0) {
419 			fprintf(stderr, "FAIL (%s): EVP mismatch\n", label);
420 			goto failed;
421 		}
422 	}
423 
424 	failed = 0;
425 
426  failed:
427 	EVP_MD_CTX_free(hash);
428 	return failed;
429 }
430 
431 int
432 main(int argc, char **argv)
433 {
434 	int failed = 0;
435 
436 	failed |= sha_test();
437 
438 	return failed;
439 }
440