• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
operator ()net::__anone1c389e00111::FreeChainEngineFunctor39   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.
MapSecurityError(SECURITY_STATUS err)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.
MapCertChainErrorStatusToCertStatus(DWORD error_status)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 
ExplodedTimeToSystemTime(const base::Time::Exploded & exploded,SYSTEMTIME * system_time)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.
MyCryptAlloc(size_t size)167 void* WINAPI MyCryptAlloc(size_t size) {
168   return malloc(size);
169 }
170 
MyCryptFree(void * p)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.
GetCertSubjectAltName(PCCERT_CONTEXT cert,scoped_ptr_malloc<CERT_ALT_NAME_INFO> * 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.
CertSubjectCommonNameHasNull(PCCERT_CONTEXT cert)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.
GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context,CertVerifyResult * verify_result)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.
GetCertPoliciesInfo(PCCERT_CONTEXT cert,scoped_ptr_malloc<CERT_POLICIES_INFO> * 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.
ParsePrincipal(const std::string & description,CertPrincipal * 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 
AddCertsFromStore(HCERTSTORE store,X509Certificate::OSCertHandles * results)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 
ParsePKCS7(const char * data,size_t length)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 
AppendPublicKeyHashes(PCCERT_CHAIN_CONTEXT chain,std::vector<SHA1Fingerprint> * hashes)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 
Initialize()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
IsIssuedByKnownRoot(PCCERT_CHAIN_CONTEXT chain_context)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
CreateSelfSigned(crypto::RSAPrivateKey * key,const std::string & subject,uint32 serial_number,base::TimeDelta valid_duration)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 
GetDNSNames(std::vector<std::string> * dns_names) const615 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:
cert_store()638   HCERTSTORE cert_store() {
639     return cert_store_;
640   }
641 
642  private:
643   friend struct base::DefaultLazyInstanceTraits<GlobalCertStore>;
644 
GlobalCertStore()645   GlobalCertStore()
646       : cert_store_(CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL)) {
647   }
648 
~GlobalCertStore()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
cert_store()662 HCERTSTORE X509Certificate::cert_store() {
663   return g_cert_store.Get().cert_store();
664 }
665 
Verify(const std::string & hostname,int flags,CertVerifyResult * verify_result) const666 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 
GetDEREncoded(std::string * encoded)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.
CheckEV(PCCERT_CHAIN_CONTEXT chain_context,const char * policy_oid) const904 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 
VerifyEV() const930 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
IsSameOSCert(X509Certificate::OSCertHandle a,X509Certificate::OSCertHandle b)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
CreateOSCertHandleFromBytes(const char * data,int length)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 
CreateOSCertHandlesFromBytes(const char * data,int length,Format format)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
DupOSCertHandle(OSCertHandle cert_handle)986 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
987     OSCertHandle cert_handle) {
988   return CertDuplicateCertificateContext(cert_handle);
989 }
990 
991 // static
FreeOSCertHandle(OSCertHandle cert_handle)992 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
993   CertFreeCertificateContext(cert_handle);
994 }
995 
996 // static
CalculateFingerprint(OSCertHandle cert)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
ReadCertHandleFromPickle(const Pickle & pickle,void ** pickle_iter)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
WriteCertHandleToPickle(OSCertHandle cert_handle,Pickle * pickle)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