From 4960eb519efae1dcc919698fa4e4547854d0e41d Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Thu, 11 Apr 2019 20:58:56 -0400 Subject: Support verifying from a v1 root Discovered in #1885, the "Verisign Class 3 Public Primary Certification Authority - G3" is a v1 certificate and is still included in distro trust stores. --- src/lib/x509/x509cert.cpp | 9 +++++ src/tests/data/x509/misc/v1ca/ee.pem | 39 ++++++++++++++++++++++ src/tests/data/x509/misc/v1ca/int.pem | 30 +++++++++++++++++ src/tests/data/x509/misc/v1ca/root.pem | 24 ++++++++++++++ src/tests/test_x509_path.cpp | 60 +++++++++++++++++++++++++++++++++- 5 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 src/tests/data/x509/misc/v1ca/ee.pem create mode 100644 src/tests/data/x509/misc/v1ca/int.pem create mode 100644 src/tests/data/x509/misc/v1ca/root.pem (limited to 'src') diff --git a/src/lib/x509/x509cert.cpp b/src/lib/x509/x509cert.cpp index 5afbcc815..dda15835e 100644 --- a/src/lib/x509/x509cert.cpp +++ b/src/lib/x509/x509cert.cpp @@ -201,10 +201,13 @@ std::unique_ptr parse_x509_cert_body(const X509_Object& o if(v3_exts_data.is_a(3, ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))) { + // Path validation will reject a v1/v2 cert with v3 extensions BER_Decoder(v3_exts_data).decode(data->m_v3_extensions).verify_end(); } else if(v3_exts_data.is_set()) + { throw BER_Bad_Tag("Unknown tag in X.509 cert", v3_exts_data.tagging()); + } // Now cache some fields from the extensions if(auto ext = data->m_v3_extensions.get_extension_object_as()) @@ -442,11 +445,17 @@ const std::vector& X509_Certificate::raw_subject_dn() const bool X509_Certificate::is_CA_cert() const { + if(data().m_version < 3 && data().m_self_signed) + return true; + return data().m_is_ca_certificate; } uint32_t X509_Certificate::path_limit() const { + if(data().m_version < 3 && data().m_self_signed) + return 32; // in theory infinite, but this is more than enough + return static_cast(data().m_path_len_constraint); } diff --git a/src/tests/data/x509/misc/v1ca/ee.pem b/src/tests/data/x509/misc/v1ca/ee.pem new file mode 100644 index 000000000..5c31e9a03 --- /dev/null +++ b/src/tests/data/x509/misc/v1ca/ee.pem @@ -0,0 +1,39 @@ +-----BEGIN CERTIFICATE----- +MIIG4jCCBcqgAwIBAgIQYy9GA8UA5qlx5vrqipbPVzANBgkqhkiG9w0BAQsFADB+ +MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd +BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVj +IENsYXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MB4XDTE3MDIwMTAwMDAwMFoX +DTIwMDIwMTIzNTk1OVowdzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3Ju +aWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHTAbBgNVBAoMFFN5bWFudGVjIENv +cnBvcmF0aW9uMRwwGgYDVQQDDBNzc2x0ZXN0My5iYnRlc3QubmV0MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAscaHBWE2Nf8BRzp6eNgK+Ta661anmssg +kopOdX+ZtrKhPXWVqdrNos+Ceq0Wzbjb/TE9VJ552smUS1I0ciOhyQtXOkT4c+KT +/ZYSZpMssgTHnXnjPxvZuX/A973R3WbITnZkQiPxncJCgDs45WnJd2k8zmd4kNUR +5LQHfBlY/+XuWG6vbhOn7I1pw0wdeoe04bCW2iKIp23275+uiLXiDTdQzD9WySjM +vDNi7Qm1vPmHPSugXouJZKsQxzyu8vAxB5OGc22i6sxtQHksZril6xPnsplXnRQt +cCvMZFwBXcyj9u2ySkeGYyPdfe7NWW9hIBCS3yZcyL/TG02Qk2ltVwIDAQABo4ID +YTCCA10wHgYDVR0RBBcwFYITc3NsdGVzdDMuYmJ0ZXN0Lm5ldDAJBgNVHRMEAjAA +MA4GA1UdDwEB/wQEAwIFoDArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vc3Muc3lt +Y2IuY29tL3NzLmNybDBhBgNVHSAEWjBYMFYGBmeBDAECAjBMMCMGCCsGAQUFBwIB +FhdodHRwczovL2Quc3ltY2IuY29tL2NwczAlBggrBgEFBQcCAjAZDBdodHRwczov +L2Quc3ltY2IuY29tL3JwYTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw +HwYDVR0jBBgwFoAUX2DPYZBV34RDFIpgKrL1evRDGO8wVwYIKwYBBQUHAQEESzBJ +MB8GCCsGAQUFBzABhhNodHRwOi8vc3Muc3ltY2QuY29tMCYGCCsGAQUFBzAChhpo +dHRwOi8vc3Muc3ltY2IuY29tL3NzLmNydDCCAfUGCisGAQQB1nkCBAIEggHlBIIB +4QHfAHcA3esdK3oNT6Ygi4GtgWhwfi6OnQHVXIiNPRHEzbbsvswAAAFZ+9pGfAAA +BAMASDBGAiEAq3g0UzvqQxdOfvWIbZoLKDW5WEwEV88zMbp8leiGSAsCIQC3cA6n +AgvExoW76LEWD3CtuwoIIi35GliCFgpx2FZkXwB1AKS5CZC0GFgUh7sTosxncAo8 +NZgE+RvfuON3zQ7IDdwQAAABWfvaRrcAAAQDAEYwRAIgK1Y5HoYVBb/8lbkwSpbv +d6Fg90+onLC49D1XljNav4gCIERSqXkpjibnfqL/xqv3BRkjpSjk1dhtq+F3F0Ip ++WQDAHUA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFZ+9pIawAA +BAMARjBEAiASOkJKxLMhxlntlK4YVse3c87mt9soN924flewVLiy9wIgbtKZM+Ub +yoyRKHQHJ/qlzN7ynv1AqYjOFGYOsDgyIIkAdgC8eOHfxfY8aEZJM02hD6FfCXlp +IAnAgbTz9pF/Ptm4pQAAAVn72kdyAAAEAwBHMEUCIDsqjiwtIIBy03n+vUplSyEd +r8rt/ZIQy1HgGRgpGB/9AiEAn9v1ZDa27SSBS9yShGuZYV+zZPM835ePfzwlQKSK +XFEwDQYJKoZIhvcNAQELBQADggEBAAjzN4oQGQuocJm45D3b34dhAZ/VoMe3MOAO +saz/5ExO2/2HkULoOv8Y6poVxCdMYVbeNn3Bw1KE+LKmQUuVRgdTaq1RntkE3yGq +FlsrRfxQyx3JLTJLBYOS2iuY8xhWHhFVRBoOCgsqWc2jjaftWmShIbWMuER//Sx9 +t+10b8HJ++KLD2g4WwZ8j15HEI1m+pAREmB/Kem/Ntfp39JDP8lW0hZkYH7iBvli +MrA6bHwrkdZgQ96yS5Xe6At+FeyKKn3h1sATdByfA3EWxEnMM3MPe6mC5HTEtUDb +u0cIInAO4BrmIdxFWWFmJntBbilmVpXfF+MVOzEwuxl51OAjNmI= +-----END CERTIFICATE----- diff --git a/src/tests/data/x509/misc/v1ca/int.pem b/src/tests/data/x509/misc/v1ca/int.pem new file mode 100644 index 000000000..b5a83a706 --- /dev/null +++ b/src/tests/data/x509/misc/v1ca/int.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFFTCCA/2gAwIBAgIQKC4nkXkzkuQo8iGnTsk3rjANBgkqhkiG9w0BAQsFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMTk5OSBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzMwHhcNMTMxMDMxMDAwMDAwWhcNMjMxMDMwMjM1OTU5WjB+MQsw +CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV +BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVjIENs +YXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAstgFyhx0LbUXVjnFSlIJluhL2AzxaJ+aQihiw6UwU35VEYJb +A3oNL+F5BMm0lncZgQGUWfm893qZJ4Itt4PdWid/sgN6nFMl6UgfRk/InSn4vnlW +9vf92Tpo2otLgjNBEsPIPMzWlnqEIRoiBAMnF4scaGGTDw5RgDMdtLXO637QYqzu +s3sBdO9pNevK1T2p7peYyo2qRA4lmUoVlqTObQJUHypqJuIGOmNIrLRM0XWTUP8T +L9ba4cYY9Z/JJV3zADreJk20KQnNDz0jbxZKgRb78oMQw7jW2FUyPfG9D72MUpVK +Fpd6UiFjdS8W+cRmvvW1Cdj/JwDNRHxvSz+w9wIDAQABo4IBQDCCATwwHQYDVR0O +BBYEFF9gz2GQVd+EQxSKYCqy9Xr0QxjvMBIGA1UdEwEB/wQIMAYBAf8CAQAwawYD +VR0gBGQwYjBgBgpghkgBhvhFAQc2MFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cu +c3ltYXV0aC5jb20vY3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6Ly93d3cuc3ltYXV0 +aC5jb20vcnBhMC8GA1UdHwQoMCYwJKAioCCGHmh0dHA6Ly9zLnN5bWNiLmNvbS9w +Y2EzLWczLmNybDAOBgNVHQ8BAf8EBAMCAQYwKQYDVR0RBCIwIKQeMBwxGjAYBgNV +BAMTEVN5bWFudGVjUEtJLTEtNTM0MC4GCCsGAQUFBwEBBCIwIDAeBggrBgEFBQcw +AYYSaHR0cDovL3Muc3ltY2QuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBbF1K+1lZ7 +9Pc0CUuWysf2IdBpgO/nmhnoJOJ/2S9h3RPrWmXk4WqQy04q6YoW51KN9kMbRwUN +gKOomv4p07wdKNWlStRxPA91xQtzPwBIZXkNq2oeJQzAAt5mrL1LBmuaV4oqgX5n +m7pSYHPEFfe7wVDJCKW6V0o6GxBzHOF7tpQDS65RsIJAOloknO4NWF2uuil6yjOe +soHCL47BJ89A8AShP/U3wsr8rFNtqVNpT+F2ZAwlgak3A/I5czTSwXx4GByoaxbn +5+CdKa/Y5Gk5eZVpuXtcXQGc1PfzSEUTZJXXCm5y2kMiJG8+WnDcwJLgLeVX+OQr +J+71/xuzAYN6 +-----END CERTIFICATE----- diff --git a/src/tests/data/x509/misc/v1ca/root.pem b/src/tests/data/x509/misc/v1ca/root.pem new file mode 100644 index 000000000..688036446 --- /dev/null +++ b/src/tests/data/x509/misc/v1ca/root.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- diff --git a/src/tests/test_x509_path.cpp b/src/tests/test_x509_path.cpp index 0e9f8eba0..71118ab2f 100644 --- a/src/tests/test_x509_path.cpp +++ b/src/tests/test_x509_path.cpp @@ -482,7 +482,65 @@ std::vector PSS_Path_Validation_Tests::run() BOTAN_REGISTER_TEST("x509_path_rsa_pss", PSS_Path_Validation_Tests); +class Validate_V1Cert_Test final : public Test + { + public: + std::vector run() override; + }; + +std::vector Validate_V1Cert_Test::run() + { + if(Botan::has_filesystem_impl() == false) + { + return {Test::Result::Note("BSI path validation", + "Skipping due to missing filesystem access")}; + } + + std::vector results; + + const std::string root_crt = Test::data_file("/x509/misc/v1ca/root.pem"); + const std::string int_crt = Test::data_file("/x509/misc/v1ca/int.pem"); + const std::string ee_crt = Test::data_file("/x509/misc/v1ca/ee.pem"); + + auto validation_time = + Botan::calendar_point(2019, 4, 19, 23, 0, 0).to_std_timepoint(); + + Botan::X509_Certificate root(root_crt); + Botan::X509_Certificate intermediate(int_crt); + Botan::X509_Certificate ee_cert(ee_crt); + + Botan::Certificate_Store_In_Memory trusted; + trusted.add_certificate(root); + + std::vector chain = { ee_cert, intermediate }; + + Botan::Path_Validation_Restrictions restrictions; + Botan::Path_Validation_Result validation_result = + Botan::x509_path_validate(chain, restrictions, trusted, "", + Botan::Usage_Type::UNSPECIFIED, validation_time); + + Test::Result result("Verifying using v1 certificate"); + result.test_eq("Path validation result", + validation_result.result_string(), "Verified"); + + Botan::Certificate_Store_In_Memory empty; + + std::vector new_chain = { ee_cert, intermediate, root }; + + Botan::Path_Validation_Result validation_result2 = + Botan::x509_path_validate(new_chain, restrictions, empty, "", + Botan::Usage_Type::UNSPECIFIED, validation_time); + + result.test_eq("Path validation result", + validation_result2.result_string(), "Cannot establish trust"); + + return {result}; + } + +BOTAN_REGISTER_TEST("x509_v1_ca", Validate_V1Cert_Test); + class BSI_Path_Validation_Tests final : public Test + { public: std::vector run() override; @@ -532,7 +590,7 @@ std::vector BSI_Path_Validation_Tests::run() std::vector certs; auto validation_time = - Botan::calendar_point(2017, 8, 19, 12, 0, 0).to_std_timepoint(); + Botan::calendar_point(2017, 8, 19, 12, 0, 0).to_std_timepoint(); // By convention: if CRL is a substring if the directory name, // we need to check the CRLs -- cgit v1.2.3