CertManager verify callback

Execute verify callback from wolfSSL_CertManagerLoadCA
This commit is contained in:
Eric Blankenhorn 2019-11-14 10:41:00 -06:00
parent 3f13b49fa3
commit 8580bd9937
8 changed files with 315 additions and 111 deletions
configure.ac
doc/dox_comments/header_files
src
tests
wolfssl

@ -661,7 +661,7 @@ AC_ARG_ENABLE([leantls],
if test "$ENABLED_LEANTLS" = "yes" if test "$ENABLED_LEANTLS" = "yes"
then then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LEANTLS -DNO_WRITEV -DHAVE_ECC -DTFM_ECC256 -DECC_USER_CURVES -DNO_WOLFSSL_SERVER -DNO_RABBIT -DNO_RSA -DNO_DSA -DNO_DH -DNO_PWDBASED -DNO_MD5 -DNO_ERROR_STRINGS -DNO_OLD_TLS -DNO_RC4 -DNO_SHA -DNO_PSK -DNO_WOLFSSL_MEMORY" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LEANTLS -DNO_WRITEV -DHAVE_ECC -DTFM_ECC256 -DECC_USER_CURVES -DNO_WOLFSSL_SERVER -DNO_RABBIT -DNO_RSA -DNO_DSA -DNO_DH -DNO_PWDBASED -DNO_MD5 -DNO_ERROR_STRINGS -DNO_OLD_TLS -DNO_RC4 -DNO_SHA -DNO_PSK -DNO_WOLFSSL_MEMORY -DNO_WOLFSSL_CM_VERIFY"
enable_lowresource=yes enable_lowresource=yes
fi fi

@ -8845,6 +8845,38 @@ WOLFSSL_API int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER*, const char* f,
WOLFSSL_API int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, WOLFSSL_API int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm,
const unsigned char* buff, long sz, int format); const unsigned char* buff, long sz, int format);
/*!
\ingroup CertManager
\brief The function sets the verifyCallback function in the Certificate
Manager. If present, it will be called for each cert loaded. If there is
a verification error, the verify callback can be used to over-ride the
error.
\return none No return.
\param cm a pointer to a WOLFSSL_CERT_MANAGER structure, created using
wolfSSL_CertManagerNew().
\param vc a VerifyCallback function pointer to the callback routine
_Example_
\code
#include <wolfssl/ssl.h>
int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store)
{ // do custom verification of certificate }
WOLFSSL_CTX* ctx = WOLFSSL_CTX_new(Protocol define);
WOLFSSL_CERT_MANAGER* cm = wolfSSL_CertManagerNew();
...
wolfSSL_CertManagerSetVerify(cm, myVerify);
\endcode
\sa wolfSSL_CertManagerVerify
*/
WOLFSSL_API void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm,
VerifyCallback vc);
/*! /*!
\brief Check CRL if the option is enabled and compares the cert to the \brief Check CRL if the option is enabled and compares the cert to the
CRL list. CRL list.

@ -9348,32 +9348,6 @@ int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx)
#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH) #if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
typedef struct ProcPeerCertArgs {
buffer* certs;
#ifdef WOLFSSL_TLS13
buffer* exts; /* extensions */
#endif
DecodedCert* dCert;
word32 idx;
word32 begin;
int totalCerts; /* number of certs in certs buffer */
int count;
int certIdx;
int lastErr;
#ifdef WOLFSSL_TLS13
byte ctxSz;
#endif
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
char untrustedDepth;
#endif
word16 fatal:1;
word16 verifyErr:1;
word16 dCertInit:1;
#ifdef WOLFSSL_TRUST_PEER_CERT
word16 haveTrustPeer:1; /* was cert verified by loaded trusted peer cert */
#endif
} ProcPeerCertArgs;
static void DoCertFatalAlert(WOLFSSL* ssl, int ret) static void DoCertFatalAlert(WOLFSSL* ssl, int ret)
{ {
int alertWhy; int alertWhy;
@ -9405,9 +9379,11 @@ static void DoCertFatalAlert(WOLFSSL* ssl, int ret)
* store->error_depth member to determine index (0=peer, >1 intermediates) * store->error_depth member to determine index (0=peer, >1 intermediates)
*/ */
static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args) int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
ProcPeerCertArgs* args)
{ {
int verify_ok = 0, use_cb = 0; int verify_ok = 0, use_cb = 0;
void *heap = (ssl != NULL) ? ssl->heap : cm->heap;
/* Determine if verify was okay */ /* Determine if verify was okay */
if (ret == 0) { if (ret == 0) {
@ -9416,7 +9392,7 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
/* Determine if verify callback should be used */ /* Determine if verify callback should be used */
if (ret != 0) { if (ret != 0) {
if (!ssl->options.verifyNone) { if ((ssl != NULL) && (!ssl->options.verifyNone)) {
use_cb = 1; /* always report errors */ use_cb = 1; /* always report errors */
} }
} }
@ -9434,7 +9410,7 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
#endif #endif
#if defined(OPENSSL_EXTRA) #if defined(OPENSSL_EXTRA)
/* perform domain name check on the peer certificate */ /* perform domain name check on the peer certificate */
if (args->dCertInit && args->dCert && if (args->dCertInit && args->dCert && (ssl != NULL) &&
ssl->param && ssl->param->hostName[0]) { ssl->param && ssl->param->hostName[0]) {
/* If altNames names is present, then subject common name is ignored */ /* If altNames names is present, then subject common name is ignored */
if (args->dCert->altNames != NULL) { if (args->dCert->altNames != NULL) {
@ -9458,7 +9434,7 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
} }
/* perform IP address check on the peer certificate */ /* perform IP address check on the peer certificate */
if ((args->dCertInit != 0) && (args->dCert != NULL) && if ((args->dCertInit != 0) && (args->dCert != NULL) && (ssl != NULL) &&
(ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) { (ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) {
if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) { if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) {
if (ret == 0) { if (ret == 0) {
@ -9468,11 +9444,15 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
} }
#endif #endif
/* if verify callback has been set */ /* if verify callback has been set */
if (use_cb && (ssl->verifyCallback if ((use_cb && (ssl != NULL) && ((ssl->verifyCallback != NULL)
#ifdef OPENSSL_ALL #ifdef OPENSSL_ALL
|| ssl->ctx->verifyCertCb || (ssl->ctx->verifyCertCb != NULL)
#endif #endif
)) { ))
#ifndef NO_WOLFSSL_CM_VERIFY
|| ((cm != NULL) && (cm->verifyCallback != NULL))
#endif
) {
int verifyFail = 0; int verifyFail = 0;
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
WOLFSSL_X509_STORE_CTX* store; WOLFSSL_X509_STORE_CTX* store;
@ -9490,23 +9470,23 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
store = (WOLFSSL_X509_STORE_CTX*)XMALLOC( store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap, DYNAMIC_TYPE_X509_STORE); sizeof(WOLFSSL_X509_STORE_CTX), heap, DYNAMIC_TYPE_X509_STORE);
if (store == NULL) { if (store == NULL) {
return MEMORY_E; return MEMORY_E;
} }
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), ssl->heap, x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
DYNAMIC_TYPE_X509); DYNAMIC_TYPE_X509);
if (x509 == NULL) { if (x509 == NULL) {
XFREE(store, ssl->heap, DYNAMIC_TYPE_X509); XFREE(store, heap, DYNAMIC_TYPE_X509);
return MEMORY_E; return MEMORY_E;
} }
#endif #endif
domain = (char*)XMALLOC(ASN_NAME_MAX, ssl->heap, DYNAMIC_TYPE_STRING); domain = (char*)XMALLOC(ASN_NAME_MAX, heap, DYNAMIC_TYPE_STRING);
if (domain == NULL) { if (domain == NULL) {
XFREE(store, ssl->heap, DYNAMIC_TYPE_X509); XFREE(store, heap, DYNAMIC_TYPE_X509);
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
XFREE(x509, ssl->heap, DYNAMIC_TYPE_X509); XFREE(x509, heap, DYNAMIC_TYPE_X509);
#endif #endif
return MEMORY_E; return MEMORY_E;
} }
@ -9533,72 +9513,80 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
store->error_depth = args->certIdx; store->error_depth = args->certIdx;
store->discardSessionCerts = 0; store->discardSessionCerts = 0;
store->domain = domain; store->domain = domain;
store->userCtx = ssl->verifyCbCtx; store->userCtx = (ssl != NULL) ? ssl->verifyCbCtx : cm;
store->certs = args->certs; store->certs = args->certs;
store->totalCerts = args->totalCerts; store->totalCerts = args->totalCerts;
#if defined(HAVE_EX_DATA) || defined(FORTRESS) #if defined(HAVE_EX_DATA) || defined(FORTRESS)
store->ex_data[0] = ssl; store->ex_data[0] = ssl;
#endif #endif
if (ssl != NULL) {
#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
if (ssl->ctx->x509_store_pt != NULL) { if (ssl->ctx->x509_store_pt != NULL) {
store->store = ssl->ctx->x509_store_pt; store->store = ssl->ctx->x509_store_pt;
} }
else { else {
store->store = &ssl->ctx->x509_store; store->store = &ssl->ctx->x509_store;
} }
#if defined(OPENSSL_EXTRA) #if defined(OPENSSL_EXTRA)
store->depth = args->count; store->depth = args->count;
store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
sizeof(WOLFSSL_X509_VERIFY_PARAM), sizeof(WOLFSSL_X509_VERIFY_PARAM),
ssl->heap, DYNAMIC_TYPE_OPENSSL); heap, DYNAMIC_TYPE_OPENSSL);
if (store->param == NULL) { if (store->param == NULL) {
return MEMORY_E; #ifdef WOLFSSL_SMALL_STACK
} XFREE(domain, heap, DYNAMIC_TYPE_STRING);
XMEMSET(store->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
/* Overwrite with non-default param values in SSL */ XFREE(x509, heap, DYNAMIC_TYPE_X509);
if (ssl->param) { #endif
if (ssl->param->check_time) XFREE(store, heap, DYNAMIC_TYPE_X509_STORE);
store->param->check_time = ssl->param->check_time; #endif
return MEMORY_E;
}
XMEMSET(store->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM));
/* Overwrite with non-default param values in SSL */
if (ssl->param) {
if (ssl->param->check_time)
store->param->check_time = ssl->param->check_time;
if (ssl->param->flags) if (ssl->param->flags)
store->param->flags = ssl->param->flags; store->param->flags = ssl->param->flags;
if (ssl->param->hostName[0]) if (ssl->param->hostName[0])
XMEMCPY(store->param->hostName, ssl->param->hostName, XMEMCPY(store->param->hostName, ssl->param->hostName,
WOLFSSL_HOST_NAME_MAX); WOLFSSL_HOST_NAME_MAX);
} }
#endif /* defined(OPENSSL_EXTRA) */ #endif /* defined(OPENSSL_EXTRA) */
#endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)*/ #endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)*/
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
#ifdef KEEP_PEER_CERT #ifdef KEEP_PEER_CERT
if (args->certIdx == 0) { if (args->certIdx == 0) {
store->current_cert = &ssl->peerCert; /* use existing X509 */ store->current_cert = &ssl->peerCert; /* use existing X509 */
} }
else else
#endif #endif
{ {
InitX509(x509, 0, ssl->heap); InitX509(x509, 0, heap);
if (CopyDecodedToX509(x509, args->dCert) == 0) { if (CopyDecodedToX509(x509, args->dCert) == 0) {
store->current_cert = x509; store->current_cert = x509;
}
else {
FreeX509(x509);
}
} }
else {
FreeX509(x509);
}
}
#endif #endif
#ifdef SESSION_CERTS #ifdef SESSION_CERTS
store->sesChain = &ssl->session.chain; store->sesChain = &ssl->session.chain;
#endif #endif
}
#ifdef OPENSSL_ALL #ifndef NO_WOLFSSL_CM_VERIFY
/* non-zero return code indicates failure override */ /* non-zero return code indicates failure override */
if (ssl->ctx->verifyCertCb) { if ((cm != NULL) && (cm->verifyCallback != NULL)) {
if (ssl->ctx->verifyCertCb(store, ssl->ctx->verifyCertCbArg)) { store->userCtx = cm;
if (cm->verifyCallback(verify_ok, store)) {
if (ret != 0) { if (ret != 0) {
WOLFSSL_MSG("Verify Cert callback overriding error!"); WOLFSSL_MSG("Verify CM callback overriding error!");
ret = 0; ret = 0;
} }
} }
@ -9608,16 +9596,33 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
} }
#endif #endif
/* non-zero return code indicates failure override */ if (ssl != NULL) {
if (ssl->verifyCallback) { #ifdef OPENSSL_ALL
if (ssl->verifyCallback(verify_ok, store)) { /* non-zero return code indicates failure override */
if (ret != 0) { if (ssl->ctx->verifyCertCb) {
WOLFSSL_MSG("Verify callback overriding error!"); if (ssl->ctx->verifyCertCb(store, ssl->ctx->verifyCertCbArg)) {
ret = 0; if (ret != 0) {
WOLFSSL_MSG("Verify Cert callback overriding error!");
ret = 0;
}
}
else {
verifyFail = 1;
} }
} }
else { #endif
verifyFail = 1;
/* non-zero return code indicates failure override */
if (ssl->verifyCallback) {
if (ssl->verifyCallback(verify_ok, store)) {
if (ret != 0) {
WOLFSSL_MSG("Verify callback overriding error!");
ret = 0;
}
}
else {
verifyFail = 1;
}
} }
} }
@ -9639,7 +9644,7 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
store->chain = NULL; store->chain = NULL;
#endif #endif
#ifdef SESSION_CERTS #ifdef SESSION_CERTS
if (store->discardSessionCerts) { if ((ssl != NULL) && (store->discardSessionCerts)) {
WOLFSSL_MSG("Verify callback requested discard sess certs"); WOLFSSL_MSG("Verify callback requested discard sess certs");
ssl->session.chain.count = 0; ssl->session.chain.count = 0;
#ifdef WOLFSSL_ALT_CERT_CHAINS #ifdef WOLFSSL_ALT_CERT_CHAINS
@ -9648,19 +9653,21 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
} }
#endif /* SESSION_CERTS */ #endif /* SESSION_CERTS */
#ifdef OPENSSL_EXTRA #ifdef OPENSSL_EXTRA
if (store->param){ if ((ssl != NULL) && (store->param)) {
XFREE(store->param, ssl->heap, DYNAMIC_TYPE_OPENSSL); XFREE(store->param, heap, DYNAMIC_TYPE_OPENSSL);
} }
#endif #endif
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
XFREE(domain, ssl->heap, DYNAMIC_TYPE_STRING); XFREE(domain, heap, DYNAMIC_TYPE_STRING);
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
XFREE(x509, ssl->heap, DYNAMIC_TYPE_X509); XFREE(x509, heap, DYNAMIC_TYPE_X509);
#endif #endif
XFREE(store, ssl->heap, DYNAMIC_TYPE_X509_STORE); XFREE(store, heap, DYNAMIC_TYPE_X509_STORE);
#endif #endif
} }
(void)heap;
return ret; return ret;
} }
@ -10285,7 +10292,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif /* HAVE_OCSP || HAVE_CRL */ #endif /* HAVE_OCSP || HAVE_CRL */
/* Do verify callback */ /* Do verify callback */
ret = DoVerifyCallback(ssl, ret, args); ret = DoVerifyCallback(ssl->ctx->cm, ssl, ret, args);
#ifdef WOLFSSL_ALT_CERT_CHAINS #ifdef WOLFSSL_ALT_CERT_CHAINS
/* For alternate cert chain, its okay for a CA cert to fail /* For alternate cert chain, its okay for a CA cert to fail
@ -10912,7 +10919,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif #endif
/* Do verify callback */ /* Do verify callback */
ret = DoVerifyCallback(ssl, ret, args); ret = DoVerifyCallback(ssl->ctx->cm, ssl, ret, args);
if (ssl->options.verifyNone && if (ssl->options.verifyNone &&
(ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) { (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) {

100
src/ssl.c

@ -5412,6 +5412,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
{ {
DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */ DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */
int ret = 0; int ret = 0;
int done = 0;
int eccKey = 0; int eccKey = 0;
int ed25519Key = 0; int ed25519Key = 0;
int rsaKey = 0; int rsaKey = 0;
@ -5529,18 +5530,22 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
/* check for error */ /* check for error */
if (ret < 0) { if (ret < 0) {
FreeDer(&der); FreeDer(&der);
return ret; done = 1;
} }
if (done == 1) {
/* No operation, just skip the next section */
}
/* Handle DER owner */ /* Handle DER owner */
if (type == CA_TYPE) { else if (type == CA_TYPE) {
if (ctx == NULL) { if (ctx == NULL) {
WOLFSSL_MSG("Need context for CA load"); WOLFSSL_MSG("Need context for CA load");
FreeDer(&der); FreeDer(&der);
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
/* verify CA unless user set to no verify */ /* verify CA unless user set to no verify */
return AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify); ret = AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify);
done = 1;
} }
#ifdef WOLFSSL_TRUST_PEER_CERT #ifdef WOLFSSL_TRUST_PEER_CERT
else if (type == TRUSTED_PEER_TYPE) { else if (type == TRUSTED_PEER_TYPE) {
@ -5550,7 +5555,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
/* add trusted peer cert */ /* add trusted peer cert */
return AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone); ret = AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone);
done = 1;
} }
#endif /* WOLFSSL_TRUST_PEER_CERT */ #endif /* WOLFSSL_TRUST_PEER_CERT */
else if (type == CERT_TYPE) { else if (type == CERT_TYPE) {
@ -5605,7 +5611,10 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
return WOLFSSL_BAD_CERTTYPE; return WOLFSSL_BAD_CERTTYPE;
} }
if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) { if (done == 1) {
/* No operation, just skip the next section */
}
else if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) {
#if defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8) #if defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8)
/* attempt to detect key type */ /* attempt to detect key type */
if (algId == RSAk) if (algId == RSAk)
@ -5892,10 +5901,26 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
#endif #endif
if (ret != 0) { if (ret != 0) {
return ret; done = 1;
} }
} }
if (done == 1) {
#ifndef NO_WOLFSSL_CM_VERIFY
if ((type == CA_TYPE) || (type == CERT_TYPE)) {
/* Call to over-ride status */
if ((ctx != NULL) && (ctx->cm != NULL) &&
(ctx->cm->verifyCallback != NULL)) {
ret = CM_VerifyBuffer_ex(ctx->cm, buff,
sz, format, (ret == WOLFSSL_SUCCESS ? 0 : ret));
}
}
#endif /* NO_WOLFSSL_CM_VERIFY */
return ret;
}
if (ssl && resetSuites) { if (ssl && resetSuites) {
word16 havePSK = 0; word16 havePSK = 0;
word16 haveRSA = 0; word16 haveRSA = 0;
@ -6161,9 +6186,21 @@ int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
return WOLFSSL_SUCCESS; return WOLFSSL_SUCCESS;
} }
#ifndef NO_WOLFSSL_CM_VERIFY
void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm, VerifyCallback vc)
{
WOLFSSL_ENTER("wolfSSL_CertManagerSetVerify");
if (cm == NULL)
return;
cm->verifyCallback = vc;
}
#endif /* NO_WOLFSSL_CM_VERIFY */
/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */ /* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
long sz, int format) long sz, int format, int err_val)
{ {
int ret = 0; int ret = 0;
DerBuffer* der = NULL; DerBuffer* der = NULL;
@ -6209,6 +6246,43 @@ int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
ret = CheckCertCRL(cm->crl, cert); ret = CheckCertCRL(cm->crl, cert);
#endif #endif
#ifndef NO_WOLFSSL_CM_VERIFY
/* if verify callback has been set */
if (cm->verifyCallback) {
buffer certBuf;
#ifdef WOLFSSL_SMALL_STACK
ProcPeerCertArgs* args = NULL;
args = (ProcPeerCertArgs*)XMALLOC(
sizeof(ProcPeerCertArgs), cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (args == NULL) {
XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
return MEMORY_E;
}
#else
ProcPeerCertArgs args[1];
#endif
certBuf.buffer = (byte*)buff;
certBuf.length = (unsigned int)sz;
XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
args->totalCerts = 1;
args->certs = &certBuf;
args->dCert = cert;
args->dCertInit = 1;
if (err_val != 0) {
ret = err_val;
}
ret = DoVerifyCallback(cm, NULL, ret, args);
#ifdef WOLFSSL_SMALL_STACK
XFREE(args, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
#else
(void)err_val;
#endif
FreeDecodedCert(cert); FreeDecodedCert(cert);
FreeDer(&der); FreeDer(&der);
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
@ -6218,7 +6292,12 @@ int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
return ret == 0 ? WOLFSSL_SUCCESS : ret; return ret == 0 ? WOLFSSL_SUCCESS : ret;
} }
/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
long sz, int format)
{
return CM_VerifyBuffer_ex(cm, buff, sz, format, 0);
}
/* turn on OCSP if off and compiled in, set options */ /* turn on OCSP if off and compiled in, set options */
int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options) int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
{ {
@ -6655,9 +6734,10 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
} }
} }
if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE) if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE)
&& format == WOLFSSL_FILETYPE_PEM) && format == WOLFSSL_FILETYPE_PEM) {
ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl, ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl,
verify); verify);
}
#ifdef HAVE_CRL #ifdef HAVE_CRL
else if (type == CRL_TYPE) else if (type == CRL_TYPE)
ret = BufferLoadCRL(crl, myBuffer, sz, format, verify); ret = BufferLoadCRL(crl, myBuffer, sz, format, verify);

@ -1143,6 +1143,49 @@ static void test_wolfSSL_CertManagerGetCerts(void)
!defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \
defined(WOLFSSL_SIGNER_DER_CERT) */ defined(WOLFSSL_SIGNER_DER_CERT) */
} }
static int test_wolfSSL_CertManagerSetVerify(void)
{
int ret = 0;
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \
!defined(NO_WOLFSSL_CM_VERIFY) && !defined(NO_RSA)
WOLFSSL_CERT_MANAGER* cm = NULL;
int tmp = myVerifyFail;
const char* ca_cert = "./certs/ca-cert.pem";
const char* expiredCert = "./certs/test/expired/expired-cert.pem";
cm = wolfSSL_CertManagerNew();
AssertNotNull(cm);
wolfSSL_CertManagerSetVerify(cm, myVerify);
ret = wolfSSL_CertManagerLoadCA(cm, ca_cert, NULL);
AssertIntEQ(ret, WOLFSSL_SUCCESS);
/* Use the test CB that always accepts certs */
myVerifyFail = 0;
ret = wolfSSL_CertManagerVerify(cm, expiredCert, WOLFSSL_FILETYPE_PEM);
AssertIntEQ(ret, WOLFSSL_SUCCESS);
#ifdef WOLFSSL_ALWAYS_VERIFY_CB
{
const char* verifyCert = "./certs/server-cert.pem";
/* Use the test CB that always fails certs */
myVerifyFail = 1;
ret = wolfSSL_CertManagerVerify(cm, verifyCert, WOLFSSL_FILETYPE_PEM);
AssertIntEQ(ret, VERIFY_CERT_ERROR);
}
#endif
wolfSSL_CertManagerFree(cm);
myVerifyFail = tmp;
#endif
return ret;
}
static void test_wolfSSL_CertManagerCRL(void) static void test_wolfSSL_CertManagerCRL(void)
{ {
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && defined(HAVE_CRL) && \ #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && defined(HAVE_CRL) && \
@ -28799,6 +28842,7 @@ void ApiTest(void)
test_wolfSSL_CTX_load_verify_locations(); test_wolfSSL_CTX_load_verify_locations();
test_wolfSSL_CertManagerLoadCABuffer(); test_wolfSSL_CertManagerLoadCABuffer();
test_wolfSSL_CertManagerGetCerts(); test_wolfSSL_CertManagerGetCerts();
test_wolfSSL_CertManagerSetVerify();
test_wolfSSL_CertManagerCRL(); test_wolfSSL_CertManagerCRL();
test_wolfSSL_CTX_load_verify_locations_ex(); test_wolfSSL_CTX_load_verify_locations_ex();
test_wolfSSL_CTX_load_verify_buffer_ex(); test_wolfSSL_CTX_load_verify_buffer_ex();

@ -1940,6 +1940,9 @@ struct WOLFSSL_CERT_MANAGER {
#endif #endif
char* ocspOverrideURL; /* use this responder */ char* ocspOverrideURL; /* use this responder */
void* ocspIOCtx; /* I/O callback CTX */ void* ocspIOCtx; /* I/O callback CTX */
#ifndef NO_WOLFSSL_CM_VERIFY
VerifyCallback verifyCallback; /* Verify callback */
#endif
CallbackCACache caCacheCallback; /* CA cache addition callback */ CallbackCACache caCacheCallback; /* CA cache addition callback */
CbMissingCRL cbMissingCRL; /* notify through cb of missing crl */ CbMissingCRL cbMissingCRL; /* notify through cb of missing crl */
CbOCSPIO ocspIOCb; /* I/O callback for OCSP lookup */ CbOCSPIO ocspIOCb; /* I/O callback for OCSP lookup */
@ -1966,6 +1969,42 @@ WOLFSSL_LOCAL int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER*, const char*);
WOLFSSL_LOCAL int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER*, void*, int, int*); WOLFSSL_LOCAL int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER*, void*, int, int*);
WOLFSSL_LOCAL int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER*, const void*, int); WOLFSSL_LOCAL int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER*, const void*, int);
WOLFSSL_LOCAL int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER*); WOLFSSL_LOCAL int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER*);
WOLFSSL_LOCAL int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
long sz, int format, int err_val);
#ifndef NO_CERTS
#if !defined NOCERTS &&\
(!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH))
typedef struct ProcPeerCertArgs {
buffer* certs;
#ifdef WOLFSSL_TLS13
buffer* exts; /* extensions */
#endif
DecodedCert* dCert;
word32 idx;
word32 begin;
int totalCerts; /* number of certs in certs buffer */
int count;
int certIdx;
int lastErr;
#ifdef WOLFSSL_TLS13
byte ctxSz;
#endif
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
char untrustedDepth;
#endif
word16 fatal:1;
word16 verifyErr:1;
word16 dCertInit:1;
#ifdef WOLFSSL_TRUST_PEER_CERT
word16 haveTrustPeer:1; /* was cert verified by loaded trusted peer cert */
#endif
} ProcPeerCertArgs;
WOLFSSL_LOCAL int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl,
int ret, ProcPeerCertArgs* args);
#endif /* !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH) */
#endif /* !defined NO_CERTS */
/* wolfSSL Sock Addr */ /* wolfSSL Sock Addr */
struct WOLFSSL_SOCKADDR { struct WOLFSSL_SOCKADDR {

@ -2560,6 +2560,8 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER*, WOLFSSL_API int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER*,
int options); int options);
WOLFSSL_API int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER*); WOLFSSL_API int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER*);
WOLFSSL_API void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm,
VerifyCallback vc);
WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER*, WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER*,
const char*, int, int); const char*, int, int);
WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER*, WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER*,

@ -525,7 +525,7 @@ enum VerifyType {
VERIFY_CRL = 2, VERIFY_CRL = 2,
VERIFY_OCSP = 3, VERIFY_OCSP = 3,
VERIFY_NAME = 4, VERIFY_NAME = 4,
VERIFY_SKIP_DATE = 5 VERIFY_SKIP_DATE = 5,
}; };
#ifdef WOLFSSL_CERT_EXT #ifdef WOLFSSL_CERT_EXT