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

Side by Side Diff: net/cert/cert_verify_proc.cc

Issue 2731603002: Check TBSCertificate.algorithm and Certificate.signatureAlgorithm for (Closed)
Patch Set: add tests for root Created 3 years, 9 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
OLDNEW
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
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 auto algorithm =
Ryan Sleevi 2017/03/09 00:45:26 This is hiding the lifetime management of Signatur
eroman 2017/03/09 01:09:43 Done.
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() calls InspectSignatureAlgorithmForCert()
447 // for each certificate in the chain (refer to its documentation).
404 // 448 //
405 // Whereas if verification was uncessful, the chain may be partial, and the 449 // Returns false if any signature algorithm in the chain was unknown or
406 // final certificate may not be a trust anchor. This heuristic is used 450 // mismatched.
407 // in both successful and failed verifications, despite this ambiguity (failure 451 WARN_UNUSED_RESULT bool InspectSignatureAlgorithmsInChain(
408 // to tag one of the signature algorithms should only affect the final error). 452 CertVerifyResult* verify_result) {
409 void ComputeSignatureHashAlgorithms(CertVerifyResult* verify_result) {
410 const X509Certificate::OSCertHandles& intermediates = 453 const X509Certificate::OSCertHandles& intermediates =
411 verify_result->verified_cert->GetIntermediateCertificates(); 454 verify_result->verified_cert->GetIntermediateCertificates();
412 455
413 // If there are no intermediates, then the leaf is trusted or verification 456 // If there are no intermediates, then the leaf is trusted or verification
414 // failed. 457 // failed.
415 if (intermediates.empty()) 458 if (intermediates.empty())
416 return; 459 return true;
417 460
418 DCHECK(!verify_result->has_sha1); 461 DCHECK(!verify_result->has_sha1);
419 462
420 // Fill in hash algorithms for the leaf certificate. 463 // Fill in hash algorithms for the leaf certificate.
421 MapHashAlgorithmToBool(X509Certificate::GetSignatureHashAlgorithm( 464 if (!InspectSignatureAlgorithmForCert(
422 verify_result->verified_cert->os_cert_handle()), 465 verify_result->verified_cert->os_cert_handle(), verify_result)) {
423 verify_result); 466 return false;
467 }
468
424 verify_result->has_sha1_leaf = verify_result->has_sha1; 469 verify_result->has_sha1_leaf = verify_result->has_sha1;
425 470
426 // Fill in hash algorithms for the intermediate cerificates, excluding the 471 // Fill in hash algorithms for the intermediate cerificates, excluding the
427 // final one (which is the trust anchor). 472 // final one (which is presumably the trust anchor; may be incorrect for
473 // partial chains).
428 for (size_t i = 0; i + 1 < intermediates.size(); ++i) { 474 for (size_t i = 0; i + 1 < intermediates.size(); ++i) {
429 MapHashAlgorithmToBool( 475 if (!InspectSignatureAlgorithmForCert(intermediates[i], verify_result))
430 X509Certificate::GetSignatureHashAlgorithm(intermediates[i]), 476 return false;
431 verify_result);
432 } 477 }
478
479 return true;
433 } 480 }
434 481
435 } // namespace 482 } // namespace
436 483
437 // static 484 // static
438 CertVerifyProc* CertVerifyProc::CreateDefault() { 485 CertVerifyProc* CertVerifyProc::CreateDefault() {
439 #if defined(USE_NSS_CERTS) 486 #if defined(USE_NSS_CERTS)
440 return new CertVerifyProcNSS(); 487 return new CertVerifyProcNSS();
441 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) 488 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
442 return new CertVerifyProcOpenSSL(); 489 return new CertVerifyProcOpenSSL();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 // We do online revocation checking for EV certificates that aren't covered 523 // We do online revocation checking for EV certificates that aren't covered
477 // by a fresh CRLSet. 524 // by a fresh CRLSet.
478 // TODO(rsleevi): http://crbug.com/142974 - Allow preferences to fully 525 // TODO(rsleevi): http://crbug.com/142974 - Allow preferences to fully
479 // disable revocation checking. 526 // disable revocation checking.
480 if (flags & CertVerifier::VERIFY_EV_CERT) 527 if (flags & CertVerifier::VERIFY_EV_CERT)
481 flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY; 528 flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY;
482 529
483 int rv = VerifyInternal(cert, hostname, ocsp_response, flags, crl_set, 530 int rv = VerifyInternal(cert, hostname, ocsp_response, flags, crl_set,
484 additional_trust_anchors, verify_result); 531 additional_trust_anchors, verify_result);
485 532
486 ComputeSignatureHashAlgorithms(verify_result); 533 // Check for mismatched signature algorithms and unknown signature algorithms
534 // in the chain. Also fills in the has_* booleans for the digest algorithms
535 // present in the chain.
536 if (!InspectSignatureAlgorithmsInChain(verify_result)) {
537 verify_result->cert_status |= CERT_STATUS_INVALID;
538 rv = MapCertStatusToNetError(verify_result->cert_status);
539 }
487 540
488 bool allow_common_name_fallback = 541 bool allow_common_name_fallback =
489 !verify_result->is_issued_by_known_root && 542 !verify_result->is_issued_by_known_root &&
490 (flags & CertVerifier::VERIFY_ENABLE_COMMON_NAME_FALLBACK_LOCAL_ANCHORS); 543 (flags & CertVerifier::VERIFY_ENABLE_COMMON_NAME_FALLBACK_LOCAL_ANCHORS);
491 if (!cert->VerifyNameMatch(hostname, allow_common_name_fallback)) { 544 if (!cert->VerifyNameMatch(hostname, allow_common_name_fallback)) {
492 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; 545 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
493 rv = MapCertStatusToNetError(verify_result->cert_status); 546 rv = MapCertStatusToNetError(verify_result->cert_status);
494 } 547 }
495 548
496 CheckOCSP(ocsp_response, *verify_result->verified_cert, 549 CheckOCSP(ocsp_response, *verify_result->verified_cert,
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 return true; 887 return true;
835 888
836 return false; 889 return false;
837 } 890 }
838 891
839 // static 892 // static
840 const base::Feature CertVerifyProc::kSHA1LegacyMode{ 893 const base::Feature CertVerifyProc::kSHA1LegacyMode{
841 "SHA1LegacyMode", base::FEATURE_DISABLED_BY_DEFAULT}; 894 "SHA1LegacyMode", base::FEATURE_DISABLED_BY_DEFAULT};
842 895
843 } // namespace net 896 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698