summaryrefslogtreecommitdiff
path: root/src/regress/lib
diff options
context:
space:
mode:
authortb <>2022-11-17 19:06:35 +0000
committertb <>2022-11-17 19:06:35 +0000
commite165e48439b7352951e9b611223bb89cf830062e (patch)
tree1734ac46b96c48486d67bf795e4be7b60b0cfcb4 /src/regress/lib
parent39401085a3fd36d7c2ad32db5f56ac0b9fb95069 (diff)
downloadopenbsd-e165e48439b7352951e9b611223bb89cf830062e.tar.gz
openbsd-e165e48439b7352951e9b611223bb89cf830062e.tar.bz2
openbsd-e165e48439b7352951e9b611223bb89cf830062e.zip
Add a regression test for curve25519.c r1.14
Generate random signatures of random messages and verify them. Then check that the signature modified by adding the edwards25519 group order to the upper half are rejected. This would not always be accepted without the check in curve25519.c r1.14, but often enough that a few iterations suffice to expose the missing check.
Diffstat (limited to 'src/regress/lib')
-rw-r--r--src/regress/lib/libcrypto/curve25519/ed25519test.c134
1 files changed, 132 insertions, 2 deletions
diff --git a/src/regress/lib/libcrypto/curve25519/ed25519test.c b/src/regress/lib/libcrypto/curve25519/ed25519test.c
index 1ad070ae3b..9053ef0a83 100644
--- a/src/regress/lib/libcrypto/curve25519/ed25519test.c
+++ b/src/regress/lib/libcrypto/curve25519/ed25519test.c
@@ -1,6 +1,6 @@
1/* $OpenBSD: ed25519test.c,v 1.3 2022/11/09 17:49:54 jsing Exp $ */ 1/* $OpenBSD: ed25519test.c,v 1.4 2022/11/17 19:06:35 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Theo Buehler <tb@openbsd.org> 3 * Copyright (c) 2019, 2022 Theo Buehler <tb@openbsd.org>
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
@@ -17,6 +17,7 @@
17 17
18#include <err.h> 18#include <err.h>
19#include <stdio.h> 19#include <stdio.h>
20#include <stdlib.h>
20#include <string.h> 21#include <string.h>
21 22
22#include <openssl/curve25519.h> 23#include <openssl/curve25519.h>
@@ -353,6 +354,134 @@ test_ED25519_sign(void)
353 return failed; 354 return failed;
354} 355}
355 356
357static void
358hexdump(const unsigned char *buf, size_t len)
359{
360 size_t i;
361
362 for (i = 1; i <= len; i++)
363 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
364
365 if (len % 8)
366 fprintf(stderr, "\n");
367}
368
369static void
370dump_info(const uint8_t *message, size_t message_len, const uint8_t *public_key,
371 const uint8_t *private_key, const uint8_t *signature)
372{
373
374 fprintf(stderr, "message:\n");
375 hexdump(message, message_len);
376
377 fprintf(stderr, "public key:\n");
378 hexdump(public_key, ED25519_PUBLIC_KEY_LENGTH);
379 fprintf(stderr, "private key:\n");
380 hexdump(private_key, ED25519_PRIVATE_KEY_LENGTH);
381
382 if (signature != NULL) {
383 fprintf(stderr, "signature:\n");
384 hexdump(signature, ED25519_SIGNATURE_LENGTH);
385 }
386}
387
388static void
389dump_once(const char *description, const uint8_t *message, size_t message_len,
390 const uint8_t *public_key, const uint8_t *private_key,
391 const uint8_t *signature)
392{
393 static int dumped = 0;
394
395 if (dumped)
396 return;
397
398 fprintf(stderr, "%s\n", description);
399 dump_info(message, message_len, public_key, private_key, signature);
400
401 dumped = 1;
402}
403
404/*
405 * Little-endian representation of the order of edwards25519,
406 * see https://www.rfc-editor.org/rfc/rfc7748#section-4.1
407 */
408static const uint8_t order[] = {
409 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
410 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
413};
414
415/*
416 * Modify signature by adding the group order to the upper half of the
417 * signature. This is caught by the check added in curve25519.c r1.14.
418 */
419static void
420modify_signature(uint8_t *signature)
421{
422 uint8_t *upper_half = &signature[32];
423 size_t i;
424
425 for (i = 0; i < sizeof(order); i++) {
426 if (i < sizeof(order) - 1 && 0xff - order[i] < upper_half[i])
427 upper_half[i + 1] += 1;
428 upper_half[i] += order[i];
429 }
430}
431
432static int
433test_signature_malleability(void)
434{
435 uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH];
436 uint8_t private_key[ED25519_PRIVATE_KEY_LENGTH];
437 uint8_t message[32];
438 uint8_t signature[ED25519_SIGNATURE_LENGTH];
439 int failed = 1;
440
441 ED25519_keypair(public_key, private_key);
442 arc4random_buf(message, sizeof(message));
443
444 if (!ED25519_sign(signature, message, sizeof(message),
445 public_key, private_key)) {
446 fprintf(stderr, "Failed to sign random message\n");
447 dump_info(message, sizeof(message), public_key, private_key,
448 NULL);
449 goto err;
450 }
451
452 if (!ED25519_verify(message, sizeof(message), signature, public_key)) {
453 fprintf(stderr, "Failed to verify random message\n");
454 dump_info(message, sizeof(message), public_key, private_key,
455 signature);
456 goto err;
457 }
458
459 modify_signature(signature);
460
461 if (ED25519_verify(message, sizeof(message), signature, public_key)) {
462 dump_once("Verified with modified signature", message,
463 sizeof(message), public_key, private_key, signature);
464 goto err;
465 }
466
467 failed = 0;
468
469 err:
470 return failed;
471}
472
473static int
474test_ED25519_signature_malleability(void)
475{
476 int i;
477 int failed = 0;
478
479 for (i = 0; i < 128; i++)
480 failed |= test_signature_malleability();
481
482 return failed;
483}
484
356int 485int
357main(int argc, char *argv[]) 486main(int argc, char *argv[])
358{ 487{
@@ -360,6 +489,7 @@ main(int argc, char *argv[])
360 489
361 failed |= test_ED25519_verify(); 490 failed |= test_ED25519_verify();
362 failed |= test_ED25519_sign(); 491 failed |= test_ED25519_sign();
492 failed |= test_ED25519_signature_malleability();
363 493
364 if (failed) 494 if (failed)
365 fprintf(stderr, "FAILED\n"); 495 fprintf(stderr, "FAILED\n");