commit 83cd5f99b7e08c064962f985a92e4b47dc2276fd Author: Zack Weinberg zackw@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
tor-commits@lists.torproject.org