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
This commit is contained in:
James Prestwood 2018-11-19 11:48:23 -08:00 committed by Denis Kenzior
parent 8c333a585a
commit c3abfde025
3 changed files with 23 additions and 11 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;