Add time callback functionality.

This commit adds `wolfSSL_SetTimeCb` and `wolfSSL_time`. The former allows the
user to override the function wolfSSL uses to get the current time,
`wolfSSL_time`. If set, `wolfSSL_time` uses that function. If not set,
`wolfSSL_time` uses the `XTIME` macro by default. This functionality is needed
for the port of chrony to wolfSSL. chrony is an NTP implementation that uses
GnuTLS by default. For TLS, chrony uses the time it computes in place of the
default system time function.
This commit is contained in:
Hayden Roche
2022-01-15 11:34:11 -08:00
parent f81e15f342
commit 1b0926a3b8
10 changed files with 154 additions and 18 deletions

View File

@ -1884,3 +1884,56 @@ WOLFSSL_API int wc_ParseCert(DecodedCert* cert, int type, int verify, void* cm);
\sa wc_ParseCert
*/
WOLFSSL_API void wc_FreeDecodedCert(struct DecodedCert* cert);
/*!
\ingroup ASN
\brief This function registers a time callback that will be used anytime
wolfSSL needs to get the current time. The prototype of the callback should
be the same as the "time" function from the C standard library.
\return 0 Returned on success.
\param f function to register as the time callback.
_Example_
\code
int ret = 0;
// Time callback prototype
time_t my_time_cb(time_t* t);
// Register it
ret = wc_SetTimeCb(my_time_cb);
if (ret != 0) {
// failed to set time callback
}
time_t my_time_cb(time_t* t)
{
// custom time function
}
\endcode
\sa wc_Time
*/
WOLFSSL_API int wc_SetTimeCb(wc_time_cb f);
/*!
\ingroup ASN
\brief This function gets the current time. By default, it uses the XTIME
macro, which varies between platforms. The user can use a function of their
choosing instead via the wc_SetTimeCb function.
\return Time Current time returned on success.
\param t Optional time_t pointer to populate with current time.
_Example_
\code
time_t currentTime = 0;
currentTime = wc_Time(NULL);
wc_Time(&currentTime);
\endcode
\sa wc_SetTimeCb
*/
WOLFSSL_API time_t wc_Time(time_t* t);

View File

@ -8341,9 +8341,14 @@ ProtocolVersion MakeDTLSv1_2(void)
#endif
#elif defined(TIME_OVERRIDES)
#if !defined(NO_ASN) && !defined(NO_ASN_TIME)
/* use same asn time overrides unless user wants tick override above */
word32 LowResTimer(void)
{
return (word32) wc_Time(0);
}
#else
#ifndef HAVE_TIME_T_TYPE
typedef long time_t;
#endif
@ -8353,6 +8358,7 @@ ProtocolVersion MakeDTLSv1_2(void)
{
return (word32) XTIME(0);
}
#endif
#elif defined(USE_WINDOWS_API)
@ -8546,7 +8552,11 @@ ProtocolVersion MakeDTLSv1_2(void)
word32 LowResTimer(void)
{
#if !defined(NO_ASN) && !defined(NO_ASN_TIME)
return (word32)wc_Time(0);
#else
return (word32)XTIME(0);
#endif
}
#endif
#else

View File

@ -1048,7 +1048,7 @@ static void Trace(int idx)
static void TraceHeader(void)
{
if (TraceOn) {
time_t ticks = XTIME(NULL);
time_t ticks = wc_Time(NULL);
XFPRINTF(TraceFile, "\n%s", XCTIME(&ticks));
}
}
@ -1449,7 +1449,7 @@ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
{
SnifferSession* session;
time_t currTime = XTIME(NULL);
time_t currTime = wc_Time(NULL);
word32 row = SessionHash(ipInfo, tcpInfo);
wc_LockMutex(&SessionMutex);
@ -4487,7 +4487,7 @@ static void RemoveStaleSessions(void)
session = SessionTable[i];
while (session) {
SnifferSession* next = session->next;
if (XTIME(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
if (wc_Time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
TraceStaleSession();
RemoveSession(session, NULL, NULL, i);
}
@ -4536,7 +4536,7 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
session->cliPort = (word16)tcpInfo->srcPort;
session->cliSeqStart = tcpInfo->sequence;
session->cliExpected = 1; /* relative */
session->lastUsed= XTIME(NULL);
session->lastUsed= wc_Time(NULL);
session->keySz = 0;
#ifdef HAVE_SNI
session->sni = NULL;

View File

@ -27848,7 +27848,7 @@ int wolfSSL_X509_cmp_time(const WOLFSSL_ASN1_TIME* asnTime, time_t* cmpTime)
if (cmpTime == NULL) {
/* Use current time */
*pTime = XTIME(0);
*pTime = wc_Time(0);
}
else {
pTime = cmpTime;
@ -27878,7 +27878,7 @@ WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj_ex(WOLFSSL_ASN1_TIME *asnTime,
int offset_day, long offset_sec, time_t *in_tm)
{
/* get current time if in_tm is null */
time_t t = in_tm ? *in_tm : XTIME(0);
time_t t = in_tm ? *in_tm : wc_Time(0);
return wolfSSL_ASN1_TIME_adj(asnTime, t, offset_day, offset_sec);
}
@ -28194,7 +28194,7 @@ int wolfSSL_ASN1_TIME_to_tm(const WOLFSSL_ASN1_TIME* asnTime, struct tm* tm)
return WOLFSSL_FAILURE;
}
currentTime = XTIME(0);
currentTime = wc_Time(0);
if (currentTime <= 0) {
WOLFSSL_MSG("Failed to get current time.");
return WOLFSSL_FAILURE;
@ -31071,7 +31071,7 @@ int wolfSSL_ASN1_TIME_diff(int *days, int *secs, const WOLFSSL_ASN1_TIME *from,
}
if (from == NULL) {
fromSecs = XTIME(0);
fromSecs = wc_Time(0);
fromTm = XGMTIME(&fromSecs, tmpTs);
if (fromTm == NULL) {
WOLFSSL_MSG("XGMTIME for from time failed.");
@ -31090,7 +31090,7 @@ int wolfSSL_ASN1_TIME_diff(int *days, int *secs, const WOLFSSL_ASN1_TIME *from,
}
if (to == NULL) {
toSecs = XTIME(0);
toSecs = wc_Time(0);
toTm = XGMTIME(&toSecs, tmpTs);
if (toTm == NULL) {
WOLFSSL_MSG("XGMTIME for to time failed.");

View File

@ -1279,6 +1279,12 @@ end:
#endif
#elif defined(TIME_OVERRIDES)
#if !defined(NO_ASN) && !defined(NO_ASN_TIME)
word32 TimeNowInMilliseconds(void)
{
return (word32) wc_Time(0) * 1000;
}
#else
#ifndef HAVE_TIME_T_TYPE
typedef long time_t;
#endif
@ -1294,6 +1300,7 @@ end:
{
return (word32) XTIME(0) * 1000;
}
#endif
#elif defined(XTIME_MS)
word32 TimeNowInMilliseconds(void)

View File

@ -35954,8 +35954,8 @@ static void test_wolfSSL_X509_time_adj(void)
WOLFSSL_FILETYPE_ASN1));
t = 0;
not_before = XTIME(0);
not_after = XTIME(0) + (60 * 24 * 30); /* 30 days after */
not_before = wc_Time(0);
not_after = wc_Time(0) + (60 * 24 * 30); /* 30 days after */
AssertNotNull(X509_time_adj(X509_get_notBefore(x509), not_before, &t));
AssertNotNull(X509_time_adj(X509_get_notAfter(x509), not_after, &t));
/* Check X509_gmtime_adj, too. */
@ -49645,7 +49645,7 @@ static void test_openssl_make_self_signed_certificate(EVP_PKEY* pkey)
AssertIntNE(X509_set_subject_name(x509, name), 0);
AssertIntNE(X509_set_issuer_name(x509, name), 0);
not_before = (long)XTIME(NULL);
not_before = (long)wc_Time(NULL);
not_after = not_before + (365 * 24 * 60 * 60);
AssertNotNull(X509_time_adj(X509_get_notBefore(x509), not_before, &epoch_off));
AssertNotNull(X509_time_adj(X509_get_notAfter(x509), not_after, &epoch_off));

View File

@ -12217,7 +12217,7 @@ int wc_ValidateDate(const byte* date, byte format, int dateType)
#endif
(void)tmpTime;
ltime = XTIME(0);
ltime = wc_Time(0);
#ifdef WOLFSSL_BEFORE_DATE_CLOCK_SKEW
if (dateType == BEFORE) {
@ -12288,11 +12288,34 @@ int wc_GetTime(void* timePtr, word32 timeSize)
return BUFFER_E;
}
*ltime = XTIME(0);
*ltime = wc_Time(0);
return 0;
}
#ifdef TIME_OVERRIDES
#ifndef HAVE_TIME_T_TYPE
typedef long time_t;
#endif
extern time_t XTIME(time_t* t);
#endif
static wc_time_cb timeFunc = NULL;
int wc_SetTimeCb(wc_time_cb f)
{
timeFunc = f;
return 0;
}
time_t wc_Time(time_t* t)
{
if (timeFunc != NULL) {
return timeFunc(t);
}
return XTIME(t);
}
#endif /* !NO_ASN_TIME */
@ -23457,7 +23480,7 @@ static int SetValidity(byte* output, int daysValid)
#endif
(void)tmpTime;
now = XTIME(0);
now = wc_Time(0);
/* before now */
before[0] = ASN_GENERALIZED_TIME;
@ -23528,7 +23551,7 @@ static int SetValidity(byte* before, byte* after, int daysValid)
#endif
(void)tmpTime;
now = XTIME(0);
now = wc_Time(0);
/* subtract 1 day of seconds for more compliance */
then = now - 86400;

View File

@ -1927,7 +1927,7 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd,
if (signingTime == NULL || signingTimeSz == 0)
return BAD_FUNC_ARG;
tm = XTIME(0);
tm = wc_Time(0);
timeSz = GetAsnTimeString(&tm, signingTime, signingTimeSz);
if (timeSz < 0)
return timeSz;

View File

@ -539,6 +539,9 @@ WOLFSSL_TEST_SUBROUTINE int prime_test(void);
WOLFSSL_TEST_SUBROUTINE int berder_test(void);
#endif
WOLFSSL_TEST_SUBROUTINE int logging_test(void);
#if !defined(NO_ASN) && !defined(NO_ASN_TIME)
WOLFSSL_TEST_SUBROUTINE int time_test(void);
#endif
WOLFSSL_TEST_SUBROUTINE int mutex_test(void);
#if defined(USE_WOLFSSL_MEMORY) && !defined(FREERTOS)
WOLFSSL_TEST_SUBROUTINE int memcb_test(void);
@ -1396,6 +1399,13 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
else
TEST_PASS("logging test passed!\n");
#if !defined(NO_ASN) && !defined(NO_ASN_TIME)
if ( (ret = time_test()) != 0)
return err_sys("time test failed!\n", ret);
else
TEST_PASS("time test passed!\n");
#endif
if ( (ret = mutex_test()) != 0)
return err_sys("mutex test failed!\n", ret);
else
@ -38599,6 +38609,35 @@ WOLFSSL_TEST_SUBROUTINE int certpiv_test(void)
}
#endif /* WOLFSSL_CERT_PIV */
#if !defined(NO_ASN) && !defined(NO_ASN_TIME)
static time_t time_cb(time_t* t)
{
if (t != NULL) {
*t = 99;
}
return 99;
}
WOLFSSL_TEST_SUBROUTINE int time_test(void)
{
time_t t;
if (wc_SetTimeCb(time_cb) != 0)
return -15000;
t = wc_Time(NULL);
if (t != 99)
return -15001;
if (wc_GetTime(&t, sizeof(time_t)) != 0)
return -15002;
if (t != 99)
return -15003;
if (wc_SetTimeCb(NULL) != 0)
return -15004;
return 0;
}
#endif
#undef ERROR_OUT

View File

@ -733,6 +733,10 @@ WOLFSSL_API int wc_CreateEncryptedPKCS8Key(byte*, word32, byte*, word32*,
rc = wc_GetTime(&lTime, (word32)sizeof(lTime));
*/
WOLFSSL_API int wc_GetTime(void* timePtr, word32 timeSize);
typedef time_t (*wc_time_cb)(time_t* t);
WOLFSSL_API int wc_SetTimeCb(wc_time_cb f);
WOLFSSL_API time_t wc_Time(time_t* t);
#endif
#ifdef WOLFSSL_ENCRYPTED_KEYS