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

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

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

Powered by Google App Engine
This is Rietveld 408576698