Skip to content

Commit

Permalink
Modify time handling so X509 is not affected by 2038 issues
Browse files Browse the repository at this point in the history
  • Loading branch information
randombit committed Jan 28, 2025
1 parent 7ecdd08 commit 3a37983
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 26 deletions.
3 changes: 1 addition & 2 deletions src/lib/asn1/asn1_time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,7 @@ std::chrono::system_clock::time_point ASN1_Time::to_std_timepoint() const {
}

uint64_t ASN1_Time::time_since_epoch() const {
auto tp = this->to_std_timepoint();
return std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch()).count();
return calendar_point(m_year, m_month, m_day, m_hour, m_minute, m_second).seconds_since_epoch();
}

/*
Expand Down
32 changes: 9 additions & 23 deletions src/lib/utils/calendar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <botan/internal/calendar.h>

#include <botan/assert.h>
#include <botan/exceptn.h>
#include <ctime>
#include <iomanip>
Expand Down Expand Up @@ -43,7 +44,9 @@ See https://howardhinnant.github.io/date_algorithms.html#days_from_civil
for details and explaination. The code is slightly simplified by our assumption
that the date is at least 1970, which is sufficient for our purposes.
*/
size_t days_since_epoch(uint32_t year, uint32_t month, uint32_t day) {
uint64_t days_since_epoch(uint32_t year, uint32_t month, uint32_t day) {
BOTAN_ARG_CHECK(year >= 1970, "Years before 1970 not supported");

if(month <= 2) {
year -= 1;
}
Expand All @@ -56,29 +59,12 @@ size_t days_since_epoch(uint32_t year, uint32_t month, uint32_t day) {

} // namespace

std::chrono::system_clock::time_point calendar_point::to_std_timepoint() const {
if(year() < 1970) {
throw Invalid_Argument("calendar_point::to_std_timepoint() does not support years before 1970");
}

// 32 bit time_t ends at January 19, 2038
// https://msdn.microsoft.com/en-us/library/2093ets1.aspx
// Throw after 2037 if 32 bit time_t is used

if constexpr(sizeof(std::time_t) == 4) {
if(year() > 2037) {
throw Invalid_Argument("calendar_point::to_std_timepoint() does not support years after 2037 on this system");
}
}

// This upper bound is completely arbitrary
if(year() >= 2400) {
throw Invalid_Argument("calendar_point::to_std_timepoint() does not support years after 2400");
}

const uint64_t seconds_64 =
(days_since_epoch(year(), month(), day()) * 86400) + (hour() * 60 * 60) + (minutes() * 60) + seconds();
uint64_t calendar_point::seconds_since_epoch() const {
return (days_since_epoch(year(), month(), day()) * 86400) + (hour() * 60 * 60) + (minutes() * 60) + seconds();
}

std::chrono::system_clock::time_point calendar_point::to_std_timepoint() const {
const uint64_t seconds_64 = this->seconds_since_epoch();
const time_t seconds_time_t = static_cast<time_t>(seconds_64);

if(seconds_64 - seconds_time_t != 0) {
Expand Down
8 changes: 8 additions & 0 deletions src/lib/utils/calendar.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,16 @@ class BOTAN_TEST_API calendar_point {
*/
calendar_point(const std::chrono::system_clock::time_point& time_point);

/**
* Return seconds since epoch
*/
uint64_t seconds_since_epoch() const;

/**
* Returns an STL timepoint object
*
* Note this throws an exception if the time is not representable
* in the system time_t
*/
std::chrono::system_clock::time_point to_std_timepoint() const;

Expand Down
7 changes: 6 additions & 1 deletion src/tests/data/dates.vec
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Date = 1970,01,01,0,0,0
Date = 1998,04,23,14,37,28
Date = 2037,12,31,23,59,59
Date = 2038,01,19,3,14,7

[valid.not_std]
# these dates are valid but not representable as a std::system_clock::time_point
Expand All @@ -12,8 +13,12 @@ Date = 1969,12,31,23,59,59

[valid.64_bit_time_t]
# only valid if 64 bit std::time_t is used
Date = 2038,01,01,0,0,0
Date = 2038,01,19,3,14,8
Date = 2083,05,20,8,30,9
Date = 2200,07,04,19,30,0

# 2262 problem
Date = 2262,04,11,23,47,16

[invalid]
#Date = 2037,12,32,24,59,59
Expand Down

0 comments on commit 3a37983

Please sign in to comment.