summaryrefslogtreecommitdiffhomepage
path: root/src/receive.c
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2016-10-19 15:46:28 +0900
committerJason A. Donenfeld <Jason@zx2c4.com>2016-10-19 17:22:13 +0900
commit99e4518974d6326c1f4c8d3ea187cd1f147e310a (patch)
tree1ed9ae57a48ad0decefb3456e7f4763d262f7cb2 /src/receive.c
parentffee48b50b8d38bd5377a04e42416df8391eed6b (diff)
timers: only have initiator rekey
If it's time to rekey, and the responder sends a message, the initator will begin the rekeying when sending his response message. In the worst case, this response message will actually just be the keepalive. This generally works well, with the one edge case of the message arriving less than 10 seconds before key expiration, in which the keepalive is not sufficient. In this case, we simply rehandshake immediately. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src/receive.c')
-rw-r--r--src/receive.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/receive.c b/src/receive.c
index 58a0086..6dda410 100644
--- a/src/receive.c
+++ b/src/receive.c
@@ -123,7 +123,6 @@ static void receive_handshake_packet(struct wireguard_device *wg, void *data, si
return;
}
net_dbg_ratelimited("Receiving handshake initiation from peer %Lu (%pISpfsc)\n", peer->internal_id, &addr);
- timers_handshake_received(peer);
update_latest_addr(peer, skb);
packet_send_handshake_response(peer);
break;
@@ -139,10 +138,10 @@ static void receive_handshake_packet(struct wireguard_device *wg, void *data, si
return;
}
net_dbg_ratelimited("Receiving handshake response from peer %Lu (%pISpfsc)\n", peer->internal_id, &addr);
- timers_handshake_received(peer);
if (noise_handshake_begin_session(&peer->handshake, &peer->keypairs, true)) {
timers_ephemeral_key_created(peer);
timers_handshake_complete(peer);
+ peer->sent_lastminute_handshake = false;
packet_send_queue(peer);
}
break;
@@ -179,6 +178,26 @@ void packet_process_queued_handshake_packets(struct work_struct *work)
}
}
+static void keep_key_fresh(struct wireguard_peer *peer)
+{
+ struct noise_keypair *keypair;
+ bool send = false;
+ if (peer->sent_lastminute_handshake)
+ return;
+
+ rcu_read_lock();
+ keypair = rcu_dereference(peer->keypairs.current_keypair);
+ if (likely(keypair && keypair->sending.is_valid) && keypair->i_am_the_initiator &&
+ unlikely(time_is_before_eq_jiffies64(keypair->sending.birthdate + REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT)))
+ send = true;
+ rcu_read_unlock();
+
+ if (send) {
+ peer->sent_lastminute_handshake = true;
+ packet_send_handshake_initiation_ratelimited(peer);
+ }
+}
+
struct packet_cb {
u8 ds;
};
@@ -198,8 +217,12 @@ static void receive_data_packet(struct sk_buff *skb, struct wireguard_peer *peer
wg = peer->device;
dev = netdev_pub(wg);
- if (unlikely(used_new_key))
+ if (unlikely(used_new_key)) {
+ peer->sent_lastminute_handshake = false;
packet_send_queue(peer);
+ }
+
+ keep_key_fresh(peer);
/* A packet with length 0 is a keepalive packet */
if (unlikely(!skb->len)) {