Browse Source

Moved CertManager APIs into own file

Split out certificate manager APIs into ssl_certman.c.
ssl.c includes ssl_certman.c
Better test coverage.
Minor fixes.
wolfSSL_X509_chain_up_ref calls XFREE with name->heap but name may be
NULL. Check for NULL first.
Sean Parkinson 9 months ago
parent
commit
3af87f6f93

+ 1 - 0
.gitignore

@@ -85,6 +85,7 @@ testsuite/testsuite.test
 tests/unit.test
 tests/bio_write_test.txt
 tests/test-log-dump-to-file.txt
+tests/cert_cache.tmp
 test-write-dhparams.pem
 testsuite/*.der
 testsuite/*.pem

+ 1 - 0
IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt

@@ -192,6 +192,7 @@ set(COMPONENT_SRCEXCLUDE
     "${WOLFSSL_ROOT}/src/pk.c"
     "${WOLFSSL_ROOT}/src/ssl_asn1.c" # included by ssl.c
     "${WOLFSSL_ROOT}/src/ssl_bn.c" # included by ssl.c
+    "${WOLFSSL_ROOT}/src/ssl_certman.c" # included by ssl.c
     "${WOLFSSL_ROOT}/src/ssl_misc.c" # included by ssl.c
     "${WOLFSSL_ROOT}/src/x509.c"
     "${WOLFSSL_ROOT}/src/x509_str.c"

+ 1 - 0
src/include.am

@@ -21,6 +21,7 @@ EXTRA_DIST += src/conf.c
 EXTRA_DIST += src/pk.c
 EXTRA_DIST += src/ssl_asn1.c
 EXTRA_DIST += src/ssl_bn.c
+EXTRA_DIST += src/ssl_certman.c
 EXTRA_DIST += src/ssl_misc.c
 EXTRA_DIST += src/x509.c
 EXTRA_DIST += src/x509_str.c

File diff suppressed because it is too large
+ 26 - 1067
src/ssl.c


+ 2355 - 0
src/ssl_certman.c

@@ -0,0 +1,2355 @@
+/* ssl_certman.c
+ *
+ * Copyright (C) 2006-2023 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+ #include <wolfssl/internal.h>
+
+#if !defined(WOLFSSL_SSL_CERTMAN_INCLUDED)
+    #ifndef WOLFSSL_IGNORE_FILE_WARN
+        #warning ssl_certman.c does not need to be compiled separately from ssl.c
+    #endif
+#else
+
+#ifndef NO_CERTS
+
+/* Pick an available TLS method.
+ *
+ * Used when creating temporary WOLFSSL_CTX.
+ *
+ * @return  A TLS method on success.
+ * @return  NULL when no TLS method built into wolfSSL.
+ */
+static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void)
+{
+    #ifndef NO_WOLFSSL_CLIENT
+        #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
+            return wolfSSLv3_client_method();
+        #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
+            return wolfTLSv1_client_method();
+        #elif !defined(NO_OLD_TLS)
+            return wolfTLSv1_1_client_method();
+        #elif !defined(WOLFSSL_NO_TLS12)
+            return wolfTLSv1_2_client_method();
+        #elif defined(WOLFSSL_TLS13)
+            return wolfTLSv1_3_client_method();
+        #else
+            return NULL;
+        #endif
+    #elif !defined(NO_WOLFSSL_SERVER)
+        #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
+            return wolfSSLv3_server_method();
+        #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
+            return wolfTLSv1_server_method();
+        #elif !defined(NO_OLD_TLS)
+            return wolfTLSv1_1_server_method();
+        #elif !defined(WOLFSSL_NO_TLS12)
+            return wolfTLSv1_2_server_method();
+        #elif defined(WOLFSSL_TLS13)
+            return wolfTLSv1_3_server_method();
+        #else
+            return NULL;
+        #endif
+    #else
+        return NULL;
+    #endif
+}
+
+/* Create a new certificate manager with a heap hint.
+ *
+ * @param [in] heap  Heap hint.
+ * @return  Certificate manager object on success.
+ * @return  NULL on failure.
+ */
+WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
+{
+    int err = 0;
+    WOLFSSL_CERT_MANAGER* cm;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerNew");
+
+    /* Allocate memory for certificate manager. */
+    cm = (WOLFSSL_CERT_MANAGER*)XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap,
+        DYNAMIC_TYPE_CERT_MANAGER);
+    if (cm == NULL) {
+        err = 1;
+    }
+    if (!err) {
+        /* Reset all fields. */
+        XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
+
+        /* Create a mutex for use when modify table of stored CAs. */
+        if (wc_InitMutex(&cm->caLock) != 0) {
+            WOLFSSL_MSG("Bad mutex init");
+            err = 1;
+        }
+    }
+    if (!err) {
+        /* Initialize reference count. */
+        wolfSSL_RefInit(&cm->ref, &err);
+    #ifdef WOLFSSL_REFCNT_ERROR_RETURN
+        if (err != 0) {
+            WOLFSSL_MSG("Bad reference count init");
+        }
+    #endif
+    }
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    /* Create a mutex for use when modify table of trusted peers. */
+    if ((!err) && (wc_InitMutex(&cm->tpLock) != 0)) {
+        WOLFSSL_MSG("Bad mutex init");
+        err = 1;
+    }
+#endif
+    if (!err) {
+        /* Set default minimum key sizes allowed. */
+    #ifndef NO_RSA
+        cm->minRsaKeySz = MIN_RSAKEY_SZ;
+    #endif
+    #ifdef HAVE_ECC
+        cm->minEccKeySz = MIN_ECCKEY_SZ;
+    #endif
+    #ifdef HAVE_PQC
+    #ifdef HAVE_FALCON
+        cm->minFalconKeySz = MIN_FALCONKEY_SZ;
+    #endif /* HAVE_FALCON */
+    #ifdef HAVE_DILITHIUM
+        cm->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ;
+    #endif /* HAVE_DILITHIUM */
+    #endif /* HAVE_PQC */
+
+        /* Set heap hint to use in certificate manager operations. */
+        cm->heap = heap;
+    }
+
+    /* Dispose of certificate manager on error. */
+    if (err && (cm != NULL)) {
+        wolfSSL_CertManagerFree(cm);
+        cm = NULL;
+    }
+    return cm;
+}
+
+/* Create a new certificate manager.
+ *
+ * @return  Certificate manager object on success.
+ * @return  NULL on failure.
+ */
+WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
+{
+    /* No heap hint. */
+    return wolfSSL_CertManagerNew_ex(NULL);
+}
+
+/* Dispose of certificate manager.
+ *
+ * @param [in, out] cm  Certificate manager.
+ */
+void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerFree");
+
+    /* Validate parameter. */
+    if (cm != NULL) {
+        int doFree = 0;
+        int ret;
+
+        /* Decrement reference count and check if value is 0. */
+        wolfSSL_RefDec(&cm->ref, &doFree, &ret);
+    #ifdef WOLFSSL_REFCNT_ERROR_RETURN
+        if (ret != 0) {
+            WOLFSSL_MSG("Couldn't lock cm mutex");
+        }
+    #else
+        (void)ret;
+    #endif
+        if (doFree) {
+        #ifdef HAVE_CRL
+            /* Dispose of CRL handler. */
+            if (cm->crl != NULL) {
+                /* Dispose of CRL object - indicating dynamicly allocated. */
+                FreeCRL(cm->crl, 1);
+            }
+        #endif
+
+    #ifdef HAVE_OCSP
+            /* Dispose of OCSP handler. */
+            if (cm->ocsp != NULL) {
+                FreeOCSP(cm->ocsp, 1);
+            }
+            /* Dispose of URL. */
+            XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
+        #if !defined(NO_WOLFSSL_SERVER) && \
+            (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+             defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+            /* Dispose of OCSP stapling handler. */
+            if (cm->ocsp_stapling) {
+                FreeOCSP(cm->ocsp_stapling, 1);
+            }
+        #endif
+    #endif /* HAVE_OCSP */
+
+            /* Dispose of CA table and mutex. */
+            FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
+            wc_FreeMutex(&cm->caLock);
+
+        #ifdef WOLFSSL_TRUST_PEER_CERT
+            /* Dispose of trusted peer table and mutex. */
+            FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
+            wc_FreeMutex(&cm->tpLock);
+        #endif
+
+            /* Dispose of reference count. */
+            wolfSSL_RefFree(&cm->ref);
+            /* Dispose of certificate manager memory. */
+            XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
+        }
+    }
+}
+
+/* Increase reference count on certificate manager.
+ *
+ * @param [in, out] cm  Certificate manager.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  0 when cm is NULL or locking mutex fails.
+ */
+int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    /* Validate parameter. */
+    if (cm == NULL) {
+        ret = 0;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        int err;
+
+        /* Increment reference. */
+        wolfSSL_RefInc(&cm->ref, &err);
+    #ifdef WOLFSSL_REFCNT_ERROR_RETURN
+        if (err) {
+            WOLFSSL_MSG("Failed to lock cm mutex");
+            ret = 0;
+        }
+    #else
+        (void)err;
+    #endif
+    }
+
+    return ret;
+}
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM)
+#if defined(WOLFSSL_SIGNER_DER_CERT)
+static WC_INLINE int wolfssl_cm_get_certs_der(WOLFSSL_CERT_MANAGER* cm,
+    DerBuffer*** buffers, int* cnt)
+{
+    int err = 0;
+    Signer* signers = NULL;
+    DerBuffer** certBuffers = NULL;
+    int i = 0;
+    word32 row = 0;
+    int numCerts = 0;
+
+    /* Iterate once to get the number of certs, for memory allocation
+     * purposes. */
+    for (row = 0; row < CA_TABLE_SIZE; row++) {
+        /* Get signer information of CAs in a row. */
+        signers = cm->caTable[row];
+        /* Count each signer in row that has a DER certificate buffer. */
+        while ((signers != NULL) && (signers->derCert != NULL) &&
+                (signers->derCert->buffer != NULL)) {
+            ++numCerts;
+            signers = signers->next;
+        }
+    }
+    /* Check we found certificates. */
+    if (numCerts == 0) {
+        err = 1;
+    }
+
+    if (!err) {
+        /* Allocate memory for pointers to each DER buffer. */
+        certBuffers = (DerBuffer**)XMALLOC(sizeof(DerBuffer*) * numCerts,
+            cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (certBuffers == NULL) {
+            err = 1;
+        }
+    }
+    if (!err) {
+        /* Reset pointers. */
+        XMEMSET(certBuffers, 0, sizeof(DerBuffer*) * numCerts);
+    }
+
+    /* Copy the certs locally so that we can release the caLock. If the lock
+     * is held when wolfSSL_d2i_X509 is called, GetCA will also try to get
+     * the lock, leading to deadlock. */
+    for (row = 0; (!err) && (row < CA_TABLE_SIZE); row++) {
+        /* Get signer information of CAs in a row. */
+        signers = cm->caTable[row];
+        /* Copy each DER certificate buffer of signers in a row. */
+        while ((signers != NULL) && (signers->derCert != NULL) &&
+                (signers->derCert->buffer != NULL)) {
+            /* Allocate memory to hold DER certificate buffer. */
+            int ret = AllocDer(&certBuffers[i], signers->derCert->length,
+                CA_TYPE, cm->heap);
+            if (ret < 0) {
+                err = 1;
+                break;
+            }
+
+            /* Copy buffer into array element. */
+            XMEMCPY(certBuffers[i]->buffer, signers->derCert->buffer,
+                signers->derCert->length);
+            certBuffers[i]->length = signers->derCert->length;
+
+            /* Store in next index. */
+            ++i;
+            /* Move on to next signer in row. */
+            signers = signers->next;
+        }
+    }
+
+    *buffers = certBuffers;
+    *cnt = numCerts;
+    return err;
+}
+
+/* Retrieve stack of X509 certificates in a certificate manager (CM).
+ *
+ * @param [in] cm  Certificate manager.
+ *
+ * @return  Stack of X509 certs on success
+ * @return  NULL on failure.
+ */
+WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_STACK* sk = NULL;
+    int numCerts = 0;
+    DerBuffer** certBuffers = NULL;
+    int i = 0;
+    int err = 0;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerGetCerts");
+
+    /* Validate parameter. */
+    if (cm == NULL) {
+        err = 1;
+    }
+    if (!err) {
+        /* Create an empty certificate stack to return. */
+        sk = wolfSSL_sk_X509_new_null();
+        if (sk == NULL) {
+            err = 1;
+        }
+    }
+    /* Lock CA table. */
+    if ((!err) && (wc_LockMutex(&cm->caLock) != 0)) {
+        err = 1;
+    }
+    if (!err) {
+        err = wolfssl_cm_get_certs_der(cm, &certBuffers, &numCerts);
+        /* Release CA lock. */
+        wc_UnLockMutex(&cm->caLock);
+    }
+
+    /* Put each DER certificate buffer into a stack of WOLFSSL_X509 */
+    for (i = 0; (!err) && (i < numCerts); ++i) {
+        const byte* derBuffer = NULL;
+        WOLFSSL_X509* x509 = NULL;
+
+        /* Get pointer to DER encoding of certificate. */
+        derBuffer = certBuffers[i]->buffer;
+        /* Decode certificate. */
+        wolfSSL_d2i_X509(&x509, &derBuffer, certBuffers[i]->length);
+        if (x509 == NULL) {
+            err = 1;
+        }
+
+        /* Decode certificate. */
+        if ((!err) && (wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS)) {
+            wolfSSL_X509_free(x509);
+            err = 1;
+        }
+    }
+
+    if (certBuffers != NULL) {
+        /* Dispose of temporary cert storage (for access outside of lock). */
+        for (i = 0; i < numCerts && certBuffers[i] != NULL; ++i) {
+            FreeDer(&certBuffers[i]);
+        }
+        XFREE(certBuffers, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+
+    /* Dispose of stack of certificates on error. */
+    if (err && (sk != NULL)) {
+        wolfSSL_sk_X509_pop_free(sk, NULL);
+        sk = NULL;
+    }
+    return sk;
+}
+
+#endif /* WOLFSSL_SIGNER_DER_CERT */
+#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM */
+
+/* Unload the CA signer table.
+ *
+ * @param [in] cm  Certificate manager.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ * @return  BAD_MUTEX_E when locking fails.
+ */
+int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadCAs");
+
+    /* Validate parameter. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    /* Lock CA table. */
+    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
+        ret = BAD_MUTEX_E;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Dispose of CA table. */
+        FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
+
+        /* Unlock CA table. */
+        wc_UnLockMutex(&cm->caLock);
+    }
+
+    return ret;
+}
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* Unload the trusted peers table.
+ *
+ * @param [in] cm  Certificate manager.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ * @return  BAD_MUTEX_E when locking fails.
+ */
+int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers");
+
+    /* Validate parameter. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    /* Lock trusted peers table. */
+    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->tpLock) != 0)) {
+        ret = BAD_MUTEX_E;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Dispose of trusted peers table. */
+        FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
+
+        /* Unlock trusted peers table. */
+        wc_UnLockMutex(&cm->tpLock);
+    }
+
+    return ret;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+/* Load certificate/s from buffer with flags.
+ *
+ * @param [in] cm         Certificate manager.
+ * @param [in] buff       Buffer holding encoding of certificate.
+ * @param [in] sz         Length in bytes of data in buffer.
+ * @param [in] format     Format of encoding. Valid values:
+ *                          WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
+ * @param [in] userChain  Indicates buffer holds chain of certificates.
+ * @param [in] flags      Flags to modify behaviour of loading. Valid flags:
+ *                          WOLFSSL_LOAD_FLAG_IGNORE_ERR,
+ *                          WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY,
+ *                          WOLFSSL_LOAD_FLAG_PEM_CA_ONLY,
+ *                          WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR, and
+ *                          WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  WOLFSSL_FATAL_ERROR when cm is NULL or failed create WOLFSSL_CTX.
+ * @return  Other values on loading failure.
+ */
+int wolfSSL_CertManagerLoadCABuffer_ex(WOLFSSL_CERT_MANAGER* cm,
+    const unsigned char* buff, long sz, int format, int userChain, word32 flags)
+{
+    int ret = WOLFSSL_SUCCESS;
+    WOLFSSL_CTX* tmp = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer_ex");
+
+    /* Validate parameters. */
+    if (cm == NULL) {
+        WOLFSSL_MSG("No CertManager error");
+        ret = WOLFSSL_FATAL_ERROR;
+    }
+    /* Allocate a temporary WOLFSSL_CTX to load with. */
+    if ((ret == WOLFSSL_SUCCESS) && ((tmp = wolfSSL_CTX_new(cm_pick_method()))
+            == NULL)) {
+        WOLFSSL_MSG("CTX new failed");
+        ret = WOLFSSL_FATAL_ERROR;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Replace certificate manager with one to load certificate/s into. */
+        wolfSSL_CertManagerFree(tmp->cm);
+        tmp->cm = cm;
+
+        /* Load certificate buffer. */
+        ret = wolfSSL_CTX_load_verify_buffer_ex(tmp, buff, sz, format,
+            userChain, flags);
+
+        /* Clear certificate manager in WOLFSSL_CTX so it won't be freed. */
+        tmp->cm = NULL;
+    }
+
+    /* Dispose of temporary WOLFSSL_CTX. */
+    wolfSSL_CTX_free(tmp);
+    return ret;
+}
+
+/* Load certificate/s from buffer into table.
+ *
+ * Uses default load verification flags and is not a user chain.
+ *
+ * @param [in] cm         Certificate manager.
+ * @param [in] buff       Buffer holding encoding of certificate.
+ * @param [in] sz         Length in bytes of data in buffer.
+ * @param [in] format     Format of encoding. Valid values:
+ *                          WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  WOLFSSL_FATAL_ERROR when cm is NULL or failed create WOLFSSL_CTX.
+ * @return  Other values on loading failure.
+ */
+int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm,
+    const unsigned char* buff, long sz, int format)
+{
+    return wolfSSL_CertManagerLoadCABuffer_ex(cm, buff, sz, format, 0,
+        WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
+}
+
+#ifndef NO_WOLFSSL_CM_VERIFY
+/* Set the verification callback into certificate manager.
+ *
+ * @param [in] cm  Certificate manager.
+ * @param [in] vc  Verification callback.
+ */
+void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm, VerifyCallback vc)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerSetVerify");
+    if (cm != NULL) {
+        cm->verifyCallback = vc;
+    }
+}
+#endif /* NO_WOLFSSL_CM_VERIFY */
+
+#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+/* Verify the certificate.
+ *
+ * Uses the verification callback if available.
+ *
+ * @param [in] cm        Certificate manager.
+ * @param [in] buff      Buffer holding encoded certificate.
+ * @param [in] sz        Size in bytes of data in buffer.
+ * @param [in] format    Format of encoding. Valid values:
+ *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
+ * @param [in] prev_err  Previous error. Passed to callback.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
+ *          the wolfSSL build.
+ */
+int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const unsigned char* buff,
+    long sz, int format, int prev_err)
+{
+    int ret = 0;
+    int fatal = 0;
+    DerBuffer* der = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    WOLFSSL_ENTER("CM_VerifyBuffer_ex");
+
+    (void)prev_err;
+
+#ifdef WOLFSSL_SMALL_STACK
+    /* Allocate memory for decoded certificate. */
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
+         DYNAMIC_TYPE_DCERT);
+    if (cert == NULL) {
+        ret = MEMORY_E;
+        fatal = 1;
+    }
+    if (ret == 0)
+#endif
+    {
+        /* Reset fields of decoded certifcate. */
+        XMEMSET(cert, 0, sizeof(DecodedCert));
+
+        if (format == WOLFSSL_FILETYPE_PEM) {
+        #ifndef WOLFSSL_PEM_TO_DER
+            ret = NOT_COMPILED_IN;
+            fatal = 1;
+        #else
+            /* Convert to DER from PEM. */
+            ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
+            if (ret != 0) {
+                fatal = 1;
+            }
+            else {
+                /* Replace buffer pointer and size with DER buffer. */
+                buff = der->buffer;
+                sz = (long)der->length;
+            }
+        #endif
+        }
+    }
+    if (ret == 0) {
+        /* Create a decoded certificate with DER buffer. */
+        InitDecodedCert(cert, buff, (word32)sz, cm->heap);
+
+        /* Parse DER into decoded certificate fields and verify signature
+         * against a known CA. */
+        ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, cm);
+     }
+
+#ifdef HAVE_CRL
+    if ((ret == 0) && cm->crlEnabled) {
+        /* Check for a CRL for the CA and check validity of certificate. */
+        ret = CheckCertCRL(cm->crl, cert);
+    }
+#endif
+
+    (void)fatal;
+
+#ifndef NO_WOLFSSL_CM_VERIFY
+    /* Use callback to perform verification too if available. */
+    if ((!fatal) && cm->verifyCallback) {
+    #ifdef WOLFSSL_SMALL_STACK
+        ProcPeerCertArgs* args;
+    #else
+        ProcPeerCertArgs  args[1];
+    #endif
+        buffer certBuf;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        /* Allocate memory for object to hold arguements for callback. */
+        args = (ProcPeerCertArgs*)XMALLOC(sizeof(ProcPeerCertArgs), cm->heap,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (args == NULL) {
+            ret = MEMORY_E;
+            fatal = 1;
+        }
+        if (!fatal)
+    #endif
+        {
+            XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
+
+            /* DER encoding. */
+            certBuf.buffer = (byte*)buff;
+            certBuf.length = (unsigned int)sz;
+
+            /* One certificate available. */
+            args->totalCerts = 1;
+            args->certs = &certBuf;
+            args->dCert = cert;
+            args->dCertInit = 1;
+
+            /* Replace value in ret with an error value passed in. */
+            if (prev_err != 0) {
+                ret = prev_err;
+            }
+            /* Use callback to verify certificate. */
+            ret = DoVerifyCallback(cm, NULL, ret, args);
+        }
+    #ifdef WOLFSSL_SMALL_STACK
+        /* Dispose of allocated callback args. */
+        XFREE(args, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+    }
+#endif
+
+    /* Dispose of allocated memory. */
+    FreeDecodedCert(cert);
+    FreeDer(&der);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+#endif
+
+    /* Convert the ret value to a return value. */
+    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
+}
+
+/* Verify the certificate.
+ *
+ * Uses the verification callback if available.
+ *
+ * @param [in] cm        Certificate manager.
+ * @param [in] buff      Buffer holding encoded certificate.
+ * @param [in] sz        Size in bytes of data in buffer.
+ * @param [in] format    Format of encoding. Valid values:
+ *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
+ * @param [in] prev_err  Previous error. Passed to callback.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm or buff is NULL ot sz is negativei or zero.
+ * @return  WOLFSSL_BAD_FILETYPE when format is invalid.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
+ *          the wolfSSL build.
+ */
+int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm,
+    const unsigned char* buff, long sz, int format)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer");
+
+    /* Validate parameters. */
+    if ((cm == NULL) || (buff == NULL) || (sz <= 0)) {
+        ret = BAD_FUNC_ARG;
+    }
+    else if ((format != WOLFSSL_FILETYPE_ASN1) &&
+             (format != WOLFSSL_FILETYPE_PEM)) {
+        ret = WOLFSSL_BAD_FILETYPE;
+    }
+    else {
+        /* No previous error. */
+        ret = CM_VerifyBuffer_ex(cm, buff, sz, format, 0);
+    }
+
+    return ret;
+}
+#endif /* !NO_WOLFSSL_CLIENT || !WOLFSSL_NO_CLIENT_AUTH */
+
+#ifndef NO_FILESYSTEM
+
+#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+/* Verify the certificate loaded from a file.
+ *
+ * Uses the verification callback if available.
+ *
+ * @param [in] cm        Certificate manager.
+ * @param [in] format    Format of encoding. Valid values:
+ *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
+ * @param [in] prev_err  Previous error. Passed to callback.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm or buff is NULL ot sz is negative.
+ * @return  WOLFSSL_BAD_FILETYPE when format is invalid.
+ * @return  WOLFSSL_BAD_FILE when reading the certificate file fails.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
+ *          the wolfSSL build.
+ */
+int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
+    int format)
+{
+    int    ret = WOLFSSL_SUCCESS;
+#ifndef WOLFSSL_SMALL_STACK
+    byte   staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte*  buff;
+    long   sz = 0;
+    XFILE  file = XBADFILE;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerVerify");
+
+#ifndef WOLFSSL_SMALL_STACK
+    buff = staticBuffer;
+#endif
+
+    /* Validate parameters. cm and format validated in:
+     *   wolfSSL_CertManagerVerifyBuffer */
+    if ((cm == NULL) || (fname == NULL)) {
+        ret = BAD_FUNC_ARG;
+    }
+
+    /* Open the file containing a certificate. */
+    if ((ret == WOLFSSL_SUCCESS) &&
+            ((file = XFOPEN(fname, "rb")) == XBADFILE)) {
+        ret = WOLFSSL_BAD_FILE;
+    }
+    /* Get the length of the file. */
+    if (ret == WOLFSSL_SUCCESS) {
+        ret = wolfssl_file_len(file, &sz);
+        if (ret == 0) {
+            ret = WOLFSSL_SUCCESS;
+        }
+    }
+    /* Allocate dynamic memory for file contents if no static buffer or too
+     * small. */
+#ifndef WOLFSSL_SMALL_STACK
+    if ((ret == WOLFSSL_SUCCESS) && (sz > (long)sizeof(staticBuffer)))
+#endif
+    {
+        WOLFSSL_MSG("Getting dynamic buffer");
+        buff = (byte*)XMALLOC(sz, cm->heap, DYNAMIC_TYPE_FILE);
+        if (buff == NULL) {
+            ret = WOLFSSL_BAD_FILE;
+        }
+    }
+    /* Read all the file into buffer. */
+    if ((ret == WOLFSSL_SUCCESS) && ((size_t)XFREAD(buff, 1, sz, file) !=
+            (size_t)sz)) {
+        ret = WOLFSSL_BAD_FILE;
+    }
+    /* Close file if opened. */
+    if (file != XBADFILE) {
+        XFCLOSE(file);
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Verify the certificate read. */
+        ret = wolfSSL_CertManagerVerifyBuffer(cm, buff, sz, format);
+    }
+
+    /* Dispose of buffer if it was allocated. */
+#ifndef WOLFSSL_SMALL_STACK
+    if (buff != staticBuffer)
+#endif
+    {
+        XFREE(buff, cm->heap, DYNAMIC_TYPE_FILE);
+    }
+    return ret;
+}
+#endif
+
+/* Load the CA file and/or certificate files in a path.
+ *
+ * @param [in] cm    Certificate manager.
+ * @param [in] file  Name of CA file.
+ * @param [in] path  Path to a directory containing certificates.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  WOLFSSL_FATAL_ERROR when cm is NULL or unalbe to create WOLFSSL_CTX.
+ * @return  Otherwise failure.
+ */
+int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file,
+                             const char* path)
+{
+    int ret = WOLFSSL_SUCCESS;
+    WOLFSSL_CTX* tmp = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA");
+
+    /* Validate parameters. file and path validated in:
+     *   wolfSSL_CTX_load_verify_locations*/
+    if (cm == NULL) {
+        WOLFSSL_MSG("No CertManager error");
+        ret = WOLFSSL_FATAL_ERROR;
+    }
+    /* Create temporary WOLFSSL_CTX. */
+    if ((ret == WOLFSSL_SUCCESS) && ((tmp = wolfSSL_CTX_new(cm_pick_method()))
+        == NULL)) {
+        WOLFSSL_MSG("CTX new failed");
+        ret = WOLFSSL_FATAL_ERROR;
+    }
+
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Replace certificate manager with one to load certificate/s into. */
+        wolfSSL_CertManagerFree(tmp->cm);
+        tmp->cm = cm;
+
+        ret = wolfSSL_CTX_load_verify_locations(tmp, file, path);
+
+        /* Clear certificate manager in WOLFSSL_CTX so it won't be freed. */
+        tmp->cm = NULL;
+    }
+
+    /* Dispose of temporary WOLFSSL_CTX. */
+    wolfSSL_CTX_free(tmp);
+    return ret;
+}
+
+#endif /* NO_FILESYSTEM */
+
+#if defined(PERSIST_CERT_CACHE)
+
+/* Version of layout of cache of CA certificates. */
+#define WOLFSSL_CACHE_CERT_VERSION 1
+
+/* CA certificates cache information. */
+typedef struct {
+    /* Cache certficate layout version id. */
+    int version;
+    /* Number of hash table rows. Maximum of CA_TABLE_SIZE. */
+    int rows;
+    /* Number of colums per row. */
+    int columns[CA_TABLE_SIZE];
+    /* Size of Signer object. */
+    int signerSz;
+} CertCacheHeader;
+
+/* current cert persistence layout is:
+
+   1) CertCacheHeader
+   2) caTable
+
+   update WOLFSSL_CERT_CACHE_VERSION if change layout for the following
+   PERSIST_CERT_CACHE functions
+*/
+
+
+/* Return number of bytes of memory needed to persist this signer.
+ *
+ * Assumes we have locked CA table.
+ *
+ * @param [in] Signer  Signer entry in CA table.
+ * @return  Number of bytes.
+ */
+static WC_INLINE int cm_get_signer_memory(Signer* signer)
+{
+    int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID)
+           + sizeof(signer->nameLen)    + sizeof(signer->subjectNameHash);
+
+#if !defined(NO_SKID)
+        sz += (int)sizeof(signer->subjectKeyIdHash);
+#endif
+
+    /* Add dynamic bytes needed. */
+    sz += signer->pubKeySize;
+    sz += signer->nameLen;
+
+    return sz;
+}
+
+
+/* Return number of bytes of memory needed to persist this row.
+ *
+ * Assumes we have locked CA table.
+ *
+ * @param [in] row  A row of signers from the CA table.
+ * @return  Number of bytes.
+ */
+static WC_INLINE int cm_get_cert_cache_row_memory(Signer* row)
+{
+    int sz = 0;
+
+    /* Each signer in row. */
+    while (row != NULL) {
+        /* Add in size of this signer. */
+        sz += cm_get_signer_memory(row);
+        row = row->next;
+    }
+
+    return sz;
+}
+
+
+/* Return the number of bytes of memory to persist cert cache.
+ *
+ * Assumes we have locked CA table.
+ *
+ * @param [in] cm  Certificate manager.
+ * @return  Number of bytes.
+ */
+static WC_INLINE int cm_get_cert_cache_mem_size(WOLFSSL_CERT_MANAGER* cm)
+{
+    int sz;
+    int i;
+
+    sz = sizeof(CertCacheHeader);
+
+    /* Each row in table. */
+    for (i = 0; i < CA_TABLE_SIZE; i++) {
+        /* Add in size of this row. */
+        sz += cm_get_cert_cache_row_memory(cm->caTable[i]);
+    }
+
+    return sz;
+}
+
+
+/* Get count of colums for each row.
+ *
+ * Assumes we have locked CA table.
+ *
+ * @param [in] cm       Certificate manager.
+ * @param [in] columns  Array of row counts.
+ */
+static WC_INLINE void cm_set_cert_header_Columns(WOLFSSL_CERT_MANAGER* cm,
+    int* columns)
+{
+    int     i;
+    Signer* row;
+
+    /* Each row in table. */
+    for (i = 0; i < CA_TABLE_SIZE; i++) {
+        int count = 0;
+
+        /* Get row from table. */
+        row = cm->caTable[i];
+        /* Each entry in row. */
+        while (row != NULL) {
+            /* Update count. */
+            ++count;
+            row = row->next;
+        }
+        /* Store row count. */
+        columns[i] = count;
+    }
+}
+
+
+/* Restore whole cert row from memory,
+ *
+ * Assumes we have locked CA table.
+ *
+ * @param [in] cm       Certificate manager.
+ * @param [in] current  Buffer containing rows.
+ * @param [in] row      Row number being restored.
+ * @param [in] listSz   Number of entries in row.
+ * @param [in] end      End of data in buffer.
+ * @return  Number of bytes consumed on success.
+ * @return  PARSE_ERROR when listSz is less than zero.
+ * @return  BUFFER_E when buffer is too small.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ * @return  Negative value on error.
+ */
+static WC_INLINE int cm_restore_cert_row(WOLFSSL_CERT_MANAGER* cm,
+    byte* current, int row, int listSz, const byte* end)
+{
+    int ret = 0;
+    int idx = 0;
+
+    /* Validate parameters. */
+    if (listSz < 0) {
+        WOLFSSL_MSG("Row header corrupted, negative value");
+        ret = PARSE_ERROR;
+    }
+
+    /* Process all entries. */
+    while ((ret == 0) && (listSz > 0)) {
+        Signer* signer = NULL;
+        byte*   publicKey;
+        byte*   start = current + idx;  /* for end checks on this signer */
+        int     minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) +
+                      sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
+        #ifndef NO_SKID
+                minSz += (int)sizeof(signer->subjectKeyIdHash);
+        #endif
+
+        /* Check minimal size of bytes available. */
+        if (start + minSz > end) {
+            WOLFSSL_MSG("Would overread restore buffer");
+            ret = BUFFER_E;
+        }
+        /* Make a new signer. */
+        if ((ret == 0) && ((signer = MakeSigner(cm->heap)) == NULL)) {
+            ret = MEMORY_E;
+        }
+
+        if (ret == 0) {
+            /* Copy in public key size. */
+            XMEMCPY(&signer->pubKeySize, current + idx,
+                sizeof(signer->pubKeySize));
+            idx += (int)sizeof(signer->pubKeySize);
+
+            /* Copy in public key OID. */
+            XMEMCPY(&signer->keyOID, current + idx, sizeof(signer->keyOID));
+            idx += (int)sizeof(signer->keyOID);
+
+            /* Check bytes available for public key. */
+            if (start + minSz + signer->pubKeySize > end) {
+                WOLFSSL_MSG("Would overread restore buffer");
+                ret = BUFFER_E;
+            }
+        }
+        if (ret == 0) {
+            /* Allocate memory for public key to be stored in. */
+            publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap,
+                DYNAMIC_TYPE_KEY);
+            if (publicKey == NULL) {
+                ret = MEMORY_E;
+            }
+        }
+
+        if (ret == 0) {
+            /* Copy in public key. */
+            XMEMCPY(publicKey, current + idx, signer->pubKeySize);
+            signer->publicKey = publicKey;
+            idx += signer->pubKeySize;
+
+            /* Copy in certificate name length. */
+            XMEMCPY(&signer->nameLen, current + idx, sizeof(signer->nameLen));
+            idx += (int)sizeof(signer->nameLen);
+
+            /* Check bytes available for certificate name. */
+            if (start + minSz + signer->pubKeySize + signer->nameLen > end) {
+                WOLFSSL_MSG("Would overread restore buffer");
+                ret = BUFFER_E;
+            }
+        }
+        if (ret == 0) {
+            /* Allocate memory for public key to be stored in. */
+            signer->name = (char*)XMALLOC(signer->nameLen, cm->heap,
+                DYNAMIC_TYPE_SUBJECT_CN);
+            if (signer->name == NULL) {
+                ret = MEMORY_E;
+            }
+        }
+
+        if (ret == 0) {
+            /* Copy in certificate name. */
+            XMEMCPY(signer->name, current + idx, signer->nameLen);
+            idx += signer->nameLen;
+
+            /* Copy in hash of subject name. */
+            XMEMCPY(signer->subjectNameHash, current + idx, SIGNER_DIGEST_SIZE);
+            idx += SIGNER_DIGEST_SIZE;
+
+        #ifndef NO_SKID
+            /* Copy in hash of subject key. */
+            XMEMCPY(signer->subjectKeyIdHash, current + idx,SIGNER_DIGEST_SIZE);
+            idx += SIGNER_DIGEST_SIZE;
+        #endif
+
+            /* Make next Signer the head of the row. */
+            signer->next = cm->caTable[row];
+            /* Add Signer to start of row. */
+            cm->caTable[row] = signer;
+
+            /* Done one more Signer. */
+            --listSz;
+        }
+
+        if ((ret != 0) && (signer != NULL)) {
+            /* Dispose of allocated signer. */
+            FreeSigner(signer, cm->heap);
+        }
+    }
+
+    if (ret == 0) {
+        /* Return the number of bytes used on success. */
+        ret = idx;
+    }
+    return ret;
+}
+
+
+/* Store whole CA certificate row into memory.
+ *
+ * Assumes we have locked CA table.
+ *
+ * @param [in] cm       Certificate manager.
+ * @param [in] current  Buffer to write to.
+ * @param [in] row      Row number being stored.
+ * @return  Number of bytes added.
+ */
+static WC_INLINE int cm_store_cert_row(WOLFSSL_CERT_MANAGER* cm, byte* current,
+    int row)
+{
+    int     added  = 0;
+    Signer* list;
+
+    /* Get the row - a linked list. */
+    list  = cm->caTable[row];
+    /* Each certificate in row. */
+    while (list != NULL) {
+        /* Public key size. */
+        XMEMCPY(current + added, &list->pubKeySize, sizeof(list->pubKeySize));
+        added += (int)sizeof(list->pubKeySize);
+
+        /* Public key OID. */
+        XMEMCPY(current + added, &list->keyOID,     sizeof(list->keyOID));
+        added += (int)sizeof(list->keyOID);
+
+        /* Public key. */
+        XMEMCPY(current + added, list->publicKey, list->pubKeySize);
+        added += list->pubKeySize;
+
+        /* Certificate name length. */
+        XMEMCPY(current + added, &list->nameLen, sizeof(list->nameLen));
+        added += (int)sizeof(list->nameLen);
+
+        /* Certificate name. */
+        XMEMCPY(current + added, list->name, list->nameLen);
+        added += list->nameLen;
+
+        /* Hash of subject name. */
+        XMEMCPY(current + added, list->subjectNameHash, SIGNER_DIGEST_SIZE);
+        added += SIGNER_DIGEST_SIZE;
+
+    #ifndef NO_SKID
+        /* Hash of public key. */
+        XMEMCPY(current + added, list->subjectKeyIdHash,SIGNER_DIGEST_SIZE);
+        added += SIGNER_DIGEST_SIZE;
+    #endif
+
+        /* Next certificate in row. */
+        list = list->next;
+    }
+
+    return added;
+}
+
+
+/* Persist CA certificate cache to memory.
+ *
+ * Assumes we have locked CA table.
+ *
+ * @param [in] cm   Certificate manager.
+ * @param [in] mem  Memory to persist into.
+ * @param [in] sz   Size in bytes of memory.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BUFFER_E when memory is too small.
+ */
+static WC_INLINE int cm_do_mem_save_cert_cache(WOLFSSL_CERT_MANAGER* cm,
+    void* mem, int sz)
+{
+    int ret = WOLFSSL_SUCCESS;
+    int realSz;
+    int i;
+
+    WOLFSSL_ENTER("cm_do_mem_save_cert_cache");
+
+    /* Calculate amount of memory required to store CA certificate table. */
+    realSz = cm_get_cert_cache_mem_size(cm);
+    if (realSz > sz) {
+        WOLFSSL_MSG("Mem output buffer too small");
+        ret = BUFFER_E;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        byte*           current;
+        CertCacheHeader hdr;
+
+        /* Create header for storage. */
+        hdr.version  = WOLFSSL_CACHE_CERT_VERSION;
+        hdr.rows     = CA_TABLE_SIZE;
+        cm_set_cert_header_Columns(cm, hdr.columns);
+        hdr.signerSz = (int)sizeof(Signer);
+
+        /* Copy header into memory. */
+        XMEMCPY(mem, &hdr, sizeof(CertCacheHeader));
+        current = (byte*)mem + sizeof(CertCacheHeader);
+
+        /* Each row of table. */
+        for (i = 0; i < CA_TABLE_SIZE; ++i) {
+            /* Append row to memory. */
+            current += cm_store_cert_row(cm, current, i);
+        }
+    }
+
+    return ret;
+}
+
+
+#if !defined(NO_FILESYSTEM)
+
+/* Persist CA certificate cache to file.
+ *
+ * Locks CA table.
+ *
+ * @param [in] cm     Certificate manager.
+ * @param [in] fname  File name to write to.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  WOLFSSL_BAD_FILE when opening file fails.
+ * @return  BAD_MUTEX_E when locking fails.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ * @return  FWRITE_ERROR when writing to file fails.
+ */
+int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
+{
+    XFILE file;
+    int   ret = WOLFSSL_SUCCESS;
+    int   memSz;
+    byte* mem;
+
+    WOLFSSL_ENTER("CM_SaveCertCache");
+
+    /* Open file for writing. */
+    file = XFOPEN(fname, "w+b");
+    if (file == XBADFILE) {
+       WOLFSSL_MSG("Couldn't open cert cache save file");
+       ret = WOLFSSL_BAD_FILE;
+    }
+
+    /* Lock CA table. */
+    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        ret = BAD_MUTEX_E;
+    }
+
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Calculate size of memory required to store CA table. */
+        memSz = cm_get_cert_cache_mem_size(cm);
+        /* Allocate memory to hold CA table. */
+        mem   = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (mem == NULL) {
+            WOLFSSL_MSG("Alloc for tmp buffer failed");
+            ret = MEMORY_E;
+        }
+        if (ret == WOLFSSL_SUCCESS) {
+            /* Store CA table in memory. */
+            ret = cm_do_mem_save_cert_cache(cm, mem, memSz);
+        }
+        if (ret == WOLFSSL_SUCCESS) {
+            /* Write memory to file. */
+            int sz = (int)XFWRITE(mem, memSz, 1, file);
+            if (sz != 1) {
+                WOLFSSL_MSG("Cert cache file write failed");
+                ret = FWRITE_ERROR;
+            }
+            XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        }
+
+        /* Unlock CA table. */
+        wc_UnLockMutex(&cm->caLock);
+    }
+
+    /* Close file. */
+    if (file != XBADFILE) {
+        XFCLOSE(file);
+    }
+    return ret;
+}
+
+
+/* Restore CA certificate cache from file.
+ *
+ * @param [in] cm     Certificate manager.
+ * @param [in] fname  File name to write to.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  WOLFSSL_BAD_FILE when opening or using file fails.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ * @return  FREAD_ERROR when reading from file fails.
+ */
+int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
+{
+    XFILE file;
+    int   ret = WOLFSSL_SUCCESS;
+    int   memSz = 0;
+    byte* mem = NULL;
+
+    WOLFSSL_ENTER("CM_RestoreCertCache");
+
+    /* Open file for reading. */
+    file = XFOPEN(fname, "rb");
+    if (file == XBADFILE) {
+       WOLFSSL_MSG("Couldn't open cert cache save file");
+       ret = WOLFSSL_BAD_FILE;
+    }
+
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Read file into allocated memory. */
+        ret = wolfssl_read_file(file, (char**)&mem, &memSz);
+        if (ret == 0) {
+            ret = WOLFSSL_SUCCESS;
+        }
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Create the CA certificate table from memory. */
+        ret = CM_MemRestoreCertCache(cm, mem, memSz);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Mem restore cert cache failed");
+        }
+    }
+
+    /* Dispose of dynamic memory read into. */
+    XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    /* Close file. */
+    if (file != XBADFILE) {
+        XFCLOSE(file);
+    }
+    return ret;
+}
+
+#endif /* NO_FILESYSTEM */
+
+
+/* Persist CA certificate cache to memory.
+ *
+ * Locks CA table.
+ *
+ * @param [in]  cm    Certificate manager.
+ * @param [in]  mem   Memory to persist into.
+ * @param [in]  sz    Size in bytes of memory.
+ * @param [out] used  Number of bytes used when persisting cache.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_MUTEX_E when locking fails.
+ * @return  BUFFER_E when memory is too small.
+ */
+int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("CM_MemSaveCertCache");
+
+    /* Lock CA table. */
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        ret = BAD_MUTEX_E;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Save CA table into memory. */
+        ret = cm_do_mem_save_cert_cache(cm, mem, sz);
+        if (ret == WOLFSSL_SUCCESS) {
+            /* Get the number of bytes used. */
+            *used  = cm_get_cert_cache_mem_size(cm);
+        }
+
+        /* Unlock CA table. */
+        wc_UnLockMutex(&cm->caLock);
+    }
+
+    return ret;
+}
+
+
+/* Restore CA certificate table from memory,
+ *
+ * Locks CA table.
+ *
+ * @param [in] cm   Certificate manager.
+ * @param [in] mem  Buffer containing rows.
+ * @param [in] sz   Size in bytes of data in buffer.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BUFFER_E when buffer is too small.
+ * @return  BAD_MUTEX_E when locking fails.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ */
+int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
+{
+    int ret = WOLFSSL_SUCCESS;
+    int i;
+    CertCacheHeader* hdr = (CertCacheHeader*)mem;
+    byte*            current = (byte*)mem + sizeof(CertCacheHeader);
+    byte*            end     = (byte*)mem + sz;  /* don't go over */
+
+    WOLFSSL_ENTER("CM_MemRestoreCertCache");
+
+    /* Check memory available is bigger than cache header. */
+    if (current > end) {
+        WOLFSSL_MSG("Cert Cache Memory buffer too small");
+        ret = BUFFER_E;
+    }
+
+    /* Validate the cache header. */
+    if ((ret == WOLFSSL_SUCCESS) &&
+            ((hdr->version  != WOLFSSL_CACHE_CERT_VERSION) ||
+             (hdr->rows     != CA_TABLE_SIZE) ||
+             (hdr->signerSz != (int)sizeof(Signer)))) {
+        WOLFSSL_MSG("Cert Cache Memory header mismatch");
+        ret = CACHE_MATCH_ERROR;
+    }
+
+    /* Lock CA table. */
+    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        ret = BAD_MUTEX_E;
+    }
+
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Dispose of current CA certificate table. */
+        FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
+
+        /* Each row. */
+        for (i = 0; i < CA_TABLE_SIZE; ++i) {
+            /* Restore a row from memory. */
+            int added = cm_restore_cert_row(cm, current, i, hdr->columns[i],
+                end);
+            /* Bail on error. */
+            if (added < 0) {
+                WOLFSSL_MSG("cm_restore_cert_row error");
+                ret = added;
+                break;
+            }
+            /* Update pointer to data of next row. */
+            current += added;
+        }
+
+        /* Unlock CA table. */
+        wc_UnLockMutex(&cm->caLock);
+    }
+
+    return ret;
+}
+
+
+/* Calculate size of CA certificate cache when persisted to memory.
+ *
+ * Locks CA table.
+ *
+ * @param [in] cm  Certificate manager.
+ * @return  Number of bytes on success.
+ * @return  BAD_MUTEX_E when locking fails.
+ */
+int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret;
+
+    WOLFSSL_ENTER("CM_GetCertCacheMemSize");
+
+    /* Lock CA table. */
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        ret = BAD_MUTEX_E;
+    }
+    else {
+        /* Calculate memory size. */
+        ret = cm_get_cert_cache_mem_size(cm);
+
+        /* Unlock CA table. */
+        wc_UnLockMutex(&cm->caLock);
+    }
+
+    return ret;
+}
+
+#endif /* PERSIST_CERT_CACHE */
+
+/*******************************************************************************
+ * CRL handling
+ ******************************************************************************/
+
+/* Enables/disables the use of CRLs when validating certificates.
+ *
+ * @param [in] cm       Certificate manager.
+ * @param [in] options  Options for using CRLs. Valid flags:
+ *                        WOLFSSL_CRL_CHECKALL, WOLFSSL_CRL_CHECK.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  WOLFSSL_FAILURE when initializing the CRL object fails.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ * @return  NOT_COMPILED_IN when the CRL feature is disabled.
+ */
+int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL");
+
+    (void)options;
+
+    /* Validate parameters. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+
+#if defined(OPENSSL_COMPATIBLE_DEFAULTS)
+    /* If disabling then don't worry about whether CRL feature is enabled. */
+    if ((ret == WOLFSSL_SUCCESS) && (options == 0)) {
+        /* Disable leaf CRL check. */
+        cm->crlEnabled = 0;
+        /* Disable all CRL checks. */
+        cm->crlCheckAll = 0;
+    }
+    else
+#endif
+    if (ret == WOLFSSL_SUCCESS) {
+#ifndef HAVE_CRL
+        /* CRL feature not enabled. */
+        ret = NOT_COMPILED_IN;
+#else
+        /* Create CRL object if not present. */
+        if (cm->crl == NULL) {
+            /* Allocate memory for CRL object. */
+            cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap,
+                                            DYNAMIC_TYPE_CRL);
+            if (cm->crl == NULL) {
+                ret = MEMORY_E;
+            }
+            if (ret == WOLFSSL_SUCCESS) {
+                /* Reset fields of CRL object. */
+                XMEMSET(cm->crl, 0, sizeof(WOLFSSL_CRL));
+                /* Initialize CRL object. */
+                if (InitCRL(cm->crl, cm) != 0) {
+                    WOLFSSL_MSG("Init CRL failed");
+                    /* Dispose of CRL object - indicating dynamicly allocated.
+                     */
+                    FreeCRL(cm->crl, 1);
+                    cm->crl = NULL;
+                    ret = WOLFSSL_FAILURE;
+                }
+            }
+        }
+
+        if (ret == WOLFSSL_SUCCESS) {
+        #if defined(HAVE_CRL_IO) && defined(USE_WOLFSSL_IO)
+            /* Use built-in callback to lookup CRL from URL. */
+            cm->crl->crlIOCb = EmbedCrlLookup;
+        #endif
+        #if defined(OPENSSL_COMPATIBLE_DEFAULTS)
+            if ((options & WOLFSSL_CRL_CHECKALL) ||
+                (options & WOLFSSL_CRL_CHECK))
+        #endif
+            {
+                /* Enable leaf CRL check. */
+                cm->crlEnabled = 1;
+                if (options & WOLFSSL_CRL_CHECKALL) {
+                    /* Enable all CRL check. */
+                    cm->crlCheckAll = 1;
+                }
+            }
+        }
+#endif
+    }
+
+    return ret;
+}
+
+
+/* Disables the CRL checks.
+ *
+ * @param [in] cm  Certificate manager.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ */
+int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL");
+
+    /* Validate parameter. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Disable CRL checking. */
+        cm->crlEnabled = 0;
+    }
+
+    return ret;
+}
+
+#ifdef HAVE_CRL
+
+/* Load CRL for use.
+ *
+ * @param [in] cm    Certificate manager.
+ * @param [in] buff  Buffer holding CRL.
+ * @param [in] sz    Size in bytes of CRL in buffer.
+ * @param [in] type  Format of encoding. Valid values:
+ *                     WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm or buff is NULL or sz is negative or zero.
+ * @return  WOLFSSL_FATAL_ERROR when creating CRL object fails.
+ */
+int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
+    const unsigned char* buff, long sz, int type)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer");
+
+    /* Validate parameters. */
+    if ((cm == NULL) || (buff == NULL) || (sz <= 0)) {
+        ret = BAD_FUNC_ARG;
+    }
+
+    /* Create a CRL object if not available and enable CRL checking. */
+    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
+            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
+             WOLFSSL_SUCCESS)) {
+        WOLFSSL_MSG("Enable CRL failed");
+        ret = WOLFSSL_FATAL_ERROR;
+    }
+
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Load CRL into CRL object of the certificate manager. */
+        ret = BufferLoadCRL(cm->crl, buff, sz, type, VERIFY);
+    }
+
+    return ret;
+}
+
+/* Free the CRL object of the certificate manager.
+ *
+ * @param [in] cm  Certificate manager.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ */
+int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerFreeCRL");
+
+    /* Validate parameter. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    /* Check whether CRL object exists. */
+    if ((ret == WOLFSSL_SUCCESS) && (cm->crl != NULL)) {
+        /* Dispose of CRL object - indicating dynamicly allocated. */
+        FreeCRL(cm->crl, 1);
+        cm->crl = NULL;
+    }
+
+    return ret;
+}
+
+/* Check DER encoded certificate against CRLs if checking enabled.
+ *
+ * @param [in] cm   Certificate manager.
+ * @param [in] der  DER encode certificate.
+ * @param [in] sz   Size in bytes of DER encode certificate.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm or der is NULL or sz is negative or zero.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ */
+int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm,
+    const unsigned char* der, int sz)
+{
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerCheckCRL");
+
+    /* Validate parameters. */
+    if ((cm == NULL) || (der == NULL) || (sz <= 0)) {
+        ret = BAD_FUNC_ARG;
+    }
+
+    /* Check if CRL checking enabled. */
+    if ((ret == 0) && cm->crlEnabled) {
+    #ifdef WOLFSSL_SMALL_STACK
+        /* Allocate memory for decoded certificate. */
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+            DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            ret = MEMORY_E;
+        if (ret == 0)
+    #endif
+        {
+            /* Initialize decoded certificate with buffer. */
+            InitDecodedCert(cert, der, sz, NULL);
+
+            /* Parse certificate and perform CRL checks. */
+            ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm);
+            if (ret != 0) {
+                WOLFSSL_MSG("ParseCert failed");
+            }
+            /* Do CRL checks with decoded certificate. */
+            else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) {
+                WOLFSSL_MSG("CheckCertCRL failed");
+            }
+
+            /* Dispose of dynamically allocated memory. */
+            FreeDecodedCert(cert);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+        #endif
+        }
+    }
+
+    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
+}
+
+/* Set the missing CRL callback.
+ *
+ * @param [in] cm  Certificate manager.
+ * @param [in] cb  Missing CRL callback.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ */
+int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
+
+    /* Validate parameters. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Store callback. */
+        cm->cbMissingCRL = cb;
+    }
+
+    return ret;
+}
+
+#ifdef HAVE_CRL_IO
+/* Set the CRL I/O callback.
+ *
+ * @param [in] cm  Certificate manager.
+ * @param [in] cb  CRL I/O callback.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ */
+int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    /* Validate parameters. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    if ((ret == WOLFSSL_SUCCESS) && (cm->crl != NULL)) {
+        /* Store callback. */
+        cm->crl->crlIOCb = cb;
+    }
+
+    return ret;
+}
+#endif
+
+#ifndef NO_FILESYSTEM
+/* Load CRL/s from path with the option of monitoring for changes.
+ *
+ * @param [in] cm       Certificate manager.
+ * @param [in] path     Path to a directory containing CRLs.
+ * @param [in] type     Format of encoding. Valid values:
+ *                        WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
+ * @param [in] monitor  Whether to monitor path for changes to files.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FNUC_ARG when cm or path is NULL.
+ * @return  WOLFSSL_FATAL_ERROR when enabling CRLs fails.
+ */
+int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path,
+    int type, int monitor)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRL");
+
+    /* Validate parameters. */
+    if ((cm == NULL) || (path == NULL)) {
+        ret = BAD_FUNC_ARG;
+    }
+
+    /* Create a CRL object if not available. */
+    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
+            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
+             WOLFSSL_SUCCESS)) {
+        WOLFSSL_MSG("Enable CRL failed");
+        ret = WOLFSSL_FATAL_ERROR;
+    }
+
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Load CRLs from path into CRL object of ceritifcate manager. */
+        ret = LoadCRL(cm->crl, path, type, monitor);
+    }
+
+    return ret;
+}
+
+/* Load CRL from file.
+ *
+ * @param [in] cm    Certificate manager.
+ * @param [in] file  Path to a directory containing CRLs.
+ * @param [in] type  Format of encoding. Valid values:
+ *                       WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FNUC_ARG when cm or file is NULL.
+ * @return  WOLFSSL_FATAL_ERROR when enabling CRLs fails.
+ */
+int wolfSSL_CertManagerLoadCRLFile(WOLFSSL_CERT_MANAGER* cm, const char* file,
+    int type)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLFile");
+
+    /* Validate parameters. */
+    if ((cm == NULL) || (file == NULL)) {
+        ret = BAD_FUNC_ARG;
+    }
+
+    /* Create a CRL object if not available. */
+    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
+            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
+             WOLFSSL_SUCCESS)) {
+        WOLFSSL_MSG("Enable CRL failed");
+        ret = WOLFSSL_FATAL_ERROR;
+    }
+
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Load CRL file into CRL object of ceritifcate manager. */
+        ret = ProcessFile(NULL, file, type, CRL_TYPE, NULL, 0, cm->crl, VERIFY);
+    }
+
+    return ret;
+}
+#endif /* !NO_FILESYSTEM */
+
+#endif /* HAVE_CRL */
+
+/*******************************************************************************
+ * OCSP handling
+ ******************************************************************************/
+
+/* Enables OCSP when validating certificates and sets options.
+ *
+ * @param [in] cm       Certificate manager.
+ * @param [in] options  Options for using OCSP. Valid flags:
+ *                        WOLFSSL_OCSP_URL_OVERRIDE, WOLFSSL_OCSP_NO_NONCE,
+ *                        WOLFSSL_OCSP_CHECKALL.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  0 when initializing the OCSP object fails.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ * @return  NOT_COMPILED_IN when the OCSP feature is disabled.
+ */
+int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    (void)options;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSP");
+
+    /* Validate parameters. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+
+#ifndef HAVE_OCSP
+    if (ret == WOLFSSL_SUCCESS) {
+        /* OCSP feature not enabled. */
+        ret = NOT_COMPILED_IN;
+    }
+#else
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Check wheter OCSP object is available. */
+        if (cm->ocsp == NULL) {
+            /* Allocate memory for OCSP object. */
+            cm->ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap,
+                DYNAMIC_TYPE_OCSP);
+            if (cm->ocsp == NULL) {
+                ret = MEMORY_E;
+            }
+            if (ret == WOLFSSL_SUCCESS) {
+                /* Reset the fields of the OCSP object. */
+                XMEMSET(cm->ocsp, 0, sizeof(WOLFSSL_OCSP));
+                /* Initialize the OCSP object. */
+                if (InitOCSP(cm->ocsp, cm) != 0) {
+                    WOLFSSL_MSG("Init OCSP failed");
+                    /* Dispose of OCSP object - indicating dynamicly allocated.
+                     */
+                    FreeOCSP(cm->ocsp, 1);
+                    cm->ocsp = NULL;
+                    ret = 0;
+                }
+            }
+        }
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Enable OCSP checking. */
+        cm->ocspEnabled = 1;
+        /* Enable URL override if requested. */
+        if (options & WOLFSSL_OCSP_URL_OVERRIDE) {
+            cm->ocspUseOverrideURL = 1;
+        }
+        /* Set nonce option for creating OCSP requests. */
+        cm->ocspSendNonce = (options & WOLFSSL_OCSP_NO_NONCE) != 0;
+        /* Set all OCSP checks on if requested. */
+        if (options & WOLFSSL_OCSP_CHECKALL) {
+            cm->ocspCheckAll = 1;
+        }
+    #ifndef WOLFSSL_USER_IO
+        /* Set built-in OCSP lookup. */
+        cm->ocspIOCb = EmbedOcspLookup;
+        cm->ocspRespFreeCb = EmbedOcspRespFree;
+        cm->ocspIOCtx = cm->heap;
+    #endif /* WOLFSSL_USER_IO */
+    }
+#endif /* HAVE_OCSP */
+
+    return ret;
+}
+
+/* Disables the OCSP checks.
+ *
+ * @param [in] cm  Certificate manager.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ */
+int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSP");
+
+    /* Validate parameter. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Disable use of OCSP with certificate validation. */
+        cm->ocspEnabled = 0;
+    }
+
+    return ret;
+}
+
+/* Enables OCSP stapling with certificates in manager.
+ *
+ * @param [in] cm       Certificate manager.
+ * @param [in] options  Options for using OCSP. Valid flags:
+ *                        WOLFSSL_OCSP_URL_OVERRIDE, WOLFSSL_OCSP_NO_NONCE,
+ *                        WOLFSSL_OCSP_CHECKALL.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  0 when initializing the OCSP stapling object fails.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ * @return  NOT_COMPILED_IN when the OCSP stapling feature is disabled.
+ */
+int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling");
+
+    /* Validate parameters. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+
+#if !defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
+    !defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    if (ret == WOLFSSL_SUCCESS) {
+        /* OCSP stapling feature not enabled. */
+        ret = NOT_COMPILED_IN;
+    }
+#else
+#ifndef NO_WOLFSSL_SERVER
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Check wheter OCSP object is available. */
+        if (cm->ocsp_stapling == NULL) {
+            /* Allocate memory for OCSP stapling object. */
+            cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP),
+                cm->heap, DYNAMIC_TYPE_OCSP);
+            if (cm->ocsp_stapling == NULL) {
+                ret = MEMORY_E;
+            }
+            if (ret == WOLFSSL_SUCCESS) {
+                /* Reset the fields of the OCSP object. */
+                XMEMSET(cm->ocsp_stapling, 0, sizeof(WOLFSSL_OCSP));
+                /* Initialize the OCSP stapling object. */
+                if (InitOCSP(cm->ocsp_stapling, cm) != 0) {
+                    WOLFSSL_MSG("Init OCSP failed");
+                    /* Dispose of OCSP stapling object - indicating dynamicly
+                     * allocated. */
+                    FreeOCSP(cm->ocsp_stapling, 1);
+                    cm->ocsp_stapling = NULL;
+                    ret = 0;
+                }
+            }
+        }
+    }
+#ifndef WOLFSSL_USER_IO
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Set built-in OCSP lookup. */
+        cm->ocspIOCb = EmbedOcspLookup;
+        cm->ocspRespFreeCb = EmbedOcspRespFree;
+        cm->ocspIOCtx = cm->heap;
+    }
+#endif /* WOLFSSL_USER_IO */
+#endif /* NO_WOLFSSL_SERVER */
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Enable OCSP stapling. */
+        cm->ocspStaplingEnabled = 1;
+    }
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST ||
+        * HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
+    return ret;
+}
+
+/* Disables OCSP Stapling.
+ *
+ * @param [in] cm  Certificate manager.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ */
+int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling");
+
+    /* Validate parameter. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+        defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+        /* Disable use of OCSP Stapling. */
+        cm->ocspStaplingEnabled = 0;
+    #else
+        /* OCSP stapling feature not enabled. */
+        ret = NOT_COMPILED_IN;
+    #endif
+    }
+
+    return ret;
+}
+
+/* Enable the must use OCSP Stapling option.
+ *
+ * @param [in] cm  Certificate manager.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ */
+int wolfSSL_CertManagerEnableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPMustStaple");
+
+    /* Validate parameter. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+    defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    #ifndef NO_WOLFSSL_CLIENT
+        /* Enable must use OCSP Stapling option. */
+        cm->ocspMustStaple = 1;
+    #endif
+#else
+        /* OCSP stapling feature not enabled. */
+        ret = NOT_COMPILED_IN;
+#endif
+    }
+
+    return ret;
+}
+
+/* Disable the must use OCSP Stapling option.
+ *
+ * @param [in] cm  Certificate manager.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ */
+int wolfSSL_CertManagerDisableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPMustStaple");
+
+    /* Validate parameter. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == WOLFSSL_SUCCESS) {
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+    defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    #ifndef NO_WOLFSSL_CLIENT
+        /* Disable must use OCSP Stapling option. */
+        cm->ocspMustStaple = 0;
+    #endif
+#else
+        /* OCSP stapling feature not enabled. */
+        ret = NOT_COMPILED_IN;
+#endif
+    }
+
+    return ret;
+}
+
+#ifdef HAVE_OCSP
+/* Check DER encoded certificate against with OCSP if checking enabled.
+ *
+ * @param [in] cm   Certificate manager.
+ * @param [in] der  DER encode certificate.
+ * @param [in] sz   Size in bytes of DER encode certificate.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm or der is NULL or sz is negative or 0.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ */
+int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm,
+    const unsigned char* der, int sz)
+{
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP");
+
+    /* Validate parameters. */
+    if ((cm == NULL) || (der == NULL) || (sz <= 0)) {
+        ret = BAD_FUNC_ARG;
+    }
+
+    /* Check if OCSP checking enabled. */
+    if ((ret == 0) && cm->ocspEnabled) {
+    #ifdef WOLFSSL_SMALL_STACK
+        /* Allocate memory for decoded certificate. */
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
+            DYNAMIC_TYPE_DCERT);
+        if (cert == NULL) {
+            ret = MEMORY_E;
+        }
+        if (ret == 0)
+    #endif
+        {
+            /* Initialize decoded certificate with buffer. */
+            InitDecodedCert(cert, der, sz, NULL);
+
+            /* Parse certificate and perform CRL checks. */
+            ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm);
+            if (ret != 0) {
+                WOLFSSL_MSG("ParseCert failed");
+            }
+            /* Do OCSP checks with decoded certificate. */
+            else if ((ret = CheckCertOCSP(cm->ocsp, cert)) != 0) {
+                WOLFSSL_MSG("CheckCertOCSP failed");
+            }
+
+            /* Dispose of dynamically allocated memory. */
+            FreeDecodedCert(cert);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+        #endif
+        }
+    }
+
+    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
+}
+
+/* Check OCSP response.
+ *
+ * @param [in] cm              Certificate manager.
+ * @param [in] response        Buffer holding OCSP response.
+ * @param [in] responseSz      Size in bytes of OCSP response.
+ * @param [in] responseBuffer  Buffer to copy response into.
+ * @param [in] status          Place to store certificate status.
+ * @param [in] entry           Place to store OCSP entry.
+ * @param [in] ocspRequest     OCSP request to match with response.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm or response is NULL.
+ */
+int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm,
+    byte *response, int responseSz, buffer *responseBuffer,
+    CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSPResponse");
+
+    /* Validate parameters. */
+    if ((cm == NULL) || (response == NULL)) {
+        ret = BAD_FUNC_ARG;
+    }
+    if ((ret == 0) && cm->ocspEnabled) {
+        /* Check OCSP response with OCSP object from certificate manager. */
+        ret = CheckOcspResponse(cm->ocsp, response, responseSz, responseBuffer,
+            status, entry, ocspRequest, NULL);
+    }
+
+    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
+}
+
+/* Set the OCSP override URL.
+ *
+ * @param [in] cm   Certificate manager.
+ * @param [in] url  URL to get an OCSP response from.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ */
+int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
+    const char* url)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL");
+
+    /* Validate parameters. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Dispose of old URL. */
+        XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
+        if (url != NULL) {
+            /* Calculate size of URL string. Include terminator character. */
+            int urlSz = (int)XSTRLEN(url) + 1;
+            /* Allocate memory for URL to be copied into. */
+            cm->ocspOverrideURL = (char*)XMALLOC(urlSz, cm->heap,
+                DYNAMIC_TYPE_URL);
+            if (cm->ocspOverrideURL == NULL) {
+                ret = MEMORY_E;
+            }
+            if (ret == WOLFSSL_SUCCESS) {
+                /* Copy URL into certificate manager. */
+                XMEMCPY(cm->ocspOverrideURL, url, urlSz);
+            }
+        }
+        else {
+            /* No URL to set so make it NULL. */
+            cm->ocspOverrideURL = NULL;
+        }
+    }
+
+    return ret;
+}
+
+/* Set the OCSP I/O callback, OCSP response free callback and related data.
+ *
+ * @param [in] cm          Certificate manager.
+ * @param [in] ioCb        OCSP callback.
+ * @param [in] respFreeCb  Callback to free OCSP response buffer.
+ * @param [in] ioCbCtx     Context daa to pass to OCSP callbacks.
+ * @return  WOLFSSL_SUCCESS on success.
+ * @return  BAD_FUNC_ARG when cm is NULL.
+ */
+int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm, CbOCSPIO ioCb,
+    CbOCSPRespFree respFreeCb, void* ioCbCtx)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSP_Cb");
+
+    /* Validate parameters. */
+    if (cm == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Set callbacks and data into certificate manager. */
+        cm->ocspIOCb = ioCb;
+        cm->ocspRespFreeCb = respFreeCb;
+        cm->ocspIOCtx = ioCbCtx;
+    }
+
+    return ret;
+}
+
+#endif /* HAVE_OCSP */
+
+#endif /* NO_CERTS */
+
+#endif /* !WOLFSSL_SSL_CERTMAN_INCLUDED */

+ 10 - 3
src/ssl_misc.c

@@ -203,8 +203,12 @@ static int wolfssl_read_bio(WOLFSSL_BIO* bio, char** data, int* dataSz,
     return ret;
 }
 #endif /* !NO_BIO */
+#endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY */
 
-#if !defined(NO_FILESYSTEM)
+#if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE) || \
+     (!defined(NO_CERTS) && (!defined(NO_WOLFSSL_CLIENT) || \
+      !defined(WOLFSSL_NO_CLIENT_AUTH)))) && !defined(WOLFCRYPT_ONLY) && \
+    !defined(NO_FILESYSTEM)
 /* Read all the data from a file.
  *
  * @param [in]  fp          File pointer to read with.
@@ -253,7 +257,10 @@ static int wolfssl_file_len(XFILE fp, long* fileSz)
 
     return ret;
 }
+#endif
 
+#if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE)) && \
+    !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
 /* Read all the data from a file.
  *
  * @param [in]  fp          File pointer to read with.
@@ -290,7 +297,7 @@ static int wolfssl_read_file(XFILE fp, char** data, int* dataSz)
     XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
     return ret;
 }
-#endif /* !NO_FILESYSTEM */
-#endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY */
+#endif /* (OPENSSL_EXTRA || PERSIST_CERT_CACHE) && !WOLFCRYPT_ONLY &&
+        * !NO_FILESYSTEM */
 #endif /* !WOLFSSL_SSL_MISC_INCLUDED */
 

+ 3 - 1
src/x509.c

@@ -9477,7 +9477,9 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref(
     {
         WOLFSSL_ENTER("wolfSSL_X509_NAME_free");
         FreeX509Name(name);
-        XFREE(name, name->heap, DYNAMIC_TYPE_X509);
+        if (name != NULL) {
+            XFREE(name, name->heap, DYNAMIC_TYPE_X509);
+        }
     }
 
 

File diff suppressed because it is too large
+ 812 - 362
tests/api.c


+ 1 - 1
wolfcrypt/src/asn.c

@@ -21584,7 +21584,7 @@ static int GetAKIHash(const byte* input, word32 maxIdx, int sigOID,
                     ret = GetHashId(
                             dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.data,
                             dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.length,
-                            hash, sigOID);
+                            hash, HashIdAlg(sigOID));
                 }
                 break;
             }

+ 1 - 1
wolfssl/internal.h

@@ -2603,7 +2603,7 @@ WOLFSSL_LOCAL int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm,
                                          const void* mem, int sz);
 WOLFSSL_LOCAL int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm);
 WOLFSSL_LOCAL int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
-                                    long sz, int format, int err_val);
+                                     long sz, int format, int prev_err);
 
 
 #ifndef NO_CERTS

+ 34 - 31
wolfssl/ssl.h

@@ -3548,70 +3548,73 @@ WOLFSSL_API void wolfSSL_CTX_SetPerformTlsRecordProcessingCb(WOLFSSL_CTX* ctx,
     WOLFSSL_API void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm);
     WOLFSSL_API int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm);
 
-    WOLFSSL_API int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* f,
-                                                                 const char* d);
+    WOLFSSL_API int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm,
+        const char* f, const char* d);
     WOLFSSL_API int wolfSSL_CertManagerLoadCABuffer_ex(WOLFSSL_CERT_MANAGER* cm,
-            const unsigned char* in, long sz, int format, int userChain,
-            word32 flags);
+        const unsigned char* buff, long sz, int format, int userChain,
+        word32 flags);
     WOLFSSL_API int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm,
-            const unsigned char* in, long sz, int format);
+        const unsigned char* buff, long sz, int format);
 
     WOLFSSL_API int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm);
 #ifdef WOLFSSL_TRUST_PEER_CERT
-    WOLFSSL_API int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm);
+    WOLFSSL_API int wolfSSL_CertManagerUnload_trust_peers(
+        WOLFSSL_CERT_MANAGER* cm);
 #endif
-    WOLFSSL_API int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* f,
-                                                                    int format);
+    WOLFSSL_API int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm,
+        const char* f, int format);
     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);
     WOLFSSL_API int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm,
-                                                        unsigned char* der, int sz);
+        const unsigned char* der, int sz);
     WOLFSSL_API int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm,
-                                                                   int options);
+        int options);
     WOLFSSL_API int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm);
     WOLFSSL_API void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm,
-            VerifyCallback vc);
+        VerifyCallback vc);
     WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm,
-                                                         const char* path, int type, int monitor);
+        const char* path, int type, int monitor);
     WOLFSSL_API int wolfSSL_CertManagerLoadCRLFile(WOLFSSL_CERT_MANAGER* cm,
-                                                         const char* file, int type);
+        const char* file, int type);
     WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
-                                            const unsigned char* buff, long sz, int type);
+        const unsigned char* buff, long sz, int type);
     WOLFSSL_API int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm,
-                                                                  CbMissingCRL cb);
+        CbMissingCRL cb);
     WOLFSSL_API int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER* cm);
 #ifdef HAVE_CRL_IO
     WOLFSSL_API int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm,
-                                                                       CbCrlIO cb);
+        CbCrlIO cb);
 #endif
 #if defined(HAVE_OCSP)
-    WOLFSSL_API int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER* cm,
-        byte *response, int responseSz, WOLFSSL_BUFFER_INFO *responseBuffer,
-        CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest);
+    WOLFSSL_API int wolfSSL_CertManagerCheckOCSPResponse(
+        WOLFSSL_CERT_MANAGER* cm, unsigned char *response, int responseSz,
+        WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status,
+        OcspEntry *entry, OcspRequest *ocspRequest);
 #endif
     WOLFSSL_API int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm,
-                                                        unsigned char* der, int sz);
+        const unsigned char* der, int sz);
     WOLFSSL_API int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm,
-                                                                   int options);
+        int options);
     WOLFSSL_API int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm);
-    WOLFSSL_API int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
-                                                                   const char* url);
+    WOLFSSL_API int wolfSSL_CertManagerSetOCSPOverrideURL(
+        WOLFSSL_CERT_MANAGER* cm, const char* url);
     WOLFSSL_API int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm,
-                                               CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx);
+        CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx);
 
     WOLFSSL_API int wolfSSL_CertManagerEnableOCSPStapling(
-                                                      WOLFSSL_CERT_MANAGER* cm);
+        WOLFSSL_CERT_MANAGER* cm);
     WOLFSSL_API int wolfSSL_CertManagerDisableOCSPStapling(
-                                                      WOLFSSL_CERT_MANAGER* cm);
+        WOLFSSL_CERT_MANAGER* cm);
     WOLFSSL_API int wolfSSL_CertManagerEnableOCSPMustStaple(
-                                                      WOLFSSL_CERT_MANAGER* cm);
+        WOLFSSL_CERT_MANAGER* cm);
     WOLFSSL_API int wolfSSL_CertManagerDisableOCSPMustStaple(
-                                                      WOLFSSL_CERT_MANAGER* cm);
+        WOLFSSL_CERT_MANAGER* cm);
 #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SIGNER_DER_CERT) && \
     !defined(NO_FILESYSTEM)
-WOLFSSL_API WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm);
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(
+    WOLFSSL_CERT_MANAGER* cm);
 WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(
-                               WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_NAME* name);
+    WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_NAME* name);
 #endif /* OPENSSL_EXTRA && WOLFSSL_SIGNER_DER_CERT && !NO_FILESYSTEM */
     WOLFSSL_API int wolfSSL_EnableCRL(WOLFSSL* ssl, int options);
     WOLFSSL_API int wolfSSL_DisableCRL(WOLFSSL* ssl);

Some files were not shown because too many files changed in this diff