[tor-commits] [stegotorus/master] Add unit tests for ECDH.

zwol at torproject.org zwol at torproject.org
Fri Jul 20 23:17:08 UTC 2012


commit 83cd5f99b7e08c064962f985a92e4b47dc2276fd
Author: Zack Weinberg <zackw at cmu.edu>
Date:   Thu Jun 7 13:59:44 2012 -0700

    Add unit tests for ECDH.
---
 src/crypt.cc               |   89 ++++++++--
 src/crypt.h                |    6 +
 src/test/unittest_crypt.cc |  433 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 515 insertions(+), 13 deletions(-)

diff --git a/src/crypt.cc b/src/crypt.cc
index 8c7a6b9..ec59511 100644
--- a/src/crypt.cc
+++ b/src/crypt.cc
@@ -419,45 +419,105 @@ gcm_decryptor_impl::decrypt(uint8_t *out, const uint8_t *in, size_t inlen,
 namespace {
   struct ecdh_message_impl : ecdh_message
   {
-    EC_KEY *priv;
+    EC_KEY *key;
     BN_CTX *ctx;
-    ecdh_message_impl(); // generate keypair from randomness
+    ecdh_message_impl();
+    ecdh_message_impl(const uint8_t *secret);
 
     virtual ~ecdh_message_impl();
     virtual void encode(uint8_t *xcoord_out) const;
     virtual int combine(const uint8_t *other, uint8_t *secret_out) const;
+
+    int regen_pubkey();
   };
 }
 
 ecdh_message_impl::ecdh_message_impl()
-  : priv(EC_KEY_new_by_curve_name(NID_secp224r1)),
+  : key(EC_KEY_new_by_curve_name(NID_secp224r1)),
     ctx(BN_CTX_new())
 {
-  if (!priv || !ctx)
+  if (!key || !ctx)
     log_crypto_abort("ecdh_message::allocate data");
-  if (!EC_KEY_generate_key(priv))
-    log_crypto_abort("ecdh_message::generate priv");
+  if (!EC_KEY_generate_key(key))
+    log_crypto_abort("ecdh_message::generate key");
 }
 
-/* static */ ecdh_message *
+ecdh_message_impl::ecdh_message_impl(const uint8_t *secret)
+  : key(EC_KEY_new_by_curve_name(NID_secp224r1)),
+    ctx(BN_CTX_new())
+{
+  BIGNUM *sb = BN_bin2bn(secret, EC_P224_LEN, 0);
+  if (!key || !ctx || !sb)
+    log_crypto_abort("ecdh_message::allocate data");
+
+  if (!EC_KEY_set_private_key(key, sb))
+    log_crypto_abort("ecdh_message::set privkey");
+
+  BN_clear_free(sb);
+}
+
+// EC_KEY_set_private_key *does not* regenerate the public key, nor is
+// there any official or unofficial EC_KEY method to do so.  So we have
+// to do it by hand.  This is separate from the constructor so that it
+// can fail by returning -1 (since we still can't use exceptions).
+// Fortunately this is only for testing.
+int
+ecdh_message_impl::regen_pubkey()
+{
+  const EC_GROUP *grp = EC_KEY_get0_group(key);
+  if (!grp)
+    return -1;
+
+  const BIGNUM *priv = EC_KEY_get0_private_key(key);
+  if (!priv)
+    return -1;
+
+  EC_POINT *pub  = EC_POINT_new(grp);
+  if (!pub)
+    return -1;
+
+  if (!EC_POINT_mul(grp, pub, priv, 0, 0, ctx))
+    return -1;
+
+  EC_KEY_set_public_key(key, pub);
+  EC_POINT_clear_free(pub);
+
+  return EC_KEY_check_key(key) ? 0 : -1;
+}
+
+ecdh_message *
 ecdh_message::generate()
 {
   REQUIRE_INIT_CRYPTO();
   return new ecdh_message_impl();
 }
 
+ecdh_message *
+ecdh_message::load_secret(const uint8_t *secret)
+{
+  REQUIRE_INIT_CRYPTO();
+  ecdh_message_impl *imp = new ecdh_message_impl(secret);
+
+  if (imp->regen_pubkey()) {
+    log_crypto_warn("regenerate public key");
+    delete imp;
+    return 0;
+  }
+  return imp;
+}
+
 ecdh_message::~ecdh_message() {}
 ecdh_message_impl::~ecdh_message_impl()
 {
-  EC_KEY_free(priv);
+  EC_KEY_free(key);
   BN_CTX_free(ctx);
 }
 
 void
 ecdh_message_impl::encode(uint8_t *xcoord_out) const
 {
-  const EC_POINT *pub = EC_KEY_get0_public_key(priv);
-  const EC_GROUP *grp = EC_KEY_get0_group(priv);
+  const EC_POINT *pub = EC_KEY_get0_public_key(key);
+  const EC_GROUP *grp = EC_KEY_get0_group(key);
   if (!pub || !grp)
     log_crypto_abort("ecdh_message_encode::extract pubkey");
 
@@ -484,9 +544,12 @@ int
 ecdh_message_impl::combine(const uint8_t *xcoord_other,
                            uint8_t *secret_out) const
 {
-  const EC_GROUP *grp = EC_KEY_get0_group(priv);
+  const EC_GROUP *grp = EC_KEY_get0_group(key);
+  if (!grp)
+    log_crypto_abort("ecdh_message_combine::retrieve curve group");
+
   EC_POINT *pub = EC_POINT_new(grp);
-  if (!grp || !pub)
+  if (!pub)
     log_crypto_abort("ecdh_message_combine::allocate data");
 
   int rv = -1;
@@ -501,7 +564,7 @@ ecdh_message_impl::combine(const uint8_t *xcoord_other,
     goto done;
   }
 
-  if (!ECDH_compute_key(secret_out, EC_P224_LEN, pub, priv, 0)) {
+  if (!ECDH_compute_key(secret_out, EC_P224_LEN, pub, key, 0)) {
     log_crypto_warn("ecdh_message_combine::compute shared secret");
     goto done;
   }
diff --git a/src/crypt.h b/src/crypt.h
index 35e3e37..cc9309a 100644
--- a/src/crypt.h
+++ b/src/crypt.h
@@ -151,6 +151,12 @@ struct ecdh_message
   /** Generate a new Diffie-Hellman message from randomness. */
   static ecdh_message *generate();
 
+  /** Generate a new Diffie-Hellman message from a specified secret
+      value (in the form of a big-endian byte string, EC_P224_LEN
+      bytes long).  This is provided for testing purposes only; it
+      should not be used in normal operation. */
+  static ecdh_message *load_secret(const uint8_t *secret);
+
   /** Encode a Diffie-Hellman message to the wire format.  This
       produces only the x-coordinate of the chosen curve point.
       The argument must point to EC_P224_LEN bytes of buffer space. */
diff --git a/src/test/unittest_crypt.cc b/src/test/unittest_crypt.cc
index c411386..f1fed0f 100644
--- a/src/test/unittest_crypt.cc
+++ b/src/test/unittest_crypt.cc
@@ -834,6 +834,437 @@ test_crypt_aesgcm_bad_dec(void *)
  end:;
 }
 
+/* ECDH/P224 test vectors from
+   http://csrc.nist.gov/groups/STM/cavp/documents/keymgmt/kastestvectors.zip
+   specifically, the P224 vectors in
+   KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.fax */
+
+static void
+test_crypt_ecdh_p224_good(void *)
+{
+  struct testvec
+  {
+    const char *dA;
+    const char *xA;
+    const char *dB;
+    const char *xB;
+    const char *z;
+  };
+  const struct testvec testvecs[] = {
+    { "\x05\x82\x59\xe4\x16\x0b\x78\x3b\x90\xec\x2e\xe9\x3a\xa1"
+      "\xd8\x51\x49\x60\xbe\x5c\x99\x59\xf5\x01\xa1\xe0\xc4\x76",
+      "\xae\x04\xaa\x96\x54\x89\xc3\x21\x29\xed\x86\x70\xa6\x3c"
+      "\xf6\x57\x01\xda\x2f\x4d\xa3\xe7\xb9\x0f\x4d\x08\x70\x55",
+      "\xa4\x08\x18\x43\x0a\x49\x72\xb5\x02\xd2\x3c\xdd\x62\x2a"
+      "\xd7\x3e\xdb\x75\x7f\x52\xa0\xc0\x7c\x85\xdd\x2a\x0d\x48",
+      "\x26\xde\xf8\xd1\x5e\x96\xde\x9a\x19\x50\x26\x01\x85\xce"
+      "\x3e\xe1\x47\x8c\xb5\xb4\xb1\x4a\x42\x37\x90\xf4\x24\xcc",
+      "\xf8\xbe\x1b\x1f\xd0\xa1\x8b\xa5\x52\x19\x10\x39\x58\x77"
+      "\xa5\xf9\x56\xbc\x80\x3a\x56\x8e\x16\xb0\xd6\xac\x13\x11" },
+
+    { "\xd6\x74\xf9\x1b\xf9\xdd\x9b\x99\x8c\x70\xa3\x04\x02\xc2"
+      "\x18\x9b\x04\xfe\xad\xd3\x05\xee\xb3\x4d\x25\x74\x31\xa9",
+      "\xab\x4a\xb8\xee\x1c\x20\x7a\xfe\x55\xbf\x5b\xf8\xc1\xb3"
+      "\x20\x7d\x6e\x6d\xcb\xad\x5b\x67\x83\xb3\x3d\xc1\x42\x6c",
+      "\x84\xf5\x5f\x59\xe4\xe0\xd8\x24\xfa\xda\x3c\x65\xd6\xc6"
+      "\xb4\x13\xa2\x98\x80\x09\x71\x2b\x0e\x05\xdf\x1f\x4a\x76",
+      "\x96\xf6\xd4\xfe\x22\x90\x0c\x0d\xf6\x09\x9c\x19\xa7\x4f"
+      "\x66\xf3\xf1\x56\x16\xeb\x3c\xaf\xb4\x79\xea\x2c\x81\xee",
+      "\xd6\xee\x73\xac\x1d\x8f\x6c\x45\x25\xc3\x55\x96\x44\x53"
+      "\xd6\x1d\xe9\x6b\xdb\x7a\x20\xb0\x62\xfd\x61\xc7\xde\x84"  },
+
+    { "\xd1\x99\x4e\xf8\xc1\xab\x97\x77\xc6\x25\x1d\xc0\x3f\xf5"
+      "\xbe\xc8\xf3\xbf\x62\x3e\x06\xd2\x29\xc5\xd6\x15\xc3\x96",
+      "\x5c\x9e\x74\x34\x5b\xd7\xe3\x02\xe1\xf2\xf7\xba\x48\x78"
+      "\xb7\x0c\x05\xf7\x40\x3d\x44\xf2\x6c\xef\x16\xe4\xb1\x21",
+      "\x8e\x17\x32\xa5\x68\xf3\xe1\xb9\x75\x06\x56\x90\x7a\x1d"
+      "\x77\x0b\x83\x2f\xc9\x3c\x42\xfe\xfb\xb5\x69\x6b\x50\x14",
+      "\x5e\x5d\x65\x39\x48\x7a\x45\x0e\x5a\xa0\x67\x98\x68\x6b"
+      "\x81\x6b\x36\xe4\x73\x73\xc9\x3c\xea\x68\xaa\xa4\x6b\x56",
+      "\x0c\x2b\xa0\x69\x10\xa1\xe6\x34\x60\x49\xfd\x6c\x82\x64"
+      "\x5a\xa6\xbe\x55\x71\x41\x09\x04\x8e\x3e\x77\x3c\xbb\x76"  },
+
+    { "\xae\x94\x56\x83\x48\x85\xf7\xb3\xc1\x32\xa9\x05\x97\xb5"
+      "\xb1\x5f\x00\x75\x7a\x6b\x01\x08\xc5\x23\x05\x69\x8a\xff",
+      "\x32\xfa\x65\x28\x51\x48\xde\xb2\x25\xef\x7a\x8e\xbb\x59"
+      "\x19\x24\xf4\x21\x12\x66\xc9\x23\x2e\x5e\x56\xfc\x0f\xa7",
+      "\xdc\x56\x0c\x5d\x5a\x65\xd0\x7c\xad\xec\x18\xd0\xfa\xe4"
+      "\xd0\x0a\x27\xb9\x9b\xe6\x25\xf9\xcd\x24\xce\x09\x6f\x60",
+      "\x29\x9f\x28\xfb\xab\xcf\x4a\x4f\x99\x12\x53\x5c\x81\x08"
+      "\xe4\x18\xf0\x36\xf1\xd3\x75\x11\x7e\x87\xe8\x59\x5f\x79",
+      "\x15\x52\x19\xe1\x51\x7d\xa8\x85\x68\xa1\x03\x44\xd8\xa9"
+      "\x27\xdd\x9a\x45\x94\xe6\x4a\x68\x52\xcb\x6d\xa8\x33\x45"  },
+
+    { "\x73\x02\x93\xbb\x30\x87\xfb\x88\x2a\xb8\xf2\xf4\x6c\xb1"
+      "\x4a\x51\x2b\x55\x29\xd8\x30\x24\x67\xb5\x92\xb1\xa5\x4b",
+      "\xa7\x40\xfa\x8a\x31\xcc\xd7\xbf\x77\x85\x7f\x24\xed\x2b"
+      "\xfd\x17\xb5\x65\x49\x5e\x75\xbd\x1e\x55\x4b\x6b\xa9\xa5",
+      "\xdb\x37\xa8\x7d\x80\x12\xa0\xcb\xf2\x55\x82\x69\x17\xb3"
+      "\xb9\xa2\x8f\x4a\x51\xdf\x58\x96\x3c\xde\x03\xf4\xa4\x46",
+      "\x3c\xc2\xe8\xbf\xcc\xac\x84\x59\xbd\x4f\x44\xfe\x58\x48"
+      "\xdd\x97\xb6\x7e\xa7\xf3\x78\x72\x2c\xb0\x81\xf9\x9d\x2f",
+      "\xb9\xbd\x07\xcd\x07\x0d\x9f\xcb\x90\x85\xa6\x36\x07\xf8"
+      "\x4a\xa7\x3a\x82\x32\xaf\x33\x28\x34\xd0\x4f\x00\xe3\xd2"  },
+
+    { "\x31\x4e\x8e\xb8\xf2\x97\x6f\x2d\xfd\x1b\x3c\xfb\xd6\x9c"
+      "\xf4\xbd\xce\x9f\x1e\x9a\x6e\xe5\x40\x15\x3a\xca\x3c\x2e",
+      "\x24\x03\x1c\x12\xca\xea\xcf\x66\x29\xc8\x78\x36\x61\x65"
+      "\xca\x4f\x76\xf2\x1a\x40\x85\xc0\xbe\x1a\x83\x58\x76\xd7",
+      "\x54\x22\x6d\x6f\x24\x0a\x0e\x6d\x05\x22\x39\xd3\x8f\xf2"
+      "\xff\x18\x55\x7f\xd2\xed\xcd\xe4\xfc\x4f\x85\xf4\x54\x9f",
+      "\xab\x87\xed\xad\x74\x9a\x6c\x2c\xc7\x4a\x92\xb0\x83\x06"
+      "\x6b\x68\xd3\x5c\x2c\x91\x89\x9a\xff\xff\xc3\x22\xb9\x6f",
+      "\x35\x63\x39\x89\x49\xc4\x0a\xa4\x88\x7b\xda\xdb\xf8\x65"
+      "\x49\xbb\x58\xa1\x66\x16\x56\x60\x51\x07\xfb\xc7\x2a\x56"  },
+
+    { "\x1f\x04\xc0\xe3\x51\x45\x7f\x27\x2f\xff\xdc\xff\x4f\x81"
+      "\xd7\x38\x56\x51\x6f\x31\x18\x8d\xbf\xec\xcc\xec\x83\x7e",
+      "\x8e\xc7\x5b\x09\xf0\x40\xa6\xb3\x24\x6e\x98\x57\x96\xfb"
+      "\x26\xbe\x66\x20\x08\x29\x1a\x00\xfe\x64\xe8\xff\xb8\xeb",
+      "\x7f\x1d\x7a\xeb\x23\xe8\x23\x01\xc0\x56\x18\x31\x91\x9a"
+      "\x1d\xb8\x69\x06\xb0\x7e\x42\xf9\xa3\x59\x17\x4b\x38\x5d",
+      "\x12\xdb\x42\x99\x03\x52\x81\x59\x17\xee\x7e\x0b\x23\xa7"
+      "\x7d\x5a\x04\xc7\x87\x62\x07\x0e\x6b\xdb\x11\x04\x75\x60",
+      "\xe0\x93\xfe\xde\xff\xff\xc3\xf1\xb9\x01\x9b\x0c\x03\x2f"
+      "\x64\x07\x25\xe6\x54\x4c\x5e\x6f\x1b\x39\x76\xaf\xe9\xfa"  },
+
+    { "\x7e\x31\x5c\x03\xd3\xf3\x2d\x62\xa1\xa2\x53\xce\x37\x30"
+      "\x78\x8a\x94\x3d\xe0\x51\x03\xb0\xae\x2d\xf6\x06\x9c\x1e",
+      "\x9b\x3b\x5d\x53\x83\x17\xeb\x4e\x05\xfe\xb6\x40\xe1\xfc"
+      "\x72\x10\x81\xb5\x11\x79\xa5\xba\x46\x83\x94\x6c\x03\x36",
+      "\x88\x39\x5f\xd4\x54\x96\xb7\xb0\x0e\xa6\x18\xfd\xf9\x96"
+      "\x5f\xf9\x27\x28\x44\xf4\xac\xb6\xd4\x48\x3e\x8a\xe5\xa5",
+      "\xd8\xc0\xd0\xe8\x70\x7b\x13\x18\xdc\x24\xd7\xb4\x3d\x1c"
+      "\xce\x32\x9c\x13\xc5\xcc\x49\xca\x96\x16\xe1\x7b\x04\xbf",
+      "\x00\xff\x17\x5c\x7b\x27\x99\x56\xc5\x43\xe7\xfb\x0c\xfd"
+      "\x26\xf8\x8b\x98\xd6\x34\x50\x02\x4b\xbf\x9e\x65\x01\xf4"  },
+
+    { "\x29\x1a\x48\x68\xef\x47\x24\x85\x51\x1c\xb3\x81\x86\x83"
+      "\x53\x98\x3e\xa2\xb6\xff\x52\xf4\x1f\x98\x47\xf1\x79\x2c",
+      "\xf3\x86\x89\xd0\xb9\xa3\xa0\x39\x57\x84\x62\xaf\x92\xf5"
+      "\xa9\x28\xea\x23\x4d\x93\xe3\xed\x4c\xb2\x41\x39\xd1\xd0",
+      "\xc1\x6a\xbc\x67\x50\x7f\x0a\xff\xd5\x56\x9d\x90\x12\x98"
+      "\x8d\x8a\xcd\x76\x2c\xa0\x04\x57\x90\xe9\xcb\xac\xf4\x50",
+      "\x7a\x9b\x85\x5b\xef\x01\x0e\xde\xf1\xb4\x85\x64\xb2\x0c"
+      "\xb2\xe4\x06\x68\xe0\xe5\xde\x16\xa2\x55\xf4\x14\x23\x5d",
+      "\xf5\x21\x7a\x73\x8a\xd9\x63\xcd\x0d\xed\xf4\xd6\x18\x5b"
+      "\x19\x0d\x77\x6e\xb8\x5a\x57\x88\xad\x7f\xba\x2e\x8a\x2c"  },
+
+    { "\x11\x62\x98\x59\xee\x09\xef\xbe\x60\xdb\x65\x58\xb9\xbd"
+      "\x80\xcc\x9a\x30\x96\xc0\xbc\x9e\x69\x50\xfa\xd9\xa8\x2d",
+      "\x1a\x2f\x4b\x80\x6b\xa2\x34\xc0\x50\xa3\xf7\x50\x52\x99"
+      "\x5a\xb8\x63\x13\xc5\x11\xa8\x41\x2e\xa0\x5f\x32\x03\x8b",
+      "\x48\x72\x4a\x5b\x79\x22\xbd\x20\x4b\xe2\x95\x3d\x47\xa4"
+      "\x5a\xf5\xaa\x9b\x0a\x72\x04\x55\x1f\xe3\x7f\xcb\x91\xa7",
+      "\x8f\x18\x48\xfa\x23\x8e\xf8\x36\xe1\x45\xcd\x32\x72\xf2"
+      "\x51\x4e\x04\x56\xc0\x67\x5c\x43\xe5\x41\x2e\xa2\xaa\x8e",
+      "\x28\xa8\xc7\x03\x0d\x70\x88\x65\xf1\xd4\x6a\xb9\x67\xd0"
+      "\xf6\xdd\x45\x70\x06\x72\xb7\xbf\xaa\x64\xa9\x7a\x01\x23"  },
+
+    { "\x17\x4c\x96\xb0\x2a\xba\x8c\xab\x99\xdd\x8c\xbc\xa8\x6b"
+      "\xfa\x8b\x0d\x3f\x4f\x4c\x9a\x8a\x1b\x75\x9d\x53\x6c\x18",
+      "\xf4\x83\xb9\x4b\x60\x26\xae\x11\xab\xed\x33\x90\x68\x16"
+      "\xfb\x63\x0c\x29\x7b\x79\x01\x82\x23\xb6\x3d\x06\xc0\x79",
+      "\x0f\x6e\x7b\x5b\x6c\xad\xe8\xfc\xd9\xb0\x93\x28\x73\xff"
+      "\xab\xdc\x69\x75\x24\x00\x1e\x03\x12\x46\xc9\xbf\x29\x79",
+      "\x98\x84\x39\xbb\xde\xee\x89\x45\x0c\xb2\x0a\x58\xa0\x96"
+      "\x0a\x74\x19\xb6\x17\xa8\xe2\x33\xef\xf5\x8b\x23\xf5\x85",
+      "\xfa\x28\xc6\x51\xeb\xbb\x03\xb3\xd1\xb5\xc7\x32\xbe\x7c"
+      "\xfd\x06\xec\xd6\x68\x5d\xae\x19\xc4\x45\x1e\x30\xd9\x69"  },
+
+    { "\x47\xa0\xc4\xf2\x9f\x82\x31\x3f\x37\x6a\x3f\x45\x9a\x52"
+      "\xa8\x15\x9c\x19\x41\xb5\xdd\x51\xa5\xb2\x51\x80\xf4\xda",
+      "\x6d\xb1\x09\xdf\xb3\x13\xb7\x9b\x96\x4b\x03\xad\x15\x92"
+      "\x58\xfe\xdd\xa0\xe3\x2c\xb1\x8d\xef\x87\xa5\xe3\xdd\x6e",
+      "\x18\xc0\x86\x35\x8b\x6b\x26\xf0\xe7\xa8\x24\x23\xd0\xe2"
+      "\xf8\x65\x29\x01\xe4\xba\x16\xd8\x39\x92\x9b\x4a\x59\x77",
+      "\xf7\x00\x7e\xcd\x09\x3d\xe4\x8c\x79\xd6\x1e\x0e\x47\xc5"
+      "\x68\x31\xcf\xc0\x9d\x5a\x66\x7f\x9a\xd3\x95\xef\x4d\x1f",
+      "\xe8\xfa\xd8\xdd\xb1\xde\x6c\x24\x42\x96\x16\x05\xd1\xb7"
+      "\xf6\xe9\xc8\xc6\xa7\x29\x87\xfc\x93\xd7\xa2\xf4\xd9\xf9"  },
+
+    { "\x7e\x96\x75\x75\x58\x4f\xb8\x8a\xcf\x3f\xe6\x92\x43\xbe"
+      "\x13\x21\xa3\xea\xa6\x8c\xe1\xe6\x8d\x72\x4c\x8e\x77\xe8",
+      "\xa6\x52\x08\xef\xdc\x22\x8e\x99\x5c\x96\x3e\xf3\x48\xd7"
+      "\x82\x8f\x1d\x6f\x53\x51\x1e\xd1\xe1\xdd\x7e\x99\xdd\xe1",
+      "\xb5\x00\xc1\xa6\x3d\x44\xa9\xec\x42\x81\xed\x2f\x68\x7e"
+      "\xdc\x47\x6e\x0d\x2d\xf3\xb3\x10\x57\x6a\xe8\xaf\x63\x67",
+      "\xfa\x27\x37\xe3\x19\x5d\xa2\x69\xfb\x48\xa3\x8a\x82\x0e"
+      "\x8c\xab\x93\xec\x9f\x90\xc5\x1a\xff\x55\x26\x6f\x4e\x85",
+      "\xc2\x8a\xc6\x40\x02\xa3\x07\xae\xf0\x4b\x85\x11\xbc\x82"
+      "\xc9\xdd\x34\x3a\x2f\x4f\x3f\xc6\xa5\x48\x6c\x6d\xaa\x68"  },
+
+    { "\xf5\x69\x65\xa6\x9f\x1e\xac\x36\x55\x5d\x24\x2b\x85\xe7"
+      "\x5c\x1d\x17\xfe\x09\x2a\xb4\xee\xeb\xec\x98\xca\x43\x82",
+      "\xe0\x02\xd5\x9d\xa5\x39\xf1\xe9\x35\xc8\xf4\xfb\xfa\x2c"
+      "\x75\x37\x5d\xcb\xd4\xc9\xbf\xb1\xc4\x56\x5e\xc2\x10\x81",
+      "\x14\xe8\xf5\x8a\x0a\xc5\xf9\xce\xab\xde\xa2\xf1\xb7\x50"
+      "\xba\xf1\x2e\x45\xd5\x59\x65\x7e\xa1\xfa\x9c\xbb\x9f\xe2",
+      "\xbb\x25\xd7\x58\xfd\x4a\x48\xbc\x6c\xf8\xc0\xbc\x70\xd7"
+      "\x9d\x6a\xca\x1a\x6d\xd7\x12\xc3\x61\x56\x69\x27\x90\xe5",
+      "\x7a\x85\x53\x35\x47\x89\xbb\x75\xde\xb3\xed\x7f\x41\xa3"
+      "\x73\xa6\x40\x64\x77\x68\xe2\x4a\x38\x08\x1f\x5a\xea\x89"  },
+
+    { "\x31\xf4\x63\x6e\x71\x16\x5a\x78\xc6\x92\x92\xdd\xb8\x58"
+      "\x19\x22\xd1\x5e\x0f\xd4\x2d\x5f\x1a\x24\xbd\x8e\x15\xcd",
+      "\xfa\x03\x95\x8e\x0d\x74\x22\x86\xff\xa6\x64\x01\x7c\x0a"
+      "\x0a\x87\xed\x61\x18\x92\xcb\xdd\xa2\xfd\x44\x48\x2b\x81",
+      "\xbe\xb0\x14\x2b\xbc\x7a\x5f\x91\xcf\x30\x45\xc0\x99\xaf"
+      "\xf8\x8f\x77\xb2\xa0\xc5\x3c\xcc\xe3\x8e\xa1\x88\x54\x01",
+      "\x9f\xe8\x75\xc3\xb1\x35\x33\x9a\xc3\x56\xa6\xbd\xac\xfe"
+      "\x53\x59\xb8\xa0\x92\xac\x5d\xd4\x1c\xe5\xaa\x05\x84\x07",
+      "\x43\x0b\xa3\x5c\x07\x62\xe9\xa0\xd3\xfd\x4b\x3a\x32\x2c"
+      "\x89\x32\x2e\x78\x33\x96\xa4\xee\xb6\x57\x03\xca\xc3\xda"  },
+
+    { "\xab\x39\xec\xa9\x01\xf7\x3b\xce\xc0\xc9\x0d\x26\xa4\x36"
+      "\x58\x2d\xb8\x00\x88\x95\xdd\x95\x25\x00\x0c\xdf\x47\x7d",
+      "\x06\x3c\x88\x08\x34\x4b\xdb\xa2\x7f\xa7\xb8\xd1\xd9\x4a"
+      "\x43\xf6\x98\xe8\xb4\x7b\x19\x3d\x85\x60\x12\xa3\x96\xd4",
+      "\xf2\x1c\xb9\x06\xb4\xd7\xaa\xf2\x90\x8a\xa5\xe4\x34\xa6"
+      "\x26\xd5\x98\xf4\x4b\x5a\x5b\x8a\xf2\x90\xae\xef\x78\xe3",
+      "\x94\x0a\xfb\x7d\xba\x27\xcc\x67\x23\xc3\xdd\x08\xc3\x46"
+      "\xb0\xe2\x12\xef\x33\x40\x21\x0e\x0c\x4f\xf7\xc8\x74\x77",
+      "\x51\xc8\x06\x43\xdf\x8c\x8d\x61\x95\xbc\x08\x00\x95\xd9"
+      "\x9a\xb3\x87\xda\x50\x55\x83\xf0\x2f\x19\x2d\x62\x36\x65"  },
+
+    { "\xd4\x69\x26\x18\x98\x17\x1d\x69\x5a\xfb\x6e\x04\xd4\xfd"
+      "\x46\xe0\x4b\xce\xfb\xd9\x39\x8a\x63\x34\x43\xd7\x8d\x48",
+      "\x05\xec\x47\xa2\xfd\xf0\x52\x81\xbc\x87\xd0\x85\xbd\xb5"
+      "\xdc\xc8\xa2\xe0\x64\x21\xbd\x69\x85\x5e\xe3\xc3\x05\x26",
+      "\x83\xe3\x71\x1c\xa0\x52\x4b\x51\x70\x2a\xea\x58\xd4\x81"
+      "\x73\x5e\xac\x71\x23\x46\x84\xb2\x5b\x76\x15\xf0\x2d\x3a",
+      "\x6a\x8c\xae\x26\x50\x88\xea\xa2\xba\x02\x32\x1f\x23\x9b"
+      "\xc6\x40\x3f\xc2\x51\xd6\xca\xbe\x84\x71\x58\xa8\xac\x94",
+      "\x1a\xb3\xff\xe4\xf1\xe6\x81\xe4\x69\x60\x30\x0d\x1e\x5b"
+      "\xd6\xde\xb6\x05\x98\x99\xc6\xa5\xee\x6d\xc5\xf4\x95\x75"  },
+
+    { "\xc1\x93\x35\xc9\x1b\x13\x1e\xd5\x67\x1e\x26\x5b\x60\x0c"
+      "\x61\xb7\x7a\xde\xd2\x52\x5b\xb5\xa7\xb1\xb6\xeb\xf4\xca",
+      "\x8e\x46\x21\x7c\x96\xd8\xa6\xe1\x6e\x3a\x74\x43\x67\x15"
+      "\xb2\x77\xa7\x29\x5c\xcd\xea\xf2\xa3\x66\x08\x81\xdc\xeb",
+      "\xb1\xc7\x1a\x00\x38\x5d\x90\xbe\x93\x25\xc8\x9c\x0e\xa6"
+      "\xea\xb9\x6c\xdb\x71\x18\x61\x3f\xe8\x46\x0c\x2c\x8b\x2e",
+      "\x77\xa6\x39\xb9\x63\x30\x1c\xbf\x6a\xac\x08\xad\x03\x8b"
+      "\x2e\xbe\x8a\x32\x15\x4c\x8d\x6b\x2b\xe3\x5b\x2a\xfb\xa3",
+      "\xff\x0f\x01\x88\x07\x26\xa4\x5f\xa5\x56\xed\xd4\x8a\x2b"
+      "\x59\x0a\xc9\xa5\x01\x74\x16\x1d\x3e\x52\xab\x73\x7a\x16"  },
+
+    { "\xa3\xc0\x62\xa4\xcb\x5e\x40\x7f\x7d\x99\xe8\xf9\xe3\x73"
+      "\x86\xb2\x76\x97\x05\x5d\x87\x39\x28\x25\xc6\xe1\x86\xbf",
+      "\x1f\x98\x95\x87\x82\x4c\xb6\x2c\x03\xa0\x18\xab\xd4\xd3"
+      "\x19\xdc\x2b\x08\x2e\xda\x66\x66\x2b\xfb\x7a\x65\x95\xfe",
+      "\x87\xb3\x39\xb3\xa4\x81\x5d\x51\x4a\xcf\xe8\x7b\xd6\x53"
+      "\xbe\xe1\xcc\xd3\x3a\x1d\xb4\x24\xc9\xea\x3f\x67\x53\xc8",
+      "\xca\xe1\x6b\xc9\x21\xa8\x51\x38\x15\x9d\x62\xd9\x20\xbb"
+      "\x73\x6b\xa4\x4c\x73\x71\x72\x5f\xa9\xc9\x59\xee\x1f\xcc",
+      "\x3a\xde\x1c\x85\x1d\x9a\x58\x39\xa9\xff\x5f\x12\x8b\x8d"
+      "\xa8\x05\x09\x5c\x76\xb7\x7b\x85\xa8\x1b\x68\x2e\x8f\xa7"  },
+
+    { "\xcd\x16\xea\xa0\x2c\xed\xaf\x67\x4f\x35\x32\xf4\xe7\xca"
+      "\x73\xe4\x01\xf0\xc4\xf5\xa6\xed\xd9\xa6\xd7\x0e\xec\xf8",
+      "\x9c\xc1\x4d\x9d\x8b\x1b\x9e\xcf\xe2\x96\x08\x45\x0c\x90"
+      "\xbc\x8e\x51\xf3\x7d\x0b\x74\xf9\x99\x61\x7e\xc4\xb3\x74",
+      "\x2c\x97\x35\x91\x60\x17\xbc\xa8\x51\xdd\xb8\x2c\x30\x9a"
+      "\x52\x47\x3e\xd3\xfd\x88\x46\x1f\xed\x66\x81\x42\xb0\x84",
+      "\xe9\xff\x59\x72\xc0\x5e\x4e\x6d\x79\x24\x61\xce\x67\x1b"
+      "\x75\x0d\xf2\x04\xcb\xe0\xa2\x73\x1d\xcc\xd6\x06\x42\xfd",
+      "\xe6\x76\xda\xbe\x28\x25\x7e\x14\x1d\xe3\xff\x7b\xd8\x95"
+      "\xdb\x55\x43\x37\xcf\x56\x71\x48\xe7\x87\x80\x9e\xd0\x3a"  },
+
+    { "\x23\x6d\x4c\x9b\x98\xcf\x11\xa3\x79\x61\x04\x5a\xbf\xe3"
+      "\x99\xe4\xa6\xab\xc8\xab\x2a\x7e\xbc\x80\xf8\xc8\x8e\x71",
+      "\x9c\xc7\x3c\x49\x82\x1c\x1c\x10\xb5\xf5\x79\x4f\xa5\xd3"
+      "\xde\x6f\x5e\xbc\x4e\x78\x0e\x47\x68\x92\xfb\xcd\x2f\x22",
+      "\xc0\xa9\xb0\x20\xe5\x79\x9e\x7f\xc6\xea\x7a\x44\x79\xb7"
+      "\x66\x13\x90\x16\x66\x74\x60\xf4\xbf\x01\xfc\x45\x21\xfc",
+      "\x39\x61\xe9\xee\x46\x75\x38\x4a\x76\xec\xf5\x29\x8b\xa0"
+      "\x43\x03\x5e\x27\x44\x38\x4c\xd0\xf9\x84\xc4\xf0\xb3\xe7",
+      "\x08\x6c\xd8\x6d\x1c\xd6\x9e\x86\x60\xb4\xf7\xae\x62\xec"
+      "\x2f\xca\xe4\xd6\x3b\xd6\x7d\x46\x78\x2e\xb2\xa4\xd8\x21"  },
+
+    { "\x04\xcd\xb9\x7e\x47\x58\xc8\x32\x85\x33\x6a\xb6\xe5\x85"
+      "\xbc\x51\xd0\xa1\x78\x04\xbc\x02\x81\x90\x25\x83\x95\x8a",
+      "\x38\x75\xd5\xc9\x01\x40\x03\x71\x83\xb7\xa6\x59\xfb\xaf"
+      "\x79\xd0\x1c\x86\x27\xbe\xdb\xc1\x88\xb7\x01\xf5\xf7\xca",
+      "\xd3\xfc\x0f\xd8\x2c\x8a\xf1\x09\x82\x58\xde\x13\xb8\x54"
+      "\x39\xe3\x3c\xf5\xb3\xb7\xe3\x5f\x8a\xdb\xf7\x1f\x7a\x06",
+      "\xc9\xcb\xa6\xd3\x91\x4d\x59\x0b\x51\x0f\xe3\x22\x59\xf6"
+      "\xd1\xe2\x4d\xa1\xa9\x93\xe9\xae\x7c\xb3\x85\xad\x15\x4d",
+      "\x2f\x8e\x72\x0f\xa0\xd8\x0b\xb0\xa0\x67\x20\x23\x22\xa7"
+      "\x07\xe7\xa0\xe7\x2e\xae\xfb\xd0\xd8\x2f\xbb\x58\xb8\x83"  },
+
+    { "\x94\x58\xed\x7f\xbf\x97\x86\xe8\xf1\xbc\x56\xea\xfd\x69"
+      "\xc9\xa8\x3b\x73\x07\x41\x98\x0f\xdd\xfc\x30\x76\xaa\xee",
+      "\x24\x66\x17\x73\x35\x0d\x72\x8e\xd2\x95\x48\x48\x2f\xf6"
+      "\x76\xe9\x77\xd6\xa0\x76\xcc\x59\xde\xb7\xe8\x2e\x00\xc0",
+      "\xfd\x5e\x7a\x2c\x5b\xb2\x2f\x43\x7d\x3b\xc6\xf0\xaf\xba"
+      "\xa5\x69\x58\xb6\x29\x5b\x03\x5c\x7e\xd8\x61\xbc\x85\xe3",
+      "\xdf\x81\x0c\xd0\xa3\xca\xf2\x5f\xac\x62\x73\x21\x0a\x18"
+      "\x09\xae\x1d\x69\xf3\xfe\xe0\x88\x7b\xc7\xe0\x2b\xc3\x94",
+      "\xfe\xb0\x44\x61\xae\x77\x2f\x66\x67\x27\x76\xdf\xd9\x11"
+      "\x0d\x11\x32\x31\x2f\x67\x4f\xff\xf3\x79\x93\x9b\xfe\xd4"  },
+
+    { "\x29\x2e\xa4\x45\xba\xb6\xd4\xa1\x10\xe9\x39\x0e\x6d\x9e"
+      "\x0a\xcb\xd6\x0f\x19\x91\xa6\x42\xcc\x33\x9d\x0c\xc7\x66",
+      "\x7c\x99\x6a\xbe\xab\x4a\x1a\xbc\x16\x64\x03\xe1\xd5\xbd"
+      "\x77\x84\x75\x25\x6b\xa5\xe5\xce\x39\x36\xd3\x2f\x5f\x41",
+      "\x2c\x74\x9f\x27\x53\x0d\x05\x96\xe1\xf3\xb3\x7d\x1b\xf8"
+      "\xac\x30\x90\xcb\xe6\xcb\xc8\x7d\x6c\x3e\x69\x6f\xb1\xd8",
+      "\xba\x49\x93\x24\xda\x93\x4a\x0c\x1f\x56\xac\x2e\x08\x4c"
+      "\xf6\xca\xc6\xc1\x2b\x91\xe7\xf5\xea\x92\xb9\xcc\xac\xaf",
+      "\x2e\x90\x90\x2a\x26\xab\x5d\x13\xe7\x1b\x4b\x73\xaf\xf4"
+      "\xd0\x82\x32\xce\x06\x6b\x0e\x89\x90\xca\x79\x12\x8d\x80"  },
+
+    { 0, 0, 0, 0, 0 }
+  };
+
+  ecdh_message *a, *b;
+  int i, rv;
+  uint8_t obuf[EC_P224_LEN];
+
+  for (i = 0; testvecs[i].dA; i++) {
+    a = ecdh_message::load_secret((const uint8_t *)testvecs[i].dA);
+    tt_int_op(a, !=, 0);
+
+    b = ecdh_message::load_secret((const uint8_t *)testvecs[i].dB);
+    tt_int_op(b, !=, 0);
+
+    a->encode(obuf);
+    tt_mem_op(obuf, ==, testvecs[i].xA, EC_P224_LEN);
+    b->encode(obuf);
+    tt_mem_op(obuf, ==, testvecs[i].xB, EC_P224_LEN);
+
+    rv = a->combine((const uint8_t *)testvecs[i].xB, obuf);
+    tt_int_op(rv, ==, 0);
+    tt_mem_op(obuf, ==, testvecs[i].z, EC_P224_LEN);
+
+    rv = b->combine((const uint8_t *)testvecs[i].xA, obuf);
+    tt_int_op(rv, ==, 0);
+    tt_mem_op(obuf, ==, testvecs[i].z, EC_P224_LEN);
+
+    delete a;
+    delete b;
+  }
+
+ end:;
+}
+
+static void
+test_crypt_ecdh_p224_bad(void *)
+{
+  enum { bad_x = 1, bad_z };
+  struct testvec
+  {
+    const char *dA;
+    const char *xA;
+    const char *dB;
+    const char *xB;
+    const char *z;
+    unsigned int what;
+  };
+  const struct testvec testvecs[] = {
+    { "\x8d\x17\x56\x30\xd4\xf8\x31\xc3\x3c\x47\xd3\x1c\xaf\xdb"
+      "\xd9\xf2\x6f\xd0\xc6\x0d\x82\x4c\x69\x6d\x0f\x50\x2a\xbe",
+      "\xd5\x50\x88\x33\x86\x53\xb4\xd3\x78\x88\xf9\x57\x83\xae"
+      "\x36\x70\xeb\x66\x31\xe9\x3c\x75\x91\xab\x4b\x33\x9b\x75",
+      "\xcd\xc7\x8f\x44\x4a\xf1\xa3\x29\x25\x97\x41\x73\xb4\x26"
+      "\x3d\xc7\x79\x1b\x54\x37\xf6\xd6\xf4\xc5\x4f\xd2\x4a\xb9",
+      "\x72\x8d\x13\x5f\xbe\xdf\x2f\xdd\x31\x16\x6f\xd5\x05\x5a"
+      "\x74\x6d\x2b\xf9\x0f\xde\xf2\xdd\xc1\x65\xea\x99\x9a\xc9",
+      "\xfd\x72\x21\x93\x90\x0d\x35\xf0\x79\x52\x8f\x11\x36\x1d"
+      "\xd2\xa8\x7a\x58\xbe\x6b\x34\xb9\xae\xa2\x18\x97\x5b\x4a",
+      bad_x },
+
+    { "\xf0\x13\x22\xb9\xcb\x1b\x17\xe5\xf5\xa6\x14\xe5\x18\x62"
+      "\xd6\x32\x6f\xe7\x64\x9e\xdd\xd8\xe7\x08\x65\xba\xba\xd0",
+      "\x8d\xf9\x90\x92\xb0\x22\x4b\x70\xc2\x26\x26\x27\x18\xce"
+      "\x9b\x4d\xa4\xfb\xbb\xc1\x7b\xb8\x5e\x21\x1f\xff\xe2\x33",
+      "\xb9\xda\x33\x22\x0c\xf1\x79\xc5\x01\x3e\xe5\x01\x69\x4a"
+      "\x70\xf0\xf2\x29\x4c\xa6\x39\x25\x21\x89\x8f\x7d\x0f\xb1",
+      "\x5f\xd7\xee\x0b\x48\x96\xbd\xc1\x72\x4c\xb5\x92\x3a\xe3"
+      "\xda\x8f\x75\xe8\xd5\x63\xa9\x51\xa7\x7e\xb5\xc4\x87\x5c",
+      "\x84\xc9\xfb\x7a\x82\x7a\x4e\xb7\x18\x00\x2a\x47\x0e\xdd"
+      "\x9e\xf0\xe8\xcd\x33\xf0\xc5\xe7\xe5\x1b\x80\xaa\x59\x4e",
+      bad_x },
+
+    { "\xc1\xf3\x83\x84\x0f\x6c\x39\x1b\xdb\x45\x70\x05\x5e\x54"
+      "\x7e\xc3\x84\x75\x8b\x25\x1c\x9c\x0e\x5e\x2e\x14\x53\x3d",
+      "\x5f\xae\xf4\x8b\xef\x7a\x4d\x4a\x8d\xb3\xd6\x4b\xea\xc1"
+      "\x72\x17\x99\xbb\xf0\x83\xd8\xa3\x70\x7e\x84\x71\xa1\xe2",
+      "\x55\x30\xfc\xf5\x2f\x1a\x02\x00\xd4\x6b\x66\x69\x8a\xa7"
+      "\xb4\x20\x1c\x8d\xee\x1c\x41\xff\x27\x1e\x8f\xac\xc7\x5c",
+      "\x3b\x57\xae\x47\x2d\xb8\x1a\xf0\x20\x0b\x8d\x53\xf9\x1d"
+      "\x5b\x5b\xe6\x13\xe7\xff\xc1\x33\x19\xe9\x14\x8b\xe9\x10",
+      "\xa6\xb3\x02\x59\xa8\x41\x77\x22\x68\xe2\xd4\xe3\x10\xb6"
+      "\x19\x05\xa7\x58\x36\xf9\xf9\x74\x73\x33\x1b\x9d\x62\xd9",
+      bad_z },
+
+    { "\x71\xa4\xc0\xbd\x85\xa9\xfb\x8e\x33\xc5\x4c\xdd\x73\x1f"
+      "\x98\x7c\xb8\xa2\x44\xc5\x2c\x27\x7d\x97\x67\x7e\x4b\x43",
+      "\x30\xd3\x18\xbe\x17\x7b\xa5\xb5\x13\x69\x87\x89\xc6\xfc"
+      "\x4e\x54\xd8\x92\x57\xd2\x62\xdf\x2f\x09\xab\x0d\x21\x16",
+      "\x4f\xf7\x7e\xb6\x4d\x97\xd7\x1c\x12\xb4\x52\x6e\xc6\xde"
+      "\x2e\x5f\x97\xbe\x5f\xcb\x5d\x16\x44\x74\x7a\x5a\x40\x03",
+      "\x32\x14\x21\x90\xe1\xda\xbb\x40\x73\x27\xc4\x4a\xb3\x18"
+      "\x82\x2a\x15\x62\x68\x38\x4c\x86\xc5\x5a\x33\xcc\x8d\x0a",
+      "\x86\x8d\x73\xd8\xca\xce\x1b\x87\xa5\xfe\x16\xcb\xf3\x49"
+      "\x9e\x4a\x69\x85\xef\x6c\xae\xe0\xf0\x92\x46\xb4\xb0\x22",
+      bad_z },
+
+    { 0, 0, 0, 0, 0, 0 }
+  };
+
+  ecdh_message *a, *b;
+  int i, rv;
+  uint8_t obuf[EC_P224_LEN];
+
+  for (i = 0; testvecs[i].dA; i++) {
+    a = ecdh_message::load_secret((const uint8_t *)testvecs[i].dA);
+    tt_int_op(a, !=, 0);
+
+    b = ecdh_message::load_secret((const uint8_t *)testvecs[i].dB);
+    tt_int_op(b, !=, 0);
+
+    a->encode(obuf);
+    if (testvecs[i].what == bad_x) {
+      tt_mem_op(obuf, !=, testvecs[i].xA, EC_P224_LEN);
+    } else {
+      tt_mem_op(obuf, ==, testvecs[i].xA, EC_P224_LEN);
+    }
+
+    b->encode(obuf);
+    tt_mem_op(obuf, ==, testvecs[i].xB, EC_P224_LEN);
+
+    memset(obuf, 0, EC_P224_LEN);
+    rv = a->combine((const uint8_t *)testvecs[i].xB, obuf);
+    tt_int_op(rv, ==, 0);
+    if (testvecs[i].what == bad_z) {
+      tt_mem_op(obuf, !=, testvecs[i].z, EC_P224_LEN);
+    } else {
+      tt_mem_op(obuf, ==, testvecs[i].z, EC_P224_LEN);
+    }
+
+    memset(obuf, 0, EC_P224_LEN);
+    rv = b->combine((const uint8_t *)testvecs[i].xA, obuf);
+    if (testvecs[i].what == bad_x) {
+      tt_int_op(rv, !=, 0);
+      tt_mem_op(obuf, !=, testvecs[i].z, EC_P224_LEN);
+    } else {
+      tt_int_op(rv, ==, 0);
+      if (testvecs[i].what == bad_z) {
+        tt_mem_op(obuf, !=, testvecs[i].z, EC_P224_LEN);
+      } else {
+        tt_mem_op(obuf, ==, testvecs[i].z, EC_P224_LEN);
+      }
+    }
+
+    delete a;
+    delete b;
+  }
+
+ end:;
+}
+
 /* HKDF-SHA256 test vectors from http://tools.ietf.org/html/rfc5869 */
 static void
 test_crypt_hkdf(void *)
@@ -988,6 +1419,8 @@ struct testcase_t crypt_tests[] = {
   T(aesgcm_enc),
   T(aesgcm_good_dec),
   T(aesgcm_bad_dec),
+  T(ecdh_p224_good),
+  T(ecdh_p224_bad),
   T(hkdf),
   T(rng),
   END_OF_TESTCASES





More information about the tor-commits mailing list