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

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

Issue 6874039: Return the constructed certificate chain in X509Certificate::Verify() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Ensure the EE cert is marked as a TLS server cert, not a CA cert Created 9 years, 8 months 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 <cert.h> 7 #include <cert.h>
8 #include <cryptohi.h> 8 #include <cryptohi.h>
9 #include <keyhi.h> 9 #include <keyhi.h>
10 #include <nss.h> 10 #include <nss.h>
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 case SEC_ERROR_EXTENSION_VALUE_INVALID: 161 case SEC_ERROR_EXTENSION_VALUE_INVALID:
162 return CERT_STATUS_INVALID; 162 return CERT_STATUS_INVALID;
163 default: 163 default:
164 return 0; 164 return 0;
165 } 165 }
166 } 166 }
167 167
168 // Saves some information about the certificate chain cert_list in 168 // Saves some information about the certificate chain cert_list in
169 // *verify_result. The caller MUST initialize *verify_result before calling 169 // *verify_result. The caller MUST initialize *verify_result before calling
170 // this function. 170 // this function.
171 // Note that cert_list[0] is the end entity certificate and cert_list doesn't 171 // Note that cert_list[0] is the end entity certificate.
172 // contain the root CA certificate.
173 void GetCertChainInfo(CERTCertList* cert_list, 172 void GetCertChainInfo(CERTCertList* cert_list,
173 CERTCertificate* root_cert,
174 CertVerifyResult* verify_result) { 174 CertVerifyResult* verify_result) {
175 // NOTE: Using a NSS library before 3.12.3.1 will crash below. To see the 175 // NOTE: Using a NSS library before 3.12.3.1 will crash below. To see the
176 // NSS version currently in use: 176 // NSS version currently in use:
177 // 1. use ldd on the chrome executable for NSS's location (ie. libnss3.so*) 177 // 1. use ldd on the chrome executable for NSS's location (ie. libnss3.so*)
178 // 2. use ident libnss3.so* for the library's version 178 // 2. use ident libnss3.so* for the library's version
179 DCHECK(cert_list); 179 if (!cert_list)
180 return;
wtc 2011/07/26 00:16:35 Why do you want to allow cert_list to be NULL? Thi
Ryan Sleevi 2011/07/26 01:44:50 Thanks for catching this. In digging down further
181
182 CERTCertificate* verified_cert = NULL;
183 std::vector<CERTCertificate*> verified_chain;
180 int i = 0; 184 int i = 0;
181 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 185 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
182 !CERT_LIST_END(node, cert_list); 186 !CERT_LIST_END(node, cert_list);
183 node = CERT_LIST_NEXT(node), i++) { 187 node = CERT_LIST_NEXT(node), ++i) {
188 if (i == 0) {
189 verified_cert = node->cert;
190 } else {
191 verified_chain.push_back(node->cert);
192 }
184 SECAlgorithmID& signature = node->cert->signature; 193 SECAlgorithmID& signature = node->cert->signature;
185 SECOidTag oid_tag = SECOID_FindOIDTag(&signature.algorithm); 194 SECOidTag oid_tag = SECOID_FindOIDTag(&signature.algorithm);
186 switch (oid_tag) { 195 switch (oid_tag) {
187 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: 196 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
188 verify_result->has_md5 = true; 197 verify_result->has_md5 = true;
189 if (i != 0) 198 if (i != 0)
190 verify_result->has_md5_ca = true; 199 verify_result->has_md5_ca = true;
191 break; 200 break;
192 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: 201 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
193 verify_result->has_md2 = true; 202 verify_result->has_md2 = true;
194 if (i != 0) 203 if (i != 0)
195 verify_result->has_md2_ca = true; 204 verify_result->has_md2_ca = true;
196 break; 205 break;
197 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: 206 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
198 verify_result->has_md4 = true; 207 verify_result->has_md4 = true;
199 break; 208 break;
200 default: 209 default:
201 break; 210 break;
202 } 211 }
203 } 212 }
213
214 if (!verified_cert)
215 return;
216
217 // If the chain was not trusted, |root_cert| may be NULL.
218 if (root_cert)
219 verified_chain.push_back(root_cert);
220 verify_result->verified_cert =
221 X509Certificate::CreateFromHandle(verified_cert, verified_chain);
204 } 222 }
205 223
206 // IsKnownRoot returns true if the given certificate is one that we believe 224 // IsKnownRoot returns true if the given certificate is one that we believe
207 // is a standard (as opposed to user-installed) root. 225 // is a standard (as opposed to user-installed) root.
208 bool IsKnownRoot(CERTCertificate* root) { 226 bool IsKnownRoot(CERTCertificate* root) {
209 if (!root->slot) 227 if (!root->slot)
210 return false; 228 return false;
211 229
212 // This magic name is taken from 230 // This magic name is taken from
213 // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw/b uiltins/constants.c&rev=1.13&mark=86,89#79 231 // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw/b uiltins/constants.c&rev=1.13&mark=86,89#79
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 780
763 X509Certificate::OSCertListHandle 781 X509Certificate::OSCertListHandle
764 X509Certificate::CreateOSCertListHandle() const { 782 X509Certificate::CreateOSCertListHandle() const {
765 return CERT_DupCertificate(cert_handle_); 783 return CERT_DupCertificate(cert_handle_);
766 } 784 }
767 785
768 int X509Certificate::Verify(const std::string& hostname, 786 int X509Certificate::Verify(const std::string& hostname,
769 int flags, 787 int flags,
770 CertVerifyResult* verify_result) const { 788 CertVerifyResult* verify_result) const {
771 verify_result->Reset(); 789 verify_result->Reset();
790 verify_result->verified_cert =
791 CreateFromHandle(cert_handle_, GetIntermediateCertificates());
772 792
773 if (IsBlacklisted()) { 793 if (IsBlacklisted()) {
774 verify_result->cert_status |= CERT_STATUS_REVOKED; 794 verify_result->cert_status |= CERT_STATUS_REVOKED;
775 return ERR_CERT_REVOKED; 795 return ERR_CERT_REVOKED;
776 } 796 }
777 797
778 // Make sure that the hostname matches with the common name of the cert. 798 // Make sure that the hostname matches with the common name of the cert.
779 SECStatus status = CERT_VerifyCertName(cert_handle_, hostname.c_str()); 799 SECStatus status = CERT_VerifyCertName(cert_handle_, hostname.c_str());
780 if (status != SECSuccess) 800 if (status != SECSuccess)
781 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; 801 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
(...skipping 18 matching lines...) Expand all
800 ScopedCERTValOutParam scoped_cvout(cvout); 820 ScopedCERTValOutParam scoped_cvout(cvout);
801 821
802 bool check_revocation = (flags & VERIFY_REV_CHECKING_ENABLED); 822 bool check_revocation = (flags & VERIFY_REV_CHECKING_ENABLED);
803 if (check_revocation) { 823 if (check_revocation) {
804 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 824 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
805 } else { 825 } else {
806 // EV requires revocation checking. 826 // EV requires revocation checking.
807 flags &= ~VERIFY_EV_CERT; 827 flags &= ~VERIFY_EV_CERT;
808 } 828 }
809 status = PKIXVerifyCert(cert_handle_, check_revocation, NULL, 0, cvout); 829 status = PKIXVerifyCert(cert_handle_, check_revocation, NULL, 0, cvout);
830
831 GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain,
832 cvout[cvout_trust_anchor_index].value.pointer.cert,
833 verify_result);
834
810 if (status != SECSuccess) { 835 if (status != SECSuccess) {
811 int err = PORT_GetError(); 836 int err = PORT_GetError();
812 LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname 837 LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname
813 << " failed err=" << err; 838 << " failed err=" << err;
814 // CERT_PKIXVerifyCert rerports the wrong error code for 839 // CERT_PKIXVerifyCert rerports the wrong error code for
815 // expired certificates (NSS bug 491174) 840 // expired certificates (NSS bug 491174)
816 if (err == SEC_ERROR_CERT_NOT_VALID && 841 if (err == SEC_ERROR_CERT_NOT_VALID &&
817 (verify_result->cert_status & CERT_STATUS_DATE_INVALID) != 0) 842 (verify_result->cert_status & CERT_STATUS_DATE_INVALID) != 0)
818 err = SEC_ERROR_EXPIRED_CERTIFICATE; 843 err = SEC_ERROR_EXPIRED_CERTIFICATE;
819 int cert_status = MapCertErrorToCertStatus(err); 844 int cert_status = MapCertErrorToCertStatus(err);
820 if (cert_status) { 845 if (cert_status) {
821 verify_result->cert_status |= cert_status; 846 verify_result->cert_status |= cert_status;
822 return MapCertStatusToNetError(verify_result->cert_status); 847 return MapCertStatusToNetError(verify_result->cert_status);
823 } 848 }
824 // |err| is not a certificate error. 849 // |err| is not a certificate error.
825 return MapSecurityError(err); 850 return MapSecurityError(err);
826 } 851 }
827 852
828 GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain,
829 verify_result);
830 if (IsCertStatusError(verify_result->cert_status)) 853 if (IsCertStatusError(verify_result->cert_status))
831 return MapCertStatusToNetError(verify_result->cert_status); 854 return MapCertStatusToNetError(verify_result->cert_status);
832 855
833 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, 856 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain,
834 cvout[cvout_trust_anchor_index].value.pointer.cert, 857 cvout[cvout_trust_anchor_index].value.pointer.cert,
835 &verify_result->public_key_hashes); 858 &verify_result->public_key_hashes);
836 859
837 verify_result->is_issued_by_known_root = 860 verify_result->is_issued_by_known_root =
838 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); 861 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert);
839 862
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 1035
1013 // static 1036 // static
1014 bool X509Certificate::WriteCertHandleToPickle(OSCertHandle cert_handle, 1037 bool X509Certificate::WriteCertHandleToPickle(OSCertHandle cert_handle,
1015 Pickle* pickle) { 1038 Pickle* pickle) {
1016 return pickle->WriteData( 1039 return pickle->WriteData(
1017 reinterpret_cast<const char*>(cert_handle->derCert.data), 1040 reinterpret_cast<const char*>(cert_handle->derCert.data),
1018 cert_handle->derCert.len); 1041 cert_handle->derCert.len);
1019 } 1042 }
1020 1043
1021 } // namespace net 1044 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698