Skip to content
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: Send zero-length NST when session key is expired #4532

Merged
merged 36 commits into from May 15, 2024

Conversation

jouho
Copy link
Contributor

@jouho jouho commented Apr 30, 2024

Resolved issues:

Resolves #4528

Description of changes:

According to RFC5077:

This message MUST be sent if the
server included a SessionTicket extension in the ServerHello.
...
If the server determines that it does not want to include a
ticket after it has included the SessionTicket extension in the
ServerHello, then it sends a zero-length ticket in the
NewSessionTicket handshake message.

Currently we throw an error during the write of NewSessionTicket message if there are no valid session ticket keys available. It is guarded by s2n_encrypt_session_ticket, which fails if there is no key available. This behavior is verified and can be reproduced by running the new test added with this change reverted.

This change modifies the condition of s2n_server_nst_send in s2n-tls/tls/s2n_server_new_session_ticket.c so that it writes a zero-length session ticket if the key used to encrypt session ticket was expired between SERVER_HELLO and CLIENT_FINISHED, before writing NewSessionTicket.

This change does not impact TLS1.3, as it bail and don't send it if no key is available: https://github.com/aws/s2n-tls/blob/main/tls/s2n_server_new_session_ticket.c#L170-L172. A test to verify this is also added.

Does this change what S2N sends over the wire?
It will now correctly sends a zero-length NewSessionTicket message in the condition described above.
Does this change any public APIs? If yes, explain.
No.
Which versions of TLS will this impact?
This will impact TLS1.2 and not TLS1.3.

Call-outs:

Currently I am verifying that client received zero-length session ticket by
EXPECT_EQUAL(client_connection->client_ticket.allocated, 0);, but this may not explicitly verify the condition and there could be a better way to test it.

Testing:

Confirmed all unit tests pass.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@github-actions github-actions bot added the s2n-core team label Apr 30, 2024
@jouho jouho requested review from lrstewart and maddeleine May 1, 2024 00:32
tests/unit/s2n_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_session_ticket_test.c Outdated Show resolved Hide resolved
@jouho jouho requested a review from maddeleine May 6, 2024 22:20
tls/s2n_server_new_session_ticket.c Outdated Show resolved Hide resolved
tests/unit/s2n_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_server_new_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_server_new_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_server_new_session_ticket_test.c Outdated Show resolved Hide resolved
@jouho jouho requested a review from maddeleine May 8, 2024 20:21
tests/unit/s2n_server_new_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_server_new_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_server_new_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_server_new_session_ticket_test.c Outdated Show resolved Hide resolved
tests/unit/s2n_session_ticket_test.c Show resolved Hide resolved
@jouho jouho requested a review from maddeleine May 8, 2024 22:45
Comment on lines 88 to 90
*= https://www.rfc-editor.org/rfc/rfc5077#section-3.3
*# This message MUST be sent if the server included
*# a SessionTicket extension in the ServerHello.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the right place for this compliance comment? This code doesn't ensure that the message is sent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is writing to stuffer not considered "sending a message", or are you suggesting to put this comment on top of code where I send zero-length nst message upon failing to retrieve a key like what I did in my latest change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writing to a stuffer isn't automatically sending a message. This code also doesn't somehow enforce that you always write to that stuffer, just that you do in this one case.

With the way the code is currently structured, I'm not sure there's a good place for this comment.

Comment on lines 98 to 102
*= https://www.rfc-editor.org/rfc/rfc5077#section-3.3
*# struct {
*# uint32 ticket_lifetime_hint;
*# opaque ticket<0..2^16-1>;
*# } NewSessionTicket;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also not convinced this is the right place for this compliance comment. The struct format applies to the whole message, not just to an empty message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make more sense to put this comment on top of this s2n_server_nst_send() function? Or is there more suitable place for this comment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like above: it's not clear to me that there is a suitable place to put this comment given the current structure of the code.

Comment on lines 103 to 104
**/
if (!conn->config->use_tickets || s2n_result_is_error(s2n_config_is_encrypt_key_available(conn->config))) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this completely solve the problem? Couldn't the key still expire between here and s2n_encrypt_session_ticket? Or couldn't s2n_config_is_encrypt_key_available still otherwise disagree with s2n_get_ticket_encrypt_decrypt_key?

To completely solve the problem, you need to write an empty message in response to actually failing to retrieve the key, not in response to a new "is there a key" check. We already made an "is there a key" check during the last message, which was probably like nanoseconds ago.

@jouho jouho requested a review from lrstewart May 13, 2024 20:18
@jouho jouho requested a review from lrstewart May 15, 2024 19:27
Co-authored-by: Lindsay Stewart <slindsay@amazon.com>
@jouho jouho enabled auto-merge (squash) May 15, 2024 19:40
@jouho jouho merged commit 885b607 into main May 15, 2024
36 checks passed
@jouho jouho deleted the zero-length-tls12-NST-message branch May 15, 2024 21:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Send zero-length TLS1.2 NewSessionTicket message if necessary
3 participants