Change ProofVerifier::VerifyCertChain to support not copying certs PiperOrigin-RevId: 924927539
diff --git a/build/source_list.bzl b/build/source_list.bzl index 601aea1..822ed4d 100644 --- a/build/source_list.bzl +++ b/build/source_list.bzl
@@ -568,6 +568,7 @@ "quic/core/crypto/p256_key_exchange.cc", "quic/core/crypto/proof_source.cc", "quic/core/crypto/proof_source_x509.cc", + "quic/core/crypto/proof_verifier.cc", "quic/core/crypto/quic_client_session_cache.cc", "quic/core/crypto/quic_compressed_certs_cache.cc", "quic/core/crypto/quic_crypter.cc",
diff --git a/build/source_list.gni b/build/source_list.gni index 1182613..c5e5f30 100644 --- a/build/source_list.gni +++ b/build/source_list.gni
@@ -568,6 +568,7 @@ "src/quiche/quic/core/crypto/p256_key_exchange.cc", "src/quiche/quic/core/crypto/proof_source.cc", "src/quiche/quic/core/crypto/proof_source_x509.cc", + "src/quiche/quic/core/crypto/proof_verifier.cc", "src/quiche/quic/core/crypto/quic_client_session_cache.cc", "src/quiche/quic/core/crypto/quic_compressed_certs_cache.cc", "src/quiche/quic/core/crypto/quic_crypter.cc",
diff --git a/build/source_list.json b/build/source_list.json index c686b3b..bc6cb56 100644 --- a/build/source_list.json +++ b/build/source_list.json
@@ -567,6 +567,7 @@ "quiche/quic/core/crypto/p256_key_exchange.cc", "quiche/quic/core/crypto/proof_source.cc", "quiche/quic/core/crypto/proof_source_x509.cc", + "quiche/quic/core/crypto/proof_verifier.cc", "quiche/quic/core/crypto/quic_client_session_cache.cc", "quiche/quic/core/crypto/quic_compressed_certs_cache.cc", "quiche/quic/core/crypto/quic_crypter.cc",
diff --git a/quiche/quic/core/crypto/proof_verifier.cc b/quiche/quic/core/crypto/proof_verifier.cc new file mode 100644 index 0000000..bf78a4b --- /dev/null +++ b/quiche/quic/core/crypto/proof_verifier.cc
@@ -0,0 +1,55 @@ +// Copyright (c) 2026 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "quiche/quic/core/crypto/proof_verifier.h" + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "absl/strings/string_view.h" +#include "quiche/quic/core/quic_types.h" +#include "quiche/common/platform/api/quiche_logging.h" + +namespace quic { + +QuicAsyncStatus ProofVerifier::VerifyCertChain( + const std::string& hostname, uint16_t port, + const std::vector<absl::string_view>& certs, + const std::string& ocsp_response, const std::string& cert_sct, + const ProofVerifyContext* context, std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* details, uint8_t* out_alert, + std::unique_ptr<ProofVerifierCallback> callback) { + // To avoid needing an atomic migration of all quiche consumers to use the new + // VerifyCertChain function definition, this shim is provided so that old + // ProofVerifier implementations continue to work. + // + // TODO(b/517611362): Remove this once all ProofVerifier implementations + // have stopped implementing the old VerifyCertChain. + std::vector<std::string> certs_str; + certs_str.reserve(certs.size()); + for (absl::string_view cert : certs) { + certs_str.push_back(std::string(cert)); + } + return VerifyCertChain(hostname, port, certs_str, ocsp_response, cert_sct, + context, error_details, details, out_alert, + std::move(callback)); +} + +QuicAsyncStatus ProofVerifier::VerifyCertChain( + const std::string&, uint16_t, const std::vector<std::string>&, + const std::string&, const std::string&, const ProofVerifyContext*, + std::string*, std::unique_ptr<ProofVerifyDetails>*, uint8_t*, + std::unique_ptr<ProofVerifierCallback>) { + // This function exists only for ProofVerifiers that don't implement the new + // VerifyCertChain (that takes a vector of absl::string_views for the certs). + // A ProofVerifier needs to implement one of the VerifyCertChain functions + // (and it should implement the other one). If it implements neither, it will + // end up here. + QUICHE_NOTREACHED(); + return QUIC_FAILURE; +} + +} // namespace quic
diff --git a/quiche/quic/core/crypto/proof_verifier.h b/quiche/quic/core/crypto/proof_verifier.h index fe4a808..15031e5 100644 --- a/quiche/quic/core/crypto/proof_verifier.h +++ b/quiche/quic/core/crypto/proof_verifier.h
@@ -101,10 +101,23 @@ // In this case, the ProofVerifier will take ownership of |callback|. virtual QuicAsyncStatus VerifyCertChain( const std::string& hostname, uint16_t port, + const std::vector<absl::string_view>& certs, + const std::string& ocsp_response, const std::string& cert_sct, + const ProofVerifyContext* context, std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* details, uint8_t* out_alert, + std::unique_ptr<ProofVerifierCallback> callback); + + // Deprecated: Same as VerifyCertChain above, but |certs| contains + // std::strings instead of absl::string_views. + // + // TODO(b/517611362): Remove this once all ProofVerifier implementations + // have migrated to the new VerifyCertChain. + virtual QuicAsyncStatus VerifyCertChain( + const std::string& hostname, uint16_t port, const std::vector<std::string>& certs, const std::string& ocsp_response, const std::string& cert_sct, const ProofVerifyContext* context, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, - uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) = 0; + uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback); // Returns a ProofVerifyContext instance which can be use for subsequent // verifications. Applications may chose create a different context and
diff --git a/quiche/quic/core/tls_client_handshaker.cc b/quiche/quic/core/tls_client_handshaker.cc index 298ffb0..a9829df 100644 --- a/quiche/quic/core/tls_client_handshaker.cc +++ b/quiche/quic/core/tls_client_handshaker.cc
@@ -556,7 +556,7 @@ } QuicAsyncStatus TlsClientHandshaker::VerifyCertChain( - const std::vector<std::string>& certs, std::string* error_details, + const std::vector<absl::string_view>& certs, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) { matched_trust_anchor_id_ = SSL_peer_matched_trust_anchor(ssl());
diff --git a/quiche/quic/core/tls_client_handshaker.h b/quiche/quic/core/tls_client_handshaker.h index 522bf60..6322ac6 100644 --- a/quiche/quic/core/tls_client_handshaker.h +++ b/quiche/quic/core/tls_client_handshaker.h
@@ -106,7 +106,7 @@ void ProcessPostHandshakeMessage() override; bool ShouldCloseConnectionOnUnexpectedError(int ssl_error) override; QuicAsyncStatus VerifyCertChain( - const std::vector<std::string>& certs, std::string* error_details, + const std::vector<absl::string_view>& certs, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) override; void OnProofVerifyDetailsAvailable(
diff --git a/quiche/quic/core/tls_client_handshaker_test.cc b/quiche/quic/core/tls_client_handshaker_test.cc index 6d5c114..d9bede8 100644 --- a/quiche/quic/core/tls_client_handshaker_test.cc +++ b/quiche/quic/core/tls_client_handshaker_test.cc
@@ -80,10 +80,10 @@ QuicAsyncStatus VerifyCertChain( const std::string& hostname, const uint16_t port, - const std::vector<std::string>& certs, const std::string& ocsp_response, - const std::string& cert_sct, const ProofVerifyContext* context, - std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, - uint8_t* out_alert, + const std::vector<absl::string_view>& certs, + const std::string& ocsp_response, const std::string& cert_sct, + const ProofVerifyContext* context, std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* details, uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) override { if (!active_) { return verifier_->VerifyCertChain( @@ -125,7 +125,7 @@ class VerifyChainPendingOp { public: VerifyChainPendingOp(const std::string& hostname, const uint16_t port, - const std::vector<std::string>& certs, + const std::vector<absl::string_view>& certs, const std::string& ocsp_response, const std::string& cert_sct, const ProofVerifyContext* context, @@ -162,7 +162,7 @@ private: std::string hostname_; const uint16_t port_; - std::vector<std::string> certs_; + std::vector<absl::string_view> certs_; std::string ocsp_response_; std::string cert_sct_; const ProofVerifyContext* context_;
diff --git a/quiche/quic/core/tls_handshaker.cc b/quiche/quic/core/tls_handshaker.cc index 9eca933..228e9dd 100644 --- a/quiche/quic/core/tls_handshaker.cc +++ b/quiche/quic/core/tls_handshaker.cc
@@ -258,12 +258,11 @@ *out_alert = SSL_AD_INTERNAL_ERROR; return ssl_verify_invalid; } - // TODO(nharper): Pass the CRYPTO_BUFFERs into the QUIC stack to avoid copies. - std::vector<std::string> certs; + std::vector<absl::string_view> certs; for (CRYPTO_BUFFER* cert : cert_chain) { - certs.push_back( - std::string(reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert)), - CRYPTO_BUFFER_len(cert))); + certs.push_back(absl::string_view( + reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert)), + CRYPTO_BUFFER_len(cert))); } QUIC_DVLOG(1) << "VerifyCert: peer cert_chain length: " << certs.size();
diff --git a/quiche/quic/core/tls_handshaker.h b/quiche/quic/core/tls_handshaker.h index ac7c6c2..cc2ddae 100644 --- a/quiche/quic/core/tls_handshaker.h +++ b/quiche/quic/core/tls_handshaker.h
@@ -112,7 +112,7 @@ // certificate_unknown. Implementations of VerifyCertChain may retain the // |out_alert| pointer while performing an async operation. virtual QuicAsyncStatus VerifyCertChain( - const std::vector<std::string>& certs, std::string* error_details, + const std::vector<absl::string_view>& certs, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) = 0; // Called when certificate verification is completed.
diff --git a/quiche/quic/core/tls_server_handshaker.cc b/quiche/quic/core/tls_server_handshaker.cc index 065edbe..df6adde 100644 --- a/quiche/quic/core/tls_server_handshaker.cc +++ b/quiche/quic/core/tls_server_handshaker.cc
@@ -683,7 +683,7 @@ // proof verifier is not set, the method will assume the certificate chain is // valid and return QUIC_SUCCESS. QuicAsyncStatus TlsServerHandshaker::VerifyCertChain( - const std::vector<std::string>& certs, std::string* error_details, + const std::vector<absl::string_view>& certs, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) { if (proof_verifier_ == nullptr) {
diff --git a/quiche/quic/core/tls_server_handshaker.h b/quiche/quic/core/tls_server_handshaker.h index 01ff093..f3bf04d 100644 --- a/quiche/quic/core/tls_server_handshaker.h +++ b/quiche/quic/core/tls_server_handshaker.h
@@ -168,7 +168,7 @@ void FinishHandshake() override; void ProcessPostHandshakeMessage() override {} QuicAsyncStatus VerifyCertChain( - const std::vector<std::string>& certs, std::string* error_details, + const std::vector<absl::string_view>& certs, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) override; void OnProofVerifyDetailsAvailable(
diff --git a/quiche/quic/core/tls_server_handshaker_test.cc b/quiche/quic/core/tls_server_handshaker_test.cc index 3490a65..bbc5623 100644 --- a/quiche/quic/core/tls_server_handshaker_test.cc +++ b/quiche/quic/core/tls_server_handshaker_test.cc
@@ -112,7 +112,7 @@ MOCK_METHOD(QuicAsyncStatus, VerifyCertChain, (const std::string& hostname, uint16_t port, - const std::vector<std::string>& certs, + const std::vector<absl::string_view>& certs, const std::string& ocsp_response, const std::string& cert_sct, const ProofVerifyContext* context, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, uint8_t* out_alert, @@ -189,7 +189,7 @@ protected: QuicAsyncStatus VerifyCertChain( - const std::vector<std::string>& certs, std::string* error_details, + const std::vector<absl::string_view>& certs, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) override { received_client_cert_ = true;
diff --git a/quiche/quic/masque/masque_connection_pool.cc b/quiche/quic/masque/masque_connection_pool.cc index 7641503..9449966 100644 --- a/quiche/quic/masque/masque_connection_pool.cc +++ b/quiche/quic/masque/masque_connection_pool.cc
@@ -645,11 +645,11 @@ *out_alert = SSL_AD_INTERNAL_ERROR; return ssl_verify_invalid; } - std::vector<std::string> certs; + std::vector<absl::string_view> certs; for (CRYPTO_BUFFER* cert : cert_chain) { - certs.push_back( - std::string(reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert)), - CRYPTO_BUFFER_len(cert))); + certs.push_back(absl::string_view( + reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert)), + CRYPTO_BUFFER_len(cert))); } const uint8_t* ocsp_response_raw; size_t ocsp_response_len;
diff --git a/quiche/quic/masque/masque_tcp_client_bin.cc b/quiche/quic/masque/masque_tcp_client_bin.cc index 828d442..dde3fe1 100644 --- a/quiche/quic/masque/masque_tcp_client_bin.cc +++ b/quiche/quic/masque/masque_tcp_client_bin.cc
@@ -169,11 +169,11 @@ *out_alert = SSL_AD_INTERNAL_ERROR; return ssl_verify_invalid; } - std::vector<std::string> certs; + std::vector<absl::string_view> certs; for (CRYPTO_BUFFER* cert : cert_chain) { - certs.push_back( - std::string(reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert)), - CRYPTO_BUFFER_len(cert))); + certs.push_back(absl::string_view( + reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert)), + CRYPTO_BUFFER_len(cert))); } const uint8_t* ocsp_response_raw; size_t ocsp_response_len;