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