fix for return values of write_ex/read_ex, propogate PARAMS, handle CRL with load_verify_locations, fix for get verified/unverified chain

This commit is contained in:
JacobBarthelmeh
2025-01-09 01:29:24 -07:00
parent 689c61cc7e
commit c6974a921d
6 changed files with 150 additions and 82 deletions

View File

@ -7785,6 +7785,11 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
return MEMORY_E; return MEMORY_E;
} }
XMEMSET(ssl->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); 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 #endif
if (ctx->suites == NULL) { if (ctx->suites == NULL) {
@ -8733,6 +8738,7 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
* isn't allocated separately. */ * isn't allocated separately. */
wolfSSL_sk_CIPHER_free(ssl->supportedCiphers); wolfSSL_sk_CIPHER_free(ssl->supportedCiphers);
wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL); wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL);
wolfSSL_sk_X509_pop_free(ssl->verifiedChain, NULL);
#ifdef KEEP_OUR_CERT #ifdef KEEP_OUR_CERT
wolfSSL_sk_X509_pop_free(ssl->ourCertChain, NULL); wolfSSL_sk_X509_pop_free(ssl->ourCertChain, NULL);
#endif #endif
@ -14997,6 +15003,25 @@ static int ProcessPeerCertsChainCRLCheck(WOLFSSL* ssl, ProcPeerCertArgs* args)
} }
#endif #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, int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 totalSz) word32 totalSz)
{ {
@ -15065,6 +15090,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif #endif
} }
#ifdef OPENSSL_EXTRA
/* account for verify params flag set */
AdjustCMForParams(ssl);
#endif
switch (ssl->options.asyncState) switch (ssl->options.asyncState)
{ {
case TLS_ASYNC_BEGIN: case TLS_ASYNC_BEGIN:

180
src/ssl.c
View File

@ -3089,7 +3089,7 @@ int wolfSSL_write_ex(WOLFSSL* ssl, const void* data, int sz, size_t* wr)
int ret; int ret;
ret = wolfSSL_write(ssl, data, sz); ret = wolfSSL_write(ssl, data, sz);
if (ret > 0 && wr != NULL) { if (ret >= 0 && wr != NULL) {
*wr = (size_t)ret; *wr = (size_t)ret;
ret = 1; ret = 1;
} }
@ -3206,6 +3206,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 wolfSSL_read_ex(WOLFSSL* ssl, void* data, int sz, size_t* rd)
{ {
int ret; int ret;
@ -3214,6 +3215,8 @@ int wolfSSL_read_ex(WOLFSSL* ssl, void* data, int sz, size_t* rd)
if (ret > 0 && rd != NULL) { if (ret > 0 && rd != NULL) {
*rd = (size_t)ret; *rd = (size_t)ret;
} }
if (ret <= 0) ret = 0;
return ret; return ret;
} }
@ -12691,63 +12694,6 @@ cleanup:
#if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \ #if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \
defined(WOLFSSL_WPAS_SMALL)) 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) WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(const WOLFSSL_CTX* ctx)
{ {
if (ctx == NULL) { if (ctx == NULL) {
@ -14331,12 +14277,13 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl)
/* Try to populate if NULL or empty */ /* Try to populate if NULL or empty */
if (ssl->peerCertChain == NULL || 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); wolfSSL_set_peer_cert_chain((WOLFSSL*) ssl);
}
return ssl->peerCertChain; return ssl->peerCertChain;
} }
#ifndef WOLFSSL_QT
static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm, static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm,
WOLFSSL_X509 *x); WOLFSSL_X509 *x);
/** /**
@ -14379,13 +14326,14 @@ static int PushCAx509Chain(WOLFSSL_CERT_MANAGER* cm,
} }
return ret; return ret;
} }
#endif /* !WOLFSSL_QT */
/* Builds up and creates a stack of peer certificates for ssl->peerCertChain /* Builds up and creates a stack of peer certificates for ssl->peerCertChain
based off of the ssl session chain. Attempts to place CA certificates or ssl->verifiedChain based off of the ssl session chain. Attempts to place
at the bottom of the stack. Returns stack of WOLFSSL_X509 certs or CA certificates at the bottom of the stack for a verified chain. Returns
NULL on failure */ stack of WOLFSSL_X509 certs or NULL on failure */
WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) static WOLF_STACK_OF(WOLFSSL_X509)* CreatePeerCertChain(WOLFSSL* ssl,
int verifiedFlag)
{ {
WOLFSSL_STACK* sk; WOLFSSL_STACK* sk;
WOLFSSL_X509* x509; WOLFSSL_X509* x509;
@ -14407,9 +14355,8 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl)
} }
ret = DecodeToX509(x509, ssl->session->chain.certs[i].buffer, ret = DecodeToX509(x509, ssl->session->chain.certs[i].buffer,
ssl->session->chain.certs[i].length); ssl->session->chain.certs[i].length);
#if !defined(WOLFSSL_QT) if (ret == 0 && i == ssl->session->chain.count-1 && verifiedFlag) {
if (ret == 0 && i == ssl->session->chain.count-1) { /* On the last element in the verified chain try to add the CA chain
/* On the last element in the chain try to add the CA chain
* first if we have one for this cert */ * first if we have one for this cert */
SSL_CM_WARNING(ssl); SSL_CM_WARNING(ssl);
if (PushCAx509Chain(SSL_CM(ssl), x509, sk) if (PushCAx509Chain(SSL_CM(ssl), x509, sk)
@ -14417,7 +14364,6 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl)
ret = WOLFSSL_FATAL_ERROR; ret = WOLFSSL_FATAL_ERROR;
} }
} }
#endif
if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) <= 0) { if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) <= 0) {
WOLFSSL_MSG("Error decoding cert"); WOLFSSL_MSG("Error decoding cert");
@ -14430,19 +14376,93 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl)
if (sk == NULL) { if (sk == NULL) {
WOLFSSL_MSG("Null session chain"); 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);
}
#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; 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;
}
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 */ #endif /* SESSION_CERTS && OPENSSL_EXTRA */
#ifndef NO_CERTS #ifndef NO_CERTS

View File

@ -2803,9 +2803,26 @@ int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file,
} }
if (file != NULL) { 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. */ /* 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, ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0,
NULL, verify); NULL, verify);
#endif
#ifndef NO_WOLFSSL_DIR #ifndef NO_WOLFSSL_DIR
if (ret == 1) { if (ret == 1) {
/* Include success in overall count. */ /* Include success in overall count. */

View File

@ -93244,7 +93244,7 @@ static int error_test(void)
{ -9, WC_SPAN1_FIRST_E + 1 }, { -9, WC_SPAN1_FIRST_E + 1 },
#endif #endif
{ -124, -124 }, { -124, -124 },
{ -166, -169 }, { -167, -169 },
{ -300, -300 }, { -300, -300 },
{ -334, -336 }, { -334, -336 },
{ -346, -349 }, { -346, -349 },

View File

@ -2777,7 +2777,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t error_test(void)
int last; int last;
} missing[] = { } missing[] = {
{ -124, -124 }, { -124, -124 },
{ -166, -169 }, { -167, -169 },
{ WC_SPAN1_LAST_E - 1, WC_SPAN2_FIRST_E + 1 }, { WC_SPAN1_LAST_E - 1, WC_SPAN2_FIRST_E + 1 },
{ WC_SPAN2_LAST_E - 1, WC_SPAN2_MIN_CODE_E } { WC_SPAN2_LAST_E - 1, WC_SPAN2_MIN_CODE_E }
}; };

View File

@ -6227,6 +6227,7 @@ struct WOLFSSL {
#if defined(OPENSSL_EXTRA) #if defined(OPENSSL_EXTRA)
WOLFSSL_STACK* supportedCiphers; /* Used in wolfSSL_get_ciphers_compat */ WOLFSSL_STACK* supportedCiphers; /* Used in wolfSSL_get_ciphers_compat */
WOLFSSL_STACK* peerCertChain; /* Used in wolfSSL_get_peer_cert_chain */ WOLFSSL_STACK* peerCertChain; /* Used in wolfSSL_get_peer_cert_chain */
WOLFSSL_STACK* verifiedChain; /* peer cert chain to CA */
#ifdef KEEP_OUR_CERT #ifdef KEEP_OUR_CERT
WOLFSSL_STACK* ourCertChain; /* Used in wolfSSL_add1_chain_cert */ WOLFSSL_STACK* ourCertChain; /* Used in wolfSSL_add1_chain_cert */
#endif #endif