| Index: net/base/x509_certificate_win.cc
|
| diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc
|
| index 566a5cfa47ffca4473f736dec6e943f1dbcab0b8..ca72f563f360a40f79a60fef82d4050d30e7a337 100644
|
| --- a/net/base/x509_certificate_win.cc
|
| +++ b/net/base/x509_certificate_win.cc
|
| @@ -536,9 +536,7 @@ X509Certificate* X509Certificate::CreateSelfSigned(
|
| DCHECK(cert_handle) << "Failed to create self-signed certificate: "
|
| << logging::GetLastSystemErrorCode();
|
|
|
| - X509Certificate* cert = CreateFromHandle(cert_handle,
|
| - SOURCE_LONE_CERT_IMPORT,
|
| - OSCertHandles());
|
| + X509Certificate* cert = CreateFromHandle(cert_handle, OSCertHandles());
|
| FreeOSCertHandle(cert_handle);
|
| return cert;
|
| }
|
| @@ -594,6 +592,46 @@ HCERTSTORE X509Certificate::cert_store() {
|
| return g_cert_store.Get().cert_store();
|
| }
|
|
|
| +X509Certificate::OSCertListHandle
|
| +X509Certificate::CreateOSCertListHandle() const {
|
| + // Create a temporary certificate store to hold |cert_handle_| and any
|
| + // associated intermediates. The store will be referenced in the returned
|
| + // OSCertListHandle, and will not be freed until the OSCertListHandle is
|
| + // freed.
|
| + OSCertListHandle cert_list = NULL;
|
| + DWORD flags = CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG;
|
| + HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0,
|
| + NULL, flags, NULL);
|
| +
|
| + if (store) {
|
| + // NOTE: This preserves all of the properties of |cert_handle_| except for
|
| + // CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two
|
| + // properties that hold access to already-opened private keys. If a handle
|
| + // has already been unlocked (eg: PIN prompt), then the first time that
|
| + // the identity is used for client auth, it may prompt the user again.
|
| + BOOL ok = CertAddCertificateContextToStore(store, cert_handle_,
|
| + CERT_STORE_ADD_ALWAYS,
|
| + &cert_list);
|
| + if (ok && cert_list) {
|
| + for (size_t i = 0; ok && i < intermediate_ca_certs_.size(); ++i) {
|
| + ok = CertAddCertificateContextToStore(store, intermediate_ca_certs_[i],
|
| + CERT_STORE_ADD_ALWAYS, NULL);
|
| + }
|
| + }
|
| +
|
| + // If |cert_list| points to a valid certificate, this will not actually
|
| + // close and free |store| until |cert_list| is freed.
|
| + CertCloseStore(store, 0);
|
| +
|
| + if (!ok) {
|
| + FreeOSCertListHandle(cert_list);
|
| + return NULL;
|
| + }
|
| + }
|
| +
|
| + return cert_list;
|
| +}
|
| +
|
| int X509Certificate::Verify(const std::string& hostname,
|
| int flags,
|
| CertVerifyResult* verify_result) const {
|
| @@ -662,21 +700,25 @@ int X509Certificate::Verify(const std::string& hostname,
|
| if (TestRootCerts::HasInstance())
|
| chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine());
|
|
|
| + OSCertListHandle cert_list = CreateOSCertListHandle();
|
| PCCERT_CHAIN_CONTEXT chain_context;
|
| // IE passes a non-NULL pTime argument that specifies the current system
|
| // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the
|
| // chain_flags argument.
|
| if (!CertGetCertificateChain(
|
| chain_engine,
|
| - cert_handle_,
|
| + cert_list,
|
| NULL, // current system time
|
| - cert_handle_->hCertStore,
|
| + cert_list->hCertStore,
|
| &chain_para,
|
| chain_flags,
|
| NULL, // reserved
|
| &chain_context)) {
|
| + FreeOSCertListHandle(cert_list);
|
| return MapSecurityError(GetLastError());
|
| }
|
| + FreeOSCertListHandle(cert_list);
|
| +
|
| if (chain_context->TrustStatus.dwErrorStatus &
|
| CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
|
| ev_policy_oid = NULL;
|
| @@ -911,6 +953,11 @@ void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
|
| }
|
|
|
| // static
|
| +void X509Certificate::FreeOSCertListHandle(OSCertListHandle cert_list) {
|
| + CertFreeCertificateContext(cert_list);
|
| +}
|
| +
|
| +// static
|
| SHA1Fingerprint X509Certificate::CalculateFingerprint(
|
| OSCertHandle cert) {
|
| DCHECK(NULL != cert->pbCertEncoded);
|
|
|