Skip to content

Commit 48ebe99

Browse files
authored
Validate asn date based on position of Z (#8603)
1 parent 5dee8dd commit 48ebe99

12 files changed

Lines changed: 116 additions & 52 deletions

File tree

certs/crl/bad_time_fmt.pem

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-----BEGIN X509 CRL-----
2+
MIIB7DCB1QIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzELMAkGA1UE
3+
CAwCVVMxCzAJBgNVBAcMAlVTMQswCQYDVQQKDAJVUzELMAkGA1UEAwwCVVMxCzAJ
4+
BgNVBAsMAlVTGA0yNDAxMjMwMDAwMDBaGA0zNDAxMjAwMDAwMDBaMDUwMwIUHIAC
5+
LvgfJAXulqYS3LYf4KxwHl4XDTI1MDMxMzAyNDQ0MFowDDAKBgNVHRUEAwoBBqAc
6+
MBowGAYDVR0UBBECDxnP/97adO3y9qRGDM7hQDANBgkqhkiG9w0BAQsFAAOCAQEA
7+
aDY9jBdAJiAujUkaLYLVtzNWF/0SxD5CB4dYIcZMqtPKLn5ykcxkXvnRbVihJ+Kn
8+
AAv9Fkn5iwj77EGwxNjyZktQ4gAmcMhCTBEcAHbmi92tHttot9Sr44+CN+0NaaQD
9+
OflIeVw7Zir90TWufjScy8/e7FkVm+aD5CicrbJWqoe21pB1Q1jS49iNrZzqZ2vw
10+
HLiqNAzpecxwUih/YPe5+CBk5Nq4vICeieGVC/JO9r5SkdDwWQTl0I3kSK6n4Jh7
11+
53FmIen80F2ZZuZu4/fhJ7C4rlr6W9i6FrK06s5mk1PeYFHKhCkwI8wp8cIudJQD
12+
lLsK2u4CTcuTKdbDLsszYA==
13+
-----END X509 CRL-----

certs/crl/include.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ EXTRA_DIST += \
1616
certs/crl/wolfssl.cnf \
1717
certs/crl/crl.der \
1818
certs/crl/crl2.der \
19-
certs/crl/crl_rsapss.pem
19+
certs/crl/crl_rsapss.pem \
20+
certs/crl/bad_time_fmt.pem
2021

2122
EXTRA_DIST += \
2223
certs/crl/crl.revoked \

src/crl.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,8 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial,
446446
#endif
447447
{
448448
#if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK)
449-
if (!XVALIDATE_DATE(crle->nextDate,crle->nextDateFormat, ASN_AFTER)) {
449+
if (!XVALIDATE_DATE(crle->nextDate, crle->nextDateFormat,
450+
ASN_AFTER, MAX_DATE_SIZE)) {
450451
WOLFSSL_MSG("CRL next date is no longer valid");
451452
nextDateValid = 0;
452453
}

src/ocsp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,10 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
296296
else if (*status) {
297297
#ifndef NO_ASN_TIME
298298
if (XVALIDATE_DATE((*status)->thisDate,
299-
(*status)->thisDateFormat, ASN_BEFORE)
299+
(*status)->thisDateFormat, ASN_BEFORE, MAX_DATE_SIZE)
300300
&& ((*status)->nextDate[0] != 0)
301301
&& XVALIDATE_DATE((*status)->nextDate,
302-
(*status)->nextDateFormat, ASN_AFTER))
302+
(*status)->nextDateFormat, ASN_AFTER, MAX_DATE_SIZE))
303303
#endif
304304
{
305305
ret = xstat2err((*status)->status);

src/ssl.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22023,7 +22023,8 @@ int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, struct tm *produced_tm) {
2202322023
return BAD_FUNC_ARG;
2202422024

2202522025
if (ExtractDate(ssl->ocspProducedDate,
22026-
(unsigned char)ssl->ocspProducedDateFormat, produced_tm, &idx))
22026+
(unsigned char)ssl->ocspProducedDateFormat, produced_tm, &idx,
22027+
MAX_DATE_SZ))
2202722028
return 0;
2202822029
else
2202922030
return ASN_PARSE_E;

src/ssl_asn1.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4194,7 +4194,7 @@ char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len)
41944194
}
41954195

41964196
/* Get time as human readable string. */
4197-
if ((buf != NULL) && !GetTimeString(t->data, t->type, buf, len)) {
4197+
if ((buf != NULL) && !GetTimeString(t->data, t->type, buf, len, t->length)) {
41984198
buf = NULL;
41994199
}
42004200

src/x509.c

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6440,9 +6440,9 @@ static int X509PrintValidity(WOLFSSL_BIO* bio, WOLFSSL_ASN1_TIME * notBefore,
64406440
}
64416441
if (notBefore->length > 0) {
64426442
if (GetTimeString(notBefore->data, ASN_UTC_TIME,
6443-
tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
6443+
tmp, sizeof(tmp), notBefore->length) != WOLFSSL_SUCCESS) {
64446444
if (GetTimeString(notBefore->data, ASN_GENERALIZED_TIME,
6445-
tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
6445+
tmp, sizeof(tmp), notBefore->length) != WOLFSSL_SUCCESS) {
64466446
WOLFSSL_MSG("Error getting not before date");
64476447
return WOLFSSL_FAILURE;
64486448
}
@@ -6462,9 +6462,9 @@ static int X509PrintValidity(WOLFSSL_BIO* bio, WOLFSSL_ASN1_TIME * notBefore,
64626462
}
64636463
if (notAfter->length > 0) {
64646464
if (GetTimeString(notAfter->data, ASN_UTC_TIME,
6465-
tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
6465+
tmp, sizeof(tmp), notAfter->length) != WOLFSSL_SUCCESS) {
64666466
if (GetTimeString(notAfter->data, ASN_GENERALIZED_TIME,
6467-
tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
6467+
tmp, sizeof(tmp), notAfter->length) != WOLFSSL_SUCCESS) {
64686468
WOLFSSL_MSG("Error getting not after date");
64696469
return WOLFSSL_FAILURE;
64706470
}
@@ -9018,9 +9018,9 @@ static int X509CRLPrintRevoked(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl,
90189018

90199019
if (revoked->revDate[0] != 0) {
90209020
if (GetTimeString(revoked->revDate, ASN_UTC_TIME,
9021-
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
9021+
tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
90229022
if (GetTimeString(revoked->revDate, ASN_GENERALIZED_TIME,
9023-
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
9023+
tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
90249024
WOLFSSL_MSG("Error getting revocation date");
90259025
return WOLFSSL_FAILURE;
90269026
}
@@ -9071,13 +9071,10 @@ static int X509CRLPrintDates(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl,
90719071
}
90729072

90739073
if (crl->crlList->lastDate[0] != 0) {
9074-
if (GetTimeString(crl->crlList->lastDate, ASN_UTC_TIME,
9075-
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
9076-
if (GetTimeString(crl->crlList->lastDate, ASN_GENERALIZED_TIME,
9077-
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
9078-
WOLFSSL_MSG("Error getting last update date");
9079-
return WOLFSSL_FAILURE;
9080-
}
9074+
if (GetTimeString(crl->crlList->lastDate, crl->crlList->lastDateFormat,
9075+
tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
9076+
WOLFSSL_MSG("Error getting last update date");
9077+
return WOLFSSL_FAILURE;
90819078
}
90829079
}
90839080
else {
@@ -9102,13 +9099,10 @@ static int X509CRLPrintDates(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl,
91029099
}
91039100

91049101
if (crl->crlList->nextDate[0] != 0) {
9105-
if (GetTimeString(crl->crlList->nextDate, ASN_UTC_TIME,
9106-
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
9107-
if (GetTimeString(crl->crlList->nextDate, ASN_GENERALIZED_TIME,
9108-
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
9109-
WOLFSSL_MSG("Error getting next update date");
9110-
return WOLFSSL_FAILURE;
9111-
}
9102+
if (GetTimeString(crl->crlList->nextDate, crl->crlList->nextDateFormat,
9103+
tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
9104+
WOLFSSL_MSG("Error getting next update date");
9105+
return WOLFSSL_FAILURE;
91129106
}
91139107
}
91149108
else {

src/x509_str.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -375,23 +375,25 @@ static int X509StoreVerifyCertDate(WOLFSSL_X509_STORE_CTX* ctx, int ret)
375375
WOLFSSL_MSG("Override date validation, WOLFSSL_USE_CHECK_TIME");
376376
if (wc_ValidateDateWithTime(afterDate,
377377
(byte)ctx->current_cert->notAfter.type, ASN_AFTER,
378-
checkTime) < 1) {
378+
checkTime, ctx->current_cert->notAfter.length) < 1) {
379379
ret = ASN_AFTER_DATE_E;
380380
}
381381
else if (wc_ValidateDateWithTime(beforeDate,
382382
(byte)ctx->current_cert->notBefore.type, ASN_BEFORE,
383-
checkTime) < 1) {
383+
checkTime, ctx->current_cert->notBefore.length) < 1) {
384384
ret = ASN_BEFORE_DATE_E;
385385
}
386386
}
387387
}
388388
#else
389389
if (XVALIDATE_DATE(afterDate,
390-
(byte)ctx->current_cert->notAfter.type, ASN_AFTER) < 1) {
390+
(byte)ctx->current_cert->notAfter.type, ASN_AFTER,
391+
ctx->current_cert->notAfter.length) < 1) {
391392
ret = ASN_AFTER_DATE_E;
392393
}
393394
else if (XVALIDATE_DATE(beforeDate,
394-
(byte)ctx->current_cert->notBefore.type, ASN_BEFORE) < 1) {
395+
(byte)ctx->current_cert->notBefore.type, ASN_BEFORE,
396+
ctx->current_cert->notBefore.length) < 1) {
395397
ret = ASN_BEFORE_DATE_E;
396398
}
397399
#endif /* USE_WOLF_VALIDDATE */

tests/api.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27601,10 +27601,25 @@ static int test_sk_X509_CRL(void)
2760127601
ExpectIntEQ(BIO_get_mem_data(bio, NULL), 1324);
2760227602
#endif
2760327603
BIO_free(bio);
27604+
bio = NULL;
27605+
wolfSSL_X509_CRL_free(crl);
27606+
crl = NULL;
27607+
27608+
#ifndef NO_ASN_TIME
27609+
/* Test CRL with invalid GeneralizedTime */
27610+
ExpectNotNull(bio = BIO_new_file("./certs/crl/bad_time_fmt.pem", "rb"));
27611+
ExpectNotNull(crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL));
27612+
BIO_free(bio);
27613+
bio = NULL;
27614+
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
27615+
ExpectIntEQ(wolfSSL_X509_CRL_print(bio, crl), WOLFSSL_FAILURE);
2760427616

27617+
BIO_free(bio);
27618+
bio = NULL;
2760527619
wolfSSL_X509_CRL_free(crl);
2760627620
crl = NULL;
27607-
#endif
27621+
#endif /* !NO_ASN_TIME */
27622+
#endif /* !NO_BIO */
2760827623

2760927624
#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
2761027625
ExpectTrue((fp = XFOPEN("./certs/crl/crl.der", "rb")) != XBADFILE);

wolfcrypt/src/asn.c

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16271,8 +16271,38 @@ static WC_INLINE int GetTime_Long(long* value, const byte* date, int* idx)
1627116271
* Reminder: idx is incremented in each call to GetTime()
1627216272
* Return 0 on failure, 1 for success. */
1627316273
int ExtractDate(const unsigned char* date, unsigned char format,
16274-
struct tm* certTime, int* idx)
16274+
struct tm* certTime, int* idx, int len)
1627516275
{
16276+
int i = *idx;
16277+
16278+
/* Validate date string length based on format. Can not assume null
16279+
* terminated strings. Must check for the 'Z'.
16280+
* Subtract 2; one for zero indexing and one to exclude null terminator
16281+
* built into macro values. */
16282+
if (format == ASN_UTC_TIME) {
16283+
/* UTCTime format requires YYMMDDHHMMSSZ (13 chars). */
16284+
/* Bounds check: ensure we have enough data before accessing. */
16285+
if (len < i + ASN_UTC_TIME_SIZE - 1) {
16286+
return 0;
16287+
}
16288+
if (date[i + ASN_UTC_TIME_SIZE - 2] != 'Z') {
16289+
return 0;
16290+
}
16291+
}
16292+
else if (format == ASN_GENERALIZED_TIME) {
16293+
/* GeneralizedTime format requires YYYYMMDDHHMMSSZ (15 chars). */
16294+
/* Bounds check: ensure we have enough data before accessing. */
16295+
if (len < i + ASN_GENERALIZED_TIME_SIZE - 1) {
16296+
return 0;
16297+
}
16298+
if (date[ i + ASN_GENERALIZED_TIME_SIZE - 2] != 'Z') {
16299+
return 0;
16300+
}
16301+
}
16302+
else {
16303+
return 0;
16304+
}
16305+
1627616306
XMEMSET(certTime, 0, sizeof(struct tm));
1627716307

1627816308
/* Get the first two bytes of the year (century) */
@@ -16341,12 +16371,12 @@ int ExtractDate(const unsigned char* date, unsigned char format,
1634116371

1634216372

1634316373
#ifdef WOLFSSL_ASN_TIME_STRING
16344-
int GetTimeString(byte* date, int format, char* buf, int len)
16374+
int GetTimeString(byte* date, int format, char* buf, int len, int dateLen)
1634516375
{
1634616376
struct tm t;
1634716377
int idx = 0;
1634816378

16349-
if (!ExtractDate(date, (unsigned char)format, &t, &idx)) {
16379+
if (!ExtractDate(date, (unsigned char)format, &t, &idx, dateLen)) {
1635016380
return 0;
1635116381
}
1635216382

@@ -16576,13 +16606,13 @@ static WC_INLINE int DateLessThan(const struct tm* a, const struct tm* b)
1657616606
/* date = ASN.1 raw */
1657716607
/* format = ASN_UTC_TIME or ASN_GENERALIZED_TIME */
1657816608
/* dateType = ASN_AFTER or ASN_BEFORE */
16579-
int wc_ValidateDate(const byte* date, byte format, int dateType)
16609+
int wc_ValidateDate(const byte* date, byte format, int dateType, int len)
1658016610
{
16581-
return wc_ValidateDateWithTime(date, format, dateType, 0);
16611+
return wc_ValidateDateWithTime(date, format, dateType, 0, len);
1658216612
}
1658316613

1658416614
int wc_ValidateDateWithTime(const byte* date, byte format, int dateType,
16585-
time_t checkTime)
16615+
time_t checkTime, int len)
1658616616
{
1658716617
time_t ltime;
1658816618
struct tm certTime;
@@ -16631,7 +16661,7 @@ int wc_ValidateDateWithTime(const byte* date, byte format, int dateType,
1663116661
}
1663216662
#endif
1663316663

16634-
if (!ExtractDate(date, format, &certTime, &i)) {
16664+
if (!ExtractDate(date, format, &certTime, &i, len)) {
1663516665
WOLFSSL_MSG("Error extracting the date");
1663616666
return 0;
1663716667
}
@@ -16853,7 +16883,7 @@ static int GetDate(DecodedCert* cert, int dateType, int verify, int maxIdx)
1685316883
#ifndef NO_ASN_TIME_CHECK
1685416884
if (verify != NO_VERIFY && verify != VERIFY_SKIP_DATE &&
1685516885
(! AsnSkipDateCheck) &&
16856-
!XVALIDATE_DATE(date, format, dateType)) {
16886+
!XVALIDATE_DATE(date, format, dateType, length)) {
1685716887
if (dateType == ASN_BEFORE) {
1685816888
WOLFSSL_ERROR_VERBOSE(ASN_BEFORE_DATE_E);
1685916889
return ASN_BEFORE_DATE_E;
@@ -16911,7 +16941,7 @@ int wc_GetDateAsCalendarTime(const byte* date, int length, byte format,
1691116941
{
1691216942
int idx = 0;
1691316943
(void)length;
16914-
if (!ExtractDate(date, format, timearg, &idx))
16944+
if (!ExtractDate(date, format, timearg, &idx, length))
1691516945
return ASN_TIME_E;
1691616946
return 0;
1691716947
}
@@ -23590,7 +23620,8 @@ static int CheckDate(ASNGetData *dataASN, int dateType)
2359023620
#ifndef NO_ASN_TIME_CHECK
2359123621
/* Check date is a valid string and ASN_BEFORE or ASN_AFTER now. */
2359223622
if ((ret == 0) && (! AsnSkipDateCheck)) {
23593-
if (!XVALIDATE_DATE(dataASN->data.ref.data, dataASN->tag, dateType)) {
23623+
if (!XVALIDATE_DATE(dataASN->data.ref.data, dataASN->tag, dateType,
23624+
(int)dataASN->data.ref.length)) {
2359423625
if (dateType == ASN_BEFORE) {
2359523626
ret = ASN_BEFORE_DATE_E;
2359623627
}
@@ -38381,7 +38412,7 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
3838138412
#ifndef NO_ASN_TIME_CHECK
3838238413
#ifndef WOLFSSL_NO_OCSP_DATE_CHECK
3838338414
if ((! AsnSkipDateCheck) && !XVALIDATE_DATE(single->status->thisDate,
38384-
single->status->thisDateFormat, ASN_BEFORE))
38415+
single->status->thisDateFormat, ASN_BEFORE, MAX_DATE_SIZE))
3838538416
return ASN_BEFORE_DATE_E;
3838638417
#endif
3838738418
#endif
@@ -38419,7 +38450,7 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
3841938450
#ifndef WOLFSSL_NO_OCSP_DATE_CHECK
3842038451
if ((! AsnSkipDateCheck) &&
3842138452
!XVALIDATE_DATE(single->status->nextDate,
38422-
single->status->nextDateFormat, ASN_AFTER))
38453+
single->status->nextDateFormat, ASN_AFTER, MAX_DATE_SIZE))
3842338454
return ASN_AFTER_DATE_E;
3842438455
#endif
3842538456
#endif
@@ -38493,7 +38524,8 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
3849338524
#if !defined(NO_ASN_TIME_CHECK) && !defined(WOLFSSL_NO_OCSP_DATE_CHECK)
3849438525
/* Check date is a valid string and ASN_BEFORE now. */
3849538526
if ((! AsnSkipDateCheck) &&
38496-
!XVALIDATE_DATE(cs->thisDate, ASN_GENERALIZED_TIME, ASN_BEFORE))
38527+
!XVALIDATE_DATE(cs->thisDate, ASN_GENERALIZED_TIME, ASN_BEFORE,
38528+
MAX_DATE_SIZE))
3849738529
{
3849838530
ret = ASN_BEFORE_DATE_E;
3849938531
}
@@ -38518,7 +38550,8 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
3851838550
#if !defined(NO_ASN_TIME_CHECK) && !defined(WOLFSSL_NO_OCSP_DATE_CHECK)
3851938551
/* Check date is a valid string and ASN_AFTER now. */
3852038552
if ((! AsnSkipDateCheck) &&
38521-
!XVALIDATE_DATE(cs->nextDate, ASN_GENERALIZED_TIME, ASN_AFTER))
38553+
!XVALIDATE_DATE(cs->nextDate, ASN_GENERALIZED_TIME, ASN_AFTER,
38554+
MAX_DATE_SIZE))
3852238555
{
3852338556
ret = ASN_AFTER_DATE_E;
3852438557
}
@@ -40605,7 +40638,8 @@ static int ParseCRL_CertList(RevokedCert* rcert, DecodedCRL* dcrl,
4060540638
#if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK)
4060640639
if (verify != NO_VERIFY &&
4060740640
(! AsnSkipDateCheck) &&
40608-
!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, ASN_AFTER)) {
40641+
!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, ASN_AFTER,
40642+
MAX_DATE_SIZE)) {
4060940643
WOLFSSL_MSG("CRL after date is no longer valid");
4061040644
WOLFSSL_ERROR_VERBOSE(CRL_CERT_DATE_ERR);
4061140645
return CRL_CERT_DATE_ERR;
@@ -41267,7 +41301,8 @@ int ParseCRL(RevokedCert* rcert, DecodedCRL* dcrl, const byte* buff, word32 sz,
4126741301
/* Next date was set, so validate it. */
4126841302
if (verify != NO_VERIFY &&
4126941303
(! AsnSkipDateCheck) &&
41270-
!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, ASN_AFTER)) {
41304+
!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, ASN_AFTER,
41305+
MAX_DATE_SIZE)) {
4127141306
WOLFSSL_MSG("CRL after date is no longer valid");
4127241307
ret = CRL_CERT_DATE_ERR;
4127341308
WOLFSSL_ERROR_VERBOSE(ret);

0 commit comments

Comments
 (0)