It also changes that payloads are built before installing the CHILD_SA
on the responder, that is, the KE payload is generated before keys are
derived, so that key_exchange_t::get_public_key() is called before
get_shared_secret(), or its internal equivalent, which could be relevant
for KE implementations that want to ensure that the key can't be
accessed again after the key derivation.
Initially, this is handled with a key derivation for each
IKE_INTERMEDIATE exchange. When rekeying, the keys are derived only
once all IKE_FOLLOWUP_KE exchanges are done.
The message ID of the first IKE_AUTH exchange is a safe-guard against
potential truncation attacks if IKE_INTERMEDIATE exchanges are not used
for multiple key exchanges but some other future use where the number of
exchanges might not depend on the selected proposal.
We currently only support these exchanges for additional key exchanges,
so once we have the final keys derived and the ike-init task is removed,
we don't expect any more of them.
The IKE_SA might be busy with a different task while a request to
terminate it is getting queued, we don't want to use such an IKE_SA to
initiate new CHILD_SAs as these tasks will get lost once the IKE_SA is
terminated.
CHILD_SA unique identifier allocation starts at 1. If the counter overflows,
a unique ID of 0 is assigned to an CHILD_SA, which may have unclear
consequences.
Overflowing the unique ID counter is theoretical for most setups, but on
a Gateway terminating 100'000 tunnels and rekeying CHILD_SAs every 60s
overflows the counter after a month uptime. So avoid a 0 unique identifier
by using ref_get_nonzero().
IKE_SA unique identifier allocation starts at 1. If the counter overflows,
a unique ID of 0 is assigned to an IKE_SA, which may have unclear consequences.
Overflowing the unique ID counter is theoretical for most setups, but on
a Gateway terminating 100'000 tunnels and rekeying the IKE_SA every 60s
overflows the counter after a month uptime. So avoid a 0 unique identifier
by using ref_get_nonzero().
Maintaining the reqid when recreating a CHILD_SA from scratch night not
strictly be necessary as we usually don't have to replace any temporary
states in the kernel. However, there could be concurrent acquires that
might actually make it necessary (we use the reqid to keep track of
acquires and it's also part of the duplicate check).
Keeping a reference ensures that if the old SA expires before the new
one is installed, the previous reqid isn't reallocated to a concurrently
established CHILD_SA with different selectors.
The reference is kept until the reqid is either confirmed (i.e.
re-allocated) or replaced by a different reqid, which happens only once
we know the final traffic selectors, or the SA is destroyed without
installing it.
Since the referenced commit, the state switch to IKE_ESTABLISHED doesn't
happen immediately after completing the authentication but only after
the remaining tasks have finished. Due to that redirects during IKE_AUTH
were treated like those during IKE_SA_INIT causing the IKE_SA and task
manager to get reset. However, unlike the ike-init task, the ike-auth
task returned SUCCESS and, therefore, got destroyed, while a different
task was removed from the array that was modified during the reset.
This later caused a dereference of the freed ike-auth task and a crash.
Fixes: 5ce1c91b58 ("ikev2: Trigger ike_updown() event after all IKE-specific tasks ran")
This works around an issue that occurs when recreating an IKE_SA with
multiple CHILD_SAs that use dynamically allocated reqids.
We currently try to preserve the reqid when reestablishing, so the
create-child task gets the reqid of the previous CHILD_SA and will try
to reallocate that once the CHILD_SA is installed. Before that, the old
CHILD_SA is destroyed and the reqid is released and added to the array
of reqids to get reused. However, because of the reverse order used here,
the first reqid in the array is the one of the last CHILD_SA.
So it can happen that a newly created CHILD_SA gets a reqid reassigned
that a later CHILD_SA will then also claim for itself and get assigned
because an entry with that reqid exists. So multiple CHILD_SAs with
different traffic selectors could then share the same reqid.
References strongswan/strongswan#1855
We track all IKE_SA_INIT requests as half-open IKE_SAs but didn't
correctly untrack them if their message ID or responder SPI was non-zero.
References strongswan/strongswan#1775
Fixes: b866ee88bf ("ike: Track unprocessed initial IKE messages like half-open IKE_SAs")
As specified in RFC 7296, section 2.25:
The SA that the initiator attempted to rekey is indicated by the SPI
field in the Notify payload, which is copied from the SPI field in
the REKEY_SA notification.
So we copy that and the protocol verbatim.
The calculation of the timeout is also shared now and the total
timeout in seconds is corrected in case retransmit_base is <= 1.
This could make it easier in the future to apply different retransmission
settings to messages/exchanges.