-
Notifications
You must be signed in to change notification settings - Fork 717
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: calculation of session ticket age #5001
base: main
Are you sure you want to change the base?
Conversation
* checked the chosen psk keying material expiration.
Why not? |
I will do it in this PR. |
* add reference check for conn->config * makes the s2n_generate_ticket_lifetime function more readable * fix the chosen_psk logic
@@ -886,6 +888,11 @@ S2N_RESULT s2n_resume_encrypt_session_ticket(struct s2n_connection *conn, struct | |||
|
|||
RESULT_GUARD_POSIX(s2n_aes256_gcm.io.aead.encrypt(&aes_ticket_key, &iv, &aad_blob, &state_blob, &state_blob)); | |||
|
|||
/* Store this key timestamp for session ticket logic */ | |||
if (key_intro_time) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly it might be better to just put this value on the ticket_fields struct as well. Doesn't really make sense to pass this by parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. It makes sense to put key_intro_time
into the ticket field. This information is supposed to be a part of the ticket field information. Doing this also improve the readability of the code, since it doesn't add additional parameter.
RESULT_ENSURE_MUT(ticket_lifetime); | ||
|
||
uint64_t ticket_key_age_in_nanos = current_time - key_intro_time; | ||
|
||
uint32_t key_lifetime_in_secs = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you pull out the calculation of the key's remaining lifetime? It's still really hard to read right now. I think what would help is if you did:
- Calculate ticket_key_age in sec
- Calculate key_lifetime in sec
- Then calculate remaining_key_lifetime = key_lifetime - ticket_key_age.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to straight up calculate those variables in seconds, since that might make the calculation a bit inaccurate: we are doing integer division with ONE_SEC_IN_NANOS
:
s2n-tls/tls/s2n_server_new_session_ticket.c
Lines 198 to 200 in e79b1b9
uint32_t key_lifetime_in_secs = | |
(conn->config->encrypt_decrypt_key_lifetime_in_nanos + conn->config->decrypt_key_lifetime_in_nanos) / ONE_SEC_IN_NANOS; | |
uint32_t session_lifetime_in_secs = conn->config->session_state_lifetime_in_nanos / ONE_SEC_IN_NANOS; |
Some details might be missed if we first convert nanos to secs and then do the calculation.
I would follow your thoughts and calculate it like this:
- Calculate ticket_key_age in nanos
- Calculate key_lifetime in nanos
- Calculate remaining_key_lifetime_in_sec = (key_lifetime - ticket_key_age) / ONE_SEC_IN_NANOS
- Calculate remaining_psk_keying_material_lifetime_in_sec
- Use
MIN
to find the minimum among them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think that approach will work. I'm basically just think you need to separate out the calculations in a way that's easy to follow.
RESULT_GUARD(s2n_generate_ticket_lifetime(conn, &ticket_lifetime_in_secs)); | ||
RESULT_GUARD_POSIX(s2n_stuffer_write_uint32(output, ticket_lifetime_in_secs)); | ||
/* key_intro_time is not yet retrieved, so skip this part and write it when the data is available */ | ||
uint32_t ticket_lifetime_write_cursor = output->write_cursor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe let's try doing uint8_t *lifetime_ptr = s2n_stuffer_raw_write(output, sizeof(uint32_t)
instead. We want to avoid messing directly with write_cursors if we can.
uint32_t session_lifetime_in_secs = conn->config->session_state_lifetime_in_nanos / ONE_SEC_IN_NANOS; | ||
struct s2n_psk *chosen_psk = conn->psk_params.chosen_psk; | ||
uint32_t psk_keying_material_lifetime_in_secs = UINT32_MAX; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, not really following this. Why are you setting it to UINT32_MAX?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally, I want to set UINT32_MAX as the default for the PSK keying material lifetime. If PSK doesn't exist, then it wouldn't be updated. Subsequently, it will always be larger than the rest variables. This method is hard to understand, and I will improve this logic.
@@ -190,21 +193,31 @@ S2N_RESULT s2n_tls13_server_nst_send(struct s2n_connection *conn, s2n_blocked_st | |||
*# unsigned integer in network byte order from the time of ticket | |||
*# issuance. | |||
**/ | |||
static S2N_RESULT s2n_generate_ticket_lifetime(struct s2n_connection *conn, uint32_t *ticket_lifetime) | |||
static S2N_RESULT s2n_generate_ticket_lifetime(struct s2n_connection *conn, uint64_t key_intro_time, uint64_t current_time, uint32_t *ticket_lifetime) | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note for this entire function, if you're doing any type of subtraction, you should assert you're not underflowing before actually doing the calculation.
Release Summary:
Fix the improper calculation of session ticket lifetime.
Resolved issues:
Resolve issue #4583. Resolve issue #2756.
Description of changes:
Our current calculations of session ticket lifetimes are incorrect, please refers to the relevant issues for more details. The session ticket age should not exceed the user defined ticket age, remaining lifetime of encrypt decrypt key, remaining lifetime of PSK keying material, and one week.
s2n_generate_ticket_lifetime()
function:uint64_t key_intro_time
, anduint64_t current_time
tos2n_generate_ticket_lifetime()
, so that the function is aware of when the key is introduced and what the current time is.chosen_psk->keying_material_expiration
in as2n_connection
struct to calculate the remaining lifetime of the PSK.uint64_t *key_intro_time
parameter tos2n_resume_encrypt_session_ticket()
:s2n_resume_encrypt_session_ticket()
function. We can retrieve thekey_intro_time
from that function without moving the location where we calleds2n_get_ticket_encrypt_decrypt_key()
.s2n_resume_decrypt_session()
:s2n-tls/tls/s2n_resume.c
Lines 892 to 893 in a439c1a
s2n-tls/tls/s2n_resume.c
Lines 959 to 960 in a439c1a
key_intro_time
, then they can passNULL
into that parameter.uint64_t current_time
intostruct s2n_ticket_fields
.s2n_connection
fromtls13_ticket_fields
toticket_fields
, since both TLS1.2 and TLS1.3 have access to that variable.now
will have consistent time stamp.Call-outs
section.s2n_generate_ticket_lifetime()
function:s2n_resumption_test_ticket_key_setup()
to set up STEK for the connection.s2n_find_ticket_key()
with the key's name to acquire the actuals2n_ticket_key
.s2n_session_ticket_tests.c
:s2n-tls/tests/unit/s2n_session_ticket_test.c
Lines 817 to 821 in 1c38961
Call-outs:
s2n_generate_ticket_lifetime()
for shortest remaining PSK keying material lifetime. I set the PSK keying material expiration to be half a week, and reuse the previous configurations.s2n_server_new_session_ticket_test.c
, I didn't record realtime time stamp for two test cases whereSession state has shortest lifetime
andBoth session state and decrypt key have longer lifetimes than a week
.s2n_resume_encrypt_session_ticket_function()
, which is to pass bothkey
andcurrent_time
parameter into all functions involved. However, that will damaged the overall readability of the code. Such changes can be found in this feature branch.Testing:
S2nIntegrationV2SmallBatch
test requires this PR to be updated with main. I have tested it on a back up branch. The test should succeed after the update. Here is the test result.S2nIntegrationV2SmallBatch
job failed, theLinters / validate start_codebuild.sh
failed as well. However, that job should pass after this PR branch is updated to main.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.