From 46f8cbc99734c77564a3b925a993fcba43da38be Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 11 Nov 2017 12:24:51 +0900 Subject: curve25519: reject deriving from NULL private keys These aren't actually valid 25519 points pre-normalization, and doing this is required to make unsetting private keys based on all zeros. --- src/crypto/curve25519.c | 7 +++++++ src/netlink.c | 16 +++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/crypto/curve25519.c b/src/crypto/curve25519.c index afc2a99..232c6d4 100644 --- a/src/crypto/curve25519.c +++ b/src/crypto/curve25519.c @@ -619,6 +619,10 @@ bool curve25519(u8 mypublic[CURVE25519_POINT_SIZE], const u8 secret[CURVE25519_P bool curve25519_generate_public(u8 pub[CURVE25519_POINT_SIZE], const u8 secret[CURVE25519_POINT_SIZE]) { static const u8 basepoint[CURVE25519_POINT_SIZE] __aligned(32) = { 9 }; + + if (unlikely(!crypto_memneq(secret, null_point, CURVE25519_POINT_SIZE))) + return false; + #ifdef CONFIG_X86_64 if (curve25519_use_avx && irq_fpu_usable()) { kernel_fpu_begin(); @@ -1676,6 +1680,9 @@ bool curve25519_generate_public(u8 pub[CURVE25519_POINT_SIZE], const u8 secret[C { static const u8 basepoint[CURVE25519_POINT_SIZE] __aligned(32) = { 9 }; + if (unlikely(!crypto_memneq(secret, null_point, CURVE25519_POINT_SIZE))) + return false; + return curve25519(pub, secret, basepoint); } #endif diff --git a/src/netlink.c b/src/netlink.c index ba9e41b..f2e724a 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -421,15 +421,17 @@ static int set_device(struct sk_buff *skb, struct genl_info *info) if (info->attrs[WGDEVICE_A_PRIVATE_KEY] && nla_len(info->attrs[WGDEVICE_A_PRIVATE_KEY]) == NOISE_PUBLIC_KEY_LEN) { struct wireguard_peer *peer, *temp; - u8 public_key[NOISE_PUBLIC_KEY_LEN] = { 0 }, *private_key = nla_data(info->attrs[WGDEVICE_A_PRIVATE_KEY]); - /* We remove before setting, to prevent race, which means doing two 25519-genpub ops. */ - __attribute((unused)) bool unused = curve25519_generate_public(public_key, private_key); + u8 public_key[NOISE_PUBLIC_KEY_LEN], *private_key = nla_data(info->attrs[WGDEVICE_A_PRIVATE_KEY]); - peer = pubkey_hashtable_lookup(&wg->peer_hashtable, public_key); - if (peer) { - peer_put(peer); - peer_remove(peer); + /* We remove before setting, to prevent race, which means doing two 25519-genpub ops. */ + if (curve25519_generate_public(public_key, private_key)) { + peer = pubkey_hashtable_lookup(&wg->peer_hashtable, public_key); + if (peer) { + peer_put(peer); + peer_remove(peer); + } } + noise_set_static_identity_private_key(&wg->static_identity, private_key); list_for_each_entry_safe(peer, temp, &wg->peer_list, peer_list) { if (!noise_precompute_static_static(peer)) -- cgit v1.2.3-59-g8ed1b