Send ECH acceptance signal from backend server.
This CL implements the backend server behavior described in Section 7.2
of draft-ietf-tls-esni-09.
Bug: 275
Change-Id: I2e162673ce564db0cb75fc9b71ef11ed15037f4b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/43924
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/tls13_enc.cc b/ssl/tls13_enc.cc
index 198adb6..cda53ec 100644
--- a/ssl/tls13_enc.cc
+++ b/ssl/tls13_enc.cc
@@ -507,4 +507,40 @@
return true;
}
+bool tls13_ech_accept_confirmation(
+ SSL_HANDSHAKE *hs, bssl::Span<uint8_t> out,
+ bssl::Span<const uint8_t> server_hello_ech_conf) {
+ // Compute the hash of the transcript concatenated with
+ // |server_hello_ech_conf| without modifying |hs->transcript|.
+ uint8_t context_hash[EVP_MAX_MD_SIZE];
+ unsigned context_hash_len;
+ ScopedEVP_MD_CTX ctx;
+ if (!hs->transcript.CopyToHashContext(ctx.get(), hs->transcript.Digest()) ||
+ !EVP_DigestUpdate(ctx.get(), server_hello_ech_conf.data(),
+ server_hello_ech_conf.size()) ||
+ !EVP_DigestFinal_ex(ctx.get(), context_hash, &context_hash_len)) {
+ return false;
+ }
+
+ // Per draft-ietf-tls-esni-09, accept_confirmation is computed with
+ // Derive-Secret, which derives a secret of size Hash.length. That value is
+ // then truncated to the first 8 bytes. Note this differs from deriving an
+ // 8-byte secret because the target length is included in the derivation.
+ uint8_t accept_confirmation_buf[EVP_MAX_MD_SIZE];
+ bssl::Span<uint8_t> accept_confirmation =
+ MakeSpan(accept_confirmation_buf, hs->transcript.DigestLen());
+ if (!hkdf_expand_label(accept_confirmation, hs->transcript.Digest(),
+ hs->secret(), label_to_span("ech accept confirmation"),
+ MakeConstSpan(context_hash, context_hash_len))) {
+ return false;
+ }
+
+ if (out.size() > accept_confirmation.size()) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return false;
+ }
+ OPENSSL_memcpy(out.data(), accept_confirmation.data(), out.size());
+ return true;
+}
+
BSSL_NAMESPACE_END