summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-06-18 20:44:32 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-06-18 20:44:32 +0200
commita97ca1117db9b34dead340707ffde1c07b369a0c (patch)
tree897cc0b848ac3d748244ea38c7e2c93aefb50de7
parent2d01527aee1308f4c07652849da569825870ed14 (diff)
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 <Jason@zx2c4.com>
-rw-r--r--src/cookie.c3
-rw-r--r--src/netlink.c2
-rw-r--r--src/noise.c6
3 files changed, 5 insertions, 6 deletions
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: