diff --git a/src/internal.c b/src/internal.c index 4eeb0329ed..04077ef59f 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7785,6 +7785,11 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) return MEMORY_E; } XMEMSET(ssl->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + + /* pass on PARAM flags value from ctx to ssl */ + wolfSSL_X509_VERIFY_PARAM_set_flags(wolfSSL_get0_param(ssl), + (unsigned long)wolfSSL_X509_VERIFY_PARAM_get_flags( + wolfSSL_CTX_get0_param(ctx))); #endif if (ctx->suites == NULL) { @@ -8733,6 +8738,7 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl) * isn't allocated separately. */ wolfSSL_sk_CIPHER_free(ssl->supportedCiphers); wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL); + wolfSSL_sk_X509_pop_free(ssl->verifiedChain, NULL); #ifdef KEEP_OUR_CERT wolfSSL_sk_X509_pop_free(ssl->ourCertChain, NULL); #endif @@ -14997,6 +15003,25 @@ static int ProcessPeerCertsChainCRLCheck(WOLFSSL* ssl, ProcPeerCertArgs* args) } #endif +#ifdef OPENSSL_EXTRA +/* account for verify params flag set */ +static int AdjustCMForParams(WOLFSSL* ssl) +{ + int flags, ret = WOLFSSL_SUCCESS; + WOLFSSL_X509_VERIFY_PARAM* param; + param = wolfSSL_get0_param(ssl); + + flags = wolfSSL_X509_VERIFY_PARAM_get_flags(param); + + if ((flags & WOLFSSL_CRL_CHECK) == WOLFSSL_CRL_CHECK || + (flags & WOLFSSL_CRL_CHECKALL) == WOLFSSL_CRL_CHECKALL) { + ret = wolfSSL_CertManagerEnableCRL(SSL_CM(ssl), flags & + (WOLFSSL_CRL_CHECK | WOLFSSL_CRL_CHECKALL)); + } + return ret; +} +#endif + int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz) { @@ -15065,6 +15090,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif } +#ifdef OPENSSL_EXTRA + /* account for verify params flag set */ + AdjustCMForParams(ssl); +#endif + switch (ssl->options.asyncState) { case TLS_ASYNC_BEGIN: diff --git a/src/ssl.c b/src/ssl.c index 5ae2afd28b..e031765d83 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -3148,7 +3148,7 @@ int wolfSSL_write_ex(WOLFSSL* ssl, const void* data, int sz, size_t* wr) int ret; ret = wolfSSL_write(ssl, data, sz); - if (ret > 0 && wr != NULL) { + if (ret >= 0 && wr != NULL) { *wr = (size_t)ret; ret = 1; } @@ -3265,6 +3265,7 @@ int wolfSSL_read(WOLFSSL* ssl, void* data, int sz) } +/* returns 0 on failure and on no read */ int wolfSSL_read_ex(WOLFSSL* ssl, void* data, int sz, size_t* rd) { int ret; @@ -3273,6 +3274,8 @@ int wolfSSL_read_ex(WOLFSSL* ssl, void* data, int sz, size_t* rd) if (ret > 0 && rd != NULL) { *rd = (size_t)ret; } + + if (ret <= 0) ret = 0; return ret; } @@ -12750,63 +12753,6 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \ defined(WOLFSSL_WPAS_SMALL)) -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - /** - * Implemented in a similar way that ngx_ssl_ocsp_validate does it when - * SSL_get0_verified_chain is not available. - * @param ssl WOLFSSL object to extract certs from - * @return Stack of verified certs - */ - WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl) - { - WOLF_STACK_OF(WOLFSSL_X509)* chain = NULL; - WOLFSSL_X509_STORE_CTX* storeCtx = NULL; - WOLFSSL_X509* peerCert = NULL; - - WOLFSSL_ENTER("wolfSSL_get0_verified_chain"); - - if (ssl == NULL || ssl->ctx == NULL) { - WOLFSSL_MSG("Bad parameter"); - return NULL; - } - - peerCert = wolfSSL_get_peer_certificate((WOLFSSL*)ssl); - if (peerCert == NULL) { - WOLFSSL_MSG("wolfSSL_get_peer_certificate error"); - return NULL; - } - /* wolfSSL_get_peer_certificate returns a copy. We want the internal - * member so that we don't have to worry about free'ing it. We call - * wolfSSL_get_peer_certificate so that we don't have to worry about - * setting up the internal pointer. */ - wolfSSL_X509_free(peerCert); - peerCert = (WOLFSSL_X509*)&ssl->peerCert; - chain = wolfSSL_get_peer_cert_chain(ssl); - if (chain == NULL) { - WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error"); - return NULL; - } - storeCtx = wolfSSL_X509_STORE_CTX_new(); - if (storeCtx == NULL) { - WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_new error"); - return NULL; - } - if (wolfSSL_X509_STORE_CTX_init(storeCtx, SSL_STORE(ssl), - peerCert, chain) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init error"); - wolfSSL_X509_STORE_CTX_free(storeCtx); - return NULL; - } - if (wolfSSL_X509_verify_cert(storeCtx) <= 0) { - WOLFSSL_MSG("wolfSSL_X509_verify_cert error"); - wolfSSL_X509_STORE_CTX_free(storeCtx); - return NULL; - } - wolfSSL_X509_STORE_CTX_free(storeCtx); - return chain; - } -#endif /* SESSION_CERTS && OPENSSL_EXTRA */ - WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(const WOLFSSL_CTX* ctx) { if (ctx == NULL) { @@ -14390,12 +14336,13 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) /* Try to populate if NULL or empty */ if (ssl->peerCertChain == NULL || - wolfSSL_sk_X509_num(ssl->peerCertChain) == 0) + wolfSSL_sk_X509_num(ssl->peerCertChain) == 0) { wolfSSL_set_peer_cert_chain((WOLFSSL*) ssl); + } return ssl->peerCertChain; } -#ifndef WOLFSSL_QT + static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm, WOLFSSL_X509 *x); /** @@ -14438,13 +14385,14 @@ static int PushCAx509Chain(WOLFSSL_CERT_MANAGER* cm, } return ret; } -#endif /* !WOLFSSL_QT */ + /* Builds up and creates a stack of peer certificates for ssl->peerCertChain - based off of the ssl session chain. Attempts to place CA certificates - at the bottom of the stack. Returns stack of WOLFSSL_X509 certs or - NULL on failure */ -WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) + or ssl->verifiedChain based off of the ssl session chain. Attempts to place + CA certificates at the bottom of the stack for a verified chain. Returns + stack of WOLFSSL_X509 certs or NULL on failure */ +static WOLF_STACK_OF(WOLFSSL_X509)* CreatePeerCertChain(WOLFSSL* ssl, + int verifiedFlag) { WOLFSSL_STACK* sk; WOLFSSL_X509* x509; @@ -14466,9 +14414,8 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) } ret = DecodeToX509(x509, ssl->session->chain.certs[i].buffer, ssl->session->chain.certs[i].length); -#if !defined(WOLFSSL_QT) - if (ret == 0 && i == ssl->session->chain.count-1) { - /* On the last element in the chain try to add the CA chain + if (ret == 0 && i == ssl->session->chain.count-1 && verifiedFlag) { + /* On the last element in the verified chain try to add the CA chain * first if we have one for this cert */ SSL_CM_WARNING(ssl); if (PushCAx509Chain(SSL_CM(ssl), x509, sk) @@ -14476,7 +14423,6 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) ret = WOLFSSL_FATAL_ERROR; } } -#endif if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) <= 0) { WOLFSSL_MSG("Error decoding cert"); @@ -14489,19 +14435,93 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) if (sk == NULL) { WOLFSSL_MSG("Null session chain"); } -#if defined(OPENSSL_ALL) - else if (ssl->options.side == WOLFSSL_SERVER_END) { - /* to be compliant with openssl - first element is kept as peer cert on server side.*/ - wolfSSL_sk_X509_pop(sk); + return sk; +} + + +/* Builds up and creates a stack of peer certificates for ssl->peerCertChain + returns the stack on success and NULL on failure */ +WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) +{ + WOLFSSL_STACK* sk; + + WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain"); + if ((ssl == NULL) || (ssl->session->chain.count == 0)) + return NULL; + + sk = CreatePeerCertChain(ssl, 0); + + if (sk != NULL) { + if (ssl->peerCertChain != NULL) + wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL); + + /* This is Free'd when ssl is Free'd */ + ssl->peerCertChain = sk; } -#endif - if (ssl->peerCertChain != NULL) - wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL); - /* This is Free'd when ssl is Free'd */ - ssl->peerCertChain = sk; return sk; } + + +/** + * Implemented in a similar way that ngx_ssl_ocsp_validate does it when + * SSL_get0_verified_chain is not available. + * @param ssl WOLFSSL object to extract certs from + * @return Stack of verified certs + */ +WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl) +{ + WOLF_STACK_OF(WOLFSSL_X509)* chain = NULL; + WOLFSSL_X509_STORE_CTX* storeCtx = NULL; + WOLFSSL_X509* peerCert = NULL; + + WOLFSSL_ENTER("wolfSSL_get0_verified_chain"); + + if (ssl == NULL || ssl->ctx == NULL) { + WOLFSSL_MSG("Bad parameter"); + return NULL; + } + + peerCert = wolfSSL_get_peer_certificate((WOLFSSL*)ssl); + if (peerCert == NULL) { + WOLFSSL_MSG("wolfSSL_get_peer_certificate error"); + return NULL; + } + /* wolfSSL_get_peer_certificate returns a copy. We want the internal + * member so that we don't have to worry about free'ing it. We call + * wolfSSL_get_peer_certificate so that we don't have to worry about + * setting up the internal pointer. */ + wolfSSL_X509_free(peerCert); + peerCert = (WOLFSSL_X509*)&ssl->peerCert; + chain = CreatePeerCertChain((WOLFSSL*)ssl, 1); + if (chain == NULL) { + WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error"); + return NULL; + } + + if (ssl->verifiedChain != NULL) { + wolfSSL_sk_X509_pop_free(ssl->verifiedChain, NULL); + } + ((WOLFSSL*)ssl)->verifiedChain = chain; + + storeCtx = wolfSSL_X509_STORE_CTX_new(); + if (storeCtx == NULL) { + WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_new error"); + return NULL; + } + if (wolfSSL_X509_STORE_CTX_init(storeCtx, SSL_STORE(ssl), + peerCert, chain) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init error"); + wolfSSL_X509_STORE_CTX_free(storeCtx); + return NULL; + } + if (wolfSSL_X509_verify_cert(storeCtx) <= 0) { + WOLFSSL_MSG("wolfSSL_X509_verify_cert error"); + wolfSSL_X509_STORE_CTX_free(storeCtx); + return NULL; + } + wolfSSL_X509_STORE_CTX_free(storeCtx); + return chain; +} #endif /* SESSION_CERTS && OPENSSL_EXTRA */ #ifndef NO_CERTS diff --git a/src/ssl_load.c b/src/ssl_load.c index 004cb65949..df35d2da45 100644 --- a/src/ssl_load.c +++ b/src/ssl_load.c @@ -2803,9 +2803,26 @@ int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file, } if (file != NULL) { + #ifdef HAVE_CRL + /* handle CRL type being passed in */ + WOLFSSL_CRL crl; + + XMEMSET(&crl, 0, sizeof(WOLFSSL_CRL)); + crl.cm = ctx->cm; + /* Load the PEM formatted CA file. */ + ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, DETECT_CERT_TYPE, + NULL, 0, &crl, verify); + /* found a good CRL, add it to ctx->cm */ + if (ret == 1 && crl.crlList != NULL) { + wolfSSL_X509_STORE_add_crl(wolfSSL_CTX_get_cert_store(ctx), &crl); + } + #else + /* Load the PEM formatted CA file. No CRL support, only expecting + * CA's */ ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL, verify); + #endif #ifndef NO_WOLFSSL_DIR if (ret == 1) { /* Include success in overall count. */ diff --git a/tests/api.c b/tests/api.c index 0ad5c086cc..536760c4e0 100644 --- a/tests/api.c +++ b/tests/api.c @@ -93229,7 +93229,7 @@ static int error_test(void) { -9, WC_SPAN1_FIRST_E + 1 }, #endif { -124, -124 }, - { -166, -169 }, + { -167, -169 }, { -300, -300 }, { -334, -336 }, { -346, -349 }, diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 093e39ca52..4e4d7e4237 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -2777,7 +2777,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t error_test(void) int last; } missing[] = { { -124, -124 }, - { -166, -169 }, + { -167, -169 }, { WC_SPAN1_LAST_E - 1, WC_SPAN2_FIRST_E + 1 }, { WC_SPAN2_LAST_E - 1, WC_SPAN2_MIN_CODE_E } }; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 4996398022..5bdccc60b1 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -6224,6 +6224,7 @@ struct WOLFSSL { #if defined(OPENSSL_EXTRA) WOLFSSL_STACK* supportedCiphers; /* Used in wolfSSL_get_ciphers_compat */ WOLFSSL_STACK* peerCertChain; /* Used in wolfSSL_get_peer_cert_chain */ + WOLFSSL_STACK* verifiedChain; /* peer cert chain to CA */ #ifdef KEEP_OUR_CERT WOLFSSL_STACK* ourCertChain; /* Used in wolfSSL_add1_chain_cert */ #endif