OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 const unsigned char* der_data = reinterpret_cast<const unsigned char*>(data); | 34 const unsigned char* der_data = reinterpret_cast<const unsigned char*>(data); |
35 ScopedSSL<PKCS7, PKCS7_free> pkcs7_cert( | 35 base::ScopedSSL<PKCS7, PKCS7_free> pkcs7_cert( |
36 d2i_PKCS7(NULL, &der_data, length)); | 36 d2i_PKCS7(NULL, &der_data, length)); |
37 if (!pkcs7_cert.get()) | 37 if (!pkcs7_cert.get()) |
38 return; | 38 return; |
39 | 39 |
40 STACK_OF(X509)* certs = NULL; | 40 STACK_OF(X509)* certs = NULL; |
41 int nid = OBJ_obj2nid(pkcs7_cert.get()->type); | 41 int nid = OBJ_obj2nid(pkcs7_cert.get()->type); |
42 if (nid == NID_pkcs7_signed) { | 42 if (nid == NID_pkcs7_signed) { |
43 certs = pkcs7_cert.get()->d.sign->cert; | 43 certs = pkcs7_cert.get()->d.sign->cert; |
44 } else if (nid == NID_pkcs7_signedAndEnveloped) { | 44 } else if (nid == NID_pkcs7_signedAndEnveloped) { |
45 certs = pkcs7_cert.get()->d.signed_and_enveloped->cert; | 45 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); | 91 &principal->country_name); |
92 } | 92 } |
93 | 93 |
94 void ParseSubjectAltNames(X509Certificate::OSCertHandle cert, | 94 void ParseSubjectAltNames(X509Certificate::OSCertHandle cert, |
95 std::vector<std::string>* dns_names) { | 95 std::vector<std::string>* dns_names) { |
96 int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); | 96 int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); |
97 X509_EXTENSION* alt_name_ext = X509_get_ext(cert, index); | 97 X509_EXTENSION* alt_name_ext = X509_get_ext(cert, index); |
98 if (!alt_name_ext) | 98 if (!alt_name_ext) |
99 return; | 99 return; |
100 | 100 |
101 ScopedSSL<GENERAL_NAMES, GENERAL_NAMES_free> alt_names( | 101 base::ScopedSSL<GENERAL_NAMES, GENERAL_NAMES_free> alt_names( |
102 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); | 102 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); |
103 if (!alt_names.get()) | 103 if (!alt_names.get()) |
104 return; | 104 return; |
105 | 105 |
106 for (int i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { | 106 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); | 107 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); |
108 if (name->type == GEN_DNS) { | 108 if (name->type == GEN_DNS) { |
109 unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); | 109 unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); |
110 if (!dns_name) | 110 if (!dns_name) |
111 continue; | 111 continue; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
199 if (!der_cache) | 199 if (!der_cache) |
200 return; | 200 return; |
201 if (der_cache->data) | 201 if (der_cache->data) |
202 OPENSSL_free(der_cache->data); | 202 OPENSSL_free(der_cache->data); |
203 OPENSSL_free(der_cache); | 203 OPENSSL_free(der_cache); |
204 } | 204 } |
205 | 205 |
206 class X509InitSingleton { | 206 class X509InitSingleton { |
207 public: | 207 public: |
208 int der_cache_ex_index() const { return der_cache_ex_index_; } | 208 int der_cache_ex_index() const { return der_cache_ex_index_; } |
209 X509_STORE* store() const { return store_.get(); } | |
209 | 210 |
210 private: | 211 private: |
211 friend struct DefaultSingletonTraits<X509InitSingleton>; | 212 friend struct DefaultSingletonTraits<X509InitSingleton>; |
212 X509InitSingleton() { | 213 X509InitSingleton() |
213 der_cache_ex_index_ = X509_get_ex_new_index(0, 0, 0, 0, DERCache_free); | 214 : der_cache_ex_index_(X509_get_ex_new_index(0, 0, 0, 0, DERCache_free)), |
215 store_(X509_STORE_new()) { | |
214 DCHECK_NE(der_cache_ex_index_, -1); | 216 DCHECK_NE(der_cache_ex_index_, -1); |
217 X509_STORE_set_default_paths(store_.get()); | |
218 // TODO(joth): Enable CRL (see X509_STORE_set_flags(X509_V_FLAG_CRL_CHECK)). | |
215 } | 219 } |
216 ~X509InitSingleton() {} | |
217 | 220 |
218 int der_cache_ex_index_; | 221 int der_cache_ex_index_; |
222 base::ScopedSSL<X509_STORE, X509_STORE_free> store_; | |
219 | 223 |
220 DISALLOW_COPY_AND_ASSIGN(X509InitSingleton); | 224 DISALLOW_COPY_AND_ASSIGN(X509InitSingleton); |
221 }; | 225 }; |
222 | 226 |
223 // Takes ownership of |data| (which must have been allocated by OpenSSL). | 227 // Takes ownership of |data| (which must have been allocated by OpenSSL). |
224 DERCache* SetDERCache(X509Certificate::OSCertHandle cert, | 228 DERCache* SetDERCache(X509Certificate::OSCertHandle cert, |
225 int x509_der_cache_index, | 229 int x509_der_cache_index, |
226 unsigned char* data, | 230 unsigned char* data, |
227 int data_length) { | 231 int data_length) { |
228 DERCache* internal_cache = static_cast<DERCache*>( | 232 DERCache* internal_cache = static_cast<DERCache*>( |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
283 | 287 |
284 // static | 288 // static |
285 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 289 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
286 // Decrement the ref-count for the cert and, if all references are gone, | 290 // 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 | 291 // free the memory and any application-specific data associated with the |
288 // certificate. | 292 // certificate. |
289 X509_free(cert_handle); | 293 X509_free(cert_handle); |
290 } | 294 } |
291 | 295 |
292 void X509Certificate::Initialize() { | 296 void X509Certificate::Initialize() { |
297 base::EnsureOpenSSLInit(); | |
293 fingerprint_ = CalculateFingerprint(cert_handle_); | 298 fingerprint_ = CalculateFingerprint(cert_handle_); |
294 ParsePrincipal(cert_handle_, X509_get_subject_name(cert_handle_), &subject_); | 299 ParsePrincipal(cert_handle_, X509_get_subject_name(cert_handle_), &subject_); |
295 ParsePrincipal(cert_handle_, X509_get_issuer_name(cert_handle_), &issuer_); | 300 ParsePrincipal(cert_handle_, X509_get_issuer_name(cert_handle_), &issuer_); |
296 nxou::ParseDate(X509_get_notBefore(cert_handle_), &valid_start_); | 301 nxou::ParseDate(X509_get_notBefore(cert_handle_), &valid_start_); |
297 nxou::ParseDate(X509_get_notAfter(cert_handle_), &valid_expiry_); | 302 nxou::ParseDate(X509_get_notAfter(cert_handle_), &valid_expiry_); |
298 } | 303 } |
299 | 304 |
300 SHA1Fingerprint X509Certificate::CalculateFingerprint(OSCertHandle cert) { | 305 SHA1Fingerprint X509Certificate::CalculateFingerprint(OSCertHandle cert) { |
301 SHA1Fingerprint sha1; | 306 SHA1Fingerprint sha1; |
302 unsigned int sha1_size = static_cast<unsigned int>(sizeof(sha1.data)); | 307 unsigned int sha1_size = static_cast<unsigned int>(sizeof(sha1.data)); |
303 int ret = X509_digest(cert, EVP_sha1(), sha1.data, &sha1_size); | 308 int ret = X509_digest(cert, EVP_sha1(), sha1.data, &sha1_size); |
304 CHECK(ret); | 309 CHECK(ret); |
305 CHECK_EQ(sha1_size, sizeof(sha1.data)); | 310 CHECK_EQ(sha1_size, sizeof(sha1.data)); |
306 return sha1; | 311 return sha1; |
307 } | 312 } |
308 | 313 |
309 // static | 314 // static |
310 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | 315 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
311 const char* data, int length) { | 316 const char* data, int length) { |
312 if (length < 0) | 317 if (length < 0) |
313 return NULL; | 318 return NULL; |
319 base::EnsureOpenSSLInit(); | |
314 const unsigned char* d2i_data = | 320 const unsigned char* d2i_data = |
315 reinterpret_cast<const unsigned char*>(data); | 321 reinterpret_cast<const unsigned char*>(data); |
316 // Don't cache this data via SetDERCache as this wire format may be not be | 322 // Don't cache this data via SetDERCache as this wire format may be not be |
317 // identical from the i2d_X509 roundtrip. | 323 // identical from the i2d_X509 roundtrip. |
318 X509* cert = d2i_X509(NULL, &d2i_data, length); | 324 X509* cert = d2i_X509(NULL, &d2i_data, length); |
319 return cert; | 325 return cert; |
320 } | 326 } |
321 | 327 |
322 // static | 328 // static |
323 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( | 329 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( |
324 const char* data, int length, Format format) { | 330 const char* data, int length, Format format) { |
325 OSCertHandles results; | 331 OSCertHandles results; |
326 if (length < 0) | 332 if (length < 0) |
327 return results; | 333 return results; |
328 | 334 |
335 base::EnsureOpenSSLInit(); | |
bulach
2010/11/16 14:23:50
you may want to remove it from here and put inside
joth
2010/11/16 15:57:41
Done.
| |
329 switch (format) { | 336 switch (format) { |
330 case FORMAT_SINGLE_CERTIFICATE: { | 337 case FORMAT_SINGLE_CERTIFICATE: { |
331 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); | 338 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); |
332 if (handle) | 339 if (handle) |
333 results.push_back(handle); | 340 results.push_back(handle); |
334 break; | 341 break; |
335 } | 342 } |
336 case FORMAT_PKCS7: { | 343 case FORMAT_PKCS7: { |
337 CreateOSCertHandlesFromPKCS7Bytes(data, length, &results); | 344 CreateOSCertHandlesFromPKCS7Bytes(data, length, &results); |
338 break; | 345 break; |
339 } | 346 } |
340 default: { | 347 default: { |
341 NOTREACHED() << "Certificate format " << format << " unimplemented"; | 348 NOTREACHED() << "Certificate format " << format << " unimplemented"; |
342 break; | 349 break; |
343 } | 350 } |
344 } | 351 } |
345 | 352 |
346 return results; | 353 return results; |
347 } | 354 } |
348 | 355 |
356 // static | |
349 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, | 357 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, |
350 void** pickle_iter) { | 358 void** pickle_iter) { |
351 const char* data; | 359 const char* data; |
352 int length; | 360 int length; |
353 if (!pickle.ReadData(pickle_iter, &data, &length)) | 361 if (!pickle.ReadData(pickle_iter, &data, &length)) |
354 return NULL; | 362 return NULL; |
355 | 363 |
356 return CreateFromBytes(data, length); | 364 return CreateFromBytes(data, length); |
357 } | 365 } |
358 | 366 |
359 void X509Certificate::Persist(Pickle* pickle) { | 367 void X509Certificate::Persist(Pickle* pickle) { |
360 DERCache der_cache; | 368 DERCache der_cache; |
361 if (!GetDERAndCacheIfNeeded(cert_handle_, &der_cache)) | 369 if (!GetDERAndCacheIfNeeded(cert_handle_, &der_cache)) |
362 return; | 370 return; |
363 | 371 |
364 pickle->WriteData(reinterpret_cast<const char*>(der_cache.data), | 372 pickle->WriteData(reinterpret_cast<const char*>(der_cache.data), |
365 der_cache.data_length); | 373 der_cache.data_length); |
366 } | 374 } |
367 | 375 |
368 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { | 376 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { |
369 dns_names->clear(); | 377 dns_names->clear(); |
370 | 378 |
371 ParseSubjectAltNames(cert_handle_, dns_names); | 379 ParseSubjectAltNames(cert_handle_, dns_names); |
372 | 380 |
373 if (dns_names->empty()) | 381 if (dns_names->empty()) |
374 dns_names->push_back(subject_.common_name); | 382 dns_names->push_back(subject_.common_name); |
375 } | 383 } |
376 | 384 |
385 // static | |
386 X509_STORE* X509Certificate::cert_store() { | |
387 base::EnsureOpenSSLInit(); | |
388 return Singleton<X509InitSingleton>::get()->store(); | |
389 } | |
390 | |
377 int X509Certificate::Verify(const std::string& hostname, | 391 int X509Certificate::Verify(const std::string& hostname, |
378 int flags, | 392 int flags, |
379 CertVerifyResult* verify_result) const { | 393 CertVerifyResult* verify_result) const { |
380 verify_result->Reset(); | 394 verify_result->Reset(); |
381 | 395 |
382 ScopedSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx(X509_STORE_CTX_new()); | 396 base::ScopedSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx( |
397 X509_STORE_CTX_new()); | |
383 | 398 |
384 ScopedSSL<STACK_OF(X509), sk_X509_free_fn> intermediates(sk_X509_new_null()); | 399 base::ScopedSSL<STACK_OF(X509), sk_X509_free_fn> intermediates( |
400 sk_X509_new_null()); | |
385 if (!intermediates.get()) | 401 if (!intermediates.get()) |
386 return ERR_OUT_OF_MEMORY; | 402 return ERR_OUT_OF_MEMORY; |
387 | 403 |
388 for (OSCertHandles::const_iterator it = intermediate_ca_certs_.begin(); | 404 for (OSCertHandles::const_iterator it = intermediate_ca_certs_.begin(); |
389 it != intermediate_ca_certs_.end(); ++it) { | 405 it != intermediate_ca_certs_.end(); ++it) { |
390 if (!sk_X509_push(intermediates.get(), *it)) | 406 if (!sk_X509_push(intermediates.get(), *it)) |
391 return ERR_OUT_OF_MEMORY; | 407 return ERR_OUT_OF_MEMORY; |
392 } | 408 } |
393 int rv = X509_STORE_CTX_init(ctx.get(), | 409 int rv = X509_STORE_CTX_init(ctx.get(), cert_store(), |
394 GetOpenSSLInitSingleton()->x509_store(), | |
395 cert_handle_, intermediates.get()); | 410 cert_handle_, intermediates.get()); |
396 CHECK_EQ(1, rv); | 411 CHECK_EQ(1, rv); |
397 | 412 |
398 if (X509_verify_cert(ctx.get()) == 1) { | 413 if (X509_verify_cert(ctx.get()) == 1) { |
399 return OK; | 414 return OK; |
400 } | 415 } |
401 | 416 |
402 int x509_error = X509_STORE_CTX_get_error(ctx.get()); | 417 int x509_error = X509_STORE_CTX_get_error(ctx.get()); |
403 int cert_status = MapCertErrorToCertStatus(x509_error); | 418 int cert_status = MapCertErrorToCertStatus(x509_error); |
404 LOG(ERROR) << "X509 Verification error " | 419 LOG(ERROR) << "X509 Verification error " |
(...skipping 17 matching lines...) Expand all Loading... | |
422 // cache the DER (if not already cached via X509_set_ex_data). | 437 // cache the DER (if not already cached via X509_set_ex_data). |
423 DERCache der_cache_a, der_cache_b; | 438 DERCache der_cache_a, der_cache_b; |
424 | 439 |
425 return GetDERAndCacheIfNeeded(a, &der_cache_a) && | 440 return GetDERAndCacheIfNeeded(a, &der_cache_a) && |
426 GetDERAndCacheIfNeeded(b, &der_cache_b) && | 441 GetDERAndCacheIfNeeded(b, &der_cache_b) && |
427 der_cache_a.data_length == der_cache_b.data_length && | 442 der_cache_a.data_length == der_cache_b.data_length && |
428 memcmp(der_cache_a.data, der_cache_b.data, der_cache_a.data_length) == 0; | 443 memcmp(der_cache_a.data, der_cache_b.data, der_cache_a.data_length) == 0; |
429 } | 444 } |
430 | 445 |
431 } // namespace net | 446 } // namespace net |
OLD | NEW |