0

[extensions] less strict CT in verifyTLSServerCertificate

This fix is related to
https://chromium-review.googlesource.com/c/chromium/src/+/6196859

In the cl above I have renamed VerifyCertForSignedExchange -> VerifyCert
thinking that the behavior has nothing specific to SignedExchange (SGX).

As mattm@chromium.org pointed out SGX have stricter CT verification.
Compare the following almost identical code:

https://crsrc.org/c/net/socket/ssl_client_socket_impl.cc;drc=20799f4c32d950ce93d495f44eec648400f38a19;l=1175

https://source.chromium.org/chromium/chromium/src/+/main:services/network/network_context.cc;drc=58fb75d86a0ad2642beec2d6c16b1e6c008e33cd;bpv=1;bpt=1;l=1732?gsn=CheckCTRequirements&gs=KYTHE%3A%2F%2Fkythe%3A%2F%2Fchromium.googlesource.com%2Fcodesearch%2Fchromium%2Fsrc%2F%2Fmain%3Flang%3Dc%252B%252B%3Fpath%3Dservices%2Fnetwork%2Fnetwork_context.cc%231BS5z2OmuEs-qsnFGg_csnxBM8OxwZDyDv74cEaGHm4

They have difference that in SGX mode if CT verifier returns
net::TransportSecurityState::CT_NOT_REQUIRED then failure might happen
in certain conditions.

For platformKeys.verifyTLSServerCertificate we don't need such strict
CT, we would like to have it as usual WebSite https verification.

Design doc is updated accordingly for history
https://docs.google.com/document/d/1jiX_rQf352WWmtkteZFqNxjoNgVDXntVWSHsZlpp5Ts/edit?tab=t.0

(cherry picked from commit 61fdd92424)

Low-Coverage-Reason: OTHER
Fixed: 402033317
Cr-Original-Commit-Position: refs/heads/main@{#1429410}
Change-Id: Ia5ae90fd4927d3f2a9f19c6aa879aa5a384e41c2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6336167
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Vlad Krot <vkrot@google.com>
Cr-Commit-Position: refs/branch-heads/7049@{#375}
Cr-Branched-From: 2dab7846d0951a552bdc4f350dad497f986e6fed-refs/heads/main@{#1427262}
This commit is contained in:
Vlad Krot
2025-03-10 04:46:27 -07:00
committed by Chromium LUCI CQ
parent e13b084de9
commit 6bcb018b3b
5 changed files with 79 additions and 9 deletions

@@ -116,9 +116,9 @@ void VerifyCert(const scoped_refptr<net::X509Certificate>& certificate,
->GetNetworkContext(); ->GetNetworkContext();
} }
network_context->VerifyCert(certificate, net::HostPortPair::FromURL(url), network_context->VerifyCertForSignedExchange(
ocsp_result, sct_list, certificate, net::HostPortPair::FromURL(url), ocsp_result, sct_list,
std::move(wrapped_callback)); std::move(wrapped_callback));
} }
std::string OCSPErrorToString(const bssl::OCSPVerifyResult& ocsp_result) { std::string OCSPErrorToString(const bssl::OCSPVerifyResult& ocsp_result) {

@@ -1731,7 +1731,8 @@ void NetworkContext::SetCTPolicy(mojom::CTPolicyPtr ct_policy) {
int NetworkContext::CheckCTRequirements( int NetworkContext::CheckCTRequirements(
net::CertVerifyResult& cert_verify_result, net::CertVerifyResult& cert_verify_result,
const net::HostPortPair& host_port_pair) { const net::HostPortPair& host_port_pair,
CTVerificationMode ct_verification_mode) {
net::X509Certificate* verified_cert = cert_verify_result.verified_cert.get(); net::X509Certificate* verified_cert = cert_verify_result.verified_cert.get();
net::TransportSecurityState::CTRequirementsStatus ct_requirement_status = net::TransportSecurityState::CTRequirementsStatus ct_requirement_status =
@@ -1751,6 +1752,13 @@ int NetworkContext::CheckCTRequirements(
case net::TransportSecurityState::CT_REQUIREMENTS_MET: case net::TransportSecurityState::CT_REQUIREMENTS_MET:
return net::OK; return net::OK;
case net::TransportSecurityState::CT_NOT_REQUIRED: case net::TransportSecurityState::CT_NOT_REQUIRED:
switch (ct_verification_mode) {
case CTVerificationMode::kTlsCertificate:
return net::OK;
case CTVerificationMode::kSignedExchange:
// Proceed.
break;
}
// CT is not required if the certificate does not chain to a publicly // CT is not required if the certificate does not chain to a publicly
// trusted root certificate. // trusted root certificate.
if (!cert_verify_result.is_issued_by_known_root) { if (!cert_verify_result.is_issued_by_known_root) {
@@ -2035,11 +2043,12 @@ void NetworkContext::CreateHostResolver(
url_request_context_->net_log())); url_request_context_->net_log()));
} }
void NetworkContext::VerifyCert( void NetworkContext::VerifyCertInternal(
const scoped_refptr<net::X509Certificate>& certificate, const scoped_refptr<net::X509Certificate>& certificate,
const net::HostPortPair& host_port, const net::HostPortPair& host_port,
const std::string& ocsp_result, const std::string& ocsp_result,
const std::string& sct_list, const std::string& sct_list,
CTVerificationMode ct_verification_mode,
VerifyCertCallback callback) { VerifyCertCallback callback) {
uint64_t cert_verify_id = ++next_cert_verify_id_; uint64_t cert_verify_id = ++next_cert_verify_id_;
CHECK_NE(0u, next_cert_verify_id_); // The request ID should not wrap around. CHECK_NE(0u, next_cert_verify_id_); // The request ID should not wrap around.
@@ -2050,6 +2059,7 @@ void NetworkContext::VerifyCert(
pending_cert_verify->host_port = host_port; pending_cert_verify->host_port = host_port;
pending_cert_verify->ocsp_result = ocsp_result; pending_cert_verify->ocsp_result = ocsp_result;
pending_cert_verify->sct_list = sct_list; pending_cert_verify->sct_list = sct_list;
pending_cert_verify->ct_verification_mode = ct_verification_mode;
net::CertVerifier* cert_verifier = net::CertVerifier* cert_verifier =
g_cert_verifier_for_testing ? g_cert_verifier_for_testing g_cert_verifier_for_testing ? g_cert_verifier_for_testing
: url_request_context_->cert_verifier(); : url_request_context_->cert_verifier();
@@ -2069,6 +2079,26 @@ void NetworkContext::VerifyCert(
} }
} }
void NetworkContext::VerifyCert(
const scoped_refptr<net::X509Certificate>& certificate,
const net::HostPortPair& host_port,
const std::string& ocsp_result,
const std::string& sct_list,
VerifyCertCallback callback) {
VerifyCertInternal(certificate, host_port, ocsp_result, sct_list,
CTVerificationMode::kTlsCertificate, std::move(callback));
}
void NetworkContext::VerifyCertForSignedExchange(
const scoped_refptr<net::X509Certificate>& certificate,
const net::HostPortPair& host_port,
const std::string& ocsp_result,
const std::string& sct_list,
VerifyCertCallback callback) {
VerifyCertInternal(certificate, host_port, ocsp_result, sct_list,
CTVerificationMode::kSignedExchange, std::move(callback));
}
void NetworkContext::NotifyExternalCacheHit(const GURL& url, void NetworkContext::NotifyExternalCacheHit(const GURL& url,
const std::string& http_method, const std::string& http_method,
const net::NetworkIsolationKey& key, const net::NetworkIsolationKey& key,
@@ -3149,8 +3179,9 @@ void NetworkContext::OnVerifyCertComplete(uint64_t cert_verify_id, int result) {
bool pkp_bypassed = false; bool pkp_bypassed = false;
if (result == net::OK) { if (result == net::OK) {
#if BUILDFLAG(IS_CT_SUPPORTED) #if BUILDFLAG(IS_CT_SUPPORTED)
int ct_result = CheckCTRequirements(*pending_cert_verify->result, int ct_result = CheckCTRequirements(
pending_cert_verify->host_port); *pending_cert_verify->result, pending_cert_verify->host_port,
pending_cert_verify->ct_verification_mode);
#endif // BUILDFLAG(IS_CT_SUPPORTED) #endif // BUILDFLAG(IS_CT_SUPPORTED)
net::TransportSecurityState::PKPStatus pin_validity = net::TransportSecurityState::PKPStatus pin_validity =
url_request_context_->transport_security_state()->CheckPublicKeyPins( url_request_context_->transport_security_state()->CheckPublicKeyPins(

@@ -411,6 +411,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
const std::string& ocsp_result, const std::string& ocsp_result,
const std::string& sct_list, const std::string& sct_list,
VerifyCertCallback callback) override; VerifyCertCallback callback) override;
void VerifyCertForSignedExchange(
const scoped_refptr<net::X509Certificate>& certificate,
const net::HostPortPair& host_port,
const std::string& ocsp_result,
const std::string& sct_list,
VerifyCertCallback callback) override;
void AddHSTS(const std::string& host, void AddHSTS(const std::string& host,
base::Time expiry, base::Time expiry,
bool include_subdomains, bool include_subdomains,
@@ -710,6 +716,15 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
const raw_ptr<NetworkService> network_service_; const raw_ptr<NetworkService> network_service_;
}; };
enum class CTVerificationMode {
// Use specific to signed exchange logic
// that requires certificate transparency compliance.
kSignedExchange,
// Use default certificate transparency verification logic
// like in TLS.
kTlsCertificate
};
// To be called back from CookieManager on settings change. // To be called back from CookieManager on settings change.
void OnCookieManagerSettingsChanged(); void OnCookieManagerSettingsChanged();
@@ -763,6 +778,14 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
void CanUploadDomainReliability(const url::Origin& origin, void CanUploadDomainReliability(const url::Origin& origin,
base::OnceCallback<void(bool)> callback); base::OnceCallback<void(bool)> callback);
void VerifyCertInternal(
const scoped_refptr<net::X509Certificate>& certificate,
const net::HostPortPair& host_port,
const std::string& ocsp_result,
const std::string& sct_list,
CTVerificationMode ct_verification_mode,
VerifyCertCallback callback);
void OnVerifyCertComplete(uint64_t cert_verify_id, int result); void OnVerifyCertComplete(uint64_t cert_verify_id, int result);
#if BUILDFLAG(IS_CT_SUPPORTED) #if BUILDFLAG(IS_CT_SUPPORTED)
@@ -775,7 +798,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
// SSLClientSocket and QUIC. Fold this into some CertVerifier-shaped class // SSLClientSocket and QUIC. Fold this into some CertVerifier-shaped class
// in //net. // in //net.
int CheckCTRequirements(net::CertVerifyResult& cert_verify_result, int CheckCTRequirements(net::CertVerifyResult& cert_verify_result,
const net::HostPortPair& host_port_pair); const net::HostPortPair& host_port_pair,
CTVerificationMode ct_verification_mode);
#endif // BUILDFLAG(IS_CT_SUPPORTED) #endif // BUILDFLAG(IS_CT_SUPPORTED)
#if BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED) #if BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED)
@@ -938,7 +962,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
host_resolvers_; host_resolvers_;
std::unique_ptr<net::HostResolver::ProbeRequest> doh_probes_request_; std::unique_ptr<net::HostResolver::ProbeRequest> doh_probes_request_;
// Used for Signed Exchange certificate verification. // Used for certificate verification.
uint64_t next_cert_verify_id_ = 0; uint64_t next_cert_verify_id_ = 0;
struct PendingCertVerify { struct PendingCertVerify {
PendingCertVerify(); PendingCertVerify();
@@ -953,6 +977,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
net::HostPortPair host_port; net::HostPortPair host_port;
std::string ocsp_result; std::string ocsp_result;
std::string sct_list; std::string sct_list;
CTVerificationMode ct_verification_mode;
}; };
std::map<uint64_t, std::unique_ptr<PendingCertVerify>> std::map<uint64_t, std::unique_ptr<PendingCertVerify>>
cert_verifier_requests_; cert_verifier_requests_;

@@ -1523,6 +1523,14 @@ interface NetworkContext {
string sct_list) string sct_list)
=> (int32 error_code, CertVerifyResult cv_result, bool pkp_bypassed); => (int32 error_code, CertVerifyResult cv_result, bool pkp_bypassed);
// Checks the given certificate against the CertVerifier and CTVerifier.
// This implementation is specific for use by Signed Exchange.
VerifyCertForSignedExchange(X509Certificate certificate,
HostPortPair host_port,
string ocsp_response,
string sct_list)
=> (int32 error_code, CertVerifyResult cv_result, bool pkp_bypassed);
// Adds explicitly-specified data as if it was processed from an // Adds explicitly-specified data as if it was processed from an
// HSTS header. Used by tests and implementation of chrome://net-internals. // HSTS header. Used by tests and implementation of chrome://net-internals.
AddHSTS(string host, mojo_base.mojom.Time expiry, bool include_subdomains) AddHSTS(string host, mojo_base.mojom.Time expiry, bool include_subdomains)

@@ -243,6 +243,12 @@ class TestNetworkContext : public mojom::NetworkContext {
const std::string& ocsp_result, const std::string& ocsp_result,
const std::string& sct_list, const std::string& sct_list,
VerifyCertCallback callback) override {} VerifyCertCallback callback) override {}
void VerifyCertForSignedExchange(
const scoped_refptr<net::X509Certificate>& certificate,
const net::HostPortPair& host_port,
const std::string& ocsp_result,
const std::string& sct_list,
VerifyCertCallback callback) override {}
void IsHSTSActiveForHost(const std::string& host, void IsHSTSActiveForHost(const std::string& host,
bool is_top_level_nav, bool is_top_level_nav,
IsHSTSActiveForHostCallback callback) override {} IsHSTSActiveForHostCallback callback) override {}