Merge pull request #5010 from haydenroche5/asn1_time_diff_2038

Fix year 2038 problem in wolfSSL_ASN1_TIME_diff.
This commit is contained in:
Sean Parkinson
2022-04-05 07:58:36 +10:00
committed by GitHub
2 changed files with 51 additions and 44 deletions

View File

@ -32169,15 +32169,34 @@ int wolfSSL_ASN1_TIME_check(const WOLFSSL_ASN1_TIME* a)
return WOLFSSL_SUCCESS; return WOLFSSL_SUCCESS;
} }
/*
* From curl.
* time2epoch: time stamp to seconds since epoch in GMT time zone. Similar to
* mktime but for GMT only.
*/
static long long time2epoch(int sec, int min, int hour, int mday, int mon,
int year)
{
static const int monthDaysCumulative [12] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};
int leapDays = year - (mon <= 1);
leapDays = ((leapDays / 4) - (leapDays / 100) + (leapDays / 400) -
(1969 / 4) + (1969 / 100) - (1969 / 400));
return ((((long long) (year - 1970) * 365 + leapDays +
monthDaysCumulative[mon] + mday - 1) * 24 + hour) * 60 + min) * 60 +
sec;
}
int wolfSSL_ASN1_TIME_diff(int *days, int *secs, const WOLFSSL_ASN1_TIME *from, int wolfSSL_ASN1_TIME_diff(int *days, int *secs, const WOLFSSL_ASN1_TIME *from,
const WOLFSSL_ASN1_TIME *to) const WOLFSSL_ASN1_TIME *to)
{ {
#if defined(XMKTIME) && defined(XDIFFTIME)
const int SECS_PER_DAY = 24 * 60 * 60; const int SECS_PER_DAY = 24 * 60 * 60;
struct tm fromTm_s, *fromTm = &fromTm_s; struct tm fromTm_s, *fromTmGmt = &fromTm_s;
struct tm toTm_s, *toTm = &toTm_s; struct tm toTm_s, *toTmGmt = &toTm_s;
time_t fromSecs; time_t currTime;
time_t toSecs; long long fromSecs;
long long toSecs;
double diffSecs; double diffSecs;
struct tm *tmpTs; struct tm *tmpTs;
#if defined(NEED_TMP_TIME) #if defined(NEED_TMP_TIME)
@ -32207,66 +32226,47 @@ int wolfSSL_ASN1_TIME_diff(int *days, int *secs, const WOLFSSL_ASN1_TIME *from,
} }
if (from == NULL) { if (from == NULL) {
fromSecs = wc_Time(0); currTime = wc_Time(0);
fromTm = XGMTIME(&fromSecs, tmpTs); fromTmGmt = XGMTIME(&currTime, tmpTs);
if (fromTm == NULL) { if (fromTmGmt == NULL) {
WOLFSSL_MSG("XGMTIME for from time failed."); WOLFSSL_MSG("XGMTIME for from time failed.");
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
} }
else if (wolfSSL_ASN1_TIME_to_tm(from, fromTm) != WOLFSSL_SUCCESS) { else if (wolfSSL_ASN1_TIME_to_tm(from, fromTmGmt) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Failed to convert from time to struct tm."); WOLFSSL_MSG("Failed to convert from time to struct tm.");
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
#ifdef HAVE_ERRNO_H /* We use time2epoch here instead of XMKTIME to avoid the Year 2038 problem
errno = 0; * on platforms where time_t is 32 bits. struct tm stores the year as years
#endif * since 1900, so we add 1900 to the year. */
fromSecs = XMKTIME(fromTm); fromSecs = time2epoch(fromTmGmt->tm_sec, fromTmGmt->tm_min,
/* Result can be negative due to time zones around UNIX epoch */ fromTmGmt->tm_hour, fromTmGmt->tm_mday,
if (fromSecs == -1 fromTmGmt->tm_mon, fromTmGmt->tm_year + 1900);
#ifdef HAVE_ERRNO_H
/* Double check with errno that -1 is actually an error */
&& errno != 0
#endif
) {
WOLFSSL_MSG("XMKTIME for from time failed.");
return WOLFSSL_FAILURE;
}
if (to == NULL) { if (to == NULL) {
toSecs = wc_Time(0); currTime = wc_Time(0);
toTm = XGMTIME(&toSecs, tmpTs); toTmGmt = XGMTIME(&currTime, tmpTs);
if (toTm == NULL) { if (toTmGmt == NULL) {
WOLFSSL_MSG("XGMTIME for to time failed."); WOLFSSL_MSG("XGMTIME for to time failed.");
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
} }
else if (wolfSSL_ASN1_TIME_to_tm(to, toTm) != WOLFSSL_SUCCESS) { else if (wolfSSL_ASN1_TIME_to_tm(to, toTmGmt) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Failed to convert to time to struct tm."); WOLFSSL_MSG("Failed to convert to time to struct tm.");
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
toSecs = XMKTIME(toTm); toSecs = time2epoch(toTmGmt->tm_sec, toTmGmt->tm_min, toTmGmt->tm_hour,
/* Result can be negative due to time zones around UNIX epoch */ toTmGmt->tm_mday, toTmGmt->tm_mon,
if (toSecs == -1 toTmGmt->tm_year + 1900);
#ifdef HAVE_ERRNO_H
/* Double check with errno that -1 is actually an error */
&& errno != 0
#endif
) {
WOLFSSL_MSG("XMKTIME for to time failed.");
return WOLFSSL_FAILURE;
}
diffSecs = XDIFFTIME(toSecs, fromSecs); diffSecs = (double)(toSecs - fromSecs);
*days = (int) (diffSecs / SECS_PER_DAY); *days = (int) (diffSecs / SECS_PER_DAY);
*secs = (int) (diffSecs - (((double)*days) * SECS_PER_DAY)); *secs = (int) (diffSecs - (((double)*days) * SECS_PER_DAY));
return WOLFSSL_SUCCESS; return WOLFSSL_SUCCESS;
#else
return WOLFSSL_FAILURE;
#endif /* XMKTIME && XDIFFTIME */
} }
#endif /* !NO_ASN_TIME */ #endif /* !NO_ASN_TIME */

View File

@ -30898,11 +30898,18 @@ static void test_wolfSSL_ASN1_TIME_diff(void)
/* Edge case with Unix epoch. */ /* Edge case with Unix epoch. */
AssertNotNull(ASN1_TIME_set_string(fromTime, "19700101000000Z")); AssertNotNull(ASN1_TIME_set_string(fromTime, "19700101000000Z"));
AssertNotNull(ASN1_TIME_set_string(toTime, "19800101000000Z")); AssertNotNull(ASN1_TIME_set_string(toTime, "19800101000000Z"));
AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, toTime), WOLFSSL_SUCCESS); AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, toTime),
WOLFSSL_SUCCESS);
AssertIntEQ(daysDiff, 3652); AssertIntEQ(daysDiff, 3652);
AssertIntEQ(secsDiff, 0); AssertIntEQ(secsDiff, 0);
/* Edge case with year > 2038 (year 2038 problem). */
AssertNotNull(ASN1_TIME_set_string(toTime, "99991231235959Z"));
AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, toTime),
WOLFSSL_SUCCESS);
AssertIntEQ(daysDiff, 2932896);
AssertIntEQ(secsDiff, 86399);
ASN1_TIME_free(fromTime); ASN1_TIME_free(fromTime);
ASN1_TIME_free(toTime); ASN1_TIME_free(toTime);