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

Side by Side Diff: net/cert/cert_verify_proc_mac.cc

Issue 1094983002: Account for the OS returning an empty certificate chain. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: third time's the charm Created 5 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_mac.h" 5 #include "net/cert/cert_verify_proc_mac.h"
6 6
7 #include <CommonCrypto/CommonDigest.h> 7 #include <CommonCrypto/CommonDigest.h>
8 #include <CoreServices/CoreServices.h> 8 #include <CoreServices/CoreServices.h>
9 #include <Security/Security.h> 9 #include <Security/Security.h>
10 10
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 177
178 // Stores the constructed certificate chain |cert_chain| and information about 178 // Stores the constructed certificate chain |cert_chain| and information about
179 // the signature algorithms used into |*verify_result|. If the leaf cert in 179 // the signature algorithms used into |*verify_result|. If the leaf cert in
180 // |cert_chain| contains a weak (MD2, MD4, MD5, SHA-1) signature, stores that 180 // |cert_chain| contains a weak (MD2, MD4, MD5, SHA-1) signature, stores that
181 // in |*leaf_is_weak|. 181 // in |*leaf_is_weak|.
182 void GetCertChainInfo(CFArrayRef cert_chain, 182 void GetCertChainInfo(CFArrayRef cert_chain,
183 CSSM_TP_APPLE_EVIDENCE_INFO* chain_info, 183 CSSM_TP_APPLE_EVIDENCE_INFO* chain_info,
184 CertVerifyResult* verify_result, 184 CertVerifyResult* verify_result,
185 bool* leaf_is_weak) { 185 bool* leaf_is_weak) {
186 *leaf_is_weak = false; 186 *leaf_is_weak = false;
187 verify_result->verified_cert = nullptr;
188 verify_result->has_md2 = false; 187 verify_result->has_md2 = false;
189 verify_result->has_md4 = false; 188 verify_result->has_md4 = false;
190 verify_result->has_md5 = false; 189 verify_result->has_md5 = false;
191 verify_result->has_sha1 = false; 190 verify_result->has_sha1 = false;
192 191
192 // If certificate verification fails unrecoverably, OS X will return an
193 // empty chain. CertVerifyResult is expected to contain the original
194 // certificate chain in this case, so leave |verify_result->verified_cert|
195 // unchanged.
196 if (CFArrayGetCount(cert_chain) == 0)
197 return;
198
193 SecCertificateRef verified_cert = NULL; 199 SecCertificateRef verified_cert = NULL;
194 std::vector<SecCertificateRef> verified_chain; 200 std::vector<SecCertificateRef> verified_chain;
195 for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) { 201 for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) {
196 SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>( 202 SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>(
197 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); 203 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
198 if (i == 0) { 204 if (i == 0) {
199 verified_cert = chain_cert; 205 verified_cert = chain_cert;
200 } else { 206 } else {
201 verified_chain.push_back(chain_cert); 207 verified_chain.push_back(chain_cert);
202 } 208 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA_OIW) || 252 CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA_OIW) ||
247 CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA) || 253 CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA) ||
248 CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_CMS) || 254 CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_CMS) ||
249 CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_JDK) || 255 CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_JDK) ||
250 CSSMOIDEqual(alg_oid, &CSSMOID_ECDSA_WithSHA1)) { 256 CSSMOIDEqual(alg_oid, &CSSMOID_ECDSA_WithSHA1)) {
251 verify_result->has_sha1 = true; 257 verify_result->has_sha1 = true;
252 if (i == 0) 258 if (i == 0)
253 *leaf_is_weak = true; 259 *leaf_is_weak = true;
254 } 260 }
255 } 261 }
256 if (!verified_cert) 262 if (!verified_cert) {
263 NOTREACHED();
257 return; 264 return;
265 }
258 266
259 verify_result->verified_cert = 267 verify_result->verified_cert =
260 X509Certificate::CreateFromHandle(verified_cert, verified_chain); 268 X509Certificate::CreateFromHandle(verified_cert, verified_chain);
261 } 269 }
262 270
263 void AppendPublicKeyHashes(CFArrayRef chain, 271 void AppendPublicKeyHashes(CFArrayRef chain,
264 HashValueVector* hashes) { 272 HashValueVector* hashes) {
265 const CFIndex n = CFArrayGetCount(chain); 273 const CFIndex n = CFArrayGetCount(chain);
266 for (CFIndex i = 0; i < n; i++) { 274 for (CFIndex i = 0; i < n; i++) {
267 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>( 275 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 status = SecTrustEvaluate(tmp_trust, &tmp_trust_result); 456 status = SecTrustEvaluate(tmp_trust, &tmp_trust_result);
449 if (status) 457 if (status)
450 return NetErrorFromOSStatus(status); 458 return NetErrorFromOSStatus(status);
451 CFArrayRef tmp_verified_chain = NULL; 459 CFArrayRef tmp_verified_chain = NULL;
452 CSSM_TP_APPLE_EVIDENCE_INFO* tmp_chain_info; 460 CSSM_TP_APPLE_EVIDENCE_INFO* tmp_chain_info;
453 status = SecTrustGetResult(tmp_trust, &tmp_trust_result, &tmp_verified_chain, 461 status = SecTrustGetResult(tmp_trust, &tmp_trust_result, &tmp_verified_chain,
454 &tmp_chain_info); 462 &tmp_chain_info);
455 if (status) 463 if (status)
456 return NetErrorFromOSStatus(status); 464 return NetErrorFromOSStatus(status);
457 465
466 // SecTrustGetResult may return an empty verified chain on some fatal
467 // errors. Guard against any library bugs which may return it in cases where
468 // a chain is expected.
469 if (CFArrayGetCount(tmp_verified_chain) == 0 &&
470 (tmp_trust_result == kSecTrustResultUnspecified ||
471 tmp_trust_result == kSecTrustResultProceed ||
472 tmp_trust_result == kSecTrustResultRecoverableTrustFailure)) {
Ryan Sleevi 2015/04/18 00:54:58 Why only these status codes? And, from your descr
davidben 2015/04/22 21:57:58 You've got it backwards. These are the status code
473 NOTREACHED();
474 return ERR_FAILED;
475 }
476
458 trust_ref->swap(scoped_tmp_trust); 477 trust_ref->swap(scoped_tmp_trust);
459 *trust_result = tmp_trust_result; 478 *trust_result = tmp_trust_result;
460 verified_chain->reset(tmp_verified_chain); 479 verified_chain->reset(tmp_verified_chain);
461 *chain_info = tmp_chain_info; 480 *chain_info = tmp_chain_info;
462 481
463 return OK; 482 return OK;
464 } 483 }
465 484
466 } // namespace 485 } // namespace
467 486
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 CertVerifyResult temp_verify_result; 583 CertVerifyResult temp_verify_result;
565 bool leaf_is_weak = false; 584 bool leaf_is_weak = false;
566 GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result, 585 GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result,
567 &leaf_is_weak); 586 &leaf_is_weak);
568 587
569 bool untrusted = (temp_trust_result != kSecTrustResultUnspecified && 588 bool untrusted = (temp_trust_result != kSecTrustResultUnspecified &&
570 temp_trust_result != kSecTrustResultProceed); 589 temp_trust_result != kSecTrustResultProceed);
571 bool weak_chain = 590 bool weak_chain =
572 !leaf_is_weak && 591 !leaf_is_weak &&
573 (temp_verify_result.has_md2 || temp_verify_result.has_md4 || 592 (temp_verify_result.has_md2 || temp_verify_result.has_md4 ||
574 temp_verify_result.has_md5 || temp_verify_result.has_sha1); 593 temp_verify_result.has_md5 || temp_verify_result.has_sha1);
Ryan Sleevi 2015/04/18 00:54:58 The result of this is that a chain that fails (for
davidben 2015/04/22 21:57:58 Hrm? A chain that fails will have untrusted = fals
575 // Set the result to the current chain if: 594 // Set the result to the current chain if:
576 // - This is the first verification attempt. This ensures that if 595 // - This is the first verification attempt. This ensures that if
577 // everything is awful (e.g. it may just be an untrusted cert), that 596 // everything is awful (e.g. it may just be an untrusted cert), that
578 // what is reported is exactly what was sent by the server 597 // what is reported is exactly what was sent by the server
579 // - If the current chain is trusted, and the old chain was not trusted, 598 // - If the current chain is trusted, and the old chain was not trusted,
580 // then prefer this chain. This ensures that if there is at least a 599 // then prefer this chain. This ensures that if there is at least a
581 // valid path to a trust anchor, it's preferred over reporting an error. 600 // valid path to a trust anchor, it's preferred over reporting an error.
582 // - If the current chain is trusted, and the old chain is trusted, but 601 // - If the current chain is trusted, and the old chain is trusted, but
583 // the old chain contained weak algorithms while the current chain only 602 // the old chain contained weak algorithms while the current chain only
584 // contains strong algorithms, then prefer the current chain over the 603 // contains strong algorithms, then prefer the current chain over the
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 } 784 }
766 } 785 }
767 } 786 }
768 } 787 }
769 } 788 }
770 789
771 return OK; 790 return OK;
772 } 791 }
773 792
774 } // namespace net 793 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698