Browse Source

Fixes and improvements for crypto callbacks with TLS (mutual auth) (#4437)

* This PR resolves issues with using TLS client authentication (mutual auth) with crypto callbacks. The TLS client auth will not be sent without a private key being set. The solution is to allow setting a public key only if crypto callbacks is enabled and a devId is set.

* Fix to allow using crypto callbacks with TLS mutual authentication where a private key is not available.
* Fix for ED25519 sign when only a private key is loaded.
* Fix to enable crypto callbacks for ED25519 and Curve25519 in TLS by using the _ex init functions.
* Fix for wc_PemToDer return code where a PKCS8 header does not exist.
* Remove duplicate logs in DoCertificateVerify.
* Doxygen API updates: Added crypto callback help and updated use_PrivateKey with info about public key use.

* * Added crypto callback tests for TLS client and server with mutual auth for RSA, ECC and ED25519.
* Enhanced the API unit test TLS code to allow setting CA, cert and key.

* Revert ED25519 changes. Opt to calculate public key directly when required for signing in the TLS crypto callback test. Build configuration fixes.

* Fix to use proper devId in `ProcessBufferTryDecode`.

* Various build fixes due to changes in PR. G++ issue with `missing-field-initializers`. Unused api.c func with DTLS and session export. Duplicate `eccKeyPubFile` def.

* Added crypto callback TLS tests at WOLFSSL object level. Fix for ED25519/ED448 with client mutual auth where the private key is not set till WOLFSSL object. Fix issues with  `wolfSSL_CTX_GetDevId` where devId is set on WOLFSSL object. Enable the `_id` API's for crypto callbacks.

* Proper fix for `eccKeyPubFile` name conflict. Was causing RSA test to fail (expected DER, not PEM).
David Garske 2 years ago
parent
commit
9d2082f7e1

+ 9 - 0
certs/client-keyPub.pem

@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwwPRK/45pDJFO1PIhCsq
+fHSavaoqUgdH1qY2sgcyjtC6aXvGw0Se1IFI/S1oootnu6F1yDYsStIb94u6zw35
+7+zxgR57mwNHmr9lzH9lJGmm6BSJW+Q098WwFJP1Z3s6enjhAVZWkaYTQo3SPECc
+TO/Rht83URsMoTv18aNKNeThzpbfG36/TpfQEOioCDCBryALQxTFdGe0MoJvjYbC
+iECZNoO6HkByIhfXUmUkc7DO7xnNrv94bHvAEgPUTnINUG07ozujmV6dyNkMhbPZ
+itlUJttt+qy7/yVMxNF59HHThkAYE7BjtXJOMMSXhIYtVi/XFfd/wK71/Fvl+6G6
+0wIDAQAB
+-----END PUBLIC KEY-----

+ 4 - 0
certs/ecc-keyPub.pem

@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U
+6iv6yyAJOSwW6GEC6a9N0wKTmjFbl5Ihf/DPGNqREQI0huggWDMLgDSJ2A==
+-----END PUBLIC KEY-----

+ 3 - 1
certs/include.am

@@ -14,6 +14,7 @@ EXTRA_DIST += \
 	     certs/client-crl-dist.pem \
 	     certs/client-crl-dist.der \
 	     certs/ecc-key.pem \
+		 certs/ecc-keyPub.pem \
 	     certs/ecc-privkey.pem \
 	     certs/ecc-privkeyPkcs8.der \
 	     certs/ecc-privkeyPkcs8.pem \
@@ -34,13 +35,13 @@ EXTRA_DIST += \
 	     certs/server-ecc-rsa.pem \
 	     certs/server-keyEnc.pem \
 	     certs/server-key.pem \
+		 certs/server-keyPub.pem \
 	     certs/server-keyPkcs8.der \
 	     certs/server-keyPkcs8Enc12.pem \
 	     certs/server-keyPkcs8Enc2.pem \
 	     certs/server-keyPkcs8Enc.pem \
 	     certs/server-keyPkcs8Enc.der \
 	     certs/server-keyPkcs8.pem \
-	     certs/server-pub-key.pem \
 	     certs/server-revoked-cert.pem \
 	     certs/server-revoked-key.pem \
 	     certs/wolfssl-website-ca.pem \
@@ -71,6 +72,7 @@ EXTRA_DIST += \
 	     certs/client-key.der \
 	     certs/client-ecc-cert.der \
 	     certs/client-keyPub.der \
+	     certs/client-keyPub.pem \
 	     certs/dh2048.der \
 	     certs/dh3072.der \
 	     certs/dh4096.der \

+ 19 - 0
certs/renewcerts.sh

@@ -86,6 +86,25 @@ run_renewcerts(){
     mv tmp.pem client-uri-cert.pem
     echo "End of section"
     echo "---------------------------------------------------------------------"
+
+    ############################################################
+    # Public Versions of client-key.pem
+    ############################################################
+    openssl rsa -inform pem -in certs/client-key.pem -outform der -out certs/client-keyPub.der -pubout
+    openssl rsa -inform pem -in certs/client-key.pem -outform pem -out certs/client-keyPub.pem -pubout
+
+    ############################################################
+    # Public Versions of server-key.pem
+    ############################################################
+    #openssl rsa -inform pem -in certs/server-key.pem -outform der -out certs/server-keyPub.der -pubout
+    openssl rsa -inform pem -in certs/server-key.pem -outform pem -out certs/server-keyPub.pem -pubout
+
+    ############################################################
+    # Public Versions of ecc-key.pem
+    ############################################################
+    #openssl ec -inform pem -in certs/ecc-key.pem -outform der -out certs/ecc-keyPub.der -pubout
+    openssl ec -inform pem -in certs/ecc-key.pem -outform pem -out certs/ecc-keyPub.pem -pubout
+
     ############################################################
     #### update the self-signed (2048-bit) client-relative-uri.pem
     ############################################################

+ 0 - 0
certs/server-pub-key.pem → certs/server-keyPub.pem


+ 111 - 0
doc/dox_comments/header_files/cryptocb.h

@@ -0,0 +1,111 @@
+/*!
+    \ingroup CryptoCb
+
+    \brief This function registers a unique device identifier (devID) and 
+    callback function for offloading crypto operations to external 
+    hardware such as Key Store, Secure Element, HSM, PKCS11 or TPM.
+
+    For STSAFE with Crypto Callbacks example see
+    wolfcrypt/src/port/st/stsafe.c and the wolfSSL_STSAFE_CryptoDevCb function.
+
+    For TPM based crypto callbacks example see the wolfTPM2_CryptoDevCb 
+    function in wolfTPM src/tpm2_wrap.c
+
+    \return CRYPTOCB_UNAVAILABLE to fallback to using software crypto
+    \return 0 for success
+    \return negative value for failure
+
+    \param devId any unique value, not -2 (INVALID_DEVID)
+    \param cb a callback function with prototype:
+    typedef int (*CryptoDevCallbackFunc)(int devId, wc_CryptoInfo* info, void* ctx);
+
+    _Example_
+    \code
+    #include <wolfssl/wolfcrypt/settings.h>
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+    static int myCryptoCb_Func(int devId, wc_CryptoInfo* info, void* ctx)
+    {
+        int ret = CRYPTOCB_UNAVAILABLE;
+
+        if (info->algo_type == WC_ALGO_TYPE_PK) {
+        #ifndef NO_RSA
+            if (info->pk.type == WC_PK_TYPE_RSA) {
+                switch (info->pk.rsa.type) {
+                    case RSA_PUBLIC_ENCRYPT:
+                    case RSA_PUBLIC_DECRYPT:
+                        // RSA public op
+                        ret = wc_RsaFunction(
+                            info->pk.rsa.in, info->pk.rsa.inLen,
+                            info->pk.rsa.out, info->pk.rsa.outLen,
+                            info->pk.rsa.type, info->pk.rsa.key,
+                            info->pk.rsa.rng);
+                        break;
+                    case RSA_PRIVATE_ENCRYPT:
+                    case RSA_PRIVATE_DECRYPT:
+                        // RSA private op
+                        ret = wc_RsaFunction(
+                            info->pk.rsa.in, info->pk.rsa.inLen,
+                            info->pk.rsa.out, info->pk.rsa.outLen,
+                            info->pk.rsa.type, info->pk.rsa.key,
+                            info->pk.rsa.rng);
+                        break;
+                }
+            }
+        #endif
+        #ifdef HAVE_ECC
+            if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) {
+                // ECDSA
+                ret = wc_ecc_sign_hash(
+                    info->pk.eccsign.in, info->pk.eccsign.inlen,
+                    info->pk.eccsign.out, info->pk.eccsign.outlen,
+                    info->pk.eccsign.rng, info->pk.eccsign.key);
+            }
+        #endif
+        #ifdef HAVE_ED25519
+            if (info->pk.type == WC_PK_TYPE_ED25519_SIGN) {
+                // ED25519 sign
+                ret = wc_ed25519_sign_msg_ex(
+                    info->pk.ed25519sign.in, info->pk.ed25519sign.inLen,
+                    info->pk.ed25519sign.out, info->pk.ed25519sign.outLen,
+                    info->pk.ed25519sign.key, info->pk.ed25519sign.type,
+                    info->pk.ed25519sign.context,
+                    info->pk.ed25519sign.contextLen);
+            }
+        #endif
+        }
+        return ret;
+    }
+
+    int devId = 1;
+    wc_CryptoCb_RegisterDevice(devId, myCryptoCb_Func, &myCtx);
+    wolfSSL_CTX_SetDevId(ctx, devId);
+    \endcode
+
+    \sa wc_CryptoCb_UnRegisterDevice
+    \sa wolfSSL_SetDevId
+    \sa wolfSSL_CTX_SetDevId
+*/
+WOLFSSL_API int  wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx);
+
+/*!
+    \ingroup CryptoCb
+
+    \brief This function un-registers a unique device identifier (devID) 
+    callback function.
+
+    \return none No returns.
+
+    \param devId any unique value, not -2 (INVALID_DEVID)
+
+    _Example_
+    \code
+    wc_CryptoCb_UnRegisterDevice(devId);
+    devId = INVALID_DEVID;
+    wolfSSL_CTX_SetDevId(ctx, devId);
+    \endcode
+
+    \sa wc_CryptoCb_RegisterDevice
+    \sa wolfSSL_SetDevId
+    \sa wolfSSL_CTX_SetDevId
+*/
+WOLFSSL_API void wc_CryptoCb_UnRegisterDevice(int devId);

+ 1 - 0
doc/dox_comments/header_files/doxygen_groups.h

@@ -6,6 +6,7 @@
     \defgroup Camellia Algorithms - Camellia
     \defgroup ChaCha Algorithms - ChaCha
     \defgroup ChaCha20Poly1305 Algorithms - ChaCha20_Poly1305
+    \defgroup Crypto Callbacks - CryptoCb
     \defgroup Curve25519 Algorithms - Curve25519
     \defgroup Curve448 Algorithms - Curve448
     \defgroup DSA Algorithms - DSA

+ 1 - 0
doc/dox_comments/header_files/doxygen_pages.h

@@ -33,6 +33,7 @@
         <li>\ref Camellia</li>
         <li>\ref ChaCha</li>
         <li>\ref ChaCha20Poly1305</li>
+        <li>\ref Crypto Callbacks</li>
         <li>\ref Curve25519</li>
         <li>\ref Curve448</li>
         <li>\ref DSA</li>

+ 18 - 0
doc/dox_comments/header_files/ssl.h

@@ -906,6 +906,13 @@ WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int)
     argument specifies the format type of the file - SSL_FILETYPE_ASN1or
     SSL_FILETYPE_PEM.  Please see the examples for proper usage.
 
+    If using an external key store and do not have the private key you can 
+    instead provide the public key and register the crypro callback to handle 
+    the signing. For this you can build with --enable-cryptocb or
+    WOLF_CRYPTO_CB and register a crypto callback using 
+    wc_CryptoCb_RegisterDevice and set the associated devId using 
+    wolfSSL_CTX_SetDevId.
+
     \return SSL_SUCCESS upon success.
     \return SSL_FAILURE The file is in the wrong format, or the wrong format
     has been given using the “format” argument. The file doesn’t exist, can’t
@@ -931,6 +938,8 @@ WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int)
     \sa wolfSSL_CTX_use_PrivateKey_buffer
     \sa wolfSSL_use_PrivateKey_file
     \sa wolfSSL_use_PrivateKey_buffer
+    \sa wc_CryptoCb_RegisterDevice
+    \sa wolfSSL_CTX_SetDevId
 */
 WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int);
 
@@ -1311,6 +1320,13 @@ WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*, int);
     The format argument specifies the format type of the file -
     SSL_FILETYPE_ASN1 or SSL_FILETYPE_PEM.
 
+    If using an external key store and do not have the private key you can 
+    instead provide the public key and register the crypro callback to handle 
+    the signing. For this you can build with --enable-cryptocb or
+    WOLF_CRYPTO_CB and register a crypto callback using 
+    wc_CryptoCb_RegisterDevice and set the associated devId using 
+    wolfSSL_SetDevId.
+
     \return SSL_SUCCESS upon success.
     \return SSL_FAILURE If the function call fails, possible causes might
     include: The file is in the wrong format, or the wrong format has been
@@ -1340,6 +1356,8 @@ WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*, int);
     \sa wolfSSL_CTX_use_PrivateKey_buffer
     \sa wolfSSL_CTX_use_PrivateKey_file
     \sa wolfSSL_use_PrivateKey_buffer
+    \sa wc_CryptoCb_RegisterDevice
+    \sa wolfSSL_SetDevId
 */
 WOLFSSL_API int wolfSSL_use_PrivateKey_file(WOLFSSL*, const char*, int);
 

+ 38 - 7
src/internal.c

@@ -6705,19 +6705,19 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
     #endif /* HAVE_ECC */
     #ifdef HAVE_ED25519
         case DYNAMIC_TYPE_ED25519:
-            wc_ed25519_init((ed25519_key*)*pKey);
+            wc_ed25519_init_ex((ed25519_key*)*pKey, ssl->heap, ssl->devId);
             ret = 0;
             break;
     #endif /* HAVE_CURVE25519 */
     #ifdef HAVE_CURVE25519
         case DYNAMIC_TYPE_CURVE25519:
-            wc_curve25519_init((curve25519_key*)*pKey);
+            wc_curve25519_init_ex((curve25519_key*)*pKey, ssl->heap, ssl->devId);
             ret = 0;
             break;
     #endif /* HAVE_CURVE25519 */
     #ifdef HAVE_ED448
         case DYNAMIC_TYPE_ED448:
-            wc_ed448_init((ed448_key*)*pKey);
+            wc_ed448_init_ex((ed448_key*)*pKey, ssl->heap, ssl->devId);
             ret = 0;
             break;
     #endif /* HAVE_CURVE448 */
@@ -6768,19 +6768,21 @@ static int ReuseKey(WOLFSSL* ssl, int type, void* pKey)
     #ifdef HAVE_ED25519
         case DYNAMIC_TYPE_ED25519:
             wc_ed25519_free((ed25519_key*)pKey);
-            ret = wc_ed25519_init((ed25519_key*)pKey);
+            ret = wc_ed25519_init_ex((ed25519_key*)pKey, ssl->heap,
+                ssl->devId);
             break;
     #endif /* HAVE_CURVE25519 */
     #ifdef HAVE_CURVE25519
         case DYNAMIC_TYPE_CURVE25519:
             wc_curve25519_free((curve25519_key*)pKey);
-            ret = wc_curve25519_init((curve25519_key*)pKey);
+            ret = wc_curve25519_init_ex((curve25519_key*)pKey, ssl->heap,
+                ssl->devId);
             break;
     #endif /* HAVE_CURVE25519 */
     #ifdef HAVE_ED448
         case DYNAMIC_TYPE_ED448:
             wc_ed448_free((ed448_key*)pKey);
-            ret = wc_ed448_init((ed448_key*)pKey);
+            ret = wc_ed448_init_ex((ed448_key*)pKey, ssl->heap, ssl->devId);
             break;
     #endif /* HAVE_CURVE448 */
     #ifdef HAVE_CURVE448
@@ -22073,6 +22075,15 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
         /* Decode the key assuming it is an RSA private key. */
         ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
                     (RsaKey*)ssl->hsKey, ssl->buffers.key->length);
+    #ifdef WOLF_CRYPTO_CB
+        /* if using crypto callbacks allow using a public key */
+        if (ret != 0 && ssl->devId != INVALID_DEVID) {
+            WOLFSSL_MSG("Trying RSA public key with crypto callbacks");
+            idx = 0;
+            ret = wc_RsaPublicKeyDecode(ssl->buffers.key->buffer, &idx,
+                        (RsaKey*)ssl->hsKey, ssl->buffers.key->length);
+        }
+    #endif
         if (ret == 0) {
             WOLFSSL_MSG("Using RSA private key");
 
@@ -22119,6 +22130,16 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
         ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
                                      (ecc_key*)ssl->hsKey,
                                      ssl->buffers.key->length);
+    #ifdef WOLF_CRYPTO_CB
+        /* if using crypto callbacks allow using a public key */
+        if (ret != 0 && ssl->devId != INVALID_DEVID) {
+            WOLFSSL_MSG("Trying ECC public key with crypto callbacks");
+            idx = 0;
+            ret = wc_EccPublicKeyDecode(ssl->buffers.key->buffer, &idx,
+                                     (ecc_key*)ssl->hsKey,
+                                     ssl->buffers.key->length);
+        }
+    #endif
         if (ret == 0) {
             WOLFSSL_MSG("Using ECC private key");
 
@@ -22162,6 +22183,16 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
         ret = wc_Ed25519PrivateKeyDecode(ssl->buffers.key->buffer, &idx,
                                          (ed25519_key*)ssl->hsKey,
                                          ssl->buffers.key->length);
+    #ifdef WOLF_CRYPTO_CB
+        /* if using crypto callbacks allow using a public key */
+        if (ret != 0 && ssl->devId != INVALID_DEVID) {
+            WOLFSSL_MSG("Trying ED25519 public key with crypto callbacks");
+            idx = 0;
+            ret = wc_Ed25519PublicKeyDecode(ssl->buffers.key->buffer, &idx,
+                                         (ed25519_key*)ssl->hsKey,
+                                         ssl->buffers.key->length);
+        }
+    #endif
         if (ret == 0) {
             WOLFSSL_MSG("Using ED25519 private key");
 
@@ -22197,7 +22228,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
         #elif !defined(NO_RSA)
             WOLFSSL_MSG("Trying ED448 private key, RSA didn't work");
         #else
-            WOLFSSL_MSG("Trying ED447 private key");
+            WOLFSSL_MSG("Trying ED448 private key");
         #endif
 
         /* Set start of data to beginning of buffer. */

+ 55 - 16
src/ssl.c

@@ -2325,10 +2325,10 @@ WOLFSSL_ABI
 int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
 {
     int devId = INVALID_DEVID;
-    if (ctx != NULL)
-        devId = ctx->devId;
-    else if (ssl != NULL)
+    if (ssl != NULL)
         devId = ssl->devId;
+    if (ctx != NULL && devId == INVALID_DEVID)
+        devId = ctx->devId;
     return devId;
 }
 void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
@@ -5354,13 +5354,22 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
         ret = wc_InitRsaKey_ex(key, heap, devId);
         if (ret == 0) {
             *idx = 0;
-            if (wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length)
-                != 0) {
+            ret = wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length);
+        #ifdef WOLF_CRYPTO_CB
+            if (ret != 0 && devId != INVALID_DEVID) {
+                /* if using crypto callbacks, try public key decode */
+                *idx = 0;
+                ret = wc_RsaPublicKeyDecode(der->buffer, idx, key, der->length);
+            }
+        #endif
+            if (ret != 0) {
             #if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \
                                                             !defined(HAVE_ED448)
                 WOLFSSL_MSG("RSA decode failed and ECC/ED25519/ED448 not "
                             "enabled to try");
                 ret = WOLFSSL_BAD_FILE;
+            #else
+                ret = 0; /* continue trying other algorithms */
             #endif
             }
             else {
@@ -5415,8 +5424,15 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
 
         if (wc_ecc_init_ex(key, heap, devId) == 0) {
             *idx = 0;
-            if (wc_EccPrivateKeyDecode(der->buffer, idx, key,
-                                                        der->length) == 0) {
+            ret = wc_EccPrivateKeyDecode(der->buffer, idx, key, der->length);
+        #ifdef WOLF_CRYPTO_CB
+            if (ret != 0 && devId != INVALID_DEVID) {
+                /* if using crypto callbacks, try public key decode */
+                *idx = 0;
+                ret = wc_EccPublicKeyDecode(der->buffer, idx, key, der->length);
+            }
+        #endif
+            if (ret == 0) {
                 /* check for minimum ECC key size and then free */
                 int minKeySz = ssl ? ssl->options.minEccKeySz :
                                                         ctx->minEccKeySz;
@@ -5442,6 +5458,9 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
                     *resetSuites = 1;
                 }
             }
+            else {
+                ret = 0; /* continue trying other algorithms */
+            }
 
             wc_ecc_free(key);
         }
@@ -5467,11 +5486,18 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
             return MEMORY_E;
     #endif
 
-        ret = wc_ed25519_init(key);
+        ret = wc_ed25519_init_ex(key, heap, devId);
         if (ret == 0) {
             *idx = 0;
-            if (wc_Ed25519PrivateKeyDecode(der->buffer, idx, key,
-                                                        der->length) == 0) {
+            ret = wc_Ed25519PrivateKeyDecode(der->buffer, idx, key, der->length);
+        #ifdef WOLF_CRYPTO_CB
+            if (ret != 0 && devId != INVALID_DEVID) {
+                /* if using crypto callbacks, try public key decode */
+                *idx = 0;
+                ret = wc_Ed25519PublicKeyDecode(der->buffer, idx, key, der->length);
+            }
+        #endif
+            if (ret == 0) {
                 /* check for minimum key size and then free */
                 int minKeySz = ssl ? ssl->options.minEccKeySz :
                                                            ctx->minEccKeySz;
@@ -5491,11 +5517,19 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
                     }
 
                     *keyFormat = ED25519k;
-                    if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
-                        *resetSuites = 1;
+                    if (ssl != NULL) {
+                        /* ED25519 requires caching enabled for tracking message 
+                         * hash used in EdDSA_Update for signing */
+                        ssl->options.cacheMessages = 1;
+                        if (ssl->options.side == WOLFSSL_SERVER_END) {
+                            *resetSuites = 1;
+                        }
                     }
                 }
             }
+            else {
+                ret = 0; /* continue trying other algorithms */
+            }
 
             wc_ed25519_free(key);
         }
@@ -5549,8 +5583,13 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
                 }
 
                 *keyFormat = ED448k;
-                if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
-                    *resetSuites = 1;
+                if (ssl != NULL) {
+                    /* ED448 requires caching enabled for tracking message 
+                     * hash used in EdDSA_Update for signing */
+                    ssl->options.cacheMessages = 1;
+                    if (ssl->options.side == WOLFSSL_SERVER_END) {
+                        *resetSuites = 1;
+                    }
                 }
             }
 
@@ -16070,7 +16109,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
         return ret;
     }
 
-#ifdef HAVE_PKCS11
+#if defined(HAVE_PKCS11) || defined(WOLF_CRYPTO_CB)
     int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id,
                                       long sz, int devId, long keySz)
     {
@@ -16124,7 +16163,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
 
         return ret;
     }
-#endif
+#endif /* HAVE_PKCS11 || WOLF_CRYPTO_CB */
 
     int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx,
                                  const unsigned char* in, long sz, int format)

+ 0 - 8
src/tls13.c

@@ -6656,8 +6656,6 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
         {
         #ifndef NO_RSA
             if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
-                WOLFSSL_MSG("Doing RSA peer cert verify");
-
                 ret = RsaVerify(ssl, sig->buffer, (word32)sig->length, &args->output,
                     args->sigAlgo, args->hashAlgo, ssl->peerRsaKey,
                 #ifdef HAVE_PK_CALLBACKS
@@ -6674,8 +6672,6 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
         #endif /* !NO_RSA */
         #ifdef HAVE_ECC
             if (ssl->peerEccDsaKeyPresent) {
-                WOLFSSL_MSG("Doing ECC peer cert verify");
-
                 ret = EccVerify(ssl, input + args->idx, args->sz,
                     args->sigData, args->sigDataSz,
                     ssl->peerEccDsaKey,
@@ -6694,8 +6690,6 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
         #endif /* HAVE_ECC */
         #ifdef HAVE_ED25519
             if (ssl->peerEd25519KeyPresent) {
-                WOLFSSL_MSG("Doing ED25519 peer cert verify");
-
                 ret = Ed25519Verify(ssl, input + args->idx, args->sz,
                     args->sigData, args->sigDataSz,
                     ssl->peerEd25519Key,
@@ -6715,8 +6709,6 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
         #endif
         #ifdef HAVE_ED448
             if (ssl->peerEd448KeyPresent) {
-                WOLFSSL_MSG("Doing ED448 peer cert verify");
-
                 ret = Ed448Verify(ssl, input + args->idx, args->sz,
                     args->sigData, args->sigDataSz,
                     ssl->peerEd448Key,

+ 493 - 81
tests/api.c

@@ -4820,20 +4820,33 @@ done:
 #endif /* defined(OPENSSL_EXTRA) && !defined(WOLFSSL_TIRTOS) && !defined(NO_WOLFSSL_CLIENT) */
 }
 
+#if (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
+     defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY)) && \
+    defined(HAVE_ALPN) && defined(HAVE_SNI) && \
+    defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(NO_BIO)
+    #define HAVE_ALPN_PROTOS_SUPPORT
+#endif
 
-/* SNI / ALPN / session export helper functions */
-#if defined(HAVE_SNI) || defined(HAVE_ALPN) ||\
-    (defined(WOLFSSL_SESSION_EXPORT) && defined(WOLFSSL_DTLS))
+/* Generic TLS client / server with callbacks for API unit tests
+ * Used by SNI / ALPN / crypto callback helper functions */
+#if defined(HAVE_IO_TESTS_DEPENDENCIES) && \
+    (defined(HAVE_SNI) || defined(HAVE_ALPN) || defined(WOLF_CRYPTO_CB) || \
+     defined(HAVE_ALPN_PROTOS_SUPPORT))
+    #define ENABLE_TLS_CALLBACK_TEST
+#endif
 
+#if defined(ENABLE_TLS_CALLBACK_TEST) || \
+    (defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT))
+/* TLS server for API unit testing - generic */
 static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
 {
     callback_functions* callbacks = ((func_args*)args)->callbacks;
 
-    WOLFSSL_CTX* ctx = wolfSSL_CTX_new(callbacks->method());
+    WOLFSSL_CTX* ctx;
     WOLFSSL*     ssl = NULL;
-    SOCKET_T    sfd = 0;
-    SOCKET_T    cfd = 0;
-    word16      port;
+    SOCKET_T     sfd = 0;
+    SOCKET_T     cfd = 0;
+    word16       port;
 
     char msg[] = "I hear you fa shizzle!";
     int  len   = (int) XSTRLEN(msg);
@@ -4841,10 +4854,27 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
     int  idx;
     int  ret, err = 0;
 
+    ((func_args*)args)->return_code = TEST_FAIL;
+
+    ctx = wolfSSL_CTX_new(callbacks->method());
+    if (ctx == NULL) {
+        printf("CTX new failed\n");
+        return 0;
+    }
+
+    /* set defaults */
+    if (callbacks->caPemFile == NULL)
+        callbacks->caPemFile = cliCertFile;
+    if (callbacks->certPemFile == NULL)
+        callbacks->certPemFile = svrCertFile;
+    if (callbacks->keyPemFile == NULL)
+        callbacks->keyPemFile = svrKeyFile;
+
 #ifdef WOLFSSL_TIRTOS
     fdOpenSession(Task_self());
 #endif
-    ((func_args*)args)->return_code = TEST_FAIL;
+
+    wolfSSL_CTX_SetDevId(ctx, callbacks->devId);
 
 #if defined(USE_WINDOWS_API)
     port = ((func_args*)args)->signal->port;
@@ -4869,19 +4899,25 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
 
 
     AssertIntEQ(WOLFSSL_SUCCESS,
-        wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0));
+        wolfSSL_CTX_load_verify_locations(ctx, callbacks->caPemFile, 0));
 
     AssertIntEQ(WOLFSSL_SUCCESS,
-        wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
+        wolfSSL_CTX_use_certificate_file(ctx, callbacks->certPemFile,
             WOLFSSL_FILETYPE_PEM));
 
     AssertIntEQ(WOLFSSL_SUCCESS,
-        wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM));
+        wolfSSL_CTX_use_PrivateKey_file(ctx, callbacks->keyPemFile,
+            WOLFSSL_FILETYPE_PEM));
 
     if (callbacks->ctx_ready)
         callbacks->ctx_ready(ctx);
 
     ssl = wolfSSL_new(ctx);
+    if (ssl == NULL) {
+        printf("SSL new failed\n");
+        wolfSSL_CTX_free(ctx);
+        return 0;
+    }
     if (wolfSSL_dtls(ssl)) {
         SOCKADDR_IN_T cliAddr;
         socklen_t     cliLen;
@@ -4900,6 +4936,18 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
 
     AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, cfd));
 
+    if (callbacks->loadToSSL) {
+        wolfSSL_SetDevId(ssl, callbacks->devId);
+
+        AssertIntEQ(WOLFSSL_SUCCESS,
+            wolfSSL_use_certificate_file(ssl, callbacks->certPemFile,
+                WOLFSSL_FILETYPE_PEM));
+
+        AssertIntEQ(WOLFSSL_SUCCESS,
+            wolfSSL_use_PrivateKey_file(ssl, callbacks->keyPemFile,
+                WOLFSSL_FILETYPE_PEM));
+    }
+
 #ifdef NO_PSK
     #if !defined(NO_FILESYSTEM) && !defined(NO_DH)
         wolfSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM);
@@ -4982,11 +5030,12 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
 #endif
 }
 
+/* TLS Client for API unit testing - generic */
 static void run_wolfssl_client(void* args)
 {
     callback_functions* callbacks = ((func_args*)args)->callbacks;
 
-    WOLFSSL_CTX* ctx = wolfSSL_CTX_new(callbacks->method());
+    WOLFSSL_CTX* ctx;
     WOLFSSL*     ssl = NULL;
     SOCKET_T    sfd = 0;
 
@@ -4996,23 +5045,46 @@ static void run_wolfssl_client(void* args)
     int  idx;
     int  ret, err = 0;
 
+    ((func_args*)args)->return_code = TEST_FAIL;
+
+    /* set defaults */
+    if (callbacks->caPemFile == NULL)
+        callbacks->caPemFile = caCertFile;
+    if (callbacks->certPemFile == NULL)
+        callbacks->certPemFile = cliCertFile;
+    if (callbacks->keyPemFile == NULL)
+        callbacks->keyPemFile = cliKeyFile;
+
+    ctx = wolfSSL_CTX_new(callbacks->method());
+    if (ctx == NULL) {
+        printf("CTX new failed\n");
+        return;
+    }
+
 #ifdef WOLFSSL_TIRTOS
     fdOpenSession(Task_self());
 #endif
 
-    ((func_args*)args)->return_code = TEST_FAIL;
+    if (!callbacks->loadToSSL) {
+        wolfSSL_CTX_SetDevId(ctx, callbacks->devId);
+    }
 
 #ifdef WOLFSSL_ENCRYPTED_KEYS
     wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
 #endif
 
-    AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0));
+    AssertIntEQ(WOLFSSL_SUCCESS, 
+        wolfSSL_CTX_load_verify_locations(ctx, callbacks->caPemFile, 0));
 
-    AssertIntEQ(WOLFSSL_SUCCESS,
-               wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, WOLFSSL_FILETYPE_PEM));
+    if (!callbacks->loadToSSL) {
+        AssertIntEQ(WOLFSSL_SUCCESS,
+            wolfSSL_CTX_use_certificate_file(ctx, callbacks->certPemFile,
+                WOLFSSL_FILETYPE_PEM));
 
-    AssertIntEQ(WOLFSSL_SUCCESS,
-                 wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, WOLFSSL_FILETYPE_PEM));
+        AssertIntEQ(WOLFSSL_SUCCESS, 
+            wolfSSL_CTX_use_PrivateKey_file(ctx, callbacks->keyPemFile,
+                WOLFSSL_FILETYPE_PEM));
+    }
 
     if (callbacks->ctx_ready)
         callbacks->ctx_ready(ctx);
@@ -5028,6 +5100,18 @@ static void run_wolfssl_client(void* args)
     }
     AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, sfd));
 
+    if (callbacks->loadToSSL) {
+        wolfSSL_SetDevId(ssl, callbacks->devId);
+
+        AssertIntEQ(WOLFSSL_SUCCESS,
+            wolfSSL_use_certificate_file(ssl, callbacks->certPemFile,
+                WOLFSSL_FILETYPE_PEM));
+
+        AssertIntEQ(WOLFSSL_SUCCESS, 
+            wolfSSL_use_PrivateKey_file(ssl, callbacks->keyPemFile,
+                WOLFSSL_FILETYPE_PEM));
+    }
+
     if (callbacks->ssl_ready)
         callbacks->ssl_ready(ssl);
 
@@ -5073,8 +5157,8 @@ static void run_wolfssl_client(void* args)
 #endif
 }
 
-#endif /* defined(HAVE_SNI) || defined(HAVE_ALPN) ||
-          defined(WOLFSSL_SESSION_EXPORT) */
+#endif /* ENABLE_TLS_CALLBACK_TEST */
+
 
 static void test_wolfSSL_read_write(void)
 {
@@ -6092,8 +6176,8 @@ static void test_wolfSSL_tls_export(void)
  | TLS extensions tests
  *----------------------------------------------------------------------------*/
 
-#if defined(HAVE_SNI) || defined(HAVE_ALPN)
-/* connection test runner */
+#ifdef ENABLE_TLS_CALLBACK_TEST
+/* Connection test runner - generic */
 static void test_wolfSSL_client_server(callback_functions* client_callbacks,
                                        callback_functions* server_callbacks)
 {
@@ -6135,8 +6219,12 @@ static void test_wolfSSL_client_server(callback_functions* client_callbacks,
 #ifdef WOLFSSL_TIRTOS
     fdCloseSession(Task_self());
 #endif
+
+    client_callbacks->return_code = client_args.return_code;
+    server_callbacks->return_code = server_args.return_code;
 }
-#endif /* defined(HAVE_SNI) || defined(HAVE_ALPN) */
+#endif /* ENABLE_TLS_CALLBACK_TEST */
+
 
 #ifdef HAVE_SNI
 static void test_wolfSSL_UseSNI_params(void)
@@ -6267,58 +6355,69 @@ static void verify_FATAL_ERROR_on_client(WOLFSSL* ssl)
 }
 /* END of connection tests callbacks */
 
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+
 static void test_wolfSSL_UseSNI_connection(void)
 {
     unsigned long i;
     callback_functions callbacks[] = {
         /* success case at ctx */
-        {0, use_SNI_at_ctx, 0, 0, 0, 0},
-        {0, use_SNI_at_ctx, 0, verify_SNI_real_matching, 0, 0},
+        {.ctx_ready = use_SNI_at_ctx},
+        {.ctx_ready = use_SNI_at_ctx, .on_result = verify_SNI_real_matching},
 
         /* success case at ssl */
-        {0, 0, use_SNI_at_ssl, verify_SNI_real_matching, 0, 0},
-        {0, 0, use_SNI_at_ssl, verify_SNI_real_matching, 0, 0},
+        {.ssl_ready = use_SNI_at_ssl, .on_result = verify_SNI_real_matching},
+        {.ssl_ready = use_SNI_at_ssl, .on_result = verify_SNI_real_matching},
 
         /* default mismatch behavior */
-        {0, 0, different_SNI_at_ssl, verify_FATAL_ERROR_on_client, 0, 0},
-        {0, 0, use_SNI_at_ssl,       verify_UNKNOWN_SNI_on_server, 0, 0},
+        {.ssl_ready = different_SNI_at_ssl, .on_result = verify_FATAL_ERROR_on_client},
+        {.ssl_ready = use_SNI_at_ssl,       .on_result = verify_UNKNOWN_SNI_on_server},
 
         /* continue on mismatch */
-        {0, 0, different_SNI_at_ssl,         0, 0, 0},
-        {0, 0, use_SNI_WITH_CONTINUE_at_ssl, verify_SNI_no_matching, 0, 0},
+        {.ssl_ready = different_SNI_at_ssl},
+        {.ssl_ready = use_SNI_WITH_CONTINUE_at_ssl, .on_result = verify_SNI_no_matching},
 
         /* fake answer on mismatch */
-        {0, 0, different_SNI_at_ssl,            0, 0, 0},
-        {0, 0, use_SNI_WITH_FAKE_ANSWER_at_ssl, verify_SNI_fake_matching, 0, 0},
+        {.ssl_ready = different_SNI_at_ssl},
+        {.ssl_ready = use_SNI_WITH_FAKE_ANSWER_at_ssl, .on_result = verify_SNI_fake_matching},
 
         /* sni abort - success */
-        {0, use_SNI_at_ctx,           0, 0, 0, 0},
-        {0, use_MANDATORY_SNI_at_ctx, 0, verify_SNI_real_matching, 0, 0},
+        {.ctx_ready = use_SNI_at_ctx},
+        {.ctx_ready = use_MANDATORY_SNI_at_ctx, .on_result = verify_SNI_real_matching},
 
         /* sni abort - abort when absent (ctx) */
-        {0, 0,                        0, verify_FATAL_ERROR_on_client, 0, 0},
-        {0, use_MANDATORY_SNI_at_ctx, 0, verify_SNI_ABSENT_on_server, 0, 0},
+        {                                       .on_result = verify_FATAL_ERROR_on_client},
+        {.ctx_ready = use_MANDATORY_SNI_at_ctx, .on_result = verify_SNI_ABSENT_on_server},
 
         /* sni abort - abort when absent (ssl) */
-        {0, 0, 0,                        verify_FATAL_ERROR_on_client, 0, 0},
-        {0, 0, use_MANDATORY_SNI_at_ssl, verify_SNI_ABSENT_on_server, 0, 0},
+        {                                       .on_result = verify_FATAL_ERROR_on_client},
+        {.ssl_ready = use_MANDATORY_SNI_at_ssl, .on_result = verify_SNI_ABSENT_on_server},
 
         /* sni abort - success when overwritten */
-        {0, 0, 0, 0, 0, 0},
-        {0, use_MANDATORY_SNI_at_ctx, use_SNI_at_ssl, verify_SNI_no_matching, 0, 0},
+        {.ctx_ready = NULL},
+        {.ctx_ready = use_MANDATORY_SNI_at_ctx, .ssl_ready = use_SNI_at_ssl, .on_result = verify_SNI_no_matching},
 
         /* sni abort - success when allowing mismatches */
-        {0, 0, different_SNI_at_ssl, 0, 0, 0},
-        {0, use_PSEUDO_MANDATORY_SNI_at_ctx, 0, verify_SNI_fake_matching, 0, 0},
+        {.ssl_ready = different_SNI_at_ssl},
+        {.ctx_ready = use_PSEUDO_MANDATORY_SNI_at_ctx, .on_result = verify_SNI_fake_matching},
     };
 
     for (i = 0; i < sizeof(callbacks) / sizeof(callback_functions); i += 2) {
         callbacks[i    ].method = wolfSSLv23_client_method;
         callbacks[i + 1].method = wolfSSLv23_server_method;
+        callbacks[i    ].devId = devId;
+        callbacks[i + 1].devId = devId;
         test_wolfSSL_client_server(&callbacks[i], &callbacks[i + 1]);
     }
 }
 
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
 static void test_wolfSSL_SNI_GetFromBuffer(void)
 {
     byte buff[] = { /* www.paypal.com */
@@ -6641,8 +6740,7 @@ static void test_wolfSSL_UseSupportedCurve(void)
 #endif
 }
 
-#if defined(HAVE_ALPN) && !defined(NO_WOLFSSL_SERVER) && \
-    defined(HAVE_IO_TESTS_DEPENDENCIES)
+#if defined(HAVE_ALPN) && defined(HAVE_IO_TESTS_DEPENDENCIES)
 
 static void verify_ALPN_FATAL_ERROR_on_client(WOLFSSL* ssl)
 {
@@ -6776,51 +6874,62 @@ static void verify_ALPN_client_list(WOLFSSL* ssl)
     AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_FreePeerProtocol(ssl, &clist));
 }
 
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+
 static void test_wolfSSL_UseALPN_connection(void)
 {
     unsigned long i;
     callback_functions callbacks[] = {
         /* success case same list */
-        {0, 0, use_ALPN_all, 0, 0, 0},
-        {0, 0, use_ALPN_all, verify_ALPN_matching_http1, 0, 0},
+        {.ssl_ready = use_ALPN_all},
+        {.ssl_ready = use_ALPN_all, .on_result = verify_ALPN_matching_http1},
 
         /* success case only one for server */
-        {0, 0, use_ALPN_all, 0, 0, 0},
-        {0, 0, use_ALPN_one, verify_ALPN_matching_spdy2, 0, 0},
+        {.ssl_ready = use_ALPN_all},
+        {.ssl_ready = use_ALPN_one, .on_result = verify_ALPN_matching_spdy2},
 
         /* success case only one for client */
-        {0, 0, use_ALPN_one, 0, 0, 0},
-        {0, 0, use_ALPN_all, verify_ALPN_matching_spdy2, 0, 0},
+        {.ssl_ready = use_ALPN_one},
+        {.ssl_ready = use_ALPN_all, .on_result = verify_ALPN_matching_spdy2},
 
         /* success case none for client */
-        {0, 0, 0, 0, 0, 0},
-        {0, 0, use_ALPN_all, 0, 0, 0},
+        {.ssl_ready = NULL},
+        {.ssl_ready = use_ALPN_all},
 
         /* success case mismatch behavior but option 'continue' set */
-        {0, 0, use_ALPN_all_continue, verify_ALPN_not_matching_continue, 0, 0},
-        {0, 0, use_ALPN_unknown_continue, 0, 0, 0},
+        {.ssl_ready = use_ALPN_all_continue, .on_result = verify_ALPN_not_matching_continue},
+        {.ssl_ready = use_ALPN_unknown_continue},
 
         /* success case read protocol send by client */
-        {0, 0, use_ALPN_all, 0, 0, 0},
-        {0, 0, use_ALPN_one, verify_ALPN_client_list, 0, 0},
+        {.ssl_ready = use_ALPN_all},
+        {.ssl_ready = use_ALPN_one, .on_result = verify_ALPN_client_list},
 
         /* mismatch behavior with same list
          * the first and only this one must be taken */
-        {0, 0, use_ALPN_all, 0, 0, 0},
-        {0, 0, use_ALPN_all, verify_ALPN_not_matching_spdy3, 0, 0},
+        {.ssl_ready = use_ALPN_all},
+        {.ssl_ready = use_ALPN_all, .on_result = verify_ALPN_not_matching_spdy3},
 
         /* default mismatch behavior */
-        {0, 0, use_ALPN_all, 0, 0, 0},
-        {0, 0, use_ALPN_unknown, verify_ALPN_FATAL_ERROR_on_client, 0, 0},
+        {.ssl_ready = use_ALPN_all},
+        {.ssl_ready = use_ALPN_unknown, .on_result = verify_ALPN_FATAL_ERROR_on_client},
     };
 
     for (i = 0; i < sizeof(callbacks) / sizeof(callback_functions); i += 2) {
         callbacks[i    ].method = wolfSSLv23_client_method;
         callbacks[i + 1].method = wolfSSLv23_server_method;
+        callbacks[i    ].devId = devId;
+        callbacks[i + 1].devId = devId;
         test_wolfSSL_client_server(&callbacks[i], &callbacks[i + 1]);
     }
 }
 
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
 static void test_wolfSSL_UseALPN_params(void)
 {
 #ifndef NO_WOLFSSL_CLIENT
@@ -6896,11 +7005,7 @@ static void test_wolfSSL_UseALPN_params(void)
 }
 #endif /* HAVE_ALPN  */
 
-#if (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
-    defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY)) && \
-    (defined(HAVE_ALPN) && defined(HAVE_SNI)) &&\
-    defined(HAVE_IO_TESTS_DEPENDENCIES)
-    
+#ifdef HAVE_ALPN_PROTOS_SUPPORT
 static void CTX_set_alpn_protos(SSL_CTX *ctx)
 {
     unsigned char p[] = {
@@ -6919,7 +7024,6 @@ static void CTX_set_alpn_protos(SSL_CTX *ctx)
 #else
     AssertIntEQ(ret, SSL_SUCCESS);
 #endif
-
 }
 
 static void set_alpn_protos(SSL* ssl) 
@@ -6972,26 +7076,38 @@ static void verify_alpn_matching_http1(WOLFSSL* ssl)
     AssertIntEQ(0, XMEMCMP(nego_proto, proto, protoSz));
 }
 
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+
 static void test_wolfSSL_set_alpn_protos(void)
 {
     unsigned long i;
     callback_functions callbacks[] = {
         /* use CTX_alpn_protos */
-        {0, CTX_set_alpn_protos, 0, 0, 0, 0},
-        {0, CTX_set_alpn_protos, 0, verify_alpn_matching_http1, 0, 0},
+        {.ctx_ready = CTX_set_alpn_protos},
+        {.ctx_ready = CTX_set_alpn_protos, .on_result = verify_alpn_matching_http1},
         /* use set_alpn_protos */
-        {0, 0, set_alpn_protos, 0, 0, 0},
-        {0, 0, set_alpn_protos, verify_alpn_matching_spdy3, 0, 0},
+        {.ssl_ready = set_alpn_protos},
+        {.ssl_ready = set_alpn_protos, .on_result = verify_alpn_matching_spdy3},
     };
 
     for (i = 0; i < sizeof(callbacks) / sizeof(callback_functions); i += 2) {
         callbacks[i    ].method = wolfSSLv23_client_method;
         callbacks[i + 1].method = wolfSSLv23_server_method;
+        callbacks[i    ].devId = devId;
+        callbacks[i + 1].devId = devId;
         test_wolfSSL_client_server(&callbacks[i], &callbacks[i + 1]);
     }
 }
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
 #endif
 
+#endif /* HAVE_ALPN_PROTOS_SUPPORT */
+
 static void test_wolfSSL_UseALPN(void)
 {
 #if defined(HAVE_ALPN) && !defined(NO_WOLFSSL_SERVER) &&\
@@ -7000,17 +7116,9 @@ static void test_wolfSSL_UseALPN(void)
     test_wolfSSL_UseALPN_params();
 #endif
 
-#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_BIO)
-
-#if (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
-    defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY)) && \
-    (defined(HAVE_ALPN) && defined(HAVE_SNI)) && \
-    defined(HAVE_IO_TESTS_DEPENDENCIES)
-    
+#ifdef HAVE_ALPN_PROTOS_SUPPORT
     test_wolfSSL_set_alpn_protos();
 #endif
-
-#endif
 }
 
 static void test_wolfSSL_DisableExtendedMasterSecret(void)
@@ -30294,7 +30402,7 @@ static void test_wolfSSL_PEM_bio_RSAKey(void)
     RSA_free(rsa);
 
     /* Ensure that keys beginning with BEGIN RSA PUBLIC KEY can be read, too. */
-    AssertNotNull(bio = BIO_new_file("./certs/server-pub-key.pem", "rb"));
+    AssertNotNull(bio = BIO_new_file("./certs/server-keyPub.pem", "rb"));
     AssertNotNull((rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL)));
     BIO_free(bio);
     RSA_free(rsa);
@@ -49768,6 +49876,308 @@ static void test_SSL_CIPHER_get_xxx(void)
 #endif
 }
 
+#if defined(WOLF_CRYPTO_CB) && defined(HAVE_IO_TESTS_DEPENDENCIES)
+
+static int load_pem_key_file_as_der(const char* privKeyFile, DerBuffer** pDer,
+    int* keyFormat)
+{
+    int ret;
+    byte* key_buf = NULL;
+    size_t key_sz = 0;
+    EncryptedInfo encInfo;
+
+    XMEMSET(&encInfo, 0, sizeof(encInfo));
+
+    ret = load_file(privKeyFile, &key_buf, &key_sz);
+    if (ret == 0) {
+        ret = wc_PemToDer(key_buf, key_sz, PRIVATEKEY_TYPE, pDer,
+            NULL, &encInfo, keyFormat);
+    }
+
+    if (key_buf != NULL) {
+        free(key_buf); key_buf = NULL;
+    }
+    (void)encInfo; /* not used in this test */
+
+#ifdef DEBUG_WOLFSSL
+    printf("%s (%d): Loading PEM %s (len %d) to DER (len %d)\n",
+        (ret == 0) ? "Success" : "Failure", ret, privKeyFile, (int)key_sz, 
+        (*pDer)->length);
+#endif
+
+    return ret;
+}
+static int test_CryptoCb_Func(int thisDevId, wc_CryptoInfo* info, void* ctx)
+{
+    int ret = CRYPTOCB_UNAVAILABLE;
+    const char* privKeyFile = (const char*)ctx;
+    DerBuffer* pDer = NULL;
+    int keyFormat = 0;
+
+    if (info->algo_type == WC_ALGO_TYPE_PK) {
+    #ifdef DEBUG_WOLFSSL
+        printf("test_CryptoCb_Func: Pk Type %d\n", info->pk.type);
+    #endif
+
+    #ifndef NO_RSA
+        if (info->pk.type == WC_PK_TYPE_RSA) {
+            switch (info->pk.rsa.type) {
+                case RSA_PUBLIC_ENCRYPT:
+                case RSA_PUBLIC_DECRYPT:
+                    /* perform software based RSA public op */
+                    ret = CRYPTOCB_UNAVAILABLE; /* fallback to software */
+                    break;
+                case RSA_PRIVATE_ENCRYPT:
+                case RSA_PRIVATE_DECRYPT:
+                {
+                    RsaKey key;
+
+                    /* perform software based RSA private op */
+                #ifdef DEBUG_WOLFSSL
+                    printf("test_CryptoCb_Func: RSA Priv\n");
+                #endif
+
+                    ret = load_pem_key_file_as_der(privKeyFile, &pDer,
+                        &keyFormat);
+                    if (ret != 0) {
+                        return ret;
+                    }
+                    ret = wc_InitRsaKey(&key, NULL);
+                    if (ret == 0) {
+                        word32 keyIdx = 0;
+                        /* load RSA private key and perform private transform */
+                        ret = wc_RsaPrivateKeyDecode(pDer->buffer, &keyIdx,
+                            &key, pDer->length);
+                        if (ret == 0) {
+                            ret = wc_RsaFunction(
+                                info->pk.rsa.in, info->pk.rsa.inLen,
+                                info->pk.rsa.out, info->pk.rsa.outLen,
+                                info->pk.rsa.type, &key, info->pk.rsa.rng);
+                        }
+                        else {
+                            /* if decode fails, then fall-back to software based crypto */
+                            printf("test_CryptoCb_Func: RSA private key decode "
+                                "failed %d, falling back to software\n", ret);
+                            ret = CRYPTOCB_UNAVAILABLE;
+                        }
+                        wc_FreeRsaKey(&key);
+                    }
+                    wc_FreeDer(&pDer); pDer = NULL;
+                    break;
+                }
+            }
+        #ifdef DEBUG_WOLFSSL
+            printf("test_CryptoCb_Func: RSA Type %d, Ret %d, Out %d\n",
+                info->pk.rsa.type, ret, *info->pk.rsa.outLen);
+        #endif
+        }
+    #endif /* !NO_RSA */
+    #ifdef HAVE_ECC
+        if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) {
+            ecc_key key;
+
+            /* perform software based ECC sign */
+        #ifdef DEBUG_WOLFSSL
+            printf("test_CryptoCb_Func: ECC Sign\n");
+        #endif
+
+            ret = load_pem_key_file_as_der(privKeyFile, &pDer, &keyFormat);
+            if (ret != 0) {
+                return ret;
+            }
+
+            ret = wc_ecc_init(&key);
+            if (ret == 0) {
+                word32 keyIdx = 0;
+                /* load ECC private key and perform private transform */
+                ret = wc_EccPrivateKeyDecode(pDer->buffer, &keyIdx,
+                    &key, pDer->length);
+                if (ret == 0) {
+                    ret = wc_ecc_sign_hash(
+                        info->pk.eccsign.in, info->pk.eccsign.inlen,
+                        info->pk.eccsign.out, info->pk.eccsign.outlen,
+                        info->pk.eccsign.rng, &key);
+                }
+                else {
+                    /* if decode fails, then fall-back to software based crypto */
+                    printf("test_CryptoCb_Func: ECC private key decode "
+                        "failed %d, falling back to software\n", ret);
+                    ret = CRYPTOCB_UNAVAILABLE;
+                }
+                wc_ecc_free(&key);
+            }
+            wc_FreeDer(&pDer); pDer = NULL;
+
+        #ifdef DEBUG_WOLFSSL
+            printf("test_CryptoCb_Func: ECC Ret %d, Out %d\n",
+                ret, *info->pk.eccsign.outlen);
+        #endif
+        }
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        if (info->pk.type == WC_PK_TYPE_ED25519_SIGN) {
+            ed25519_key key;
+
+            /* perform software based ED25519 sign */
+        #ifdef DEBUG_WOLFSSL
+            printf("test_CryptoCb_Func: ED25519 Sign\n");
+        #endif
+
+            ret = load_pem_key_file_as_der(privKeyFile, &pDer, &keyFormat);
+            if (ret != 0) {
+                return ret;
+            }
+            ret = wc_ed25519_init(&key);
+            if (ret == 0) {
+                word32 keyIdx = 0;
+                /* load ED25519 private key and perform private transform */
+                ret = wc_Ed25519PrivateKeyDecode(pDer->buffer, &keyIdx,
+                    &key, pDer->length);
+                if (ret == 0) {
+                    /* calculate public key */
+                    ret = wc_ed25519_make_public(&key, key.p, ED25519_PUB_KEY_SIZE);
+                    if (ret == 0) {
+                        key.pubKeySet = 1;
+                        ret = wc_ed25519_sign_msg_ex(
+                            info->pk.ed25519sign.in, info->pk.ed25519sign.inLen,
+                            info->pk.ed25519sign.out, info->pk.ed25519sign.outLen,
+                            &key, info->pk.ed25519sign.type,
+                            info->pk.ed25519sign.context,
+                            info->pk.ed25519sign.contextLen);
+                    }
+                }
+                else {
+                    /* if decode fails, then fall-back to software based crypto */
+                    printf("test_CryptoCb_Func: ED25519 private key decode "
+                        "failed %d, falling back to software\n", ret);
+                    ret = CRYPTOCB_UNAVAILABLE;
+                }
+                wc_ed25519_free(&key);
+            }
+            wc_FreeDer(&pDer); pDer = NULL;
+
+        #ifdef DEBUG_WOLFSSL
+            printf("test_CryptoCb_Func: ED25519 Ret %d, Out %d\n",
+                ret, *info->pk.ed25519sign.outLen);
+        #endif
+        }
+    #endif /* HAVE_ED25519 */
+    }
+    (void)thisDevId;
+    (void)keyFormat;
+
+    return ret;
+}
+
+/* tlsVer: WOLFSSL_TLSV1_2 or WOLFSSL_TLSV1_3 */
+static void test_wc_CryptoCb_TLS(int tlsVer,
+    const char* cliCaPemFile, const char* cliCertPemFile, 
+    const char* cliPrivKeyPemFile, const char* cliPubKeyPemFile,
+    const char* svrCaPemFile, const char* svrCertPemFile, 
+    const char* svrPrivKeyPemFile, const char* svrPubKeyPemFile)
+{
+    callback_functions client_cbf;
+    callback_functions server_cbf;
+
+    XMEMSET(&client_cbf, 0, sizeof(client_cbf));
+    XMEMSET(&server_cbf, 0, sizeof(server_cbf));
+
+    if (tlsVer == WOLFSSL_TLSV1_3) {
+    #ifdef WOLFSSL_TLS13
+        server_cbf.method = wolfTLSv1_3_server_method;
+        client_cbf.method = wolfTLSv1_3_client_method;
+    #endif
+    }
+    else if (tlsVer == WOLFSSL_TLSV1_2) {
+    #ifndef WOLFSSL_NO_TLS12
+        server_cbf.method = wolfTLSv1_2_server_method;
+        client_cbf.method = wolfTLSv1_2_client_method;
+    #endif
+    }
+    if (server_cbf.method == NULL) {
+        /* not enabled */
+        return;
+    }
+
+    /* Setup the keys for the TLS test */
+    client_cbf.certPemFile = cliCertPemFile;
+    client_cbf.keyPemFile = cliPubKeyPemFile;
+    client_cbf.caPemFile = cliCaPemFile;
+
+    server_cbf.certPemFile = svrCertPemFile;
+    server_cbf.keyPemFile = svrPubKeyPemFile;
+    server_cbf.caPemFile = svrCaPemFile;
+
+    /* Setup a crypto callback with pointer to private key file for testing */
+    client_cbf.devId = 1;
+    wc_CryptoCb_RegisterDevice(client_cbf.devId, test_CryptoCb_Func,
+        (void*)cliPrivKeyPemFile);
+    server_cbf.devId = 2;
+    wc_CryptoCb_RegisterDevice(server_cbf.devId, test_CryptoCb_Func,
+        (void*)svrPrivKeyPemFile);
+
+    /* Perform TLS server and client test */
+    /* First test is at WOLFSSL_CTX level */
+    test_wolfSSL_client_server(&client_cbf, &server_cbf);
+    /* Check for success */
+    AssertIntEQ(server_cbf.return_code, TEST_SUCCESS);
+    AssertIntEQ(client_cbf.return_code, TEST_SUCCESS);
+
+    /* Second test is a WOLFSSL object level */
+    client_cbf.loadToSSL = 1; server_cbf.loadToSSL = 1;
+    test_wolfSSL_client_server(&client_cbf, &server_cbf);
+
+    /* Check for success */
+    AssertIntEQ(server_cbf.return_code, TEST_SUCCESS);
+    AssertIntEQ(client_cbf.return_code, TEST_SUCCESS);
+
+    /* Un register the devId's */
+    wc_CryptoCb_UnRegisterDevice(client_cbf.devId);
+    client_cbf.devId = INVALID_DEVID;
+    wc_CryptoCb_UnRegisterDevice(server_cbf.devId);
+    server_cbf.devId = INVALID_DEVID;
+}
+#endif /* WOLF_CRYPTO_CB && HAVE_IO_TESTS_DEPENDENCIES */
+
+static void test_wc_CryptoCb(void)
+{
+#ifdef WOLF_CRYPTO_CB
+    /* TODO: Add crypto callback API tests */
+
+#ifdef HAVE_IO_TESTS_DEPENDENCIES
+    #ifndef NO_RSA
+    /* RSA */
+    test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_3,
+        svrCertFile, cliCertFile, cliKeyFile, cliKeyPubFile,
+        cliCertFile, svrCertFile, svrKeyFile, svrKeyPubFile);
+    test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_2,
+        svrCertFile, cliCertFile, cliKeyFile, cliKeyPubFile,
+        cliCertFile, svrCertFile, svrKeyFile, svrKeyPubFile);
+    #endif
+
+    #ifdef HAVE_ECC
+    /* ECC */
+    test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_3,
+        caEccCertFile, cliEccCertFile, cliEccKeyFile, cliEccKeyPubFile,
+        cliEccCertFile, eccCertFile, eccKeyFile, eccKeyPubFile);
+    test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_2,
+        caEccCertFile, cliEccCertFile, cliEccKeyFile, cliEccKeyPubFile,
+        cliEccCertFile, eccCertFile, eccKeyFile, eccKeyPubFile);
+    #endif
+
+    #ifdef HAVE_ED25519
+    /* ED25519 */
+    test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_3,
+        caEdCertFile, cliEdCertFile, cliEdKeyFile, cliEdKeyPubFile,
+        cliEdCertFile, edCertFile, edKeyFile, edKeyPubFile);
+    test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_2,
+        caEdCertFile, cliEdCertFile, cliEdKeyFile, cliEdKeyPubFile,
+        cliEdCertFile, edCertFile, edKeyFile, edKeyPubFile);
+    #endif
+#endif /* HAVE_IO_TESTS_DEPENDENCIES */
+#endif /* WOLF_CRYPTO_CB */
+}
+
 /*----------------------------------------------------------------------------*
  | Main
  *----------------------------------------------------------------------------*/
@@ -50616,6 +51026,8 @@ void ApiTest(void)
 
     test_wolfSSL_CTX_LoadCRL();
 
+    test_wc_CryptoCb();
+
     AssertIntEQ(test_ForceZero(), 0);
 
     AssertIntEQ(test_wolfSSL_Cleanup(), WOLFSSL_SUCCESS);

+ 26 - 8
wolfcrypt/src/asn.c

@@ -6382,7 +6382,7 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz,
             return MEMORY_E;
 
         tmpIdx = 0;
-        if (wc_ed25519_init(ed25519) == 0) {
+        if (wc_ed25519_init_ex(ed25519, heap, INVALID_DEVID) == 0) {
             if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, ed25519, keySz) == 0) {
                 *algoID = ED25519k;
             }
@@ -13034,7 +13034,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
                     if (sigCtx->key.ed25519 == NULL) {
                         ERROR_OUT(MEMORY_E, exit_cs);
                     }
-                    if ((ret = wc_ed25519_init(sigCtx->key.ed25519)) < 0) {
+                    if ((ret = wc_ed25519_init_ex(sigCtx->key.ed25519,
+                                            sigCtx->heap, sigCtx->devId)) < 0) {
                         goto exit_cs;
                     }
                     if ((ret = wc_ed25519_import_public(key, keySz,
@@ -18771,7 +18772,6 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
     /* map header if not found for type */
     for (;;) {
         headerEnd = XSTRNSTR((char*)buff, header, sz);
-
         if (headerEnd) {
             break;
         }
@@ -18806,7 +18806,14 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
             }
 #endif
             else {
+            #ifdef WOLF_CRYPTO_CB
+                /* allow loading a public key for use with crypto callbacks */
+                type = PUBLICKEY_TYPE;
+                header = BEGIN_PUB_KEY;
+                footer = END_PUB_KEY;
+            #else
                 break;
+            #endif
             }
         }
         else if (type == PUBLICKEY_TYPE) {
@@ -18907,18 +18914,30 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
     /* eat end of line characters */
     headerEnd = SkipEndOfLineChars(headerEnd, bufferEnd);
 
-    if (type == PRIVATEKEY_TYPE) {
+    if (keyFormat) {
         /* keyFormat is Key_Sum enum */
-        if (keyFormat) {
+        if (type == PRIVATEKEY_TYPE) {
+        #ifndef NO_RSA
+            if (header == BEGIN_RSA_PRIV)
+                *keyFormat = RSAk;
+        #endif
         #ifdef HAVE_ECC
             if (header == BEGIN_EC_PRIV)
                 *keyFormat = ECDSAk;
         #endif
-        #if !defined(NO_DSA)
+        #ifndef NO_DSA
             if (header == BEGIN_DSA_PRIV)
                 *keyFormat = DSAk;
         #endif
         }
+    #ifdef WOLF_CRYPTO_CB
+        else if (type == PUBLICKEY_TYPE) {
+        #ifndef NO_RSA
+            if (header == BEGIN_RSA_PUB)
+                *keyFormat = RSAk;
+        #endif
+        }
+    #endif
     }
 
 #ifdef WOLFSSL_ENCRYPTED_KEYS
@@ -18993,7 +19012,6 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
         return 0;
     }
 
-
 #ifdef WOLFSSL_ENCRYPTED_KEYS
     if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) {
         int   passwordSz = NAME_SZ;
@@ -19112,8 +19130,8 @@ int wc_PemToDer(const unsigned char* buff, long longSz, int type,
         ret = ToTraditional(der->buffer, der->length);
         if (ret > 0) {
             der->length = ret;
-            ret = 0;
         }
+        ret = 0; /* ignore error removing PKCS8 header */
     }
 #endif
     return ret;

+ 2 - 3
wolfcrypt/test/test.c

@@ -12021,8 +12021,7 @@ WOLFSSL_TEST_SUBROUTINE int memory_test(void)
 #if !defined(USE_CERT_BUFFERS_256) && !defined(NO_ASN)
         #if defined(HAVE_ECC) && defined(WOLFSSL_CERT_GEN)
             #ifndef NO_RSA
-                /* eccKeyPubFile is used in a test that requires RSA. */
-                static const char* eccKeyPubFile = CERT_ROOT "ecc-keyPub.der";
+                static const char* eccKeyPubFileDer = CERT_ROOT "ecc-keyPub.der";
             #endif
             static const char* eccCaKeyFile  = CERT_ROOT "ca-ecc-key.der";
             static const char* eccCaCertFile = CERT_ROOT "ca-ecc-cert.pem";
@@ -14542,7 +14541,7 @@ static int rsa_ecc_certgen_test(WC_RNG* rng, byte* tmp)
     XMEMCPY(tmp, ecc_key_pub_der_256, sizeof_ecc_key_pub_der_256);
     bytes3 = sizeof_ecc_key_pub_der_256;
 #else
-    file3 = XFOPEN(eccKeyPubFile, "rb");
+    file3 = XFOPEN(eccKeyPubFileDer, "rb");
     if (!file3) {
         ERROR_OUT(-7855, exit_rsa);
     }

+ 18 - 0
wolfssl/test.h

@@ -335,23 +335,29 @@
 #define caCertFile        "certs/ca-cert.pem"
 #define eccCertFile       "certs/server-ecc.pem"
 #define eccKeyFile        "certs/ecc-key.pem"
+#define eccKeyPubFile     "certs/ecc-keyPub.pem"
 #define eccRsaCertFile    "certs/server-ecc-rsa.pem"
 #define svrCertFile       "certs/server-cert.pem"
 #define svrKeyFile        "certs/server-key.pem"
+#define svrKeyPubFile     "certs/server-keyPub.pem"
 #define cliCertFile       "certs/client-cert.pem"
 #define cliCertDerFile    "certs/client-cert.der"
 #define cliCertFileExt    "certs/client-cert-ext.pem"
 #define cliCertDerFileExt "certs/client-cert-ext.der"
 #define cliKeyFile        "certs/client-key.pem"
+#define cliKeyPubFile     "certs/client-keyPub.pem"
 #define dhParamFile       "certs/dh2048.pem"
 #define cliEccKeyFile     "certs/ecc-client-key.pem"
+#define cliEccKeyPubFile  "certs/ecc-client-keyPub.pem"
 #define cliEccCertFile    "certs/client-ecc-cert.pem"
 #define caEccCertFile     "certs/ca-ecc-cert.pem"
 #define crlPemDir         "certs/crl"
 #define edCertFile        "certs/ed25519/server-ed25519-cert.pem"
 #define edKeyFile         "certs/ed25519/server-ed25519-priv.pem"
+#define edKeyPubFile      "certs/ed25519/server-ed25519-key.pem"
 #define cliEdCertFile     "certs/ed25519/client-ed25519.pem"
 #define cliEdKeyFile      "certs/ed25519/client-ed25519-priv.pem"
+#define cliEdKeyPubFile   "certs/ed25519/client-ed25519-key.pem"
 #define caEdCertFile      "certs/ed25519/ca-ed25519.pem"
 #define ed448CertFile     "certs/ed448/server-ed448-cert.pem"
 #define ed448KeyFile      "certs/ed448/server-ed448-priv.pem"
@@ -367,23 +373,29 @@
 #define caCertFile        "./certs/ca-cert.pem"
 #define eccCertFile       "./certs/server-ecc.pem"
 #define eccKeyFile        "./certs/ecc-key.pem"
+#define eccKeyPubFile     "./certs/ecc-keyPub.pem"
 #define eccRsaCertFile    "./certs/server-ecc-rsa.pem"
 #define svrCertFile       "./certs/server-cert.pem"
 #define svrKeyFile        "./certs/server-key.pem"
+#define svrKeyPubFile     "./certs/server-keyPub.pem"
 #define cliCertFile       "./certs/client-cert.pem"
 #define cliCertDerFile    "./certs/client-cert.der"
 #define cliCertFileExt    "./certs/client-cert-ext.pem"
 #define cliCertDerFileExt "./certs/client-cert-ext.der"
 #define cliKeyFile        "./certs/client-key.pem"
+#define cliKeyPubFile     "./certs/client-keyPub.pem"
 #define dhParamFile       "./certs/dh2048.pem"
 #define cliEccKeyFile     "./certs/ecc-client-key.pem"
+#define cliEccKeyPubFile  "./certs/ecc-client-keyPub.pem"
 #define cliEccCertFile    "./certs/client-ecc-cert.pem"
 #define caEccCertFile     "./certs/ca-ecc-cert.pem"
 #define crlPemDir         "./certs/crl"
 #define edCertFile        "./certs/ed25519/server-ed25519-cert.pem"
 #define edKeyFile         "./certs/ed25519/server-ed25519-priv.pem"
+#define edKeyPubFile      "./certs/ed25519/server-ed25519-key.pem"
 #define cliEdCertFile     "./certs/ed25519/client-ed25519.pem"
 #define cliEdKeyFile      "./certs/ed25519/client-ed25519-priv.pem"
+#define cliEdKeyPubFile   "./certs/ed25519/client-ed25519-key.pem"
 #define caEdCertFile      "./certs/ed25519/ca-ed25519.pem"
 #define ed448CertFile     "./certs/ed448/server-ed448-cert.pem"
 #define ed448KeyFile      "./certs/ed448/server-ed448-priv.pem"
@@ -443,7 +455,13 @@ typedef struct callback_functions {
     ssl_callback ssl_ready;
     ssl_callback on_result;
     WOLFSSL_CTX* ctx;
+    const char* caPemFile;
+    const char* certPemFile;
+    const char* keyPemFile;
+    int devId;
+    int return_code;
     unsigned char isSharedCtx:1;
+    unsigned char loadToSSL:1;
 } callback_functions;
 
 typedef struct func_args {