File: test_root_certs.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (193 lines) | stat: -rw-r--r-- 6,880 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_CERT_TEST_ROOT_CERTS_H_
#define NET_CERT_TEST_ROOT_CERTS_H_

#include <set>

#include "base/containers/span.h"
#include "base/lazy_instance.h"
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
#include "build/build_config.h"
#include "net/base/net_export.h"
#include "third_party/boringssl/src/pki/trust_store.h"
#include "third_party/boringssl/src/pki/trust_store_in_memory.h"

#if BUILDFLAG(IS_IOS)
#include <CoreFoundation/CFArray.h>
#include <Security/SecTrust.h>
#include "base/apple/scoped_cftyperef.h"
#endif

namespace net {

class X509Certificate;
typedef std::vector<scoped_refptr<X509Certificate>> CertificateList;

class ThreadSafeTrustStoreInMemory : public bssl::TrustStore {
 public:
  // TrustStoreInMemory wrappers:
  bool IsEmpty() const;
  void Clear();
  void AddCertificate(std::shared_ptr<const bssl::ParsedCertificate> cert,
                      const bssl::CertificateTrust& trust);

  // TrustStore implementation:
  void SyncGetIssuersOf(const bssl::ParsedCertificate* cert,
                        bssl::ParsedCertificateList* issuers) override;
  bssl::CertificateTrust GetTrust(const bssl::ParsedCertificate* cert) override;

 private:
  mutable base::Lock lock_;
  bssl::TrustStoreInMemory impl_ GUARDED_BY(lock_);
};

// TestRootCerts is a helper class for unit tests that is used to
// artificially mark a certificate as trusted, independent of the local
// machine configuration.
//
// Test roots can be added using the ScopedTestRoot class below. See the
// class documentation for usage and limitations.
class NET_EXPORT TestRootCerts {
 public:
  // Obtains the Singleton instance to the trusted certificates.
  static TestRootCerts* GetInstance();

  TestRootCerts(const TestRootCerts&) = delete;
  TestRootCerts& operator=(const TestRootCerts&) = delete;

  // Returns true if an instance exists, without forcing an initialization.
  static bool HasInstance();

  // Clears the trusted status of any certificates that were previously
  // marked trusted via Add().
  void Clear();

  // Returns true if there are no certificates that have been marked trusted.
  bool IsEmpty() const;

  // Returns true if `der_cert` has been marked as a known root for testing.
  bool IsKnownRoot(base::span<const uint8_t> der_cert) const;

#if BUILDFLAG(IS_IOS)
  // Modifies the root certificates of |trust_ref| to include the
  // certificates stored in |temporary_roots_|. If IsEmpty() is true, this
  // does not modify |trust_ref|.
  OSStatus FixupSecTrustRef(SecTrustRef trust_ref) const;
#endif

  bssl::TrustStore* test_trust_store() { return &test_trust_store_; }

 private:
  friend struct base::LazyInstanceTraitsBase<TestRootCerts>;
  friend class ScopedTestRoot;
  friend class ScopedTestKnownRoot;

  TestRootCerts();
  ~TestRootCerts();

  // Marks |certificate| as trusted in the effective trust store
  // used by CertVerifier::Verify(). Returns false if the
  // certificate could not be marked trusted.
  bool Add(X509Certificate* certificate, bssl::CertificateTrust trust);

  // Marks |der_cert| as a known root. Does not change trust.
  void AddKnownRoot(base::span<const uint8_t> der_cert);

  // Performs platform-dependent operations.
  void Init() EXCLUSIVE_LOCKS_REQUIRED(lock_);
  bool AddImpl(X509Certificate* certificate) EXCLUSIVE_LOCKS_REQUIRED(lock_);
  void ClearImpl() EXCLUSIVE_LOCKS_REQUIRED(lock_);

  // `test_trust_store_` uses its own internal lock rather than the
  // TestRootCerts::lock_, since a pointer to the trust store is returned by
  // `test_trust_store` the methods on the trust store must themselves be
  // thread-safe.
  ThreadSafeTrustStoreInMemory test_trust_store_;

  mutable base::Lock lock_;

#if BUILDFLAG(IS_IOS)
  base::apple::ScopedCFTypeRef<CFMutableArrayRef> temporary_roots_
      GUARDED_BY(lock_);
#endif

  std::set<std::string, std::less<>> test_known_roots_ GUARDED_BY(lock_);
};

// Scoped helper for unittests to handle safely managing trusted roots.
//
// Limitations:
// Multiple instances of ScopedTestRoot may be created at once, which will
// trust the union of the certs provided. However, when one of the
// ScopedTestRoot instances removes its trust, either by going out of scope, or
// by Reset() being called, *all* test root certs will be untrusted. (This
// limitation could be removed if a reason arises.)
class NET_EXPORT ScopedTestRoot {
 public:
  ScopedTestRoot();
  // Creates a ScopedTestRoot that adds |cert| to the TestRootCerts store.
  // |trust| may be specified to change the details of how the trust is
  // interpreted (applies only to CertVerifyProcBuiltin).
  explicit ScopedTestRoot(
      scoped_refptr<X509Certificate> cert,
      bssl::CertificateTrust trust = bssl::CertificateTrust::ForTrustAnchor());
  // Creates a ScopedTestRoot that adds |certs| to the TestRootCerts store.
  // |trust| may be specified to change the details of how the trust is
  // interpreted (applies only to CertVerifyProcBuiltin).
  explicit ScopedTestRoot(
      CertificateList certs,
      bssl::CertificateTrust trust = bssl::CertificateTrust::ForTrustAnchor());

  ScopedTestRoot(const ScopedTestRoot&) = delete;
  ScopedTestRoot& operator=(const ScopedTestRoot&) = delete;

  ScopedTestRoot(ScopedTestRoot&& other);
  ScopedTestRoot& operator=(ScopedTestRoot&& other);

  ~ScopedTestRoot();

  // Assigns |certs| to be the new test root certs. If |certs| is empty, undoes
  // any work the ScopedTestRoot may have previously done.
  // If |certs_| contains certificates (due to a prior call to Reset or due to
  // certs being passed at construction), the existing TestRootCerts store is
  // cleared.
  void Reset(
      CertificateList certs,
      bssl::CertificateTrust trust = bssl::CertificateTrust::ForTrustAnchor());

  // Returns true if this ScopedTestRoot has no certs assigned.
  bool IsEmpty() const { return certs_.empty(); }

 private:
  CertificateList certs_;
};

// Scoped helper for unittests to handle safely marking additional roots as
// known roots. Note that this does not trust the root. If the root should be
// trusted, a ScopedTestRoot should also be created.
//
// Limitations:
// Same as for ScopedTestRoot, see comment above.
class NET_EXPORT ScopedTestKnownRoot {
 public:
  ScopedTestKnownRoot();
  explicit ScopedTestKnownRoot(X509Certificate* cert);

  ScopedTestKnownRoot(const ScopedTestKnownRoot&) = delete;
  ScopedTestKnownRoot& operator=(const ScopedTestKnownRoot&) = delete;
  ScopedTestKnownRoot(ScopedTestKnownRoot&& other) = delete;
  ScopedTestKnownRoot& operator=(ScopedTestKnownRoot&& other) = delete;

  ~ScopedTestKnownRoot();

 private:
  CertificateList certs_;
};

}  // namespace net

#endif  // NET_CERT_TEST_ROOT_CERTS_H_