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

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

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

Powered by Google App Engine
This is Rietveld 408576698