Skip to content

Commit

Permalink
Change the TLS handshake keys early if we're not doing early data
Browse files Browse the repository at this point in the history
We change the client TLS handshake keys as late as possible so that we
don't disturb the keys if we are writing early data. However for QUIC we
want to do this as early as possible (after ServerHello). Since we will
never do TLS early data with QUIC we just do it as early as possible if
early data is not being used.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
(Merged from #21810)
  • Loading branch information
mattcaswell authored and hlandau committed Aug 24, 2023
1 parent 27315a9 commit 84a1492
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 9 deletions.
41 changes: 36 additions & 5 deletions ssl/statem/statem_clnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1782,12 +1782,29 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL_CONNECTION *s, PACKET *pkt)
* In TLSv1.3 we have some post-processing to change cipher state, otherwise
* we're done with this message
*/
if (SSL_CONNECTION_IS_TLS13(s)
&& (!ssl->method->ssl3_enc->setup_key_block(s)
if (SSL_CONNECTION_IS_TLS13(s)) {
if (!ssl->method->ssl3_enc->setup_key_block(s)
|| !ssl->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ))) {
/* SSLfatal() already called */
goto err;
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ)) {
/* SSLfatal() already called */
goto err;
}
/*
* If we're not doing early-data and we're not going to send a dummy CCS
* (i.e. no middlebox compat mode) then we can change the write keys
* immediately. Otherwise we have to defer this until after all possible
* early data is written. We could just alway defer until the last
* moment except QUIC needs it done at the same time as the read keys
* are changed. Since QUIC doesn't do TLS early data or need middlebox
* compat this doesn't cause a problem.
*/
if (s->early_data_state == SSL_EARLY_DATA_NONE
&& (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0
&& !ssl->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
/* SSLfatal() already called */
goto err;
}
}

OPENSSL_free(extensions);
Expand Down Expand Up @@ -3772,8 +3789,15 @@ CON_FUNC_RETURN tls_construct_client_certificate(SSL_CONNECTION *s,
return CON_FUNC_ERROR;
}

/*
* If we attempted to write early data or we're in middlebox compat mode
* then we deferred changing the handshake write keys to the last possible
* moment. We need to do it now.
*/
if (SSL_CONNECTION_IS_TLS13(s)
&& SSL_IS_FIRST_HANDSHAKE(s)
&& (s->early_data_state != SSL_EARLY_DATA_NONE
|| (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0)
&& (!ssl->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
/*
Expand Down Expand Up @@ -3855,7 +3879,14 @@ CON_FUNC_RETURN tls_construct_client_compressed_certificate(SSL_CONNECTION *sc,
|| !WPACKET_close(pkt))
goto err;

/*
* If we attempted to write early data or we're in middlebox compat mode
* then we deferred changing the handshake write keys to the last possible
* moment. We need to do it now.
*/
if (SSL_IS_FIRST_HANDSHAKE(sc)
&& (sc->early_data_state != SSL_EARLY_DATA_NONE
|| (sc->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0)
&& (!ssl->method->ssl3_enc->change_cipher_state(sc,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
/*
Expand Down
8 changes: 6 additions & 2 deletions ssl/statem/statem_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,11 +615,15 @@ CON_FUNC_RETURN tls_construct_finished(SSL_CONNECTION *s, WPACKET *pkt)
s->statem.cleanuphand = 1;

/*
* We only change the keys if we didn't already do this when we sent the
* client certificate
* If we attempted to write early data or we're in middlebox compat mode
* then we deferred changing the handshake write keys to the last possible
* moment. If we didn't already do this when we sent the client certificate
* then we need to do it now.
*/
if (SSL_CONNECTION_IS_TLS13(s)
&& !s->server
&& (s->early_data_state != SSL_EARLY_DATA_NONE
|| (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0)
&& s->s3.tmp.cert_req == 0
&& (!ssl->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {;
Expand Down
10 changes: 8 additions & 2 deletions test/recipes/75-test_quicapi_data/ssltraceref.txt
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,11 @@ YeeuLO02zToHhnQ6KbPXOrQAqcL1kngO4g+j/ru+4AZThFkdkGnltvk=
------------------
No extensions

Sent Frame: Ack (without ECN)
Largest acked: 0
Ack delay (raw) 0
Ack range count: 0
First ack range: 0
Sent Frame: Ack (without ECN)
Largest acked: 0
Ack delay (raw) 0
Expand All @@ -244,9 +249,10 @@ Sent Packet
Version: 0x00000001
Destination Conn Id: 0x????????????????
Source Conn Id: <zero length id>
Payload length: 1178
Payload length: 1137
Token: <zero length token>
Packet Number: 0x00000001

Sent Datagram
Length: 1200
Received Datagram
Expand Down Expand Up @@ -297,6 +303,6 @@ Sent Packet
Destination Conn Id: 0x????????????????
Source Conn Id: <zero length id>
Payload length: 60
Packet Number: 0x00000000
Packet Number: 0x00000001
Sent Datagram
Length: 81

0 comments on commit 84a1492

Please sign in to comment.