summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/md/md_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libcrypto/md/md_test.c')
-rw-r--r--src/regress/lib/libcrypto/md/md_test.c210
1 files changed, 94 insertions, 116 deletions
diff --git a/src/regress/lib/libcrypto/md/md_test.c b/src/regress/lib/libcrypto/md/md_test.c
index 590bb50ee3..752f2e4958 100644
--- a/src/regress/lib/libcrypto/md/md_test.c
+++ b/src/regress/lib/libcrypto/md/md_test.c
@@ -1,6 +1,6 @@
1/* $OpenBSD: md_test.c,v 1.3 2025/01/19 10:17:39 tb Exp $ */ 1/* $OpenBSD: md_test.c,v 1.4 2025/05/22 03:24:47 joshua Exp $ */
2/* 2/*
3 * Copyright (c) 2022 Joshua Sing <joshua@hypera.dev> 3 * Copyright (c) 2022, 2025 Joshua Sing <joshua@joshuasing.dev>
4 * 4 *
5 * Permission to use, copy, modify, and distribute this software for any 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 6 * purpose with or without fee is hereby granted, provided that the above
@@ -22,6 +22,8 @@
22#include <stdint.h> 22#include <stdint.h>
23#include <string.h> 23#include <string.h>
24 24
25#include "test.h"
26
25struct md_test { 27struct md_test {
26 const int algorithm; 28 const int algorithm;
27 const uint8_t in[128]; 29 const uint8_t in[128];
@@ -30,7 +32,7 @@ struct md_test {
30}; 32};
31 33
32static const struct md_test md_tests[] = { 34static const struct md_test md_tests[] = {
33 /* MD4 (RFC 1320 test vectors) */ 35 /* MD4 (RFC 1320 test vectors) */
34 { 36 {
35 .algorithm = NID_md4, 37 .algorithm = NID_md4,
36 .in = "", 38 .in = "",
@@ -99,7 +101,7 @@ static const struct md_test md_tests[] = {
99 } 101 }
100 }, 102 },
101 103
102 /* MD5 (RFC 1321 test vectors) */ 104 /* MD5 (RFC 1321 test vectors) */
103 { 105 {
104 .algorithm = NID_md5, 106 .algorithm = NID_md5,
105 .in = "", 107 .in = "",
@@ -175,25 +177,21 @@ typedef unsigned char *(*md_hash_func)(const unsigned char *, size_t,
175 unsigned char *); 177 unsigned char *);
176 178
177static int 179static int
178md_hash_from_algorithm(int algorithm, const char **out_label, 180md_hash_from_algorithm(int algorithm, md_hash_func *out_func,
179 md_hash_func *out_func, const EVP_MD **out_md, size_t *out_len) 181 const EVP_MD **out_md, size_t *out_len)
180{ 182{
181 switch (algorithm) { 183 switch (algorithm) {
182 case NID_md4: 184 case NID_md4:
183 *out_label = SN_md4;
184 *out_func = MD4; 185 *out_func = MD4;
185 *out_md = EVP_md4(); 186 *out_md = EVP_md4();
186 *out_len = MD4_DIGEST_LENGTH; 187 *out_len = MD4_DIGEST_LENGTH;
187 break; 188 break;
188 case NID_md5: 189 case NID_md5:
189 *out_label = SN_md5;
190 *out_func = MD5; 190 *out_func = MD5;
191 *out_md = EVP_md5(); 191 *out_md = EVP_md5();
192 *out_len = MD5_DIGEST_LENGTH; 192 *out_len = MD5_DIGEST_LENGTH;
193 break; 193 break;
194 default: 194 default:
195 fprintf(stderr, "FAIL: unknown algorithm (%d)\n",
196 algorithm);
197 return 0; 195 return 0;
198 } 196 }
199 197
@@ -201,108 +199,100 @@ md_hash_from_algorithm(int algorithm, const char **out_label,
201} 199}
202 200
203static void 201static void
204hexdump(const unsigned char *buf, size_t len) 202test_md_tv(struct test *t, const void *arg)
205{
206 size_t i;
207
208 for (i = 1; i <= len; i++)
209 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
210
211 fprintf(stderr, "\n");
212}
213
214static int
215md_test(void)
216{ 203{
217 unsigned char *(*md_func)(const unsigned char *, size_t, unsigned char *); 204 const struct md_test *st = arg;
218 const struct md_test *st; 205 md_hash_func md_func;
219 EVP_MD_CTX *hash = NULL;
220 const EVP_MD *md; 206 const EVP_MD *md;
207 EVP_MD_CTX *hash = NULL;
221 uint8_t out[EVP_MAX_MD_SIZE]; 208 uint8_t out[EVP_MAX_MD_SIZE];
222 size_t in_len, out_len; 209 size_t in_len, out_len;
223 size_t i;
224 const char *label;
225 int failed = 1;
226 210
227 if ((hash = EVP_MD_CTX_new()) == NULL) { 211 if (!md_hash_from_algorithm(st->algorithm, &md_func, &md, &out_len)) {
228 fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n"); 212 test_errorf(t, "md_hash_from_algorithm: unknown algorithm: %d",
229 goto failed; 213 st->algorithm);
214 goto fail;
230 } 215 }
231 216
232 for (i = 0; i < N_MD_TESTS; i++) { 217 if ((hash = EVP_MD_CTX_new()) == NULL) {
233 st = &md_tests[i]; 218 test_errorf(t, "EVP_MD_CTX_new()");
234 if (!md_hash_from_algorithm(st->algorithm, &label, &md_func, 219 goto fail;
235 &md, &out_len)) 220 }
236 goto failed;
237
238 /* Digest */
239 memset(out, 0, sizeof(out));
240 md_func(st->in, st->in_len, out);
241 if (memcmp(st->out, out, out_len) != 0) {
242 fprintf(stderr, "FAIL (%s): mismatch\n", label);
243 goto failed;
244 }
245 221
246 /* EVP single-shot digest */ 222 /* Digest */
247 memset(out, 0, sizeof(out)); 223 memset(out, 0, sizeof(out));
248 if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) { 224 md_func(st->in, st->in_len, out);
249 fprintf(stderr, "FAIL (%s): EVP_Digest failed\n", 225 if (memcmp(st->out, out, out_len) != 0) {
250 label); 226 test_errorf(t, "MD: digest output mismatch");
251 goto failed; 227 test_hexdiff(t, out, out_len, st->out);
252 } 228 }
253 229
254 if (memcmp(st->out, out, out_len) != 0) { 230 /* EVP single-shot digest */
255 fprintf(stderr, "FAIL (%s): EVP single-shot mismatch\n", 231 memset(out, 0, sizeof(out));
256 label); 232 if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) {
257 goto failed; 233 test_errorf(t, "EVP_Digest()");
258 } 234 goto fail;
235 }
236 if (memcmp(st->out, out, out_len) != 0) {
237 test_errorf(t, "EVP_Digest: digest output mismatch");
238 test_hexdiff(t, out, out_len, st->out);
239 }
259 240
260 /* EVP digest */ 241 /* EVP digest */
261 memset(out, 0, sizeof(out)); 242 memset(out, 0, sizeof(out));
262 if (!EVP_DigestInit_ex(hash, md, NULL)) { 243 if (!EVP_DigestInit_ex(hash, md, NULL)) {
263 fprintf(stderr, "FAIL (%s): EVP_DigestInit_ex failed\n", 244 test_errorf(t, "EVP_DigestInit_ex()");
264 label); 245 goto fail;
265 goto failed; 246 }
266 }
267 247
268 in_len = st->in_len / 2; 248 in_len = st->in_len / 2;
269 if (!EVP_DigestUpdate(hash, st->in, in_len)) { 249 if (!EVP_DigestUpdate(hash, st->in, in_len)) {
270 fprintf(stderr, 250 test_errorf(t, "EVP_DigestUpdate: first half failed");
271 "FAIL (%s): EVP_DigestUpdate first half failed\n", 251 goto fail;
272 label); 252 }
273 goto failed;
274 }
275 253
276 if (!EVP_DigestUpdate(hash, st->in + in_len, 254 if (!EVP_DigestUpdate(hash, st->in + in_len,
277 st->in_len - in_len)) { 255 st->in_len - in_len)) {
278 fprintf(stderr, 256 test_errorf(t, "EVP_DigestUpdate: second half failed");
279 "FAIL (%s): EVP_DigestUpdate second half failed\n", 257 goto fail;
280 label); 258 }
281 goto failed;
282 }
283 259
284 if (!EVP_DigestFinal_ex(hash, out, NULL)) { 260 if (!EVP_DigestFinal_ex(hash, out, NULL)) {
285 fprintf(stderr, 261 test_errorf(t, "EVP_DigestFinal_ex()");
286 "FAIL (%s): EVP_DigestFinal_ex failed\n", 262 goto fail;
287 label); 263 }
288 goto failed;
289 }
290 264
291 if (memcmp(st->out, out, out_len) != 0) { 265 if (memcmp(st->out, out, out_len) != 0) {
292 fprintf(stderr, "FAIL (%s): EVP mismatch\n", label); 266 test_errorf(t, "EVP: digest output mismatch");
293 goto failed; 267 test_hexdiff(t, out, out_len, st->out);
294 }
295 } 268 }
296 269
297 failed = 0;
298 270
299 failed: 271 fail:
300 EVP_MD_CTX_free(hash); 272 EVP_MD_CTX_free(hash);
301 return failed;
302} 273}
303 274
304static int 275static void
305md5_large_test(void) 276test_md(struct test *t, const void *arg)
277{
278 const struct md_test *st;
279 size_t i;
280 char *name;
281
282 for (i = 0; i < N_MD_TESTS; i++) {
283 st = &md_tests[i];
284 if (asprintf(&name, "%s: '%s'", OBJ_nid2sn(st->algorithm), st->in) == -1) {
285 test_errorf(t, "create test name");
286 return;
287 }
288
289 test_run(t, name, test_md_tv, st);
290 free(name);
291 }
292}
293
294static void
295test_md5_large(struct test *t, const void *arg)
306{ 296{
307 MD5_CTX ctx; 297 MD5_CTX ctx;
308 uint8_t in[1024]; 298 uint8_t in[1024];
@@ -310,12 +300,10 @@ md5_large_test(void)
310 unsigned int out_len; 300 unsigned int out_len;
311 size_t in_len; 301 size_t in_len;
312 size_t i; 302 size_t i;
313 const char *label;
314 uint8_t want[] = { 303 uint8_t want[] = {
315 0xd8, 0xbc, 0xae, 0x13, 0xb5, 0x5a, 0xb0, 0xfc, 304 0xd8, 0xbc, 0xae, 0x13, 0xb5, 0x5a, 0xb0, 0xfc,
316 0x7f, 0x8a, 0xe1, 0x78, 0x27, 0x8d, 0x44, 0x1b, 305 0x7f, 0x8a, 0xe1, 0x78, 0x27, 0x8d, 0x44, 0x1b,
317 }; 306 };
318 int failed = 1;
319 307
320 memset(in, 'A', sizeof(in)); 308 memset(in, 'A', sizeof(in));
321 in_len = sizeof(in); 309 in_len = sizeof(in);
@@ -323,44 +311,34 @@ md5_large_test(void)
323 memset(out, 0, sizeof(out)); 311 memset(out, 0, sizeof(out));
324 out_len = 16; 312 out_len = 16;
325 313
326 label = "md5";
327
328 MD5_Init(&ctx); 314 MD5_Init(&ctx);
329 315
330 for (i = 0; i < (1<<29) + 1; i += in_len) { 316 for (i = 0; i < (1<<29) + 1; i += in_len) {
331 if (!MD5_Update(&ctx, in, in_len)) { 317 if (!MD5_Update(&ctx, in, in_len)) {
332 fprintf(stderr, "FAIL (%s): MD5_Update failed\n", label); 318 test_errorf(t, "MD5_Update()");
333 goto failed; 319 return;
334 } 320 }
335 } 321 }
336 if (!MD5_Final(out, &ctx)) { 322 if (!MD5_Final(out, &ctx)) {
337 fprintf(stderr, "FAIL (%s): MD5_Final failed\n", label); 323 test_errorf(t, "MD5_Final()");
338 goto failed; 324 return;
339 } 325 }
340 326
341 if (memcmp(out, want, out_len) != 0) { 327 if (memcmp(out, want, out_len) != 0) {
342 fprintf(stderr, "FAIL (%s): MD5 mismatch\n", label); 328 test_errorf(t, "MD5 digest output mismatch");
343 hexdump(out, out_len); 329 test_hexdump(t, out, out_len);
344 goto failed;
345 } 330 }
346 if (ctx.Nh != 0x1 || ctx.Nl != 0x2000) { 331 if (ctx.Nh != 0x1 || ctx.Nl != 0x2000)
347 fprintf(stderr, "FAIL (%s): MD5 incorrect bit length\n", label); 332 test_errorf(t, "MD5 incorrect bit length");
348 goto failed;
349 }
350
351 failed = 0;
352
353 failed:
354 return failed;
355} 333}
356 334
357int 335int
358main(int argc, char **argv) 336main(int argc, char **argv)
359{ 337{
360 int failed = 0; 338 struct test *t = test_init();
361 339
362 failed |= md_test(); 340 test_run(t, "md", test_md, NULL);
363 failed |= md5_large_test(); 341 test_run(t, "md5 large", test_md5_large, NULL);
364 342
365 return failed; 343 return test_result(t);
366} 344}