Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Side by Side Diff: net/base/x509_certificate_openssl.cc

Issue 4963002: Refactor EnsureOpenSSLInit and openssl_util into base (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review comments Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/x509_certificate.h ('k') | net/net.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/base/x509_certificate.h ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698