• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/lazy_instance.h"
9 #include "build/build_config.h"
10 #include "net/base/net_export.h"
11 #include "net/cert/pki/trust_store.h"
12 #include "net/cert/pki/trust_store_in_memory.h"
13 
14 #if BUILDFLAG(IS_WIN)
15 #include <windows.h>
16 #include "base/win/wincrypt_shim.h"
17 #include "crypto/scoped_capi_types.h"
18 #elif BUILDFLAG(IS_IOS)
19 #include <CoreFoundation/CFArray.h>
20 #include <Security/SecTrust.h>
21 #include "base/mac/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_; }
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 #elif BUILDFLAG(IS_WIN)
temporary_roots()64   HCERTSTORE temporary_roots() const { return temporary_roots_; }
65 
66   // Returns an HCERTCHAINENGINE suitable to be used for certificate
67   // validation routines, or NULL to indicate that the default system chain
68   // engine is appropriate.
69   crypto::ScopedHCERTCHAINENGINE GetChainEngine() const;
70 #endif
71 
test_trust_store()72   TrustStore* test_trust_store() { return &test_trust_store_; }
73 
74  private:
75   friend struct base::LazyInstanceTraitsBase<TestRootCerts>;
76   friend class ScopedTestRoot;
77   friend class ScopedTestKnownRoot;
78 
79   TestRootCerts();
80   ~TestRootCerts();
81 
82   // Marks |certificate| as trusted in the effective trust store
83   // used by CertVerifier::Verify(). Returns false if the
84   // certificate could not be marked trusted.
85   bool Add(X509Certificate* certificate, CertificateTrust trust);
86 
87   // Marks |der_cert| as a known root. Does not change trust.
88   void AddKnownRoot(base::span<const uint8_t> der_cert);
89 
90   // Performs platform-dependent operations.
91   void Init();
92   bool AddImpl(X509Certificate* certificate);
93   void ClearImpl();
94 
95 #if BUILDFLAG(IS_WIN)
96   HCERTSTORE temporary_roots_;
97 #elif BUILDFLAG(IS_IOS)
98   base::ScopedCFTypeRef<CFMutableArrayRef> temporary_roots_;
99 #endif
100 
101   TrustStoreInMemory test_trust_store_;
102 
103   std::set<std::string, std::less<>> test_known_roots_;
104 };
105 
106 // Scoped helper for unittests to handle safely managing trusted roots.
107 //
108 // Limitations:
109 // Multiple instances of ScopedTestRoot may be created at once, which will
110 // trust the union of the certs provided. However, when one of the
111 // ScopedTestRoot instances removes its trust, either by going out of scope, or
112 // by Reset() being called, *all* test root certs will be untrusted. (This
113 // limitation could be removed if a reason arises.)
114 class NET_EXPORT ScopedTestRoot {
115  public:
116   ScopedTestRoot();
117   // Creates a ScopedTestRoot that adds |cert| to the TestRootCerts store.
118   // |trust| may be specified to change the details of how the trust is
119   // interpreted (applies only to CertVerifyProcBuiltin).
120   explicit ScopedTestRoot(
121       X509Certificate* cert,
122       CertificateTrust trust = CertificateTrust::ForTrustAnchor());
123   // Creates a ScopedTestRoot that adds |certs| to the TestRootCerts store.
124   // |trust| may be specified to change the details of how the trust is
125   // interpreted (applies only to CertVerifyProcBuiltin).
126   explicit ScopedTestRoot(
127       CertificateList certs,
128       CertificateTrust trust = CertificateTrust::ForTrustAnchor());
129 
130   ScopedTestRoot(const ScopedTestRoot&) = delete;
131   ScopedTestRoot& operator=(const ScopedTestRoot&) = delete;
132 
133   ScopedTestRoot(ScopedTestRoot&& other);
134   ScopedTestRoot& operator=(ScopedTestRoot&& other);
135 
136   ~ScopedTestRoot();
137 
138   // Assigns |certs| to be the new test root certs. If |certs| is empty, undoes
139   // any work the ScopedTestRoot may have previously done.
140   // If |certs_| contains certificates (due to a prior call to Reset or due to
141   // certs being passed at construction), the existing TestRootCerts store is
142   // cleared.
143   void Reset(CertificateList certs,
144              CertificateTrust trust = CertificateTrust::ForTrustAnchor());
145 
146   // Returns true if this ScopedTestRoot has no certs assigned.
147   bool IsEmpty() const { return certs_.empty(); }
148 
149  private:
150   CertificateList certs_;
151 };
152 
153 // Scoped helper for unittests to handle safely marking additional roots as
154 // known roots. Note that this does not trust the root. If the root should be
155 // trusted, a ScopedTestRoot should also be created.
156 //
157 // Limitations:
158 // Same as for ScopedTestRoot, see comment above.
159 class NET_EXPORT ScopedTestKnownRoot {
160  public:
161   ScopedTestKnownRoot();
162   explicit ScopedTestKnownRoot(X509Certificate* cert);
163 
164   ScopedTestKnownRoot(const ScopedTestKnownRoot&) = delete;
165   ScopedTestKnownRoot& operator=(const ScopedTestKnownRoot&) = delete;
166   ScopedTestKnownRoot(ScopedTestKnownRoot&& other) = delete;
167   ScopedTestKnownRoot& operator=(ScopedTestKnownRoot&& other) = delete;
168 
169   ~ScopedTestKnownRoot();
170 
171  private:
172   CertificateList certs_;
173 };
174 
175 }  // namespace net
176 
177 #endif  // NET_CERT_TEST_ROOT_CERTS_H_
178