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 |