From a97ca1117db9b34dead340707ffde1c07b369a0c Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Mon, 18 Jun 2018 20:44:32 +0200 Subject: netlink: maintain static_identity lock over entire private key update We don't want the local private key to not correspond with a precomputed ss or precomputed cookie hash at any intermediate point. Signed-off-by: Jason A. Donenfeld --- src/cookie.c | 3 +-- src/netlink.c | 2 ++ src/noise.c | 6 ++---- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/cookie.c b/src/cookie.c index c1e184c..41f6ddb 100644 --- a/src/cookie.c +++ b/src/cookie.c @@ -37,9 +37,9 @@ static void precompute_key(u8 key[NOISE_SYMMETRIC_KEY_LEN], const u8 pubkey[NOIS blake2s_final(&blake, key, NOISE_SYMMETRIC_KEY_LEN); } +/* Must hold peer->handshake.static_identity->lock */ void cookie_checker_precompute_device_keys(struct cookie_checker *checker) { - down_read(&checker->device->static_identity.lock); if (likely(checker->device->static_identity.has_identity)) { precompute_key(checker->cookie_encryption_key, checker->device->static_identity.static_public, cookie_key_label); precompute_key(checker->message_mac1_key, checker->device->static_identity.static_public, mac1_key_label); @@ -47,7 +47,6 @@ void cookie_checker_precompute_device_keys(struct cookie_checker *checker) memset(checker->cookie_encryption_key, 0, NOISE_SYMMETRIC_KEY_LEN); memset(checker->message_mac1_key, 0, NOISE_SYMMETRIC_KEY_LEN); } - up_read(&checker->device->static_identity.lock); } void cookie_checker_precompute_peer_keys(struct wireguard_peer *peer) diff --git a/src/netlink.c b/src/netlink.c index c61657c..2f5157d 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -435,12 +435,14 @@ static int set_device(struct sk_buff *skb, struct genl_info *info) } } + down_write(&wg->static_identity.lock); 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)) peer_remove(peer); } cookie_checker_precompute_device_keys(&wg->cookie_checker); + up_write(&wg->static_identity.lock); } if (info->attrs[WGDEVICE_A_PEERS]) { diff --git a/src/noise.c b/src/noise.c index bab8e7c..b70504f 100644 --- a/src/noise.c +++ b/src/noise.c @@ -42,17 +42,16 @@ void __init noise_init(void) blake2s_final(&blake, handshake_init_hash, NOISE_HASH_LEN); } +/* Must hold peer->handshake.static_identity->lock */ bool noise_precompute_static_static(struct wireguard_peer *peer) { bool ret = true; - down_read(&peer->handshake.static_identity->lock); down_write(&peer->handshake.lock); if (peer->handshake.static_identity->has_identity) ret = curve25519(peer->handshake.precomputed_static_static, peer->handshake.static_identity->static_private, peer->handshake.remote_static); else memset(peer->handshake.precomputed_static_static, 0, NOISE_PUBLIC_KEY_LEN); up_write(&peer->handshake.lock); - up_read(&peer->handshake.static_identity->lock); return ret; } @@ -227,12 +226,11 @@ bool noise_received_with_keypair(struct noise_keypairs *keypairs, struct noise_k return true; } +/* Must hold static_identity->lock */ void noise_set_static_identity_private_key(struct noise_static_identity *static_identity, const u8 private_key[NOISE_PUBLIC_KEY_LEN]) { - down_write(&static_identity->lock); memcpy(static_identity->static_private, private_key, NOISE_PUBLIC_KEY_LEN); static_identity->has_identity = curve25519_generate_public(static_identity->static_public, private_key); - up_write(&static_identity->lock); } /* This is Hugo Krawczyk's HKDF: -- cgit v1.2.3-59-g8ed1b