Add out_alert to ProofVerifier::VerifyCertChain This change will allow a ProofVerifier in the future to provide more detail to the server when closing a connection due to a certificate verification failure. Right now, this CL only plumbs through a new (currently unused) argument to ProofVerifier::VerifyCertChain. PiperOrigin-RevId: 342087110 Change-Id: I4d04b61d8c89b18556a7a6ef08289081087f694b
diff --git a/quic/core/crypto/proof_verifier.h b/quic/core/crypto/proof_verifier.h index 7576620..ab09811 100644 --- a/quic/core/crypto/proof_verifier.h +++ b/quic/core/crypto/proof_verifier.h
@@ -97,6 +97,11 @@ // for some implementations) that provides useful information for the // verifier, e.g. logging handles. // + // If certificate verification fails, a TLS alert will be sent when closing + // the connection. This alert defaults to certificate_unknown. By setting + // |*out_alert|, a different alert can be sent to provide a more specific + // reason why verification failed. + // // This function may also return QUIC_PENDING, in which case the ProofVerifier // will call back, on the original thread, via |callback| when complete. // In this case, the ProofVerifier will take ownership of |callback|. @@ -109,6 +114,7 @@ const ProofVerifyContext* context, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, + uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) = 0; // Returns a ProofVerifyContext instance which can be use for subsequent
diff --git a/quic/core/quic_crypto_client_handshaker_test.cc b/quic/core/quic_crypto_client_handshaker_test.cc index cfae506..2d6db7f 100644 --- a/quic/core/quic_crypto_client_handshaker_test.cc +++ b/quic/core/quic_crypto_client_handshaker_test.cc
@@ -54,6 +54,7 @@ const ProofVerifyContext* /*context*/, std::string* /*error_details*/, std::unique_ptr<ProofVerifyDetails>* /*details*/, + uint8_t* /*out_alert*/, std::unique_ptr<ProofVerifierCallback> /*callback*/) override { return QUIC_SUCCESS; }
diff --git a/quic/core/tls_client_handshaker.cc b/quic/core/tls_client_handshaker.cc index fc69ad6..6ea06b8 100644 --- a/quic/core/tls_client_handshaker.cc +++ b/quic/core/tls_client_handshaker.cc
@@ -376,6 +376,7 @@ const std::vector<std::string>& certs, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, + uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) { const uint8_t* ocsp_response_raw; size_t ocsp_response_len; @@ -390,7 +391,8 @@ return proof_verifier_->VerifyCertChain( server_id_.host(), server_id_.port(), certs, ocsp_response, sct_list, - verify_context_.get(), error_details, details, std::move(callback)); + verify_context_.get(), error_details, details, out_alert, + std::move(callback)); } void TlsClientHandshaker::OnProofVerifyDetailsAvailable(
diff --git a/quic/core/tls_client_handshaker.h b/quic/core/tls_client_handshaker.h index c2707c7..aadfa0b 100644 --- a/quic/core/tls_client_handshaker.h +++ b/quic/core/tls_client_handshaker.h
@@ -92,6 +92,7 @@ const std::vector<std::string>& certs, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, + uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) override; void OnProofVerifyDetailsAvailable( const ProofVerifyDetails& verify_details) override;
diff --git a/quic/core/tls_client_handshaker_test.cc b/quic/core/tls_client_handshaker_test.cc index 7cd7d45..2488426 100644 --- a/quic/core/tls_client_handshaker_test.cc +++ b/quic/core/tls_client_handshaker_test.cc
@@ -74,15 +74,16 @@ 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(hostname, port, certs, ocsp_response, - cert_sct, context, error_details, - details, std::move(callback)); + return verifier_->VerifyCertChain( + hostname, port, certs, ocsp_response, cert_sct, context, + error_details, details, out_alert, std::move(callback)); } pending_ops_.push_back(std::make_unique<VerifyChainPendingOp>( hostname, port, certs, ocsp_response, cert_sct, context, error_details, - details, std::move(callback), verifier_.get())); + details, out_alert, std::move(callback), verifier_.get())); return QUIC_PENDING; } @@ -123,6 +124,7 @@ const ProofVerifyContext* context, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, + uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback, ProofVerifier* delegate) : hostname_(hostname), @@ -133,6 +135,7 @@ context_(context), error_details_(error_details), details_(details), + out_alert_(out_alert), callback_(std::move(callback)), delegate_(delegate) {} @@ -143,7 +146,7 @@ // synchronously. QuicAsyncStatus status = delegate_->VerifyCertChain( hostname_, port_, certs_, ocsp_response_, cert_sct_, context_, - error_details_, details_, + error_details_, details_, out_alert_, std::make_unique<FailingProofVerifierCallback>()); ASSERT_NE(status, QUIC_PENDING); callback_->Run(status == QUIC_SUCCESS, *error_details_, details_); @@ -158,6 +161,7 @@ const ProofVerifyContext* context_; std::string* error_details_; std::unique_ptr<ProofVerifyDetails>* details_; + uint8_t* out_alert_; std::unique_ptr<ProofVerifierCallback> callback_; ProofVerifier* delegate_; };
diff --git a/quic/core/tls_handshaker.cc b/quic/core/tls_handshaker.cc index 495312d..bfe3545 100644 --- a/quic/core/tls_handshaker.cc +++ b/quic/core/tls_handshaker.cc
@@ -146,6 +146,7 @@ expected_ssl_error() == SSL_ERROR_WANT_CERTIFICATE_VERIFY) { enum ssl_verify_result_t result = verify_result_; verify_result_ = ssl_verify_retry; + *out_alert = cert_verify_tls_alert_; return result; } const STACK_OF(CRYPTO_BUFFER)* cert_chain = SSL_get0_peer_certificates(ssl()); @@ -164,8 +165,10 @@ ProofVerifierCallbackImpl* proof_verify_callback = new ProofVerifierCallbackImpl(this); + cert_verify_tls_alert_ = *out_alert; QuicAsyncStatus verify_result = VerifyCertChain( certs, &cert_verify_error_details_, &verify_details_, + &cert_verify_tls_alert_, std::unique_ptr<ProofVerifierCallback>(proof_verify_callback)); switch (verify_result) { case QUIC_SUCCESS: @@ -179,6 +182,7 @@ return ssl_verify_retry; case QUIC_FAILURE: default: + *out_alert = cert_verify_tls_alert_; QUIC_LOG(INFO) << "Cert chain verification failed: " << cert_verify_error_details_; return ssl_verify_invalid;
diff --git a/quic/core/tls_handshaker.h b/quic/core/tls_handshaker.h index 657c9c7..12b27f1 100644 --- a/quic/core/tls_handshaker.h +++ b/quic/core/tls_handshaker.h
@@ -90,10 +90,16 @@ // non-owning pointer to |callback|; the callback must live until this // function returns QUIC_SUCCESS or QUIC_FAILURE, or until the callback is // run. + // + // If certificate verification fails, |*out_alert| may be set to a TLS alert + // that will be sent when closing the connection; it defaults to + // 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, std::unique_ptr<ProofVerifyDetails>* details, + uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) = 0; // Called when certificate verification is completed. virtual void OnProofVerifyDetailsAvailable( @@ -173,6 +179,7 @@ ProofVerifierCallbackImpl* proof_verify_callback_ = nullptr; std::unique_ptr<ProofVerifyDetails> verify_details_; enum ssl_verify_result_t verify_result_ = ssl_verify_retry; + uint8_t cert_verify_tls_alert_ = SSL_AD_CERTIFICATE_UNKNOWN; std::string cert_verify_error_details_; int expected_ssl_error_ = SSL_ERROR_WANT_READ;
diff --git a/quic/core/tls_server_handshaker.cc b/quic/core/tls_server_handshaker.cc index aa49597..e0fe84d 100644 --- a/quic/core/tls_server_handshaker.cc +++ b/quic/core/tls_server_handshaker.cc
@@ -397,6 +397,7 @@ const std::vector<std::string>& /*certs*/, std::string* /*error_details*/, std::unique_ptr<ProofVerifyDetails>* /*details*/, + uint8_t* /*out_alert*/, std::unique_ptr<ProofVerifierCallback> /*callback*/) { QUIC_BUG << "Client certificates are not yet supported on the server"; return QUIC_FAILURE;
diff --git a/quic/core/tls_server_handshaker.h b/quic/core/tls_server_handshaker.h index 2fba611..4d12bf3 100644 --- a/quic/core/tls_server_handshaker.h +++ b/quic/core/tls_server_handshaker.h
@@ -97,6 +97,7 @@ const std::vector<std::string>& certs, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, + uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) override; void OnProofVerifyDetailsAvailable( const ProofVerifyDetails& verify_details) override;
diff --git a/quic/qbone/qbone_session_test.cc b/quic/qbone/qbone_session_test.cc index 92f8fa7..5059274 100644 --- a/quic/qbone/qbone_session_test.cc +++ b/quic/qbone/qbone_session_test.cc
@@ -167,13 +167,14 @@ const ProofVerifyContext* context, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, + uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) override { if (!proof_verifier_) { return QUIC_FAILURE; } return proof_verifier_->VerifyCertChain( hostname, port, certs, ocsp_response, cert_sct, context, error_details, - details, std::move(callback)); + details, out_alert, std::move(callback)); } std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
diff --git a/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc b/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc index 2ea1e44..5932b9c 100644 --- a/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc +++ b/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc
@@ -139,6 +139,7 @@ const ProofVerifyContext* /*context*/, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, + uint8_t* /*out_alert*/, std::unique_ptr<ProofVerifierCallback> /*callback*/) { if (certs.empty()) { *details = std::make_unique<Details>(Status::kInternalError);
diff --git a/quic/quic_transport/web_transport_fingerprint_proof_verifier.h b/quic/quic_transport/web_transport_fingerprint_proof_verifier.h index fba1f83..ad83788 100644 --- a/quic/quic_transport/web_transport_fingerprint_proof_verifier.h +++ b/quic/quic_transport/web_transport_fingerprint_proof_verifier.h
@@ -100,6 +100,7 @@ const ProofVerifyContext* context, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, + uint8_t* out_alert, std::unique_ptr<ProofVerifierCallback> callback) override; std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override;
diff --git a/quic/quic_transport/web_transport_fingerprint_proof_verifier_test.cc b/quic/quic_transport/web_transport_fingerprint_proof_verifier_test.cc index b527ae6..a84a8a5 100644 --- a/quic/quic_transport/web_transport_fingerprint_proof_verifier_test.cc +++ b/quic/quic_transport/web_transport_fingerprint_proof_verifier_test.cc
@@ -40,12 +40,13 @@ VerifyResult Verify(absl::string_view certificate) { VerifyResult result; std::unique_ptr<ProofVerifyDetails> details; + uint8_t tls_alert; result.status = verifier_->VerifyCertChain( /*hostname=*/"", /*port=*/0, std::vector<std::string>{std::string(certificate)}, /*ocsp_response=*/"", /*cert_sct=*/"", - /*context=*/nullptr, &result.error, &details, + /*context=*/nullptr, &result.error, &details, &tls_alert, /*callback=*/nullptr); result.detailed_status = static_cast<WebTransportFingerprintProofVerifier::Details*>(
diff --git a/quic/test_tools/quic_test_client.cc b/quic/test_tools/quic_test_client.cc index d7f2033..5b93de5 100644 --- a/quic/test_tools/quic_test_client.cc +++ b/quic/test_tools/quic_test_client.cc
@@ -82,6 +82,7 @@ const ProofVerifyContext* /*context*/, std::string* /*error_details*/, std::unique_ptr<ProofVerifyDetails>* /*details*/, + uint8_t* /*out_alert*/, std::unique_ptr<ProofVerifierCallback> /*callback*/) override { return ProcessCerts(certs, cert_sct); }
diff --git a/quic/tools/fake_proof_verifier.h b/quic/tools/fake_proof_verifier.h index 2d7d7f4..8707879 100644 --- a/quic/tools/fake_proof_verifier.h +++ b/quic/tools/fake_proof_verifier.h
@@ -38,6 +38,7 @@ const ProofVerifyContext* /*context*/, std::string* /*error_details*/, std::unique_ptr<ProofVerifyDetails>* /*details*/, + uint8_t* /*out_alert*/, std::unique_ptr<ProofVerifierCallback> /*callback*/) override { return QUIC_SUCCESS; }