OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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> |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) | 358 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) |
359 continue; | 359 continue; |
360 | 360 |
361 SHA1Fingerprint hash; | 361 SHA1Fingerprint hash; |
362 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), | 362 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), |
363 spki_bytes.size(), hash.data); | 363 spki_bytes.size(), hash.data); |
364 hashes->push_back(hash); | 364 hashes->push_back(hash); |
365 } | 365 } |
366 } | 366 } |
367 | 367 |
| 368 #if defined(OS_ANDROID) |
| 369 |
| 370 // Returns true if we have verification result in |verify_result| from Android |
| 371 // Trust Manager. Otherwise returns false. |
| 372 bool VerifyFromAndroidTrustManager(const std::vector<std::string>& cert_bytes, |
| 373 CertVerifyResult* verify_result) { |
| 374 // TODO(joth): Fetch the authentication type from SSL rather than hardcode. |
| 375 // TODO(jnd): Remove unused |hostname| from net::android::VerifyX509CertChain. |
| 376 bool verified = true; |
| 377 #if 0 |
| 378 android::VerifyResult result = |
| 379 android::VerifyX509CertChain(cert_bytes, hostname, "RSA"); |
| 380 #else |
| 381 // TODO(jingzhao): Recover the original implementation once we support JNI. |
| 382 android::VerifyResult result = android::VERIFY_INVOCATION_ERROR; |
| 383 NOTIMPLEMENTED(); |
| 384 #endif |
| 385 switch (result) { |
| 386 case android::VERIFY_OK: |
| 387 break; |
| 388 case android::VERIFY_BAD_HOSTNAME: |
| 389 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; |
| 390 break; |
| 391 case android::VERIFY_NO_TRUSTED_ROOT: |
| 392 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; |
| 393 break; |
| 394 case android::VERIFY_INVOCATION_ERROR: |
| 395 verified = false; |
| 396 break; |
| 397 default: |
| 398 verify_result->cert_status |= CERT_STATUS_INVALID; |
| 399 break; |
| 400 } |
| 401 return verified; |
| 402 } |
| 403 |
| 404 #endif |
| 405 |
368 } // namespace | 406 } // namespace |
369 | 407 |
370 // static | 408 // static |
371 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | 409 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( |
372 OSCertHandle cert_handle) { | 410 OSCertHandle cert_handle) { |
373 DCHECK(cert_handle); | 411 DCHECK(cert_handle); |
374 // Using X509_dup causes the entire certificate to be reparsed. This | 412 // Using X509_dup causes the entire certificate to be reparsed. This |
375 // conversion, besides being non-trivial, drops any associated | 413 // conversion, besides being non-trivial, drops any associated |
376 // application-specific data set by X509_set_ex_data. Using CRYPTO_add | 414 // application-specific data set by X509_set_ex_data. Using CRYPTO_add |
377 // just bumps up the ref-count for the cert, without causing any allocations | 415 // just bumps up the ref-count for the cert, without causing any allocations |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 ip_addrs->clear(); | 547 ip_addrs->clear(); |
510 | 548 |
511 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); | 549 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); |
512 } | 550 } |
513 | 551 |
514 // static | 552 // static |
515 X509_STORE* X509Certificate::cert_store() { | 553 X509_STORE* X509Certificate::cert_store() { |
516 return X509InitSingleton::GetInstance()->store(); | 554 return X509InitSingleton::GetInstance()->store(); |
517 } | 555 } |
518 | 556 |
519 #if defined(OS_ANDROID) | |
520 int X509Certificate::VerifyInternal(const std::string& hostname, | 557 int X509Certificate::VerifyInternal(const std::string& hostname, |
521 int flags, | 558 int flags, |
522 CRLSet* crl_set, | 559 CRLSet* crl_set, |
523 CertVerifyResult* verify_result) const { | 560 CertVerifyResult* verify_result) const { |
524 if (!VerifyNameMatch(hostname)) | 561 if (!VerifyNameMatch(hostname)) |
525 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | 562 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; |
526 | 563 |
| 564 bool verify_attempted = false; |
| 565 |
| 566 #if defined(OS_ANDROID) |
527 std::vector<std::string> cert_bytes; | 567 std::vector<std::string> cert_bytes; |
528 GetChainDEREncodedBytes(&cert_bytes); | 568 GetChainDEREncodedBytes(&cert_bytes); |
529 | 569 |
530 // TODO(joth): Fetch the authentication type from SSL rather than hardcode. | 570 verify_attempted = VerifyFromAndroidTrustManager(cert_bytes, verify_result); |
531 // TODO(jingzhao): Recover the original implementation once we support JNI. | |
532 #if 0 | |
533 android::VerifyResult result = | |
534 android::VerifyX509CertChain(cert_bytes, hostname, "RSA"); | |
535 #else | |
536 android::VerifyResult result = android::VERIFY_INVOCATION_ERROR; | |
537 NOTIMPLEMENTED(); | |
538 #endif | 571 #endif |
539 switch (result) { | |
540 case android::VERIFY_OK: | |
541 break; | |
542 case android::VERIFY_BAD_HOSTNAME: | |
543 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | |
544 break; | |
545 case android::VERIFY_NO_TRUSTED_ROOT: | |
546 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; | |
547 break; | |
548 case android::VERIFY_INVOCATION_ERROR: | |
549 default: | |
550 verify_result->cert_status |= CERT_STATUS_INVALID; | |
551 break; | |
552 } | |
553 if (IsCertStatusError(verify_result->cert_status)) | |
554 return MapCertStatusToNetError(verify_result->cert_status); | |
555 return OK; | |
556 } | |
557 | 572 |
558 #else | 573 if (verify_attempted) { |
559 int X509Certificate::VerifyInternal(const std::string& hostname, | 574 if (IsCertStatusError(verify_result->cert_status)) |
560 int flags, | 575 return MapCertStatusToNetError(verify_result->cert_status); |
561 CRLSet* crl_set, | 576 } else { |
562 CertVerifyResult* verify_result) const { | 577 crypto::ScopedOpenSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx( |
563 if (!VerifyNameMatch(hostname)) | 578 X509_STORE_CTX_new()); |
564 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | |
565 | 579 |
566 crypto::ScopedOpenSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx( | 580 crypto::ScopedOpenSSL<STACK_OF(X509), sk_X509_free_fn> intermediates( |
567 X509_STORE_CTX_new()); | 581 sk_X509_new_null()); |
| 582 if (!intermediates.get()) |
| 583 return ERR_OUT_OF_MEMORY; |
568 | 584 |
569 crypto::ScopedOpenSSL<STACK_OF(X509), sk_X509_free_fn> intermediates( | 585 for (OSCertHandles::const_iterator it = intermediate_ca_certs_.begin(); |
570 sk_X509_new_null()); | 586 it != intermediate_ca_certs_.end(); ++it) { |
571 if (!intermediates.get()) | 587 if (!sk_X509_push(intermediates.get(), *it)) |
572 return ERR_OUT_OF_MEMORY; | 588 return ERR_OUT_OF_MEMORY; |
| 589 } |
| 590 int rv = X509_STORE_CTX_init(ctx.get(), cert_store(), |
| 591 cert_handle_, intermediates.get()); |
| 592 CHECK_EQ(1, rv); |
573 | 593 |
574 for (OSCertHandles::const_iterator it = intermediate_ca_certs_.begin(); | 594 if (X509_verify_cert(ctx.get()) != 1) { |
575 it != intermediate_ca_certs_.end(); ++it) { | 595 int x509_error = X509_STORE_CTX_get_error(ctx.get()); |
576 if (!sk_X509_push(intermediates.get(), *it)) | 596 CertStatus cert_status = MapCertErrorToCertStatus(x509_error); |
577 return ERR_OUT_OF_MEMORY; | 597 LOG(ERROR) << "X509 Verification error " |
578 } | 598 << X509_verify_cert_error_string(x509_error) |
579 int rv = X509_STORE_CTX_init(ctx.get(), cert_store(), | 599 << " : " << x509_error |
580 cert_handle_, intermediates.get()); | 600 << " : " << X509_STORE_CTX_get_error_depth(ctx.get()) |
581 CHECK_EQ(1, rv); | 601 << " : " << cert_status; |
| 602 verify_result->cert_status |= cert_status; |
| 603 } |
582 | 604 |
583 if (X509_verify_cert(ctx.get()) != 1) { | 605 GetCertChainInfo(ctx.get(), verify_result); |
584 int x509_error = X509_STORE_CTX_get_error(ctx.get()); | 606 if (IsCertStatusError(verify_result->cert_status)) |
585 CertStatus cert_status = MapCertErrorToCertStatus(x509_error); | 607 return MapCertStatusToNetError(verify_result->cert_status); |
586 LOG(ERROR) << "X509 Verification error " | 608 AppendPublicKeyHashes(ctx.get(), &verify_result->public_key_hashes); |
587 << X509_verify_cert_error_string(x509_error) | |
588 << " : " << x509_error | |
589 << " : " << X509_STORE_CTX_get_error_depth(ctx.get()) | |
590 << " : " << cert_status; | |
591 verify_result->cert_status |= cert_status; | |
592 } | 609 } |
593 | 610 |
594 GetCertChainInfo(ctx.get(), verify_result); | |
595 | |
596 if (IsCertStatusError(verify_result->cert_status)) | |
597 return MapCertStatusToNetError(verify_result->cert_status); | |
598 | |
599 AppendPublicKeyHashes(ctx.get(), &verify_result->public_key_hashes); | |
600 // Currently we only ues OpenSSL's default root CA paths, so treat all | 611 // Currently we only ues OpenSSL's default root CA paths, so treat all |
601 // correctly verified certs as being from a known root. TODO(joth): if the | 612 // correctly verified certs as being from a known root. TODO(joth): if the |
602 // motivations described in http://src.chromium.org/viewvc/chrome?view=rev&rev
ision=80778 | 613 // motivations described in http://src.chromium.org/viewvc/chrome?view=rev&rev
ision=80778 |
603 // become an issue on OpenSSL builds, we will need to embed a hardcoded list | 614 // become an issue on OpenSSL builds, we will need to embed a hardcoded list |
604 // of well known root CAs, as per the _mac and _win versions. | 615 // of well known root CAs, as per the _mac and _win versions. |
605 verify_result->is_issued_by_known_root = true; | 616 verify_result->is_issued_by_known_root = true; |
606 | 617 |
607 return OK; | 618 return OK; |
608 } | 619 } |
609 | 620 |
610 #endif // defined(OS_ANDROID) | |
611 | |
612 // static | 621 // static |
613 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | 622 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, |
614 std::string* encoded) { | 623 std::string* encoded) { |
615 DERCache der_cache; | 624 DERCache der_cache; |
616 if (!GetDERAndCacheIfNeeded(cert_handle, &der_cache)) | 625 if (!GetDERAndCacheIfNeeded(cert_handle, &der_cache)) |
617 return false; | 626 return false; |
618 encoded->assign(reinterpret_cast<const char*>(der_cache.data), | 627 encoded->assign(reinterpret_cast<const char*>(der_cache.data), |
619 der_cache.data_length); | 628 der_cache.data_length); |
620 return true; | 629 return true; |
621 } | 630 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 for (OSCertHandles::const_iterator it = cert_handles.begin(); | 717 for (OSCertHandles::const_iterator it = cert_handles.begin(); |
709 it != cert_handles.end(); ++it) { | 718 it != cert_handles.end(); ++it) { |
710 std::string cert_bytes; | 719 std::string cert_bytes; |
711 GetDEREncoded(*it, &cert_bytes); | 720 GetDEREncoded(*it, &cert_bytes); |
712 chain_bytes->push_back(cert_bytes); | 721 chain_bytes->push_back(cert_bytes); |
713 } | 722 } |
714 } | 723 } |
715 #endif | 724 #endif |
716 | 725 |
717 } // namespace net | 726 } // namespace net |
OLD | NEW |