| 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/cert/cert_verify_proc_nss.h" | 5 #include "net/cert/cert_verify_proc_nss.h" |
| 6 | 6 |
| 7 #include <cert.h> | 7 #include <cert.h> |
| 8 #include <nss.h> | 8 #include <nss.h> |
| 9 #include <prerror.h> | 9 #include <prerror.h> |
| 10 #include <secerr.h> | 10 #include <secerr.h> |
| 11 #include <sechash.h> | 11 #include <sechash.h> |
| 12 #include <sslerr.h> | 12 #include <sslerr.h> |
| 13 | 13 |
| 14 #include <memory> | 14 #include <memory> |
| 15 #include <string> | 15 #include <string> |
| 16 #include <vector> | 16 #include <vector> |
| 17 | 17 |
| 18 #include "base/logging.h" | 18 #include "base/logging.h" |
| 19 #include "base/macros.h" | 19 #include "base/macros.h" |
| 20 #include "base/sha1.h" |
| 20 #include "build/build_config.h" | 21 #include "build/build_config.h" |
| 21 #include "crypto/nss_util.h" | 22 #include "crypto/nss_util.h" |
| 22 #include "crypto/scoped_nss_types.h" | 23 #include "crypto/scoped_nss_types.h" |
| 23 #include "crypto/sha2.h" | 24 #include "crypto/sha2.h" |
| 24 #include "net/base/net_errors.h" | 25 #include "net/base/net_errors.h" |
| 25 #include "net/cert/asn1_util.h" | 26 #include "net/cert/asn1_util.h" |
| 26 #include "net/cert/cert_status_flags.h" | 27 #include "net/cert/cert_status_flags.h" |
| 27 #include "net/cert/cert_verifier.h" | 28 #include "net/cert/cert_verifier.h" |
| 28 #include "net/cert/cert_verify_result.h" | 29 #include "net/cert/cert_verify_result.h" |
| 29 #include "net/cert/crl_set.h" | 30 #include "net/cert/crl_set.h" |
| 30 #include "net/cert/ev_root_ca_metadata.h" | 31 #include "net/cert/ev_root_ca_metadata.h" |
| 31 #include "net/cert/x509_certificate.h" | 32 #include "net/cert/x509_certificate.h" |
| 32 #include "net/cert/x509_util_nss.h" | 33 #include "net/cert/x509_util_nss.h" |
| 33 | 34 |
| 34 #if defined(OS_IOS) | |
| 35 #include <CommonCrypto/CommonDigest.h> | |
| 36 #include "net/cert/x509_util_ios.h" | |
| 37 #endif // defined(OS_IOS) | |
| 38 | |
| 39 #if defined(USE_NSS_CERTS) | |
| 40 #include <dlfcn.h> | 35 #include <dlfcn.h> |
| 41 #else | |
| 42 #include <ocsp.h> | |
| 43 #endif | |
| 44 | 36 |
| 45 namespace net { | 37 namespace net { |
| 46 | 38 |
| 47 namespace { | 39 namespace { |
| 48 | 40 |
| 49 typedef std::unique_ptr< | 41 typedef std::unique_ptr< |
| 50 CERTCertificatePolicies, | 42 CERTCertificatePolicies, |
| 51 crypto::NSSDestroyer<CERTCertificatePolicies, | 43 crypto::NSSDestroyer<CERTCertificatePolicies, |
| 52 CERT_DestroyCertificatePoliciesExtension>> | 44 CERT_DestroyCertificatePoliciesExtension>> |
| 53 ScopedCERTCertificatePolicies; | 45 ScopedCERTCertificatePolicies; |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 if (i == 0) | 212 if (i == 0) |
| 221 verify_result->has_sha1_leaf = true; | 213 verify_result->has_sha1_leaf = true; |
| 222 break; | 214 break; |
| 223 default: | 215 default: |
| 224 break; | 216 break; |
| 225 } | 217 } |
| 226 } | 218 } |
| 227 | 219 |
| 228 if (root_cert) | 220 if (root_cert) |
| 229 verified_chain.push_back(root_cert); | 221 verified_chain.push_back(root_cert); |
| 230 #if defined(OS_IOS) | |
| 231 verify_result->verified_cert = | |
| 232 x509_util_ios::CreateCertFromNSSHandles(verified_cert, verified_chain); | |
| 233 #else | |
| 234 verify_result->verified_cert = | 222 verify_result->verified_cert = |
| 235 X509Certificate::CreateFromHandle(verified_cert, verified_chain); | 223 X509Certificate::CreateFromHandle(verified_cert, verified_chain); |
| 236 #endif // defined(OS_IOS) | |
| 237 } | 224 } |
| 238 | 225 |
| 239 // IsKnownRoot returns true if the given certificate is one that we believe | 226 // IsKnownRoot returns true if the given certificate is one that we believe |
| 240 // is a standard (as opposed to user-installed) root. | 227 // is a standard (as opposed to user-installed) root. |
| 241 bool IsKnownRoot(CERTCertificate* root) { | 228 bool IsKnownRoot(CERTCertificate* root) { |
| 242 if (!root || !root->slot) | 229 if (!root || !root->slot) |
| 243 return false; | 230 return false; |
| 244 | 231 |
| 245 // This magic name is taken from | 232 // This magic name is taken from |
| 246 // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw/b
uiltins/constants.c&rev=1.13&mark=86,89#79 | 233 // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw/b
uiltins/constants.c&rev=1.13&mark=86,89#79 |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 // default description here. The description doesn't need to be unique for | 640 // default description here. The description doesn't need to be unique for |
| 654 // each OID. | 641 // each OID. |
| 655 od.desc = "a certificate policy"; | 642 od.desc = "a certificate policy"; |
| 656 od.mechanism = CKM_INVALID_MECHANISM; | 643 od.mechanism = CKM_INVALID_MECHANISM; |
| 657 od.supportedExtension = INVALID_CERT_EXTENSION; | 644 od.supportedExtension = INVALID_CERT_EXTENSION; |
| 658 return SECOID_AddEntry(&od); | 645 return SECOID_AddEntry(&od); |
| 659 } | 646 } |
| 660 | 647 |
| 661 HashValue CertPublicKeyHashSHA1(CERTCertificate* cert) { | 648 HashValue CertPublicKeyHashSHA1(CERTCertificate* cert) { |
| 662 HashValue hash(HASH_VALUE_SHA1); | 649 HashValue hash(HASH_VALUE_SHA1); |
| 663 #if defined(OS_IOS) | |
| 664 CC_SHA1(cert->derPublicKey.data, cert->derPublicKey.len, hash.data()); | |
| 665 #else | |
| 666 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data(), | 650 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data(), |
| 667 cert->derPublicKey.data, cert->derPublicKey.len); | 651 cert->derPublicKey.data, cert->derPublicKey.len); |
| 668 DCHECK_EQ(SECSuccess, rv); | 652 DCHECK_EQ(SECSuccess, rv); |
| 669 #endif | |
| 670 return hash; | 653 return hash; |
| 671 } | 654 } |
| 672 | 655 |
| 673 HashValue CertPublicKeyHashSHA256(CERTCertificate* cert) { | 656 HashValue CertPublicKeyHashSHA256(CERTCertificate* cert) { |
| 674 HashValue hash(HASH_VALUE_SHA256); | 657 HashValue hash(HASH_VALUE_SHA256); |
| 675 #if defined(OS_IOS) | |
| 676 CC_SHA256(cert->derPublicKey.data, cert->derPublicKey.len, hash.data()); | |
| 677 #else | |
| 678 SECStatus rv = HASH_HashBuf(HASH_AlgSHA256, hash.data(), | 658 SECStatus rv = HASH_HashBuf(HASH_AlgSHA256, hash.data(), |
| 679 cert->derPublicKey.data, cert->derPublicKey.len); | 659 cert->derPublicKey.data, cert->derPublicKey.len); |
| 680 DCHECK_EQ(rv, SECSuccess); | 660 DCHECK_EQ(rv, SECSuccess); |
| 681 #endif | |
| 682 return hash; | 661 return hash; |
| 683 } | 662 } |
| 684 | 663 |
| 685 void AppendPublicKeyHashes(CERTCertList* cert_list, | 664 void AppendPublicKeyHashes(CERTCertList* cert_list, |
| 686 CERTCertificate* root_cert, | 665 CERTCertificate* root_cert, |
| 687 HashValueVector* hashes) { | 666 HashValueVector* hashes) { |
| 688 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); | 667 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); |
| 689 !CERT_LIST_END(node, cert_list); | 668 !CERT_LIST_END(node, cert_list); |
| 690 node = CERT_LIST_NEXT(node)) { | 669 node = CERT_LIST_NEXT(node)) { |
| 691 hashes->push_back(CertPublicKeyHashSHA1(node->cert)); | 670 hashes->push_back(CertPublicKeyHashSHA1(node->cert)); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 // the old path, might have been revoked. | 756 // the old path, might have been revoked. |
| 778 if (crl_set) { | 757 if (crl_set) { |
| 779 CRLSetResult crl_set_result = CheckRevocationWithCRLSet( | 758 CRLSetResult crl_set_result = CheckRevocationWithCRLSet( |
| 780 cvout[cvout_cert_list_index].value.pointer.chain, | 759 cvout[cvout_cert_list_index].value.pointer.chain, |
| 781 cvout[cvout_trust_anchor_index].value.pointer.cert, | 760 cvout[cvout_trust_anchor_index].value.pointer.cert, |
| 782 crl_set); | 761 crl_set); |
| 783 if (crl_set_result == kCRLSetRevoked) | 762 if (crl_set_result == kCRLSetRevoked) |
| 784 return false; | 763 return false; |
| 785 } | 764 } |
| 786 | 765 |
| 787 #if defined(OS_IOS) | 766 SHA1HashValue weak_fingerprint; |
| 788 SHA1HashValue fingerprint = x509_util_ios::CalculateFingerprintNSS(root_ca); | 767 base::SHA1HashBytes(root_ca->derCert.data, root_ca->derCert.len, |
| 789 #else | 768 weak_fingerprint.data); |
| 790 SHA1HashValue fingerprint = | 769 return metadata->HasEVPolicyOID(weak_fingerprint, ev_policy_oid); |
| 791 X509Certificate::CalculateFingerprint(root_ca); | |
| 792 #endif | |
| 793 return metadata->HasEVPolicyOID(fingerprint, ev_policy_oid); | |
| 794 } | 770 } |
| 795 | 771 |
| 796 CERTCertList* CertificateListToCERTCertList(const CertificateList& list) { | 772 CERTCertList* CertificateListToCERTCertList(const CertificateList& list) { |
| 797 CERTCertList* result = CERT_NewCertList(); | 773 CERTCertList* result = CERT_NewCertList(); |
| 798 for (size_t i = 0; i < list.size(); ++i) { | 774 for (size_t i = 0; i < list.size(); ++i) { |
| 799 #if defined(OS_IOS) | |
| 800 // X509Certificate::os_cert_handle() on iOS is a SecCertificateRef; convert | |
| 801 // it to an NSS CERTCertificate. | |
| 802 CERTCertificate* cert = x509_util_ios::CreateNSSCertHandleFromOSHandle( | |
| 803 list[i]->os_cert_handle()); | |
| 804 #else | |
| 805 CERTCertificate* cert = list[i]->os_cert_handle(); | 775 CERTCertificate* cert = list[i]->os_cert_handle(); |
| 806 #endif | |
| 807 CERT_AddCertToListTail(result, CERT_DupCertificate(cert)); | 776 CERT_AddCertToListTail(result, CERT_DupCertificate(cert)); |
| 808 } | 777 } |
| 809 return result; | 778 return result; |
| 810 } | 779 } |
| 811 | 780 |
| 812 } // namespace | 781 } // namespace |
| 813 | 782 |
| 814 CertVerifyProcNSS::CertVerifyProcNSS() | 783 CertVerifyProcNSS::CertVerifyProcNSS() |
| 815 #if defined(USE_NSS_CERTS) | |
| 816 : cache_ocsp_response_from_side_channel_( | 784 : cache_ocsp_response_from_side_channel_( |
| 817 reinterpret_cast<CacheOCSPResponseFromSideChannelFunction>( | 785 reinterpret_cast<CacheOCSPResponseFromSideChannelFunction>( |
| 818 dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel"))) | 786 dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel"))) |
| 819 #else | |
| 820 : cache_ocsp_response_from_side_channel_( | |
| 821 &CERT_CacheOCSPResponseFromSideChannel) | |
| 822 #endif | |
| 823 { | 787 { |
| 824 } | 788 } |
| 825 | 789 |
| 826 CertVerifyProcNSS::~CertVerifyProcNSS() {} | 790 CertVerifyProcNSS::~CertVerifyProcNSS() {} |
| 827 | 791 |
| 828 bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const { | 792 bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const { |
| 829 return true; | 793 return true; |
| 830 } | 794 } |
| 831 | 795 |
| 832 bool CertVerifyProcNSS::SupportsOCSPStapling() const { | 796 bool CertVerifyProcNSS::SupportsOCSPStapling() const { |
| 833 return cache_ocsp_response_from_side_channel_; | 797 return cache_ocsp_response_from_side_channel_; |
| 834 } | 798 } |
| 835 | 799 |
| 836 int CertVerifyProcNSS::VerifyInternalImpl( | 800 int CertVerifyProcNSS::VerifyInternalImpl( |
| 837 X509Certificate* cert, | 801 X509Certificate* cert, |
| 838 const std::string& hostname, | 802 const std::string& hostname, |
| 839 const std::string& ocsp_response, | 803 const std::string& ocsp_response, |
| 840 int flags, | 804 int flags, |
| 841 CRLSet* crl_set, | 805 CRLSet* crl_set, |
| 842 const CertificateList& additional_trust_anchors, | 806 const CertificateList& additional_trust_anchors, |
| 843 CERTChainVerifyCallback* chain_verify_callback, | 807 CERTChainVerifyCallback* chain_verify_callback, |
| 844 CertVerifyResult* verify_result) { | 808 CertVerifyResult* verify_result) { |
| 845 #if defined(OS_IOS) | |
| 846 // For iOS, the entire chain must be loaded into NSS's in-memory certificate | |
| 847 // store. | |
| 848 x509_util_ios::NSSCertChain scoped_chain(cert); | |
| 849 CERTCertificate* cert_handle = scoped_chain.cert_handle(); | |
| 850 #else | |
| 851 CERTCertificate* cert_handle = cert->os_cert_handle(); | 809 CERTCertificate* cert_handle = cert->os_cert_handle(); |
| 852 #endif // defined(OS_IOS) | |
| 853 | 810 |
| 854 if (!ocsp_response.empty() && cache_ocsp_response_from_side_channel_) { | 811 if (!ocsp_response.empty() && cache_ocsp_response_from_side_channel_) { |
| 855 // Note: NSS uses a thread-safe global hash table, so this call will | 812 // Note: NSS uses a thread-safe global hash table, so this call will |
| 856 // affect any concurrent verification operations on |cert| or copies of | 813 // affect any concurrent verification operations on |cert| or copies of |
| 857 // the same certificate. This is an unavoidable limitation of NSS's OCSP | 814 // the same certificate. This is an unavoidable limitation of NSS's OCSP |
| 858 // API. | 815 // API. |
| 859 SECItem ocsp_response_item; | 816 SECItem ocsp_response_item; |
| 860 ocsp_response_item.data = reinterpret_cast<unsigned char*>( | 817 ocsp_response_item.data = reinterpret_cast<unsigned char*>( |
| 861 const_cast<char*>(ocsp_response.data())); | 818 const_cast<char*>(ocsp_response.data())); |
| 862 ocsp_response_item.len = ocsp_response.size(); | 819 ocsp_response_item.len = ocsp_response.size(); |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 CRLSet* crl_set, | 983 CRLSet* crl_set, |
| 1027 const CertificateList& additional_trust_anchors, | 984 const CertificateList& additional_trust_anchors, |
| 1028 CertVerifyResult* verify_result) { | 985 CertVerifyResult* verify_result) { |
| 1029 return VerifyInternalImpl(cert, hostname, ocsp_response, flags, crl_set, | 986 return VerifyInternalImpl(cert, hostname, ocsp_response, flags, crl_set, |
| 1030 additional_trust_anchors, | 987 additional_trust_anchors, |
| 1031 NULL, // chain_verify_callback | 988 NULL, // chain_verify_callback |
| 1032 verify_result); | 989 verify_result); |
| 1033 } | 990 } |
| 1034 | 991 |
| 1035 } // namespace net | 992 } // namespace net |
| OLD | NEW |