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