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