[Openvpn-devel,RFC,net-next,00/14] ovpn: add epoch data channel keys

Message ID cover.1782919654.git.ralf@mandelbit.com
Headers
Series ovpn: add epoch data channel keys |

Message

Ralf Lici July 1, 2026, 3:43 p.m. UTC
  Hi,

This series adds support for OpenVPN epoch data channel keys to the ovpn
kernel module.

Epoch keys are described in the OpenVPN wire protocol draft:

  https://openvpn.github.io/openvpn-rfc/openvpn-wire-protocol.html#section-7.2
  https://openvpn.github.io/openvpn-rfc/openvpn-wire-protocol.html#section-7.5

At a high level, epoch keys allow OpenVPN to rotate data-channel AEAD
keys without requiring a full userspace renegotiation whenever a
data-channel key reaches a usage or packet-ID limit. Instead of
installing one concrete AEAD key and nonce tail per direction, userspace
installs per-direction epoch PRKs. The kernel derives the concrete AEAD
key and implicit IV for each epoch using the OpenVPN HKDF-Expand-Label
construction, and can then move between pre-derived epochs in the data
path.

The DATA_V2 opcode is still used, but epoch packets use the extended
packet ID layout defined by the draft: a 64-bit packet ID carrying a
16-bit epoch and a 48-bit sequence number, an XOR-based IV construction,
and the AEAD tag at the end of the packet.

The series is structured in three parts. The first adds packet-ID and
AES-GCM usage-limit accounting. TX now notifies userspace before
packet-ID wrap or AES-GCM hard exhaustion, and stops before the hard
limit. RX accounts authenticated packets and reports threshold crossings
without dropping packets solely because the peer crossed a local usage
threshold. The series also limits AEAD decrypt verification failures.

The middle part moves per-direction key state into explicit key
contexts, makes those contexts refcounted for async crypto completion,
and makes packet layout handling explicit. This keeps the epoch
implementation from adding more special cases to the direct-key path.

The epoch implementation keeps current TX/RX key contexts, one retiring
RX key for reordered packets, and bounded rings of future TX/RX keys. TX
rotates to a future key before hard packet-ID or AEAD usage exhaustion,
and also rotates on the soft AEAD threshold. RX authenticates a packet
with a future key before promoting that key to current, then refills
consumed future-key slots from workqueue context.

Selftest coverage is intentionally limited: the tests install epoch keys
and verify steady-state UDP/TCP packet layout, including the epoch field
in captured DATA_V2 packets. They do not exercise rotation or future-key
refill because the production thresholds are cryptographic safety
limits, so reaching them needs an enormous packet-ID/AEAD budget and
lowering them would mean test-only knobs in security-sensitive data-path
policy.

Thanks,

Ralf Lici
Mandelbit Srl

---

Ralf Lici (14):
  ovpn: prepare packet ID state for usage limits
  ovpn: enforce AES-GCM usage limits
  ovpn: limit AEAD decrypt verification failures
  ovpn: make direct-key AEAD layout explicit
  ovpn: move key slot lifecycle out of AEAD
  ovpn: move direct key state into key contexts
  ovpn: make key contexts refcounted
  ovpn: generalize AEAD packet ID handling
  ovpn: add epoch key derivation support
  ovpn: add epoch key slot state
  ovpn: handle epoch AEAD packet format
  ovpn: rotate epoch data keys
  ovpn: accept epoch keys from netlink
  selftests: ovpn: exercise epoch keys

 Documentation/netlink/specs/ovpn.yaml         |  31 +
 drivers/net/Kconfig                           |   2 +
 drivers/net/ovpn/Makefile                     |   2 +
 drivers/net/ovpn/crypto.c                     |   7 +-
 drivers/net/ovpn/crypto.h                     | 121 +++-
 drivers/net/ovpn/crypto_aead.c                | 584 +++++++++++-------
 drivers/net/ovpn/crypto_aead.h                |   9 +-
 drivers/net/ovpn/crypto_epoch.c               | 200 ++++++
 drivers/net/ovpn/crypto_epoch.h               |  54 ++
 drivers/net/ovpn/crypto_key.c                 | 522 ++++++++++++++++
 drivers/net/ovpn/crypto_limits.h              | 125 ++++
 drivers/net/ovpn/io.c                         | 254 +++++++-
 drivers/net/ovpn/io.h                         |   8 +-
 drivers/net/ovpn/netlink-gen.c                |   9 +-
 drivers/net/ovpn/netlink-gen.h                |   3 +-
 drivers/net/ovpn/netlink.c                    | 112 +++-
 drivers/net/ovpn/pktid.c                      |  13 +-
 drivers/net/ovpn/pktid.h                      | 164 ++++-
 drivers/net/ovpn/proto.h                      |  38 ++
 drivers/net/ovpn/skb.h                        |   2 +
 include/uapi/linux/ovpn.h                     |  11 +
 tools/testing/selftests/net/ovpn/Makefile     |   2 +
 tools/testing/selftests/net/ovpn/common.sh    |  30 +-
 tools/testing/selftests/net/ovpn/ovpn-cli.c   | 116 +++-
 .../selftests/net/ovpn/test-epoch-tcp.sh      |  11 +
 .../testing/selftests/net/ovpn/test-epoch.sh  |  10 +
 tools/testing/selftests/net/ovpn/test-mark.sh |   3 +-
 tools/testing/selftests/net/ovpn/test.sh      |  12 +-
 28 files changed, 2140 insertions(+), 315 deletions(-)
 create mode 100644 drivers/net/ovpn/crypto_epoch.c
 create mode 100644 drivers/net/ovpn/crypto_epoch.h
 create mode 100644 drivers/net/ovpn/crypto_key.c
 create mode 100644 drivers/net/ovpn/crypto_limits.h
 create mode 100755 tools/testing/selftests/net/ovpn/test-epoch-tcp.sh
 create mode 100755 tools/testing/selftests/net/ovpn/test-epoch.sh


base-commit: 903db046d5579bef0ea699eae4b279dd6455fc9f