| 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 | 
|---|