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

Side by Side Diff: net/cert/cert_verify_proc_unittest.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 <vector> 7 #include <vector>
8 8
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/sha1.h" 14 #include "base/sha1.h"
15 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
16 #include "base/test/histogram_tester.h" 16 #include "base/test/histogram_tester.h"
17 #include "base/test/scoped_feature_list.h" 17 #include "base/test/scoped_feature_list.h"
18 #include "build/build_config.h" 18 #include "build/build_config.h"
19 #include "crypto/sha2.h" 19 #include "crypto/sha2.h"
20 #include "net/base/net_errors.h" 20 #include "net/base/net_errors.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_result.h" 24 #include "net/cert/cert_verify_result.h"
25 #include "net/cert/crl_set.h" 25 #include "net/cert/crl_set.h"
26 #include "net/cert/crl_set_storage.h" 26 #include "net/cert/crl_set_storage.h"
27 #include "net/cert/internal/signature_algorithm.h"
27 #include "net/cert/test_root_certs.h" 28 #include "net/cert/test_root_certs.h"
28 #include "net/cert/x509_certificate.h" 29 #include "net/cert/x509_certificate.h"
30 #include "net/der/input.h"
31 #include "net/der/parser.h"
29 #include "net/test/cert_test_util.h" 32 #include "net/test/cert_test_util.h"
30 #include "net/test/gtest_util.h" 33 #include "net/test/gtest_util.h"
31 #include "net/test/test_certificate_data.h" 34 #include "net/test/test_certificate_data.h"
32 #include "net/test/test_data_directory.h" 35 #include "net/test/test_data_directory.h"
33 #include "testing/gmock/include/gmock/gmock.h" 36 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h" 37 #include "testing/gtest/include/gtest/gtest.h"
35 38
36 #if defined(OS_ANDROID) 39 #if defined(OS_ANDROID)
37 #include "base/android/build_info.h" 40 #include "base/android/build_info.h"
38 #endif 41 #endif
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 CertificateList(), &verify_result); 630 CertificateList(), &verify_result);
628 EXPECT_THAT(error, IsOk()); 631 EXPECT_THAT(error, IsOk());
629 EXPECT_EQ(0U, verify_result.cert_status); 632 EXPECT_EQ(0U, verify_result.cert_status);
630 633
631 error = Verify(leaf.get(), "foo.test2.example.com", flags, NULL, 634 error = Verify(leaf.get(), "foo.test2.example.com", flags, NULL,
632 CertificateList(), &verify_result); 635 CertificateList(), &verify_result);
633 EXPECT_THAT(error, IsOk()); 636 EXPECT_THAT(error, IsOk());
634 EXPECT_EQ(0U, verify_result.cert_status); 637 EXPECT_EQ(0U, verify_result.cert_status);
635 } 638 }
636 639
640 // This fixture is for testing the verification of a certificate chain which
641 // has some sort of mismatched signature algorithm (i.e.
642 // Certificate.signatureAlgorithm and TBSCertificate.algorithm are different).
643 //
644 // X509 certificates contain two redundant descriptors for the signature
645 // algorithm. Although RFC 5280 states that they must be the same, in practice
646 // system verifiers don't check this. This can lead to confusion as the
647 // signature itself may be checked using algorithm A, but then subsequent
648 // consumers may inspect the certificate and look at signature algorithm B when
649 // making policy choices.
650 class CertVerifyProcInspectSignatureAlgorithmsTest : public ::testing::Test {
651 protected:
652 // In the test setup, SHA384 is given special treatment as an unknown
653 // algorithm.
654 static constexpr DigestAlgorithm kUnknownDigestAlgorithm =
655 DigestAlgorithm::Sha384;
656
657 struct CertParams {
658 DigestAlgorithm cert_algorithm;
659 DigestAlgorithm tbs_algorithm;
660 };
661
662 // Shorthand for VerifyChain() where only the leaf parameters need
663 // to be specified.
664 WARN_UNUSED_RESULT int VerifyLeaf(DigestAlgorithm cert_algorithm,
665 DigestAlgorithm tbs_algorithm) {
666 return VerifyChain({{cert_algorithm, tbs_algorithm},
667 // Shouldn't matter what root uses.
668 {DigestAlgorithm::Sha1, DigestAlgorithm::Sha256}});
669 }
670
671 // Manufactures a certificate chain where each certificate has the indicated
672 // signature algorithms, and then returns the result of verifying this chain.
673 WARN_UNUSED_RESULT int VerifyChain(
674 const std::vector<CertParams>& chain_params) {
675 auto chain = CreateChain(chain_params);
676 if (!chain) {
677 ADD_FAILURE() << "Failed creating certificate chain";
678 return ERR_UNEXPECTED;
679 }
680
681 int flags = 0;
682 CertVerifyResult dummy_result;
683 CertVerifyResult verify_result;
684
685 scoped_refptr<CertVerifyProc> verify_proc =
686 new MockCertVerifyProc(dummy_result);
687
688 return verify_proc->Verify(chain.get(), "test.example.com", std::string(),
689 flags, NULL, CertificateList(), &verify_result);
690 }
691
692 private:
693 // Overwrites the AlgorithmIdentifier pointed to by |algorithm_sequence| with
694 // |algorithm|. Note this violates the constness of StringPiece.
695 WARN_UNUSED_RESULT static bool SetAlgorithmSequence(
696 DigestAlgorithm algorithm,
697 base::StringPiece* algorithm_sequence) {
698 // This string of bytes is the full SEQUENCE for an AlgorithmIdentifier.
699 std::vector<uint8_t> replacement_sequence;
700 switch (algorithm) {
701 case DigestAlgorithm::Sha1:
702 // sha1WithRSAEncryption
703 replacement_sequence = {0x30, 0x0D, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
704 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00};
705 break;
706 case DigestAlgorithm::Sha256:
707 // sha256WithRSAEncryption
708 replacement_sequence = {0x30, 0x0D, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
709 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00};
710 break;
711 case kUnknownDigestAlgorithm:
712 // This shouldn't be anything meaningful (modified numbers at random).
713 replacement_sequence = {0x30, 0x0D, 0x06, 0x09, 0x8a, 0x87, 0x18, 0x46,
714 0xd7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00};
715 break;
716 default:
717 ADD_FAILURE() << "Unsupported digest algorithm";
718 return false;
719 }
720
721 // For this simple replacement to work (without modifying any
722 // other sequence lengths) the original algorithm and replacement
723 // algorithm must have the same encoded length.
724 if (algorithm_sequence->size() != replacement_sequence.size()) {
725 ADD_FAILURE() << "AlgorithmIdentifier must have length "
726 << replacement_sequence.size();
727 return false;
728 }
729
730 memcpy(const_cast<char*>(algorithm_sequence->data()),
731 replacement_sequence.data(), replacement_sequence.size());
732 return true;
733 }
734
735 // Locate the serial number bytes.
736 WARN_UNUSED_RESULT static bool ExtractSerialNumberFromDERCert(
737 base::StringPiece der_cert,
738 base::StringPiece* serial_value) {
739 der::Parser parser((der::Input(der_cert)));
740 der::Parser certificate;
741 if (!parser.ReadSequence(&certificate))
742 return false;
743
744 der::Parser tbs_certificate;
745 if (!certificate.ReadSequence(&tbs_certificate))
746 return false;
747
748 bool unused;
749 if (!tbs_certificate.SkipOptionalTag(
750 der::kTagConstructed | der::kTagContextSpecific | 0, &unused)) {
751 return false;
752 }
753
754 // serialNumber
755 der::Input serial_value_der;
756 if (!tbs_certificate.ReadTag(der::kInteger, &serial_value_der))
757 return false;
758
759 *serial_value = serial_value_der.AsStringPiece();
760 return true;
761 }
762
763 // Creates a certificate (based on some base certificate file) using the
764 // specified signature algorithms.
765 static scoped_refptr<X509Certificate> CreateCertificate(
766 const CertParams& params) {
767 // Dosn't really matter which base certificate is used, so long as it is
768 // valid and uses a signature AlgorithmIdentifier with the same encoded
769 // length as sha1WithRSASignature.
770 const char* kLeafFilename = "name_constraint_good.pem";
771
772 auto cert = CreateCertificateChainFromFile(
773 GetTestCertsDirectory(), kLeafFilename, X509Certificate::FORMAT_AUTO);
774 if (!cert) {
775 ADD_FAILURE() << "Failed to load certificate: " << kLeafFilename;
776 return nullptr;
777 }
778
779 // Start with the DER bytes of a valid certificate. This will be the basis
780 // for building a modified certificate.
781 std::string cert_der;
782 if (!X509Certificate::GetDEREncoded(cert->os_cert_handle(), &cert_der)) {
783 ADD_FAILURE() << "Failed getting DER bytes";
784 return nullptr;
785 }
786
787 // Parse the certificate and identify the locations of interest within
788 // |cert_der|.
789 base::StringPiece cert_algorithm_sequence;
790 base::StringPiece tbs_algorithm_sequence;
791 if (!asn1::ExtractSignatureAlgorithmsFromDERCert(
792 cert_der, &cert_algorithm_sequence, &tbs_algorithm_sequence)) {
793 ADD_FAILURE() << "Failed parsing certificate algorithms";
794 return nullptr;
795 }
796
797 base::StringPiece serial_value;
798 if (!ExtractSerialNumberFromDERCert(cert_der, &serial_value)) {
799 ADD_FAILURE() << "Failed parsing certificate serial number";
800 return nullptr;
801 }
802
803 // Give the certificate a new serial number -- this is necessary because
804 // otherwise importing it may fail. Changing the high order byte is good
805 // enough for these tests.
806 *const_cast<char*>(serial_value.data()) = next_serial_number_++;
807
808 // Change the signature AlgorithmIdentifiers.
809 if (!SetAlgorithmSequence(params.cert_algorithm,
810 &cert_algorithm_sequence) ||
811 !SetAlgorithmSequence(params.tbs_algorithm, &tbs_algorithm_sequence)) {
812 return nullptr;
813 }
814
815 // NOTE: The signature is NOT recomputed over TBSCertificate -- for these
816 // tests it isn't needed.
817 return X509Certificate::CreateFromBytes(cert_der.data(), cert_der.size());
818 }
819
820 static scoped_refptr<X509Certificate> CreateChain(
821 const std::vector<CertParams>& params) {
822 // Manufacture a chain with the given combinations of signature algorithms.
823 // This chain isn't actually a valid chain, but it is good enough for
824 // testing the base CertVerifyProc.
825 CertificateList certs;
826 for (const auto& cert_params : params) {
827 certs.push_back(CreateCertificate(cert_params));
828 if (!certs.back())
829 return nullptr;
830 }
831
832 X509Certificate::OSCertHandles intermediates;
833 for (size_t i = 1; i < certs.size(); ++i)
834 intermediates.push_back(certs[i]->os_cert_handle());
835
836 return X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(),
837 intermediates);
838 }
839
840 static int next_serial_number_;
841 };
842
843 // Global counter to ensure that during test runs the same issuer/serialnumber
844 // isn't used when manufacturing certificates.
845 int CertVerifyProcInspectSignatureAlgorithmsTest::next_serial_number_ = 9;
846
847 // This is a control test to make sure that the test helper
848 // VerifyLeaf() works as expected. There is no actual mismatch in the
849 // algorithms used here.
850 //
851 // Certificate.signatureAlgorithm: sha1WithRSASignature
852 // TBSCertificate.algorithm: sha1WithRSAEncryption
853 TEST_F(CertVerifyProcInspectSignatureAlgorithmsTest, LeafSha1Sha1) {
854 int rv = VerifyLeaf(DigestAlgorithm::Sha1, DigestAlgorithm::Sha1);
855 ASSERT_THAT(rv, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM));
856 }
857
858 // This is a control test to make sure that the test helper
859 // VerifyLeaf() works as expected. There is no actual mismatch in the
860 // algorithms used here.
861 //
862 // Certificate.signatureAlgorithm: sha256WithRSASignature
863 // TBSCertificate.algorithm: sha256WithRSAEncryption
864 TEST_F(CertVerifyProcInspectSignatureAlgorithmsTest, LeafSha256Sha256) {
865 int rv = VerifyLeaf(DigestAlgorithm::Sha256, DigestAlgorithm::Sha256);
866 ASSERT_THAT(rv, IsOk());
867 }
868
869 // Mismatched signature algorithms in the leaf certificate.
870 //
871 // Certificate.signatureAlgorithm: sha1WithRSASignature
872 // TBSCertificate.algorithm: sha256WithRSAEncryption
873 TEST_F(CertVerifyProcInspectSignatureAlgorithmsTest, LeafSha1Sha256) {
874 int rv = VerifyLeaf(DigestAlgorithm::Sha1, DigestAlgorithm::Sha256);
875 ASSERT_THAT(rv, IsError(ERR_CERT_INVALID));
876 }
877
878 // Mismatched signature algorithms in the leaf certificate.
879 //
880 // Certificate.signatureAlgorithm: sha256WithRSAEncryption
881 // TBSCertificate.algorithm: sha1WithRSASignature
882 TEST_F(CertVerifyProcInspectSignatureAlgorithmsTest, LeafSha256Sha1) {
883 int rv = VerifyLeaf(DigestAlgorithm::Sha256, DigestAlgorithm::Sha1);
884 ASSERT_THAT(rv, IsError(ERR_CERT_INVALID));
885 }
886
887 // Mismatched signature algorithms in the intermediate certificate.
888 //
889 // Certificate.signatureAlgorithm: sha1WithRSASignature
890 // TBSCertificate.algorithm: sha256WithRSAEncryption
891 TEST_F(CertVerifyProcInspectSignatureAlgorithmsTest, IntermediateSha1Sha256) {
892 int rv = VerifyChain({{DigestAlgorithm::Sha256, DigestAlgorithm::Sha256},
893 {DigestAlgorithm::Sha1, DigestAlgorithm::Sha256},
894 {DigestAlgorithm::Sha256, DigestAlgorithm::Sha256}});
895 ASSERT_THAT(rv, IsError(ERR_CERT_INVALID));
896 }
897
898 // Mismatched signature algorithms in the intermediate certificate.
899 //
900 // Certificate.signatureAlgorithm: sha256WithRSAEncryption
901 // TBSCertificate.algorithm: sha1WithRSASignature
902 TEST_F(CertVerifyProcInspectSignatureAlgorithmsTest, IntermediateSha256Sha1) {
903 int rv = VerifyChain({{DigestAlgorithm::Sha256, DigestAlgorithm::Sha256},
904 {DigestAlgorithm::Sha256, DigestAlgorithm::Sha1},
905 {DigestAlgorithm::Sha256, DigestAlgorithm::Sha256}});
906 ASSERT_THAT(rv, IsError(ERR_CERT_INVALID));
907 }
908
909 // Unrecognized signature algorithm in the leaf certificate.
910 //
911 // Certificate.signatureAlgorithm: sha256WithRSAEncryption
912 // TBSCertificate.algorithm: ?
913 TEST_F(CertVerifyProcInspectSignatureAlgorithmsTest, LeafSha256Unknown) {
914 int rv = VerifyLeaf(DigestAlgorithm::Sha256, kUnknownDigestAlgorithm);
915 ASSERT_THAT(rv, IsError(ERR_CERT_INVALID));
916 }
917
918 // Unrecognized signature algorithm in the leaf certificate.
919 //
920 // Certificate.signatureAlgorithm: ?
921 // TBSCertificate.algorithm: sha256WithRSAEncryption
922 TEST_F(CertVerifyProcInspectSignatureAlgorithmsTest, LeafUnknownSha256) {
923 int rv = VerifyLeaf(kUnknownDigestAlgorithm, DigestAlgorithm::Sha256);
924 ASSERT_THAT(rv, IsError(ERR_CERT_INVALID));
925 }
926
637 TEST_P(CertVerifyProcInternalTest, NameConstraintsFailure) { 927 TEST_P(CertVerifyProcInternalTest, NameConstraintsFailure) {
638 if (!SupportsReturningVerifiedChain()) { 928 if (!SupportsReturningVerifiedChain()) {
639 LOG(INFO) << "Skipping this test in this platform."; 929 LOG(INFO) << "Skipping this test in this platform.";
640 return; 930 return;
641 } 931 }
642 932
643 CertificateList ca_cert_list = 933 CertificateList ca_cert_list =
644 CreateCertificateListFromFile(GetTestCertsDirectory(), "root_ca_cert.pem", 934 CreateCertificateListFromFile(GetTestCertsDirectory(), "root_ca_cert.pem",
645 X509Certificate::FORMAT_AUTO); 935 X509Certificate::FORMAT_AUTO);
646 ASSERT_EQ(1U, ca_cert_list.size()); 936 ASSERT_EQ(1U, ca_cert_list.size());
(...skipping 1249 matching lines...) Expand 10 before | Expand all | Expand 10 after
1896 int flags = 0; 2186 int flags = 0;
1897 CertVerifyResult verify_result; 2187 CertVerifyResult verify_result;
1898 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, 2188 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags,
1899 NULL, CertificateList(), &verify_result); 2189 NULL, CertificateList(), &verify_result);
1900 EXPECT_EQ(OK, error); 2190 EXPECT_EQ(OK, error);
1901 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); 2191 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0);
1902 histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); 2192 histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0);
1903 } 2193 }
1904 2194
1905 } // namespace net 2195 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698