Commit 72899ddf authored by Matt Mueller's avatar Matt Mueller Committed by Commit Bot

Remove x509_certificate_win.

Windows has been on use_byte_certs since M61.

Bug: 671420
Change-Id: I78c7f7f2a2e94ebd18d4d0c76909a9549231ec85
Reviewed-on: https://chromium-review.googlesource.com/661885Reviewed-by: default avatarDavid Benjamin <davidben@chromium.org>
Commit-Queue: Matt Mueller <mattm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#501374}
parent f7923136
...@@ -601,10 +601,8 @@ component("net") { ...@@ -601,10 +601,8 @@ component("net") {
"cert/test_root_certs_mac.cc", "cert/test_root_certs_mac.cc",
"cert/test_root_certs_nss.cc", "cert/test_root_certs_nss.cc",
"cert/test_root_certs_win.cc", "cert/test_root_certs_win.cc",
"cert/x509_cert_types_win.cc",
"cert/x509_certificate_known_roots_win.h", "cert/x509_certificate_known_roots_win.h",
"cert/x509_certificate_nss.cc", "cert/x509_certificate_nss.cc",
"cert/x509_certificate_win.cc",
"cert/x509_util_android.cc", "cert/x509_util_android.cc",
"cert/x509_util_ios.cc", "cert/x509_util_ios.cc",
"cert/x509_util_ios.h", "cert/x509_util_ios.h",
...@@ -1824,12 +1822,6 @@ component("net") { ...@@ -1824,12 +1822,6 @@ component("net") {
if (use_nss_certs) { if (use_nss_certs) {
sources -= [ "cert/x509_certificate_nss.cc" ] sources -= [ "cert/x509_certificate_nss.cc" ]
} }
if (is_win) {
sources -= [
"cert/x509_cert_types_win.cc",
"cert/x509_certificate_win.cc",
]
}
} else { } else {
sources -= [ "cert/x509_certificate_bytes.cc" ] sources -= [ "cert/x509_certificate_bytes.cc" ]
} }
......
...@@ -37,7 +37,7 @@ struct NET_EXPORT CertPrincipal { ...@@ -37,7 +37,7 @@ struct NET_EXPORT CertPrincipal {
explicit CertPrincipal(const std::string& name); explicit CertPrincipal(const std::string& name);
~CertPrincipal(); ~CertPrincipal();
#if BUILDFLAG(USE_BYTE_CERTS) || defined(OS_WIN) #if BUILDFLAG(USE_BYTE_CERTS)
// Parses a BER-format DistinguishedName. // Parses a BER-format DistinguishedName.
// TODO(mattm): change this to take a der::Input. // TODO(mattm): change this to take a der::Input.
bool ParseDistinguishedName(const void* ber_name_data, size_t length); bool ParseDistinguishedName(const void* ber_name_data, size_t length);
......
...@@ -14,7 +14,7 @@ namespace net { ...@@ -14,7 +14,7 @@ namespace net {
namespace { namespace {
#if BUILDFLAG(USE_BYTE_CERTS) || defined(OS_WIN) #if BUILDFLAG(USE_BYTE_CERTS)
TEST(X509TypesTest, ParseDNVerisign) { TEST(X509TypesTest, ParseDNVerisign) {
CertPrincipal verisign; CertPrincipal verisign;
EXPECT_TRUE(verisign.ParseDistinguishedName(VerisignDN, sizeof(VerisignDN))); EXPECT_TRUE(verisign.ParseDistinguishedName(VerisignDN, sizeof(VerisignDN)));
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/cert/x509_cert_types.h"
#include <windows.h>
#include <memory>
#include "base/logging.h"
#include "base/memory/free_deleter.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "crypto/capi_util.h"
#include "crypto/wincrypt_shim.h"
namespace net {
namespace {
// A list of OIDs to decode. Any OID not on this list will be ignored for
// purposes of parsing.
const char* const kOIDs[] = {
szOID_COMMON_NAME,
szOID_LOCALITY_NAME,
szOID_STATE_OR_PROVINCE_NAME,
szOID_COUNTRY_NAME,
szOID_STREET_ADDRESS,
szOID_ORGANIZATION_NAME,
szOID_ORGANIZATIONAL_UNIT_NAME,
szOID_DOMAIN_COMPONENT
};
// Converts the value for |attribute| to an UTF-8 string, storing the result
// in |value|. Returns false if the string cannot be converted.
bool GetAttributeValue(PCERT_RDN_ATTR attribute,
std::string* value) {
DWORD chars_needed = CertRDNValueToStrW(attribute->dwValueType,
&attribute->Value, NULL, 0);
if (chars_needed == 0)
return false;
if (chars_needed == 1) {
// The value is actually an empty string (chars_needed includes a single
// char for a NULL value). Don't bother converting - just clear the
// string.
value->clear();
return true;
}
std::wstring wide_name;
DWORD chars_written = CertRDNValueToStrW(
attribute->dwValueType, &attribute->Value,
base::WriteInto(&wide_name, chars_needed), chars_needed);
if (chars_written <= 1)
return false;
wide_name.resize(chars_written - 1);
*value = base::WideToUTF8(wide_name);
return true;
}
// Adds a type+value pair to the appropriate vector from a C array.
// The array is keyed by the matching OIDs from kOIDS[].
bool AddTypeValuePair(PCERT_RDN_ATTR attribute,
std::vector<std::string>* values[]) {
for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
if (strcmp(attribute->pszObjId, kOIDs[oid]) == 0) {
std::string value;
if (!GetAttributeValue(attribute, &value))
return false;
values[oid]->push_back(value);
break;
}
}
return true;
}
// Stores the first string of the vector, if any, to *single_value.
void SetSingle(const std::vector<std::string>& values,
std::string* single_value) {
// We don't expect to have more than one CN, L, S, and C.
LOG_IF(WARNING, values.size() > 1) << "Didn't expect multiple values";
if (!values.empty())
*single_value = values[0];
}
} // namespace
bool CertPrincipal::ParseDistinguishedName(const void* ber_name_data,
size_t length) {
DCHECK(ber_name_data);
CRYPT_DECODE_PARA decode_para;
decode_para.cbSize = sizeof(decode_para);
decode_para.pfnAlloc = crypto::CryptAlloc;
decode_para.pfnFree = crypto::CryptFree;
CERT_NAME_INFO* name_info = NULL;
DWORD name_info_size = 0;
BOOL rv;
rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
WINCRYPT_X509_NAME,
reinterpret_cast<const BYTE*>(ber_name_data),
length,
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
&decode_para,
&name_info, &name_info_size);
if (!rv)
return false;
std::unique_ptr<CERT_NAME_INFO, base::FreeDeleter> scoped_name_info(
name_info);
std::vector<std::string> common_names, locality_names, state_names,
country_names;
std::vector<std::string>* values[] = {
&common_names, &locality_names,
&state_names, &country_names,
&this->street_addresses,
&this->organization_names,
&this->organization_unit_names,
&this->domain_components
};
DCHECK(arraysize(kOIDs) == arraysize(values));
for (DWORD cur_rdn = 0; cur_rdn < name_info->cRDN; ++cur_rdn) {
PCERT_RDN rdn = &name_info->rgRDN[cur_rdn];
for (DWORD cur_ava = 0; cur_ava < rdn->cRDNAttr; ++cur_ava) {
PCERT_RDN_ATTR ava = &rdn->rgRDNAttr[cur_ava];
if (!AddTypeValuePair(ava, values))
return false;
}
}
SetSingle(common_names, &this->common_name);
SetSingle(locality_names, &this->locality_name);
SetSingle(state_names, &this->state_or_province_name);
SetSingle(country_names, &this->country_name);
return true;
}
} // namespace net
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
#if BUILDFLAG(USE_BYTE_CERTS) #if BUILDFLAG(USE_BYTE_CERTS)
#include "third_party/boringssl/src/include/openssl/base.h" #include "third_party/boringssl/src/include/openssl/base.h"
#elif defined(OS_WIN)
#include <windows.h>
#include "crypto/wincrypt_shim.h"
#elif defined(USE_NSS_CERTS) #elif defined(USE_NSS_CERTS)
// Forward declaration; real one in <cert.h> // Forward declaration; real one in <cert.h>
struct CERTCertificateStr; struct CERTCertificateStr;
...@@ -55,8 +52,6 @@ class NET_EXPORT X509Certificate ...@@ -55,8 +52,6 @@ class NET_EXPORT X509Certificate
// TODO(mattm): Remove OSCertHandle type and clean up the interfaces once all // TODO(mattm): Remove OSCertHandle type and clean up the interfaces once all
// platforms use the CRYPTO_BUFFER version. // platforms use the CRYPTO_BUFFER version.
typedef CRYPTO_BUFFER* OSCertHandle; typedef CRYPTO_BUFFER* OSCertHandle;
#elif defined(OS_WIN)
typedef PCCERT_CONTEXT OSCertHandle;
#elif defined(USE_NSS_CERTS) #elif defined(USE_NSS_CERTS)
typedef struct CERTCertificateStr* OSCertHandle; typedef struct CERTCertificateStr* OSCertHandle;
#else #else
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/cert/x509_certificate.h"
#include <memory>
#include "base/logging.h"
#include "base/memory/free_deleter.h"
#include "base/numerics/safe_conversions.h"
#include "base/pickle.h"
#include "base/sha1.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "crypto/capi_util.h"
#include "crypto/scoped_capi_types.h"
#include "crypto/sha2.h"
#include "net/base/net_errors.h"
#include "net/cert/x509_util_win.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
using base::Time;
namespace net {
namespace {
typedef crypto::ScopedCAPIHandle<
HCERTSTORE,
crypto::CAPIDestroyerWithFlags<HCERTSTORE,
CertCloseStore, 0> > ScopedHCERTSTORE;
//-----------------------------------------------------------------------------
// Decodes the cert's subjectAltName extension into a CERT_ALT_NAME_INFO
// structure and stores it in *output.
void GetCertSubjectAltName(
PCCERT_CONTEXT cert,
std::unique_ptr<CERT_ALT_NAME_INFO, base::FreeDeleter>* output) {
PCERT_EXTENSION extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2,
cert->pCertInfo->cExtension,
cert->pCertInfo->rgExtension);
if (!extension)
return;
CRYPT_DECODE_PARA decode_para;
decode_para.cbSize = sizeof(decode_para);
decode_para.pfnAlloc = crypto::CryptAlloc;
decode_para.pfnFree = crypto::CryptFree;
CERT_ALT_NAME_INFO* alt_name_info = NULL;
DWORD alt_name_info_size = 0;
BOOL rv;
rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
szOID_SUBJECT_ALT_NAME2,
extension->Value.pbData,
extension->Value.cbData,
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
&decode_para,
&alt_name_info,
&alt_name_info_size);
if (rv)
output->reset(alt_name_info);
}
void AddCertsFromStore(HCERTSTORE store,
X509Certificate::OSCertHandles* results) {
PCCERT_CONTEXT cert = NULL;
while ((cert = CertEnumCertificatesInStore(store, cert)) != NULL) {
PCCERT_CONTEXT to_add = NULL;
if (CertAddCertificateContextToStore(
NULL, // The cert won't be persisted in any cert store. This breaks
// any association the context currently has to |store|, which
// allows us, the caller, to safely close |store| without
// releasing the cert handles.
cert,
CERT_STORE_ADD_USE_EXISTING,
&to_add) && to_add != NULL) {
// When processing stores generated from PKCS#7/PKCS#12 files, it
// appears that the order returned is the inverse of the order that it
// appeared in the file.
// TODO(rsleevi): Ensure this order is consistent across all Win
// versions
results->insert(results->begin(), to_add);
}
}
}
X509Certificate::OSCertHandles ParsePKCS7(const char* data, size_t length) {
X509Certificate::OSCertHandles results;
CERT_BLOB data_blob;
data_blob.cbData = base::checked_cast<DWORD>(length);
data_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(data));
HCERTSTORE out_store = NULL;
DWORD expected_types = CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED |
CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED;
if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &data_blob, expected_types,
CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL,
&out_store, NULL, NULL) || out_store == NULL) {
return results;
}
AddCertsFromStore(out_store, &results);
CertCloseStore(out_store, CERT_CLOSE_STORE_CHECK_FLAG);
return results;
}
// Given a CERT_NAME_BLOB, returns true if it appears in a given list,
// formatted as a vector of strings holding DER-encoded X.509
// DistinguishedName entries.
bool IsCertNameBlobInIssuerList(
CERT_NAME_BLOB* name_blob,
const std::vector<std::string>& issuer_names) {
for (std::vector<std::string>::const_iterator it = issuer_names.begin();
it != issuer_names.end(); ++it) {
CERT_NAME_BLOB issuer_blob;
issuer_blob.pbData =
reinterpret_cast<BYTE*>(const_cast<char*>(it->data()));
issuer_blob.cbData = static_cast<DWORD>(it->length());
BOOL rb = CertCompareCertificateName(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &issuer_blob, name_blob);
if (rb)
return true;
}
return false;
}
} // namespace
bool X509Certificate::Initialize() {
DCHECK(cert_handle_);
if (!subject_.ParseDistinguishedName(
cert_handle_->pCertInfo->Subject.pbData,
cert_handle_->pCertInfo->Subject.cbData) ||
!issuer_.ParseDistinguishedName(cert_handle_->pCertInfo->Issuer.pbData,
cert_handle_->pCertInfo->Issuer.cbData))
return false;
valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore);
valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter);
const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber;
std::unique_ptr<uint8_t[]> serial_bytes(new uint8_t[serial->cbData]);
for (unsigned i = 0; i < serial->cbData; i++)
serial_bytes[i] = serial->pbData[serial->cbData - i - 1];
serial_number_ = std::string(
reinterpret_cast<char*>(serial_bytes.get()), serial->cbData);
return true;
}
bool X509Certificate::GetSubjectAltName(
std::vector<std::string>* dns_names,
std::vector<std::string>* ip_addrs) const {
if (dns_names)
dns_names->clear();
if (ip_addrs)
ip_addrs->clear();
if (!cert_handle_)
return false;
std::unique_ptr<CERT_ALT_NAME_INFO, base::FreeDeleter> alt_name_info;
GetCertSubjectAltName(cert_handle_, &alt_name_info);
CERT_ALT_NAME_INFO* alt_name = alt_name_info.get();
if (!alt_name)
return false;
bool has_san = false;
for (DWORD i = 0, num_entries = alt_name->cAltEntry; i < num_entries; i++) {
// dNSName is an ASN.1 IA5String representing a string of ASCII
// characters, so we can use UTF16ToASCII here.
const CERT_ALT_NAME_ENTRY& entry = alt_name->rgAltEntry[i];
if (entry.dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) {
has_san = true;
if (dns_names)
dns_names->push_back(base::UTF16ToASCII(entry.pwszDNSName));
} else if (entry.dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS) {
has_san = true;
if (ip_addrs) {
ip_addrs->push_back(std::string(
reinterpret_cast<const char*>(entry.IPAddress.pbData),
entry.IPAddress.cbData));
}
}
// Fast path: Found at least one subjectAltName and the caller doesn't
// need the actual values.
if (has_san && !ip_addrs && !dns_names)
return true;
}
return has_san;
}
// static
bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
std::string* encoded) {
if (!cert_handle || !cert_handle->pbCertEncoded ||
!cert_handle->cbCertEncoded) {
return false;
}
encoded->assign(reinterpret_cast<char*>(cert_handle->pbCertEncoded),
cert_handle->cbCertEncoded);
return true;
}
// static
bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
X509Certificate::OSCertHandle b) {
DCHECK(a && b);
if (a == b)
return true;
return a->cbCertEncoded == b->cbCertEncoded &&
memcmp(a->pbCertEncoded, b->pbCertEncoded, a->cbCertEncoded) == 0;
}
// static
X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
const char* data,
size_t length) {
if (!base::IsValueInRangeForNumericType<DWORD>(length))
return nullptr;
OSCertHandle cert_handle = nullptr;
if (!CertAddEncodedCertificateToStore(
NULL, X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(data),
base::checked_cast<DWORD>(length), CERT_STORE_ADD_USE_EXISTING,
&cert_handle)) {
return nullptr;
}
return cert_handle;
}
X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
const char* data,
size_t length,
Format format) {
OSCertHandles results;
switch (format) {
case FORMAT_SINGLE_CERTIFICATE: {
OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
if (handle != NULL)
results.push_back(handle);
break;
}
case FORMAT_PKCS7:
results = ParsePKCS7(data, length);
break;
default:
NOTREACHED() << "Certificate format " << format << " unimplemented";
break;
}
return results;
}
// static
X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
OSCertHandle cert_handle) {
return CertDuplicateCertificateContext(cert_handle);
}
// static
void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
CertFreeCertificateContext(cert_handle);
}
// static
SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
return x509_util::CalculateFingerprint256(cert);
}
SHA256HashValue X509Certificate::CalculateCAFingerprint256(
const OSCertHandles& intermediates) {
SHA256HashValue sha256;
memset(sha256.data, 0, sizeof(sha256.data));
SHA256_CTX ctx;
if (!SHA256_Init(&ctx))
return sha256;
for (size_t i = 0; i < intermediates.size(); ++i) {
PCCERT_CONTEXT ca_cert = intermediates[i];
if (!SHA256_Update(&ctx, ca_cert->pbCertEncoded, ca_cert->cbCertEncoded))
return sha256;
}
SHA256_Final(sha256.data, &ctx);
return sha256;
}
// static
X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle(
base::PickleIterator* pickle_iter) {
const char* data;
int length;
if (!pickle_iter->ReadData(&data, &length))
return NULL;
// Legacy serialized certificates were serialized with extended attributes,
// rather than as DER only. As a result, these serialized certificates are
// not portable across platforms and may have side-effects on Windows due
// to extended attributes being serialized/deserialized -
// http://crbug.com/118706. To avoid deserializing these attributes, write
// the deserialized cert into a temporary cert store and then create a new
// cert from the DER - that is, without attributes.
ScopedHCERTSTORE store(
CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL));
if (!store.get())
return NULL;
OSCertHandle cert_handle = NULL;
if (!CertAddSerializedElementToStore(
store.get(), reinterpret_cast<const BYTE*>(data), length,
CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
NULL, reinterpret_cast<const void **>(&cert_handle))) {
return NULL;
}
std::string encoded;
bool ok = GetDEREncoded(cert_handle, &encoded);
FreeOSCertHandle(cert_handle);
cert_handle = NULL;
if (ok)
cert_handle = CreateOSCertHandleFromBytes(encoded.data(), encoded.size());
return cert_handle;
}
// static
bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
base::Pickle* pickle) {
return pickle->WriteData(
reinterpret_cast<char*>(cert_handle->pbCertEncoded),
cert_handle->cbCertEncoded);
}
// static
void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
size_t* size_bits,
PublicKeyType* type) {
*type = kPublicKeyTypeUnknown;
*size_bits = 0;
PCCRYPT_OID_INFO oid_info = CryptFindOIDInfo(
CRYPT_OID_INFO_OID_KEY,
cert_handle->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId,
CRYPT_PUBKEY_ALG_OID_GROUP_ID);
if (!oid_info)
return;
CHECK_EQ(oid_info->dwGroupId,
static_cast<DWORD>(CRYPT_PUBKEY_ALG_OID_GROUP_ID));
*size_bits = CertGetPublicKeyLength(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
&cert_handle->pCertInfo->SubjectPublicKeyInfo);
if (IS_SPECIAL_OID_INFO_ALGID(oid_info->Algid)) {
// For an EC public key, oid_info->Algid is CALG_OID_INFO_PARAMETERS
// (0xFFFFFFFE). Need to handle it as a special case.
if (strcmp(oid_info->pszOID, szOID_ECC_PUBLIC_KEY) == 0) {
*type = kPublicKeyTypeECDSA;
} else {
NOTREACHED();
}
return;
}
switch (oid_info->Algid) {
case CALG_RSA_SIGN:
case CALG_RSA_KEYX:
*type = kPublicKeyTypeRSA;
break;
case CALG_DSS_SIGN:
*type = kPublicKeyTypeDSA;
break;
case CALG_ECDSA:
*type = kPublicKeyTypeECDSA;
break;
case CALG_ECDH:
*type = kPublicKeyTypeECDH;
break;
}
}
bool X509Certificate::IsIssuedByEncoded(
const std::vector<std::string>& valid_issuers) {
// If the certificate's issuer in the list?
if (IsCertNameBlobInIssuerList(&cert_handle_->pCertInfo->Issuer,
valid_issuers)) {
return true;
}
// Otherwise, is any of the intermediate CA subjects in the list?
for (OSCertHandles::iterator it = intermediate_ca_certs_.begin();
it != intermediate_ca_certs_.end(); ++it) {
if (IsCertNameBlobInIssuerList(&(*it)->pCertInfo->Issuer,
valid_issuers)) {
return true;
}
}
return false;
}
// static
bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) {
return x509_util::IsSelfSigned(cert_handle);
}
} // namespace net
...@@ -25,7 +25,6 @@ using ScopedHCERTSTORE = crypto::ScopedCAPIHandle< ...@@ -25,7 +25,6 @@ using ScopedHCERTSTORE = crypto::ScopedCAPIHandle<
scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts( scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
PCCERT_CONTEXT os_cert, PCCERT_CONTEXT os_cert,
const std::vector<PCCERT_CONTEXT>& os_chain) { const std::vector<PCCERT_CONTEXT>& os_chain) {
#if BUILDFLAG(USE_BYTE_CERTS)
if (!os_cert || !os_cert->pbCertEncoded || !os_cert->cbCertEncoded) if (!os_cert || !os_cert->pbCertEncoded || !os_cert->cbCertEncoded)
return nullptr; return nullptr;
bssl::UniquePtr<CRYPTO_BUFFER> cert_handle( bssl::UniquePtr<CRYPTO_BUFFER> cert_handle(
...@@ -52,9 +51,6 @@ scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts( ...@@ -52,9 +51,6 @@ scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
scoped_refptr<X509Certificate> result( scoped_refptr<X509Certificate> result(
X509Certificate::CreateFromHandle(cert_handle.get(), intermediates_raw)); X509Certificate::CreateFromHandle(cert_handle.get(), intermediates_raw));
return result; return result;
#else
return X509Certificate::CreateFromHandle(os_cert, os_chain);
#endif
} }
ScopedPCCERT_CONTEXT CreateCertContextWithChain(const X509Certificate* cert) { ScopedPCCERT_CONTEXT CreateCertContextWithChain(const X509Certificate* cert) {
...@@ -75,7 +71,6 @@ ScopedPCCERT_CONTEXT CreateCertContextWithChain( ...@@ -75,7 +71,6 @@ ScopedPCCERT_CONTEXT CreateCertContextWithChain(
PCCERT_CONTEXT primary_cert = nullptr; PCCERT_CONTEXT primary_cert = nullptr;
#if BUILDFLAG(USE_BYTE_CERTS)
BOOL ok = CertAddEncodedCertificateToStore( BOOL ok = CertAddEncodedCertificateToStore(
store.get(), X509_ASN_ENCODING, store.get(), X509_ASN_ENCODING,
CRYPTO_BUFFER_data(cert->os_cert_handle()), CRYPTO_BUFFER_data(cert->os_cert_handle()),
...@@ -97,27 +92,6 @@ ScopedPCCERT_CONTEXT CreateCertContextWithChain( ...@@ -97,27 +92,6 @@ ScopedPCCERT_CONTEXT CreateCertContextWithChain(
LOG(WARNING) << "error parsing intermediate"; LOG(WARNING) << "error parsing intermediate";
} }
} }
#else
PCCERT_CONTEXT os_cert_handle = cert->os_cert_handle();
const std::vector<PCCERT_CONTEXT>& intermediate_ca_certs =
cert->GetIntermediateCertificates();
// NOTE: This preserves all of the properties of |os_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.get(), os_cert_handle, CERT_STORE_ADD_ALWAYS, &primary_cert);
if (!ok || !primary_cert)
return nullptr;
ScopedPCCERT_CONTEXT scoped_primary_cert(primary_cert);
for (PCCERT_CONTEXT intermediate : intermediate_ca_certs) {
CertAddCertificateContextToStore(store.get(), intermediate,
CERT_STORE_ADD_ALWAYS, NULL);
}
#endif
// Note: |primary_cert| retains a reference to |store|, so the store will // Note: |primary_cert| retains a reference to |store|, so the store will
// actually be freed when |primary_cert| is freed. // actually be freed when |primary_cert| is freed.
......
...@@ -47,35 +47,6 @@ NET_EXPORT scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts( ...@@ -47,35 +47,6 @@ NET_EXPORT scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
// multiple threads if no further modifications happen, it is generally // multiple threads if no further modifications happen, it is generally
// preferable for each thread that needs such a context to obtain its own, // preferable for each thread that needs such a context to obtain its own,
// rather than risk thread-safety issues by sharing. // rather than risk thread-safety issues by sharing.
//
// ------------------------------------------------------------------------
// The following remarks only apply when USE_BYTE_CERTS=false (e.g., when
// using x509_certificate_win).
// TODO(mattm): remove references to USE_BYTE_CERTS and clean up the rest of
// the comment when x509_certificate_win is deleted.
//
// The returned PCCERT_CONTEXT *MUST NOT* be stored in an X509Certificate, as
// this will cause os_cert_handle() to return incorrect results.
//
// Depending on the CryptoAPI function, Windows may need to access the
// HCERTSTORE that the passed-in PCCERT_CONTEXT belongs to, such as to
// locate additional intermediates. However, all X509Certificate handles are
// added to a NULL HCERTSTORE, allowing the system to manage the resources. As
// a result, intermediates for |cert->os_cert_handle()| cannot be located
// simply via |cert->os_cert_handle()->hCertStore|, as it refers to a magic
// value indicating "only this certificate".
//
// To avoid this problems, a new in-memory HCERTSTORE is created containing
// just this certificate and its intermediates. The handle to the version of
// the current certificate in the new HCERTSTORE is then returned, with the
// PCCERT_CONTEXT's HCERTSTORE set to be automatically freed when the returned
// certificate handle is freed.
//
// Because of how X509Certificate caching is implemented, attempting to
// create an X509Certificate from the returned PCCERT_CONTEXT may result in
// the original handle (and thus the originall HCERTSTORE) being returned by
// os_cert_handle(). For this reason, the returned PCCERT_CONTEXT *MUST NOT*
// be stored in an X509Certificate.
NET_EXPORT ScopedPCCERT_CONTEXT NET_EXPORT ScopedPCCERT_CONTEXT
CreateCertContextWithChain(const X509Certificate* cert); CreateCertContextWithChain(const X509Certificate* cert);
......
...@@ -187,13 +187,6 @@ ClientCertIdentityList GetClientCertsImpl(HCERTSTORE cert_store, ...@@ -187,13 +187,6 @@ ClientCertIdentityList GetClientCertsImpl(HCERTSTORE cert_store,
intermediates.pop_back(); intermediates.pop_back();
} }
// TODO(mattm): The following comment is only true when not using
// USE_BYTE_CERTS. Remove it once the non-byte-certs code is also removed.
// TODO(svaldez): cert currently wraps cert_context2 which may be backed
// by a smartcard with threading difficulties. Instead, create a fresh
// X509Certificate with CreateFromBytes and route cert_context2 into the
// SSLPrivateKey. Probably changing CertificateList to be a
// pair<X509Certificate, SSLPrivateKeyCallback>.
scoped_refptr<X509Certificate> cert = scoped_refptr<X509Certificate> cert =
x509_util::CreateX509CertificateFromCertContexts(cert_context2, x509_util::CreateX509CertificateFromCertContexts(cert_context2,
intermediates); intermediates);
...@@ -237,7 +230,6 @@ void ClientCertStoreWin::GetClientCerts( ...@@ -237,7 +230,6 @@ void ClientCertStoreWin::GetClientCerts(
return; return;
} }
#if BUILDFLAG(USE_BYTE_CERTS)
if (base::PostTaskAndReplyWithResult( if (base::PostTaskAndReplyWithResult(
GetSSLPlatformKeyTaskRunner().get(), FROM_HERE, GetSSLPlatformKeyTaskRunner().get(), FROM_HERE,
// Caller is responsible for keeping the |request| alive // Caller is responsible for keeping the |request| alive
...@@ -250,11 +242,6 @@ void ClientCertStoreWin::GetClientCerts( ...@@ -250,11 +242,6 @@ void ClientCertStoreWin::GetClientCerts(
// If the task could not be posted, behave as if there were no certificates. // If the task could not be posted, behave as if there were no certificates.
callback.Run(ClientCertIdentityList()); callback.Run(ClientCertIdentityList());
#else
// When using PCERT_CONTEXT based X509Certificate, must do this on the same
// thread.
callback.Run(GetClientCertsWithMyCertStore(request));
#endif
} }
// static // static
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment