| OLD | NEW |
| 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" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 // ----------------------------------------------- | 30 // ----------------------------------------------- |
| 31 // Errors/Warnings set by VerifyCertificateChain | 31 // Errors/Warnings set by VerifyCertificateChain |
| 32 // ----------------------------------------------- | 32 // ----------------------------------------------- |
| 33 | 33 |
| 34 DEFINE_CERT_ERROR_ID( | 34 DEFINE_CERT_ERROR_ID( |
| 35 kSignatureAlgorithmMismatch, | 35 kSignatureAlgorithmMismatch, |
| 36 "Certificate.signatureAlgorithm != TBSCertificate.signature"); | 36 "Certificate.signatureAlgorithm != TBSCertificate.signature"); |
| 37 DEFINE_CERT_ERROR_ID(kInvalidOrUnsupportedSignatureAlgorithm, | 37 DEFINE_CERT_ERROR_ID(kInvalidOrUnsupportedSignatureAlgorithm, |
| 38 "Invalid or unsupported signature algorithm"); | 38 "Invalid or unsupported signature algorithm"); |
| 39 DEFINE_CERT_ERROR_ID(kChainIsEmpty, "Chain is empty"); | 39 DEFINE_CERT_ERROR_ID(kChainIsEmpty, "Chain is empty"); |
| 40 DEFINE_CERT_ERROR_ID(kChainIsLength1, |
| 41 "TODO: Cannot verify a chain of length 1"); |
| 40 DEFINE_CERT_ERROR_ID(kUnconsumedCriticalExtension, | 42 DEFINE_CERT_ERROR_ID(kUnconsumedCriticalExtension, |
| 41 "Unconsumed critical extension"); | 43 "Unconsumed critical extension"); |
| 42 DEFINE_CERT_ERROR_ID( | 44 DEFINE_CERT_ERROR_ID( |
| 43 kTargetCertInconsistentCaBits, | 45 kTargetCertInconsistentCaBits, |
| 44 "Target certificate looks like a CA but does not set all CA properties"); | 46 "Target certificate looks like a CA but does not set all CA properties"); |
| 45 DEFINE_CERT_ERROR_ID(kKeyCertSignBitNotSet, "keyCertSign bit is not set"); | 47 DEFINE_CERT_ERROR_ID(kKeyCertSignBitNotSet, "keyCertSign bit is not set"); |
| 46 DEFINE_CERT_ERROR_ID(kMaxPathLengthViolated, "max_path_length reached"); | 48 DEFINE_CERT_ERROR_ID(kMaxPathLengthViolated, "max_path_length reached"); |
| 47 DEFINE_CERT_ERROR_ID(kBasicConstraintsIndicatesNotCa, | 49 DEFINE_CERT_ERROR_ID(kBasicConstraintsIndicatesNotCa, |
| 48 "Basic Constraints indicates not a CA"); | 50 "Basic Constraints indicates not a CA"); |
| 49 DEFINE_CERT_ERROR_ID(kMissingBasicConstraints, | 51 DEFINE_CERT_ERROR_ID(kMissingBasicConstraints, |
| 50 "Does not have Basic Constraints"); | 52 "Does not have Basic Constraints"); |
| 51 DEFINE_CERT_ERROR_ID(kNotPermittedByNameConstraints, | 53 DEFINE_CERT_ERROR_ID(kNotPermittedByNameConstraints, |
| 52 "Not permitted by name constraints"); | 54 "Not permitted by name constraints"); |
| 53 DEFINE_CERT_ERROR_ID(kSubjectDoesNotMatchIssuer, | 55 DEFINE_CERT_ERROR_ID(kSubjectDoesNotMatchIssuer, |
| 54 "subject does not match issuer"); | 56 "subject does not match issuer"); |
| 55 DEFINE_CERT_ERROR_ID(kVerifySignedDataFailed, "VerifySignedData failed"); | 57 DEFINE_CERT_ERROR_ID(kVerifySignedDataFailed, "VerifySignedData failed"); |
| 56 DEFINE_CERT_ERROR_ID(kSignatureAlgorithmsDifferentEncoding, | 58 DEFINE_CERT_ERROR_ID(kSignatureAlgorithmsDifferentEncoding, |
| 57 "Certificate.signatureAlgorithm is encoded differently " | 59 "Certificate.signatureAlgorithm is encoded differently " |
| 58 "than TBSCertificate.signature"); | 60 "than TBSCertificate.signature"); |
| 59 DEFINE_CERT_ERROR_ID(kEkuLacksServerAuth, | 61 DEFINE_CERT_ERROR_ID(kEkuLacksServerAuth, |
| 60 "The extended key usage does not include server auth"); | 62 "The extended key usage does not include server auth"); |
| 61 DEFINE_CERT_ERROR_ID(kEkuLacksClientAuth, | 63 DEFINE_CERT_ERROR_ID(kEkuLacksClientAuth, |
| 62 "The extended key usage does not include client auth"); | 64 "The extended key usage does not include client auth"); |
| 65 DEFINE_CERT_ERROR_ID(kCertIsDistrusted, "Certificate is distrusted"); |
| 66 DEFINE_CERT_ERROR_ID(kCertIsNotTrustAnchor, |
| 67 "Certificate is not a trust anchor"); |
| 63 | 68 |
| 64 bool IsHandledCriticalExtensionOid(const der::Input& oid) { | 69 bool IsHandledCriticalExtensionOid(const der::Input& oid) { |
| 65 if (oid == BasicConstraintsOid()) | 70 if (oid == BasicConstraintsOid()) |
| 66 return true; | 71 return true; |
| 67 // Key Usage is NOT processed for end-entity certificates (this is the | 72 // Key Usage is NOT processed for end-entity certificates (this is the |
| 68 // responsibility of callers), however it is considered "handled" here in | 73 // responsibility of callers), however it is considered "handled" here in |
| 69 // order to allow being marked as critical. | 74 // order to allow being marked as critical. |
| 70 if (oid == KeyUsageOid()) | 75 if (oid == KeyUsageOid()) |
| 71 return true; | 76 return true; |
| 72 if (oid == ExtKeyUsageOid()) | 77 if (oid == ExtKeyUsageOid()) |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 VerifyNoUnconsumedCriticalExtensions(cert, errors); | 437 VerifyNoUnconsumedCriticalExtensions(cert, errors); |
| 433 | 438 |
| 434 // TODO(eroman): Step g is omitted, as policy constraints are not yet | 439 // TODO(eroman): Step g is omitted, as policy constraints are not yet |
| 435 // implemented. | 440 // implemented. |
| 436 | 441 |
| 437 // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", | 442 // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", |
| 438 // however is implied by RFC 5280 section 4.2.1.9. | 443 // however is implied by RFC 5280 section 4.2.1.9. |
| 439 VerifyTargetCertHasConsistentCaBits(cert, errors); | 444 VerifyTargetCertHasConsistentCaBits(cert, errors); |
| 440 } | 445 } |
| 441 | 446 |
| 442 // Initializes the path validation algorithm given anchor constraints. This | 447 // Enforces trust anchor constraints compatibile with RFC 5937. |
| 443 // follows the description in RFC 5937 | 448 // |
| 444 void ProcessTrustAnchorConstraints( | 449 // Note that the anchor constraints are encoded via the attached certificate |
| 445 const TrustAnchor& trust_anchor, | 450 // itself. |
| 451 void ApplyTrustAnchorConstraints( |
| 452 const ParsedCertificate& cert, |
| 446 KeyPurpose required_key_purpose, | 453 KeyPurpose required_key_purpose, |
| 447 size_t* max_path_length_ptr, | 454 size_t* max_path_length_ptr, |
| 448 std::vector<const NameConstraints*>* name_constraints_list, | 455 std::vector<const NameConstraints*>* name_constraints_list, |
| 449 CertErrors* errors) { | 456 CertErrors* errors) { |
| 450 // In RFC 5937 the enforcement of anchor constraints is governed by the input | |
| 451 // enforceTrustAnchorConstraints to path validation. In our implementation | |
| 452 // this is always on, and enforcement is controlled solely by whether or not | |
| 453 // the trust anchor specified constraints. | |
| 454 if (!trust_anchor.enforces_constraints()) | |
| 455 return; | |
| 456 | |
| 457 // Anchor constraints are encoded via the attached certificate. | |
| 458 const ParsedCertificate& cert = *trust_anchor.cert(); | |
| 459 | |
| 460 // This is not part of RFC 5937 nor RFC 5280, but matches the EKU handling | 457 // This is not part of RFC 5937 nor RFC 5280, but matches the EKU handling |
| 461 // done for intermediates (described in Web PKI's Baseline Requirements). | 458 // done for intermediates (described in Web PKI's Baseline Requirements). |
| 462 VerifyExtendedKeyUsage(cert, required_key_purpose, errors); | 459 VerifyExtendedKeyUsage(cert, required_key_purpose, errors); |
| 463 | 460 |
| 464 // The following enforcements follow from RFC 5937 (primarily section 3.2): | 461 // The following enforcements follow from RFC 5937 (primarily section 3.2): |
| 465 | 462 |
| 466 // Initialize name constraints initial-permitted/excluded-subtrees. | 463 // Initialize name constraints initial-permitted/excluded-subtrees. |
| 467 if (cert.has_name_constraints()) | 464 if (cert.has_name_constraints()) |
| 468 name_constraints_list->push_back(&cert.name_constraints()); | 465 name_constraints_list->push_back(&cert.name_constraints()); |
| 469 | 466 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 491 *max_path_length_ptr = cert.basic_constraints().path_len; | 488 *max_path_length_ptr = cert.basic_constraints().path_len; |
| 492 | 489 |
| 493 // From RFC 5937 section 2: | 490 // From RFC 5937 section 2: |
| 494 // | 491 // |
| 495 // Extensions may be marked critical or not critical. When trust anchor | 492 // Extensions may be marked critical or not critical. When trust anchor |
| 496 // constraints are enforced, clients MUST reject certification paths | 493 // constraints are enforced, clients MUST reject certification paths |
| 497 // containing a trust anchor with unrecognized critical extensions. | 494 // containing a trust anchor with unrecognized critical extensions. |
| 498 VerifyNoUnconsumedCriticalExtensions(cert, errors); | 495 VerifyNoUnconsumedCriticalExtensions(cert, errors); |
| 499 } | 496 } |
| 500 | 497 |
| 498 // Initializes the path validation algorithm given anchor constraints. This |
| 499 // follows the description in RFC 5937 |
| 500 void ProcessRootCertificate( |
| 501 const ParsedCertificate& cert, |
| 502 const CertificateTrust& trust, |
| 503 KeyPurpose required_key_purpose, |
| 504 size_t* max_path_length_ptr, |
| 505 std::vector<const NameConstraints*>* name_constraints_list, |
| 506 der::Input* working_spki, |
| 507 der::Input* working_normalized_issuer_name, |
| 508 CertErrors* errors) { |
| 509 // Use the certificate's SPKI and subject when verifying the next certificate. |
| 510 // Note this is initialized even in the case of untrusted roots (they already |
| 511 // emit an error for the distrust). |
| 512 *working_spki = cert.tbs().spki_tlv; |
| 513 *working_normalized_issuer_name = cert.normalized_subject(); |
| 514 |
| 515 switch (trust.type) { |
| 516 case CertificateTrustType::UNSPECIFIED: |
| 517 // Doesn't chain to a trust anchor - implicitly distrusted |
| 518 errors->AddError(kCertIsNotTrustAnchor); |
| 519 break; |
| 520 case CertificateTrustType::DISTRUSTED: |
| 521 // Chains to an actively distrusted certificate. |
| 522 // |
| 523 // TODO(eroman): There are not currently any verification or path building |
| 524 // tests for the distrusted case. |
| 525 errors->AddError(kCertIsDistrusted); |
| 526 break; |
| 527 case CertificateTrustType::TRUSTED_ANCHOR: |
| 528 case CertificateTrustType::TRUSTED_ANCHOR_WITH_CONSTRAINTS: |
| 529 // If the trust anchor has constraints, enforce them. |
| 530 if (trust.type == CertificateTrustType::TRUSTED_ANCHOR_WITH_CONSTRAINTS) { |
| 531 ApplyTrustAnchorConstraints(cert, required_key_purpose, |
| 532 max_path_length_ptr, name_constraints_list, |
| 533 errors); |
| 534 } |
| 535 break; |
| 536 } |
| 537 } |
| 538 |
| 539 } // namespace |
| 540 |
| 501 // This implementation is structured to mimic the description of certificate | 541 // This implementation is structured to mimic the description of certificate |
| 502 // path verification given by RFC 5280 section 6.1. | 542 // path verification given by RFC 5280 section 6.1. |
| 503 void VerifyCertificateChainNoReturnValue( | 543 void VerifyCertificateChain(const ParsedCertificateList& certs, |
| 504 const ParsedCertificateList& certs, | 544 const CertificateTrust& last_cert_trust, |
| 505 const TrustAnchor* trust_anchor, | 545 const SignaturePolicy* signature_policy, |
| 506 const SignaturePolicy* signature_policy, | 546 const der::GeneralizedTime& time, |
| 507 const der::GeneralizedTime& time, | 547 KeyPurpose required_key_purpose, |
| 508 KeyPurpose required_key_purpose, | 548 CertPathErrors* errors) { |
| 509 CertPathErrors* errors) { | |
| 510 DCHECK(trust_anchor); | |
| 511 DCHECK(signature_policy); | 549 DCHECK(signature_policy); |
| 512 DCHECK(errors); | 550 DCHECK(errors); |
| 513 | 551 |
| 514 // An empty chain is necessarily invalid. | 552 // An empty chain is necessarily invalid. |
| 515 if (certs.empty()) { | 553 if (certs.empty()) { |
| 516 errors->GetOtherErrors()->AddError(kChainIsEmpty); | 554 errors->GetOtherErrors()->AddError(kChainIsEmpty); |
| 517 return; | 555 return; |
| 518 } | 556 } |
| 519 | 557 |
| 558 // TODO(eroman): Verifying a trusted leaf certificate is not currently |
| 559 // permitted. |
| 560 if (certs.size() == 1) { |
| 561 errors->GetOtherErrors()->AddError(kChainIsLength1); |
| 562 return; |
| 563 } |
| 564 |
| 520 // Will contain a NameConstraints for each previous cert in the chain which | 565 // Will contain a NameConstraints for each previous cert in the chain which |
| 521 // had nameConstraints. This corresponds to the permitted_subtrees and | 566 // had nameConstraints. This corresponds to the permitted_subtrees and |
| 522 // excluded_subtrees state variables from RFC 5280. | 567 // excluded_subtrees state variables from RFC 5280. |
| 523 std::vector<const NameConstraints*> name_constraints_list; | 568 std::vector<const NameConstraints*> name_constraints_list; |
| 524 | 569 |
| 525 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: | 570 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: |
| 526 // * working_public_key | 571 // * working_public_key |
| 527 // * working_public_key_algorithm | 572 // * working_public_key_algorithm |
| 528 // * working_public_key_parameters | 573 // * working_public_key_parameters |
| 529 // | 574 // |
| 530 // They are combined for simplicity since the signature verification takes an | 575 // They are combined for simplicity since the signature verification takes an |
| 531 // SPKI, and the parameter inheritence is not applicable for the supported | 576 // SPKI, and the parameter inheritence is not applicable for the supported |
| 532 // key types. | 577 // key types. |
| 533 // | 578 // |
| 534 // An approximate explanation of |working_spki| is this description from RFC | 579 // An approximate explanation of |working_spki| is this description from RFC |
| 535 // 5280 section 6.1.2: | 580 // 5280 section 6.1.2: |
| 536 // | 581 // |
| 537 // working_public_key: the public key used to verify the | 582 // working_public_key: the public key used to verify the |
| 538 // signature of a certificate. | 583 // signature of a certificate. |
| 539 der::Input working_spki = trust_anchor->spki(); | 584 der::Input working_spki; |
| 540 | 585 |
| 541 // |working_normalized_issuer_name| is the normalized value of the | 586 // |working_normalized_issuer_name| is the normalized value of the |
| 542 // working_issuer_name variable in RFC 5280 section 6.1.2: | 587 // working_issuer_name variable in RFC 5280 section 6.1.2: |
| 543 // | 588 // |
| 544 // working_issuer_name: the issuer distinguished name expected | 589 // working_issuer_name: the issuer distinguished name expected |
| 545 // in the next certificate in the chain. | 590 // in the next certificate in the chain. |
| 546 der::Input working_normalized_issuer_name = | 591 der::Input working_normalized_issuer_name; |
| 547 trust_anchor->normalized_subject(); | |
| 548 | 592 |
| 549 // |max_path_length| corresponds with the same named variable in RFC 5280 | 593 // |max_path_length| corresponds with the same named variable in RFC 5280 |
| 550 // section 6.1.2: | 594 // section 6.1.2: |
| 551 // | 595 // |
| 552 // max_path_length: this integer is initialized to n, is | 596 // max_path_length: this integer is initialized to n, is |
| 553 // decremented for each non-self-issued certificate in the path, | 597 // decremented for each non-self-issued certificate in the path, |
| 554 // and may be reduced to the value in the path length constraint | 598 // and may be reduced to the value in the path length constraint |
| 555 // field within the basic constraints extension of a CA | 599 // field within the basic constraints extension of a CA |
| 556 // certificate. | 600 // certificate. |
| 557 size_t max_path_length = certs.size(); | 601 size_t max_path_length = certs.size(); |
| 558 | 602 |
| 559 // Apply any trust anchor constraints per RFC 5937. | 603 // Iterate over all the certificates in the reverse direction: starting from |
| 604 // the root certificate and progressing towards the target certificate. |
| 560 // | 605 // |
| 561 // TODO(eroman): Errors on the trust anchor are put into a certificate bucket | 606 // * i=0 : Root certificate (i.e. trust anchor) |
| 562 // GetErrorsForCert(certs.size()). This is a bit magical, and | 607 // * i=1 : Certificated signed by the root certificate |
| 563 // has some integration issues. | 608 // * i=certs.size()-1 : Target certificate. |
| 564 ProcessTrustAnchorConstraints(*trust_anchor, required_key_purpose, | |
| 565 &max_path_length, &name_constraints_list, | |
| 566 errors->GetErrorsForCert(certs.size())); | |
| 567 | |
| 568 // Iterate over all the certificates in the reverse direction: starting from | |
| 569 // the certificate signed by trust anchor and progressing towards the target | |
| 570 // certificate. | |
| 571 // | |
| 572 // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based. | |
| 573 // | |
| 574 // * i=0 : Certificated signed by trust anchor. | |
| 575 // * i=N-1 : Target certificate. | |
| 576 for (size_t i = 0; i < certs.size(); ++i) { | 609 for (size_t i = 0; i < certs.size(); ++i) { |
| 577 const size_t index_into_certs = certs.size() - i - 1; | 610 const size_t index_into_certs = certs.size() - i - 1; |
| 578 | 611 |
| 579 // |is_target_cert| is true if the current certificate is the target | 612 // |is_target_cert| is true if the current certificate is the target |
| 580 // certificate being verified. The target certificate isn't necessarily an | 613 // certificate being verified. The target certificate isn't necessarily an |
| 581 // end-entity certificate. | 614 // end-entity certificate. |
| 582 const bool is_target_cert = index_into_certs == 0; | 615 const bool is_target_cert = index_into_certs == 0; |
| 616 const bool is_root_cert = i == 0; |
| 583 | 617 |
| 584 const ParsedCertificate& cert = *certs[index_into_certs]; | 618 const ParsedCertificate& cert = *certs[index_into_certs]; |
| 585 | 619 |
| 586 // Output errors for the current certificate into an error bucket that is | 620 // Output errors for the current certificate into an error bucket that is |
| 587 // associated with that certificate. | 621 // associated with that certificate. |
| 588 CertErrors* cert_errors = errors->GetErrorsForCert(index_into_certs); | 622 CertErrors* cert_errors = errors->GetErrorsForCert(index_into_certs); |
| 589 | 623 |
| 624 if (is_root_cert) { |
| 625 ProcessRootCertificate(cert, last_cert_trust, required_key_purpose, |
| 626 &max_path_length, &name_constraints_list, |
| 627 &working_spki, &working_normalized_issuer_name, |
| 628 cert_errors); |
| 629 |
| 630 // Don't do any other checks for root certificates. |
| 631 continue; |
| 632 } |
| 633 |
| 590 // Per RFC 5280 section 6.1: | 634 // Per RFC 5280 section 6.1: |
| 591 // * Do basic processing for each certificate | 635 // * Do basic processing for each certificate |
| 592 // * If it is the last certificate in the path (target certificate) | 636 // * If it is the last certificate in the path (target certificate) |
| 593 // - Then run "Wrap up" | 637 // - Then run "Wrap up" |
| 594 // - Otherwise run "Prepare for Next cert" | 638 // - Otherwise run "Prepare for Next cert" |
| 595 BasicCertificateProcessing(cert, is_target_cert, signature_policy, time, | 639 BasicCertificateProcessing(cert, is_target_cert, signature_policy, time, |
| 596 working_spki, working_normalized_issuer_name, | 640 working_spki, working_normalized_issuer_name, |
| 597 name_constraints_list, cert_errors); | 641 name_constraints_list, cert_errors); |
| 598 | 642 |
| 599 // The key purpose is checked not just for the end-entity certificate, but | 643 // The key purpose is checked not just for the end-entity certificate, but |
| (...skipping 10 matching lines...) Expand all Loading... |
| 610 WrapUp(cert, cert_errors); | 654 WrapUp(cert, cert_errors); |
| 611 } | 655 } |
| 612 } | 656 } |
| 613 | 657 |
| 614 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: | 658 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: |
| 615 // | 659 // |
| 616 // A certificate MUST NOT appear more than once in a prospective | 660 // A certificate MUST NOT appear more than once in a prospective |
| 617 // certification path. | 661 // certification path. |
| 618 } | 662 } |
| 619 | 663 |
| 620 } // namespace | |
| 621 | |
| 622 bool VerifyCertificateChain(const ParsedCertificateList& certs, | |
| 623 const TrustAnchor* trust_anchor, | |
| 624 const SignaturePolicy* signature_policy, | |
| 625 const der::GeneralizedTime& time, | |
| 626 KeyPurpose required_key_purpose, | |
| 627 CertPathErrors* errors) { | |
| 628 // TODO(eroman): This function requires that |errors| is empty upon entry, | |
| 629 // which is not part of the API contract. | |
| 630 DCHECK(!errors->ContainsHighSeverityErrors()); | |
| 631 VerifyCertificateChainNoReturnValue(certs, trust_anchor, signature_policy, | |
| 632 time, required_key_purpose, errors); | |
| 633 return !errors->ContainsHighSeverityErrors(); | |
| 634 } | |
| 635 | |
| 636 } // namespace net | 664 } // namespace net |
| OLD | NEW |