Index: azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/wolfcrypt/src/evp.c
===================================================================
--- azure_iot_hub_f767zi/trunk/wolfssl-4.4.0/wolfcrypt/src/evp.c	(revision 457)
+++ azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/wolfcrypt/src/evp.c	(revision 464)
@@ -20,4 +20,11 @@
  */
 
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
 #if !defined(WOLFSSL_EVP_INCLUDED)
     #ifndef WOLFSSL_IGNORE_FILE_WARN
@@ -27,25 +34,26 @@
 #else
 
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
+#if defined(OPENSSL_EXTRA)
+
+#if !defined(HAVE_PKCS7) && \
+      ((defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \
+       (HAVE_FIPS_VERSION == 2)) || defined(HAVE_SELFTEST))
+    #include <wolfssl/wolfcrypt/aes.h>
+#endif
+
 
 #include <wolfssl/openssl/ecdsa.h>
 #include <wolfssl/openssl/evp.h>
-
-#if defined(OPENSSL_EXTRA)
 
 #ifndef NO_AES
     #ifdef HAVE_AES_CBC
     #ifdef WOLFSSL_AES_128
-        static char *EVP_AES_128_CBC = NULL;
+        static const char EVP_AES_128_CBC[] = "AES-128-CBC";
     #endif
     #ifdef WOLFSSL_AES_192
-        static char *EVP_AES_192_CBC = NULL;
+        static const char EVP_AES_192_CBC[] = "AES-192-CBC";
     #endif
     #ifdef WOLFSSL_AES_256
-        static char *EVP_AES_256_CBC = NULL;
+        static const char EVP_AES_256_CBC[] = "AES-256-CBC";
     #endif
     #endif /* HAVE_AES_CBC */
@@ -53,11 +61,11 @@
     #ifdef WOLFSSL_AES_OFB
     #ifdef WOLFSSL_AES_128
-        static char *EVP_AES_128_OFB = NULL;
+        static const char EVP_AES_128_OFB[] = "AES-128-OFB";
     #endif
     #ifdef WOLFSSL_AES_192
-        static char *EVP_AES_192_OFB = NULL;
+        static const char EVP_AES_192_OFB[] = "AES-192-OFB";
     #endif
     #ifdef WOLFSSL_AES_256
-        static char *EVP_AES_256_OFB = NULL;
+        static const char EVP_AES_256_OFB[] = "AES-256-OFB";
     #endif
     #endif /* WOLFSSL_AES_OFB */
@@ -65,8 +73,8 @@
     #ifdef WOLFSSL_AES_XTS
     #ifdef WOLFSSL_AES_128
-        static char *EVP_AES_128_XTS = NULL;
+        static const char EVP_AES_128_XTS[] = "AES-128-XTS";
     #endif
     #ifdef WOLFSSL_AES_256
-        static char *EVP_AES_256_XTS = NULL;
+        static const char EVP_AES_256_XTS[] = "AES-256-XTS";
     #endif
     #endif /* WOLFSSL_AES_XTS */
@@ -74,31 +82,31 @@
     #ifdef WOLFSSL_AES_CFB
     #ifdef WOLFSSL_AES_128
-        static char *EVP_AES_128_CFB1 = NULL;
+        static const char EVP_AES_128_CFB1[] = "AES-128-CFB1";
     #endif
     #ifdef WOLFSSL_AES_192
-        static char *EVP_AES_192_CFB1 = NULL;
+        static const char EVP_AES_192_CFB1[] = "AES-192-CFB1";
     #endif
     #ifdef WOLFSSL_AES_256
-        static char *EVP_AES_256_CFB1 = NULL;
+        static const char EVP_AES_256_CFB1[] = "AES-256-CFB1";
     #endif
 
     #ifdef WOLFSSL_AES_128
-        static char *EVP_AES_128_CFB8 = NULL;
+        static const char EVP_AES_128_CFB8[] = "AES-128-CFB8";
     #endif
     #ifdef WOLFSSL_AES_192
-        static char *EVP_AES_192_CFB8 = NULL;
+        static const char EVP_AES_192_CFB8[] = "AES-192-CFB8";
     #endif
     #ifdef WOLFSSL_AES_256
-        static char *EVP_AES_256_CFB8 = NULL;
+        static const char EVP_AES_256_CFB8[] = "AES-256-CFB8";
     #endif
 
     #ifdef WOLFSSL_AES_128
-        static char *EVP_AES_128_CFB128 = NULL;
+        static const char EVP_AES_128_CFB128[] = "AES-128-CFB128";
     #endif
     #ifdef WOLFSSL_AES_192
-        static char *EVP_AES_192_CFB128 = NULL;
+        static const char EVP_AES_192_CFB128[] = "AES-192-CFB128";
     #endif
     #ifdef WOLFSSL_AES_256
-        static char *EVP_AES_256_CFB128 = NULL;
+        static const char EVP_AES_256_CFB128[] = "AES-256-CFB128";
     #endif
     #endif /* WOLFSSL_AES_CFB */
@@ -106,31 +114,36 @@
     #ifdef HAVE_AESGCM
         #ifdef WOLFSSL_AES_128
-            static char *EVP_AES_128_GCM = NULL;
+            static const char EVP_AES_128_GCM[] = "AES-128-GCM";
         #endif
         #ifdef WOLFSSL_AES_192
-            static char *EVP_AES_192_GCM = NULL;
+            static const char EVP_AES_192_GCM[] = "AES-192-GCM";
         #endif
         #ifdef WOLFSSL_AES_256
-            static char *EVP_AES_256_GCM = NULL;
+            static const char EVP_AES_256_GCM[] = "AES-256-GCM";
         #endif
     #endif /* HAVE_AESGCM */
+
+    #ifdef WOLFSSL_AES_COUNTER
     #ifdef WOLFSSL_AES_128
-        static char *EVP_AES_128_CTR = NULL;
+        static const char EVP_AES_128_CTR[] = "AES-128-CTR";
     #endif
     #ifdef WOLFSSL_AES_192
-        static char *EVP_AES_192_CTR = NULL;
+        static const char EVP_AES_192_CTR[] = "AES-192-CTR";
     #endif
     #ifdef WOLFSSL_AES_256
-        static char *EVP_AES_256_CTR = NULL;
-    #endif
-
+        static const char EVP_AES_256_CTR[] = "AES-256-CTR";
+    #endif
+    #endif
+
+    #ifdef HAVE_AES_ECB
     #ifdef WOLFSSL_AES_128
-        static char *EVP_AES_128_ECB = NULL;
+        static const char EVP_AES_128_ECB[] = "AES-128-ECB";
     #endif
     #ifdef WOLFSSL_AES_192
-        static char *EVP_AES_192_ECB = NULL;
+        static const char EVP_AES_192_ECB[] = "AES-192-ECB";
     #endif
     #ifdef WOLFSSL_AES_256
-        static char *EVP_AES_256_ECB = NULL;
+        static const char EVP_AES_256_ECB[] = "AES-256-ECB";
+    #endif
     #endif
         #define      EVP_AES_SIZE 11
@@ -141,9 +154,9 @@
 
 #ifndef NO_DES3
-    static char *EVP_DES_CBC = NULL;
-    static char *EVP_DES_ECB = NULL;
-
-    static char *EVP_DES_EDE3_CBC = NULL;
-    static char *EVP_DES_EDE3_ECB = NULL;
+    static const char EVP_DES_CBC[] = "DES-CBC";
+    static const char EVP_DES_ECB[] = "DES-ECB";
+
+    static const char EVP_DES_EDE3_CBC[] = "DES-EDE3-CBC";
+    static const char EVP_DES_EDE3_ECB[] = "DES-EDE3-ECB";
 
     #define EVP_DES_SIZE 7
@@ -152,7 +165,16 @@
 
 #ifdef HAVE_IDEA
-    static char *EVP_IDEA_CBC;
+    static const char EVP_IDEA_CBC[] = "IDEA-CBC";
     #define EVP_IDEA_SIZE 8
 #endif
+
+#ifndef NO_RC4
+    static const char EVP_ARC4[] = "ARC4";
+    #define EVP_ARC4_SIZE 4
+#endif
+
+static const char EVP_NULL[] = "NULL";
+#define EVP_NULL_SIZE 4
+
 
 static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher);
@@ -200,6 +222,7 @@
   #endif
   #if defined(WOLFSSL_AES_XTS)
-      case AES_128_XTS_TYPE: return 16;
-      case AES_256_XTS_TYPE: return 32;
+      /* Two keys for XTS. */
+      case AES_128_XTS_TYPE: return 16 * 2;
+      case AES_256_XTS_TYPE: return 32 * 2;
   #endif
   #if defined(HAVE_AESGCM)
@@ -418,45 +441,4 @@
             break;
     #endif
-    #if defined(HAVE_AESGCM)
-        case AES_128_GCM_TYPE:
-        case AES_192_GCM_TYPE:
-        case AES_256_GCM_TYPE:
-            if (ctx->enc) {
-                if (out){
-                    /* encrypt confidential data*/
-                    ret = wc_AesGcmEncrypt(&ctx->cipher.aes, out, in, inl,
-                              ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
-                              NULL, 0);
-                }
-                else {
-                    /* authenticated, non-confidential data */
-                    ret = wc_AesGcmEncrypt(&ctx->cipher.aes, NULL, NULL, 0,
-                              ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
-                              in, inl);
-                    /* Reset partial authTag error for AAD*/
-                    if (ret == AES_GCM_AUTH_E)
-                        ret = 0;
-                }
-            }
-            else {
-                if (out){
-                    /* decrypt confidential data*/
-                    ret = wc_AesGcmDecrypt(&ctx->cipher.aes, out, in, inl,
-                              ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
-                              NULL, 0);
-                }
-                else {
-                    /* authenticated, non-confidential data*/
-                    ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0,
-                              ctx->iv, ctx->ivSz,
-                              ctx->authTag, ctx->authTagSz,
-                              in, inl);
-                    /* Reset partial authTag error for AAD*/
-                    if (ret == AES_GCM_AUTH_E)
-                        ret = 0;
-                }
-            }
-            break;
-    #endif
     #if defined(WOLFSSL_AES_COUNTER)
         case AES_128_CTR_TYPE:
@@ -572,12 +554,56 @@
 
 #if defined(HAVE_AESGCM)
+static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx,
+        const unsigned char *in, int inl) {
+    if (in && inl > 0) {
+        byte* tmp = (byte*)XREALLOC(ctx->gcmAuthIn,
+                ctx->gcmAuthInSz + inl, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (tmp) {
+            ctx->gcmAuthIn = tmp;
+            XMEMCPY(ctx->gcmAuthIn + ctx->gcmAuthInSz, in, inl);
+            ctx->gcmAuthInSz += inl;
+        }
+        else {
+            WOLFSSL_MSG("realloc error");
+            return MEMORY_E;
+        }
+    }
+    return 0;
+}
+
 static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx,
                                    unsigned char *out, int *outl,
                                    const unsigned char *in, int inl)
 {
-    /* process blocks */
-    if (evpCipherBlock(ctx, out, in, inl) == 0)
+    int ret = 0;
+
+    *outl = inl;
+    if (out) {
+        /* Buffer input for one-shot API */
+        if (inl > 0) {
+            byte* tmp;
+            tmp = (byte*)XREALLOC(ctx->gcmBuffer,
+                    ctx->gcmBufferLen + inl, NULL,
+                    DYNAMIC_TYPE_OPENSSL);
+            if (tmp) {
+                XMEMCPY(tmp + ctx->gcmBufferLen, in, inl);
+                ctx->gcmBufferLen += inl;
+                ctx->gcmBuffer = tmp;
+                *outl = 0;
+            }
+            else {
+                ret = MEMORY_E;
+            }
+        }
+    }
+    else {
+        ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, in, inl);
+    }
+
+    if (ret != 0) {
+        *outl = 0;
         return WOLFSSL_FAILURE;
-    *outl = inl;
+    }
+
     return WOLFSSL_SUCCESS;
 }
@@ -599,7 +625,4 @@
 
     *outl = 0;
-    if (inl == 0) {
-        return WOLFSSL_SUCCESS;
-    }
 
 #if !defined(NO_AES) && defined(HAVE_AESGCM)
@@ -620,5 +643,8 @@
     }
 
-
+    /* if(inl == 0)wolfSSL_EVP_CipherUpdate_GCM to get tag */ 
+    if (inl == 0) {
+        return WOLFSSL_SUCCESS;
+    }
     if (ctx->bufUsed > 0) { /* concatenate them if there is anything */
         fill = fillBuff(ctx, in, inl);
@@ -740,77 +766,105 @@
 
     WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal");
-
+    switch (ctx->cipherType) {
 #if !defined(NO_AES) && defined(HAVE_AESGCM)
-        switch (ctx->cipherType) {
-            case AES_128_GCM_TYPE:
-            case AES_192_GCM_TYPE:
-            case AES_256_GCM_TYPE:
+        case AES_128_GCM_TYPE:
+        case AES_192_GCM_TYPE:
+        case AES_256_GCM_TYPE:
+            if ((ctx->gcmBuffer && ctx->gcmBufferLen > 0)
+             || (ctx->gcmBufferLen == 0)) {
+                if (ctx->enc)
+                    ret = wc_AesGcmEncrypt(&ctx->cipher.aes, out,
+                            ctx->gcmBuffer, ctx->gcmBufferLen,
+                            ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
+                            ctx->gcmAuthIn, ctx->gcmAuthInSz);
+                else
+                    ret = wc_AesGcmDecrypt(&ctx->cipher.aes, out,
+                            ctx->gcmBuffer, ctx->gcmBufferLen,
+                            ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
+                            ctx->gcmAuthIn, ctx->gcmAuthInSz);
+
+                if (ret == 0) {
+                    ret = WOLFSSL_SUCCESS;
+                    *outl = ctx->gcmBufferLen;
+                }
+                else {
+                    ret = WOLFSSL_FAILURE;
+                    *outl = 0;
+                }
+
+                XFREE(ctx->gcmBuffer, NULL, DYNAMIC_TYPE_OPENSSL);
+                ctx->gcmBuffer = NULL;
+                ctx->gcmBufferLen = 0;
+            }
+            else {
                 *outl = 0;
-                /* Clear IV, since IV reuse is not recommended for AES GCM. */
-                XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE);
-                return WOLFSSL_SUCCESS;
-            default:
-                /* fall-through */
-                break;
-        }
+            }
+            /* Clear IV, since IV reuse is not recommended for AES GCM. */
+            XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE);
+            break;
 #endif /* !NO_AES && HAVE_AESGCM */
-
-    if (!out)
-        return WOLFSSL_FAILURE;
-
-    if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) {
-        if (ctx->bufUsed != 0) return WOLFSSL_FAILURE;
-        *outl = 0;
-    }
-    else if (ctx->enc) {
-        if (ctx->block_size == 1) {
-            *outl = 0;
-        }
-        else if ((ctx->bufUsed >= 0) && (ctx->block_size != 1)) {
-            padBlock(ctx);
-            PRINT_BUF(ctx->buf, ctx->block_size);
-            if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) {
-                WOLFSSL_MSG("Final Cipher Block failed");
-                ret = WOLFSSL_FAILURE;
+        default:
+            if (!out)
+                return WOLFSSL_FAILURE;
+
+            if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) {
+                if (ctx->bufUsed != 0) return WOLFSSL_FAILURE;
+                *outl = 0;
+            }
+            else if (ctx->enc) {
+                if (ctx->block_size == 1) {
+                    *outl = 0;
+                }
+                else if ((ctx->bufUsed >= 0) && (ctx->block_size != 1)) {
+                    padBlock(ctx);
+                    PRINT_BUF(ctx->buf, ctx->block_size);
+                    if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) {
+                        WOLFSSL_MSG("Final Cipher Block failed");
+                        ret = WOLFSSL_FAILURE;
+                    }
+                    else {
+                        PRINT_BUF(out, ctx->block_size);
+                        *outl = ctx->block_size;
+                    }
+                }
             }
             else {
-                PRINT_BUF(out, ctx->block_size);
-                *outl = ctx->block_size;
-            }
-        }
-    }
-    else {
-        if (ctx->block_size == 1) {
-            *outl = 0;
-        }
-        else if ((ctx->bufUsed % ctx->block_size) != 0) {
-            *outl = 0;
-            /* not enough padding for decrypt */
-            WOLFSSL_MSG("Final Cipher Block not enough padding");
-            ret = WOLFSSL_FAILURE;
-        }
-        else if (ctx->lastUsed) {
-            PRINT_BUF(ctx->lastBlock, ctx->block_size);
-            if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) {
-                XMEMCPY(out, ctx->lastBlock, fl);
-                *outl = fl;
-                if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
-                    /* return error in cases where the block length is incorrect */
-                    WOLFSSL_MSG("Final Cipher Block bad length");
+                if (ctx->block_size == 1) {
+                    *outl = 0;
+                }
+                else if ((ctx->bufUsed % ctx->block_size) != 0) {
+                    *outl = 0;
+                    /* not enough padding for decrypt */
+                    WOLFSSL_MSG("Final Cipher Block not enough padding");
                     ret = WOLFSSL_FAILURE;
                 }
-            }
-            else {
-                ret = WOLFSSL_FAILURE;
-            }
-        }
-        else if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
-            /* return error in cases where the block length is incorrect */
-            ret = WOLFSSL_FAILURE;
-        }
-    }
+                else if (ctx->lastUsed) {
+                    PRINT_BUF(ctx->lastBlock, ctx->block_size);
+                    if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) {
+                        XMEMCPY(out, ctx->lastBlock, fl);
+                        *outl = fl;
+                        if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
+                            /* return error in cases where the block length is
+                             * incorrect */
+                            WOLFSSL_MSG("Final Cipher Block bad length");
+                            ret = WOLFSSL_FAILURE;
+                        }
+                    }
+                    else {
+                        ret = WOLFSSL_FAILURE;
+                    }
+                }
+                else if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
+                    /* return error in cases where the block length is
+                     * incorrect */
+                    ret = WOLFSSL_FAILURE;
+                }
+            }
+            break;
+    }
+
     if (ret == WOLFSSL_SUCCESS) {
         /* reset cipher state after final */
-        wolfSSL_EVP_CipherInit(ctx, NULL, NULL, NULL, -1);
+        ret = wolfSSL_EVP_CipherInit(ctx, NULL, NULL, NULL, -1);
     }
     return ret;
@@ -867,5 +921,4 @@
 #endif
 
-
 int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx)
 {
@@ -931,12 +984,12 @@
     if (cipher == NULL) return 0; /* dummy for #ifdef */
 #ifndef NO_DES3
-    else if (EVP_DES_CBC && XSTRNCMP(cipher, EVP_DES_CBC, EVP_DES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_DES_CBC, EVP_DES_SIZE) == 0)
         return DES_CBC_TYPE;
-    else if (EVP_DES_EDE3_CBC && XSTRNCMP(cipher, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)
         return DES_EDE3_CBC_TYPE;
 #if !defined(NO_DES3)
-    else if (EVP_DES_ECB && XSTRNCMP(cipher, EVP_DES_ECB, EVP_DES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_DES_ECB, EVP_DES_SIZE) == 0)
         return DES_ECB_TYPE;
-    else if (EVP_DES_EDE3_ECB && XSTRNCMP(cipher, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)
         return DES_EDE3_ECB_TYPE;
 #endif /* NO_DES3 && HAVE_AES_ECB */
@@ -945,13 +998,13 @@
 #if defined(HAVE_AES_CBC)
     #ifdef WOLFSSL_AES_128
-    else if (EVP_AES_128_CBC && XSTRNCMP(cipher, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)
         return AES_128_CBC_TYPE;
     #endif
     #ifdef WOLFSSL_AES_192
-    else if (EVP_AES_192_CBC && XSTRNCMP(cipher, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)
         return AES_192_CBC_TYPE;
     #endif
     #ifdef WOLFSSL_AES_256
-    else if (EVP_AES_256_CBC && XSTRNCMP(cipher, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)
         return AES_256_CBC_TYPE;
     #endif
@@ -959,13 +1012,13 @@
 #if defined(HAVE_AESGCM)
     #ifdef WOLFSSL_AES_128
-    else if (EVP_AES_128_GCM && XSTRNCMP(cipher, EVP_AES_128_GCM, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_128_GCM, EVP_AES_SIZE) == 0)
         return AES_128_GCM_TYPE;
     #endif
     #ifdef WOLFSSL_AES_192
-    else if (EVP_AES_192_GCM && XSTRNCMP(cipher, EVP_AES_192_GCM, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_192_GCM, EVP_AES_SIZE) == 0)
         return AES_192_GCM_TYPE;
     #endif
     #ifdef WOLFSSL_AES_256
-    else if (EVP_AES_256_GCM && XSTRNCMP(cipher, EVP_AES_256_GCM, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_256_GCM, EVP_AES_SIZE) == 0)
         return AES_256_GCM_TYPE;
     #endif
@@ -973,13 +1026,13 @@
 #if defined(WOLFSSL_AES_COUNTER)
     #ifdef WOLFSSL_AES_128
-    else if (EVP_AES_128_CTR && XSTRNCMP(cipher, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)
         return AES_128_CTR_TYPE;
     #endif
     #ifdef WOLFSSL_AES_192
-    else if (EVP_AES_192_CTR && XSTRNCMP(cipher, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)
         return AES_192_CTR_TYPE;
     #endif
     #ifdef WOLFSSL_AES_256
-    else if (EVP_AES_256_CTR && XSTRNCMP(cipher, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)
         return AES_256_CTR_TYPE;
     #endif
@@ -987,13 +1040,13 @@
 #if defined(HAVE_AES_ECB)
     #ifdef WOLFSSL_AES_128
-    else if (EVP_AES_128_ECB && XSTRNCMP(cipher, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)
         return AES_128_ECB_TYPE;
     #endif
     #ifdef WOLFSSL_AES_192
-    else if (EVP_AES_192_ECB && XSTRNCMP(cipher, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)
         return AES_192_ECB_TYPE;
     #endif
     #ifdef WOLFSSL_AES_256
-    else if (EVP_AES_256_ECB && XSTRNCMP(cipher, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)
         return AES_256_ECB_TYPE;
     #endif
@@ -1001,9 +1054,9 @@
 #if defined(WOLFSSL_AES_XTS)
     #ifdef WOLFSSL_AES_128
-    else if (EVP_AES_128_XTS && XSTRNCMP(cipher, EVP_AES_128_XTS, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_128_XTS, EVP_AES_SIZE) == 0)
         return AES_128_XTS_TYPE;
     #endif
     #ifdef WOLFSSL_AES_256
-    else if (EVP_AES_256_XTS && XSTRNCMP(cipher, EVP_AES_256_XTS, EVP_AES_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_256_XTS, EVP_AES_SIZE) == 0)
         return AES_256_XTS_TYPE;
     #endif
@@ -1011,41 +1064,60 @@
 #if defined(WOLFSSL_AES_CFB)
     #ifdef WOLFSSL_AES_128
-    else if (EVP_AES_128_CFB1 && XSTRNCMP(cipher, EVP_AES_128_CFB1, EVP_AESCFB_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_128_CFB1, EVP_AESCFB_SIZE) == 0)
         return AES_128_CFB1_TYPE;
     #endif
     #ifdef WOLFSSL_AES_192
-    else if (EVP_AES_192_CFB1 && XSTRNCMP(cipher, EVP_AES_192_CFB1, EVP_AESCFB_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_192_CFB1, EVP_AESCFB_SIZE) == 0)
         return AES_192_CFB1_TYPE;
     #endif
     #ifdef WOLFSSL_AES_256
-    else if (EVP_AES_256_CFB1 && XSTRNCMP(cipher, EVP_AES_256_CFB1, EVP_AESCFB_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_256_CFB1, EVP_AESCFB_SIZE) == 0)
         return AES_256_CFB1_TYPE;
     #endif
     #ifdef WOLFSSL_AES_128
-    else if (EVP_AES_128_CFB8 && XSTRNCMP(cipher, EVP_AES_128_CFB8, EVP_AESCFB_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_128_CFB8, EVP_AESCFB_SIZE) == 0)
         return AES_128_CFB8_TYPE;
     #endif
     #ifdef WOLFSSL_AES_192
-    else if (EVP_AES_192_CFB8 && XSTRNCMP(cipher, EVP_AES_192_CFB8, EVP_AESCFB_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_192_CFB8, EVP_AESCFB_SIZE) == 0)
         return AES_192_CFB8_TYPE;
     #endif
     #ifdef WOLFSSL_AES_256
-    else if (EVP_AES_256_CFB8 && XSTRNCMP(cipher, EVP_AES_256_CFB8, EVP_AESCFB_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_256_CFB8, EVP_AESCFB_SIZE) == 0)
         return AES_256_CFB8_TYPE;
     #endif
     #ifdef WOLFSSL_AES_128
-    else if (EVP_AES_128_CFB128 && XSTRNCMP(cipher, EVP_AES_128_CFB128, EVP_AESCFB_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_128_CFB128, EVP_AESCFB_SIZE) == 0)
         return AES_128_CFB128_TYPE;
     #endif
     #ifdef WOLFSSL_AES_192
-    else if (EVP_AES_192_CFB128 && XSTRNCMP(cipher, EVP_AES_192_CFB128, EVP_AESCFB_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_192_CFB128, EVP_AESCFB_SIZE) == 0)
         return AES_192_CFB128_TYPE;
     #endif
     #ifdef WOLFSSL_AES_256
-    else if (EVP_AES_256_CFB128 && XSTRNCMP(cipher, EVP_AES_256_CFB128, EVP_AESCFB_SIZE) == 0)
+    else if (XSTRNCMP(cipher, EVP_AES_256_CFB128, EVP_AESCFB_SIZE) == 0)
         return AES_256_CFB128_TYPE;
     #endif
 #endif /*HAVE_AES_CBC */
+#if defined(WOLFSSL_AES_OFB)
+    #ifdef WOLFSSL_AES_128
+    else if (XSTRNCMP(cipher, EVP_AES_128_OFB, EVP_AES_SIZE) == 0)
+      return AES_128_OFB_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    else if (XSTRNCMP(cipher, EVP_AES_192_OFB, EVP_AES_SIZE) == 0)
+      return AES_192_OFB_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    else if (XSTRNCMP(cipher, EVP_AES_256_OFB, EVP_AES_SIZE) == 0)
+      return AES_256_OFB_TYPE;
+    #endif
+#endif
 #endif /* !NO_AES */
+
+#ifndef NO_RC4
+    else if (XSTRNCMP(cipher, EVP_ARC4, EVP_ARC4_SIZE) == 0)
+      return ARC4_TYPE;
+#endif
       else return 0;
 }
@@ -1066,5 +1138,5 @@
       case AES_192_GCM_TYPE:
       case AES_256_GCM_TYPE:
-          return AES_BLOCK_SIZE;
+          return 1;
   #endif
   #if defined(WOLFSSL_AES_COUNTER)
@@ -1072,5 +1144,5 @@
       case AES_192_CTR_TYPE:
       case AES_256_CTR_TYPE:
-          return AES_BLOCK_SIZE;
+          return 1;
   #endif
   #if defined(HAVE_AES_ECB)
@@ -1080,11 +1152,40 @@
           return AES_BLOCK_SIZE;
   #endif
+  #if defined(WOLFSSL_AES_CFB)
+      case AES_128_CFB1_TYPE:
+      case AES_192_CFB1_TYPE:
+      case AES_256_CFB1_TYPE:
+      case AES_128_CFB8_TYPE:
+      case AES_192_CFB8_TYPE:
+      case AES_256_CFB8_TYPE:
+      case AES_128_CFB128_TYPE:
+      case AES_192_CFB128_TYPE:
+      case AES_256_CFB128_TYPE:
+          return 1;
+  #endif
+  #if defined(WOLFSSL_AES_OFB)
+      case AES_128_OFB_TYPE:
+      case AES_192_OFB_TYPE:
+      case AES_256_OFB_TYPE:
+          return 1;
+  #endif
+  #if defined(WOLFSSL_AES_XTS)
+      case AES_128_XTS_TYPE:
+      case AES_256_XTS_TYPE:
+          return 1;
+  #endif
 #endif /* NO_AES */
-  #ifndef NO_DES3
+
+#ifndef NO_RC4
+      case ARC4_TYPE:
+          return 1;
+#endif
+
+#ifndef NO_DES3
       case DES_CBC_TYPE: return 8;
       case DES_EDE3_CBC_TYPE: return 8;
       case DES_ECB_TYPE: return 8;
       case DES_EDE3_ECB_TYPE: return 8;
-  #endif
+#endif
       default:
           return 0;
@@ -1106,5 +1207,6 @@
         case AES_192_GCM_TYPE:
         case AES_256_GCM_TYPE:
-            return WOLFSSL_EVP_CIPH_GCM_MODE;
+            return WOLFSSL_EVP_CIPH_GCM_MODE &
+                    WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
     #endif
     #if defined(WOLFSSL_AES_COUNTER)
@@ -1114,9 +1216,32 @@
             return WOLFSSL_EVP_CIPH_CTR_MODE;
     #endif
+    #if defined(WOLFSSL_AES_CFB)
+        case AES_128_CFB1_TYPE:
+        case AES_192_CFB1_TYPE:
+        case AES_256_CFB1_TYPE:
+        case AES_128_CFB8_TYPE:
+        case AES_192_CFB8_TYPE:
+        case AES_256_CFB8_TYPE:
+        case AES_128_CFB128_TYPE:
+        case AES_192_CFB128_TYPE:
+        case AES_256_CFB128_TYPE:
+            return WOLFSSL_EVP_CIPH_CFB_MODE;
+    #endif
+    #if defined(WOLFSSL_AES_OFB)
+        case AES_128_OFB_TYPE:
+        case AES_192_OFB_TYPE:
+        case AES_256_OFB_TYPE:
+            return WOLFSSL_EVP_CIPH_OFB_MODE;
+    #endif
+    #if defined(WOLFSSL_AES_XTS)
+        case AES_128_XTS_TYPE:
+        case AES_256_XTS_TYPE:
+            return WOLFSSL_EVP_CIPH_XTS_MODE;
+    #endif
         case AES_128_ECB_TYPE:
         case AES_192_ECB_TYPE:
         case AES_256_ECB_TYPE:
             return WOLFSSL_EVP_CIPH_ECB_MODE;
-#endif /* NO_ASE */
+#endif /* NO_AES */
     #ifndef NO_DES3
         case DES_CBC_TYPE:
@@ -1209,5 +1334,4 @@
 {
     WOLFSSL_EVP_PKEY_CTX* ctx;
-    int type = NID_undef;
 
     if (pkey == NULL) return 0;
@@ -1223,13 +1347,6 @@
     ctx->padding = RSA_PKCS1_PADDING;
 #endif
-    type = wolfSSL_EVP_PKEY_type(pkey->type);
-
-    if (type != NID_undef) {
-        if (wc_LockMutex(&pkey->refMutex) != 0) {
-            WOLFSSL_MSG("Couldn't lock pkey mutex");
-        }
-        pkey->references++;
-
-        wc_UnLockMutex(&pkey->refMutex);
+    if (wolfSSL_EVP_PKEY_up_ref(pkey) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("Couldn't increase key reference count");
     }
     return ctx;
@@ -1264,7 +1381,10 @@
         pkey->type = id;
         ctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e);
-        if (ctx == NULL) {
-            wolfSSL_EVP_PKEY_free(pkey);
-        }
+        /* wolfSSL_EVP_PKEY_CTX_new calls wolfSSL_EVP_PKEY_up_ref so we need
+         * to always call wolfSSL_EVP_PKEY_free (either to free it if an
+         * error occured in the previous function or to decrease the reference
+         * count so that pkey is actually free'd when wolfSSL_EVP_PKEY_CTX_free
+         * is called) */
+        wolfSSL_EVP_PKEY_free(pkey);
     }
     return ctx;
@@ -1311,5 +1431,18 @@
 }
 
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_EVP_PKEY_CTX_ctrl_str(WOLFSSL_EVP_PKEY_CTX *ctx,
+                          const char *name, const char *value)
+{
+    WOLFSSL_STUB("wolfSSL_EVP_PKEY_CTX_ctrl_str");
+    (void)ctx;
+    (void)name;
+    (void)value;
+    return WOLFSSL_FAILURE;
+}
+#endif /* NO_WOLFSSL_STUB */
+
 #if !defined(NO_DH) && defined(HAVE_ECC)
+#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION!=2))
 int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
 {
@@ -1336,6 +1469,7 @@
                 return WOLFSSL_FAILURE;
             }
+            /* computed DH agreement can be less than DH size if leading zeros */
             if (wolfSSL_DH_compute_key(key, ctx->peerKey->dh->pub_key,
-                                       ctx->pkey->dh) != len) {
+                                       ctx->pkey->dh) <= 0) {
                 return WOLFSSL_FAILURE;
             }
@@ -1368,6 +1502,23 @@
         if (key) {
             word32 len32 = (word32)len;
+#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \
+    && (!defined(HAVE_FIPS) || \
+         (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2))
+
+            WC_RNG rng;
+            if (wc_InitRng(&rng) != MP_OKAY) {
+                WOLFSSL_MSG("Init RNG failed");
+                return WOLFSSL_FAILURE;
+            }
+            ((ecc_key*)ctx->pkey->ecc->internal)->rng = &rng;
+#endif
             if (*keylen < len32) {
                 WOLFSSL_MSG("buffer too short");
+#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \
+    && (!defined(HAVE_FIPS) || \
+         (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2))
+                ((ecc_key*)ctx->pkey->ecc->internal)->rng = NULL;
+                wc_FreeRng(&rng);
+#endif
                 return WOLFSSL_FAILURE;
             }
@@ -1376,6 +1527,18 @@
                                          key, &len32) != MP_OKAY) {
                 WOLFSSL_MSG("wc_ecc_shared_secret failed");
+#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \
+    && (!defined(HAVE_FIPS) || \
+         (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2))
+                ((ecc_key*)ctx->pkey->ecc->internal)->rng = NULL;
+                wc_FreeRng(&rng);
+#endif
                 return WOLFSSL_FAILURE;
             }
+#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \
+    && (!defined(HAVE_FIPS) || \
+         (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2))
+            ((ecc_key*)ctx->pkey->ecc->internal)->rng = NULL;
+            wc_FreeRng(&rng);
+#endif
             len = (int)len32;
         }
@@ -1389,5 +1552,6 @@
     return WOLFSSL_SUCCESS;
 }
-#endif
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
+#endif /* !NO_DH || HAVE_ECC */
 
 /* Uses the WOLFSSL_EVP_PKEY_CTX to decrypt a buffer.
@@ -1720,4 +1884,87 @@
 }
 
+
+int wolfSSL_EVP_PKEY_copy_parameters(WOLFSSL_EVP_PKEY *to,
+        const WOLFSSL_EVP_PKEY *from)
+{
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_copy_parameters");
+
+    if (!to || !from) {
+        WOLFSSL_MSG("Bad parameter");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (to->type == EVP_PKEY_NONE) {
+        to->type = from->type;
+    }
+    else if (to->type != from->type) {
+        WOLFSSL_MSG("Different key types");
+        return WOLFSSL_FAILURE;
+    }
+
+    switch(from->type) {
+#ifdef HAVE_ECC
+    case EVP_PKEY_EC:
+        if (from->ecc) {
+            if (!to->ecc && !(to->ecc = wolfSSL_EC_KEY_new())) {
+                WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
+                return WOLFSSL_FAILURE;
+            }
+            to->ownEcc = 1;
+            to->ecc->group->curve_idx = from->ecc->group->curve_idx;
+            to->ecc->group->curve_nid = from->ecc->group->curve_nid;
+            to->ecc->group->curve_oid = from->ecc->group->curve_oid;
+        }
+        else {
+            WOLFSSL_MSG("Missing ECC struct");
+            return WOLFSSL_FAILURE;
+        }
+        break;
+#endif
+#ifndef NO_DSA
+    case EVP_PKEY_DSA:
+        if (from->dsa) {
+            WOLFSSL_BIGNUM* cpy;
+            if (!to->dsa && !(to->dsa = wolfSSL_DSA_new())) {
+                WOLFSSL_MSG("wolfSSL_DSA_new error");
+                return WOLFSSL_FAILURE;
+            }
+            if (!(cpy = wolfSSL_BN_dup(from->dsa->p))) {
+                WOLFSSL_MSG("wolfSSL_BN_dup error");
+                return WOLFSSL_FAILURE;
+            }
+            to->dsa->p = cpy;
+            if (!(cpy = wolfSSL_BN_dup(from->dsa->q))) {
+                WOLFSSL_MSG("wolfSSL_BN_dup error");
+                return WOLFSSL_FAILURE;
+            }
+            to->dsa->q = cpy;
+            if (!(cpy = wolfSSL_BN_dup(from->dsa->g))) {
+                WOLFSSL_MSG("wolfSSL_BN_dup error");
+                return WOLFSSL_FAILURE;
+            }
+            to->dsa->g = cpy;
+        }
+        else {
+            WOLFSSL_MSG("Missing DSA struct");
+            return WOLFSSL_FAILURE;
+        }
+        break;
+#endif
+#ifndef NO_RSA
+    case EVP_PKEY_RSA:
+#endif
+#ifndef NO_DH
+    case EVP_PKEY_DH:
+#endif
+    default:
+        WOLFSSL_MSG("Copy parameters not available for this key type");
+        return WOLFSSL_FAILURE;
+    }
+#if defined(HAVE_ECC) || !defined(NO_DSA)
+    return WOLFSSL_SUCCESS;
+#endif
+}
+
 #ifndef NO_WOLFSSL_STUB
 WOLFSSL_API int wolfSSL_EVP_PKEY_missing_parameters(WOLFSSL_EVP_PKEY *pkey)
@@ -1760,5 +2007,5 @@
 #endif /* HAVE_ECC */
     default:
-        break;
+        return ret;
     } /* switch (a->type) */
 
@@ -1824,5 +2071,5 @@
 
 static const struct s_ent {
-    const int macType;
+    const enum wc_HashType macType;
     const int nid;
     const char *name;
@@ -1837,5 +2084,6 @@
 
 #ifndef NO_SHA
-    {WC_HASH_TYPE_SHA, NID_sha1, "SHA"},
+    {WC_HASH_TYPE_SHA, NID_sha1, "SHA1"},
+    {WC_HASH_TYPE_SHA, NID_sha1, "SHA"}, /* Leave for backwards compatibility */
 #endif /* NO_SHA */
 
@@ -1859,12 +2107,14 @@
     {WC_HASH_TYPE_SHA3_256, NID_sha3_256, "SHA3_256"},
 #endif
+#ifndef WOLFSSL_NOSHA3_384
     {WC_HASH_TYPE_SHA3_384, NID_sha3_384, "SHA3_384"},
+#endif
 #ifndef WOLFSSL_NOSHA3_512
     {WC_HASH_TYPE_SHA3_512, NID_sha3_512, "SHA3_512"},
 #endif
-    {0, 0, NULL}
+    {WC_HASH_TYPE_NONE, 0, NULL}
 };
 
-static int wolfSSL_EVP_md2macType(const WOLFSSL_EVP_MD *md)
+static enum wc_HashType wolfSSL_EVP_md2macType(const WOLFSSL_EVP_MD *md)
 {
     const struct s_ent *ent ;
@@ -2047,5 +2297,4 @@
 }
 
-
 /* Initialize an EVP_DigestSign/Verify operation.
  * Initialize a digest for RSA and ECC keys, or HMAC for HMAC key.
@@ -2057,8 +2306,20 @@
                                       WOLFSSL_EVP_PKEY *pkey)
 {
+    if (!type) {
+        int default_digest;
+        if (wolfSSL_EVP_PKEY_get_default_digest_nid(pkey, &default_digest)
+                != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Could not get default digest");
+            return WOLFSSL_FAILURE;
+        }
+        type = wolfSSL_EVP_get_digestbynid(default_digest);
+        if (!type) {
+            return BAD_FUNC_ARG;
+        }
+    }
+
     if (pkey->type == EVP_PKEY_HMAC) {
         int                  hashType;
         const unsigned char* key;
-        size_t               keySz;
 
         if (XSTRNCMP(type, "SHA256", 6) == 0) {
@@ -2080,4 +2341,24 @@
         }
     #endif
+#ifdef WOLFSSL_SHA3
+    #ifndef WOLFSSL_NOSHA3_224
+        else if (XSTRNCMP(type, "SHA3_224", 8) == 0) {
+            hashType = WC_SHA3_224;
+        }
+    #endif
+    #ifndef WOLFSSL_NOSHA3_256
+        else if (XSTRNCMP(type, "SHA3_256", 8) == 0) {
+            hashType = WC_SHA3_256;
+        }
+    #endif
+        else if (XSTRNCMP(type, "SHA3_384", 8) == 0) {
+            hashType = WC_SHA3_384;
+        }
+    #ifndef WOLFSSL_NOSHA3_512
+        else if (XSTRNCMP(type, "SHA3_512", 8) == 0) {
+            hashType = WC_SHA3_512;
+        }
+    #endif
+#endif
     #ifndef NO_MD5
         else if (XSTRNCMP(type, "MD5", 3) == 0) {
@@ -2088,5 +2369,5 @@
         /* has to be last since would pick or 224, 256, 384, or 512 too */
         else if (XSTRNCMP(type, "SHA", 3) == 0) {
-             hashType = WC_SHA;
+            hashType = WC_SHA;
         }
     #endif /* NO_SHA */
@@ -2094,29 +2375,28 @@
              return BAD_FUNC_ARG;
 
-        key = wolfSSL_EVP_PKEY_get0_hmac(pkey, &keySz);
-
-        if (wc_HmacInit(&ctx->hash.hmac, NULL, INVALID_DEVID) != 0)
+        {
+            size_t keySz = 0;
+
+            key = wolfSSL_EVP_PKEY_get0_hmac(pkey, &keySz);
+
+            if (wc_HmacInit(&ctx->hash.hmac, NULL, INVALID_DEVID) != 0)
+                return WOLFSSL_FAILURE;
+
+            if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0)
+                return WOLFSSL_FAILURE;
+        }
+
+        ctx->isHMAC = 1;
+    }
+    else if (wolfSSL_EVP_DigestInit(ctx, type) != 1)
             return WOLFSSL_FAILURE;
 
-        if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0)
+    if (ctx->pctx == NULL) {
+        ctx->pctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e);
+        if (ctx->pctx == NULL)
             return WOLFSSL_FAILURE;
-
-        ctx->macType = NID_hmac;
-    }
-    else {
-        int ret;
-
-        if (ctx->pctx == NULL) {
-            ctx->pctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e);
-            if (ctx->pctx == NULL)
-                return WOLFSSL_FAILURE;
-        }
-
-        ret = wolfSSL_EVP_DigestInit(ctx, type);
-        if (ret == WOLFSSL_SUCCESS && pctx != NULL)
-            *pctx = ctx->pctx;
-        return ret;
-    }
-
+    }
+    if (pctx != NULL)
+        *pctx = ctx->pctx;
     return WOLFSSL_SUCCESS;
 }
@@ -2128,8 +2408,5 @@
                                         const void *d, unsigned int cnt)
 {
-    if (ctx->pctx == NULL) {
-        if (ctx->macType != NID_hmac)
-            return WOLFSSL_FAILURE;
-
+    if (ctx->isHMAC) {
         if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0)
             return WOLFSSL_FAILURE;
@@ -2150,9 +2427,6 @@
     int  ret;
 
-    if (ctx->pctx == NULL) {
+    if (ctx->isHMAC) {
         Hmac hmacCopy;
-
-        if (ctx->macType != NID_hmac)
-            return WOLFSSL_FAILURE;
 
         if (wolfSSL_HmacCopy(&hmacCopy, &ctx->hash.hmac) != WOLFSSL_SUCCESS)
@@ -2221,4 +2495,27 @@
     #endif /* HAVE_BLAKE2 */
 
+    #ifdef WOLFSSL_SHA3
+        #ifndef WOLFSSL_NOSHA3_224
+        case WC_SHA3_224:
+            hashLen = WC_SHA3_224_DIGEST_SIZE;
+            break;
+        #endif
+        #ifndef WOLFSSL_NOSHA3_256
+        case WC_SHA3_256:
+            hashLen = WC_SHA3_256_DIGEST_SIZE;
+            break;
+        #endif
+        #ifndef WOLFSSL_NOSHA3_384
+        case WC_SHA3_384:
+            hashLen = WC_SHA3_384_DIGEST_SIZE;
+            break;
+        #endif
+        #ifndef WOLFSSL_NOSHA3_512
+        case WC_SHA3_512:
+            hashLen = WC_SHA3_512_DIGEST_SIZE;
+            break;
+        #endif
+    #endif
+
         default:
             hashLen = 0;
@@ -2236,5 +2533,5 @@
     WOLFSSL_ENTER("EVP_DigestSignInit");
 
-    if (ctx == NULL || type == NULL || pkey == NULL)
+    if (ctx == NULL || pkey == NULL)
         return BAD_FUNC_ARG;
 
@@ -2267,8 +2564,5 @@
 
     /* Return the maximum size of the signaure when sig is NULL. */
-    if (ctx->pctx == NULL) {
-        if (ctx->macType != NID_hmac)
-            return WOLFSSL_FAILURE;
-
+    if (ctx->isHMAC) {
         hashLen = wolfssl_mac_len(ctx->hash.hmac.macType);
 
@@ -2300,5 +2594,5 @@
         return WOLFSSL_FAILURE;
 
-    if (ctx->pctx == NULL) {
+    if (ctx->isHMAC) {
         /* Copy the HMAC result as signature. */
         if ((unsigned int)(*siglen) > hashLen)
@@ -2318,6 +2612,6 @@
             if (nid < 0)
                 break;
-            ret = wolfSSL_RSA_sign(nid, digest, hashLen, sig, &sigSz,
-                                   ctx->pctx->pkey->rsa);
+            ret = wolfSSL_RSA_sign_generic_padding(nid, digest, hashLen,
+                    sig, &sigSz, ctx->pctx->pkey->rsa, 1, ctx->pctx->padding);
             if (ret >= 0)
                 *siglen = sigSz;
@@ -2385,7 +2679,5 @@
         return WOLFSSL_FAILURE;
 
-    if (ctx->pctx == NULL) {
-        if (ctx->macType != NID_hmac)
-            return WOLFSSL_FAILURE;
+    if (ctx->isHMAC) {
 
         hashLen = wolfssl_mac_len(ctx->hash.hmac.macType);
@@ -2399,5 +2691,5 @@
         return WOLFSSL_FAILURE;
 
-    if (ctx->pctx == NULL) {
+    if (ctx->isHMAC) {
         /* Check HMAC result matches the signature. */
         if (XMEMCMP(sig, digest, siglen) == 0)
@@ -2413,7 +2705,7 @@
             if (nid < 0)
                 return WOLFSSL_FAILURE;
-            return wolfSSL_RSA_verify(nid, digest, hashLen, sig,
+            return wolfSSL_RSA_verify_ex(nid, digest, hashLen, sig,
                                       (unsigned int)siglen,
-                                      ctx->pctx->pkey->rsa);
+                                      ctx->pctx->pkey->rsa, ctx->pctx->padding);
         }
     #endif /* NO_RSA */
@@ -2574,106 +2866,120 @@
 
 #ifndef NO_AES
+    #ifdef HAVE_AES_CBC
     #ifdef WOLFSSL_AES_128
-    {AES_128_CBC_TYPE, "AES-128-CBC", NID_aes_128_cbc},
+    {AES_128_CBC_TYPE, EVP_AES_128_CBC, NID_aes_128_cbc},
     #endif
     #ifdef WOLFSSL_AES_192
-    {AES_192_CBC_TYPE, "AES-192-CBC", NID_aes_192_cbc},
+    {AES_192_CBC_TYPE, EVP_AES_192_CBC, NID_aes_192_cbc},
     #endif
     #ifdef WOLFSSL_AES_256
-    {AES_256_CBC_TYPE, "AES-256-CBC", NID_aes_256_cbc},
-    #endif
-
+    {AES_256_CBC_TYPE, EVP_AES_256_CBC, NID_aes_256_cbc},
+    #endif
+    #endif
+
+    #ifdef WOLFSSL_AES_CFB
     #ifdef WOLFSSL_AES_128
-    {AES_128_CFB1_TYPE, "AES-128-CFB1", NID_aes_128_cfb1},
+    {AES_128_CFB1_TYPE, EVP_AES_128_CFB1, NID_aes_128_cfb1},
     #endif
     #ifdef WOLFSSL_AES_192
-    {AES_192_CFB1_TYPE, "AES-192-CFB1", NID_aes_192_cfb1},
+    {AES_192_CFB1_TYPE, EVP_AES_192_CFB1, NID_aes_192_cfb1},
     #endif
     #ifdef WOLFSSL_AES_256
-    {AES_256_CFB1_TYPE, "AES-256-CFB1", NID_aes_256_cfb1},
+    {AES_256_CFB1_TYPE, EVP_AES_256_CFB1, NID_aes_256_cfb1},
     #endif
 
     #ifdef WOLFSSL_AES_128
-    {AES_128_CFB8_TYPE, "AES-128-CFB8", NID_aes_128_cfb8},
+    {AES_128_CFB8_TYPE, EVP_AES_128_CFB8, NID_aes_128_cfb8},
     #endif
     #ifdef WOLFSSL_AES_192
-    {AES_192_CFB8_TYPE, "AES-192-CFB8", NID_aes_192_cfb8},
+    {AES_192_CFB8_TYPE, EVP_AES_192_CFB8, NID_aes_192_cfb8},
     #endif
     #ifdef WOLFSSL_AES_256
-    {AES_256_CFB8_TYPE, "AES-256-CFB8", NID_aes_256_cfb8},
+    {AES_256_CFB8_TYPE, EVP_AES_256_CFB8, NID_aes_256_cfb8},
     #endif
 
     #ifdef WOLFSSL_AES_128
-    {AES_128_CFB128_TYPE, "AES-128-CFB128", NID_aes_128_cfb128},
+    {AES_128_CFB128_TYPE, EVP_AES_128_CFB128, NID_aes_128_cfb128},
     #endif
     #ifdef WOLFSSL_AES_192
-    {AES_192_CFB128_TYPE, "AES-192-CFB128", NID_aes_192_cfb128},
+    {AES_192_CFB128_TYPE, EVP_AES_192_CFB128, NID_aes_192_cfb128},
     #endif
     #ifdef WOLFSSL_AES_256
-    {AES_256_CFB128_TYPE, "AES-256-CFB128", NID_aes_256_cfb128},
-    #endif
-
+    {AES_256_CFB128_TYPE, EVP_AES_256_CFB128, NID_aes_256_cfb128},
+    #endif
+    #endif
+
+    #ifdef HAVE_AES_OFB
     #ifdef WOLFSSL_AES_128
-    {AES_128_OFB_TYPE, "AES-128-OFB", NID_aes_128_ofb},
+    {AES_128_OFB_TYPE, EVP_AES_128_OFB, NID_aes_128_ofb},
     #endif
     #ifdef WOLFSSL_AES_192
-    {AES_192_OFB_TYPE, "AES-192-OFB", NID_aes_192_ofb},
+    {AES_192_OFB_TYPE, EVP_AES_192_OFB, NID_aes_192_ofb},
     #endif
     #ifdef WOLFSSL_AES_256
-    {AES_256_OFB_TYPE, "AES-256-OFB", NID_aes_256_ofb},
-    #endif
-
+    {AES_256_OFB_TYPE, EVP_AES_256_OFB, NID_aes_256_ofb},
+    #endif
+    #endif
+
+    #ifdef HAVE_AES_XTS
     #ifdef WOLFSSL_AES_128
-    {AES_128_XTS_TYPE, "AES-128-XTS", NID_aes_128_xts},
+    {AES_128_XTS_TYPE, EVP_AES_128_XTS, NID_aes_128_xts},
     #endif
     #ifdef WOLFSSL_AES_256
-    {AES_256_XTS_TYPE, "AES-256-XTS", NID_aes_256_xts},
-    #endif
-
+    {AES_256_XTS_TYPE, EVP_AES_256_XTS, NID_aes_256_xts},
+    #endif
+    #endif
+
+    #ifdef HAVE_AESGCM
     #ifdef WOLFSSL_AES_128
-    {AES_128_GCM_TYPE, "AES-128-GCM", NID_aes_128_gcm},
+    {AES_128_GCM_TYPE, EVP_AES_128_GCM, NID_aes_128_gcm},
     #endif
     #ifdef WOLFSSL_AES_192
-    {AES_192_GCM_TYPE, "AES-192-GCM", NID_aes_192_gcm},
+    {AES_192_GCM_TYPE, EVP_AES_192_GCM, NID_aes_192_gcm},
     #endif
     #ifdef WOLFSSL_AES_256
-    {AES_256_GCM_TYPE, "AES-256-GCM", NID_aes_256_gcm},
-    #endif
+    {AES_256_GCM_TYPE, EVP_AES_256_GCM, NID_aes_256_gcm},
+    #endif
+    #endif
+
+    #ifdef WOLFSSL_AES_COUNTER
     #ifdef WOLFSSL_AES_128
-        {AES_128_CTR_TYPE, "AES-128-CTR", NID_aes_128_ctr},
+        {AES_128_CTR_TYPE, EVP_AES_128_CTR, NID_aes_128_ctr},
     #endif
     #ifdef WOLFSSL_AES_192
-        {AES_192_CTR_TYPE, "AES-192-CTR", NID_aes_192_ctr},
+        {AES_192_CTR_TYPE, EVP_AES_192_CTR, NID_aes_192_ctr},
     #endif
     #ifdef WOLFSSL_AES_256
-        {AES_256_CTR_TYPE, "AES-256-CTR", NID_aes_256_ctr},
-    #endif
-
+        {AES_256_CTR_TYPE, EVP_AES_256_CTR, NID_aes_256_ctr},
+    #endif
+    #endif
+
+    #ifdef HAVE_AES_ECB
     #ifdef WOLFSSL_AES_128
-        {AES_128_ECB_TYPE, "AES-128-ECB", NID_aes_128_ecb},
+        {AES_128_ECB_TYPE, EVP_AES_128_ECB, NID_aes_128_ecb},
     #endif
     #ifdef WOLFSSL_AES_192
-        {AES_192_ECB_TYPE, "AES-192-ECB", NID_aes_192_ecb},
+        {AES_192_ECB_TYPE, EVP_AES_192_ECB, NID_aes_192_ecb},
     #endif
     #ifdef WOLFSSL_AES_256
-        {AES_256_ECB_TYPE, "AES-256-ECB", NID_aes_256_ecb},
-    #endif
-
+        {AES_256_ECB_TYPE, EVP_AES_256_ECB, NID_aes_256_ecb},
+    #endif
+    #endif
 #endif
 
 #ifndef NO_DES3
-    {DES_CBC_TYPE, "DES-CBC", NID_des_cbc},
-    {DES_ECB_TYPE, "DES-ECB", NID_des_ecb},
-
-    {DES_EDE3_CBC_TYPE, "DES-EDE3-CBC", NID_des_ede3_cbc},
-    {DES_EDE3_ECB_TYPE, "DES-EDE3-ECB", NID_des_ede3_ecb},
+    {DES_CBC_TYPE, EVP_DES_CBC, NID_des_cbc},
+    {DES_ECB_TYPE, EVP_DES_ECB, NID_des_ecb},
+
+    {DES_EDE3_CBC_TYPE, EVP_DES_EDE3_CBC, NID_des_ede3_cbc},
+    {DES_EDE3_ECB_TYPE, EVP_DES_EDE3_ECB, NID_des_ede3_ecb},
 #endif
 
 #ifndef NO_RC4
-    {ARC4_TYPE, "ARC4", NID_undef},
+    {ARC4_TYPE, EVP_ARC4, NID_undef},
 #endif
 
 #ifdef HAVE_IDEA
-    {IDEA_CBC_TYPE, "IDEA-CBC", NID_idea_cbc},
+    {IDEA_CBC_TYPE, EVP_IDEA_CBC, NID_idea_cbc},
 #endif
     { 0, NULL, 0}
@@ -2719,5 +3025,5 @@
 {
 
-    static const struct alias {
+    const struct alias {
         const char *name;
         const char *alias;
@@ -2725,61 +3031,63 @@
     {
 #ifndef NO_DES3
-        {"DES-CBC", "DES"},
-        {"DES-CBC", "des"},
-        {"DES-ECB", "DES-ECB"},
-        {"DES-ECB", "des-ecb"},
-        {"DES-EDE3-CBC", "DES3"},
-        {"DES-EDE3-CBC", "des3"},
-        {"DES-EDE3-ECB", "DES-EDE3"},
-        {"DES-EDE3-ECB", "des-ede3"},
-        {"DES-EDE3-ECB", "des-ede3-ecb"},
+        {EVP_DES_CBC, "DES"},
+        {EVP_DES_CBC, "des"},
+        {EVP_DES_ECB, "DES-ECB"},
+        {EVP_DES_ECB, "des-ecb"},
+        {EVP_DES_EDE3_CBC, "DES3"},
+        {EVP_DES_EDE3_CBC, "des3"},
+        {EVP_DES_EDE3_ECB, "DES-EDE3"},
+        {EVP_DES_EDE3_ECB, "des-ede3"},
+        {EVP_DES_EDE3_ECB, "des-ede3-ecb"},
 #endif
 #ifdef HAVE_IDEA
-        {"IDEA-CBC", "IDEA"},
-        {"IDEA-CBC", "idea"},
+        {EVP_IDEA_CBC, "IDEA"},
+        {EVP_IDEA_CBC, "idea"},
 #endif
 #ifndef NO_AES
     #ifdef HAVE_AES_CBC
         #ifdef WOLFSSL_AES_128
-        {"AES-128-CBC", "AES128-CBC"},
-        {"AES-128-CBC", "aes128-cbc"},
+            {EVP_AES_128_CBC, "AES128-CBC"},
+            {EVP_AES_128_CBC, "aes128-cbc"},
         #endif
         #ifdef WOLFSSL_AES_192
-        {"AES-192-CBC", "AES192-CBC"},
-        {"AES-192-CBC", "aes192-cbc"},
+            {EVP_AES_192_CBC, "AES192-CBC"},
+            {EVP_AES_192_CBC, "aes192-cbc"},
         #endif
         #ifdef WOLFSSL_AES_256
-        {"AES-256-CBC", "AES256-CBC"},
-        {"AES-256-CBC", "aes256-cbc"},
+            {EVP_AES_256_CBC, "AES256-CBC"},
+            {EVP_AES_256_CBC, "aes256-cbc"},
         #endif
     #endif
-    #ifdef WOLFSSL_AES_128
-        {"AES-128-ECB", "AES128-ECB"},
-        {"AES-128-ECB", "aes128-ecb"},
-    #endif
-    #ifdef WOLFSSL_AES_192
-        {"AES-192-ECB", "AES192-ECB"},
-        {"AES-192-ECB", "aes192-ecb"},
-    #endif
-    #ifdef WOLFSSL_AES_256
-        {"AES-256-ECB", "AES256-ECB"},
+    #ifdef HAVE_AES_ECB
+        #ifdef WOLFSSL_AES_128
+            {EVP_AES_128_ECB, "AES128-ECB"},
+            {EVP_AES_128_ECB, "aes128-ecb"},
+        #endif
+        #ifdef WOLFSSL_AES_192
+            {EVP_AES_192_ECB, "AES192-ECB"},
+            {EVP_AES_192_ECB, "aes192-ecb"},
+        #endif
+        #ifdef WOLFSSL_AES_256
+            {EVP_AES_256_ECB, "AES256-ECB"},
+        #endif
     #endif
     #ifdef HAVE_AESGCM
         #ifdef WOLFSSL_AES_128
-        {"AES-128-GCM", "aes-128-gcm"},
-        {"AES-128-GCM", "id-aes128-GCM"},
+            {EVP_AES_128_GCM, "aes-128-gcm"},
+            {EVP_AES_128_GCM, "id-aes128-GCM"},
         #endif
         #ifdef WOLFSSL_AES_192
-        {"AES-192-GCM", "aes-192-gcm"},
-        {"AES-192-GCM", "id-aes192-GCM"},
+            {EVP_AES_192_GCM, "aes-192-gcm"},
+            {EVP_AES_192_GCM, "id-aes192-GCM"},
         #endif
         #ifdef WOLFSSL_AES_256
-        {"AES-256-GCM", "aes-256-gcm"},
-        {"AES-256-GCM", "id-aes256-GCM"},
+            {EVP_AES_256_GCM, "aes-256-gcm"},
+            {EVP_AES_256_GCM, "id-aes256-GCM"},
         #endif
     #endif
 #endif
 #ifndef NO_RC4
-        {"ARC4", "RC4"},
+        {EVP_ARC4, "RC4"},
 #endif
         { NULL, NULL}
@@ -2906,194 +3214,8 @@
 void wolfSSL_EVP_init(void)
 {
-#ifndef NO_AES
-    #ifdef HAVE_AES_CBC
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_CBC = (char *)EVP_get_cipherbyname("AES-128-CBC");
-        #endif
-        #ifdef WOLFSSL_AES_192
-        EVP_AES_192_CBC = (char *)EVP_get_cipherbyname("AES-192-CBC");
-        #endif
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_CBC = (char *)EVP_get_cipherbyname("AES-256-CBC");
-        #endif
-    #endif /* HAVE_AES_CBC */
-
-    #ifdef WOLFSSL_AES_CFB
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_CFB1 = (char *)EVP_get_cipherbyname("AES-128-CFB1");
-        #endif
-
-        #ifdef WOLFSSL_AES_192
-        EVP_AES_192_CFB1 = (char *)EVP_get_cipherbyname("AES-192-CFB1");
-        #endif
-
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_CFB1 = (char *)EVP_get_cipherbyname("AES-256-CFB1");
-        #endif
-
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_CFB8 = (char *)EVP_get_cipherbyname("AES-128-CFB8");
-        #endif
-
-        #ifdef WOLFSSL_AES_192
-        EVP_AES_192_CFB8 = (char *)EVP_get_cipherbyname("AES-192-CFB8");
-        #endif
-
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_CFB8 = (char *)EVP_get_cipherbyname("AES-256-CFB8");
-        #endif
-
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_CFB128 = (char *)EVP_get_cipherbyname("AES-128-CFB128");
-        #endif
-
-        #ifdef WOLFSSL_AES_192
-        EVP_AES_192_CFB128 = (char *)EVP_get_cipherbyname("AES-192-CFB128");
-        #endif
-
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_CFB128 = (char *)EVP_get_cipherbyname("AES-256-CFB128");
-        #endif
-    #endif /* WOLFSSL_AES_CFB */
-
-    #ifdef WOLFSSL_AES_OFB
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_OFB = (char *)EVP_get_cipherbyname("AES-128-OFB");
-        #endif
-
-        #ifdef WOLFSSL_AES_192
-        EVP_AES_192_OFB = (char *)EVP_get_cipherbyname("AES-192-OFB");
-        #endif
-
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_OFB = (char *)EVP_get_cipherbyname("AES-256-OFB");
-        #endif
-    #endif /* WOLFSSL_AES_OFB */
-
-    #ifdef WOLFSSL_AES_XTS
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_XTS = (char *)EVP_get_cipherbyname("AES-128-XTS");
-        #endif
-
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_XTS = (char *)EVP_get_cipherbyname("AES-256-XTS");
-        #endif
-    #endif /* WOLFSSL_AES_XTS */
-
-    #ifdef HAVE_AESGCM
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_GCM = (char *)EVP_get_cipherbyname("AES-128-GCM");
-        #endif
-        #ifdef WOLFSSL_AES_192
-        EVP_AES_192_GCM = (char *)EVP_get_cipherbyname("AES-192-GCM");
-        #endif
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_GCM = (char *)EVP_get_cipherbyname("AES-256-GCM");
-        #endif
-    #endif /* HAVE_AESGCM*/
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_CTR = (char *)EVP_get_cipherbyname("AES-128-CTR");
-        #endif
-        #ifdef WOLFSSL_AES_192
-        EVP_AES_192_CTR = (char *)EVP_get_cipherbyname("AES-192-CTR");
-        #endif
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_CTR = (char *)EVP_get_cipherbyname("AES-256-CTR");
-        #endif
-
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_ECB = (char *)EVP_get_cipherbyname("AES-128-ECB");
-        #endif
-        #ifdef WOLFSSL_AES_192
-        EVP_AES_192_ECB = (char *)EVP_get_cipherbyname("AES-192-ECB");
-        #endif
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_ECB = (char *)EVP_get_cipherbyname("AES-256-ECB");
-        #endif
-#endif /* ifndef NO_AES*/
-
-#ifndef NO_DES3
-    EVP_DES_CBC = (char *)EVP_get_cipherbyname("DES-CBC");
-    EVP_DES_ECB = (char *)EVP_get_cipherbyname("DES-ECB");
-
-    EVP_DES_EDE3_CBC = (char *)EVP_get_cipherbyname("DES-EDE3-CBC");
-    EVP_DES_EDE3_ECB = (char *)EVP_get_cipherbyname("DES-EDE3-ECB");
-#endif
-
-#ifdef HAVE_IDEA
-    EVP_IDEA_CBC = (char *)EVP_get_cipherbyname("IDEA-CBC");
-#endif
+    /* Does nothing. */
 }
 
 #if !defined(NO_PWDBASED)
-int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp,
-    int* pHash, int* pHashSz)
-{
-    enum wc_HashType hash = WC_HASH_TYPE_NONE;
-    int hashSz;
-
-    if (XSTRLEN(evp) < 3) {
-        /* do not try comparing strings if size is too small */
-        return WOLFSSL_FAILURE;
-    }
-
-    if (XSTRNCMP("SHA", evp, 3) == 0) {
-        if (XSTRLEN(evp) > 3) {
-        #ifndef NO_SHA256
-            if (XSTRNCMP("SHA256", evp, 6) == 0) {
-                hash = WC_HASH_TYPE_SHA256;
-            }
-            else
-        #endif
-        #ifdef WOLFSSL_SHA384
-            if (XSTRNCMP("SHA384", evp, 6) == 0) {
-                hash = WC_HASH_TYPE_SHA384;
-            }
-            else
-        #endif
-        #ifdef WOLFSSL_SHA512
-            if (XSTRNCMP("SHA512", evp, 6) == 0) {
-                hash = WC_HASH_TYPE_SHA512;
-            }
-            else
-        #endif
-            {
-                WOLFSSL_MSG("Unknown SHA hash");
-            }
-        }
-        else {
-            hash = WC_HASH_TYPE_SHA;
-        }
-    }
-#ifdef WOLFSSL_MD2
-    else if (XSTRNCMP("MD2", evp, 3) == 0) {
-        hash = WC_HASH_TYPE_MD2;
-    }
-#endif
-#ifndef NO_MD4
-    else if (XSTRNCMP("MD4", evp, 3) == 0) {
-        hash = WC_HASH_TYPE_MD4;
-    }
-#endif
-#ifndef NO_MD5
-    else if (XSTRNCMP("MD5", evp, 3) == 0) {
-        hash = WC_HASH_TYPE_MD5;
-    }
-#endif
-
-    if (pHash)
-        *pHash = hash;
-
-    hashSz = wc_HashGetDigestSize(hash);
-    if (pHashSz)
-        *pHashSz = hashSz;
-
-    if (hashSz < 0) {
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
 /* this function makes the assumption that out buffer is big enough for digest*/
 int wolfSSL_EVP_Digest(const unsigned char* in, int inSz, unsigned char* out,
@@ -3136,13 +3258,23 @@
         {"MD4", "ssl3-md4"},
         {"MD5", "ssl3-md5"},
-        {"SHA", "ssl3-sha1"},
-        {"SHA", "SHA1"},
+        {"SHA1", "ssl3-sha1"},
+        {"SHA1", "SHA"},
         { NULL, NULL}
     };
+    char nameUpper[15]; /* 15 bytes should be enough for any name */
+    size_t i;
 
     const struct alias  *al;
     const struct s_ent *ent;
 
-
+    for (i = 0; i < sizeof(nameUpper) && name[i] != '\0'; i++) {
+        nameUpper[i] = (char)XTOUPPER(name[i]);
+    }
+    if (i < sizeof(nameUpper))
+        nameUpper[i] = '\0';
+    else
+        return NULL;
+
+    name = nameUpper;
     for (al = alias_tbl; al->name != NULL; al++)
         if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) {
@@ -3205,5 +3337,5 @@
     {
         WOLFSSL_ENTER("EVP_sha1");
-        return EVP_get_digestbyname("SHA");
+        return EVP_get_digestbyname("SHA1");
     }
 #endif /* NO_SHA */
@@ -3295,11 +3427,12 @@
         if (ctx) {
             WOLFSSL_ENTER("EVP_MD_CTX_free");
-                wolfSSL_EVP_MD_CTX_cleanup(ctx);
-                XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
-            }
+            wolfSSL_EVP_MD_CTX_cleanup(ctx);
+            XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
+        }
     }
 
     /* returns the NID of message digest used by the ctx */
-    int wolfSSL_EVP_MD_CTX_type(const WOLFSSL_EVP_MD_CTX *ctx) {
+    int wolfSSL_EVP_MD_CTX_type(const WOLFSSL_EVP_MD_CTX *ctx)
+    {
         const struct s_ent *ent;
 
@@ -3307,4 +3440,8 @@
 
         if (ctx) {
+            if (ctx->isHMAC) {
+                return NID_hmac;
+            }
+
             for(ent = md_tbl; ent->name != NULL; ent++) {
                 if (ctx->macType == ent->macType) {
@@ -3339,81 +3476,102 @@
             const WOLFSSL_EVP_MD_CTX* src)
     {
-        if (src->macType == NID_hmac) {
-            wolfSSL_HmacCopy(&des->hash.hmac, (Hmac*)&src->hash.hmac);
+        int ret;
+        if (src->isHMAC) {
+            ret = wolfSSL_HmacCopy(&des->hash.hmac, (Hmac*)&src->hash.hmac);
         }
         else {
             switch (src->macType) {
+                case WC_HASH_TYPE_MD5:
             #ifndef NO_MD5
-                case WC_HASH_TYPE_MD5:
-                    wc_Md5Copy((wc_Md5*)&src->hash.digest,
+                    ret = wc_Md5Copy((wc_Md5*)&src->hash.digest,
                             (wc_Md5*)&des->hash.digest);
+            #else
+                    ret = NOT_COMPILED_IN;
+            #endif /* !NO_MD5 */
                     break;
-            #endif /* !NO_MD5 */
-
+                case WC_HASH_TYPE_SHA:
             #ifndef NO_SHA
-                case WC_HASH_TYPE_SHA:
-                    wc_ShaCopy((wc_Sha*)&src->hash.digest,
+                    ret = wc_ShaCopy((wc_Sha*)&src->hash.digest,
                             (wc_Sha*)&des->hash.digest);
+            #else
+                    ret = NOT_COMPILED_IN;
+            #endif /* !NO_SHA */
                     break;
-            #endif /* !NO_SHA */
-
+                case WC_HASH_TYPE_SHA224:
             #ifdef WOLFSSL_SHA224
-                case WC_HASH_TYPE_SHA224:
-                    wc_Sha224Copy((wc_Sha224*)&src->hash.digest,
+                    ret = wc_Sha224Copy((wc_Sha224*)&src->hash.digest,
                             (wc_Sha224*)&des->hash.digest);
+            #else
+                    ret = NOT_COMPILED_IN;
+            #endif /* WOLFSSL_SHA224 */
                     break;
-            #endif /* WOLFSSL_SHA224 */
-
+                case WC_HASH_TYPE_SHA256:
             #ifndef NO_SHA256
-                case WC_HASH_TYPE_SHA256:
-                    wc_Sha256Copy((wc_Sha256*)&src->hash.digest,
+                    ret = wc_Sha256Copy((wc_Sha256*)&src->hash.digest,
                             (wc_Sha256*)&des->hash.digest);
+            #else
+                    ret = NOT_COMPILED_IN;
+            #endif /* !NO_SHA256 */
                     break;
-            #endif /* !NO_SHA256 */
-
+                case WC_HASH_TYPE_SHA384:
             #ifdef WOLFSSL_SHA384
-                case WC_HASH_TYPE_SHA384:
-                    wc_Sha384Copy((wc_Sha384*)&src->hash.digest,
+                    ret = wc_Sha384Copy((wc_Sha384*)&src->hash.digest,
                             (wc_Sha384*)&des->hash.digest);
+            #else
+                    ret = NOT_COMPILED_IN;
+            #endif /* WOLFSSL_SHA384 */
                     break;
-            #endif /* WOLFSSL_SHA384 */
+                case WC_HASH_TYPE_SHA512:
             #ifdef WOLFSSL_SHA512
-                case WC_HASH_TYPE_SHA512:
-                    wc_Sha512Copy((wc_Sha512*)&src->hash.digest,
+                    ret = wc_Sha512Copy((wc_Sha512*)&src->hash.digest,
                         (wc_Sha512*)&des->hash.digest);
+            #else
+                    ret = NOT_COMPILED_IN;
+            #endif /* WOLFSSL_SHA512 */
                     break;
-            #endif /* WOLFSSL_SHA512 */
-        #ifdef WOLFSSL_SHA3
-            #ifndef WOLFSSL_NOSHA3_224
                 case WC_HASH_TYPE_SHA3_224:
-                    wc_Sha3_224_Copy((wc_Sha3*)&src->hash.digest,
+            #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
+                    ret = wc_Sha3_224_Copy((wc_Sha3*)&src->hash.digest,
                             (wc_Sha3*)&des->hash.digest);
+            #else
+                    ret = NOT_COMPILED_IN;
+            #endif
                     break;
+                case WC_HASH_TYPE_SHA3_256:
+            #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+                    ret = wc_Sha3_256_Copy((wc_Sha3*)&src->hash.digest,
+                            (wc_Sha3*)&des->hash.digest);
+            #else
+                    ret = NOT_COMPILED_IN;
             #endif
-
-            #ifndef WOLFSSL_NOSHA3_256
-                case WC_HASH_TYPE_SHA3_256:
-                    wc_Sha3_256_Copy((wc_Sha3*)&src->hash.digest,
+                    break;
+                case WC_HASH_TYPE_SHA3_384:
+            #if defined(WOLFSSL_SHA3)
+                    ret = wc_Sha3_384_Copy((wc_Sha3*)&src->hash.digest,
                             (wc_Sha3*)&des->hash.digest);
+            #else
+                    ret = NOT_COMPILED_IN;
+            #endif
                     break;
+                case WC_HASH_TYPE_SHA3_512:
+            #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
+                    ret = wc_Sha3_512_Copy((wc_Sha3*)&src->hash.digest,
+                        (wc_Sha3*)&des->hash.digest);
+            #else
+                    ret = NOT_COMPILED_IN;
             #endif
-
-                case WC_HASH_TYPE_SHA3_384:
-                    wc_Sha3_384_Copy((wc_Sha3*)&src->hash.digest,
-                            (wc_Sha3*)&des->hash.digest);
                     break;
-
-            #ifndef WOLFSSL_NOSHA3_512
-                case WC_HASH_TYPE_SHA3_512:
-                    wc_Sha3_512_Copy((wc_Sha3*)&src->hash.digest,
-                        (wc_Sha3*)&des->hash.digest);
+                case WC_HASH_TYPE_NONE:
+                case WC_HASH_TYPE_MD2:
+                case WC_HASH_TYPE_MD4:
+                case WC_HASH_TYPE_MD5_SHA:
+                case WC_HASH_TYPE_BLAKE2B:
+                case WC_HASH_TYPE_BLAKE2S:
+                default:
+                    ret = BAD_FUNC_ARG;
                     break;
-            #endif
-        #endif
-                default:
-                    return WOLFSSL_FAILURE;
-            }
-        }
-        return WOLFSSL_SUCCESS;
+            }
+        }
+        return ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
     }
 
@@ -3446,4 +3604,7 @@
             return NULL;
         WOLFSSL_ENTER("EVP_MD_CTX_md");
+        if (ctx->isHMAC) {
+            return "HMAC";
+        }
         for(ent = md_tbl; ent->name != NULL; ent++) {
             if(ctx->macType == ent->macType) {
@@ -3461,6 +3622,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cbc");
-        if (EVP_AES_128_CBC == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_128_CBC;
     }
@@ -3472,6 +3631,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cbc");
-        if (EVP_AES_192_CBC == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_192_CBC;
     }
@@ -3483,6 +3640,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cbc");
-        if (EVP_AES_256_CBC == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_256_CBC;
     }
@@ -3496,6 +3651,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb1");
-        if (EVP_AES_128_CFB1 == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_128_CFB1;
     }
@@ -3506,6 +3659,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb1");
-        if (EVP_AES_192_CFB1 == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_192_CFB1;
     }
@@ -3516,6 +3667,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb1");
-        if (EVP_AES_256_CFB1 == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_256_CFB1;
     }
@@ -3526,6 +3675,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb8");
-        if (EVP_AES_128_CFB8 == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_128_CFB8;
     }
@@ -3536,6 +3683,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb8");
-        if (EVP_AES_192_CFB8 == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_192_CFB8;
     }
@@ -3546,6 +3691,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb8");
-        if (EVP_AES_256_CFB8 == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_256_CFB8;
     }
@@ -3557,6 +3700,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb128");
-        if (EVP_AES_128_CFB128 == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_128_CFB128;
     }
@@ -3567,6 +3708,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb128");
-        if (EVP_AES_192_CFB128 == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_192_CFB128;
     }
@@ -3577,6 +3716,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb128");
-        if (EVP_AES_256_CFB128 == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_256_CFB128;
     }
@@ -3589,6 +3726,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ofb");
-        if (EVP_AES_128_OFB == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_128_OFB;
     }
@@ -3599,6 +3734,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ofb");
-        if (EVP_AES_192_OFB == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_192_OFB;
     }
@@ -3609,6 +3742,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ofb");
-        if (EVP_AES_256_OFB == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_256_OFB;
     }
@@ -3621,6 +3752,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_128_xts");
-        if (EVP_AES_128_XTS == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_128_XTS;
     }
@@ -3631,6 +3760,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_256_xts");
-        if (EVP_AES_256_XTS == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_256_XTS;
     }
@@ -3643,6 +3770,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_128_gcm");
-        if (EVP_AES_128_GCM == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_128_GCM;
     }
@@ -3653,6 +3778,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_192_gcm");
-        if (EVP_AES_192_GCM == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_192_GCM;
     }
@@ -3663,6 +3786,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_256_gcm");
-        if (EVP_AES_256_GCM == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_256_GCM;
     }
@@ -3670,10 +3791,9 @@
     #endif /* HAVE_AESGCM */
 
+    #ifdef WOLFSSL_AES_COUNTER
     #ifdef WOLFSSL_AES_128
     const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void)
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ctr");
-        if (EVP_AES_128_CTR == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_128_CTR;
     }
@@ -3685,6 +3805,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ctr");
-        if (EVP_AES_192_CTR == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_192_CTR;
     }
@@ -3696,16 +3814,14 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ctr");
-        if (EVP_AES_256_CTR == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_256_CTR;
     }
     #endif /* WOLFSSL_AES_256 */
-
+    #endif /* WOLFSSL_AES_COUNTER */
+
+    #ifdef HAVE_AES_ECB
     #ifdef WOLFSSL_AES_128
     const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void)
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ecb");
-        if (EVP_AES_128_ECB == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_128_ECB;
     }
@@ -3717,6 +3833,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ecb");
-        if (EVP_AES_192_ECB == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_192_ECB;
     }
@@ -3728,9 +3842,8 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ecb");
-        if (EVP_AES_256_ECB == NULL)
-            wolfSSL_EVP_init();
         return EVP_AES_256_ECB;
     }
     #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AES_ECB */
     #endif /* NO_AES */
 
@@ -3739,6 +3852,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_des_cbc");
-        if (EVP_DES_CBC == NULL)
-            wolfSSL_EVP_init();
         return EVP_DES_CBC;
     }
@@ -3747,6 +3858,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_des_ecb");
-        if (EVP_DES_ECB == NULL)
-            wolfSSL_EVP_init();
         return EVP_DES_ECB;
     }
@@ -3755,6 +3864,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc");
-        if (EVP_DES_EDE3_CBC == NULL)
-            wolfSSL_EVP_init();
         return EVP_DES_EDE3_CBC;
     }
@@ -3763,6 +3870,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_ecb");
-        if (EVP_DES_EDE3_ECB == NULL)
-            wolfSSL_EVP_init();
         return EVP_DES_EDE3_ECB;
     }
@@ -3773,7 +3878,6 @@
     const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void)
     {
-        static const char* type = "ARC4";
         WOLFSSL_ENTER("wolfSSL_EVP_rc4");
-        return type;
+        return EVP_ARC4;
     }
 #endif
@@ -3783,6 +3887,4 @@
     {
         WOLFSSL_ENTER("wolfSSL_EVP_idea_cbc");
-        if (EVP_IDEA_CBC == NULL)
-            wolfSSL_EVP_init();
         return EVP_IDEA_CBC;
     }
@@ -3790,84 +3892,84 @@
     const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void)
     {
-        static const char* type = "NULL";
         WOLFSSL_ENTER("wolfSSL_EVP_enc_null");
-        return type;
+        return EVP_NULL;
     }
 
     int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx)
     {
+        int ret = WOLFSSL_SUCCESS;
         WOLFSSL_ENTER("EVP_MD_CTX_cleanup");
         if (ctx->pctx != NULL)
             wolfSSL_EVP_PKEY_CTX_free(ctx->pctx);
 
-        if (ctx->macType == NID_hmac) {
+        if (ctx->isHMAC) {
             wc_HmacFree(&ctx->hash.hmac);
         }
         else {
             switch (ctx->macType) {
+                case WC_HASH_TYPE_MD5:
             #ifndef NO_MD5
-                case WC_HASH_TYPE_MD5:
                     wc_Md5Free((wc_Md5*)&ctx->hash.digest);
+            #endif /* !NO_MD5 */
                     break;
-            #endif /* !NO_MD5 */
-
+                case WC_HASH_TYPE_SHA:
             #ifndef NO_SHA
-                case WC_HASH_TYPE_SHA:
                     wc_ShaFree((wc_Sha*)&ctx->hash.digest);
+            #endif /* !NO_SHA */
                     break;
-            #endif /* !NO_SHA */
-
+                case WC_HASH_TYPE_SHA224:
             #ifdef WOLFSSL_SHA224
-                case WC_HASH_TYPE_SHA224:
                     wc_Sha224Free((wc_Sha224*)&ctx->hash.digest);
+            #endif /* WOLFSSL_SHA224 */
                     break;
-            #endif /* WOLFSSL_SHA224 */
-
+                case WC_HASH_TYPE_SHA256:
             #ifndef NO_SHA256
-                case WC_HASH_TYPE_SHA256:
                     wc_Sha256Free((wc_Sha256*)&ctx->hash.digest);
+            #endif /* !NO_SHA256 */
                     break;
-            #endif /* !NO_SHA256 */
-
+                case WC_HASH_TYPE_SHA384:
             #ifdef WOLFSSL_SHA384
-                case WC_HASH_TYPE_SHA384:
                     wc_Sha384Free((wc_Sha384*)&ctx->hash.digest);
+            #endif /* WOLFSSL_SHA384 */
                     break;
-            #endif /* WOLFSSL_SHA384 */
+                case WC_HASH_TYPE_SHA512:
             #ifdef WOLFSSL_SHA512
-                case WC_HASH_TYPE_SHA512:
                     wc_Sha512Free((wc_Sha512*)&ctx->hash.digest);
+            #endif /* WOLFSSL_SHA512 */
                     break;
-            #endif /* WOLFSSL_SHA512 */
-        #ifdef WOLFSSL_SHA3
-            #ifndef WOLFSSL_NOSHA3_224
                 case WC_HASH_TYPE_SHA3_224:
+            #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
                     wc_Sha3_224_Free((wc_Sha3*)&ctx->hash.digest);
+            #endif
                     break;
+                case WC_HASH_TYPE_SHA3_256:
+            #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+                    wc_Sha3_256_Free((wc_Sha3*)&ctx->hash.digest);
             #endif
-
-            #ifndef WOLFSSL_NOSHA3_256
-                case WC_HASH_TYPE_SHA3_256:
-                    wc_Sha3_256_Free((wc_Sha3*)&ctx->hash.digest);
                     break;
+                case WC_HASH_TYPE_SHA3_384:
+            #if defined(WOLFSSL_SHA3)
+                    wc_Sha3_384_Free((wc_Sha3*)&ctx->hash.digest);
             #endif
-
-                case WC_HASH_TYPE_SHA3_384:
-                    wc_Sha3_384_Free((wc_Sha3*)&ctx->hash.digest);
                     break;
-
-            #ifndef WOLFSSL_NOSHA3_512
                 case WC_HASH_TYPE_SHA3_512:
+            #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
                     wc_Sha3_512_Free((wc_Sha3*)&ctx->hash.digest);
+            #endif
                     break;
-            #endif
-        #endif
+                case WC_HASH_TYPE_NONE:
+                case WC_HASH_TYPE_MD2:
+                case WC_HASH_TYPE_MD4:
+                case WC_HASH_TYPE_MD5_SHA:
+                case WC_HASH_TYPE_BLAKE2B:
+                case WC_HASH_TYPE_BLAKE2S:
                 default:
-                    return WOLFSSL_FAILURE;
+                    ret = WOLFSSL_FAILURE;
+                    break;
             }
         }
         ForceZero(ctx, sizeof(*ctx));
         ctx->macType = WC_HASH_TYPE_NONE;
-        return 1;
+        return ret;
     }
 
@@ -4011,4 +4113,16 @@
             ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT;  /* not yet initialized  */
             ctx->keyLen     = 0;
+#ifdef HAVE_AESGCM
+            if (ctx->gcmBuffer) {
+                XFREE(ctx->gcmBuffer, NULL, DYNAMIC_TYPE_OPENSSL);
+                ctx->gcmBuffer = NULL;
+            }
+            ctx->gcmBufferLen = 0;
+            if (ctx->gcmAuthIn) {
+                XFREE(ctx->gcmAuthIn, NULL, DYNAMIC_TYPE_OPENSSL);
+                ctx->gcmAuthIn = NULL;
+            }
+            ctx->gcmAuthInSz = 0;
+#endif
         }
 
@@ -4081,5 +4195,18 @@
 #endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */
 
+
 #ifndef NO_AES
+#if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
+    defined(WOLFSSL_AES_256)
+    #define AES_SIZE_ANY
+#endif
+
+#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) || \
+    defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_CFB) || \
+    defined(WOLFSSSL_AES_OFB)
+    #define AES_SET_KEY
+#endif
+
+#if defined(AES_SIZE_ANY) && defined(AES_SET_KEY)
     static int   AesSetKey_ex(Aes* aes, const byte* key, word32 len,
                               const byte* iv, int dir, int direct)
@@ -4104,5 +4231,6 @@
         return ret;
     }
-#endif
+#endif /* AES_ANY_SIZE && AES_SET_KEY */
+#endif /* NO_AES */
 
     /* return WOLFSSL_SUCCESS on ok, 0 on failure to match API compatibility */
@@ -4139,4 +4267,11 @@
             iv = ctx->iv;
         }
+#endif
+#ifdef HAVE_AESGCM
+        if (ctx->gcmAuthIn) {
+            XFREE(ctx->gcmAuthIn, NULL, DYNAMIC_TYPE_OPENSSL);
+            ctx->gcmAuthIn = NULL;
+        }
+        ctx->gcmAuthInSz = 0;
 #endif
 
@@ -4223,5 +4358,6 @@
         #endif /* WOLFSSL_AES_256 */
     #endif /* HAVE_AES_CBC */
-#if !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+#if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))
     #ifdef HAVE_AESGCM
         #ifdef WOLFSSL_AES_128
@@ -4231,5 +4367,6 @@
             ctx->cipherType = AES_128_GCM_TYPE;
             ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_GCM_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_GCM_MODE |
+                    WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
             ctx->keyLen     = 16;
             ctx->block_size = AES_BLOCK_SIZE;
@@ -4237,5 +4374,4 @@
             ctx->ivSz       = GCM_NONCE_MID_SZ;
 
-            XMEMSET(ctx->authTag, 0, ctx->authTagSz);
             if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
                 WOLFSSL_MSG("wc_AesGcmSetKey() failed");
@@ -4256,5 +4392,6 @@
             ctx->cipherType = AES_192_GCM_TYPE;
             ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_GCM_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_GCM_MODE |
+                    WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
             ctx->keyLen     = 24;
             ctx->block_size = AES_BLOCK_SIZE;
@@ -4262,5 +4399,4 @@
             ctx->ivSz       = GCM_NONCE_MID_SZ;
 
-            XMEMSET(ctx->authTag, 0, ctx->authTagSz);
             if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
                 WOLFSSL_MSG("wc_AesGcmSetKey() failed");
@@ -4281,5 +4417,6 @@
             ctx->cipherType = AES_256_GCM_TYPE;
             ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_GCM_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_GCM_MODE |
+                    WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
             ctx->keyLen     = 32;
             ctx->block_size = AES_BLOCK_SIZE;
@@ -4287,5 +4424,4 @@
             ctx->ivSz       = GCM_NONCE_MID_SZ;
 
-            XMEMSET(ctx->authTag, 0, ctx->authTagSz);
             if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
                 WOLFSSL_MSG("wc_AesGcmSetKey() failed");
@@ -4301,5 +4437,5 @@
         #endif /* WOLFSSL_AES_256 */
     #endif /* HAVE_AESGCM */
-#endif /* !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) */
+#endif /*!HAVE_FIPS && !HAVE_SELFTEST ||(HAVE_FIPS_VERSION && HAVE_FIPS_VERSION > 2)*/
 #ifdef WOLFSSL_AES_COUNTER
         #ifdef WOLFSSL_AES_128
@@ -4388,4 +4524,5 @@
         #endif /* WOLFSSL_AES_256 */
 #endif /* WOLFSSL_AES_COUNTER */
+    #ifdef HAVE_AES_ECB
         #ifdef WOLFSSL_AES_128
         if (ctx->cipherType == AES_128_ECB_TYPE ||
@@ -4445,4 +4582,5 @@
         }
         #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AES_ECB */
     #ifdef WOLFSSL_AES_CFB
         #ifdef WOLFSSL_AES_128
@@ -4674,5 +4812,5 @@
         }
         #endif /* WOLFSSL_AES_256 */
-    #endif /* HAVE_AES_CFB */
+    #endif /* WOLFSSL_AES_CFB */
     #ifdef WOLFSSL_AES_OFB
         #ifdef WOLFSSL_AES_128
@@ -4904,6 +5042,6 @@
 #endif /* NO_DES3 */
 #ifndef NO_RC4
-        if (ctx->cipherType == ARC4_TYPE || (type &&
-                                     XSTRNCMP(type, "ARC4", 4) == 0)) {
+        if (ctx->cipherType == ARC4_TYPE ||
+                (type && XSTRNCMP(type, EVP_ARC4, 4) == 0)) {
             WOLFSSL_MSG("ARC4");
             ctx->cipherType = ARC4_TYPE;
@@ -4941,6 +5079,6 @@
         }
 #endif /* HAVE_IDEA */
-        if (ctx->cipherType == NULL_CIPHER_TYPE || (type &&
-                                     XSTRNCMP(type, "NULL", 4) == 0)) {
+        if (ctx->cipherType == NULL_CIPHER_TYPE ||
+                (type && XSTRNCMP(type, EVP_NULL, 4) == 0)) {
             WOLFSSL_MSG("NULL cipher");
             ctx->cipherType = NULL_CIPHER_TYPE;
@@ -5017,5 +5155,5 @@
 #endif
 
-    /* WOLFSSL_SUCCESS on ok */
+    /* Return length on ok */
     int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src,
                           word32 len)
@@ -5030,10 +5168,10 @@
              ctx->cipherType != AES_256_GCM_TYPE)) {
             WOLFSSL_MSG("Bad function argument");
-            return 0;  /* failure */
+            return WOLFSSL_FATAL_ERROR;
         }
 
         if (ctx->cipherType == 0xff) {
             WOLFSSL_MSG("no init");
-            return 0;  /* failure */
+            return WOLFSSL_FATAL_ERROR;
         }
 
@@ -5050,4 +5188,6 @@
                 else
                     ret = wc_AesCbcDecrypt(&ctx->cipher.aes, dst, src, len);
+                if (ret == 0)
+                    ret = (len / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
                 break;
 #endif /* HAVE_AES_CBC */
@@ -5063,4 +5203,6 @@
                 else
                     ret = wc_AesCfb1Decrypt(&ctx->cipher.aes, dst, src, len);
+                if (ret == 0)
+                    ret = len;
                 break;
             case AES_128_CFB8_TYPE:
@@ -5072,4 +5214,6 @@
                 else
                     ret = wc_AesCfb8Decrypt(&ctx->cipher.aes, dst, src, len);
+                if (ret == 0)
+                    ret = len;
                 break;
 #endif /* !HAVE_SELFTEST && !HAVE_FIPS */
@@ -5082,4 +5226,6 @@
                 else
                     ret = wc_AesCfbDecrypt(&ctx->cipher.aes, dst, src, len);
+                if (ret == 0)
+                    ret = len;
                 break;
 #endif /* WOLFSSL_AES_CFB */
@@ -5093,4 +5239,6 @@
                 else
                     ret = wc_AesOfbDecrypt(&ctx->cipher.aes, dst, src, len);
+                if (ret == 0)
+                    ret = len;
                 break;
 #endif /* WOLFSSL_AES_OFB */
@@ -5105,4 +5253,6 @@
                     ret = wc_AesXtsDecrypt(&ctx->cipher.xts, dst, src, len,
                             ctx->iv, ctx->ivSz);
+                if (ret == 0)
+                    ret = len;
                 break;
 #endif /* WOLFSSL_AES_XTS */
@@ -5113,39 +5263,19 @@
             case AES_256_GCM_TYPE :
                 WOLFSSL_MSG("AES GCM");
-                if (ctx->enc) {
-                    if (dst){
-                        /* encrypt confidential data*/
-                        ret = wc_AesGcmEncrypt(&ctx->cipher.aes, dst, src, len,
-                                  ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
-                                  NULL, 0);
-                    }
-                    else {
-                        /* authenticated, non-confidential data */
-                        ret = wc_AesGcmEncrypt(&ctx->cipher.aes, NULL, NULL, 0,
-                                  ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
-                                  src, len);
-                        /* Reset partial authTag error for AAD*/
-                        if (ret == AES_GCM_AUTH_E)
-                            ret = 0;
-                    }
+                if (!dst) {
+                    ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, src, len);
                 }
                 else {
-                    if (dst){
-                        /* decrypt confidential data*/
-                        ret = wc_AesGcmDecrypt(&ctx->cipher.aes, dst, src, len,
-                                  ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
-                                  NULL, 0);
-                    }
-                    else {
-                        /* authenticated, non-confidential data*/
-                        ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0,
-                                  ctx->iv, ctx->ivSz,
-                                  ctx->authTag, ctx->authTagSz,
-                                  src, len);
-                        /* Reset partial authTag error for AAD*/
-                        if (ret == AES_GCM_AUTH_E)
-                            ret = 0;
-                    }
+                    if (ctx->enc)
+                        ret = wc_AesGcmEncrypt(&ctx->cipher.aes, dst, src,
+                                len, ctx->iv, ctx->ivSz, ctx->authTag,
+                                ctx->authTagSz, ctx->gcmAuthIn, ctx->gcmAuthInSz);
+                    else
+                        ret = wc_AesGcmDecrypt(&ctx->cipher.aes, dst, src,
+                                len, ctx->iv, ctx->ivSz, ctx->authTag,
+                                ctx->authTagSz, ctx->gcmAuthIn, ctx->gcmAuthInSz);
                 }
+                if (ret == 0)
+                    ret = len;
                 break;
 #endif /* HAVE_AESGCM */
@@ -5159,4 +5289,6 @@
                 else
                     ret = wc_AesEcbDecrypt(&ctx->cipher.aes, dst, src, len);
+                if (ret == 0)
+                    ret = (len / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
                 break;
 #endif
@@ -5165,6 +5297,8 @@
             case AES_192_CTR_TYPE :
             case AES_256_CTR_TYPE :
-                    WOLFSSL_MSG("AES CTR");
-                    ret = wc_AesCtrEncrypt(&ctx->cipher.aes, dst, src, len);
+                WOLFSSL_MSG("AES CTR");
+                ret = wc_AesCtrEncrypt(&ctx->cipher.aes, dst, src, len);
+                if (ret == 0)
+                    ret = len;
                 break;
 #endif /* WOLFSSL_AES_COUNTER */
@@ -5178,4 +5312,6 @@
                 else
                     wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len);
+                if (ret == 0)
+                    ret = (len / DES_BLOCK_SIZE) * DES_BLOCK_SIZE;
                 break;
             case DES_EDE3_CBC_TYPE :
@@ -5185,4 +5321,6 @@
                 else
                     ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len);
+                if (ret == 0)
+                    ret = (len / DES_BLOCK_SIZE) * DES_BLOCK_SIZE;
                 break;
 #ifdef WOLFSSL_DES_ECB
@@ -5190,8 +5328,12 @@
                 WOLFSSL_MSG("DES ECB");
                 ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len);
+                if (ret == 0)
+                    ret = (len / DES_BLOCK_SIZE) * DES_BLOCK_SIZE;
                 break;
             case DES_EDE3_ECB_TYPE :
                 WOLFSSL_MSG("DES3 ECB");
                 ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len);
+                if (ret == 0)
+                    ret = (len / DES_BLOCK_SIZE) * DES_BLOCK_SIZE;
                 break;
 #endif
@@ -5202,4 +5344,6 @@
                 WOLFSSL_MSG("ARC4");
                 wc_Arc4Process(&ctx->cipher.arc4, dst, src, len);
+                if (ret == 0)
+                    ret = len;
                 break;
 #endif
@@ -5212,4 +5356,6 @@
                 else
                     wc_IdeaCbcDecrypt(&ctx->cipher.idea, dst, src, len);
+                if (ret == 0)
+                    ret = (len / IDEA_BLOCK_SIZE) * IDEA_BLOCK_SIZE;
                 break;
 #endif
@@ -5217,23 +5363,24 @@
                 WOLFSSL_MSG("NULL CIPHER");
                 XMEMCPY(dst, src, len);
+                ret = len;
                 break;
 
             default: {
                 WOLFSSL_MSG("bad type");
-                return 0;  /* failure */
-            }
-        }
-
-        if (ret != 0) {
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+
+        if (ret < 0) {
             WOLFSSL_MSG("wolfSSL_EVP_Cipher failure");
-            return 0;  /* failure */
+            return WOLFSSL_FATAL_ERROR;
         }
 
         if (wolfSSL_StoreExternalIV(ctx) != WOLFSSL_SUCCESS) {
-            return WOLFSSL_FAILURE;
+            return WOLFSSL_FATAL_ERROR;
         }
 
         WOLFSSL_MSG("wolfSSL_EVP_Cipher success");
-        return WOLFSSL_SUCCESS;  /* success */
+        return ret;
     }
 
@@ -5246,5 +5393,5 @@
         WOLFSSL_ENTER("EVP_DigestInit");
 
-        if (ctx == NULL || md == NULL) {
+        if (ctx == NULL) {
             return BAD_FUNC_ARG;
         }
@@ -5260,5 +5407,8 @@
         /* Set to 0 if no match */
         ctx->macType = wolfSSL_EVP_md2macType(md);
-        if (XSTRNCMP(md, "SHA256", 6) == 0) {
+        if (md == NULL) {
+             XMEMSET(&ctx->hash.digest, 0, sizeof(WOLFSSL_Hasher));
+        }
+        else if (XSTRNCMP(md, "SHA256", 6) == 0) {
              ret = wolfSSL_SHA256_Init(&(ctx->hash.digest.sha256));
         }
@@ -5326,5 +5476,6 @@
                                 size_t sz)
     {
-        int macType;
+        int ret = WOLFSSL_FAILURE;
+        enum wc_HashType macType;
 
         WOLFSSL_ENTER("EVP_DigestUpdate");
@@ -5332,75 +5483,81 @@
         macType = wolfSSL_EVP_md2macType(EVP_MD_CTX_md(ctx));
         switch (macType) {
-#ifndef NO_MD4
             case WC_HASH_TYPE_MD4:
+        #ifndef NO_MD4
                 wolfSSL_MD4_Update((MD4_CTX*)&ctx->hash, data,
                                   (unsigned long)sz);
+                ret = WOLFSSL_SUCCESS;
+        #endif
                 break;
-#endif
-#ifndef NO_MD5
             case WC_HASH_TYPE_MD5:
-                wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data,
+        #ifndef NO_MD5
+                ret = wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data,
                                   (unsigned long)sz);
+        #endif
                 break;
-#endif
-#ifndef NO_SHA
             case WC_HASH_TYPE_SHA:
-                wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data,
+        #ifndef NO_SHA
+                ret = wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data,
                                   (unsigned long)sz);
+        #endif
                 break;
-#endif
-#ifdef WOLFSSL_SHA224
             case WC_HASH_TYPE_SHA224:
-                wolfSSL_SHA224_Update((SHA224_CTX*)&ctx->hash, data,
+        #ifdef WOLFSSL_SHA224
+                ret = wolfSSL_SHA224_Update((SHA224_CTX*)&ctx->hash, data,
                                      (unsigned long)sz);
+        #endif
                 break;
-#endif
-#ifndef NO_SHA256
             case WC_HASH_TYPE_SHA256:
-                wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data,
+        #ifndef NO_SHA256
+                ret = wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data,
                                      (unsigned long)sz);
+        #endif /* !NO_SHA256 */
                 break;
-#endif /* !NO_SHA256 */
-#ifdef WOLFSSL_SHA384
             case WC_HASH_TYPE_SHA384:
-                wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data,
+        #ifdef WOLFSSL_SHA384
+                ret = wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data,
                                      (unsigned long)sz);
+        #endif
                 break;
-#endif
-#ifdef WOLFSSL_SHA512
             case WC_HASH_TYPE_SHA512:
-                wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data,
+        #ifdef WOLFSSL_SHA512
+                ret = wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data,
                                      (unsigned long)sz);
+        #endif /* WOLFSSL_SHA512 */
                 break;
-#endif /* WOLFSSL_SHA512 */
-    #ifdef WOLFSSL_SHA3
-        #ifndef WOLFSSL_NOSHA3_224
             case WC_HASH_TYPE_SHA3_224:
-                wolfSSL_SHA3_224_Update((SHA3_224_CTX*)&ctx->hash, data,
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
+                ret = wolfSSL_SHA3_224_Update((SHA3_224_CTX*)&ctx->hash, data,
                                      (unsigned long)sz);
+        #endif
                 break;
+            case WC_HASH_TYPE_SHA3_256:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+                ret = wolfSSL_SHA3_256_Update((SHA3_256_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
         #endif
-        #ifndef WOLFSSL_NOSHA3_256
-            case WC_HASH_TYPE_SHA3_256:
-                wolfSSL_SHA3_256_Update((SHA3_256_CTX*)&ctx->hash, data,
+                break;
+            case WC_HASH_TYPE_SHA3_384:
+        #if defined(WOLFSSL_SHA3)
+                ret = wolfSSL_SHA3_384_Update((SHA3_384_CTX*)&ctx->hash, data,
                                      (unsigned long)sz);
+        #endif
                 break;
+            case WC_HASH_TYPE_SHA3_512:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
+                ret = wolfSSL_SHA3_512_Update((SHA3_512_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
         #endif
-            case WC_HASH_TYPE_SHA3_384:
-                wolfSSL_SHA3_384_Update((SHA3_384_CTX*)&ctx->hash, data,
-                                     (unsigned long)sz);
                 break;
-        #ifndef WOLFSSL_NOSHA3_512
-            case WC_HASH_TYPE_SHA3_512:
-                wolfSSL_SHA3_512_Update((SHA3_512_CTX*)&ctx->hash, data,
-                                     (unsigned long)sz);
-                break;
-        #endif
-    #endif
+            case WC_HASH_TYPE_NONE:
+            case WC_HASH_TYPE_MD2:
+            case WC_HASH_TYPE_MD5_SHA:
+            case WC_HASH_TYPE_BLAKE2B:
+            case WC_HASH_TYPE_BLAKE2S:
             default:
                 return WOLFSSL_FAILURE;
         }
 
-        return WOLFSSL_SUCCESS;
+        return ret;
     }
 
@@ -5409,80 +5566,87 @@
                                unsigned int* s)
     {
-        int macType;
+        int ret = WOLFSSL_FAILURE;
+        enum wc_HashType macType;
 
         WOLFSSL_ENTER("EVP_DigestFinal");
         macType = wolfSSL_EVP_md2macType(EVP_MD_CTX_md(ctx));
         switch (macType) {
-#ifndef NO_MD4
             case WC_HASH_TYPE_MD4:
+        #ifndef NO_MD4
                 wolfSSL_MD4_Final(md, (MD4_CTX*)&ctx->hash);
                 if (s) *s = MD4_DIGEST_SIZE;
+                ret = WOLFSSL_SUCCESS;
+        #endif
                 break;
-#endif
-#ifndef NO_MD5
             case WC_HASH_TYPE_MD5:
-                wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash);
+        #ifndef NO_MD5
+                ret = wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash);
                 if (s) *s = WC_MD5_DIGEST_SIZE;
+        #endif
                 break;
-#endif
-#ifndef NO_SHA
             case WC_HASH_TYPE_SHA:
-                wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash);
+        #ifndef NO_SHA
+                ret = wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash);
                 if (s) *s = WC_SHA_DIGEST_SIZE;
+        #endif
                 break;
-#endif
-#ifdef WOLFSSL_SHA224
             case WC_HASH_TYPE_SHA224:
-                wolfSSL_SHA224_Final(md, (SHA224_CTX*)&ctx->hash);
+        #ifdef WOLFSSL_SHA224
+                ret = wolfSSL_SHA224_Final(md, (SHA224_CTX*)&ctx->hash);
                 if (s) *s = WC_SHA224_DIGEST_SIZE;
+        #endif
                 break;
-#endif
-#ifndef NO_SHA256
             case WC_HASH_TYPE_SHA256:
-                wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash);
+        #ifndef NO_SHA256
+                ret = wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash);
                 if (s) *s = WC_SHA256_DIGEST_SIZE;
+        #endif /* !NO_SHA256 */
                 break;
-#endif /* !NO_SHA256 */
-#ifdef WOLFSSL_SHA384
             case WC_HASH_TYPE_SHA384:
-                wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash);
+        #ifdef WOLFSSL_SHA384
+                ret = wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash);
                 if (s) *s = WC_SHA384_DIGEST_SIZE;
+        #endif
                 break;
-#endif
-#ifdef WOLFSSL_SHA512
             case WC_HASH_TYPE_SHA512:
-                wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash);
+        #ifdef WOLFSSL_SHA512
+                ret = wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash);
                 if (s) *s = WC_SHA512_DIGEST_SIZE;
+        #endif /* WOLFSSL_SHA512 */
                 break;
-#endif /* WOLFSSL_SHA512 */
-    #ifdef WOLFSSL_SHA3
-        #ifndef WOLFSSL_NOSHA3_224
             case WC_HASH_TYPE_SHA3_224:
-                wolfSSL_SHA3_224_Final(md, (SHA3_224_CTX*)&ctx->hash);
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
+                ret = wolfSSL_SHA3_224_Final(md, (SHA3_224_CTX*)&ctx->hash);
                 if (s) *s = WC_SHA3_224_DIGEST_SIZE;
+        #endif
                 break;
+            case WC_HASH_TYPE_SHA3_256:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+                ret = wolfSSL_SHA3_256_Final(md, (SHA3_256_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA3_256_DIGEST_SIZE;
         #endif
-        #ifndef WOLFSSL_NOSHA3_256
-            case WC_HASH_TYPE_SHA3_256:
-                wolfSSL_SHA3_256_Final(md, (SHA3_256_CTX*)&ctx->hash);
-                if (s) *s = WC_SHA3_256_DIGEST_SIZE;
                 break;
+            case WC_HASH_TYPE_SHA3_384:
+        #if defined(WOLFSSL_SHA3)
+                ret = wolfSSL_SHA3_384_Final(md, (SHA3_384_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA3_384_DIGEST_SIZE;
         #endif
-            case WC_HASH_TYPE_SHA3_384:
-                wolfSSL_SHA3_384_Final(md, (SHA3_384_CTX*)&ctx->hash);
-                if (s) *s = WC_SHA3_384_DIGEST_SIZE;
                 break;
-        #ifndef WOLFSSL_NOSHA3_512
             case WC_HASH_TYPE_SHA3_512:
-                wolfSSL_SHA3_512_Final(md, (SHA3_512_CTX*)&ctx->hash);
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
+                ret = wolfSSL_SHA3_512_Final(md, (SHA3_512_CTX*)&ctx->hash);
                 if (s) *s = WC_SHA3_512_DIGEST_SIZE;
+        #endif
                 break;
-        #endif
-    #endif
+            case WC_HASH_TYPE_NONE:
+            case WC_HASH_TYPE_MD2:
+            case WC_HASH_TYPE_MD5_SHA:
+            case WC_HASH_TYPE_BLAKE2B:
+            case WC_HASH_TYPE_BLAKE2S:
             default:
                 return WOLFSSL_FAILURE;
         }
 
-        return WOLFSSL_SUCCESS;
+        return ret;
     }
 
@@ -5512,4 +5676,8 @@
         case NID_sha1:
             return wolfSSL_EVP_sha1();
+#endif
+#ifndef NO_SHA256
+        case NID_sha256:
+            return wolfSSL_EVP_sha256();
 #endif
         default:
@@ -5581,9 +5749,13 @@
         return WOLFSSL_FAILURE;
 
+    if (wolfSSL_RSA_up_ref(key) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_RSA_up_ref failed");
+        return WOLFSSL_FAILURE;
+    }
     if (pkey->rsa != NULL && pkey->ownRsa == 1) {
         wolfSSL_RSA_free(pkey->rsa);
     }
     pkey->rsa    = key;
-    pkey->ownRsa = 0; /* pkey does not own RSA */
+    pkey->ownRsa = 1; /* pkey does not own RSA but needs to call free on it */
     pkey->type   = EVP_PKEY_RSA;
     if (key->inSet == 0) {
@@ -5718,4 +5890,12 @@
 
     return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_DSA* wolfSSL_EVP_PKEY_get0_DSA(struct WOLFSSL_EVP_PKEY *pkey)
+{
+    if (!pkey) {
+        return NULL;
+    }
+    return pkey->dsa;
 }
 
@@ -5814,4 +5994,5 @@
 #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
 #if !defined(NO_DH) && !defined(NO_FILESYSTEM)
+#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))
 /* with set1 functions the pkey struct does not own the DH structure
  * Build the following DH Key format from the passed in WOLFSSL_DH
@@ -5892,4 +6073,5 @@
     return WOLFSSL_SUCCESS;
 }
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
 
 WOLFSSL_DH* wolfSSL_EVP_PKEY_get0_DH(WOLFSSL_EVP_PKEY* key)
@@ -5901,4 +6083,5 @@
 }
 
+#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))
 WOLFSSL_DH* wolfSSL_EVP_PKEY_get1_DH(WOLFSSL_EVP_PKEY* key)
 {
@@ -5934,4 +6117,5 @@
     return local;
 }
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
 #endif /* NO_DH && NO_FILESYSTEM */
 
@@ -5959,5 +6143,5 @@
             break;
     #endif
-    #ifdef NO_DH
+    #ifndef NO_DH
          case EVP_PKEY_DH:
             ret = wolfSSL_EVP_PKEY_assign_DH(pkey, (WOLFSSL_DH*)key);
@@ -5975,27 +6159,27 @@
 #if defined(HAVE_ECC)
 /* try and populate public pkey_sz and pkey.ptr */
-static void ECC_populate_EVP_PKEY(EVP_PKEY* pkey, ecc_key* ecc)
-{
-    int ret;
+static int ECC_populate_EVP_PKEY(EVP_PKEY* pkey, ecc_key* ecc)
+{
+    word32 derSz = 0;
     if (!pkey || !ecc)
-        return;
-    if ((ret = wc_EccPublicKeyDerSize(ecc, 1)) > 0) {
-        int derSz = ret;
-        char* derBuf = (char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    if (wc_EccKeyToPKCS8(ecc, NULL, &derSz) == LENGTH_ONLY_E) {
+        byte* derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
         if (derBuf) {
-            ret = wc_EccPublicKeyToDer(ecc, (byte*)derBuf, derSz, 1);
-            if (ret >= 0) {
+            if (wc_EccKeyToPKCS8(ecc, derBuf, &derSz) >= 0) {
                 if (pkey->pkey.ptr) {
                     XFREE(pkey->pkey.ptr, NULL, DYNAMIC_TYPE_OPENSSL);
                 }
-                pkey->pkey_sz = ret;
-                pkey->pkey.ptr = derBuf;
-            }
-            else { /* failure - okay to ignore */
-                XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                pkey->pkey_sz = (int)derSz;
+                pkey->pkey.ptr = (char*)derBuf;
+                return WOLFSSL_SUCCESS;
+            }
+            else {
+                XFREE(derBuf, NULL, DYNAMIC_TYPE_OPENSSL);
                 derBuf = NULL;
             }
         }
     }
+    return WOLFSSL_FAILURE;
 }
 
@@ -6029,6 +6213,5 @@
     pkey->ownEcc = 0; /* pkey does not own EC key */
     pkey->type   = EVP_PKEY_EC;
-    ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal);
-    return WOLFSSL_SUCCESS;
+    return ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal);
 #else
     (void)pkey;
@@ -6066,7 +6249,5 @@
 
     /* try and populate public pkey_sz and pkey.ptr */
-    ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal);
-
-    return WOLFSSL_SUCCESS;
+    return ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal);
 }
 #endif /* HAVE_ECC */
@@ -6180,4 +6361,6 @@
             return AES_BLOCK_SIZE;
 #endif
+#if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))
 #ifdef HAVE_AESGCM
         case AES_128_GCM_TYPE :
@@ -6187,4 +6370,5 @@
             return GCM_NONCE_MID_SZ;
 #endif
+#endif /* (HAVE_FIPS && !HAVE_SELFTEST) || HAVE_FIPS_VERSION > 2 */
 #ifdef WOLFSSL_AES_COUNTER
         case AES_128_CTR_TYPE :
@@ -6265,41 +6449,44 @@
 #ifdef HAVE_AES_CBC
     #ifdef WOLFSSL_AES_128
-    if (EVP_AES_128_CBC && XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0)
+    if (XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0)
         return AES_BLOCK_SIZE;
     #endif
     #ifdef WOLFSSL_AES_192
-    if (EVP_AES_192_CBC && XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0)
+    if (XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0)
         return AES_BLOCK_SIZE;
     #endif
     #ifdef WOLFSSL_AES_256
-    if (EVP_AES_256_CBC && XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0)
+    if (XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0)
         return AES_BLOCK_SIZE;
     #endif
 #endif /* HAVE_AES_CBC */
+#if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))
 #ifdef HAVE_AESGCM
     #ifdef WOLFSSL_AES_128
-    if (EVP_AES_128_GCM && XSTRNCMP(name, EVP_AES_128_GCM, XSTRLEN(EVP_AES_128_GCM)) == 0)
+    if (XSTRNCMP(name, EVP_AES_128_GCM, XSTRLEN(EVP_AES_128_GCM)) == 0)
         return GCM_NONCE_MID_SZ;
     #endif
     #ifdef WOLFSSL_AES_192
-    if (EVP_AES_192_GCM && XSTRNCMP(name, EVP_AES_192_GCM, XSTRLEN(EVP_AES_192_GCM)) == 0)
+    if (XSTRNCMP(name, EVP_AES_192_GCM, XSTRLEN(EVP_AES_192_GCM)) == 0)
         return GCM_NONCE_MID_SZ;
     #endif
     #ifdef WOLFSSL_AES_256
-    if (EVP_AES_256_GCM && XSTRNCMP(name, EVP_AES_256_GCM, XSTRLEN(EVP_AES_256_GCM)) == 0)
+    if (XSTRNCMP(name, EVP_AES_256_GCM, XSTRLEN(EVP_AES_256_GCM)) == 0)
         return GCM_NONCE_MID_SZ;
     #endif
 #endif /* HAVE_AESGCM */
+#endif /* (HAVE_FIPS && !HAVE_SELFTEST) || HAVE_FIPS_VERSION > 2 */
 #ifdef WOLFSSL_AES_COUNTER
     #ifdef WOLFSSL_AES_128
-    if (EVP_AES_128_CTR && XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0)
+    if (XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0)
         return AES_BLOCK_SIZE;
     #endif
     #ifdef WOLFSSL_AES_192
-    if (EVP_AES_192_CTR && XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0)
+    if (XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0)
         return AES_BLOCK_SIZE;
     #endif
     #ifdef WOLFSSL_AES_256
-    if (EVP_AES_256_CTR && XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0)
+    if (XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0)
         return AES_BLOCK_SIZE;
     #endif
@@ -6307,10 +6494,10 @@
 #ifdef WOLFSSL_AES_XTS
     #ifdef WOLFSSL_AES_128
-    if (EVP_AES_128_XTS && XSTRNCMP(name, EVP_AES_128_XTS, XSTRLEN(EVP_AES_128_XTS)) == 0)
+    if (XSTRNCMP(name, EVP_AES_128_XTS, XSTRLEN(EVP_AES_128_XTS)) == 0)
         return AES_BLOCK_SIZE;
     #endif /* WOLFSSL_AES_128 */
 
     #ifdef WOLFSSL_AES_256
-    if (EVP_AES_256_XTS && XSTRNCMP(name, EVP_AES_256_XTS, XSTRLEN(EVP_AES_256_XTS)) == 0)
+    if (XSTRNCMP(name, EVP_AES_256_XTS, XSTRLEN(EVP_AES_256_XTS)) == 0)
         return AES_BLOCK_SIZE;
     #endif /* WOLFSSL_AES_256 */
@@ -6320,6 +6507,6 @@
 
 #ifndef NO_DES3
-    if ((EVP_DES_CBC && XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) ||
-           (EVP_DES_EDE3_CBC && XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) {
+    if ((XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) ||
+           (XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) {
         return DES_BLOCK_SIZE;
     }
@@ -6327,5 +6514,5 @@
 
 #ifdef HAVE_IDEA
-    if (EVP_IDEA_CBC && XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0)
+    if (XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0)
         return IDEA_BLOCK_SIZE;
 #endif
@@ -6382,5 +6569,5 @@
 
 
-int wolfSSL_EVP_PKEY_id(const EVP_PKEY *pkey)
+int wolfSSL_EVP_PKEY_id(const WOLFSSL_EVP_PKEY *pkey)
 {
     if (pkey != NULL)
@@ -6390,5 +6577,5 @@
 
 
-int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey)
+int wolfSSL_EVP_PKEY_base_id(const WOLFSSL_EVP_PKEY *pkey)
 {
     if (pkey == NULL)
@@ -6397,4 +6584,30 @@
 }
 
+int wolfSSL_EVP_PKEY_get_default_digest_nid(WOLFSSL_EVP_PKEY *pkey, int *pnid)
+{
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get_default_digest_nid");
+
+    if (!pkey || !pnid) {
+        WOLFSSL_MSG("Bad parameter");
+        return WOLFSSL_FAILURE;
+    }
+
+    switch (pkey->type) {
+    case EVP_PKEY_HMAC:
+#ifndef NO_DSA
+    case EVP_PKEY_DSA:
+#endif
+#ifndef NO_RSA
+    case EVP_PKEY_RSA:
+#endif
+#ifdef HAVE_ECC
+    case EVP_PKEY_EC:
+#endif
+        *pnid = NID_sha256;
+        return WOLFSSL_SUCCESS;
+    default:
+        return WOLFSSL_FAILURE;
+    }
+}
 
 /* increments ref count of WOLFSSL_EVP_PKEY. Return 1 on success, 0 on error */
@@ -6408,8 +6621,8 @@
         wc_UnLockMutex(&pkey->refMutex);
 
-        return 1;
-    }
-
-    return 0;
+        return WOLFSSL_SUCCESS;
+    }
+
+    return WOLFSSL_FAILURE;
 }
 
@@ -6479,5 +6692,5 @@
 #endif /* OPENSSL_EXTRA */
 
-#if defined(OPENSSL_EXTRA_X509_SMALL)
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
 /* Subset of OPENSSL_EXTRA for PKEY operations PKEY free is needed by the
  * subset of X509 API */
@@ -6503,4 +6716,7 @@
         ret = wc_InitRng(&pkey->rng);
 #endif
+        pkey->references = 1;
+        wc_InitMutex(&pkey->refMutex); /* init of mutex needs to come before
+                                        * wolfSSL_EVP_PKEY_free */
         if (ret != 0){
             wolfSSL_EVP_PKEY_free(pkey);
@@ -6508,6 +6724,4 @@
             return NULL;
         }
-        pkey->references = 1;
-        wc_InitMutex(&pkey->refMutex);
     }
     else {
@@ -6591,5 +6805,79 @@
 }
 
-#endif /* OPENSSL_EXTRA_X509_SMALL */
+#if !defined(NO_PWDBASED)
+int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp,
+    int* pHash, int* pHashSz)
+{
+    enum wc_HashType hash = WC_HASH_TYPE_NONE;
+    int hashSz;
+
+    if (XSTRLEN(evp) < 3) {
+        /* do not try comparing strings if size is too small */
+        return WOLFSSL_FAILURE;
+    }
+
+    if (XSTRNCMP("SHA", evp, 3) == 0) {
+        if (XSTRLEN(evp) > 3) {
+        #ifndef NO_SHA256
+            if (XSTRNCMP("SHA256", evp, 6) == 0) {
+                hash = WC_HASH_TYPE_SHA256;
+            }
+            else
+        #endif
+        #ifdef WOLFSSL_SHA384
+            if (XSTRNCMP("SHA384", evp, 6) == 0) {
+                hash = WC_HASH_TYPE_SHA384;
+            }
+            else
+        #endif
+        #ifdef WOLFSSL_SHA512
+            if (XSTRNCMP("SHA512", evp, 6) == 0) {
+                hash = WC_HASH_TYPE_SHA512;
+            }
+            else
+        #endif
+            if (XSTRNCMP("SHA1", evp, 4) == 0) {
+                hash = WC_HASH_TYPE_SHA;
+            }
+            else {
+                WOLFSSL_MSG("Unknown SHA hash");
+            }
+        }
+        else {
+            hash = WC_HASH_TYPE_SHA;
+        }
+    }
+#ifdef WOLFSSL_MD2
+    else if (XSTRNCMP("MD2", evp, 3) == 0) {
+        hash = WC_HASH_TYPE_MD2;
+    }
+#endif
+#ifndef NO_MD4
+    else if (XSTRNCMP("MD4", evp, 3) == 0) {
+        hash = WC_HASH_TYPE_MD4;
+    }
+#endif
+#ifndef NO_MD5
+    else if (XSTRNCMP("MD5", evp, 3) == 0) {
+        hash = WC_HASH_TYPE_MD5;
+    }
+#endif
+
+    if (pHash)
+        *pHash = hash;
+
+    hashSz = wc_HashGetDigestSize(hash);
+    if (pHashSz)
+        *pHashSz = hashSz;
+
+    if (hashSz < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !defined(NO_PWDBASED) */
+
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
 
 #endif /* WOLFSSL_EVP_INCLUDED */
