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