diff options
author | Jack Lloyd <[email protected]> | 2016-10-21 16:44:10 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-10-21 16:44:10 -0400 |
commit | 6aa855bba613c7b6fedfbe71d15930964acb1633 (patch) | |
tree | 2365c5a5bba8d77c5703e036c111dbeeb317cde3 | |
parent | 6ceeab949aae9d53914838c542e7b156c80b4b57 (diff) |
Allow setting the validation time during PKIX path validation
Previously validation asked the system clock which is not always
the correct thing (for example when using Roughtime protocol).
Had been on the todo list forever, forced into it by some of
the test certs expiring today.
-rw-r--r-- | src/lib/cert/x509/x509path.cpp | 34 | ||||
-rw-r--r-- | src/lib/cert/x509/x509path.h | 13 | ||||
-rw-r--r-- | src/tests/test_x509_path.cpp | 6 |
3 files changed, 34 insertions, 19 deletions
diff --git a/src/lib/cert/x509/x509path.cpp b/src/lib/cert/x509/x509path.cpp index a0cae2c93..f0b07e5fc 100644 --- a/src/lib/cert/x509/x509path.cpp +++ b/src/lib/cert/x509/x509path.cpp @@ -77,13 +77,14 @@ std::shared_ptr<const X509_CRL> find_crls_for(const X509_Certificate& cert, std::vector<std::set<Certificate_Status_Code>> check_chain(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path, const Path_Validation_Restrictions& restrictions, - const std::vector<Certificate_Store*>& certstores) + const std::vector<Certificate_Store*>& certstores, + std::chrono::system_clock::time_point ref_time) { const std::set<std::string>& trusted_hashes = restrictions.trusted_hashes(); const bool self_signed_ee_cert = (cert_path.size() == 1); - X509_Time current_time(std::chrono::system_clock::now()); + X509_Time validation_time(ref_time); std::vector<std::future<OCSP::Response>> ocsp_responses; @@ -109,10 +110,10 @@ check_chain(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_pat } // Check all certs for valid time range - if(current_time < X509_Time(subject->start_time(), ASN1_Tag::UTC_OR_GENERALIZED_TIME)) + if(validation_time < X509_Time(subject->start_time(), ASN1_Tag::UTC_OR_GENERALIZED_TIME)) status.insert(Certificate_Status_Code::CERT_NOT_YET_VALID); - if(current_time > X509_Time(subject->end_time(), ASN1_Tag::UTC_OR_GENERALIZED_TIME)) + if(validation_time > X509_Time(subject->end_time(), ASN1_Tag::UTC_OR_GENERALIZED_TIME)) status.insert(Certificate_Status_Code::CERT_HAS_EXPIRED); // Check issuer constraints @@ -198,10 +199,10 @@ check_chain(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_pat if(!ca->allowed_usage(CRL_SIGN)) status.insert(Certificate_Status_Code::CA_CERT_NOT_FOR_CRL_ISSUER); - if(current_time < X509_Time(crl.this_update())) + if(validation_time < X509_Time(crl.this_update())) status.insert(Certificate_Status_Code::CRL_NOT_YET_VALID); - if(current_time > X509_Time(crl.next_update())) + if(validation_time > X509_Time(crl.next_update())) status.insert(Certificate_Status_Code::CRL_HAS_EXPIRED); if(crl.check_signature(ca->subject_public_key()) == false) @@ -224,7 +225,8 @@ Path_Validation_Result x509_path_validate( const Path_Validation_Restrictions& restrictions, const std::vector<Certificate_Store*>& certstores, const std::string& hostname, - Usage_Type usage) + Usage_Type usage, + std::chrono::system_clock::time_point validation_time) { if(end_certs.empty()) throw Invalid_Argument("x509_path_validate called with no subjects"); @@ -259,7 +261,8 @@ Path_Validation_Result x509_path_validate( cert_path.push_back(cert); } - std::vector<std::set<Certificate_Status_Code>> res = check_chain(cert_path, restrictions, certstores); + std::vector<std::set<Certificate_Status_Code>> res = + check_chain(cert_path, restrictions, certstores, validation_time); if(!hostname.empty() && !cert_path[0]->matches_dns_name(hostname)) res[0].insert(Certificate_Status_Code::CERT_NAME_NOMATCH); @@ -275,11 +278,12 @@ Path_Validation_Result x509_path_validate( const Path_Validation_Restrictions& restrictions, const std::vector<Certificate_Store*>& certstores, const std::string& hostname, - Usage_Type usage) + Usage_Type usage, + std::chrono::system_clock::time_point when) { std::vector<X509_Certificate> certs; certs.push_back(end_cert); - return x509_path_validate(certs, restrictions, certstores, hostname, usage); + return x509_path_validate(certs, restrictions, certstores, hostname, usage, when); } Path_Validation_Result x509_path_validate( @@ -287,12 +291,13 @@ Path_Validation_Result x509_path_validate( const Path_Validation_Restrictions& restrictions, const Certificate_Store& store, const std::string& hostname, - Usage_Type usage) + Usage_Type usage, + std::chrono::system_clock::time_point when) { std::vector<Certificate_Store*> certstores; certstores.push_back(const_cast<Certificate_Store*>(&store)); - return x509_path_validate(end_certs, restrictions, certstores, hostname, usage); + return x509_path_validate(end_certs, restrictions, certstores, hostname, usage, when); } Path_Validation_Result x509_path_validate( @@ -300,7 +305,8 @@ Path_Validation_Result x509_path_validate( const Path_Validation_Restrictions& restrictions, const Certificate_Store& store, const std::string& hostname, - Usage_Type usage) + Usage_Type usage, + std::chrono::system_clock::time_point when) { std::vector<X509_Certificate> certs; certs.push_back(end_cert); @@ -308,7 +314,7 @@ Path_Validation_Result x509_path_validate( std::vector<Certificate_Store*> certstores; certstores.push_back(const_cast<Certificate_Store*>(&store)); - return x509_path_validate(certs, restrictions, certstores, hostname, usage); + return x509_path_validate(certs, restrictions, certstores, hostname, usage, when); } Path_Validation_Restrictions::Path_Validation_Restrictions(bool require_rev, diff --git a/src/lib/cert/x509/x509path.h b/src/lib/cert/x509/x509path.h index 362f65852..b33069f72 100644 --- a/src/lib/cert/x509/x509path.h +++ b/src/lib/cert/x509/x509path.h @@ -12,6 +12,7 @@ #include <botan/x509cert.h> #include <botan/certstor.h> #include <set> +#include <chrono> namespace Botan { @@ -175,7 +176,8 @@ Path_Validation_Result BOTAN_DLL x509_path_validate( const Path_Validation_Restrictions& restrictions, const std::vector<Certificate_Store*>& certstores, const std::string& hostname = "", - Usage_Type usage = Usage_Type::UNSPECIFIED); + Usage_Type usage = Usage_Type::UNSPECIFIED, + std::chrono::system_clock::time_point validation_time = std::chrono::system_clock::now()); /** * PKIX Path Validation @@ -191,7 +193,8 @@ Path_Validation_Result BOTAN_DLL x509_path_validate( const Path_Validation_Restrictions& restrictions, const std::vector<Certificate_Store*>& certstores, const std::string& hostname = "", - Usage_Type usage = Usage_Type::UNSPECIFIED); + Usage_Type usage = Usage_Type::UNSPECIFIED, + std::chrono::system_clock::time_point validation_time = std::chrono::system_clock::now()); /** * PKIX Path Validation @@ -207,7 +210,8 @@ Path_Validation_Result BOTAN_DLL x509_path_validate( const Path_Validation_Restrictions& restrictions, const Certificate_Store& store, const std::string& hostname = "", - Usage_Type usage = Usage_Type::UNSPECIFIED); + Usage_Type usage = Usage_Type::UNSPECIFIED, + std::chrono::system_clock::time_point validation_time = std::chrono::system_clock::now()); /** * PKIX Path Validation @@ -223,7 +227,8 @@ Path_Validation_Result BOTAN_DLL x509_path_validate( const Path_Validation_Restrictions& restrictions, const Certificate_Store& store, const std::string& hostname = "", - Usage_Type usage = Usage_Type::UNSPECIFIED); + Usage_Type usage = Usage_Type::UNSPECIFIED, + std::chrono::system_clock::time_point validation_time = std::chrono::system_clock::now()); } diff --git a/src/tests/test_x509_path.cpp b/src/tests/test_x509_path.cpp index 96cc7a190..ae52de541 100644 --- a/src/tests/test_x509_path.cpp +++ b/src/tests/test_x509_path.cpp @@ -8,6 +8,7 @@ #if defined(BOTAN_HAS_X509_CERTIFICATES) #include <botan/x509path.h> + #include <botan/calendar.h> #include <botan/internal/filesystem.h> #endif @@ -70,6 +71,8 @@ class X509test_Path_Validation_Tests : public Test Botan::Certificate_Store_In_Memory trusted; trusted.add_certificate(root); + auto validation_time = Botan::calendar_point(2016,10,21,4,20,0).to_std_timepoint(); + for(auto i = expected.begin(); i != expected.end(); ++i) { Test::Result result("X509test path validation"); @@ -84,7 +87,8 @@ class X509test_Path_Validation_Tests : public Test Botan::Path_Validation_Result path_result = Botan::x509_path_validate( certs, default_restrictions, trusted, - "www.tls.test", Botan::Usage_Type::TLS_SERVER_AUTH); + "www.tls.test", Botan::Usage_Type::TLS_SERVER_AUTH, + validation_time); if(path_result.successful_validation() && path_result.trust_root() != root) path_result = Botan::Path_Validation_Result(Botan::Certificate_Status_Code::CANNOT_ESTABLISH_TRUST); |