xref: /linux/drivers/net/ovpn/pktid.h (revision 8534731dbf2d52a539b94defd06d2a8d3514aacb)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*  OpenVPN data channel offload
3  *
4  *  Copyright (C) 2020-2025 OpenVPN, Inc.
5  *
6  *  Author:	Antonio Quartulli <antonio@openvpn.net>
7  *		James Yonan <james@openvpn.net>
8  */
9 
10 #ifndef _NET_OVPN_OVPNPKTID_H_
11 #define _NET_OVPN_OVPNPKTID_H_
12 
13 #include "proto.h"
14 
15 /* If no packets received for this length of time, set a backtrack floor
16  * at highest received packet ID thus far.
17  */
18 #define PKTID_RECV_EXPIRE (30 * HZ)
19 
20 /* Packet-ID state for transmitter */
21 struct ovpn_pktid_xmit {
22 	atomic_t seq_num;
23 };
24 
25 /* replay window sizing in bytes = 2^REPLAY_WINDOW_ORDER */
26 #define REPLAY_WINDOW_ORDER 8
27 
28 #define REPLAY_WINDOW_BYTES BIT(REPLAY_WINDOW_ORDER)
29 #define REPLAY_WINDOW_SIZE  (REPLAY_WINDOW_BYTES * 8)
30 #define REPLAY_INDEX(base, i) (((base) + (i)) & (REPLAY_WINDOW_SIZE - 1))
31 
32 /* Packet-ID state for receiver.
33  * Other than lock member, can be zeroed to initialize.
34  */
35 struct ovpn_pktid_recv {
36 	/* "sliding window" bitmask of recent packet IDs received */
37 	u8 history[REPLAY_WINDOW_BYTES];
38 	/* bit position of deque base in history */
39 	unsigned int base;
40 	/* extent (in bits) of deque in history */
41 	unsigned int extent;
42 	/* expiration of history in jiffies */
43 	unsigned long expire;
44 	/* highest sequence number received */
45 	u32 id;
46 	/* highest time stamp received */
47 	u32 time;
48 	/* we will only accept backtrack IDs > id_floor */
49 	u32 id_floor;
50 	unsigned int max_backtrack;
51 	/* protects entire pktd ID state */
52 	spinlock_t lock;
53 };
54 
55 /* Get the next packet ID for xmit */
56 static inline int ovpn_pktid_xmit_next(struct ovpn_pktid_xmit *pid, u32 *pktid)
57 {
58 	const u32 seq_num = atomic_fetch_add_unless(&pid->seq_num, 1, 0);
59 	/* when the 32bit space is over, we return an error because the packet
60 	 * ID is used to create the cipher IV and we do not want to reuse the
61 	 * same value more than once
62 	 */
63 	if (unlikely(!seq_num))
64 		return -ERANGE;
65 
66 	*pktid = seq_num;
67 
68 	return 0;
69 }
70 
71 /* Write 12-byte AEAD IV to dest */
72 static inline void ovpn_pktid_aead_write(const u32 pktid,
73 					 const u8 nt[],
74 					 unsigned char *dest)
75 {
76 	*(__force __be32 *)(dest) = htonl(pktid);
77 	BUILD_BUG_ON(4 + OVPN_NONCE_TAIL_SIZE != OVPN_NONCE_SIZE);
78 	memcpy(dest + 4, nt, OVPN_NONCE_TAIL_SIZE);
79 }
80 
81 void ovpn_pktid_xmit_init(struct ovpn_pktid_xmit *pid);
82 void ovpn_pktid_recv_init(struct ovpn_pktid_recv *pr);
83 
84 int ovpn_pktid_recv(struct ovpn_pktid_recv *pr, u32 pkt_id, u32 pkt_time);
85 
86 #endif /* _NET_OVPN_OVPNPKTID_H_ */
87