]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Add tests for edge cases in poly1305 digest folding.
authorNiels Möller <nisse@lysator.liu.se>
Fri, 28 Jan 2022 18:35:38 +0000 (19:35 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Fri, 28 Jan 2022 18:35:38 +0000 (19:35 +0100)
ChangeLog
misc/poly1305-gen-example.pike [new file with mode: 0755]
testsuite/poly1305-test.c

index eac25a0d969c8484bbcc5e0179fab0bd94943c88..ca2a6718de31e2d11f12baf6f8fbac5f09de4fbb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2022-01-28  Niels Möller  <nisse@lysator.liu.se>
+
+       * testsuite/poly1305-test.c (poly1305_internal): Renamed function,
+       was test_poly1305_internal.
+       (test_poly1305_internal): New helper function.
+       (test_fixed): New function, to test internal functions with fixed
+       test inputs.
+       (test_random): Use test_poly1305_internal.
+       (test_main): Call test_fixed.
+
+       * misc/poly1305-gen-example.pike: Program to generate poly1305
+       inputs with a given digest.
+
 2022-01-27  Niels Möller  <nisse@lysator.liu.se>
 
        * x86_64/poly1305-internal.asm: Rewrote. Rearrange folding, so
diff --git a/misc/poly1305-gen-example.pike b/misc/poly1305-gen-example.pike
new file mode 100755 (executable)
index 0000000..8e5bfa2
--- /dev/null
@@ -0,0 +1,42 @@
+#! /usr/bin/pike
+
+void write_little_endian(int x) {
+  for (int i = 0; i < 16; i++, x >>= 8) {
+    write("%02x", x & 0xff);
+  }
+}
+
+int main (int argc, array(string) argv) {
+  int p = (1<<130) - 5;
+  int mask = 0x0ffffffc0ffffffc0ffffffc0fffffff;
+
+  int digest = (argc > 1) ? (int) argv[1] % p : 0;
+  int r = random(1<<128) & mask;
+  int r2 = r*r%p;
+
+  for (;;) {
+    int m0 = random(1<<128) | (1<<128);
+    /* We want m0 r^2 + m1 r = digest (mod p), or
+
+         m1 = (digest - m0 r^2 ) r^-1 (mod p)
+
+       To be a valid message, this must also satisfy (m1 >> 128) == 1
+    */
+    int m1 = r->invert(p) * (digest - m0 * r2) % p;
+    if ((m1 >> 128) == 1) {
+      write ("r = 0x%x\n", r);
+      write ("m0 = 0x%x\n", m0);
+      write ("m1 = 0x%x\n", m1);
+      write ("out = 0x%x\n\n", digest);
+
+      write ("r = le "); write_little_endian(r);
+      write ("\nm0 = le "); write_little_endian(m0);
+      write ("\nm1 = le "); write_little_endian(m1);
+      write ("\nout = le "); write_little_endian(digest);
+      write("\n");
+      if ((m0*r2 + m1*r) % p != digest)
+        error("inconsistent result");
+      return 0;
+    }
+  }
+}
index 8bca9dd6625eb4f78fbdae11028ca11a79377919..d13af236076bb4ce63e7f7daff642e44c316565b 100644 (file)
@@ -43,9 +43,9 @@ test_poly1305 (const struct tstring *key,
 }
 
 static void
-test_poly1305_internal (const uint8_t key[16],
-                       size_t length, const uint8_t *message,
-                       union nettle_block16 *nonce)
+poly1305_internal (const uint8_t key[16],
+                  size_t length, const uint8_t *message,
+                  union nettle_block16 *nonce)
 {
   struct poly1305_ctx ctx;
   _nettle_poly1305_set_key (&ctx, key);
@@ -123,6 +123,68 @@ ref_poly1305_internal (const uint8_t key[16],
   mpz_clear (m);
 }
 
+static void
+test_poly1305_internal (const uint8_t key[16],
+                       size_t length, const uint8_t *message,
+                       const uint8_t nonce[16],
+                       const uint8_t ref[16])
+{
+  union nettle_block16 digest;
+
+  memcpy (digest.b, nonce, sizeof(digest.b));
+  poly1305_internal (key, length, message, &digest);
+
+  if (!MEMEQ (sizeof(digest.b), digest.b, ref))
+    {
+      printf ("poly1305_internal failed\n");
+      printf ("key: "); print_hex (16, key);
+      printf ("nonce: "); print_hex (16, nonce);
+      printf ("msg: "); print_hex (length, message);
+      printf ("length: %u\n", (unsigned) length);
+      printf ("tag: "); print_hex (16, digest.b);
+      printf ("ref: "); print_hex (16, ref);
+      abort();
+    }
+}
+
+static void
+test_fixed (void)
+{
+  static uint8_t nonce[16] = {0};
+  static const struct {
+    char *key;
+    char *message;
+    char *digest;
+  } test_cases[] = {
+    {"9959780624f5670ccc9e530738ddd70a",
+     "82785d0bbe75181ea188c1a0d8dd81cf90d1c0f1cfa97912e92ab91bd3357368",
+     "00000000000000000000000000000000"},
+    {"6c72ea0dc487510934252a01544e9307",
+     "0b6a6a734cb67fe9a548a81f21ec3db398c1ed1a62715e993e67f0a682b75990",
+     "01000000000000000000000000000000"},
+    {"64447e0bdca48e0a30c5af06ec830008",
+     "1fd9b81b8310bdf6007549d6d06df6d07e37c8a8500edd91874a5657cff1c1ba",
+     "faffffffffffffffffffffffffffffff"},
+    {"054a840700390c092c422e037825c709",
+     "3faabe212f024da30f8f7064d3dab6f426c5a408de0bec35624b6793a0d4a353",
+     "05000000000000000000000000000000",}
+  };
+  size_t i;
+
+  for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++)
+    {
+      struct tstring *key = tstring_hex(test_cases[i].key);
+      struct tstring *message = tstring_hex(test_cases[i].message);
+      struct tstring *digest = tstring_hex(test_cases[i].digest);
+      union nettle_block16 out;
+      ASSERT (key->length == 16);
+      ASSERT (digest->length == 16);
+
+      memset (out.b, 0, sizeof(out.b));
+      test_poly1305_internal (key->data, message->length, message->data, nonce, digest->data);
+    }
+}
+
 #define COUNT 100000
 #define MAX_MESSAGE_SIZE 300
 
@@ -139,7 +201,6 @@ test_random(void)
       uint8_t nonce[16];
       uint8_t message[MAX_MESSAGE_SIZE];
       size_t length;
-      union nettle_block16 digest;
       union nettle_block16 ref;
 
       knuth_lfib_random (&rand_ctx, sizeof(key), key);
@@ -150,22 +211,10 @@ test_random(void)
 
       knuth_lfib_random (&rand_ctx, length, message);
 
-      memcpy (digest.b, nonce, sizeof(digest.b));
-      test_poly1305_internal (key, length, message, &digest);
-
       memcpy (ref.b, nonce, sizeof(ref.b));
       ref_poly1305_internal (key, length, message, &ref);
-      if (!MEMEQ (sizeof(ref.b), digest.b, ref.b))
-       {
-         printf ("poly1305-internal failed\n");
-         printf ("key: "); print_hex (16, key);
-         printf ("nonce: "); print_hex (16, nonce);
-         printf ("msg: "); print_hex (length, message);
-         printf ("length: %u\n", (unsigned) length);
-         printf ("tag: "); print_hex (16, digest.b);
-         printf ("ref: "); print_hex (16, ref.b);
-         abort();
-       }
+
+      test_poly1305_internal (key, length, message, nonce, ref.b);
     }
 }
 
@@ -201,5 +250,6 @@ test_main(void)
          "5c1bf9"),
     SHEX("5154ad0d2cb26e01274fc51148491f1b"));
 
+  test_fixed();
   test_random();
 }