[tor-commits] [tor/master] ed25519: Add func that checks for torsion component in pubkeys.

nickm at torproject.org nickm at torproject.org
Tue Jun 27 21:25:46 UTC 2017


commit 559658ff1ca1492543ad60d10b7101c70a62eaa2
Author: George Kadianakis <desnacked at riseup.net>
Date:   Tue Apr 25 15:19:41 2017 +0300

    ed25519: Add func that checks for torsion component in pubkeys.
    
    See https://lists.torproject.org/pipermail/tor-dev/2017-April/012213.html .
---
 changes/bug22006                          |  4 +++
 src/common/crypto_ed25519.c               | 50 +++++++++++++++++++++++++++++++
 src/common/crypto_ed25519.h               |  2 ++
 src/ext/ed25519/donna/ed25519_donna_tor.h |  5 ++++
 src/ext/ed25519/donna/ed25519_tor.c       | 27 +++++++++++++++++
 src/ext/ed25519/ref10/blinding.c          | 37 +++++++++++++++++++++++
 src/ext/ed25519/ref10/ed25519_ref10.h     |  4 +++
 7 files changed, 129 insertions(+)

diff --git a/changes/bug22006 b/changes/bug22006
new file mode 100644
index 0000000..912bdd8
--- /dev/null
+++ b/changes/bug22006
@@ -0,0 +1,4 @@
+  o Minor features (ed25519):
+    - Add validation function that checks for torsion components in ed25119
+      public keys. Currently unused but will be used by prop224 client-side
+      code. Addresses ticket #22006. Math help by Ian Goldberg.
diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c
index 188e18c..6ebb2a7 100644
--- a/src/common/crypto_ed25519.c
+++ b/src/common/crypto_ed25519.c
@@ -28,6 +28,7 @@
 #include "crypto_format.h"
 #include "torlog.h"
 #include "util.h"
+#include "util_format.h"
 
 #include "ed25519/ref10/ed25519_ref10.h"
 #include "ed25519/donna/ed25519_donna_tor.h"
@@ -57,6 +58,9 @@ typedef struct {
 
   int (*pubkey_from_curve25519_pubkey)(unsigned char *, const unsigned char *,
                                        int);
+
+  int (*ed25519_scalarmult_with_group_order)(unsigned char *,
+                                             const unsigned char *);
 } ed25519_impl_t;
 
 /** The Ref10 Ed25519 implementation. This one is pure C and lightly
@@ -77,6 +81,7 @@ static const ed25519_impl_t impl_ref10 = {
   ed25519_ref10_blind_public_key,
 
   ed25519_ref10_pubkey_from_curve25519_pubkey,
+  ed25519_ref10_scalarmult_with_group_order,
 };
 
 /** The Ref10 Ed25519 implementation. This one is heavily optimized, but still
@@ -97,6 +102,7 @@ static const ed25519_impl_t impl_donna = {
   ed25519_donna_blind_public_key,
 
   ed25519_donna_pubkey_from_curve25519_pubkey,
+  ed25519_donna_scalarmult_with_group_order,
 };
 
 /** Which Ed25519 implementation are we using?  NULL if we haven't decided
@@ -754,3 +760,47 @@ ed25519_init(void)
   pick_ed25519_impl();
 }
 
+/* Return true if <b>point</b> is the identity element of the ed25519 group. */
+static int
+ed25519_point_is_identity_element(const uint8_t *point)
+{
+  /* The identity element in ed25159 is the point with coordinates (0,1). */
+  static const uint8_t ed25519_identity[32] = {
+    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+  tor_assert(sizeof(ed25519_identity) == ED25519_PUBKEY_LEN);
+  return tor_memeq(point, ed25519_identity, sizeof(ed25519_identity));
+}
+
+/** Validate <b>pubkey</b> to ensure that it has no torsion component.
+ *  Return 0 if <b>pubkey</b> is valid, else return -1. */
+int
+ed25519_validate_pubkey(const ed25519_public_key_t *pubkey)
+{
+  uint8_t result[32] = {9};
+
+  /* First check that we were not given the identity element */
+  if (ed25519_point_is_identity_element(pubkey->pubkey)) {
+    log_warn(LD_CRYPTO, "ed25519 pubkey is the identity\n");
+    return -1;
+  }
+
+  /* For any point on the curve, doing l*point should give the identity element
+   * (where l is the group order). Do the computation and check that the
+   * identity element is returned. */
+  if (get_ed_impl()->ed25519_scalarmult_with_group_order(result,
+                                                         pubkey->pubkey) < 0) {
+    log_warn(LD_CRYPTO, "ed25519 group order scalarmult failed\n");
+    return -1;
+  }
+
+  if (!ed25519_point_is_identity_element(result)) {
+    log_warn(LD_CRYPTO, "ed25519 validation failed\n");
+    return -1;
+  }
+
+  return 0;
+}
+
diff --git a/src/common/crypto_ed25519.h b/src/common/crypto_ed25519.h
index 77a3313..3a43920 100644
--- a/src/common/crypto_ed25519.h
+++ b/src/common/crypto_ed25519.h
@@ -127,6 +127,8 @@ void ed25519_pubkey_copy(ed25519_public_key_t *dest,
 void ed25519_set_impl_params(int use_donna);
 void ed25519_init(void);
 
+int ed25519_validate_pubkey(const ed25519_public_key_t *pubkey);
+
 #ifdef TOR_UNIT_TESTS
 void crypto_ed25519_testing_force_impl(const char *name);
 void crypto_ed25519_testing_restore_impl(void);
diff --git a/src/ext/ed25519/donna/ed25519_donna_tor.h b/src/ext/ed25519/donna/ed25519_donna_tor.h
index d225407..7d7b8c0 100644
--- a/src/ext/ed25519/donna/ed25519_donna_tor.h
+++ b/src/ext/ed25519/donna/ed25519_donna_tor.h
@@ -30,4 +30,9 @@ int ed25519_donna_blind_public_key(unsigned char *out, const unsigned char *inp,
 int ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out,
   const unsigned char *inp, int signbit);
 
+
+int
+ed25519_donna_scalarmult_with_group_order(unsigned char *out,
+                                          const unsigned char *pubkey);
+
 #endif
diff --git a/src/ext/ed25519/donna/ed25519_tor.c b/src/ext/ed25519/donna/ed25519_tor.c
index 9537ae6..bd11027 100644
--- a/src/ext/ed25519/donna/ed25519_tor.c
+++ b/src/ext/ed25519/donna/ed25519_tor.c
@@ -340,5 +340,32 @@ ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out,
   return 0;
 }
 
+/* Do the scalar multiplication of <b>pubkey</b> with the group order
+ * <b>modm_m</b>.  Place the result in <b>out</b> which must be at least 32
+ * bytes long. */
+int
+ed25519_donna_scalarmult_with_group_order(unsigned char *out,
+                                          const unsigned char *pubkey)
+{
+  static const bignum256modm ALIGN(16) zero = { 0 };
+  unsigned char pkcopy[32];
+  ge25519 ALIGN(16) Point, Result;
+
+  /* No "ge25519_unpack", negate the public key and unpack it back.
+   * See ed25519_donna_blind_public_key() */
+  memcpy(pkcopy, pubkey, 32);
+  pkcopy[31] ^= (1<<7);
+  if (!ge25519_unpack_negative_vartime(&Point, pkcopy)) {
+    return -1; /* error: bail out */
+  }
+
+  /* There is no regular scalarmult function so we have to do:
+   * Result = l*P + 0*B */
+  ge25519_double_scalarmult_vartime(&Result, &Point, modm_m, zero);
+  ge25519_pack(out, &Result);
+
+  return 0;
+}
+
 #include "test-internals.c"
 
diff --git a/src/ext/ed25519/ref10/blinding.c b/src/ext/ed25519/ref10/blinding.c
index ee3e866..8503f90 100644
--- a/src/ext/ed25519/ref10/blinding.c
+++ b/src/ext/ed25519/ref10/blinding.c
@@ -74,3 +74,40 @@ int ed25519_ref10_blind_public_key(unsigned char *out,
 
   return 0;
 }
+
+/* This is the group order encoded in a format that
+ * ge_double_scalarmult_vartime() understands. The group order m is:
+ * m = 	 2^252 +  27742317777372353535851937790883648493 =
+ *       0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed
+ */
+static const uint8_t modm_m[32] = {0xed,0xd3,0xf5,0x5c,0x1a,0x63,0x12,0x58,
+                                   0xd6,0x9c,0xf7,0xa2,0xde,0xf9,0xde,0x14,
+                                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10};
+
+/* Do the scalar multiplication of <b>pubkey</b> with the group order
+ * <b>modm_m</b>.  Place the result in <b>out</b> which must be at least 32
+ * bytes long. */
+int
+ed25519_ref10_scalarmult_with_group_order(unsigned char *out,
+                                          const unsigned char *pubkey)
+{
+  unsigned char pkcopy[32];
+  unsigned char zero[32] = {0};
+  ge_p3 Point;
+  ge_p2 Result;
+
+  /* All this is done to fit 'pubkey' in 'Point' so that it can be used by
+   * ed25519 ref code. Same thing as in blinding function */
+  memcpy(pkcopy, pubkey, 32);
+  pkcopy[31] ^= (1<<7);
+  if (ge_frombytes_negate_vartime(&Point, pkcopy) != 0) {
+    return -1; /* error: bail out */
+  }
+
+  /* There isn't a regular scalarmult -- we have to do r = l*P + 0*B */
+  ge_double_scalarmult_vartime(&Result, modm_m, &Point, zero);
+  ge_tobytes(out, &Result);
+
+  return 0;
+}
diff --git a/src/ext/ed25519/ref10/ed25519_ref10.h b/src/ext/ed25519/ref10/ed25519_ref10.h
index af7e21a..5965694 100644
--- a/src/ext/ed25519/ref10/ed25519_ref10.h
+++ b/src/ext/ed25519/ref10/ed25519_ref10.h
@@ -27,4 +27,8 @@ int ed25519_ref10_blind_public_key(unsigned char *out,
                               const unsigned char *inp,
                               const unsigned char *param);
 
+int
+ed25519_ref10_scalarmult_with_group_order(unsigned char *out,
+                                          const unsigned char *pubkey);
+
 #endif





More information about the tor-commits mailing list