Skip to content

Commit 4ae2d28

Browse files
committed
Add checks for ascii digits in time decode functions
1 parent 353a379 commit 4ae2d28

3 files changed

Lines changed: 67 additions & 25 deletions

File tree

src/ssl_asn1.c

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4293,6 +4293,14 @@ static int wolfssl_utctime_year(const unsigned char* str, int len, int* year)
42934293
ret = 0;
42944294
}
42954295

4296+
if (ret == 1) {
4297+
if ((str[0] < '0') || (str[0] > '9') ||
4298+
(str[1] < '0') || (str[1] > '9')) {
4299+
WOLFSSL_MSG("Invalid characters in UTC year.");
4300+
ret = 0;
4301+
}
4302+
}
4303+
42964304
if (ret == 1) {
42974305
int tm_year;
42984306
/* 2-digit year. */
@@ -4334,6 +4342,16 @@ static int wolfssl_gentime_year(const unsigned char* str, int len, int* year)
43344342
ret = 0;
43354343
}
43364344

4345+
if (ret == 1) {
4346+
if ((str[0] < '0') || (str[0] > '9') ||
4347+
(str[1] < '0') || (str[1] > '9') ||
4348+
(str[2] < '0') || (str[2] > '9') ||
4349+
(str[3] < '0') || (str[3] > '9')) {
4350+
WOLFSSL_MSG("Invalid characters in generalized year.");
4351+
ret = 0;
4352+
}
4353+
}
4354+
43374355
if (ret == 1) {
43384356
int tm_year;
43394357
/* 4-digit year. */
@@ -4363,11 +4381,12 @@ static int wolfssl_asn1_time_to_tm(const WOLFSSL_ASN1_TIME* asnTime,
43634381
const unsigned char* asn1TimeBuf;
43644382
int asn1TimeBufLen;
43654383
int i = 0;
4366-
#ifdef XMKTIME
4384+
/* Parse into a local struct so the caller's tm is only written on
4385+
* success. Avoids leaving a partially-populated struct behind when
4386+
* the input fails validation. */
43674387
struct tm localTm;
43684388

4369-
XMEMSET(&localTm, 0, sizeof localTm);
4370-
#endif
4389+
XMEMSET(&localTm, 0, sizeof(localTm));
43714390

43724391
/* Get the string buffer - fixed array, can't fail. */
43734392
asn1TimeBuf = wolfSSL_ASN1_TIME_get_data(asnTime);
@@ -4378,15 +4397,12 @@ static int wolfssl_asn1_time_to_tm(const WOLFSSL_ASN1_TIME* asnTime,
43784397
ret = 0;
43794398
}
43804399
if (ret == 1) {
4381-
/* Zero out values in broken-down time. */
4382-
XMEMSET(tm, 0, sizeof(struct tm));
4383-
43844400
if (asnTime->type == WOLFSSL_V_ASN1_UTCTIME) {
43854401
/* Get year from UTC TIME string. */
43864402
int tm_year;
43874403
if ((ret = wolfssl_utctime_year(asn1TimeBuf, asn1TimeBufLen,
43884404
&tm_year)) == 1) {
4389-
tm->tm_year = tm_year;
4405+
localTm.tm_year = tm_year;
43904406
/* Month starts after year - 2 characters. */
43914407
i = 2;
43924408
}
@@ -4396,7 +4412,7 @@ static int wolfssl_asn1_time_to_tm(const WOLFSSL_ASN1_TIME* asnTime,
43964412
int tm_year;
43974413
if ((ret = wolfssl_gentime_year(asn1TimeBuf, asn1TimeBufLen,
43984414
&tm_year)) == 1) {
4399-
tm->tm_year = tm_year;
4415+
localTm.tm_year = tm_year;
44004416
/* Month starts after year - 4 characters. */
44014417
i = 4;
44024418
}
@@ -4406,26 +4422,51 @@ static int wolfssl_asn1_time_to_tm(const WOLFSSL_ASN1_TIME* asnTime,
44064422
WOLFSSL_MSG("asnTime->type is invalid.");
44074423
ret = 0;
44084424
}
4409-
}
4410-
if (ret == 1) {
4425+
}
4426+
4427+
if (ret == 1) {
4428+
int j;
4429+
/* Validate 10 digits: MMDDHHMMSS. Length was already checked
4430+
* (>= UTCTIME_LEN or >= GENTIME_LEN), so i+10 is in range. */
4431+
for (j = i; j < i + 10; j++) {
4432+
if (asn1TimeBuf[j] < '0' || asn1TimeBuf[j] > '9') {
4433+
WOLFSSL_MSG("Non-digit in ASN.1 TIME.");
4434+
ret = 0;
4435+
break;
4436+
}
4437+
}
4438+
}
4439+
4440+
if (ret == 1) {
44114441
/* Fill in rest of broken-down time from string. */
44124442
/* January is 0 not 1 */
4413-
tm->tm_mon = (asn1TimeBuf[i] - '0') * 10; i++;
4414-
tm->tm_mon += (asn1TimeBuf[i] - '0') - 1; i++;
4415-
tm->tm_mday = (asn1TimeBuf[i] - '0') * 10; i++;
4416-
tm->tm_mday += (asn1TimeBuf[i] - '0'); i++;
4417-
tm->tm_hour = (asn1TimeBuf[i] - '0') * 10; i++;
4418-
tm->tm_hour += (asn1TimeBuf[i] - '0'); i++;
4419-
tm->tm_min = (asn1TimeBuf[i] - '0') * 10; i++;
4420-
tm->tm_min += (asn1TimeBuf[i] - '0'); i++;
4421-
tm->tm_sec = (asn1TimeBuf[i] - '0') * 10; i++;
4422-
tm->tm_sec += (asn1TimeBuf[i] - '0');
4443+
localTm.tm_mon = (asn1TimeBuf[i] - '0') * 10; i++;
4444+
localTm.tm_mon += (asn1TimeBuf[i] - '0') - 1; i++;
4445+
localTm.tm_mday = (asn1TimeBuf[i] - '0') * 10; i++;
4446+
localTm.tm_mday += (asn1TimeBuf[i] - '0'); i++;
4447+
localTm.tm_hour = (asn1TimeBuf[i] - '0') * 10; i++;
4448+
localTm.tm_hour += (asn1TimeBuf[i] - '0'); i++;
4449+
localTm.tm_min = (asn1TimeBuf[i] - '0') * 10; i++;
4450+
localTm.tm_min += (asn1TimeBuf[i] - '0'); i++;
4451+
localTm.tm_sec = (asn1TimeBuf[i] - '0') * 10; i++;
4452+
localTm.tm_sec += (asn1TimeBuf[i] - '0');
4453+
}
44234454

4455+
if (ret == 1) {
4456+
/* Range-check broken-down fields. ValidateGmtime returns 0 on
4457+
* success. */
4458+
if (ValidateGmtime(&localTm)) {
4459+
WOLFSSL_MSG("Out-of-range field in ASN.1 TIME.");
4460+
ret = 0;
4461+
}
4462+
}
4463+
4464+
if (ret == 1) {
4465+
/* Publish to caller. */
4466+
XMEMCPY(tm, &localTm, sizeof(*tm));
44244467
#ifdef XMKTIME
4425-
XMEMCPY(&localTm, tm, sizeof(struct tm));
4426-
/* Call XMKTIME on tm to get tm_wday and tm_yday fields populated.
4427-
Note that localTm is used here to avoid modifying other fields,
4428-
such as tm_isdst/tm_gmtoff. */
4468+
/* XMKTIME may set tm_isdst/tm_gmtoff on localTm; call after the
4469+
* copy so those fields stay zero in the caller's tm. */
44294470
XMKTIME(&localTm);
44304471
tm->tm_wday = localTm.tm_wday;
44314472
tm->tm_yday = localTm.tm_yday;

wolfcrypt/src/asn.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14664,7 +14664,7 @@ int GetTimeString(byte* date, int format, char* buf, int len, int dateLen)
1466414664
#endif /* WOLFSSL_ASN_TIME_STRING */
1466514665

1466614666
/* Check time struct for valid values. Returns 0 for success */
14667-
static int ValidateGmtime(struct tm* inTime)
14667+
int ValidateGmtime(struct tm* inTime)
1466814668
{
1466914669
int ret = 1;
1467014670
if ((inTime != NULL) &&

wolfssl/wolfcrypt/asn.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2452,6 +2452,7 @@ WOLFSSL_LOCAL int GetFormattedTime_ex(void* currTime, byte* buf, word32 len, byt
24522452
WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format,
24532453
wolfssl_tm* certTime, int* idx, int len);
24542454
WOLFSSL_LOCAL int DateGreaterThan(const struct tm* a, const struct tm* b);
2455+
WOLFSSL_LOCAL int ValidateGmtime(struct tm* inTime);
24552456
WOLFSSL_LOCAL int wc_ValidateDate(const byte* date, byte format, int dateType,
24562457
int len);
24572458
#ifndef NO_ASN_TIME

0 commit comments

Comments
 (0)