1 // Copyright 2012 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 "net/cert/test_root_certs.h"
6
7 #include <string>
8 #include <string_view>
9 #include <utility>
10
11 #include "net/cert/x509_certificate.h"
12 #include "net/cert/x509_util.h"
13 #include "third_party/boringssl/src/include/openssl/pool.h"
14 #include "third_party/boringssl/src/pki/cert_errors.h"
15 #include "third_party/boringssl/src/pki/trust_store.h"
16
17 namespace net {
18
19 namespace {
20
21 bool g_has_instance = false;
22
23 base::LazyInstance<TestRootCerts>::Leaky
24 g_test_root_certs = LAZY_INSTANCE_INITIALIZER;
25
26 } // namespace
27
28 // static
GetInstance()29 TestRootCerts* TestRootCerts::GetInstance() {
30 return g_test_root_certs.Pointer();
31 }
32
HasInstance()33 bool TestRootCerts::HasInstance() {
34 return g_has_instance;
35 }
36
Add(X509Certificate * certificate,bssl::CertificateTrust trust)37 bool TestRootCerts::Add(X509Certificate* certificate,
38 bssl::CertificateTrust trust) {
39 bssl::CertErrors errors;
40 std::shared_ptr<const bssl::ParsedCertificate> parsed =
41 bssl::ParsedCertificate::Create(
42 bssl::UpRef(certificate->cert_buffer()),
43 x509_util::DefaultParseCertificateOptions(), &errors);
44 if (!parsed) {
45 return false;
46 }
47
48 test_trust_store_.AddCertificate(std::move(parsed), trust);
49 if (trust.HasUnspecifiedTrust() || trust.IsDistrusted()) {
50 // TestRootCerts doesn't support passing the specific trust settings into
51 // the OS implementations in any case, but in the case of unspecified trust
52 // or explicit distrust, simply not passing the certs to the OS
53 // implementation is better than nothing.
54 return true;
55 }
56 return AddImpl(certificate);
57 }
58
AddKnownRoot(base::span<const uint8_t> der_cert)59 void TestRootCerts::AddKnownRoot(base::span<const uint8_t> der_cert) {
60 test_known_roots_.insert(std::string(
61 reinterpret_cast<const char*>(der_cert.data()), der_cert.size()));
62 }
63
Clear()64 void TestRootCerts::Clear() {
65 ClearImpl();
66 test_trust_store_.Clear();
67 test_known_roots_.clear();
68 }
69
IsEmpty() const70 bool TestRootCerts::IsEmpty() const {
71 return test_trust_store_.IsEmpty();
72 }
73
IsKnownRoot(base::span<const uint8_t> der_cert) const74 bool TestRootCerts::IsKnownRoot(base::span<const uint8_t> der_cert) const {
75 return test_known_roots_.find(
76 std::string_view(reinterpret_cast<const char*>(der_cert.data()),
77 der_cert.size())) != test_known_roots_.end();
78 }
79
TestRootCerts()80 TestRootCerts::TestRootCerts() {
81 Init();
82 g_has_instance = true;
83 }
84
85 ScopedTestRoot::ScopedTestRoot() = default;
86
ScopedTestRoot(scoped_refptr<X509Certificate> cert,bssl::CertificateTrust trust)87 ScopedTestRoot::ScopedTestRoot(scoped_refptr<X509Certificate> cert,
88 bssl::CertificateTrust trust) {
89 Reset({std::move(cert)}, trust);
90 }
91
ScopedTestRoot(CertificateList certs,bssl::CertificateTrust trust)92 ScopedTestRoot::ScopedTestRoot(CertificateList certs,
93 bssl::CertificateTrust trust) {
94 Reset(std::move(certs), trust);
95 }
96
ScopedTestRoot(ScopedTestRoot && other)97 ScopedTestRoot::ScopedTestRoot(ScopedTestRoot&& other) {
98 *this = std::move(other);
99 }
100
operator =(ScopedTestRoot && other)101 ScopedTestRoot& ScopedTestRoot::operator=(ScopedTestRoot&& other) {
102 CertificateList tmp_certs;
103 tmp_certs.swap(other.certs_);
104 Reset(std::move(tmp_certs));
105 return *this;
106 }
107
~ScopedTestRoot()108 ScopedTestRoot::~ScopedTestRoot() {
109 Reset({});
110 }
111
Reset(CertificateList certs,bssl::CertificateTrust trust)112 void ScopedTestRoot::Reset(CertificateList certs,
113 bssl::CertificateTrust trust) {
114 if (!certs_.empty())
115 TestRootCerts::GetInstance()->Clear();
116 for (const auto& cert : certs)
117 TestRootCerts::GetInstance()->Add(cert.get(), trust);
118 certs_ = std::move(certs);
119 }
120
121 ScopedTestKnownRoot::ScopedTestKnownRoot() = default;
122
ScopedTestKnownRoot(X509Certificate * cert)123 ScopedTestKnownRoot::ScopedTestKnownRoot(X509Certificate* cert) {
124 TestRootCerts::GetInstance()->AddKnownRoot(
125 x509_util::CryptoBufferAsSpan(cert->cert_buffer()));
126 }
127
~ScopedTestKnownRoot()128 ScopedTestKnownRoot::~ScopedTestKnownRoot() {
129 TestRootCerts::GetInstance()->Clear();
130 }
131
132 } // namespace net
133