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;
}