forked from wolfSSL/wolfssl
Merge pull request #5010 from haydenroche5/asn1_time_diff_2038
Fix year 2038 problem in wolfSSL_ASN1_TIME_diff.
This commit is contained in:
84
src/ssl.c
84
src/ssl.c
@ -32169,15 +32169,34 @@ int wolfSSL_ASN1_TIME_check(const WOLFSSL_ASN1_TIME* a)
|
||||
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,
|
||||
const WOLFSSL_ASN1_TIME *to)
|
||||
{
|
||||
#if defined(XMKTIME) && defined(XDIFFTIME)
|
||||
const int SECS_PER_DAY = 24 * 60 * 60;
|
||||
struct tm fromTm_s, *fromTm = &fromTm_s;
|
||||
struct tm toTm_s, *toTm = &toTm_s;
|
||||
time_t fromSecs;
|
||||
time_t toSecs;
|
||||
struct tm fromTm_s, *fromTmGmt = &fromTm_s;
|
||||
struct tm toTm_s, *toTmGmt = &toTm_s;
|
||||
time_t currTime;
|
||||
long long fromSecs;
|
||||
long long toSecs;
|
||||
double diffSecs;
|
||||
struct tm *tmpTs;
|
||||
#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) {
|
||||
fromSecs = wc_Time(0);
|
||||
fromTm = XGMTIME(&fromSecs, tmpTs);
|
||||
if (fromTm == NULL) {
|
||||
currTime = wc_Time(0);
|
||||
fromTmGmt = XGMTIME(&currTime, tmpTs);
|
||||
if (fromTmGmt == NULL) {
|
||||
WOLFSSL_MSG("XGMTIME for from time failed.");
|
||||
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.");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
errno = 0;
|
||||
#endif
|
||||
fromSecs = XMKTIME(fromTm);
|
||||
/* Result can be negative due to time zones around UNIX epoch */
|
||||
if (fromSecs == -1
|
||||
#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;
|
||||
}
|
||||
/* We use time2epoch here instead of XMKTIME to avoid the Year 2038 problem
|
||||
* on platforms where time_t is 32 bits. struct tm stores the year as years
|
||||
* since 1900, so we add 1900 to the year. */
|
||||
fromSecs = time2epoch(fromTmGmt->tm_sec, fromTmGmt->tm_min,
|
||||
fromTmGmt->tm_hour, fromTmGmt->tm_mday,
|
||||
fromTmGmt->tm_mon, fromTmGmt->tm_year + 1900);
|
||||
|
||||
if (to == NULL) {
|
||||
toSecs = wc_Time(0);
|
||||
toTm = XGMTIME(&toSecs, tmpTs);
|
||||
if (toTm == NULL) {
|
||||
currTime = wc_Time(0);
|
||||
toTmGmt = XGMTIME(&currTime, tmpTs);
|
||||
if (toTmGmt == NULL) {
|
||||
WOLFSSL_MSG("XGMTIME for to time failed.");
|
||||
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.");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
toSecs = XMKTIME(toTm);
|
||||
/* Result can be negative due to time zones around UNIX epoch */
|
||||
if (toSecs == -1
|
||||
#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;
|
||||
}
|
||||
toSecs = time2epoch(toTmGmt->tm_sec, toTmGmt->tm_min, toTmGmt->tm_hour,
|
||||
toTmGmt->tm_mday, toTmGmt->tm_mon,
|
||||
toTmGmt->tm_year + 1900);
|
||||
|
||||
diffSecs = XDIFFTIME(toSecs, fromSecs);
|
||||
diffSecs = (double)(toSecs - fromSecs);
|
||||
*days = (int) (diffSecs / SECS_PER_DAY);
|
||||
*secs = (int) (diffSecs - (((double)*days) * SECS_PER_DAY));
|
||||
|
||||
return WOLFSSL_SUCCESS;
|
||||
#else
|
||||
return WOLFSSL_FAILURE;
|
||||
#endif /* XMKTIME && XDIFFTIME */
|
||||
}
|
||||
#endif /* !NO_ASN_TIME */
|
||||
|
||||
|
11
tests/api.c
11
tests/api.c
@ -30898,11 +30898,18 @@ static void test_wolfSSL_ASN1_TIME_diff(void)
|
||||
/* Edge case with Unix epoch. */
|
||||
AssertNotNull(ASN1_TIME_set_string(fromTime, "19700101000000Z"));
|
||||
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(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(toTime);
|
||||
|
||||
|
Reference in New Issue
Block a user