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
CreateOSCertHandlesFromPKCS7Bytes(const char * data,int length,X509Certificate::OSCertHandles * handles)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
ParsePrincipalValues(X509_NAME * name,int nid,std::vector<std::string> * fields)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
ParsePrincipal(X509Certificate::OSCertHandle cert,X509_NAME * x509_name,CertPrincipal * principal)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
ParseSubjectAltNames(X509Certificate::OSCertHandle cert,std::vector<std::string> * dns_names)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.
MapCertErrorToCertStatus(int err)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.
sk_X509_free_fn(STACK_OF (X509)* st)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
DERCache_free(void * parent,void * ptr,CRYPTO_EX_DATA * ad,int idx,long argl,void * argp)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:
GetInstance()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 }
der_cache_ex_index() const218 int der_cache_ex_index() const { return der_cache_ex_index_; }
store() const219 X509_STORE* store() const { return store_.get(); }
220
ResetCertStore()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>;
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).
SetDERCache(X509Certificate::OSCertHandle cert,int x509_der_cache_index,unsigned char * data,int data_length)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).
GetDERAndCacheIfNeeded(X509Certificate::OSCertHandle cert,DERCache * der_cache)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
DupOSCertHandle(OSCertHandle cert_handle)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
FreeOSCertHandle(OSCertHandle cert_handle)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
Initialize()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
ResetCertStore()333 void X509Certificate::ResetCertStore() {
334 X509InitSingleton::GetInstance()->ResetCertStore();
335 }
336
CalculateFingerprint(OSCertHandle cert)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
CreateOSCertHandleFromBytes(const char * data,int length)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
CreateOSCertHandlesFromBytes(const char * data,int length,Format format)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
CreateSelfSigned(crypto::RSAPrivateKey * key,const std::string & subject,uint32 serial_number,base::TimeDelta valid_duration)388 scoped_refptr<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
GetDNSNames(std::vector<std::string> * dns_names) const397 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
cert_store()407 X509_STORE* X509Certificate::cert_store() {
408 return X509InitSingleton::GetInstance()->store();
409 }
410
411 #ifndef ANDROID
Verify(const std::string & hostname,int flags,CertVerifyResult * verify_result) const412 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
GetDEREncoded(std::string * encoded)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
IsSameOSCert(X509Certificate::OSCertHandle a,X509Certificate::OSCertHandle b)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
ReadCertHandleFromPickle(const Pickle & pickle,void ** pickle_iter)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
WriteCertHandleToPickle(OSCertHandle cert_handle,Pickle * pickle)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
GetDEREncodedBytes(OSCertHandle handle)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)
GetChainDEREncodedBytes(std::vector<std::string> * chain_bytes) const558 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