Validate asn date based on position of Z (#8603)

This commit is contained in:
Anthony Hu
2025-12-29 17:01:22 -05:00
committed by GitHub
parent 5dee8ddfcb
commit 48ebe99372
12 changed files with 117 additions and 53 deletions
+13
View File
@@ -0,0 +1,13 @@
-----BEGIN X509 CRL-----
MIIB7DCB1QIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzELMAkGA1UE
CAwCVVMxCzAJBgNVBAcMAlVTMQswCQYDVQQKDAJVUzELMAkGA1UEAwwCVVMxCzAJ
BgNVBAsMAlVTGA0yNDAxMjMwMDAwMDBaGA0zNDAxMjAwMDAwMDBaMDUwMwIUHIAC
LvgfJAXulqYS3LYf4KxwHl4XDTI1MDMxMzAyNDQ0MFowDDAKBgNVHRUEAwoBBqAc
MBowGAYDVR0UBBECDxnP/97adO3y9qRGDM7hQDANBgkqhkiG9w0BAQsFAAOCAQEA
aDY9jBdAJiAujUkaLYLVtzNWF/0SxD5CB4dYIcZMqtPKLn5ykcxkXvnRbVihJ+Kn
AAv9Fkn5iwj77EGwxNjyZktQ4gAmcMhCTBEcAHbmi92tHttot9Sr44+CN+0NaaQD
OflIeVw7Zir90TWufjScy8/e7FkVm+aD5CicrbJWqoe21pB1Q1jS49iNrZzqZ2vw
HLiqNAzpecxwUih/YPe5+CBk5Nq4vICeieGVC/JO9r5SkdDwWQTl0I3kSK6n4Jh7
53FmIen80F2ZZuZu4/fhJ7C4rlr6W9i6FrK06s5mk1PeYFHKhCkwI8wp8cIudJQD
lLsK2u4CTcuTKdbDLsszYA==
-----END X509 CRL-----
+2 -1
View File
@@ -16,7 +16,8 @@ EXTRA_DIST += \
certs/crl/wolfssl.cnf \
certs/crl/crl.der \
certs/crl/crl2.der \
certs/crl/crl_rsapss.pem
certs/crl/crl_rsapss.pem \
certs/crl/bad_time_fmt.pem
EXTRA_DIST += \
certs/crl/crl.revoked \
+2 -1
View File
@@ -446,7 +446,8 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial,
#endif
{
#if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK)
if (!XVALIDATE_DATE(crle->nextDate,crle->nextDateFormat, ASN_AFTER)) {
if (!XVALIDATE_DATE(crle->nextDate, crle->nextDateFormat,
ASN_AFTER, MAX_DATE_SIZE)) {
WOLFSSL_MSG("CRL next date is no longer valid");
nextDateValid = 0;
}
+2 -2
View File
@@ -296,10 +296,10 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
else if (*status) {
#ifndef NO_ASN_TIME
if (XVALIDATE_DATE((*status)->thisDate,
(*status)->thisDateFormat, ASN_BEFORE)
(*status)->thisDateFormat, ASN_BEFORE, MAX_DATE_SIZE)
&& ((*status)->nextDate[0] != 0)
&& XVALIDATE_DATE((*status)->nextDate,
(*status)->nextDateFormat, ASN_AFTER))
(*status)->nextDateFormat, ASN_AFTER, MAX_DATE_SIZE))
#endif
{
ret = xstat2err((*status)->status);
+2 -1
View File
@@ -22023,7 +22023,8 @@ int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, struct tm *produced_tm) {
return BAD_FUNC_ARG;
if (ExtractDate(ssl->ocspProducedDate,
(unsigned char)ssl->ocspProducedDateFormat, produced_tm, &idx))
(unsigned char)ssl->ocspProducedDateFormat, produced_tm, &idx,
MAX_DATE_SZ))
return 0;
else
return ASN_PARSE_E;
+1 -1
View File
@@ -4194,7 +4194,7 @@ char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len)
}
/* Get time as human readable string. */
if ((buf != NULL) && !GetTimeString(t->data, t->type, buf, len)) {
if ((buf != NULL) && !GetTimeString(t->data, t->type, buf, len, t->length)) {
buf = NULL;
}
+14 -20
View File
@@ -6440,9 +6440,9 @@ static int X509PrintValidity(WOLFSSL_BIO* bio, WOLFSSL_ASN1_TIME * notBefore,
}
if (notBefore->length > 0) {
if (GetTimeString(notBefore->data, ASN_UTC_TIME,
tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
tmp, sizeof(tmp), notBefore->length) != WOLFSSL_SUCCESS) {
if (GetTimeString(notBefore->data, ASN_GENERALIZED_TIME,
tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
tmp, sizeof(tmp), notBefore->length) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Error getting not before date");
return WOLFSSL_FAILURE;
}
@@ -6462,9 +6462,9 @@ static int X509PrintValidity(WOLFSSL_BIO* bio, WOLFSSL_ASN1_TIME * notBefore,
}
if (notAfter->length > 0) {
if (GetTimeString(notAfter->data, ASN_UTC_TIME,
tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
tmp, sizeof(tmp), notAfter->length) != WOLFSSL_SUCCESS) {
if (GetTimeString(notAfter->data, ASN_GENERALIZED_TIME,
tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
tmp, sizeof(tmp), notAfter->length) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Error getting not after date");
return WOLFSSL_FAILURE;
}
@@ -9018,9 +9018,9 @@ static int X509CRLPrintRevoked(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl,
if (revoked->revDate[0] != 0) {
if (GetTimeString(revoked->revDate, ASN_UTC_TIME,
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
if (GetTimeString(revoked->revDate, ASN_GENERALIZED_TIME,
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Error getting revocation date");
return WOLFSSL_FAILURE;
}
@@ -9071,13 +9071,10 @@ static int X509CRLPrintDates(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl,
}
if (crl->crlList->lastDate[0] != 0) {
if (GetTimeString(crl->crlList->lastDate, ASN_UTC_TIME,
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
if (GetTimeString(crl->crlList->lastDate, ASN_GENERALIZED_TIME,
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Error getting last update date");
return WOLFSSL_FAILURE;
}
if (GetTimeString(crl->crlList->lastDate, crl->crlList->lastDateFormat,
tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Error getting last update date");
return WOLFSSL_FAILURE;
}
}
else {
@@ -9102,13 +9099,10 @@ static int X509CRLPrintDates(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl,
}
if (crl->crlList->nextDate[0] != 0) {
if (GetTimeString(crl->crlList->nextDate, ASN_UTC_TIME,
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
if (GetTimeString(crl->crlList->nextDate, ASN_GENERALIZED_TIME,
tmp, MAX_WIDTH) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Error getting next update date");
return WOLFSSL_FAILURE;
}
if (GetTimeString(crl->crlList->nextDate, crl->crlList->nextDateFormat,
tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Error getting next update date");
return WOLFSSL_FAILURE;
}
}
else {
+6 -4
View File
@@ -375,23 +375,25 @@ static int X509StoreVerifyCertDate(WOLFSSL_X509_STORE_CTX* ctx, int ret)
WOLFSSL_MSG("Override date validation, WOLFSSL_USE_CHECK_TIME");
if (wc_ValidateDateWithTime(afterDate,
(byte)ctx->current_cert->notAfter.type, ASN_AFTER,
checkTime) < 1) {
checkTime, ctx->current_cert->notAfter.length) < 1) {
ret = ASN_AFTER_DATE_E;
}
else if (wc_ValidateDateWithTime(beforeDate,
(byte)ctx->current_cert->notBefore.type, ASN_BEFORE,
checkTime) < 1) {
checkTime, ctx->current_cert->notBefore.length) < 1) {
ret = ASN_BEFORE_DATE_E;
}
}
}
#else
if (XVALIDATE_DATE(afterDate,
(byte)ctx->current_cert->notAfter.type, ASN_AFTER) < 1) {
(byte)ctx->current_cert->notAfter.type, ASN_AFTER,
ctx->current_cert->notAfter.length) < 1) {
ret = ASN_AFTER_DATE_E;
}
else if (XVALIDATE_DATE(beforeDate,
(byte)ctx->current_cert->notBefore.type, ASN_BEFORE) < 1) {
(byte)ctx->current_cert->notBefore.type, ASN_BEFORE,
ctx->current_cert->notBefore.length) < 1) {
ret = ASN_BEFORE_DATE_E;
}
#endif /* USE_WOLF_VALIDDATE */
+17 -2
View File
@@ -27601,10 +27601,25 @@ static int test_sk_X509_CRL(void)
ExpectIntEQ(BIO_get_mem_data(bio, NULL), 1324);
#endif
BIO_free(bio);
bio = NULL;
wolfSSL_X509_CRL_free(crl);
crl = NULL;
#endif
#ifndef NO_ASN_TIME
/* Test CRL with invalid GeneralizedTime */
ExpectNotNull(bio = BIO_new_file("./certs/crl/bad_time_fmt.pem", "rb"));
ExpectNotNull(crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL));
BIO_free(bio);
bio = NULL;
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntEQ(wolfSSL_X509_CRL_print(bio, crl), WOLFSSL_FAILURE);
BIO_free(bio);
bio = NULL;
wolfSSL_X509_CRL_free(crl);
crl = NULL;
#endif /* !NO_ASN_TIME */
#endif /* !NO_BIO */
#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
ExpectTrue((fp = XFOPEN("./certs/crl/crl.der", "rb")) != XBADFILE);
+51 -16
View File
@@ -16271,8 +16271,38 @@ static WC_INLINE int GetTime_Long(long* value, const byte* date, int* idx)
* Reminder: idx is incremented in each call to GetTime()
* Return 0 on failure, 1 for success. */
int ExtractDate(const unsigned char* date, unsigned char format,
struct tm* certTime, int* idx)
struct tm* certTime, int* idx, int len)
{
int i = *idx;
/* Validate date string length based on format. Can not assume null
* terminated strings. Must check for the 'Z'.
* Subtract 2; one for zero indexing and one to exclude null terminator
* built into macro values. */
if (format == ASN_UTC_TIME) {
/* UTCTime format requires YYMMDDHHMMSSZ (13 chars). */
/* Bounds check: ensure we have enough data before accessing. */
if (len < i + ASN_UTC_TIME_SIZE - 1) {
return 0;
}
if (date[i + ASN_UTC_TIME_SIZE - 2] != 'Z') {
return 0;
}
}
else if (format == ASN_GENERALIZED_TIME) {
/* GeneralizedTime format requires YYYYMMDDHHMMSSZ (15 chars). */
/* Bounds check: ensure we have enough data before accessing. */
if (len < i + ASN_GENERALIZED_TIME_SIZE - 1) {
return 0;
}
if (date[ i + ASN_GENERALIZED_TIME_SIZE - 2] != 'Z') {
return 0;
}
}
else {
return 0;
}
XMEMSET(certTime, 0, sizeof(struct tm));
/* Get the first two bytes of the year (century) */
@@ -16341,12 +16371,12 @@ int ExtractDate(const unsigned char* date, unsigned char format,
#ifdef WOLFSSL_ASN_TIME_STRING
int GetTimeString(byte* date, int format, char* buf, int len)
int GetTimeString(byte* date, int format, char* buf, int len, int dateLen)
{
struct tm t;
int idx = 0;
if (!ExtractDate(date, (unsigned char)format, &t, &idx)) {
if (!ExtractDate(date, (unsigned char)format, &t, &idx, dateLen)) {
return 0;
}
@@ -16576,13 +16606,13 @@ static WC_INLINE int DateLessThan(const struct tm* a, const struct tm* b)
/* date = ASN.1 raw */
/* format = ASN_UTC_TIME or ASN_GENERALIZED_TIME */
/* dateType = ASN_AFTER or ASN_BEFORE */
int wc_ValidateDate(const byte* date, byte format, int dateType)
int wc_ValidateDate(const byte* date, byte format, int dateType, int len)
{
return wc_ValidateDateWithTime(date, format, dateType, 0);
return wc_ValidateDateWithTime(date, format, dateType, 0, len);
}
int wc_ValidateDateWithTime(const byte* date, byte format, int dateType,
time_t checkTime)
time_t checkTime, int len)
{
time_t ltime;
struct tm certTime;
@@ -16631,7 +16661,7 @@ int wc_ValidateDateWithTime(const byte* date, byte format, int dateType,
}
#endif
if (!ExtractDate(date, format, &certTime, &i)) {
if (!ExtractDate(date, format, &certTime, &i, len)) {
WOLFSSL_MSG("Error extracting the date");
return 0;
}
@@ -16853,7 +16883,7 @@ static int GetDate(DecodedCert* cert, int dateType, int verify, int maxIdx)
#ifndef NO_ASN_TIME_CHECK
if (verify != NO_VERIFY && verify != VERIFY_SKIP_DATE &&
(! AsnSkipDateCheck) &&
!XVALIDATE_DATE(date, format, dateType)) {
!XVALIDATE_DATE(date, format, dateType, length)) {
if (dateType == ASN_BEFORE) {
WOLFSSL_ERROR_VERBOSE(ASN_BEFORE_DATE_E);
return ASN_BEFORE_DATE_E;
@@ -16911,7 +16941,7 @@ int wc_GetDateAsCalendarTime(const byte* date, int length, byte format,
{
int idx = 0;
(void)length;
if (!ExtractDate(date, format, timearg, &idx))
if (!ExtractDate(date, format, timearg, &idx, length))
return ASN_TIME_E;
return 0;
}
@@ -23590,7 +23620,8 @@ static int CheckDate(ASNGetData *dataASN, int dateType)
#ifndef NO_ASN_TIME_CHECK
/* Check date is a valid string and ASN_BEFORE or ASN_AFTER now. */
if ((ret == 0) && (! AsnSkipDateCheck)) {
if (!XVALIDATE_DATE(dataASN->data.ref.data, dataASN->tag, dateType)) {
if (!XVALIDATE_DATE(dataASN->data.ref.data, dataASN->tag, dateType,
(int)dataASN->data.ref.length)) {
if (dateType == ASN_BEFORE) {
ret = ASN_BEFORE_DATE_E;
}
@@ -38381,7 +38412,7 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
#ifndef NO_ASN_TIME_CHECK
#ifndef WOLFSSL_NO_OCSP_DATE_CHECK
if ((! AsnSkipDateCheck) && !XVALIDATE_DATE(single->status->thisDate,
single->status->thisDateFormat, ASN_BEFORE))
single->status->thisDateFormat, ASN_BEFORE, MAX_DATE_SIZE))
return ASN_BEFORE_DATE_E;
#endif
#endif
@@ -38419,7 +38450,7 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
#ifndef WOLFSSL_NO_OCSP_DATE_CHECK
if ((! AsnSkipDateCheck) &&
!XVALIDATE_DATE(single->status->nextDate,
single->status->nextDateFormat, ASN_AFTER))
single->status->nextDateFormat, ASN_AFTER, MAX_DATE_SIZE))
return ASN_AFTER_DATE_E;
#endif
#endif
@@ -38493,7 +38524,8 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
#if !defined(NO_ASN_TIME_CHECK) && !defined(WOLFSSL_NO_OCSP_DATE_CHECK)
/* Check date is a valid string and ASN_BEFORE now. */
if ((! AsnSkipDateCheck) &&
!XVALIDATE_DATE(cs->thisDate, ASN_GENERALIZED_TIME, ASN_BEFORE))
!XVALIDATE_DATE(cs->thisDate, ASN_GENERALIZED_TIME, ASN_BEFORE,
MAX_DATE_SIZE))
{
ret = ASN_BEFORE_DATE_E;
}
@@ -38518,7 +38550,8 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
#if !defined(NO_ASN_TIME_CHECK) && !defined(WOLFSSL_NO_OCSP_DATE_CHECK)
/* Check date is a valid string and ASN_AFTER now. */
if ((! AsnSkipDateCheck) &&
!XVALIDATE_DATE(cs->nextDate, ASN_GENERALIZED_TIME, ASN_AFTER))
!XVALIDATE_DATE(cs->nextDate, ASN_GENERALIZED_TIME, ASN_AFTER,
MAX_DATE_SIZE))
{
ret = ASN_AFTER_DATE_E;
}
@@ -40605,7 +40638,8 @@ static int ParseCRL_CertList(RevokedCert* rcert, DecodedCRL* dcrl,
#if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK)
if (verify != NO_VERIFY &&
(! AsnSkipDateCheck) &&
!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, ASN_AFTER)) {
!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, ASN_AFTER,
MAX_DATE_SIZE)) {
WOLFSSL_MSG("CRL after date is no longer valid");
WOLFSSL_ERROR_VERBOSE(CRL_CERT_DATE_ERR);
return CRL_CERT_DATE_ERR;
@@ -41267,7 +41301,8 @@ end:
/* Next date was set, so validate it. */
if (verify != NO_VERIFY &&
(! AsnSkipDateCheck) &&
!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, ASN_AFTER)) {
!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, ASN_AFTER,
MAX_DATE_SIZE)) {
WOLFSSL_MSG("CRL after date is no longer valid");
ret = CRL_CERT_DATE_ERR;
WOLFSSL_ERROR_VERBOSE(ret);
+6 -4
View File
@@ -2244,7 +2244,8 @@ WOLFSSL_LOCAL int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID,
typedef struct tm wolfssl_tm;
#ifdef WOLFSSL_ASN_TIME_STRING
WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len);
WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len,
int dateLen);
#endif
#if !defined(NO_ASN_TIME) && !defined(USER_TIME) && \
!defined(TIME_OVERRIDES) && (defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7))
@@ -2252,12 +2253,13 @@ WOLFSSL_LOCAL int GetFormattedTime(void* currTime, byte* buf, word32 len);
WOLFSSL_LOCAL int GetAsnTimeString(void* currTime, byte* buf, word32 len);
#endif
WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format,
wolfssl_tm* certTime, int* idx);
wolfssl_tm* certTime, int* idx, int len);
WOLFSSL_LOCAL int DateGreaterThan(const struct tm* a, const struct tm* b);
WOLFSSL_LOCAL int wc_ValidateDate(const byte* date, byte format, int dateType);
WOLFSSL_LOCAL int wc_ValidateDate(const byte* date, byte format, int dateType,
int len);
#ifndef NO_ASN_TIME
WOLFSSL_LOCAL int wc_ValidateDateWithTime(const byte* date, byte format,
int dateType, time_t checkTime);
int dateType, time_t checkTime, int len);
#endif
WOLFSSL_TEST_VIS int wc_AsnSetSkipDateCheck(int skip_p);
WOLFSSL_LOCAL int wc_AsnGetSkipDateCheck(void);
+1 -1
View File
@@ -1586,7 +1586,7 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void);
#endif
#if !defined(XVALIDATE_DATE) && !defined(HAVE_VALIDATE_DATE)
#define USE_WOLF_VALIDDATE
#define XVALIDATE_DATE(d, f, t) wc_ValidateDate((d), (f), (t))
#define XVALIDATE_DATE(d, f, t, l) wc_ValidateDate((d), (f), (t), (l))
#endif
/* wolf struct tm and time_t */