]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Fix ECDSA verify corner case
authorNiels Möller <nisse@lysator.liu.se>
Wed, 14 Sep 2022 14:17:52 +0000 (16:17 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Wed, 14 Sep 2022 14:17:52 +0000 (16:17 +0200)
* ecc-ecdsa-verify.c (ecc_ecdsa_verify): Use ecc_nonsec_add_jjj,
to produce correct result in a corner case where point addition
needs to use point duplication. Also use ecc_j_to_a rather than
ecc->h_to_a, since ecdsa supports only weierstrass curves.
* ecc-gostdsa-verify.c (ecc_gostdsa_verify): Analogous change.

* testsuite/ecdsa-verify-test.c (test_main): Add corresponding test.
* testsuite/ecdsa-sign-test.c (test_main): And a test producing
the problematic signature.

ChangeLog
ecc-ecdsa-verify.c
ecc-gostdsa-verify.c
testsuite/ecdsa-sign-test.c
testsuite/ecdsa-verify-test.c

index 41863a07b1dac14ad4c8106c17333903b146f80c..0f497b525f850a7bf364981a0b7e9d840cbb7a2d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,16 @@
        * Makefile.in (hogweed_SOURCES): Add ecc-nonsec-add-jjj.c.
        * testsuite/ecc-add-test.c (test_main): Add tests for ecc_nonsec_add_jjj.
 
+       * ecc-ecdsa-verify.c (ecc_ecdsa_verify): Use ecc_nonsec_add_jjj,
+       to produce correct result in a corner case where point addition
+       needs to use point duplication. Also use ecc_j_to_a rather than
+       ecc->h_to_a, since ecdsa supports only weierstrass curves.
+       * ecc-gostdsa-verify.c (ecc_gostdsa_verify): Analogous change.
+
+       * testsuite/ecdsa-verify-test.c (test_main): Add corresponding test.
+       * testsuite/ecdsa-sign-test.c (test_main): And a test producing
+       the problematic signature.
+
 2022-09-08  Niels Möller  <nisse@lysator.liu.se>
 
        * eccdata.c (string_toupper): New utility function.
index f3b112b0360c00d53f1c6050f683b2147bc72fe9..bd6491a19c2109ad3fdce674337d480eaa713a0b 100644 (file)
@@ -117,25 +117,13 @@ ecc_ecdsa_verify (const struct ecc_curve *ecc,
       /* Total storage: 7*ecc->p.size + ecc->mul_g_itch (ecc->p.size) */
       ecc->mul_g (ecc, P1, u1, P1 + 3*ecc->p.size);
 
-      /* NOTE: ecc_add_jjj and/or ecc_j_to_a will produce garbage in
-        case u1 G = +/- u2 V. However, anyone who gets his or her
-        hands on a signature where this happens during verification,
-        can also get the private key as z = +/- u1 / u_2 (mod q). And
-        then it doesn't matter very much if verification of
-        signatures with that key succeeds or fails.
-
-        u1 G = - u2 V can never happen for a correctly generated
-        signature, since it implies k = 0.
-
-        u1 G = u2 V is possible, if we are unlucky enough to get h /
-        s_1 = z. Hitting that is about as unlikely as finding the
-        private key by guessing.
-       */
-      /* Total storage: 6*ecc->p.size + ecc->add_hhh_itch */
-      ecc->add_hhh (ecc, P2, P2, P1, P1 + 3*ecc->p.size);
+      /* Total storage: 6*ecc->p.size + ECC_ADD_JJA_ITCH(size) */
+      if (!ecc_nonsec_add_jjj (ecc, P2, P2, P1, P1 + 3*ecc->p.size))
+       /* Infinity point, not a valid signature. */
+       return 0;
     }
   /* x coordinate only, modulo q */
-  ecc->h_to_a (ecc, 2, P1, P2, P1 + 3*ecc->p.size);
+  ecc_j_to_a (ecc, 2, P1, P2, P1 + 3*ecc->p.size);
 
   return (mpn_cmp (rp, P1, ecc->p.size) == 0);
 #undef P2
index fcdd46442553c25cb21070e3d286ad9907cc6791..d1b0454f9218a0914f4d0146f276d0ddcefa2072 100644 (file)
@@ -115,10 +115,11 @@ ecc_gostdsa_verify (const struct ecc_curve *ecc,
   ecc->mul_g (ecc, P1, z1, P1 + 3*ecc->p.size);
 
   /* Total storage: 6*ecc->p.size + ecc->add_hhh_itch */
-  ecc->add_hhh (ecc, P1, P1, P2, P1 + 3*ecc->p.size);
+  if (!ecc_nonsec_add_jjj (ecc, P1, P1, P2, P1 + 3*ecc->p.size))
+    return 0;
 
   /* x coordinate only, modulo q */
-  ecc->h_to_a (ecc, 2, P2, P1, P1 + 3*ecc->p.size);
+  ecc_j_to_a (ecc, 2, P2, P1, P1 + 3*ecc->p.size);
 
   return (mpn_cmp (rp, P2, ecc->p.size) == 0);
 #undef P2
index c79493aeebaf18271d0d5f348f8ab20a20d5517a..b8a100b60324e5e4f049e9a9f1475481338cccb8 100644 (file)
@@ -77,6 +77,18 @@ test_main (void)
              "3a41e1423b1853e8aa89747b1f987364"
              "44705d6d6d8371ea1f578f2e"); /* s */
 
+  /* Produce a signature where verify operation results in a point duplication. */
+  test_ecdsa (&_nettle_secp_256r1,
+             "1", /* Private key */
+             "01010101010101010101010101010101"
+             "01010101010101010101010101010101", /* nonce */
+             SHEX("6ff03b949241ce1dadd43519e6960e0a"
+                  "85b41a69a05c328103aa2bce1594ca16"), /* hash */
+             "6ff03b949241ce1dadd43519e6960e0a"
+             "85b41a69a05c328103aa2bce1594ca16", /* r */
+             "53f097727a0e0dc284a0daa0da0ab77d"
+             "5792ae67ed075d1f8d5bda0f853fa093"); /* s */
+
   /* Test cases for the smaller groups, verified with a
      proof-of-concept implementation done for Yubico AB. */
   test_ecdsa (&_nettle_secp_192r1,
index 8110c64dc2c7da758af24765bde5b2406f8982e0..8d527000b3410b47dd9bde6a7a0a79a2f5e32a8e 100644 (file)
@@ -109,6 +109,21 @@ test_main (void)
              "952800792ed19341fdeeec047f2514f3b0f150d6066151fb", /* r */
              "ec5971222014878b50d7a19d8954bc871e7e65b00b860ffb"); /* s */
 
+  /* Test case provided by Guido Vranken, from oss-fuzz. Triggers
+     point duplication in the verify operation by using private key =
+     1 (public key = generator) and hash = r. */
+  test_ecdsa (&_nettle_secp_256r1,
+             "6B17D1F2E12C4247F8BCE6E563A440F2"
+             "77037D812DEB33A0F4A13945D898C296", /* x */
+             "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16"
+             "2BCE33576B315ECECBB6406837BF51F5", /* y */
+             SHEX("6ff03b949241ce1dadd43519e6960e0a"
+                  "85b41a69a05c328103aa2bce1594ca16"), /* hash */
+             "6ff03b949241ce1dadd43519e6960e0a"
+             "85b41a69a05c328103aa2bce1594ca16", /* r */
+             "53f097727a0e0dc284a0daa0da0ab77d"
+             "5792ae67ed075d1f8d5bda0f853fa093"); /* s */
+
   /* From RFC 4754 */
   test_ecdsa (&_nettle_secp_256r1,
              "2442A5CC 0ECD015F A3CA31DC 8E2BBC70"