Defer releasing early secrets to QUIC servers. We want the QUIC/TLS interface to never release a read key without the corresponding write key for ACKs. This is mostly done by shipping both keys simultaneously, but 0-RTT is weird because it is ACKed by 1-RTT. Note this means we actually release 0-RTT keys to the server *after* the 1-RTT keys. This is kinda weird but more directly maintains our invariant. (We may want to revisit the key configuring API in light of https://github.com/quicwg/base-drafts/issues/3159 and https://github.com/quicwg/base-drafts/issues/3173, but start with this more local tweak.) Bug: 303 Change-Id: I317fe6ae8150533738373c219f19d3034bb040ad Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38884 Commit-Queue: Steven Valdez <svaldez@google.com> Reviewed-by: Nick Harper <nharper@google.com> Reviewed-by: Steven Valdez <svaldez@google.com>
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc index 8fbf698..6211c56 100644 --- a/ssl/ssl_test.cc +++ b/ssl/ssl_test.cc
@@ -4811,6 +4811,10 @@ expect_read_secret = false; } else { expect_write_secret = false; + if (!HasSecrets(ssl_encryption_application)) { + ADD_FAILURE() << "early secrets installed without keys to ACK them"; + return false; + } } }
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc index d8115f5..c74d834 100644 --- a/ssl/tls13_server.cc +++ b/ssl/tls13_server.cc
@@ -471,15 +471,6 @@ return ssl_hs_error; } - // Note we defer releasing the early traffic secret to QUIC until after ECDHE - // is resolved. The early traffic secret should be derived before the key - // schedule incorporates ECDHE, but doing so may reject 0-RTT. To avoid - // confusing the caller, we split derivation and releasing the secret to QUIC. - if (ssl->s3->early_data_accepted && - !tls13_set_early_secret_for_quic(hs)) { - return ssl_hs_error; - } - ssl->method->next_message(ssl); hs->tls13_state = state_send_server_hello; return ssl_hs_ok; @@ -737,6 +728,19 @@ } if (ssl->s3->early_data_accepted) { + // We defer releasing the early traffic secret to QUIC to this point. First, + // the early traffic secret is derived before ECDHE, but ECDHE may later + // reject 0-RTT. We only release the secret after 0-RTT is fully resolved. + // + // Second, 0-RTT data is acknowledged with 1-RTT keys. Both are derived as + // part of the ServerHello flight, but future TLS extensions may insert an + // asynchronous point in the middle of this flight. We defer releasing the + // 0-RTT keys to ensure the QUIC implementation never installs read keys + // without the write keys to send the corresponding ACKs. + if (!tls13_set_early_secret_for_quic(hs)) { + return ssl_hs_error; + } + // If accepting 0-RTT, we send tickets half-RTT. This gets the tickets on // the wire sooner and also avoids triggering a write on |SSL_read| when // processing the client Finished. This requires computing the client