-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
TLS 1.3: Refine and test client early data status #8755
TLS 1.3: Refine and test client early data status #8755
Conversation
80120b7
to
60c27aa
Compare
60c27aa
to
90f50c4
Compare
5ca8eae
to
b9127dc
Compare
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Fix cases where the client was sending two CCS, no harm but better to send only one. Prevent to send even more CCS when early data are involved without having to add conditional state transitions. Signed-off-by: Ronald Cron <ronald.cron@arm.com>
The main purpose of the change is to know from the status, at any point in the handshake, if early data can be sent or not and why. Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
b9127dc
to
2261ab2
Compare
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.
Looks pretty good to me! I only have minor suggestions for improvements (mostly comments, naming, etc.) but everything looks correct and well-tested to me.
if (ret == 0) { | ||
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); | ||
ret = 0; | ||
if (ssl->handshake->ccs_count == 0) { |
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.
Suggestion: I think we could put that check inside mbedtls_ssl_tls13_write_change_cipher_spec()
(which would do nothing and return 0 if CCS has already been sent). This would avoid having to repeat this at each call site, saving a few bytes of code size but more importantly making sure we don't forget the check.
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.
Done in #8760 commit "tls13: client: Improve CCS handling"
* one CCS per handshake without having to complicate the handshake state | ||
* transitions. | ||
*/ | ||
uint8_t ccs_count; |
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 find the name slightly misleading, since we expect to send no more than once. I'd prefer ccs_sent
. (Said otherwise, if an integer variable's only legal values are 0 and 1, I prefer to think of it as a boolean rather than a counter.)
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 with Manuel, but minor, can be done in a follow-up PR
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 as well, done in #8760 commit "tls13: Use a flag not a counter for CCS and HRR handling".
#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 0 | ||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED 1 | ||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED 2 | ||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 1 |
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.
Pre-exisiting: it would be good to have comment here like we have for the other values defined in ssl_misc.h
. In particular, out of context it might not be clear if STATUS_NOT_SENT
means the extension has not been sent, or early data itself has not been sent.
Btw, maybe renaming to STATUS_NOT_OFFERED
or STATUS_EXT_NOT_SENT
would make that clearer? (In addition to comments I mean.)
Edit, after reading more of the code: IIUC this actually means "we decided not to send it" as opposed to "we haven't sent it yet but might send it in the future". This only strengthens my point about adding a comment to make that clear.
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.
(pre-existing, minor) feels like this should be an enum
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.
see #8755 (comment)
ssl_tls13_early_data_has_valid_ticket(ssl) && | ||
ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED && | ||
ssl->handshake->hello_retry_request_count == 0) { | ||
if (ssl->handshake->hello_retry_request_count == 0) { |
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.
Pre-existing, but: can there really be more that on HRR per handshake? If not, I'd also suggest making that a boolean instead as I think that count
may mislead readers into thinking there may be more than one. (I'll agree if you say that's out of scope.)
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, done in #8760 commit "tls13: Use a flag not a counter for CCS and HRR handling".
ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED && | ||
ssl->handshake->hello_retry_request_count == 0) { | ||
if (ssl->handshake->hello_retry_request_count == 0) { | ||
if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) && |
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.
[edit: skip to last paragraph, only requesting adding a comment after all]
I'm not sure I understand or agree with the logic here:
if no_hrr:
if other_conditions:
send it and mark as sent
else:
mark as not sent
So, it there was an HRR in this handshake, we will not send the extension and not update the status to "not sent" either? Is that intentional? I'd have expected:
if no_hrr and other_conditions:
send it and mark as sent
else:
mark as not sent
What am I missing?
Edit, after reading more of the code: I think what I was missing is that if there was an HRR earlier, status has already been updated to "rejected" and we want to leave it at that. So, now I think I understand and agree with the logic here, but a comment would be welcome.
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.
Done in #8760 commit "tls13: client: Add comment about early data in 2nd ClientHello".
* The client has not sent the first ClientHello yet, it is unknown if the | ||
* client will send an early data indication extension or not. | ||
*/ | ||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN 0 |
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: the documentation for the early_data_status
field still says Reset to #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT
- does it need updating?
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.
Fixed in #8760, commit "tls13: Fix/Improve comments"
@@ -2145,6 +2145,38 @@ int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, | |||
unsigned char *buf, | |||
const unsigned char *end, | |||
size_t *out_len); | |||
|
|||
#if defined(MBEDTLS_SSL_CLI_C) |
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: the definitions in ssl.h
are not guarded by this, should they be?
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.
(minor) I'd prefer to see them defined in one place, even if values are defined that aren't used under some circumstances - they are well-enough namespaced
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.
see #8755 (comment)
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.
LGTM - I only have minor comments, and given @mpg's review is similar, and these commits are in another PR that is under review, it seems best to merge this as-is and address those comments in a follow-on PR
#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 0 | ||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED 1 | ||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED 2 | ||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 1 |
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.
(pre-existing, minor) feels like this should be an enum
* one CCS per handshake without having to complicate the handshake state | ||
* transitions. | ||
*/ | ||
uint8_t ccs_count; |
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 with Manuel, but minor, can be done in a follow-up PR
|
||
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) | ||
/** | ||
* Number of dummy change_cipher_spec (CCS) record sent. Used to send only |
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.
(minor, fix in follow-up) should be plural records sent
. Also, there seem to be two spaces after the *
on each line :)
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.
comment changed in #8760
* ClientHello, the server has accepted them and the client has received the | ||
* server Finished message. It cannot send early data to the server anymore. | ||
*/ | ||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED 6 |
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.
(for follow-up) If these are all possible values of early_data_status
i.e. return values from mbedtls_ssl_get_early_data_status()
could they be defined together, ideally in an enum?
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.
mbedtls_ssl_get_early_data_status()
returns only NOT_SENT or ACCEPTED or REJECTED. The other values are for internal use only. See also #8755 (comment).
@@ -2145,6 +2145,38 @@ int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, | |||
unsigned char *buf, | |||
const unsigned char *end, | |||
size_t *out_len); | |||
|
|||
#if defined(MBEDTLS_SSL_CLI_C) |
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.
(minor) I'd prefer to see them defined in one place, even if values are defined that aren't used under some circumstances - they are well-enough namespaced
mbedtls_test_handshake_test_options *client_options, | ||
mbedtls_test_handshake_test_options *server_options, | ||
mbedtls_ssl_session *session); | ||
#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SRV_C && |
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.
(minor) we don't really need the list of conditions in the #endif
since it's so close to the #if
- it clutters the text, and if the condition needs changing in the future it's an unnecessary thing to have to keep in sync
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.
Done in #8760, commit "tls13: Fix/Improve comments"
TEST_EQUAL(client_ep.ssl.early_data_status, | ||
MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); | ||
} | ||
break; |
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 wonder if we should have default: TEST_FAIL("Missing scenario");
in these in case we extend the set of scenarios and forget to update one of the switch
es in the future?
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.
Yes that should reduce the risk of missing something when adding a scenario. Done in #8760, last commit.
Thank you @mpg! |
@mpg and @tom-cosgrove-arm thanks for the review. I have addressed your comments in five additional commits in #8760 (thanks for its rebase). Regarding the definition of MBEDTLS_SSL_EARLY_DATA_STATUS_xyz (various comments about it) I've tried to improve things (penultimate commit). MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT/ACCEPTED/REJECTED documentation is still in the documentation of |
Description
First PR of two addressing #6340.
PR checklist