xref: /openbmc/linux/drivers/net/wireguard/receive.c (revision 78739d72)
1e7096c13SJason A. Donenfeld // SPDX-License-Identifier: GPL-2.0
2e7096c13SJason A. Donenfeld /*
3e7096c13SJason A. Donenfeld  * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
4e7096c13SJason A. Donenfeld  */
5e7096c13SJason A. Donenfeld 
6e7096c13SJason A. Donenfeld #include "queueing.h"
7e7096c13SJason A. Donenfeld #include "device.h"
8e7096c13SJason A. Donenfeld #include "peer.h"
9e7096c13SJason A. Donenfeld #include "timers.h"
10e7096c13SJason A. Donenfeld #include "messages.h"
11e7096c13SJason A. Donenfeld #include "cookie.h"
12e7096c13SJason A. Donenfeld #include "socket.h"
13e7096c13SJason A. Donenfeld 
14e7096c13SJason A. Donenfeld #include <linux/ip.h>
15e7096c13SJason A. Donenfeld #include <linux/ipv6.h>
16e7096c13SJason A. Donenfeld #include <linux/udp.h>
17e7096c13SJason A. Donenfeld #include <net/ip_tunnels.h>
18e7096c13SJason A. Donenfeld 
19e7096c13SJason A. Donenfeld /* Must be called with bh disabled. */
update_rx_stats(struct wg_peer * peer,size_t len)20e7096c13SJason A. Donenfeld static void update_rx_stats(struct wg_peer *peer, size_t len)
21e7096c13SJason A. Donenfeld {
22eeb15885SEric Dumazet 	dev_sw_netstats_rx_add(peer->device->dev, len);
23e7096c13SJason A. Donenfeld 	peer->rx_bytes += len;
24e7096c13SJason A. Donenfeld }
25e7096c13SJason A. Donenfeld 
26e7096c13SJason A. Donenfeld #define SKB_TYPE_LE32(skb) (((struct message_header *)(skb)->data)->type)
27e7096c13SJason A. Donenfeld 
validate_header_len(struct sk_buff * skb)28e7096c13SJason A. Donenfeld static size_t validate_header_len(struct sk_buff *skb)
29e7096c13SJason A. Donenfeld {
30e7096c13SJason A. Donenfeld 	if (unlikely(skb->len < sizeof(struct message_header)))
31e7096c13SJason A. Donenfeld 		return 0;
32e7096c13SJason A. Donenfeld 	if (SKB_TYPE_LE32(skb) == cpu_to_le32(MESSAGE_DATA) &&
33e7096c13SJason A. Donenfeld 	    skb->len >= MESSAGE_MINIMUM_LENGTH)
34e7096c13SJason A. Donenfeld 		return sizeof(struct message_data);
35e7096c13SJason A. Donenfeld 	if (SKB_TYPE_LE32(skb) == cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION) &&
36e7096c13SJason A. Donenfeld 	    skb->len == sizeof(struct message_handshake_initiation))
37e7096c13SJason A. Donenfeld 		return sizeof(struct message_handshake_initiation);
38e7096c13SJason A. Donenfeld 	if (SKB_TYPE_LE32(skb) == cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE) &&
39e7096c13SJason A. Donenfeld 	    skb->len == sizeof(struct message_handshake_response))
40e7096c13SJason A. Donenfeld 		return sizeof(struct message_handshake_response);
41e7096c13SJason A. Donenfeld 	if (SKB_TYPE_LE32(skb) == cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE) &&
42e7096c13SJason A. Donenfeld 	    skb->len == sizeof(struct message_handshake_cookie))
43e7096c13SJason A. Donenfeld 		return sizeof(struct message_handshake_cookie);
44e7096c13SJason A. Donenfeld 	return 0;
45e7096c13SJason A. Donenfeld }
46e7096c13SJason A. Donenfeld 
prepare_skb_header(struct sk_buff * skb,struct wg_device * wg)47e7096c13SJason A. Donenfeld static int prepare_skb_header(struct sk_buff *skb, struct wg_device *wg)
48e7096c13SJason A. Donenfeld {
49e7096c13SJason A. Donenfeld 	size_t data_offset, data_len, header_len;
50e7096c13SJason A. Donenfeld 	struct udphdr *udp;
51e7096c13SJason A. Donenfeld 
52a5588604SJason A. Donenfeld 	if (unlikely(!wg_check_packet_protocol(skb) ||
53e7096c13SJason A. Donenfeld 		     skb_transport_header(skb) < skb->head ||
54e7096c13SJason A. Donenfeld 		     (skb_transport_header(skb) + sizeof(struct udphdr)) >
55e7096c13SJason A. Donenfeld 			     skb_tail_pointer(skb)))
56e7096c13SJason A. Donenfeld 		return -EINVAL; /* Bogus IP header */
57e7096c13SJason A. Donenfeld 	udp = udp_hdr(skb);
58e7096c13SJason A. Donenfeld 	data_offset = (u8 *)udp - skb->data;
59e7096c13SJason A. Donenfeld 	if (unlikely(data_offset > U16_MAX ||
60e7096c13SJason A. Donenfeld 		     data_offset + sizeof(struct udphdr) > skb->len))
61e7096c13SJason A. Donenfeld 		/* Packet has offset at impossible location or isn't big enough
62e7096c13SJason A. Donenfeld 		 * to have UDP fields.
63e7096c13SJason A. Donenfeld 		 */
64e7096c13SJason A. Donenfeld 		return -EINVAL;
65e7096c13SJason A. Donenfeld 	data_len = ntohs(udp->len);
66e7096c13SJason A. Donenfeld 	if (unlikely(data_len < sizeof(struct udphdr) ||
67e7096c13SJason A. Donenfeld 		     data_len > skb->len - data_offset))
68e7096c13SJason A. Donenfeld 		/* UDP packet is reporting too small of a size or lying about
69e7096c13SJason A. Donenfeld 		 * its size.
70e7096c13SJason A. Donenfeld 		 */
71e7096c13SJason A. Donenfeld 		return -EINVAL;
72e7096c13SJason A. Donenfeld 	data_len -= sizeof(struct udphdr);
73e7096c13SJason A. Donenfeld 	data_offset = (u8 *)udp + sizeof(struct udphdr) - skb->data;
74e7096c13SJason A. Donenfeld 	if (unlikely(!pskb_may_pull(skb,
75e7096c13SJason A. Donenfeld 				data_offset + sizeof(struct message_header)) ||
76e7096c13SJason A. Donenfeld 		     pskb_trim(skb, data_len + data_offset) < 0))
77e7096c13SJason A. Donenfeld 		return -EINVAL;
78e7096c13SJason A. Donenfeld 	skb_pull(skb, data_offset);
79e7096c13SJason A. Donenfeld 	if (unlikely(skb->len != data_len))
80e7096c13SJason A. Donenfeld 		/* Final len does not agree with calculated len */
81e7096c13SJason A. Donenfeld 		return -EINVAL;
82e7096c13SJason A. Donenfeld 	header_len = validate_header_len(skb);
83e7096c13SJason A. Donenfeld 	if (unlikely(!header_len))
84e7096c13SJason A. Donenfeld 		return -EINVAL;
85e7096c13SJason A. Donenfeld 	__skb_push(skb, data_offset);
86e7096c13SJason A. Donenfeld 	if (unlikely(!pskb_may_pull(skb, data_offset + header_len)))
87e7096c13SJason A. Donenfeld 		return -EINVAL;
88e7096c13SJason A. Donenfeld 	__skb_pull(skb, data_offset);
89e7096c13SJason A. Donenfeld 	return 0;
90e7096c13SJason A. Donenfeld }
91e7096c13SJason A. Donenfeld 
wg_receive_handshake_packet(struct wg_device * wg,struct sk_buff * skb)92e7096c13SJason A. Donenfeld static void wg_receive_handshake_packet(struct wg_device *wg,
93e7096c13SJason A. Donenfeld 					struct sk_buff *skb)
94e7096c13SJason A. Donenfeld {
95e7096c13SJason A. Donenfeld 	enum cookie_mac_state mac_state;
96e7096c13SJason A. Donenfeld 	struct wg_peer *peer = NULL;
97e7096c13SJason A. Donenfeld 	/* This is global, so that our load calculation applies to the whole
98e7096c13SJason A. Donenfeld 	 * system. We don't care about races with it at all.
99e7096c13SJason A. Donenfeld 	 */
100e7096c13SJason A. Donenfeld 	static u64 last_under_load;
101e7096c13SJason A. Donenfeld 	bool packet_needs_cookie;
102e7096c13SJason A. Donenfeld 	bool under_load;
103e7096c13SJason A. Donenfeld 
104e7096c13SJason A. Donenfeld 	if (SKB_TYPE_LE32(skb) == cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE)) {
105e7096c13SJason A. Donenfeld 		net_dbg_skb_ratelimited("%s: Receiving cookie response from %pISpfsc\n",
106e7096c13SJason A. Donenfeld 					wg->dev->name, skb);
107e7096c13SJason A. Donenfeld 		wg_cookie_message_consume(
108e7096c13SJason A. Donenfeld 			(struct message_handshake_cookie *)skb->data, wg);
109e7096c13SJason A. Donenfeld 		return;
110e7096c13SJason A. Donenfeld 	}
111e7096c13SJason A. Donenfeld 
112886fcee9SJason A. Donenfeld 	under_load = atomic_read(&wg->handshake_queue_len) >=
113e7096c13SJason A. Donenfeld 			MAX_QUEUED_INCOMING_HANDSHAKES / 8;
1142a8a4df3SJason A. Donenfeld 	if (under_load) {
115e7096c13SJason A. Donenfeld 		last_under_load = ktime_get_coarse_boottime_ns();
1162a8a4df3SJason A. Donenfeld 	} else if (last_under_load) {
117e7096c13SJason A. Donenfeld 		under_load = !wg_birthdate_has_expired(last_under_load, 1);
1182a8a4df3SJason A. Donenfeld 		if (!under_load)
1192a8a4df3SJason A. Donenfeld 			last_under_load = 0;
1202a8a4df3SJason A. Donenfeld 	}
121e7096c13SJason A. Donenfeld 	mac_state = wg_cookie_validate_packet(&wg->cookie_checker, skb,
122e7096c13SJason A. Donenfeld 					      under_load);
123e7096c13SJason A. Donenfeld 	if ((under_load && mac_state == VALID_MAC_WITH_COOKIE) ||
124e7096c13SJason A. Donenfeld 	    (!under_load && mac_state == VALID_MAC_BUT_NO_COOKIE)) {
125e7096c13SJason A. Donenfeld 		packet_needs_cookie = false;
126e7096c13SJason A. Donenfeld 	} else if (under_load && mac_state == VALID_MAC_BUT_NO_COOKIE) {
127e7096c13SJason A. Donenfeld 		packet_needs_cookie = true;
128e7096c13SJason A. Donenfeld 	} else {
129e7096c13SJason A. Donenfeld 		net_dbg_skb_ratelimited("%s: Invalid MAC of handshake, dropping packet from %pISpfsc\n",
130e7096c13SJason A. Donenfeld 					wg->dev->name, skb);
131e7096c13SJason A. Donenfeld 		return;
132e7096c13SJason A. Donenfeld 	}
133e7096c13SJason A. Donenfeld 
134e7096c13SJason A. Donenfeld 	switch (SKB_TYPE_LE32(skb)) {
135e7096c13SJason A. Donenfeld 	case cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION): {
136e7096c13SJason A. Donenfeld 		struct message_handshake_initiation *message =
137e7096c13SJason A. Donenfeld 			(struct message_handshake_initiation *)skb->data;
138e7096c13SJason A. Donenfeld 
139e7096c13SJason A. Donenfeld 		if (packet_needs_cookie) {
140e7096c13SJason A. Donenfeld 			wg_packet_send_handshake_cookie(wg, skb,
141e7096c13SJason A. Donenfeld 							message->sender_index);
142e7096c13SJason A. Donenfeld 			return;
143e7096c13SJason A. Donenfeld 		}
144e7096c13SJason A. Donenfeld 		peer = wg_noise_handshake_consume_initiation(message, wg);
145e7096c13SJason A. Donenfeld 		if (unlikely(!peer)) {
146e7096c13SJason A. Donenfeld 			net_dbg_skb_ratelimited("%s: Invalid handshake initiation from %pISpfsc\n",
147e7096c13SJason A. Donenfeld 						wg->dev->name, skb);
148e7096c13SJason A. Donenfeld 			return;
149e7096c13SJason A. Donenfeld 		}
150e7096c13SJason A. Donenfeld 		wg_socket_set_peer_endpoint_from_skb(peer, skb);
151e7096c13SJason A. Donenfeld 		net_dbg_ratelimited("%s: Receiving handshake initiation from peer %llu (%pISpfsc)\n",
152e7096c13SJason A. Donenfeld 				    wg->dev->name, peer->internal_id,
153e7096c13SJason A. Donenfeld 				    &peer->endpoint.addr);
154e7096c13SJason A. Donenfeld 		wg_packet_send_handshake_response(peer);
155e7096c13SJason A. Donenfeld 		break;
156e7096c13SJason A. Donenfeld 	}
157e7096c13SJason A. Donenfeld 	case cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE): {
158e7096c13SJason A. Donenfeld 		struct message_handshake_response *message =
159e7096c13SJason A. Donenfeld 			(struct message_handshake_response *)skb->data;
160e7096c13SJason A. Donenfeld 
161e7096c13SJason A. Donenfeld 		if (packet_needs_cookie) {
162e7096c13SJason A. Donenfeld 			wg_packet_send_handshake_cookie(wg, skb,
163e7096c13SJason A. Donenfeld 							message->sender_index);
164e7096c13SJason A. Donenfeld 			return;
165e7096c13SJason A. Donenfeld 		}
166e7096c13SJason A. Donenfeld 		peer = wg_noise_handshake_consume_response(message, wg);
167e7096c13SJason A. Donenfeld 		if (unlikely(!peer)) {
168e7096c13SJason A. Donenfeld 			net_dbg_skb_ratelimited("%s: Invalid handshake response from %pISpfsc\n",
169e7096c13SJason A. Donenfeld 						wg->dev->name, skb);
170e7096c13SJason A. Donenfeld 			return;
171e7096c13SJason A. Donenfeld 		}
172e7096c13SJason A. Donenfeld 		wg_socket_set_peer_endpoint_from_skb(peer, skb);
173e7096c13SJason A. Donenfeld 		net_dbg_ratelimited("%s: Receiving handshake response from peer %llu (%pISpfsc)\n",
174e7096c13SJason A. Donenfeld 				    wg->dev->name, peer->internal_id,
175e7096c13SJason A. Donenfeld 				    &peer->endpoint.addr);
176e7096c13SJason A. Donenfeld 		if (wg_noise_handshake_begin_session(&peer->handshake,
177e7096c13SJason A. Donenfeld 						     &peer->keypairs)) {
178e7096c13SJason A. Donenfeld 			wg_timers_session_derived(peer);
179e7096c13SJason A. Donenfeld 			wg_timers_handshake_complete(peer);
180e7096c13SJason A. Donenfeld 			/* Calling this function will either send any existing
181e7096c13SJason A. Donenfeld 			 * packets in the queue and not send a keepalive, which
182e7096c13SJason A. Donenfeld 			 * is the best case, Or, if there's nothing in the
183e7096c13SJason A. Donenfeld 			 * queue, it will send a keepalive, in order to give
184e7096c13SJason A. Donenfeld 			 * immediate confirmation of the session.
185e7096c13SJason A. Donenfeld 			 */
186e7096c13SJason A. Donenfeld 			wg_packet_send_keepalive(peer);
187e7096c13SJason A. Donenfeld 		}
188e7096c13SJason A. Donenfeld 		break;
189e7096c13SJason A. Donenfeld 	}
190e7096c13SJason A. Donenfeld 	}
191e7096c13SJason A. Donenfeld 
192e7096c13SJason A. Donenfeld 	if (unlikely(!peer)) {
193e7096c13SJason A. Donenfeld 		WARN(1, "Somehow a wrong type of packet wound up in the handshake queue!\n");
194e7096c13SJason A. Donenfeld 		return;
195e7096c13SJason A. Donenfeld 	}
196e7096c13SJason A. Donenfeld 
197e7096c13SJason A. Donenfeld 	local_bh_disable();
198e7096c13SJason A. Donenfeld 	update_rx_stats(peer, skb->len);
199e7096c13SJason A. Donenfeld 	local_bh_enable();
200e7096c13SJason A. Donenfeld 
201e7096c13SJason A. Donenfeld 	wg_timers_any_authenticated_packet_received(peer);
202e7096c13SJason A. Donenfeld 	wg_timers_any_authenticated_packet_traversal(peer);
203e7096c13SJason A. Donenfeld 	wg_peer_put(peer);
204e7096c13SJason A. Donenfeld }
205e7096c13SJason A. Donenfeld 
wg_packet_handshake_receive_worker(struct work_struct * work)206e7096c13SJason A. Donenfeld void wg_packet_handshake_receive_worker(struct work_struct *work)
207e7096c13SJason A. Donenfeld {
208886fcee9SJason A. Donenfeld 	struct crypt_queue *queue = container_of(work, struct multicore_worker, work)->ptr;
209886fcee9SJason A. Donenfeld 	struct wg_device *wg = container_of(queue, struct wg_device, handshake_queue);
210e7096c13SJason A. Donenfeld 	struct sk_buff *skb;
211e7096c13SJason A. Donenfeld 
212886fcee9SJason A. Donenfeld 	while ((skb = ptr_ring_consume_bh(&queue->ring)) != NULL) {
213e7096c13SJason A. Donenfeld 		wg_receive_handshake_packet(wg, skb);
214e7096c13SJason A. Donenfeld 		dev_kfree_skb(skb);
215886fcee9SJason A. Donenfeld 		atomic_dec(&wg->handshake_queue_len);
216e7096c13SJason A. Donenfeld 		cond_resched();
217e7096c13SJason A. Donenfeld 	}
218e7096c13SJason A. Donenfeld }
219e7096c13SJason A. Donenfeld 
keep_key_fresh(struct wg_peer * peer)220e7096c13SJason A. Donenfeld static void keep_key_fresh(struct wg_peer *peer)
221e7096c13SJason A. Donenfeld {
222e7096c13SJason A. Donenfeld 	struct noise_keypair *keypair;
223243f2148SJason A. Donenfeld 	bool send;
224e7096c13SJason A. Donenfeld 
225e7096c13SJason A. Donenfeld 	if (peer->sent_lastminute_handshake)
226e7096c13SJason A. Donenfeld 		return;
227e7096c13SJason A. Donenfeld 
228e7096c13SJason A. Donenfeld 	rcu_read_lock_bh();
229e7096c13SJason A. Donenfeld 	keypair = rcu_dereference_bh(peer->keypairs.current_keypair);
230243f2148SJason A. Donenfeld 	send = keypair && READ_ONCE(keypair->sending.is_valid) &&
231e7096c13SJason A. Donenfeld 	       keypair->i_am_the_initiator &&
232243f2148SJason A. Donenfeld 	       wg_birthdate_has_expired(keypair->sending.birthdate,
233243f2148SJason A. Donenfeld 			REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT);
234e7096c13SJason A. Donenfeld 	rcu_read_unlock_bh();
235e7096c13SJason A. Donenfeld 
236243f2148SJason A. Donenfeld 	if (unlikely(send)) {
237e7096c13SJason A. Donenfeld 		peer->sent_lastminute_handshake = true;
238e7096c13SJason A. Donenfeld 		wg_packet_send_queued_handshake_initiation(peer, false);
239e7096c13SJason A. Donenfeld 	}
240e7096c13SJason A. Donenfeld }
241e7096c13SJason A. Donenfeld 
decrypt_packet(struct sk_buff * skb,struct noise_keypair * keypair)242a9e90d99SJason A. Donenfeld static bool decrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair)
243e7096c13SJason A. Donenfeld {
244e7096c13SJason A. Donenfeld 	struct scatterlist sg[MAX_SKB_FRAGS + 8];
245e7096c13SJason A. Donenfeld 	struct sk_buff *trailer;
246e7096c13SJason A. Donenfeld 	unsigned int offset;
247e7096c13SJason A. Donenfeld 	int num_frags;
248e7096c13SJason A. Donenfeld 
249a9e90d99SJason A. Donenfeld 	if (unlikely(!keypair))
250e7096c13SJason A. Donenfeld 		return false;
251e7096c13SJason A. Donenfeld 
252a9e90d99SJason A. Donenfeld 	if (unlikely(!READ_ONCE(keypair->receiving.is_valid) ||
253a9e90d99SJason A. Donenfeld 		  wg_birthdate_has_expired(keypair->receiving.birthdate, REJECT_AFTER_TIME) ||
254*78739d72SNikita Zhandarovich 		  READ_ONCE(keypair->receiving_counter.counter) >= REJECT_AFTER_MESSAGES)) {
255a9e90d99SJason A. Donenfeld 		WRITE_ONCE(keypair->receiving.is_valid, false);
256e7096c13SJason A. Donenfeld 		return false;
257e7096c13SJason A. Donenfeld 	}
258e7096c13SJason A. Donenfeld 
259e7096c13SJason A. Donenfeld 	PACKET_CB(skb)->nonce =
260e7096c13SJason A. Donenfeld 		le64_to_cpu(((struct message_data *)skb->data)->counter);
261e7096c13SJason A. Donenfeld 
262e7096c13SJason A. Donenfeld 	/* We ensure that the network header is part of the packet before we
263e7096c13SJason A. Donenfeld 	 * call skb_cow_data, so that there's no chance that data is removed
264e7096c13SJason A. Donenfeld 	 * from the skb, so that later we can extract the original endpoint.
265e7096c13SJason A. Donenfeld 	 */
266e7096c13SJason A. Donenfeld 	offset = skb->data - skb_network_header(skb);
267e7096c13SJason A. Donenfeld 	skb_push(skb, offset);
268e7096c13SJason A. Donenfeld 	num_frags = skb_cow_data(skb, 0, &trailer);
269e7096c13SJason A. Donenfeld 	offset += sizeof(struct message_data);
270e7096c13SJason A. Donenfeld 	skb_pull(skb, offset);
271e7096c13SJason A. Donenfeld 	if (unlikely(num_frags < 0 || num_frags > ARRAY_SIZE(sg)))
272e7096c13SJason A. Donenfeld 		return false;
273e7096c13SJason A. Donenfeld 
274e7096c13SJason A. Donenfeld 	sg_init_table(sg, num_frags);
275e7096c13SJason A. Donenfeld 	if (skb_to_sgvec(skb, sg, 0, skb->len) <= 0)
276e7096c13SJason A. Donenfeld 		return false;
277e7096c13SJason A. Donenfeld 
278e7096c13SJason A. Donenfeld 	if (!chacha20poly1305_decrypt_sg_inplace(sg, skb->len, NULL, 0,
279e7096c13SJason A. Donenfeld 					         PACKET_CB(skb)->nonce,
280a9e90d99SJason A. Donenfeld 						 keypair->receiving.key))
281e7096c13SJason A. Donenfeld 		return false;
282e7096c13SJason A. Donenfeld 
283e7096c13SJason A. Donenfeld 	/* Another ugly situation of pushing and pulling the header so as to
284e7096c13SJason A. Donenfeld 	 * keep endpoint information intact.
285e7096c13SJason A. Donenfeld 	 */
286e7096c13SJason A. Donenfeld 	skb_push(skb, offset);
287e7096c13SJason A. Donenfeld 	if (pskb_trim(skb, skb->len - noise_encrypted_len(0)))
288e7096c13SJason A. Donenfeld 		return false;
289e7096c13SJason A. Donenfeld 	skb_pull(skb, offset);
290e7096c13SJason A. Donenfeld 
291e7096c13SJason A. Donenfeld 	return true;
292e7096c13SJason A. Donenfeld }
293e7096c13SJason A. Donenfeld 
294e7096c13SJason A. Donenfeld /* This is RFC6479, a replay detection bitmap algorithm that avoids bitshifts */
counter_validate(struct noise_replay_counter * counter,u64 their_counter)295a9e90d99SJason A. Donenfeld static bool counter_validate(struct noise_replay_counter *counter, u64 their_counter)
296e7096c13SJason A. Donenfeld {
297e7096c13SJason A. Donenfeld 	unsigned long index, index_current, top, i;
298e7096c13SJason A. Donenfeld 	bool ret = false;
299e7096c13SJason A. Donenfeld 
300a9e90d99SJason A. Donenfeld 	spin_lock_bh(&counter->lock);
301e7096c13SJason A. Donenfeld 
302a9e90d99SJason A. Donenfeld 	if (unlikely(counter->counter >= REJECT_AFTER_MESSAGES + 1 ||
303e7096c13SJason A. Donenfeld 		     their_counter >= REJECT_AFTER_MESSAGES))
304e7096c13SJason A. Donenfeld 		goto out;
305e7096c13SJason A. Donenfeld 
306e7096c13SJason A. Donenfeld 	++their_counter;
307e7096c13SJason A. Donenfeld 
308e7096c13SJason A. Donenfeld 	if (unlikely((COUNTER_WINDOW_SIZE + their_counter) <
309a9e90d99SJason A. Donenfeld 		     counter->counter))
310e7096c13SJason A. Donenfeld 		goto out;
311e7096c13SJason A. Donenfeld 
312e7096c13SJason A. Donenfeld 	index = their_counter >> ilog2(BITS_PER_LONG);
313e7096c13SJason A. Donenfeld 
314a9e90d99SJason A. Donenfeld 	if (likely(their_counter > counter->counter)) {
315a9e90d99SJason A. Donenfeld 		index_current = counter->counter >> ilog2(BITS_PER_LONG);
316e7096c13SJason A. Donenfeld 		top = min_t(unsigned long, index - index_current,
317e7096c13SJason A. Donenfeld 			    COUNTER_BITS_TOTAL / BITS_PER_LONG);
318e7096c13SJason A. Donenfeld 		for (i = 1; i <= top; ++i)
319a9e90d99SJason A. Donenfeld 			counter->backtrack[(i + index_current) &
320e7096c13SJason A. Donenfeld 				((COUNTER_BITS_TOTAL / BITS_PER_LONG) - 1)] = 0;
321*78739d72SNikita Zhandarovich 		WRITE_ONCE(counter->counter, their_counter);
322e7096c13SJason A. Donenfeld 	}
323e7096c13SJason A. Donenfeld 
324e7096c13SJason A. Donenfeld 	index &= (COUNTER_BITS_TOTAL / BITS_PER_LONG) - 1;
325e7096c13SJason A. Donenfeld 	ret = !test_and_set_bit(their_counter & (BITS_PER_LONG - 1),
326a9e90d99SJason A. Donenfeld 				&counter->backtrack[index]);
327e7096c13SJason A. Donenfeld 
328e7096c13SJason A. Donenfeld out:
329a9e90d99SJason A. Donenfeld 	spin_unlock_bh(&counter->lock);
330e7096c13SJason A. Donenfeld 	return ret;
331e7096c13SJason A. Donenfeld }
332e7096c13SJason A. Donenfeld 
333e7096c13SJason A. Donenfeld #include "selftest/counter.c"
334e7096c13SJason A. Donenfeld 
wg_packet_consume_data_done(struct wg_peer * peer,struct sk_buff * skb,struct endpoint * endpoint)335e7096c13SJason A. Donenfeld static void wg_packet_consume_data_done(struct wg_peer *peer,
336e7096c13SJason A. Donenfeld 					struct sk_buff *skb,
337e7096c13SJason A. Donenfeld 					struct endpoint *endpoint)
338e7096c13SJason A. Donenfeld {
339e7096c13SJason A. Donenfeld 	struct net_device *dev = peer->device->dev;
340e7096c13SJason A. Donenfeld 	unsigned int len, len_before_trim;
341e7096c13SJason A. Donenfeld 	struct wg_peer *routed_peer;
342e7096c13SJason A. Donenfeld 
343e7096c13SJason A. Donenfeld 	wg_socket_set_peer_endpoint(peer, endpoint);
344e7096c13SJason A. Donenfeld 
345e7096c13SJason A. Donenfeld 	if (unlikely(wg_noise_received_with_keypair(&peer->keypairs,
346e7096c13SJason A. Donenfeld 						    PACKET_CB(skb)->keypair))) {
347e7096c13SJason A. Donenfeld 		wg_timers_handshake_complete(peer);
348e7096c13SJason A. Donenfeld 		wg_packet_send_staged_packets(peer);
349e7096c13SJason A. Donenfeld 	}
350e7096c13SJason A. Donenfeld 
351e7096c13SJason A. Donenfeld 	keep_key_fresh(peer);
352e7096c13SJason A. Donenfeld 
353e7096c13SJason A. Donenfeld 	wg_timers_any_authenticated_packet_received(peer);
354e7096c13SJason A. Donenfeld 	wg_timers_any_authenticated_packet_traversal(peer);
355e7096c13SJason A. Donenfeld 
356e7096c13SJason A. Donenfeld 	/* A packet with length 0 is a keepalive packet */
357e7096c13SJason A. Donenfeld 	if (unlikely(!skb->len)) {
358e7096c13SJason A. Donenfeld 		update_rx_stats(peer, message_data_len(0));
359e7096c13SJason A. Donenfeld 		net_dbg_ratelimited("%s: Receiving keepalive packet from peer %llu (%pISpfsc)\n",
360e7096c13SJason A. Donenfeld 				    dev->name, peer->internal_id,
361e7096c13SJason A. Donenfeld 				    &peer->endpoint.addr);
362e7096c13SJason A. Donenfeld 		goto packet_processed;
363e7096c13SJason A. Donenfeld 	}
364e7096c13SJason A. Donenfeld 
365e7096c13SJason A. Donenfeld 	wg_timers_data_received(peer);
366e7096c13SJason A. Donenfeld 
367e7096c13SJason A. Donenfeld 	if (unlikely(skb_network_header(skb) < skb->head))
368e7096c13SJason A. Donenfeld 		goto dishonest_packet_size;
369e7096c13SJason A. Donenfeld 	if (unlikely(!(pskb_network_may_pull(skb, sizeof(struct iphdr)) &&
370e7096c13SJason A. Donenfeld 		       (ip_hdr(skb)->version == 4 ||
371e7096c13SJason A. Donenfeld 			(ip_hdr(skb)->version == 6 &&
372e7096c13SJason A. Donenfeld 			 pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))))))
373e7096c13SJason A. Donenfeld 		goto dishonest_packet_type;
374e7096c13SJason A. Donenfeld 
375e7096c13SJason A. Donenfeld 	skb->dev = dev;
376e7096c13SJason A. Donenfeld 	/* We've already verified the Poly1305 auth tag, which means this packet
377e7096c13SJason A. Donenfeld 	 * was not modified in transit. We can therefore tell the networking
378e7096c13SJason A. Donenfeld 	 * stack that all checksums of every layer of encapsulation have already
379a2ec8b57SJosh Soref 	 * been checked "by the hardware" and therefore is unnecessary to check
380e7096c13SJason A. Donenfeld 	 * again in software.
381e7096c13SJason A. Donenfeld 	 */
382e7096c13SJason A. Donenfeld 	skb->ip_summed = CHECKSUM_UNNECESSARY;
383e7096c13SJason A. Donenfeld 	skb->csum_level = ~0; /* All levels */
3841a574074SJason A. Donenfeld 	skb->protocol = ip_tunnel_parse_protocol(skb);
385e7096c13SJason A. Donenfeld 	if (skb->protocol == htons(ETH_P_IP)) {
386e7096c13SJason A. Donenfeld 		len = ntohs(ip_hdr(skb)->tot_len);
387e7096c13SJason A. Donenfeld 		if (unlikely(len < sizeof(struct iphdr)))
388e7096c13SJason A. Donenfeld 			goto dishonest_packet_size;
389eebabcb2SToke Høiland-Jørgensen 		INET_ECN_decapsulate(skb, PACKET_CB(skb)->ds, ip_hdr(skb)->tos);
390e7096c13SJason A. Donenfeld 	} else if (skb->protocol == htons(ETH_P_IPV6)) {
391e7096c13SJason A. Donenfeld 		len = ntohs(ipv6_hdr(skb)->payload_len) +
392e7096c13SJason A. Donenfeld 		      sizeof(struct ipv6hdr);
393eebabcb2SToke Høiland-Jørgensen 		INET_ECN_decapsulate(skb, PACKET_CB(skb)->ds, ipv6_get_dsfield(ipv6_hdr(skb)));
394e7096c13SJason A. Donenfeld 	} else {
395e7096c13SJason A. Donenfeld 		goto dishonest_packet_type;
396e7096c13SJason A. Donenfeld 	}
397e7096c13SJason A. Donenfeld 
398e7096c13SJason A. Donenfeld 	if (unlikely(len > skb->len))
399e7096c13SJason A. Donenfeld 		goto dishonest_packet_size;
400e7096c13SJason A. Donenfeld 	len_before_trim = skb->len;
401e7096c13SJason A. Donenfeld 	if (unlikely(pskb_trim(skb, len)))
402e7096c13SJason A. Donenfeld 		goto packet_processed;
403e7096c13SJason A. Donenfeld 
404e7096c13SJason A. Donenfeld 	routed_peer = wg_allowedips_lookup_src(&peer->device->peer_allowedips,
405e7096c13SJason A. Donenfeld 					       skb);
406e7096c13SJason A. Donenfeld 	wg_peer_put(routed_peer); /* We don't need the extra reference. */
407e7096c13SJason A. Donenfeld 
408e7096c13SJason A. Donenfeld 	if (unlikely(routed_peer != peer))
409e7096c13SJason A. Donenfeld 		goto dishonest_packet_peer;
410e7096c13SJason A. Donenfeld 
411df08126eSJason A. Donenfeld 	napi_gro_receive(&peer->napi, skb);
412e7096c13SJason A. Donenfeld 	update_rx_stats(peer, message_data_len(len_before_trim));
413e7096c13SJason A. Donenfeld 	return;
414e7096c13SJason A. Donenfeld 
415e7096c13SJason A. Donenfeld dishonest_packet_peer:
416e7096c13SJason A. Donenfeld 	net_dbg_skb_ratelimited("%s: Packet has unallowed src IP (%pISc) from peer %llu (%pISpfsc)\n",
417e7096c13SJason A. Donenfeld 				dev->name, skb, peer->internal_id,
418e7096c13SJason A. Donenfeld 				&peer->endpoint.addr);
419b605d23cSEric Dumazet 	DEV_STATS_INC(dev, rx_errors);
420b605d23cSEric Dumazet 	DEV_STATS_INC(dev, rx_frame_errors);
421e7096c13SJason A. Donenfeld 	goto packet_processed;
422e7096c13SJason A. Donenfeld dishonest_packet_type:
423e7096c13SJason A. Donenfeld 	net_dbg_ratelimited("%s: Packet is neither ipv4 nor ipv6 from peer %llu (%pISpfsc)\n",
424e7096c13SJason A. Donenfeld 			    dev->name, peer->internal_id, &peer->endpoint.addr);
425b605d23cSEric Dumazet 	DEV_STATS_INC(dev, rx_errors);
426b605d23cSEric Dumazet 	DEV_STATS_INC(dev, rx_frame_errors);
427e7096c13SJason A. Donenfeld 	goto packet_processed;
428e7096c13SJason A. Donenfeld dishonest_packet_size:
429e7096c13SJason A. Donenfeld 	net_dbg_ratelimited("%s: Packet has incorrect size from peer %llu (%pISpfsc)\n",
430e7096c13SJason A. Donenfeld 			    dev->name, peer->internal_id, &peer->endpoint.addr);
431b605d23cSEric Dumazet 	DEV_STATS_INC(dev, rx_errors);
432b605d23cSEric Dumazet 	DEV_STATS_INC(dev, rx_length_errors);
433e7096c13SJason A. Donenfeld 	goto packet_processed;
434e7096c13SJason A. Donenfeld packet_processed:
435e7096c13SJason A. Donenfeld 	dev_kfree_skb(skb);
436e7096c13SJason A. Donenfeld }
437e7096c13SJason A. Donenfeld 
wg_packet_rx_poll(struct napi_struct * napi,int budget)438e7096c13SJason A. Donenfeld int wg_packet_rx_poll(struct napi_struct *napi, int budget)
439e7096c13SJason A. Donenfeld {
440e7096c13SJason A. Donenfeld 	struct wg_peer *peer = container_of(napi, struct wg_peer, napi);
441e7096c13SJason A. Donenfeld 	struct noise_keypair *keypair;
442e7096c13SJason A. Donenfeld 	struct endpoint endpoint;
443e7096c13SJason A. Donenfeld 	enum packet_state state;
444e7096c13SJason A. Donenfeld 	struct sk_buff *skb;
445e7096c13SJason A. Donenfeld 	int work_done = 0;
446e7096c13SJason A. Donenfeld 	bool free;
447e7096c13SJason A. Donenfeld 
448e7096c13SJason A. Donenfeld 	if (unlikely(budget <= 0))
449e7096c13SJason A. Donenfeld 		return 0;
450e7096c13SJason A. Donenfeld 
4518b5553acSJason A. Donenfeld 	while ((skb = wg_prev_queue_peek(&peer->rx_queue)) != NULL &&
452e7096c13SJason A. Donenfeld 	       (state = atomic_read_acquire(&PACKET_CB(skb)->state)) !=
453e7096c13SJason A. Donenfeld 		       PACKET_STATE_UNCRYPTED) {
4548b5553acSJason A. Donenfeld 		wg_prev_queue_drop_peeked(&peer->rx_queue);
455e7096c13SJason A. Donenfeld 		keypair = PACKET_CB(skb)->keypair;
456e7096c13SJason A. Donenfeld 		free = true;
457e7096c13SJason A. Donenfeld 
458e7096c13SJason A. Donenfeld 		if (unlikely(state != PACKET_STATE_CRYPTED))
459e7096c13SJason A. Donenfeld 			goto next;
460e7096c13SJason A. Donenfeld 
461a9e90d99SJason A. Donenfeld 		if (unlikely(!counter_validate(&keypair->receiving_counter,
462e7096c13SJason A. Donenfeld 					       PACKET_CB(skb)->nonce))) {
463e7096c13SJason A. Donenfeld 			net_dbg_ratelimited("%s: Packet has invalid nonce %llu (max %llu)\n",
464e7096c13SJason A. Donenfeld 					    peer->device->dev->name,
465e7096c13SJason A. Donenfeld 					    PACKET_CB(skb)->nonce,
466*78739d72SNikita Zhandarovich 					    READ_ONCE(keypair->receiving_counter.counter));
467e7096c13SJason A. Donenfeld 			goto next;
468e7096c13SJason A. Donenfeld 		}
469e7096c13SJason A. Donenfeld 
470e7096c13SJason A. Donenfeld 		if (unlikely(wg_socket_endpoint_from_skb(&endpoint, skb)))
471e7096c13SJason A. Donenfeld 			goto next;
472e7096c13SJason A. Donenfeld 
473c78a0b4aSJason A. Donenfeld 		wg_reset_packet(skb, false);
474e7096c13SJason A. Donenfeld 		wg_packet_consume_data_done(peer, skb, &endpoint);
475e7096c13SJason A. Donenfeld 		free = false;
476e7096c13SJason A. Donenfeld 
477e7096c13SJason A. Donenfeld next:
478e7096c13SJason A. Donenfeld 		wg_noise_keypair_put(keypair, false);
479e7096c13SJason A. Donenfeld 		wg_peer_put(peer);
480e7096c13SJason A. Donenfeld 		if (unlikely(free))
481e7096c13SJason A. Donenfeld 			dev_kfree_skb(skb);
482e7096c13SJason A. Donenfeld 
483e7096c13SJason A. Donenfeld 		if (++work_done >= budget)
484e7096c13SJason A. Donenfeld 			break;
485e7096c13SJason A. Donenfeld 	}
486e7096c13SJason A. Donenfeld 
487e7096c13SJason A. Donenfeld 	if (work_done < budget)
488e7096c13SJason A. Donenfeld 		napi_complete_done(napi, work_done);
489e7096c13SJason A. Donenfeld 
490e7096c13SJason A. Donenfeld 	return work_done;
491e7096c13SJason A. Donenfeld }
492e7096c13SJason A. Donenfeld 
wg_packet_decrypt_worker(struct work_struct * work)493e7096c13SJason A. Donenfeld void wg_packet_decrypt_worker(struct work_struct *work)
494e7096c13SJason A. Donenfeld {
495e7096c13SJason A. Donenfeld 	struct crypt_queue *queue = container_of(work, struct multicore_worker,
496e7096c13SJason A. Donenfeld 						 work)->ptr;
497e7096c13SJason A. Donenfeld 	struct sk_buff *skb;
498e7096c13SJason A. Donenfeld 
499e7096c13SJason A. Donenfeld 	while ((skb = ptr_ring_consume_bh(&queue->ring)) != NULL) {
500a9e90d99SJason A. Donenfeld 		enum packet_state state =
501a9e90d99SJason A. Donenfeld 			likely(decrypt_packet(skb, PACKET_CB(skb)->keypair)) ?
502e7096c13SJason A. Donenfeld 				PACKET_STATE_CRYPTED : PACKET_STATE_DEAD;
5038b5553acSJason A. Donenfeld 		wg_queue_enqueue_per_peer_rx(skb, state);
5044005f5c3SJason A. Donenfeld 		if (need_resched())
5054005f5c3SJason A. Donenfeld 			cond_resched();
506e7096c13SJason A. Donenfeld 	}
507e7096c13SJason A. Donenfeld }
508e7096c13SJason A. Donenfeld 
wg_packet_consume_data(struct wg_device * wg,struct sk_buff * skb)509e7096c13SJason A. Donenfeld static void wg_packet_consume_data(struct wg_device *wg, struct sk_buff *skb)
510e7096c13SJason A. Donenfeld {
511e7096c13SJason A. Donenfeld 	__le32 idx = ((struct message_data *)skb->data)->key_idx;
512e7096c13SJason A. Donenfeld 	struct wg_peer *peer = NULL;
513e7096c13SJason A. Donenfeld 	int ret;
514e7096c13SJason A. Donenfeld 
515e7096c13SJason A. Donenfeld 	rcu_read_lock_bh();
516e7096c13SJason A. Donenfeld 	PACKET_CB(skb)->keypair =
517e7096c13SJason A. Donenfeld 		(struct noise_keypair *)wg_index_hashtable_lookup(
518e7096c13SJason A. Donenfeld 			wg->index_hashtable, INDEX_HASHTABLE_KEYPAIR, idx,
519e7096c13SJason A. Donenfeld 			&peer);
520e7096c13SJason A. Donenfeld 	if (unlikely(!wg_noise_keypair_get(PACKET_CB(skb)->keypair)))
521e7096c13SJason A. Donenfeld 		goto err_keypair;
522e7096c13SJason A. Donenfeld 
523e7096c13SJason A. Donenfeld 	if (unlikely(READ_ONCE(peer->is_dead)))
524e7096c13SJason A. Donenfeld 		goto err;
525e7096c13SJason A. Donenfeld 
5268b5553acSJason A. Donenfeld 	ret = wg_queue_enqueue_per_device_and_peer(&wg->decrypt_queue, &peer->rx_queue, skb,
5277387943fSJason A. Donenfeld 						   wg->packet_crypt_wq);
528e7096c13SJason A. Donenfeld 	if (unlikely(ret == -EPIPE))
5298b5553acSJason A. Donenfeld 		wg_queue_enqueue_per_peer_rx(skb, PACKET_STATE_DEAD);
530e7096c13SJason A. Donenfeld 	if (likely(!ret || ret == -EPIPE)) {
531e7096c13SJason A. Donenfeld 		rcu_read_unlock_bh();
532e7096c13SJason A. Donenfeld 		return;
533e7096c13SJason A. Donenfeld 	}
534e7096c13SJason A. Donenfeld err:
535e7096c13SJason A. Donenfeld 	wg_noise_keypair_put(PACKET_CB(skb)->keypair, false);
536e7096c13SJason A. Donenfeld err_keypair:
537e7096c13SJason A. Donenfeld 	rcu_read_unlock_bh();
538e7096c13SJason A. Donenfeld 	wg_peer_put(peer);
539e7096c13SJason A. Donenfeld 	dev_kfree_skb(skb);
540e7096c13SJason A. Donenfeld }
541e7096c13SJason A. Donenfeld 
wg_packet_receive(struct wg_device * wg,struct sk_buff * skb)542e7096c13SJason A. Donenfeld void wg_packet_receive(struct wg_device *wg, struct sk_buff *skb)
543e7096c13SJason A. Donenfeld {
544e7096c13SJason A. Donenfeld 	if (unlikely(prepare_skb_header(skb, wg) < 0))
545e7096c13SJason A. Donenfeld 		goto err;
546e7096c13SJason A. Donenfeld 	switch (SKB_TYPE_LE32(skb)) {
547e7096c13SJason A. Donenfeld 	case cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION):
548e7096c13SJason A. Donenfeld 	case cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE):
549e7096c13SJason A. Donenfeld 	case cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE): {
550fb32f4f6SJason A. Donenfeld 		int cpu, ret = -EBUSY;
551fb32f4f6SJason A. Donenfeld 
552fb32f4f6SJason A. Donenfeld 		if (unlikely(!rng_is_initialized()))
553fb32f4f6SJason A. Donenfeld 			goto drop;
554fb32f4f6SJason A. Donenfeld 		if (atomic_read(&wg->handshake_queue_len) > MAX_QUEUED_INCOMING_HANDSHAKES / 2) {
555fb32f4f6SJason A. Donenfeld 			if (spin_trylock_bh(&wg->handshake_queue.ring.producer_lock)) {
556fb32f4f6SJason A. Donenfeld 				ret = __ptr_ring_produce(&wg->handshake_queue.ring, skb);
557fb32f4f6SJason A. Donenfeld 				spin_unlock_bh(&wg->handshake_queue.ring.producer_lock);
558fb32f4f6SJason A. Donenfeld 			}
559fb32f4f6SJason A. Donenfeld 		} else
560fb32f4f6SJason A. Donenfeld 			ret = ptr_ring_produce_bh(&wg->handshake_queue.ring, skb);
561fb32f4f6SJason A. Donenfeld 		if (ret) {
562fb32f4f6SJason A. Donenfeld 	drop:
563e7096c13SJason A. Donenfeld 			net_dbg_skb_ratelimited("%s: Dropping handshake packet from %pISpfsc\n",
564e7096c13SJason A. Donenfeld 						wg->dev->name, skb);
565e7096c13SJason A. Donenfeld 			goto err;
566e7096c13SJason A. Donenfeld 		}
567886fcee9SJason A. Donenfeld 		atomic_inc(&wg->handshake_queue_len);
568886fcee9SJason A. Donenfeld 		cpu = wg_cpumask_next_online(&wg->handshake_queue.last_cpu);
569886fcee9SJason A. Donenfeld 		/* Queues up a call to packet_process_queued_handshake_packets(skb): */
570e7096c13SJason A. Donenfeld 		queue_work_on(cpu, wg->handshake_receive_wq,
571886fcee9SJason A. Donenfeld 			      &per_cpu_ptr(wg->handshake_queue.worker, cpu)->work);
572e7096c13SJason A. Donenfeld 		break;
573e7096c13SJason A. Donenfeld 	}
574e7096c13SJason A. Donenfeld 	case cpu_to_le32(MESSAGE_DATA):
575e7096c13SJason A. Donenfeld 		PACKET_CB(skb)->ds = ip_tunnel_get_dsfield(ip_hdr(skb), skb);
576e7096c13SJason A. Donenfeld 		wg_packet_consume_data(wg, skb);
577e7096c13SJason A. Donenfeld 		break;
578e7096c13SJason A. Donenfeld 	default:
5792b8765c5SJason A. Donenfeld 		WARN(1, "Non-exhaustive parsing of packet header lead to unknown packet type!\n");
580e7096c13SJason A. Donenfeld 		goto err;
581e7096c13SJason A. Donenfeld 	}
582e7096c13SJason A. Donenfeld 	return;
583e7096c13SJason A. Donenfeld 
584e7096c13SJason A. Donenfeld err:
585e7096c13SJason A. Donenfeld 	dev_kfree_skb(skb);
586e7096c13SJason A. Donenfeld }
587