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

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

Issue 2731603002: Check TBSCertificate.algorithm and Certificate.signatureAlgorithm for (Closed)
Patch Set: fix 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 // * Sets |*has_mismatched_signature_algorithms| to true if
mattm 2017/03/04 02:34:26 note that the has_mismatched_signature_algorithms
eroman 2017/03/07 23:43:00 N/A -- I removed these out-parameters and combined
402 // certificate in the chain (either the final intermediate, or the leaf 405 // Certificate.signatureAlgorithm is not consistent with
403 // certificate). 406 // TBSCertificate.algorithm
404 // 407 //
405 // Whereas if verification was uncessful, the chain may be partial, and the 408 // * Sets |*has_unknown_signature_algorithms| to true if one or both of the
406 // final certificate may not be a trust anchor. This heuristic is used 409 // signature algorithms could not be parsed or matched against a known
407 // in both successful and failed verifications, despite this ambiguity (failure 410 // whitelist.
mattm 2017/03/04 02:34:26 Maybe just me, but I was a bit confused by the com
eroman 2017/03/07 23:43:00 N/A -- replaced this with a hopefully clearer com
408 // to tag one of the signature algorithms should only affect the final error). 411 void InspectSignatureAlgorithmForCert(X509Certificate::OSCertHandle cert,
409 void ComputeSignatureHashAlgorithms(CertVerifyResult* verify_result) { 412 CertVerifyResult* verify_result,
413 bool* has_mismatched_signature_algorithms,
414 bool* has_unknown_signature_algorithms) {
415 std::string cert_der;
416 base::StringPiece cert_algorithm_sequence;
417 base::StringPiece tbs_algorithm_sequence;
418
419 // Extract the AlgorithmIdentifier SEQUENCEs
420 if (!X509Certificate::GetDEREncoded(cert, &cert_der) ||
421 !asn1::ExtractSignatureAlgorithmsFromDERCert(
422 cert_der, &cert_algorithm_sequence, &tbs_algorithm_sequence)) {
423 *has_unknown_signature_algorithms = true;
424 return;
425 }
426
427 if (!SignatureAlgorithm::IsEquivalent(der::Input(cert_algorithm_sequence),
428 der::Input(tbs_algorithm_sequence))) {
429 *has_mismatched_signature_algorithms = true;
430 }
431
432 auto algorithm =
433 SignatureAlgorithm::Create(der::Input(cert_algorithm_sequence), nullptr);
434
435 if (!algorithm) {
436 // Couldn't parse the signature algorithm (either malformed, or an unknown
437 // OID).
438 *has_unknown_signature_algorithms = true;
439 return;
mattm 2017/03/04 02:34:26 I guess it doesn't matter with the current usage,
eroman 2017/03/07 23:43:00 N/A -- I no longer distinguish between the two, an
440 }
441
442 MapAlgorithmToBool(algorithm->digest(), verify_result);
443
444 // Check the MGF1 digest for RSASSA-PSS if applicable.
445 if (algorithm->has_params()) {
446 switch (algorithm->algorithm()) {
447 case SignatureAlgorithmId::Ecdsa:
448 case SignatureAlgorithmId::RsaPkcs1:
449 NOTREACHED();
mattm 2017/03/04 02:34:26 Is this reachable with malformed input data? Or do
eroman 2017/03/07 23:43:00 I restructured this code so there is no longer a N
450 break;
451 case SignatureAlgorithmId::RsaPss:
452 MapAlgorithmToBool(algorithm->ParamsForRsaPss()->mgf1_hash(),
453 verify_result);
454 break;
455 }
456 }
457 }
458
459 // InspectSignatureAlgorithms() calls InspectSignatureAlgorithmForCert() for
460 // each certificate in the chain.
461 void InspectSignatureAlgorithms(CertVerifyResult* verify_result,
462 bool* has_mismatched_signature_algorithms,
463 bool* has_unknown_signature_algorithms) {
464 *has_mismatched_signature_algorithms = false;
465 *has_unknown_signature_algorithms = false;
466
410 const X509Certificate::OSCertHandles& intermediates = 467 const X509Certificate::OSCertHandles& intermediates =
411 verify_result->verified_cert->GetIntermediateCertificates(); 468 verify_result->verified_cert->GetIntermediateCertificates();
412 469
413 // If there are no intermediates, then the leaf is trusted or verification 470 // If there are no intermediates, then the leaf is trusted or verification
414 // failed. 471 // failed.
415 if (intermediates.empty()) 472 if (intermediates.empty())
416 return; 473 return;
417 474
418 DCHECK(!verify_result->has_sha1); 475 DCHECK(!verify_result->has_sha1);
419 476
420 // Fill in hash algorithms for the leaf certificate. 477 // Fill in hash algorithms for the leaf certificate.
421 MapHashAlgorithmToBool(X509Certificate::GetSignatureHashAlgorithm( 478 InspectSignatureAlgorithmForCert(
422 verify_result->verified_cert->os_cert_handle()), 479 verify_result->verified_cert->os_cert_handle(), verify_result,
423 verify_result); 480 has_mismatched_signature_algorithms, has_unknown_signature_algorithms);
424 verify_result->has_sha1_leaf = verify_result->has_sha1; 481 verify_result->has_sha1_leaf = verify_result->has_sha1;
425 482
426 // Fill in hash algorithms for the intermediate cerificates, excluding the 483 // Fill in hash algorithms for the intermediate cerificates, excluding the
427 // final one (which is the trust anchor). 484 // final one (which is presumably the trust anchor; may be incorrect for
485 // partial chains).
428 for (size_t i = 0; i + 1 < intermediates.size(); ++i) { 486 for (size_t i = 0; i + 1 < intermediates.size(); ++i) {
429 MapHashAlgorithmToBool( 487 InspectSignatureAlgorithmForCert(intermediates[i], verify_result,
430 X509Certificate::GetSignatureHashAlgorithm(intermediates[i]), 488 has_mismatched_signature_algorithms,
431 verify_result); 489 has_unknown_signature_algorithms);
432 } 490 }
433 } 491 }
434 492
435 } // namespace 493 } // namespace
436 494
437 // static 495 // static
438 CertVerifyProc* CertVerifyProc::CreateDefault() { 496 CertVerifyProc* CertVerifyProc::CreateDefault() {
439 #if defined(USE_NSS_CERTS) 497 #if defined(USE_NSS_CERTS)
440 return new CertVerifyProcNSS(); 498 return new CertVerifyProcNSS();
441 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) 499 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 // We do online revocation checking for EV certificates that aren't covered 534 // We do online revocation checking for EV certificates that aren't covered
477 // by a fresh CRLSet. 535 // by a fresh CRLSet.
478 // TODO(rsleevi): http://crbug.com/142974 - Allow preferences to fully 536 // TODO(rsleevi): http://crbug.com/142974 - Allow preferences to fully
479 // disable revocation checking. 537 // disable revocation checking.
480 if (flags & CertVerifier::VERIFY_EV_CERT) 538 if (flags & CertVerifier::VERIFY_EV_CERT)
481 flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY; 539 flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY;
482 540
483 int rv = VerifyInternal(cert, hostname, ocsp_response, flags, crl_set, 541 int rv = VerifyInternal(cert, hostname, ocsp_response, flags, crl_set,
484 additional_trust_anchors, verify_result); 542 additional_trust_anchors, verify_result);
485 543
486 ComputeSignatureHashAlgorithms(verify_result); 544 // Look through all the signature algorithms in the chain.
545 bool has_mismatched_signature_algorithms = false;
546 bool has_unknown_signature_algorithms = false;
547 InspectSignatureAlgorithms(verify_result,
548 &has_mismatched_signature_algorithms,
549 &has_unknown_signature_algorithms);
550 if (has_mismatched_signature_algorithms || has_unknown_signature_algorithms) {
551 verify_result->cert_status |= CERT_STATUS_INVALID;
552 rv = MapCertStatusToNetError(verify_result->cert_status);
553 }
487 554
488 if (!cert->VerifyNameMatch(hostname, 555 if (!cert->VerifyNameMatch(hostname,
489 &verify_result->common_name_fallback_used)) { 556 &verify_result->common_name_fallback_used)) {
490 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; 557 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
491 rv = MapCertStatusToNetError(verify_result->cert_status); 558 rv = MapCertStatusToNetError(verify_result->cert_status);
492 } 559 }
493 560
494 UMA_HISTOGRAM_BOOLEAN("Net.CertCommonNameFallback", 561 UMA_HISTOGRAM_BOOLEAN("Net.CertCommonNameFallback",
495 verify_result->common_name_fallback_used); 562 verify_result->common_name_fallback_used);
496 if (!verify_result->is_issued_by_known_root) { 563 if (!verify_result->is_issued_by_known_root) {
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 return true; 906 return true;
840 907
841 return false; 908 return false;
842 } 909 }
843 910
844 // static 911 // static
845 const base::Feature CertVerifyProc::kSHA1LegacyMode{ 912 const base::Feature CertVerifyProc::kSHA1LegacyMode{
846 "SHA1LegacyMode", base::FEATURE_DISABLED_BY_DEFAULT}; 913 "SHA1LegacyMode", base::FEATURE_DISABLED_BY_DEFAULT};
847 914
848 } // namespace net 915 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698