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

Side by Side Diff: net/cert/internal/verify_certificate_chain.cc

Issue 2329593002: Add optional context for certificate errors. (Closed)
Patch Set: wrap long comment line Created 4 years, 3 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/internal/verify_certificate_chain.h" 5 #include "net/cert/internal/verify_certificate_chain.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h"
11 #include "net/cert/internal/cert_error_params.h"
12 #include "net/cert/internal/cert_error_scoper.h"
10 #include "net/cert/internal/cert_errors.h" 13 #include "net/cert/internal/cert_errors.h"
11 #include "net/cert/internal/name_constraints.h" 14 #include "net/cert/internal/name_constraints.h"
12 #include "net/cert/internal/parse_certificate.h" 15 #include "net/cert/internal/parse_certificate.h"
13 #include "net/cert/internal/signature_algorithm.h" 16 #include "net/cert/internal/signature_algorithm.h"
14 #include "net/cert/internal/signature_policy.h" 17 #include "net/cert/internal/signature_policy.h"
15 #include "net/cert/internal/trust_store.h" 18 #include "net/cert/internal/trust_store.h"
16 #include "net/cert/internal/verify_signed_data.h" 19 #include "net/cert/internal/verify_signed_data.h"
17 #include "net/der/input.h" 20 #include "net/der/input.h"
18 #include "net/der/parser.h" 21 #include "net/der/parser.h"
19 22
20 namespace net { 23 namespace net {
21 24
22 using namespace verify_certificate_chain_errors; 25 using namespace verify_certificate_chain_errors;
23 26
24 namespace { 27 namespace {
25 28
29 DEFINE_CERT_ERROR_ID(kContextTrustAnchor, "Processing Trust Anchor");
30 DEFINE_CERT_ERROR_ID(kContextCertificate, "Processing Certificate");
31
32 class ScopedCertificateContext : public CertErrorScoper {
33 public:
34 ScopedCertificateContext(CertErrors* parent_errors, size_t index)
35 : CertErrorScoper(parent_errors), index_(index) {}
36
37 std::unique_ptr<CertErrorNode> BuildRootNode() override {
38 return base::MakeUnique<CertErrorNode>(
39 CertErrorNodeType::TYPE_CONTEXT, kContextCertificate,
40 CreateCertErrorParamsSizeT("index", index_));
41 }
42
43 private:
44 size_t index_;
45 };
46
26 // Returns true if the certificate does not contain any unconsumed _critical_ 47 // Returns true if the certificate does not contain any unconsumed _critical_
27 // extensions. 48 // extensions.
28 WARN_UNUSED_RESULT bool VerifyNoUnconsumedCriticalExtensions( 49 WARN_UNUSED_RESULT bool VerifyNoUnconsumedCriticalExtensions(
29 const ParsedCertificate& cert, 50 const ParsedCertificate& cert,
30 CertErrors* errors) { 51 CertErrors* errors) {
31 bool has_unconsumed_critical_extensions = false; 52 bool has_unconsumed_critical_extensions = false;
32 53
33 for (const auto& entry : cert.unparsed_extensions()) { 54 for (const auto& entry : cert.unparsed_extensions()) {
34 if (entry.second.critical) { 55 if (entry.second.critical) {
35 has_unconsumed_critical_extensions = true; 56 has_unconsumed_critical_extensions = true;
36 errors->AddWith2DerParams(kUnconsumedCriticalExtension, entry.second.oid, 57 errors->AddError(kUnconsumedCriticalExtension,
37 entry.second.value); 58 CreateCertErrorParams2Der("oid", entry.second.oid,
59 "value", entry.second.value));
38 } 60 }
39 } 61 }
40 62
41 return !has_unconsumed_critical_extensions; 63 return !has_unconsumed_critical_extensions;
42 } 64 }
43 65
44 // Returns true if |cert| was self-issued. The definition of self-issuance 66 // Returns true if |cert| was self-issued. The definition of self-issuance
45 // comes from RFC 5280 section 6.1: 67 // comes from RFC 5280 section 6.1:
46 // 68 //
47 // A certificate is self-issued if the same DN appears in the subject 69 // A certificate is self-issued if the same DN appears in the subject
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 const der::Input& alg2_tlv = cert.tbs().signature_algorithm_tlv; 139 const der::Input& alg2_tlv = cert.tbs().signature_algorithm_tlv;
118 140
119 // Ensure that the two DER-encoded signature algorithms are byte-for-byte 141 // Ensure that the two DER-encoded signature algorithms are byte-for-byte
120 // equal. 142 // equal.
121 if (alg1_tlv == alg2_tlv) 143 if (alg1_tlv == alg2_tlv)
122 return true; 144 return true;
123 145
124 // But make a compatibility concession for RSA with SHA1. 146 // But make a compatibility concession for RSA with SHA1.
125 if (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) && 147 if (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) &&
126 IsRsaWithSha1SignatureAlgorithm(alg2_tlv)) { 148 IsRsaWithSha1SignatureAlgorithm(alg2_tlv)) {
127 errors->AddWith2DerParams(kSignatureAlgorithmsDifferentEncoding, alg1_tlv, 149 errors->AddWarning(
128 alg2_tlv); 150 kSignatureAlgorithmsDifferentEncoding,
151 CreateCertErrorParams2Der("Certificate.algorithm", alg1_tlv,
152 "TBSCertificate.signature", alg2_tlv));
129 return true; 153 return true;
130 } 154 }
131 155
132 errors->AddWith2DerParams(kSignatureAlgorithmMismatch, alg1_tlv, alg2_tlv); 156 errors->AddError(
157 kSignatureAlgorithmMismatch,
158 CreateCertErrorParams2Der("Certificate.algorithm", alg1_tlv,
159 "TBSCertificate.signature", alg2_tlv));
133 160
134 return false; 161 return false;
135 } 162 }
136 163
137 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate 164 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate
138 // Processing" procedure. 165 // Processing" procedure.
139 WARN_UNUSED_RESULT bool BasicCertificateProcessing( 166 WARN_UNUSED_RESULT bool BasicCertificateProcessing(
140 const ParsedCertificate& cert, 167 const ParsedCertificate& cert,
141 bool is_target_cert, 168 bool is_target_cert,
142 const SignaturePolicy* signature_policy, 169 const SignaturePolicy* signature_policy,
143 const der::GeneralizedTime& time, 170 const der::GeneralizedTime& time,
144 const der::Input& working_spki, 171 const der::Input& working_spki,
145 const der::Input& working_normalized_issuer_name, 172 const der::Input& working_normalized_issuer_name,
146 const std::vector<const NameConstraints*>& name_constraints_list, 173 const std::vector<const NameConstraints*>& name_constraints_list,
147 CertErrors* errors) { 174 CertErrors* errors) {
148 // Check that the signature algorithms in Certificate vs TBSCertificate 175 // Check that the signature algorithms in Certificate vs TBSCertificate
149 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by 176 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by
150 // sections 4.1.1.2 and 4.1.2.3. 177 // sections 4.1.1.2 and 4.1.2.3.
151 if (!VerifySignatureAlgorithmsMatch(cert, errors)) 178 if (!VerifySignatureAlgorithmsMatch(cert, errors))
152 return false; 179 return false;
153 180
154 // Verify the digital signature using the previous certificate's key (RFC 181 // Verify the digital signature using the previous certificate's key (RFC
155 // 5280 section 6.1.3 step a.1). 182 // 5280 section 6.1.3 step a.1).
156 if (!cert.has_valid_supported_signature_algorithm()) { 183 if (!cert.has_valid_supported_signature_algorithm()) {
157 errors->AddWith1DerParam(kInvalidOrUnsupportedAlgorithm, 184 errors->AddError(
158 cert.signature_algorithm_tlv()); 185 kInvalidOrUnsupportedSignatureAlgorithm,
186 CreateCertErrorParams1Der("algorithm", cert.signature_algorithm_tlv()));
159 return false; 187 return false;
160 } 188 }
161 189
162 if (!VerifySignedData(cert.signature_algorithm(), cert.tbs_certificate_tlv(), 190 if (!VerifySignedData(cert.signature_algorithm(), cert.tbs_certificate_tlv(),
163 cert.signature_value(), working_spki, signature_policy, 191 cert.signature_value(), working_spki, signature_policy,
164 errors)) { 192 errors)) {
165 errors->Add(kVerifySignedDataFailed); 193 errors->Add(kVerifySignedDataFailed);
166 return false; 194 return false;
167 } 195 }
168 196
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 } 415 }
388 416
389 // Initializes the path validation algorithm given anchor constraints. This 417 // Initializes the path validation algorithm given anchor constraints. This
390 // follows the description in RFC 5937 418 // follows the description in RFC 5937
391 WARN_UNUSED_RESULT bool ProcessTrustAnchorConstraints( 419 WARN_UNUSED_RESULT bool ProcessTrustAnchorConstraints(
392 const TrustAnchor& trust_anchor, 420 const TrustAnchor& trust_anchor,
393 size_t* max_path_length_ptr, 421 size_t* max_path_length_ptr,
394 std::vector<const NameConstraints*>* name_constraints_list, 422 std::vector<const NameConstraints*>* name_constraints_list,
395 CertErrors* errors) { 423 CertErrors* errors) {
396 // Set the trust anchor as the current context for any subsequent errors. 424 // Set the trust anchor as the current context for any subsequent errors.
397 ScopedCertErrorsTrustAnchorContext error_context(errors, &trust_anchor); 425 CertErrorScoperNoParams error_context(errors, kContextTrustAnchor);
mattm 2016/09/12 22:26:39 nit, but the naming style mismatch between CertErr
eroman 2016/09/12 23:04:35 Done.
398 426
399 // In RFC 5937 the enforcement of anchor constraints is governed by the input 427 // In RFC 5937 the enforcement of anchor constraints is governed by the input
400 // enforceTrustAnchorConstraints to path validation. In our implementation 428 // enforceTrustAnchorConstraints to path validation. In our implementation
401 // this is always on, and enforcement is controlled solely by whether or not 429 // this is always on, and enforcement is controlled solely by whether or not
402 // the trust anchor specified constraints. 430 // the trust anchor specified constraints.
403 if (!trust_anchor.enforces_constraints()) 431 if (!trust_anchor.enforces_constraints())
404 return true; 432 return true;
405 433
406 // Anchor constraints are encoded via the attached certificate. 434 // Anchor constraints are encoded via the attached certificate.
407 const ParsedCertificate& cert = *trust_anchor.cert(); 435 const ParsedCertificate& cert = *trust_anchor.cert();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 const size_t index_into_certs = certs.size() - i - 1; 550 const size_t index_into_certs = certs.size() - i - 1;
523 551
524 // |is_target_cert| is true if the current certificate is the target 552 // |is_target_cert| is true if the current certificate is the target
525 // certificate being verified. The target certificate isn't necessarily an 553 // certificate being verified. The target certificate isn't necessarily an
526 // end-entity certificate. 554 // end-entity certificate.
527 const bool is_target_cert = index_into_certs == 0; 555 const bool is_target_cert = index_into_certs == 0;
528 556
529 const ParsedCertificate& cert = *certs[index_into_certs]; 557 const ParsedCertificate& cert = *certs[index_into_certs];
530 558
531 // Set the current certificate as the context for any subsequent errors. 559 // Set the current certificate as the context for any subsequent errors.
532 ScopedCertErrorsCertContext error_context(errors, &cert, i); 560 ScopedCertificateContext error_context(errors, i);
533 561
534 // Per RFC 5280 section 6.1: 562 // Per RFC 5280 section 6.1:
535 // * Do basic processing for each certificate 563 // * Do basic processing for each certificate
536 // * If it is the last certificate in the path (target certificate) 564 // * If it is the last certificate in the path (target certificate)
537 // - Then run "Wrap up" 565 // - Then run "Wrap up"
538 // - Otherwise run "Prepare for Next cert" 566 // - Otherwise run "Prepare for Next cert"
539 if (!BasicCertificateProcessing( 567 if (!BasicCertificateProcessing(
540 cert, is_target_cert, signature_policy, time, working_spki, 568 cert, is_target_cert, signature_policy, time, working_spki,
541 working_normalized_issuer_name, name_constraints_list, errors)) { 569 working_normalized_issuer_name, name_constraints_list, errors)) {
542 return false; 570 return false;
(...skipping 13 matching lines...) Expand all
556 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: 584 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1:
557 // 585 //
558 // A certificate MUST NOT appear more than once in a prospective 586 // A certificate MUST NOT appear more than once in a prospective
559 // certification path. 587 // certification path.
560 588
561 return true; 589 return true;
562 } 590 }
563 591
564 namespace verify_certificate_chain_errors { 592 namespace verify_certificate_chain_errors {
565 593
566 DEFINE_CERT_ERROR_TYPE( 594 DEFINE_CERT_ERROR_ID(
567 kSignatureAlgorithmMismatch, 595 kSignatureAlgorithmMismatch,
568 "Certificate.signatureAlgorithm != TBSCertificate.signature"); 596 "Certificate.signatureAlgorithm != TBSCertificate.signature");
569 DEFINE_CERT_ERROR_TYPE(kInvalidOrUnsupportedAlgorithm, 597 DEFINE_CERT_ERROR_ID(kInvalidOrUnsupportedSignatureAlgorithm,
570 "Invalid or unsupported signature algorithm"); 598 "Invalid or unsupported signature algorithm");
571 DEFINE_CERT_ERROR_TYPE(kChainIsEmpty, "Chain is empty"); 599 DEFINE_CERT_ERROR_ID(kChainIsEmpty, "Chain is empty");
572 DEFINE_CERT_ERROR_TYPE(kUnconsumedCriticalExtension, 600 DEFINE_CERT_ERROR_ID(kUnconsumedCriticalExtension,
573 "Unconsumed critical extension"); 601 "Unconsumed critical extension");
574 DEFINE_CERT_ERROR_TYPE( 602 DEFINE_CERT_ERROR_ID(
575 kTargetCertInconsistentCaBits, 603 kTargetCertInconsistentCaBits,
576 "Target certificate looks like a CA but does not set all CA properties"); 604 "Target certificate looks like a CA but does not set all CA properties");
577 DEFINE_CERT_ERROR_TYPE(kKeyCertSignBitNotSet, "keyCertSign bit is not set"); 605 DEFINE_CERT_ERROR_ID(kKeyCertSignBitNotSet, "keyCertSign bit is not set");
578 DEFINE_CERT_ERROR_TYPE(kMaxPathLengthViolated, "max_path_length reached"); 606 DEFINE_CERT_ERROR_ID(kMaxPathLengthViolated, "max_path_length reached");
579 DEFINE_CERT_ERROR_TYPE(kBasicConstraintsIndicatesNotCa, 607 DEFINE_CERT_ERROR_ID(kBasicConstraintsIndicatesNotCa,
580 "Basic Constraints indicates not a CA"); 608 "Basic Constraints indicates not a CA");
581 DEFINE_CERT_ERROR_TYPE(kMissingBasicConstraints, 609 DEFINE_CERT_ERROR_ID(kMissingBasicConstraints,
582 "Does not have Basic Constraints"); 610 "Does not have Basic Constraints");
583 DEFINE_CERT_ERROR_TYPE(kNotPermittedByNameConstraints, 611 DEFINE_CERT_ERROR_ID(kNotPermittedByNameConstraints,
584 "Not permitted by name constraints"); 612 "Not permitted by name constraints");
585 DEFINE_CERT_ERROR_TYPE(kSubjectDoesNotMatchIssuer, 613 DEFINE_CERT_ERROR_ID(kSubjectDoesNotMatchIssuer,
586 "subject does not match issuer"); 614 "subject does not match issuer");
587 DEFINE_CERT_ERROR_TYPE(kVerifySignedDataFailed, "VerifySignedData failed"); 615 DEFINE_CERT_ERROR_ID(kVerifySignedDataFailed, "VerifySignedData failed");
588 DEFINE_CERT_ERROR_TYPE(kValidityFailedNotAfter, "Time is after notAfter"); 616 DEFINE_CERT_ERROR_ID(kValidityFailedNotAfter, "Time is after notAfter");
589 DEFINE_CERT_ERROR_TYPE(kValidityFailedNotBefore, "Time is before notBefore"); 617 DEFINE_CERT_ERROR_ID(kValidityFailedNotBefore, "Time is before notBefore");
590 DEFINE_CERT_ERROR_TYPE(kSignatureAlgorithmsDifferentEncoding, 618 DEFINE_CERT_ERROR_ID(kSignatureAlgorithmsDifferentEncoding,
591 "Certificate.signatureAlgorithm is encoded differently " 619 "Certificate.signatureAlgorithm is encoded differently "
592 "than TBSCertificate.signature"); 620 "than TBSCertificate.signature");
593 621
594 } // verify_certificate_chain_errors 622 } // verify_certificate_chain_errors
595 623
596 } // namespace net 624 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698