Restrict when 0-RTT will be accepted in QUIC.
QUIC imposes additional restrictions on when 0-RTT data can be accepted.
With this change, a QUIC server configured to support 0-RTT will only
accept early data if the transport parameters and application protocol
specific context are a byte-for-byte match from the original connection
to the 0-RTT resumption attempt.
Bug: 295
Change-Id: Ie5d4688d1c9076b49f2131bb66b27c87e2ba041a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41145
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/ssl_session.cc b/ssl/ssl_session.cc
index 0d372cb..fa994e8 100644
--- a/ssl/ssl_session.cc
+++ b/ssl/ssl_session.cc
@@ -268,6 +268,11 @@
if (!new_session->early_alpn.CopyFrom(session->early_alpn)) {
return nullptr;
}
+
+ if (!new_session->quic_early_data_hash.CopyFrom(
+ session->quic_early_data_hash)) {
+ return nullptr;
+ }
}
// Copy the ticket.
@@ -344,6 +349,25 @@
session->cipher);
}
+bool compute_quic_early_data_hash(const SSL_CONFIG *config,
+ uint8_t hash_out[SHA256_DIGEST_LENGTH]) {
+ ScopedEVP_MD_CTX hash_ctx;
+ uint32_t transport_param_len = config->quic_transport_params.size();
+ uint32_t context_len = config->quic_early_data_context.size();
+ if (!EVP_DigestInit(hash_ctx.get(), EVP_sha256()) ||
+ !EVP_DigestUpdate(hash_ctx.get(), &transport_param_len,
+ sizeof(transport_param_len)) ||
+ !EVP_DigestUpdate(hash_ctx.get(), config->quic_transport_params.data(),
+ config->quic_transport_params.size()) ||
+ !EVP_DigestUpdate(hash_ctx.get(), &context_len, sizeof(context_len)) ||
+ !EVP_DigestUpdate(hash_ctx.get(), config->quic_early_data_context.data(),
+ config->quic_early_data_context.size()) ||
+ !EVP_DigestFinal(hash_ctx.get(), hash_out, nullptr)) {
+ return false;
+ }
+ return true;
+}
+
int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
SSL *const ssl = hs->ssl;
if (ssl->mode & SSL_MODE_NO_SESSION_CREATION) {
@@ -359,6 +383,13 @@
session->is_server = is_server;
session->ssl_version = ssl->version;
session->is_quic = ssl->quic_method != nullptr;
+ if (is_server && ssl->enable_early_data && session->is_quic) {
+ if (!session->quic_early_data_hash.Init(SHA256_DIGEST_LENGTH) ||
+ !compute_quic_early_data_hash(hs->config,
+ session->quic_early_data_hash.data())) {
+ return 0;
+ }
+ }
// Fill in the time from the |SSL_CTX|'s clock.
struct OPENSSL_timeval now;