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 |