However, this fails to account for the fact that the STEK has likely already been in use for some amount of time.
Consider the following scenario
encrypt_lifetime = 1000, decrypt_lifetime = 1000
time=0: stek added to s2n-tls
time=500: a client handshakes with the server
time=500: the client receives a session ticket with session ticket lifetime set to 2000.
time=2000: the stek is expired by s2n-tls.
time=2100: the client attempts resumption, which is expects to succeed, because only 1600 seconds have elapsed
time=2100: the resumption attempt fails, because the STEK has expired.
While the above scenario is simplest to understand, the real-world scenario is a bit more complicated.
s2n-tls will choose a STEK based upon the remaining encryption lifetime of the key. The maximum probability of selection occurs once encryption_lifetime / 2 has elapsed.
https://github.com/aws/s2n-tls/blob/7ec1446ac1d836cefb6a5363b9bfb438a4faa792/tls/s2n_resume.c#L656-L665
Therefore the expected key material lifetime for a session_ticket is encryption_lifetime / 2 + decryption_lifetime, but the session_ticket_lifetime will always be set to encryption_lifetime + decryption_lifetime.
I wrote a simulation to confirm this behavior, which can be viewed here
It shows the following output.
2024-06-04T23:37:43.655801Z ERROR node{name="client"}: session_resumption: 251: Ticket supposed to be valid for 360s, only 310.017s elapsed
2024-06-04T23:37:43.664387Z DEBUG node{name="client"}: session_resumption: 110: stek name is 7
2024-06-04T23:37:44.395429Z ERROR node{name="client"}: session_resumption: 251: Ticket supposed to be valid for 360s, only 309.867s elapsed
2024-06-04T23:37:44.399744Z DEBUG node{name="client"}: session_resumption: 110: stek name is 8
2024-06-04T23:37:45.146100Z ERROR node{name="client"}: session_resumption: 251: Ticket supposed to be valid for 360s, only 309.916s elapsed
2024-06-04T23:37:45.149128Z DEBUG node{name="client"}: session_resumption: 110: stek name is 9
2024-06-04T23:37:45.892796Z DEBUG node{name="client"}: session_resumption: 110: stek name is 9
2024-06-04T23:37:46.627179Z INFO node{name="client"}: session_resumption: 273: session resumption attempts: 29, successes: 10
Solution:
Option 1: STEK lifetime calculation
s2n_generate_ticket_lifetime should be made aware of the specific STEK that the ticket is being encrypted under. Then the actual ticket lifetime could be accurately set to the remaining lifetime of the STEK.
Option 2: Bigger Overhaul
We don't have great documentation around it, but I am a little dubious of the "weighted key selection" logic. To get an effective lifetime of $TARGET, the STEK lifetime has to be set strictly larger than $TARGET, which is non-ideal because it forces sensitive cryptographic secrets to be kept around longer.
This might just be an opportunity to do a larger overhaul of our STEK selection logic 😄 .
Requirements / Acceptance Criteria:
s2n-tls should return session tickets with accurate session ticket lifetimes.
Problem:
s2n-tls configures STEK lifetime through two parameters
The session ticket lifetime is then set to the sum of these values: https://github.com/aws/s2n-tls/blob/7ec1446ac1d836cefb6a5363b9bfb438a4faa792/tls/s2n_server_new_session_ticket.c#L193-L199
However, this fails to account for the fact that the STEK has likely already been in use for some amount of time.
Consider the following scenario
encrypt_lifetime = 1000
,decrypt_lifetime = 1000
time=0
: stek added to s2n-tlstime=500
: a client handshakes with the servertime=500
: the client receives a session ticket with session ticket lifetime set to2000
.time=2000
: the stek is expired by s2n-tls.time=2100
: the client attempts resumption, which is expects to succeed, because only1600
seconds have elapsedtime=2100
: the resumption attempt fails, because the STEK has expired.While the above scenario is simplest to understand, the real-world scenario is a bit more complicated.
s2n-tls will choose a STEK based upon the remaining encryption lifetime of the key. The maximum probability of selection occurs once
encryption_lifetime / 2
has elapsed. https://github.com/aws/s2n-tls/blob/7ec1446ac1d836cefb6a5363b9bfb438a4faa792/tls/s2n_resume.c#L656-L665 Therefore the expected key material lifetime for a session_ticket isencryption_lifetime / 2 + decryption_lifetime
, but thesession_ticket_lifetime
will always be set toencryption_lifetime + decryption_lifetime
.I wrote a simulation to confirm this behavior, which can be viewed here
It shows the following output.
Solution:
Option 1: STEK lifetime calculation
s2n_generate_ticket_lifetime
should be made aware of the specific STEK that the ticket is being encrypted under. Then the actual ticket lifetime could be accurately set to the remaining lifetime of the STEK.Option 2: Bigger Overhaul
We don't have great documentation around it, but I am a little dubious of the "weighted key selection" logic. To get an effective lifetime of
$TARGET
, the STEK lifetime has to be set strictly larger than$TARGET
, which is non-ideal because it forces sensitive cryptographic secrets to be kept around longer.This might just be an opportunity to do a larger overhaul of our STEK selection logic 😄 .
Requirements / Acceptance Criteria:
s2n-tls should return session tickets with accurate session ticket lifetimes.