Skip to content

Commit

Permalink
fix for return values of write_ex/read_ex, propogate PARAMS, handle C…
Browse files Browse the repository at this point in the history
…RL with load_verify_locations, fix for get verified/unverified chain
  • Loading branch information
JacobBarthelmeh committed Jan 9, 2025
1 parent 474ea39 commit 908a163
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 81 deletions.
30 changes: 30 additions & 0 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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:
Expand Down
178 changes: 99 additions & 79 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
/**
Expand Down Expand Up @@ -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;
Expand All @@ -14466,17 +14414,15 @@ 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)
== WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) {
ret = WOLFSSL_FATAL_ERROR;
}
}
#endif

if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) <= 0) {
WOLFSSL_MSG("Error decoding cert");
Expand All @@ -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
Expand Down
17 changes: 17 additions & 0 deletions src/ssl_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
2 changes: 1 addition & 1 deletion tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
2 changes: 1 addition & 1 deletion wolfcrypt/test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
};
Expand Down
1 change: 1 addition & 0 deletions wolfssl/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 908a163

Please sign in to comment.