From c3abfde0251ec36c4b8f6f81ebdf8d27088a6a65 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 19 Nov 2018 11:48:23 -0800 Subject: [PATCH] ecdh: make key byte ordering consistent ECDH was expecting the private key in LE, but the public key in BE byte ordering. For consistency the ECDH now expect all inputs in LE byte ordering. It is up to the caller to order the bytes appropriately. This required adding some ecc_native2be/be2native calls in OWE --- src/ecdh.c | 10 +--------- src/ecdh.h | 7 +++++++ src/owe.c | 17 +++++++++++++++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/ecdh.c b/src/ecdh.c index 062bdfa9..3b2a4583 100644 --- a/src/ecdh.c +++ b/src/ecdh.c @@ -85,9 +85,6 @@ bool ecdh_generate_key_pair(void *private, size_t priv_len, return false; } - ecc_native2be(pub.x); - ecc_native2be(pub.y); - memcpy(public, &pub, pub_len); return true; @@ -132,6 +129,7 @@ bool ecdh_generate_shared_secret(const void *private, const void *other_public, if (secret_len > 32) return false; + /* * TODO: Once other ECC groups are added this will need to be modified * to check for 1/2 the full public key lengths @@ -142,7 +140,6 @@ bool ecdh_generate_shared_secret(const void *private, const void *other_public, * be decoded. */ memcpy(x, other_public, 32); - ecc_be2native(x); if (!decode_point(x, &public)) { l_error("could not decode compressed public key"); @@ -150,9 +147,6 @@ bool ecdh_generate_shared_secret(const void *private, const void *other_public, } } else if (pub_len == 64) { memcpy(&public, other_public, 64); - - ecc_be2native(public.x); - ecc_be2native(public.y); } else { l_error("unsupported public key length %ld", pub_len); return false; @@ -164,8 +158,6 @@ bool ecdh_generate_shared_secret(const void *private, const void *other_public, ecc_point_mult(&product, &public, (uint64_t *)private, z, vli_num_bits(private)); - ecc_native2be(product.x); - memcpy(secret, product.x, secret_len); return true; diff --git a/src/ecdh.h b/src/ecdh.h index 502fbab8..e0837251 100644 --- a/src/ecdh.h +++ b/src/ecdh.h @@ -20,8 +20,15 @@ * */ +/* + * Generate a private/public key pair. All inputs are expected in little-endian. + */ bool ecdh_generate_key_pair(void *private, size_t priv_len, void *public, size_t pub_len); +/* + * Generate a shared secret from a private/public key. All inputs are expected + * in little-endian. + */ bool ecdh_generate_shared_secret(const void *private, const void *other_public, size_t pub_len, void *secret, size_t secret_len); diff --git a/src/owe.c b/src/owe.c index e702d478..3ff8ee3e 100644 --- a/src/owe.c +++ b/src/owe.c @@ -60,6 +60,13 @@ struct owe_sm *owe_sm_new(struct handshake_state *hs, return NULL; } + /* + * Store our own public key in BE ordering since all future uses + * will need it. + */ + ecc_native2be(owe->public_key); + ecc_native2be(owe->public_key + 4); + return owe; } @@ -113,16 +120,20 @@ void owe_rx_authenticate(struct owe_sm *owe) static bool owe_compute_keys(struct owe_sm *owe, const void *public_key, size_t pub_len) { - uint8_t shared_secret[32]; + uint64_t shared_secret[4]; uint8_t prk[32]; uint8_t pmk[32]; uint8_t pmkid[16]; uint8_t key[32 + 32 + 2]; + uint64_t public_native[4]; struct iovec iov[2]; struct l_checksum *sha; + memcpy(public_native, public_key, 32); + ecc_be2native(public_native); + /* z = F(DH(x, Y)) */ - if (!ecdh_generate_shared_secret(owe->private, public_key, pub_len, + if (!ecdh_generate_shared_secret(owe->private, public_native, pub_len, shared_secret, 32)) return false; @@ -130,6 +141,8 @@ static bool owe_compute_keys(struct owe_sm *owe, const void *public_key, memcpy(key + 32, public_key, 32); l_put_le16(19, key + 64); + ecc_native2be(shared_secret); + /* prk = HKDF-extract(C | A | group, z) */ if (!hkdf_extract_sha256(key, 66, 1, prk, shared_secret, 32)) goto failed;