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 */
ovpn_pktid_xmit_next(struct ovpn_pktid_xmit * pid,u32 * pktid)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 */
ovpn_pktid_aead_write(const u32 pktid,const u8 nt[],unsigned char * 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