xref: /aosp_15_r20/external/cronet/net/cert/test_root_certs.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #ifndef NET_CERT_TEST_ROOT_CERTS_H_
6 #define NET_CERT_TEST_ROOT_CERTS_H_
7 
8 #include <set>
9 
10 #include "base/containers/span.h"
11 #include "base/lazy_instance.h"
12 #include "base/memory/scoped_refptr.h"
13 #include "build/build_config.h"
14 #include "net/base/net_export.h"
15 #include "third_party/boringssl/src/pki/trust_store.h"
16 #include "third_party/boringssl/src/pki/trust_store_in_memory.h"
17 
18 #if BUILDFLAG(IS_IOS)
19 #include <CoreFoundation/CFArray.h>
20 #include <Security/SecTrust.h>
21 #include "base/apple/scoped_cftyperef.h"
22 #endif
23 
24 namespace net {
25 
26 class X509Certificate;
27 typedef std::vector<scoped_refptr<X509Certificate>> CertificateList;
28 
29 // TestRootCerts is a helper class for unit tests that is used to
30 // artificially mark a certificate as trusted, independent of the local
31 // machine configuration.
32 //
33 // Test roots can be added using the ScopedTestRoot class below. See the
34 // class documentation for usage and limitations.
35 class NET_EXPORT TestRootCerts {
36  public:
37   // Obtains the Singleton instance to the trusted certificates.
38   static TestRootCerts* GetInstance();
39 
40   TestRootCerts(const TestRootCerts&) = delete;
41   TestRootCerts& operator=(const TestRootCerts&) = delete;
42 
43   // Returns true if an instance exists, without forcing an initialization.
44   static bool HasInstance();
45 
46   // Clears the trusted status of any certificates that were previously
47   // marked trusted via Add().
48   void Clear();
49 
50   // Returns true if there are no certificates that have been marked trusted.
51   bool IsEmpty() const;
52 
53   // Returns true if `der_cert` has been marked as a known root for testing.
54   bool IsKnownRoot(base::span<const uint8_t> der_cert) const;
55 
56 #if BUILDFLAG(IS_IOS)
temporary_roots()57   CFArrayRef temporary_roots() const { return temporary_roots_.get(); }
58 
59   // Modifies the root certificates of |trust_ref| to include the
60   // certificates stored in |temporary_roots_|. If IsEmpty() is true, this
61   // does not modify |trust_ref|.
62   OSStatus FixupSecTrustRef(SecTrustRef trust_ref) const;
63 #endif
64 
test_trust_store()65   bssl::TrustStore* test_trust_store() { return &test_trust_store_; }
66 
67  private:
68   friend struct base::LazyInstanceTraitsBase<TestRootCerts>;
69   friend class ScopedTestRoot;
70   friend class ScopedTestKnownRoot;
71 
72   TestRootCerts();
73   ~TestRootCerts();
74 
75   // Marks |certificate| as trusted in the effective trust store
76   // used by CertVerifier::Verify(). Returns false if the
77   // certificate could not be marked trusted.
78   bool Add(X509Certificate* certificate, bssl::CertificateTrust trust);
79 
80   // Marks |der_cert| as a known root. Does not change trust.
81   void AddKnownRoot(base::span<const uint8_t> der_cert);
82 
83   // Performs platform-dependent operations.
84   void Init();
85   bool AddImpl(X509Certificate* certificate);
86   void ClearImpl();
87 
88 #if BUILDFLAG(IS_IOS)
89   base::apple::ScopedCFTypeRef<CFMutableArrayRef> temporary_roots_;
90 #endif
91 
92   bssl::TrustStoreInMemory test_trust_store_;
93 
94   std::set<std::string, std::less<>> test_known_roots_;
95 };
96 
97 // Scoped helper for unittests to handle safely managing trusted roots.
98 //
99 // Limitations:
100 // Multiple instances of ScopedTestRoot may be created at once, which will
101 // trust the union of the certs provided. However, when one of the
102 // ScopedTestRoot instances removes its trust, either by going out of scope, or
103 // by Reset() being called, *all* test root certs will be untrusted. (This
104 // limitation could be removed if a reason arises.)
105 class NET_EXPORT ScopedTestRoot {
106  public:
107   ScopedTestRoot();
108   // Creates a ScopedTestRoot that adds |cert| to the TestRootCerts store.
109   // |trust| may be specified to change the details of how the trust is
110   // interpreted (applies only to CertVerifyProcBuiltin).
111   explicit ScopedTestRoot(
112       scoped_refptr<X509Certificate> cert,
113       bssl::CertificateTrust trust = bssl::CertificateTrust::ForTrustAnchor());
114   // Creates a ScopedTestRoot that adds |certs| to the TestRootCerts store.
115   // |trust| may be specified to change the details of how the trust is
116   // interpreted (applies only to CertVerifyProcBuiltin).
117   explicit ScopedTestRoot(
118       CertificateList certs,
119       bssl::CertificateTrust trust = bssl::CertificateTrust::ForTrustAnchor());
120 
121   ScopedTestRoot(const ScopedTestRoot&) = delete;
122   ScopedTestRoot& operator=(const ScopedTestRoot&) = delete;
123 
124   ScopedTestRoot(ScopedTestRoot&& other);
125   ScopedTestRoot& operator=(ScopedTestRoot&& other);
126 
127   ~ScopedTestRoot();
128 
129   // Assigns |certs| to be the new test root certs. If |certs| is empty, undoes
130   // any work the ScopedTestRoot may have previously done.
131   // If |certs_| contains certificates (due to a prior call to Reset or due to
132   // certs being passed at construction), the existing TestRootCerts store is
133   // cleared.
134   void Reset(
135       CertificateList certs,
136       bssl::CertificateTrust trust = bssl::CertificateTrust::ForTrustAnchor());
137 
138   // Returns true if this ScopedTestRoot has no certs assigned.
139   bool IsEmpty() const { return certs_.empty(); }
140 
141  private:
142   CertificateList certs_;
143 };
144 
145 // Scoped helper for unittests to handle safely marking additional roots as
146 // known roots. Note that this does not trust the root. If the root should be
147 // trusted, a ScopedTestRoot should also be created.
148 //
149 // Limitations:
150 // Same as for ScopedTestRoot, see comment above.
151 class NET_EXPORT ScopedTestKnownRoot {
152  public:
153   ScopedTestKnownRoot();
154   explicit ScopedTestKnownRoot(X509Certificate* cert);
155 
156   ScopedTestKnownRoot(const ScopedTestKnownRoot&) = delete;
157   ScopedTestKnownRoot& operator=(const ScopedTestKnownRoot&) = delete;
158   ScopedTestKnownRoot(ScopedTestKnownRoot&& other) = delete;
159   ScopedTestKnownRoot& operator=(ScopedTestKnownRoot&& other) = delete;
160 
161   ~ScopedTestKnownRoot();
162 
163  private:
164   CertificateList certs_;
165 };
166 
167 }  // namespace net
168 
169 #endif  // NET_CERT_TEST_ROOT_CERTS_H_
170