diff options
-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); |