OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/x509_certificate.h" | 5 #include "net/base/x509_certificate.h" |
6 | 6 |
7 #include <openssl/asn1.h> | 7 #include <openssl/asn1.h> |
8 #include <openssl/crypto.h> | 8 #include <openssl/crypto.h> |
9 #include <openssl/obj_mac.h> | 9 #include <openssl/obj_mac.h> |
10 #include <openssl/pem.h> | 10 #include <openssl/pem.h> |
11 #include <openssl/pkcs7.h> | 11 #include <openssl/pkcs7.h> |
12 #include <openssl/sha.h> | 12 #include <openssl/sha.h> |
13 #include <openssl/ssl.h> | 13 #include <openssl/ssl.h> |
14 #include <openssl/x509v3.h> | 14 #include <openssl/x509v3.h> |
15 | 15 |
| 16 #include "base/openssl_util.h" |
16 #include "base/pickle.h" | 17 #include "base/pickle.h" |
17 #include "base/singleton.h" | 18 #include "base/singleton.h" |
18 #include "base/string_number_conversions.h" | 19 #include "base/string_number_conversions.h" |
19 #include "net/base/cert_status_flags.h" | 20 #include "net/base/cert_status_flags.h" |
20 #include "net/base/cert_verify_result.h" | 21 #include "net/base/cert_verify_result.h" |
21 #include "net/base/net_errors.h" | 22 #include "net/base/net_errors.h" |
22 #include "net/base/openssl_util.h" | |
23 #include "net/base/x509_openssl_util.h" | 23 #include "net/base/x509_openssl_util.h" |
24 | 24 |
25 namespace net { | 25 namespace net { |
26 | 26 |
27 namespace nxou = net::x509_openssl_util; | 27 namespace nxou = net::x509_openssl_util; |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 void CreateOSCertHandlesFromPKCS7Bytes( | 31 void CreateOSCertHandlesFromPKCS7Bytes( |
32 const char* data, int length, | 32 const char* data, int length, |
33 X509Certificate::OSCertHandles* handles) { | 33 X509Certificate::OSCertHandles* handles) { |
| 34 base::EnsureOpenSSLInit(); |
34 const unsigned char* der_data = reinterpret_cast<const unsigned char*>(data); | 35 const unsigned char* der_data = reinterpret_cast<const unsigned char*>(data); |
35 ScopedSSL<PKCS7, PKCS7_free> pkcs7_cert( | 36 base::ScopedOpenSSL<PKCS7, PKCS7_free> pkcs7_cert( |
36 d2i_PKCS7(NULL, &der_data, length)); | 37 d2i_PKCS7(NULL, &der_data, length)); |
37 if (!pkcs7_cert.get()) | 38 if (!pkcs7_cert.get()) |
38 return; | 39 return; |
39 | 40 |
40 STACK_OF(X509)* certs = NULL; | 41 STACK_OF(X509)* certs = NULL; |
41 int nid = OBJ_obj2nid(pkcs7_cert.get()->type); | 42 int nid = OBJ_obj2nid(pkcs7_cert.get()->type); |
42 if (nid == NID_pkcs7_signed) { | 43 if (nid == NID_pkcs7_signed) { |
43 certs = pkcs7_cert.get()->d.sign->cert; | 44 certs = pkcs7_cert.get()->d.sign->cert; |
44 } else if (nid == NID_pkcs7_signedAndEnveloped) { | 45 } else if (nid == NID_pkcs7_signedAndEnveloped) { |
45 certs = pkcs7_cert.get()->d.signed_and_enveloped->cert; | 46 certs = pkcs7_cert.get()->d.signed_and_enveloped->cert; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 &principal->country_name); | 92 &principal->country_name); |
92 } | 93 } |
93 | 94 |
94 void ParseSubjectAltNames(X509Certificate::OSCertHandle cert, | 95 void ParseSubjectAltNames(X509Certificate::OSCertHandle cert, |
95 std::vector<std::string>* dns_names) { | 96 std::vector<std::string>* dns_names) { |
96 int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); | 97 int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); |
97 X509_EXTENSION* alt_name_ext = X509_get_ext(cert, index); | 98 X509_EXTENSION* alt_name_ext = X509_get_ext(cert, index); |
98 if (!alt_name_ext) | 99 if (!alt_name_ext) |
99 return; | 100 return; |
100 | 101 |
101 ScopedSSL<GENERAL_NAMES, GENERAL_NAMES_free> alt_names( | 102 base::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free> alt_names( |
102 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); | 103 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); |
103 if (!alt_names.get()) | 104 if (!alt_names.get()) |
104 return; | 105 return; |
105 | 106 |
106 for (int i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { | 107 for (int i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { |
107 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); | 108 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); |
108 if (name->type == GEN_DNS) { | 109 if (name->type == GEN_DNS) { |
109 unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); | 110 unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); |
110 if (!dns_name) | 111 if (!dns_name) |
111 continue; | 112 continue; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 if (!der_cache) | 200 if (!der_cache) |
200 return; | 201 return; |
201 if (der_cache->data) | 202 if (der_cache->data) |
202 OPENSSL_free(der_cache->data); | 203 OPENSSL_free(der_cache->data); |
203 OPENSSL_free(der_cache); | 204 OPENSSL_free(der_cache); |
204 } | 205 } |
205 | 206 |
206 class X509InitSingleton { | 207 class X509InitSingleton { |
207 public: | 208 public: |
208 int der_cache_ex_index() const { return der_cache_ex_index_; } | 209 int der_cache_ex_index() const { return der_cache_ex_index_; } |
| 210 X509_STORE* store() const { return store_.get(); } |
209 | 211 |
210 private: | 212 private: |
211 friend struct DefaultSingletonTraits<X509InitSingleton>; | 213 friend struct DefaultSingletonTraits<X509InitSingleton>; |
212 X509InitSingleton() { | 214 X509InitSingleton() |
213 der_cache_ex_index_ = X509_get_ex_new_index(0, 0, 0, 0, DERCache_free); | 215 : der_cache_ex_index_((base::EnsureOpenSSLInit(), |
| 216 X509_get_ex_new_index(0, 0, 0, 0, |
| 217 DERCache_free))), |
| 218 store_(X509_STORE_new()) { |
214 DCHECK_NE(der_cache_ex_index_, -1); | 219 DCHECK_NE(der_cache_ex_index_, -1); |
| 220 X509_STORE_set_default_paths(store_.get()); |
| 221 // TODO(joth): Enable CRL (see X509_STORE_set_flags(X509_V_FLAG_CRL_CHECK)). |
215 } | 222 } |
216 ~X509InitSingleton() {} | |
217 | 223 |
218 int der_cache_ex_index_; | 224 int der_cache_ex_index_; |
| 225 base::ScopedOpenSSL<X509_STORE, X509_STORE_free> store_; |
219 | 226 |
220 DISALLOW_COPY_AND_ASSIGN(X509InitSingleton); | 227 DISALLOW_COPY_AND_ASSIGN(X509InitSingleton); |
221 }; | 228 }; |
222 | 229 |
223 // Takes ownership of |data| (which must have been allocated by OpenSSL). | 230 // Takes ownership of |data| (which must have been allocated by OpenSSL). |
224 DERCache* SetDERCache(X509Certificate::OSCertHandle cert, | 231 DERCache* SetDERCache(X509Certificate::OSCertHandle cert, |
225 int x509_der_cache_index, | 232 int x509_der_cache_index, |
226 unsigned char* data, | 233 unsigned char* data, |
227 int data_length) { | 234 int data_length) { |
228 DERCache* internal_cache = static_cast<DERCache*>( | 235 DERCache* internal_cache = static_cast<DERCache*>( |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 | 290 |
284 // static | 291 // static |
285 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 292 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
286 // Decrement the ref-count for the cert and, if all references are gone, | 293 // Decrement the ref-count for the cert and, if all references are gone, |
287 // free the memory and any application-specific data associated with the | 294 // free the memory and any application-specific data associated with the |
288 // certificate. | 295 // certificate. |
289 X509_free(cert_handle); | 296 X509_free(cert_handle); |
290 } | 297 } |
291 | 298 |
292 void X509Certificate::Initialize() { | 299 void X509Certificate::Initialize() { |
| 300 base::EnsureOpenSSLInit(); |
293 fingerprint_ = CalculateFingerprint(cert_handle_); | 301 fingerprint_ = CalculateFingerprint(cert_handle_); |
294 ParsePrincipal(cert_handle_, X509_get_subject_name(cert_handle_), &subject_); | 302 ParsePrincipal(cert_handle_, X509_get_subject_name(cert_handle_), &subject_); |
295 ParsePrincipal(cert_handle_, X509_get_issuer_name(cert_handle_), &issuer_); | 303 ParsePrincipal(cert_handle_, X509_get_issuer_name(cert_handle_), &issuer_); |
296 nxou::ParseDate(X509_get_notBefore(cert_handle_), &valid_start_); | 304 nxou::ParseDate(X509_get_notBefore(cert_handle_), &valid_start_); |
297 nxou::ParseDate(X509_get_notAfter(cert_handle_), &valid_expiry_); | 305 nxou::ParseDate(X509_get_notAfter(cert_handle_), &valid_expiry_); |
298 } | 306 } |
299 | 307 |
300 SHA1Fingerprint X509Certificate::CalculateFingerprint(OSCertHandle cert) { | 308 SHA1Fingerprint X509Certificate::CalculateFingerprint(OSCertHandle cert) { |
301 SHA1Fingerprint sha1; | 309 SHA1Fingerprint sha1; |
302 unsigned int sha1_size = static_cast<unsigned int>(sizeof(sha1.data)); | 310 unsigned int sha1_size = static_cast<unsigned int>(sizeof(sha1.data)); |
303 int ret = X509_digest(cert, EVP_sha1(), sha1.data, &sha1_size); | 311 int ret = X509_digest(cert, EVP_sha1(), sha1.data, &sha1_size); |
304 CHECK(ret); | 312 CHECK(ret); |
305 CHECK_EQ(sha1_size, sizeof(sha1.data)); | 313 CHECK_EQ(sha1_size, sizeof(sha1.data)); |
306 return sha1; | 314 return sha1; |
307 } | 315 } |
308 | 316 |
309 // static | 317 // static |
310 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | 318 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
311 const char* data, int length) { | 319 const char* data, int length) { |
312 if (length < 0) | 320 if (length < 0) |
313 return NULL; | 321 return NULL; |
| 322 base::EnsureOpenSSLInit(); |
314 const unsigned char* d2i_data = | 323 const unsigned char* d2i_data = |
315 reinterpret_cast<const unsigned char*>(data); | 324 reinterpret_cast<const unsigned char*>(data); |
316 // Don't cache this data via SetDERCache as this wire format may be not be | 325 // Don't cache this data via SetDERCache as this wire format may be not be |
317 // identical from the i2d_X509 roundtrip. | 326 // identical from the i2d_X509 roundtrip. |
318 X509* cert = d2i_X509(NULL, &d2i_data, length); | 327 X509* cert = d2i_X509(NULL, &d2i_data, length); |
319 return cert; | 328 return cert; |
320 } | 329 } |
321 | 330 |
322 // static | 331 // static |
323 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( | 332 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( |
(...skipping 15 matching lines...) Expand all Loading... |
339 } | 348 } |
340 default: { | 349 default: { |
341 NOTREACHED() << "Certificate format " << format << " unimplemented"; | 350 NOTREACHED() << "Certificate format " << format << " unimplemented"; |
342 break; | 351 break; |
343 } | 352 } |
344 } | 353 } |
345 | 354 |
346 return results; | 355 return results; |
347 } | 356 } |
348 | 357 |
| 358 // static |
349 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, | 359 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, |
350 void** pickle_iter) { | 360 void** pickle_iter) { |
351 const char* data; | 361 const char* data; |
352 int length; | 362 int length; |
353 if (!pickle.ReadData(pickle_iter, &data, &length)) | 363 if (!pickle.ReadData(pickle_iter, &data, &length)) |
354 return NULL; | 364 return NULL; |
355 | 365 |
356 return CreateFromBytes(data, length); | 366 return CreateFromBytes(data, length); |
357 } | 367 } |
358 | 368 |
359 void X509Certificate::Persist(Pickle* pickle) { | 369 void X509Certificate::Persist(Pickle* pickle) { |
360 DERCache der_cache; | 370 DERCache der_cache; |
361 if (!GetDERAndCacheIfNeeded(cert_handle_, &der_cache)) | 371 if (!GetDERAndCacheIfNeeded(cert_handle_, &der_cache)) |
362 return; | 372 return; |
363 | 373 |
364 pickle->WriteData(reinterpret_cast<const char*>(der_cache.data), | 374 pickle->WriteData(reinterpret_cast<const char*>(der_cache.data), |
365 der_cache.data_length); | 375 der_cache.data_length); |
366 } | 376 } |
367 | 377 |
368 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { | 378 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { |
369 dns_names->clear(); | 379 dns_names->clear(); |
370 | 380 |
371 ParseSubjectAltNames(cert_handle_, dns_names); | 381 ParseSubjectAltNames(cert_handle_, dns_names); |
372 | 382 |
373 if (dns_names->empty()) | 383 if (dns_names->empty()) |
374 dns_names->push_back(subject_.common_name); | 384 dns_names->push_back(subject_.common_name); |
375 } | 385 } |
376 | 386 |
| 387 // static |
| 388 X509_STORE* X509Certificate::cert_store() { |
| 389 return Singleton<X509InitSingleton>::get()->store(); |
| 390 } |
| 391 |
377 int X509Certificate::Verify(const std::string& hostname, | 392 int X509Certificate::Verify(const std::string& hostname, |
378 int flags, | 393 int flags, |
379 CertVerifyResult* verify_result) const { | 394 CertVerifyResult* verify_result) const { |
380 verify_result->Reset(); | 395 verify_result->Reset(); |
381 | 396 |
382 // TODO(joth): We should fetch the subjectAltNames directly rather than via | 397 // TODO(joth): We should fetch the subjectAltNames directly rather than via |
383 // GetDNSNames, so we can apply special handling for IP addresses vs DNS | 398 // GetDNSNames, so we can apply special handling for IP addresses vs DNS |
384 // names, etc. See http://crbug.com/62973. | 399 // names, etc. See http://crbug.com/62973. |
385 std::vector<std::string> cert_names; | 400 std::vector<std::string> cert_names; |
386 GetDNSNames(&cert_names); | 401 GetDNSNames(&cert_names); |
387 if (!x509_openssl_util::VerifyHostname(hostname, cert_names)) | 402 if (!x509_openssl_util::VerifyHostname(hostname, cert_names)) |
388 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | 403 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; |
389 | 404 |
390 ScopedSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx(X509_STORE_CTX_new()); | 405 base::ScopedOpenSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx( |
| 406 X509_STORE_CTX_new()); |
391 | 407 |
392 ScopedSSL<STACK_OF(X509), sk_X509_free_fn> intermediates(sk_X509_new_null()); | 408 base::ScopedOpenSSL<STACK_OF(X509), sk_X509_free_fn> intermediates( |
| 409 sk_X509_new_null()); |
393 if (!intermediates.get()) | 410 if (!intermediates.get()) |
394 return ERR_OUT_OF_MEMORY; | 411 return ERR_OUT_OF_MEMORY; |
395 | 412 |
396 for (OSCertHandles::const_iterator it = intermediate_ca_certs_.begin(); | 413 for (OSCertHandles::const_iterator it = intermediate_ca_certs_.begin(); |
397 it != intermediate_ca_certs_.end(); ++it) { | 414 it != intermediate_ca_certs_.end(); ++it) { |
398 if (!sk_X509_push(intermediates.get(), *it)) | 415 if (!sk_X509_push(intermediates.get(), *it)) |
399 return ERR_OUT_OF_MEMORY; | 416 return ERR_OUT_OF_MEMORY; |
400 } | 417 } |
401 int rv = X509_STORE_CTX_init(ctx.get(), | 418 int rv = X509_STORE_CTX_init(ctx.get(), cert_store(), |
402 GetOpenSSLInitSingleton()->x509_store(), | |
403 cert_handle_, intermediates.get()); | 419 cert_handle_, intermediates.get()); |
404 CHECK_EQ(1, rv); | 420 CHECK_EQ(1, rv); |
405 | 421 |
406 if (X509_verify_cert(ctx.get()) == 1) { | 422 if (X509_verify_cert(ctx.get()) == 1) { |
407 return OK; | 423 return OK; |
408 } | 424 } |
409 | 425 |
410 int x509_error = X509_STORE_CTX_get_error(ctx.get()); | 426 int x509_error = X509_STORE_CTX_get_error(ctx.get()); |
411 int cert_status = MapCertErrorToCertStatus(x509_error); | 427 int cert_status = MapCertErrorToCertStatus(x509_error); |
412 LOG(ERROR) << "X509 Verification error " | 428 LOG(ERROR) << "X509 Verification error " |
(...skipping 17 matching lines...) Expand all Loading... |
430 // cache the DER (if not already cached via X509_set_ex_data). | 446 // cache the DER (if not already cached via X509_set_ex_data). |
431 DERCache der_cache_a, der_cache_b; | 447 DERCache der_cache_a, der_cache_b; |
432 | 448 |
433 return GetDERAndCacheIfNeeded(a, &der_cache_a) && | 449 return GetDERAndCacheIfNeeded(a, &der_cache_a) && |
434 GetDERAndCacheIfNeeded(b, &der_cache_b) && | 450 GetDERAndCacheIfNeeded(b, &der_cache_b) && |
435 der_cache_a.data_length == der_cache_b.data_length && | 451 der_cache_a.data_length == der_cache_b.data_length && |
436 memcmp(der_cache_a.data, der_cache_b.data, der_cache_a.data_length) == 0; | 452 memcmp(der_cache_a.data, der_cache_b.data, der_cache_a.data_length) == 0; |
437 } | 453 } |
438 | 454 |
439 } // namespace net | 455 } // namespace net |
OLD | NEW |