0

Use log list timestamp to calculate timeliness.

This CL changes CT enforcement so the log list included timestamp is
used after a CT log list is updated via component updater, instead of
the build date.

Bug: 1199877
Change-Id: I74165814fa29f7ff5d148b28ab6aad6012fa027a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2946451
Commit-Queue: Carlos IL <carlosil@chromium.org>
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
Reviewed-by: danakj <danakj@chromium.org>
Reviewed-by: Ryan Sleevi <rsleevi@chromium.org>
Reviewed-by: Joshua Pawlicki <waffles@chromium.org>
Cr-Commit-Position: refs/heads/master@{#893099}
This commit is contained in:
Carlos IL
2021-06-16 19:19:36 +00:00
committed by Chromium LUCI CQ
parent c482676ff2
commit 1518adb0ef
17 changed files with 151 additions and 31 deletions

@ -193,7 +193,11 @@ void PKIMetadataComponentInstallerPolicy::UpdateNetworkServiceOnUI(
log_list_mojo.push_back(std::move(log_ptr)); log_list_mojo.push_back(std::move(log_ptr));
} }
network_service->UpdateCtLogList(std::move(log_list_mojo)); base::Time update_time =
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(proto->log_list().timestamp().seconds()) +
base::TimeDelta::FromNanoseconds(proto->log_list().timestamp().nanos());
network_service->UpdateCtLogList(std::move(log_list_mojo), update_time);
#endif // BUILDFLAG(IS_CT_SUPPORTED) #endif // BUILDFLAG(IS_CT_SUPPORTED)
} }

@ -526,7 +526,8 @@ void SystemNetworkContextManager::OnNetworkServiceCreated(
} }
log_list_mojo.push_back(std::move(log_info)); log_list_mojo.push_back(std::move(log_info));
} }
network_service->UpdateCtLogList(std::move(log_list_mojo)); network_service->UpdateCtLogList(std::move(log_list_mojo),
base::GetBuildTime());
} }
#endif #endif
@ -680,7 +681,6 @@ void SystemNetworkContextManager::ConfigureDefaultNetworkContextParams(
if (g_enable_certificate_transparency) { if (g_enable_certificate_transparency) {
network_context_params->enforce_chrome_ct_policy = true; network_context_params->enforce_chrome_ct_policy = true;
network_context_params->ct_log_update_time = base::GetBuildTime();
} }
#endif #endif

@ -142,8 +142,10 @@ CTPolicyCompliance ChromeCTPolicyEnforcer::CheckCompliance(
} }
void ChromeCTPolicyEnforcer::UpdateCTLogList( void ChromeCTPolicyEnforcer::UpdateCTLogList(
base::Time update_time,
std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs, std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs,
std::vector<std::string> operated_by_google_logs) { std::vector<std::string> operated_by_google_logs) {
log_list_date_ = update_time;
disqualified_logs_ = std::move(disqualified_logs); disqualified_logs_ = std::move(disqualified_logs);
operated_by_google_logs_ = std::move(operated_by_google_logs); operated_by_google_logs_ = std::move(operated_by_google_logs);
} }

@ -47,6 +47,7 @@ class ChromeCTPolicyEnforcer : public net::CTPolicyEnforcer {
// a map of log ID to disqualification date. |operated_by_google_logs| is a // a map of log ID to disqualification date. |operated_by_google_logs| is a
// list of log IDs operated by Google // list of log IDs operated by Google
void UpdateCTLogList( void UpdateCTLogList(
base::Time update_time,
std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs, std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs,
std::vector<std::string> operated_by_google_logs); std::vector<std::string> operated_by_google_logs);
@ -95,7 +96,7 @@ class ChromeCTPolicyEnforcer : public net::CTPolicyEnforcer {
// The time at which |disqualified_logs_| and |operated_by_google_logs_| were // The time at which |disqualified_logs_| and |operated_by_google_logs_| were
// generated. // generated.
const base::Time log_list_date_; base::Time log_list_date_;
}; };
} // namespace certificate_transparency } // namespace certificate_transparency

@ -480,7 +480,7 @@ TEST_F(ChromeCTPolicyEnforcerTest, UpdateCTLogList) {
std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs; std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs;
std::vector<std::string> operated_by_google_logs; std::vector<std::string> operated_by_google_logs;
chrome_policy_enforcer->UpdateCTLogList(disqualified_logs, chrome_policy_enforcer->UpdateCTLogList(base::Time::Now(), disqualified_logs,
operated_by_google_logs); operated_by_google_logs);
// The check should fail since the Google Aviator log is no longer in the // The check should fail since the Google Aviator log is no longer in the
@ -492,7 +492,7 @@ TEST_F(ChromeCTPolicyEnforcerTest, UpdateCTLogList) {
// Update the list again, this time including all the known operated by Google // Update the list again, this time including all the known operated by Google
// logs. // logs.
operated_by_google_logs = certificate_transparency::GetLogsOperatedByGoogle(); operated_by_google_logs = certificate_transparency::GetLogsOperatedByGoogle();
chrome_policy_enforcer->UpdateCTLogList(disqualified_logs, chrome_policy_enforcer->UpdateCTLogList(base::Time::Now(), disqualified_logs,
operated_by_google_logs); operated_by_google_logs);
// The check should now succeed. // The check should now succeed.
@ -501,6 +501,37 @@ TEST_F(ChromeCTPolicyEnforcerTest, UpdateCTLogList) {
NetLogWithSource())); NetLogWithSource()));
} }
TEST_F(ChromeCTPolicyEnforcerTest, TimestampUpdates) {
ChromeCTPolicyEnforcer* chrome_policy_enforcer =
static_cast<ChromeCTPolicyEnforcer*>(policy_enforcer_.get());
SCTList scts;
FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
2, &scts);
// Clear the log list and set the last updated time to more than 10 weeks ago.
std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs;
std::vector<std::string> operated_by_google_logs;
chrome_policy_enforcer->UpdateCTLogList(
base::Time::Now() - base::TimeDelta::FromDays(71), disqualified_logs,
operated_by_google_logs);
// The check should return build not timely even though the Google Aviator log
// is no longer in the list, since the last update time is greater than 10
// weeks.
EXPECT_EQ(CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY,
chrome_policy_enforcer->CheckCompliance(chain_.get(), scts,
NetLogWithSource()));
// Update the last update time value again, this time with a recent time.
chrome_policy_enforcer->UpdateCTLogList(base::Time::Now(), disqualified_logs,
operated_by_google_logs);
// The check should now fail
EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
chrome_policy_enforcer->CheckCompliance(chain_.get(), scts,
NetLogWithSource()));
}
} // namespace } // namespace
} // namespace certificate_transparency } // namespace certificate_transparency

@ -61,6 +61,7 @@
#include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/ssl/client_cert_identity.h" #include "net/ssl/client_cert_identity.h"
#include "services/device/public/cpp/geolocation/location_system_permission_status.h" #include "services/device/public/cpp/geolocation/location_system_permission_status.h"
#include "services/network/public/mojom/ct_log_info.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/network_service.mojom.h"
#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/features.h"
@ -563,7 +564,6 @@ void ShellContentBrowserClient::ConfigureNetworkContextParamsForShell(
if (g_enable_expect_ct_for_testing) { if (g_enable_expect_ct_for_testing) {
context_params->enforce_chrome_ct_policy = true; context_params->enforce_chrome_ct_policy = true;
context_params->ct_log_update_time = base::Time::Now();
context_params->enable_expect_ct_reporting = true; context_params->enable_expect_ct_reporting = true;
} }
} }
@ -653,4 +653,19 @@ void ShellContentBrowserClient::SetUpFieldTrials() {
&safe_seed_manager, absl::nullopt); &safe_seed_manager, absl::nullopt);
} }
void ShellContentBrowserClient::OnNetworkServiceCreated(
network::mojom::NetworkService* network_service) {
// Explicitly configure Certificate Transparency with no logs, but with
// a fresh enough log update time that policy enforcement will still be
// run. This does not use base::GetBuildTime(), as that may cause certain
// checks to be disabled if too far in the past. Callers that set
// `g_enable_expect_ct_reporting` are expected to simulate CT verification
// using `MockCertVerifier` (otherwise CT validation would fail due to the
// empty log list).
if (g_enable_expect_ct_for_testing) {
network_service->UpdateCtLogList(
std::vector<network::mojom::CTLogInfoPtr>(), base::Time::Now());
}
}
} // namespace content } // namespace content

@ -122,6 +122,8 @@ class ShellContentBrowserClient : public ContentBrowserClient {
void GetHyphenationDictionary( void GetHyphenationDictionary(
base::OnceCallback<void(const base::FilePath&)>) override; base::OnceCallback<void(const base::FilePath&)>) override;
bool HasErrorPage(int http_status_code) override; bool HasErrorPage(int http_status_code) override;
void OnNetworkServiceCreated(
network::mojom::NetworkService* network_service) override;
void CreateFeatureListAndFieldTrials(); void CreateFeatureListAndFieldTrials();

@ -393,7 +393,12 @@ void SetTransportSecurityStateSourceForTesting(
} }
TransportSecurityState::TransportSecurityState() TransportSecurityState::TransportSecurityState()
: TransportSecurityState(std::vector<std::string>()) {} : TransportSecurityState(std::vector<std::string>()) {
// By default the CT log list is treated as last updated at build time (since
// a compiled-in list is used), this is overridden if the list is dynamically
// updated.
ct_log_list_last_update_time_ = base::GetBuildTime();
}
TransportSecurityState::TransportSecurityState( TransportSecurityState::TransportSecurityState(
std::vector<std::string> hsts_host_bypass_list) std::vector<std::string> hsts_host_bypass_list)
@ -607,6 +612,10 @@ void TransportSecurityState::SetRequireCTDelegate(RequireCTDelegate* delegate) {
require_ct_delegate_ = delegate; require_ct_delegate_ = delegate;
} }
void TransportSecurityState::SetCTLogListUpdateTime(base::Time update_time) {
ct_log_list_last_update_time_ = update_time;
}
void TransportSecurityState::AddHSTSInternal( void TransportSecurityState::AddHSTSInternal(
const std::string& host, const std::string& host,
TransportSecurityState::STSState::UpgradeMode upgrade_mode, TransportSecurityState::STSState::UpgradeMode upgrade_mode,
@ -773,7 +782,7 @@ bool TransportSecurityState::GetStaticExpectCTState(
ExpectCTState* expect_ct_state) const { ExpectCTState* expect_ct_state) const {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!IsBuildTimely()) if (!IsCTLogListTimely())
return false; return false;
PreloadResult result; PreloadResult result;
@ -1531,4 +1540,16 @@ bool TransportSecurityState::ExpectCTPruningSorter(
it2->second.last_observed); it2->second.last_observed);
} }
bool TransportSecurityState::IsCTLogListTimely() const {
// Preloaded Expect-CT is enforced if the CT log list is timely. Note that
// unlike HSTS and HPKP, the date of the preloaded list itself (i.e.
// base::GetBuildTime()) is not directly consulted. Consulting the
// build time would allow sites that have subsequently disabled Expect-CT
// to opt-out. However, because as of June 2021, all unexpired certificates
// are already expected to comply with the policies expressed by Expect-CT,
// there's no need to offer an opt-out.
return (base::Time::Now() - ct_log_list_last_update_time_).InDays() <
70 /* 10 weeks */;
}
} // namespace net } // namespace net

@ -440,6 +440,8 @@ class NET_EXPORT TransportSecurityState {
ct_emergency_disable_ = emergency_disable; ct_emergency_disable_ = emergency_disable;
} }
void SetCTLogListUpdateTime(base::Time update_time);
// Clears all dynamic data (e.g. HSTS and HPKP data). // Clears all dynamic data (e.g. HSTS and HPKP data).
// //
// Does NOT persist changes using the Delegate, as this function is only // Does NOT persist changes using the Delegate, as this function is only
@ -691,6 +693,9 @@ class NET_EXPORT TransportSecurityState {
static bool ExpectCTPruningSorter(const ExpectCTStateMap::iterator& it1, static bool ExpectCTPruningSorter(const ExpectCTStateMap::iterator& it1,
const ExpectCTStateMap::iterator& it2); const ExpectCTStateMap::iterator& it2);
// Returns true if the CT log list has been updated in the last 10 weeks.
bool IsCTLogListTimely() const;
// The sets of hosts that have enabled TransportSecurity. |domain| will always // The sets of hosts that have enabled TransportSecurity. |domain| will always
// be empty for a STSState, PKPState, or ExpectCTState in these maps; the // be empty for a STSState, PKPState, or ExpectCTState in these maps; the
// domain comes from the map keys instead. In addition, |upgrade_mode| in the // domain comes from the map keys instead. In addition, |upgrade_mode| in the
@ -736,6 +741,8 @@ class NET_EXPORT TransportSecurityState {
bool ct_emergency_disable_ = false; bool ct_emergency_disable_ = false;
base::Time ct_log_list_last_update_time_;
THREAD_CHECKER(thread_checker_); THREAD_CHECKER(thread_checker_);
DISALLOW_COPY_AND_ASSIGN(TransportSecurityState); DISALLOW_COPY_AND_ASSIGN(TransportSecurityState);

@ -1804,6 +1804,34 @@ TEST_F(TransportSecurityStateTest, CTEmergencyDisable) {
NetworkIsolationKey())); NetworkIsolationKey()));
} }
// Tests that the if the CT log list last update time is set, it is used for
// enforcement decisions.
TEST_F(TransportSecurityStateTest, CTTimestampUpdate) {
TransportSecurityState state;
TransportSecurityStateTest::EnableStaticExpectCT(&state);
TransportSecurityState::ExpectCTState expect_ct_state;
// Initially the preloaded host should require CT.
EXPECT_TRUE(
GetExpectCTState(&state, kExpectCTStaticHostname, &expect_ct_state));
// Change the last updated time to a value greater than 10 weeks.
// We use a close value (70 days + 1 hour ago) to ensure rounding behavior is
// working properly.
state.SetCTLogListUpdateTime(
base::Time::Now() -
(base::TimeDelta::FromDays(70) + base::TimeDelta::FromHours(1)));
// CT should no longer be required.
EXPECT_FALSE(
GetExpectCTState(&state, kExpectCTStaticHostname, &expect_ct_state));
// CT should once again be required after the log list is newer than 70 days.
state.SetCTLogListUpdateTime(
base::Time::Now() -
(base::TimeDelta::FromDays(70) - base::TimeDelta::FromHours(1)));
EXPECT_TRUE(
GetExpectCTState(&state, kExpectCTStaticHostname, &expect_ct_state));
}
// Tests that Certificate Transparency is required for Symantec-issued // Tests that Certificate Transparency is required for Symantec-issued
// certificates, unless the certificate was issued prior to 1 June 2016 // certificates, unless the certificate was issued prior to 1 June 2016
// or the issuing CA is permitted as independently operated. // or the issuing CA is permitted as independently operated.

@ -1274,17 +1274,18 @@ void NetworkContext::SetSCTAuditingEnabled(bool enabled) {
} }
void NetworkContext::OnCTLogListUpdated( void NetworkContext::OnCTLogListUpdated(
const std::vector<network::mojom::CTLogInfoPtr>& log_list) { const std::vector<network::mojom::CTLogInfoPtr>& log_list,
base::Time update_time) {
if (!ct_policy_enforcer_) if (!ct_policy_enforcer_)
return; return;
std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs; std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs;
std::vector<std::string> operated_by_google_logs; std::vector<std::string> operated_by_google_logs;
GetCTPolicyConfigForCTLogInfo(log_list, &disqualified_logs, GetCTPolicyConfigForCTLogInfo(log_list, &disqualified_logs,
&operated_by_google_logs); &operated_by_google_logs);
ct_policy_enforcer_->UpdateCTLogList(std::move(disqualified_logs), ct_policy_enforcer_->UpdateCTLogList(update_time,
std::move(disqualified_logs),
std::move(operated_by_google_logs)); std::move(operated_by_google_logs));
} }
#endif // BUILDFLAG(IS_CT_SUPPORTED) #endif // BUILDFLAG(IS_CT_SUPPORTED)
void NetworkContext::CreateUDPSocket( void NetworkContext::CreateUDPSocket(
@ -1995,10 +1996,9 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
&disqualified_logs, &operated_by_google_logs); &disqualified_logs, &operated_by_google_logs);
auto ct_policy_enforcer = auto ct_policy_enforcer =
std::make_unique<certificate_transparency::ChromeCTPolicyEnforcer>( std::make_unique<certificate_transparency::ChromeCTPolicyEnforcer>(
params_->ct_log_update_time, std::move(disqualified_logs), network_service_->ct_log_list_update_time(),
std::move(operated_by_google_logs)); std::move(disqualified_logs), std::move(operated_by_google_logs));
ct_policy_enforcer_ = ct_policy_enforcer.get(); ct_policy_enforcer_ = ct_policy_enforcer.get();
builder.set_ct_policy_enforcer(std::move(ct_policy_enforcer)); builder.set_ct_policy_enforcer(std::move(ct_policy_enforcer));
} }

@ -278,7 +278,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
signed_certificate_timestamps); signed_certificate_timestamps);
void SetSCTAuditingEnabled(bool enabled) override; void SetSCTAuditingEnabled(bool enabled) override;
void OnCTLogListUpdated( void OnCTLogListUpdated(
const std::vector<network::mojom::CTLogInfoPtr>& log_list); const std::vector<network::mojom::CTLogInfoPtr>& log_list,
base::Time update_time);
bool is_sct_auditing_enabled() { return is_sct_auditing_enabled_; } bool is_sct_auditing_enabled() { return is_sct_auditing_enabled_; }
#endif // BUILDFLAG(IS_CT_SUPPORTED) #endif // BUILDFLAG(IS_CT_SUPPORTED)
void CreateUDPSocket( void CreateUDPSocket(

@ -6078,12 +6078,12 @@ TEST_F(NetworkContextTest, CertificateTransparencyConfig) {
log_list_mojo.push_back(std::move(log_info)); log_list_mojo.push_back(std::move(log_info));
} }
network_service()->UpdateCtLogList(std::move(log_list_mojo)); network_service()->UpdateCtLogList(std::move(log_list_mojo),
base::Time::Now());
// Configure CT params in network context. // Configure CT params in network context.
mojom::NetworkContextParamsPtr params = CreateContextParams(); mojom::NetworkContextParamsPtr params = CreateContextParams();
params->enforce_chrome_ct_policy = true; params->enforce_chrome_ct_policy = true;
params->ct_log_update_time = base::Time::Now();
std::unique_ptr<NetworkContext> network_context = std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(params)); CreateContextWithParams(std::move(params));

@ -730,15 +730,20 @@ void NetworkService::ConfigureSCTAuditing(
sct_auditing_cache_->set_url_loader_factory(std::move(factory)); sct_auditing_cache_->set_url_loader_factory(std::move(factory));
} }
void NetworkService::UpdateCtLogList( void NetworkService::UpdateCtLogList(std::vector<mojom::CTLogInfoPtr> log_list,
std::vector<mojom::CTLogInfoPtr> log_list) { base::Time update_time) {
log_list_ = std::move(log_list); log_list_ = std::move(log_list);
ct_log_list_update_time_ = update_time;
if (base::FeatureList::IsEnabled( if (base::FeatureList::IsEnabled(
certificate_transparency::features:: certificate_transparency::features::
kCertificateTransparencyComponentUpdater)) { kCertificateTransparencyComponentUpdater)) {
ct_log_list_distributor_->OnNewCtConfig(log_list_); ct_log_list_distributor_->OnNewCtConfig(log_list_);
for (auto* context : network_contexts_) { for (auto* context : network_contexts_) {
context->OnCTLogListUpdated(log_list_); context->OnCTLogListUpdated(log_list_, update_time);
context->url_request_context()
->transport_security_state()
->SetCTLogListUpdateTime(update_time);
} }
} }
} }

@ -192,7 +192,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
const GURL& reporting_uri, const GURL& reporting_uri,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
mojo::PendingRemote<mojom::URLLoaderFactory> factory) override; mojo::PendingRemote<mojom::URLLoaderFactory> factory) override;
void UpdateCtLogList(std::vector<mojom::CTLogInfoPtr> log_list) override; void UpdateCtLogList(std::vector<mojom::CTLogInfoPtr> log_list,
base::Time update_time) override;
void SetCtEnforcementEnabled(bool enabled) override; void SetCtEnforcementEnabled(bool enabled) override;
#endif #endif
@ -268,6 +269,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
SCTAuditingCache* sct_auditing_cache() { return sct_auditing_cache_.get(); } SCTAuditingCache* sct_auditing_cache() { return sct_auditing_cache_.get(); }
const std::vector<mojom::CTLogInfoPtr>& log_list() const { return log_list_; } const std::vector<mojom::CTLogInfoPtr>& log_list() const { return log_list_; }
base::Time ct_log_list_update_time() const {
return ct_log_list_update_time_;
}
#endif #endif
mojom::URLLoaderNetworkServiceObserver* mojom::URLLoaderNetworkServiceObserver*
@ -374,6 +379,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
std::vector<mojom::CTLogInfoPtr> log_list_; std::vector<mojom::CTLogInfoPtr> log_list_;
std::unique_ptr<CtLogListDistributor> ct_log_list_distributor_; std::unique_ptr<CtLogListDistributor> ct_log_list_distributor_;
base::Time ct_log_list_update_time_;
#endif #endif
// Map from a renderer process id, to the set of plugin origins embedded by // Map from a renderer process id, to the set of plugin origins embedded by

@ -365,13 +365,6 @@ struct NetworkContextParams {
[EnableIf=is_ct_supported] [EnableIf=is_ct_supported]
CTPolicy? ct_policy; CTPolicy? ct_policy;
// When the built-in Certificate Transparency logs were last updated. If
// |enforce_chrome_ct_policy| is set, and |ct_log_update_time| is not
// sufficiently recent, enforcement of the "Certificate Transparency in
// Chrome" policy will be disabled.
[EnableIf=is_ct_supported]
mojo_base.mojom.Time ct_log_update_time;
// Contains a pipe to a CertVerifierService. // Contains a pipe to a CertVerifierService.
CertVerifierServiceRemoteParams cert_verifier_params; CertVerifierServiceRemoteParams cert_verifier_params;

@ -343,9 +343,12 @@ interface NetworkService {
pending_remote<network.mojom.URLLoaderFactory> factory); pending_remote<network.mojom.URLLoaderFactory> factory);
// Updates the log list used for CT verification. // Updates the log list used for CT verification. `update_time` should
// contain the timestamp that the log list was considered fresh/current, in
// order to ensure that CT is not enforced if the log list is too out of
// date.
[EnableIf=is_ct_supported] [EnableIf=is_ct_supported]
UpdateCtLogList(array<CTLogInfo> log_list); UpdateCtLogList(array<CTLogInfo> log_list, mojo_base.mojom.Time update_time);
// Disables or enables CT Enforcement. // Disables or enables CT Enforcement.
[EnableIf=is_ct_supported] [EnableIf=is_ct_supported]