diff --git a/src/internal.c b/src/internal.c index 22b8ef66a..35b4c0864 100644 --- a/src/internal.c +++ b/src/internal.c @@ -33505,6 +33505,16 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } else { #ifdef WOLFSSL_TLS13 + #ifdef WOLFSSL_32BIT_MILLI_TIME + word32 now = TimeNowInMilliseconds(); + #else + sword64 now = TimeNowInMilliseconds(); + #endif + if (now == 0) { + ret = GETTIME_ERROR; + goto error; + } + /* Client adds to ticket age to obfuscate. */ ret = wc_RNG_GenerateBlock(ssl->rng, it->ageAdd, sizeof(it->ageAdd)); @@ -33514,7 +33524,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } ato32(it->ageAdd, &ssl->session->ticketAdd); c16toa(ssl->session->namedGroup, it->namedGroup); - c32toa(TimeNowInMilliseconds(), it->timestamp); + #ifdef WOLFSSL_32BIT_MILLI_TIME + c32toa(now, it->timestamp); + #else + c32toa((word32)(now >> 32), it->timestamp); + c32toa((word32)now , it->timestamp + OPAQUE32_LEN); + #endif /* Resumption master secret. */ XMEMCPY(it->msecret, ssl->session->masterSecret, SECRET_LEN); XMEMCPY(&it->ticketNonce, &ssl->session->ticketNonce, @@ -33777,7 +33792,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, else { #ifdef WOLFSSL_TLS13 /* Restore information to renegotiate. */ + #ifdef WOLFSSL_32BIT_MILLI_TIME ato32(it->timestamp, &ssl->session->ticketSeen); + #else + word32 seenHi, seenLo; + + ato32(it->timestamp , &seenHi); + ato32(it->timestamp + OPAQUE32_LEN, &seenLo); + ssl->session->ticketSeen = ((sword64)seenHi << 32) + seenLo; + #endif ato32(it->ageAdd, &ssl->session->ticketAdd); ssl->session->cipherSuite0 = it->suite[0]; ssl->session->cipherSuite = it->suite[1]; diff --git a/src/ssl.c b/src/ssl.c index 39c7f1caf..cc4a13608 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -25363,8 +25363,13 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) #ifdef WOLFSSL_TLS13 +#ifdef WOLFSSL_32BIT_MILLI_TIME /* ticketSeen | ticketAdd */ size += OPAQUE32_LEN + OPAQUE32_LEN; +#else + /* ticketSeen Hi 32 bits | ticketSeen Lo 32 bits | ticketAdd */ + size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE32_LEN; +#endif /* ticketNonce */ size += OPAQUE8_LEN + sess->ticketNonce.len; #endif @@ -25436,13 +25441,20 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) #ifdef WOLFSSL_TLS13 - c32toa(sess->ticketSeen, data + idx); - idx += OPAQUE32_LEN; - c32toa(sess->ticketAdd, data + idx); - idx += OPAQUE32_LEN; - data[idx++] = sess->ticketNonce.len; - XMEMCPY(data + idx, sess->ticketNonce.data, sess->ticketNonce.len); - idx += sess->ticketNonce.len; +#ifdef WOLFSSL_32BIT_MILLI_TIME + c32toa(sess->ticketSeen, data + idx); + idx += OPAQUE32_LEN; +#else + c32toa((word32)(sess->ticketSeen >> 32), data + idx); + idx += OPAQUE32_LEN; + c32toa((word32)sess->ticketSeen, data + idx); + idx += OPAQUE32_LEN; +#endif + c32toa(sess->ticketAdd, data + idx); + idx += OPAQUE32_LEN; + data[idx++] = sess->ticketNonce.len; + XMEMCPY(data + idx, sess->ticketNonce.data, sess->ticketNonce.len); + idx += sess->ticketNonce.len; #endif #ifdef WOLFSSL_EARLY_DATA c32toa(sess->maxEarlyDataSz, data + idx); @@ -25632,8 +25644,20 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, ret = BUFFER_ERROR; goto end; } +#ifdef WOLFSSL_32BIT_MILLI_TIME ato32(data + idx, &s->ticketSeen); idx += OPAQUE32_LEN; +#else + { + word32 seenHi, seenLo; + + ato32(data + idx, &seenHi); + idx += OPAQUE32_LEN; + ato32(data + idx, &seenLo); + idx += OPAQUE32_LEN; + s->ticketSeen = ((sword64)seenHi << 32) + seenLo; + } +#endif ato32(data + idx, &s->ticketAdd); idx += OPAQUE32_LEN; if (i - idx < OPAQUE8_LEN) { diff --git a/src/tls.c b/src/tls.c index 102fc873d..9419ac082 100644 --- a/src/tls.c +++ b/src/tls.c @@ -11507,7 +11507,11 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #if defined(HAVE_SESSION_TICKET) if (ssl->options.resuming && ssl->session->ticketLen > 0) { WOLFSSL_SESSION* sess = ssl->session; - word32 now, milli; + #ifdef WOLFSSL_32BIT_MILLI_TIME + word32 now, milli; + #else + word64 now, milli; + #endif if (sess->ticketLen > MAX_PSK_ID_LEN) { WOLFSSL_MSG("Session ticket length for PSK ext is too large"); @@ -11521,6 +11525,9 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) if (ret != 0) return ret; now = TimeNowInMilliseconds(); + if (now == 0) + return GETTIME_ERROR; + #ifdef WOLFSSL_32BIT_MILLI_TIME if (now < sess->ticketSeen) milli = (0xFFFFFFFFU - sess->ticketSeen) + 1 + now; else @@ -11529,10 +11536,17 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) /* Pre-shared key is mandatory extension for resumption. */ ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen, - milli, ssl->specs.mac_algorithm, - ssl->options.cipherSuite0, - ssl->options.cipherSuite, 1, - NULL); + milli, ssl->specs.mac_algorithm, ssl->options.cipherSuite0, + ssl->options.cipherSuite, 1, NULL); + #else + milli = now - sess->ticketSeen + sess->ticketAdd; + + /* Pre-shared key is mandatory extension for resumption. */ + ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen, + (word32)milli, ssl->specs.mac_algorithm, + ssl->options.cipherSuite0, ssl->options.cipherSuite, 1, + NULL); + #endif if (ret != 0) return ret; diff --git a/src/tls13.c b/src/tls13.c index cd4762b47..fff5923e7 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -81,6 +81,9 @@ * Verifies the ECC signature after signing in case of faults in the * calculation of the signature. Useful when signature fault injection is a * possible attack. + * WOLFSSL_32BIT_MILLI_TIME + * Function TimeNowInMilliseconds() returns an unsigned 32-bit value. + * Default behavior is to return a signed 64-bit value. */ #ifdef HAVE_CONFIG_H @@ -1372,6 +1375,7 @@ end: } #if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) +#ifdef WOLFSSL_32BIT_MILLI_TIME #ifndef NO_ASN_TIME #if defined(USER_TICKS) #if 0 @@ -1617,7 +1621,7 @@ end: { struct timeval now; if (FCL_GETTIMEOFDAY(&now, 0) < 0) - return (word32)GETTIME_ERROR; /* TODO: return 0 for failure */ + return 0; /* Convert to milliseconds number. */ return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000); @@ -1643,7 +1647,7 @@ end: struct timeval now; if (gettimeofday(&now, 0) < 0) - return (word32)GETTIME_ERROR; /* TODO: return 0 for failure */ + return 0; /* Convert to milliseconds number. */ return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000); @@ -1655,6 +1659,290 @@ end: * The response is milliseconds elapsed */ #endif /* !NO_ASN_TIME */ +#else +#ifndef NO_ASN_TIME +#if defined(USER_TICKS) +#if 0 + sword64 TimeNowInMilliseconds(void) + { + /* + write your own clock tick function if don't want gettimeofday() + needs millisecond accuracy but doesn't have to correlated to EPOCH + */ + } +#endif + +#elif defined(TIME_OVERRIDES) +#if !defined(NO_ASN) && !defined(NO_ASN_TIME) + sword64 TimeNowInMilliseconds(void) + { + return (sword64) wc_Time(0) * 1000; + } +#else + #ifndef HAVE_TIME_T_TYPE + typedef long time_t; + #endif + extern time_t XTIME(time_t * timer); + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + return (sword64) XTIME(0) * 1000; + } +#endif + +#elif defined(XTIME_MS) + sword64 TimeNowInMilliseconds(void) + { + return (sword64)XTIME_MS(0); + } + +#elif defined(USE_WINDOWS_API) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + static int init = 0; + static LARGE_INTEGER freq; + LARGE_INTEGER count; + + if (!init) { + QueryPerformanceFrequency(&freq); + init = 1; + } + + QueryPerformanceCounter(&count); + + return (sword64)(count.QuadPart / (freq.QuadPart / 1000)); + } + +#elif defined(HAVE_RTP_SYS) + #include "rtptime.h" + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + return (sword64)rtp_get_system_sec() * 1000; + } +#elif defined(WOLFSSL_DEOS) + sword64 TimeNowInMilliseconds(void) + { + const word32 systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); + word32 *systemTickPtr = systemTickPointer(); + + return (sword64) (*systemTickPtr/systemTickTimeInHz) * 1000; + } +#elif defined(MICRIUM) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + OS_TICK ticks = 0; + OS_ERR err; + + ticks = OSTimeGet(&err); + + return (sword64) (ticks / OSCfg_TickRate_Hz) * 1000; + } +#elif defined(MICROCHIP_TCPIP_V5) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + return (sword64) (TickGet() / (TICKS_PER_SECOND / 1000)); + } +#elif defined(MICROCHIP_TCPIP) + #if defined(MICROCHIP_MPLAB_HARMONY) + #include + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + return (sword64)SYS_TMR_TickCountGet() / + (SYS_TMR_TickCounterFrequencyGet() / 1000); + } + #else + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + return (sword64)SYS_TICK_Get() / (SYS_TICK_TicksPerSecondGet() / 1000); + } + + #endif + +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + TIME_STRUCT mqxTime; + + _time_get_elapsed(&mqxTime); + + return (sword64) mqxTime.SECONDS * 1000; + } +#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) + #include "include/task.h" + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + return (sword64)xTaskGetTickCount() / (configTICK_RATE_HZ / 1000); + } +#elif defined(FREESCALE_KSDK_BM) + #include "lwip/sys.h" /* lwIP */ + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + return sys_now(); + } +#elif defined(WOLFSSL_TIRTOS) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + return (sword64) Seconds_get() * 1000; + } +#elif defined(WOLFSSL_UTASKER) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + return (sword64)(uTaskerSystemTick / (TICK_RESOLUTION / 1000)); + } +#elif defined(WOLFSSL_LINUXKM) + sword64 TimeNowInMilliseconds(void) + { + s64 t; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) + struct timespec ts; + getnstimeofday(&ts); + t = ts.tv_sec * (s64)1000; + t += ts.tv_nsec / (s64)1000000; +#else + struct timespec64 ts; +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) + ts = current_kernel_time64(); +#else + ktime_get_coarse_real_ts64(&ts); +#endif + t = ts.tv_sec * 1000L; + t += ts.tv_nsec / 1000000L; +#endif + return (sword64)t; + } +#elif defined(WOLFSSL_QNX_CAAM) + sword64 TimeNowInMilliseconds(void) + { + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); + return (sword64)(now.tv_sec * 1000 + now.tv_nsec / 1000000); + } +#elif defined(FUSION_RTOS) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + struct timeval now; + if (FCL_GETTIMEOFDAY(&now, 0) < 0) + return 0; + + /* Convert to milliseconds number. */ + return (sword64)now.tv_sec * 1000 + now.tv_usec / 1000; + } +#elif defined(WOLFSSL_ZEPHYR) + sword64 TimeNowInMilliseconds(void) + { + #if defined(CONFIG_ARCH_POSIX) + k_cpu_idle(); + #endif + return (sword64)k_uptime_get() / 1000; + } + +#else + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 64-bit value. + */ + sword64 TimeNowInMilliseconds(void) + { + struct timeval now; + + if (gettimeofday(&now, 0) < 0) + return 0; + + /* Convert to milliseconds number. */ + return (sword64)now.tv_sec * 1000 + now.tv_usec / 1000; + } +#endif +#else + /* user must supply time in milliseconds function: + * sword64 TimeNowInMilliseconds(void); + * The response is milliseconds elapsed + */ +#endif /* !NO_ASN_TIME */ +#endif /* WOLFSSL_32BIT_MILLI_TIME */ #endif /* HAVE_SESSION_TICKET || !NO_PSK */ @@ -4633,12 +4921,13 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz, #endif if (ret == WOLFSSL_TICKET_RET_OK) { - word32 now; + #ifdef WOLFSSL_32BIT_MILLI_TIME + word32 now; sword64 diff; now = TimeNowInMilliseconds(); - if (now == (word32)GETTIME_ERROR) - return now; + if (now == 0) + return GETTIME_ERROR; /* Difference between now and time ticket constructed * (from decrypted ticket). */ diff = now; @@ -4648,6 +4937,21 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz, current = current->next; continue; } + #else + sword64 diff; + + diff = TimeNowInMilliseconds(); + if (diff == 0) + return GETTIME_ERROR; + /* Difference between now and time ticket constructed + * (from decrypted ticket). */ + diff -= ssl->session->ticketSeen; + if (diff > (sword64)ssl->timeout * 1000 || + diff > (sword64)TLS13_MAX_TICKET_AGE * 1000) { + current = current->next; + continue; + } + #endif /* Subtract client's ticket age and unobfuscate. */ diff -= current->ticketAge; diff += ssl->session->ticketAdd; @@ -8883,7 +9187,11 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, word32 lifetime; word32 ageAdd; word16 length; +#ifdef WOLFSSL_32BIT_MILLI_TIME word32 now; +#else + sword64 now; +#endif const byte* nonce; byte nonceLength; @@ -8934,22 +9242,22 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, *inOutIdx += length; now = TimeNowInMilliseconds(); - if (now == (word32)GETTIME_ERROR) - return now; + if (now == 0) + return GETTIME_ERROR; /* Copy in ticket data (server identity). */ - ssl->timeout = lifetime; - ssl->session->timeout = lifetime; - ssl->session->cipherSuite0 = ssl->options.cipherSuite0; - ssl->session->cipherSuite = ssl->options.cipherSuite; - ssl->session->ticketSeen = now; - ssl->session->ticketAdd = ageAdd; + ssl->timeout = lifetime; + ssl->session->timeout = lifetime; + ssl->session->cipherSuite0 = ssl->options.cipherSuite0; + ssl->session->cipherSuite = ssl->options.cipherSuite; + ssl->session->ticketSeen = now; + ssl->session->ticketAdd = ageAdd; #ifdef WOLFSSL_EARLY_DATA - ssl->session->maxEarlyDataSz = ssl->options.maxEarlyDataSz; + ssl->session->maxEarlyDataSz = ssl->options.maxEarlyDataSz; #endif ssl->session->ticketNonce.len = nonceLength; if (nonceLength > 0) XMEMCPY(&ssl->session->ticketNonce.data, nonce, nonceLength); - ssl->session->namedGroup = ssl->namedGroup; + ssl->session->namedGroup = ssl->namedGroup; if ((*inOutIdx - begin) + EXTS_SZ > size) return BUFFER_ERROR; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 1470c4f50..a2f95daf7 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1255,6 +1255,15 @@ enum { #error "Max size for DTLS CID is 255 bytes" #endif +#ifndef MAX_TICKET_AGE_DIFF +/* maximum ticket age difference in seconds, 10 seconds */ +#define MAX_TICKET_AGE_DIFF 10 +#endif +#ifndef TLS13_MAX_TICKET_AGE +/* max ticket age in seconds, 7 days */ +#define TLS13_MAX_TICKET_AGE (7*24*60*60) +#endif + enum Misc { CIPHER_BYTE = 0x00, /* Default ciphers */ ECC_BYTE = 0xC0, /* ECC first cipher suite byte */ @@ -1285,7 +1294,11 @@ enum Misc { HELLO_EXT_EXTMS = 0x0017, /* ID for the extended master secret ext */ SECRET_LEN = WOLFSSL_MAX_MASTER_KEY_LENGTH, /* pre RSA and all master */ +#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_32BIT_MILLI_TIME) TIMESTAMP_LEN = 4, /* timestamp size in ticket */ +#else + TIMESTAMP_LEN = 8, /* timestamp size in ticket */ +#endif #ifdef WOLFSSL_TLS13 AGEADD_LEN = 4, /* ageAdd size in ticket */ NAMEDGROUP_LEN = 2, /* namedGroup size in ticket */ @@ -1555,8 +1568,6 @@ enum Misc { MAX_PSK_KEY_LEN = 64, /* max psk key supported */ MIN_PSK_ID_LEN = 6, /* min length of identities */ MIN_PSK_BINDERS_LEN = 33, /* min length of binders */ - MAX_TICKET_AGE_DIFF = 10, /* maximum ticket age difference in seconds */ - TLS13_MAX_TICKET_AGE = 7*24*60*60, /* max ticket age in seconds, 7 days */ #ifndef MAX_WOLFSSL_FILE_SIZE MAX_WOLFSSL_FILE_SIZE = 1024UL * 1024UL * 4, /* 4 mb file size alloc limit */ @@ -3709,14 +3720,18 @@ struct WOLFSSL_SESSION { word16 namedGroup; #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - #ifdef WOLFSSL_TLS13 +#ifdef WOLFSSL_TLS13 +#ifdef WOLFSSL_32BIT_MILLI_TIME word32 ticketSeen; /* Time ticket seen (ms) */ +#else + sword64 ticketSeen; /* Time ticket seen (ms) */ +#endif word32 ticketAdd; /* Added by client */ TicketNonce ticketNonce; /* Nonce used to derive PSK */ - #endif - #ifdef WOLFSSL_EARLY_DATA +#endif +#ifdef WOLFSSL_EARLY_DATA word32 maxEarlyDataSz; - #endif +#endif #endif #ifdef HAVE_SESSION_TICKET byte staticTicket[SESSION_TICKET_LEN]; @@ -5488,7 +5503,11 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl); WOLFSSL_LOCAL void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out); #if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) +#ifdef WOLFSSL_32BIT_MILLI_TIME WOLFSSL_LOCAL word32 TimeNowInMilliseconds(void); +#else + WOLFSSL_LOCAL sword64 TimeNowInMilliseconds(void); +#endif WOLFSSL_LOCAL int FindSuiteMac(WOLFSSL* ssl, byte* suite); #endif