mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-10 23:40:51 +02:00
Merge pull request #9522 from JacobBarthelmeh/time
tie in use of check_time with x509 store
This commit is contained in:
+91
-28
@@ -230,6 +230,18 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx,
|
||||
XMEMSET(ctx->param, 0, sizeof(*ctx->param));
|
||||
}
|
||||
|
||||
/* Copy check_time from store parameters if available */
|
||||
if (store != NULL && store->param != NULL) {
|
||||
if ((store->param->flags & WOLFSSL_USE_CHECK_TIME) != 0 &&
|
||||
store->param->check_time != 0) {
|
||||
ctx->param->check_time = store->param->check_time;
|
||||
ctx->param->flags |= WOLFSSL_USE_CHECK_TIME;
|
||||
}
|
||||
if ((store->param->flags & WOLFSSL_NO_CHECK_TIME) != 0) {
|
||||
ctx->param->flags |= WOLFSSL_NO_CHECK_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
return WOLFSSL_SUCCESS;
|
||||
}
|
||||
return WOLFSSL_FAILURE;
|
||||
@@ -321,6 +333,74 @@ static void SetupStoreCtxError(WOLFSSL_X509_STORE_CTX* ctx, int ret)
|
||||
SetupStoreCtxError_ex(ctx, ret, depth);
|
||||
}
|
||||
|
||||
#ifndef NO_ASN_TIME
|
||||
/* Post certificate validation date handling. This function is called after the
|
||||
* certificate has been verified by the certificate manager. It then checks if
|
||||
* X509 store parameters are set for date validation override.
|
||||
* @param ctx The certificate store context
|
||||
* @param ret The return value from the certificate manager verify
|
||||
* @return The return value for the certificate date validation after override
|
||||
*/
|
||||
static int X509StoreVerifyCertDate(WOLFSSL_X509_STORE_CTX* ctx, int ret)
|
||||
{
|
||||
byte *afterDate = ctx->current_cert->notAfter.data;
|
||||
byte *beforeDate = ctx->current_cert->notBefore.data;
|
||||
|
||||
/* Only override existing date errors or WOLFSSL_SUCCESS. */
|
||||
if (ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) ||
|
||||
ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E) ||
|
||||
ret == WC_NO_ERR_TRACE(WOLFSSL_SUCCESS)) {
|
||||
#ifdef USE_WOLF_VALIDDATE
|
||||
WOLFSSL_X509_VERIFY_PARAM* param = NULL;
|
||||
|
||||
/* If no external XVALIDATE_DATE was defined then use param for date
|
||||
validation overrides. */
|
||||
if (ctx->param != NULL) {
|
||||
param = ctx->param;
|
||||
}
|
||||
else if (ctx->store != NULL && ctx->store->param != NULL) {
|
||||
param = ctx->store->param;
|
||||
}
|
||||
|
||||
if (param != NULL) {
|
||||
if ((param->flags & WOLFSSL_NO_CHECK_TIME) != 0) {
|
||||
WOLFSSL_MSG("Overriding date validation WOLFSSL_NO_CHECK_TIME");
|
||||
ret = WOLFSSL_SUCCESS;
|
||||
}
|
||||
else if ((param->flags & WOLFSSL_USE_CHECK_TIME) != 0 &&
|
||||
(param->check_time != 0)) {
|
||||
time_t checkTime = param->check_time;
|
||||
ret = WOLFSSL_SUCCESS; /* override date error and use custom set
|
||||
time for validating certificate dates */
|
||||
WOLFSSL_MSG("Override date validation, WOLFSSL_USE_CHECK_TIME");
|
||||
if (wc_ValidateDateWithTime(afterDate,
|
||||
(byte)ctx->current_cert->notAfter.type, ASN_AFTER,
|
||||
checkTime) < 1) {
|
||||
ret = ASN_AFTER_DATE_E;
|
||||
}
|
||||
else if (wc_ValidateDateWithTime(beforeDate,
|
||||
(byte)ctx->current_cert->notBefore.type, ASN_BEFORE,
|
||||
checkTime) < 1) {
|
||||
ret = ASN_BEFORE_DATE_E;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (XVALIDATE_DATE(afterDate,
|
||||
(byte)ctx->current_cert->notAfter.type, ASN_AFTER) < 1) {
|
||||
ret = ASN_AFTER_DATE_E;
|
||||
}
|
||||
else if (XVALIDATE_DATE(beforeDate,
|
||||
(byte)ctx->current_cert->notBefore.type, ASN_BEFORE) < 1) {
|
||||
ret = ASN_BEFORE_DATE_E;
|
||||
}
|
||||
#endif /* USE_WOLF_VALIDDATE */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* NO_ASN_TIME */
|
||||
|
||||
static int X509StoreVerifyCert(WOLFSSL_X509_STORE_CTX* ctx)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
|
||||
@@ -331,39 +411,16 @@ static int X509StoreVerifyCert(WOLFSSL_X509_STORE_CTX* ctx)
|
||||
ctx->current_cert->derCert->buffer,
|
||||
ctx->current_cert->derCert->length,
|
||||
WOLFSSL_FILETYPE_ASN1);
|
||||
#ifndef NO_ASN_TIME
|
||||
/* update return value with any date validation overrides */
|
||||
ret = X509StoreVerifyCertDate(ctx, ret);
|
||||
#endif
|
||||
SetupStoreCtxError(ctx, ret);
|
||||
#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
|
||||
if (ctx->store->verify_cb)
|
||||
ret = ctx->store->verify_cb(ret >= 0 ? 1 : 0, ctx) == 1 ?
|
||||
WOLFSSL_SUCCESS : ret;
|
||||
#endif
|
||||
|
||||
#ifndef NO_ASN_TIME
|
||||
if (ret != WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) &&
|
||||
ret != WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) {
|
||||
/* wolfSSL_CertManagerVerifyBuffer only returns ASN_AFTER_DATE_E or
|
||||
* ASN_BEFORE_DATE_E if there are no additional errors found in the
|
||||
* cert. Therefore, check if the cert is expired or not yet valid
|
||||
* in order to return the correct expected error. */
|
||||
byte *afterDate = ctx->current_cert->notAfter.data;
|
||||
byte *beforeDate = ctx->current_cert->notBefore.data;
|
||||
|
||||
if (XVALIDATE_DATE(afterDate,
|
||||
(byte)ctx->current_cert->notAfter.type, ASN_AFTER) < 1) {
|
||||
ret = ASN_AFTER_DATE_E;
|
||||
}
|
||||
else if (XVALIDATE_DATE(beforeDate,
|
||||
(byte)ctx->current_cert->notBefore.type, ASN_BEFORE) < 1) {
|
||||
ret = ASN_BEFORE_DATE_E;
|
||||
}
|
||||
SetupStoreCtxError(ctx, ret);
|
||||
#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
|
||||
if (ctx->store->verify_cb)
|
||||
ret = ctx->store->verify_cb(ret >= 0 ? 1 : 0,
|
||||
ctx) == 1 ? WOLFSSL_SUCCESS : -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1445,16 +1502,22 @@ static int X509StoreAddCa(WOLFSSL_X509_STORE* store,
|
||||
{
|
||||
int result = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
|
||||
DerBuffer* derCert = NULL;
|
||||
int verify = VERIFY;
|
||||
|
||||
WOLFSSL_ENTER("X509StoreAddCa");
|
||||
if (store != NULL && x509 != NULL && x509->derCert != NULL) {
|
||||
/* Check if NO_CHECK_TIME flag is set - if so, skip date validation */
|
||||
if (store->param != NULL &&
|
||||
(store->param->flags & WOLFSSL_NO_CHECK_TIME) != 0) {
|
||||
verify = VERIFY_SKIP_DATE;
|
||||
}
|
||||
result = AllocDer(&derCert, x509->derCert->length,
|
||||
x509->derCert->type, NULL);
|
||||
if (result == 0) {
|
||||
/* AddCA() frees the buffer. */
|
||||
XMEMCPY(derCert->buffer,
|
||||
x509->derCert->buffer, x509->derCert->length);
|
||||
result = AddCA(store->cm, &derCert, type, VERIFY);
|
||||
result = AddCA(store->cm, &derCert, type, verify);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,117 @@ int test_wolfSSL_X509_STORE_CTX_set_time(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_wolfSSL_X509_STORE_check_time(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && \
|
||||
!defined(NO_ASN_TIME) && !defined(NO_RSA)
|
||||
WOLFSSL_X509_STORE* store = NULL;
|
||||
WOLFSSL_X509_STORE_CTX* ctx = NULL;
|
||||
WOLFSSL_X509* ca = NULL;
|
||||
WOLFSSL_X509* cert = NULL;
|
||||
int ret;
|
||||
time_t check_time;
|
||||
const char* srvCertFile = "./certs/server-cert.pem";
|
||||
const char* expiredCertFile = "./certs/test/expired/expired-cert.pem";
|
||||
|
||||
/* Set check_time to May 26, 2000 - should fail "not yet valid" check */
|
||||
ExpectNotNull(store = wolfSSL_X509_STORE_new());
|
||||
if (store != NULL) {
|
||||
/* Load CA certificate - should validate with current time by default */
|
||||
ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile,
|
||||
SSL_FILETYPE_PEM));
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, ca), WOLFSSL_SUCCESS);
|
||||
|
||||
/* Set check_time to May 26, 2000 (timestamp: 959320800) */
|
||||
check_time = (time_t)959320800; /* May 26, 2000 00:00:00 UTC */
|
||||
store->param->check_time = check_time;
|
||||
wolfSSL_X509_VERIFY_PARAM_set_flags(store->param,
|
||||
WOLFSSL_USE_CHECK_TIME);
|
||||
ExpectTrue(store->param->check_time == check_time);
|
||||
ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(srvCertFile,
|
||||
SSL_FILETYPE_PEM));
|
||||
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, cert, NULL),
|
||||
WOLFSSL_SUCCESS);
|
||||
|
||||
/* Verify that check_time was copied to context */
|
||||
ExpectTrue((ctx->param->flags & WOLFSSL_USE_CHECK_TIME) ==
|
||||
WOLFSSL_USE_CHECK_TIME);
|
||||
ExpectTrue(ctx->param->check_time == check_time);
|
||||
|
||||
/* Verify certificate using the custom check_time - should fail because
|
||||
* certificate is not yet valid (use before check fails) */
|
||||
ret = wolfSSL_X509_verify_cert(ctx);
|
||||
ExpectIntNE(ret, WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error(ctx),
|
||||
WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID);
|
||||
wolfSSL_X509_STORE_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
wolfSSL_X509_STORE_free(store);
|
||||
store = NULL;
|
||||
wolfSSL_X509_free(cert);
|
||||
cert = NULL;
|
||||
wolfSSL_X509_free(ca);
|
||||
ca = NULL;
|
||||
|
||||
/* Verify without setting check_time - should work with current time */
|
||||
ExpectNotNull(store = wolfSSL_X509_STORE_new());
|
||||
if (store != NULL) {
|
||||
ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile,
|
||||
SSL_FILETYPE_PEM));
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, ca), WOLFSSL_SUCCESS);
|
||||
ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(srvCertFile,
|
||||
SSL_FILETYPE_PEM));
|
||||
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, cert, NULL),
|
||||
WOLFSSL_SUCCESS);
|
||||
ret = wolfSSL_X509_verify_cert(ctx);
|
||||
ExpectIntEQ(ret, WOLFSSL_SUCCESS);
|
||||
wolfSSL_X509_STORE_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
wolfSSL_X509_STORE_free(store);
|
||||
store = NULL;
|
||||
wolfSSL_X509_free(cert);
|
||||
cert = NULL;
|
||||
wolfSSL_X509_free(ca);
|
||||
ca = NULL;
|
||||
|
||||
/* Test WOLFSSL_NO_CHECK_TIME flag with expired certificate */
|
||||
ExpectNotNull(store = wolfSSL_X509_STORE_new());
|
||||
if (store != NULL) {
|
||||
/* Set NO_CHECK_TIME flag to skip time validation */
|
||||
wolfSSL_X509_VERIFY_PARAM_set_flags(store->param,
|
||||
WOLFSSL_NO_CHECK_TIME);
|
||||
ExpectTrue((store->param->flags & WOLFSSL_NO_CHECK_TIME) ==
|
||||
WOLFSSL_NO_CHECK_TIME);
|
||||
|
||||
/* Load expired certificate (self-signed) */
|
||||
ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(expiredCertFile,
|
||||
SSL_FILETYPE_PEM));
|
||||
/* Add expired certificate as trusted CA (self-signed) */
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, cert), WOLFSSL_SUCCESS);
|
||||
|
||||
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, cert, NULL),
|
||||
WOLFSSL_SUCCESS);
|
||||
/* Verify expired certificate with NO_CHECK_TIME - should succeed
|
||||
* because time validation is skipped */
|
||||
ret = wolfSSL_X509_verify_cert(ctx);
|
||||
ExpectIntEQ(ret, WOLFSSL_SUCCESS);
|
||||
}
|
||||
wolfSSL_X509_STORE_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
wolfSSL_X509_STORE_free(store);
|
||||
store = NULL;
|
||||
wolfSSL_X509_free(cert);
|
||||
cert = NULL;
|
||||
#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM && !NO_ASN_TIME && !NO_RSA */
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_wolfSSL_X509_STORE_CTX_get0_store(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <tests/api/api_decl.h>
|
||||
|
||||
int test_wolfSSL_X509_STORE_CTX_set_time(void);
|
||||
int test_wolfSSL_X509_STORE_check_time(void);
|
||||
int test_wolfSSL_X509_STORE_CTX_get0_store(void);
|
||||
int test_wolfSSL_X509_STORE_CTX(void);
|
||||
int test_wolfSSL_X509_STORE_CTX_ex(void);
|
||||
@@ -43,6 +44,7 @@ int test_X509_STORE_No_SSL_CTX(void);
|
||||
|
||||
#define TEST_OSSL_X509_STORE_DECLS \
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_CTX_set_time), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_check_time), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", \
|
||||
test_wolfSSL_X509_STORE_CTX_get0_store), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_CTX), \
|
||||
|
||||
+14
-1
@@ -16574,6 +16574,12 @@ static WC_INLINE int DateLessThan(const struct tm* a, const struct tm* b)
|
||||
/* format = ASN_UTC_TIME or ASN_GENERALIZED_TIME */
|
||||
/* dateType = ASN_AFTER or ASN_BEFORE */
|
||||
int wc_ValidateDate(const byte* date, byte format, int dateType)
|
||||
{
|
||||
return wc_ValidateDateWithTime(date, format, dateType, 0);
|
||||
}
|
||||
|
||||
int wc_ValidateDateWithTime(const byte* date, byte format, int dateType,
|
||||
time_t checkTime)
|
||||
{
|
||||
time_t ltime;
|
||||
struct tm certTime;
|
||||
@@ -16591,7 +16597,14 @@ int wc_ValidateDate(const byte* date, byte format, int dateType)
|
||||
#endif
|
||||
(void)tmpTime;
|
||||
|
||||
ltime = wc_Time(0);
|
||||
/* Use checkTime if provided (non-zero), otherwise use current time */
|
||||
if (checkTime != 0) {
|
||||
ltime = checkTime;
|
||||
}
|
||||
else {
|
||||
ltime = wc_Time(0);
|
||||
}
|
||||
|
||||
#ifndef NO_TIME_SIGNEDNESS_CHECK
|
||||
if (sizeof(ltime) == sizeof(word32) && (sword32)ltime < 0){
|
||||
/* A negative response here could be due to a 32-bit time_t
|
||||
|
||||
@@ -2255,6 +2255,10 @@ WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format,
|
||||
wolfssl_tm* certTime, int* idx);
|
||||
WOLFSSL_LOCAL int DateGreaterThan(const struct tm* a, const struct tm* b);
|
||||
WOLFSSL_LOCAL int wc_ValidateDate(const byte* date, byte format, int dateType);
|
||||
#ifndef NO_ASN_TIME
|
||||
WOLFSSL_LOCAL int wc_ValidateDateWithTime(const byte* date, byte format,
|
||||
int dateType, time_t checkTime);
|
||||
#endif
|
||||
WOLFSSL_TEST_VIS int wc_AsnSetSkipDateCheck(int skip_p);
|
||||
WOLFSSL_LOCAL int wc_AsnGetSkipDateCheck(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user