From b7c08988dc5f026aa32ad17510c3a8760ede53c8 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 13 Sep 2019 09:23:07 -0700 Subject: [PATCH 1/2] Fix for verify callback override of intermediate CA provided by peer not being added to trusted CA list. Feature: Added support for testing date override at build-time using `TEST_BEFORE_DATE`. ``` ./examples/server/server -H overrideDateErr -A ./certs/ca-cert.pem -k ./certs/server-key.pem -c ./certs/intermediate/server-chain.pem & ./examples/client/client -D -A ./certs/ca-cert.pem -k ./certs/client-key.pem -c ./certs/intermediate/client-chain.pem ``` --- examples/client/client.c | 8 +++-- examples/server/server.c | 25 +++++++++++++-- src/internal.c | 61 ++++++++++++++++++++----------------- wolfssl/wolfcrypt/wc_port.h | 4 +++ 4 files changed, 65 insertions(+), 33 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 56f551b95..78fb9df0b 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -2346,7 +2346,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (!usePsk && !useAnon && !useVerifyCb && !myVerifyFail) { #ifndef TEST_LOAD_BUFFER - if (wolfSSL_CTX_load_verify_locations(ctx, verifyCert, 0) + unsigned int verify_flags = 0; + #ifdef TEST_BEFORE_DATE + verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY; + #endif + if (wolfSSL_CTX_load_verify_locations_ex(ctx, verifyCert, 0, verify_flags) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("can't load ca file, Please run from wolfSSL home dir"); @@ -2358,7 +2362,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_ECC /* load ecc verify too, echoserver uses it by default w/ ecc */ #ifndef TEST_LOAD_BUFFER - if (wolfSSL_CTX_load_verify_locations(ctx, eccCertFile, 0) + if (wolfSSL_CTX_load_verify_locations_ex(ctx, eccCertFile, 0, verify_flags) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("can't load ecc ca file, Please run from wolfSSL home dir"); diff --git a/examples/server/server.c b/examples/server/server.c index a7e89ef2c..893bc251c 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -924,6 +924,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) unsigned char alpn_opt = 0; char* cipherList = NULL; int useDefCipherList = 0; + int overrideDateErrors = 0; const char* verifyCert = cliCertFile; const char* ourCert = svrCertFile; const char* ourKey = svrKeyFile; @@ -1036,6 +1037,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) (void)postHandAuth; (void)mcastID; (void)loadCertKeyIntoSSLObj; + (void)overrideDateErrors; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); @@ -1186,6 +1188,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) disallowETM = 1; #endif } + else if (XSTRNCMP(myoptarg, "overrideDateErr", 15) == 0) { + overrideDateErrors = 1; + } else { Usage(); XEXIT_T(MY_EX_USAGE); @@ -1717,10 +1722,17 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) /* if not using PSK, verify peer with certs if using PSK Plus then verify peer certs except PSK suites */ if (doCliCertCheck && (usePsk == 0 || usePskPlus) && useAnon == 0) { + unsigned int verify_flags = 0; SSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | (usePskPlus ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK : - WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), 0); - if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != WOLFSSL_SUCCESS) + WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), + overrideDateErrors == 1 ? myDateCb : NULL); + + #ifdef TEST_BEFORE_DATE + verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY; + #endif + + if (wolfSSL_CTX_load_verify_locations_ex(ctx, verifyCert, 0, verify_flags) != WOLFSSL_SUCCESS) err_sys_ex(runWithErrors, "can't load ca file, Please run from wolfSSL home dir"); #ifdef WOLFSSL_TRUST_PEER_CERT if (trustCert) { @@ -2211,10 +2223,17 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) if (postHandAuth) { + unsigned int verify_flags = 0; + SSL_set_verify(ssl, WOLFSSL_VERIFY_PEER | ((usePskPlus) ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK : WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), 0); - if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) + + #ifdef TEST_BEFORE_DATE + verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY; + #endif + + if (wolfSSL_CTX_load_verify_locations_ex(ctx, verifyCert, 0, verify_flags) != WOLFSSL_SUCCESS) { err_sys_ex(runWithErrors, "can't load ca file, Please run from " "wolfSSL home dir"); diff --git a/src/internal.c b/src/internal.c index e96755cf9..f668933a1 100644 --- a/src/internal.c +++ b/src/internal.c @@ -9547,7 +9547,8 @@ static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args, /* Parse Certificate */ ret = ParseCertRelative(args->dCert, certType, verify, ssl->ctx->cm); - if (ret == 0) { + /* perform below checks for date failure cases */ + if (ret == 0 || ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) { /* get subject and determine if already loaded */ #ifndef NO_SKID if (args->dCert->extAuthKeyIdSet) @@ -9963,39 +9964,13 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, "not adding as CA"); } else if (ret == 0) { - buffer* cert = &args->certs[args->certIdx]; - - /* Is valid CA */ - #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS) - /* if using alternate chain, store the cert used */ - if (ssl->options.usingAltCertChain) { - AddSessionCertToChain(&ssl->session.altChain, - cert->buffer, cert->length); - } - #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */ #ifdef OPENSSL_EXTRA if (args->certIdx > args->untrustedDepth) { args->untrustedDepth = (char)args->certIdx + 1; } #endif - if (!alreadySigner) { - DerBuffer* add = NULL; - ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap); - if (ret < 0) - goto exit_ppc; - - XMEMCPY(add->buffer, cert->buffer, cert->length); - - /* CA already verified above in ParseCertRelative */ - WOLFSSL_MSG("Adding CA from chain"); - ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, - NO_VERIFY); - if (ret == WOLFSSL_SUCCESS) { - ret = 0; - } - } - else { + if (alreadySigner) { WOLFSSL_MSG("Verified CA from chain and already had it"); } } @@ -10077,6 +10052,36 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* Do verify callback */ ret = DoVerifyCallback(ssl, ret, args); + /* If valid CA then add to Certificate Manager */ + if (ret == 0) { + buffer* cert = &args->certs[args->certIdx]; + + /* Is valid CA */ + #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS) + /* if using alternate chain, store the cert used */ + if (ssl->options.usingAltCertChain) { + AddSessionCertToChain(&ssl->session.altChain, + cert->buffer, cert->length); + } + #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */ + if (!alreadySigner) { + DerBuffer* add = NULL; + ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap); + if (ret < 0) + goto exit_ppc; + + XMEMCPY(add->buffer, cert->buffer, cert->length); + + /* CA already verified above in ParseCertRelative */ + WOLFSSL_MSG("Adding CA from chain"); + ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, + NO_VERIFY); + if (ret == WOLFSSL_SUCCESS) { + ret = 0; + } + } + } + /* Handle error codes */ if (ret != 0 && args->lastErr == 0) { args->lastErr = ret; /* save error from last time */ diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 208f3f32d..c4a9eb37b 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -642,7 +642,11 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); /* Map default time functions */ #if !defined(XTIME) && !defined(TIME_OVERRIDES) && !defined(USER_TIME) + #ifdef TEST_BEFORE_DATE + #define XTIME(tl) (946681200UL) /* Jan 1, 2000 */ + #else #define XTIME(tl) time((tl)) + #endif #endif #if !defined(XGMTIME) && !defined(TIME_OVERRIDES) #if defined(WOLFSSL_GMTIME) || !defined(HAVE_GMTIME_R) || defined(WOLF_C99) From 0e5de0c076eb567f6c050ee788e54ef8b93ef9bf Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 17 Sep 2019 07:56:02 -0700 Subject: [PATCH 2/2] Fix to only AddCA when its CA type and veryNone is not set. --- src/internal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index f668933a1..af4c41739 100644 --- a/src/internal.c +++ b/src/internal.c @@ -10053,7 +10053,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = DoVerifyCallback(ssl, ret, args); /* If valid CA then add to Certificate Manager */ - if (ret == 0) { + if (ret == 0 && args->dCert->isCA && !ssl->options.verifyNone) { buffer* cert = &args->certs[args->certIdx]; /* Is valid CA */