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 <openssl/asn1.h>
      8 #include <openssl/crypto.h>
      9 #include <openssl/obj_mac.h>
     10 #include <openssl/pem.h>
     11 #include <openssl/pkcs7.h>
     12 #include <openssl/sha.h>
     13 #include <openssl/ssl.h>
     14 #include <openssl/x509v3.h>
     15 
     16 #include "base/memory/singleton.h"
     17 #include "base/pickle.h"
     18 #include "base/sha1.h"
     19 #include "base/string_number_conversions.h"
     20 #include "crypto/openssl_util.h"
     21 #include "net/base/asn1_util.h"
     22 #include "net/base/cert_status_flags.h"
     23 #include "net/base/cert_verify_result.h"
     24 #include "net/base/net_errors.h"
     25 #include "net/base/x509_openssl_util.h"
     26 
     27 namespace net {
     28 
     29 namespace nxou = net::x509_openssl_util;
     30 
     31 namespace {
     32 
     33 void CreateOSCertHandlesFromPKCS7Bytes(
     34     const char* data, int length,
     35     X509Certificate::OSCertHandles* handles) {
     36   crypto::EnsureOpenSSLInit();
     37   const unsigned char* der_data = reinterpret_cast<const unsigned char*>(data);
     38   crypto::ScopedOpenSSL<PKCS7, PKCS7_free> pkcs7_cert(
     39       d2i_PKCS7(NULL, &der_data, length));
     40   if (!pkcs7_cert.get())
     41     return;
     42 
     43   STACK_OF(X509)* certs = NULL;
     44   int nid = OBJ_obj2nid(pkcs7_cert.get()->type);
     45   if (nid == NID_pkcs7_signed) {
     46     certs = pkcs7_cert.get()->d.sign->cert;
     47   } else if (nid == NID_pkcs7_signedAndEnveloped) {
     48     certs = pkcs7_cert.get()->d.signed_and_enveloped->cert;
     49   }
     50 
     51   if (certs) {
     52     for (int i = 0; i < sk_X509_num(certs); ++i) {
     53       X509* x509_cert =
     54           X509Certificate::DupOSCertHandle(sk_X509_value(certs, i));
     55       handles->push_back(x509_cert);
     56     }
     57   }
     58 }
     59 
     60 void ParsePrincipalValues(X509_NAME* name,
     61                           int nid,
     62                           std::vector<std::string>* fields) {
     63   for (int index = -1;
     64        (index = X509_NAME_get_index_by_NID(name, nid, index)) != -1;) {
     65     std::string field;
     66     if (!nxou::ParsePrincipalValueByIndex(name, index, &field))
     67       break;
     68     fields->push_back(field);
     69   }
     70 }
     71 
     72 void ParsePrincipal(X509Certificate::OSCertHandle cert,
     73                     X509_NAME* x509_name,
     74                     CertPrincipal* principal) {
     75   if (!x509_name)
     76     return;
     77 
     78   ParsePrincipalValues(x509_name, NID_streetAddress,
     79                        &principal->street_addresses);
     80   ParsePrincipalValues(x509_name, NID_organizationName,
     81                        &principal->organization_names);
     82   ParsePrincipalValues(x509_name, NID_organizationalUnitName,
     83                        &principal->organization_unit_names);
     84   ParsePrincipalValues(x509_name, NID_domainComponent,
     85                        &principal->domain_components);
     86 
     87   nxou::ParsePrincipalValueByNID(x509_name, NID_commonName,
     88                                  &principal->common_name);
     89   nxou::ParsePrincipalValueByNID(x509_name, NID_localityName,
     90                                  &principal->locality_name);
     91   nxou::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName,
     92                                  &principal->state_or_province_name);
     93   nxou::ParsePrincipalValueByNID(x509_name, NID_countryName,
     94                                  &principal->country_name);
     95 }
     96 
     97 void ParseSubjectAltNames(X509Certificate::OSCertHandle cert,
     98                           std::vector<std::string>* dns_names) {
     99   int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
    100   X509_EXTENSION* alt_name_ext = X509_get_ext(cert, index);
    101   if (!alt_name_ext)
    102     return;
    103 
    104   crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free> alt_names(
    105       reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext)));
    106   if (!alt_names.get())
    107     return;
    108 
    109   for (int i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) {
    110     const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i);
    111     if (name->type == GEN_DNS) {
    112       unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName);
    113       if (!dns_name)
    114         continue;
    115       int dns_name_len = ASN1_STRING_length(name->d.dNSName);
    116       dns_names->push_back(
    117           std::string(reinterpret_cast<char*>(dns_name), dns_name_len));
    118     }
    119   }
    120 }
    121 
    122 // Maps X509_STORE_CTX_get_error() return values to our cert status flags.
    123 int MapCertErrorToCertStatus(int err) {
    124   switch (err) {
    125     case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
    126       return CERT_STATUS_COMMON_NAME_INVALID;
    127     case X509_V_ERR_CERT_NOT_YET_VALID:
    128     case X509_V_ERR_CERT_HAS_EXPIRED:
    129     case X509_V_ERR_CRL_NOT_YET_VALID:
    130     case X509_V_ERR_CRL_HAS_EXPIRED:
    131     case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
    132     case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
    133     case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
    134     case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
    135       return CERT_STATUS_DATE_INVALID;
    136     case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
    137     case X509_V_ERR_UNABLE_TO_GET_CRL:
    138     case X509_V_ERR_INVALID_CA:
    139     case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
    140     case X509_V_ERR_INVALID_NON_CA:
    141     case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
    142     case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
    143     case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
    144       return CERT_STATUS_AUTHORITY_INVALID;
    145 #if 0
    146 // TODO(bulach): what should we map to these status?
    147       return CERT_STATUS_NO_REVOCATION_MECHANISM;
    148       return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
    149       return CERT_STATUS_NOT_IN_DNS;
    150 #endif
    151     case X509_V_ERR_CERT_REVOKED:
    152       return CERT_STATUS_REVOKED;
    153     case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
    154       return CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
    155     // All these status are mapped to CERT_STATUS_INVALID.
    156     case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
    157     case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
    158     case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
    159     case X509_V_ERR_CERT_SIGNATURE_FAILURE:
    160     case X509_V_ERR_CRL_SIGNATURE_FAILURE:
    161     case X509_V_ERR_OUT_OF_MEM:
    162     case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
    163     case X509_V_ERR_CERT_CHAIN_TOO_LONG:
    164     case X509_V_ERR_PATH_LENGTH_EXCEEDED:
    165     case X509_V_ERR_INVALID_PURPOSE:
    166     case X509_V_ERR_CERT_UNTRUSTED:
    167     case X509_V_ERR_CERT_REJECTED:
    168     case X509_V_ERR_AKID_SKID_MISMATCH:
    169     case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
    170     case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
    171     case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
    172     case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
    173     case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
    174     case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE:
    175     case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
    176     case X509_V_ERR_INVALID_EXTENSION:
    177     case X509_V_ERR_INVALID_POLICY_EXTENSION:
    178     case X509_V_ERR_NO_EXPLICIT_POLICY:
    179     case X509_V_ERR_UNNESTED_RESOURCE:
    180     case X509_V_ERR_APPLICATION_VERIFICATION:
    181       return CERT_STATUS_INVALID;
    182     default:
    183       NOTREACHED() << "Invalid X509 err " << err;
    184       return CERT_STATUS_INVALID;
    185   }
    186 }
    187 
    188 // sk_X509_free is a function-style macro, so can't be used as a template
    189 // param directly.
    190 void sk_X509_free_fn(STACK_OF(X509)* st) {
    191   sk_X509_free(st);
    192 }
    193 
    194 struct DERCache {
    195   unsigned char* data;
    196   int data_length;
    197 };
    198 
    199 void DERCache_free(void* parent, void* ptr, CRYPTO_EX_DATA* ad, int idx,
    200                    long argl, void* argp) {
    201   DERCache* der_cache = static_cast<DERCache*>(ptr);
    202   if (!der_cache)
    203       return;
    204   if (der_cache->data)
    205       OPENSSL_free(der_cache->data);
    206   OPENSSL_free(der_cache);
    207 }
    208 
    209 class X509InitSingleton {
    210  public:
    211   static X509InitSingleton* GetInstance() {
    212     // We allow the X509 store to leak, because it is used from a non-joinable
    213     // worker that is not stopped on shutdown, hence may still be using
    214     // OpenSSL library after the AtExit runner has completed.
    215     return Singleton<X509InitSingleton,
    216                      LeakySingletonTraits<X509InitSingleton> >::get();
    217   }
    218   int der_cache_ex_index() const { return der_cache_ex_index_; }
    219   X509_STORE* store() const { return store_.get(); }
    220 
    221   void ResetCertStore() {
    222     store_.reset(X509_STORE_new());
    223     DCHECK(store_.get());
    224     X509_STORE_set_default_paths(store_.get());
    225     // TODO(joth): Enable CRL (see X509_STORE_set_flags(X509_V_FLAG_CRL_CHECK)).
    226   }
    227 
    228  private:
    229   friend struct DefaultSingletonTraits<X509InitSingleton>;
    230   X509InitSingleton() {
    231     crypto::EnsureOpenSSLInit();
    232     der_cache_ex_index_ = X509_get_ex_new_index(0, 0, 0, 0, DERCache_free);
    233     DCHECK_NE(der_cache_ex_index_, -1);
    234     ResetCertStore();
    235   }
    236 
    237   int der_cache_ex_index_;
    238   crypto::ScopedOpenSSL<X509_STORE, X509_STORE_free> store_;
    239 
    240   DISALLOW_COPY_AND_ASSIGN(X509InitSingleton);
    241 };
    242 
    243 // Takes ownership of |data| (which must have been allocated by OpenSSL).
    244 DERCache* SetDERCache(X509Certificate::OSCertHandle cert,
    245                       int x509_der_cache_index,
    246                       unsigned char* data,
    247                       int data_length) {
    248   DERCache* internal_cache = static_cast<DERCache*>(
    249       OPENSSL_malloc(sizeof(*internal_cache)));
    250   if (!internal_cache) {
    251     // We took ownership of |data|, so we must free if we can't add it to
    252     // |cert|.
    253     OPENSSL_free(data);
    254     return NULL;
    255   }
    256 
    257   internal_cache->data = data;
    258   internal_cache->data_length = data_length;
    259   X509_set_ex_data(cert, x509_der_cache_index, internal_cache);
    260   return internal_cache;
    261 }
    262 
    263 // Returns true if |der_cache| points to valid data, false otherwise.
    264 // (note: the DER-encoded data in |der_cache| is owned by |cert|, callers should
    265 // not free it).
    266 bool GetDERAndCacheIfNeeded(X509Certificate::OSCertHandle cert,
    267                             DERCache* der_cache) {
    268   int x509_der_cache_index =
    269       X509InitSingleton::GetInstance()->der_cache_ex_index();
    270 
    271   // Re-encoding the DER data via i2d_X509 is an expensive operation, but it's
    272   // necessary for comparing two certificates. We re-encode at most once per
    273   // certificate and cache the data within the X509 cert using X509_set_ex_data.
    274   DERCache* internal_cache = static_cast<DERCache*>(
    275       X509_get_ex_data(cert, x509_der_cache_index));
    276   if (!internal_cache) {
    277     unsigned char* data = NULL;
    278     int data_length = i2d_X509(cert, &data);
    279     if (data_length <= 0 || !data)
    280       return false;
    281     internal_cache = SetDERCache(cert, x509_der_cache_index, data, data_length);
    282     if (!internal_cache)
    283       return false;
    284   }
    285   *der_cache = *internal_cache;
    286   return true;
    287 }
    288 
    289 }  // namespace
    290 
    291 // static
    292 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
    293     OSCertHandle cert_handle) {
    294   DCHECK(cert_handle);
    295   // Using X509_dup causes the entire certificate to be reparsed. This
    296   // conversion, besides being non-trivial, drops any associated
    297   // application-specific data set by X509_set_ex_data. Using CRYPTO_add
    298   // just bumps up the ref-count for the cert, without causing any allocations
    299   // or deallocations.
    300   CRYPTO_add(&cert_handle->references, 1, CRYPTO_LOCK_X509);
    301   return cert_handle;
    302 }
    303 
    304 // static
    305 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
    306   // Decrement the ref-count for the cert and, if all references are gone,
    307   // free the memory and any application-specific data associated with the
    308   // certificate.
    309   X509_free(cert_handle);
    310 }
    311 
    312 void X509Certificate::Initialize() {
    313   crypto::EnsureOpenSSLInit();
    314   fingerprint_ = CalculateFingerprint(cert_handle_);
    315 
    316   ASN1_INTEGER* num = X509_get_serialNumber(cert_handle_);
    317   if (num) {
    318     serial_number_ = std::string(
    319         reinterpret_cast<char*>(num->data),
    320         num->length);
    321     // Remove leading zeros.
    322     while (serial_number_.size() > 1 && serial_number_[0] == 0)
    323       serial_number_ = serial_number_.substr(1, serial_number_.size() - 1);
    324   }
    325 
    326   ParsePrincipal(cert_handle_, X509_get_subject_name(cert_handle_), &subject_);
    327   ParsePrincipal(cert_handle_, X509_get_issuer_name(cert_handle_), &issuer_);
    328   nxou::ParseDate(X509_get_notBefore(cert_handle_), &valid_start_);
    329   nxou::ParseDate(X509_get_notAfter(cert_handle_), &valid_expiry_);
    330 }
    331 
    332 // static
    333 void X509Certificate::ResetCertStore() {
    334   X509InitSingleton::GetInstance()->ResetCertStore();
    335 }
    336 
    337 SHA1Fingerprint X509Certificate::CalculateFingerprint(OSCertHandle cert) {
    338   SHA1Fingerprint sha1;
    339   unsigned int sha1_size = static_cast<unsigned int>(sizeof(sha1.data));
    340   int ret = X509_digest(cert, EVP_sha1(), sha1.data, &sha1_size);
    341   CHECK(ret);
    342   CHECK_EQ(sha1_size, sizeof(sha1.data));
    343   return sha1;
    344 }
    345 
    346 // static
    347 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
    348     const char* data, int length) {
    349   if (length < 0)
    350     return NULL;
    351   crypto::EnsureOpenSSLInit();
    352   const unsigned char* d2i_data =
    353       reinterpret_cast<const unsigned char*>(data);
    354   // Don't cache this data via SetDERCache as this wire format may be not be
    355   // identical from the i2d_X509 roundtrip.
    356   X509* cert = d2i_X509(NULL, &d2i_data, length);
    357   return cert;
    358 }
    359 
    360 // static
    361 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
    362     const char* data, int length, Format format) {
    363   OSCertHandles results;
    364   if (length < 0)
    365     return results;
    366 
    367   switch (format) {
    368     case FORMAT_SINGLE_CERTIFICATE: {
    369       OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
    370       if (handle)
    371         results.push_back(handle);
    372       break;
    373     }
    374     case FORMAT_PKCS7: {
    375       CreateOSCertHandlesFromPKCS7Bytes(data, length, &results);
    376       break;
    377     }
    378     default: {
    379       NOTREACHED() << "Certificate format " << format << " unimplemented";
    380       break;
    381     }
    382   }
    383 
    384   return results;
    385 }
    386 
    387 // static
    388 X509Certificate* X509Certificate::CreateSelfSigned(
    389     crypto::RSAPrivateKey* key,
    390     const std::string& subject,
    391     uint32 serial_number,
    392     base::TimeDelta valid_duration) {
    393   // TODO(port): Implement.
    394   return NULL;
    395 }
    396 
    397 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
    398   dns_names->clear();
    399 
    400   ParseSubjectAltNames(cert_handle_, dns_names);
    401 
    402   if (dns_names->empty())
    403     dns_names->push_back(subject_.common_name);
    404 }
    405 
    406 // static
    407 X509_STORE* X509Certificate::cert_store() {
    408   return X509InitSingleton::GetInstance()->store();
    409 }
    410 
    411 #ifndef ANDROID
    412 int X509Certificate::Verify(const std::string& hostname,
    413                             int flags,
    414                             CertVerifyResult* verify_result) const {
    415   verify_result->Reset();
    416 
    417   if (IsBlacklisted()) {
    418     verify_result->cert_status |= CERT_STATUS_REVOKED;
    419     return ERR_CERT_REVOKED;
    420   }
    421 
    422   // TODO(joth): We should fetch the subjectAltNames directly rather than via
    423   // GetDNSNames, so we can apply special handling for IP addresses vs DNS
    424   // names, etc. See http://crbug.com/62973.
    425   std::vector<std::string> cert_names;
    426   GetDNSNames(&cert_names);
    427   if (!VerifyHostname(hostname, cert_names))
    428     verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
    429 
    430   crypto::ScopedOpenSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx(
    431       X509_STORE_CTX_new());
    432 
    433   crypto::ScopedOpenSSL<STACK_OF(X509), sk_X509_free_fn> intermediates(
    434       sk_X509_new_null());
    435   if (!intermediates.get())
    436     return ERR_OUT_OF_MEMORY;
    437 
    438   for (OSCertHandles::const_iterator it = intermediate_ca_certs_.begin();
    439        it != intermediate_ca_certs_.end(); ++it) {
    440     if (!sk_X509_push(intermediates.get(), *it))
    441       return ERR_OUT_OF_MEMORY;
    442   }
    443   int rv = X509_STORE_CTX_init(ctx.get(), cert_store(),
    444                                cert_handle_, intermediates.get());
    445   CHECK_EQ(1, rv);
    446 
    447   if (X509_verify_cert(ctx.get()) != 1) {
    448     int x509_error = X509_STORE_CTX_get_error(ctx.get());
    449     int cert_status = MapCertErrorToCertStatus(x509_error);
    450     LOG(ERROR) << "X509 Verification error "
    451         << X509_verify_cert_error_string(x509_error)
    452         << " : " << x509_error
    453         << " : " << X509_STORE_CTX_get_error_depth(ctx.get())
    454         << " : " << cert_status;
    455     verify_result->cert_status |= cert_status;
    456   }
    457 
    458   if (IsCertStatusError(verify_result->cert_status))
    459     return MapCertStatusToNetError(verify_result->cert_status);
    460 
    461   STACK_OF(X509)* chain = X509_STORE_CTX_get_chain(ctx.get());
    462   for (int i = 0; i < sk_X509_num(chain); ++i) {
    463     X509* cert = sk_X509_value(chain, i);
    464     DERCache der_cache;
    465     if (!GetDERAndCacheIfNeeded(cert, &der_cache))
    466       continue;
    467 
    468     base::StringPiece der_bytes(reinterpret_cast<const char*>(der_cache.data),
    469                                 der_cache.data_length);
    470     base::StringPiece spki_bytes;
    471     if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes))
    472       continue;
    473 
    474     SHA1Fingerprint hash;
    475     base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()),
    476                         spki_bytes.size(), hash.data);
    477     verify_result->public_key_hashes.push_back(hash);
    478   }
    479 
    480   if (IsPublicKeyBlacklisted(verify_result->public_key_hashes)) {
    481     verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
    482     return MapCertStatusToNetError(verify_result->cert_status);
    483   }
    484 
    485   // Currently we only ues OpenSSL's default root CA paths, so treat all
    486   // correctly verified certs as being from a known root. TODO(joth): if the
    487   // motivations described in http://src.chromium.org/viewvc/chrome?view=rev&revision=80778
    488   // become an issue on OpenSSL builds, we will need to embed a hardcoded list
    489   // of well known root CAs, as per the _mac and _win versions.
    490   verify_result->is_issued_by_known_root = true;
    491 
    492   return OK;
    493 }
    494 
    495 bool X509Certificate::GetDEREncoded(std::string* encoded) {
    496   DERCache der_cache;
    497   if (!GetDERAndCacheIfNeeded(cert_handle_, &der_cache))
    498       return false;
    499   encoded->assign(reinterpret_cast<const char*>(der_cache.data),
    500                   der_cache.data_length);
    501   return true;
    502 }
    503 #endif
    504 
    505 // static
    506 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
    507                                    X509Certificate::OSCertHandle b) {
    508   DCHECK(a && b);
    509   if (a == b)
    510     return true;
    511 
    512   // X509_cmp only checks the fingerprint, but we want to compare the whole
    513   // DER data. Encoding it from OSCertHandle is an expensive operation, so we
    514   // cache the DER (if not already cached via X509_set_ex_data).
    515   DERCache der_cache_a, der_cache_b;
    516 
    517   return GetDERAndCacheIfNeeded(a, &der_cache_a) &&
    518       GetDERAndCacheIfNeeded(b, &der_cache_b) &&
    519       der_cache_a.data_length == der_cache_b.data_length &&
    520       memcmp(der_cache_a.data, der_cache_b.data, der_cache_a.data_length) == 0;
    521 }
    522 
    523 // static
    524 X509Certificate::OSCertHandle
    525 X509Certificate::ReadCertHandleFromPickle(const Pickle& pickle,
    526                                           void** pickle_iter) {
    527   const char* data;
    528   int length;
    529   if (!pickle.ReadData(pickle_iter, &data, &length))
    530     return NULL;
    531 
    532   return CreateOSCertHandleFromBytes(data, length);
    533 }
    534 
    535 // static
    536 bool X509Certificate::WriteCertHandleToPickle(OSCertHandle cert_handle,
    537                                               Pickle* pickle) {
    538   DERCache der_cache;
    539   if (!GetDERAndCacheIfNeeded(cert_handle, &der_cache))
    540     return false;
    541 
    542   return pickle->WriteData(
    543       reinterpret_cast<const char*>(der_cache.data),
    544       der_cache.data_length);
    545 }
    546 
    547 #if defined(ANDROID)
    548 // static
    549 std::string X509Certificate::GetDEREncodedBytes(OSCertHandle handle) {
    550   DERCache der_cache = {0};
    551   GetDERAndCacheIfNeeded(handle, &der_cache);
    552   return std::string(reinterpret_cast<const char*>(der_cache.data),
    553                      der_cache.data_length);
    554 }
    555 #endif
    556 
    557 #if defined(ANDROID)
    558 void X509Certificate::GetChainDEREncodedBytes(
    559     std::vector<std::string>* chain_bytes) const {
    560   OSCertHandles cert_handles(intermediate_ca_certs_);
    561   // Make sure the peer's own cert is the first in the chain, if it's not
    562   // already there.
    563   if (cert_handles.empty() || cert_handles[0] != cert_handle_)
    564     cert_handles.insert(cert_handles.begin(), cert_handle_);
    565 
    566   chain_bytes->reserve(cert_handles.size());
    567   for (OSCertHandles::const_iterator it = cert_handles.begin();
    568        it != cert_handles.end(); ++it) {
    569     DERCache der_cache = {0};
    570     GetDERAndCacheIfNeeded(*it, &der_cache);
    571     std::string cert_bytes = std::string(
    572         reinterpret_cast<const char*>(der_cache.data), der_cache.data_length);
    573     chain_bytes->push_back(cert_bytes);
    574   }
    575 }
    576 #endif
    577 
    578 } // namespace net
    579