Support for Multiple Key Exchanges (RFC 9370 and RFC 9242)
Support for multiple IKEv2 key exchanges (RFC 9370) has been added, which allows to use up to seven additional key exchanges (classic or post-quantum) to establish key material when negotiating IKE and/or Child SAs.
Work on this started over six years ago and went through multiple iterations. First with our own protocol, then various variations of extensions that were developed in IETF's ipsecme working group. The standardized protocol uses the new IKE_INTERMEDIATE
exchanges (RFC 9242) to transport additional KE payloads between the IKE_SA_INIT
and IKE_AUTH
exchanges. To create additional Child SAs and to rekey IKE and Child SAs using multiple key exchanges, new IKE_FOLLOWUP_KE
exchanges are used for the additional KE payloads.
The reason for the new IKEv2 exchange types is the size of the KE payloads, in particular, for post-quantum key exchange methods. Because IKEv2's fragmentation extension (RFC 7383) only works with encrypted messages, the initial IKE_SA_INIT
messages can't be fragmented. So the initial key exchange (classic and usually small) is used to establish keys to encrypt and fragment the following IKE_INTERMEDIATE
exchange that transports the KE payload for the next negotiated key exchange method. New keys are derived after each exchange, based on the previous key material and the one currently established.
Similarly, after a CREATE_CHILD_SA
exchange, the IKE_FOLLOWUP_KE
exchanges are used to transport KE payloads for additional key exchange methods that were negotiated. While CREATE_CHILD_SA
messages can already be fragemented, this reduces the number of fragments per message (as compared to sending all required KE payloads in a single CREATE_CHILD_SA
message). This is useful because IKEv2 fragmentation does not acknowledge individual fragments, that is, all fragments of a message have to be retransmitted if even one gets lost. Unlike the initial key derivation, where keys are derived after each exchange, keys for new and rekeyed SAs are only derived once all of these IKE_FOLLOWUP_KE
exchanges are done.
In proposals, additional key exchange methods are configured with a keX_
prefix, where X
is a number between 1 and 7. So a total of eight key exchanges may be used for each SA (not that this would be necessary in practice). For example, curve25519-ke1_mlkem786
adds ML-KEM-786 as additional key exchange method after the initial key exchange with Curve25519. This works with any key exchange method, whether post-quantum or classic Diffie-Hellman. As with any algorithm in proposals, peers have to agree on a KE method for each round unless no algorithms are defined by both or keX_none
is configured to make a particular round explicitly optional (there can be gaps, so it's technically fine to negotiate e.g. curve25519-ke7_mlkem786
).
Support for ML-KEM (FIPS 203)
The Module-Lattice-Based Key-Encapsulation Mechanism (ML-KEM, FIPS 203) is a mechanism to establish a shared secret that, at present, is believed to be secure even against adversaries who possess a quantum computer. Support for it has been added via Botan 3.6.0+ (botan
plugin, test scenario), wolfSSL 5.7.4+ (wolfssl
plugin, test scenario), AWS-LC 1.37.0+ (openssl
plugin), and the new ml
plugin (test scenario).
Using such a post-quantum algorithm to establish a shared secret can make sense even now, i.e. when no quantum computers powerful enough to attack classic (EC)DH algorithms are known to exist, to guard against harvest now, decrypt later type of scenarios.
The keywords for ML-KEM-512 (security strength category 1), ML-KEM-786 (3), ML-KEM-1024 (5) are mlkem512
, mlkem786
and mlkem1024
, respectively. NIST recommends using ML-KEM-768 as the default parameter set, as it "provides a large security
margin at a reasonable performance cost." But also states that "in cases where this is impractical or even higher
security is required, other parameter sets may be used" (see section 8 in FIPS 203 for details).
Note that KEMs work quite differently than classic (EC)DH mechanisms. Instead of both peers sharing a public component that each peer combines with an individual secret component to derive a common shared secret, the initiator of a KEM exchange generates a key pair and shares the public key with the peer, who in turn uses it to encapsulate a randomly generated shared secret that the initiator can decapsulate with its private key. To learn how KEMs may be impleented in a custom plugin, please refer to the documentation of the key_exchange_method_t
interface.
Plugin and Configuration Changes
The legacy stroke
plugin is no longer enabled by default and must be enabled explicitly.
The openssl
plugin is now enabled by default. Because of its nearly all-encompassing capabilities, the following crypto plugins are no longer enabled by default: aes
, curve25519
, des
, fips-prf
, gmp
, hmac
, md5
, pkcs12
, rc2
, sha1
, sha2
.
The following deprecated plugins have been removed: bliss
(signature scheme), newhope
(key exchange method), ntru
(key exchange method).
The charon.make_before_break
setting is now enabled by default, which causes the initiation of IKEv2 reauthentication with a make-before-break instead of a break-before-make scheme. Make-before-break creates overlapping IKE and Child SAs during reauthentication by first recreating all SAs before deleting the old ones. This behavior can be beneficial to avoid connectivity gaps during reauthentication (but unlike rekeying still not completely without interruption). However, it requires support for overlapping SAs by the peer. strongSwan can handle such overlapping SAs since version 5.3.0. Note that reauthentication is disabled by default when using swanctl.conf
(reauth_time
setting), but enabled by default when using the legacy ipsec.conf
(reauth
setting).
Improved Child SA Rekey Collision Handling
Handling of Child SA rekey collisions has been improved, which makes Child SAs properly trackable via child_rekey()
hook.
In previous releases, the winner of a rekey collision always triggered the child_rekey()
event once when creating the redundant SA on behalf of the peer in the passive child-rekey task and then a second time when creating the winning SA in the active task. However, both calls passed the replaced Child SA as old
to the hook. This made tracking Child SAs impossible because there was no transition from the redundant SA (passed as new
) of the first event call to the winning SA of the second call. Of course, when the second event was triggered, the redundant SA might not have existed anymore because the peer is expected to delete it, which could happen before the CREATE_CHILD_SA
response arrives at the initiator.
It is now ensured that the child_rekey()
event is triggered in a way that makes the Child SAs trackable in all reasonable (and even some unreasonable) scenarios. The event is generally only triggered once, after installing the outbound SA for the new/winning Child SA. This can be when processing the CREATE_CHILD_SA
in the active child-rekey task, or when processing the DELETE
for the old SA in a passive child-delete task. There are some cases where the event is still triggered twice, but it is now ensured that listeners can properly transition to the winning SA.
Some corner cases are now also handled correctly e.g. the one mentioned above if a peer's DELETE
arrives before its CREATE_CHILD_SA
response that creates the SA in the first place. Also handled properly are responders of rekeyings that incorrectly send a DELETE
for the old Child SA (previously, this caused both, the new and the old SA, to get deleted).
Other Notable Features and Fixes
AF_VSOCK
sockets can be used on Linux to communicate with a daemon that runs in a VM (e.g. via thevici
plugin).- The file logger can optionally log messages as JSON objects (see the docs for details), and can add timestamps in microseconds via the new
time_precision
setting. - The behavior when reloading or unloading connections that include
start
in theirstart_action
has been improved. - If no identity is configured but a certificate is available, the subject DN is used instead of the IP address.
- The NetworkManager plugin (
charon-nm
) now uses a different routing table than the regular IKE daemon to avoid conflicts if both are running. - The
cert-enroll
script now supports three generations of CA certificates. - TUN devices can properly handle IPv6 addresses and routes via them are now correctly installed on FreeBSD.