Skip to content
This repository was archived by the owner on Dec 27, 2019. It is now read-only.

Commit 6c8a36a

Browse files
committed
noise: immediately rekey all peers after changing device private key
Reported-by: Derrick Pallas <[email protected]>
1 parent c903f49 commit 6c8a36a

File tree

5 files changed

+41
-7
lines changed

5 files changed

+41
-7
lines changed

src/device.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,7 @@ static int wg_stop(struct net_device *dev)
112112
wg_timers_stop(peer);
113113
wg_noise_handshake_clear(&peer->handshake);
114114
wg_noise_keypairs_clear(&peer->keypairs);
115-
atomic64_set(&peer->last_sent_handshake,
116-
ktime_get_coarse_boottime_ns() -
117-
(u64)(REKEY_TIMEOUT + 1) * NSEC_PER_SEC);
115+
wg_noise_reset_last_sent_handshake(&peer->last_sent_handshake);
118116
}
119117
mutex_unlock(&wg->device_update_lock);
120118
skb_queue_purge(&wg->incoming_handshakes);

src/netlink.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/if.h>
1414
#include <net/genetlink.h>
1515
#include <net/sock.h>
16+
#include <crypto/algapi.h>
1617

1718
static struct genl_family genl_family;
1819

@@ -546,6 +547,10 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info)
546547
u8 public_key[NOISE_PUBLIC_KEY_LEN];
547548
struct wg_peer *peer, *temp;
548549

550+
if (!crypto_memneq(wg->static_identity.static_private,
551+
private_key, NOISE_PUBLIC_KEY_LEN))
552+
goto skip_set_private_key;
553+
549554
/* We remove before setting, to prevent race, which means doing
550555
* two 25519-genpub ops.
551556
*/
@@ -563,12 +568,15 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info)
563568
private_key);
564569
list_for_each_entry_safe(peer, temp, &wg->peer_list,
565570
peer_list) {
566-
if (!wg_noise_precompute_static_static(peer))
571+
if (wg_noise_precompute_static_static(peer))
572+
wg_noise_expire_current_peer_keypairs(peer);
573+
else
567574
wg_peer_remove(peer);
568575
}
569576
wg_cookie_checker_precompute_device_keys(&wg->cookie_checker);
570577
up_write(&wg->static_identity.lock);
571578
}
579+
skip_set_private_key:
572580

573581
if (info->attrs[WGDEVICE_A_PEERS]) {
574582
struct nlattr *attr, *peer[WGPEER_A_MAX + 1];

src/noise.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,29 @@ void wg_noise_keypairs_clear(struct noise_keypairs *keypairs)
183183
spin_unlock_bh(&keypairs->keypair_update_lock);
184184
}
185185

186+
static void rekey_sending_keypair(struct noise_keypair *keypair)
187+
{
188+
u64 rekey_ns = ktime_get_coarse_boottime_ns() -
189+
(u64)(REKEY_AFTER_TIME + 1) * NSEC_PER_SEC;
190+
if ((s64)rekey_ns < (s64)keypair->sending.birthdate)
191+
keypair->sending.birthdate = rekey_ns;
192+
}
193+
194+
void wg_noise_expire_current_peer_keypairs(struct wg_peer *peer)
195+
{
196+
wg_noise_handshake_clear(&peer->handshake);
197+
wg_noise_reset_last_sent_handshake(&peer->last_sent_handshake);
198+
199+
spin_lock_bh(&peer->keypairs.keypair_update_lock);
200+
rekey_sending_keypair(
201+
rcu_dereference_protected(peer->keypairs.next_keypair,
202+
lockdep_is_held(&peer->keypairs.keypair_update_lock)));
203+
rekey_sending_keypair(
204+
rcu_dereference_protected(peer->keypairs.current_keypair,
205+
lockdep_is_held(&peer->keypairs.keypair_update_lock)));
206+
spin_unlock_bh(&peer->keypairs.keypair_update_lock);
207+
}
208+
186209
static void add_new_keypair(struct noise_keypairs *keypairs,
187210
struct noise_keypair *new_keypair)
188211
{

src/noise.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,18 @@ bool wg_noise_handshake_init(struct noise_handshake *handshake,
100100
const u8 peer_preshared_key[NOISE_SYMMETRIC_KEY_LEN],
101101
struct wg_peer *peer);
102102
void wg_noise_handshake_clear(struct noise_handshake *handshake);
103+
static inline void wg_noise_reset_last_sent_handshake(atomic64_t *handshake_ns)
104+
{
105+
atomic64_set(handshake_ns, ktime_get_coarse_boottime_ns() -
106+
(u64)(REKEY_TIMEOUT + 1) * NSEC_PER_SEC);
107+
}
108+
103109
void wg_noise_keypair_put(struct noise_keypair *keypair, bool unreference_now);
104110
struct noise_keypair *wg_noise_keypair_get(struct noise_keypair *keypair);
105111
void wg_noise_keypairs_clear(struct noise_keypairs *keypairs);
106112
bool wg_noise_received_with_keypair(struct noise_keypairs *keypairs,
107113
struct noise_keypair *received_keypair);
114+
void wg_noise_expire_current_peer_keypairs(struct wg_peer *peer);
108115

109116
void wg_noise_set_static_identity_private_key(
110117
struct noise_static_identity *static_identity,

src/peer.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ struct wg_peer *wg_peer_create(struct wg_device *wg,
5656
rwlock_init(&peer->endpoint_lock);
5757
kref_init(&peer->refcount);
5858
skb_queue_head_init(&peer->staged_packet_queue);
59-
atomic64_set(&peer->last_sent_handshake,
60-
ktime_get_coarse_boottime_ns() -
61-
(u64)(REKEY_TIMEOUT + 1) * NSEC_PER_SEC);
59+
wg_noise_reset_last_sent_handshake(&peer->last_sent_handshake);
6260
set_bit(NAPI_STATE_NO_BUSY_POLL, &peer->napi.state);
6361
netif_napi_add(wg->dev, &peer->napi, wg_packet_rx_poll,
6462
NAPI_POLL_WEIGHT);

0 commit comments

Comments
 (0)