OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/cert_verify_proc.h" | 5 #include "net/cert/cert_verify_proc.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
13 #include "base/sha1.h" | 13 #include "base/sha1.h" |
14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
16 #include "base/time/time.h" | 16 #include "base/time/time.h" |
17 #include "build/build_config.h" | 17 #include "build/build_config.h" |
18 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
19 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 19 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
20 #include "net/base/url_util.h" | 20 #include "net/base/url_util.h" |
21 #include "net/cert/asn1_util.h" | 21 #include "net/cert/asn1_util.h" |
22 #include "net/cert/cert_status_flags.h" | 22 #include "net/cert/cert_status_flags.h" |
23 #include "net/cert/cert_verifier.h" | 23 #include "net/cert/cert_verifier.h" |
24 #include "net/cert/cert_verify_proc_whitelist.h" | 24 #include "net/cert/cert_verify_proc_whitelist.h" |
25 #include "net/cert/cert_verify_result.h" | 25 #include "net/cert/cert_verify_result.h" |
26 #include "net/cert/crl_set.h" | 26 #include "net/cert/crl_set.h" |
27 #include "net/cert/internal/parse_ocsp.h" | 27 #include "net/cert/internal/parse_ocsp.h" |
| 28 #include "net/cert/internal/signature_algorithm.h" |
28 #include "net/cert/ocsp_revocation_status.h" | 29 #include "net/cert/ocsp_revocation_status.h" |
29 #include "net/cert/x509_certificate.h" | 30 #include "net/cert/x509_certificate.h" |
30 #include "net/der/encode_values.h" | 31 #include "net/der/encode_values.h" |
31 #include "url/url_canon.h" | 32 #include "url/url_canon.h" |
32 | 33 |
33 #if defined(USE_NSS_CERTS) | 34 #if defined(USE_NSS_CERTS) |
34 #include "net/cert/cert_verify_proc_nss.h" | 35 #include "net/cert/cert_verify_proc_nss.h" |
35 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) | 36 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) |
36 #include "net/cert/cert_verify_proc_openssl.h" | 37 #include "net/cert/cert_verify_proc_openssl.h" |
37 #elif defined(OS_ANDROID) | 38 #elif defined(OS_ANDROID) |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 // Note: This must be kept in sync with cert_verify_proc_unittest.cc | 366 // Note: This must be kept in sync with cert_verify_proc_unittest.cc |
366 return base::win::GetVersion() < base::win::VERSION_WIN8; | 367 return base::win::GetVersion() < base::win::VERSION_WIN8; |
367 #else | 368 #else |
368 return false; | 369 return false; |
369 #endif | 370 #endif |
370 }; | 371 }; |
371 | 372 |
372 // Sets the "has_*" boolean members in |verify_result| that correspond with | 373 // Sets the "has_*" boolean members in |verify_result| that correspond with |
373 // the the presence of |hash| somewhere in the certificate chain (excluding the | 374 // the the presence of |hash| somewhere in the certificate chain (excluding the |
374 // trust anchor). | 375 // trust anchor). |
375 void MapHashAlgorithmToBool(X509Certificate::SignatureHashAlgorithm hash, | 376 void MapAlgorithmToBool(DigestAlgorithm hash, CertVerifyResult* verify_result) { |
376 CertVerifyResult* verify_result) { | |
377 switch (hash) { | 377 switch (hash) { |
378 case X509Certificate::kSignatureHashAlgorithmMd2: | 378 case DigestAlgorithm::Md2: |
379 verify_result->has_md2 = true; | 379 verify_result->has_md2 = true; |
380 break; | 380 break; |
381 case X509Certificate::kSignatureHashAlgorithmMd4: | 381 case DigestAlgorithm::Md4: |
382 verify_result->has_md4 = true; | 382 verify_result->has_md4 = true; |
383 break; | 383 break; |
384 case X509Certificate::kSignatureHashAlgorithmMd5: | 384 case DigestAlgorithm::Md5: |
385 verify_result->has_md5 = true; | 385 verify_result->has_md5 = true; |
386 break; | 386 break; |
387 case X509Certificate::kSignatureHashAlgorithmSha1: | 387 case DigestAlgorithm::Sha1: |
388 verify_result->has_sha1 = true; | 388 verify_result->has_sha1 = true; |
389 break; | 389 break; |
390 case X509Certificate::kSignatureHashAlgorithmOther: | 390 case DigestAlgorithm::Sha256: |
| 391 case DigestAlgorithm::Sha384: |
| 392 case DigestAlgorithm::Sha512: |
391 break; | 393 break; |
392 } | 394 } |
393 } | 395 } |
394 | 396 |
395 // Sets to true the |verify_result->has_*| boolean members for the hash | 397 // Inspects the signature algorithms in a single certificate |cert|. |
396 // algorithms present in the certificate chain. | |
397 // | 398 // |
398 // This considers the hash algorithms in all certificates except trusted | 399 // * Sets |verify_result->has_md2| to true if the certificate uses MD2. |
399 // certificates. | 400 // * Sets |verify_result->has_md4| to true if the certificate uses MD4. |
| 401 // * Sets |verify_result->has_md5| to true if the certificate uses MD5. |
| 402 // * Sets |verify_result->has_sha1| to true if the certificate uses SHA1. |
400 // | 403 // |
401 // In the case of a successful verification the trust anchor is the final | 404 // Returns false if the signature algorithm was unknown or mismatched. |
402 // certificate in the chain (either the final intermediate, or the leaf | 405 WARN_UNUSED_RESULT bool InspectSignatureAlgorithmForCert( |
403 // certificate). | 406 X509Certificate::OSCertHandle cert, |
| 407 CertVerifyResult* verify_result) { |
| 408 std::string cert_der; |
| 409 base::StringPiece cert_algorithm_sequence; |
| 410 base::StringPiece tbs_algorithm_sequence; |
| 411 |
| 412 // Extract the AlgorithmIdentifier SEQUENCEs |
| 413 if (!X509Certificate::GetDEREncoded(cert, &cert_der) || |
| 414 !asn1::ExtractSignatureAlgorithmsFromDERCert( |
| 415 cert_der, &cert_algorithm_sequence, &tbs_algorithm_sequence)) { |
| 416 return false; |
| 417 } |
| 418 |
| 419 if (!SignatureAlgorithm::IsEquivalent(der::Input(cert_algorithm_sequence), |
| 420 der::Input(tbs_algorithm_sequence))) { |
| 421 return false; |
| 422 } |
| 423 |
| 424 std::unique_ptr<SignatureAlgorithm> algorithm = |
| 425 SignatureAlgorithm::Create(der::Input(cert_algorithm_sequence), nullptr); |
| 426 if (!algorithm) |
| 427 return false; |
| 428 |
| 429 MapAlgorithmToBool(algorithm->digest(), verify_result); |
| 430 |
| 431 // Check algorithm-specific parameters. |
| 432 switch (algorithm->algorithm()) { |
| 433 case SignatureAlgorithmId::RsaPkcs1: |
| 434 case SignatureAlgorithmId::Ecdsa: |
| 435 DCHECK(!algorithm->has_params()); |
| 436 break; |
| 437 case SignatureAlgorithmId::RsaPss: |
| 438 MapAlgorithmToBool(algorithm->ParamsForRsaPss()->mgf1_hash(), |
| 439 verify_result); |
| 440 break; |
| 441 } |
| 442 |
| 443 return true; |
| 444 } |
| 445 |
| 446 // InspectSignatureAlgorithmsInChain() sets |verify_result->has_*| based on |
| 447 // the signature algorithms used in the chain, and also checks that certificates |
| 448 // don't have contradictory signature algorithms. |
404 // | 449 // |
405 // Whereas if verification was uncessful, the chain may be partial, and the | 450 // Returns false if any signature algorithm in the chain is unknown or |
406 // final certificate may not be a trust anchor. This heuristic is used | 451 // mismatched. |
407 // in both successful and failed verifications, despite this ambiguity (failure | 452 // |
408 // to tag one of the signature algorithms should only affect the final error). | 453 // Background: |
409 void ComputeSignatureHashAlgorithms(CertVerifyResult* verify_result) { | 454 // |
| 455 // X.509 certificates contain two redundant descriptors for the signature |
| 456 // algorithm; one is covered by the signature, but in order to verify the |
| 457 // signature, the other signature algorithm is untrusted. |
| 458 // |
| 459 // RFC 5280 states that the two should be equal, in order to mitigate risk of |
| 460 // signature substitution attacks, but also discourages verifiers from enforcing |
| 461 // the profile of RFC 5280. |
| 462 // |
| 463 // System verifiers are inconsistent - some use the unsigned signature, some use |
| 464 // the signed signature, and they generally do not enforce that both match. This |
| 465 // creates confusion, as it's possible that the signature itself may be checked |
| 466 // using algorithm A, but if subsequent consumers report the certificate |
| 467 // algorithm, they may end up reporting algorithm B, which was not used to |
| 468 // verify the certificate. This function enforces that the two signatures match |
| 469 // in order to prevent such confusion. |
| 470 WARN_UNUSED_RESULT bool InspectSignatureAlgorithmsInChain( |
| 471 CertVerifyResult* verify_result) { |
410 const X509Certificate::OSCertHandles& intermediates = | 472 const X509Certificate::OSCertHandles& intermediates = |
411 verify_result->verified_cert->GetIntermediateCertificates(); | 473 verify_result->verified_cert->GetIntermediateCertificates(); |
412 | 474 |
413 // If there are no intermediates, then the leaf is trusted or verification | 475 // If there are no intermediates, then the leaf is trusted or verification |
414 // failed. | 476 // failed. |
415 if (intermediates.empty()) | 477 if (intermediates.empty()) |
416 return; | 478 return true; |
417 | 479 |
418 DCHECK(!verify_result->has_sha1); | 480 DCHECK(!verify_result->has_sha1); |
419 | 481 |
420 // Fill in hash algorithms for the leaf certificate. | 482 // Fill in hash algorithms for the leaf certificate. |
421 MapHashAlgorithmToBool(X509Certificate::GetSignatureHashAlgorithm( | 483 if (!InspectSignatureAlgorithmForCert( |
422 verify_result->verified_cert->os_cert_handle()), | 484 verify_result->verified_cert->os_cert_handle(), verify_result)) { |
423 verify_result); | 485 return false; |
| 486 } |
| 487 |
424 verify_result->has_sha1_leaf = verify_result->has_sha1; | 488 verify_result->has_sha1_leaf = verify_result->has_sha1; |
425 | 489 |
426 // Fill in hash algorithms for the intermediate cerificates, excluding the | 490 // Fill in hash algorithms for the intermediate cerificates, excluding the |
427 // final one (which is the trust anchor). | 491 // final one (which is presumably the trust anchor; may be incorrect for |
| 492 // partial chains). |
428 for (size_t i = 0; i + 1 < intermediates.size(); ++i) { | 493 for (size_t i = 0; i + 1 < intermediates.size(); ++i) { |
429 MapHashAlgorithmToBool( | 494 if (!InspectSignatureAlgorithmForCert(intermediates[i], verify_result)) |
430 X509Certificate::GetSignatureHashAlgorithm(intermediates[i]), | 495 return false; |
431 verify_result); | |
432 } | 496 } |
| 497 |
| 498 return true; |
433 } | 499 } |
434 | 500 |
435 } // namespace | 501 } // namespace |
436 | 502 |
437 // static | 503 // static |
438 CertVerifyProc* CertVerifyProc::CreateDefault() { | 504 CertVerifyProc* CertVerifyProc::CreateDefault() { |
439 #if defined(USE_NSS_CERTS) | 505 #if defined(USE_NSS_CERTS) |
440 return new CertVerifyProcNSS(); | 506 return new CertVerifyProcNSS(); |
441 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) | 507 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) |
442 return new CertVerifyProcOpenSSL(); | 508 return new CertVerifyProcOpenSSL(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 // We do online revocation checking for EV certificates that aren't covered | 542 // We do online revocation checking for EV certificates that aren't covered |
477 // by a fresh CRLSet. | 543 // by a fresh CRLSet. |
478 // TODO(rsleevi): http://crbug.com/142974 - Allow preferences to fully | 544 // TODO(rsleevi): http://crbug.com/142974 - Allow preferences to fully |
479 // disable revocation checking. | 545 // disable revocation checking. |
480 if (flags & CertVerifier::VERIFY_EV_CERT) | 546 if (flags & CertVerifier::VERIFY_EV_CERT) |
481 flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY; | 547 flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY; |
482 | 548 |
483 int rv = VerifyInternal(cert, hostname, ocsp_response, flags, crl_set, | 549 int rv = VerifyInternal(cert, hostname, ocsp_response, flags, crl_set, |
484 additional_trust_anchors, verify_result); | 550 additional_trust_anchors, verify_result); |
485 | 551 |
486 ComputeSignatureHashAlgorithms(verify_result); | 552 // Check for mismatched signature algorithms and unknown signature algorithms |
| 553 // in the chain. Also fills in the has_* booleans for the digest algorithms |
| 554 // present in the chain. |
| 555 if (!InspectSignatureAlgorithmsInChain(verify_result)) { |
| 556 verify_result->cert_status |= CERT_STATUS_INVALID; |
| 557 rv = MapCertStatusToNetError(verify_result->cert_status); |
| 558 } |
487 | 559 |
488 bool allow_common_name_fallback = | 560 bool allow_common_name_fallback = |
489 !verify_result->is_issued_by_known_root && | 561 !verify_result->is_issued_by_known_root && |
490 (flags & CertVerifier::VERIFY_ENABLE_COMMON_NAME_FALLBACK_LOCAL_ANCHORS); | 562 (flags & CertVerifier::VERIFY_ENABLE_COMMON_NAME_FALLBACK_LOCAL_ANCHORS); |
491 if (!cert->VerifyNameMatch(hostname, allow_common_name_fallback)) { | 563 if (!cert->VerifyNameMatch(hostname, allow_common_name_fallback)) { |
492 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | 564 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; |
493 rv = MapCertStatusToNetError(verify_result->cert_status); | 565 rv = MapCertStatusToNetError(verify_result->cert_status); |
494 } | 566 } |
495 | 567 |
496 CheckOCSP(ocsp_response, *verify_result->verified_cert, | 568 CheckOCSP(ocsp_response, *verify_result->verified_cert, |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 return true; | 906 return true; |
835 | 907 |
836 return false; | 908 return false; |
837 } | 909 } |
838 | 910 |
839 // static | 911 // static |
840 const base::Feature CertVerifyProc::kSHA1LegacyMode{ | 912 const base::Feature CertVerifyProc::kSHA1LegacyMode{ |
841 "SHA1LegacyMode", base::FEATURE_DISABLED_BY_DEFAULT}; | 913 "SHA1LegacyMode", base::FEATURE_DISABLED_BY_DEFAULT}; |
842 | 914 |
843 } // namespace net | 915 } // namespace net |
OLD | NEW |