@@ -191,7 +191,7 @@ ccf::crypto::Pem generate_self_signed_cert(
191191 constexpr size_t certificate_validity_period_days = 365 ;
192192 using namespace std ::literals;
193193 auto valid_from =
194- ccf::ds::to_x509_time_string (std::chrono::system_clock ::now () - 24h);
194+ ccf::ds::to_x509_time_string (ccf::nonstd::SystemClock ::now () - 24h);
195195
196196 return ccf::crypto::create_self_signed_cert (
197197 kp, name, {}, valid_from, certificate_validity_period_days);
@@ -750,6 +750,11 @@ TEST_CASE("Non-ASN.1 timepoint formats")
750750 conv = ccf::ds::to_x509_time_string (tp);
751751 REQUIRE (conv == " 20220405215327Z" );
752752
753+ time_str = " 2026-02-09 05:00:00 -03:30" ;
754+ tp = ccf::ds::time_point_from_string (time_str);
755+ conv = ccf::ds::to_x509_time_string (tp);
756+ REQUIRE (conv == " 20260209083000Z" );
757+
753758 time_str = " 2022-04-07T10:37:49.567612" ;
754759 tp = ccf::ds::time_point_from_string (time_str);
755760 conv = ccf::ds::to_x509_time_string (tp);
@@ -781,6 +786,91 @@ TEST_CASE("Non-ASN.1 timepoint formats")
781786 REQUIRE (conv == " 20220425195619Z" );
782787}
783788
789+ TEST_CASE (" Timepoint bounds" )
790+ {
791+ // Can handle values beyond bounds of system_clock::time_point
792+ {
793+ INFO (" Beyond system_clock::time_point min" );
794+ auto time_str = " 1677-09-21 00:12:44" ;
795+ auto tp = ccf::ds::time_point_from_string (time_str);
796+ auto conv = ccf::ds::to_x509_time_string (tp);
797+ REQUIRE (conv == " 16770921001244Z" );
798+
799+ time_str = " 1677-09-21 00:12:43" ;
800+ tp = ccf::ds::time_point_from_string (time_str);
801+ conv = ccf::ds::to_x509_time_string (tp);
802+ REQUIRE (conv == " 16770921001243Z" );
803+ }
804+
805+ {
806+ INFO (" Beyond system_clock::time_point max" );
807+ auto time_str = " 2262-04-11 23:47:16" ;
808+ auto tp = ccf::ds::time_point_from_string (time_str);
809+ auto conv = ccf::ds::to_x509_time_string (tp);
810+ REQUIRE (conv == " 22620411234716Z" );
811+
812+ time_str = " 2262-04-11 23:47:17" ;
813+ tp = ccf::ds::time_point_from_string (time_str);
814+ conv = ccf::ds::to_x509_time_string (tp);
815+ CHECK (conv == " 22620411234717Z" );
816+ }
817+
818+ {
819+ INFO (" Approx ASN.1 format bounds" );
820+ auto time_str = " 9999-12-31 23:59:59" ;
821+ auto tp = ccf::ds::time_point_from_string (time_str);
822+ auto conv = ccf::ds::to_x509_time_string (tp);
823+ REQUIRE (conv == " 99991231235959Z" );
824+
825+ INFO (" sscanf variants of near-min value" );
826+ for (auto time_str : {
827+ " 0001-02-03 04:05:06" ,
828+ " 0001-02-03 04:05:06.700000 +0:00" ,
829+ " 0001-02-03 12:14:06.700000 +8:09" ,
830+ " 0001-02-02 19:56:06.700000 -8:09" ,
831+
832+ " 0001-02-03T04:05:06.700000 +0:00" ,
833+ " 0001-02-03T12:14:06.700000 +8:09" ,
834+ " 0001-02-02T19:56:06.700000 -8:09" ,
835+
836+ " 0001-02-03 04:05:06.700000 +00 00" ,
837+ " 0001-02-03 12:14:06.700000 +08:09" ,
838+ " 0001-02-02 19:56:06.700000 -08:09" ,
839+
840+ " 00010203040506.700000+0000" ,
841+ " 00010203121406.700000+0809" ,
842+ " 00010202195606.700000-0809" ,
843+
844+ " 0001-02-03T04:05:06.700000" ,
845+ " 0001-02-03 04:05:06.700000" ,
846+ })
847+ {
848+ tp = ccf::ds::time_point_from_string (time_str);
849+ conv = ccf::ds::to_x509_time_string (tp);
850+ CHECK (conv == " 00010203040506Z" );
851+ }
852+ }
853+ }
854+
855+ TEST_CASE (" Invalid times" )
856+ {
857+ REQUIRE_THROWS_WITH (
858+ ccf::ds::time_point_from_string (" hello" ),
859+ " 'hello' does not match any accepted time format" );
860+
861+ REQUIRE_THROWS_WITH (
862+ ccf::ds::time_point_from_string (" Monday" ),
863+ " 'Monday' does not match any accepted time format" );
864+
865+ REQUIRE_THROWS_WITH (
866+ ccf::ds::time_point_from_string (" April 1st, 1984" ),
867+ " 'April 1st, 1984' does not match any accepted time format" );
868+
869+ REQUIRE_THROWS_WITH (
870+ ccf::ds::time_point_from_string (" 1111-1111" ),
871+ " '1111-1111' does not match any accepted time format" );
872+ }
873+
784874TEST_CASE (" Create sign and verify certificates" )
785875{
786876 bool corrupt_csr = false ;
@@ -885,7 +975,7 @@ TEST_CASE("AES-GCM convenience functions")
885975
886976TEST_CASE (" x509 time" )
887977{
888- auto time = std::chrono::system_clock ::now ();
978+ auto time = ccf::nonstd::SystemClock ::now ();
889979
890980 auto next_minute_time = time + 1min;
891981 auto next_day_time = time + 24h;
@@ -897,8 +987,8 @@ TEST_CASE("x509 time")
897987 {
898988 struct Input
899989 {
900- std::chrono::system_clock ::time_point from;
901- std::chrono::system_clock ::time_point to;
990+ ccf::nonstd::SystemClock ::time_point from;
991+ ccf::nonstd::SystemClock ::time_point to;
902992 std::optional<uint32_t > maximum_validity_period_days = std::nullopt ;
903993 };
904994 Input input;
@@ -933,7 +1023,7 @@ TEST_CASE("x509 time")
9331023
9341024 INFO (" Adjust time" );
9351025 {
936- std::vector<std::chrono::system_clock ::time_point> times = {
1026+ std::vector<ccf::nonstd::SystemClock ::time_point> times = {
9371027 time, next_day_time, next_day_time};
9381028 size_t days_offset = 100 ;
9391029
@@ -1415,7 +1505,7 @@ TEST_CASE("Do not trust non-ca certs")
14151505 constexpr size_t certificate_validity_period_days = 365 ;
14161506 using namespace std ::literals;
14171507 auto valid_from =
1418- ccf::ds::to_x509_time_string (std::chrono::system_clock ::now () - 24h);
1508+ ccf::ds::to_x509_time_string (ccf::nonstd::SystemClock ::now () - 24h);
14191509 auto valid_to = compute_cert_valid_to_string (
14201510 valid_from, certificate_validity_period_days);
14211511 std::vector<SubjectAltName> subject_alt_names = {};
0 commit comments