-
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
Changes from all commits
fb53647
b4ad3e7
ced99be
1f6e4e4
bfcdc06
fe59ff7
90e2233
a7f94e4
5c208d7
265273e
d6dba67
2261ab2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -731,14 +731,23 @@ struct mbedtls_ssl_handshake_params { | |
uint8_t key_exchange_mode; /*!< Selected key exchange mode */ | ||
|
||
/** Number of HelloRetryRequest messages received/sent from/to the server. */ | ||
int hello_retry_request_count; | ||
uint8_t hello_retry_request_count; | ||
|
||
#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 commentThe reason will be displayed to describe this comment to others. Learn more. (minor, fix in follow-up) should be plural There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment changed in #8760 |
||
* 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 commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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". |
||
#endif | ||
|
||
#if defined(MBEDTLS_SSL_SRV_C) | ||
/** selected_group of key_share extension in HelloRetryRequest message. */ | ||
uint16_t hrr_selected_group; | ||
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) | ||
uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */ | ||
#endif | ||
/** selected_group of key_share extension in HelloRetryRequest message. */ | ||
uint16_t hrr_selected_group; | ||
#if defined(MBEDTLS_SSL_SESSION_TICKETS) | ||
uint16_t new_session_tickets_count; /*!< number of session tickets */ | ||
#endif | ||
|
@@ -2136,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 commentThe reason will be displayed to describe this comment to others. Learn more. Note: the definitions in There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. see #8755 (comment) |
||
/* | ||
* 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 commentThe reason will be displayed to describe this comment to others. Learn more. Note: the documentation for the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in #8760, commit "tls13: Fix/Improve comments" |
||
|
||
/* | ||
* The client has sent an early data indication extension in its first | ||
* ClientHello, it has not received the response (ServerHello or | ||
* HelloRetryRequest) from the server yet. The transform to protect early data | ||
* is not set and early data cannot be sent yet. | ||
*/ | ||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_SENT 4 | ||
|
||
/* | ||
* The client has sent an early data indication extension in its first | ||
* ClientHello, it has not received the response (ServerHello or | ||
* HelloRetryRequest) from the server yet. The transform to protect early data | ||
* has been set and early data can be written now. | ||
*/ | ||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE 5 | ||
|
||
/* | ||
* The client has sent an early data indication extension in its first | ||
* 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 commentThe reason will be displayed to describe this comment to others. Learn more. (for follow-up) If these are all possible values of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
#endif /* MBEDTLS_SSL_CLI_C */ | ||
|
||
#endif /* MBEDTLS_SSL_EARLY_DATA */ | ||
|
||
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1180,26 +1180,21 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, | |
#endif | ||
|
||
#if defined(MBEDTLS_SSL_EARLY_DATA) | ||
if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) && | ||
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 commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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". |
||
if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
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:
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 commentThe 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". |
||
ssl_tls13_early_data_has_valid_ticket(ssl) && | ||
ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) { | ||
ret = mbedtls_ssl_tls13_write_early_data_ext( | ||
ssl, 0, p, end, &ext_len); | ||
if (ret != 0) { | ||
return ret; | ||
} | ||
p += ext_len; | ||
|
||
ret = mbedtls_ssl_tls13_write_early_data_ext( | ||
ssl, 0, p, end, &ext_len); | ||
if (ret != 0) { | ||
return ret; | ||
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_SENT; | ||
} else { | ||
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT; | ||
} | ||
p += ext_len; | ||
|
||
/* Initializes the status to `rejected`. It will be updated to | ||
* `accepted` if the EncryptedExtension message contain an early data | ||
* indication extension. | ||
*/ | ||
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED; | ||
} else { | ||
MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write early_data extension")); | ||
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT; | ||
} | ||
#endif /* MBEDTLS_SSL_EARLY_DATA */ | ||
|
||
|
@@ -1236,7 +1231,7 @@ int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl) | |
size_t psk_len; | ||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info; | ||
|
||
if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) { | ||
if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT) { | ||
MBEDTLS_SSL_DEBUG_MSG( | ||
1, ("Set hs psk for early data when writing the first psk")); | ||
|
||
|
@@ -1299,6 +1294,7 @@ int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl) | |
1, ("Switch to early data keys for outbound traffic")); | ||
mbedtls_ssl_set_outbound_transform( | ||
ssl, ssl->handshake->transform_earlydata); | ||
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE; | ||
#endif | ||
} | ||
#endif /* MBEDTLS_SSL_EARLY_DATA */ | ||
|
@@ -1971,6 +1967,13 @@ static int ssl_tls13_postprocess_hrr(mbedtls_ssl_context *ssl) | |
} | ||
|
||
ssl->session_negotiate->ciphersuite = ssl->handshake->ciphersuite_info->id; | ||
|
||
#if defined(MBEDTLS_SSL_EARLY_DATA) | ||
if (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) { | ||
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED; | ||
} | ||
#endif | ||
|
||
return 0; | ||
} | ||
|
||
|
@@ -2230,6 +2233,8 @@ static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl) | |
} | ||
|
||
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED; | ||
} else if (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) { | ||
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED; | ||
} | ||
#endif | ||
|
||
|
@@ -2567,9 +2572,8 @@ static int ssl_tls13_process_server_finished(mbedtls_ssl_context *ssl) | |
|
||
#if defined(MBEDTLS_SSL_EARLY_DATA) | ||
if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) { | ||
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED; | ||
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA); | ||
} else if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) { | ||
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); | ||
} else | ||
#endif /* MBEDTLS_SSL_EARLY_DATA */ | ||
{ | ||
|
@@ -3059,18 +3063,25 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl) | |
*/ | ||
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) | ||
case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: | ||
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); | ||
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 commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: I think we could put that check inside There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in #8760 commit "tls13: client: Improve CCS handling" |
||
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); | ||
if (ret != 0) { | ||
break; | ||
} | ||
} | ||
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); | ||
break; | ||
|
||
case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: | ||
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); | ||
if (ret == 0) { | ||
mbedtls_ssl_handshake_set_state( | ||
ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); | ||
ret = 0; | ||
if (ssl->handshake->ccs_count == 0) { | ||
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); | ||
if (ret != 0) { | ||
break; | ||
} | ||
} | ||
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); | ||
break; | ||
|
||
#if defined(MBEDTLS_SSL_EARLY_DATA) | ||
|
@@ -3083,6 +3094,7 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl) | |
1, ("Switch to early data keys for outbound traffic")); | ||
mbedtls_ssl_set_outbound_transform( | ||
ssl, ssl->handshake->transform_earlydata); | ||
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE; | ||
} | ||
break; | ||
#endif /* MBEDTLS_SSL_EARLY_DATA */ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,6 +85,7 @@ typedef struct mbedtls_test_ssl_log_pattern { | |
|
||
typedef struct mbedtls_test_handshake_test_options { | ||
const char *cipher; | ||
uint16_t *group_list; | ||
mbedtls_ssl_protocol_version client_min_version; | ||
mbedtls_ssl_protocol_version client_max_version; | ||
mbedtls_ssl_protocol_version server_min_version; | ||
|
@@ -112,6 +113,7 @@ typedef struct mbedtls_test_handshake_test_options { | |
void (*srv_log_fun)(void *, int, const char *, int, const char *); | ||
void (*cli_log_fun)(void *, int, const char *, int, const char *); | ||
int resize_buffers; | ||
int early_data; | ||
#if defined(MBEDTLS_SSL_CACHE_C) | ||
mbedtls_ssl_cache_context *cache; | ||
#endif | ||
|
@@ -440,8 +442,7 @@ int mbedtls_test_ssl_endpoint_init( | |
mbedtls_test_handshake_test_options *options, | ||
mbedtls_test_message_socket_context *dtls_context, | ||
mbedtls_test_ssl_message_queue *input_queue, | ||
mbedtls_test_ssl_message_queue *output_queue, | ||
uint16_t *group_list); | ||
mbedtls_test_ssl_message_queue *output_queue); | ||
|
||
/* | ||
* Deinitializes endpoint represented by \p ep. | ||
|
@@ -599,6 +600,17 @@ int mbedtls_test_ticket_parse(void *p_ticket, mbedtls_ssl_session *session, | |
unsigned char *buf, size_t len); | ||
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ | ||
|
||
#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SRV_C) && \ | ||
defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) && \ | ||
defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) | ||
int mbedtls_test_get_tls13_ticket( | ||
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 commentThe reason will be displayed to describe this comment to others. Learn more. (minor) we don't really need the list of conditions in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in #8760, commit "tls13: Fix/Improve comments" |
||
MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS && | ||
MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ | ||
|
||
#define ECJPAKE_TEST_PWD "bla" | ||
|
||
#if defined(MBEDTLS_USE_PSA_CRYPTO) | ||
|
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 ifSTATUS_NOT_SENT
means the extension has not been sent, or early data itself has not been sent.Btw, maybe renaming to
STATUS_NOT_OFFERED
orSTATUS_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)