1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/memory/raw_ptr.h"
6 #include "net/cert/internal/system_trust_store.h"
7
8 #include <cert.h>
9 #include <certdb.h>
10
11 #include <memory>
12
13 #include "crypto/scoped_nss_types.h"
14 #include "crypto/scoped_test_nss_db.h"
15 #include "net/cert/internal/system_trust_store_nss.h"
16 #include "net/cert/internal/trust_store_chrome.h"
17 #include "net/cert/internal/trust_store_features.h"
18 #include "net/cert/test_root_certs.h"
19 #include "net/cert/x509_certificate.h"
20 #include "net/cert/x509_util.h"
21 #include "net/cert/x509_util_nss.h"
22 #include "net/test/cert_test_util.h"
23 #include "net/test/test_data_directory.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/boringssl/src/include/openssl/evp.h"
27 #include "third_party/boringssl/src/pki/cert_errors.h"
28 #include "third_party/boringssl/src/pki/parsed_certificate.h"
29
30 namespace net {
31
32 namespace {
33
34 // Parses |x509_cert| as a bssl::ParsedCertificate and stores the output in
35 // *|out_parsed_cert|. Wrap in ASSERT_NO_FATAL_FAILURE on callsites.
ParseX509Certificate(const scoped_refptr<X509Certificate> & x509_cert,std::shared_ptr<const bssl::ParsedCertificate> * out_parsed_cert)36 ::testing::AssertionResult ParseX509Certificate(
37 const scoped_refptr<X509Certificate>& x509_cert,
38 std::shared_ptr<const bssl::ParsedCertificate>* out_parsed_cert) {
39 bssl::CertErrors parsing_errors;
40 *out_parsed_cert = bssl::ParsedCertificate::Create(
41 bssl::UpRef(x509_cert->cert_buffer()),
42 x509_util::DefaultParseCertificateOptions(), &parsing_errors);
43 if (!*out_parsed_cert) {
44 return ::testing::AssertionFailure()
45 << "bssl::ParseCertificate::Create() failed:\n"
46 << parsing_errors.ToDebugString();
47 }
48 return ::testing::AssertionSuccess();
49 }
50
51 class SystemTrustStoreNSSTest : public ::testing::Test {
52 public:
SystemTrustStoreNSSTest()53 SystemTrustStoreNSSTest() : test_root_certs_(TestRootCerts::GetInstance()) {}
54
55 SystemTrustStoreNSSTest(const SystemTrustStoreNSSTest&) = delete;
56 SystemTrustStoreNSSTest& operator=(const SystemTrustStoreNSSTest&) = delete;
57
58 ~SystemTrustStoreNSSTest() override = default;
59
SetUp()60 void SetUp() override {
61 ::testing::Test::SetUp();
62
63 root_cert_ =
64 ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem");
65 ASSERT_TRUE(root_cert_);
66 ASSERT_NO_FATAL_FAILURE(
67 ParseX509Certificate(root_cert_, &parsed_root_cert_));
68 nss_root_cert_ =
69 x509_util::CreateCERTCertificateFromX509Certificate(root_cert_.get());
70 ASSERT_TRUE(nss_root_cert_);
71
72 ASSERT_TRUE(test_nssdb_.is_open());
73 ASSERT_TRUE(other_test_nssdb_.is_open());
74 }
75
76 protected:
77 // Imports |nss_root_cert_| into |slot| and sets trust flags so that it is a
78 // trusted CA for SSL.
ImportRootCertAsTrusted(PK11SlotInfo * slot)79 void ImportRootCertAsTrusted(PK11SlotInfo* slot) {
80 SECStatus srv = PK11_ImportCert(slot, nss_root_cert_.get(),
81 CK_INVALID_HANDLE, "nickname_root_cert",
82 PR_FALSE /* includeTrust (unused) */);
83 ASSERT_EQ(SECSuccess, srv);
84
85 CERTCertTrust trust = {0};
86 trust.sslFlags = CERTDB_TRUSTED_CA | CERTDB_VALID_CA;
87 srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nss_root_cert_.get(),
88 &trust);
89 ASSERT_EQ(SECSuccess, srv);
90 }
91
92 crypto::ScopedTestNSSDB test_nssdb_;
93 crypto::ScopedTestNSSDB other_test_nssdb_;
94
95 raw_ptr<TestRootCerts> test_root_certs_;
96
97 scoped_refptr<X509Certificate> root_cert_;
98 std::shared_ptr<const bssl::ParsedCertificate> parsed_root_cert_;
99 ScopedCERTCertificate nss_root_cert_;
100 };
101
102 // Tests that SystemTrustStore created for NSS with a user-slot restriction
103 // allows certificates stored on the specified user slot to be trusted.
TEST_F(SystemTrustStoreNSSTest,UserSlotRestrictionAllows)104 TEST_F(SystemTrustStoreNSSTest, UserSlotRestrictionAllows) {
105 ScopedLocalAnchorConstraintsEnforcementForTesting
106 scoped_enforce_local_anchor_constraints(true);
107 std::unique_ptr<SystemTrustStore> system_trust_store =
108 CreateSslSystemTrustStoreChromeRootWithUserSlotRestriction(
109 std::make_unique<TrustStoreChrome>(),
110 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot())));
111
112 ASSERT_NO_FATAL_FAILURE(ImportRootCertAsTrusted(test_nssdb_.slot()));
113
114 bssl::CertificateTrust trust =
115 system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get());
116 EXPECT_EQ(bssl::CertificateTrust::ForTrustAnchor()
117 .WithEnforceAnchorConstraints()
118 .WithEnforceAnchorExpiry()
119 .ToDebugString(),
120 trust.ToDebugString());
121 }
122
TEST_F(SystemTrustStoreNSSTest,UserSlotRestrictionAllowsWithAnchorConstraintsDisabled)123 TEST_F(SystemTrustStoreNSSTest,
124 UserSlotRestrictionAllowsWithAnchorConstraintsDisabled) {
125 ScopedLocalAnchorConstraintsEnforcementForTesting
126 scoped_enforce_local_anchor_constraints(false);
127 std::unique_ptr<SystemTrustStore> system_trust_store =
128 CreateSslSystemTrustStoreChromeRootWithUserSlotRestriction(
129 std::make_unique<TrustStoreChrome>(),
130 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot())));
131
132 ASSERT_NO_FATAL_FAILURE(ImportRootCertAsTrusted(test_nssdb_.slot()));
133
134 bssl::CertificateTrust trust =
135 system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get());
136 EXPECT_EQ(bssl::CertificateTrust::ForTrustAnchor().ToDebugString(),
137 trust.ToDebugString());
138 }
139
140 // Tests that SystemTrustStore created for NSS with a user-slot restriction
141 // does not allows certificates stored only on user slots different from the one
142 // specified to be trusted.
TEST_F(SystemTrustStoreNSSTest,UserSlotRestrictionDisallows)143 TEST_F(SystemTrustStoreNSSTest, UserSlotRestrictionDisallows) {
144 std::unique_ptr<SystemTrustStore> system_trust_store =
145 CreateSslSystemTrustStoreChromeRootWithUserSlotRestriction(
146 std::make_unique<TrustStoreChrome>(),
147 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot())));
148
149 ASSERT_NO_FATAL_FAILURE(ImportRootCertAsTrusted(other_test_nssdb_.slot()));
150
151 bssl::CertificateTrust trust =
152 system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get());
153 EXPECT_EQ(bssl::CertificateTrust::ForUnspecified().ToDebugString(),
154 trust.ToDebugString());
155 }
156
157 // Tests that SystemTrustStore created for NSS without allowing trust for
158 // certificate stored on user slots.
TEST_F(SystemTrustStoreNSSTest,NoUserSlots)159 TEST_F(SystemTrustStoreNSSTest, NoUserSlots) {
160 std::unique_ptr<SystemTrustStore> system_trust_store =
161 CreateSslSystemTrustStoreChromeRootWithUserSlotRestriction(
162 std::make_unique<TrustStoreChrome>(), nullptr);
163
164 ASSERT_NO_FATAL_FAILURE(ImportRootCertAsTrusted(test_nssdb_.slot()));
165
166 bssl::CertificateTrust trust =
167 system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get());
168 EXPECT_EQ(bssl::CertificateTrust::ForUnspecified().ToDebugString(),
169 trust.ToDebugString());
170 }
171
172 } // namespace
173
174 } // namespace net
175