Index: azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/wolfcrypt/src/rsa.c
===================================================================
--- azure_iot_hub_f767zi/trunk/wolfssl-4.4.0/wolfcrypt/src/rsa.c	(revision 457)
+++ azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/wolfcrypt/src/rsa.c	(revision 464)
@@ -20,5 +20,11 @@
  */
 
-
+/*
+
+DESCRIPTION
+This library provides the interface to the RSA.
+RSA keys can be used to encrypt, decrypt, sign and verify data.
+
+*/
 #ifdef HAVE_CONFIG_H
     #include <config.h>
@@ -336,5 +342,5 @@
 }
 
-#ifdef HAVE_PKCS11
+#ifdef WOLF_CRYPTO_CB
 int wc_InitRsaKey_Id(RsaKey* key, unsigned char* id, int len, void* heap,
                      int devId)
@@ -349,8 +355,30 @@
     if (ret == 0)
         ret = wc_InitRsaKey_ex(key, heap, devId);
-
     if (ret == 0 && id != NULL && len != 0) {
         XMEMCPY(key->id, id, len);
         key->idLen = len;
+    }
+
+    return ret;
+}
+
+int wc_InitRsaKey_Label(RsaKey* key, const char* label, void* heap, int devId)
+{
+    int ret = 0;
+    int labelLen = 0;
+
+    if (key == NULL || label == NULL)
+        ret = BAD_FUNC_ARG;
+    if (ret == 0) {
+        labelLen = (int)XSTRLEN(label);
+        if (labelLen == 0 || labelLen > RSA_MAX_LABEL_LEN)
+            ret = BUFFER_E;
+    }
+
+    if (ret == 0)
+        ret = wc_InitRsaKey_ex(key, heap, devId);
+    if (ret == 0) {
+        XMEMCPY(key->label, label, labelLen);
+        key->labelLen = labelLen;
     }
 
@@ -381,5 +409,5 @@
     mSz = mp_unsigned_bin_size(&(key->n));
     m = (unsigned char*)XMALLOC(mSz, key->heap, DYNAMIC_TYPE_KEY);
-    if (m == 0) {
+    if (m == NULL) {
         return MEMORY_E;
     }
@@ -478,12 +506,12 @@
     CRYS_RSAKGFipsContext_t FipsCtx;
     byte ex[3];
-    uint16_t eSz = sizeof(ex);
+    word16 eSz = sizeof(ex);
     byte n[256];
-    uint16_t nSz = sizeof(n);
+    word16 nSz = sizeof(n);
 
     ret = CRYS_RSA_KG_GenerateKeyPair(&wc_rndState,
                         wc_rndGenVectFunc,
                         (byte*)&e,
-                        3*sizeof(uint8_t),
+                        3*sizeof(byte),
                         size,
                         &key->ctx.privKey,
@@ -606,57 +634,71 @@
             ret = MP_READ_E;
     }
-
 #ifdef WOLFSSL_HAVE_SP_RSA
-#ifndef WOLFSSL_SP_NO_2048
-    if (mp_count_bits(&key->n) == 2048) {
-        ret = sp_ModExp_2048(k, &key->e, &key->n, tmp);
-        if (ret != 0)
+    if (ret == 0) {
+        switch (mp_count_bits(&key->n)) {
+    #ifndef WOLFSSL_SP_NO_2048
+            case 2048:
+                ret = sp_ModExp_2048(k, &key->e, &key->n, tmp);
+                if (ret != 0)
+                    ret = MP_EXPTMOD_E;
+                if (ret == 0) {
+                    ret = sp_ModExp_2048(tmp, &key->d, &key->n, tmp);
+                    if (ret != 0)
+                        ret = MP_EXPTMOD_E;
+                }
+                break;
+    #endif /* WOLFSSL_SP_NO_2048 */
+    #ifndef WOLFSSL_SP_NO_3072
+            case 3072:
+                ret = sp_ModExp_3072(k, &key->e, &key->n, tmp);
+                if (ret != 0)
+                    ret = MP_EXPTMOD_E;
+                if (ret == 0) {
+                  ret = sp_ModExp_3072(tmp, &key->d, &key->n, tmp);
+                  if (ret != 0)
+                      ret = MP_EXPTMOD_E;
+                }
+                break;
+    #endif /* WOLFSSL_SP_NO_3072 */
+    #ifdef WOLFSSL_SP_4096
+            case 4096:
+                ret = sp_ModExp_4096(k, &key->e, &key->n, tmp);
+                if (ret != 0)
+                    ret = MP_EXPTMOD_E;
+                if (ret == 0) {
+                  ret = sp_ModExp_4096(tmp, &key->d, &key->n, tmp);
+                  if (ret != 0)
+                      ret = MP_EXPTMOD_E;
+                }
+                break;
+    #endif /* WOLFSSL_SP_4096 */
+                default:
+                /* If using only single precsision math then issue key size
+                 * error, otherwise fall-back to multi-precision math
+                 * calculation */
+                #if defined(WOLFSSL_SP_MATH)
+                    ret = WC_KEY_SIZE_E;
+                #else
+                    if (mp_exptmod_nct(k, &key->e, &key->n, tmp) != MP_OKAY)
+                        ret = MP_EXPTMOD_E;
+                    if (ret == 0) {
+                        if (mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY)
+                            ret = MP_EXPTMOD_E;
+                    }
+                #endif
+                    break;
+        }
+    }
+#else
+    if (ret == 0) {
+        if (mp_exptmod_nct(k, &key->e, &key->n, tmp) != MP_OKAY)
             ret = MP_EXPTMOD_E;
-        ret = sp_ModExp_2048(tmp, &key->d, &key->n, tmp);
-        if (ret != 0)
+    }
+
+    if (ret == 0) {
+        if (mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY)
             ret = MP_EXPTMOD_E;
     }
-    else
-#endif
-#ifndef WOLFSSL_SP_NO_3072
-    if (mp_count_bits(&key->n) == 3072) {
-        ret = sp_ModExp_3072(k, &key->e, &key->n, tmp);
-        if (ret != 0)
-            ret = MP_EXPTMOD_E;
-        ret = sp_ModExp_3072(tmp, &key->d, &key->n, tmp);
-        if (ret != 0)
-            ret = MP_EXPTMOD_E;
-    }
-    else
-#endif
-#ifdef WOLFSSL_SP_4096
-    if (mp_count_bits(&key->n) == 4096) {
-        ret = sp_ModExp_4096(k, &key->e, &key->n, tmp);
-        if (ret != 0)
-            ret = MP_EXPTMOD_E;
-        ret = sp_ModExp_4096(tmp, &key->d, &key->n, tmp);
-        if (ret != 0)
-            ret = MP_EXPTMOD_E;
-    }
-    else
-#endif
-#endif
-#ifdef WOLFSSL_SP_MATH
-    {
-        ret = WC_KEY_SIZE_E;
-    }
-#else
-    {
-        if (ret == 0) {
-            if (mp_exptmod(k, &key->e, &key->n, tmp) != MP_OKAY)
-                ret = MP_EXPTMOD_E;
-        }
-
-        if (ret == 0) {
-            if (mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY)
-                ret = MP_EXPTMOD_E;
-        }
-    }
-#endif
+#endif /* WOLFSSL_HAVE_SP_RSA */
 
     if (ret == 0) {
@@ -757,6 +799,6 @@
     return ret;
 }
-#endif
-#endif
+#endif /* WOLFSSL_KEY_GEN && !WOLFSSL_NO_RSA_KEY_CHECK */
+#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
 
 
@@ -816,8 +858,8 @@
 
         /* counter to byte array appended to tmp */
-        tmp[seedSz]     = (counter >> 24) & 0xFF;
-        tmp[seedSz + 1] = (counter >> 16) & 0xFF;
-        tmp[seedSz + 2] = (counter >>  8) & 0xFF;
-        tmp[seedSz + 3] = (counter)       & 0xFF;
+        tmp[seedSz]     = (byte)((counter >> 24) & 0xFF);
+        tmp[seedSz + 1] = (byte)((counter >> 16) & 0xFF);
+        tmp[seedSz + 2] = (byte)((counter >>  8) & 0xFF);
+        tmp[seedSz + 3] = (byte)((counter)       & 0xFF);
 
         /* hash and append to existing output */
@@ -1103,10 +1145,11 @@
     byte* m;
     byte* s;
+#if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY)
+    byte msg[RSA_MAX_SIZE/8 + RSA_PSS_PAD_SZ];
+#else
+    byte* msg = NULL;
+#endif
 #if defined(WOLFSSL_PSS_LONG_SALT) || defined(WOLFSSL_PSS_SALT_LEN_DISCOVER)
-    #if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY)
-        byte salt[RSA_MAX_SIZE/8 + RSA_PSS_PAD_SZ];
-    #else
-        byte* salt = NULL;
-    #endif
+    byte* salt;
 #else
     byte salt[WC_MAX_DIGEST_SIZE];
@@ -1122,7 +1165,13 @@
     if (hLen < 0)
         return hLen;
+    if ((int)inputLen != hLen) {
+        return BAD_FUNC_ARG;
+    }
 
     hiBits = (bits - 1) & 0x7;
     if (hiBits == 0) {
+        /* Per RFC8017, set the leftmost 8emLen - emBits bits of the
+           leftmost octet in DB to zero.
+        */
         *(pkcsBlock++) = 0;
         pkcsBlockLen--;
@@ -1161,16 +1210,15 @@
         return PSS_SALTLEN_E;
     }
-
     maskLen = pkcsBlockLen - 1 - hLen;
 
 #if defined(WOLFSSL_PSS_LONG_SALT) || defined(WOLFSSL_PSS_SALT_LEN_DISCOVER)
     #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
-        salt = (byte*)XMALLOC(RSA_PSS_PAD_SZ + inputLen + saltLen, heap,
+        msg = (byte*)XMALLOC(RSA_PSS_PAD_SZ + inputLen + saltLen, heap,
                                                        DYNAMIC_TYPE_RSA_BUFFER);
-        if (salt == NULL) {
+        if (msg == NULL) {
             return MEMORY_E;
         }
     #endif
-    s = m = salt;
+    salt = s = m = msg;
     XMEMSET(m, 0, RSA_PSS_PAD_SZ);
     m += RSA_PSS_PAD_SZ;
@@ -1185,5 +1233,18 @@
     }
 #else
-    s = m = pkcsBlock;
+    if (pkcsBlockLen < RSA_PSS_PAD_SZ + inputLen + saltLen) {
+    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
+        msg = (byte*)XMALLOC(RSA_PSS_PAD_SZ + inputLen + saltLen, heap,
+                                                       DYNAMIC_TYPE_RSA_BUFFER);
+        if (msg == NULL) {
+            return MEMORY_E;
+        }
+    #endif
+        m = msg;
+    }
+    else {
+        m = pkcsBlock;
+    }
+    s = m;
     XMEMSET(m, 0, RSA_PSS_PAD_SZ);
     m += RSA_PSS_PAD_SZ;
@@ -1204,4 +1265,5 @@
     }
     if (ret == 0) {
+       /* Set the last eight bits or trailer field to the octet 0xbc */
         pkcsBlock[pkcsBlockLen - 1] = RSA_PSS_PAD_TERM;
 
@@ -1209,5 +1271,8 @@
     }
     if (ret == 0) {
-        pkcsBlock[0] &= (1 << hiBits) - 1;
+        /* Clear the first high bit when "8emLen - emBits" is non-zero.
+           where emBits = n modBits - 1 */
+        if (hiBits)
+            pkcsBlock[0] &= (1 << hiBits) - 1;
 
         m = pkcsBlock + maskLen - saltLen - 1;
@@ -1218,11 +1283,9 @@
     }
 
-#if defined(WOLFSSL_PSS_LONG_SALT) || defined(WOLFSSL_PSS_SALT_LEN_DISCOVER)
     #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
-        if (salt != NULL) {
-            XFREE(salt, heap, DYNAMIC_TYPE_RSA_BUFFER);
+        if (msg != NULL) {
+            XFREE(msg, heap, DYNAMIC_TYPE_RSA_BUFFER);
         }
     #endif
-#endif
     return ret;
 }
@@ -1238,4 +1301,8 @@
     }
 
+    if (pkcsBlockLen - RSA_MIN_PAD_SZ < inputLen) {
+        WOLFSSL_MSG("RsaPad error, invalid length");
+        return RSA_PAD_E;
+    }
     pkcsBlock[0] = 0x0;       /* set first byte to zero and advance */
     pkcsBlock++; pkcsBlockLen--;
@@ -1243,8 +1310,4 @@
 
     if (padValue == RSA_BLOCK_TYPE_1) {
-        if (pkcsBlockLen < inputLen + 2) {
-            WOLFSSL_MSG("RsaPad error, invalid length");
-            return RSA_PAD_E;
-        }
 
         /* pad with 0xff bytes */
@@ -1256,10 +1319,4 @@
         word32 padLen, i;
         int    ret;
-
-        if (pkcsBlockLen < inputLen + 1) {
-            WOLFSSL_MSG("RsaPad error, invalid length");
-            return RSA_PAD_E;
-        }
-
         padLen = pkcsBlockLen - inputLen - 1;
         ret    = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen);
@@ -1458,7 +1515,8 @@
  * bits          Length of key in bits.
  * heap          Used for dynamic memory allocation.
- * returns 0 on success, PSS_SALTLEN_E when the salt length is invalid,
- * BAD_PADDING_E when the padding is not valid, MEMORY_E when allocation fails
- * and other negative values on error.
+ * returns       the sum of salt length and SHA-256 digest size on success.
+ *               Otherwise, PSS_SALTLEN_E for an incorrect salt length,
+ *               WC_KEY_SIZE_E for an incorrect encoded message (EM) size
+                 and other negative values on error.
  */
 static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen,
@@ -1597,5 +1655,5 @@
 #endif
 
-    if (output == NULL || pkcsBlockLen == 0 || pkcsBlockLen > 0xFFFF) {
+    if (output == NULL || pkcsBlockLen < 2 || pkcsBlockLen > 0xFFFF) {
         return BAD_FUNC_ARG;
     }
@@ -1719,52 +1777,55 @@
 }
 
-#if defined(WOLFSSL_XILINX_CRYPT)
-/*
- * Xilinx hardened crypto acceleration.
- *
- * Returns 0 on success and negative values on error.
- */
-static int wc_RsaFunctionXil(const byte* in, word32 inLen, byte* out,
-                          word32* outLen, int type, RsaKey* key, WC_RNG* rng)
-{
-    int    ret = 0;
-    word32 keyLen;
-    (void)rng;
-
-    keyLen = wc_RsaEncryptSize(key);
-    if (keyLen > *outLen) {
-        WOLFSSL_MSG("Output buffer is not big enough");
-        return BAD_FUNC_ARG;
-    }
-
-    if (inLen != keyLen) {
-        WOLFSSL_MSG("Expected that inLen equals RSA key length");
-        return BAD_FUNC_ARG;
-    }
-
-    switch(type) {
-    case RSA_PRIVATE_DECRYPT:
-    case RSA_PRIVATE_ENCRYPT:
-        /* Currently public exponent is loaded by default.
-         * In SDK 2017.1 RSA exponent values are expected to be of 4 bytes
-         * leading to private key operations with Xsecure_RsaDecrypt not being
-         * supported */
-        ret = RSA_WRONG_TYPE_E;
+int wc_hash2mgf(enum wc_HashType hType)
+{
+    switch (hType) {
+    case WC_HASH_TYPE_NONE:
+        return WC_MGF1NONE;
+    case WC_HASH_TYPE_SHA:
+#ifndef NO_SHA
+        return WC_MGF1SHA1;
+#else
         break;
-    case RSA_PUBLIC_ENCRYPT:
-    case RSA_PUBLIC_DECRYPT:
-        if (XSecure_RsaDecrypt(&(key->xRsa), in, out) != XST_SUCCESS) {
-            ret = BAD_STATE_E;
-        }
+#endif
+    case WC_HASH_TYPE_SHA224:
+#ifdef WOLFSSL_SHA224
+        return WC_MGF1SHA224;
+#else
         break;
+#endif
+    case WC_HASH_TYPE_SHA256:
+#ifndef NO_SHA256
+        return WC_MGF1SHA256;
+#else
+        break;
+#endif
+    case WC_HASH_TYPE_SHA384:
+#ifdef WOLFSSL_SHA384
+        return WC_MGF1SHA384;
+#else
+        break;
+#endif
+    case WC_HASH_TYPE_SHA512:
+#ifdef WOLFSSL_SHA512
+        return WC_MGF1SHA512;
+#else
+        break;
+#endif
+    case WC_HASH_TYPE_MD2:
+    case WC_HASH_TYPE_MD4:
+    case WC_HASH_TYPE_MD5:
+    case WC_HASH_TYPE_MD5_SHA:
+    case WC_HASH_TYPE_SHA3_224:
+    case WC_HASH_TYPE_SHA3_256:
+    case WC_HASH_TYPE_SHA3_384:
+    case WC_HASH_TYPE_SHA3_512:
+    case WC_HASH_TYPE_BLAKE2B:
+    case WC_HASH_TYPE_BLAKE2S:
     default:
-        ret = RSA_WRONG_TYPE_E;
-    }
-
-    *outLen = keyLen;
-
-    return ret;
-}
-#endif /* WOLFSSL_XILINX_CRYPT */
+        break;
+    }
+    WOLFSSL_MSG("Unrecognized or unsupported hash function");
+    return WC_MGF1NONE;
+}
 
 #ifdef WC_RSA_NONBLOCK
@@ -1846,5 +1907,90 @@
 #endif /* WC_RSA_NONBLOCK */
 
-#ifdef WOLFSSL_AFALG_XILINX_RSA
+#ifdef WOLFSSL_XILINX_CRYPT
+/*
+ * Xilinx hardened crypto acceleration.
+ *
+ * Returns 0 on success and negative values on error.
+ */
+static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out,
+                          word32* outLen, int type, RsaKey* key, WC_RNG* rng)
+{
+    int    ret = 0;
+    word32 keyLen;
+    (void)rng;
+
+    keyLen = wc_RsaEncryptSize(key);
+    if (keyLen > *outLen) {
+        WOLFSSL_MSG("Output buffer is not big enough");
+        return BAD_FUNC_ARG;
+    }
+
+    if (inLen != keyLen) {
+        WOLFSSL_MSG("Expected that inLen equals RSA key length");
+        return BAD_FUNC_ARG;
+    }
+
+    switch(type) {
+    case RSA_PRIVATE_DECRYPT:
+    case RSA_PRIVATE_ENCRYPT:
+    #ifdef WOLFSSL_XILINX_CRYPTO_OLD
+        /* Currently public exponent is loaded by default.
+         * In SDK 2017.1 RSA exponent values are expected to be of 4 bytes
+         * leading to private key operations with Xsecure_RsaDecrypt not being
+         * supported */
+        ret = RSA_WRONG_TYPE_E;
+    #else
+        {
+            byte *d;
+            int dSz;
+            XSecure_Rsa rsa;
+
+            dSz = mp_unsigned_bin_size(&key->d);
+            d = (byte*)XMALLOC(dSz, key->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+            if (d == NULL) {
+                ret = MEMORY_E;
+            }
+            else {
+                ret = mp_to_unsigned_bin(&key->d, d);
+                XSecure_RsaInitialize(&rsa, key->mod, NULL, d);
+            }
+
+            if (ret == 0) {
+                if (XSecure_RsaPrivateDecrypt(&rsa, (u8*)in, inLen, out) !=
+                        XST_SUCCESS) {
+                    ret = BAD_STATE_E;
+                }
+            }
+
+            if (d != NULL) {
+                XFREE(d, key->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+            }
+        }
+    #endif
+        break;
+    case RSA_PUBLIC_ENCRYPT:
+    case RSA_PUBLIC_DECRYPT:
+#ifdef WOLFSSL_XILINX_CRYPTO_OLD
+        if (XSecure_RsaDecrypt(&(key->xRsa), in, out) != XST_SUCCESS) {
+            ret = BAD_STATE_E;
+        }
+#else
+        /* starting at Xilinx release 2019 the function XSecure_RsaDecrypt was removed */
+        if (XSecure_RsaPublicEncrypt(&(key->xRsa), (u8*)in, inLen, out) != XST_SUCCESS) {
+            WOLFSSL_MSG("Error happened when calling hardware RSA public operation");
+            ret = BAD_STATE_E;
+        }
+#endif
+        break;
+    default:
+        ret = RSA_WRONG_TYPE_E;
+    }
+
+    *outLen = keyLen;
+
+    return ret;
+}
+
+#elif defined(WOLFSSL_AFALG_XILINX_RSA)
 #ifndef ERROR_OUT
 #define ERROR_OUT(x) ret = (x); goto done
@@ -2010,5 +2156,5 @@
                           word32* outLen, int type, RsaKey* key, WC_RNG* rng)
 {
-#ifndef WOLFSSL_SP_MATH
+#if !defined(WOLFSSL_SP_MATH)
 #ifdef WOLFSSL_SMALL_STACK
     mp_int* tmp;
@@ -2039,10 +2185,14 @@
     #endif
     #ifndef RSA_LOW_MEM
-            return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q,
-                                      &key->dP, &key->dQ, &key->u, &key->n,
-                                      out, outLen);
+            if ((mp_count_bits(&key->p) == 1024) &&
+                                             (mp_count_bits(&key->q) == 1024)) {
+                return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q,
+                                          &key->dP, &key->dQ, &key->u, &key->n,
+                                          out, outLen);
+            }
+            break;
     #else
-            return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q,
-                                      NULL, NULL, NULL, &key->n, out, outLen);
+            return sp_RsaPrivate_2048(in, inLen, &key->d, NULL, NULL, NULL,
+                                      NULL, NULL, &key->n, out, outLen);
     #endif
 #endif
@@ -2064,10 +2214,14 @@
     #endif
     #ifndef RSA_LOW_MEM
-            return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q,
-                                      &key->dP, &key->dQ, &key->u, &key->n,
-                                      out, outLen);
+            if ((mp_count_bits(&key->p) == 1536) &&
+                                             (mp_count_bits(&key->q) == 1536)) {
+                return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q,
+                                          &key->dP, &key->dQ, &key->u, &key->n,
+                                          out, outLen);
+            }
+            break;
     #else
-            return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q,
-                                      NULL, NULL, NULL, &key->n, out, outLen);
+            return sp_RsaPrivate_3072(in, inLen, &key->d, NULL, NULL, NULL,
+                                      NULL, NULL, &key->n, out, outLen);
     #endif
 #endif
@@ -2089,10 +2243,14 @@
     #endif
     #ifndef RSA_LOW_MEM
-            return sp_RsaPrivate_4096(in, inLen, &key->d, &key->p, &key->q,
-                                      &key->dP, &key->dQ, &key->u, &key->n,
-                                      out, outLen);
+            if ((mp_count_bits(&key->p) == 2048) &&
+                                             (mp_count_bits(&key->q) == 2048)) {
+                return sp_RsaPrivate_4096(in, inLen, &key->d, &key->p, &key->q,
+                                          &key->dP, &key->dQ, &key->u, &key->n,
+                                          out, outLen);
+            }
+            break;
     #else
-            return sp_RsaPrivate_4096(in, inLen, &key->d, &key->p, &key->q,
-                                      NULL, NULL, NULL, &key->n, out, outLen);
+            return sp_RsaPrivate_4096(in, inLen, &key->d, NULL, NULL, NULL,
+                                      NULL, NULL, &key->n, out, outLen);
     #endif
 #endif
@@ -2105,5 +2263,5 @@
 #endif /* WOLFSSL_HAVE_SP_RSA */
 
-#ifdef WOLFSSL_SP_MATH
+#if defined(WOLFSSL_SP_MATH)
     (void)rng;
     WOLFSSL_MSG("SP Key Size Error");
@@ -2116,4 +2274,5 @@
     if (tmp == NULL)
         return MEMORY_E;
+#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY)
 #ifdef WC_RSA_BLINDING
     rnd = (mp_int*)XMALLOC(sizeof(mp_int) * 2, key->heap, DYNAMIC_TYPE_RSA);
@@ -2124,4 +2283,5 @@
     rndi = rnd + 1;
 #endif /* WC_RSA_BLINDING */
+#endif
 #endif /* WOLFSSL_SMALL_STACK */
 
@@ -2129,4 +2289,5 @@
         ret = MP_INIT_E;
 
+#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY)
 #ifdef WC_RSA_BLINDING
     if (ret == 0) {
@@ -2139,4 +2300,5 @@
     }
 #endif
+#endif
 
 #ifndef TEST_UNPAD_CONSTANT_TIME
@@ -2146,5 +2308,5 @@
     if (ret == 0) {
         switch(type) {
-    #ifndef WOLFSSL_RSA_PUBLIC_ONLY
+    #if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY)
         case RSA_PRIVATE_DECRYPT:
         case RSA_PRIVATE_ENCRYPT:
@@ -2159,6 +2321,13 @@
 
             /* rnd = rnd^e */
+        #ifndef WOLFSSL_SP_MATH_ALL
             if (ret == 0 && mp_exptmod(rnd, &key->e, &key->n, rnd) != MP_OKAY)
                 ret = MP_EXPTMOD_E;
+        #else
+            if (ret == 0 && mp_exptmod_nct(rnd, &key->e, &key->n,
+                                                              rnd) != MP_OKAY) {
+                ret = MP_EXPTMOD_E;
+            }
+        #endif
 
             /* tmp = tmp*rnd mod n */
@@ -2214,6 +2383,12 @@
 
                 /* tmp = (tmpa - tmpb) * qInv (mod p) */
+#if defined(WOLFSSL_SP_MATH) || (defined(WOLFSSL_SP_MATH_ALL) && \
+                                              !defined(WOLFSSL_SP_INT_NEGATIVE))
+                if (ret == 0 && mp_submod(tmpa, tmpb, &key->p, tmp) != MP_OKAY)
+                    ret = MP_SUB_E;
+#else
                 if (ret == 0 && mp_sub(tmpa, tmpb, tmp) != MP_OKAY)
                     ret = MP_SUB_E;
+#endif
 
                 if (ret == 0 && mp_mulmod(tmp, &key->u, &key->p,
@@ -2254,10 +2429,6 @@
         case RSA_PUBLIC_ENCRYPT:
         case RSA_PUBLIC_DECRYPT:
-        #ifdef WOLFSSL_XILINX_CRYPT
-            ret = wc_RsaFunctionXil(in, inLen, out, outLen, type, key, rng);
-        #else
             if (mp_exptmod_nct(tmp, &key->e, &key->n, tmp) != MP_OKAY)
                 ret = MP_EXPTMOD_E;
-        #endif
             break;
         default:
@@ -2272,4 +2443,6 @@
             ret = RSA_BUFFER_E;
     }
+
+#ifndef WOLFSSL_XILINX_CRYPT
     if (ret == 0) {
         *outLen = keyLen;
@@ -2277,4 +2450,5 @@
              ret = MP_TO_E;
     }
+#endif
 #else
     (void)type;
@@ -2510,5 +2684,5 @@
     CRYSError_t ret = 0;
     CRYS_RSAPrimeData_t primeData;
-    uint16_t actualOutLen = outLen;
+    word16 actualOutLen = outLen;
 
     ret = CRYS_RSA_PKCS1v15_Decrypt(&key->ctx.privKey,
@@ -2530,5 +2704,5 @@
 {
     CRYSError_t ret = 0;
-    uint16_t actualOutLen = outLen*sizeof(byte);
+    word16 actualOutLen = outLen*sizeof(byte);
     CRYS_RSAPrivUserContext_t  contextPrivate;
 
@@ -2593,4 +2767,5 @@
 #endif
 
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
 #ifndef TEST_UNPAD_CONSTANT_TIME
 #ifndef NO_RSA_BOUNDS_CHECK
@@ -2612,5 +2787,5 @@
 
         if (mp_init(c) != MP_OKAY)
-            ret = MEMORY_E;
+            ret = MP_INIT_E;
         if (ret == 0) {
             if (mp_read_unsigned_bin(c, in, inLen) != 0)
@@ -2642,4 +2817,5 @@
     }
 #endif /* NO_RSA_BOUNDS_CHECK */
+#endif
 #endif
 
@@ -2990,5 +3166,6 @@
         if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
                                                    pad_type != WC_RSA_PSS_PAD) {
-            if (ret > 0) {
+            ret = key->asyncDev.event.ret;
+            if (ret >= 0) {
                 /* convert result */
                 byte* dataLen = (byte*)&key->dataLen;
@@ -3132,5 +3309,5 @@
                                                                  RsaKey* key)
 {
-    return wc_RsaSSL_Verify_ex(in, inLen, out, outLen, key , WC_RSA_PKCSV15_PAD);
+    return wc_RsaSSL_Verify_ex(in, inLen, out, outLen, key, WC_RSA_PKCSV15_PAD);
 }
 
@@ -3138,4 +3315,11 @@
                          RsaKey* key, int pad_type)
 {
+    return wc_RsaSSL_Verify_ex2(in, inLen, out, outLen, key, pad_type,
+            WC_HASH_TYPE_NONE);
+}
+
+int  wc_RsaSSL_Verify_ex2(const byte* in, word32 inLen, byte* out, word32 outLen,
+                         RsaKey* key, int pad_type, enum wc_HashType hash)
+{
     WC_RNG* rng;
 
@@ -3150,7 +3334,13 @@
 #endif
 
+#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
     return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key,
         RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, pad_type,
-        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
+        hash, wc_hash2mgf(hash), NULL, 0, RSA_PSS_SALT_LEN_DEFAULT, rng);
+#else
+    return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key,
+        RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, pad_type,
+        hash, wc_hash2mgf(hash), NULL, 0, RSA_PSS_SALT_LEN_DISCOVER, rng);
+#endif
 }
 #endif
@@ -3407,5 +3597,5 @@
     hLen = wc_HashGetDigestSize(hash);
     if (hLen < 0)
-        return hLen;
+        return BAD_FUNC_ARG;
     if ((word32)hLen != digestLen)
         return BAD_FUNC_ARG;
@@ -3674,6 +3864,9 @@
         ret = mp_sub(p, q, &d);
 
+#if !defined(WOLFSSL_SP_MATH) && (!defined(WOLFSSL_SP_MATH_ALL) || \
+                                               defined(WOLFSSL_SP_INT_NEGATIVE))
     if (ret == 0)
         ret = mp_abs(&d, &d);
+#endif
 
     /* compare */
@@ -3887,20 +4080,50 @@
 {
 #ifndef WC_NO_RNG
-    mp_int p, q, tmp1, tmp2, tmp3;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int *p = (mp_int *)XMALLOC(sizeof *p, key->heap, DYNAMIC_TYPE_RSA);
+    mp_int *q = (mp_int *)XMALLOC(sizeof *q, key->heap, DYNAMIC_TYPE_RSA);
+    mp_int *tmp1 = (mp_int *)XMALLOC(sizeof *tmp1, key->heap, DYNAMIC_TYPE_RSA);
+    mp_int *tmp2 = (mp_int *)XMALLOC(sizeof *tmp2, key->heap, DYNAMIC_TYPE_RSA);
+    mp_int *tmp3 = (mp_int *)XMALLOC(sizeof *tmp3, key->heap, DYNAMIC_TYPE_RSA);
+#else
+    mp_int p_buf, *p = &p_buf;
+    mp_int q_buf, *q = &q_buf;
+    mp_int tmp1_buf, *tmp1 = &tmp1_buf;
+    mp_int tmp2_buf, *tmp2 = &tmp2_buf;
+    mp_int tmp3_buf, *tmp3 = &tmp3_buf;
+#endif
     int err, i, failCount, primeSz, isPrime = 0;
     byte* buf = NULL;
 
-    if (key == NULL || rng == NULL)
-        return BAD_FUNC_ARG;
-
-    if (!RsaSizeCheck(size))
-        return BAD_FUNC_ARG;
-
-    if (e < 3 || (e & 1) == 0)
-        return BAD_FUNC_ARG;
+#ifdef WOLFSSL_SMALL_STACK
+    if ((p == NULL) ||
+	(q == NULL) ||
+	(tmp1 == NULL) ||
+	(tmp2 == NULL) ||
+	(tmp3 == NULL)) {
+      err = MEMORY_E;
+      goto out;
+    }
+#endif
+
+    if (key == NULL || rng == NULL) {
+        err = BAD_FUNC_ARG;
+        goto out;
+    }
+
+    if (!RsaSizeCheck(size)) {
+        err = BAD_FUNC_ARG;
+        goto out;
+    }
+
+    if (e < 3 || (e & 1) == 0) {
+        err = BAD_FUNC_ARG;
+        goto out;
+    }
 
 #if defined(WOLFSSL_CRYPTOCELL)
 
-    return cc310_RSA_GenerateKeyPair(key, size, e);
+    err = cc310_RSA_GenerateKeyPair(key, size, e);
+    goto out;
 
 #endif /*WOLFSSL_CRYPTOCELL*/
@@ -3908,7 +4131,7 @@
 #ifdef WOLF_CRYPTO_CB
     if (key->devId != INVALID_DEVID) {
-        int ret = wc_CryptoCb_MakeRsaKey(key, size, e, rng);
-        if (ret != CRYPTOCB_UNAVAILABLE)
-            return ret;
+        err = wc_CryptoCb_MakeRsaKey(key, size, e, rng);
+        if (err != CRYPTOCB_UNAVAILABLE)
+            goto out;
         /* fall-through when unavailable */
     }
@@ -3921,5 +4144,6 @@
         /* TODO: Not implemented */
     #elif defined(HAVE_INTEL_QA)
-        return IntelQaRsaKeyGen(&key->asyncDev, key, size, e, rng);
+        err = IntelQaRsaKeyGen(&key->asyncDev, key, size, e, rng);
+        goto out;
     #else
         if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_RSA_MAKE)) {
@@ -3929,5 +4153,6 @@
             testDev->rsaMake.size = size;
             testDev->rsaMake.e = e;
-            return WC_PENDING_E;
+            err = WC_PENDING_E;
+            goto out;
         }
     #endif
@@ -3935,8 +4160,8 @@
 #endif
 
-    err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL);
+    err = mp_init_multi(p, q, tmp1, tmp2, tmp3, NULL);
 
     if (err == MP_OKAY)
-        err = mp_set_int(&tmp3, e);
+        err = mp_set_int(tmp3, e);
 
     /* The failCount value comes from NIST FIPS 186-4, section B.3.3,
@@ -3970,9 +4195,9 @@
                 buf[primeSz-1] |= 0x01;
                 /* load value */
-                err = mp_read_unsigned_bin(&p, buf, primeSz);
+                err = mp_read_unsigned_bin(p, buf, primeSz);
             }
 
             if (err == MP_OKAY)
-                err = _CheckProbablePrime(&p, NULL, &tmp3, size, &isPrime, rng);
+                err = _CheckProbablePrime(p, NULL, tmp3, size, &isPrime, rng);
 
 #ifdef HAVE_FIPS
@@ -4005,9 +4230,9 @@
                 buf[primeSz-1] |= 0x01;
                 /* load value */
-                err = mp_read_unsigned_bin(&q, buf, primeSz);
+                err = mp_read_unsigned_bin(q, buf, primeSz);
             }
 
             if (err == MP_OKAY)
-                err = _CheckProbablePrime(&p, &q, &tmp3, size, &isPrime, rng);
+                err = _CheckProbablePrime(p, q, tmp3, size, &isPrime, rng);
 
 #ifdef HAVE_FIPS
@@ -4028,10 +4253,10 @@
     }
 
-    if (err == MP_OKAY && mp_cmp(&p, &q) < 0) {
-        err = mp_copy(&p, &tmp1);
+    if (err == MP_OKAY && mp_cmp(p, q) < 0) {
+        err = mp_copy(p, tmp1);
         if (err == MP_OKAY)
-            err = mp_copy(&q, &p);
+            err = mp_copy(q, p);
         if (err == MP_OKAY)
-            mp_copy(&tmp1, &q);
+            mp_copy(tmp1, q);
     }
 
@@ -4044,13 +4269,13 @@
     /* Software Key Calculation */
     if (err == MP_OKAY)                /* tmp1 = p-1 */
-        err = mp_sub_d(&p, 1, &tmp1);
+        err = mp_sub_d(p, 1, tmp1);
     if (err == MP_OKAY)                /* tmp2 = q-1 */
-        err = mp_sub_d(&q, 1, &tmp2);
+        err = mp_sub_d(q, 1, tmp2);
 #ifdef WC_RSA_BLINDING
     if (err == MP_OKAY)                /* tmp3 = order of n */
-        err = mp_mul(&tmp1, &tmp2, &tmp3);
+        err = mp_mul(tmp1, tmp2, tmp3);
 #else
     if (err == MP_OKAY)                /* tmp3 = lcm(p-1, q-1), last loop */
-        err = mp_lcm(&tmp1, &tmp2, &tmp3);
+        err = mp_lcm(tmp1, tmp2, tmp3);
 #endif
     /* make key */
@@ -4061,5 +4286,5 @@
     if (err == MP_OKAY) {
         do {
-            err = mp_rand(&key->p, get_digit_count(&tmp3), rng);
+            err = mp_rand(&key->p, get_digit_count(tmp3), rng);
             if (err == MP_OKAY)
                 err = mp_set_bit(&key->p, 0);
@@ -4067,5 +4292,5 @@
                 err = mp_set_bit(&key->p, size - 1);
             if (err == MP_OKAY)
-                err = mp_gcd(&key->p, &tmp3, &key->q);
+                err = mp_gcd(&key->p, tmp3, &key->q);
         }
         while ((err == MP_OKAY) && !mp_isone(&key->q));
@@ -4075,31 +4300,31 @@
 #endif
     if (err == MP_OKAY)                /* key->d = 1/e mod lcm(p-1, q-1) */
-        err = mp_invmod(&key->e, &tmp3, &key->d);
+        err = mp_invmod(&key->e, tmp3, &key->d);
 #ifdef WC_RSA_BLINDING
     /* Take off blinding from d and reset e */
     if (err == MP_OKAY)
-        err = mp_mulmod(&key->d, &key->p, &tmp3, &key->d);
+        err = mp_mulmod(&key->d, &key->p, tmp3, &key->d);
     if (err == MP_OKAY)
         err = mp_set_int(&key->e, (mp_digit)e);
 #endif
     if (err == MP_OKAY)                /* key->n = pq */
-        err = mp_mul(&p, &q, &key->n);
+        err = mp_mul(p, q, &key->n);
     if (err == MP_OKAY)                /* key->dP = d mod(p-1) */
-        err = mp_mod(&key->d, &tmp1, &key->dP);
+        err = mp_mod(&key->d, tmp1, &key->dP);
     if (err == MP_OKAY)                /* key->dQ = d mod(q-1) */
-        err = mp_mod(&key->d, &tmp2, &key->dQ);
+        err = mp_mod(&key->d, tmp2, &key->dQ);
 #ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME
     if (err == MP_OKAY)                /* key->u = 1/q mod p */
-        err = mp_invmod(&q, &p, &key->u);
+        err = mp_invmod(q, p, &key->u);
 #else
     if (err == MP_OKAY)
-        err = mp_sub_d(&p, 2, &tmp3);
+        err = mp_sub_d(p, 2, tmp3);
     if (err == MP_OKAY)                /* key->u = 1/q mod p = q^p-2 mod p */
-        err = mp_exptmod(&q, &tmp3 , &p, &key->u);
+        err = mp_exptmod(q, tmp3 , p, &key->u);
 #endif
     if (err == MP_OKAY)
-        err = mp_copy(&p, &key->p);
+        err = mp_copy(p, &key->p);
     if (err == MP_OKAY)
-        err = mp_copy(&q, &key->q);
+        err = mp_copy(q, &key->q);
 
 #ifdef HAVE_WOLF_BIGINT
@@ -4126,9 +4351,9 @@
         key->type = RSA_PRIVATE;
 
-    mp_clear(&tmp1);
-    mp_clear(&tmp2);
-    mp_clear(&tmp3);
-    mp_clear(&p);
-    mp_clear(&q);
+    mp_clear(tmp1);
+    mp_clear(tmp2);
+    mp_clear(tmp3);
+    mp_clear(p);
+    mp_clear(q);
 
 #if defined(WOLFSSL_KEY_GEN) && !defined(WOLFSSL_NO_RSA_KEY_CHECK)
@@ -4140,5 +4365,5 @@
     if (err != 0) {
         wc_FreeRsaKey(key);
-        return err;
+        goto out;
     }
 
@@ -4148,5 +4373,23 @@
     }
 #endif
-    return 0;
+
+    err = 0;
+
+  out:
+
+#ifdef WOLFSSL_SMALL_STACK
+    if (p)
+        XFREE(p, key->heap, DYNAMIC_TYPE_RSA);
+    if (q)
+        XFREE(q, key->heap, DYNAMIC_TYPE_RSA);
+    if (tmp1)
+        XFREE(tmp1, key->heap, DYNAMIC_TYPE_RSA);
+    if (tmp2)
+        XFREE(tmp2, key->heap, DYNAMIC_TYPE_RSA);
+    if (tmp3)
+        XFREE(tmp3, key->heap, DYNAMIC_TYPE_RSA);
+#endif
+
+    return err;
 #else
     return NOT_COMPILED_IN;
@@ -4160,19 +4403,19 @@
 int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng)
 {
+    if (key == NULL || rng == NULL)
+        return BAD_FUNC_ARG;
+
+    key->rng = rng;
+
+    return 0;
+}
+#endif /* WC_RSA_BLINDING */
+
+#ifdef WC_RSA_NONBLOCK
+int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb)
+{
     if (key == NULL)
         return BAD_FUNC_ARG;
 
-    key->rng = rng;
-
-    return 0;
-}
-#endif /* WC_RSA_BLINDING */
-
-#ifdef WC_RSA_NONBLOCK
-int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb)
-{
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
     if (nb) {
         XMEMSET(nb, 0, sizeof(RsaNb));
