121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Copyright (c) 2010 The Chromium Authors. All rights reserved. 221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Use of this source code is governed by a BSD-style license that can be 321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// found in the LICENSE file. 421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/test_root_certs.h" 621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <windows.h> 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <wincrypt.h> 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/basictypes.h" 1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/lazy_instance.h" 1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/logging.h" 1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/x509_certificate.h" 1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace net { 1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace { 1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Provides a CertDllOpenStoreProv callback provider function, to be called 2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// by CertOpenStore when the CERT_STORE_PROV_SYSTEM_W store is opened. See 2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// http://msdn.microsoft.com/en-us/library/aa376043(VS.85).aspx. 2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenBOOL WINAPI InterceptedOpenStoreW(LPCSTR store_provider, 2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DWORD encoding, 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen HCRYPTPROV crypt_provider, 2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DWORD flags, 2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const void* extra, 2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen HCERTSTORE memory_store, 2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PCERT_STORE_PROV_INFO store_info); 2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// CryptoAPIInjector is used to inject a store provider function for system 3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// certificate stores before the one provided internally by Crypt32.dll. 3221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Once injected, there is no way to remove, so every call to open a system 3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// store will be redirected to the injected function. 3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstruct CryptoAPIInjector { 3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // The previous default function for opening system stores. For most 3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // configurations, this should point to Crypt32's internal 3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // I_CertDllOpenSystemStoreProvW function. 3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PFN_CERT_DLL_OPEN_STORE_PROV_FUNC original_function; 3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // The handle that CryptoAPI uses to ensure the DLL implementing 4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // |original_function| remains loaded in memory. 4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen HCRYPTOIDFUNCADDR original_handle; 4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private: 4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen friend struct base::DefaultLazyInstanceTraits<CryptoAPIInjector>; 4621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CryptoAPIInjector() 4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : original_function(NULL), 4921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen original_handle(NULL) { 5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen HCRYPTOIDFUNCSET registered_functions = 5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CryptInitOIDFunctionSet(CRYPT_OID_OPEN_STORE_PROV_FUNC, 0); 5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Preserve the original handler function in |original_function|. If other 5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // functions are overridden, they will also need to be preserved. 5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen BOOL ok = CryptGetOIDFunctionAddress( 5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen registered_functions, 0, CERT_STORE_PROV_SYSTEM_W, 0, 5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen reinterpret_cast<void**>(&original_function), &original_handle); 5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(ok); 5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // For now, intercept only the numeric form of the system store 6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // function, CERT_STORE_PROV_SYSTEM_W (0x0A), which is what Crypt32 6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // functionality uses exclusively. Depending on the machine that tests 6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // are being run on, it may prove necessary to also intercept 6421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // sz_CERT_STORE_PROV_SYSTEM_[A/W] and CERT_STORE_PROV_SYSTEM_A, based 6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // on whether or not any third-party CryptoAPI modules have been 6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // installed. 6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const CRYPT_OID_FUNC_ENTRY kFunctionToIntercept = 6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen { CERT_STORE_PROV_SYSTEM_W, &InterceptedOpenStoreW }; 6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Inject kFunctionToIntercept at the front of the linked list that 7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // crypt32 uses when CertOpenStore is called, replacing the existing 7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // registered function. 7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ok = CryptInstallOIDFunctionAddress(NULL, 0, 7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CRYPT_OID_OPEN_STORE_PROV_FUNC, 1, 7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen &kFunctionToIntercept, 7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG); 7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(ok); 7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // This is never called, because this object is intentionally leaked. 8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Certificate verification happens on a non-joinable worker thread, which 8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // may still be running when ~AtExitManager is called, so the LazyInstance 8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // must be leaky. 8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ~CryptoAPIInjector() { 8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen original_function = NULL; 8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CryptFreeOIDFunctionAddress(original_handle, NULL); 8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbase::LazyInstance<CryptoAPIInjector, 9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::LeakyLazyInstanceTraits<CryptoAPIInjector> > 9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen g_capi_injector(base::LINKER_INITIALIZED); 9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenBOOL WINAPI InterceptedOpenStoreW(LPCSTR store_provider, 9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DWORD encoding, 9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen HCRYPTPROV crypt_provider, 9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DWORD flags, 9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const void* store_name, 9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen HCERTSTORE memory_store, 10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PCERT_STORE_PROV_INFO store_info) { 10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // If the high word is all zeroes, then |store_provider| is a numeric ID. 10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Otherwise, it's a pointer to a null-terminated ASCII string. See the 10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // documentation for CryptGetOIDFunctionAddress for more information. 10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen uint32 store_as_uint = reinterpret_cast<uint32>(store_provider); 10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (store_as_uint > 0xFFFF || store_provider != CERT_STORE_PROV_SYSTEM_W || 10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen !g_capi_injector.Get().original_function) 10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return FALSE; 10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen BOOL ok = g_capi_injector.Get().original_function(store_provider, encoding, 11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen crypt_provider, flags, 11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen store_name, memory_store, 11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen store_info); 11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Only the Root store should have certificates injected. If 11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // CERT_SYSTEM_STORE_RELOCATE_FLAG is set, then |store_name| points to a 11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // CERT_SYSTEM_STORE_RELOCATE_PARA structure, rather than a 11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // NULL-terminated wide string, so check before making a string 11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // comparison. 11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!ok || TestRootCerts::GetInstance()->IsEmpty() || 11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen (flags & CERT_SYSTEM_STORE_RELOCATE_FLAG) || 12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen lstrcmpiW(reinterpret_cast<LPCWSTR>(store_name), L"root")) 12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return ok; 12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // The result of CertOpenStore with CERT_STORE_PROV_SYSTEM_W is documented 12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // to be a collection store, and that appears to hold for |memory_store|. 12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Attempting to add an individual certificate to |memory_store| causes 12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // the request to be forwarded to the first physical store in the 12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // collection that accepts modifications, which will cause a secure 12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // confirmation dialog to be displayed, confirming the user wishes to 12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // trust the certificate. However, appending a store to the collection 13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // will merely modify the temporary collection store, and will not persist 13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // any changes to the underlying physical store. When the |memory_store| is 13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // searched to see if a certificate is in the Root store, all the 13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // underlying stores in the collection will be searched, and any certificate 13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // in temporary_roots() will be found and seen as trusted. 13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return CertAddStoreToCollection( 13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen memory_store, TestRootCerts::GetInstance()->temporary_roots(), 0, 0); 13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 13821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 13921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} // namespace 14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool TestRootCerts::Add(X509Certificate* certificate) { 14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Ensure that the default CryptoAPI functionality has been intercepted. 14321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // If a test certificate is never added, then no interception should 14421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // happen. 14521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen g_capi_injector.Get(); 14621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 14721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen BOOL ok = CertAddCertificateContextToStore( 14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen temporary_roots_, certificate->os_cert_handle(), 14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_STORE_ADD_NEW, NULL); 15021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!ok) { 15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // If the certificate is already added, return successfully. 15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return GetLastError() == CRYPT_E_EXISTS; 15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen empty_ = false; 15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 15821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid TestRootCerts::Clear() { 16021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen empty_ = true; 16121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 16221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PCCERT_CONTEXT prev_cert = NULL; 16321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen while (prev_cert = CertEnumCertificatesInStore(temporary_roots_, NULL)) 16421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertDeleteCertificateFromStore(prev_cert); 16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool TestRootCerts::IsEmpty() const { 16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return empty_; 16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenHCERTCHAINENGINE TestRootCerts::GetChainEngine() const { 17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (IsEmpty()) 17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; // Default chain engine will suffice. 17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Each HCERTCHAINENGINE caches both the configured system stores and 17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // information about each chain that has been built. In order to ensure 17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // that changes to |temporary_roots_| are properly propagated and that the 17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // various caches are flushed, when at least one certificate is added, 17921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // return a new chain engine for every call. Each chain engine creation 18021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // should re-open the root store, ensuring the most recent changes are 18121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // visible. 18221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_CHAIN_ENGINE_CONFIG engine_config = { 18321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen sizeof(engine_config) 18421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen }; 18521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen engine_config.dwFlags = 18621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_CHAIN_ENABLE_CACHE_AUTO_UPDATE | 18721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_CHAIN_ENABLE_SHARE_STORE; 18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen HCERTCHAINENGINE chain_engine = NULL; 18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen BOOL ok = CertCreateCertificateChainEngine(&engine_config, &chain_engine); 19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(ok); 19121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return chain_engine; 19221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 19321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 19421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenTestRootCerts::~TestRootCerts() { 19521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertCloseStore(temporary_roots_, 0); 19621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 19721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 19821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid TestRootCerts::Init() { 19921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen empty_ = true; 20021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen temporary_roots_ = CertOpenStore( 20121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_STORE_PROV_MEMORY, 0, NULL, 20221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL); 20321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(temporary_roots_); 20421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 20521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 20621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} // namespace net 207