Index: asp3_tinet_ecnl_rx/trunk/wolfssl-3.12.2/wolfcrypt/src/ecc.c
===================================================================
--- asp3_tinet_ecnl_rx/trunk/wolfssl-3.12.2/wolfcrypt/src/ecc.c	(revision 337)
+++ asp3_tinet_ecnl_rx/trunk/wolfssl-3.12.2/wolfcrypt/src/ecc.c	(revision 372)
@@ -94,4 +94,14 @@
 
 
+#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+    #define FIPS_NO_WRAPPERS
+
+	#ifdef USE_WINDOWS_API
+		#pragma code_seg(".fipsA$f")
+		#pragma const_seg(".fipsB$f")
+	#endif
+#endif
+
 #include <wolfssl/wolfcrypt/ecc.h>
 #include <wolfssl/wolfcrypt/asn.h>
@@ -113,4 +123,8 @@
 #endif
 
+#ifdef WOLF_CRYPTO_DEV
+    #include <wolfssl/wolfcrypt/cryptodev.h>
+#endif
+
 #ifdef NO_INLINE
     #include <wolfssl/wolfcrypt/misc.h>
@@ -124,5 +138,7 @@
 #endif
 
-#ifdef USE_FAST_MATH
+#ifdef WOLFSSL_SP_MATH
+    #define GEN_MEM_ERR MP_MEM
+#elif defined(USE_FAST_MATH)
     #define GEN_MEM_ERR FP_MEM
 #else
@@ -186,269 +202,431 @@
 #endif
 
-
 /* The encoded OID's for ECC curves */
 #ifdef ECC112
     #ifndef NO_ECC_SECP
-        static const ecc_oid_t ecc_oid_secp112r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,6
+            #define CODED_SECP112R1    {1,3,132,0,6}
+            #define CODED_SECP112R1_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x06
+            #define CODED_SECP112R1    {0x2B,0x81,0x04,0x00,0x06}
+            #define CODED_SECP112R1_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp112r1[] = CODED_SECP112R1;
+        #else
+            #define ecc_oid_secp112r1 CODED_SECP112R1
+        #endif
+        #define ecc_oid_secp112r1_sz CODED_SECP112R1_SZ
     #endif /* !NO_ECC_SECP */
     #ifdef HAVE_ECC_SECPR2
-        static const ecc_oid_t ecc_oid_secp112r2[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,7
+            #define CODED_SECP112R2    {1,3,132,0,7}
+            #define CODED_SECP112R2_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x07
+            #define CODED_SECP112R2    {0x2B,0x81,0x04,0x00,0x07}
+            #define CODED_SECP112R2_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp112r2[] = CODED_SECP112R2;
+        #else
+            #define ecc_oid_secp112r2 CODED_SECP112R2
+        #endif
+        #define ecc_oid_secp112r2_sz CODED_SECP112R2_SZ
     #endif /* HAVE_ECC_SECPR2 */
 #endif /* ECC112 */
 #ifdef ECC128
     #ifndef NO_ECC_SECP
-        static const ecc_oid_t ecc_oid_secp128r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,28
+            #define CODED_SECP128R1    {1,3,132,0,28}
+            #define CODED_SECP128R1_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x1C
+            #define CODED_SECP128R1    {0x2B,0x81,0x04,0x00,0x1C}
+            #define CODED_SECP128R1_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp128r1[] = CODED_SECP128R1;
+        #else
+            #define ecc_oid_secp128r1 CODED_SECP128R1
+        #endif
+        #define ecc_oid_secp128r1_sz CODED_SECP128R1_SZ
     #endif /* !NO_ECC_SECP */
     #ifdef HAVE_ECC_SECPR2
-        static const ecc_oid_t ecc_oid_secp128r2[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,29
+            #define CODED_SECP128R2    {1,3,132,0,29}
+            #define CODED_SECP128R2_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x1D
+            #define CODED_SECP128R2    {0x2B,0x81,0x04,0x00,0x1D}
+            #define CODED_SECP128R2_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp128r2[] = CODED_SECP128R2;
+        #else
+            #define ecc_oid_secp128r2 CODED_SECP128R2
+        #endif
+        #define ecc_oid_secp128r2_sz CODED_SECP128R2_SZ
     #endif /* HAVE_ECC_SECPR2 */
 #endif /* ECC128 */
 #ifdef ECC160
     #ifndef NO_ECC_SECP
-        static const ecc_oid_t ecc_oid_secp160r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,8
+            #define CODED_SECP160R1    {1,3,132,0,8}
+            #define CODED_SECP160R1_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x08
+            #define CODED_SECP160R1    {0x2B,0x81,0x04,0x00,0x08}
+            #define CODED_SECP160R1_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp160r1[] = CODED_SECP160R1;
+        #else
+            #define ecc_oid_secp160r1 CODED_SECP160R1
+        #endif
+        #define ecc_oid_secp160r1_sz CODED_SECP160R1_SZ
     #endif /* !NO_ECC_SECP */
     #ifdef HAVE_ECC_SECPR2
-        static const ecc_oid_t ecc_oid_secp160r2[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,30
+            #define CODED_SECP160R2    {1,3,132,0,30}
+            #define CODED_SECP160R1_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x1E
+            #define CODED_SECP160R2    {0x2B,0x81,0x04,0x00,0x1E}
+            #define CODED_SECP160R2_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp160r2[] = CODED_SECP160R2;
+        #else
+            #define ecc_oid_secp160r2 CODED_SECP160R2
+        #endif
+        #define ecc_oid_secp160r2_sz CODED_SECP160R2_SZ
     #endif /* HAVE_ECC_SECPR2 */
     #ifdef HAVE_ECC_KOBLITZ
-        static const ecc_oid_t ecc_oid_secp160k1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,9
+            #define CODED_SECP160K1    {1,3,132,0,9}
+            #define CODED_SECP160K1_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x09
+            #define CODED_SECP160K1    {0x2B,0x81,0x04,0x00,0x09}
+            #define CODED_SECP160K1_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp160k1[] = CODED_SECP160K1;
+        #else
+            #define ecc_oid_secp160k1 CODED_SECP160K1
+        #endif
+        #define ecc_oid_secp160k1_sz CODED_SECP160K1_SZ
     #endif /* HAVE_ECC_KOBLITZ */
     #ifdef HAVE_ECC_BRAINPOOL
-        static const ecc_oid_t ecc_oid_brainpoolp160r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,36,3,3,2,8,1,1,1
+            #define CODED_BRAINPOOLP160R1    {1,3,36,3,3,2,8,1,1,1}
+            #define CODED_BRAINPOOLP160R1_SZ 10
         #else
-            0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x01
+            #define CODED_BRAINPOOLP160R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x01}
+            #define CODED_BRAINPOOLP160R1_SZ 9
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_brainpoolp160r1[] = CODED_BRAINPOOLP160R1;
+        #else
+            #define ecc_oid_brainpoolp160r1 CODED_BRAINPOOLP160R1
+        #endif
+        #define ecc_oid_brainpoolp160r1_sz CODED_BRAINPOOLP160R1_SZ
     #endif /* HAVE_ECC_BRAINPOOL */
 #endif /* ECC160 */
 #ifdef ECC192
     #ifndef NO_ECC_SECP
-        static const ecc_oid_t ecc_oid_secp192r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,2,840,10045,3,1,1
+            #define CODED_SECP192R1    {1,2,840,10045,3,1,1}
+            #define CODED_SECP192R1_SZ 7
         #else
-            0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01
+            #define CODED_SECP192R1    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01}
+            #define CODED_SECP192R1_SZ 8
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp192r1[] = CODED_SECP192R1;
+        #else
+            #define ecc_oid_secp192r1 CODED_SECP192R1
+        #endif
+        #define ecc_oid_secp192r1_sz CODED_SECP192R1_SZ
     #endif /* !NO_ECC_SECP */
     #ifdef HAVE_ECC_SECPR2
-        static const ecc_oid_t ecc_oid_prime192v2[] = {
         #ifdef HAVE_OID_ENCODING
-            1,2,840,10045,3,1,2
+            #define CODED_PRIME192V2    {1,2,840,10045,3,1,2}
+            #define CODED_PRIME192V2_SZ 7
         #else
-            0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x02
+            #define CODED_PRIME192V2    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x02}
+            #define CODED_PRIME192V2_SZ 8
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_prime192v2[] = CODED_PRIME192V2;
+        #else
+            #define ecc_oid_prime192v2 CODED_PRIME192V2
+        #endif
+        #define ecc_oid_prime192v2_sz CODED_PRIME192V2_SZ
     #endif /* HAVE_ECC_SECPR2 */
     #ifdef HAVE_ECC_SECPR3
-        static const ecc_oid_t ecc_oid_prime192v3[] = {
         #ifdef HAVE_OID_ENCODING
-            1,2,840,10045,3,1,3
+            #define CODED_PRIME192V3    {1,2,840,10045,3,1,3}
+            #define CODED_PRIME192V3_SZ 7
         #else
-            0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x03
+            #define CODED_PRIME192V3    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x03}
+            #define CODED_PRIME192V3_SZ 8
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_prime192v3[] = CODED_PRIME192V3;
+        #else
+            #define ecc_oid_prime192v3 CODED_PRIME192V3
+        #endif
+        #define ecc_oid_prime192v3_sz CODED_PRIME192V3_SZ
     #endif /* HAVE_ECC_SECPR3 */
     #ifdef HAVE_ECC_KOBLITZ
-        static const ecc_oid_t ecc_oid_secp192k1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,31
+            #define CODED_SECP192K1    {1,3,132,0,31}
+            #define CODED_SECP192K1_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x1F
+            #define CODED_SECP192K1    {0x2B,0x81,0x04,0x00,0x1F}
+            #define CODED_SECP192K1_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp192k1[] = CODED_SECP192K1;
+        #else
+            #define ecc_oid_secp192k1 CODED_SECP192K1
+        #endif
+        #define ecc_oid_secp192k1_sz CODED_SECP192K1_SZ
     #endif /* HAVE_ECC_KOBLITZ */
     #ifdef HAVE_ECC_BRAINPOOL
-        static const ecc_oid_t ecc_oid_brainpoolp192r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,36,3,3,2,8,1,1,3
+            #define CODED_BRAINPOOLP192R1    {1,3,36,3,3,2,8,1,1,3}
+            #define CODED_BRAINPOOLP192R1_SZ 10
         #else
-            0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x03
+            #define CODED_BRAINPOOLP192R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x03}
+            #define CODED_BRAINPOOLP192R1_SZ 9
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_brainpoolp192r1[] = CODED_BRAINPOOLP192R1;
+        #else
+            #define ecc_oid_brainpoolp192r1 CODED_BRAINPOOLP192R1
+        #endif
+        #define ecc_oid_brainpoolp192r1_sz CODED_BRAINPOOLP192R1_SZ
     #endif /* HAVE_ECC_BRAINPOOL */
 #endif /* ECC192 */
 #ifdef ECC224
     #ifndef NO_ECC_SECP
-        static const ecc_oid_t ecc_oid_secp224r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,33
+            #define CODED_SECP224R1    {1,3,132,0,33}
+            #define CODED_SECP224R1_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x21
+            #define CODED_SECP224R1    {0x2B,0x81,0x04,0x00,0x21}
+            #define CODED_SECP224R1_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp224r1[] = CODED_SECP224R1;
+        #else
+            #define ecc_oid_secp224r1 CODED_SECP224R1
+        #endif
+        #define ecc_oid_secp224r1_sz CODED_SECP224R1_SZ
     #endif /* !NO_ECC_SECP */
     #ifdef HAVE_ECC_KOBLITZ
-        static const ecc_oid_t ecc_oid_secp224k1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,32
+            #define CODED_SECP224K1    {1,3,132,0,32}
+            #define CODED_SECP224K1_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x20
+            #define CODED_SECP224K1    {0x2B,0x81,0x04,0x00,0x20}
+            #define CODED_SECP224K1_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp224k1[] = CODED_SECP224K1;
+        #else
+            #define ecc_oid_secp224k1 CODED_SECP224K1
+        #endif
+        #define ecc_oid_secp224k1_sz CODED_SECP224K1_SZ
     #endif /* HAVE_ECC_KOBLITZ */
     #ifdef HAVE_ECC_BRAINPOOL
-        static const ecc_oid_t ecc_oid_brainpoolp224r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,36,3,3,2,8,1,1,5
+            #define CODED_BRAINPOOLP224R1    {1,3,36,3,3,2,8,1,1,5}
+            #define CODED_BRAINPOOLP224R1_SZ 10
         #else
-            0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x05
+            #define CODED_BRAINPOOLP224R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x05}
+            #define CODED_BRAINPOOLP224R1_SZ 9
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_brainpoolp224r1[] = CODED_BRAINPOOLP224R1;
+        #else
+            #define ecc_oid_brainpoolp224r1 CODED_BRAINPOOLP224R1
+        #endif
+        #define ecc_oid_brainpoolp224r1_sz CODED_BRAINPOOLP224R1_SZ
     #endif /* HAVE_ECC_BRAINPOOL */
 #endif /* ECC224 */
 #ifdef ECC239
     #ifndef NO_ECC_SECP
-        static const ecc_oid_t ecc_oid_prime239v1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,2,840,10045,3,1,4
+            #define CODED_PRIME239V1    {1,2,840,10045,3,1,4}
+            #define CODED_PRIME239V1_SZ 7
         #else
-            0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x04
+            #define CODED_PRIME239V1    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x04}
+            #define CODED_PRIME239V1_SZ 8
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_prime239v1[] = CODED_PRIME239V1;
+        #else
+            #define ecc_oid_prime239v1 CODED_PRIME239V1
+        #endif
+        #define ecc_oid_prime239v1_sz CODED_PRIME239V1_SZ
     #endif /* !NO_ECC_SECP */
     #ifdef HAVE_ECC_SECPR2
-        static const ecc_oid_t ecc_oid_prime239v2[] = {
         #ifdef HAVE_OID_ENCODING
-            1,2,840,10045,3,1,5
+            #define CODED_PRIME239V2    {1,2,840,10045,3,1,5}
+            #define CODED_PRIME239V2_SZ 7
         #else
-            0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x05
+            #define CODED_PRIME239V2    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x05}
+            #define CODED_PRIME239V2_SZ 8
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_prime239v2[] = CODED_PRIME239V2;
+        #else
+            #define ecc_oid_prime239v2 CODED_PRIME239V2
+        #endif
+        #define ecc_oid_prime239v2_sz CODED_PRIME239V2_SZ
     #endif /* HAVE_ECC_SECPR2 */
     #ifdef HAVE_ECC_SECPR3
-        static const ecc_oid_t ecc_oid_prime239v3[] = {
         #ifdef HAVE_OID_ENCODING
-            1,2,840,10045,3,1,6
+            #define CODED_PRIME239V3    {1,2,840,10045,3,1,6}
+            #define CODED_PRIME239V3_SZ 7
         #else
-            0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x06
+            #define CODED_PRIME239V3    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x06}
+            #define CODED_PRIME239V3_SZ 8
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_prime239v3[] = CODED_PRIME239V3;
+        #else
+            #define ecc_oid_prime239v3 CODED_PRIME239V3
+        #endif
+        #define ecc_oid_prime239v3_sz CODED_PRIME239V3_SZ
     #endif /* HAVE_ECC_SECPR3 */
 #endif /* ECC239 */
 #ifdef ECC256
     #ifndef NO_ECC_SECP
-        static const ecc_oid_t ecc_oid_secp256r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,2,840,10045,3,1,7
+            #define CODED_SECP256R1    {1,2,840,10045,3,1,7}
+            #define CODED_SECP256R1_SZ 7
         #else
-            0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07
+            #define CODED_SECP256R1    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07}
+            #define CODED_SECP256R1_SZ 8
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp256r1[] = CODED_SECP256R1;
+        #else
+            #define ecc_oid_secp256r1 CODED_SECP256R1
+        #endif
+        #define ecc_oid_secp256r1_sz CODED_SECP256R1_SZ
     #endif /* !NO_ECC_SECP */
     #ifdef HAVE_ECC_KOBLITZ
-        static const ecc_oid_t ecc_oid_secp256k1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,10
+            #define CODED_SECP256K1    {1,3,132,0,10}
+            #define CODED_SECP256K1_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x0A
+            #define CODED_SECP256K1    {0x2B,0x81,0x04,0x00,0x0A}
+            #define CODED_SECP256K1_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp256k1[] = CODED_SECP256K1;
+        #else
+            #define ecc_oid_secp256k1 CODED_SECP256K1
+        #endif
+        #define ecc_oid_secp256k1_sz CODED_SECP256K1_SZ
     #endif /* HAVE_ECC_KOBLITZ */
     #ifdef HAVE_ECC_BRAINPOOL
-        static const ecc_oid_t ecc_oid_brainpoolp256r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,36,3,3,2,8,1,1,7
+            #define CODED_BRAINPOOLP256R1    {1,3,36,3,3,2,8,1,1,7}
+            #define CODED_BRAINPOOLP256R1_SZ 10
         #else
-            0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07
+            #define CODED_BRAINPOOLP256R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07}
+            #define CODED_BRAINPOOLP256R1_SZ 9
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_brainpoolp256r1[] = CODED_BRAINPOOLP256R1;
+        #else
+            #define ecc_oid_brainpoolp256r1 CODED_BRAINPOOLP256R1
+        #endif
+        #define ecc_oid_brainpoolp256r1_sz CODED_BRAINPOOLP256R1_SZ
     #endif /* HAVE_ECC_BRAINPOOL */
 #endif /* ECC256 */
 #ifdef ECC320
     #ifdef HAVE_ECC_BRAINPOOL
-        static const ecc_oid_t ecc_oid_brainpoolp320r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,36,3,3,2,8,1,1,9
+            #define CODED_BRAINPOOLP320R1    {1,3,36,3,3,2,8,1,1,9}
+            #define CODED_BRAINPOOLP320R1_SZ 10
         #else
-            0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x09
+            #define CODED_BRAINPOOLP320R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x09}
+            #define CODED_BRAINPOOLP320R1_SZ 9
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_brainpoolp320r1[] = CODED_BRAINPOOLP320R1;
+        #else
+            #define ecc_oid_brainpoolp320r1 CODED_BRAINPOOLP320R1
+        #endif
+        #define ecc_oid_brainpoolp320r1_sz CODED_BRAINPOOLP320R1_SZ
     #endif /* HAVE_ECC_BRAINPOOL */
 #endif /* ECC320 */
 #ifdef ECC384
     #ifndef NO_ECC_SECP
-        static const ecc_oid_t ecc_oid_secp384r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,34
+            #define CODED_SECP384R1    {1,3,132,0,34}
+            #define CODED_SECP384R1_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x22
+            #define CODED_SECP384R1    {0x2B,0x81,0x04,0x00,0x22}
+            #define CODED_SECP384R1_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp384r1[] = CODED_SECP384R1;
+            #define CODED_SECP384R1_OID ecc_oid_secp384r1
+        #else
+			#define ecc_oid_secp384r1 CODED_SECP384R1
+        #endif
+        #define ecc_oid_secp384r1_sz CODED_SECP384R1_SZ
     #endif /* !NO_ECC_SECP */
     #ifdef HAVE_ECC_BRAINPOOL
-        static const ecc_oid_t ecc_oid_brainpoolp384r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,36,3,3,2,8,1,1,11
+            #define CODED_BRAINPOOLP384R1    {1,3,36,3,3,2,8,1,1,11}
+            #define CODED_BRAINPOOLP384R1_SZ 10
         #else
-            0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0B
+            #define CODED_BRAINPOOLP384R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0B}
+            #define CODED_BRAINPOOLP384R1_SZ 9
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_brainpoolp384r1[] = CODED_BRAINPOOLP384R1;
+        #else
+            #define ecc_oid_brainpoolp384r1 CODED_BRAINPOOLP384R1
+        #endif
+        #define ecc_oid_brainpoolp384r1_sz CODED_BRAINPOOLP384R1_SZ
     #endif /* HAVE_ECC_BRAINPOOL */
 #endif /* ECC384 */
 #ifdef ECC512
     #ifdef HAVE_ECC_BRAINPOOL
-        static const ecc_oid_t ecc_oid_brainpoolp512r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,36,3,3,2,8,1,1,13
+            #define CODED_BRAINPOOLP512R1    {1,3,36,3,3,2,8,1,1,13}
+            #define CODED_BRAINPOOLP512R1_SZ 10
         #else
-            0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0D
+            #define CODED_BRAINPOOLP512R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0D}
+            #define CODED_BRAINPOOLP512R1_SZ 9
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_brainpoolp512r1[] = CODED_BRAINPOOLP512R1;
+        #else
+            #define ecc_oid_brainpoolp512r1 CODED_BRAINPOOLP512R1
+        #endif
+        #define ecc_oid_brainpoolp512r1_sz CODED_BRAINPOOLP512R1_SZ
     #endif /* HAVE_ECC_BRAINPOOL */
 #endif /* ECC512 */
 #ifdef ECC521
     #ifndef NO_ECC_SECP
-        static const ecc_oid_t ecc_oid_secp521r1[] = {
         #ifdef HAVE_OID_ENCODING
-            1,3,132,0,35
+            #define CODED_SECP521R1     {1,3,132,0,35}
+            #define CODED_SECP521R1_SZ 5
         #else
-            0x2B,0x81,0x04,0x00,0x23
+            #define CODED_SECP521R1     {0x2B,0x81,0x04,0x00,0x23}
+            #define CODED_SECP521R1_SZ 5
         #endif
-        };
+        #ifndef USE_WINDOWS_API
+            static const ecc_oid_t ecc_oid_secp521r1[] = CODED_SECP521R1;
+        #else
+            #define ecc_oid_secp521r1 CODED_SECP521R1
+        #endif
+        #define ecc_oid_secp521r1_sz CODED_SECP521R1_SZ
     #endif /* !NO_ECC_SECP */
 #endif /* ECC521 */
@@ -472,5 +650,5 @@
         "A89CE5AF8724C0A23E0E0FF77500", /* Gy         */
         ecc_oid_secp112r1,              /* oid/oidSz  */
-        sizeof(ecc_oid_secp112r1) / sizeof(ecc_oid_t),
+        ecc_oid_secp112r1_sz,
         ECC_SECP112R1_OID,              /* oid sum    */
         1,                              /* cofactor   */
@@ -489,5 +667,5 @@
         "ADCD46F5882E3747DEF36E956E97", /* Gy         */
         ecc_oid_secp112r2,              /* oid/oidSz  */
-        sizeof(ecc_oid_secp112r2) / sizeof(ecc_oid_t),
+        ecc_oid_secp112r2_sz,
         ECC_SECP112R2_OID,              /* oid sum    */
         4,                              /* cofactor   */
@@ -508,5 +686,5 @@
         "CF5AC8395BAFEB13C02DA292DDED7A83", /* Gy         */
         ecc_oid_secp128r1,                  /* oid/oidSz  */
-        sizeof(ecc_oid_secp128r1) / sizeof(ecc_oid_t),
+        ecc_oid_secp128r1_sz,
         ECC_SECP128R1_OID,                  /* oid sum    */
         1,                                  /* cofactor   */
@@ -525,5 +703,5 @@
         "27B6916A894D3AEE7106FE805FC34B44", /* Gy         */
         ecc_oid_secp128r2,                  /* oid/oidSz  */
-        sizeof(ecc_oid_secp128r2) / sizeof(ecc_oid_t),
+        ecc_oid_secp128r2_sz,
         ECC_SECP128R2_OID,                  /* oid sum    */
         4,                                  /* cofactor   */
@@ -544,5 +722,5 @@
         "23A628553168947D59DCC912042351377AC5FB32", /* Gy         */
         ecc_oid_secp160r1,                          /* oid/oidSz  */
-        sizeof(ecc_oid_secp160r1) / sizeof(ecc_oid_t),
+        ecc_oid_secp160r1_sz,
         ECC_SECP160R1_OID,                          /* oid sum    */
         1,                                          /* cofactor   */
@@ -561,5 +739,5 @@
         "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", /* Gy         */
         ecc_oid_secp160r2,                          /* oid/oidSz  */
-        sizeof(ecc_oid_secp160r2) / sizeof(ecc_oid_t),
+        ecc_oid_secp160r2_sz,
         ECC_SECP160R2_OID,                          /* oid sum    */
         1,                                          /* cofactor   */
@@ -578,5 +756,5 @@
         "938CF935318FDCED6BC28286531733C3F03C4FEE", /* Gy         */
         ecc_oid_secp160k1,                          /* oid/oidSz  */
-        sizeof(ecc_oid_secp160k1) / sizeof(ecc_oid_t),
+        ecc_oid_secp160k1_sz,
         ECC_SECP160K1_OID,                          /* oid sum    */
         1,                                          /* cofactor   */
@@ -595,5 +773,5 @@
         "1667CB477A1A8EC338F94741669C976316DA6321", /* Gy         */
         ecc_oid_brainpoolp160r1,                    /* oid/oidSz  */
-        sizeof(ecc_oid_brainpoolp160r1) / sizeof(ecc_oid_t),
+        ecc_oid_brainpoolp160r1_sz,
         ECC_BRAINPOOLP160R1_OID,                    /* oid sum    */
         1,                                          /* cofactor   */
@@ -614,5 +792,5 @@
         "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",  /* Gy         */
         ecc_oid_secp192r1,                                  /* oid/oidSz  */
-        sizeof(ecc_oid_secp192r1) / sizeof(ecc_oid_t),
+        ecc_oid_secp192r1_sz,
         ECC_SECP192R1_OID,                                  /* oid sum    */
         1,                                                  /* cofactor   */
@@ -631,5 +809,5 @@
         "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", /* Gy         */
         ecc_oid_prime192v2,                                 /* oid/oidSz  */
-        sizeof(ecc_oid_prime192v2) / sizeof(ecc_oid_t),
+        ecc_oid_prime192v2_sz,
         ECC_PRIME192V2_OID,                                 /* oid sum    */
         1,                                                  /* cofactor   */
@@ -648,5 +826,5 @@
         "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", /* Gy         */
         ecc_oid_prime192v3,                                 /* oid/oidSz  */
-        sizeof(ecc_oid_prime192v3) / sizeof(ecc_oid_t),
+        ecc_oid_prime192v3_sz,
         ECC_PRIME192V3_OID,                                 /* oid sum    */
         1,                                                  /* cofactor   */
@@ -665,5 +843,5 @@
         "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", /* Gy         */
         ecc_oid_secp192k1,                                  /* oid/oidSz  */
-        sizeof(ecc_oid_secp192k1) / sizeof(ecc_oid_t),
+        ecc_oid_secp192k1_sz,
         ECC_SECP192K1_OID,                                  /* oid sum    */
         1,                                                  /* cofactor   */
@@ -682,5 +860,5 @@
         "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", /* Gy         */
         ecc_oid_brainpoolp192r1,                            /* oid/oidSz  */
-        sizeof(ecc_oid_brainpoolp192r1) / sizeof(ecc_oid_t),
+        ecc_oid_brainpoolp192r1_sz,
         ECC_BRAINPOOLP192R1_OID,                            /* oid sum    */
         1,                                                  /* cofactor   */
@@ -701,5 +879,5 @@
         "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy         */
         ecc_oid_secp224r1,                                          /* oid/oidSz  */
-        sizeof(ecc_oid_secp224r1) / sizeof(ecc_oid_t),
+        ecc_oid_secp224r1_sz,
         ECC_SECP224R1_OID,                                          /* oid sum    */
         1,                                                          /* cofactor   */
@@ -718,5 +896,5 @@
         "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", /* Gy         */
         ecc_oid_secp224k1,                                          /* oid/oidSz  */
-        sizeof(ecc_oid_secp224k1) / sizeof(ecc_oid_t),
+        ecc_oid_secp224k1_sz,
         ECC_SECP224K1_OID,                                          /* oid sum    */
         1,                                                          /* cofactor   */
@@ -735,5 +913,5 @@
         "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", /* Gy         */
         ecc_oid_brainpoolp224r1,                                    /* oid/oidSz  */
-        sizeof(ecc_oid_brainpoolp224r1) / sizeof(ecc_oid_t),
+        ecc_oid_brainpoolp224r1_sz,
         ECC_BRAINPOOLP224R1_OID,                                    /* oid sum    */
         1,                                                          /* cofactor   */
@@ -754,5 +932,5 @@
         "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", /* Gy         */
         ecc_oid_prime239v1,                                             /* oid/oidSz  */
-        sizeof(ecc_oid_prime239v1) / sizeof(ecc_oid_t),
+        ecc_oid_prime239v1_sz,
         ECC_PRIME239V1_OID,                                             /* oid sum    */
         1,                                                              /* cofactor   */
@@ -771,5 +949,5 @@
         "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", /* Gy         */
         ecc_oid_prime239v2,                                             /* oid/oidSz  */
-        sizeof(ecc_oid_prime239v2) / sizeof(ecc_oid_t),
+        ecc_oid_prime239v2_sz,
         ECC_PRIME239V2_OID,                                             /* oid sum    */
         1,                                                              /* cofactor   */
@@ -788,5 +966,5 @@
         "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", /* Gy         */
         ecc_oid_prime239v3,                                             /* oid/oidSz  */
-        sizeof(ecc_oid_prime239v3) / sizeof(ecc_oid_t),
+        ecc_oid_prime239v3_sz,
         ECC_PRIME239V3_OID,                                             /* oid sum    */
         1,                                                              /* cofactor   */
@@ -807,5 +985,5 @@
         "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", /* Gy         */
         ecc_oid_secp256r1,                                                  /* oid/oidSz  */
-        sizeof(ecc_oid_secp256r1) / sizeof(ecc_oid_t),
+        ecc_oid_secp256r1_sz,
         ECC_SECP256R1_OID,                                                  /* oid sum    */
         1,                                                                  /* cofactor   */
@@ -824,5 +1002,5 @@
         "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", /* Gy         */
         ecc_oid_secp256k1,                                                  /* oid/oidSz  */
-        sizeof(ecc_oid_secp256k1) / sizeof(ecc_oid_t),
+        ecc_oid_secp256k1_sz,
         ECC_SECP256K1_OID,                                                  /* oid sum    */
         1,                                                                  /* cofactor   */
@@ -841,5 +1019,5 @@
         "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", /* Gy         */
         ecc_oid_brainpoolp256r1,                                            /* oid/oidSz  */
-        sizeof(ecc_oid_brainpoolp256r1) / sizeof(ecc_oid_t),
+        ecc_oid_brainpoolp256r1_sz,
         ECC_BRAINPOOLP256R1_OID,                                            /* oid sum    */
         1,                                                                  /* cofactor   */
@@ -859,5 +1037,5 @@
         "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", /* Gx         */
         "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", /* Gy         */
-        ecc_oid_brainpoolp320r1, sizeof(ecc_oid_brainpoolp320r1) / sizeof(ecc_oid_t),       /* oid/oidSz  */
+        ecc_oid_brainpoolp320r1, ecc_oid_brainpoolp320r1_sz,                                /* oid/oidSz  */
         ECC_BRAINPOOLP320R1_OID,                                                            /* oid sum    */
         1,                                                                                  /* cofactor   */
@@ -877,5 +1055,5 @@
         "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", /* Gx         */
         "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", /* Gy         */
-        ecc_oid_secp384r1, sizeof(ecc_oid_secp384r1) / sizeof(ecc_oid_t),                                   /* oid/oidSz  */
+        ecc_oid_secp384r1, ecc_oid_secp384r1_sz,                                                            /* oid/oidSz  */
         ECC_SECP384R1_OID,                                                                                  /* oid sum    */
         1,                                                                                                  /* cofactor   */
@@ -893,5 +1071,5 @@
         "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", /* Gx         */
         "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", /* Gy         */
-        ecc_oid_brainpoolp384r1, sizeof(ecc_oid_brainpoolp384r1) / sizeof(ecc_oid_t),                       /* oid/oidSz  */
+        ecc_oid_brainpoolp384r1, ecc_oid_brainpoolp384r1_sz,                                                /* oid/oidSz  */
         ECC_BRAINPOOLP384R1_OID,                                                                            /* oid sum    */
         1,                                                                                                  /* cofactor   */
@@ -911,5 +1089,5 @@
         "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", /* Gx         */
         "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", /* Gy         */
-        ecc_oid_brainpoolp512r1, sizeof(ecc_oid_brainpoolp512r1) / sizeof(ecc_oid_t),                                                       /* oid/oidSz  */
+        ecc_oid_brainpoolp512r1, ecc_oid_brainpoolp512r1_sz,                                                                                /* oid/oidSz  */
         ECC_BRAINPOOLP512R1_OID,                                                                                                            /* oid sum    */
         1,                                                                                                                                  /* cofactor   */
@@ -929,5 +1107,5 @@
         "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",  /* Gx         */
         "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", /* Gy         */
-        ecc_oid_secp521r1, sizeof(ecc_oid_secp521r1) / sizeof(ecc_oid_t),                                                                      /* oid/oidSz  */
+        ecc_oid_secp521r1, ecc_oid_secp521r1_sz,                                                                                               /* oid/oidSz  */
         ECC_SECP521R1_OID,                                                                                                                     /* oid sum    */
         1,                                                                                                                                     /* cofactor   */
@@ -940,15 +1118,25 @@
         1, /* non-zero */
         ECC_CURVE_CUSTOM,
-        NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-        NULL, 0, 0, 0
+        #ifndef USE_WINDOWS_API
+            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+        #else
+            {0},{0},{0},{0},{0},{0},{0},{0},
+        #endif
+        0, 0, 0
     },
 #endif
 {
-   0, -1,
-   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-   NULL, 0, 0, 0
+        0,
+        ECC_CURVE_INVALID,
+        #ifndef USE_WINDOWS_API
+            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+        #else
+            {0},{0},{0},{0},{0},{0},{0},{0},
+        #endif
+        0, 0, 0
 }
 };
 #define ECC_SET_COUNT   (sizeof(ecc_sets)/sizeof(ecc_set_type))
+
 
 #ifdef HAVE_OID_ENCODING
@@ -970,9 +1158,7 @@
 #else
 
+#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH)
 static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a,
         mp_int* prime, mp_int* order);
-#ifdef ECC_SHAMIR
-static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB,
-                       ecc_point* C, mp_int* a, mp_int* modulus, void* heap);
 #endif
 
@@ -1038,7 +1224,25 @@
     #endif
 
-    #define DECLARE_CURVE_SPECS(intcount) ecc_curve_spec* curve = NULL;
+    #define DECLARE_CURVE_SPECS(curve, intcount) ecc_curve_spec* curve = NULL
+    #define ALLOC_CURVE_SPECS(intcount)
+    #define FREE_CURVE_SPECS()
+#elif defined(WOLFSSL_SMALL_STACK)
+    #define DECLARE_CURVE_SPECS(curve, intcount)                        \
+        mp_int* spec_ints = NULL;                                       \
+        ecc_curve_spec curve_lcl;                                       \
+        ecc_curve_spec* curve = &curve_lcl;                             \
+        XMEMSET(curve, 0, sizeof(ecc_curve_spec));                      \
+        curve->spec_count = intcount
+
+    #define ALLOC_CURVE_SPECS(intcount)                                 \
+        spec_ints = (mp_int*)XMALLOC(sizeof(mp_int) * (intcount), NULL, \
+                            DYNAMIC_TYPE_ECC);                          \
+        if (spec_ints == NULL)                                          \
+            return MEMORY_E;                                            \
+        curve->spec_ints = spec_ints
+    #define FREE_CURVE_SPECS()                                          \
+        XFREE(spec_ints, NULL, DYNAMIC_TYPE_ECC)
 #else
-    #define DECLARE_CURVE_SPECS(intcount) \
+    #define DECLARE_CURVE_SPECS(curve, intcount) \
         mp_int spec_ints[(intcount)]; \
         ecc_curve_spec curve_lcl; \
@@ -1046,5 +1250,7 @@
         XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \
         curve->spec_ints = spec_ints; \
-        curve->spec_count = intcount;
+        curve->spec_count = intcount
+    #define ALLOC_CURVE_SPECS(intcount)
+    #define FREE_CURVE_SPECS()
 #endif /* ECC_CACHE_CURVE */
 
@@ -1100,5 +1306,5 @@
         curve->load_mask |= mask;
 
-        err = mp_read_radix(*dst, src, 16);
+        err = mp_read_radix(*dst, src, MP_RADIX_HEX);
 
     #ifdef HAVE_WOLF_BIGINT
@@ -1169,5 +1375,5 @@
 
     /* determine items to load */
-    load_items = (~curve->load_mask & load_mask);
+    load_items = (((byte)~(word32)curve->load_mask) & load_mask);
     curve->load_mask |= load_items;
 
@@ -1293,5 +1499,17 @@
 }
 
+
+#ifdef ALT_ECC_SIZE
+static void alt_fp_init(mp_int* a)
+{
+    a->size = FP_SIZE_ECC;
+    mp_zero(a);
+}
+#endif /* ALT_ECC_SIZE */
+
+
 #ifndef WOLFSSL_ATECC508A
+
+#if !defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_PUBLIC_ECC_ADD_DBL)
 
 /**
@@ -1308,7 +1526,18 @@
                              mp_int* a, mp_int* modulus, mp_digit mp)
 {
-   mp_int t1, t2;
+#ifndef WOLFSSL_SP_MATH
+#ifdef WOLFSSL_SMALL_STACK
+   mp_int* t1 = NULL;
+   mp_int* t2 = NULL;
 #ifdef ALT_ECC_SIZE
-   mp_int rx, ry, rz;
+   mp_int* rx = NULL;
+   mp_int* ry = NULL;
+   mp_int* rz = NULL;
+#endif
+#else
+   mp_int  t1[1], t2[1];
+#ifdef ALT_ECC_SIZE
+   mp_int  rx[1], ry[1], rz[1];
+#endif
 #endif
    mp_int *x, *y, *z;
@@ -1326,5 +1555,56 @@
    }
 
-   if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (R->key != NULL) {
+       t1 = R->key->t1;
+       t2 = R->key->t2;
+#ifdef ALT_ECC_SIZE
+       rx = R->key->x;
+       ry = R->key->y;
+       rz = R->key->z;
+#endif
+   }
+   else
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+   {
+       t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (t1 == NULL || t2 == NULL) {
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+#ifdef ALT_ECC_SIZE
+       rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (rx == NULL || ry == NULL || rz == NULL) {
+           XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+#endif
+   }
+#endif /* WOLFSSL_SMALL_STACK */
+
+   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK
+   #ifdef WOLFSSL_SMALL_STACK_CACHE
+       if (R->key == NULL)
+   #endif
+       {
+       #ifdef ALT_ECC_SIZE
+          XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+       #endif
+          XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+       }
+#endif
       return err;
    }
@@ -1332,11 +1612,25 @@
    /* should we dbl instead? */
    if (err == MP_OKAY)
-       err = mp_sub(modulus, Q->y, &t1);
+       err = mp_sub(modulus, Q->y, t1);
    if (err == MP_OKAY) {
        if ( (mp_cmp(P->x, Q->x) == MP_EQ) &&
             (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) &&
-            (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, &t1) == MP_EQ)) {
-           mp_clear(&t1);
-           mp_clear(&t2);
+            (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, t1) == MP_EQ)) {
+           mp_clear(t1);
+           mp_clear(t2);
+    #ifdef WOLFSSL_SMALL_STACK
+       #ifdef WOLFSSL_SMALL_STACK_CACHE
+           if (R->key == NULL)
+       #endif
+           {
+            #ifdef ALT_ECC_SIZE
+               XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+               XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+               XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+            #endif
+               XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+               XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           }
+        #endif
           return ecc_projective_dbl_point(P, R, a, modulus, mp);
        }
@@ -1351,7 +1645,7 @@
 #ifdef ALT_ECC_SIZE
    /* Use local stack variable */
-   x = &rx;
-   y = &ry;
-   z = &rz;
+   x = rx;
+   y = ry;
+   z = rz;
 
    if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) {
@@ -1376,11 +1670,11 @@
        if (!mp_iszero(Q->z)) {
            /* T1 = Z' * Z' */
-           err = mp_sqr(Q->z, &t1);
+           err = mp_sqr(Q->z, t1);
            if (err == MP_OKAY)
-               err = mp_montgomery_reduce(&t1, modulus, mp);
+               err = mp_montgomery_reduce(t1, modulus, mp);
 
            /* X = X * T1 */
            if (err == MP_OKAY)
-               err = mp_mul(&t1, x, x);
+               err = mp_mul(t1, x, x);
            if (err == MP_OKAY)
                err = mp_montgomery_reduce(x, modulus, mp);
@@ -1388,11 +1682,11 @@
            /* T1 = Z' * T1 */
            if (err == MP_OKAY)
-               err = mp_mul(Q->z, &t1, &t1);
+               err = mp_mul(Q->z, t1, t1);
            if (err == MP_OKAY)
-               err = mp_montgomery_reduce(&t1, modulus, mp);
+               err = mp_montgomery_reduce(t1, modulus, mp);
 
            /* Y = Y * T1 */
            if (err == MP_OKAY)
-               err = mp_mul(&t1, y, y);
+               err = mp_mul(t1, y, y);
            if (err == MP_OKAY)
                err = mp_montgomery_reduce(y, modulus, mp);
@@ -1402,29 +1696,29 @@
    /* T1 = Z*Z */
    if (err == MP_OKAY)
-       err = mp_sqr(z, &t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(&t1, modulus, mp);
+       err = mp_sqr(z, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
 
    /* T2 = X' * T1 */
    if (err == MP_OKAY)
-       err = mp_mul(Q->x, &t1, &t2);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(&t2, modulus, mp);
+       err = mp_mul(Q->x, t1, t2);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t2, modulus, mp);
 
    /* T1 = Z * T1 */
    if (err == MP_OKAY)
-       err = mp_mul(z, &t1, &t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(&t1, modulus, mp);
+       err = mp_mul(z, t1, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
 
    /* T1 = Y' * T1 */
    if (err == MP_OKAY)
-       err = mp_mul(Q->y, &t1, &t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(&t1, modulus, mp);
+       err = mp_mul(Q->y, t1, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
 
    /* Y = Y - T1 */
    if (err == MP_OKAY)
-       err = mp_sub(y, &t1, y);
+       err = mp_sub(y, t1, y);
    if (err == MP_OKAY) {
        if (mp_isneg(y))
@@ -1433,19 +1727,19 @@
    /* T1 = 2T1 */
    if (err == MP_OKAY)
-       err = mp_add(&t1, &t1, &t1);
+       err = mp_add(t1, t1, t1);
    if (err == MP_OKAY) {
-       if (mp_cmp(&t1, modulus) != MP_LT)
-           err = mp_sub(&t1, modulus, &t1);
+       if (mp_cmp(t1, modulus) != MP_LT)
+           err = mp_sub(t1, modulus, t1);
    }
    /* T1 = Y + T1 */
    if (err == MP_OKAY)
-       err = mp_add(&t1, y, &t1);
+       err = mp_add(t1, y, t1);
    if (err == MP_OKAY) {
-       if (mp_cmp(&t1, modulus) != MP_LT)
-           err = mp_sub(&t1, modulus, &t1);
+       if (mp_cmp(t1, modulus) != MP_LT)
+           err = mp_sub(t1, modulus, t1);
    }
    /* X = X - T2 */
    if (err == MP_OKAY)
-       err = mp_sub(x, &t2, x);
+       err = mp_sub(x, t2, x);
    if (err == MP_OKAY) {
        if (mp_isneg(x))
@@ -1454,15 +1748,15 @@
    /* T2 = 2T2 */
    if (err == MP_OKAY)
-       err = mp_add(&t2, &t2, &t2);
+       err = mp_add(t2, t2, t2);
    if (err == MP_OKAY) {
-       if (mp_cmp(&t2, modulus) != MP_LT)
-           err = mp_sub(&t2, modulus, &t2);
+       if (mp_cmp(t2, modulus) != MP_LT)
+           err = mp_sub(t2, modulus, t2);
    }
    /* T2 = X + T2 */
    if (err == MP_OKAY)
-       err = mp_add(&t2, x, &t2);
+       err = mp_add(t2, x, t2);
    if (err == MP_OKAY) {
-       if (mp_cmp(&t2, modulus) != MP_LT)
-           err = mp_sub(&t2, modulus, &t2);
+       if (mp_cmp(t2, modulus) != MP_LT)
+           err = mp_sub(t2, modulus, t2);
    }
 
@@ -1484,7 +1778,7 @@
    /* T1 = T1 * X  */
    if (err == MP_OKAY)
-       err = mp_mul(&t1, x, &t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(&t1, modulus, mp);
+       err = mp_mul(t1, x, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
 
    /* X = X * X */
@@ -1496,13 +1790,13 @@
    /* T2 = T2 * x */
    if (err == MP_OKAY)
-       err = mp_mul(&t2, x, &t2);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(&t2, modulus, mp);
+       err = mp_mul(t2, x, t2);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t2, modulus, mp);
 
    /* T1 = T1 * X  */
    if (err == MP_OKAY)
-       err = mp_mul(&t1, x, &t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(&t1, modulus, mp);
+       err = mp_mul(t1, x, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
 
    /* X = Y*Y */
@@ -1514,5 +1808,5 @@
    /* X = X - T2 */
    if (err == MP_OKAY)
-       err = mp_sub(x, &t2, x);
+       err = mp_sub(x, t2, x);
    if (err == MP_OKAY) {
        if (mp_isneg(x))
@@ -1521,25 +1815,25 @@
    /* T2 = T2 - X */
    if (err == MP_OKAY)
-       err = mp_sub(&t2, x, &t2);
+       err = mp_sub(t2, x, t2);
    if (err == MP_OKAY) {
-       if (mp_isneg(&t2))
-           err = mp_add(&t2, modulus, &t2);
+       if (mp_isneg(t2))
+           err = mp_add(t2, modulus, t2);
    }
    /* T2 = T2 - X */
    if (err == MP_OKAY)
-       err = mp_sub(&t2, x, &t2);
+       err = mp_sub(t2, x, t2);
    if (err == MP_OKAY) {
-       if (mp_isneg(&t2))
-           err = mp_add(&t2, modulus, &t2);
+       if (mp_isneg(t2))
+           err = mp_add(t2, modulus, t2);
    }
    /* T2 = T2 * Y */
    if (err == MP_OKAY)
-       err = mp_mul(&t2, y, &t2);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(&t2, modulus, mp);
+       err = mp_mul(t2, y, t2);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t2, modulus, mp);
 
    /* Y = T2 - T1 */
    if (err == MP_OKAY)
-       err = mp_sub(&t2, &t1, y);
+       err = mp_sub(t2, t1, y);
    if (err == MP_OKAY) {
        if (mp_isneg(y))
@@ -1566,8 +1860,33 @@
 
    /* clean up */
-   mp_clear(&t1);
-   mp_clear(&t2);
+   mp_clear(t1);
+   mp_clear(t2);
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (R->key == NULL)
+#endif
+   {
+   #ifdef ALT_ECC_SIZE
+      XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+   #endif
+      XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+   }
+#endif
 
    return err;
+#else
+    if (P == NULL || Q == NULL || R == NULL || modulus == NULL) {
+        return ECC_BAD_ARG_E;
+    }
+
+    (void)a;
+    (void)mp;
+
+    return sp_ecc_proj_add_point_256(P->x, P->y, P->z, Q->x, Q->y, Q->z,
+                                     R->x, R->y, R->z);
+#endif
 }
 
@@ -1602,7 +1921,18 @@
                                        mp_int* modulus, mp_digit mp)
 {
-   mp_int t1, t2;
+#ifndef WOLFSSL_SP_MATH
+#ifdef WOLFSSL_SMALL_STACK
+   mp_int* t1 = NULL;
+   mp_int* t2 = NULL;
 #ifdef ALT_ECC_SIZE
-   mp_int rx, ry, rz;
+   mp_int* rx = NULL;
+   mp_int* ry = NULL;
+   mp_int* rz = NULL;
+#endif
+#else
+   mp_int  t1[1], t2[1];
+#ifdef ALT_ECC_SIZE
+   mp_int  rx[1], ry[1], rz[1];
+#endif
 #endif
    mp_int *x, *y, *z;
@@ -1612,5 +1942,56 @@
        return ECC_BAD_ARG_E;
 
-   if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (R->key != NULL) {
+       t1 = R->key->t1;
+       t2 = R->key->t2;
+   #ifdef ALT_ECC_SIZE
+       rx = R->key->x;
+       ry = R->key->y;
+       rz = R->key->z;
+   #endif
+   }
+   else
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+   {
+       t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (t1 == NULL || t2 == NULL) {
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+    #ifdef ALT_ECC_SIZE
+       rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (rx == NULL || ry == NULL || rz == NULL) {
+           XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+    #endif
+    }
+#endif
+
+   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    if (R->key == NULL)
+#endif
+    {
+    #ifdef ALT_ECC_SIZE
+       XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+    #endif
+       XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+     }
+#endif
       return err;
    }
@@ -1620,11 +2001,25 @@
 #ifdef ALT_ECC_SIZE
    /* Use local stack variable */
-   x = &rx;
-   y = &ry;
-   z = &rz;
+   x = rx;
+   y = ry;
+   z = rz;
 
    if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) {
-       mp_clear(&t1);
-       mp_clear(&t2);
+       mp_clear(t1);
+       mp_clear(t2);
+    #ifdef WOLFSSL_SMALL_STACK
+    #ifdef WOLFSSL_SMALL_STACK_CACHE
+       if (R->key == NULL)
+    #endif
+       {
+       #ifdef ALT_ECC_SIZE
+          XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+       #endif
+          XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+       }
+    #endif
        return err;
    }
@@ -1645,7 +2040,7 @@
    /* T1 = Z * Z */
    if (err == MP_OKAY)
-       err = mp_sqr(z, &t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(&t1, modulus, mp);
+       err = mp_sqr(z, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
 
    /* Z = Y * Z */
@@ -1667,42 +2062,42 @@
    if (err == MP_OKAY) {
       /* Use a and prime to determine if a == 3 */
-      err = mp_submod(modulus, a, modulus, &t2);
-   }
-   if (err == MP_OKAY && mp_cmp_d(&t2, 3) != MP_EQ) {
+      err = mp_submod(modulus, a, modulus, t2);
+   }
+   if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) {
       /* use "a" in calc */
 
       /* T2 = T1 * T1 */
       if (err == MP_OKAY)
-          err = mp_sqr(&t1, &t2);
+          err = mp_sqr(t1, t2);
       if (err == MP_OKAY)
-          err = mp_montgomery_reduce(&t2, modulus, mp);
+          err = mp_montgomery_reduce(t2, modulus, mp);
       /* T1 = T2 * a */
       if (err == MP_OKAY)
-          err = mp_mulmod(&t2, a, modulus, &t1);
+          err = mp_mulmod(t2, a, modulus, t1);
       /* T2 = X * X */
       if (err == MP_OKAY)
-          err = mp_sqr(x, &t2);
+          err = mp_sqr(x, t2);
       if (err == MP_OKAY)
-          err = mp_montgomery_reduce(&t2, modulus, mp);
+          err = mp_montgomery_reduce(t2, modulus, mp);
       /* T1 = T2 + T1 */
       if (err == MP_OKAY)
-          err = mp_add(&t1, &t2, &t1);
+          err = mp_add(t1, t2, t1);
       if (err == MP_OKAY) {
-         if (mp_cmp(&t1, modulus) != MP_LT)
-            err = mp_sub(&t1, modulus, &t1);
+         if (mp_cmp(t1, modulus) != MP_LT)
+            err = mp_sub(t1, modulus, t1);
       }
       /* T1 = T2 + T1 */
       if (err == MP_OKAY)
-          err = mp_add(&t1, &t2, &t1);
+          err = mp_add(t1, t2, t1);
       if (err == MP_OKAY) {
-          if (mp_cmp(&t1, modulus) != MP_LT)
-              err = mp_sub(&t1, modulus, &t1);
+          if (mp_cmp(t1, modulus) != MP_LT)
+              err = mp_sub(t1, modulus, t1);
       }
       /* T1 = T2 + T1 */
       if (err == MP_OKAY)
-          err = mp_add(&t1, &t2, &t1);
+          err = mp_add(t1, t2, t1);
       if (err == MP_OKAY) {
-         if (mp_cmp(&t1, modulus) != MP_LT)
-            err = mp_sub(&t1, modulus, &t1);
+         if (mp_cmp(t1, modulus) != MP_LT)
+            err = mp_sub(t1, modulus, t1);
       }
    }
@@ -1715,35 +2110,35 @@
       /* T2 = X - T1 */
       if (err == MP_OKAY)
-          err = mp_sub(x, &t1, &t2);
+          err = mp_sub(x, t1, t2);
       if (err == MP_OKAY) {
-          if (mp_isneg(&t2))
-              err = mp_add(&t2, modulus, &t2);
+          if (mp_isneg(t2))
+              err = mp_add(t2, modulus, t2);
       }
       /* T1 = X + T1 */
       if (err == MP_OKAY)
-          err = mp_add(&t1, x, &t1);
+          err = mp_add(t1, x, t1);
       if (err == MP_OKAY) {
-          if (mp_cmp(&t1, modulus) != MP_LT)
-              err = mp_sub(&t1, modulus, &t1);
+          if (mp_cmp(t1, modulus) != MP_LT)
+              err = mp_sub(t1, modulus, t1);
       }
       /* T2 = T1 * T2 */
       if (err == MP_OKAY)
-          err = mp_mul(&t1, &t2, &t2);
+          err = mp_mul(t1, t2, t2);
       if (err == MP_OKAY)
-          err = mp_montgomery_reduce(&t2, modulus, mp);
+          err = mp_montgomery_reduce(t2, modulus, mp);
 
       /* T1 = 2T2 */
       if (err == MP_OKAY)
-          err = mp_add(&t2, &t2, &t1);
+          err = mp_add(t2, t2, t1);
       if (err == MP_OKAY) {
-          if (mp_cmp(&t1, modulus) != MP_LT)
-              err = mp_sub(&t1, modulus, &t1);
+          if (mp_cmp(t1, modulus) != MP_LT)
+              err = mp_sub(t1, modulus, t1);
       }
       /* T1 = T1 + T2 */
       if (err == MP_OKAY)
-          err = mp_add(&t1, &t2, &t1);
+          err = mp_add(t1, t2, t1);
       if (err == MP_OKAY) {
-          if (mp_cmp(&t1, modulus) != MP_LT)
-              err = mp_sub(&t1, modulus, &t1);
+          if (mp_cmp(t1, modulus) != MP_LT)
+              err = mp_sub(t1, modulus, t1);
       }
    }
@@ -1764,15 +2159,15 @@
    /* T2 = Y * Y */
    if (err == MP_OKAY)
-       err = mp_sqr(y, &t2);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(&t2, modulus, mp);
+       err = mp_sqr(y, t2);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t2, modulus, mp);
 
    /* T2 = T2/2 */
    if (err == MP_OKAY) {
-       if (mp_isodd(&t2) == MP_YES)
-           err = mp_add(&t2, modulus, &t2);
-   }
-   if (err == MP_OKAY)
-       err = mp_div_2(&t2, &t2);
+       if (mp_isodd(t2) == MP_YES)
+           err = mp_add(t2, modulus, t2);
+   }
+   if (err == MP_OKAY)
+       err = mp_div_2(t2, t2);
 
    /* Y = Y * X */
@@ -1784,5 +2179,5 @@
    /* X = T1 * T1 */
    if (err == MP_OKAY)
-       err = mp_sqr(&t1, x);
+       err = mp_sqr(t1, x);
    if (err == MP_OKAY)
        err = mp_montgomery_reduce(x, modulus, mp);
@@ -1812,5 +2207,5 @@
    /* Y = Y * T1 */
    if (err == MP_OKAY)
-       err = mp_mul(y, &t1, y);
+       err = mp_mul(y, t1, y);
    if (err == MP_OKAY)
        err = mp_montgomery_reduce(y, modulus, mp);
@@ -1818,5 +2213,5 @@
    /* Y = Y - T2 */
    if (err == MP_OKAY)
-       err = mp_sub(y, &t2, y);
+       err = mp_sub(y, t2, y);
    if (err == MP_OKAY) {
        if (mp_isneg(y))
@@ -1834,8 +2229,32 @@
 
    /* clean up */
-   mp_clear(&t1);
-   mp_clear(&t2);
+   mp_clear(t1);
+   mp_clear(t2);
+
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (R->key == NULL)
+#endif
+   {
+    #ifdef ALT_ECC_SIZE
+       XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+    #endif
+       XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+    }
+#endif
 
    return err;
+#else
+    if (P == NULL || R == NULL || modulus == NULL)
+        return ECC_BAD_ARG_E;
+
+    (void)a;
+    (void)mp;
+
+    return sp_ecc_proj_dbl_point_256(P->x, P->y, P->z, R->x, R->y, R->z);
+#endif
 }
 
@@ -1850,8 +2269,19 @@
 int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp)
 {
-   mp_int t1, t2;
+#ifndef WOLFSSL_SP_MATH
+#ifdef WOLFSSL_SMALL_STACK
+   mp_int* t1 = NULL;
+   mp_int* t2 = NULL;
 #ifdef ALT_ECC_SIZE
-   mp_int rx, ry, rz;
-#endif
+   mp_int* rx = NULL;
+   mp_int* ry = NULL;
+   mp_int* rz = NULL;
+#endif
+#else
+   mp_int  t1[1], t2[1];
+#ifdef ALT_ECC_SIZE
+   mp_int  rx[1], ry[1], rz[1];
+#endif
+#endif /* WOLFSSL_SMALL_STACK */
    mp_int *x, *y, *z;
    int    err;
@@ -1870,5 +2300,56 @@
    }
 
-   if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (P->key != NULL) {
+       t1 = P->key->t1;
+       t2 = P->key->t2;
+   #ifdef ALT_ECC_SIZE
+       rx = P->key->x;
+       ry = P->key->y;
+       rz = P->key->z;
+   #endif
+   }
+   else
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+   {
+       t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (t1 == NULL || t2 == NULL) {
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+#ifdef ALT_ECC_SIZE
+       rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (rx == NULL || ry == NULL || rz == NULL) {
+           XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+#endif
+   }
+#endif /* WOLFSSL_SMALL_STACK */
+
+   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+      if (P->key == NULL)
+#endif
+      {
+      #ifdef ALT_ECC_SIZE
+         XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+         XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+         XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+      #endif
+         XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+         XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+      }
+#endif
       return MEMORY_E;
    }
@@ -1876,7 +2357,7 @@
 #ifdef ALT_ECC_SIZE
    /* Use local stack variable */
-   x = &rx;
-   y = &ry;
-   z = &rz;
+   x = rx;
+   y = ry;
+   z = rz;
 
    if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) {
@@ -1906,23 +2387,23 @@
    /* get 1/z */
    if (err == MP_OKAY)
-       err = mp_invmod(z, modulus, &t1);
+       err = mp_invmod(z, modulus, t1);
 
    /* get 1/z^2 and 1/z^3 */
    if (err == MP_OKAY)
-       err = mp_sqr(&t1, &t2);
-   if (err == MP_OKAY)
-       err = mp_mod(&t2, modulus, &t2);
-   if (err == MP_OKAY)
-       err = mp_mul(&t1, &t2, &t1);
-   if (err == MP_OKAY)
-       err = mp_mod(&t1, modulus, &t1);
+       err = mp_sqr(t1, t2);
+   if (err == MP_OKAY)
+       err = mp_mod(t2, modulus, t2);
+   if (err == MP_OKAY)
+       err = mp_mul(t1, t2, t1);
+   if (err == MP_OKAY)
+       err = mp_mod(t1, modulus, t1);
 
    /* multiply against x/y */
    if (err == MP_OKAY)
-       err = mp_mul(x, &t2, x);
+       err = mp_mul(x, t2, x);
    if (err == MP_OKAY)
        err = mp_montgomery_reduce(x, modulus, mp);
    if (err == MP_OKAY)
-       err = mp_mul(y, &t1, y);
+       err = mp_mul(y, t1, y);
    if (err == MP_OKAY)
        err = mp_montgomery_reduce(y, modulus, mp);
@@ -1944,12 +2425,38 @@
 
    /* clean up */
-   mp_clear(&t1);
-   mp_clear(&t2);
+   mp_clear(t1);
+   mp_clear(t2);
+
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (P->key == NULL)
+#endif
+   {
+   #ifdef ALT_ECC_SIZE
+      XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+   #endif
+      XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+}
+#endif
 
    return err;
-}
+#else
+    if (P == NULL || modulus == NULL)
+        return ECC_BAD_ARG_E;
+
+    (void)mp;
+
+    return sp_ecc_map_256(P->x, P->y, P->z);
+#endif
+}
+
+#endif /* !WOLFSSL_SP_MATH || WOLFSSL_PUBLIC_ECC_ADD_DBL */
 
 #if !defined(FREESCALE_LTC_ECC)
 
+#if !defined(FP_ECC) || !defined(WOLFSSL_SP_MATH)
 /**
    Perform a point multiplication
@@ -1973,4 +2480,5 @@
 #endif
 {
+#ifndef WOLFSSL_SP_MATH
 #ifndef ECC_TIMING_RESISTANT
    /* size of sliding window, don't change this! */
@@ -1984,5 +2492,12 @@
    ecc_point     *tG, *M[M_POINTS];
    int           i, err;
-   mp_int        mu;
+#ifdef WOLFSSL_SMALL_STACK
+   mp_int*       mu = NULL;
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   ecc_key       key;
+#endif
+#else
+   mp_int        mu[1];
+#endif
    mp_digit      mp;
    mp_digit      buf;
@@ -1996,15 +2511,80 @@
    tG = NULL;
    XMEMSET(M, 0, sizeof(M));
+#ifdef WOLFSSL_SMALL_STACK
+   mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+   if (mu == NULL)
+       return MEMORY_E;
+#endif
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+   key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+#ifdef ALT_ECC_SIZE
+   key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+   key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+   key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+#endif
+   if (key.t1 == NULL || key.t2 == NULL
+#ifdef ALT_ECC_SIZE
+      || key.x == NULL || key.y == NULL || key.z == NULL
+#endif
+   ) {
+#ifdef ALT_ECC_SIZE
+       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+       return MEMORY_E;
+   }
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
 
    /* init montgomery reduction */
    if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+#ifdef ALT_ECC_SIZE
+       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+#ifdef WOLFSSL_SMALL_STACK
+       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+#endif
        return err;
    }
 
-   if ((err = mp_init(&mu)) != MP_OKAY) {
+   if ((err = mp_init(mu)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+#ifdef ALT_ECC_SIZE
+       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+#ifdef WOLFSSL_SMALL_STACK
+       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+#endif
        return err;
    }
-   if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) {
-       mp_clear(&mu);
+   if ((err = mp_montgomery_calc_normalization(mu, modulus)) != MP_OKAY) {
+       mp_clear(mu);
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+#ifdef ALT_ECC_SIZE
+       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+#ifdef WOLFSSL_SMALL_STACK
+       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+#endif
        return err;
    }
@@ -2014,7 +2594,10 @@
       M[i] = wc_ecc_new_point_h(heap);
       if (M[i] == NULL) {
-         mp_clear(&mu);
+         mp_clear(mu);
          err = MEMORY_E; goto exit;
       }
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+      M[i]->key = &key;
+#endif
   }
 
@@ -2026,5 +2609,5 @@
    /* tG = G  and convert to montgomery */
    if (err == MP_OKAY) {
-       if (mp_cmp_d(&mu, 1) == MP_EQ) {
+       if (mp_cmp_d(mu, 1) == MP_EQ) {
            err = mp_copy(G->x, tG->x);
            if (err == MP_OKAY)
@@ -2033,15 +2616,18 @@
                err = mp_copy(G->z, tG->z);
        } else {
-           err = mp_mulmod(G->x, &mu, modulus, tG->x);
+           err = mp_mulmod(G->x, mu, modulus, tG->x);
            if (err == MP_OKAY)
-               err = mp_mulmod(G->y, &mu, modulus, tG->y);
+               err = mp_mulmod(G->y, mu, modulus, tG->y);
            if (err == MP_OKAY)
-               err = mp_mulmod(G->z, &mu, modulus, tG->z);
+               err = mp_mulmod(G->z, mu, modulus, tG->z);
        }
    }
 
    /* done with mu */
-   mp_clear(&mu);
-
+   mp_clear(mu);
+
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   R->key = &key;
+#endif
 #ifndef ECC_TIMING_RESISTANT
 
@@ -2305,7 +2891,31 @@
        wc_ecc_del_point_h(M[i], heap);
    }
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   R->key = NULL;
+#ifdef ALT_ECC_SIZE
+   XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+   XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+   XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+   XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+   XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+#ifdef WOLFSSL_SMALL_STACK
+   XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+#endif
 
    return err;
-}
+#else
+   if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
+       return ECC_BAD_ARG_E;
+}
+
+   (void)a;
+
+   return sp_ecc_mulmod_256(k, G, R, map, heap);
+#endif
+}
+
+#endif /* !FP_ECC || !WOLFSSL_SP_MATH */
 
 #endif /* !FREESCALE_LTC_ECC */
@@ -2327,15 +2937,5 @@
 }
 
-
-#ifdef ALT_ECC_SIZE
-
-static void alt_fp_init(fp_int* a)
-{
-    a->size = FP_SIZE_ECC;
-    fp_zero(a);
-}
-
-#endif /* ALT_ECC_SIZE */
-
+#endif /* !WOLFSSL_ATECC508A */
 
 /**
@@ -2346,4 +2946,6 @@
 {
    ecc_point* p;
+
+   (void)heap;
 
    p = (ecc_point*)XMALLOC(sizeof(ecc_point), heap, DYNAMIC_TYPE_ECC);
@@ -2455,6 +3057,4 @@
 }
 
-#endif /* !WOLFSSL_ATECC508A */
-
 
 /** Returns whether an ECC idx is valid or not
@@ -2588,20 +3188,41 @@
 {
     int err = MP_OKAY;
-    mp_int a, b;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* a = NULL;
+    mp_int* b = NULL;
+#else
+    mp_int  a[1], b[1];
+#endif
 
     if (param == NULL || curveParam == NULL)
         return BAD_FUNC_ARG;
 
-    if ((err = mp_init_multi(&a, &b, NULL, NULL, NULL, NULL)) != MP_OKAY)
+#ifdef WOLFSSL_SMALL_STACK
+    a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (a == NULL)
+        return MEMORY_E;
+    b = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (b == NULL) {
+        XFREE(a, NULL, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+#endif
+
+    if ((err = mp_init_multi(a, b, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(a, NULL, DYNAMIC_TYPE_ECC);
+        XFREE(b, NULL, DYNAMIC_TYPE_ECC);
+    #endif
         return err;
+    }
 
     if (err == MP_OKAY)
-        err = mp_read_unsigned_bin(&a, param, paramSz);
+        err = mp_read_unsigned_bin(a, param, paramSz);
 
     if (err == MP_OKAY)
-        err = mp_read_radix(&b, curveParam, 16);
+        err = mp_read_radix(b, curveParam, MP_RADIX_HEX);
 
     if (err == MP_OKAY) {
-        if (mp_cmp(&a, &b) != MP_EQ) {
+        if (mp_cmp(a, b) != MP_EQ) {
             err = -1;
         } else {
@@ -2610,6 +3231,10 @@
     }
 
-    mp_clear(&a);
-    mp_clear(&b);
+    mp_clear(a);
+    mp_clear(b);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(b, NULL, DYNAMIC_TYPE_ECC);
+    XFREE(a, NULL, DYNAMIC_TYPE_ECC);
+#endif
 
     return err;
@@ -2672,4 +3297,75 @@
 }
 
+/* Returns the curve id that corresponds to a given OID,
+ * as listed in ecc_sets[] of ecc.c.
+ *
+ * oid   OID, from ecc_sets[].name in ecc.c
+ * len   OID len, from ecc_sets[].name in ecc.c
+ * return curve id, from ecc_sets[] on success, negative on error
+ */
+int wc_ecc_get_curve_id_from_oid(const byte* oid, word32 len)
+{
+    int curve_idx;
+
+    if (oid == NULL)
+        return BAD_FUNC_ARG;
+
+    for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) {
+        if (ecc_sets[curve_idx].oid && ecc_sets[curve_idx].oidSz == len &&
+                              XMEMCMP(ecc_sets[curve_idx].oid, oid, len) == 0) {
+            break;
+        }
+    }
+    if (ecc_sets[curve_idx].size == 0) {
+        WOLFSSL_MSG("ecc_set curve name not found");
+        return ECC_CURVE_INVALID;
+    }
+
+    return ecc_sets[curve_idx].id;
+}
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+static WC_INLINE int wc_ecc_alloc_mpint(ecc_key* key, mp_int** mp)
+{
+   if (key == NULL || mp == NULL)
+      return BAD_FUNC_ARG;
+   if (*mp == NULL) {
+      *mp = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT);
+      if (*mp == NULL) {
+         return MEMORY_E;
+      }
+      XMEMSET(*mp, 0, sizeof(mp_int));
+   }
+   return 0;
+}
+static WC_INLINE void wc_ecc_free_mpint(ecc_key* key, mp_int** mp)
+{
+   if (key && mp && *mp) {
+      mp_clear(*mp);
+      XFREE(*mp, key->heap, DYNAMIC_TYPE_BIGINT);
+      *mp = NULL;
+   }
+}
+
+static int wc_ecc_alloc_async(ecc_key* key)
+{
+    int err = wc_ecc_alloc_mpint(key, &key->r);
+    if (err == 0)
+        err = wc_ecc_alloc_mpint(key, &key->s);
+    return err;
+}
+
+static void wc_ecc_free_async(ecc_key* key)
+{
+    wc_ecc_free_mpint(key, &key->r);
+    wc_ecc_free_mpint(key, &key->s);
+#ifdef HAVE_CAVIUM_V
+    wc_ecc_free_mpint(key, &key->e);
+    wc_ecc_free_mpint(key, &key->signK);
+#endif /* HAVE_CAVIUM_V */
+}
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
 
 #ifdef HAVE_ECC_DHE
@@ -2693,4 +3389,12 @@
    }
 
+#ifdef WOLF_CRYPTO_DEV
+    if (private_key->devId != INVALID_DEVID) {
+        err = wc_CryptoDev_Ecdh(private_key, public_key, out, outlen);
+        if (err != NOT_COMPILED_IN)
+            return err;
+    }
+#endif
+
    /* type valid? */
    if (private_key->type != ECC_PRIVATEKEY &&
@@ -2711,10 +3415,15 @@
 
 #ifdef WOLFSSL_ATECC508A
-   err = atcatls_ecdh(private_key->slot, public_key->pubkey, out);
-   if (err != ATCA_SUCCESS) {
-      err = BAD_COND_E;
-   }
+   /* For SECP256R1 use hardware */
+   if (private_key->dp->id == ECC_SECP256R1) {
+       err = atmel_ecc_create_pms(private_key->slot, public_key->pubkey_raw, out);
    *outlen = private_key->dp->size;
+   }
+   else {
+      err = NOT_COMPILED_IN;
+   }
+
 #else
+
    err = wc_ecc_shared_secret_ex(private_key, &public_key->pubkey, out, outlen);
 #endif /* WOLFSSL_ATECC508A */
@@ -2730,6 +3439,8 @@
 {
     int err;
+#ifndef WOLFSSL_SP_MATH
     ecc_point* result = NULL;
     word32 x = 0;
+#endif
     mp_int* k = &private_key->k;
 #ifdef HAVE_ECC_CDH
@@ -2763,4 +3474,11 @@
 #endif
 #endif
+#ifdef WOLFSSL_SP_MATH
+    {
+        err = WC_KEY_SIZE_E;
+
+        (void)curve;
+    }
+#else
     {
         /* make new point */
@@ -2792,4 +3510,5 @@
         wc_ecc_del_point_h(result, private_key->heap);
     }
+#endif
 #ifdef HAVE_ECC_CDH
     if (k == &k_lcl)
@@ -2807,17 +3526,33 @@
     int err;
 
-#ifdef HAVE_CAVIUM
-    /* TODO: Not implemented - use software for now */
-    err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve);
-
-#elif defined(HAVE_INTEL_QA)
+#if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)
+#ifdef HAVE_CAVIUM_V
+    /* verify the curve is supported by hardware */
+    if (NitroxEccIsCurveSupported(private_key))
+#endif
+    {
+        word32 keySz = private_key->dp->size;
+
     /* sync public key x/y */
-    err = wc_ecc_curve_load(private_key->dp, &curve, ECC_CURVE_FIELD_BF);
+        err = wc_mp_to_bigint_sz(&private_key->k, &private_key->k.raw, keySz);
+        if (err == MP_OKAY)
+            err = wc_mp_to_bigint_sz(point->x, &point->x->raw, keySz);
+        if (err == MP_OKAY)
+            err = wc_mp_to_bigint_sz(point->y, &point->y->raw, keySz);
+    #ifdef HAVE_CAVIUM_V
+        /* allocate buffer for output */
     if (err == MP_OKAY)
-        err = wc_mp_to_bigint(&private_key->k, &private_key->k.raw);
+            err = wc_ecc_alloc_mpint(private_key, &private_key->e);
     if (err == MP_OKAY)
-        err = wc_mp_to_bigint(point->x, &point->x->raw);
+            err = wc_bigint_alloc(&private_key->e->raw,
+                NitroxEccGetSize(private_key)*2);
     if (err == MP_OKAY)
-        err = wc_mp_to_bigint(point->y, &point->y->raw);
+            err = NitroxEcdh(private_key,
+                &private_key->k.raw, &point->x->raw, &point->y->raw,
+                private_key->e->raw.buf, &private_key->e->raw.len,
+                &curve->prime->raw);
+    #else
+        if (err == MP_OKAY)
+            err = wc_ecc_curve_load(private_key->dp, &curve, ECC_CURVE_FIELD_BF);
     if (err == MP_OKAY)
         err = IntelQaEcdh(&private_key->asyncDev,
@@ -2826,5 +3561,8 @@
             &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw,
             private_key->dp->cofactor);
-#else /* WOLFSSL_ASYNC_CRYPT_TEST */
+    #endif
+        return err;
+    }
+#elif defined(WOLFSSL_ASYNC_CRYPT_TEST)
     if (wc_AsyncTestInit(&private_key->asyncDev, ASYNC_TEST_ECC_SHARED_SEC)) {
         WC_ASYNC_TEST* testDev = &private_key->asyncDev.test;
@@ -2835,6 +3573,8 @@
         return WC_PENDING_E;
     }
+#endif
+
+    /* use sync in other cases */
     err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve);
-#endif
 
     return err;
@@ -2846,5 +3586,5 @@
 {
     int err;
-    DECLARE_CURVE_SPECS(2)
+    DECLARE_CURVE_SPECS(curve, 2);
 
     if (private_key == NULL || point == NULL || out == NULL ||
@@ -2853,9 +3593,13 @@
     }
 
+    ALLOC_CURVE_SPECS(2);
+
     /* load curve info */
     err = wc_ecc_curve_load(private_key->dp, &curve,
         (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF));
-    if (err != MP_OKAY)
+    if (err != MP_OKAY) {
+        FREE_CURVE_SPECS();
         return err;
+    }
 
 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
@@ -2872,4 +3616,5 @@
 
     wc_ecc_curve_free(curve);
+    FREE_CURVE_SPECS();
 
     return err;
@@ -2918,4 +3663,16 @@
         case ECC_STATE_SHARED_SEC_RES:
             private_key->state = ECC_STATE_SHARED_SEC_RES;
+        #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+            if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
+            #ifdef HAVE_CAVIUM_V
+                /* verify the curve is supported by hardware */
+                if (NitroxEccIsCurveSupported(private_key)) {
+                    /* copy output */
+                    *outlen = private_key->dp->size;
+                    XMEMCPY(out, private_key->e->raw.buf, *outlen);
+                }
+            #endif /* HAVE_CAVIUM_V */
+            }
+        #endif /* WOLFSSL_ASYNC_CRYPT */
             err = 0;
             break;
@@ -2931,4 +3688,8 @@
     }
 
+    /* cleanup */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    wc_ecc_free_async(private_key);
+#endif
     private_key->state = ECC_STATE_NONE;
 
@@ -2952,18 +3713,14 @@
 }
 
+#ifndef WOLFSSL_SP_MATH
 /* generate random and ensure its greater than 0 and less than order */
 static int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order)
 {
+#ifndef WC_NO_RNG
     int err;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* buf;
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    DECLARE_VAR(buf, byte, ECC_MAXSIZE_GEN, rng->heap);
 #else
     byte  buf[ECC_MAXSIZE_GEN];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-    if (buf == NULL)
-        return MEMORY_E;
 #endif
 
@@ -2978,10 +3735,4 @@
     if (err == 0)
         err = mp_read_unsigned_bin(k, (byte*)buf, size);
-
-    /* quick sanity check to make sure we're not dealing with a 0 key */
-    if (err == MP_OKAY) {
-        if (mp_iszero(k) == MP_YES)
-          err = MP_ZERO_E;
-    }
 
     /* the key should be smaller than the order of base point */
@@ -2992,14 +3743,28 @@
     }
 
+    /* quick sanity check to make sure we're not dealing with a 0 key */
+    if (err == MP_OKAY) {
+        if (mp_iszero(k) == MP_YES)
+          err = MP_ZERO_E;
+    }
+
     ForceZero(buf, ECC_MAXSIZE);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    FREE_VAR(buf, rng->heap);
 #endif
 
     return err;
-}
+#else
+    (void)rng;
+    (void)size;
+    (void)k;
+    (void)order;
+    return NOT_COMPILED_IN;
+#endif /* !WC_NO_RNG */
+}
+#endif /* WOLFSSL_SP_MATH */
 #endif /* !WOLFSSL_ATECC508A */
 
-static INLINE void wc_ecc_reset(ecc_key* key)
+static WC_INLINE void wc_ecc_reset(ecc_key* key)
 {
     /* make sure required key variables are reset */
@@ -3026,8 +3791,10 @@
     int err = MP_OKAY;
 #ifndef WOLFSSL_ATECC508A
+#ifndef WOLFSSL_SP_MATH
     ecc_point* base = NULL;
+#endif
     ecc_point* pub;
-    DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT)
-#endif
+    DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
+#endif /* !WOLFSSL_ATECC508A */
 
     if (key == NULL) {
@@ -3036,4 +3803,5 @@
 
 #ifndef WOLFSSL_ATECC508A
+
     /* if ecc_point passed in then use it as output for public key point */
     if (pubOut != NULL) {
@@ -3052,4 +3820,6 @@
     }
     else {
+        ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
+
         /* load curve info */
         if (err == MP_OKAY)
@@ -3080,4 +3850,7 @@
 #endif
 #endif
+#ifdef WOLFSSL_SP_MATH
+        err = WC_KEY_SIZE_E;
+#else
     {
         if (err == MP_OKAY) {
@@ -3102,4 +3875,5 @@
         wc_ecc_del_point_h(base, key->heap);
     }
+#endif
 
 #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
@@ -3122,6 +3896,9 @@
     if (curveIn == NULL) {
         wc_ecc_curve_free(curve);
-    }
-
+        FREE_CURVE_SPECS();
+    }
+
+#else
+    (void)curveIn;
 #endif /* WOLFSSL_ATECC508A */
 
@@ -3156,6 +3933,8 @@
     int            err;
 #ifndef WOLFSSL_ATECC508A
-    DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT)
-#endif
+#ifndef WOLFSSL_SP_MATH
+    DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
+#endif
+#endif /* !WOLFSSL_ATECC508A */
 
     if (key == NULL || rng == NULL) {
@@ -3170,4 +3949,12 @@
         return err;
     }
+
+#ifdef WOLF_CRYPTO_DEV
+    if (key->devId != INVALID_DEVID) {
+        err = wc_CryptoDev_MakeEccKey(rng, keysize, key, curve_id);
+        if (err != NOT_COMPILED_IN)
+            return err;
+    }
+#endif
 
 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
@@ -3188,11 +3975,21 @@
     #endif
     }
-#endif /* WOLFSSL_ASYNC_CRYPT */
+#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */
 
 #ifdef WOLFSSL_ATECC508A
     key->type = ECC_PRIVATEKEY;
-    err = atcatls_create_key(key->slot, key->pubkey);
-    if (err != ATCA_SUCCESS)
-        err = BAD_COND_E;
+   key->slot = atmel_ecc_alloc(ATMEL_SLOT_ECDHE);
+   err = atmel_ecc_create_key(key->slot, key->pubkey_raw);
+
+   /* populate key->pubkey */
+   if (err == 0 && key->pubkey.x) {
+       err = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw,
+                                  ECC_MAX_CRYPTO_HW_SIZE);
+   }
+   if (err == 0 && key->pubkey.y) {
+       err = mp_read_unsigned_bin(key->pubkey.y,
+                                  key->pubkey_raw + ECC_MAX_CRYPTO_HW_SIZE,
+                                  ECC_MAX_CRYPTO_HW_SIZE);
+   }
 #else
 
@@ -3206,6 +4003,12 @@
     else
 #endif
-#endif
-    {
+#endif /* WOLFSSL_HAVE_SP_ECC */
+
+   { /* software key gen */
+#ifdef WOLFSSL_SP_MATH
+        err = WC_KEY_SIZE_E;
+#else
+        ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
+
         /* setup the key variables */
         err = mp_init(&key->k);
@@ -3234,5 +4037,18 @@
         /* cleanup allocations */
         wc_ecc_curve_free(curve);
-    }
+        FREE_CURVE_SPECS();
+#endif /* WOLFSSL_SP_MATH */
+    }
+
+#ifdef HAVE_WOLF_BIGINT
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(&key->k, &key->k.raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(key->pubkey.x, &key->pubkey.x->raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(key->pubkey.y, &key->pubkey.y->raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(key->pubkey.z, &key->pubkey.z->raw);
+#endif
 
 #endif /* WOLFSSL_ATECC508A */
@@ -3311,64 +4127,4 @@
 }
 
-static INLINE int wc_ecc_alloc_rs(ecc_key* key, mp_int** r, mp_int** s)
-{
-    int err = 0;
-
-#ifndef WOLFSSL_ASYNC_CRYPT
-    (void)key;
-#endif
-
-    if (*r == NULL) {
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        *r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT);
-        if (*r == NULL) {
-            return MEMORY_E;
-        }
-        key->r = *r;
-    #endif
-    }
-    if (*s == NULL) {
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        *s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT);
-        if (*s == NULL) {
-            XFREE(*r, key->heap, DYNAMIC_TYPE_BIGINT);
-            return MEMORY_E;
-        }
-        key->s = *s;
-    #endif
-    }
-
-    /* initialize mp_int */
-    if (*r)
-        XMEMSET(*r, 0, sizeof(mp_int));
-    if (*s)
-        XMEMSET(*s, 0, sizeof(mp_int));
-
-    return err;
-}
-
-static INLINE void wc_ecc_free_rs(ecc_key* key, mp_int** r, mp_int** s)
-{
-    if (*r) {
-        mp_clear(*r);
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        XFREE(*r, key->heap, DYNAMIC_TYPE_BIGINT);
-        key->r = NULL;
-    #endif
-        *r = NULL;
-    }
-    if (*s) {
-        mp_clear(*s);
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        XFREE(*s, key->heap, DYNAMIC_TYPE_BIGINT);
-        key->s = NULL;
-    #endif
-        *s = NULL;
-    }
-    (void)key;
-}
-
 /* Setup dynamic pointers if using normal math for proper freeing */
 int wc_ecc_init_ex(ecc_key* key, void* heap, int devId)
@@ -3387,9 +4143,12 @@
     key->state = ECC_STATE_NONE;
 
+#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_DEV)
+    key->devId = devId;
+#else
+    (void)devId;
+#endif
+
 #ifdef WOLFSSL_ATECC508A
-    key->slot = atmel_ecc_alloc();
-    if (key->slot == ATECC_INVALID_SLOT) {
-        return ECC_BAD_ARG_E;
-    }
+    key->slot = ATECC_INVALID_SLOT;
 #else
 #ifdef ALT_ECC_SIZE
@@ -3420,6 +4179,4 @@
     ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC,
                                                             key->heap, devId);
-#else
-    (void)devId;
 #endif
 
@@ -3431,4 +4188,27 @@
     return wc_ecc_init_ex(key, NULL, INVALID_DEVID);
 }
+
+#ifdef HAVE_PKCS11
+int wc_ecc_init_id(ecc_key* key, unsigned char* id, int len, void* heap,
+                   int devId)
+{
+    int ret = 0;
+
+    if (key == NULL)
+        ret = BAD_FUNC_ARG;
+    if (ret == 0 && (len < 0 || len > ECC_MAX_ID_LEN))
+        ret = BUFFER_E;
+
+    if (ret == 0)
+        ret = wc_ecc_init_ex(key, heap, devId);
+
+    if (ret == 0 && id != NULL && len != 0) {
+        XMEMCPY(key->id, id, len);
+        key->idLen = len;
+    }
+
+    return ret;
+}
+#endif
 
 int wc_ecc_set_flags(ecc_key* key, word32 flags)
@@ -3444,4 +4224,72 @@
 
 #ifndef NO_ASN
+
+#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC)
+static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen,
+    mp_int* r, mp_int* s, byte* out, word32 *outlen, WC_RNG* rng,
+    ecc_key* key)
+{
+    int err;
+
+#ifdef PLUTON_CRYPTO_ECC
+    if (key->devId != INVALID_DEVID) /* use hardware */
+#endif
+    {
+        word32 keysize = (word32)key->dp->size;
+
+        /* Check args */
+        if (keysize > ECC_MAX_CRYPTO_HW_SIZE || inlen != keysize ||
+                                                *outlen < keysize*2) {
+            return ECC_BAD_ARG_E;
+        }
+
+    #if defined(WOLFSSL_ATECC508A)
+        key->slot = atmel_ecc_alloc(ATMEL_SLOT_DEVICE);
+        if (key->slot == ATECC_INVALID_SLOT) {
+            return ECC_BAD_ARG_E;
+        }
+
+        /* Sign: Result is 32-bytes of R then 32-bytes of S */
+        err = atmel_ecc_sign(key->slot, in, out);
+        if (err != 0) {
+           return err;
+        }
+    #elif defined(PLUTON_CRYPTO_ECC)
+        {
+            /* perform ECC sign */
+            word32 raw_sig_size = *outlen;
+            err = Crypto_EccSign(in, inlen, out, &raw_sig_size);
+            if (err != CRYPTO_RES_SUCCESS || raw_sig_size != keysize*2){
+               return BAD_COND_E;
+            }
+        }
+    #endif
+
+        /* Load R and S */
+        err = mp_read_unsigned_bin(r, &out[0], keysize);
+        if (err != MP_OKAY) {
+            return err;
+        }
+        err = mp_read_unsigned_bin(s, &out[keysize], keysize);
+        if (err != MP_OKAY) {
+            return err;
+        }
+
+        /* Check for zeros */
+        if (mp_iszero(r) || mp_iszero(s)) {
+            return MP_ZERO_E;
+        }
+    }
+#ifdef PLUTON_CRYPTO_ECC
+    else {
+        err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
+    }
+#endif
+    (void)rng;
+
+    return err;
+}
+#endif /* WOLFSSL_ATECC508A || PLUTON_CRYPTO_ECC */
+
 /**
  Sign a message digest
@@ -3458,8 +4306,6 @@
     int err;
     mp_int *r = NULL, *s = NULL;
-#ifndef WOLFSSL_ASYNC_CRYPT
+#if !defined(WOLFSSL_ASYNC_CRYPT) && !defined(WOLFSSL_SMALL_STACK)
     mp_int r_lcl, s_lcl;
-    r = &r_lcl;
-    s = &s_lcl;
 #endif
 
@@ -3468,4 +4314,32 @@
         return ECC_BAD_ARG_E;
     }
+
+#ifdef WOLF_CRYPTO_DEV
+    if (key->devId != INVALID_DEVID) {
+        err = wc_CryptoDev_EccSign(in, inlen, out, outlen, rng, key);
+        if (err != NOT_COMPILED_IN)
+            return err;
+    }
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    err = wc_ecc_alloc_async(key);
+    if (err != 0)
+        return err;
+    r = key->r;
+    s = key->s;
+#elif !defined(WOLFSSL_SMALL_STACK)
+    r = &r_lcl;
+    s = &s_lcl;
+#else
+    r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+    if (r == NULL)
+        return MEMORY_E;
+    s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+    if (s == NULL) {
+        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+#endif
 
     switch(key->state) {
@@ -3474,47 +4348,18 @@
             key->state = ECC_STATE_SIGN_DO;
 
-            err = wc_ecc_alloc_rs(key, &r, &s);
-            if (err != 0)
-                break;
-
             if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){
                 break;
             }
 
-        #ifdef WOLFSSL_ATECC508A
-            /* Check args */
-            if (inlen != ATECC_KEY_SIZE || *outlen < SIGN_RSP_SIZE) {
-                return ECC_BAD_ARG_E;
-            }
-
-            /* Sign: Result is 32-bytes of R then 32-bytes of S */
-            err = atcatls_sign(key->slot, in, out);
-            if (err != ATCA_SUCCESS) {
-               return BAD_COND_E;
-           }
-
-            /* Load R and S */
-            err = mp_read_unsigned_bin(r, &out[0], ATECC_KEY_SIZE);
-            if (err != MP_OKAY) {
-                return err;
-            }
-            err = mp_read_unsigned_bin(s, &out[ATECC_KEY_SIZE], ATECC_KEY_SIZE);
-            if (err != MP_OKAY) {
-                return err;
-            }
-
-            /* Check for zeros */
-            if (mp_iszero(r) || mp_iszero(s)) {
-                return MP_ZERO_E;
-            }
-
+        /* hardware crypto */
+        #if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC)
+            err = wc_ecc_sign_hash_hw(in, inlen, r, s, out, outlen, rng, key);
         #else
-
             err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
+        #endif
             if (err < 0) {
                 break;
             }
 
-        #endif /* WOLFSSL_ATECC508A */
             FALL_THROUGH;
 
@@ -3523,11 +4368,11 @@
 
         #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
-            /* restore r/s */
-            r = key->r;
-            s = key->s;
-
             if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
-                /* only do this if not simulator, since it overwrites result */
+                #ifdef HAVE_CAVIUM_V
+                    /* Nitrox requires r and s in sep buffer, so split it */
+                    NitroxEccRsSplit(key, &r->raw, &s->raw);
+                #endif
                 #ifndef WOLFSSL_ASYNC_CRYPT_TEST
+                    /* only do this if not simulator, since it overwrites result */
                     wc_bigint_to_mp(&r->raw, r);
                     wc_bigint_to_mp(&s->raw, s);
@@ -3539,11 +4384,16 @@
             err = StoreECC_DSA_Sig(out, outlen, r, s);
 
-            /* always free r/s */
+            /* done with R/S */
             mp_clear(r);
             mp_clear(s);
+        #if !defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_SMALL_STACK)
+            XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
+            XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+        #endif
             break;
 
         default:
             err = BAD_STATE_E;
+            break;
     }
 
@@ -3555,5 +4405,7 @@
 
     /* cleanup */
-    wc_ecc_free_rs(key, &r, &s);
+#ifdef WOLFSSL_ASYNC_CRYPT
+    wc_ecc_free_async(key);
+#endif
     key->state = ECC_STATE_NONE;
 
@@ -3576,6 +4428,12 @@
 {
    int    err;
-   mp_int e;
-   DECLARE_CURVE_SPECS(1)
+#ifndef WOLFSSL_SP_MATH
+   mp_int* e;
+#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)) && \
+                                                   !defined(WOLFSSL_SMALL_STACK)
+   mp_int  e_lcl;
+#endif
+   DECLARE_CURVE_SPECS(curve, 1);
+#endif /* !WOLFSSL_SP_MATH */
 
    if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL)
@@ -3592,4 +4450,10 @@
    }
 
+#ifdef WOLFSSL_SP_MATH
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1)
+        return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->heap);
+    else
+        return WC_KEY_SIZE_E;
+#else
 #ifdef WOLFSSL_HAVE_SP_ECC
     #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
@@ -3603,5 +4467,6 @@
 #endif
     }
-#endif
+#endif /* WOLFSSL_HAVE_SP_ECC */
+
 
 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
@@ -3621,7 +4486,30 @@
 #endif
 
+   ALLOC_CURVE_SPECS(1);
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V)
+   err = wc_ecc_alloc_mpint(key, &key->e);
+   if (err != 0) {
+      FREE_CURVE_SPECS();
+      return err;
+   }
+   e = key->e;
+#elif !defined(WOLFSSL_SMALL_STACK)
+   e = &e_lcl;
+#else
+   e = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+   if (e == NULL) {
+      FREE_CURVE_SPECS();
+      return MEMORY_E;
+   }
+#endif
+
    /* get the hash and load it as a bignum into 'e' */
    /* init the bignums */
-   if ((err = mp_init(&e)) != MP_OKAY) {
+   if ((err = mp_init(e)) != MP_OKAY) {
+   #ifdef WOLFSSL_SMALL_STACK
+      XFREE(e, key->heap, DYNAMIC_TYPE_ECC);
+   #endif
+      FREE_CURVE_SPECS();
       return err;
    }
@@ -3638,9 +4526,9 @@
        if ((WOLFSSL_BIT_SIZE * inlen) > orderBits)
            inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE;
-       err = mp_read_unsigned_bin(&e, (byte*)in, inlen);
+       err = mp_read_unsigned_bin(e, (byte*)in, inlen);
 
        /* may still need bit truncation too */
        if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * inlen) > orderBits)
-           mp_rshb(&e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
+           mp_rshb(e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
    }
 
@@ -3648,94 +4536,191 @@
    if (err == MP_OKAY) {
        int loop_check = 0;
-       ecc_key pubkey;
+   #ifdef WOLFSSL_SMALL_STACK
+       ecc_key* pubkey = NULL;
+   #else
+       ecc_key  pubkey[1];
+   #endif
 
    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
         if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
-        #ifdef HAVE_CAVIUM
-            /* TODO: Not implemented */
-        #elif defined(HAVE_INTEL_QA)
-           mp_int k;
-
-           err = mp_init(&k);
+        #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)
+        #ifdef HAVE_CAVIUM_V
+            if (NitroxEccIsCurveSupported(key))
+        #endif
+            {
+               word32 keySz = key->dp->size;
+               mp_int* k;
+            #ifdef HAVE_CAVIUM_V
+               err = wc_ecc_alloc_mpint(key, &key->signK);
+               if (err != 0)
+                  return err;
+               k = key->signK;
+            #else
+               mp_int k_lcl;
+               k = &k_lcl;
+            #endif
+
+               err = mp_init(k);
+
            /* make sure r and s are allocated */
+           #ifdef HAVE_CAVIUM_V
+               /* Nitrox V needs single buffer for R and S */
+               if (err == MP_OKAY)
+                   err = wc_bigint_alloc(&key->r->raw, NitroxEccGetSize(key)*2);
+               /* Nitrox V only needs Prime and Order */
+               if (err == MP_OKAY)
+                   err = wc_ecc_curve_load(key->dp, &curve,
+                        (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_ORDER));
+           #else
            if (err == MP_OKAY)
                err = wc_bigint_alloc(&key->r->raw, key->dp->size);
            if (err == MP_OKAY)
+                   err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
+           #endif
+               if (err == MP_OKAY)
                err = wc_bigint_alloc(&key->s->raw, key->dp->size);
+
            /* load e and k */
            if (err == MP_OKAY)
-               err = wc_mp_to_bigint(&e, &e.raw);
+                   err = wc_mp_to_bigint_sz(e, &e->raw, keySz);
            if (err == MP_OKAY)
-               err = wc_mp_to_bigint(&key->k, &key->k.raw);
+                   err = wc_mp_to_bigint_sz(&key->k, &key->k.raw, keySz);
            if (err == MP_OKAY)
-               err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
+                   err = wc_ecc_gen_k(rng, key->dp->size, k, curve->order);
            if (err == MP_OKAY)
-               err = wc_ecc_gen_k(rng, key->dp->size, &k, curve->order);
+                   err = wc_mp_to_bigint_sz(k, &k->raw, keySz);
+
+           #ifdef HAVE_CAVIUM_V
            if (err == MP_OKAY)
-               err = wc_mp_to_bigint(&k, &k.raw);
+                   err = NitroxEcdsaSign(key, &e->raw, &key->k.raw, &k->raw,
+                    &r->raw, &s->raw, &curve->prime->raw, &curve->order->raw);
+           #else
            if (err == MP_OKAY)
-               err = IntelQaEcdsaSign(&key->asyncDev, &e.raw, &key->k.raw,
-                  &k.raw, &r->raw, &s->raw, &curve->Af->raw, &curve->Bf->raw,
+                   err = IntelQaEcdsaSign(&key->asyncDev, &e->raw, &key->k.raw,
+                      &k->raw, &r->raw, &s->raw, &curve->Af->raw, &curve->Bf->raw,
                   &curve->prime->raw, &curve->order->raw, &curve->Gx->raw,
                   &curve->Gy->raw);
-
-           mp_clear(&e);
-           mp_clear(&k);
+           #endif
+
+           #ifndef HAVE_CAVIUM_V
+               mp_clear(e);
+               mp_clear(k);
+           #endif
            wc_ecc_curve_free(curve);
+               FREE_CURVE_SPECS();
 
            return err;
-       #endif
+           }
+       #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */
        }
    #endif /* WOLFSSL_ASYNC_CRYPT */
 
+   #ifdef WOLFSSL_SMALL_STACK
+       pubkey = (ecc_key*)XMALLOC(sizeof(ecc_key), key->heap, DYNAMIC_TYPE_ECC);
+       if (pubkey == NULL)
+           err = MEMORY_E;
+   #endif
+
        /* don't use async for key, since we don't support async return here */
-       if (wc_ecc_init_ex(&pubkey, key->heap, INVALID_DEVID) == MP_OKAY) {
+       if (err == MP_OKAY && (err = wc_ecc_init_ex(pubkey, key->heap,
+                                                   INVALID_DEVID)) == MP_OKAY) {
+       #ifdef WOLFSSL_SMALL_STACK
+           mp_int* b = NULL;
+       #else
+           mp_int  b[1];
+       #endif
+
+       #ifdef WOLFSSL_SMALL_STACK
+           if (err == MP_OKAY) {
+               b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap,
+                                                              DYNAMIC_TYPE_ECC);
+               if (b == NULL)
+                   err = MEMORY_E;
+           }
+       #endif
+
+           if (err == MP_OKAY) {
+               err = mp_init(b);
+           }
+
        #ifdef WOLFSSL_CUSTOM_CURVES
            /* if custom curve, apply params to pubkey */
-           if (key->idx == ECC_CUSTOM_IDX) {
-               wc_ecc_set_custom_curve(&pubkey, key->dp);
+           if (err == MP_OKAY && key->idx == ECC_CUSTOM_IDX) {
+               err = wc_ecc_set_custom_curve(pubkey, key->dp);
            }
        #endif
 
-           for (;;) {
+           if (err == MP_OKAY) {
+               /* Generate blinding value - non-zero value. */
+               do {
+                   if (++loop_check > 64) {
+                        err = RNG_FAILURE_E;
+                        break;
+                   }
+
+                   err = wc_ecc_gen_k(rng, key->dp->size, b, curve->order);
+               }
+               while (err == MP_ZERO_E);
+               loop_check = 0;
+           }
+
+           for (; err == MP_OKAY;) {
                if (++loop_check > 64) {
                     err = RNG_FAILURE_E;
                     break;
                }
-               err = wc_ecc_make_key_ex(rng, key->dp->size, &pubkey,
+               err = wc_ecc_make_key_ex(rng, key->dp->size, pubkey,
                                                               key->dp->id);
                if (err != MP_OKAY) break;
 
                /* find r = x1 mod n */
-               err = mp_mod(pubkey.pubkey.x, curve->order, r);
+               err = mp_mod(pubkey->pubkey.x, curve->order, r);
                if (err != MP_OKAY) break;
 
                if (mp_iszero(r) == MP_YES) {
                 #ifndef ALT_ECC_SIZE
-                   mp_clear(pubkey.pubkey.x);
-                   mp_clear(pubkey.pubkey.y);
-                   mp_clear(pubkey.pubkey.z);
+                   mp_clear(pubkey->pubkey.x);
+                   mp_clear(pubkey->pubkey.y);
+                   mp_clear(pubkey->pubkey.z);
                 #endif
-                   mp_forcezero(&pubkey.k);
+                   mp_forcezero(&pubkey->k);
                }
                else {
-                   /* find s = (e + xr)/k */
-                   err = mp_invmod(&pubkey.k, curve->order, &pubkey.k);
+                   /* find s = (e + xr)/k
+                             = b.(e/k.b + x.r/k.b) */
+
+                   /* k = k.b */
+                   err = mp_mulmod(&pubkey->k, b, curve->order, &pubkey->k);
                    if (err != MP_OKAY) break;
 
-                   /* s = xr */
+                   /* k = 1/k.b */
+                   err = mp_invmod(&pubkey->k, curve->order, &pubkey->k);
+                   if (err != MP_OKAY) break;
+
+                   /* s = x.r */
                    err = mp_mulmod(&key->k, r, curve->order, s);
                    if (err != MP_OKAY) break;
 
-                   /* s = e +  xr */
-                   err = mp_add(&e, s, s);
+                   /* s = x.r/k.b */
+                   err = mp_mulmod(&pubkey->k, s, curve->order, s);
                    if (err != MP_OKAY) break;
 
-                   /* s = e +  xr */
+                   /* e = e/k.b */
+                   err = mp_mulmod(&pubkey->k, e, curve->order, e);
+                   if (err != MP_OKAY) break;
+
+                   /* s = e/k.b + x.r/k.b
+                        = (e + x.r)/k.b */
+                   err = mp_add(e, s, s);
+                   if (err != MP_OKAY) break;
+
+                   /* s = b.(e + x.r)/k.b
+                        = (e + x.r)/k */
+                   err = mp_mulmod(s, b, curve->order, s);
+                   if (err != MP_OKAY) break;
+
+                   /* s = (e + xr)/k */
                    err = mp_mod(s, curve->order, s);
                    if (err != MP_OKAY) break;
-
-                   /* s = (e + xr)/k */
-                   err = mp_mulmod(s, &pubkey.k, curve->order, s);
 
                    if (mp_iszero(s) == MP_NO)
@@ -3743,10 +4728,23 @@
                 }
            }
-           wc_ecc_free(&pubkey);
+           mp_clear(b);
+           mp_free(b);
+       #ifdef WOLFSSL_SMALL_STACK
+           XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
+       #endif
+           wc_ecc_free(pubkey);
+       #ifdef WOLFSSL_SMALL_STACK
+           XFREE(pubkey, key->heap, DYNAMIC_TYPE_ECC);
+       #endif
        }
    }
 
-   mp_clear(&e);
+   mp_clear(e);
    wc_ecc_curve_free(curve);
+#ifdef WOLFSSL_SMALL_STACK
+   XFREE(e, key->heap, DYNAMIC_TYPE_ECC);
+#endif
+   FREE_CURVE_SPECS();
+#endif /* WOLFSSL_SP_MATH */
 
    return err;
@@ -3754,4 +4752,26 @@
 #endif /* WOLFSSL_ATECC508A */
 #endif /* HAVE_ECC_SIGN */
+
+#ifdef WOLFSSL_CUSTOM_CURVES
+void wc_ecc_free_curve(const ecc_set_type* curve, void* heap)
+{
+    if (curve->prime != NULL)
+        XFREE((void*)curve->prime, heap, DYNAMIC_TYPE_ECC_BUFFER);
+    if (curve->Af != NULL)
+        XFREE((void*)curve->Af, heap, DYNAMIC_TYPE_ECC_BUFFER);
+    if (curve->Bf != NULL)
+        XFREE((void*)curve->Bf, heap, DYNAMIC_TYPE_ECC_BUFFER);
+    if (curve->order != NULL)
+        XFREE((void*)curve->order, heap, DYNAMIC_TYPE_ECC_BUFFER);
+    if (curve->Gx != NULL)
+        XFREE((void*)curve->Gx, heap, DYNAMIC_TYPE_ECC_BUFFER);
+    if (curve->Gy != NULL)
+        XFREE((void*)curve->Gy, heap, DYNAMIC_TYPE_ECC_BUFFER);
+
+    XFREE((void*)curve, heap, DYNAMIC_TYPE_ECC_BUFFER);
+
+    (void)heap;
+}
+#endif /* WOLFSSL_CUSTOM_CURVES */
 
 /**
@@ -3759,18 +4779,20 @@
   key   The key you wish to free
 */
-void wc_ecc_free(ecc_key* key)
+int wc_ecc_free(ecc_key* key)
 {
     if (key == NULL) {
-        return;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+        return 0;
+    }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #ifdef WC_ASYNC_ENABLE_ECC
     wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC);
-    wc_ecc_free_rs(key, &key->r, &key->s);
+    #endif
+    wc_ecc_free_async(key);
 #endif
 
 #ifdef WOLFSSL_ATECC508A
    atmel_ecc_free(key->slot);
-   key->slot = -1;
+    key->slot = ATECC_INVALID_SLOT;
 #else
 
@@ -3781,6 +4803,14 @@
     mp_forcezero(&key->k);
 #endif /* WOLFSSL_ATECC508A */
-}
-
+
+#ifdef WOLFSSL_CUSTOM_CURVES
+    if (key->deallocSet && key->dp != NULL)
+        wc_ecc_free_curve(key->dp, key->heap);
+#endif
+
+    return 0;
+}
+
+#if !defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_ATECC508A)
 #ifdef ECC_SHAMIR
 
@@ -3801,5 +4831,5 @@
                              void* heap)
 #else
-static int ecc_mul2add(ecc_point* A, mp_int* kA,
+int ecc_mul2add(ecc_point* A, mp_int* kA,
                     ecc_point* B, mp_int* kB,
                     ecc_point* C, mp_int* a, mp_int* modulus,
@@ -3807,10 +4837,17 @@
 #endif
 {
-  ecc_point*     precomp[16];
+#ifdef WOLFSSL_SMALL_STACK
+  ecc_point**    precomp = NULL;
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+  ecc_key        key;
+#endif
+#else
+  ecc_point*     precomp[SHAMIR_PRECOMP_SZ];
+#endif
   unsigned       bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble;
   unsigned char* tA;
   unsigned char* tB;
   int            err = MP_OKAY, first, x, y;
-  mp_digit mp;
+  mp_digit       mp = 0;
 
   /* argchks */
@@ -3830,9 +4867,49 @@
      return GEN_MEM_ERR;
   }
+#ifdef WOLFSSL_SMALL_STACK
+  precomp = (ecc_point**)XMALLOC(sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ, heap,
+                                                       DYNAMIC_TYPE_ECC_BUFFER);
+  if (precomp == NULL) {
+     XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER);
+     XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER);
+     return GEN_MEM_ERR;
+  }
+#endif
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+  key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+  key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+#ifdef ALT_ECC_SIZE
+  key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+  key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+  key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+#endif
+  if (key.t1 == NULL || key.t2 == NULL
+#ifdef ALT_ECC_SIZE
+     || key.x == NULL || key.y == NULL || key.z == NULL
+#endif
+  ) {
+#ifdef ALT_ECC_SIZE
+      XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+      XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+      XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+      XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+      XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+      XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER);
+      XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER);
+      XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER);
+      return MEMORY_E;
+  }
+  C->key = &key;
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
 
   /* init variables */
   XMEMSET(tA, 0, ECC_BUFSIZE);
   XMEMSET(tB, 0, ECC_BUFSIZE);
+#ifndef WOLFSSL_SMALL_STACK
   XMEMSET(precomp, 0, sizeof(precomp));
+#else
+  XMEMSET(precomp, 0, sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ);
+#endif
 
   /* get sizes */
@@ -3856,5 +4933,5 @@
     /* allocate the table */
     if (err == MP_OKAY) {
-        for (x = 0; x < 16; x++) {
+        for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) {
             precomp[x] = wc_ecc_new_point_h(heap);
             if (precomp[x] == NULL) {
@@ -3862,4 +4939,7 @@
                 break;
             }
+        #ifdef WOLFSSL_SMALL_STACK_CACHE
+            precomp[x]->key = &key;
+        #endif
         }
     }
@@ -3871,27 +4951,41 @@
 
   if (err == MP_OKAY) {
-    mp_int mu;
-    err = mp_init(&mu);
+  #ifdef WOLFSSL_SMALL_STACK
+    mp_int* mu = NULL;
+  #else
+    mp_int  mu[1];
+  #endif
+  #ifdef WOLFSSL_SMALL_STACK
+    mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+    if (mu == NULL)
+        err = MEMORY_E;
+  #endif
     if (err == MP_OKAY) {
-      err = mp_montgomery_calc_normalization(&mu, modulus);
+        err = mp_init(mu);
+    }
+    if (err == MP_OKAY) {
+      err = mp_montgomery_calc_normalization(mu, modulus);
 
       if (err == MP_OKAY)
         /* copy ones ... */
-        err = mp_mulmod(A->x, &mu, modulus, precomp[1]->x);
+        err = mp_mulmod(A->x, mu, modulus, precomp[1]->x);
 
       if (err == MP_OKAY)
-        err = mp_mulmod(A->y, &mu, modulus, precomp[1]->y);
+        err = mp_mulmod(A->y, mu, modulus, precomp[1]->y);
       if (err == MP_OKAY)
-        err = mp_mulmod(A->z, &mu, modulus, precomp[1]->z);
+        err = mp_mulmod(A->z, mu, modulus, precomp[1]->z);
 
       if (err == MP_OKAY)
-        err = mp_mulmod(B->x, &mu, modulus, precomp[1<<2]->x);
+        err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x);
       if (err == MP_OKAY)
-        err = mp_mulmod(B->y, &mu, modulus, precomp[1<<2]->y);
+        err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y);
       if (err == MP_OKAY)
-        err = mp_mulmod(B->z, &mu, modulus, precomp[1<<2]->z);
+        err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z);
 
       /* done with mu */
-      mp_clear(&mu);
+      mp_clear(mu);
+  #ifdef WOLFSSL_SMALL_STACK
+      XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+  #endif
     }
   }
@@ -3916,9 +5010,10 @@
     for (x = 1; x < 4; x++) {
         for (y = 1; y < 4; y++) {
-            if (err == MP_OKAY)
+        if (err == MP_OKAY) {
                 err = ecc_projective_add_point(precomp[x], precomp[(y<<2)],
                                                precomp[x+(y<<2)], a, modulus, mp);
         }
     }
+  }
   }
 
@@ -3994,5 +5089,5 @@
 
   /* clean up */
-  for (x = 0; x < 16; x++) {
+  for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) {
      wc_ecc_del_point_h(precomp[x], heap);
   }
@@ -4000,6 +5095,19 @@
   ForceZero(tA, ECC_BUFSIZE);
   ForceZero(tB, ECC_BUFSIZE);
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+#ifdef ALT_ECC_SIZE
+  XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+  XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+  XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+  XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+  XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+  C->key = NULL;
+#endif
+#ifdef WOLFSSL_SMALL_STACK
+  XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+  XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER);
   XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER);
-  XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER);
 
   return err;
@@ -4007,4 +5115,5 @@
 
 #endif /* ECC_SHAMIR */
+#endif /* !WOLFSSL_SP_MATH && !WOLFSSL_ATECC508A */
 
 
@@ -4037,7 +5146,7 @@
     mp_int *r = NULL, *s = NULL;
 #ifndef WOLFSSL_ASYNC_CRYPT
-    mp_int r_lcl, s_lcl;
-    r = &r_lcl;
-    s = &s_lcl;
+#ifndef WOLFSSL_SMALL_STACK
+    mp_int r_lcl[1], s_lcl[1];
+#endif
 #endif
 
@@ -4045,4 +5154,36 @@
         return ECC_BAD_ARG_E;
     }
+
+#ifdef WOLF_CRYPTO_DEV
+    if (key->devId != INVALID_DEVID) {
+        err = wc_CryptoDev_EccVerify(sig, siglen, hash, hashlen, res, key);
+        if (err != NOT_COMPILED_IN)
+            return err;
+    }
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    err = wc_ecc_alloc_async(key);
+    if (err != 0)
+        return err;
+    r = key->r;
+    s = key->s;
+#else
+    #ifndef WOLFSSL_SMALL_STACK
+    r = r_lcl;
+    s = s_lcl;
+    #else
+    r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+    if (r == NULL)
+        return MEMORY_E;
+    s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+    if (s == NULL) {
+        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+    #endif
+    XMEMSET(r, 0, sizeof(mp_int));
+    XMEMSET(s, 0, sizeof(mp_int));
+#endif /* WOLFSSL_ASYNC_CRYPT */
 
     switch(key->state) {
@@ -4058,8 +5199,4 @@
              * the rest of this function will execute, and everything
              * gets cleaned up at the end. */
-            err = wc_ecc_alloc_rs(key, &r, &s);
-            if (err != 0)
-                break;
-
             /* decode DSA header */
             err = DecodeECC_DSA_Sig(sig, siglen, r, s);
@@ -4073,4 +5210,17 @@
 
             err = wc_ecc_verify_hash_ex(r, s, hash, hashlen, res, key);
+
+        #ifndef WOLFSSL_ASYNC_CRYPT
+            /* done with R/S */
+            mp_clear(r);
+            mp_clear(s);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
+            XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+            r = NULL;
+            s = NULL;
+        #endif
+        #endif
+
             if (err < 0) {
                 break;
@@ -4081,14 +5231,4 @@
             key->state = ECC_STATE_VERIFY_RES;
             err = 0;
-
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* restore r/s */
-            r = key->r;
-            s = key->s;
-        #endif
-
-            /* done with R/S */
-            mp_clear(r);
-            mp_clear(s);
             break;
 
@@ -4104,6 +5244,17 @@
 
     /* cleanup */
-    wc_ecc_free_rs(key, &r, &s);
+#ifdef WOLFSSL_ASYNC_CRYPT
+    wc_ecc_free_async(key);
+#endif
     key->state = ECC_STATE_NONE;
+
+#ifdef WOLFSSL_SMALL_STACK
+    if (err != WC_PENDING_E) {
+            XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
+            XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+            r = NULL;
+            s = NULL;
+    }
+#endif
 
     return err;
@@ -4126,15 +5277,29 @@
 {
    int           err;
-#ifndef WOLFSSL_ATECC508A
+   word32        keySz;
+#ifdef WOLFSSL_ATECC508A
+   byte sigRS[ATECC_KEY_SIZE*2];
+#elif !defined(WOLFSSL_SP_MATH)
    int          did_init = 0;
    ecc_point    *mG = NULL, *mQ = NULL;
-   mp_int        v;
-   mp_int        w;
-   mp_int        u1;
-   mp_int        u2;
-   mp_int        e;
-   DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT)
-#else
-   byte sigRS[ATECC_KEY_SIZE*2];
+#ifdef WOLFSSL_SMALL_STACK
+   mp_int*       v = NULL;
+   mp_int*       w = NULL;
+   mp_int*       u1 = NULL;
+   mp_int*       u2 = NULL;
+#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)
+   mp_int*       e_lcl = NULL;
+#endif
+#else /* WOLFSSL_SMALL_STACK */
+   mp_int        v[1];
+   mp_int        w[1];
+   mp_int        u1[1];
+   mp_int        u2[1];
+#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)
+   mp_int        e_lcl[1];
+#endif
+#endif /* WOLFSSL_SMALL_STACK */
+   mp_int*       e;
+   DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
 #endif
 
@@ -4149,4 +5314,6 @@
       return ECC_BAD_ARG_E;
    }
+
+   keySz = key->dp->size;
 
 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
@@ -4172,16 +5339,16 @@
         return err;
     }
-    err = mp_to_unsigned_bin(s, &sigRS[ATECC_KEY_SIZE]);
+    err = mp_to_unsigned_bin(s, &sigRS[keySz]);
     if (err != MP_OKAY) {
         return err;
     }
 
-    err = atcatls_verify(hash, sigRS, key->pubkey, (bool*)res);
-    if (err != ATCA_SUCCESS) {
-       return BAD_COND_E;
-   }
+    err = atmel_ecc_verify(hash, sigRS, key->pubkey_raw, res);
+    if (err != 0) {
+       return err;
+   }
+    (void)hashlen;
 
 #else
-
   /* checking if private key with no public part */
   if (key->type == ECC_PRIVATEKEY_ONLY) {
@@ -4194,4 +5361,12 @@
   }
 
+#ifdef WOLFSSL_SP_MATH
+  if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
+      return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y,
+                                           key->pubkey.z, r, s, res, key->heap);
+  }
+  else
+      return WC_KEY_SIZE_E;
+#else
 #ifdef WOLFSSL_HAVE_SP_ECC
 #ifndef WOLFSSL_SP_NO_256
@@ -4205,8 +5380,28 @@
                                      key->pubkey.z,r, s, res, key->heap);
     }
-#endif
-#endif
-
-   err = mp_init(&e);
+#endif /* WOLFSSL_SP_NO_256 */
+#endif /* WOLFSSL_HAVE_SP_ECC */
+
+   ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V)
+   err = wc_ecc_alloc_mpint(key, &key->e);
+   if (err != 0) {
+      FREE_CURVE_SPECS();
+      return err;
+   }
+   e = key->e;
+#else
+#ifdef WOLFSSL_SMALL_STACK
+   e_lcl = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+   if (e_lcl == NULL) {
+       FREE_CURVE_SPECS();
+       return MEMORY_E;
+   }
+#endif
+   e = e_lcl;
+#endif
+
+   err = mp_init(e);
    if (err != MP_OKAY)
       return MEMORY_E;
@@ -4232,9 +5427,9 @@
        if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits)
            hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE;
-       err = mp_read_unsigned_bin(&e, hash, hashlen);
+       err = mp_read_unsigned_bin(e, hash, hashlen);
 
        /* may still need bit truncation too */
        if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * hashlen) > orderBits)
-           mp_rshb(&e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
+           mp_rshb(e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
    }
 
@@ -4242,30 +5437,64 @@
 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
-   #ifdef HAVE_CAVIUM
-      /* TODO: Not implemented */
-   #elif defined(HAVE_INTEL_QA)
-      err = wc_mp_to_bigint(&e, &e.raw);
+   #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)
+   #ifdef HAVE_CAVIUM_V
+      if (NitroxEccIsCurveSupported(key))
+   #endif
+      {
+          err = wc_mp_to_bigint_sz(e, &e->raw, keySz);
       if (err == MP_OKAY)
-          err = wc_mp_to_bigint(key->pubkey.x, &key->pubkey.x->raw);
+              err = wc_mp_to_bigint_sz(key->pubkey.x, &key->pubkey.x->raw, keySz);
       if (err == MP_OKAY)
-          err = wc_mp_to_bigint(key->pubkey.y, &key->pubkey.y->raw);
+              err = wc_mp_to_bigint_sz(key->pubkey.y, &key->pubkey.y->raw, keySz);
       if (err == MP_OKAY)
-          err = IntelQaEcdsaVerify(&key->asyncDev, &e.raw, &key->pubkey.x->raw,
+          #ifdef HAVE_CAVIUM_V
+              err = NitroxEcdsaVerify(key, &e->raw, &key->pubkey.x->raw,
+                    &key->pubkey.y->raw, &r->raw, &s->raw,
+                    &curve->prime->raw, &curve->order->raw, res);
+          #else
+              err = IntelQaEcdsaVerify(&key->asyncDev, &e->raw, &key->pubkey.x->raw,
                 &key->pubkey.y->raw, &r->raw, &s->raw, &curve->Af->raw,
                 &curve->Bf->raw, &curve->prime->raw, &curve->order->raw,
                 &curve->Gx->raw, &curve->Gy->raw, res);
-
-      mp_clear(&e);
-
+          #endif
+
+      #ifndef HAVE_CAVIUM_V
+          mp_clear(e);
+      #endif
       wc_ecc_curve_free(curve);
+          FREE_CURVE_SPECS();
 
       return err;
-   #endif
+      }
+   #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */
    }
 #endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef WOLFSSL_SMALL_STACK
+   if (err == MP_OKAY) {
+       v = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+       if (v == NULL)
+           err = MEMORY_E;
+   }
+   if (err == MP_OKAY) {
+       w = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+       if (w == NULL)
+           err = MEMORY_E;
+   }
+   if (err == MP_OKAY) {
+       u1 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+       if (u1 == NULL)
+           err = MEMORY_E;
+   }
+   if (err == MP_OKAY) {
+       u2 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+       if (u2 == NULL)
+           err = MEMORY_E;
+   }
+#endif
 
    /* allocate ints */
    if (err == MP_OKAY) {
-       if ((err = mp_init_multi(&v, &w, &u1, &u2, NULL, NULL)) != MP_OKAY) {
+       if ((err = mp_init_multi(v, w, u1, u2, NULL, NULL)) != MP_OKAY) {
           err = MEMORY_E;
        }
@@ -4283,13 +5512,13 @@
    /*  w  = s^-1 mod n */
    if (err == MP_OKAY)
-       err = mp_invmod(s, curve->order, &w);
+       err = mp_invmod(s, curve->order, w);
 
    /* u1 = ew */
    if (err == MP_OKAY)
-       err = mp_mulmod(&e, &w, curve->order, &u1);
+       err = mp_mulmod(e, w, curve->order, u1);
 
    /* u2 = rw */
    if (err == MP_OKAY)
-       err = mp_mulmod(r, &w, curve->order, &u2);
+       err = mp_mulmod(r, w, curve->order, u2);
 
    /* find mG and mQ */
@@ -4311,21 +5540,21 @@
    /* use PKHA to compute u1*mG + u2*mQ */
    if (err == MP_OKAY)
-       err = wc_ecc_mulmod_ex(&u1, mG, mG, curve->Af, curve->prime, 0, key->heap);
-   if (err == MP_OKAY)
-       err = wc_ecc_mulmod_ex(&u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap);
+       err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, key->heap);
+   if (err == MP_OKAY)
+       err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap);
    if (err == MP_OKAY)
        err = wc_ecc_point_add(mG, mQ, mG, curve->prime);
-#else /* FREESCALE_LTC_ECC */
+#else
 #ifndef ECC_SHAMIR
     {
-        mp_digit      mp;
+        mp_digit mp = 0;
 
         /* compute u1*mG + u2*mQ = mG */
         if (err == MP_OKAY) {
-            err = wc_ecc_mulmod_ex(&u1, mG, mG, curve->Af, curve->prime, 0,
+            err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0,
                                                                      key->heap);
         }
         if (err == MP_OKAY) {
-            err = wc_ecc_mulmod_ex(&u2, mQ, mQ, curve->Af, curve->prime, 0,
+            err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0,
                                                                      key->heap);
         }
@@ -4347,5 +5576,5 @@
        /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */
         if (err == MP_OKAY) {
-            err = ecc_mul2add(mG, &u1, mQ, &u2, mG, curve->Af, curve->prime,
+            err = ecc_mul2add(mG, u1, mQ, u2, mG, curve->Af, curve->prime,
                                                                     key->heap);
         }
@@ -4354,9 +5583,9 @@
    /* v = X_x1 mod n */
    if (err == MP_OKAY)
-       err = mp_mod(mG->x, curve->order, &v);
+       err = mp_mod(mG->x, curve->order, v);
 
    /* does v == r */
    if (err == MP_OKAY) {
-       if (mp_cmp(&v, r) == MP_EQ)
+       if (mp_cmp(v, r) == MP_EQ)
            *res = 1;
    }
@@ -4366,16 +5595,30 @@
    wc_ecc_del_point_h(mQ, key->heap);
 
-   mp_clear(&e);
+   mp_clear(e);
    if (did_init) {
-       mp_clear(&v);
-       mp_clear(&w);
-       mp_clear(&u1);
-       mp_clear(&u2);
-   }
+       mp_clear(v);
+       mp_clear(w);
+       mp_clear(u1);
+       mp_clear(u2);
+   }
+#ifdef WOLFSSL_SMALL_STACK
+   XFREE(u2, key->heap, DYNAMIC_TYPE_ECC);
+   XFREE(u1, key->heap, DYNAMIC_TYPE_ECC);
+   XFREE(w, key->heap, DYNAMIC_TYPE_ECC);
+   XFREE(v, key->heap, DYNAMIC_TYPE_ECC);
+#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)
+   XFREE(e_lcl, key->heap, DYNAMIC_TYPE_ECC);
+#endif
+#endif
 
    wc_ecc_curve_free(curve);
-
+   FREE_CURVE_SPECS();
+
+#endif /* WOLFSSL_SP_MATH */
 #endif /* WOLFSSL_ATECC508A */
 
+   (void)keySz;
+   (void)hashlen;
+
    return err;
 }
@@ -4383,5 +5626,4 @@
 
 #ifdef HAVE_ECC_KEY_IMPORT
-#ifndef WOLFSSL_ATECC508A
 /* import point from der */
 int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx,
@@ -4390,4 +5632,6 @@
     int err = 0;
     int compressed = 0;
+    int keysize;
+    byte pointType;
 
     if (in == NULL || point == NULL || (curve_idx < 0) ||
@@ -4414,10 +5658,12 @@
         return MEMORY_E;
 
-    /* check for 4, 2, or 3 */
-    if (in[0] != 0x04 && in[0] != 0x02 && in[0] != 0x03) {
+    /* check for point type (4, 2, or 3) */
+    pointType = in[0];
+    if (pointType != ECC_POINT_UNCOMP && pointType != ECC_POINT_COMP_EVEN &&
+                                         pointType != ECC_POINT_COMP_ODD) {
         err = ASN_PARSE_E;
     }
 
-    if (in[0] == 0x02 || in[0] == 0x03) {
+    if (pointType == ECC_POINT_COMP_EVEN || pointType == ECC_POINT_COMP_ODD) {
 #ifdef HAVE_COMP_KEY
         compressed = 1;
@@ -4427,13 +5673,23 @@
     }
 
+    /* adjust to skip first byte */
+    inLen -= 1;
+    in += 1;
+
+    /* calculate key size based on inLen / 2 */
+    keysize = inLen>>1;
+
     /* read data */
     if (err == MP_OKAY)
-        err = mp_read_unsigned_bin(point->x, (byte*)in+1, (inLen-1)>>1);
+        err = mp_read_unsigned_bin(point->x, (byte*)in, keysize);
 
 #ifdef HAVE_COMP_KEY
     if (err == MP_OKAY && compressed == 1) {   /* build y */
+#ifndef WOLFSSL_SP_MATH
         int did_init = 0;
         mp_int t1, t2;
-        DECLARE_CURVE_SPECS(3)
+        DECLARE_CURVE_SPECS(curve, 3);
+
+        ALLOC_CURVE_SPECS(3);
 
         if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY)
@@ -4470,6 +5726,6 @@
         /* adjust y */
         if (err == MP_OKAY) {
-            if ((mp_isodd(&t2) == MP_YES && in[0] == 0x03) ||
-                (mp_isodd(&t2) == MP_NO && in[0] == 0x02)) {
+            if ((mp_isodd(&t2) == MP_YES && pointType == ECC_POINT_COMP_ODD) ||
+                (mp_isodd(&t2) == MP_NO &&  pointType == ECC_POINT_COMP_EVEN)) {
                 err = mp_mod(&t2, curve->prime, point->y);
             }
@@ -4485,10 +5741,13 @@
 
         wc_ecc_curve_free(curve);
+        FREE_CURVE_SPECS();
+#else
+        sp_ecc_uncompress_256(point->x, pointType, point->y);
+#endif
     }
 #endif
 
     if (err == MP_OKAY && compressed == 0)
-        err = mp_read_unsigned_bin(point->y,
-                                   (byte*)in+1+((inLen-1)>>1), (inLen-1)>>1);
+        err = mp_read_unsigned_bin(point->y, (byte*)in + keysize, keysize);
     if (err == MP_OKAY)
         err = mp_set(point->z, 1);
@@ -4502,5 +5761,4 @@
     return err;
 }
-#endif /* !WOLFSSL_ATECC508A */
 #endif /* HAVE_ECC_KEY_IMPORT */
 
@@ -4512,5 +5770,4 @@
     int    ret = MP_OKAY;
     word32 numlen;
-#ifndef WOLFSSL_ATECC508A
 #ifdef WOLFSSL_SMALL_STACK
     byte*  buf;
@@ -4518,5 +5775,4 @@
     byte   buf[ECC_BUFSIZE];
 #endif
-#endif /* !WOLFSSL_ATECC508A */
 
     if ((curve_idx < 0) || (wc_ecc_is_valid_idx(curve_idx) == 0))
@@ -4540,12 +5796,6 @@
     }
 
-#ifdef WOLFSSL_ATECC508A
-   /* TODO: Implement equiv call to ATECC508A */
-   ret = BAD_COND_E;
-
-#else
-
-    /* store byte 0x04 */
-    out[0] = 0x04;
+    /* store byte point type */
+    out[0] = ECC_POINT_UNCOMP;
 
 #ifdef WOLFSSL_SMALL_STACK
@@ -4577,5 +5827,4 @@
     XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER);
 #endif
-#endif /* WOLFSSL_ATECC508A */
 
     return ret;
@@ -4588,5 +5837,4 @@
    int    ret = MP_OKAY;
    word32 numlen;
-#ifndef WOLFSSL_ATECC508A
 #ifdef WOLFSSL_SMALL_STACK
    byte*  buf;
@@ -4595,5 +5843,4 @@
 #endif
    word32 pubxlen, pubylen;
-#endif /* WOLFSSL_ATECC508A */
 
    /* return length needed only */
@@ -4620,10 +5867,4 @@
       return BUFFER_E;
    }
-
-#ifdef WOLFSSL_ATECC508A
-   /* TODO: Implement equiv call to ATECC508A */
-   ret = BAD_COND_E;
-
-#else
 
    /* verify public key length is less than key size */
@@ -4635,6 +5876,6 @@
    }
 
-   /* store byte 0x04 */
-   out[0] = 0x04;
+   /* store byte point type */
+   out[0] = ECC_POINT_UNCOMP;
 
 #ifdef WOLFSSL_SMALL_STACK
@@ -4664,5 +5905,4 @@
    XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER);
 #endif
-#endif /* WOLFSSL_ATECC508A */
 
    return ret;
@@ -4692,8 +5932,29 @@
 int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime)
 {
+#ifndef WOLFSSL_SP_MATH
    int err;
-   mp_int t1, t2;
-
-   if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK
+   mp_int* t1 = NULL;
+   mp_int* t2 = NULL;
+#else
+   mp_int  t1[1], t2[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+   t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+   if (t1 == NULL)
+       return MEMORY_E;
+   t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+   if (t2 == NULL) {
+       XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+       return MEMORY_E;
+   }
+#endif
+
+   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+   #ifdef WOLFSSL_SMALL_STACK
+      XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+   #endif
       return err;
    }
@@ -4701,17 +5962,17 @@
    /* compute y^2 */
    if (err == MP_OKAY)
-       err = mp_sqr(ecp->y, &t1);
+       err = mp_sqr(ecp->y, t1);
 
    /* compute x^3 */
    if (err == MP_OKAY)
-       err = mp_sqr(ecp->x, &t2);
-   if (err == MP_OKAY)
-       err = mp_mod(&t2, prime, &t2);
-   if (err == MP_OKAY)
-       err = mp_mul(ecp->x, &t2, &t2);
+       err = mp_sqr(ecp->x, t2);
+   if (err == MP_OKAY)
+       err = mp_mod(t2, prime, t2);
+   if (err == MP_OKAY)
+       err = mp_mul(ecp->x, t2, t2);
 
    /* compute y^2 - x^3 */
    if (err == MP_OKAY)
-       err = mp_sub(&t1, &t2, &t1);
+       err = mp_sub(t1, t2, t1);
 
    /* Determine if curve "a" should be used in calc */
@@ -4719,14 +5980,14 @@
    if (err == MP_OKAY) {
       /* Use a and prime to determine if a == 3 */
-      err = mp_set(&t2, 0);
+      err = mp_set(t2, 0);
       if (err == MP_OKAY)
-          err = mp_submod(prime, a, prime, &t2);
-   }
-   if (err == MP_OKAY && mp_cmp_d(&t2, 3) != MP_EQ) {
+          err = mp_submod(prime, a, prime, t2);
+   }
+   if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) {
       /* compute y^2 - x^3 + a*x */
       if (err == MP_OKAY)
-          err = mp_mulmod(&t2, ecp->x, prime, &t2);
+          err = mp_mulmod(t2, ecp->x, prime, t2);
       if (err == MP_OKAY)
-          err = mp_addmod(&t1, &t2, prime, &t1);
+          err = mp_addmod(t1, t2, prime, t1);
    }
    else
@@ -4738,24 +5999,24 @@
       /* compute y^2 - x^3 + 3x */
       if (err == MP_OKAY)
-          err = mp_add(&t1, ecp->x, &t1);
+          err = mp_add(t1, ecp->x, t1);
       if (err == MP_OKAY)
-          err = mp_add(&t1, ecp->x, &t1);
+          err = mp_add(t1, ecp->x, t1);
       if (err == MP_OKAY)
-          err = mp_add(&t1, ecp->x, &t1);
+          err = mp_add(t1, ecp->x, t1);
       if (err == MP_OKAY)
-          err = mp_mod(&t1, prime, &t1);
+          err = mp_mod(t1, prime, t1);
   }
 
    /* adjust range (0, prime) */
-   while (err == MP_OKAY && mp_isneg(&t1)) {
-      err = mp_add(&t1, prime, &t1);
-   }
-   while (err == MP_OKAY && mp_cmp(&t1, prime) != MP_LT) {
-      err = mp_sub(&t1, prime, &t1);
+   while (err == MP_OKAY && mp_isneg(t1)) {
+      err = mp_add(t1, prime, t1);
+   }
+   while (err == MP_OKAY && mp_cmp(t1, prime) != MP_LT) {
+      err = mp_sub(t1, prime, t1);
    }
 
    /* compare to b */
    if (err == MP_OKAY) {
-       if (mp_cmp(&t1, b) != MP_EQ) {
+       if (mp_cmp(t1, b) != MP_EQ) {
           err = MP_VAL;
        } else {
@@ -4764,11 +6025,22 @@
    }
 
-   mp_clear(&t1);
-   mp_clear(&t2);
+   mp_clear(t1);
+   mp_clear(t2);
+#ifdef WOLFSSL_SMALL_STACK
+   XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+   XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+#endif
 
    return err;
-}
-
-
+#else
+   (void)a;
+   (void)b;
+   (void)prime;
+
+   return sp_ecc_is_point_256(ecp->x, ecp->y);
+#endif
+}
+
+#ifndef WOLFSSL_SP_MATH
 /* validate privkey * generator == pubkey, 0 on success */
 static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime)
@@ -4777,8 +6049,10 @@
     ecc_point* base = NULL;
     ecc_point* res  = NULL;
-    DECLARE_CURVE_SPECS(2)
+    DECLARE_CURVE_SPECS(curve, 2);
 
     if (key == NULL)
         return BAD_FUNC_ARG;
+
+    ALLOC_CURVE_SPECS(2);
 
     res = wc_ecc_new_point_h(key->heap);
@@ -4831,7 +6105,9 @@
     wc_ecc_del_point_h(res, key->heap);
     wc_ecc_del_point_h(base, key->heap);
+    FREE_CURVE_SPECS();
 
     return err;
 }
+#endif
 
 #ifdef WOLFSSL_VALIDATE_ECC_IMPORT
@@ -4842,5 +6118,5 @@
     int    err;
 #ifndef WOLFSSL_ATECC508A
-    DECLARE_CURVE_SPECS(2)
+    DECLARE_CURVE_SPECS(curve, 2);
 #endif
 
@@ -4849,8 +6125,9 @@
 
 #ifdef WOLFSSL_ATECC508A
-    /* TODO: Implement equiv call to ATECC508A */
-    err = BAD_COND_E;
+    /* Hardware based private key, so this operation is not supported */
+    err = MP_OKAY; /* just report success */
 
 #else
+    ALLOC_CURVE_SPECS(2);
 
     /* load curve info */
@@ -4862,4 +6139,5 @@
 
     wc_ecc_curve_free(curve);
+    FREE_CURVE_SPECS();
 
 #endif /* WOLFSSL_ATECC508A */
@@ -4871,4 +6149,5 @@
 
 
+#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH)
 /* validate order * pubkey = point at infinity, 0 on success */
 static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a,
@@ -4894,7 +6173,14 @@
 #endif
 #endif
+#ifndef WOLFSSL_SP_MATH
             err = wc_ecc_mulmod_ex(order, pubkey, inf, a, prime, 1, key->heap);
         if (err == MP_OKAY && !wc_ecc_point_is_at_infinity(inf))
             err = ECC_INF_E;
+#else
+            (void)a;
+            (void)prime;
+
+            err = WC_KEY_SIZE_E;
+#endif
     }
 
@@ -4903,5 +6189,5 @@
     return err;
 }
-
+#endif
 #endif /* !WOLFSSL_ATECC508A */
 
@@ -4911,14 +6197,15 @@
 {
     int    err;
+#ifndef WOLFSSL_SP_MATH
 #ifndef WOLFSSL_ATECC508A
-    mp_int* b;
+    mp_int* b = NULL;
 #ifdef USE_ECC_B_PARAM
-    DECLARE_CURVE_SPECS(4)
+    DECLARE_CURVE_SPECS(curve, 4);
 #else
+#ifndef WOLFSSL_SMALL_STACK
     mp_int b_lcl;
-    DECLARE_CURVE_SPECS(3)
-    b = &b_lcl;
-    XMEMSET(b, 0, sizeof(mp_int));
-#endif
+#endif
+    DECLARE_CURVE_SPECS(curve, 3);
+#endif /* USE_ECC_B_PARAM */
 #endif /* WOLFSSL_ATECC508A */
 
@@ -4928,14 +6215,32 @@
 #ifdef WOLFSSL_ATECC508A
 
-    if (key->slot == ATECC_INVALID_SLOT)
-        return ECC_BAD_ARG_E;
-
-    err = 0; /* consider key check success on ECC508A */
+    err = 0; /* consider key check success on ATECC508A */
 
 #else
-
+    #ifdef USE_ECC_B_PARAM
+        ALLOC_CURVE_SPECS(4);
+    #else
+        ALLOC_CURVE_SPECS(3);
+        #ifndef WOLFSSL_SMALL_STACK
+            b = &b_lcl;
+        #else
+            b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+            if (b == NULL) {
+                FREE_CURVE_SPECS();
+                return MEMORY_E;
+            }
+        #endif
+        XMEMSET(b, 0, sizeof(mp_int));
+    #endif
+
+    /* SP 800-56Ar3, section 5.6.2.3.3, process step 1 */
     /* pubkey point cannot be at infinity */
-    if (wc_ecc_point_is_at_infinity(&key->pubkey))
+    if (wc_ecc_point_is_at_infinity(&key->pubkey)) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
+    #endif
+        FREE_CURVE_SPECS();
         return ECC_INF_E;
+    }
 
     /* load curve info */
@@ -4952,9 +6257,10 @@
         err = mp_init(b);
     if (err == MP_OKAY)
-        err = mp_read_radix(b, key->dp->Bf, 16);
+        err = mp_read_radix(b, key->dp->Bf, MP_RADIX_HEX);
 #else
     b = curve->Bf;
 #endif
 
+    /* SP 800-56Ar3, section 5.6.2.3.3, process step 2 */
     /* Qx must be in the range [0, p-1] */
     if (mp_cmp(key->pubkey.x, curve->prime) != MP_LT)
@@ -4965,8 +6271,10 @@
         err = ECC_OUT_OF_RANGE_E;
 
+    /* SP 800-56Ar3, section 5.6.2.3.3, process steps 3 */
     /* make sure point is actually on curve */
     if (err == MP_OKAY)
         err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime);
 
+    /* SP 800-56Ar3, section 5.6.2.3.3, process steps 4 */
     /* pubkey * order must be at infinity */
     if (err == MP_OKAY)
@@ -4974,4 +6282,5 @@
                 curve->order);
 
+    /* SP 800-56Ar3, section 5.6.2.1.4, method (b) for ECC */
     /* private * base generator must equal pubkey */
     if (err == MP_OKAY && key->type == ECC_PRIVATEKEY)
@@ -4982,7 +6291,24 @@
 #ifndef USE_ECC_B_PARAM
     mp_clear(b);
-#endif
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
+#endif
+#endif
+
+    FREE_CURVE_SPECS();
 
 #endif /* WOLFSSL_ATECC508A */
+#else
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+    /* pubkey point cannot be at infinity */
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
+        err = sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y, &key->k,
+                                                                     key->heap);
+    }
+    else
+        err = WC_KEY_SIZE_E;
+#endif
 
     return err;
@@ -4995,7 +6321,7 @@
 {
     int err = MP_OKAY;
-#ifndef WOLFSSL_ATECC508A
     int compressed = 0;
-#endif /* !WOLFSSL_ATECC508A */
+    int keysize = 0;
+    byte pointType;
 
     if (in == NULL || key == NULL)
@@ -5009,10 +6335,4 @@
     /* make sure required variables are reset */
     wc_ecc_reset(key);
-
-#ifdef WOLFSSL_ATECC508A
-    /* TODO: Implement equiv call to ATECC508A */
-    err = BAD_COND_E;
-
-#else
 
     /* init key */
@@ -5032,10 +6352,12 @@
         return MEMORY_E;
 
-    /* check for 4, 2, or 3 */
-    if (in[0] != 0x04 && in[0] != 0x02 && in[0] != 0x03) {
+    /* check for point type (4, 2, or 3) */
+    pointType = in[0];
+    if (pointType != ECC_POINT_UNCOMP && pointType != ECC_POINT_COMP_EVEN &&
+                                         pointType != ECC_POINT_COMP_ODD) {
         err = ASN_PARSE_E;
     }
 
-    if (in[0] == 0x02 || in[0] == 0x03) {
+    if (pointType == ECC_POINT_COMP_EVEN || pointType == ECC_POINT_COMP_ODD) {
     #ifdef HAVE_COMP_KEY
         compressed = 1;
@@ -5045,14 +6367,25 @@
     }
 
+    /* adjust to skip first byte */
+    inLen -= 1;
+    in += 1;
+
+#ifdef WOLFSSL_ATECC508A
+    /* For SECP256R1 only save raw public key for hardware */
+    if (curve_id == ECC_SECP256R1 && !compressed &&
+                                            inLen <= sizeof(key->pubkey_raw)) {
+        XMEMCPY(key->pubkey_raw, (byte*)in, inLen);
+    }
+#endif
+
     if (err == MP_OKAY) {
-        int keysize;
     #ifdef HAVE_COMP_KEY
         /* adjust inLen if compressed */
         if (compressed)
-            inLen = (inLen-1)*2 + 1;  /* used uncompressed len */
+            inLen = inLen*2 + 1;  /* used uncompressed len */
     #endif
 
         /* determine key size */
-        keysize = ((inLen-1)>>1);
+        keysize = (inLen>>1);
         err = wc_ecc_set_curve(key, keysize, curve_id);
         key->type = ECC_PUBLICKEY;
@@ -5061,12 +6394,14 @@
     /* read data */
     if (err == MP_OKAY)
-        err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in+1, (inLen-1)>>1);
+        err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in, keysize);
 
 #ifdef HAVE_COMP_KEY
     if (err == MP_OKAY && compressed == 1) {   /* build y */
+#ifndef WOLFSSL_SP_MATH
         mp_int t1, t2;
         int did_init = 0;
 
-        DECLARE_CURVE_SPECS(3)
+        DECLARE_CURVE_SPECS(curve, 3);
+        ALLOC_CURVE_SPECS(3);
 
         if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY)
@@ -5103,6 +6438,6 @@
         /* adjust y */
         if (err == MP_OKAY) {
-            if ((mp_isodd(&t2) == MP_YES && in[0] == 0x03) ||
-                (mp_isodd(&t2) == MP_NO && in[0] == 0x02)) {
+            if ((mp_isodd(&t2) == MP_YES && pointType == ECC_POINT_COMP_ODD) ||
+                (mp_isodd(&t2) == MP_NO &&  pointType == ECC_POINT_COMP_EVEN)) {
                 err = mp_mod(&t2, curve->prime, &t2);
             }
@@ -5120,10 +6455,13 @@
 
         wc_ecc_curve_free(curve);
+        FREE_CURVE_SPECS();
+#else
+        sp_ecc_uncompress_256(key->pubkey.x, pointType, key->pubkey.y);
+#endif
     }
 #endif /* HAVE_COMP_KEY */
 
     if (err == MP_OKAY && compressed == 0)
-        err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in+1+((inLen-1)>>1),
-                                                                (inLen-1)>>1);
+        err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in + keysize, keysize);
     if (err == MP_OKAY)
         err = mp_set(key->pubkey.z, 1);
@@ -5140,8 +6478,7 @@
         mp_clear(&key->k);
     }
-#endif /* WOLFSSL_ATECC508A */
 
     return err;
-}
+    }
 
 int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
@@ -5152,148 +6489,96 @@
 
 #ifdef HAVE_ECC_KEY_EXPORT
-/* export ecc private key only raw, outLen is in/out size
+
+/* export ecc key to component form, d is optional if only exporting public
+ * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR
+ * return MP_OKAY on success */
+int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen,
+                 byte* qy, word32* qyLen, byte* d, word32* dLen, int encType)
+{
+    int err = 0;
+    word32 keySz;
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (wc_ecc_is_valid_idx(key->idx) == 0) {
+        return ECC_BAD_ARG_E;
+    }
+    keySz = key->dp->size;
+
+    /* private key, d */
+    if (d != NULL) {
+        if (dLen == NULL ||
+            (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY))
+            return BAD_FUNC_ARG;
+
+    #ifdef WOLFSSL_ATECC508A
+        /* Hardware cannot export private portion */
+        return NOT_COMPILED_IN;
+    #else
+        err = wc_export_int(&key->k, d, dLen, keySz, encType);
+        if (err != MP_OKAY)
+            return err;
+    #endif
+    }
+
+    /* public x component */
+    if (qx != NULL) {
+        if (qxLen == NULL || key->type == ECC_PRIVATEKEY_ONLY)
+            return BAD_FUNC_ARG;
+
+        err = wc_export_int(key->pubkey.x, qx, qxLen, keySz, encType);
+    if (err != MP_OKAY)
+        return err;
+    }
+
+    /* public y component */
+    if (qy != NULL) {
+        if (qyLen == NULL || key->type == ECC_PRIVATEKEY_ONLY)
+            return BAD_FUNC_ARG;
+
+        err = wc_export_int(key->pubkey.y, qy, qyLen, keySz, encType);
+    if (err != MP_OKAY)
+        return err;
+    }
+
+    return err;
+}
+
+
+/* export ecc private key only raw, outLen is in/out size as unsigned bin
    return MP_OKAY on success */
 int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen)
 {
-    word32 numlen;
-
-    if (key == NULL || out == NULL || outLen == NULL) {
+    if (out == NULL || outLen == NULL) {
         return BAD_FUNC_ARG;
-    }
-
-    if (wc_ecc_is_valid_idx(key->idx) == 0) {
-        return ECC_BAD_ARG_E;
-    }
-    numlen = key->dp->size;
-
-    if (*outLen < numlen) {
-        *outLen = numlen;
-        return BUFFER_E;
-    }
-    *outLen = numlen;
-    XMEMSET(out, 0, *outLen);
-
-#ifdef WOLFSSL_ATECC508A
-   /* TODO: Implement equiv call to ATECC508A */
-   return BAD_COND_E;
-
-#else
-
-    return mp_to_unsigned_bin(&key->k, out + (numlen -
-                                           mp_unsigned_bin_size(&key->k)));
-#endif /* WOLFSSL_ATECC508A */
-}
-
-
-/* export ecc key to component form, d is optional if only exporting public
- * return MP_OKAY on success */
-static int wc_ecc_export_raw(ecc_key* key, byte* qx, word32* qxLen,
-                             byte* qy, word32* qyLen, byte* d, word32* dLen)
-{
-    int  err;
-    byte exportPriv = 0;
-    word32 numLen;
-
-    if (key == NULL || qx == NULL || qxLen == NULL || qy == NULL ||
-        qyLen == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (key->type == ECC_PRIVATEKEY_ONLY) {
-        return ECC_PRIVATEONLY_E;
-    }
-
-    if (wc_ecc_is_valid_idx(key->idx) == 0) {
-        return ECC_BAD_ARG_E;
-    }
-    numLen = key->dp->size;
-
-    if (d != NULL) {
-        if (dLen == NULL || key->type != ECC_PRIVATEKEY)
-            return BAD_FUNC_ARG;
-        exportPriv = 1;
-    }
-
-    /* check public buffer sizes */
-    if ((*qxLen < numLen) || (*qyLen < numLen)) {
-        *qxLen = numLen;
-        *qyLen = numLen;
-        return BUFFER_E;
-    }
-
-    *qxLen = numLen;
-    *qyLen = numLen;
-
-    XMEMSET(qx, 0, *qxLen);
-    XMEMSET(qy, 0, *qyLen);
-
-    /* private d component */
-    if (exportPriv == 1) {
-
-        /* check private buffer size */
-        if (*dLen < numLen) {
-            *dLen = numLen;
-            return BUFFER_E;
-        }
-
-        *dLen = numLen;
-        XMEMSET(d, 0, *dLen);
-
-    #ifdef WOLFSSL_ATECC508A
-       /* TODO: Implement equiv call to ATECC508A */
-       return BAD_COND_E;
-
-    #else
-
-        /* private key, d */
-        err = mp_to_unsigned_bin(&key->k, d +
-                            (numLen - mp_unsigned_bin_size(&key->k)));
-        if (err != MP_OKAY)
-            return err;
-    #endif /* WOLFSSL_ATECC508A */
-    }
-
-#ifdef WOLFSSL_ATECC508A
-    /* TODO: Implement equiv call to ATECC508A */
-    return BAD_COND_E;
-
-#else
-
-    /* public x component */
-    err = mp_to_unsigned_bin(key->pubkey.x, qx +
-                            (numLen - mp_unsigned_bin_size(key->pubkey.x)));
-    if (err != MP_OKAY)
-        return err;
-
-    /* public y component */
-    err = mp_to_unsigned_bin(key->pubkey.y, qy +
-                            (numLen - mp_unsigned_bin_size(key->pubkey.y)));
-    if (err != MP_OKAY)
-        return err;
-
-    return 0;
-#endif /* WOLFSSL_ATECC508A */
-}
-
-
-/* export public key to raw elements including public (Qx,Qy)
+}
+
+    return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen,
+        WC_TYPE_UNSIGNED_BIN);
+}
+
+/* export public key to raw elements including public (Qx,Qy) as unsigned bin
  * return MP_OKAY on success, negative on error */
 int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen,
                              byte* qy, word32* qyLen)
 {
-    return wc_ecc_export_raw(key, qx, qxLen, qy, qyLen, NULL, NULL);
-}
-
-
-/* export ecc key to raw elements including public (Qx,Qy) and private (d)
+    if (qx == NULL || qxLen == NULL || qy == NULL || qyLen == NULL) {
+        return BAD_FUNC_ARG;
+}
+
+    return wc_ecc_export_ex(key, qx, qxLen, qy, qyLen, NULL, NULL,
+        WC_TYPE_UNSIGNED_BIN);
+}
+
+/* export ecc key to raw elements including public (Qx,Qy) and
+ *   private (d) as unsigned bin
  * return MP_OKAY on success, negative on error */
 int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen,
                               byte* qy, word32* qyLen, byte* d, word32* dLen)
 {
-    /* sanitize d and dLen, other args are checked later */
-    if (d == NULL || dLen == NULL)
-        return BAD_FUNC_ARG;
-
-    return wc_ecc_export_raw(key, qx, qxLen, qy, qyLen, d, dLen);
+    return wc_ecc_export_ex(key, qx, qxLen, qy, qyLen, d, dLen,
+        WC_TYPE_UNSIGNED_BIN);
 }
 
@@ -5307,14 +6592,17 @@
 {
     int ret;
+    word32 idx = 0;
+
+    if (key == NULL || priv == NULL)
+        return BAD_FUNC_ARG;
 
     /* public optional, NULL if only importing private */
     if (pub != NULL) {
         ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id);
+        if (ret < 0)
+            ret = wc_EccPublicKeyDecode(pub, &idx, key, pubSz);
         key->type = ECC_PRIVATEKEY;
     }
     else {
-        if (key == NULL || priv == NULL)
-            return BAD_FUNC_ARG;
-
         /* make sure required variables are reset */
         wc_ecc_reset(key);
@@ -5328,12 +6616,19 @@
         return ret;
 
-
 #ifdef WOLFSSL_ATECC508A
-    /* TODO: Implement equiv call to ATECC508A */
-    return BAD_COND_E;
+    /* Hardware does not support loading private keys */
+    return NOT_COMPILED_IN;
 
 #else
 
     ret = mp_read_unsigned_bin(&key->k, priv, privSz);
+#ifdef HAVE_WOLF_BIGINT
+    if (ret == 0 &&
+                  wc_bigint_from_unsigned_bin(&key->k.raw, priv, privSz) != 0) {
+        mp_clear(&key->k);
+        ret = ASN_GETINT_E;
+    }
+#endif /* HAVE_WOLF_BIGINT */
+
 
 #endif /* WOLFSSL_ATECC508A */
@@ -5369,33 +6664,125 @@
 {
     int err;
-    mp_int rtmp;
-    mp_int stmp;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* rtmp = NULL;
+    mp_int* stmp = NULL;
+#else
+    mp_int  rtmp[1];
+    mp_int  stmp[1];
+#endif
 
     if (r == NULL || s == NULL || out == NULL || outlen == NULL)
         return ECC_BAD_ARG_E;
 
-    err = mp_init_multi(&rtmp, &stmp, NULL, NULL, NULL, NULL);
-    if (err != MP_OKAY)
+#ifdef WOLFSSL_SMALL_STACK
+    rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (rtmp == NULL)
+        return MEMORY_E;
+    stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (stmp == NULL) {
+        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+#endif
+
+    err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL);
+    if (err != MP_OKAY) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
+        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+    #endif
         return err;
-
-    err = mp_read_radix(&rtmp, r, 16);
+    }
+
+    err = mp_read_radix(rtmp, r, MP_RADIX_HEX);
     if (err == MP_OKAY)
-        err = mp_read_radix(&stmp, s, 16);
+        err = mp_read_radix(stmp, s, MP_RADIX_HEX);
 
     /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */
     if (err == MP_OKAY)
-        err = StoreECC_DSA_Sig(out, outlen, &rtmp, &stmp);
+        err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp);
 
     if (err == MP_OKAY) {
-        if (mp_iszero(&rtmp) == MP_YES || mp_iszero(&stmp) == MP_YES)
+        if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES)
             err = MP_ZERO_E;
     }
 
-    mp_clear(&rtmp);
-    mp_clear(&stmp);
+    mp_clear(rtmp);
+    mp_clear(stmp);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
+    XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+#endif
 
     return err;
 }
 
+/**
+   Convert ECC R,S raw unsigned bin to signature
+   r       R component of signature
+   rSz     R size
+   s       S component of signature
+   sSz     S size
+   out     DER-encoded ECDSA signature
+   outlen  [in/out] output buffer size, output signature size
+   return  MP_OKAY on success
+*/
+int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz,
+    byte* out, word32* outlen)
+{
+    int err;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* rtmp = NULL;
+    mp_int* stmp = NULL;
+#else
+    mp_int  rtmp[1];
+    mp_int  stmp[1];
+#endif
+
+    if (r == NULL || s == NULL || out == NULL || outlen == NULL)
+        return ECC_BAD_ARG_E;
+
+#ifdef WOLFSSL_SMALL_STACK
+    rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (rtmp == NULL)
+        return MEMORY_E;
+    stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (stmp == NULL) {
+        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+#endif
+
+    err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL);
+    if (err != MP_OKAY) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
+        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+    #endif
+    return err;
+}
+
+    err = mp_read_unsigned_bin(rtmp, r, rSz);
+    if (err == MP_OKAY)
+        err = mp_read_unsigned_bin(stmp, s, sSz);
+
+    /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */
+    if (err == MP_OKAY)
+        err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp);
+
+    if (err == MP_OKAY) {
+        if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES)
+            err = MP_ZERO_E;
+    }
+
+    mp_clear(rtmp);
+    mp_clear(stmp);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
+    XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+#endif
+
+    return err;
+}
 
 /**
@@ -5414,15 +6801,31 @@
     int err;
     word32 x = 0;
-    mp_int rtmp;
-    mp_int stmp;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* rtmp = NULL;
+    mp_int* stmp = NULL;
+#else
+    mp_int  rtmp[1];
+    mp_int  stmp[1];
+#endif
 
     if (sig == NULL || r == NULL || rLen == NULL || s == NULL || sLen == NULL)
         return ECC_BAD_ARG_E;
 
-    err = DecodeECC_DSA_Sig(sig, sigLen, &rtmp, &stmp);
+#ifdef WOLFSSL_SMALL_STACK
+    rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (rtmp == NULL)
+        return MEMORY_E;
+    stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (stmp == NULL) {
+        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+#endif
+
+    err = DecodeECC_DSA_Sig(sig, sigLen, rtmp, stmp);
 
     /* extract r */
     if (err == MP_OKAY) {
-        x = mp_unsigned_bin_size(&rtmp);
+        x = mp_unsigned_bin_size(rtmp);
         if (*rLen < x)
             err = BUFFER_E;
@@ -5430,5 +6833,5 @@
         if (err == MP_OKAY) {
             *rLen = x;
-            err = mp_to_unsigned_bin(&rtmp, r);
+            err = mp_to_unsigned_bin(rtmp, r);
         }
     }
@@ -5436,5 +6839,5 @@
     /* extract s */
     if (err == MP_OKAY) {
-        x = mp_unsigned_bin_size(&stmp);
+        x = mp_unsigned_bin_size(stmp);
         if (*sLen < x)
             err = BUFFER_E;
@@ -5442,10 +6845,14 @@
         if (err == MP_OKAY) {
             *sLen = x;
-            err = mp_to_unsigned_bin(&stmp, s);
+            err = mp_to_unsigned_bin(stmp, s);
         }
     }
 
-    mp_clear(&rtmp);
-    mp_clear(&stmp);
+    mp_clear(rtmp);
+    mp_clear(stmp);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
+    XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+#endif
 
     return err;
@@ -5455,5 +6862,5 @@
 #ifdef HAVE_ECC_KEY_IMPORT
 static int wc_ecc_import_raw_private(ecc_key* key, const char* qx,
-          const char* qy, const char* d, int curve_id)
+          const char* qy, const char* d, int curve_id, int encType)
 {
     int err = MP_OKAY;
@@ -5472,10 +6879,4 @@
         return err;
     }
-
-#ifdef WOLFSSL_ATECC508A
-    /* TODO: Implement equiv call to ATECC508A */
-    err = BAD_COND_E;
-
-#else
 
     /* init key */
@@ -5496,19 +6897,52 @@
 
     /* read Qx */
-    if (err == MP_OKAY)
-        err = mp_read_radix(key->pubkey.x, qx, 16);
+    if (err == MP_OKAY) {
+        if (encType == WC_TYPE_HEX_STR)
+            err = mp_read_radix(key->pubkey.x, qx, MP_RADIX_HEX);
+        else
+            err = mp_read_unsigned_bin(key->pubkey.x, (const byte*)qx,
+                key->dp->size);
+    }
 
     /* read Qy */
-    if (err == MP_OKAY)
-        err = mp_read_radix(key->pubkey.y, qy, 16);
+    if (err == MP_OKAY) {
+        if (encType == WC_TYPE_HEX_STR)
+            err = mp_read_radix(key->pubkey.y, qy, MP_RADIX_HEX);
+        else
+            err = mp_read_unsigned_bin(key->pubkey.y, (const byte*)qy,
+                key->dp->size);
+
+    }
 
     if (err == MP_OKAY)
         err = mp_set(key->pubkey.z, 1);
+
+#ifdef WOLFSSL_ATECC508A
+    /* For SECP256R1 only save raw public key for hardware */
+    if (err == MP_OKAY && curve_id == ECC_SECP256R1) {
+        word32 keySz = key->dp->size;
+        err = wc_export_int(key->pubkey.x, key->pubkey_raw,
+            &keySz, keySz, WC_TYPE_UNSIGNED_BIN);
+        if (err == MP_OKAY)
+            err = wc_export_int(key->pubkey.y, &key->pubkey_raw[keySz],
+                &keySz, keySz, WC_TYPE_UNSIGNED_BIN);
+    }
+#endif
 
     /* import private key */
     if (err == MP_OKAY) {
         if (d != NULL) {
+        #ifdef WOLFSSL_ATECC508A
+            /* Hardware doesn't support loading private key */
+            err = NOT_COMPILED_IN;
+        #else
             key->type = ECC_PRIVATEKEY;
-            err = mp_read_radix(&key->k, d, 16);
+
+            if (encType == WC_TYPE_HEX_STR)
+                err = mp_read_radix(&key->k, d, MP_RADIX_HEX);
+            else
+                err = mp_read_unsigned_bin(&key->k, (const byte*)d,
+                    key->dp->size);
+        #endif /* WOLFSSL_ATECC508A */
         } else {
             key->type = ECC_PUBLICKEY;
@@ -5527,5 +6961,4 @@
         mp_clear(&key->k);
     }
-#endif /* WOLFSSL_ATECC508A */
 
     return err;
@@ -5545,6 +6978,15 @@
                    const char* d, int curve_id)
 {
-    return wc_ecc_import_raw_private(key, qx, qy, d, curve_id);
-
+    return wc_ecc_import_raw_private(key, qx, qy, d, curve_id,
+        WC_TYPE_HEX_STR);
+
+}
+
+/* Import x, y and optional private (d) as unsigned binary */
+int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy,
+                   byte* d, int curve_id)
+{
+    return wc_ecc_import_raw_private(key, (const char*)qx, (const char*)qy,
+        (const char*)d, curve_id, WC_TYPE_UNSIGNED_BIN);
 }
 
@@ -5581,5 +7023,6 @@
         err = ASN_PARSE_E;
     } else {
-        return wc_ecc_import_raw_private(key, qx, qy, d, ecc_sets[x].id);
+        return wc_ecc_import_raw_private(key, qx, qy, d, ecc_sets[x].id,
+            WC_TYPE_HEX_STR);
     }
 
@@ -5596,4 +7039,8 @@
 }
 
+int wc_ecc_sig_size_calc(int sz)
+{
+    return (sz * 2) + SIG_HEADER_SZ + ECC_MAX_PAD_SZ;
+}
 
 /* worst case estimate, check actual return from wc_ecc_sign_hash for actual
@@ -5605,5 +7052,5 @@
         return sz;
 
-    return (sz * 2) + SIG_HEADER_SZ + ECC_MAX_PAD_SZ;
+    return wc_ecc_sig_size_calc(sz);
 }
 
@@ -5633,4 +7080,6 @@
 #endif
 
+
+#ifndef WOLFSSL_SP_MATH
 
 /** Our FP cache */
@@ -6182,4 +7631,5 @@
 };
 
+
 /* find a hole and free as required, return -1 if no hole found */
 static int find_hole(void)
@@ -6271,5 +7721,7 @@
    return MP_OKAY;
 }
-
+#endif
+
+#ifndef WOLFSSL_SP_MATH
 /* build the LUT by spacing the bits of the input by #modulus/FP_LUT bits apart
  *
@@ -6441,5 +7893,6 @@
       if (y == 66) --x;
 
-      if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
+      if ((err = mp_read_radix(&order, ecc_sets[x].order,
+                                                MP_RADIX_HEX)) != MP_OKAY) {
          goto done;
       }
@@ -6492,5 +7945,5 @@
 
       while ((unsigned)x < y) {
-         z = kb[x]; kb[x] = kb[y]; kb[y] = z;
+         z = kb[x]; kb[x] = kb[y]; kb[y] = (byte)z;
          ++x; --y;
       }
@@ -6559,6 +8012,8 @@
    return err;
 }
+#endif
 
 #ifdef ECC_SHAMIR
+#ifndef WOLFSSL_SP_MATH
 /* perform a fixed point ECC mulmod */
 static int accel_fp_mul2add(int idx1, int idx2,
@@ -6592,5 +8047,6 @@
       if (y == 66) --x;
 
-      if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
+      if ((err = mp_read_radix(&order, ecc_sets[x].order,
+                                                MP_RADIX_HEX)) != MP_OKAY) {
          goto done;
       }
@@ -6623,5 +8079,6 @@
       if (y == 66) --x;
 
-      if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
+      if ((err = mp_read_radix(&order, ecc_sets[x].order,
+                                                MP_RADIX_HEX)) != MP_OKAY) {
          goto done;
       }
@@ -6678,5 +8135,5 @@
    mp_clear(&tka);
    while ((unsigned)x < y) {
-      z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = z;
+      z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = (byte)z;
       ++x; --y;
    }
@@ -6699,5 +8156,5 @@
 
       while ((unsigned)x < y) {
-         z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z;
+         z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = (byte)z;
          ++x; --y;
       }
@@ -6919,4 +8376,5 @@
     return err;
 }
+#endif
 #endif /* ECC_SHAMIR */
 
@@ -6934,8 +8392,13 @@
     mp_int* modulus, int map, void* heap)
 {
+#ifndef WOLFSSL_SP_MATH
    int   idx, err = MP_OKAY;
    mp_digit mp;
    mp_int   mu;
    int      mpSetup = 0;
+
+   if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL) {
+       return ECC_BAD_ARG_E;
+   }
 
    if (mp_init(&mu) != MP_OKAY)
@@ -7006,6 +8469,14 @@
 
     return err;
-}
-
+#else
+    if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL) {
+        return ECC_BAD_ARG_E;
+    }
+
+    return sp_ecc_mulmod_256(k, G, R, map, heap);
+#endif
+}
+
+#ifndef WOLFSSL_SP_MATH
 /* helper function for freeing the cache ...
    must be called with the cache mutex locked */
@@ -7027,8 +8498,10 @@
    }
 }
+#endif
 
 /** Free the Fixed Point cache */
 void wc_ecc_fp_free(void)
 {
+#ifndef WOLFSSL_SP_MATH
 #ifndef HAVE_THREAD_LS
    if (initMutex == 0) {
@@ -7048,4 +8521,5 @@
    }
 #endif /* HAVE_THREAD_LS */
+#endif
 }
 
@@ -7407,12 +8881,19 @@
                {
                    Aes aes;
+                   ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
+                   if (ret == 0) {
                    ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
                                                                 AES_ENCRYPTION);
-                   if (ret != 0)
-                       break;
+                       if (ret == 0) {
                    ret = wc_AesCbcEncrypt(&aes, out, msg, msgSz);
                 #if defined(WOLFSSL_ASYNC_CRYPT)
-                   ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE);
+                           ret = wc_AsyncWait(ret, &aes.asyncDev,
+                                              WC_ASYNC_FLAG_NONE);
                 #endif
+               }
+                       wc_AesFree(&aes);
+                   }
+                   if (ret != 0)
+                      break;
                }
                break;
@@ -7637,4 +9118,5 @@
 #ifndef WOLFSSL_ATECC508A
 
+#ifndef WOLFSSL_SP_MATH
 int do_mp_jacobi(mp_int* a, mp_int* n, int* c);
 
@@ -7760,4 +9242,21 @@
 int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret)
 {
+#ifdef SQRTMOD_USE_MOD_EXP
+  int res;
+
+  mp_int e;
+
+  res = mp_init(&e);
+  if (res == MP_OKAY)
+      res = mp_add_d(prime, 1, &e);
+  if (res == MP_OKAY)
+      res = mp_div_2d(&e, 2, &e, NULL);
+  if (res == MP_OKAY)
+      res = mp_exptmod(n, &e, prime, ret);
+
+  mp_clear(&e);
+
+  return res;
+#else
   int res, legendre, done = 0;
   mp_int t1, C, Q, S, Z, M, T, R, two;
@@ -7938,5 +9437,7 @@
 
   return res;
-}
+#endif
+}
+#endif
 #endif /* !WOLFSSL_ATECC508A */
 
@@ -7961,12 +9462,6 @@
    }
 
-#ifdef WOLFSSL_ATECC508A
-   /* TODO: Implement equiv call to ATECC508A */
-   ret = BAD_COND_E;
-
-#else
-
    /* store first byte */
-   out[0] = mp_isodd(key->pubkey.y) == MP_YES ? 0x03 : 0x02;
+   out[0] = mp_isodd(key->pubkey.y) == MP_YES ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;
 
    /* pad and store x */
@@ -7975,6 +9470,4 @@
                        out+1 + (numlen - mp_unsigned_bin_size(key->pubkey.x)));
    *outLen = 1 + numlen;
-
-#endif /* WOLFSSL_ATECC508A */
 
    return ret;
@@ -8045,5 +9538,5 @@
 #ifdef HAVE_X963_KDF
 
-static INLINE void IncrementX963KdfCounter(byte* inOutCtr)
+static WC_INLINE void IncrementX963KdfCounter(byte* inOutCtr)
 {
     int i;
@@ -8110,16 +9603,10 @@
         ret = wc_HashUpdate(hash, type, secret, secretSz);
         if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
-#endif
-            return ret;
+            break;
         }
 
         ret = wc_HashUpdate(hash, type, counter, sizeof(counter));
         if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
-#endif
-            return ret;
+            break;
         }
 
@@ -8127,8 +9614,5 @@
             ret = wc_HashUpdate(hash, type, sinfo, sinfoSz);
             if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-                XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
-#endif
-                return ret;
+                break;
             }
         }
@@ -8136,8 +9620,5 @@
         ret = wc_HashFinal(hash, type, tmp);
         if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
-#endif
-            return ret;
+            break;
         }
 
@@ -8149,9 +9630,11 @@
     }
 
+    wc_HashFree(hash, type);
+
 #ifdef WOLFSSL_SMALL_STACK
      XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
 #endif
 
-    return 0;
+    return ret;
 }
 #endif /* HAVE_X963_KDF */
