Add DNS name constraints support to Chrome Root Store constraints
Bug: 40941039 Change-Id: I9a66f35b718cf65c45ade666707c1e5e3898a861 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5943563 Reviewed-by: Joshua Pawlicki <waffles@chromium.org> Reviewed-by: Hubert Chao <hchao@chromium.org> Commit-Queue: Matt Mueller <mattm@chromium.org> Cr-Commit-Position: refs/heads/main@{#1372832}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
dd890d94b0
commit
2367275f29
chrome/browser/component_updater
net
cert
data
ssl
chrome_root_store
tools
root_store_tool
@ -599,13 +599,7 @@ class PKIMetadataComponentChromeRootStoreUpdateTest
|
||||
raw_ptr<PKIMetadataComponentChromeRootStoreUpdateTest> test_;
|
||||
};
|
||||
|
||||
void InstallCRSUpdate(const std::vector<std::string>& der_roots) {
|
||||
chrome_root_store::RootStore root_store_proto;
|
||||
root_store_proto.set_version_major(++last_used_crs_version_);
|
||||
for (const auto& der_root : der_roots) {
|
||||
root_store_proto.add_trust_anchors()->set_der(der_root);
|
||||
}
|
||||
|
||||
void InstallCRSUpdate(chrome_root_store::RootStore root_store_proto) {
|
||||
{
|
||||
base::ScopedAllowBlockingForTesting allow_blocking;
|
||||
ASSERT_TRUE(
|
||||
@ -620,6 +614,16 @@ class PKIMetadataComponentChromeRootStoreUpdateTest
|
||||
waiter.Wait();
|
||||
}
|
||||
|
||||
void InstallCRSUpdate(const std::vector<std::string>& der_roots) {
|
||||
chrome_root_store::RootStore root_store_proto;
|
||||
root_store_proto.set_version_major(++last_used_crs_version_);
|
||||
for (const auto& der_root : der_roots) {
|
||||
root_store_proto.add_trust_anchors()->set_der(der_root);
|
||||
}
|
||||
|
||||
InstallCRSUpdate(std::move(root_store_proto));
|
||||
}
|
||||
|
||||
protected:
|
||||
base::ScopedTempDir component_dir_;
|
||||
|
||||
@ -763,6 +767,83 @@ IN_PROC_BROWSER_TEST_F(PKIMetadataComponentChromeRootStoreUpdateTest,
|
||||
ssl_test_util::AuthState::SHOWING_INTERSTITIAL);
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(PKIMetadataComponentChromeRootStoreUpdateTest,
|
||||
CheckCRSUpdateDnsConstraint) {
|
||||
net::EmbeddedTestServer https_server_ok(net::EmbeddedTestServer::TYPE_HTTPS);
|
||||
net::EmbeddedTestServer::ServerCertificateConfig server_config;
|
||||
server_config.dns_names = {"*.example.com"};
|
||||
https_server_ok.SetSSLConfig(server_config);
|
||||
https_server_ok.ServeFilesFromSourceDirectory("chrome/test/data");
|
||||
|
||||
// Clear test roots so that cert validation only happens with
|
||||
// what's in Chrome Root Store.
|
||||
net::TestRootCerts::GetInstance()->Clear();
|
||||
|
||||
ASSERT_TRUE(https_server_ok.Start());
|
||||
ASSERT_TRUE(ui_test_utils::NavigateToURL(
|
||||
browser(), https_server_ok.GetURL("a.example.com", "/simple.html")));
|
||||
|
||||
// The page should be blocked as the test root is not trusted yet.
|
||||
content::WebContents* tab = chrome_test_utils::GetActiveWebContents(this);
|
||||
ASSERT_TRUE(WaitForRenderFrameReady(tab->GetPrimaryMainFrame()));
|
||||
EXPECT_NE(chrome_test_utils::GetActiveWebContents(this)->GetTitle(), u"OK");
|
||||
ssl_test_util::CheckAuthenticationBrokenState(
|
||||
tab, net::CERT_STATUS_AUTHORITY_INVALID,
|
||||
ssl_test_util::AuthState::SHOWING_INTERSTITIAL);
|
||||
|
||||
int64_t crs_version = net::CompiledChromeRootStoreVersion();
|
||||
scoped_refptr<net::X509Certificate> root_cert =
|
||||
net::ImportCertFromFile(net::EmbeddedTestServer::GetRootCertPemPath());
|
||||
ASSERT_TRUE(root_cert);
|
||||
// Install CRS update that trusts root with a constraint that matches the
|
||||
// leaf's subjectAltName.
|
||||
{
|
||||
chrome_root_store::RootStore root_store_proto;
|
||||
root_store_proto.set_version_major(++crs_version);
|
||||
chrome_root_store::TrustAnchor* anchor =
|
||||
root_store_proto.add_trust_anchors();
|
||||
anchor->set_der(std::string(
|
||||
net::x509_util::CryptoBufferAsStringPiece(root_cert->cert_buffer())));
|
||||
anchor->add_constraints()->add_permitted_dns_names("example.com");
|
||||
|
||||
InstallCRSUpdate(std::move(root_store_proto));
|
||||
}
|
||||
|
||||
ASSERT_TRUE(ui_test_utils::NavigateToURL(
|
||||
browser(), https_server_ok.GetURL("b.example.com", "/simple.html")));
|
||||
|
||||
// Check that the page is allowed now.
|
||||
tab = chrome_test_utils::GetActiveWebContents(this);
|
||||
ASSERT_TRUE(WaitForRenderFrameReady(tab->GetPrimaryMainFrame()));
|
||||
EXPECT_EQ(chrome_test_utils::GetActiveWebContents(this)->GetTitle(), u"OK");
|
||||
ssl_test_util::CheckAuthenticatedState(tab, ssl_test_util::AuthState::NONE);
|
||||
|
||||
// Install CRS update that trusts root with a constraint that does not match
|
||||
// the leaf's subjectAltName.
|
||||
{
|
||||
chrome_root_store::RootStore root_store_proto;
|
||||
root_store_proto.set_version_major(++crs_version);
|
||||
chrome_root_store::TrustAnchor* anchor =
|
||||
root_store_proto.add_trust_anchors();
|
||||
anchor->set_der(std::string(
|
||||
net::x509_util::CryptoBufferAsStringPiece(root_cert->cert_buffer())));
|
||||
anchor->add_constraints()->add_permitted_dns_names("example.org");
|
||||
|
||||
InstallCRSUpdate(std::move(root_store_proto));
|
||||
}
|
||||
|
||||
ASSERT_TRUE(ui_test_utils::NavigateToURL(
|
||||
browser(), https_server_ok.GetURL("c.example.com", "/simple.html")));
|
||||
|
||||
// Check that the page is blocked now.
|
||||
tab = chrome_test_utils::GetActiveWebContents(this);
|
||||
ASSERT_TRUE(WaitForRenderFrameReady(tab->GetPrimaryMainFrame()));
|
||||
EXPECT_NE(chrome_test_utils::GetActiveWebContents(this)->GetTitle(), u"OK");
|
||||
ssl_test_util::CheckAuthenticationBrokenState(
|
||||
tab, net::CERT_STATUS_AUTHORITY_INVALID,
|
||||
ssl_test_util::AuthState::SHOWING_INTERSTITIAL);
|
||||
}
|
||||
|
||||
// Test suite for tests that depend on both Certificate Transparency and Chrome
|
||||
// Root Store updates.
|
||||
class PKIMetadataComponentCtAndCrsUpdaterTest
|
||||
|
@ -477,6 +477,30 @@ class PathBuilderDelegateImpl : public bssl::SimplePathBuilderDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
if (!constraint.permitted_dns_names.empty()) {
|
||||
bssl::GeneralNames permitted_names;
|
||||
for (const auto& dns_name : constraint.permitted_dns_names) {
|
||||
permitted_names.dns_names.push_back(dns_name);
|
||||
}
|
||||
permitted_names.present_name_types |=
|
||||
bssl::GeneralNameTypes::GENERAL_NAME_DNS_NAME;
|
||||
|
||||
std::unique_ptr<bssl::NameConstraints> nc =
|
||||
bssl::NameConstraints::CreateFromPermittedSubtrees(
|
||||
std::move(permitted_names));
|
||||
|
||||
const std::shared_ptr<const bssl::ParsedCertificate>& leaf_cert =
|
||||
path->certs[0];
|
||||
bssl::CertErrors name_constraint_errors;
|
||||
nc->IsPermittedCert(leaf_cert->normalized_subject(),
|
||||
leaf_cert->subject_alt_names(),
|
||||
&name_constraint_errors);
|
||||
if (name_constraint_errors.ContainsAnyErrorWithSeverity(
|
||||
bssl::CertError::SEVERITY_HIGH)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (constraint.min_version.has_value() &&
|
||||
version_info::GetVersion() < constraint.min_version.value()) {
|
||||
return false;
|
||||
|
@ -1659,6 +1659,51 @@ TEST_F(CertVerifyProcBuiltinTest, ChromeRootStoreConstraintMinAndMaxVersion) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CertVerifyProcBuiltinTest, ChromeRootStoreConstraintNameConstraints) {
|
||||
auto [leaf, root] = CertBuilder::CreateSimpleChain2();
|
||||
ScopedTestRoot scoped_root(root->GetX509Certificate());
|
||||
|
||||
// If the the CRS root has dns name constraints and the cert's names don't
|
||||
// match the name constraints, verification should fail.
|
||||
{
|
||||
std::array<std::string_view, 2> permitted_dns_names = {
|
||||
std::string_view("example.org"),
|
||||
std::string_view("foo.example.com"),
|
||||
};
|
||||
SetMockChromeRootConstraints(
|
||||
{{.permitted_dns_names = permitted_dns_names}});
|
||||
CertVerifyResult verify_result;
|
||||
NetLogSource verify_net_log_source;
|
||||
TestCompletionCallback callback;
|
||||
Verify(leaf->GetX509Certificate(), "www.example.com",
|
||||
/*flags=*/0, &verify_result, &verify_net_log_source,
|
||||
callback.callback());
|
||||
|
||||
int error = callback.WaitForResult();
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
|
||||
}
|
||||
|
||||
// If cert's names match the CRS name constraints, verification should
|
||||
// succeed.
|
||||
{
|
||||
std::array<std::string_view, 2> permitted_dns_names = {
|
||||
std::string_view("example.org"),
|
||||
std::string_view("example.com"),
|
||||
};
|
||||
SetMockChromeRootConstraints(
|
||||
{{.permitted_dns_names = permitted_dns_names}});
|
||||
CertVerifyResult verify_result;
|
||||
NetLogSource verify_net_log_source;
|
||||
TestCompletionCallback callback;
|
||||
Verify(leaf->GetX509Certificate(), "www.example.com",
|
||||
/*flags=*/0, &verify_result, &verify_net_log_source,
|
||||
callback.callback());
|
||||
|
||||
int error = callback.WaitForResult();
|
||||
EXPECT_THAT(error, IsOk());
|
||||
}
|
||||
}
|
||||
|
||||
// Tests multiple constraint objects in the constraints vector. The CRS
|
||||
// constraints are satisfied if at least one of the constraint objects is
|
||||
// satisfied.
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/containers/span.h"
|
||||
#include "base/containers/to_vector.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
@ -32,17 +33,23 @@ ChromeRootCertConstraints::ChromeRootCertConstraints(
|
||||
std::optional<base::Time> sct_not_after,
|
||||
std::optional<base::Time> sct_all_after,
|
||||
std::optional<base::Version> min_version,
|
||||
std::optional<base::Version> max_version_exclusive)
|
||||
std::optional<base::Version> max_version_exclusive,
|
||||
std::vector<std::string> permitted_dns_names)
|
||||
: sct_not_after(sct_not_after),
|
||||
sct_all_after(sct_all_after),
|
||||
min_version(std::move(min_version)),
|
||||
max_version_exclusive(std::move(max_version_exclusive)) {}
|
||||
max_version_exclusive(std::move(max_version_exclusive)),
|
||||
permitted_dns_names(std::move(permitted_dns_names)) {}
|
||||
|
||||
ChromeRootCertConstraints::ChromeRootCertConstraints(
|
||||
const StaticChromeRootCertConstraints& constraints)
|
||||
: sct_not_after(constraints.sct_not_after),
|
||||
sct_all_after(constraints.sct_all_after),
|
||||
min_version(constraints.min_version),
|
||||
max_version_exclusive(constraints.max_version_exclusive) {
|
||||
for (std::string_view name : constraints.permitted_dns_names) {
|
||||
permitted_dns_names.emplace_back(name);
|
||||
}
|
||||
if (min_version) {
|
||||
CHECK(min_version->IsValid());
|
||||
}
|
||||
@ -50,6 +57,7 @@ ChromeRootCertConstraints::ChromeRootCertConstraints(
|
||||
CHECK(max_version_exclusive->IsValid());
|
||||
}
|
||||
}
|
||||
|
||||
ChromeRootCertConstraints::~ChromeRootCertConstraints() = default;
|
||||
ChromeRootCertConstraints::ChromeRootCertConstraints(
|
||||
const ChromeRootCertConstraints& other) = default;
|
||||
@ -134,7 +142,8 @@ ChromeRootStoreData::CreateChromeRootStoreData(
|
||||
? std::optional(base::Time::UnixEpoch() +
|
||||
base::Seconds(constraint.sct_all_after_sec()))
|
||||
: std::nullopt,
|
||||
min_version, max_version_exclusive);
|
||||
min_version, max_version_exclusive,
|
||||
base::ToVector(constraint.permitted_dns_names()));
|
||||
}
|
||||
root_store_data.anchors_.emplace_back(std::move(parsed),
|
||||
std::move(constraints));
|
||||
@ -298,6 +307,8 @@ TrustStoreChrome::ParseCrsConstraintsSwitch(std::string_view switch_value) {
|
||||
continue;
|
||||
}
|
||||
constraint.max_version_exclusive = version;
|
||||
} else if (constraint_name_lower == "dns") {
|
||||
constraint.permitted_dns_names.push_back(constraint_value);
|
||||
} else {
|
||||
LOG(ERROR) << "unrecognized constraint " << constraint_name_lower;
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ struct StaticChromeRootCertConstraints {
|
||||
|
||||
std::optional<std::string_view> min_version;
|
||||
std::optional<std::string_view> max_version_exclusive;
|
||||
|
||||
base::span<const std::string_view> permitted_dns_names;
|
||||
};
|
||||
|
||||
struct ChromeRootCertInfo {
|
||||
@ -43,7 +45,8 @@ struct NET_EXPORT ChromeRootCertConstraints {
|
||||
ChromeRootCertConstraints(std::optional<base::Time> sct_not_after,
|
||||
std::optional<base::Time> sct_all_after,
|
||||
std::optional<base::Version> min_version,
|
||||
std::optional<base::Version> max_version_exclusive);
|
||||
std::optional<base::Version> max_version_exclusive,
|
||||
std::vector<std::string> permitted_dns_names);
|
||||
explicit ChromeRootCertConstraints(
|
||||
const StaticChromeRootCertConstraints& constraints);
|
||||
~ChromeRootCertConstraints();
|
||||
@ -57,6 +60,8 @@ struct NET_EXPORT ChromeRootCertConstraints {
|
||||
|
||||
std::optional<base::Version> min_version;
|
||||
std::optional<base::Version> max_version_exclusive;
|
||||
|
||||
std::vector<std::string> permitted_dns_names;
|
||||
};
|
||||
|
||||
// ChromeRootStoreData is a container class that stores all of the Chrome Root
|
||||
@ -119,6 +124,7 @@ class NET_EXPORT TrustStoreChrome : public bssl::TrustStore {
|
||||
// `sctallafter=${seconds_since_epoch}`
|
||||
// `minversion=${dotted_version_string}`
|
||||
// `maxversionexclusive=${dotted_version_string}`
|
||||
// `dns=${permitted_dns_name}` (can be specified multiple times)
|
||||
//
|
||||
// If the same root hash is specified multiple times in separate constraint
|
||||
// specifications, each time will create a new constraintset for that root,
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "net/test/cert_builder.h"
|
||||
#include "net/test/cert_test_util.h"
|
||||
#include "net/test/test_data_directory.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "third_party/boringssl/src/pki/cert_errors.h"
|
||||
#include "third_party/boringssl/src/pki/parsed_certificate.h"
|
||||
@ -117,7 +118,7 @@ TEST(TrustStoreChromeTestNoFixture, Constraints) {
|
||||
ASSERT_TRUE(constrained_cert);
|
||||
base::span<const ChromeRootCertConstraints> constraints =
|
||||
trust_store_chrome->GetConstraintsForCert(constrained_cert.get());
|
||||
ASSERT_EQ(constraints.size(), 2U);
|
||||
ASSERT_EQ(constraints.size(), 3U);
|
||||
|
||||
EXPECT_FALSE(constraints[0].sct_all_after.has_value());
|
||||
ASSERT_TRUE(constraints[0].sct_not_after.has_value());
|
||||
@ -129,6 +130,8 @@ TEST(TrustStoreChromeTestNoFixture, Constraints) {
|
||||
ASSERT_TRUE(constraints[0].max_version_exclusive.has_value());
|
||||
EXPECT_EQ(constraints[0].max_version_exclusive.value().components(),
|
||||
std::vector<uint32_t>({125, 0, 6368, 2}));
|
||||
EXPECT_THAT(constraints[0].permitted_dns_names,
|
||||
testing::ElementsAre("foo.example.com", "bar.example.com"));
|
||||
|
||||
EXPECT_FALSE(constraints[1].sct_not_after.has_value());
|
||||
ASSERT_TRUE(constraints[1].sct_all_after.has_value());
|
||||
@ -140,6 +143,10 @@ TEST(TrustStoreChromeTestNoFixture, Constraints) {
|
||||
EXPECT_FALSE(constraints[1].max_version_exclusive.has_value());
|
||||
EXPECT_EQ(constraints[1].min_version.value().components(),
|
||||
std::vector<uint32_t>({128}));
|
||||
EXPECT_TRUE(constraints[1].permitted_dns_names.empty());
|
||||
|
||||
EXPECT_THAT(constraints[2].permitted_dns_names,
|
||||
testing::ElementsAre("baz.example.com"));
|
||||
|
||||
// Other certificates should return nullptr if they are queried for CRS
|
||||
// constraints. Which test cert used here isn't important as long as it isn't
|
||||
@ -183,16 +190,25 @@ TEST(TrustStoreChromeTestNoFixture, OverrideConstraints) {
|
||||
override_constraints;
|
||||
|
||||
override_constraints[crypto::SHA256Hash(root3->cert_span())] = {
|
||||
{std::nullopt, std::nullopt, std::nullopt,
|
||||
/*max_version_exclusive=*/std::make_optional(base::Version("31"))}};
|
||||
{std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
/*max_version_exclusive=*/std::make_optional(base::Version("31")),
|
||||
{}}};
|
||||
|
||||
override_constraints[crypto::SHA256Hash(root4->cert_span())] = {
|
||||
{std::nullopt, std::nullopt, std::nullopt,
|
||||
/*max_version_exclusive=*/std::make_optional(base::Version("41"))}};
|
||||
{std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
/*max_version_exclusive=*/std::make_optional(base::Version("41")),
|
||||
{}}};
|
||||
|
||||
override_constraints[crypto::SHA256Hash(root6->cert_span())] = {
|
||||
{std::nullopt, std::nullopt, std::nullopt,
|
||||
/*max_version_exclusive=*/std::make_optional(base::Version("61"))}};
|
||||
{std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
/*max_version_exclusive=*/std::make_optional(base::Version("61")),
|
||||
{}}};
|
||||
|
||||
std::unique_ptr<TrustStoreChrome> trust_store_chrome =
|
||||
TrustStoreChrome::CreateTrustStoreForTesting(
|
||||
@ -325,6 +341,7 @@ TEST(TrustStoreChromeTestNoFixture, ParseCommandLineConstraintsErrorHandling) {
|
||||
EXPECT_FALSE(constraint1.sct_all_after.has_value());
|
||||
EXPECT_FALSE(constraint1.min_version.has_value());
|
||||
EXPECT_FALSE(constraint1.max_version_exclusive.has_value());
|
||||
EXPECT_THAT(constraint1.permitted_dns_names, testing::IsEmpty());
|
||||
}
|
||||
{
|
||||
constexpr uint8_t hash[] = {0xa7, 0xe0, 0xc7, 0x5d, 0x7f, 0x77, 0x2f, 0xcc,
|
||||
@ -342,6 +359,7 @@ TEST(TrustStoreChromeTestNoFixture, ParseCommandLineConstraintsErrorHandling) {
|
||||
EXPECT_FALSE(constraint1.sct_all_after.has_value());
|
||||
EXPECT_FALSE(constraint1.min_version.has_value());
|
||||
EXPECT_FALSE(constraint1.max_version_exclusive.has_value());
|
||||
EXPECT_THAT(constraint1.permitted_dns_names, testing::IsEmpty());
|
||||
}
|
||||
|
||||
{
|
||||
@ -360,6 +378,7 @@ TEST(TrustStoreChromeTestNoFixture, ParseCommandLineConstraintsErrorHandling) {
|
||||
EXPECT_FALSE(constraint.sct_all_after.has_value());
|
||||
EXPECT_FALSE(constraint.min_version.has_value());
|
||||
EXPECT_EQ(constraint.max_version_exclusive, base::Version({2, 3}));
|
||||
EXPECT_THAT(constraint.permitted_dns_names, testing::IsEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@ -392,7 +411,8 @@ TEST(TrustStoreChromeTestNoFixture,
|
||||
"784ecaa8b9dfcc826547f806f759abd6b4481582fc7e377dc3e6a0a959025126,"
|
||||
"a7e0c75d7f772fccf26a6ac1f7b0a86a482e2f3d326bc911c95d56ff3d4906d5:"
|
||||
"sctnotafter=123456,sctallafter=7689,"
|
||||
"minversion=1.2.3.4,maxversionexclusive=10+"
|
||||
"minversion=1.2.3.4,maxversionexclusive=10,"
|
||||
"dns=foo.com,dns=bar.com+"
|
||||
"a7e0c75d7f772fccf26a6ac1f7b0a86a482e2f3d326bc911c95d56ff3d4906d5,"
|
||||
"568c8ef6b526d1394bca052ba3e4d1f4d7a8d9c88c55a1a9ab7ca0fae2dc5473:"
|
||||
"sctallafter=9876543,sctnotafter=1234567890");
|
||||
@ -415,6 +435,8 @@ TEST(TrustStoreChromeTestNoFixture,
|
||||
7689);
|
||||
EXPECT_EQ(constraint1.min_version, base::Version({1, 2, 3, 4}));
|
||||
EXPECT_EQ(constraint1.max_version_exclusive, base::Version({10}));
|
||||
EXPECT_THAT(constraint1.permitted_dns_names,
|
||||
testing::ElementsAre("foo.com", "bar.com"));
|
||||
}
|
||||
|
||||
{
|
||||
@ -435,6 +457,8 @@ TEST(TrustStoreChromeTestNoFixture,
|
||||
7689);
|
||||
EXPECT_EQ(constraint1.min_version, base::Version({1, 2, 3, 4}));
|
||||
EXPECT_EQ(constraint1.max_version_exclusive, base::Version({10}));
|
||||
EXPECT_THAT(constraint1.permitted_dns_names,
|
||||
testing::ElementsAre("foo.com", "bar.com"));
|
||||
|
||||
const auto& constraint2 = it->second[1];
|
||||
ASSERT_TRUE(constraint2.sct_not_after.has_value());
|
||||
@ -445,6 +469,7 @@ TEST(TrustStoreChromeTestNoFixture,
|
||||
9876543);
|
||||
EXPECT_FALSE(constraint2.min_version.has_value());
|
||||
EXPECT_FALSE(constraint2.max_version_exclusive.has_value());
|
||||
EXPECT_THAT(constraint2.permitted_dns_names, testing::IsEmpty());
|
||||
}
|
||||
|
||||
{
|
||||
@ -464,6 +489,7 @@ TEST(TrustStoreChromeTestNoFixture,
|
||||
9876543);
|
||||
EXPECT_FALSE(constraint1.min_version.has_value());
|
||||
EXPECT_FALSE(constraint1.max_version_exclusive.has_value());
|
||||
EXPECT_THAT(constraint1.permitted_dns_names, testing::IsEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,11 @@ message ConstraintSet {
|
||||
// For example, max_version_exclusive="122" will match any M-121 or earlier
|
||||
// version, and will not match any M-122 version.
|
||||
optional string max_version_exclusive = 4;
|
||||
|
||||
// All DNS names in the leaf certificate subjectAltNames must fall within the
|
||||
// subtrees defined by `permitted_dns_names`. The constraints are interpereted
|
||||
// as described in RFC 5280 section 4.2.1.10.
|
||||
repeated string permitted_dns_names = 5;
|
||||
}
|
||||
|
||||
message TrustAnchor {
|
||||
|
@ -18,9 +18,14 @@ trust_anchors {
|
||||
constraints: {
|
||||
sct_not_after_sec: 0x5AF
|
||||
max_version_exclusive: "125.0.6368.2"
|
||||
permitted_dns_names: "foo.example.com"
|
||||
permitted_dns_names: "bar.example.com"
|
||||
}
|
||||
constraints: {
|
||||
sct_all_after_sec: 0x2579
|
||||
min_version: "128"
|
||||
}
|
||||
constraints: {
|
||||
permitted_dns_names: "baz.example.com"
|
||||
}
|
||||
}
|
||||
|
@ -186,12 +186,28 @@ bool WriteRootCppFile(const RootStore& root_store,
|
||||
string_to_write += "};\n";
|
||||
|
||||
if (anchor.constraints_size() > 0) {
|
||||
int constraint_num = 0;
|
||||
for (const auto& constraint : anchor.constraints()) {
|
||||
if (constraint.permitted_dns_names_size() > 0) {
|
||||
base::StringAppendF(&string_to_write,
|
||||
"constexpr std::string_view "
|
||||
"kChromeRootConstraint%dNames%d[] = {",
|
||||
i, constraint_num);
|
||||
for (const auto& name : constraint.permitted_dns_names()) {
|
||||
base::StringAppendF(&string_to_write, "\"%s\",", name);
|
||||
}
|
||||
string_to_write += "};\n";
|
||||
}
|
||||
constraint_num++;
|
||||
}
|
||||
|
||||
base::StringAppendF(&string_to_write,
|
||||
"constexpr StaticChromeRootCertConstraints "
|
||||
"kChromeRootConstraints%d[] = {",
|
||||
i);
|
||||
|
||||
std::vector<std::string> constraint_strings;
|
||||
constraint_num = 0;
|
||||
for (const auto& constraint : anchor.constraints()) {
|
||||
std::vector<std::string> constraint_params;
|
||||
|
||||
@ -215,8 +231,17 @@ bool WriteRootCppFile(const RootStore& root_store,
|
||||
? VersionFromString(constraint.max_version_exclusive())
|
||||
: kNulloptString);
|
||||
|
||||
if (constraint.permitted_dns_names_size() > 0) {
|
||||
constraint_params.push_back(base::StringPrintf(
|
||||
"kChromeRootConstraint%dNames%d", i, constraint_num));
|
||||
} else {
|
||||
constraint_params.push_back("{}");
|
||||
}
|
||||
|
||||
constraint_strings.push_back(
|
||||
base::StrCat({"{", base::JoinString(constraint_params, ","), "}"}));
|
||||
|
||||
constraint_num++;
|
||||
}
|
||||
|
||||
string_to_write += base::JoinString(constraint_strings, ",");
|
||||
|
Reference in New Issue
Block a user