xref: /aosp_15_r20/external/cronet/net/cert/internal/system_trust_store_nss_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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