git: 81877287a99e - main - if_ovpn: ensure we never re-use sequence numbers
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 23 May 2023 14:12:58 UTC
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=81877287a99e55b47a7045efa76945f368e90917
commit 81877287a99e55b47a7045efa76945f368e90917
Author: Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2023-05-20 17:43:49 +0000
Commit: Kristof Provost <kp@FreeBSD.org>
CommitDate: 2023-05-23 14:11:26 +0000
if_ovpn: ensure we never re-use sequence numbers
if_ovpn already notified userpsace when there was a risk of sequence
number re-use, but it trusted userspace to actually rotate the key.
Convert the internal sequence number counter to 64 bits so we can detect
overflows and then refuse to send packets.
Event: BSDCan 2023
Reviewed by: Leon Dang <ldang@netgate.com>
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D40187
---
sys/net/if_ovpn.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c
index 3aec073c052e..49c8c8e9677a 100644
--- a/sys/net/if_ovpn.c
+++ b/sys/net/if_ovpn.c
@@ -93,7 +93,7 @@ struct ovpn_kkey_dir {
* strictly higher than this.
*/
uint32_t rx_seq;
- uint32_t tx_seq;
+ uint64_t tx_seq;
/* Seen packets, relative to rx_seq. bit(0) will always be 0. */
uint64_t rx_window;
@@ -1830,6 +1830,7 @@ ovpn_transmit_to_peer(struct ifnet *ifp, struct mbuf *m,
struct ovpn_softc *sc;
struct cryptop *crp;
uint32_t af, seq;
+ uint64_t seq64;
size_t len, ovpn_hdr_len;
int tunnel_len;
int ret;
@@ -1873,11 +1874,24 @@ ovpn_transmit_to_peer(struct ifnet *ifp, struct mbuf *m,
ohdr->opcode |= key->peerid;
ohdr->opcode = htonl(ohdr->opcode);
- seq = atomic_fetchadd_32(&peer->keys[OVPN_KEY_SLOT_PRIMARY].encrypt->tx_seq, 1);
- if (seq == OVPN_SEQ_ROTATE)
+ seq64 = atomic_fetchadd_64(&peer->keys[OVPN_KEY_SLOT_PRIMARY].encrypt->tx_seq, 1);
+ if (seq64 == OVPN_SEQ_ROTATE) {
ovpn_notify_key_rotation(sc, peer);
+ } else if (seq64 > UINT32_MAX) {
+ /* We've wrapped, give up on this packet. */
+ if (_ovpn_lock_trackerp != NULL)
+ OVPN_RUNLOCK(sc);
+ OVPN_COUNTER_ADD(sc, nomem_data_pkts_out, 1);
+
+ /* Let's avoid (very unlikely, but still) wraparounds of the
+ * 64-bit counter taking us back to 0. */
+ atomic_set_64(&peer->keys[OVPN_KEY_SLOT_PRIMARY].encrypt->tx_seq,
+ UINT32_MAX);
+
+ return (ENOBUFS);
+ }
- seq = htonl(seq);
+ seq = htonl(seq64 & UINT32_MAX);
ohdr->seq = seq;
OVPN_PEER_COUNTER_ADD(peer, pkt_out, 1);