Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/base/x509_certificate.h"
      6 
      7 #include "base/lazy_instance.h"
      8 #include "base/logging.h"
      9 #include "base/pickle.h"
     10 #include "base/sha1.h"
     11 #include "base/string_tokenizer.h"
     12 #include "base/string_util.h"
     13 #include "base/utf_string_conversions.h"
     14 #include "crypto/rsa_private_key.h"
     15 #include "crypto/scoped_capi_types.h"
     16 #include "net/base/asn1_util.h"
     17 #include "net/base/cert_status_flags.h"
     18 #include "net/base/cert_verify_result.h"
     19 #include "net/base/ev_root_ca_metadata.h"
     20 #include "net/base/net_errors.h"
     21 #include "net/base/scoped_cert_chain_context.h"
     22 #include "net/base/test_root_certs.h"
     23 #include "net/base/x509_certificate_known_roots_win.h"
     24 
     25 #pragma comment(lib, "crypt32.lib")
     26 
     27 using base::Time;
     28 
     29 namespace net {
     30 
     31 namespace {
     32 
     33 typedef crypto::ScopedCAPIHandle<
     34     HCERTSTORE,
     35     crypto::CAPIDestroyerWithFlags<HCERTSTORE,
     36                                    CertCloseStore, 0> > ScopedHCERTSTORE;
     37 
     38 struct FreeChainEngineFunctor {
     39   void operator()(HCERTCHAINENGINE engine) const {
     40     if (engine)
     41       CertFreeCertificateChainEngine(engine);
     42   }
     43 };
     44 
     45 typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor>
     46     ScopedHCERTCHAINENGINE;
     47 
     48 //-----------------------------------------------------------------------------
     49 
     50 // TODO(wtc): This is a copy of the MapSecurityError function in
     51 // ssl_client_socket_win.cc.  Another function that maps Windows error codes
     52 // to our network error codes is WinInetUtil::OSErrorToNetError.  We should
     53 // eliminate the code duplication.
     54 int MapSecurityError(SECURITY_STATUS err) {
     55   // There are numerous security error codes, but these are the ones we thus
     56   // far find interesting.
     57   switch (err) {
     58     case SEC_E_WRONG_PRINCIPAL:  // Schannel
     59     case CERT_E_CN_NO_MATCH:  // CryptoAPI
     60       return ERR_CERT_COMMON_NAME_INVALID;
     61     case SEC_E_UNTRUSTED_ROOT:  // Schannel
     62     case CERT_E_UNTRUSTEDROOT:  // CryptoAPI
     63       return ERR_CERT_AUTHORITY_INVALID;
     64     case SEC_E_CERT_EXPIRED:  // Schannel
     65     case CERT_E_EXPIRED:  // CryptoAPI
     66       return ERR_CERT_DATE_INVALID;
     67     case CRYPT_E_NO_REVOCATION_CHECK:
     68       return ERR_CERT_NO_REVOCATION_MECHANISM;
     69     case CRYPT_E_REVOCATION_OFFLINE:
     70       return ERR_CERT_UNABLE_TO_CHECK_REVOCATION;
     71     case CRYPT_E_REVOKED:  // Schannel and CryptoAPI
     72       return ERR_CERT_REVOKED;
     73     case SEC_E_CERT_UNKNOWN:
     74     case CERT_E_ROLE:
     75       return ERR_CERT_INVALID;
     76     case CERT_E_WRONG_USAGE:
     77       // TODO(wtc): Should we add ERR_CERT_WRONG_USAGE?
     78       return ERR_CERT_INVALID;
     79     // We received an unexpected_message or illegal_parameter alert message
     80     // from the server.
     81     case SEC_E_ILLEGAL_MESSAGE:
     82       return ERR_SSL_PROTOCOL_ERROR;
     83     case SEC_E_ALGORITHM_MISMATCH:
     84       return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
     85     case SEC_E_INVALID_HANDLE:
     86       return ERR_UNEXPECTED;
     87     case SEC_E_OK:
     88       return OK;
     89     default:
     90       LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
     91       return ERR_FAILED;
     92   }
     93 }
     94 
     95 // Map the errors in the chain_context->TrustStatus.dwErrorStatus returned by
     96 // CertGetCertificateChain to our certificate status flags.
     97 int MapCertChainErrorStatusToCertStatus(DWORD error_status) {
     98   int cert_status = 0;
     99 
    100   // We don't include CERT_TRUST_IS_NOT_TIME_NESTED because it's obsolete and
    101   // we wouldn't consider it an error anyway
    102   const DWORD kDateInvalidErrors = CERT_TRUST_IS_NOT_TIME_VALID |
    103                                    CERT_TRUST_CTL_IS_NOT_TIME_VALID;
    104   if (error_status & kDateInvalidErrors)
    105     cert_status |= CERT_STATUS_DATE_INVALID;
    106 
    107   const DWORD kAuthorityInvalidErrors = CERT_TRUST_IS_UNTRUSTED_ROOT |
    108                                         CERT_TRUST_IS_EXPLICIT_DISTRUST |
    109                                         CERT_TRUST_IS_PARTIAL_CHAIN;
    110   if (error_status & kAuthorityInvalidErrors)
    111     cert_status |= CERT_STATUS_AUTHORITY_INVALID;
    112 
    113   if ((error_status & CERT_TRUST_REVOCATION_STATUS_UNKNOWN) &&
    114       !(error_status & CERT_TRUST_IS_OFFLINE_REVOCATION))
    115     cert_status |= CERT_STATUS_NO_REVOCATION_MECHANISM;
    116 
    117   if (error_status & CERT_TRUST_IS_OFFLINE_REVOCATION)
    118     cert_status |= CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
    119 
    120   if (error_status & CERT_TRUST_IS_REVOKED)
    121     cert_status |= CERT_STATUS_REVOKED;
    122 
    123   const DWORD kWrongUsageErrors = CERT_TRUST_IS_NOT_VALID_FOR_USAGE |
    124                                   CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE;
    125   if (error_status & kWrongUsageErrors) {
    126     // TODO(wtc): Should we add CERT_STATUS_WRONG_USAGE?
    127     cert_status |= CERT_STATUS_INVALID;
    128   }
    129 
    130   // The rest of the errors.
    131   const DWORD kCertInvalidErrors =
    132       CERT_TRUST_IS_NOT_SIGNATURE_VALID |
    133       CERT_TRUST_IS_CYCLIC |
    134       CERT_TRUST_INVALID_EXTENSION |
    135       CERT_TRUST_INVALID_POLICY_CONSTRAINTS |
    136       CERT_TRUST_INVALID_BASIC_CONSTRAINTS |
    137       CERT_TRUST_INVALID_NAME_CONSTRAINTS |
    138       CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID |
    139       CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT |
    140       CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT |
    141       CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT |
    142       CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT |
    143       CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY |
    144       CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT;
    145   if (error_status & kCertInvalidErrors)
    146     cert_status |= CERT_STATUS_INVALID;
    147 
    148   return cert_status;
    149 }
    150 
    151 void ExplodedTimeToSystemTime(const base::Time::Exploded& exploded,
    152                               SYSTEMTIME* system_time) {
    153   system_time->wYear = exploded.year;
    154   system_time->wMonth = exploded.month;
    155   system_time->wDayOfWeek = exploded.day_of_week;
    156   system_time->wDay = exploded.day_of_month;
    157   system_time->wHour = exploded.hour;
    158   system_time->wMinute = exploded.minute;
    159   system_time->wSecond = exploded.second;
    160   system_time->wMilliseconds = exploded.millisecond;
    161 }
    162 
    163 //-----------------------------------------------------------------------------
    164 
    165 // Wrappers of malloc and free for CRYPT_DECODE_PARA, which requires the
    166 // WINAPI calling convention.
    167 void* WINAPI MyCryptAlloc(size_t size) {
    168   return malloc(size);
    169 }
    170 
    171 void WINAPI MyCryptFree(void* p) {
    172   free(p);
    173 }
    174 
    175 // Decodes the cert's subjectAltName extension into a CERT_ALT_NAME_INFO
    176 // structure and stores it in *output.
    177 void GetCertSubjectAltName(PCCERT_CONTEXT cert,
    178                            scoped_ptr_malloc<CERT_ALT_NAME_INFO>* output) {
    179   PCERT_EXTENSION extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2,
    180                                                 cert->pCertInfo->cExtension,
    181                                                 cert->pCertInfo->rgExtension);
    182   if (!extension)
    183     return;
    184 
    185   CRYPT_DECODE_PARA decode_para;
    186   decode_para.cbSize = sizeof(decode_para);
    187   decode_para.pfnAlloc = MyCryptAlloc;
    188   decode_para.pfnFree = MyCryptFree;
    189   CERT_ALT_NAME_INFO* alt_name_info = NULL;
    190   DWORD alt_name_info_size = 0;
    191   BOOL rv;
    192   rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
    193                            szOID_SUBJECT_ALT_NAME2,
    194                            extension->Value.pbData,
    195                            extension->Value.cbData,
    196                            CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
    197                            &decode_para,
    198                            &alt_name_info,
    199                            &alt_name_info_size);
    200   if (rv)
    201     output->reset(alt_name_info);
    202 }
    203 
    204 // Returns true if any common name in the certificate's Subject field contains
    205 // a NULL character.
    206 bool CertSubjectCommonNameHasNull(PCCERT_CONTEXT cert) {
    207   CRYPT_DECODE_PARA decode_para;
    208   decode_para.cbSize = sizeof(decode_para);
    209   decode_para.pfnAlloc = MyCryptAlloc;
    210   decode_para.pfnFree = MyCryptFree;
    211   CERT_NAME_INFO* name_info = NULL;
    212   DWORD name_info_size = 0;
    213   BOOL rv;
    214   rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
    215                            X509_NAME,
    216                            cert->pCertInfo->Subject.pbData,
    217                            cert->pCertInfo->Subject.cbData,
    218                            CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
    219                            &decode_para,
    220                            &name_info,
    221                            &name_info_size);
    222   if (rv) {
    223     scoped_ptr_malloc<CERT_NAME_INFO> scoped_name_info(name_info);
    224 
    225     // The Subject field may have multiple common names.  According to the
    226     // "PKI Layer Cake" paper, CryptoAPI uses every common name in the
    227     // Subject field, so we inspect every common name.
    228     //
    229     // From RFC 5280:
    230     // X520CommonName ::= CHOICE {
    231     //       teletexString     TeletexString   (SIZE (1..ub-common-name)),
    232     //       printableString   PrintableString (SIZE (1..ub-common-name)),
    233     //       universalString   UniversalString (SIZE (1..ub-common-name)),
    234     //       utf8String        UTF8String      (SIZE (1..ub-common-name)),
    235     //       bmpString         BMPString       (SIZE (1..ub-common-name)) }
    236     //
    237     // We also check IA5String and VisibleString.
    238     for (DWORD i = 0; i < name_info->cRDN; ++i) {
    239       PCERT_RDN rdn = &name_info->rgRDN[i];
    240       for (DWORD j = 0; j < rdn->cRDNAttr; ++j) {
    241         PCERT_RDN_ATTR rdn_attr = &rdn->rgRDNAttr[j];
    242         if (strcmp(rdn_attr->pszObjId, szOID_COMMON_NAME) == 0) {
    243           switch (rdn_attr->dwValueType) {
    244             // After the CryptoAPI ASN.1 security vulnerabilities described in
    245             // http://www.microsoft.com/technet/security/Bulletin/MS09-056.mspx
    246             // were patched, we get CERT_RDN_ENCODED_BLOB for a common name
    247             // that contains a NULL character.
    248             case CERT_RDN_ENCODED_BLOB:
    249               break;
    250             // Array of 8-bit characters.
    251             case CERT_RDN_PRINTABLE_STRING:
    252             case CERT_RDN_TELETEX_STRING:
    253             case CERT_RDN_IA5_STRING:
    254             case CERT_RDN_VISIBLE_STRING:
    255               for (DWORD k = 0; k < rdn_attr->Value.cbData; ++k) {
    256                 if (rdn_attr->Value.pbData[k] == '\0')
    257                   return true;
    258               }
    259               break;
    260             // Array of 16-bit characters.
    261             case CERT_RDN_BMP_STRING:
    262             case CERT_RDN_UTF8_STRING: {
    263               DWORD num_wchars = rdn_attr->Value.cbData / 2;
    264               wchar_t* common_name =
    265                   reinterpret_cast<wchar_t*>(rdn_attr->Value.pbData);
    266               for (DWORD k = 0; k < num_wchars; ++k) {
    267                 if (common_name[k] == L'\0')
    268                   return true;
    269               }
    270               break;
    271             }
    272             // Array of ints (32-bit).
    273             case CERT_RDN_UNIVERSAL_STRING: {
    274               DWORD num_ints = rdn_attr->Value.cbData / 4;
    275               int* common_name =
    276                   reinterpret_cast<int*>(rdn_attr->Value.pbData);
    277               for (DWORD k = 0; k < num_ints; ++k) {
    278                 if (common_name[k] == 0)
    279                   return true;
    280               }
    281               break;
    282             }
    283             default:
    284               NOTREACHED();
    285               break;
    286           }
    287         }
    288       }
    289     }
    290   }
    291   return false;
    292 }
    293 
    294 // Saves some information about the certificate chain chain_context in
    295 // *verify_result.  The caller MUST initialize *verify_result before calling
    296 // this function.
    297 void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context,
    298                       CertVerifyResult* verify_result) {
    299   PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0];
    300   int num_elements = first_chain->cElement;
    301   PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement;
    302 
    303   // Each chain starts with the end entity certificate (i = 0) and ends with
    304   // the root CA certificate (i = num_elements - 1).  Do not inspect the
    305   // signature algorithm of the root CA certificate because the signature on
    306   // the trust anchor is not important.
    307   for (int i = 0; i < num_elements - 1; ++i) {
    308     PCCERT_CONTEXT cert = element[i]->pCertContext;
    309     const char* algorithm = cert->pCertInfo->SignatureAlgorithm.pszObjId;
    310     if (strcmp(algorithm, szOID_RSA_MD5RSA) == 0) {
    311       // md5WithRSAEncryption: 1.2.840.113549.1.1.4
    312       verify_result->has_md5 = true;
    313       if (i != 0)
    314         verify_result->has_md5_ca = true;
    315     } else if (strcmp(algorithm, szOID_RSA_MD2RSA) == 0) {
    316       // md2WithRSAEncryption: 1.2.840.113549.1.1.2
    317       verify_result->has_md2 = true;
    318       if (i != 0)
    319         verify_result->has_md2_ca = true;
    320     } else if (strcmp(algorithm, szOID_RSA_MD4RSA) == 0) {
    321       // md4WithRSAEncryption: 1.2.840.113549.1.1.3
    322       verify_result->has_md4 = true;
    323     }
    324   }
    325 }
    326 
    327 // Decodes the cert's certificatePolicies extension into a CERT_POLICIES_INFO
    328 // structure and stores it in *output.
    329 void GetCertPoliciesInfo(PCCERT_CONTEXT cert,
    330                          scoped_ptr_malloc<CERT_POLICIES_INFO>* output) {
    331   PCERT_EXTENSION extension = CertFindExtension(szOID_CERT_POLICIES,
    332                                                 cert->pCertInfo->cExtension,
    333                                                 cert->pCertInfo->rgExtension);
    334   if (!extension)
    335     return;
    336 
    337   CRYPT_DECODE_PARA decode_para;
    338   decode_para.cbSize = sizeof(decode_para);
    339   decode_para.pfnAlloc = MyCryptAlloc;
    340   decode_para.pfnFree = MyCryptFree;
    341   CERT_POLICIES_INFO* policies_info = NULL;
    342   DWORD policies_info_size = 0;
    343   BOOL rv;
    344   rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
    345                            szOID_CERT_POLICIES,
    346                            extension->Value.pbData,
    347                            extension->Value.cbData,
    348                            CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
    349                            &decode_para,
    350                            &policies_info,
    351                            &policies_info_size);
    352   if (rv)
    353     output->reset(policies_info);
    354 }
    355 
    356 // Helper function to parse a principal from a WinInet description of that
    357 // principal.
    358 void ParsePrincipal(const std::string& description,
    359                     CertPrincipal* principal) {
    360   // The description of the principal is a string with each LDAP value on
    361   // a separate line.
    362   const std::string kDelimiters("\r\n");
    363 
    364   std::vector<std::string> common_names, locality_names, state_names,
    365       country_names;
    366 
    367   // TODO(jcampan): add business_category and serial_number.
    368   const std::string kPrefixes[] = { std::string("CN="),
    369                                     std::string("L="),
    370                                     std::string("S="),
    371                                     std::string("C="),
    372                                     std::string("STREET="),
    373                                     std::string("O="),
    374                                     std::string("OU="),
    375                                     std::string("DC=") };
    376 
    377   std::vector<std::string>* values[] = {
    378       &common_names, &locality_names,
    379       &state_names, &country_names,
    380       &(principal->street_addresses),
    381       &(principal->organization_names),
    382       &(principal->organization_unit_names),
    383       &(principal->domain_components) };
    384   DCHECK(arraysize(kPrefixes) == arraysize(values));
    385 
    386   StringTokenizer str_tok(description, kDelimiters);
    387   while (str_tok.GetNext()) {
    388     std::string entry = str_tok.token();
    389     for (int i = 0; i < arraysize(kPrefixes); i++) {
    390       if (!entry.compare(0, kPrefixes[i].length(), kPrefixes[i])) {
    391         std::string value = entry.substr(kPrefixes[i].length());
    392         // Remove enclosing double-quotes if any.
    393         if (value.size() >= 2 &&
    394             value[0] == '"' && value[value.size() - 1] == '"')
    395           value = value.substr(1, value.size() - 2);
    396         values[i]->push_back(value);
    397         break;
    398       }
    399     }
    400   }
    401 
    402   // We don't expect to have more than one CN, L, S, and C. If there is more
    403   // than one entry for CN, L, S, and C, we will use the first entry. Although
    404   // RFC 2818 Section 3.1 says the "most specific" CN should be used, that term
    405   // has been removed in draft-saintandre-tls-server-id-check, which requires
    406   // that the Subject field contains only one CN. So it is fine for us to just
    407   // use the first CN.
    408   std::vector<std::string>* single_value_lists[4] = {
    409       &common_names, &locality_names, &state_names, &country_names };
    410   std::string* single_values[4] = {
    411       &principal->common_name, &principal->locality_name,
    412       &principal->state_or_province_name, &principal->country_name };
    413   for (int i = 0; i < arraysize(single_value_lists); ++i) {
    414     int length = static_cast<int>(single_value_lists[i]->size());
    415     if (!single_value_lists[i]->empty())
    416       *(single_values[i]) = (*(single_value_lists[i]))[0];
    417   }
    418 }
    419 
    420 void AddCertsFromStore(HCERTSTORE store,
    421                        X509Certificate::OSCertHandles* results) {
    422   PCCERT_CONTEXT cert = NULL;
    423 
    424   while ((cert = CertEnumCertificatesInStore(store, cert)) != NULL) {
    425     PCCERT_CONTEXT to_add = NULL;
    426     if (CertAddCertificateContextToStore(
    427         NULL,  // The cert won't be persisted in any cert store. This breaks
    428                // any association the context currently has to |store|, which
    429                // allows us, the caller, to safely close |store| without
    430                // releasing the cert handles.
    431         cert,
    432         CERT_STORE_ADD_USE_EXISTING,
    433         &to_add) && to_add != NULL) {
    434       // When processing stores generated from PKCS#7/PKCS#12 files, it
    435       // appears that the order returned is the inverse of the order that it
    436       // appeared in the file.
    437       // TODO(rsleevi): Ensure this order is consistent across all Win
    438       // versions
    439       results->insert(results->begin(), to_add);
    440     }
    441   }
    442 }
    443 
    444 X509Certificate::OSCertHandles ParsePKCS7(const char* data, size_t length) {
    445   X509Certificate::OSCertHandles results;
    446   CERT_BLOB data_blob;
    447   data_blob.cbData = length;
    448   data_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(data));
    449 
    450   HCERTSTORE out_store = NULL;
    451 
    452   DWORD expected_types = CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
    453                          CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED |
    454                          CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED;
    455 
    456   if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &data_blob, expected_types,
    457                         CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL,
    458                         &out_store, NULL, NULL) || out_store == NULL) {
    459     return results;
    460   }
    461 
    462   AddCertsFromStore(out_store, &results);
    463   CertCloseStore(out_store, CERT_CLOSE_STORE_CHECK_FLAG);
    464 
    465   return results;
    466 }
    467 
    468 void AppendPublicKeyHashes(PCCERT_CHAIN_CONTEXT chain,
    469                            std::vector<SHA1Fingerprint>* hashes) {
    470   if (chain->cChain == 0)
    471     return;
    472 
    473   PCERT_SIMPLE_CHAIN first_chain = chain->rgpChain[0];
    474   PCERT_CHAIN_ELEMENT* const element = first_chain->rgpElement;
    475 
    476   const DWORD num_elements = first_chain->cElement;
    477   for (DWORD i = 0; i < num_elements; i++) {
    478     PCCERT_CONTEXT cert = element[i]->pCertContext;
    479 
    480     base::StringPiece der_bytes(
    481         reinterpret_cast<const char*>(cert->pbCertEncoded),
    482         cert->cbCertEncoded);
    483     base::StringPiece spki_bytes;
    484     if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes))
    485       continue;
    486 
    487     SHA1Fingerprint hash;
    488     base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()),
    489                         spki_bytes.size(), hash.data);
    490     hashes->push_back(hash);
    491   }
    492 }
    493 
    494 }  // namespace
    495 
    496 void X509Certificate::Initialize() {
    497   std::wstring subject_info;
    498   std::wstring issuer_info;
    499   DWORD name_size;
    500   DCHECK(cert_handle_);
    501   name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
    502                             &cert_handle_->pCertInfo->Subject,
    503                             CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
    504                             NULL, 0);
    505   name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
    506                             &cert_handle_->pCertInfo->Subject,
    507                             CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
    508                             WriteInto(&subject_info, name_size), name_size);
    509   name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
    510                             &cert_handle_->pCertInfo->Issuer,
    511                             CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
    512                             NULL, 0);
    513   name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
    514                             &cert_handle_->pCertInfo->Issuer,
    515                             CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
    516                             WriteInto(&issuer_info, name_size), name_size);
    517   ParsePrincipal(WideToUTF8(subject_info), &subject_);
    518   ParsePrincipal(WideToUTF8(issuer_info), &issuer_);
    519 
    520   valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore);
    521   valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter);
    522 
    523   fingerprint_ = CalculateFingerprint(cert_handle_);
    524 
    525   const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber;
    526   scoped_array<uint8> serial_bytes(new uint8[serial->cbData]);
    527   for (unsigned i = 0; i < serial->cbData; i++)
    528     serial_bytes[i] = serial->pbData[serial->cbData - i - 1];
    529   serial_number_ = std::string(
    530       reinterpret_cast<char*>(serial_bytes.get()), serial->cbData);
    531   // Remove leading zeros.
    532   while (serial_number_.size() > 1 && serial_number_[0] == 0)
    533     serial_number_ = serial_number_.substr(1, serial_number_.size() - 1);
    534 }
    535 
    536 // IsIssuedByKnownRoot returns true if the given chain is rooted at a root CA
    537 // which we recognise as a standard root.
    538 // static
    539 bool X509Certificate::IsIssuedByKnownRoot(PCCERT_CHAIN_CONTEXT chain_context) {
    540   PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0];
    541   int num_elements = first_chain->cElement;
    542   if (num_elements < 1)
    543     return false;
    544   PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement;
    545   PCCERT_CONTEXT cert = element[num_elements - 1]->pCertContext;
    546 
    547   SHA1Fingerprint hash = CalculateFingerprint(cert);
    548   return IsSHA1HashInSortedArray(
    549       hash, &kKnownRootCertSHA1Hashes[0][0], sizeof(kKnownRootCertSHA1Hashes));
    550 }
    551 
    552 // static
    553 X509Certificate* X509Certificate::CreateSelfSigned(
    554     crypto::RSAPrivateKey* key,
    555     const std::string& subject,
    556     uint32 serial_number,
    557     base::TimeDelta valid_duration) {
    558   // Get the ASN.1 encoding of the certificate subject.
    559   std::wstring w_subject = ASCIIToWide(subject);
    560   DWORD encoded_subject_length = 0;
    561   if (!CertStrToName(
    562           X509_ASN_ENCODING,
    563           w_subject.c_str(),
    564           CERT_X500_NAME_STR, NULL, NULL, &encoded_subject_length, NULL)) {
    565     return NULL;
    566   }
    567 
    568   scoped_array<BYTE> encoded_subject(new BYTE[encoded_subject_length]);
    569   if (!CertStrToName(
    570           X509_ASN_ENCODING,
    571           w_subject.c_str(),
    572           CERT_X500_NAME_STR, NULL,
    573           encoded_subject.get(),
    574           &encoded_subject_length, NULL)) {
    575     return NULL;
    576   }
    577 
    578   CERT_NAME_BLOB subject_name;
    579   memset(&subject_name, 0, sizeof(subject_name));
    580   subject_name.cbData = encoded_subject_length;
    581   subject_name.pbData = encoded_subject.get();
    582 
    583   CRYPT_ALGORITHM_IDENTIFIER sign_algo;
    584   memset(&sign_algo, 0, sizeof(sign_algo));
    585   sign_algo.pszObjId = szOID_RSA_SHA1RSA;
    586 
    587   base::Time not_before = base::Time::Now();
    588   base::Time not_after = not_before + valid_duration;
    589   base::Time::Exploded exploded;
    590 
    591   // Create the system time structs representing our exploded times.
    592   not_before.UTCExplode(&exploded);
    593   SYSTEMTIME start_time;
    594   ExplodedTimeToSystemTime(exploded, &start_time);
    595   not_after.UTCExplode(&exploded);
    596   SYSTEMTIME end_time;
    597   ExplodedTimeToSystemTime(exploded, &end_time);
    598 
    599   PCCERT_CONTEXT cert_handle =
    600       CertCreateSelfSignCertificate(key->provider(), &subject_name,
    601                                     CERT_CREATE_SELFSIGN_NO_KEY_INFO, NULL,
    602                                     &sign_algo, &start_time, &end_time, NULL);
    603   DCHECK(cert_handle) << "Failed to create self-signed certificate: "
    604                       << GetLastError();
    605   if (!cert_handle)
    606     return NULL;
    607 
    608   X509Certificate* cert = CreateFromHandle(cert_handle,
    609                                            SOURCE_LONE_CERT_IMPORT,
    610                                            OSCertHandles());
    611   FreeOSCertHandle(cert_handle);
    612   return cert;
    613 }
    614 
    615 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
    616   dns_names->clear();
    617   if (cert_handle_) {
    618     scoped_ptr_malloc<CERT_ALT_NAME_INFO> alt_name_info;
    619     GetCertSubjectAltName(cert_handle_, &alt_name_info);
    620     CERT_ALT_NAME_INFO* alt_name = alt_name_info.get();
    621     if (alt_name) {
    622       int num_entries = alt_name->cAltEntry;
    623       for (int i = 0; i < num_entries; i++) {
    624         // dNSName is an ASN.1 IA5String representing a string of ASCII
    625         // characters, so we can use WideToASCII here.
    626         if (alt_name->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME)
    627           dns_names->push_back(
    628               WideToASCII(alt_name->rgAltEntry[i].pwszDNSName));
    629       }
    630     }
    631   }
    632   if (dns_names->empty())
    633     dns_names->push_back(subject_.common_name);
    634 }
    635 
    636 class GlobalCertStore {
    637  public:
    638   HCERTSTORE cert_store() {
    639     return cert_store_;
    640   }
    641 
    642  private:
    643   friend struct base::DefaultLazyInstanceTraits<GlobalCertStore>;
    644 
    645   GlobalCertStore()
    646       : cert_store_(CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL)) {
    647   }
    648 
    649   ~GlobalCertStore() {
    650     CertCloseStore(cert_store_, 0 /* flags */);
    651   }
    652 
    653   const HCERTSTORE cert_store_;
    654 
    655   DISALLOW_COPY_AND_ASSIGN(GlobalCertStore);
    656 };
    657 
    658 static base::LazyInstance<GlobalCertStore> g_cert_store(
    659     base::LINKER_INITIALIZED);
    660 
    661 // static
    662 HCERTSTORE X509Certificate::cert_store() {
    663   return g_cert_store.Get().cert_store();
    664 }
    665 
    666 int X509Certificate::Verify(const std::string& hostname,
    667                             int flags,
    668                             CertVerifyResult* verify_result) const {
    669   verify_result->Reset();
    670   if (!cert_handle_)
    671     return ERR_UNEXPECTED;
    672 
    673   if (IsBlacklisted()) {
    674     verify_result->cert_status |= CERT_STATUS_REVOKED;
    675     return ERR_CERT_REVOKED;
    676   }
    677 
    678   // Build and validate certificate chain.
    679 
    680   CERT_CHAIN_PARA chain_para;
    681   memset(&chain_para, 0, sizeof(chain_para));
    682   chain_para.cbSize = sizeof(chain_para);
    683   // ExtendedKeyUsage.
    684   // We still need to request szOID_SERVER_GATED_CRYPTO and szOID_SGC_NETSCAPE
    685   // today because some certificate chains need them.  IE also requests these
    686   // two usages.
    687   static const LPSTR usage[] = {
    688     szOID_PKIX_KP_SERVER_AUTH,
    689     szOID_SERVER_GATED_CRYPTO,
    690     szOID_SGC_NETSCAPE
    691   };
    692   chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
    693   chain_para.RequestedUsage.Usage.cUsageIdentifier = arraysize(usage);
    694   chain_para.RequestedUsage.Usage.rgpszUsageIdentifier =
    695       const_cast<LPSTR*>(usage);
    696   // We can set CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS to get more chains.
    697   DWORD chain_flags = CERT_CHAIN_CACHE_END_CERT;
    698   if (flags & VERIFY_REV_CHECKING_ENABLED) {
    699     verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
    700     chain_flags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
    701   } else {
    702     chain_flags |= CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
    703     // EV requires revocation checking.
    704     flags &= ~VERIFY_EV_CERT;
    705   }
    706 
    707   // Get the certificatePolicies extension of the certificate.
    708   scoped_ptr_malloc<CERT_POLICIES_INFO> policies_info;
    709   LPSTR ev_policy_oid = NULL;
    710   if (flags & VERIFY_EV_CERT) {
    711     GetCertPoliciesInfo(cert_handle_, &policies_info);
    712     if (policies_info.get()) {
    713       EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
    714       for (DWORD i = 0; i < policies_info->cPolicyInfo; ++i) {
    715         LPSTR policy_oid = policies_info->rgPolicyInfo[i].pszPolicyIdentifier;
    716         if (metadata->IsEVPolicyOID(policy_oid)) {
    717           ev_policy_oid = policy_oid;
    718           chain_para.RequestedIssuancePolicy.dwType = USAGE_MATCH_TYPE_AND;
    719           chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 1;
    720           chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier =
    721               &ev_policy_oid;
    722           break;
    723         }
    724       }
    725     }
    726   }
    727 
    728   // For non-test scenarios, use the default HCERTCHAINENGINE, NULL, which
    729   // corresponds to HCCE_CURRENT_USER and is is initialized as needed by
    730   // crypt32. However, when testing, it is necessary to create a new
    731   // HCERTCHAINENGINE and use that instead. This is because each
    732   // HCERTCHAINENGINE maintains a cache of information about certificates
    733   // encountered, and each test run may modify the trust status of a
    734   // certificate.
    735   ScopedHCERTCHAINENGINE chain_engine(NULL);
    736   if (TestRootCerts::HasInstance())
    737     chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine());
    738 
    739   PCCERT_CHAIN_CONTEXT chain_context;
    740   // IE passes a non-NULL pTime argument that specifies the current system
    741   // time.  IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the
    742   // chain_flags argument.
    743   if (!CertGetCertificateChain(
    744            chain_engine,
    745            cert_handle_,
    746            NULL,  // current system time
    747            cert_handle_->hCertStore,
    748            &chain_para,
    749            chain_flags,
    750            NULL,  // reserved
    751            &chain_context)) {
    752     return MapSecurityError(GetLastError());
    753   }
    754   if (chain_context->TrustStatus.dwErrorStatus &
    755       CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
    756     ev_policy_oid = NULL;
    757     chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0;
    758     chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL;
    759     CertFreeCertificateChain(chain_context);
    760     if (!CertGetCertificateChain(
    761              chain_engine,
    762              cert_handle_,
    763              NULL,  // current system time
    764              cert_handle_->hCertStore,
    765              &chain_para,
    766              chain_flags,
    767              NULL,  // reserved
    768              &chain_context)) {
    769       return MapSecurityError(GetLastError());
    770     }
    771   }
    772   ScopedCertChainContext scoped_chain_context(chain_context);
    773 
    774   GetCertChainInfo(chain_context, verify_result);
    775   verify_result->cert_status |= MapCertChainErrorStatusToCertStatus(
    776       chain_context->TrustStatus.dwErrorStatus);
    777 
    778   // Treat certificates signed using broken signature algorithms as invalid.
    779   if (verify_result->has_md4)
    780     verify_result->cert_status |= CERT_STATUS_INVALID;
    781 
    782   // Flag certificates signed using weak signature algorithms.
    783   if (verify_result->has_md2)
    784     verify_result->cert_status |= CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
    785 
    786   // Flag certificates that have a Subject common name with a NULL character.
    787   if (CertSubjectCommonNameHasNull(cert_handle_))
    788     verify_result->cert_status |= CERT_STATUS_INVALID;
    789 
    790   std::wstring wstr_hostname = ASCIIToWide(hostname);
    791 
    792   SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para;
    793   memset(&extra_policy_para, 0, sizeof(extra_policy_para));
    794   extra_policy_para.cbSize = sizeof(extra_policy_para);
    795   extra_policy_para.dwAuthType = AUTHTYPE_SERVER;
    796   extra_policy_para.fdwChecks = 0;
    797   extra_policy_para.pwszServerName =
    798       const_cast<wchar_t*>(wstr_hostname.c_str());
    799 
    800   CERT_CHAIN_POLICY_PARA policy_para;
    801   memset(&policy_para, 0, sizeof(policy_para));
    802   policy_para.cbSize = sizeof(policy_para);
    803   policy_para.dwFlags = 0;
    804   policy_para.pvExtraPolicyPara = &extra_policy_para;
    805 
    806   CERT_CHAIN_POLICY_STATUS policy_status;
    807   memset(&policy_status, 0, sizeof(policy_status));
    808   policy_status.cbSize = sizeof(policy_status);
    809 
    810   if (!CertVerifyCertificateChainPolicy(
    811            CERT_CHAIN_POLICY_SSL,
    812            chain_context,
    813            &policy_para,
    814            &policy_status)) {
    815     return MapSecurityError(GetLastError());
    816   }
    817 
    818   if (policy_status.dwError) {
    819     verify_result->cert_status |= MapNetErrorToCertStatus(
    820         MapSecurityError(policy_status.dwError));
    821 
    822     // CertVerifyCertificateChainPolicy reports only one error (in
    823     // policy_status.dwError) if the certificate has multiple errors.
    824     // CertGetCertificateChain doesn't report certificate name mismatch, so
    825     // CertVerifyCertificateChainPolicy is the only function that can report
    826     // certificate name mismatch.
    827     //
    828     // To prevent a potential certificate name mismatch from being hidden by
    829     // some other certificate error, if we get any other certificate error,
    830     // we call CertVerifyCertificateChainPolicy again, ignoring all other
    831     // certificate errors.  Both extra_policy_para.fdwChecks and
    832     // policy_para.dwFlags allow us to ignore certificate errors, so we set
    833     // them both.
    834     if (policy_status.dwError != CERT_E_CN_NO_MATCH) {
    835       const DWORD extra_ignore_flags =
    836           0x00000080 |  // SECURITY_FLAG_IGNORE_REVOCATION
    837           0x00000100 |  // SECURITY_FLAG_IGNORE_UNKNOWN_CA
    838           0x00002000 |  // SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
    839           0x00000200;   // SECURITY_FLAG_IGNORE_WRONG_USAGE
    840       extra_policy_para.fdwChecks = extra_ignore_flags;
    841       const DWORD ignore_flags =
    842           CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS |
    843           CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG |
    844           CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG |
    845           CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG |
    846           CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG |
    847           CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG |
    848           CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS |
    849           CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG |
    850           CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG |
    851           CERT_CHAIN_POLICY_IGNORE_NOT_SUPPORTED_CRITICAL_EXT_FLAG |
    852           CERT_CHAIN_POLICY_IGNORE_PEER_TRUST_FLAG;
    853       policy_para.dwFlags = ignore_flags;
    854       if (!CertVerifyCertificateChainPolicy(
    855                CERT_CHAIN_POLICY_SSL,
    856                chain_context,
    857                &policy_para,
    858                &policy_status)) {
    859         return MapSecurityError(GetLastError());
    860       }
    861       if (policy_status.dwError) {
    862         verify_result->cert_status |= MapNetErrorToCertStatus(
    863             MapSecurityError(policy_status.dwError));
    864       }
    865     }
    866   }
    867 
    868   // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be
    869   // compatible with WinHTTP, which doesn't report this error (bug 3004).
    870   verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM;
    871 
    872   if (IsCertStatusError(verify_result->cert_status))
    873     return MapCertStatusToNetError(verify_result->cert_status);
    874 
    875   AppendPublicKeyHashes(chain_context, &verify_result->public_key_hashes);
    876   verify_result->is_issued_by_known_root = IsIssuedByKnownRoot(chain_context);
    877 
    878   if (ev_policy_oid && CheckEV(chain_context, ev_policy_oid))
    879     verify_result->cert_status |= CERT_STATUS_IS_EV;
    880 
    881   if (IsPublicKeyBlacklisted(verify_result->public_key_hashes)) {
    882     verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
    883     return MapCertStatusToNetError(verify_result->cert_status);
    884   }
    885 
    886   return OK;
    887 }
    888 
    889 bool X509Certificate::GetDEREncoded(std::string* encoded) {
    890   if (!cert_handle_->pbCertEncoded || !cert_handle_->cbCertEncoded)
    891     return false;
    892   encoded->clear();
    893   encoded->append(reinterpret_cast<char*>(cert_handle_->pbCertEncoded),
    894                   cert_handle_->cbCertEncoded);
    895   return true;
    896 }
    897 
    898 // Returns true if the certificate is an extended-validation certificate.
    899 //
    900 // This function checks the certificatePolicies extensions of the
    901 // certificates in the certificate chain according to Section 7 (pp. 11-12)
    902 // of the EV Certificate Guidelines Version 1.0 at
    903 // http://cabforum.org/EV_Certificate_Guidelines.pdf.
    904 bool X509Certificate::CheckEV(PCCERT_CHAIN_CONTEXT chain_context,
    905                               const char* policy_oid) const {
    906   DCHECK(chain_context->cChain != 0);
    907   // If the cert doesn't match any of the policies, the
    908   // CERT_TRUST_IS_NOT_VALID_FOR_USAGE bit (0x10) in
    909   // chain_context->TrustStatus.dwErrorStatus is set.
    910   DWORD error_status = chain_context->TrustStatus.dwErrorStatus;
    911   DWORD info_status = chain_context->TrustStatus.dwInfoStatus;
    912   if (!chain_context->cChain || error_status != CERT_TRUST_NO_ERROR)
    913     return false;
    914 
    915   // Check the end certificate simple chain (chain_context->rgpChain[0]).
    916   // If the end certificate's certificatePolicies extension contains the
    917   // EV policy OID of the root CA, return true.
    918   PCERT_CHAIN_ELEMENT* element = chain_context->rgpChain[0]->rgpElement;
    919   int num_elements = chain_context->rgpChain[0]->cElement;
    920   if (num_elements < 2)
    921     return false;
    922 
    923   // Look up the EV policy OID of the root CA.
    924   PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext;
    925   SHA1Fingerprint fingerprint = CalculateFingerprint(root_cert);
    926   EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
    927   return metadata->HasEVPolicyOID(fingerprint, policy_oid);
    928 }
    929 
    930 bool X509Certificate::VerifyEV() const {
    931   // We don't call this private method, but we do need to implement it because
    932   // it's defined in x509_certificate.h. We perform EV checking in the
    933   // Verify() above.
    934   NOTREACHED();
    935   return false;
    936 }
    937 
    938 // static
    939 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
    940                                    X509Certificate::OSCertHandle b) {
    941   DCHECK(a && b);
    942   if (a == b)
    943     return true;
    944   return a->cbCertEncoded == b->cbCertEncoded &&
    945       memcmp(a->pbCertEncoded, b->pbCertEncoded, a->cbCertEncoded) == 0;
    946 }
    947 
    948 // static
    949 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
    950     const char* data, int length) {
    951   OSCertHandle cert_handle = NULL;
    952   if (!CertAddEncodedCertificateToStore(
    953       NULL,  // the cert won't be persisted in any cert store
    954       X509_ASN_ENCODING,
    955       reinterpret_cast<const BYTE*>(data), length,
    956       CERT_STORE_ADD_USE_EXISTING,
    957       &cert_handle))
    958     return NULL;
    959 
    960   return cert_handle;
    961 }
    962 
    963 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
    964     const char* data, int length, Format format) {
    965   OSCertHandles results;
    966   switch (format) {
    967     case FORMAT_SINGLE_CERTIFICATE: {
    968       OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
    969       if (handle != NULL)
    970         results.push_back(handle);
    971       break;
    972     }
    973     case FORMAT_PKCS7:
    974       results = ParsePKCS7(data, length);
    975       break;
    976     default:
    977       NOTREACHED() << "Certificate format " << format << " unimplemented";
    978       break;
    979   }
    980 
    981   return results;
    982 }
    983 
    984 
    985 // static
    986 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
    987     OSCertHandle cert_handle) {
    988   return CertDuplicateCertificateContext(cert_handle);
    989 }
    990 
    991 // static
    992 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
    993   CertFreeCertificateContext(cert_handle);
    994 }
    995 
    996 // static
    997 SHA1Fingerprint X509Certificate::CalculateFingerprint(
    998     OSCertHandle cert) {
    999   DCHECK(NULL != cert->pbCertEncoded);
   1000   DCHECK(0 != cert->cbCertEncoded);
   1001 
   1002   BOOL rv;
   1003   SHA1Fingerprint sha1;
   1004   DWORD sha1_size = sizeof(sha1.data);
   1005   rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded,
   1006                             cert->cbCertEncoded, sha1.data, &sha1_size);
   1007   DCHECK(rv && sha1_size == sizeof(sha1.data));
   1008   if (!rv)
   1009     memset(sha1.data, 0, sizeof(sha1.data));
   1010   return sha1;
   1011 }
   1012 
   1013 // static
   1014 X509Certificate::OSCertHandle
   1015 X509Certificate::ReadCertHandleFromPickle(const Pickle& pickle,
   1016                                           void** pickle_iter) {
   1017   const char* data;
   1018   int length;
   1019   if (!pickle.ReadData(pickle_iter, &data, &length))
   1020     return NULL;
   1021 
   1022   OSCertHandle cert_handle = NULL;
   1023   if (!CertAddSerializedElementToStore(
   1024           NULL,  // the cert won't be persisted in any cert store
   1025           reinterpret_cast<const BYTE*>(data), length,
   1026           CERT_STORE_ADD_USE_EXISTING, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
   1027           NULL, reinterpret_cast<const void **>(&cert_handle))) {
   1028     return NULL;
   1029   }
   1030 
   1031   return cert_handle;
   1032 }
   1033 
   1034 // static
   1035 bool X509Certificate::WriteCertHandleToPickle(OSCertHandle cert_handle,
   1036                                               Pickle* pickle) {
   1037   DWORD length = 0;
   1038   if (!CertSerializeCertificateStoreElement(cert_handle, 0, NULL, &length))
   1039     return false;
   1040 
   1041   std::vector<BYTE> buffer(length);
   1042   // Serialize |cert_handle| in a way that will preserve any extended
   1043   // attributes set on the handle, such as the location to the certificate's
   1044   // private key.
   1045   if (!CertSerializeCertificateStoreElement(cert_handle, 0, &buffer[0],
   1046                                             &length)) {
   1047     return false;
   1048   }
   1049 
   1050   return pickle->WriteData(reinterpret_cast<const char*>(&buffer[0]),
   1051                            length);
   1052 }
   1053 
   1054 }  // namespace net
   1055