| 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 "net/cert/internal/name_constraints.h" | 10 #include "net/cert/internal/name_constraints.h" |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 // to the rules specified in Section 7.1). In general, the issuer and | 191 // to the rules specified in Section 7.1). In general, the issuer and |
| 192 // subject of the certificates that make up a path are different for | 192 // subject of the certificates that make up a path are different for |
| 193 // each certificate. However, a CA may issue a certificate to itself to | 193 // each certificate. However, a CA may issue a certificate to itself to |
| 194 // support key rollover or changes in certificate policies. These | 194 // support key rollover or changes in certificate policies. These |
| 195 // self-issued certificates are not counted when evaluating path length | 195 // self-issued certificates are not counted when evaluating path length |
| 196 // or name constraints. | 196 // or name constraints. |
| 197 WARN_UNUSED_RESULT bool IsSelfIssued(const FullyParsedCert& cert) { | 197 WARN_UNUSED_RESULT bool IsSelfIssued(const FullyParsedCert& cert) { |
| 198 return NameMatches(cert.tbs.subject_tlv, cert.tbs.issuer_tlv); | 198 return NameMatches(cert.tbs.subject_tlv, cert.tbs.issuer_tlv); |
| 199 } | 199 } |
| 200 | 200 |
| 201 // Finds a trust anchor that matches |name| in |trust_store| or returns | |
| 202 // nullptr. The returned pointer references data in |trust_store|. | |
| 203 // | |
| 204 // TODO(eroman): This implementation is linear in the size of the trust store, | |
| 205 // and also presumes that all names are unique. In practice it is possible to | |
| 206 // have multiple SPKIs with the same name. Also this mechanism of | |
| 207 // searching is fairly primitive, and does not take advantage of other | |
| 208 // properties like the authority key id. | |
| 209 WARN_UNUSED_RESULT const TrustAnchor* FindTrustAnchorByName( | |
| 210 const TrustStore& trust_store, | |
| 211 const der::Input& name) { | |
| 212 for (const auto& anchor : trust_store.anchors) { | |
| 213 if (NameMatches(name, der::Input(&anchor.name))) | |
| 214 return &anchor; | |
| 215 } | |
| 216 return nullptr; | |
| 217 } | |
| 218 | |
| 219 // Returns true if |cert| is valid at time |time|. | 201 // Returns true if |cert| is valid at time |time|. |
| 220 // | 202 // |
| 221 // The certificate's validity requirements are described by RFC 5280 section | 203 // The certificate's validity requirements are described by RFC 5280 section |
| 222 // 4.1.2.5: | 204 // 4.1.2.5: |
| 223 // | 205 // |
| 224 // The validity period for a certificate is the period of time from | 206 // The validity period for a certificate is the period of time from |
| 225 // notBefore through notAfter, inclusive. | 207 // notBefore through notAfter, inclusive. |
| 226 WARN_UNUSED_RESULT bool VerifyTimeValidity(const FullyParsedCert& cert, | 208 WARN_UNUSED_RESULT bool VerifyTimeValidity(const FullyParsedCert& cert, |
| 227 const der::GeneralizedTime time) { | 209 const der::GeneralizedTime time) { |
| 228 return !(time < cert.tbs.validity_not_before) && | 210 return !(time < cert.tbs.validity_not_before) && |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 const der::Input& alg2_tlv = cert.tbs.signature_algorithm_tlv; | 248 const der::Input& alg2_tlv = cert.tbs.signature_algorithm_tlv; |
| 267 | 249 |
| 268 // Ensure that the two DER-encoded signature algorithms are byte-for-byte | 250 // Ensure that the two DER-encoded signature algorithms are byte-for-byte |
| 269 // equal, but make a compatibility concession for RSA with SHA1. | 251 // equal, but make a compatibility concession for RSA with SHA1. |
| 270 return alg1_tlv == alg2_tlv || (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) && | 252 return alg1_tlv == alg2_tlv || (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) && |
| 271 IsRsaWithSha1SignatureAlgorithm(alg2_tlv)); | 253 IsRsaWithSha1SignatureAlgorithm(alg2_tlv)); |
| 272 } | 254 } |
| 273 | 255 |
| 274 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate | 256 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate |
| 275 // Processing" procedure. | 257 // Processing" procedure. |
| 258 // |
| 259 // |skip_issuer_checks| controls whether the function will skip: |
| 260 // - Checking that |cert|'s signature using |working_spki| |
| 261 // - Checkinging that |cert|'s issuer matches |working_issuer_name| |
| 262 // This should be set to true only when verifying a trusted root certificate. |
| 276 WARN_UNUSED_RESULT bool BasicCertificateProcessing( | 263 WARN_UNUSED_RESULT bool BasicCertificateProcessing( |
| 277 const FullyParsedCert& cert, | 264 const FullyParsedCert& cert, |
| 278 bool is_target_cert, | 265 bool is_target_cert, |
| 266 bool skip_issuer_checks, |
| 279 const SignaturePolicy* signature_policy, | 267 const SignaturePolicy* signature_policy, |
| 280 const der::GeneralizedTime& time, | 268 const der::GeneralizedTime& time, |
| 281 const der::Input& working_spki, | 269 const der::Input& working_spki, |
| 282 const der::Input& working_issuer_name, | 270 const der::Input& working_issuer_name, |
| 283 const std::vector<std::unique_ptr<NameConstraints>>& | 271 const std::vector<std::unique_ptr<NameConstraints>>& |
| 284 name_constraints_list) { | 272 name_constraints_list) { |
| 285 // Check that the signature algorithms in Certificate vs TBSCertificate | 273 // Check that the signature algorithms in Certificate vs TBSCertificate |
| 286 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by | 274 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by |
| 287 // sections 4.1.1.2 and 4.1.2.3. | 275 // sections 4.1.1.2 and 4.1.2.3. |
| 288 if (!VerifySignatureAlgorithmsMatch(cert)) | 276 if (!VerifySignatureAlgorithmsMatch(cert)) |
| 289 return false; | 277 return false; |
| 290 | 278 |
| 291 // Verify the digital signature using the previous certificate's (or trust | 279 // Verify the digital signature using the previous certificate's key (RFC |
| 292 // anchor's) key (RFC 5280 section 6.1.3 step a.1). | 280 // 5280 section 6.1.3 step a.1). |
| 293 if (!VerifySignedData( | 281 if (!skip_issuer_checks) { |
| 294 *cert.signature_algorithm, cert.cert.tbs_certificate_tlv, | 282 if (!VerifySignedData( |
| 295 cert.cert.signature_value, working_spki, signature_policy)) { | 283 *cert.signature_algorithm, cert.cert.tbs_certificate_tlv, |
| 296 return false; | 284 cert.cert.signature_value, working_spki, signature_policy)) { |
| 285 return false; |
| 286 } |
| 297 } | 287 } |
| 298 | 288 |
| 299 // Check the time range for the certificate's validity, ensuring it is valid | 289 // Check the time range for the certificate's validity, ensuring it is valid |
| 300 // at |time|. | 290 // at |time|. |
| 301 // (RFC 5280 section 6.1.3 step a.2) | 291 // (RFC 5280 section 6.1.3 step a.2) |
| 302 if (!VerifyTimeValidity(cert, time)) | 292 if (!VerifyTimeValidity(cert, time)) |
| 303 return false; | 293 return false; |
| 304 | 294 |
| 305 // TODO(eroman): Check revocation (RFC 5280 section 6.1.3 step a.3) | 295 // TODO(eroman): Check revocation (RFC 5280 section 6.1.3 step a.3) |
| 306 | 296 |
| 307 // Verify the certificate's issuer name matches the issuing certificate's (or | 297 // Verify the certificate's issuer name matches the issuing certificate's |
| 308 // trust anchor's) subject name. (RFC 5280 section 6.1.3 step a.4) | 298 // subject name. (RFC 5280 section 6.1.3 step a.4) |
| 309 if (!NameMatches(cert.tbs.issuer_tlv, working_issuer_name)) | 299 if (!skip_issuer_checks) { |
| 310 return false; | 300 if (!NameMatches(cert.tbs.issuer_tlv, working_issuer_name)) |
| 301 return false; |
| 302 } |
| 311 | 303 |
| 312 // Name constraints (RFC 5280 section 6.1.3 step b & c) | 304 // Name constraints (RFC 5280 section 6.1.3 step b & c) |
| 313 // If certificate i is self-issued and it is not the final certificate in the | 305 // If certificate i is self-issued and it is not the final certificate in the |
| 314 // path, skip this step for certificate i. | 306 // path, skip this step for certificate i. |
| 315 if (!name_constraints_list.empty() && | 307 if (!name_constraints_list.empty() && |
| 316 (!IsSelfIssued(cert) || is_target_cert)) { | 308 (!IsSelfIssued(cert) || is_target_cert)) { |
| 317 der::Input subject_value; | 309 der::Input subject_value; |
| 318 if (!GetSequenceValue(cert.tbs.subject_tlv, &subject_value)) | 310 if (!GetSequenceValue(cert.tbs.subject_tlv, &subject_value)) |
| 319 return false; | 311 return false; |
| 320 for (const auto& nc : name_constraints_list) { | 312 for (const auto& nc : name_constraints_list) { |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", | 487 // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", |
| 496 // however is implied by RFC 5280 section 4.2.1.9. | 488 // however is implied by RFC 5280 section 4.2.1.9. |
| 497 if (!VerifyTargetCertHasConsistentCaBits(cert)) | 489 if (!VerifyTargetCertHasConsistentCaBits(cert)) |
| 498 return false; | 490 return false; |
| 499 | 491 |
| 500 return true; | 492 return true; |
| 501 } | 493 } |
| 502 | 494 |
| 503 } // namespace | 495 } // namespace |
| 504 | 496 |
| 497 TrustAnchor::TrustAnchor() {} |
| 505 TrustAnchor::~TrustAnchor() {} | 498 TrustAnchor::~TrustAnchor() {} |
| 506 | 499 |
| 500 std::unique_ptr<TrustAnchor> TrustAnchor::CreateFromCertificateData( |
| 501 const uint8_t* data, |
| 502 size_t length, |
| 503 DataSource source) { |
| 504 std::unique_ptr<TrustAnchor> result(new TrustAnchor); |
| 505 |
| 506 switch (source) { |
| 507 case DataSource::INTERNAL_COPY: |
| 508 result->cert_data_.assign(data, data + length); |
| 509 result->cert_ = |
| 510 der::Input(result->cert_data_.data(), result->cert_data_.size()); |
| 511 break; |
| 512 case DataSource::EXTERNAL_REFERENCE: |
| 513 result->cert_ = der::Input(data, length); |
| 514 break; |
| 515 } |
| 516 |
| 517 // Parse the certificate to get its name. |
| 518 ParsedCertificate cert; |
| 519 if (!ParseCertificate(result->cert(), &cert)) |
| 520 return nullptr; |
| 521 |
| 522 ParsedTbsCertificate tbs; |
| 523 if (!ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs)) |
| 524 return nullptr; |
| 525 |
| 526 result->name_ = tbs.subject_tlv; |
| 527 |
| 528 // TODO(eroman): If adding a self-signed certificate, check that its |
| 529 // signature is correct? This check will not otherwise be done during |
| 530 // verification. |
| 531 |
| 532 return result; |
| 533 } |
| 534 |
| 535 bool TrustAnchor::MatchesName(const der::Input& name) const { |
| 536 return NameMatches(name, name_); |
| 537 } |
| 538 |
| 507 TrustStore::TrustStore() {} | 539 TrustStore::TrustStore() {} |
| 508 TrustStore::TrustStore(const TrustStore& other) = default; | |
| 509 TrustStore::~TrustStore() {} | 540 TrustStore::~TrustStore() {} |
| 510 | 541 |
| 542 void TrustStore::Clear() { |
| 543 anchors_.clear(); |
| 544 } |
| 545 |
| 546 bool TrustStore::AddTrustedCertificate(const uint8_t* data, size_t length) { |
| 547 return AddTrustedCertificate(data, length, |
| 548 TrustAnchor::DataSource::INTERNAL_COPY); |
| 549 } |
| 550 |
| 551 bool TrustStore::AddTrustedCertificate(const base::StringPiece& data) { |
| 552 return AddTrustedCertificate(reinterpret_cast<const uint8_t*>(data.data()), |
| 553 data.size()); |
| 554 } |
| 555 |
| 556 bool TrustStore::AddTrustedCertificateWithoutCopying(const uint8_t* data, |
| 557 size_t length) { |
| 558 return AddTrustedCertificate(data, length, |
| 559 TrustAnchor::DataSource::EXTERNAL_REFERENCE); |
| 560 } |
| 561 |
| 562 const TrustAnchor* TrustStore::FindTrustAnchorByName( |
| 563 const der::Input& name) const { |
| 564 for (const auto& anchor : anchors_) { |
| 565 if (anchor->MatchesName(name)) { |
| 566 return anchor.get(); |
| 567 } |
| 568 } |
| 569 return nullptr; |
| 570 } |
| 571 |
| 572 bool TrustStore::IsTrustedCertificate(const der::Input& cert_der) const { |
| 573 for (const auto& anchor : anchors_) { |
| 574 if (anchor->cert() == cert_der) |
| 575 return true; |
| 576 } |
| 577 return false; |
| 578 } |
| 579 |
| 580 bool TrustStore::AddTrustedCertificate(const uint8_t* data, |
| 581 size_t length, |
| 582 TrustAnchor::DataSource source) { |
| 583 auto anchor = TrustAnchor::CreateFromCertificateData(data, length, source); |
| 584 if (!anchor) |
| 585 return false; |
| 586 anchors_.push_back(std::move(anchor)); |
| 587 return true; |
| 588 } |
| 589 |
| 590 // TODO(eroman): Move this into existing anonymous namespace. |
| 591 namespace { |
| 592 |
| 511 // This implementation is structured to mimic the description of certificate | 593 // This implementation is structured to mimic the description of certificate |
| 512 // path verification given by RFC 5280 section 6.1. | 594 // path verification given by RFC 5280 section 6.1. |
| 513 bool VerifyCertificateChain(const std::vector<der::Input>& certs_der, | 595 // |
| 514 const TrustStore& trust_store, | 596 // Unlike RFC 5280, the trust anchor is specified as the root certificate in |
| 515 const SignaturePolicy* signature_policy, | 597 // the chain. This root certificate is assumed to be trusted, and neither its |
| 516 const der::GeneralizedTime& time) { | 598 // signature nor issuer name are verified. (It needn't be self-signed). |
| 599 bool VerifyCertificateChainAssumingTrustedRoot( |
| 600 const std::vector<der::Input>& certs_der, |
| 601 // The trust store is only used for assertions. |
| 602 const TrustStore& trust_store, |
| 603 const SignaturePolicy* signature_policy, |
| 604 const der::GeneralizedTime& time) { |
| 517 // An empty chain is necessarily invalid. | 605 // An empty chain is necessarily invalid. |
| 518 if (certs_der.empty()) | 606 if (certs_der.empty()) |
| 519 return false; | 607 return false; |
| 520 | 608 |
| 609 // IMPORTANT: the assumption being made is that the root certificate in |
| 610 // the given path is the trust anchor (and has already been verified as |
| 611 // such). |
| 612 DCHECK(trust_store.IsTrustedCertificate(certs_der.back())); |
| 613 |
| 521 // Will contain a NameConstraints for each previous cert in the chain which | 614 // Will contain a NameConstraints for each previous cert in the chain which |
| 522 // had nameConstraints. This corresponds to the permitted_subtrees and | 615 // had nameConstraints. This corresponds to the permitted_subtrees and |
| 523 // excluded_subtrees state variables from RFC 5280. | 616 // excluded_subtrees state variables from RFC 5280. |
| 524 std::vector<std::unique_ptr<NameConstraints>> name_constraints_list; | 617 std::vector<std::unique_ptr<NameConstraints>> name_constraints_list; |
| 525 | 618 |
| 526 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: | 619 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: |
| 527 // * working_public_key | 620 // * working_public_key |
| 528 // * working_public_key_algorithm | 621 // * working_public_key_algorithm |
| 529 // * working_public_key_parameters | 622 // * working_public_key_parameters |
| 530 // | 623 // |
| 531 // They are combined for simplicity since the signature verification takes an | 624 // They are combined for simplicity since the signature verification takes an |
| 532 // SPKI, and the parameter inheritence is not applicable for the supported | 625 // SPKI, and the parameter inheritence is not applicable for the supported |
| 533 // key types. | 626 // key types. |
| 534 // | 627 // |
| 535 // An approximate explanation of |working_spki| is this description from RFC | 628 // An approximate explanation of |working_spki| is this description from RFC |
| 536 // 5280 section 6.1.2: | 629 // 5280 section 6.1.2: |
| 537 // | 630 // |
| 538 // working_public_key: the public key used to verify the | 631 // working_public_key: the public key used to verify the |
| 539 // signature of a certificate. The working_public_key is | 632 // signature of a certificate. |
| 540 // initialized from the trusted public key provided in the trust | |
| 541 // anchor information. | |
| 542 der::Input working_spki; | 633 der::Input working_spki; |
| 543 | 634 |
| 544 // |working_issuer_name| corresponds with the same named variable in RFC 5280 | 635 // |working_issuer_name| corresponds with the same named variable in RFC 5280 |
| 545 // section 6.1.2: | 636 // section 6.1.2: |
| 546 // | 637 // |
| 547 // working_issuer_name: the issuer distinguished name expected | 638 // working_issuer_name: the issuer distinguished name expected |
| 548 // in the next certificate in the chain. The | 639 // in the next certificate in the chain. |
| 549 // working_issuer_name is initialized to the trusted issuer name | |
| 550 // provided in the trust anchor information. | |
| 551 der::Input working_issuer_name; | 640 der::Input working_issuer_name; |
| 552 | 641 |
| 553 // |max_path_length| corresponds with the same named variable in RFC 5280 | 642 // |max_path_length| corresponds with the same named variable in RFC 5280 |
| 554 // section 6.1.2: | 643 // section 6.1.2: |
| 555 // | 644 // |
| 556 // max_path_length: this integer is initialized to n, is | 645 // max_path_length: this integer is initialized to n, is |
| 557 // decremented for each non-self-issued certificate in the path, | 646 // decremented for each non-self-issued certificate in the path, |
| 558 // and may be reduced to the value in the path length constraint | 647 // and may be reduced to the value in the path length constraint |
| 559 // field within the basic constraints extension of a CA | 648 // field within the basic constraints extension of a CA |
| 560 // certificate. | 649 // certificate. |
| 561 size_t max_path_length = certs_der.size(); | 650 size_t max_path_length = certs_der.size(); |
| 562 | 651 |
| 563 // Iterate over all the certificates in the reverse direction: starting from | 652 // Iterate over all the certificates in the reverse direction: starting from |
| 564 // the trust anchor and progressing towards the target certificate. | 653 // the trust anchor and progressing towards the target certificate. |
| 565 // | 654 // |
| 566 // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based. | 655 // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based. |
| 567 // | 656 // |
| 568 // * i=0 : Certificate signed by a trust anchor. | 657 // * i=0 : Trust anchor. |
| 569 // * i=N-1 : Target certificate. | 658 // * i=N-1 : Target certificate. |
| 570 for (size_t i = 0; i < certs_der.size(); ++i) { | 659 for (size_t i = 0; i < certs_der.size(); ++i) { |
| 571 const size_t index_into_certs_der = certs_der.size() - i - 1; | 660 const size_t index_into_certs_der = certs_der.size() - i - 1; |
| 661 |
| 662 // |is_target_cert| is true if the current certificate is the target |
| 663 // certificate being verified. The target certificate isn't necessarily an |
| 664 // end-entity certificate. |
| 572 const bool is_target_cert = index_into_certs_der == 0; | 665 const bool is_target_cert = index_into_certs_der == 0; |
| 573 | 666 |
| 667 // |is_trust_anchor| is true if the current certificate is the trust |
| 668 // anchor. This certificate is implicitly trusted. |
| 669 const bool is_trust_anchor = i == 0; |
| 670 |
| 574 // Parse the current certificate into |cert|. | 671 // Parse the current certificate into |cert|. |
| 575 FullyParsedCert cert; | 672 FullyParsedCert cert; |
| 576 const der::Input& cert_der = certs_der[index_into_certs_der]; | 673 const der::Input& cert_der = certs_der[index_into_certs_der]; |
| 577 if (!FullyParseCertificate(cert_der, &cert)) | 674 if (!FullyParseCertificate(cert_der, &cert)) |
| 578 return false; | 675 return false; |
| 579 | 676 |
| 580 // When processing the first certificate, initialize |working_spki| | |
| 581 // and |working_issuer_name| to the trust anchor per RFC 5280 section 6.1.2. | |
| 582 // This is done inside the loop in order to have access to the parsed | |
| 583 // certificate. | |
| 584 if (i == 0) { | |
| 585 const TrustAnchor* trust_anchor = | |
| 586 FindTrustAnchorByName(trust_store, cert.tbs.issuer_tlv); | |
| 587 if (!trust_anchor) | |
| 588 return false; | |
| 589 working_spki = der::Input(&trust_anchor->spki); | |
| 590 working_issuer_name = der::Input(&trust_anchor->name); | |
| 591 } | |
| 592 | |
| 593 // Per RFC 5280 section 6.1: | 677 // Per RFC 5280 section 6.1: |
| 594 // * Do basic processing for each certificate | 678 // * Do basic processing for each certificate |
| 595 // * If it is the last certificate in the path (target certificate) | 679 // * If it is the last certificate in the path (target certificate) |
| 596 // - Then run "Wrap up" | 680 // - Then run "Wrap up" |
| 597 // - Otherwise run "Prepare for Next cert" | 681 // - Otherwise run "Prepare for Next cert" |
| 598 if (!BasicCertificateProcessing(cert, is_target_cert, signature_policy, | 682 if (!BasicCertificateProcessing( |
| 599 time, working_spki, working_issuer_name, | 683 cert, is_target_cert, is_trust_anchor, signature_policy, time, |
| 600 name_constraints_list)) { | 684 working_spki, working_issuer_name, name_constraints_list)) { |
| 601 return false; | 685 return false; |
| 602 } | 686 } |
| 603 if (!is_target_cert) { | 687 if (!is_target_cert) { |
| 604 if (!PrepareForNextCertificate(cert, &max_path_length, &working_spki, | 688 if (!PrepareForNextCertificate(cert, &max_path_length, &working_spki, |
| 605 &working_issuer_name, | 689 &working_issuer_name, |
| 606 &name_constraints_list)) { | 690 &name_constraints_list)) { |
| 607 return false; | 691 return false; |
| 608 } | 692 } |
| 609 } else { | 693 } else { |
| 610 if (!WrapUp(cert)) | 694 if (!WrapUp(cert)) |
| 611 return false; | 695 return false; |
| 612 } | 696 } |
| 613 } | 697 } |
| 614 | 698 |
| 615 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: | 699 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: |
| 616 // | 700 // |
| 617 // A certificate MUST NOT appear more than once in a prospective | 701 // A certificate MUST NOT appear more than once in a prospective |
| 618 // certification path. | 702 // certification path. |
| 619 | 703 |
| 620 return true; | 704 return true; |
| 621 } | 705 } |
| 622 | 706 |
| 707 // TODO(eroman): This function is a temporary hack in the absence of full |
| 708 // path building. It may insert 1 certificate at the root of the |
| 709 // chain to ensure that the path's root certificate is a trust anchor. |
| 710 // |
| 711 // Beyond this no other verification is done on the chain. The caller is |
| 712 // responsible for verifying the subsequent chain's correctness. |
| 713 WARN_UNUSED_RESULT bool BuildSimplePathToTrustAnchor( |
| 714 const std::vector<der::Input>& certs_der, |
| 715 const TrustStore& trust_store, |
| 716 std::vector<der::Input>* certs_der_trusted_root) { |
| 717 // Copy the input chain. |
| 718 *certs_der_trusted_root = certs_der; |
| 719 |
| 720 if (certs_der.empty()) |
| 721 return false; |
| 722 |
| 723 // Check if the current root certificate is trusted. If it is then no |
| 724 // extra work is needed. |
| 725 if (trust_store.IsTrustedCertificate(certs_der_trusted_root->back())) |
| 726 return true; |
| 727 |
| 728 // Otherwise if it is not trusted, check whether its issuer is trusted. If |
| 729 // so, make *that* trusted certificate the root. If the issuer is not in |
| 730 // the trust store then give up and fail (this is not full path building). |
| 731 ParsedCertificate cert; |
| 732 ParsedTbsCertificate tbs; |
| 733 if (!ParseCertificate(certs_der.back(), &cert) || |
| 734 !ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs)) { |
| 735 return false; |
| 736 } |
| 737 |
| 738 auto trust_anchor = trust_store.FindTrustAnchorByName(tbs.issuer_tlv); |
| 739 if (!trust_anchor) |
| 740 return false; |
| 741 certs_der_trusted_root->push_back(trust_anchor->cert()); |
| 742 return true; |
| 743 } |
| 744 |
| 745 } // namespace |
| 746 |
| 747 bool VerifyCertificateChain(const std::vector<der::Input>& certs_der, |
| 748 const TrustStore& trust_store, |
| 749 const SignaturePolicy* signature_policy, |
| 750 const der::GeneralizedTime& time) { |
| 751 // Modify the certificate chain so that its root is a trusted certificate. |
| 752 std::vector<der::Input> certs_der_trusted_root; |
| 753 if (!BuildSimplePathToTrustAnchor(certs_der, trust_store, |
| 754 &certs_der_trusted_root)) { |
| 755 return false; |
| 756 } |
| 757 |
| 758 // Verify the chain. |
| 759 return VerifyCertificateChainAssumingTrustedRoot( |
| 760 certs_der_trusted_root, trust_store, signature_policy, time); |
| 761 } |
| 762 |
| 623 } // namespace net | 763 } // namespace net |
| OLD | NEW |