Avoid re-hashing the transcript multiple times. tls13_init_key_schedule calls InitHash internally, but we also call InitHash earlier at various times. On the client, we do it early to handle HelloRetryRequest and 0-RTT. ECH draft-12 will also need to do it early. Apparently we do it early on the server too. Probably tls13_init_key_schedule doesn't need to call InitHash, but for now, it is an easy check in SSLTranscript. Change-Id: I5473047c1f29bdeb60901e4e6e80979e592bd6e9 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48911 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/internal.h b/ssl/internal.h index f9cee53..6b7528c 100644 --- a/ssl/internal.h +++ b/ssl/internal.h
@@ -694,7 +694,8 @@ // InitHash initializes the handshake hash based on the PRF and contents of // the handshake transcript. Subsequent calls to |Update| will update the // rolling hash. It returns one on success and zero on failure. It is an error - // to call this function after the handshake buffer is released. + // to call this function after the handshake buffer is released. This may be + // called multiple times to change the hash function. bool InitHash(uint16_t version, const SSL_CIPHER *cipher); // UpdateForHelloRetryRequest resets the rolling hash with the
diff --git a/ssl/ssl_transcript.cc b/ssl/ssl_transcript.cc index 1599c80..58fd21e 100644 --- a/ssl/ssl_transcript.cc +++ b/ssl/ssl_transcript.cc
@@ -158,20 +158,14 @@ return true; } -// InitDigestWithData calls |EVP_DigestInit_ex| on |ctx| with |md| and then -// writes the data in |buf| to it. -static bool InitDigestWithData(EVP_MD_CTX *ctx, const EVP_MD *md, - const BUF_MEM *buf) { - if (!EVP_DigestInit_ex(ctx, md, NULL)) { - return false; - } - EVP_DigestUpdate(ctx, buf->data, buf->length); - return true; -} - bool SSLTranscript::InitHash(uint16_t version, const SSL_CIPHER *cipher) { const EVP_MD *md = ssl_get_handshake_digest(version, cipher); - return InitDigestWithData(hash_.get(), md, buffer_.get()); + if (Digest() == md) { + // No need to re-hash the buffer. + return true; + } + return EVP_DigestInit_ex(hash_.get(), md, nullptr) && + EVP_DigestUpdate(hash_.get(), buffer_->data, buffer_->length); } void SSLTranscript::FreeBuffer() {
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc index 6509cc4..79968bc 100644 --- a/ssl/tls13_server.cc +++ b/ssl/tls13_server.cc
@@ -246,8 +246,7 @@ return ssl_hs_error; } - // The PRF hash is now known. Set up the key schedule and hash the - // ClientHello. + // The PRF hash is now known. if (!hs->transcript.InitHash(ssl_protocol_version(ssl), hs->new_cipher)) { return ssl_hs_error; }