15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <blapi.h>  // Implement CalculateChainFingerprint() with NSS.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/pickle.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sha1.h"
135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/capi_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/scoped_capi_types.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(lib, "crypt32.lib")
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef crypto::ScopedCAPIHandle<
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HCERTSTORE,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crypto::CAPIDestroyerWithFlags<HCERTSTORE,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   CertCloseStore, 0> > ScopedHCERTSTORE;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExplodedTimeToSystemTime(const base::Time::Exploded& exploded,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              SYSTEMTIME* system_time) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_time->wYear = exploded.year;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_time->wMonth = exploded.month;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_time->wDayOfWeek = exploded.day_of_week;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_time->wDay = exploded.day_of_month;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_time->wHour = exploded.hour;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_time->wMinute = exploded.minute;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_time->wSecond = exploded.second;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_time->wMilliseconds = exploded.millisecond;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Decodes the cert's subjectAltName extension into a CERT_ALT_NAME_INFO
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// structure and stores it in *output.
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GetCertSubjectAltName(
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PCCERT_CONTEXT cert,
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<CERT_ALT_NAME_INFO, base::FreeDeleter>* output) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PCERT_EXTENSION extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                cert->pCertInfo->cExtension,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                cert->pCertInfo->rgExtension);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CRYPT_DECODE_PARA decode_para;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decode_para.cbSize = sizeof(decode_para);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decode_para.pfnAlloc = crypto::CryptAlloc;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decode_para.pfnFree = crypto::CryptFree;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERT_ALT_NAME_INFO* alt_name_info = NULL;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD alt_name_info_size = 0;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL rv;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           szOID_SUBJECT_ALT_NAME2,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           extension->Value.pbData,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           extension->Value.cbData,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &decode_para,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &alt_name_info,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &alt_name_info_size);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output->reset(alt_name_info);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddCertsFromStore(HCERTSTORE store,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       X509Certificate::OSCertHandles* results) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PCCERT_CONTEXT cert = NULL;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while ((cert = CertEnumCertificatesInStore(store, cert)) != NULL) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PCCERT_CONTEXT to_add = NULL;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CertAddCertificateContextToStore(
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NULL,  // The cert won't be persisted in any cert store. This breaks
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               // any association the context currently has to |store|, which
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               // allows us, the caller, to safely close |store| without
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               // releasing the cert handles.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cert,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_STORE_ADD_USE_EXISTING,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &to_add) && to_add != NULL) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // When processing stores generated from PKCS#7/PKCS#12 files, it
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // appears that the order returned is the inverse of the order that it
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // appeared in the file.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(rsleevi): Ensure this order is consistent across all Win
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // versions
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      results->insert(results->begin(), to_add);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandles ParsePKCS7(const char* data, size_t length) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  X509Certificate::OSCertHandles results;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERT_BLOB data_blob;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_blob.cbData = length;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(data));
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HCERTSTORE out_store = NULL;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD expected_types = CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED |
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &data_blob, expected_types,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        &out_store, NULL, NULL) || out_store == NULL) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return results;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddCertsFromStore(out_store, &results);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertCloseStore(out_store, CERT_CLOSE_STORE_CHECK_FLAG);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return results;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Given a CERT_NAME_BLOB, returns true if it appears in a given list,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// formatted as a vector of strings holding DER-encoded X.509
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DistinguishedName entries.
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsCertNameBlobInIssuerList(
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CERT_NAME_BLOB* name_blob,
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<std::string>& issuer_names) {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<std::string>::const_iterator it = issuer_names.begin();
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != issuer_names.end(); ++it) {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CERT_NAME_BLOB issuer_blob;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    issuer_blob.pbData =
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<BYTE*>(const_cast<char*>(it->data()));
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    issuer_blob.cbData = static_cast<DWORD>(it->length());
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BOOL rb = CertCompareCertificateName(
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &issuer_blob, name_blob);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rb)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::Initialize() {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(cert_handle_);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subject_.ParseDistinguishedName(cert_handle_->pCertInfo->Subject.pbData,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  cert_handle_->pCertInfo->Subject.cbData);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  issuer_.ParseDistinguishedName(cert_handle_->pCertInfo->Issuer.pbData,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 cert_handle_->pCertInfo->Issuer.cbData);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fingerprint_ = CalculateFingerprint(cert_handle_);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber;
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> serial_bytes(new uint8[serial->cbData]);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0; i < serial->cbData; i++)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    serial_bytes[i] = serial->pbData[serial->cbData - i - 1];
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  serial_number_ = std::string(
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<char*>(serial_bytes.get()), serial->cbData);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::GetSubjectAltName(
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string>* dns_names,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string>* ip_addrs) const {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dns_names)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dns_names->clear();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ip_addrs)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ip_addrs->clear();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cert_handle_)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<CERT_ALT_NAME_INFO, base::FreeDeleter> alt_name_info;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetCertSubjectAltName(cert_handle_, &alt_name_info);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERT_ALT_NAME_INFO* alt_name = alt_name_info.get();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (alt_name) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_entries = alt_name->cAltEntry;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < num_entries; i++) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // dNSName is an ASN.1 IA5String representing a string of ASCII
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // characters, so we can use UTF16ToASCII here.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const CERT_ALT_NAME_ENTRY& entry = alt_name->rgAltEntry[i];
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (dns_names && entry.dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) {
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        dns_names->push_back(base::UTF16ToASCII(entry.pwszDNSName));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (ip_addrs &&
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 entry.dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ip_addrs->push_back(std::string(
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            reinterpret_cast<const char*>(entry.IPAddress.pbData),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            entry.IPAddress.cbData));
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PCCERT_CONTEXT X509Certificate::CreateOSCertChainForCert() const {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create an in-memory certificate store to hold this certificate and
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // any intermediate certificates in |intermediate_ca_certs_|. The store
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will be referenced in the returned PCCERT_CONTEXT, and will not be freed
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // until the PCCERT_CONTEXT is freed.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedHCERTSTORE store(CertOpenStore(
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERT_STORE_PROV_MEMORY, 0, NULL,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL));
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!store.get())
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: This preserves all of the properties of |os_cert_handle()| except
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // properties that hold access to already-opened private keys. If a handle
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has already been unlocked (eg: PIN prompt), then the first time that the
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // identity is used for client auth, it may prompt the user again.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PCCERT_CONTEXT primary_cert;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL ok = CertAddCertificateContextToStore(store.get(), os_cert_handle(),
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             CERT_STORE_ADD_ALWAYS,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             &primary_cert);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ok || !primary_cert)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CertAddCertificateContextToStore(store.get(), intermediate_ca_certs_[i],
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     CERT_STORE_ADD_ALWAYS, NULL);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: |store| is explicitly not released, as the call to CertCloseStore()
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // when |store| goes out of scope will not actually free the store. Instead,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the store will be freed when |primary_cert| is freed.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return primary_cert;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    std::string* encoded) {
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!cert_handle || !cert_handle->pbCertEncoded ||
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      !cert_handle->cbCertEncoded) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoded->assign(reinterpret_cast<char*>(cert_handle->pbCertEncoded),
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  cert_handle->cbCertEncoded);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   X509Certificate::OSCertHandle b) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(a && b);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (a == b)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return a->cbCertEncoded == b->cbCertEncoded &&
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcmp(a->pbCertEncoded, b->pbCertEncoded, a->cbCertEncoded) == 0;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* data, int length) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSCertHandle cert_handle = NULL;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CertAddEncodedCertificateToStore(
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL, X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(data),
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      length, CERT_STORE_ADD_USE_EXISTING, &cert_handle))
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return cert_handle;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* data, int length, Format format) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSCertHandles results;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (format) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FORMAT_SINGLE_CERTIFICATE: {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (handle != NULL)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        results.push_back(handle);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FORMAT_PKCS7:
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      results = ParsePKCS7(data, length);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Certificate format " << format << " unimplemented";
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return results;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSCertHandle cert_handle) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CertDuplicateCertificateContext(cert_handle);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertFreeCertificateContext(cert_handle);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SHA1HashValue X509Certificate::CalculateFingerprint(
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSCertHandle cert) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(NULL != cert->pbCertEncoded);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL rv;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHA1HashValue sha1;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD sha1_size = sizeof(sha1.data);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            cert->cbCertEncoded, sha1.data, &sha1_size);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(rv && sha1_size == sizeof(sha1.data));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!rv)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(sha1.data, 0, sizeof(sha1.data));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sha1;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(wtc): This function is implemented with NSS low-level hash
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functions to ensure it is fast.  Reimplement this function with
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CryptoAPI.  May need to cache the HCRYPTPROV to reduce the overhead.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SHA1HashValue X509Certificate::CalculateCAFingerprint(
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OSCertHandles& intermediates) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHA1HashValue sha1;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(sha1.data, 0, sizeof(sha1.data));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHA1Context* sha1_ctx = SHA1_NewContext();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!sha1_ctx)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sha1;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHA1_Begin(sha1_ctx);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < intermediates.size(); ++i) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PCCERT_CONTEXT ca_cert = intermediates[i];
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SHA1_Update(sha1_ctx, ca_cert->pbCertEncoded, ca_cert->cbCertEncoded);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int result_len;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHA1_End(sha1_ctx, sha1.data, &result_len, SHA1_LENGTH);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHA1_DestroyContext(sha1_ctx, PR_TRUE);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sha1;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandle
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* data;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int length;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pickle_iter->ReadData(&data, &length))
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Legacy serialized certificates were serialized with extended attributes,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rather than as DER only. As a result, these serialized certificates are
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not portable across platforms and may have side-effects on Windows due
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to extended attributes being serialized/deserialized -
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://crbug.com/118706. To avoid deserializing these attributes, write
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the deserialized cert into a temporary cert store and then create a new
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cert from the DER - that is, without attributes.
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedHCERTSTORE store(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL));
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!store.get())
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSCertHandle cert_handle = NULL;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CertAddSerializedElementToStore(
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          store.get(), reinterpret_cast<const BYTE*>(data), length,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL, reinterpret_cast<const void **>(&cert_handle))) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string encoded;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = GetDEREncoded(cert_handle, &encoded);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FreeOSCertHandle(cert_handle);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cert_handle = NULL;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cert_handle = CreateOSCertHandleFromBytes(encoded.data(), encoded.size());
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return cert_handle;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                Pickle* pickle) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pickle->WriteData(
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<char*>(cert_handle->pbCertEncoded),
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cert_handle->cbCertEncoded);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       size_t* size_bits,
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       PublicKeyType* type) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *type = kPublicKeyTypeUnknown;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *size_bits = 0;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PCCRYPT_OID_INFO oid_info = CryptFindOIDInfo(
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CRYPT_OID_INFO_OID_KEY,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cert_handle->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CRYPT_PUBKEY_ALG_OID_GROUP_ID);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!oid_info)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(oid_info->dwGroupId,
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           static_cast<DWORD>(CRYPT_PUBKEY_ALG_OID_GROUP_ID));
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *size_bits = CertGetPublicKeyLength(
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &cert_handle->pCertInfo->SubjectPublicKeyInfo);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
409a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (IS_SPECIAL_OID_INFO_ALGID(oid_info->Algid)) {
410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // For an EC public key, oid_info->Algid is CALG_OID_INFO_PARAMETERS
411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // (0xFFFFFFFE). Need to handle it as a special case.
412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (strcmp(oid_info->pszOID, szOID_ECC_PUBLIC_KEY) == 0) {
413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      *type = kPublicKeyTypeECDSA;
414a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    } else {
415a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      NOTREACHED();
416a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
418a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (oid_info->Algid) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CALG_RSA_SIGN:
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CALG_RSA_KEYX:
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *type = kPublicKeyTypeRSA;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CALG_DSS_SIGN:
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *type = kPublicKeyTypeDSA;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CALG_ECDSA:
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *type = kPublicKeyTypeECDSA;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CALG_ECDH:
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *type = kPublicKeyTypeECDH;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool X509Certificate::IsIssuedByEncoded(
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<std::string>& valid_issuers) {
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the certificate's issuer in the list?
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsCertNameBlobInIssuerList(&cert_handle_->pCertInfo->Issuer,
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 valid_issuers)) {
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Otherwise, is any of the intermediate CA subjects in the list?
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (OSCertHandles::iterator it = intermediate_ca_certs_.begin();
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != intermediate_ca_certs_.end(); ++it) {
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (IsCertNameBlobInIssuerList(&(*it)->pCertInfo->Issuer,
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   valid_issuers)) {
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
457