Browse Source

Merge pull request #5926 from SparkiDev/openssl_ec_api_rework

EC OpenSSL compat: rework EC API
David Garske 1 year ago
parent
commit
934d8e274f
11 changed files with 5834 additions and 3529 deletions
  1. 4235 2751
      src/pk.c
  2. 141 42
      src/ssl.c
  3. 1 1
      src/x509.c
  4. 1413 566
      tests/api.c
  5. 22 150
      wolfcrypt/src/asn.c
  6. 1 3
      wolfssl/internal.h
  7. 12 10
      wolfssl/openssl/ec.h
  8. 3 1
      wolfssl/openssl/pem.h
  9. 5 0
      wolfssl/ssl.h
  10. 0 4
      wolfssl/wolfcrypt/asn.h
  11. 1 1
      wolfssl/wolfcrypt/asn_public.h

+ 4235 - 2751
src/pk.c

@@ -25,6 +25,11 @@
 
 #include <wolfssl/wolfcrypt/settings.h>
 
+ #include <wolfssl/internal.h>
+#ifndef WC_NO_RNG
+    #include <wolfssl/wolfcrypt/random.h>
+#endif
+
 #if !defined(WOLFSSL_PK_INCLUDED)
     #ifndef WOLFSSL_IGNORE_FILE_WARN
         #warning pk.c does not need to be compiled separately from ssl.c
@@ -38,8 +43,7 @@
 #if defined(OPENSSL_EXTRA) && !defined(NO_BIO) && defined(WOLFSSL_KEY_GEN) && \
     (!defined(HAVE_USER_RSA) || defined(HAVE_ECC) || \
      (!defined(NO_DSA) && !defined(HAVE_SELFTEST)))
-/* Forward declaration for wolfSSL_PEM_write_bio_RSA_PUBKEY,
- * wolfSSL_PEM_write_bio_DSA_PUBKEY and wolfSSL_PEM_write_bio_EC_PUBKEY.
+/* Forward declaration for wolfSSL_PEM_write_bio_DSA_PUBKEY.
  * Implementation in ssl.c.
  */
 static int pem_write_bio_pubkey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key);
@@ -49,8 +53,18 @@ static int pem_write_bio_pubkey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key);
  * COMMON FUNCTIONS
  ******************************************************************************/
 
+/* Calculate the number of bytes require to represent a length value in ASN.
+ *
+ * @param [in] l  Length value to use.
+ * @return  Number of bytes required to represent length value.
+ */
+#define ASN_LEN_SIZE(l)             \
+    (((l) < 128) ? 1 : (((l) < 256) ? 2 : 3))
+
 #if defined(OPENSSL_EXTRA)
 
+#ifndef NO_ASN
+
 #if (!defined(NO_FILESYSTEM) && (defined(OPENSSL_EXTRA) || \
      defined(OPENSSL_ALL))) || (!defined(NO_BIO) && defined(OPENSSL_EXTRA))
 /* Convert the PEM encoding in the buffer to DER.
@@ -276,7 +290,9 @@ static int der_write_to_bio_as_pem(const unsigned char* der, int derSz,
 #endif
 
 #if (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && \
-     !defined(HAVE_USER_RSA)) || (!defined(NO_DH) && defined(WOLFSSL_DH_EXTRA))
+     !defined(HAVE_USER_RSA)) || \
+     (!defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)) || \
+     (defined(HAVE_ECC) && defined(WOLFSSL_KEY_GEN))
 #if !defined(NO_FILESYSTEM)
 /* Write the DER data as PEM into file pointer.
  *
@@ -310,9 +326,93 @@ static int der_write_to_file_as_pem(const unsigned char* der, int derSz,
 #endif
 #endif
 
+#if defined(WOLFSSL_KEY_GEN) && \
+    (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)) && \
+    ((!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || defined(HAVE_ECC))
+static int der_to_enc_pem_alloc(unsigned char* der, int derSz,
+    const EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz, int type,
+    void* heap, byte** out, int* outSz)
+{
+    int ret = 1;
+    byte* tmp = NULL;
+    byte* cipherInfo = NULL;
+    int pemSz = 0;
+
+    /* Macro doesn't always use it. */
+    (void)heap;
+
+    /* Encrypt DER buffer if required. */
+    if ((ret == 1) && (passwd != NULL) && (passwdSz > 0) && (cipher != NULL)) {
+        int blockSz = wolfSSL_EVP_CIPHER_block_size(cipher);
+        byte *tmpBuf;
+
+        /* Add space for padding. */
+        tmpBuf = (byte*)XREALLOC(der, derSz + blockSz, heap,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (tmpBuf == NULL) {
+            WOLFSSL_ERROR_MSG("Extending DER buffer failed");
+            XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            ret = 0;
+        }
+        else {
+            der = tmpBuf;
+
+            /* Encrypt DER inline. */
+            ret = EncryptDerKey(der, &derSz, cipher, passwd, passwdSz,
+                &cipherInfo, derSz + blockSz);
+            if (ret != 1) {
+                WOLFSSL_ERROR_MSG("EncryptDerKey failed");
+            }
+        }
+    }
+
+    if (ret == 1) {
+        /* Calculate PEM encoding size. */
+        pemSz = wc_DerToPemEx(der, derSz, NULL, 0, cipherInfo, type);
+        if (pemSz <= 0) {
+            WOLFSSL_ERROR_MSG("wc_DerToPemEx failed");
+            ret = 0;
+        }
+    }
+    if (ret == 1) {
+        /* Allocate space for PEM encoding plus a NUL terminator. */
+        tmp = (byte*)XMALLOC(pemSz + 1, NULL, DYNAMIC_TYPE_KEY);
+        if (tmp == NULL) {
+            WOLFSSL_ERROR_MSG("malloc failed");
+            ret = 0;
+        }
+    }
+    if (ret == 1) {
+        /* DER to PEM */
+        pemSz = wc_DerToPemEx(der, derSz, tmp, pemSz, cipherInfo, type);
+        if (pemSz <= 0) {
+            WOLFSSL_ERROR_MSG("wc_DerToPemEx failed");
+            ret = 0;
+        }
+    }
+    if (ret == 1) {
+        /* NUL terminate string - PEM.  */
+        tmp[pemSz] = 0x00;
+        /* Return allocated buffer and size. */
+        *out = tmp;
+        *outSz = pemSz;
+        /* Don't free returning buffer. */
+        tmp = NULL;
+    }
+
+    XFREE(tmp, NULL, DYNAMIC_TYPE_KEY);
+    XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+    XFREE(der, heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    return ret;
+}
+#endif
+
+#endif /* !NO_ASN */
+
 #if !defined(NO_CERTS) && defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \
     !defined(NO_STDIO_FILESYSTEM) && (!defined(NO_RSA) || !defined(NO_DSA) || \
-    defined(HAVE_ECC))
+    defined(HAVE_ECC)) && defined(OPENSSL_EXTRA)
 /* Print the number bn in hex with name field and indentation indent to file fp.
  *
  * Used by wolfSSL_DSA_print_fp, wolfSSL_RSA_print_fp and
@@ -422,9 +522,7 @@ static int pk_bn_field_print_fp(XFILE fp, int indent, const char* field,
 }
 #endif /* !NO_CERTS && XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM &&
         * (!NO_DSA || !NO_RSA || HAVE_ECC) */
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
 
-#if defined(OPENSSL_EXTRA)
 #if defined(XSNPRINTF) && !defined(NO_BIO) && !defined(NO_RSA) && \
     !defined(HAVE_FAST_RSA)
 /* snprintf() must be available */
@@ -634,7 +732,7 @@ static int wolfssl_print_number(WOLFSSL_BIO* bio, mp_int* num, const char* name,
 #endif /* XSNPRINTF && !NO_BIO && !NO_RSA && !HAVE_FAST_RSA */
 
 #if !defined(NO_RSA) || (!defined(NO_DH) && !defined(NO_CERTS) && \
-    defined(HAVE_FIPS) && !FIPS_VERSION_GT(2,0))
+    defined(HAVE_FIPS) && !FIPS_VERSION_GT(2,0)) || defined(HAVE_ECC)
 
 /* Uses the DER SEQUENCE to determine size of DER data.
  *
@@ -666,7 +764,7 @@ static int wolfssl_der_length(const unsigned char* seq, int len)
 
 #endif /* OPENSSL_EXTRA */
 
-#if !defined(NO_RSA) || !defined(NO_DH)
+#if !defined(NO_RSA) || !defined(NO_DH) || defined(HAVE_ECC)
 /* Too many defines to check explicitly - prototype it and always include
  * for RSA and DH. */
 WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local);
@@ -699,16 +797,8 @@ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local)
     if (ret == NULL) {
     #ifdef HAVE_GLOBAL_RNG
         WOLFSSL_MSG("Bad RNG Init, trying global");
-        /* Get the global random number generator instead. */
-        ret = wolfssl_get_global_rng();
-        if (ret == NULL) {
-            /* Create a global random if possible. */
-            (void)wolfSSL_RAND_Init();
-            ret = wolfssl_get_global_rng();
-        }
-    #else
-        WOLFSSL_ERROR_MSG("Bad RNG Init");
     #endif
+        ret = wolfssl_make_global_rng();
     }
 
     if (ret != rng) {
@@ -919,9 +1009,9 @@ void wolfSSL_RSA_free(WOLFSSL_RSA* rsa)
 
 /* Allocate and initialize a new RSA key.
  *
- * wolfSSL API.
+ * Not OpenSSL API.
  *
- * @param [in] heap   Heap hint.
+ * @param [in] heap   Heap hint for dynamic memory allocation.
  * @param [in] devId  Device identifier value.
  * @return  RSA key on success.
  * @return  NULL on failure.
@@ -1429,7 +1519,7 @@ WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
 #if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA)
 /* Create a DER encoding of key.
  *
- * wolfSSL API.
+ * Not OpenSSL API.
  *
  * @param [in]  rsa        RSA key.
  * @param [out] outBuf     Allocated buffer containing DER encoding.
@@ -1566,7 +1656,7 @@ static int wolfSSL_RSA_To_Der_ex(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey,
 #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
 /* Load the DER encoded private RSA key.
  *
- * wolfSSL API.
+ * Not OpenSSL API.
  *
  * @param [in] rsa     RSA key.
  * @param [in] derBuf  Buffer holding DER encoding.
@@ -1583,7 +1673,7 @@ int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
 
 /* Load the DER encoded public or private RSA key.
  *
- * wolfSSL API.
+ * Not OpenSSL API.
  *
  * @param [in] rsa     RSA key.
  * @param [in] derBuf  Buffer holding DER encoding.
@@ -1946,25 +2036,21 @@ WOLFSSL_RSA* wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA** rsa,
  * @param [in]  passwd    Password string when PEM encrypted. May be NULL.
  * @param [in]  passwdSz  Length of password string when PEM encrypted.
  * @param [out] pem       Allocated buffer with PEM encoding.
- * @param [out] plen      Length of PEM encoding.
+ * @param [out] pLen      Length of PEM encoding.
  * @return  1 on success.
  * @return  0 on failure.
  */
 int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
-    unsigned char* passwd, int passwdSz, unsigned char **pem, int *plen)
+    unsigned char* passwd, int passwdSz, unsigned char **pem, int *pLen)
 {
     int ret = 1;
     byte* derBuf = NULL;
-    byte* tmp = NULL;
-    byte* cipherInfo = NULL;
     int  derSz = 0;
-    int  pemSz = 0;
-    const int type = PRIVATEKEY_TYPE;
 
     WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey");
 
     /* Validate parameters. */
-    if ((pem == NULL) || (plen == NULL) || (rsa == NULL) ||
+    if ((pem == NULL) || (pLen == NULL) || (rsa == NULL) ||
             (rsa->internal == NULL)) {
         WOLFSSL_ERROR_MSG("Bad function arguments");
         ret = 0;
@@ -1982,68 +2068,12 @@ int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
         ret = 0;
     }
 
-    /* Encrypt DER buffer if required. */
-    if ((ret == 1) && (passwd != NULL) && (passwdSz > 0) && (cipher != NULL)) {
-        int blockSz = wolfSSL_EVP_CIPHER_block_size(cipher);
-        byte *tmpBuf;
-
-        /* Add space for padding. */
-        tmpBuf = (byte*)XREALLOC(derBuf, derSz + blockSz, rsa->heap,
-            DYNAMIC_TYPE_TMP_BUFFER);
-        if (tmpBuf == NULL) {
-            WOLFSSL_ERROR_MSG("Extending DER buffer failed");
-            XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            ret = 0;
-        }
-        else {
-            derBuf = tmpBuf;
-
-            /* Encrypt DER inline. */
-            ret = EncryptDerKey(derBuf, &derSz, cipher, passwd, passwdSz,
-                &cipherInfo, derSz + blockSz);
-            if (ret != 1) {
-                WOLFSSL_ERROR_MSG("EncryptDerKey failed");
-            }
-        }
-    }
-
-    if (ret == 1) {
-        /* Calculate PEM encoding size. */
-        pemSz = wc_DerToPemEx(derBuf, derSz, NULL, 0, cipherInfo, type);
-        if (pemSz <= 0) {
-            WOLFSSL_ERROR_MSG("wc_DerToPemEx failed");
-            ret = 0;
-        }
-    }
-    if (ret == 1) {
-        /* Allocate space for PEM encoding plus a NUL terminator. */
-        tmp = (byte*)XMALLOC(pemSz + 1, NULL, DYNAMIC_TYPE_KEY);
-        if (tmp == NULL) {
-            WOLFSSL_ERROR_MSG("malloc failed");
-            ret = 0;
-        }
-    }
-    if (ret == 1) {
-        /* DER to PEM */
-        pemSz = wc_DerToPemEx(derBuf, derSz, tmp, pemSz, cipherInfo, type);
-        if (pemSz <= 0) {
-            WOLFSSL_ERROR_MSG("wc_DerToPemEx failed");
-            ret = 0;
-        }
-    }
-    if (ret == 1) {
-        /* NUL terminate string - PEM.  */
-        tmp[pemSz] = 0x00;
-        /* Return allocated buffer and size. */
-        *pem = tmp;
-        *plen = pemSz;
-        /* Don't free returning buffer. */
-        tmp = NULL;
+    if ((ret == 1) && (der_to_enc_pem_alloc(derBuf, derSz, cipher, passwd,
+            passwdSz, PRIVATEKEY_TYPE, NULL, pem, pLen) != 1)) {
+        WOLFSSL_ERROR_MSG("der_to_enc_pem_alloc failed");
+        ret = 0;
     }
 
-    XFREE(tmp, NULL, DYNAMIC_TYPE_KEY);
-    XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-    XFREE(derBuf, rsa ? rsa->heap : NULL, DYNAMIC_TYPE_TMP_BUFFER);
     return ret;
 }
 
@@ -2066,7 +2096,7 @@ int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa,
 {
     int ret = 1;
     byte* pem = NULL;
-    int plen;
+    int pLen;
 
     (void)cb;
     (void)arg;
@@ -2082,13 +2112,13 @@ int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa,
     if (ret == 1) {
         /* Write PEM to buffer that is allocated in the call. */
         ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, cipher, passwd, len,
-            &pem, &plen);
+            &pem, &pLen);
         if (ret != 1) {
             WOLFSSL_ERROR_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
         }
     }
     /* Write PEM to BIO. */
-    if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, plen) <= 0)) {
+    if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) <= 0)) {
         WOLFSSL_ERROR_MSG("RSA private key BIO write failed");
         ret = 0;
     }
@@ -2121,7 +2151,7 @@ int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa,
 {
     int ret = 1;
     byte* pem = NULL;
-    int plen;
+    int pLen;
 
     (void)cb;
     (void)arg;
@@ -2137,13 +2167,13 @@ int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa,
     if (ret == 1) {
         /* Write PEM to buffer that is allocated in the call. */
         ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, cipher, passwd, passwdSz,
-            &pem, &plen);
+            &pem, &pLen);
         if (ret != 1) {
             WOLFSSL_ERROR_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
         }
     }
     /* Write PEM to file pointer. */
-    if ((ret == 1) && ((int)XFWRITE(pem, plen, 1, fp) != 1)) {
+    if ((ret == 1) && ((int)XFWRITE(pem, pLen, 1, fp) != 1)) {
         WOLFSSL_ERROR_MSG("RSA private key file write failed");
         ret = 0;
     }
@@ -2368,7 +2398,7 @@ int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int indent)
 
     for (i = 0; (ret == 1) && (i < RSA_INTS); i++) {
         /* Get mp_int for index. */
-        switch(i) {
+        switch (i) {
             case 0:
                 /* Print out modulus */
                 num = &key->n;
@@ -3017,7 +3047,7 @@ int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data)
 #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
 /* Set the extra data and cleanup callback against the RSA key at an index.
  *
- * wolfSSL API.
+ * Not OpenSSL API.
  *
  * @param [in, out] rsa     RSA key.
  * @param [in]      idx     Index set set extra data at.
@@ -3714,7 +3744,8 @@ int wolfSSL_RSA_sign(int hashAlg, const unsigned char* hash, unsigned int hLen,
 }
 
 /* Sign the message hash using hash algorithm and RSA key.
- * wolfSSL API.
+ *
+ * Not OpenSSL API.
  *
  * @param [in]  hashAlg   Hash algorithm NID.
  * @param [in]  hash      Hash of message to encode for signing.
@@ -3748,7 +3779,7 @@ int wolfSSL_RSA_sign_ex(int hashAlg, const unsigned char* hash,
 /**
  * Sign a message hash with the chosen message digest, padding, and RSA key.
  *
- * wolfSSL API.
+ * Not OpenSSL API.
  *
  * @param [in]      hashAlg  Hash NID
  * @param [in]      hash     Message hash to sign.
@@ -3945,7 +3976,7 @@ int wolfSSL_RSA_verify(int hashAlg, const unsigned char* hash,
 /**
  * Verify a message hash with the chosen message digest, padding, and RSA key.
  *
- * wolfSSL API.
+ * Not OpenSSL API.
  *
  * @param [in]  hashAlg  Hash NID
  * @param [in]  hash     Message hash.
@@ -4470,7 +4501,7 @@ int wolfSSL_RSA_private_encrypt(int len, const unsigned char* from,
 
 /* Calculate d mod p-1 and q-1 into BNs.
  *
- * wolfSSL API.
+ * Not OpenSSL API.
  *
  * @param [in, out] rsa  RSA key.
  * @return 1 on success.
@@ -5682,7 +5713,7 @@ int wolfSSL_PEM_write_bio_DSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa)
 int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
                                         const EVP_CIPHER* cipher,
                                         unsigned char* passwd, int passwdSz,
-                                        unsigned char **pem, int *plen)
+                                        unsigned char **pem, int *pLen)
 {
 #if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
     byte *derBuf, *tmp, *cipherInfo = NULL;
@@ -5693,7 +5724,7 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
 
     WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey");
 
-    if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) {
+    if (pem == NULL || pLen == NULL || dsa == NULL || dsa->internal == NULL) {
         WOLFSSL_MSG("Bad function arguments");
         return 0;
     }
@@ -5738,15 +5769,15 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
             return ret;
         }
         /* tmp buffer with a max size */
-        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+        *pLen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
             (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
     }
     else { /* tmp buffer with a max size */
-        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+        *pLen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
             (int)XSTRLEN(footer) + 1;
     }
 
-    tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
+    tmp = (byte*)XMALLOC(*pLen, NULL, DYNAMIC_TYPE_PEM);
     if (tmp == NULL) {
         WOLFSSL_MSG("malloc failed");
         XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
@@ -5756,8 +5787,8 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
     }
 
     /* DER to PEM */
-    *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
-    if (*plen <= 0) {
+    *pLen = wc_DerToPemEx(derBuf, derSz, tmp, *pLen, cipherInfo, type);
+    if (*pLen <= 0) {
         WOLFSSL_MSG("wc_DerToPemEx failed");
         XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
         XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
@@ -5769,15 +5800,15 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
     if (cipherInfo != NULL)
         XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
 
-    *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
+    *pem = (byte*)XMALLOC((*pLen)+1, NULL, DYNAMIC_TYPE_KEY);
     if (*pem == NULL) {
         WOLFSSL_MSG("malloc failed");
         XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
         return 0;
     }
-    XMEMSET(*pem, 0, (*plen)+1);
+    XMEMSET(*pem, 0, (*pLen)+1);
 
-    if (XMEMCPY(*pem, tmp, *plen) == NULL) {
+    if (XMEMCPY(*pem, tmp, *pLen) == NULL) {
         WOLFSSL_MSG("XMEMCPY failed");
         XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
         XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
@@ -5792,7 +5823,7 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
     (void)passwd;
     (void)passwdSz;
     (void)pem;
-    (void)plen;
+    (void)pLen;
     return 0;
 #endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
 }
@@ -5807,7 +5838,7 @@ int wolfSSL_PEM_write_DSAPrivateKey(XFILE fp, WOLFSSL_DSA *dsa,
                                     wc_pem_password_cb *cb, void *u)
 {
     byte *pem;
-    int  plen, ret;
+    int  pLen, ret;
 
     (void)cb;
     (void)u;
@@ -5820,13 +5851,13 @@ int wolfSSL_PEM_write_DSAPrivateKey(XFILE fp, WOLFSSL_DSA *dsa,
     }
 
     ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem,
-        &plen);
+        &pLen);
     if (ret != 1) {
         WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed");
         return 0;
     }
 
-    ret = (int)XFWRITE(pem, plen, 1, fp);
+    ret = (int)XFWRITE(pem, pLen, 1, fp);
     if (ret != 1) {
         WOLFSSL_MSG("DSA private key file write failed");
         return 0;
@@ -7259,14 +7290,6 @@ WOLFSSL_DH *wolfSSL_d2i_DHparams(WOLFSSL_DH** dh, const unsigned char** pp,
 }
 #endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */
 
-/* Calculate the number of bytes require to represent a length value in ASN.
- *
- * @param [in] l  Length value to use.
- * @return  Number of bytes required to represent length value.
- */
-#define ASN_LEN_SIZE(l)             \
-    (((l) < 128) ? 1 : (((l) < 256) ? 2 : 3))
-
 /* Converts internal WOLFSSL_DH structure to DER encoded DH parameters.
  *
  * @params [in]      dh   DH key with parameters to encode.
@@ -7877,7 +7900,7 @@ int wolfSSL_DH_size(WOLFSSL_DH* dh)
 
     WOLFSSL_ENTER("wolfSSL_DH_size");
 
-    /* Validate paramater. */
+    /* Validate parameter. */
     if (dh != NULL) {
         /* Size of key is size of prime in bytes. */
         ret = wolfSSL_BN_num_bytes(dh->p);
@@ -8620,3484 +8643,4945 @@ int wolfSSL_DH_compute_key(unsigned char* key, const WOLFSSL_BIGNUM* otherPub,
 
 #if defined(OPENSSL_EXTRA)
 
-#ifndef NO_CERTS
+/* Start EC_curve */
 
-#if defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \
-    !defined(NO_STDIO_FILESYSTEM)
-int wolfSSL_EC_KEY_print_fp(XFILE fp, WOLFSSL_EC_KEY* key, int indent)
+/* Get the NIST name for the numeric ID.
+ *
+ * @param [in] nid  Numeric ID of an EC curve.
+ * @return  String representing NIST name of EC curve on success.
+ * @return  NULL on error.
+ */
+const char* wolfSSL_EC_curve_nid2nist(int nid)
 {
-    int ret = 1;
-    int bits = 0;
-    int priv = 0;
-    int nid = 0;
-    const char* curve;
-    const char* nistName;
-    WOLFSSL_BIGNUM* pubBn = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_print_fp");
-
-    if (fp == XBADFILE || key == NULL || key->group == NULL || indent < 0) {
-        ret = 0;
-    }
+    const char* name = NULL;
+    const WOLF_EC_NIST_NAME* nist_name;
 
-    if (ret == 1) {
-        bits = wolfSSL_EC_GROUP_order_bits(key->group);
-        if (bits <= 0) {
-            WOLFSSL_MSG("Failed to get group order bits.");
-            ret = 0;
+    /* Attempt to find the curve info matching the NID passed in. */
+    for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
+        if (nist_name->nid == nid) {
+            /* NID found - return name. */
+            name = nist_name->name;
+            break;
         }
     }
-    if (ret == 1) {
-        if (XFPRINTF(fp, "%*s", indent, "") < 0)
-            ret = 0;
-    }
-    if (ret == 1) {
-        if (key->priv_key != NULL && !wolfSSL_BN_is_zero(key->priv_key)) {
-            if (XFPRINTF(fp, "Private-Key: (%d bit)\n", bits) < 0)
-                ret = 0;
-            priv = 1;
-        }
-        else {
-            if (XFPRINTF(fp, "Public-Key: (%d bit)\n", bits) < 0)
-                ret = 0;
-        }
 
-        if (priv) {
-            ret = pk_bn_field_print_fp(fp, indent, "priv", key->priv_key);
-        }
-    }
-    if (ret == 1 && key->pub_key != NULL && key->pub_key->exSet) {
-        pubBn = wolfSSL_EC_POINT_point2bn(key->group, key->pub_key,
-                                          POINT_CONVERSION_UNCOMPRESSED, NULL,
-                                          NULL);
-        if (pubBn == NULL) {
-            WOLFSSL_MSG("wolfSSL_EC_POINT_point2bn failed.");
-            ret = 0;
-        }
-        else {
-            ret = pk_bn_field_print_fp(fp, indent, "pub", pubBn);
-        }
-    }
-    if (ret == 1) {
-        nid = wolfSSL_EC_GROUP_get_curve_name(key->group);
-        if (nid > 0) {
-            curve = wolfSSL_OBJ_nid2ln(nid);
-            if (curve != NULL) {
-                if (XFPRINTF(fp, "%*s", indent, "") < 0)
-                    ret = 0;
-                else if (XFPRINTF(fp, "ASN1 OID: %s\n", curve) < 0)
-                    ret = 0;
-            }
-            nistName = wolfSSL_EC_curve_nid2nist(nid);
-            if (nistName != NULL) {
-                if (XFPRINTF(fp, "%*s", indent, "") < 0)
-                    ret = 0;
-                else if (XFPRINTF(fp, "NIST CURVE: %s\n", nistName) < 0)
-                    ret = 0;
-            }
+    return name;
+}
+
+/* Get the numeric ID for the NIST name.
+ *
+ * @param [in] name  NIST name of EC curve.
+ * @return  NID matching NIST name on success.
+ * @return  0 on error.
+ */
+int wolfSSL_EC_curve_nist2nid(const char* name)
+{
+    int nid = 0;
+    const WOLF_EC_NIST_NAME* nist_name;
+
+    /* Attempt to find the curve info matching the NIST name passed in. */
+    for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
+        if (XSTRCMP(nist_name->name, name) == 0) {
+            /* Name found - return NID. */
+            nid = nist_name->nid;
+            break;
         }
     }
 
-    if (pubBn != NULL) {
-        wolfSSL_BN_free(pubBn);
-    }
+    return nid;
+}
 
-    WOLFSSL_LEAVE("wolfSSL_EC_KEY_print_fp", ret);
+#endif /* OPENSSL_EXTRA */
 
-    return ret;
-}
-#endif /* XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */
+/* End EC_curve */
 
-#if defined(OPENSSL_ALL)
+/* Start EC_METHOD */
 
-/* Copies ecc_key into new WOLFSSL_EC_KEY object
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Get the EC method of the EC group object.
  *
- * src  : EC_KEY to duplicate. If EC_KEY is not null, create new EC_KEY and copy
- * internal ecc_key from src to dup.
+ * wolfSSL doesn't use method tables. Implementation used is dependent upon
+ * the NID.
  *
- * Returns pointer to duplicate EC_KEY.
+ * @param [in] group  EC group object.
+ * @return  EC method.
  */
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src)
+const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of(
+    const WOLFSSL_EC_GROUP *group)
 {
-    WOLFSSL_EC_KEY *newKey;
-    ecc_key *key, *srcKey;
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_dup");
+    /* No method table used so just return the same object. */
+    return group;
+}
 
-    if (src == NULL || src->internal == NULL || src->group == NULL || \
-       src->pub_key == NULL || src->priv_key == NULL) {
+/* Get field type for method.
+ *
+ * Only prime fields are supported.
+ *
+ * @param [in] meth  EC method.
+ * @return  X9.63 prime field NID on success.
+ * @return  0 on error.
+ */
+int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth)
+{
+    int nid = 0;
 
-        WOLFSSL_MSG("src NULL error");
-        return NULL;
+    if (meth != NULL) {
+        /* Only field type supported by code base. */
+        nid = NID_X9_62_prime_field;
     }
 
-    newKey = wolfSSL_EC_KEY_new();
-    if (newKey == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
-        return NULL;
-    }
+    return nid;
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
 
-    key = (ecc_key*)newKey->internal;
-    if (key == NULL) {
-        WOLFSSL_MSG("ecc_key NULL error");
-        wolfSSL_EC_KEY_free(newKey);
-        return NULL;
-    }
-    srcKey = (ecc_key*)src->internal;
+/* End EC_METHOD */
 
-    /* ecc_key */
-    /* copy pubkey */
-    ret = wc_ecc_copy_point(&srcKey->pubkey, &key->pubkey);
-    if (ret != MP_OKAY) {
-        WOLFSSL_MSG("wc_ecc_copy_point error");
-        wolfSSL_EC_KEY_free(newKey);
-        return NULL;
-    }
+/* Start EC_GROUP */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Converts ECC curve enum values in ecc_curve_id to the associated OpenSSL NID
+ * value.
+ *
+ * @param [in] n  ECC curve id.
+ * @return  ECC curve NID (OpenSSL compatible value).
+ */
+int EccEnumToNID(int n)
+{
+    WOLFSSL_ENTER("EccEnumToNID()");
+
+    switch(n) {
+        case ECC_SECP192R1:
+            return NID_X9_62_prime192v1;
+        case ECC_PRIME192V2:
+            return NID_X9_62_prime192v2;
+        case ECC_PRIME192V3:
+            return NID_X9_62_prime192v3;
+        case ECC_PRIME239V1:
+            return NID_X9_62_prime239v1;
+        case ECC_PRIME239V2:
+            return NID_X9_62_prime239v2;
+        case ECC_PRIME239V3:
+            return NID_X9_62_prime239v3;
+        case ECC_SECP256R1:
+            return NID_X9_62_prime256v1;
+        case ECC_SECP112R1:
+            return NID_secp112r1;
+        case ECC_SECP112R2:
+            return NID_secp112r2;
+        case ECC_SECP128R1:
+            return NID_secp128r1;
+        case ECC_SECP128R2:
+            return NID_secp128r2;
+        case ECC_SECP160R1:
+            return NID_secp160r1;
+        case ECC_SECP160R2:
+            return NID_secp160r2;
+        case ECC_SECP224R1:
+            return NID_secp224r1;
+        case ECC_SECP384R1:
+            return NID_secp384r1;
+        case ECC_SECP521R1:
+            return NID_secp521r1;
+        case ECC_SECP160K1:
+            return NID_secp160k1;
+        case ECC_SECP192K1:
+            return NID_secp192k1;
+        case ECC_SECP224K1:
+            return NID_secp224k1;
+        case ECC_SECP256K1:
+            return NID_secp256k1;
+        case ECC_BRAINPOOLP160R1:
+            return NID_brainpoolP160r1;
+        case ECC_BRAINPOOLP192R1:
+            return NID_brainpoolP192r1;
+        case ECC_BRAINPOOLP224R1:
+            return NID_brainpoolP224r1;
+        case ECC_BRAINPOOLP256R1:
+            return NID_brainpoolP256r1;
+        case ECC_BRAINPOOLP320R1:
+            return NID_brainpoolP320r1;
+        case ECC_BRAINPOOLP384R1:
+            return NID_brainpoolP384r1;
+        case ECC_BRAINPOOLP512R1:
+            return NID_brainpoolP512r1;
+        default:
+            WOLFSSL_MSG("NID not found");
+            return -1;
+    }
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* Converts OpenSSL NID of EC curve to the enum value in ecc_curve_id
+ *
+ * Used by ecc_sets[].
+ *
+ * @param [in] n  OpenSSL NID of EC curve.
+ * @return  wolfCrypt EC curve id.
+ * @return  -1 on error.
+ */
+int NIDToEccEnum(int nid)
+{
+    /* -1 on error. */
+    int id = -1;
+
+    WOLFSSL_ENTER("NIDToEccEnum()");
+
+    switch (nid) {
+        case NID_X9_62_prime192v1:
+            id = ECC_SECP192R1;
+            break;
+        case NID_X9_62_prime192v2:
+            id = ECC_PRIME192V2;
+            break;
+        case NID_X9_62_prime192v3:
+            id = ECC_PRIME192V3;
+            break;
+        case NID_X9_62_prime239v1:
+            id = ECC_PRIME239V1;
+            break;
+        case NID_X9_62_prime239v2:
+            id = ECC_PRIME239V2;
+            break;
+        case NID_X9_62_prime239v3:
+            id = ECC_PRIME239V3;
+            break;
+        case NID_X9_62_prime256v1:
+            id = ECC_SECP256R1;
+            break;
+        case NID_secp112r1:
+            id = ECC_SECP112R1;
+            break;
+        case NID_secp112r2:
+            id = ECC_SECP112R2;
+            break;
+        case NID_secp128r1:
+            id = ECC_SECP128R1;
+            break;
+        case NID_secp128r2:
+            id = ECC_SECP128R2;
+            break;
+        case NID_secp160r1:
+            id = ECC_SECP160R1;
+            break;
+        case NID_secp160r2:
+            id = ECC_SECP160R2;
+            break;
+        case NID_secp224r1:
+            id = ECC_SECP224R1;
+            break;
+        case NID_secp384r1:
+            id = ECC_SECP384R1;
+            break;
+        case NID_secp521r1:
+            id = ECC_SECP521R1;
+            break;
+        case NID_secp160k1:
+            id = ECC_SECP160K1;
+            break;
+        case NID_secp192k1:
+            id = ECC_SECP192K1;
+            break;
+        case NID_secp224k1:
+            id = ECC_SECP224K1;
+            break;
+        case NID_secp256k1:
+            id = ECC_SECP256K1;
+            break;
+        case NID_brainpoolP160r1:
+            id = ECC_BRAINPOOLP160R1;
+            break;
+        case NID_brainpoolP192r1:
+            id = ECC_BRAINPOOLP192R1;
+            break;
+        case NID_brainpoolP224r1:
+            id = ECC_BRAINPOOLP224R1;
+            break;
+        case NID_brainpoolP256r1:
+            id = ECC_BRAINPOOLP256R1;
+            break;
+        case NID_brainpoolP320r1:
+            id = ECC_BRAINPOOLP320R1;
+            break;
+        case NID_brainpoolP384r1:
+            id = ECC_BRAINPOOLP384R1;
+            break;
+        case NID_brainpoolP512r1:
+            id = ECC_BRAINPOOLP512R1;
+            break;
+        default:
+            WOLFSSL_MSG("NID not found");
+    }
+
+    return id;
+}
+
+/* Set the fields of the EC group based on numeric ID.
+ *
+ * @param [in, out] group  EC group.
+ * @param [in]      nid    Numeric ID of an EC curve.
+ */
+static void ec_group_set_nid(WOLFSSL_EC_GROUP* group, int nid)
+{
+    int eccEnum;
+    int realNid;
+
+    /* Convert ecc_curve_id enum to NID. */
+    if ((realNid = EccEnumToNID(nid)) != -1) {
+        /* ecc_curve_id enum passed in - have real NID value set. */
+        eccEnum = nid;
+    }
+    else {
+        /* NID passed in is OpenSSL type. */
+        realNid = nid;
+        /* Convert NID to ecc_curve_id enum. */
+        eccEnum = NIDToEccEnum(nid);
+    }
+
+    /* Set the numeric ID of the curve */
+    group->curve_nid = realNid;
+    /* Initialize index to -1 (i.e. wolfCrypt doesn't support curve). */
+    group->curve_idx = -1;
+
+    /* Find index and OID sum for curve if wolfCrypt supports it. */
+    if (eccEnum != -1) {
+        int i;
+
+        /* Find id and set the internal curve idx and OID sum. */
+        for (i = 0; ecc_sets[i].size != 0; i++) {
+            if (ecc_sets[i].id == eccEnum) {
+                /* Found id in wolfCrypt supported EC curves. */
+                group->curve_idx = i;
+                group->curve_oid = ecc_sets[i].oidSum;
+                break;
+            }
+        }
+    }
+}
+
+/* Create a new EC group with the numeric ID for an EC curve.
+ *
+ * @param [in] nid  Numeric ID of an EC curve.
+ * @return  New, allocated EC group on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_EC_GROUP* wolfSSL_EC_GROUP_new_by_curve_name(int nid)
+{
+    int err = 0;
+    WOLFSSL_EC_GROUP* group;
+
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name");
+
+    /* Allocate EC group. */
+    group = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL,
+        DYNAMIC_TYPE_ECC);
+    if (group == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure");
+        err = 1;
+    }
+
+    if (!err) {
+        /* Reset all fields. */
+        XMEMSET(group, 0, sizeof(WOLFSSL_EC_GROUP));
+
+        /* Set the fields of group based on the numeric ID. */
+        ec_group_set_nid(group, nid);
+    }
+
+    return group;
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Dispose of the EC group.
+ *
+ * Cannot use group after this call.
+ *
+ * @param [in] group  EC group to free.
+ */
+void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_free");
+
+    /* Dispose of EC group. */
+    XFREE(group, NULL, DYNAMIC_TYPE_ECC);
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#ifdef OPENSSL_EXTRA
+#ifndef NO_BIO
+
+/* Creates an EC group from the DER encoding.
+ *
+ * Only named curves supported.
+ *
+ * @param [out] group  Reference to EC group object.
+ * @param [in]  in     Buffer holding DER encoding of curve.
+ * @param [in]  inSz   Length of data in buffer.
+ * @return  EC group on success.
+ * @return  NULL on error.
+ */
+static WOLFSSL_EC_GROUP* wolfssl_ec_group_d2i(WOLFSSL_EC_GROUP** group,
+    const unsigned char* in, long inSz)
+{
+    int err = 0;
+    WOLFSSL_EC_GROUP* ret = NULL;
+    word32 idx = 0;
+    word32 oid = 0;
+    int id = 0;
+
+    /* Use the group passed in. */
+    if ((group != NULL) && (*group != NULL)) {
+        ret = *group;
+    }
+
+    /* Only support named curves. */
+    if (in[0] != ASN_OBJECT_ID) {
+        WOLFSSL_ERROR_MSG("Invalid or unsupported encoding");
+        err = 1;
+    }
+    /* Decode the OBJECT ID - expecting an EC curve OID. */
+    if ((!err) && (GetObjectId(in, &idx, &oid, oidCurveType, (word32)inSz) !=
+            0)) {
+        err = 1;
+    }
+    if (!err) {
+        /* Get the internal ID for OID. */
+        id = wc_ecc_get_oid(oid, NULL, NULL);
+        if (id < 0) {
+            err = 1;
+        }
+    }
+    if (!err) {
+        /* Get the NID for the internal ID. */
+        int nid = EccEnumToNID(id);
+        if (ret == NULL) {
+            /* Create a new EC group with the numeric ID. */
+            ret = wolfSSL_EC_GROUP_new_by_curve_name(nid);
+            if (ret == NULL) {
+                err = 1;
+            }
+        }
+        else {
+            ec_group_set_nid(ret, nid);
+        }
+    }
+    if ((!err) && (group != NULL)) {
+        /* Return the EC group through reference. */
+        *group = ret;
+    }
+
+    if (err) {
+        if ((ret != NULL) && (ret != *group)) {
+            wolfSSL_EC_GROUP_free(ret);
+        }
+        ret = NULL;
+    }
+    return ret;
+}
+
+/* Creates a new EC group from the PEM encoding in the BIO.
+ *
+ * @param [in]  bio    BIO to read PEM encoding from.
+ * @param [out] group  Reference to EC group object.
+ * @param [in]  cb     Password callback when PEM encrypted.
+ * @param [in]  pass   NUL terminated string for passphrase when PEM encrypted.
+ * @return  EC group on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio,
+    WOLFSSL_EC_GROUP** group, wc_pem_password_cb* cb, void* pass)
+{
+    int err = 0;
+    WOLFSSL_EC_GROUP* ret = NULL;
+    DerBuffer*        der = NULL;
+    int               keyFormat = 0;
+
+     if (bio == NULL) {
+         err = 1;
+     }
+
+    /* Read parameters from BIO and convert PEM to DER. */
+    if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PARAM_TYPE,
+            &keyFormat, &der) < 0)) {
+        err = 1;
+    }
+    if (!err) {
+        /* Create EC group from DER encoding. */
+        ret = wolfssl_ec_group_d2i(group, der->buffer, der->length);
+        if (ret == NULL) {
+            WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_GROUP");
+        }
+    }
+
+    /* Dispose of any allocated data. */
+    FreeDer(&der);
+    return ret;
+}
+
+#endif /* !NO_BIO */
+
+#if defined(OPENSSL_ALL) && !defined(NO_CERTS)
+/* Copy an EC group.
+ *
+ * Only used by wolfSSL_EC_KEY_dup at this time.
+ *
+ * @param [in, out] dst  Destination EC group.
+ * @param [in]      src  Source EC group.
+ * @return  0 on success.
+ */
+static int wolfssl_ec_group_copy(WOLFSSL_EC_GROUP* dst,
+    const WOLFSSL_EC_GROUP* src)
+{
+    /* Copy the fields. */
+    dst->curve_idx = src->curve_idx;
+    dst->curve_nid = src->curve_nid;
+    dst->curve_oid = src->curve_oid;
+
+    return 0;
+}
+#endif /* OPENSSL_ALL && !NO_CERTS */
+
+/* Copies ecc_key into new WOLFSSL_EC_GROUP object
+ *
+ * @param [in] src  EC group to duplicate.
+ *
+ * @return  EC group on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_EC_GROUP* wolfSSL_EC_GROUP_dup(const WOLFSSL_EC_GROUP *src)
+{
+    WOLFSSL_EC_GROUP* newGroup = NULL;
+
+    if (src != NULL) {
+        /* Create new group base on NID in original EC group. */
+        newGroup = wolfSSL_EC_GROUP_new_by_curve_name(src->curve_nid);
+     }
+
+    return newGroup;
+}
+
+/* Compare two EC groups.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] a    First EC group.
+ * @param [in] b    Second EC group.
+ * @param [in] ctx  Big number context to use when comparing fields. Unused.
+ *
+ * @return  0 if equal.
+ * @return  1 if not equal.
+ * @return  -1 on error.
+ */
+int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b,
+                         WOLFSSL_BN_CTX *ctx)
+{
+    int ret;
+
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp");
+
+    /* Validate parameters. */
+    if ((a == NULL) || (b == NULL)) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments");
+        /* Return error value. */
+        ret = -1;
+    }
+    /* Compare NID and wolfSSL curve index. */
+    else {
+        /* 0 when same, 1 when not. */
+        ret = ((a->curve_nid == b->curve_nid) &&
+               (a->curve_idx == b->curve_idx)) ? 0 : 1;
+    }
+
+    return ret;
+}
+
+#ifndef NO_WOLFSSL_STUB
+/* Set the ASN.1 flag that indicate encoding of curve.
+ *
+ * Stub function - flag not used elsewhere.
+ * Always encoded as named curve.
+ *
+ * @param [in] group  EC group to modify.
+ * @param [in] flag   ASN.1 flag to set. Valid values:
+ *                    OPENSSL_EC_EXPLICIT_CURVE, OPENSSL_EC_NAMED_CURVE
+ */
+void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag)
+{
+    (void)group;
+    (void)flag;
+
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag");
+    WOLFSSL_STUB("EC_GROUP_set_asn1_flag");
+}
+#endif
+
+/* Get the curve NID of the group.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] group  EC group.
+ * @return  Curve NID on success.
+ * @return  0 on error.
+ */
+int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group)
+{
+    int nid = 0;
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name");
+
+    if (group == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments");
+    }
+    else {
+        nid = group->curve_nid;
+    }
+
+    return nid;
+}
+
+/* Get the degree (curve size in bits) of the EC group.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @return  Degree of the curve on success.
+ * @return  0 on error.
+ */
+int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group)
+{
+    int degree = 0;
+
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree");
+
+    if (group == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments");
+    }
+    else {
+        switch (group->curve_nid) {
+            case NID_secp112r1:
+            case NID_secp112r2:
+                degree = 112;
+                break;
+            case NID_secp128r1:
+            case NID_secp128r2:
+                degree = 128;
+                break;
+            case NID_secp160k1:
+            case NID_secp160r1:
+            case NID_secp160r2:
+            case NID_brainpoolP160r1:
+                degree = 160;
+                break;
+            case NID_secp192k1:
+            case NID_brainpoolP192r1:
+            case NID_X9_62_prime192v1:
+            case NID_X9_62_prime192v2:
+            case NID_X9_62_prime192v3:
+                degree = 192;
+                break;
+            case NID_secp224k1:
+            case NID_secp224r1:
+            case NID_brainpoolP224r1:
+                degree = 224;
+                break;
+            case NID_X9_62_prime239v1:
+            case NID_X9_62_prime239v2:
+            case NID_X9_62_prime239v3:
+                degree = 239;
+                break;
+            case NID_secp256k1:
+            case NID_brainpoolP256r1:
+            case NID_X9_62_prime256v1:
+                degree = 256;
+                break;
+            case NID_brainpoolP320r1:
+                degree = 320;
+                break;
+            case NID_secp384r1:
+            case NID_brainpoolP384r1:
+                degree = 384;
+                break;
+            case NID_brainpoolP512r1:
+                degree = 512;
+                break;
+            case NID_secp521r1:
+                degree = 521;
+                break;
+        }
+    }
+
+    return degree;
+}
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* Get the length of the order in bits of the EC group.
+ *
+ * TODO: consider switch statement or calculating directly from hex string
+ * array instead of using mp_int.
+ *
+ * @param [in] group  EC group.
+ * @return  Length of order in bits on success.
+ * @return  0 on error.
+ */
+int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group)
+{
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int *order = NULL;
+#else
+    mp_int order[1];
+#endif
+
+    /* Validate parameter. */
+    if ((group == NULL) || (group->curve_idx < 0)) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error");
+        ret = -1;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    if (ret == 0) {
+        /* Allocate memory for mp_int that will hold order value. */
+        order = (mp_int *)XMALLOC(sizeof(*order), NULL,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (order == NULL) {
+            ret = -1;
+        }
+    }
+#endif
 
-    /* copy private key k */
-    ret = mp_copy(&srcKey->k, &key->k);
-    if (ret != MP_OKAY) {
-        WOLFSSL_MSG("mp_copy error");
-        wolfSSL_EC_KEY_free(newKey);
-        return NULL;
+    if (ret == 0) {
+        /* Initialize mp_int. */
+        ret = mp_init(order);
     }
 
-    /* copy domain parameters */
-    if (srcKey->dp) {
-        ret = wc_ecc_set_curve(key, 0, srcKey->dp->id);
-        if (ret != 0) {
-            WOLFSSL_MSG("wc_ecc_set_curve error");
-            return NULL;
+    if (ret == 0) {
+        /* Read hex string of order from wolfCrypt array of curves. */
+        ret = mp_read_radix(order, ecc_sets[group->curve_idx].order,
+            MP_RADIX_HEX);
+        if (ret == 0) {
+            /* Get bits of order. */
+            ret = mp_count_bits(order);
         }
+        /* Clear and free mp_int. */
+        mp_clear(order);
     }
 
-    key->type  = srcKey->type;
-    key->idx   = srcKey->idx;
-    key->state = srcKey->state;
-    key->flags = srcKey->flags;
+#ifdef WOLFSSL_SMALL_STACK
+    /* Deallocate order. */
+    XFREE(order, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
 
-    /* Copy group */
-    if (newKey->group == NULL) {
-        WOLFSSL_MSG("EC_GROUP_new_by_curve_name error");
-        wolfSSL_EC_KEY_free(newKey);
-        return NULL;
+    /* Convert error code to length of 0. */
+    if (ret < 0) {
+        ret = 0;
     }
 
-    newKey->group->curve_idx = src->group->curve_idx;
-    newKey->group->curve_nid = src->group->curve_nid;
-    newKey->group->curve_oid = src->group->curve_oid;
+    return ret;
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
 
-    /* Copy public key */
-    if (src->pub_key->internal == NULL || newKey->pub_key->internal == NULL) {
-        WOLFSSL_MSG("NULL pub_key error");
-        wolfSSL_EC_KEY_free(newKey);
-        return NULL;
-    }
+#if defined(OPENSSL_EXTRA)
+/* Get the order of the group as a BN.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in]      group  EC group.
+ * @param [in, out] order  BN to hold order value.
+ * @param [in]      ctx    Context to use for BN operations. Unused.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group,
+    WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx)
+{
+    int ret = 1;
+    mp_int* mp = NULL;
 
-    /* Copy public key internal */
-    ret = wc_ecc_copy_point((ecc_point*)src->pub_key->internal,
-                            (ecc_point*)newKey->pub_key->internal);
-    if (ret != MP_OKAY) {
-        WOLFSSL_MSG("ecc_copy_point error");
-        wolfSSL_EC_KEY_free(newKey);
-        return NULL;
+    /* No BN operations performed - done with mp_int in BN. */
+    (void)ctx;
+
+    /* Validate parameters. */
+    if ((group == NULL) || (order == NULL) || (order->internal == NULL)) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error");
+        ret = 0;
     }
 
-    /* Copy X, Y, Z */
-    newKey->pub_key->X = wolfSSL_BN_dup(src->pub_key->X);
-    if (!newKey->pub_key->X && src->pub_key->X) {
-        WOLFSSL_MSG("Error copying EC_POINT");
-        wolfSSL_EC_KEY_free(newKey);
-        return NULL;
+    if (ret == 1) {
+        mp = (mp_int*)order->internal;
     }
-    newKey->pub_key->Y = wolfSSL_BN_dup(src->pub_key->Y);
-    if (!newKey->pub_key->Y && src->pub_key->Y) {
-        WOLFSSL_MSG("Error copying EC_POINT");
-        wolfSSL_EC_KEY_free(newKey);
-        return NULL;
+    /* Initialize */
+    if ((ret == 1) && (mp_init(mp) != MP_OKAY)) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure");
+        ret = 0;
     }
-    newKey->pub_key->Z = wolfSSL_BN_dup(src->pub_key->Z);
-    if (!newKey->pub_key->Z && src->pub_key->Z) {
-        WOLFSSL_MSG("Error copying EC_POINT");
-        wolfSSL_EC_KEY_free(newKey);
-        return NULL;
+    /* Read hex string of order from wolfCrypt array of curves. */
+    if ((ret == 1) && (mp_read_radix(mp, ecc_sets[group->curve_idx].order,
+            MP_RADIX_HEX) != MP_OKAY)) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure");
+        /* Zero out any partial value but don't free. */
+        mp_zero(mp);
+        ret = 0;
     }
 
-    newKey->pub_key->inSet = src->pub_key->inSet;
-    newKey->pub_key->exSet = src->pub_key->exSet;
-    newKey->pkcs8HeaderSz = src->pkcs8HeaderSz;
+    return ret;
+}
 
-    /* Copy private key */
-    if (src->priv_key->internal == NULL || newKey->priv_key->internal == NULL) {
-        WOLFSSL_MSG("NULL priv_key error");
-        wolfSSL_EC_KEY_free(newKey);
-        return NULL;
+#endif /* OPENSSL_EXTRA */
+
+/* End EC_GROUP */
+
+/* Start EC_POINT */
+
+#if defined(OPENSSL_EXTRA)
+
+/* Set data of EC point into internal, wolfCrypt EC point object.
+ *
+ * EC_POINT Openssl -> WolfSSL
+ *
+ * @param [in, out] p  EC point to update.
+ * @return  1 on success.
+ * @return  -1 on failure.
+ */
+static int ec_point_internal_set(WOLFSSL_EC_POINT *p)
+{
+    int ret = 1;
+
+    WOLFSSL_ENTER("ec_point_internal_set");
+
+    /* Validate parameter. */
+    if ((p == NULL) || (p->internal == NULL)) {
+        WOLFSSL_MSG("ECPoint NULL error");
+        ret = -1;
     }
+    else {
+        /* Get internal point as a wolfCrypt EC point. */
+        ecc_point* point = (ecc_point*)p->internal;
 
-    /* Free priv_key before call to newKey function */
-    wolfSSL_BN_free(newKey->priv_key);
-    newKey->priv_key = wolfSSL_BN_dup(src->priv_key);
-    if (newKey->priv_key == NULL) {
-        WOLFSSL_MSG("BN_newKey error");
-        wolfSSL_EC_KEY_free(newKey);
-        return NULL;
+        /* Set X ordinate if available. */
+        if ((p->X != NULL) && (SetIndividualInternal(p->X, point->x) != 1)) {
+            WOLFSSL_MSG("ecc point X error");
+            ret = -1;
+        }
+        /* Set Y ordinate if available. */
+        if ((ret == 1) && (p->Y != NULL) && (SetIndividualInternal(p->Y,
+                point->y) != 1)) {
+            WOLFSSL_MSG("ecc point Y error");
+            ret = -1;
+        }
+        /* Set Z ordinate if available. */
+        if ((ret == 1) && (p->Z != NULL) && (SetIndividualInternal(p->Z,
+                point->z) != 1)) {
+            WOLFSSL_MSG("ecc point Z error");
+            ret = -1;
+        }
+        /* Internal values set when operations succeeded. */
+        p->inSet = (ret == 1);
     }
 
-    return newKey;
+    return ret;
 }
 
-#endif /* OPENSSL_ALL */
+/* Set data of internal, wolfCrypt EC point object into EC point.
+ *
+ * EC_POINT WolfSSL -> OpenSSL
+ *
+ * @param [in, out] p  EC point to update.
+ * @return  1 on success.
+ * @return  -1 on failure.
+ */
+static int ec_point_external_set(WOLFSSL_EC_POINT *p)
+{
+    int ret = 1;
 
-#endif /* !NO_CERTS */
+    WOLFSSL_ENTER("ec_point_external_set");
+
+    /* Validate parameter. */
+    if ((p == NULL) || (p->internal == NULL)) {
+        WOLFSSL_MSG("ECPoint NULL error");
+        ret = -1;
+    }
+    else {
+        /* Get internal point as a wolfCrypt EC point. */
+        ecc_point* point = (ecc_point*)p->internal;
+
+        /* Set X ordinate. */
+        if (SetIndividualExternal(&p->X, point->x) != 1) {
+            WOLFSSL_MSG("ecc point X error");
+            ret = -1;
+        }
+        /* Set Y ordinate. */
+        if ((ret == 1) && (SetIndividualExternal(&p->Y, point->y) != 1)) {
+            WOLFSSL_MSG("ecc point Y error");
+            ret = -1;
+        }
+        /* Set Z ordinate. */
+        if ((ret == 1) && (SetIndividualExternal(&p->Z, point->z) != 1)) {
+            WOLFSSL_MSG("ecc point Z error");
+            ret = -1;
+        }
+        /* External values set when operations succeeded. */
+        p->exSet = (ret == 1);
+    }
+
+    return ret;
+}
+
+/* Setup internals of EC point.
+ *
+ * Assumes point is not NULL.
+ *
+ * @param [in, out] point  EC point to update.
+ * @return  1 on success.
+ * @return  0 on failure.
+ */
+static int ec_point_setup(const WOLFSSL_EC_POINT *point) {
+    int ret = 1;
+
+    /* Check if internal values need setting. */
+    if (!point->inSet) {
+        WOLFSSL_MSG("No ECPoint internal set, do it");
+
+        /* Forcing to non-constant type to update internals. */
+        if (ec_point_internal_set((WOLFSSL_EC_POINT *)point) != 1) {
+            WOLFSSL_MSG("ec_point_internal_set failed");
+            ret = 0;
+        }
+    }
+
+    return ret;
+}
 
-#ifdef ALT_ECC_SIZE
-static int SetIndividualInternalEcc(WOLFSSL_BIGNUM* bn, mp_int* mpi)
+/* Create a new EC point from the group.
+ *
+ * @param [in] group  EC group.
+ * @return  EC point on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_EC_POINT* wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP* group)
 {
-    WOLFSSL_MSG("Entering SetIndividualInternal");
+    int err = 0;
+    WOLFSSL_EC_POINT* point = NULL;
 
-    if (bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return -1;
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_new");
+
+    /* Validate parameter. */
+    if (group == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error");
+        err = 1;
     }
 
-    if (mpi == NULL) {
-        WOLFSSL_MSG("mpi NULL error");
-        return -1;
+    if (!err) {
+        /* Allocate memory for new EC point. */
+        point = (WOLFSSL_EC_POINT*)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL,
+            DYNAMIC_TYPE_ECC);
+        if (point == NULL) {
+            WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure");
+            err = 1;
+        }
     }
+    if (!err) {
+        /* Clear fields of EC point. */
+        XMEMSET(point, 0, sizeof(WOLFSSL_EC_POINT));
 
-    if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) {
-        WOLFSSL_MSG("mp_copy error");
-        return -1;
+        /* Allocate internal EC point. */
+        point->internal = wc_ecc_new_point();
+        if (point->internal == NULL) {
+            WOLFSSL_MSG("ecc_new_point failure");
+            err = 1;
+        }
     }
 
-    return 1;
+    if (err) {
+        XFREE(point, NULL, DYNAMIC_TYPE_ECC);
+        point = NULL;
+    }
+    return point;
 }
-#endif /* ALT_ECC_SIZE */
 
-/* EC_POINT Openssl -> WolfSSL */
-static int SetECPointInternal(WOLFSSL_EC_POINT *p)
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Dispose of the EC point.
+ *
+ * Cannot use point after this call.
+ *
+ * @param [in, out] point  EC point to free.
+ */
+void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *point)
 {
-    ecc_point* point;
-    WOLFSSL_ENTER("SetECPointInternal");
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_free");
 
-    if (p == NULL || p->internal == NULL) {
-        WOLFSSL_MSG("ECPoint NULL error");
-        return -1;
-    }
+    if (point != NULL) {
+        if (point->internal != NULL) {
+            wc_ecc_del_point((ecc_point*)point->internal);
+            point->internal = NULL;
+        }
 
-    point = (ecc_point*)p->internal;
+        /* Free ordinates. */
+        wolfSSL_BN_free(point->X);
+        wolfSSL_BN_free(point->Y);
+        wolfSSL_BN_free(point->Z);
+        /* Clear fields. */
+        point->X = NULL;
+        point->Y = NULL;
+        point->Z = NULL;
+        point->inSet = 0;
+        point->exSet = 0;
 
-#ifndef ALT_ECC_SIZE
-    if (p->X != NULL && SetIndividualInternal(p->X, point->x)
-                                                           != 1) {
-        WOLFSSL_MSG("ecc point X error");
-        return -1;
+        /* Dispose of EC point. */
+        XFREE(point, NULL, DYNAMIC_TYPE_ECC);
     }
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
 
-    if (p->Y != NULL && SetIndividualInternal(p->Y, point->y)
-                                                           != 1) {
-        WOLFSSL_MSG("ecc point Y error");
-        return -1;
+#ifdef OPENSSL_EXTRA
+
+/* Clear and dispose of the EC point.
+ *
+ * Cannot use point after this call.
+ *
+ * @param [in, out] point  EC point to free.
+ */
+void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *point)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free");
+
+    if (point != NULL) {
+        if (point->internal != NULL) {
+            /* Force internal point to be zeros. */
+    #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+            wc_ecc_forcezero_point((ecc_point*)point->internal);
+    #else
+            ecc_point* p = (ecc_point*)point->internal;
+            mp_forcezero(p->x);
+            mp_forcezero(p->y);
+            mp_forcezero(p->z);
+    #endif
+            wc_ecc_del_point((ecc_point*)point->internal);
+            point->internal = NULL;
+        }
+
+        /* Clear the ordinates before freeing. */
+        wolfSSL_BN_clear_free(point->X);
+        wolfSSL_BN_clear_free(point->Y);
+        wolfSSL_BN_clear_free(point->Z);
+        /* Clear fields. */
+        point->X = NULL;
+        point->Y = NULL;
+        point->Z = NULL;
+        point->inSet = 0;
+        point->exSet = 0;
+
+        /* Dispose of EC point. */
+        XFREE(point, NULL, DYNAMIC_TYPE_ECC);
     }
+}
 
-    if (p->Z != NULL && SetIndividualInternal(p->Z, point->z)
-                                                           != 1) {
-        WOLFSSL_MSG("ecc point Z error");
-        return -1;
+/* Print out the internals of EC point in debug and when logging callback set.
+ *
+ * Not an OpenSSL API.
+ *
+ * TODO: Use WOLFSSL_MSG_EX()?
+ *
+ * @param [in] msg    Message to prepend.
+ * @param [in] point  EC point to print.
+ */
+void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *point)
+{
+#if defined(DEBUG_WOLFSSL)
+    char *num;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_dump");
+
+    /* Only print when debugging on and logging callback set. */
+    if (WOLFSSL_IS_DEBUG_ON() && (wolfSSL_GetLoggingCb() == NULL)) {
+        if (point == NULL) {
+            /* No point passed in so just put out "NULL". */
+            XFPRINTF(stderr, "%s = NULL\n", msg);
+        }
+        else {
+            /* Put out message and status of internal/external data set. */
+            XFPRINTF(stderr, "%s:\n\tinSet=%d, exSet=%d\n", msg, point->inSet,
+                point->exSet);
+            /* Get x-ordinate as a hex string and print. */
+            num = wolfSSL_BN_bn2hex(point->X);
+            XFPRINTF(stderr, "\tX = %s\n", num);
+            XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
+            /* Get x-ordinate as a hex string and print. */
+            num = wolfSSL_BN_bn2hex(point->Y);
+            XFPRINTF(stderr, "\tY = %s\n", num);
+            XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
+            /* Get z-ordinate as a hex string and print. */
+            num = wolfSSL_BN_bn2hex(point->Z);
+            XFPRINTF(stderr, "\tZ = %s\n", num);
+            XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
+        }
     }
 #else
-    if (p->X != NULL && SetIndividualInternalEcc(p->X, point->x)
-                                                           != 1) {
-        WOLFSSL_MSG("ecc point X error");
-        return -1;
+    (void)msg;
+    (void)point;
+#endif
+}
+
+#ifndef HAVE_SELFTEST
+/* Convert EC point to hex string that as either uncompressed or compressed.
+ *
+ * ECC point compression types were not included in selftest ecc.h
+ *
+ * @param [in] group  EC group for point.
+ * @param [in] point  EC point to encode.
+ * @param [in] form   Format of encoding. Valid values:
+ *                    POINT_CONVERSION_UNCOMPRESSED, POINT_CONVERSION_COMPRESSED
+ * @param [in] ctx    Context to use for BN operations. Unused.
+ * @return  Allocated hex string on success.
+ * @return  NULL on error.
+ */
+char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group,
+    const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BN_CTX* ctx)
+{
+    static const char* hexDigit = "0123456789ABCDEF";
+    char* hex = NULL;
+    int id;
+    int i;
+    int sz = 0;
+    int len = 0;
+    int err = 0;
+
+    /* No BN operations performed. */
+    (void)ctx;
+
+    /* Validate parameters. */
+    if ((group == NULL) || (point == NULL)) {
+        err = 1;
+    }
+    /* Get curve id expects a positive index. */
+    if ((!err) && (group->curve_idx < 0)) {
+        err = 1;
     }
 
-    if (p->Y != NULL && SetIndividualInternalEcc(p->Y, point->y)
-                                                           != 1) {
-        WOLFSSL_MSG("ecc point Y error");
-        return -1;
+    if (!err) {
+        /* Get curve id to look up ordinate size. */
+        id = wc_ecc_get_curve_id(group->curve_idx);
+        /* Get size of ordinate. */
+        if ((sz = wc_ecc_get_curve_size_from_id(id)) < 0) {
+            err = 1;
+        }
     }
+    if (!err) {
+        /* <format byte> <x-ordinate> [<y-ordinate>] */
+        len = sz + 1;
+        if (form == POINT_CONVERSION_UNCOMPRESSED) {
+            /* Include y ordinate when uncompressed. */
+            len += sz;
+        }
 
-    if (p->Z != NULL && SetIndividualInternalEcc(p->Z, point->z)
-                                                           != 1) {
-        WOLFSSL_MSG("ecc point Z error");
-        return -1;
+        /* Hex string: allocate 2 bytes to represent each byte plus 1 for '\0'.
+         */
+        hex = (char*)XMALLOC(2 * len + 1, NULL, DYNAMIC_TYPE_ECC);
+        if (hex == NULL) {
+            err = 1;
+        }
     }
-#endif
+    if (!err) {
+        /* Make bytes all zeros to allow for ordinate values less than max size.
+         */
+        XMEMSET(hex, 0, 2 * len + 1);
 
-    p->inSet = 1;
+        /* Calculate offset as leading zeros not encoded. */
+        i = sz - mp_unsigned_bin_size((mp_int*)point->X->internal) + 1;
+        /* Put in x-ordinate after format byte. */
+        if (mp_to_unsigned_bin((mp_int*)point->X->internal, (byte*)(hex + i)) <
+                0) {
+            err = 1;
+        }
+    }
+    if (!err) {
+        if (form == POINT_CONVERSION_COMPRESSED) {
+            /* Compressed format byte value dependent on whether y-ordinate is
+             * odd.
+             */
+            hex[0] = mp_isodd((mp_int*)point->Y->internal) ?
+                ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;
+            /* No y-ordinate. */
+        }
+        else {
+            /* Put in uncompressed format byte. */
+            hex[0] = ECC_POINT_UNCOMP;
+            /* Calculate offset as leading zeros not encoded. */
+            i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal);
+            /* Put in y-ordinate after x-ordinate. */
+            if (mp_to_unsigned_bin((mp_int*)point->Y->internal,
+                    (byte*)(hex + i)) < 0) {
+                err = 1;
+            }
+        }
+    }
+    if (!err) {
+        /* Convert binary encoding to hex string. */
+        /* Start at end so as not to overwrite. */
+        for (i = len-1; i >= 0; i--) {
+            /* Get byte value and store has hex string. */
+            byte b = (byte)hex[i];
+            hex[i * 2 + 1] = hexDigit[b  & 0xf];
+            hex[i * 2    ] = hexDigit[b >>   4];
+        }
+        /* Memset put trailing zero or '\0' on end of string. */
+    }
 
-    return 1;
+    if (err && (hex != NULL)) {
+        /* Dispose of allocated data not being returned. */
+        XFREE(hex,  NULL, DYNAMIC_TYPE_ECC);
+        hex = NULL;
+    }
+    /* Return hex string encoding. */
+    return hex;
 }
 
-/* EC_POINT WolfSSL -> OpenSSL */
-static int SetECPointExternal(WOLFSSL_EC_POINT *p)
+#endif /* HAVE_SELFTEST */
+
+/* Encode the EC point as an uncompressed point in DER.
+ *
+ * Return code compliant with OpenSSL.
+ * Not OpenSSL API.
+ *
+ * @param [in]      group  EC group point belongs to.
+ * @param [in]      point  EC point to encode.
+ * @param [out]     out    Buffer to encode into. May be NULL.
+ * @param [in, out] len    On in, length of buffer in bytes.
+ *                         On out, length of encoding in bytes.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group,
+    const WOLFSSL_EC_POINT *point, unsigned char *out, unsigned int *len)
 {
-    ecc_point* point;
+    int res = 1;
+    int ret;
 
-    WOLFSSL_ENTER("SetECPointExternal");
+    WOLFSSL_ENTER("wolfSSL_ECPoint_i2d");
 
-    if (p == NULL || p->internal == NULL) {
-        WOLFSSL_MSG("ECPoint NULL error");
-        return -1;
+    /* Validate parameters. */
+    if ((group == NULL) || (point == NULL) || (len == NULL)) {
+        WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error");
+        res = 0;
     }
 
-    point = (ecc_point*)p->internal;
-
-    if (SetIndividualExternal(&p->X, point->x) != 1) {
-        WOLFSSL_MSG("ecc point X error");
-        return -1;
+    /* Ensure points internals are set up. */
+    if ((res == 1) && (ec_point_setup(point) != 1)) {
+        res = 0;
     }
 
-    if (SetIndividualExternal(&p->Y, point->y) != 1) {
-        WOLFSSL_MSG("ecc point Y error");
-        return -1;
+    /* Dump the point if encoding. */
+    if ((res == 1) && (out != NULL)) {
+        wolfSSL_EC_POINT_dump("i2d p", point);
     }
 
-    if (SetIndividualExternal(&p->Z, point->z) != 1) {
-        WOLFSSL_MSG("ecc point Z error");
-        return -1;
+    if (res == 1) {
+        /* DER encode point in uncompressed format. */
+        ret = wc_ecc_export_point_der(group->curve_idx,
+            (ecc_point*)point->internal, out, len);
+        /* Check return. When out is NULL, return will be length only error. */
+        if ((ret != MP_OKAY) && ((out != NULL) || (ret != LENGTH_ONLY_E))) {
+            WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed");
+            res = 0;
+        }
     }
 
-    p->exSet = 1;
-
-    return 1;
+    return res;
 }
 
-
-/* EC_KEY wolfSSL -> OpenSSL */
-int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
+/* Decode the uncompressed point in DER into EC point.
+ *
+ * Return code compliant with OpenSSL.
+ * Not OpenSSL API.
+ *
+ * @param [in]      in     Buffer containing DER encoded point.
+ * @param [in]      len    Length of data in bytes.
+ * @param [in]      group  EC group associated with point.
+ * @param [in, out] point  EC point to set data into.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+int wolfSSL_ECPoint_d2i(const unsigned char *in, unsigned int len,
+    const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *point)
 {
-    ecc_key* key;
+    int ret = 1;
 
-    WOLFSSL_ENTER("SetECKeyExternal");
+    WOLFSSL_ENTER("wolfSSL_ECPoint_d2i");
 
-    if (eckey == NULL || eckey->internal == NULL) {
-        WOLFSSL_MSG("ec key NULL error");
-        return -1;
+    /* Validate parameters. */
+    if ((in == NULL) || (group == NULL) || (point == NULL) ||
+            (point->internal == NULL)) {
+        WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error");
+        ret = 0;
     }
 
-    key = (ecc_key*)eckey->internal;
-
-    /* set group (OID, nid and idx) */
-    eckey->group->curve_oid = ecc_sets[key->idx].oidSum;
-    eckey->group->curve_nid = EccEnumToNID(ecc_sets[key->idx].id);
-    eckey->group->curve_idx = key->idx;
-
-    if (eckey->pub_key->internal != NULL) {
-        /* set the internal public key */
-        if (wc_ecc_copy_point(&key->pubkey,
-                             (ecc_point*)eckey->pub_key->internal) != MP_OKAY) {
-            WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed");
-            return -1;
+    if (ret == 1) {
+    #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+        /* Import point into internal EC point. */
+        if (wc_ecc_import_point_der_ex(in, len, group->curve_idx,
+                (ecc_point*)point->internal, 0) != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_import_point_der_ex failed");
+            ret = 0;
         }
-
-        /* set the external pubkey (point) */
-        if (SetECPointExternal(eckey->pub_key) != 1) {
-            WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed");
-            return -1;
+    #else
+        /* ECC_POINT_UNCOMP is not defined CAVP self test so use magic number */
+        if (in[0] == 0x04) {
+            /* Import point into internal EC point. */
+            if (wc_ecc_import_point_der((unsigned char *)in, len,
+                    group->curve_idx, (ecc_point*)point->internal) != MP_OKAY) {
+                WOLFSSL_MSG("wc_ecc_import_point_der failed");
+                ret = 0;
+            }
+        }
+        else {
+            WOLFSSL_MSG("Only uncompressed points supported with "
+                        "HAVE_SELFTEST");
+            ret = 0;
         }
+    #endif
     }
 
-    /* set the external privkey */
-    if (key->type == ECC_PRIVATEKEY) {
-        if (SetIndividualExternal(&eckey->priv_key, &key->k) != 1) {
-            WOLFSSL_MSG("ec priv key error");
-            return -1;
-        }
+    /* Set new external point. */
+    if ((ret == 1) && (ec_point_external_set(point) != 1)) {
+        WOLFSSL_MSG("ec_point_external_set failed");
+        ret = 0;
     }
 
-    eckey->exSet = 1;
+    if (ret == 1) {
+        /* Dump new point. */
+        wolfSSL_EC_POINT_dump("d2i p", point);
+    }
 
-    return 1;
+    return ret;
 }
 
-/* EC_KEY Openssl -> WolfSSL */
-int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
+/* Encode point as octet string.
+ *
+ * HYBRID not supported.
+ *
+ * @param [in]  group  EC group that point belongs to.
+ * @param [in]  point  EC point to encode.
+ * @param [in]  form   Format of encoding. Valid values:
+ *                     POINT_CONVERSION_UNCOMPRESSED,POINT_CONVERSION_COMPRESSED
+ * @param [out] buf    Buffer to write encoding into.
+ * @param [in]  len    Length of buffer.
+ * @param [in]  ctx    Context to use for BN operations. Unused.
+ * @return  Length of encoded data on success.
+ * @return  0 on error.
+ */
+size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
+   const WOLFSSL_EC_POINT *point, int form, byte *buf, size_t len,
+   WOLFSSL_BN_CTX *ctx)
 {
-    ecc_key* key;
-
-    WOLFSSL_ENTER("SetECKeyInternal");
+    int err = 0;
+    word32 enc_len = (word32)len;
+#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+    int compressed = ((form == POINT_CONVERSION_COMPRESSED) ? 1 : 0);
+#endif /* !HAVE_SELFTEST */
 
-    if (eckey == NULL || eckey->internal == NULL || eckey->group == NULL) {
-        WOLFSSL_MSG("ec key NULL error");
-        return -1;
-    }
+    WOLFSSL_ENTER("EC_POINT_point2oct");
 
-    key = (ecc_key*)eckey->internal;
+    /* No BN operations performed. */
+    (void)ctx;
 
-    /* validate group */
-    if ((eckey->group->curve_idx < 0) ||
-        (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) {
-        WOLFSSL_MSG("invalid curve idx");
-        return -1;
+    /* Validate parameters. */
+    if ((group == NULL) || (point == NULL)) {
+        err = 1;
     }
 
-    /* set group (idx of curve and corresponding domain parameters) */
-    key->idx = eckey->group->curve_idx;
-    key->dp = &ecc_sets[key->idx];
-
-    /* set pubkey (point) */
-    if (eckey->pub_key != NULL) {
-        if (SetECPointInternal(eckey->pub_key) != 1) {
-            WOLFSSL_MSG("ec key pub error");
-            return -1;
-        }
-
-        /* copy over the public point to key */
-        if (wc_ecc_copy_point((ecc_point*)eckey->pub_key->internal,
-                                                     &key->pubkey) != MP_OKAY) {
-            WOLFSSL_MSG("wc_ecc_copy_point error");
-            return -1;
-        }
-
-        /* public key */
-        key->type = ECC_PUBLICKEY;
+    /* Ensure points internals are set up. */
+    if ((!err) && (ec_point_setup(point) != 1)) {
+        err = 1;
     }
 
-    /* set privkey */
-    if (eckey->priv_key != NULL) {
-        if (SetIndividualInternal(eckey->priv_key, &key->k)
-                                                           != 1) {
-            WOLFSSL_MSG("ec key priv error");
-            return -1;
+    /* Special case when point is infinity. */
+    if ((!err) && wolfSSL_EC_POINT_is_at_infinity(group, point)) {
+        /* Encoding is a single octet: 0x00. */
+        enc_len = 1;
+        if (buf != NULL) {
+            /* Check whether buffer has space. */
+            if (len < 1) {
+                ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+                err = 1;
+            }
+            else {
+                /* Put in encoding of infinity. */
+                buf[0] = 0x00;
+            }
         }
-
-        /* private key */
-        if (!mp_iszero(&key->k))
-            key->type = ECC_PRIVATEKEY;
     }
+    /* Not infinity. */
+    else if (!err) {
+        int ret;
 
-    eckey->inSet = 1;
-
-    return 1;
-}
-
-WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key");
+        /* Validate format. */
+        if (form != POINT_CONVERSION_UNCOMPRESSED
+        #ifndef HAVE_SELFTEST
+                && form != POINT_CONVERSION_COMPRESSED
+        #endif /* !HAVE_SELFTEST */
+            ) {
+            WOLFSSL_MSG("Unsupported point form");
+            err = 1;
+        }
 
-    if (key == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_public_key Bad arguments");
-        return NULL;
+    #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+        if (!err) {
+            /* Encode as compressed or uncompressed. */
+            ret = wc_ecc_export_point_der_ex(group->curve_idx,
+                (ecc_point*)point->internal, buf, &enc_len, compressed);
+            /* Check return. When buf is NULL, return will be length only
+             * error.
+             */
+            if (ret != ((buf != NULL) ? MP_OKAY : LENGTH_ONLY_E)) {
+                err = 1;
+            }
+        }
+    #else
+        if (!err) {
+            /* Encode uncompressed point in DER format. */
+            ret = wc_ecc_export_point_der(group->curve_idx,
+                (ecc_point*)point->internal, buf, &enc_len);
+            /* Check return. When buf is NULL, return will be length only
+             * error.
+             */
+            if (ret != ((buf != NULL) ? MP_OKAY : LENGTH_ONLY_E)) {
+                err = 1;
+            }
+        }
+    #endif /* !HAVE_SELFTEST */
     }
 
-    return key->pub_key;
-}
-
-const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group");
-
-    if (key == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments");
-        return NULL;
+    /* On error, return encoding length of 0. */
+    if (err) {
+        enc_len = 0;
     }
-
-    return key->group;
+    return (size_t)enc_len;
 }
 
 
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
+/* Convert octet string to EC point.
+ *
+ * @param [in]      group  EC group.
+ * @param [in, out] point  EC point to set data into.
+ * @param [in]      buf    Buffer holding octet string.
+ * @param [in]      len    Length of data in buffer in bytes.
+ * @param [in]      ctx    Context to use for BN operations. Unused.
  */
-int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key,
-                                   const WOLFSSL_BIGNUM *priv_key)
+int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group,
+    WOLFSSL_EC_POINT *point, const unsigned char *buf, size_t len,
+    WOLFSSL_BN_CTX *ctx)
 {
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key");
+    int ret;
 
-    if (key == NULL || priv_key == NULL) {
-        WOLFSSL_MSG("Bad arguments");
-        return 0;
-    }
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
 
-    /* free key if previously set */
-    if (key->priv_key != NULL)
-        wolfSSL_BN_free(key->priv_key);
+    /* No BN operations performed. */
+    (void)ctx;
 
-    key->priv_key = wolfSSL_BN_dup(priv_key);
-    if (key->priv_key == NULL) {
-        WOLFSSL_MSG("key ecc priv key NULL");
-        return 0;
+    /* Validate parameters. */
+    if ((group == NULL) || (point == NULL)) {
+        ret = 0;
     }
-
-    if (SetECKeyInternal(key) != 1) {
-        WOLFSSL_MSG("SetECKeyInternal failed");
-        wolfSSL_BN_free(key->priv_key);
-        return 0;
+    else {
+        /* Decode DER encoding into EC point. */
+        ret = wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group,
+            point);
     }
 
-    return 1;
+    return ret;
 }
 
-
-WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key)
+/* Convert an EC point to a single BN.
+ *
+ * @param [in]      group  EC group.
+ * @param [in]      point  EC point.
+ * @param [in]      form   Format of encoding. Valid values:
+ *                         POINT_CONVERSION_UNCOMPRESSED,
+ *                         POINT_CONVERSION_COMPRESSED.
+ * @param [in, out] bn     BN to hold point value.
+ *                         When NULL a new BN is allocated otherwise this is
+ *                         returned on success.
+ * @param [in]      ctx    Context to use for BN operations. Unused.
+ * @return  BN object with point as a value on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP* group,
+    const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BIGNUM* bn,
+    WOLFSSL_BN_CTX* ctx)
 {
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key");
+    int err = 0;
+    size_t len = 0;
+    byte *buf = NULL;
+    WOLFSSL_BIGNUM *ret = NULL;
 
-    if (key == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments");
-        return NULL;
-    }
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
 
-    if (wolfSSL_BN_is_zero(key->priv_key)) {
-        /* return NULL if not set */
-        return NULL;
+    /* Validate parameters. */
+    if ((group == NULL) || (point == NULL)) {
+        err = 1;
     }
 
-    return key->priv_key;
-}
-
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid)
-{
-    WOLFSSL_EC_KEY *key;
-    int x;
-    int eccEnum = NIDToEccEnum(nid);
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name");
-
-    key = wolfSSL_EC_KEY_new();
-    if (key == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_new failure");
-        return NULL;
+    /* Calculate length of octet encoding. */
+    if ((!err) && ((len = wolfSSL_EC_POINT_point2oct(group, point, form, NULL,
+            0, ctx)) == 0)) {
+        err = 1;
     }
-
-    /* set the nid of the curve */
-    key->group->curve_nid = nid;
-
-    if (eccEnum != -1) {
-        /* search and set the corresponding internal curve idx */
-        for (x = 0; ecc_sets[x].size != 0; x++) {
-            if (ecc_sets[x].id == eccEnum) {
-                key->group->curve_idx = x;
-                key->group->curve_oid = ecc_sets[x].oidSum;
-                break;
-            }
-        }
-
-        /* if not found, we don't support this curve. */
-        if (ecc_sets[x].size == 0) {
-            wolfSSL_EC_KEY_free(key);
-            key = NULL;
-        }
+    /* Allocate buffer to hold octet encoding. */
+    if ((!err) && ((buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER)) ==
+            NULL)) {
+        WOLFSSL_MSG("malloc failed");
+        err = 1;
     }
-
-    return key;
-}
-
-const char* wolfSSL_EC_curve_nid2nist(int nid)
-{
-    const WOLF_EC_NIST_NAME* nist_name;
-    for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
-        if (nist_name->nid == nid) {
-            return nist_name->name;
-        }
+    /* Encode EC point as an octet string. */
+    if ((!err) && (wolfSSL_EC_POINT_point2oct(group, point, form, buf, len,
+            ctx) != len)) {
+        err = 1;
     }
-    return NULL;
-}
-
-/**
- * return nist curve id
- * @param name nist curve name
- * @return nist curve id when found, 0 when not found
- */
-int wolfSSL_EC_curve_nist2nid(const char* name)
-{
-    const WOLF_EC_NIST_NAME* nist_name;
-    for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
-        if (XSTRCMP(nist_name->name, name) == 0) {
-            return nist_name->nid;
-        }
+    /* Load BN with octet string data. */
+    if (!err) {
+        ret = wolfSSL_BN_bin2bn(buf, (int)len, bn);
     }
-    return 0;
-}
 
-static void InitwolfSSL_ECKey(WOLFSSL_EC_KEY* key)
-{
-    if (key) {
-        key->group    = NULL;
-        key->pub_key  = NULL;
-        key->priv_key = NULL;
-        key->internal = NULL;
-        key->inSet    = 0;
-        key->exSet    = 0;
-        key->form     = POINT_CONVERSION_UNCOMPRESSED;
-    }
+    /* Dispose of any allocated data. */
+    XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    return ret;
 }
 
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId)
+#if defined(USE_ECC_B_PARAM) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+/* Check if EC point is on the the curve defined by the EC group.
+ *
+ * @param [in] group  EC group defining curve.
+ * @param [in] point  EC point to check.
+ * @param [in] ctx    Context to use for BN operations. Unused.
+ * @return  1 when point is on curve.
+ * @return  0 when point is not on curve or error.
+ */
+int wolfSSL_EC_POINT_is_on_curve(const WOLFSSL_EC_GROUP *group,
+    const WOLFSSL_EC_POINT *point, WOLFSSL_BN_CTX *ctx)
 {
-    WOLFSSL_EC_KEY *external;
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_new");
-
-    external = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), heap,
-                                        DYNAMIC_TYPE_ECC);
-    if (external == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure");
-        return NULL;
-    }
-    XMEMSET(external, 0, sizeof(WOLFSSL_EC_KEY));
-    external->heap = heap;
-
-    InitwolfSSL_ECKey(external);
-
-    external->refCount = 1;
-#ifndef SINGLE_THREADED
-    if (wc_InitMutex(&external->refMutex) != 0) {
-        WOLFSSL_MSG("wc_InitMutex WOLFSSL_EC_KEY failure");
-        XFREE(external, heap, DYNAMIC_TYPE_ECC);
-        return NULL;
-    }
-#endif
+    int err = 0;
 
-    external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), heap,
-                                           DYNAMIC_TYPE_ECC);
-    if (external->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure");
-        goto error;
-    }
-    XMEMSET(external->internal, 0, sizeof(ecc_key));
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_is_on_curve");
 
-    if (wc_ecc_init_ex((ecc_key*)external->internal, heap, devId) != 0) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure");
-        goto error;
-    }
+    /* No BN operations performed. */
+    (void)ctx;
 
-    /* Group unknown at creation */
-    external->group = wolfSSL_EC_GROUP_new_by_curve_name(NID_undef);
-    if (external->group == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure");
-        goto error;
+    /* Validate parameters. */
+    if ((group == NULL) || (point == NULL)) {
+        WOLFSSL_MSG("Invalid arguments");
+        err = 1;
     }
 
-    /* public key */
-    external->pub_key = wolfSSL_EC_POINT_new(external->group);
-    if (external->pub_key == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_new failure");
-        goto error;
+    /* Ensure internal EC point set. */
+    if ((!err) && (!point->inSet) && ec_point_internal_set(
+            (WOLFSSL_EC_POINT*)point) != 1) {
+        WOLFSSL_MSG("ec_point_internal_set error");
+        err = 1;
     }
 
-    /* private key */
-    external->priv_key = wolfSSL_BN_new();
-    if (external->priv_key == NULL) {
-        WOLFSSL_MSG("wolfSSL_BN_new failure");
-        goto error;
+    /* Check point is on curve from group. */
+    if ((!err) && (wc_ecc_point_is_on_curve((ecc_point*)point->internal,
+            group->curve_idx) != MP_OKAY)) {
+        err = 1;
     }
 
-    return external;
-error:
-    wolfSSL_EC_KEY_free(external);
-    return NULL;
-}
-
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void)
-{
-    return wolfSSL_EC_KEY_new_ex(NULL, INVALID_DEVID);
+    /* Return boolean of on curve. No error means on curve. */
+    return !err;
 }
+#endif /* USE_ECC_B_PARAM && !(FIPS_VERSION <= 2) */
 
-void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key)
+#if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
+/* Convert Jacobian ordinates to affine.
+ *
+ * @param [in]      group  EC group.
+ * @param [in]      point  EC point to get co-ordinates from.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+static int ec_point_convert_to_affine(const WOLFSSL_EC_GROUP *group,
+    WOLFSSL_EC_POINT *point)
 {
-    int doFree = 0;
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_free");
+    int err = 0;
+    mp_digit mp;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* modulus;
+#else
+    mp_int modulus[1];
+#endif
 
-    if (key != NULL) {
-        void* heap = key->heap;
+#ifdef WOLFSSL_SMALL_STACK
+    /* Allocate memory for curve's prime modulus. */
+    modulus = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+    if (modulus == NULL) {
+        err = 1;
+    }
+#endif
+    /* Initialize the MP integer. */
+    if ((!err) && (mp_init(modulus) != MP_OKAY)) {
+        WOLFSSL_MSG("mp_init failed");
+        err = 1;
+    }
 
-    #ifndef SINGLE_THREADED
-        if (wc_LockMutex(&key->refMutex) != 0) {
-            WOLFSSL_MSG("Could not lock EC_KEY mutex");
-            return;
+    if (!err) {
+        /* Get the modulus from the hex string in the EC curve set. */
+        if (mp_read_radix(modulus, ecc_sets[group->curve_idx].prime,
+                MP_RADIX_HEX) != MP_OKAY) {
+            WOLFSSL_MSG("mp_read_radix failed");
+            err = 1;
         }
-    #endif
-
-        /* only free if all references to it are done */
-        key->refCount--;
-        if (key->refCount == 0) {
-            doFree = 1;
+        /* Get Montgomery multiplier for the modulus as ordinates in
+         * Montgomery form.
+         */
+        if ((!err) && (mp_montgomery_setup(modulus, &mp) != MP_OKAY)) {
+            WOLFSSL_MSG("mp_montgomery_setup failed");
+            err = 1;
         }
-    #ifndef SINGLE_THREADED
-        wc_UnLockMutex(&key->refMutex);
-    #endif
-
-        if (doFree == 0) {
-            return;
+        /* Map internal EC point from Jacobian to affine. */
+        if ((!err) && (ecc_map((ecc_point*)point->internal, modulus, mp) !=
+                MP_OKAY)) {
+            WOLFSSL_MSG("ecc_map failed");
+            err = 1;
         }
-
-    #ifndef SINGLE_THREADED
-        wc_FreeMutex(&key->refMutex);
-    #endif
-
-        if (key->internal != NULL) {
-            wc_ecc_free((ecc_key*)key->internal);
-            XFREE(key->internal, heap, DYNAMIC_TYPE_ECC);
+        /* Set new ordinates into external EC point. */
+        if ((!err) && (ec_point_external_set((WOLFSSL_EC_POINT *)point) != 1)) {
+            WOLFSSL_MSG("ec_point_external_set failed");
+            err = 1;
         }
-        wolfSSL_BN_free(key->priv_key);
-        wolfSSL_EC_POINT_free(key->pub_key);
-        wolfSSL_EC_GROUP_free(key->group);
-        InitwolfSSL_ECKey(key); /* set back to NULLs for safety */
 
-        XFREE(key, heap, DYNAMIC_TYPE_ECC);
-        (void)heap;
-        /* key = NULL, don't try to access or double free it */
+        point->exSet = !err;
+        mp_clear(modulus);
     }
-}
 
-/* Increments ref count of WOLFSSL_EC_KEY.
- * Return 1 on success, 0 on error */
-int wolfSSL_EC_KEY_up_ref(WOLFSSL_EC_KEY* key)
-{
-    if (key) {
-    #ifndef SINGLE_THREADED
-        if (wc_LockMutex(&key->refMutex) != 0) {
-            WOLFSSL_MSG("Failed to lock EC_KEY mutex");
-        }
-    #endif
-        key->refCount++;
-    #ifndef SINGLE_THREADED
-        wc_UnLockMutex(&key->refMutex);
-    #endif
-        return 1;
-    }
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
 
-    return 0;
+    return err;
 }
 
-/* set the group in WOLFSSL_EC_KEY and return 1 on success */
-int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group)
+/* Get the affine co-ordinates of the EC point on a Prime curve.
+ *
+ * When z-ordinate is not one then co-ordinates are Jacobian and need to be
+ * converted to affine before storing in BNs.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * TODO: OpenSSL doesn't change point when Jacobian. Do the same?
+ *
+ * @param [in]      group  EC group.
+ * @param [in]      point  EC point to get co-ordinates from.
+ * @param [in, out] x      BN to hold x-ordinate.
+ * @param [in, out] y      BN to hold y-ordinate.
+ * @param [in]      ctx    Context to use for BN operations. Unused.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP* group,
+    const WOLFSSL_EC_POINT* point, WOLFSSL_BIGNUM* x, WOLFSSL_BIGNUM* y,
+    WOLFSSL_BN_CTX* ctx)
 {
-    if (key == NULL || group == NULL)
-        return 0;
+    int ret = 1;
 
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group");
+    /* BN operations don't need context. */
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp");
 
-    if (key->group != NULL) {
-        /* free the current group */
-        wolfSSL_EC_GROUP_free(key->group);
+    /* Validate parameters. */
+    if ((group == NULL) || (point == NULL) || (point->internal == NULL) ||
+            (x == NULL) || (y == NULL)) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error");
+        ret = 0;
+    }
+    /* Don't return point at infinity. */
+    if ((ret == 1) && wolfSSL_EC_POINT_is_at_infinity(group, point)) {
+        ret = 0;
     }
 
-    key->group = wolfSSL_EC_GROUP_dup(group);
-    if (key->group == NULL) {
-        return 0;
+    /* Ensure internal EC point has values of external EC point. */
+    if ((ret == 1) && (ec_point_setup(point) != 1)) {
+        ret = 0;
     }
 
-    return 1;
-}
+    /* Check whether ordinates are in Jacobian form. */
+    if ((ret == 1) && (!wolfSSL_BN_is_one(point->Z))) {
+        /* Convert from Jacobian to affine. */
+        if (ec_point_convert_to_affine(group, (WOLFSSL_EC_POINT*)point) == 1) {
+            ret = 0;
+        }
+    }
 
+    /* Copy the externally set x and y ordinates. */
+    if ((ret == 1) && (BN_copy(x, point->X) == NULL)) {
+        ret = 0;
+    }
+    if ((ret == 1) && (BN_copy(y, point->Y) == NULL)) {
+        ret = 0;
+    }
 
-int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key)
+    return ret;
+}
+#endif /* !WOLFSSL_SP_MATH && !WOLF_CRYPTO_CB_ONLY_ECC */
+
+/* Sets the affine co-ordinates that belong on a prime curve.
+ *
+ * @param [in]      group  EC group.
+ * @param [in, out] point  EC point to set co-ordinates into.
+ * @param [in]      x      BN holding x-ordinate.
+ * @param [in]      y      BN holding y-ordinate.
+ * @param [in]      ctx    Context to use for BN operations. Unused.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group,
+    WOLFSSL_EC_POINT *point, const WOLFSSL_BIGNUM *x, const WOLFSSL_BIGNUM *y,
+    WOLFSSL_BN_CTX *ctx)
 {
-    int     initTmpRng = 0;
-    int     eccEnum;
-    WC_RNG* rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG* tmpRng = NULL;
-#else
-    WC_RNG  tmpRng[1];
-#endif
-    int ret;
-    ecc_key* ecKey;
+    int ret = 1;
 
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key");
+    /* BN operations don't need context. */
+    (void)ctx;
 
-    if (key == NULL || key->internal == NULL ||
-        key->group == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments");
-        return 0;
-    }
-    if (key->group->curve_idx < 0) {
-        /* generate key using the default curve */
-        /* group should be set, but to retain compat use index 0 */
-        key->group->curve_idx = ECC_CURVE_DEF;
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_set_affine_coordinates_GFp");
+
+    /* Validate parameters. */
+    if ((group == NULL) || (point == NULL) || (point->internal == NULL) ||
+            (x == NULL) || (y == NULL)) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp NULL error");
+        ret = 0;
     }
 
-#ifdef WOLFSSL_SMALL_STACK
-    tmpRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    if (tmpRng == NULL)
-        return 0;
-#endif
+    /* Ensure we have a object for x-ordinate. */
+    if ((ret == 1) && (point->X == NULL) &&
+            ((point->X = wolfSSL_BN_new()) == NULL)) {
+        WOLFSSL_MSG("wolfSSL_BN_new failed");
+        ret = 0;
+    }
+    /* Ensure we have a object for y-ordinate. */
+    if ((ret == 1) && (point->Y == NULL) &&
+            ((point->Y = wolfSSL_BN_new()) == NULL)) {
+        WOLFSSL_MSG("wolfSSL_BN_new failed");
+        ret = 0;
+    }
+    /* Ensure we have a object for z-ordinate. */
+    if ((ret == 1) && (point->Z == NULL) &&
+            ((point->Z = wolfSSL_BN_new()) == NULL)) {
+        WOLFSSL_MSG("wolfSSL_BN_new failed");
+        ret = 0;
+    }
 
-    if (wc_InitRng(tmpRng) == 0) {
-        rng = tmpRng;
-        initTmpRng = 1;
+    /* Copy the x-ordinate. */
+    if ((ret == 1) && ((wolfSSL_BN_copy(point->X, x)) == NULL)) {
+        WOLFSSL_MSG("wolfSSL_BN_copy failed");
+        ret = 0;
     }
-    else {
-        WOLFSSL_MSG("Bad RNG Init, trying global");
-        rng = wolfssl_get_global_rng();
+    /* Copy the y-ordinate. */
+    if ((ret == 1) && ((wolfSSL_BN_copy(point->Y, y)) == NULL)) {
+        WOLFSSL_MSG("wolfSSL_BN_copy failed");
+        ret = 0;
+    }
+    /* z-ordinate is one for affine co-ordinates. */
+    if ((ret == 1) && ((wolfSSL_BN_one(point->Z)) == 0)) {
+        WOLFSSL_MSG("wolfSSL_BN_one failed");
+        ret = 0;
     }
 
-    if (rng == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG");
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-#endif
-        return 0;
+    /* Copy the new point data to internal object. */
+    if ((ret == 1) && (ec_point_internal_set((WOLFSSL_EC_POINT *)point) != 1)) {
+        WOLFSSL_MSG("ec_point_internal_set failed");
+        ret = 0;
     }
 
-    /* NIDToEccEnum returns -1 for invalid NID so if key->group->curve_nid
-     * is 0 then pass ECC_CURVE_DEF as arg */
-    ecKey = (ecc_key*)key->internal;
-    eccEnum = key->group->curve_nid ?
-            NIDToEccEnum(key->group->curve_nid) : ECC_CURVE_DEF;
-    ret = wc_ecc_make_key_ex(rng, 0, ecKey, eccEnum);
-#if defined(WOLFSSL_ASYNC_CRYPT)
-    ret = wc_AsyncWait(ret, &ecKey->asyncDev, WC_ASYNC_FLAG_NONE);
-#endif
+    return ret;
+}
 
-    if (ret != 0) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed");
+#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
+    !defined(HAVE_SELFTEST) && !defined(WOLFSSL_SP_MATH) && \
+    !defined(WOLF_CRYPTO_CB_ONLY_ECC)
+/* Add two points on the same together.
+ *
+ * @param [in]  curveIdx  Index of curve in ecc_set.
+ * @oaram [out] r         Result point.
+ * @param [in]  p1        First point to add.
+ * @param [in]  p2        Second point to add.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+static int wolfssl_ec_point_add(int curveIdx, ecc_point* r, ecc_point* p1,
+    ecc_point* p2)
+{
+    int ret = 1;
 #ifdef WOLFSSL_SMALL_STACK
-        XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
+    mp_int* a = NULL;
+    mp_int* prime = NULL;
+    mp_int* mu = NULL;
+#else
+    mp_int a[1];
+    mp_int prime[1];
+    mp_int mu[1];
 #endif
-        return 0;
-    }
+    mp_digit mp = 0;
+    ecc_point* montP1 = NULL;
+    ecc_point* montP2 = NULL;
 
-    if (initTmpRng)
-        wc_FreeRng(tmpRng);
 #ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
+    if (ret == 1) {
+        /* Allocate memory for curve parameter: a. */
+        a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+        if (a == NULL) {
+            WOLFSSL_MSG("Failed to allocate memory for mp_int a");
+            ret = 0;
+        }
+    }
+    if (ret == 1) {
+        /* Allocate memory for curve parameter: prime. */
+        prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+        if (prime == NULL) {
+            WOLFSSL_MSG("Failed to allocate memory for mp_int prime");
+            ret = 0;
+        }
+    }
+    if (ret == 1) {
+        /* Allocate memory for mu (Montgomery normalizer). */
+        mu = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+        if (mu == NULL) {
+            WOLFSSL_MSG("Failed to allocate memory for mp_int mu");
+            ret = 0;
+        }
+    }
+    if (ret == 1) {
+        /* Zero out all MP int data in case initialization fails. */
+        XMEMSET(a, 0, sizeof(mp_int));
+        XMEMSET(prime, 0, sizeof(mp_int));
+        XMEMSET(mu, 0, sizeof(mp_int));
+    }
 #endif
 
-    if (SetECKeyExternal(key) != 1) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed");
-        return 0;
+    /* Initialize the MP ints. */
+    if ((ret == 1) && (mp_init_multi(prime, a, mu, NULL, NULL, NULL) !=
+            MP_OKAY)) {
+        WOLFSSL_MSG("mp_init_multi error");
+        ret = 0;
     }
 
-    return 1;
-}
-
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag)
-{
-    (void)key;
-    (void)asn1_flag;
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag");
-    WOLFSSL_STUB("EC_KEY_set_asn1_flag");
-}
-#endif
+    /* Read the curve parameter: a. */
+    if ((ret == 1) && (mp_read_radix(a, ecc_sets[curveIdx].Af, MP_RADIX_HEX) !=
+            MP_OKAY)) {
+        WOLFSSL_MSG("mp_read_radix a error");
+        ret = 0;
+    }
 
-static int setupPoint(const WOLFSSL_EC_POINT *p) {
-    if (!p) {
-        return 0;
+    /* Read the curve parameter: prime. */
+    if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime,
+            MP_RADIX_HEX) != MP_OKAY)) {
+        WOLFSSL_MSG("mp_read_radix prime error");
+        ret = 0;
     }
-    if (p->inSet == 0) {
-        WOLFSSL_MSG("No ECPoint internal set, do it");
 
-        if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != 1) {
-            WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed");
-            return 0;
-        }
+    /* Calculate the Montgomery product. */
+    if ((ret == 1) && (mp_montgomery_setup(prime, &mp) != MP_OKAY)) {
+        WOLFSSL_MSG("mp_montgomery_setup nqm error");
+        ret = 0;
     }
-    return 1;
-}
 
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key,
-                                  const WOLFSSL_EC_POINT *pub)
-{
-    ecc_point *pub_p, *key_p;
+    /* TODO: use the heap filed of one of the points? */
+    /* Allocate new points to hold the Montgomery form values. */
+    if ((ret == 1) && (((montP1 = wc_ecc_new_point_h(NULL)) == NULL) ||
+            ((montP2 = wc_ecc_new_point_h(NULL)) == NULL))) {
+        WOLFSSL_MSG("wc_ecc_new_point_h nqm error");
+        ret = 0;
+    }
 
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key");
+    /* Calculate the Montgomery normalizer. */
+    if ((ret == 1) && (mp_montgomery_calc_normalization(mu, prime) !=
+            MP_OKAY)) {
+        WOLFSSL_MSG("mp_montgomery_calc_normalization error");
+        ret = 0;
+    }
 
-    if (key == NULL || key->internal == NULL ||
-        pub == NULL || pub->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_set_public_key Bad arguments");
-        return 0;
+    /* Convert to Montgomery form. */
+    if ((ret == 1) && (mp_cmp_d(mu, 1) == MP_EQ)) {
+        /* Copy the points if the normalizer is 1.  */
+        if ((wc_ecc_copy_point(p1, montP1) != MP_OKAY) ||
+                (wc_ecc_copy_point(p2, montP2) != MP_OKAY)) {
+            WOLFSSL_MSG("wc_ecc_copy_point error");
+            ret = 0;
+        }
     }
-
-    if (key->inSet == 0) {
-        if (SetECKeyInternal(key) != 1) {
-            WOLFSSL_MSG("SetECKeyInternal failed");
-            return 0;
+    else if (ret == 1) {
+        /* Multiply each ordinate by the Montgomery normalizer.  */
+        if ((mp_mulmod(p1->x, mu, prime, montP1->x) != MP_OKAY) ||
+                (mp_mulmod(p1->y, mu, prime, montP1->y) != MP_OKAY) ||
+                (mp_mulmod(p1->z, mu, prime, montP1->z) != MP_OKAY)) {
+            WOLFSSL_MSG("mp_mulmod error");
+            ret = 0;
+        }
+        /* Multiply each ordinate by the Montgomery normalizer.  */
+        if ((mp_mulmod(p2->x, mu, prime, montP2->x) != MP_OKAY) ||
+                (mp_mulmod(p2->y, mu, prime, montP2->y) != MP_OKAY) ||
+                (mp_mulmod(p2->z, mu, prime, montP2->z) != MP_OKAY)) {
+            WOLFSSL_MSG("mp_mulmod error");
+            ret = 0;
         }
     }
 
-    if (setupPoint(pub) != 1) {
-        return 0;
+    /* Perform point addition with internal EC point objects - Jacobian form
+     * result.
+     */
+    if ((ret == 1) && (ecc_projective_add_point(montP1, montP2, r, a, prime,
+            mp) != MP_OKAY)) {
+        WOLFSSL_MSG("ecc_projective_add_point error");
+        ret = 0;
     }
 
-    pub_p = (ecc_point*)pub->internal;
-    key_p = (ecc_point*)key->pub_key->internal;
+    /* Map point back to affine co-ordinates. Converts from Montogomery form. */
+    if ((ret == 1) && (ecc_map(r, prime, mp) != MP_OKAY)) {
+        WOLFSSL_MSG("ecc_map error");
+        ret = 0;
+    }
 
-    /* create new point if required */
-    if (key_p == NULL)
-        key_p = wc_ecc_new_point();
+    /* Dispose of allocated memory. */
+    mp_clear(a);
+    mp_clear(prime);
+    mp_clear(mu);
+    wc_ecc_del_point_h(montP1, NULL);
+    wc_ecc_del_point_h(montP2, NULL);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
+    XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
+    XFREE(mu, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+    return ret;
+}
 
-    if (key_p == NULL) {
-        WOLFSSL_MSG("key ecc point NULL");
-        return 0;
-    }
+/* Add two points on the same curve together.
+ *
+ * @param [in]  group  EC group.
+ * @param [out] r      EC point that is result of point addition.
+ * @param [in]  p1     First EC point to add.
+ * @param [in]  p2     Second EC point to add.
+ * @param [in]  ctx    Context to use for BN operations. Unused.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+int wolfSSL_EC_POINT_add(const WOLFSSL_EC_GROUP* group, WOLFSSL_EC_POINT* r,
+    const WOLFSSL_EC_POINT* p1, const WOLFSSL_EC_POINT* p2, WOLFSSL_BN_CTX* ctx)
+{
+    int ret = 1;
 
-    if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) {
-        WOLFSSL_MSG("ecc_copy_point failure");
-        return 0;
-    }
+    /* No BN operations performed. */
+    (void)ctx;
 
-    if (SetECPointExternal(key->pub_key) != 1) {
-        WOLFSSL_MSG("SetECKeyInternal failed");
-        return 0;
+    /* Validate parameters. */
+    if ((group == NULL) || (r == NULL) || (p1 == NULL) || (p2 == NULL)) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_add error");
+        ret = 0;
     }
 
-    if (SetECKeyInternal(key) != 1) {
-        WOLFSSL_MSG("SetECKeyInternal failed");
-        return 0;
+    /* Ensure the internal objects of the EC points are setup. */
+    if ((ret == 1) && ((ec_point_setup(r) != 1) || (ec_point_setup(p1) != 1) ||
+            (ec_point_setup(p2) != 1))) {
+        WOLFSSL_MSG("ec_point_setup error");
+        ret = 0;
     }
 
-    wolfSSL_EC_POINT_dump("pub", pub);
-    wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key);
-
-    return 1;
-}
-
-int wolfSSL_EC_KEY_check_key(const WOLFSSL_EC_KEY *key)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_check_key");
-
-    if (key == NULL || key->internal == NULL) {
-        WOLFSSL_MSG("Bad parameter");
-        return 0;
+    if (ret == 1) {
+        /* Add points using wolfCrypt objects. */
+        ret = wolfssl_ec_point_add(group->curve_idx, (ecc_point*)r->internal,
+            (ecc_point*)p1->internal, (ecc_point*)p2->internal);
     }
 
-    if (key->inSet == 0) {
-        if (SetECKeyInternal((WOLFSSL_EC_KEY*)key) != 1) {
-            WOLFSSL_MSG("SetECKeyInternal failed");
-            return 0;
-        }
+    /* Copy internal EC point values out to external EC point. */
+    if ((ret == 1) && (ec_point_external_set(r) != 1)) {
+        WOLFSSL_MSG("ec_point_external_set error");
+        ret = 0;
     }
 
-    return wc_ecc_check_key((ecc_key*)key->internal) == 0 ?
-            1 : 0;
+    return ret;
 }
-/* End EC_KEY */
 
-/* Calculate and return maximum size of the ECDSA signature for the curve */
-int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key)
+/* Sum the scalar multiplications of the base point and n, and q and m.
+ *
+ * r = base point * n + q * m
+ *
+ * @param [out] r      EC point that is result of operation.
+ * @param [in]  b      Base point of curve.
+ * @param [in]  n      Scalar to multiply by base point.
+ * @param [in]  q      EC point to be scalar multiplied.
+ * @param [in]  m      Scalar to multiply q by.
+ * @param [in]  a      Parameter A of curve.
+ * @param [in]  prime  Prime (modulus) of curve.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+static int ec_mul2add(ecc_point* r, ecc_point* b, mp_int* n, ecc_point* q,
+    mp_int* m, mp_int* a, mp_int* prime)
 {
-    const EC_GROUP *group;
-    int bits, bytes;
-    word32 headerSz = SIG_HEADER_SZ; /* 2*ASN_TAG + 2*LEN(ENUM) */
-
-    if (key == NULL) {
-        return 0;
+    int ret = 1;
+#if defined(ECC_SHAMIR) && !defined(WOLFSSL_KCAPI_ECC)
+    if (ecc_mul2add(b, n, q, m, r, a, prime, NULL) != MP_OKAY) {
+        WOLFSSL_MSG("ecc_mul2add error");
+        ret = 0;
     }
+#else
+    ecc_point* tmp = NULL;
+    mp_digit mp = 0;
 
-    if ((group = wolfSSL_EC_KEY_get0_group(key)) == NULL) {
-        return 0;
+    /* Calculate Montgomery product. */
+    if (mp_montgomery_setup(prime, &mp) != MP_OKAY) {
+        WOLFSSL_MSG("mp_montgomery_setup nqm error");
+        ret = 0;
     }
-    if ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0) {
-        /* group is not set */
-        return 0;
+    /* Create temporary point to hold: q * m */
+    if ((ret == 1) && ((tmp = wc_ecc_new_point()) == NULL)) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_new nqm error");
+        ret = 0;
+    }
+    /* r = base point * n */
+    if ((ret == 1) && (wc_ecc_mulmod(n, b, r, a, prime, 0) !=
+            MP_OKAY)) {
+        WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+        ret = 0;
+    }
+    /* tmp = q * m */
+    if ((ret == 1) && (wc_ecc_mulmod(m, q, tmp, a, prime, 0) != MP_OKAY)) {
+        WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+        ret = 0;
+    }
+    /* r = r + tmp */
+    if ((ret == 1) && (ecc_projective_add_point(tmp, r, r, a, prime, mp) !=
+            MP_OKAY)) {
+        WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+        ret = 0;
+    }
+    /* Map point back to affine co-ordinates. Converts from Montogomery
+     * form. */
+    if ((ret == 1) && (ecc_map(r, prime, mp) != MP_OKAY)) {
+        WOLFSSL_MSG("ecc_map nqm error");
+        ret = 0;
     }
 
-    bytes = (bits + 7) / 8;  /* bytes needed to hold bits */
-    return headerSz +
-            ECC_MAX_PAD_SZ + /* possible leading zeroes in r and s */
-            bytes + bytes;   /* r and s */
+    /* Dispose of allocated temporary point. */
+    wc_ecc_del_point(tmp);
+#endif
+
+    return ret;
 }
 
-int wolfSSL_ECDSA_sign(int type,
-    const unsigned char *digest, int digestSz,
-    unsigned char *sig, unsigned int *sigSz, WOLFSSL_EC_KEY *key)
+/* Sum the scalar multiplications of the base point and n, and q and m.
+ *
+ * r = base point * n + q * m
+ *
+ * @param [in]  curveIdx  Index of curve in ecc_set.
+ * @param [out] r         EC point that is result of operation.
+ * @param [in]  n         Scalar to multiply by base point. May be NULL.
+ * @param [in]  q         EC point to be scalar multiplied. May be NULL.
+ * @param [in]  m         Scalar to multiply q by. May be NULL.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+static int wolfssl_ec_point_mul(int curveIdx, ecc_point* r, mp_int* n,
+    ecc_point* q, mp_int* m)
 {
     int ret = 1;
-    WC_RNG* rng = NULL;
 #ifdef WOLFSSL_SMALL_STACK
-    WC_RNG* tmpRng = NULL;
+    mp_int* a = NULL;
+    mp_int* prime = NULL;
 #else
-    WC_RNG  tmpRng[1];
+    mp_int a[1], prime[1];
 #endif
-    int initTmpRng = 0;
 
-    WOLFSSL_ENTER("wolfSSL_ECDSA_sign");
+#ifdef WOLFSSL_SMALL_STACK
+    /* Allocate MP integer for curve parameter: a. */
+    a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+    if (a == NULL) {
+        ret = 0;
+    }
+    if (ret == 1) {
+        /* Allocate MP integer for curve parameter: prime. */
+        prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+        if (prime == NULL)  {
+            ret = 0;
+        }
+    }
+#endif
 
-    if (!key) {
-        return 0;
+    /* Initialize the MP ints. */
+    if ((ret == 1) && (mp_init_multi(prime, a, NULL, NULL, NULL, NULL) !=
+             MP_OKAY)) {
+        WOLFSSL_MSG("mp_init_multi error");
+        ret = 0;
     }
 
-#ifdef WOLFSSL_SMALL_STACK
-    tmpRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    if (tmpRng == NULL)
-        return 0;
-#endif
+    /* Read the curve parameter: prime. */
+    if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime,
+            MP_RADIX_HEX) != MP_OKAY)) {
+        WOLFSSL_MSG("mp_read_radix prime error");
+        ret = 0;
+    }
 
-    if (wc_InitRng(tmpRng) == 0) {
-        rng = tmpRng;
-        initTmpRng = 1;
+    /* Read the curve parameter: a. */
+    if ((ret == 1) && (mp_read_radix(a, ecc_sets[curveIdx].Af,
+            MP_RADIX_HEX) != MP_OKAY)) {
+        WOLFSSL_MSG("mp_read_radix a error");
+        ret = 0;
     }
-    else {
-        WOLFSSL_MSG("Bad RNG Init, trying global");
-        rng = wolfssl_get_global_rng();
+
+    if ((ret == 1) && (n != NULL)) {
+        /* Get generator - base point. */
+    #if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
+        if ((ret == 1) && (wc_ecc_get_generator(r, curveIdx) != MP_OKAY)) {
+            WOLFSSL_MSG("wc_ecc_get_generator error");
+            ret = 0;
+        }
+    #else
+        /* wc_ecc_get_generator is not defined in the FIPS v2 module. */
+        /* Read generator (base point) x-ordinate. */
+        if ((ret == 1) && (mp_read_radix(r->x, ecc_sets[curveIdx].Gx,
+                MP_RADIX_HEX) != MP_OKAY)) {
+            WOLFSSL_MSG("mp_read_radix Gx error");
+            ret = 0;
+        }
+        /* Read generator (base point) y-ordinate. */
+        if ((ret == 1) && (mp_read_radix(r->y, ecc_sets[curveIdx].Gy,
+                MP_RADIX_HEX) != MP_OKAY)) {
+            WOLFSSL_MSG("mp_read_radix Gy error");
+            ret = 0;
+        }
+        /* z-ordinate is one as point is affine. */
+        if ((ret == 1) && (mp_set(r->z, 1) != MP_OKAY)) {
+            WOLFSSL_MSG("mp_set Gz error");
+            ret = 0;
+        }
+    #endif /* NOPT_FIPS_VERSION == 2 */
     }
-    if (rng) {
-        if (wc_ecc_sign_hash(digest, digestSz, sig, sigSz, rng,
-                (ecc_key*)key->internal) != 0) {
+
+    if ((ret == 1) && (n != NULL) && (q != NULL) && (m != NULL)) {
+        /* r = base point * n + q * m */
+        ec_mul2add(r, r, m, q, n, a, prime);
+    }
+    /* Not all values present, see if we are only doing base point * n. */
+    else if ((ret == 1) && (n != NULL)) {
+        /* r = base point * n */
+        if (wc_ecc_mulmod(n, r, r, a, prime, 1) != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_mulmod gn error");
             ret = 0;
         }
-        if (initTmpRng) {
-            wc_FreeRng(tmpRng);
+    }
+    /* Not all values present, see if we are only doing q * m. */
+    else if ((ret == 1) && (q != NULL) && (m != NULL)) {
+        /* r = q * m */
+        if (wc_ecc_mulmod(m, q, r, a, prime, 1) != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_mulmod qm error");
+            ret = 0;
         }
-    } else {
-        ret = 0;
+    }
+    /* No values to use. */
+    else if (ret == 1) {
+        /* Set result to infinity as no values passed in. */
+        mp_zero(r->x);
+        mp_zero(r->y);
+        mp_zero(r->z);
     }
 
+    mp_clear(a);
+    mp_clear(prime);
 #ifdef WOLFSSL_SMALL_STACK
-    if (tmpRng)
-        XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
+    XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
+    XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
 #endif
-
-    (void)type;
     return ret;
 }
 
-int wolfSSL_ECDSA_verify(int type,
-    const unsigned char *digest, int digestSz,
-    const unsigned char *sig, int sigSz, WOLFSSL_EC_KEY *key)
+/* Sum the scalar multiplications of the base point and n, and q and m.
+ *
+ * r = base point * n + q * m
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in]  group  EC group.
+ * @param [out] r      EC point that is result of operation.
+ * @param [in]  n      Scalar to multiply by base point. May be NULL.
+ * @param [in]  q      EC point to be scalar multiplied. May be NULL.
+ * @param [in]  m      Scalar to multiply q by. May be NULL.
+ * @param [in]  ctx    Context to use for BN operations. Unused.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r,
+    const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q, const WOLFSSL_BIGNUM *m,
+    WOLFSSL_BN_CTX *ctx)
 {
     int ret = 1;
-    int verify = 0;
 
-    WOLFSSL_ENTER("wolfSSL_ECDSA_verify");
+    /* No BN operations performed. */
+    (void)ctx;
 
-    if (key == NULL) {
-        return 0;
-    }
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_mul");
 
-    if (wc_ecc_verify_hash(sig, sigSz, digest, digestSz,
-            &verify, (ecc_key*)key->internal) != 0) {
+    /* Validate parameters. */
+    if ((group == NULL) || (r == NULL)) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error");
         ret = 0;
     }
-    if (ret == 1 && verify != 1) {
-        WOLFSSL_MSG("wolfSSL_ECDSA_verify failed");
+
+    /* Ensure the internal representation of the EC point q is setup. */
+    if ((ret == 1) && (q != NULL) && (ec_point_setup(q) != 1)) {
+        WOLFSSL_MSG("ec_point_setup error");
         ret = 0;
     }
 
-    (void)type;
-    return ret;
-}
-
-#ifndef HAVE_SELFTEST
-/* ECC point compression types were not included in selftest ecc.h */
-
-char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group,
-                                 const WOLFSSL_EC_POINT* point, int form,
-                                 WOLFSSL_BN_CTX* ctx)
-{
-    static const char* hexDigit = "0123456789ABCDEF";
-    char* hex = NULL;
-    int id;
-    int i, sz, len;
-
-    (void)ctx;
-
-    if (group == NULL || point == NULL)
-        return NULL;
-
-    id = wc_ecc_get_curve_id(group->curve_idx);
-
-    if ((sz = wc_ecc_get_curve_size_from_id(id)) < 0)
-        return NULL;
-
-    len = sz + 1;
-    if (form == POINT_CONVERSION_UNCOMPRESSED)
-        len += sz;
-    hex = (char*)XMALLOC(2 * len + 1, NULL, DYNAMIC_TYPE_ECC);
-    if (hex == NULL)
-        return NULL;
-    XMEMSET(hex, 0, 2 * len + 1);
+    if (ret == 1) {
+        mp_int* ni = (n != NULL) ? (mp_int*)n->internal : NULL;
+        ecc_point* qi = (q != NULL) ? (ecc_point*)q->internal : NULL;
+        mp_int* mi = (m != NULL) ? (mp_int*)m->internal : NULL;
 
-    /* Put in x-ordinate after format byte. */
-    i = sz - mp_unsigned_bin_size((mp_int*)point->X->internal) + 1;
-    if (mp_to_unsigned_bin((mp_int*)point->X->internal, (byte*)(hex + i)) < 0) {
-        XFREE(hex,  NULL, DYNAMIC_TYPE_ECC);
-        return NULL;
+        /* Perform multiplication with wolfCrypt objects. */
+        ret = wolfssl_ec_point_mul(group->curve_idx, (ecc_point*)r->internal,
+            ni, qi, mi);
     }
 
-    if (form == POINT_CONVERSION_COMPRESSED) {
-        hex[0] = mp_isodd((mp_int*)point->Y->internal) ? ECC_POINT_COMP_ODD :
-                                                         ECC_POINT_COMP_EVEN;
-    }
-    else {
-        hex[0] = ECC_POINT_UNCOMP;
-        /* Put in y-ordinate after x-ordinate */
-        i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal);
-        if (mp_to_unsigned_bin((mp_int*)point->Y->internal,
-                                                        (byte*)(hex + i)) < 0) {
-            XFREE(hex,  NULL, DYNAMIC_TYPE_ECC);
-            return NULL;
-        }
+    /* Only on success is the internal point guaranteed to be set. */
+    if (r != NULL) {
+        r->inSet = (ret == 1);
     }
-
-    for (i = len-1; i >= 0; i--) {
-        byte b = hex[i];
-        hex[i * 2 + 1] = hexDigit[b  & 0xf];
-        hex[i * 2    ] = hexDigit[b >>   4];
+    /* Copy internal EC point values out to external EC point. */
+    if ((ret == 1) && (ec_point_external_set(r) != 1)) {
+        WOLFSSL_MSG("ec_point_external_set error");
+        ret = 0;
     }
 
-    return hex;
+    return ret;
 }
+#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_ATECC608A && !HAVE_SELFTEST &&
+        * !WOLFSSL_SP_MATH */
 
-#endif /* HAVE_SELFTEST */
-
-void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p)
+/* Invert the point on the curve.
+ * (x, y) -> (x, -y) = (x, (prime - y) % prime)
+ *
+ * @param [in]      curveIdx  Index of curve in ecc_set.
+ * @param [in, out] point     EC point to invert.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+static int wolfssl_ec_point_invert(int curveIdx, ecc_point* point)
 {
-#if defined(DEBUG_WOLFSSL)
-    char *num;
+    int ret = 1;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* prime = NULL;
+#else
+    mp_int prime[1];
+#endif
 
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_dump");
+#ifdef WOLFSSL_SMALL_STACK
+    /* Allocate memory for an MP int to hold the prime of the curve. */
+    prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+    if (prime == NULL) {
+        ret = 0;
+    }
+#endif
+
+    /* Initialize MP int. */
+    if ((ret == 1) && (mp_init(prime) != MP_OKAY)) {
+        WOLFSSL_MSG("mp_init_multi error");
+        ret = 0;
+    }
 
-    if (!WOLFSSL_IS_DEBUG_ON() || wolfSSL_GetLoggingCb()) {
-        return;
+    /* Read the curve parameter: prime. */
+    if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime,
+            MP_RADIX_HEX) != MP_OKAY)) {
+        WOLFSSL_MSG("mp_read_radix prime error");
+        ret = 0;
     }
 
-    if (p == NULL) {
-        printf("%s = NULL", msg);
-        return;
+    /* y = (prime - y) mod prime. */
+    if ((ret == 1) && (!mp_iszero(point->y)) && (mp_sub(prime, point->y,
+            point->y) != MP_OKAY)) {
+        WOLFSSL_MSG("mp_sub error");
+        ret = 0;
     }
 
-    printf("%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet);
-    num = wolfSSL_BN_bn2hex(p->X);
-    printf("\tX = %s\n", num);
-    XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
-    num = wolfSSL_BN_bn2hex(p->Y);
-    printf("\tY = %s\n", num);
-    XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
-    num = wolfSSL_BN_bn2hex(p->Z);
-    printf("\tZ = %s\n", num);
-    XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
-#else
-    (void)msg;
-    (void)p;
+    /* Dispose of memory associated with MP. */
+    mp_free(prime);
+#ifdef WOLFSSL_SMALL_STACK
+    /* Dispose of dynamically allocated temporaries. */
+    XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
 #endif
+    return ret;
 }
 
-/* Start EC_GROUP */
-
-/* return code compliant with OpenSSL :
- *   0 if equal, 1 if not and -1 in case of error
+/* Invert the point on the curve.
+ * (x, y) -> (x, -y) = (x, (prime - y) % prime)
+ *
+ * @param [in]      group  EC group.
+ * @param [in, out] point  EC point to invert.
+ * @param [in]      ctx    Context to use for BN operations. Unused.
+ * @return  1 on success.
+ * @return  0 on error.
  */
-int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b,
-                         WOLFSSL_BN_CTX *ctx)
+int wolfSSL_EC_POINT_invert(const WOLFSSL_EC_GROUP *group,
+    WOLFSSL_EC_POINT *point, WOLFSSL_BN_CTX *ctx)
 {
+    int ret = 1;
+
+    /* No BN operations performed. */
     (void)ctx;
 
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp");
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_invert");
 
-    if (a == NULL || b == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments");
-        return -1;
+    /* Validate parameters. */
+    if ((group == NULL) || (point == NULL) || (point->internal == NULL)) {
+        ret = 0;
     }
 
-    /* ok */
-    if ((a->curve_idx == b->curve_idx) && (a->curve_nid == b->curve_nid))
-        return 0;
-
-    /* ko */
-    return 1;
-}
-
-WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_dup(const WOLFSSL_EC_GROUP *src)
-{
-    if (!src)
-        return NULL;
-    return wolfSSL_EC_GROUP_new_by_curve_name(src->curve_nid);
-}
-
-#endif /* OPENSSL_EXTRA */
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of(
-                                                const WOLFSSL_EC_GROUP *group)
-{
-    return group;
-}
+    /* Ensure internal representation of point is setup. */
+    if ((ret == 1) && (ec_point_setup(point) != 1)) {
+        ret = 0;
+    }
 
-int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth)
-{
-    if (meth) {
-        return NID_X9_62_prime_field;
+    if (ret == 1) {
+        /* Perform inversion using wolfCrypt objects. */
+        ret = wolfssl_ec_point_invert(group->curve_idx,
+            (ecc_point*)point->internal);
     }
-    return 0;
-}
 
-void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_free");
+    /* Set the external EC point representation based on internal. */
+    if ((ret == 1) && (ec_point_external_set(point) != 1)) {
+        WOLFSSL_MSG("ec_point_external_set error");
+        ret = 0;
+    }
 
-    XFREE(group, NULL, DYNAMIC_TYPE_ECC);
-    /* group = NULL, don't try to access or double free it */
+    return ret;
 }
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
 
-#ifdef OPENSSL_EXTRA
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag)
+/* Compare two points on a the same curve.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * TODO: Compare affine co-ordinate like OpenSSL?
+ *
+ * @param [in] group  EC group.
+ * @param [in] a      EC point to invert.
+ * @param [in] b      EC point to invert.
+ * @param [in] ctx    Context to use for BN operations. Unused.
+ * @return  0 when equal.
+ * @return  1 when different.
+ * @return  -1 on error.
+ */
+int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group,
+    const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, WOLFSSL_BN_CTX *ctx)
 {
-    (void)group;
-    (void)flag;
+    int ret;
 
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag");
-    WOLFSSL_STUB("EC_GROUP_set_asn1_flag");
-}
-#endif
+    /* No BN operations performed. */
+    (void)ctx;
 
-/* return code compliant with OpenSSL :
- *   the curve nid if success, 0 if error
- */
-int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group)
-{
-    int nid;
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name");
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp");
 
-    if (group == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments");
-        return 0;
+    /* Validate parameters. */
+    if ((group == NULL) || (a == NULL) || (a->internal == NULL) ||
+            (b == NULL) || (b->internal == NULL)) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments");
+        ret = -1;
+    }
+    else  {
+        ret = (wc_ecc_cmp_point((ecc_point*)a->internal,
+            (ecc_point*)b->internal) != MP_EQ);
     }
 
-    /* If curve_nid is ECC Enum type, return corresponding OpenSSL nid */
-    if ((nid = EccEnumToNID(group->curve_nid)) != -1)
-        return nid;
-
-    return group->curve_nid;
+    return ret;
 }
 
-/* return code compliant with OpenSSL :
- *   the degree of the curve if success, 0 if error
+/* Copy EC point.
+ *
+ * @param [out] dest  EC point to copy into.
+ * @param [in]  src   EC point to copy.
+ * @return  1 on success.
+ * @return  0 on error.
  */
-int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group)
+int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src)
 {
-    int nid;
-    int tmp;
+    int ret = 1;
 
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree");
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_copy");
 
-    if (group == NULL || group->curve_idx < 0) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments");
-        return 0;
+    /* Validate parameters. */
+    if ((dest == NULL) || (src == NULL)) {
+        ret = 0;
     }
 
-    /* If curve_nid passed in is an ecc_curve_id enum, convert it to the
-        corresponding OpenSSL NID */
-    tmp = EccEnumToNID(group->curve_nid);
-    if (tmp != -1) {
-        nid = tmp;
+    /* Ensure internal EC point of src is setup. */
+    if ((ret == 1) && (ec_point_setup(src) != 1)) {
+        ret = 0;
     }
-    else {
-        nid = group->curve_nid;
+
+    /* Copy internal EC points. */
+    if ((ret == 1) && (wc_ecc_copy_point((ecc_point*) dest->internal,
+            (ecc_point*) src->internal) != MP_OKAY)) {
+        ret = 0;
     }
 
-    switch(nid) {
-        case NID_secp112r1:
-        case NID_secp112r2:
-            return 112;
-        case NID_secp128r1:
-        case NID_secp128r2:
-            return 128;
-        case NID_secp160k1:
-        case NID_secp160r1:
-        case NID_secp160r2:
-        case NID_brainpoolP160r1:
-            return 160;
-        case NID_secp192k1:
-        case NID_brainpoolP192r1:
-        case NID_X9_62_prime192v1:
-            return 192;
-        case NID_secp224k1:
-        case NID_secp224r1:
-        case NID_brainpoolP224r1:
-            return 224;
-        case NID_secp256k1:
-        case NID_brainpoolP256r1:
-        case NID_X9_62_prime256v1:
-            return 256;
-        case NID_brainpoolP320r1:
-            return 320;
-        case NID_secp384r1:
-        case NID_brainpoolP384r1:
-            return 384;
-        case NID_secp521r1:
-            return 521;
-        case NID_brainpoolP512r1:
-            return 512;
-        default:
-            return 0;
+    if (ret == 1) {
+        /* Destinatation internal point is set. */
+        dest->inSet = 1;
+
+        /* Set the external EC point of dest based on internal. */
+        if (ec_point_external_set(dest) != 1) {
+            ret = 0;
+        }
     }
+
+    return ret;
 }
-#endif /* OPENSSL_EXTRA */
 
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid)
+/* Checks whether point is at infinity.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] group  EC group.
+ * @param [in] point  EC point to check.
+ * @return  1 when at infinity.
+ * @return  0 when not at infinity.
+ */
+int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group,
+    const WOLFSSL_EC_POINT *point)
 {
-    WOLFSSL_EC_GROUP *g;
-    int x, eccEnum;
+    int ret = 1;
 
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name");
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity");
 
-    /* curve group */
-    g = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL,
-                                    DYNAMIC_TYPE_ECC);
-    if (g == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure");
-        return NULL;
+    /* Validate parameters. */
+    if ((group == NULL) || (point == NULL) || (point->internal == NULL)) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error");
+        ret = 0;
     }
-    XMEMSET(g, 0, sizeof(WOLFSSL_EC_GROUP));
-
-    /* set the nid of the curve */
-    g->curve_nid = nid;
-    g->curve_idx = -1;
 
-    /* If NID passed in is OpenSSL type, convert it to ecc_curve_id enum */
-    eccEnum = NIDToEccEnum(nid);
-    if (eccEnum != -1) {
-        /* search and set the corresponding internal curve idx */
-        for (x = 0; ecc_sets[x].size != 0; x++) {
-            if (ecc_sets[x].id == eccEnum) {
-                g->curve_idx = x;
-                g->curve_oid = ecc_sets[x].oidSum;
-                break;
-            }
+    /* Ensure internal EC point is setup. */
+    if ((ret == 1) && (ec_point_setup(point) != 1)) {
+        ret = 0;
+    }
+    if (ret == 1) {
+    #ifndef WOLF_CRYPTO_CB_ONLY_ECC
+        /* Check for infinity. */
+        ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal);
+        if (ret < 0) {
+            WOLFSSL_MSG("ecc_point_is_at_infinity failure");
+            /* Error return is 0 by OpenSSL. */
+            ret = 0;
         }
+    #else
+        WOLFSSL_MSG("ecc_point_is_at_infinitiy compiled out");
+        ret = 0;
+    #endif
     }
 
-    return g;
+    return ret;
 }
 
-/* Converts OpenSSL NID value of ECC curves to the associated enum values in
-   ecc_curve_id, used by ecc_sets[].*/
-int NIDToEccEnum(int n)
+#endif /* OPENSSL_EXTRA */
+
+/* End EC_POINT */
+
+/* Start EC_KEY */
+
+#ifdef OPENSSL_EXTRA
+
+/*
+ * EC key constructor/deconstructor APIs
+ */
+
+/* Allocate a new EC key.
+ *
+ * Not OpenSSL API.
+ *
+ * @param [in] heap   Heap hint for dynamic memory allocation.
+ * @param [in] devId  Device identifier value.
+ * @return  New, allocated EC key on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId)
 {
-    WOLFSSL_ENTER("NIDToEccEnum()");
+    WOLFSSL_EC_KEY *key = NULL;
+    int err = 0;
 
-    switch(n) {
-        case NID_X9_62_prime192v1:
-            return ECC_SECP192R1;
-        case NID_X9_62_prime192v2:
-            return ECC_PRIME192V2;
-        case NID_X9_62_prime192v3:
-            return ECC_PRIME192V3;
-        case NID_X9_62_prime239v1:
-            return ECC_PRIME239V1;
-        case NID_X9_62_prime239v2:
-            return ECC_PRIME239V2;
-        case NID_X9_62_prime239v3:
-            return ECC_PRIME239V3;
-        case NID_X9_62_prime256v1:
-            return ECC_SECP256R1;
-        case NID_secp112r1:
-            return ECC_SECP112R1;
-        case NID_secp112r2:
-            return ECC_SECP112R2;
-        case NID_secp128r1:
-            return ECC_SECP128R1;
-        case NID_secp128r2:
-            return ECC_SECP128R2;
-        case NID_secp160r1:
-            return ECC_SECP160R1;
-        case NID_secp160r2:
-            return ECC_SECP160R2;
-        case NID_secp224r1:
-            return ECC_SECP224R1;
-        case NID_secp384r1:
-            return ECC_SECP384R1;
-        case NID_secp521r1:
-            return ECC_SECP521R1;
-        case NID_secp160k1:
-            return ECC_SECP160K1;
-        case NID_secp192k1:
-            return ECC_SECP192K1;
-        case NID_secp224k1:
-            return ECC_SECP224K1;
-        case NID_secp256k1:
-            return ECC_SECP256K1;
-        case NID_brainpoolP160r1:
-            return ECC_BRAINPOOLP160R1;
-        case NID_brainpoolP192r1:
-            return ECC_BRAINPOOLP192R1;
-        case NID_brainpoolP224r1:
-            return ECC_BRAINPOOLP224R1;
-        case NID_brainpoolP256r1:
-            return ECC_BRAINPOOLP256R1;
-        case NID_brainpoolP320r1:
-            return ECC_BRAINPOOLP320R1;
-        case NID_brainpoolP384r1:
-            return ECC_BRAINPOOLP384R1;
-        case NID_brainpoolP512r1:
-            return ECC_BRAINPOOLP512R1;
-        default:
-            WOLFSSL_MSG("NID not found");
-            return -1;
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_new");
+
+    /* Allocate memory for EC key. */
+    key = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), heap,
+        DYNAMIC_TYPE_ECC);
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure");
+        err = 1;
     }
-}
+    if (!err) {
+        /* Reset all fields to 0. */
+        XMEMSET(key, 0, sizeof(WOLFSSL_EC_KEY));
+        /* Cache heap hint. */
+        key->heap = heap;
+        /* Initialize fields to defaults. */
+        key->form     = POINT_CONVERSION_UNCOMPRESSED;
 
-int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group)
-{
-    int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int *order = (mp_int *)XMALLOC(sizeof(*order), NULL,
-                                      DYNAMIC_TYPE_TMP_BUFFER);
-    if (order == NULL)
-        return 0;
-#else
-    mp_int order[1];
-#endif
+        /* Initialize reference count. */
+        wolfSSL_RefInit(&key->ref, &err);
+    }
 
-    if (group == NULL || group->curve_idx < 0) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error");
-        ret = -1;
+    if (!err) {
+        /* Allocate memory for internal EC key representation. */
+        key->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), heap,
+            DYNAMIC_TYPE_ECC);
+        if (key->internal == NULL) {
+            WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure");
+            err = 1;
+        }
+    }
+    if (!err) {
+        /* Initialize wolfCrypt EC key. */
+        if (wc_ecc_init_ex((ecc_key*)key->internal, heap, devId) != 0) {
+            WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure");
+            err = 1;
+        }
     }
 
-    if (ret == 0)
-        ret = mp_init(order);
+    if (!err) {
+        /* Group unknown at creation */
+        key->group = wolfSSL_EC_GROUP_new_by_curve_name(NID_undef);
+        if (key->group == NULL) {
+            WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure");
+            err = 1;
+        }
+    }
 
-    if (ret == 0) {
-        ret = mp_read_radix(order, ecc_sets[group->curve_idx].order,
-            MP_RADIX_HEX);
-        if (ret == 0)
-            ret = mp_count_bits(order);
-        mp_clear(order);
+    if (!err) {
+        /* Allocate a point as public key. */
+        key->pub_key = wolfSSL_EC_POINT_new(key->group);
+        if (key->pub_key == NULL) {
+            WOLFSSL_MSG("wolfSSL_EC_POINT_new failure");
+            err = 1;
+        }
     }
 
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(order, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+    if (!err) {
+        /* Allocate a BN as private key. */
+        key->priv_key = wolfSSL_BN_new();
+        if (key->priv_key == NULL) {
+            WOLFSSL_MSG("wolfSSL_BN_new failure");
+            err = 1;
+        }
+    }
 
-    if (ret == -1)
-        ret = 0;
+    if (err) {
+        /* Dispose of EC key on error. */
+        wolfSSL_EC_KEY_free(key);
+        key = NULL;
+    }
+    /* Return new EC key object. */
+    return key;
+}
 
-    return ret;
+/* Allocate a new EC key.
+ *
+ * @return  New, allocated EC key on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void)
+{
+    return wolfSSL_EC_KEY_new_ex(NULL, INVALID_DEVID);
 }
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
 
-#if defined(OPENSSL_EXTRA)
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
+/* Create new EC key with the group having the specified numeric ID.
+ *
+ * @param [in] nid  Numeric ID.
+ * @return  New, allocated EC key on success.
+ * @return  NULL on error.
  */
-int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group,
-                               WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx)
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid)
 {
-    (void)ctx;
+    WOLFSSL_EC_KEY *key;
+    int err = 0;
 
-    if (group == NULL || order == NULL || order->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error");
-        return 0;
-    }
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name");
 
-    if (mp_init((mp_int*)order->internal) != MP_OKAY) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure");
-        return 0;
+    /* Allocate empty, EC key. */
+    key = wolfSSL_EC_KEY_new();
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new failure");
+        err = 1;
     }
 
-    if (mp_read_radix((mp_int*)order->internal,
-                  ecc_sets[group->curve_idx].order, MP_RADIX_HEX) != MP_OKAY) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure");
-        mp_clear((mp_int*)order->internal);
-        return 0;
+    if (!err) {
+        /* Set group to be nid. */
+        ec_group_set_nid(key->group, nid);
+        if (key->group->curve_idx == -1) {
+            wolfSSL_EC_KEY_free(key);
+            key = NULL;
+        }
     }
 
-    return 1;
+    /* Return the new EC key object. */
+    return key;
 }
 
-/* End EC_GROUP */
-
-/* Start EC_POINT */
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
+/* Dispose of the EC key and allocated data.
+ *
+ * Cannot use key after this call.
+ *
+ * @param [in] key  EC key to free.
  */
-int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group,
-                        const WOLFSSL_EC_POINT *p,
-                        unsigned char *out, unsigned int *len)
+void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key)
 {
+    int doFree = 0;
     int err;
 
-    WOLFSSL_ENTER("wolfSSL_ECPoint_i2d");
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_free");
 
-    if (group == NULL || p == NULL || len == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error");
-        return 0;
-    }
+    if (key != NULL) {
+        void* heap = key->heap;
 
-    if (setupPoint(p) != 1) {
-        return 0;
-    }
+        /* Decrement reference count. */
+        wolfSSL_RefDec(&key->ref, &doFree, &err);
+        if ((!err) && doFree) {
+            /* Dispose of allocated reference counting data. */
+            wolfSSL_RefFree(&key->ref);
+
+            /* Dispose of private key. */
+            wolfSSL_BN_free(key->priv_key);
+            wolfSSL_EC_POINT_free(key->pub_key);
+            wolfSSL_EC_GROUP_free(key->group);
+            if (key->internal != NULL) {
+                /* Dispose of wolfCrypt representation of EC key. */
+                wc_ecc_free((ecc_key*)key->internal);
+                XFREE(key->internal, heap, DYNAMIC_TYPE_ECC);
+            }
 
-    if (out != NULL) {
-        wolfSSL_EC_POINT_dump("i2d p", p);
+            /* Set back to NULLs for safety. */
+            ForceZero(key, sizeof(*key));
+
+            /* Dispose of the memory associated with the EC key. */
+            XFREE(key, heap, DYNAMIC_TYPE_ECC);
+            (void)heap;
+        }
     }
+}
 
-    err = wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal,
-                                  out, len);
-    if (err != MP_OKAY && !(out == NULL && err == LENGTH_ONLY_E)) {
-        WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed");
-        return 0;
+/* Increments ref count of EC key.
+ *
+ * @param [in, out] key  EC key.
+ * @return  1 on success
+ * @return  0 on error
+ */
+int wolfSSL_EC_KEY_up_ref(WOLFSSL_EC_KEY* key)
+{
+    int err = 1;
+
+    if (key != NULL) {
+        wolfSSL_RefInc(&key->ref, &err);
     }
 
-    return 1;
+    return !err;
 }
 
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
+#ifndef NO_CERTS
+
+#if defined(OPENSSL_ALL)
+/* Copy the internal, wolfCrypt EC key.
+ *
+ * @param [in, out] dst  Destination wolfCrypt EC key.
+ * @param [in]      src  Source wolfCrypt EC key.
+ * @return  0 on success.
+ * @return  Negative on error.
  */
-int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len,
-                        const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *p)
+static int wolfssl_ec_key_int_copy(ecc_key* dst, const ecc_key* src)
 {
-    WOLFSSL_ENTER("wolfSSL_ECPoint_d2i");
+    int ret;
 
-    if (group == NULL || p == NULL || p->internal == NULL || in == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error");
-        return 0;
+    /* Copy public key. */
+#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
+    ret = wc_ecc_copy_point(&src->pubkey, &dst->pubkey);
+#else
+    ret = wc_ecc_copy_point((ecc_point*)&src->pubkey, &dst->pubkey);
+#endif
+    if (ret != MP_OKAY) {
+        WOLFSSL_MSG("wc_ecc_copy_point error");
     }
 
-#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
-    if (wc_ecc_import_point_der_ex(in, len, group->curve_idx,
-                                   (ecc_point*)p->internal, 0) != MP_OKAY) {
-        WOLFSSL_MSG("wc_ecc_import_point_der_ex failed");
-       return 0;
-    }
-#else
-    /* ECC_POINT_UNCOMP is not defined CAVP self test so use magic number */
-    if (in[0] == 0x04) {
-        if (wc_ecc_import_point_der(in, len, group->curve_idx,
-                                    (ecc_point*)p->internal) != MP_OKAY) {
-            WOLFSSL_MSG("wc_ecc_import_point_der failed");
-            return 0;
+    if (ret == 0) {
+        /* Copy private key. */
+        ret = mp_copy(&src->k, &dst->k);
+        if (ret != MP_OKAY) {
+            WOLFSSL_MSG("mp_copy error");
         }
     }
-    else {
-        WOLFSSL_MSG("Only uncompressed points supported with HAVE_SELFTEST");
-        return 0;
-    }
-#endif
 
-    /* Set new external point */
-    if (SetECPointExternal(p) != 1) {
-        WOLFSSL_MSG("SetECPointExternal failed");
-        return 0;
+    if (ret == 0) {
+        /* Copy domain parameters. */
+        if (src->dp) {
+            ret = wc_ecc_set_curve(dst, 0, src->dp->id);
+            if (ret != 0) {
+                WOLFSSL_MSG("wc_ecc_set_curve error");
+            }
+        }
     }
 
-    wolfSSL_EC_POINT_dump("d2i p", p);
+    if (ret == 0) {
+        /* Copy the other components. */
+        dst->type  = src->type;
+        dst->idx   = src->idx;
+        dst->state = src->state;
+        dst->flags = src->flags;
+    }
 
-    return 1;
+    return ret;
 }
 
-size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
-                                  const WOLFSSL_EC_POINT *p,
-                                  char form,
-                                  byte *buf, size_t len, WOLFSSL_BN_CTX *ctx)
+/* Copies ecc_key into new WOLFSSL_EC_KEY object
+ *
+ * Copies the internal represention as well.
+ *
+ * @param [in] src  EC key to duplicate.
+ *
+ * @return  EC key on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src)
 {
-    word32 min_len = (word32)len;
-#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
-    int compressed = form == POINT_CONVERSION_COMPRESSED ? 1 : 0;
-#endif /* !HAVE_SELFTEST */
-
-    WOLFSSL_ENTER("EC_POINT_point2oct");
+    int err = 0;
+    WOLFSSL_EC_KEY* newKey = NULL;
 
-    if (!group || !p) {
-        return 0;
-    }
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_dup");
 
-    if (setupPoint(p) != 1) {
-        return 0;
+    /* Validate EC key. */
+    if ((src == NULL) || (src->internal == NULL) || (src->group == NULL) ||
+         (src->pub_key == NULL) || (src->priv_key == NULL)) {
+        WOLFSSL_MSG("src NULL error");
+        err = 1;
     }
 
-    if (wolfSSL_EC_POINT_is_at_infinity(group, p)) {
-        /* encodes to a single 0 octet */
-        if (buf != NULL) {
-            if (len < 1) {
-                ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
-                return 0;
-            }
-            buf[0] = 0;
+    if (!err) {
+        /* Create a new, empty key. */
+        newKey = wolfSSL_EC_KEY_new();
+        if (newKey == NULL) {
+            WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
+            err = 1;
         }
-        return 1;
     }
 
-    if (form != POINT_CONVERSION_UNCOMPRESSED
-#ifndef HAVE_SELFTEST
-            && form != POINT_CONVERSION_COMPRESSED
-#endif /* !HAVE_SELFTEST */
-            ) {
-        WOLFSSL_MSG("Unsupported curve form");
-        return 0;
+    if (!err) {
+        /* Copy internal EC key. */
+        if (wolfssl_ec_key_int_copy((ecc_key*)newKey->internal,
+                (ecc_key*)src->internal) != 0) {
+            WOLFSSL_MSG("Copying internal EC key error");
+            err = 1;
+        }
     }
+    if (!err) {
+        /* Internal key set. */
+        newKey->inSet = 1;
 
-#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
-    if (wc_ecc_export_point_der_ex(group->curve_idx, (ecc_point*)p->internal,
-               buf, &min_len, compressed) != (buf ? MP_OKAY : LENGTH_ONLY_E)) {
-        return 0;
+        /* Copy group */
+        err = wolfssl_ec_group_copy(newKey->group, src->group);
     }
-#else
-    if (wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal,
-                                buf, &min_len) != (buf ? MP_OKAY : LENGTH_ONLY_E)) {
-        return 0;
+    /* Copy public key. */
+    if ((!err) && (wolfSSL_EC_POINT_copy(newKey->pub_key, src->pub_key) != 1)) {
+        WOLFSSL_MSG("Copying EC public key error");
+        err = 1;
     }
-#endif /* !HAVE_SELFTEST */
-
-    (void)ctx;
-
-    return (size_t)min_len;
-}
 
+    if (!err) {
+        /* Set header size of private key in PKCS#8 format.*/
+        newKey->pkcs8HeaderSz = src->pkcs8HeaderSz;
 
-int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group,
-                               WOLFSSL_EC_POINT *p, const unsigned char *buf,
-                               size_t len, WOLFSSL_BN_CTX *ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
+        /* Copy private key. */
+        if (wolfSSL_BN_copy(newKey->priv_key, src->priv_key) == NULL) {
+            WOLFSSL_MSG("Copying EC private key error");
+            err = 1;
+        }
+    }
 
-    if (!group || !p) {
-        return 0;
+    if (err) {
+        /* Dispose of EC key on error. */
+        wolfSSL_EC_KEY_free(newKey);
+        newKey = NULL;
     }
+    /* Return the new EC key. */
+    return newKey;
+}
 
-    (void)ctx;
+#endif /* OPENSSL_ALL */
 
-    return wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group, p);
-}
+#endif /* !NO_CERTS */
 
+/*
+ * EC key to/from bin/octet APIs
+ */
 
-WOLFSSL_EC_KEY *wolfSSL_o2i_ECPublicKey(WOLFSSL_EC_KEY **a, const unsigned char **in,
-                                        long len)
+/* Create an EC key from the octet encoded public key.
+ *
+ * Behaviour checked against OpenSSL.
+ *
+ * @param [out]     key  Reference to EC key. Must pass in a valid object with
+ *                       group set.
+ * @param [in, out] in   On in, reference to buffer that contains data.
+ *                       On out, reference to buffer after public key data.
+ * @param [in]      len  Length of data in the buffer. Must be length of the
+ *                       encoded public key.
+ * @return  Allocated EC key on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_EC_KEY *wolfSSL_o2i_ECPublicKey(WOLFSSL_EC_KEY **key,
+   const unsigned char **in, long len)
 {
-    WOLFSSL_EC_KEY* ret;
+    int err = 0;
+    WOLFSSL_EC_KEY* ret = NULL;
 
     WOLFSSL_ENTER("wolfSSL_o2i_ECPublicKey");
 
-    if (!a || !*a || !(*a)->group || !in || !*in || len <= 0) {
+    /* Validate parameters: EC group needed to perform import. */
+    if ((key == NULL) || (*key == NULL) || ((*key)->group == NULL) ||
+            (in == NULL) || (*in == NULL) || (len <= 0)) {
         WOLFSSL_MSG("wolfSSL_o2i_ECPublicKey Bad arguments");
-        return NULL;
+        err = 1;
     }
 
-    ret = *a;
-
-    if (wolfSSL_EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)
-            != 1) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_oct2point error");
-        return NULL;
+    if (!err) {
+        /* Return the EC key object passed in. */
+        ret = *key;
+
+        /* Import point into public key field. */
+        if (wolfSSL_EC_POINT_oct2point(ret->group, ret->pub_key, *in, len,
+                NULL) != 1) {
+            WOLFSSL_MSG("wolfSSL_EC_POINT_oct2point error");
+            ret = NULL;
+            err = 1;
+        }
+    }
+    if (!err) {
+        /* Assumed length passed in is all the data. */
+        *in += len;
     }
 
-    *in += len;
     return ret;
 }
 
-int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *in, unsigned char **out)
+/* Puts the encoded public key into out.
+ *
+ * Passing in NULL for out returns length only.
+ * Passing in NULL for *out has buffer allocated, encoded into and passed back.
+ * Passing non-NULL for *out has it encoded into and pointer moved past.
+ *
+ * @param [in]      key  EC key to encode.
+ * @param [in, out] out  Reference to buffer to encode into. May be NULL or
+ *                       point to NULL.
+ * @return  Length of encoding in bytes on success.
+ * @return  0 on error.
+ */
+int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *key, unsigned char **out)
 {
-    size_t len;
-    unsigned char *tmp = NULL;
-    char form;
+    int ret = 1;
+    size_t len = 0;
+    int form = POINT_CONVERSION_UNCOMPRESSED;
+
     WOLFSSL_ENTER("wolfSSL_i2o_ECPublicKey");
 
-    if (!in) {
+    /* Validate parameters. */
+    if (key == NULL) {
         WOLFSSL_MSG("wolfSSL_i2o_ECPublicKey Bad arguments");
-        return 0;
+        ret = 0;
     }
 
-    if (!in->exSet) {
-        if (SetECKeyExternal((WOLFSSL_EC_KEY*)in) != 1) {
-            WOLFSSL_MSG("SetECKeyExternal failure");
-            return 0;
-        }
+    /* Ensure the external key data is set from the internal EC key. */
+    if ((ret == 1) && (!key->exSet) && (SetECKeyExternal((WOLFSSL_EC_KEY*)
+            key) != 1)) {
+        WOLFSSL_MSG("SetECKeyExternal failure");
+        ret = 0;
     }
 
-#ifdef HAVE_COMP_KEY
-    /* Default to compressed form if not set */
-    form = in->form == POINT_CONVERSION_UNCOMPRESSED ?
-            POINT_CONVERSION_UNCOMPRESSED:
-            POINT_CONVERSION_COMPRESSED;
-#else
-    form = POINT_CONVERSION_UNCOMPRESSED;
-#endif
+    if (ret == 1) {
+    #ifdef HAVE_COMP_KEY
+        /* Default to compressed form if not set */
+        form = (key->form != POINT_CONVERSION_UNCOMPRESSED) ?
+               POINT_CONVERSION_UNCOMPRESSED :
+               POINT_CONVERSION_COMPRESSED;
+    #endif
 
-    len = wolfSSL_EC_POINT_point2oct(in->group, in->pub_key, form,
-                                     NULL, 0, NULL);
+        /* Calculate length of point encoding. */
+        len = wolfSSL_EC_POINT_point2oct(key->group, key->pub_key, form, NULL,
+            0, NULL);
+    }
+    /* Encode if length calculated and pointer supplied to update. */
+    if ((ret == 1) && (len != 0) && (out != NULL)) {
+        unsigned char *tmp = NULL;
 
-    if (len != 0 && out) {
-        if (!*out) {
-            if (!(tmp = (unsigned char*)XMALLOC(len, NULL,
-                                                DYNAMIC_TYPE_OPENSSL))) {
+        /* Allocate buffer for encoding if no buffer supplied. */
+        if (*out == NULL) {
+            tmp = (unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
+            if (tmp == NULL) {
                 WOLFSSL_MSG("malloc failed");
-                return 0;
+                ret = 0;
             }
-            *out = tmp;
+        }
+        else {
+            /* Get buffer to encode into. */
+            tmp = *out;
         }
 
-        if (wolfSSL_EC_POINT_point2oct(in->group, in->pub_key, form, *out,
-                                       len, NULL) == 0) {
-            if (tmp) {
-                XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
-                *out = NULL;
-            }
-            return 0;
+        /* Encode public key into buffer. */
+        if ((ret == 1) && (wolfSSL_EC_POINT_point2oct(key->group, key->pub_key,
+                form, tmp, len, NULL) == 0)) {
+            ret = 0;
         }
 
-        if (!tmp) {
-            /* Move buffer forward if it was not alloced in this function */
-            *out += len;
+        if (ret == 1) {
+            /* Return buffer if allocated. */
+            if (*out == NULL) {
+                *out = tmp;
+            }
+            else {
+                /* Step over encoded data if not allocated. */
+                *out += len;
+            }
+        }
+        else if (*out == NULL) {
+            /* Dispose of allocated buffer. */
+            XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
         }
     }
 
-    return (int)len;
+    if (ret == 1) {
+        /* Return length on success. */
+        ret = (int)len;
+    }
+    return ret;
 }
 
 #ifdef HAVE_ECC_KEY_IMPORT
-WOLFSSL_EC_KEY *wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY **key, const unsigned char **in,
-                                         long len)
+/* Create a EC key from the DER encoded private key.
+ *
+ * @param [out]     key   Reference to EC key.
+ * @param [in, out] in    On in, reference to buffer that contains DER data.
+ *                        On out, reference to buffer after private key data.
+ * @param [in]      long  Length of data in the buffer. May be larger than the
+ *                        length of the encoded private key.
+ * @return  Allocated EC key on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_EC_KEY* wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY** key,
+    const unsigned char** in, long len)
 {
+    int err = 0;
     word32 idx = 0;
-    WOLFSSL_EC_KEY *eckey = NULL;
+    WOLFSSL_EC_KEY* ret = NULL;
+
     WOLFSSL_ENTER("wolfSSL_d2i_ECPrivateKey");
 
-    if (!in || !*in || len <= 0) {
+    /* Validate parameters. */
+    if ((in == NULL) || (*in == NULL) || (len <= 0)) {
         WOLFSSL_MSG("wolfSSL_d2i_ECPrivateKey Bad arguments");
-        return NULL;
+        err = 1;
     }
 
-    if (!(eckey = wolfSSL_EC_KEY_new())) {
+    /* Create a new, empty EC key.  */
+    if ((!err) && ((ret = wolfSSL_EC_KEY_new()) == NULL)) {
         WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
-        return NULL;
+        err = 1;
     }
 
-    if (wc_EccPrivateKeyDecode(*in, &idx, (ecc_key*)eckey->internal,
-            (word32)len) != 0) {
+    /* Decode the private key DER data into internal EC key. */
+    if ((!err) && (wc_EccPrivateKeyDecode(*in, &idx, (ecc_key*)ret->internal,
+            (word32)len) != 0)) {
         WOLFSSL_MSG("wc_EccPrivateKeyDecode error");
-        goto error;
+        err = 1;
     }
 
-    eckey->inSet = 1;
+    if (!err) {
+        /* Internal EC key setup. */
+        ret->inSet = 1;
+
+        /* Set the EC key from the internal values. */
+        if (SetECKeyExternal(ret) != 1) {
+            WOLFSSL_MSG("SetECKeyExternal error");
+            err = 1;
+        }
+    }
 
-    if (SetECKeyExternal(eckey) != 1) {
-        WOLFSSL_MSG("SetECKeyExternal error");
-        goto error;
+    if (!err) {
+        /* Move buffer on to next byte after data used. */
+        *in += idx;
+        if (key) {
+            /* Return new EC key through reference. */
+            *key = ret;
+        }
     }
 
-    if (key) {
-        *key = eckey;
+    if (err && (ret != NULL)) {
+        /* Dispose of allocated EC key. */
+        wolfSSL_EC_KEY_free(ret);
+        ret = NULL;
     }
-
-    return eckey;
-
-error:
-    wolfSSL_EC_KEY_free(eckey);
-    return NULL;
+    return ret;
 }
 #endif /* HAVE_ECC_KEY_IMPORT */
 
-int wolfSSL_i2d_ECPrivateKey(const WOLFSSL_EC_KEY *in, unsigned char **out)
+/* Enecode the private key of the EC key into the buffer as DER.
+ *
+ * @param [in]      key  EC key to encode.
+ * @param [in, out] out  On in, reference to buffer to place DER encoding into.
+ *                       On out, reference to buffer adter the encoding.
+ *                       May be NULL.
+ * @return  Length of DER encoding on success.
+ * @return  0 on error.
+ */
+int wolfSSL_i2d_ECPrivateKey(const WOLFSSL_EC_KEY *key, unsigned char **out)
 {
-    word32 len;
-    byte* buf = NULL;
+    int err = 0;
+    word32 len = 0;
+
     WOLFSSL_ENTER("wolfSSL_i2d_ECPrivateKey");
 
-    if (!in) {
+    /* Validate parameters. */
+    if (key == NULL) {
         WOLFSSL_MSG("wolfSSL_i2d_ECPrivateKey Bad arguments");
-        return 0;
+        err = 1;
     }
 
-    if (!in->inSet && SetECKeyInternal(
-            (WOLFSSL_EC_KEY*)in) != 1) {
+    /* Update the internal EC key if not set. */
+    if ((!err) && (!key->inSet) && (SetECKeyInternal((WOLFSSL_EC_KEY*)key) !=
+            1)) {
         WOLFSSL_MSG("SetECKeyInternal error");
-        return 0;
+        err = 1;
     }
 
-    if ((len = wc_EccKeyDerSize((ecc_key*)in->internal, 0)) <= 0) {
+    /* Calculate the length of the private key DER encoding using internal EC
+     * key. */
+    if ((!err) && ((len = wc_EccKeyDerSize((ecc_key*)key->internal, 0)) <= 0)) {
         WOLFSSL_MSG("wc_EccKeyDerSize error");
-        return 0;
+        err = 1;
     }
 
-    if (out) {
-        if (!(buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
-            WOLFSSL_MSG("tmp buffer malloc error");
-            return 0;
-        }
+    /* Only return length when out is NULL. */
+    if ((!err) && (out != NULL)) {
+        unsigned char* buf = NULL;
 
-        if (wc_EccPrivateKeyToDer((ecc_key*)in->internal, buf, len) < 0) {
+        /* Must have a buffer to encode into. */
+        if (*out == NULL) {
+            /* Allocate a new buffer of appropriate length. */
+            buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            if (buf == NULL) {
+                /* Error and return 0. */
+                err = 1;
+                len = 0;
+            }
+            else {
+                /* Return the allocated buffer. */
+                *out = buf;
+            }
+        }
+        /* Encode the internal EC key as a private key in DER format. */
+        if ((!err) && wc_EccPrivateKeyToDer((ecc_key*)key->internal, *out,
+                len) < 0) {
             WOLFSSL_MSG("wc_EccPrivateKeyToDer error");
-            XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            return 0;
+            err = 1;
+        }
+        else if (buf != *out) {
+            /* Move the reference to byte past encoded private key. */
+            *out += len;
         }
 
-        if (*out) {
-            XMEMCPY(*out, buf, len);
+        /* Dispose of any allocated buffer on error. */
+        if (err && (*out == buf)) {
             XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        }
-        else {
-            *out = buf;
+            *out = NULL;
         }
     }
 
     return (int)len;
 }
 
-void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *eckey, char form)
-{
-    if (eckey && (form == POINT_CONVERSION_UNCOMPRESSED
-#ifdef HAVE_COMP_KEY
-                  || form == POINT_CONVERSION_COMPRESSED
-#endif
-                  )) {
-        eckey->form = form;
-    } else {
-        WOLFSSL_MSG("Incorrect form or HAVE_COMP_KEY not compiled in");
-    }
-}
-
-point_conversion_form_t wolfSSL_EC_KEY_get_conv_form(const WOLFSSL_EC_KEY* key)
+/* Load private key into EC key from DER encoding.
+ *
+ * Not an OpenSSL compatibility API.
+ *
+ * @param [in, out] key     EC key to put private key values into.
+ * @param [in]      derBuf  Buffer holding DER encoding.
+ * @param [in]      derSz   Size of DER encoding in bytes.
+ * @return  1 on success.
+ * @return  -1 on error.
+ */
+int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
+                           int derSz)
 {
-    if (key != NULL) {
-        return key->form;
-    }
-
-    return -1;
+    return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz,
+        WOLFSSL_EC_KEY_LOAD_PRIVATE);
 }
 
-/* wolfSSL_EC_POINT_point2bn should return "in" if not null */
-WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP *group,
-    const WOLFSSL_EC_POINT *p, char form, WOLFSSL_BIGNUM *in,
-    WOLFSSL_BN_CTX *ctx)
+/* Load private/public key into EC key from DER encoding.
+ *
+ * Not an OpenSSL compatibility API.
+ *
+ * @param [in, out] key     EC key to put private/public key values into.
+ * @param [in]      derBuf  Buffer holding DER encoding.
+ * @param [in]      derSz   Size of DER encoding in bytes.
+ * @param [in]      opt     Key type option. Valid values:
+ *                            WOLFSSL_EC_KEY_LOAD_PRIVATE,
+ *                            WOLFSSL_EC_KEY_LOAD_PUBLIC.
+ * @return  1 on success.
+ * @return  -1 on error.
+ */
+int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
+                              int derSz, int opt)
 {
-    size_t len;
-    byte *buf;
-    WOLFSSL_BIGNUM *ret = NULL;
+    int res = 1;
+    int ret;
+    word32 idx = 0;
+    word32 algId;
 
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer");
 
-    if (!group || !p) {
-        return NULL;
+    /* Validate parameters. */
+    if ((key == NULL) || (key->internal == NULL) || (derBuf == NULL) ||
+            (derSz <= 0)) {
+        WOLFSSL_MSG("Bad function arguments");
+        res = -1;
     }
-
-    if ((len = wolfSSL_EC_POINT_point2oct(group, p, form,
-                                          NULL, 0, ctx)) == 0) {
-        return NULL;
+    if ((res == 1) && (opt != WOLFSSL_EC_KEY_LOAD_PRIVATE) &&
+            (opt != WOLFSSL_EC_KEY_LOAD_PUBLIC)) {
+        res = -1;
     }
 
-    if (!(buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
-        WOLFSSL_MSG("malloc failed");
-        return NULL;
-    }
+    if (res == 1) {
+        /* Assume no PKCS#8 header. */
+        key->pkcs8HeaderSz = 0;
 
-    if (wolfSSL_EC_POINT_point2oct(group, p, form,
-                                   buf, len, ctx) == len) {
-        ret = wolfSSL_BN_bin2bn(buf, (int)len, in);
+        /* Check if input buffer has PKCS8 header. In the case that it does not
+         * have a PKCS8 header then do not error out.
+         */
+        if ((ret = ToTraditionalInline_ex((const byte*)derBuf, &idx,
+                (word32)derSz, &algId)) > 0) {
+            WOLFSSL_MSG("Found PKCS8 header");
+            key->pkcs8HeaderSz = (word16)idx;
+            res = 1;
+        }
+        /* Error out on parsing error. */
+        else if (ret != ASN_PARSE_E) {
+            WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header");
+            res = -1;
+        }
     }
 
-    XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return ret;
-}
-
-#if defined(USE_ECC_B_PARAM) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
-int wolfSSL_EC_POINT_is_on_curve(const WOLFSSL_EC_GROUP *group,
-                                 const WOLFSSL_EC_POINT *point,
-                                 WOLFSSL_BN_CTX *ctx)
-{
-    (void)ctx;
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_is_on_curve");
+    if (res == 1) {
+        /* Load into internal EC key based on key type option. */
+        if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
+            ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
+                derSz);
+        }
+        else {
+            ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
+                derSz);
+        }
+        if (ret < 0) {
+            /* Error returned from wolfSSL. */
+            if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
+                WOLFSSL_MSG("wc_EccPrivateKeyDecode failed");
+            }
+            else {
+                WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
+            }
+            res = -1;
+        }
 
-    if (!group || !point) {
-        WOLFSSL_MSG("Invalid arguments");
-        return 0;
+        /* Internal key updated - update whether it is a valid key. */
+        key->inSet = (res == 1);
     }
 
-    if (!point->inSet && SetECPointInternal((WOLFSSL_EC_POINT*)point)) {
-        WOLFSSL_MSG("SetECPointInternal error");
-        return 0;
+    /* Set the external EC key based on value in internal. */
+    if ((res == 1) && (SetECKeyExternal(key) != 1)) {
+        WOLFSSL_MSG("SetECKeyExternal failed");
+        res = -1;
     }
 
-    return wc_ecc_point_is_on_curve((ecc_point*)point->internal,
-        group->curve_idx)
-            == MP_OKAY ? 1 : 0;
+    return res;
 }
-#endif /* USE_ECC_B_PARAM && !(FIPS_VERSION <= 2) */
 
-WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group)
+/*
+ * EC key PEM APIs
+ */
+
+#if (defined(WOLFSSL_KEY_GEN) && !defined(NO_FILESYSTEM)) || \
+    (!defined(NO_BIO) && (defined(WOLFSSL_KEY_GEN) || \
+     defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)))
+/* Encode the EC public key as DER.
+ *
+ * Also used by pem_write_pubkey().
+ *
+ * @param [in]  key   EC key to encode.
+ * @param [out] der   Pointer through which buffer is returned.
+ * @param [in]  heap  Heap hint.
+ * @return  Size of encoding on success.
+ * @return  0 on error.
+ */
+static int wolfssl_ec_key_to_pubkey_der(WOLFSSL_EC_KEY* key,
+    unsigned char** der, void* heap)
 {
-    WOLFSSL_EC_POINT *p;
+    int sz;
+    unsigned char* buf = NULL;
 
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_new");
+    (void)heap;
 
-    if (group == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error");
-        return NULL;
+    /* Calculate encoded size to allocate. */
+    sz = wc_EccPublicKeyDerSize((ecc_key*)key->internal, 1);
+    if (sz <= 0) {
+        WOLFSSL_MSG("wc_EccPublicKeyDerSize failed");
+        sz = 0;
     }
-
-    p = (WOLFSSL_EC_POINT *)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL,
-                                    DYNAMIC_TYPE_ECC);
-    if (p == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure");
-        return NULL;
+    if (sz > 0) {
+        /* Allocate memory to hold encoding. */
+        buf = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (buf == NULL) {
+            WOLFSSL_MSG("malloc failed");
+            sz = 0;
+        }
+    }
+    if (sz > 0) {
+        /* Encode public key to DER using wolfSSL.  */
+        sz = wc_EccPublicKeyToDer((ecc_key*)key->internal, buf, sz, 1);
+        if (sz < 0) {
+            WOLFSSL_MSG("wc_EccPublicKeyToDer failed");
+            sz = 0;
+        }
     }
-    XMEMSET(p, 0, sizeof(WOLFSSL_EC_POINT));
 
-    p->internal = wc_ecc_new_point();
-    if (p->internal == NULL) {
-        WOLFSSL_MSG("ecc_new_point failure");
-        XFREE(p, NULL, DYNAMIC_TYPE_ECC);
-        return NULL;
+    /* Return buffer on success. */
+    if (sz > 0) {
+        *der = buf;
+    }
+    else {
+        /* Dispose of any dynamically allocated data not returned. */
+        XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER);
     }
 
-    return p;
+    return sz;
 }
+#endif
 
-#if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_KEY_GEN)
+/*
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] fp   File pointer to write PEM encoding to.
+ * @param [in] key  EC key to encode and write.
+ * @return  1 on success.
+ * @return  0 on error.
  */
-int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group,
-                                                const WOLFSSL_EC_POINT *point,
-                                                WOLFSSL_BIGNUM *x,
-                                                WOLFSSL_BIGNUM *y,
-                                                WOLFSSL_BN_CTX *ctx)
+int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key)
 {
-    mp_digit mp;
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* modulus = NULL;
-#else
-    mp_int modulus[1];
-#endif
-    (void)ctx;
-
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp");
-
-    if (group == NULL || point == NULL || point->internal == NULL ||
-        x == NULL || y == NULL ||
-        wolfSSL_EC_POINT_is_at_infinity(group, point)) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error");
-        return 0;
-    }
+    int ret = 1;
+    unsigned char* derBuf = NULL;
+    int derSz = 0;
 
-    if (setupPoint(point) != 1) {
-        return 0;
-    }
+    WOLFSSL_ENTER("wolfSSL_PEM_write_EC_PUBKEY");
 
-#ifdef WOLFSSL_SMALL_STACK
-    modulus = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
-    if (modulus == NULL) {
-        return 0;
+    /* Validate parameters. */
+    if ((fp == XBADFILE) || (key == NULL)) {
+        WOLFSSL_MSG("Bad argument.");
+        ret = 0;
     }
-#endif
 
-    if (!wolfSSL_BN_is_one(point->Z)) {
-        if (mp_init(modulus) != MP_OKAY) {
-            WOLFSSL_MSG("mp_init failed");
-       #ifdef WOLFSSL_SMALL_STACK
-            XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT);
-        #endif
-            return 0;
-        }
-        /* Map the Jacobian point back to affine space */
-        if (mp_read_radix(modulus, ecc_sets[group->curve_idx].prime,
-                MP_RADIX_HEX) != MP_OKAY) {
-            WOLFSSL_MSG("mp_read_radix failed");
-            mp_clear(modulus);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT);
-        #endif
-            return 0;
-        }
-        if (mp_montgomery_setup(modulus, &mp) != MP_OKAY) {
-            WOLFSSL_MSG("mp_montgomery_setup failed");
-            mp_clear(modulus);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT);
-        #endif
-            return 0;
-        }
-        if (ecc_map((ecc_point*)point->internal, modulus, mp) != MP_OKAY) {
-            WOLFSSL_MSG("ecc_map failed");
-            mp_clear(modulus);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT);
-        #endif
-            return 0;
-        }
-        if (SetECPointExternal((WOLFSSL_EC_POINT *)point) != 1) {
-            WOLFSSL_MSG("SetECPointExternal failed");
-            mp_clear(modulus);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT);
-        #endif
-            return 0;
+    if (ret == 1) {
+        /* Encode public key in EC key as DER. */
+        derSz = wolfssl_ec_key_to_pubkey_der(key, &derBuf, key->heap);
+        if (derSz == 0) {
+            ret = 0;
         }
+    }
 
-        mp_clear(modulus);
+    /* Write out to file the PEM encoding of the DER. */
+    if ((ret == 1) && (der_write_to_file_as_pem(derBuf, derSz, fp,
+            ECC_PUBLICKEY_TYPE, key->heap) != 1)) {
+        ret = 0;
     }
 
-    BN_copy(x, point->X);
-    BN_copy(y, point->Y);
+    /* Dispose of any dynamically allocated data. */
+    XFREE(derBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
 
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
+    WOLFSSL_LEAVE("wolfSSL_PEM_write_EC_PUBKEY", ret);
 
-    return 1;
+    return ret;
 }
 #endif
 
-int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group,
-                                                WOLFSSL_EC_POINT *point,
-                                                const WOLFSSL_BIGNUM *x,
-                                                const WOLFSSL_BIGNUM *y,
-                                                WOLFSSL_BN_CTX *ctx)
+#ifndef NO_BIO
+/* Read a PEM encoded EC public key from a BIO.
+ *
+ * @param [in]  bio   BIO to read EC public key from.
+ * @param [out] out   Pointer to return EC key object through. May be NULL.
+ * @param [in]  cb    Password callback when PEM encrypted.
+ * @param [in]  pass  NUL terminated string for passphrase when PEM
+ *                    encrypted.
+ * @return  New EC key object on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio,
+    WOLFSSL_EC_KEY** out, wc_pem_password_cb* cb, void *pass)
 {
-    (void)ctx;
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_set_affine_coordinates_GFp");
+    int             err = 0;
+    WOLFSSL_EC_KEY* ec = NULL;
+    DerBuffer*      der = NULL;
+    int             keyFormat = 0;
 
-    if (group == NULL || point == NULL || point->internal == NULL ||
-        x == NULL || y == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp NULL error");
-        return 0;
-    }
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY");
 
-    if (!point->X) {
-        point->X = wolfSSL_BN_new();
-    }
-    if (!point->Y) {
-        point->Y = wolfSSL_BN_new();
-    }
-    if (!point->Z) {
-        point->Z = wolfSSL_BN_new();
-    }
-    if (!point->X || !point->Y || !point->Z) {
-        WOLFSSL_MSG("wolfSSL_BN_new failed");
-        return 0;
+    /* Validate parameters. */
+    if (bio == NULL) {
+        err = 1;
     }
 
-    BN_copy(point->X, x);
-    BN_copy(point->Y, y);
-    BN_copy(point->Z, wolfSSL_BN_value_one());
-
-    if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != 1) {
-        WOLFSSL_MSG("SetECPointInternal failed");
-        return 0;
+    if (!err) {
+        /* Create an empty EC key. */
+        ec = wolfSSL_EC_KEY_new();
+        if (ec == NULL) {
+            err = 1;
+        }
     }
-
-    return 1;
-}
-
-#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
-    !defined(HAVE_SELFTEST) && !defined(WOLFSSL_SP_MATH) && \
-    !defined(WOLF_CRYPTO_CB_ONLY_ECC)
-int wolfSSL_EC_POINT_add(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r,
-                         const WOLFSSL_EC_POINT *p1,
-                         const WOLFSSL_EC_POINT *p2, WOLFSSL_BN_CTX *ctx)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* a = NULL;
-    mp_int* prime = NULL;
-    mp_int* mu = NULL;
-#else
-    mp_int a[1];
-    mp_int prime[1];
-    mp_int mu[1];
-#endif
-    mp_digit mp = 0;
-    ecc_point* montP1 = NULL;
-    ecc_point* montP2 = NULL;
-    ecc_point* eccP1;
-    ecc_point* eccP2;
-    int ret = 0;
-
-    (void)ctx;
-
-    if (!group || !r || !p1 || !p2) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_add error");
-        return 0;
+    /* Read a PEM key in to a new DER buffer. */
+    if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PUBLICKEY_TYPE,
+            &keyFormat, &der) <= 0)) {
+        err = 1;
     }
-
-    if (setupPoint(r) != 1 ||
-        setupPoint(p1) != 1 ||
-        setupPoint(p2) != 1) {
-        WOLFSSL_MSG("setupPoint error");
-        return 0;
+    /* Load the EC key with the public key from the DER encoding. */
+    if ((!err) && (wolfSSL_EC_KEY_LoadDer_ex(ec, der->buffer, der->length,
+            WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1)) {
+        WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_KEY");
+        err = 1;
     }
 
-#ifdef WOLFSSL_SMALL_STACK
-    a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
-    if (a == NULL) {
-        WOLFSSL_MSG("Failed to allocate memory for mp_int a");
-        return 0;
-    }
-    prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
-    if (prime == NULL) {
-        WOLFSSL_MSG("Failed to allocate memory for mp_int prime");
-        XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
-        return 0;
+    /* Dispose of dynamically allocated data not needed anymore. */
+    FreeDer(&der);
+    if (err) {
+        wolfSSL_EC_KEY_free(ec);
+        ec = NULL;
     }
-    mu = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
-    if (mu == NULL) {
-        WOLFSSL_MSG("Failed to allocate memory for mp_int mu");
-        XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
-        XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
-        return 0;
+
+    /* Return EC key through out if required. */
+    if ((out != NULL) && (ec != NULL)) {
+        *out = ec;
     }
-    XMEMSET(a, 0, sizeof(mp_int));
-    XMEMSET(prime, 0, sizeof(mp_int));
-    XMEMSET(mu, 0, sizeof(mp_int));
-#endif
+    return ec;
+}
 
-    /* read the curve prime and a */
-    if (mp_init_multi(prime, a, mu, NULL, NULL, NULL) != MP_OKAY) {
-        WOLFSSL_MSG("mp_init_multi error");
-        goto cleanup;
+/* Read a PEM encoded EC private key from a BIO.
+ *
+ * @param [in]  bio   BIO to read EC private key from.
+ * @param [out] out   Pointer to return EC key object through. May be NULL.
+ * @param [in]  cb    Password callback when PEM encrypted.
+ * @param [in]  pass  NUL terminated string for passphrase when PEM
+ *                    encrypted.
+ * @return  New EC key object on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio,
+   WOLFSSL_EC_KEY** out, wc_pem_password_cb* cb, void *pass)
+{
+    int             err = 0;
+    WOLFSSL_EC_KEY* ec = NULL;
+    DerBuffer*      der = NULL;
+    int             keyFormat = 0;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY");
+
+    /* Validate parameters. */
+    if (bio == NULL) {
+        err = 1;
     }
 
-    if (mp_read_radix(a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX)
-            != MP_OKAY) {
-        WOLFSSL_MSG("mp_read_radix a error");
-        goto cleanup;
+    if (!err) {
+        /* Create an empty EC key. */
+        ec = wolfSSL_EC_KEY_new();
+        if (ec == NULL) {
+            err = 1;
+        }
+    }
+    /* Read a PEM key in to a new DER buffer. */
+    if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PRIVATEKEY_TYPE,
+            &keyFormat, &der) <= 0)) {
+        err = 1;
+    }
+    /* Load the EC key with the private key from the DER encoding. */
+    if ((!err) && (wolfSSL_EC_KEY_LoadDer_ex(ec, der->buffer, der->length,
+            WOLFSSL_EC_KEY_LOAD_PRIVATE) != 1)) {
+        WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_KEY");
+        err = 1;
     }
 
-    if (mp_read_radix(prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX)
-            != MP_OKAY) {
-        WOLFSSL_MSG("mp_read_radix prime error");
-        goto cleanup;
+    /* Dispose of dynamically allocated data not needed anymore. */
+    FreeDer(&der);
+    if (err) {
+        wolfSSL_EC_KEY_free(ec);
+        ec = NULL;
     }
 
-    if (mp_montgomery_setup(prime, &mp) != MP_OKAY) {
-        WOLFSSL_MSG("mp_montgomery_setup nqm error");
-        goto cleanup;
+    /* Return EC key through out if required. */
+    if ((out != NULL) && (ec != NULL)) {
+        *out = ec;
     }
+    return ec;
+}
+#endif /* !NO_BIO */
 
-    eccP1 = (ecc_point*)p1->internal;
-    eccP2 = (ecc_point*)p2->internal;
+#if defined(WOLFSSL_KEY_GEN)
+#ifndef NO_BIO
+/* Write out the EC public key as PEM to the BIO.
+ *
+ * @param [in] bio  BIO to write PEM encoding to.
+ * @param [in] ec   EC public key to encode.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec)
+{
+    int ret = 1;
+    unsigned char* derBuf = NULL;
+    int derSz = 0;
 
-    if (!(montP1 = wc_ecc_new_point_h(NULL)) ||
-            !(montP2 = wc_ecc_new_point_h(NULL))) {
-        WOLFSSL_MSG("wc_ecc_new_point_h nqm error");
-        goto cleanup;
-    }
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_EC_PUBKEY");
 
-    if ((mp_montgomery_calc_normalization(mu, prime)) != MP_OKAY) {
-        WOLFSSL_MSG("mp_montgomery_calc_normalization error");
-        goto cleanup;
+    /* Validate parameters. */
+    if ((bio == NULL) || (ec == NULL)) {
+        WOLFSSL_MSG("Bad Function Arguments");
+        ret = 0;
     }
 
-    /* Convert to Montgomery form */
-    if (mp_cmp_d(mu, 1) == MP_EQ) {
-        if (wc_ecc_copy_point(eccP1, montP1) != MP_OKAY ||
-                wc_ecc_copy_point(eccP2, montP2) != MP_OKAY) {
-            WOLFSSL_MSG("wc_ecc_copy_point error");
-            goto cleanup;
-        }
-    } else {
-        if (mp_mulmod(eccP1->x, mu, prime, montP1->x) != MP_OKAY ||
-                mp_mulmod(eccP1->y, mu, prime, montP1->y) != MP_OKAY ||
-                mp_mulmod(eccP1->z, mu, prime, montP1->z) != MP_OKAY) {
-            WOLFSSL_MSG("mp_mulmod error");
-            goto cleanup;
-        }
-        if (mp_mulmod(eccP2->x, mu, prime, montP2->x) != MP_OKAY ||
-                mp_mulmod(eccP2->y, mu, prime, montP2->y) != MP_OKAY ||
-                mp_mulmod(eccP2->z, mu, prime, montP2->z) != MP_OKAY) {
-            WOLFSSL_MSG("mp_mulmod error");
-            goto cleanup;
+    if (ret == 1) {
+        /* Encode public key in EC key as DER. */
+        derSz = wolfssl_ec_key_to_pubkey_der(ec, &derBuf, ec->heap);
+        if (derSz == 0) {
+            ret = 0;
         }
     }
 
-    if (ecc_projective_add_point(montP1, montP2, (ecc_point*)r->internal,
-            a, prime, mp) != MP_OKAY) {
-        WOLFSSL_MSG("ecc_projective_add_point error");
-        goto cleanup;
+    /* Write out to BIO the PEM encoding of the EC private key. */
+    if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio,
+            ECC_PUBLICKEY_TYPE) != 1)) {
+        ret = 0;
     }
 
-    if (ecc_map((ecc_point*)r->internal, prime, mp) != MP_OKAY) {
-        WOLFSSL_MSG("ecc_map error");
-        goto cleanup;
-    }
+    /* Dispose of any dynamically allocated data. */
+    XFREE(derBuf, ec->heap, DYNAMIC_TYPE_TMP_BUFFER);
 
-    ret = 1;
-cleanup:
-    mp_clear(a);
-    mp_clear(prime);
-    mp_clear(mu);
-    wc_ecc_del_point_h(montP1, NULL);
-    wc_ecc_del_point_h(montP2, NULL);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
-    XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
-    XFREE(mu, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
     return ret;
 }
 
-/* Calculate the value: generator * n + q * m
- * return code compliant with OpenSSL :
- *   1 if success, 0 if error
+/* Write out the EC private key as PEM to the BIO.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] bio       BIO to write PEM encoding to.
+ * @param [in] ec        EC private key to encode.
+ * @param [in] cipher    Cipher to use when PEM encrypted. May be NULL.
+ * @param [in] passwd    Password string when PEM encrypted. May be NULL.
+ * @param [in] passwdSz  Length of password string when PEM encrypted.
+ * @param [in] cb        Password callback when PEM encrypted. Unused.
+ * @param [in] pass      NUL terminated string for passphrase when PEM
+ *                       encrypted. Unused.
+ * @return  1 on success.
+ * @return  0 on error.
  */
-int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r,
-                         const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q,
-                         const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
+int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec,
+    const EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
+    wc_pem_password_cb* cb, void* arg)
 {
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* a = NULL;
-    mp_int* prime = NULL;
-#else
-    mp_int a[1], prime[1];
-#endif
-    int ret = 0;
-    ecc_point* result = NULL;
-    ecc_point* tmp = NULL;
-
-    (void)ctx;
+    int ret = 1;
+    unsigned char* pem = NULL;
+    int pLen = 0;
 
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_mul");
+    (void)cb;
+    (void)arg;
 
-    if (!group || !r) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error");
-        return 0;
+    /* Validate parameters. */
+    if ((bio == NULL) || (ec == NULL)) {
+        ret = 0;
     }
 
-#ifdef WOLFSSL_SMALL_STACK
-    a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
-    if (a == NULL)  {
-        return 0;
+    /* Write EC private key to PEM. */
+    if ((ret == 1) && (wolfSSL_PEM_write_mem_ECPrivateKey(ec, cipher, passwd,
+            passwdSz, &pem, &pLen) != 1)) {
+       ret = 0;
     }
-    prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
-    if (prime == NULL)  {
-        XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
-        return 0;
+    /* Write PEM to BIO. */
+    if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) != pLen)) {
+        WOLFSSL_ERROR_MSG("EC private key BIO write failed");
+        ret = 0;
     }
-#endif
 
-    if (!(result = wc_ecc_new_point())) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_new error");
-        return 0;
-    }
+    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
 
-    /* read the curve prime and a */
-    if (mp_init_multi(prime, a, NULL, NULL, NULL, NULL) != MP_OKAY) {
-        WOLFSSL_MSG("mp_init_multi error");
-        goto cleanup;
-    }
+    return ret;
+}
 
-    if (q && setupPoint(q) != 1) {
-        WOLFSSL_MSG("setupPoint error");
-        goto cleanup;
-    }
+#endif /* !NO_BIO */
 
-    if (mp_read_radix(prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX)
-            != MP_OKAY) {
-        WOLFSSL_MSG("mp_read_radix prime error");
-        goto cleanup;
-    }
+/* Encode the EC private key as PEM into buffer.
+ *
+ * Return code compliant with OpenSSL.
+ * Not an OpenSSL API.
+ *
+ * @param [in]  ec        EC private key to encode.
+ * @param [in]  cipher    Cipher to use when PEM encrypted. May be NULL.
+ * @param [in]  passwd    Password string when PEM encrypted. May be NULL.
+ * @param [in]  passwdSz  Length of password string when PEM encrypted.
+ * @param [out] pem       Newly allocated buffer holding PEM encoding.
+ * @param [out] pLen      Length of PEM encoding in bytes.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ec,
+    const EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
+    unsigned char **pem, int *pLen)
+{
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+    int ret = 1;
+    byte* derBuf;
+    int der_max_len = 0;
+    int derSz = 0;
 
-    if (mp_read_radix(a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX)
-            != MP_OKAY) {
-        WOLFSSL_MSG("mp_read_radix a error");
-        goto cleanup;
-    }
+    WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey");
 
-    if (n) {
-        /* load generator */
-    #if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
-        if (wc_ecc_get_generator(result, group->curve_idx)
-                != MP_OKAY) {
-            WOLFSSL_MSG("wc_ecc_get_generator error");
-            goto cleanup;
-        }
-    #else
-        /* wc_ecc_get_generator is not defined in the FIPS v2 module. */
-        if (mp_read_radix(result->x, ecc_sets[group->curve_idx].Gx,
-                MP_RADIX_HEX) != MP_OKAY) {
-            WOLFSSL_MSG("mp_read_radix Gx error");
-            goto cleanup;
-        }
-        if (mp_read_radix(result->y, ecc_sets[group->curve_idx].Gy,
-                MP_RADIX_HEX) != MP_OKAY) {
-            WOLFSSL_MSG("mp_read_radix Gy error");
-            goto cleanup;
-        }
-        if (mp_set(result->z, 1) != MP_OKAY) {
-            WOLFSSL_MSG("mp_set Gz error");
-            goto cleanup;
-        }
-    #endif /* NOPT_FIPS_VERSION == 2 */
+    /* Validate parameters. */
+    if ((pem == NULL) || (pLen == NULL) || (ec == NULL) ||
+            (ec->internal == NULL)) {
+        WOLFSSL_MSG("Bad function arguments");
+        ret = 0;
     }
 
-    if (n && q && m) {
-        /* r = generator * n + q * m */
-#if defined(ECC_SHAMIR) && !defined(WOLFSSL_KCAPI_ECC)
-        if (ecc_mul2add(result, (mp_int*)n->internal,
-                        (ecc_point*)q->internal, (mp_int*)m->internal,
-                        result, a, prime, NULL)
-                != MP_OKAY) {
-            WOLFSSL_MSG("ecc_mul2add error");
-            goto cleanup;
-        }
-#else
-        mp_digit mp = 0;
-        if (mp_montgomery_setup(prime, &mp) != MP_OKAY) {
-            WOLFSSL_MSG("mp_montgomery_setup nqm error");
-            goto cleanup;
-        }
-        if (!(tmp = wc_ecc_new_point())) {
-            WOLFSSL_MSG("wolfSSL_EC_POINT_new nqm error");
-            goto cleanup;
-        }
-        /* r = generator * n */
-        if (wc_ecc_mulmod((mp_int*)n->internal, result, result, a, prime, 0)
-                != MP_OKAY) {
-            WOLFSSL_MSG("wc_ecc_mulmod nqm error");
-            goto cleanup;
-        }
-        /* tmp = q * m */
-        if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal,
-                tmp, a, prime, 0) != MP_OKAY) {
-            WOLFSSL_MSG("wc_ecc_mulmod nqm error");
-            goto cleanup;
-        }
-        /* result = result + tmp */
-        if (ecc_projective_add_point(tmp, result, result, a, prime, mp)
-                != MP_OKAY) {
-            WOLFSSL_MSG("wc_ecc_mulmod nqm error");
-            goto cleanup;
-        }
-        if (ecc_map(result, prime, mp) != MP_OKAY) {
-            WOLFSSL_MSG("ecc_map nqm error");
-            goto cleanup;
+    /* Ensure internal EC key is set from external. */
+    if ((ret == 1) && (ec->inSet == 0)) {
+        WOLFSSL_MSG("No ECC internal set, do it");
+
+        if (SetECKeyInternal(ec) != 1) {
+            WOLFSSL_MSG("SetECKeyInternal failed");
+            ret = 0;
         }
-#endif
     }
-    else if (n) {
-        /* r = generator * n */
-        if (wc_ecc_mulmod((mp_int*)n->internal, result, result, a, prime, 1)
-                != MP_OKAY) {
-            WOLFSSL_MSG("wc_ecc_mulmod gn error");
-            goto cleanup;
+
+    if (ret == 1) {
+        /* Calculate maximum size of DER encoding.
+         * 4 > size of pub, priv + ASN.1 additional information */
+        der_max_len = 4 * wc_ecc_size((ecc_key*)ec->internal) + AES_BLOCK_SIZE;
+
+        /* Allocate buffer big enough to hold encoding. */
+        derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (derBuf == NULL) {
+            WOLFSSL_MSG("malloc failed");
+            ret = 0;
         }
     }
-    else if (q && m) {
-        /* r = q * m */
-        if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal,
-                           result, a, prime, 1) != MP_OKAY) {
-            WOLFSSL_MSG("wc_ecc_mulmod qm error");
-            goto cleanup;
+
+    if (ret == 1) {
+        /* Encode EC private key as DER. */
+        derSz = wc_EccKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len);
+        if (derSz < 0) {
+            WOLFSSL_MSG("wc_EccKeyToDer failed");
+            XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+            ret = 0;
         }
     }
 
-    /* copy to destination */
-    if (wc_ecc_copy_point(result, (ecc_point*)r->internal)) {
-        WOLFSSL_MSG("wc_ecc_copy_point error");
-        goto cleanup;
-    }
-    r->inSet = 1;
-    if (SetECPointExternal(r) != 1) {
-        WOLFSSL_MSG("SetECPointExternal error");
-        goto cleanup;
+    /* Convert DER to PEM - possibly encrypting. */
+    if ((ret == 1) && (der_to_enc_pem_alloc(derBuf, derSz, cipher, passwd,
+            passwdSz, ECC_PRIVATEKEY_TYPE, NULL, pem, pLen) != 1)) {
+        WOLFSSL_ERROR_MSG("der_to_enc_pem_alloc failed");
+        ret = 0;
     }
 
-    ret = 1;
-cleanup:
-    mp_clear(a);
-    mp_clear(prime);
-    wc_ecc_del_point(result);
-    wc_ecc_del_point(tmp);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
-    XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
     return ret;
+#else
+    (void)ec;
+    (void)cipher;
+    (void)passwd;
+    (void)passwdSz;
+    (void)pem;
+    (void)pLen;
+    return 0;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
 }
-#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_ATECC608A && !HAVE_SELFTEST &&
-        * !WOLFSSL_SP_MATH */
 
-/* (x, y) -> (x, -y) */
-int wolfSSL_EC_POINT_invert(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *a,
-                            WOLFSSL_BN_CTX *ctx)
+#ifndef NO_FILESYSTEM
+/* Write out the EC private key as PEM to file.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] fp        File pointer to write PEM encoding to.
+ * @param [in] ec        EC private key to encode.
+ * @param [in] cipher    Cipher to use when PEM encrypted. May be NULL.
+ * @param [in] passwd    Password string when PEM encrypted. May be NULL.
+ * @param [in] passwdSz  Length of password string when PEM encrypted.
+ * @param [in] cb        Password callback when PEM encrypted. Unused.
+ * @param [in] pass      NUL terminated string for passphrase when PEM
+ *                       encrypted. Unused.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ec,
+    const EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
+    wc_pem_password_cb *cb, void *pass)
 {
-    ecc_point* p;
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* prime = NULL;
-#else
-    mp_int prime[1];
-#endif
-
-    (void)ctx;
-
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_invert");
-
-    if (!group || !a || !a->internal || setupPoint(a) != 1) {
-        return 0;
-    }
+    int ret = 1;
+    byte *pem = NULL;
+    int pLen = 0;
 
-    p = (ecc_point*)a->internal;
+    (void)cb;
+    (void)pass;
 
-#ifdef WOLFSSL_SMALL_STACK
-    prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
-    if (prime == NULL) {
-        return 0;
-    }
-#endif
+    WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey");
 
-    /* read the curve prime and a */
-    if (mp_init_multi(prime, NULL, NULL, NULL, NULL, NULL) != MP_OKAY) {
-        WOLFSSL_MSG("mp_init_multi error");
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
-    #endif
-        return 0;
+    /* Validate parameters. */
+    if ((fp == XBADFILE) || (ec == NULL) || (ec->internal == NULL)) {
+        WOLFSSL_MSG("Bad function arguments");
+        ret = 0;
     }
 
-    if (mp_sub(prime, p->y, p->y) != MP_OKAY) {
-        WOLFSSL_MSG("mp_sub error");
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
-    #endif
-        return 0;
+    /* Write EC private key to PEM. */
+    if ((ret == 1) && (wolfSSL_PEM_write_mem_ECPrivateKey(ec, cipher, passwd,
+            passwdSz, &pem, &pLen) != 1)) {
+        WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed");
+        ret = 0;
     }
 
-    if (SetECPointExternal(a) != 1) {
-        WOLFSSL_MSG("SetECPointExternal error");
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
-    #endif
-        return 0;
+    /* Write out to file the PEM encoding of the EC private key. */
+    if ((ret == 1) && (XFWRITE(pem, pLen, 1, fp) != 1)) {
+        WOLFSSL_MSG("ECC private key file write failed");
+        ret = 0;
     }
 
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
+    /* Dispose of any dynamically allocated data. */
+    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
 
-    return 1;
+    return ret;
 }
 
-void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free");
+#endif /* NO_FILESYSTEM */
+#endif /* defined(WOLFSSL_KEY_GEN) */
 
-    wolfSSL_EC_POINT_free(p);
-}
+/*
+ * EC key print APIs
+ */
 
-/* return code compliant with OpenSSL :
- *   0 if equal, 1 if not and -1 in case of error
+#ifndef NO_CERTS
+
+#if defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \
+    !defined(NO_STDIO_FILESYSTEM)
+/* Print the EC key to a file pointer as text.
+ *
+ * @param [in] fp      File pointer.
+ * @param [in] key     EC key to print.
+ * @param [in] indent  Number of spaces to place before each line printed.
+ * @return  1 on success.
+ * @return  0 on failure.
  */
-int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group,
-                         const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b,
-                         WOLFSSL_BN_CTX *ctx)
+int wolfSSL_EC_KEY_print_fp(XFILE fp, WOLFSSL_EC_KEY* key, int indent)
 {
-    int ret;
-
-    (void)ctx;
+    int ret = 1;
+    int bits = 0;
+    int priv = 0;
 
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp");
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_print_fp");
 
-    if (group == NULL || a == NULL || a->internal == NULL || b == NULL ||
-        b->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments");
-        return -1;
+    /* Validate parameters. */
+    if ((fp == XBADFILE) || (key == NULL) || (key->group == NULL) ||
+            (indent < 0)) {
+        ret = 0;
     }
 
-    ret = wc_ecc_cmp_point((ecc_point*)a->internal, (ecc_point*)b->internal);
-    if (ret == MP_EQ)
-        return 0;
-    else if (ret == MP_LT || ret == MP_GT)
-        return 1;
-
-    return -1;
-}
+    if (ret == 1) {
+        /* Get EC groups order size in bits. */
+        bits = wolfSSL_EC_GROUP_order_bits(key->group);
+        if (bits <= 0) {
+            WOLFSSL_MSG("Failed to get group order bits.");
+            ret = 0;
+        }
+    }
+    if (ret == 1) {
+        const char* keyType;
 
-int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_copy");
+        /* Determine whether this is a private or public key. */
+        if ((key->priv_key != NULL) && (!wolfSSL_BN_is_zero(key->priv_key))) {
+            keyType = "Private-Key";
+            priv = 1;
+        }
+        else {
+            keyType = "Public-Key";
+        }
 
-    if (!dest || !src) {
-        return 0;
+        /* Print key header. */
+        if (XFPRINTF(fp, "%*s%s: (%d bit)\n", indent, "", keyType, bits) < 0) {
+            ret = 0;
+        }
     }
-
-    if (setupPoint(src) != 1) {
-        return 0;
+    if ((ret == 1) && priv) {
+        /* Print the private key BN. */
+        ret = pk_bn_field_print_fp(fp, indent, "priv", key->priv_key);
     }
+    /* Check for public key data in EC key. */
+    if ((ret == 1) && (key->pub_key != NULL) && (key->pub_key->exSet)) {
+        /* Get the public key point as one BN. */
+        WOLFSSL_BIGNUM* pubBn = wolfSSL_EC_POINT_point2bn(key->group,
+            key->pub_key, POINT_CONVERSION_UNCOMPRESSED, NULL, NULL);
+        if (pubBn == NULL) {
+            WOLFSSL_MSG("wolfSSL_EC_POINT_point2bn failed.");
+            ret = 0;
+        }
+        else {
+            /* Print the public key in a BN. */
+            ret = pk_bn_field_print_fp(fp, indent, "pub", pubBn);
+            wolfSSL_BN_free(pubBn);
+        }
+    }
+    if (ret == 1) {
+        /* Get the NID of the group. */
+        int nid = wolfSSL_EC_GROUP_get_curve_name(key->group);
+        if (nid > 0) {
+            /* Convert the NID into a long name and NIST name. */
+            const char* curve = wolfSSL_OBJ_nid2ln(nid);
+            const char* nistName = wolfSSL_EC_curve_nid2nist(nid);
 
-    if (wc_ecc_copy_point((ecc_point*) dest->internal,
-                          (ecc_point*) src->internal) != MP_OKAY) {
-        return 0;
+            /* Print OID name if known. */
+            if ((curve != NULL) &&
+                (XFPRINTF(fp, "%*sASN1 OID: %s\n", indent, "", curve) < 0)) {
+                ret = 0;
+            }
+            /* Print NIST curve name if known. */
+            if ((nistName != NULL) &&
+                (XFPRINTF(fp, "%*sNIST CURVE: %s\n", indent, "",
+                    nistName) < 0)) {
+                ret = 0;
+            }
+        }
     }
 
-    dest->inSet = 1;
 
-    if (SetECPointExternal(dest) != 1) {
-        return 0;
-    }
+    WOLFSSL_LEAVE("wolfSSL_EC_KEY_print_fp", ret);
 
-    return 1;
+    return ret;
 }
-#endif /* OPENSSL_EXTRA */
+#endif /* XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */
 
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p)
+#endif /* !NO_CERTS */
+
+/*
+ * EC_KEY get/set/test APIs
+ */
+
+/* Set data of internal, wolfCrypt EC key object into EC key.
+ *
+ * EC_KEY wolfSSL -> OpenSSL
+ *
+ * @param [in, out] p  EC key to update.
+ * @return  1 on success.
+ * @return  -1 on failure.
+ */
+int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
 {
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_free");
+    int ret = 1;
 
-    if (p != NULL) {
-        if (p->internal != NULL) {
-            wc_ecc_del_point((ecc_point*)p->internal);
-            p->internal = NULL;
+    WOLFSSL_ENTER("SetECKeyExternal");
+
+    /* Validate parameter. */
+    if ((eckey == NULL) || (eckey->internal == NULL)) {
+        WOLFSSL_MSG("ec key NULL error");
+        ret = -1;
+    }
+    else {
+        ecc_key* key = (ecc_key*)eckey->internal;
+
+        /* Set group (OID, nid and idx) from wolfCrypt EC key. */
+        eckey->group->curve_oid = key->dp->oidSum;
+        eckey->group->curve_nid = EccEnumToNID(key->dp->id);
+        eckey->group->curve_idx = key->idx;
+
+        if (eckey->pub_key->internal != NULL) {
+            /* Copy internal public point from internal key's public point. */
+            if (wc_ecc_copy_point(&key->pubkey,
+                    (ecc_point*)eckey->pub_key->internal) != MP_OKAY) {
+                WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed");
+                ret = -1;
+            }
+
+            /* Set external public key from internal wolfCrypt, public key. */
+            if ((ret == 1) && (ec_point_external_set(eckey->pub_key) != 1)) {
+                WOLFSSL_MSG("SetECKeyExternal ec_point_external_set failed");
+                ret = -1;
+            }
         }
 
-        wolfSSL_BN_free(p->X);
-        wolfSSL_BN_free(p->Y);
-        wolfSSL_BN_free(p->Z);
-        p->X = NULL;
-        p->Y = NULL;
-        p->Z = NULL;
-        p->inSet = p->exSet = 0;
+        /* set the external privkey */
+        if ((ret == 1) && (key->type == ECC_PRIVATEKEY) &&
+                (SetIndividualExternal(&eckey->priv_key, &key->k) != 1)) {
+            WOLFSSL_MSG("ec priv key error");
+            ret = -1;
+        }
 
-        XFREE(p, NULL, DYNAMIC_TYPE_ECC);
-        /* p = NULL, don't try to access or double free it */
+        /* External values set when operations succeeded. */
+        eckey->exSet = (ret == 1);
     }
+
+    return ret;
 }
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
 
-#ifdef OPENSSL_EXTRA
-/* return code compliant with OpenSSL :
- *   1 if point at infinity, 0 else
+/* Set data of EC key into internal, wolfCrypt EC key object.
+ *
+ * EC_KEY Openssl -> WolfSSL
+ *
+ * @param [in, out] p  EC key to update.
+ * @return  1 on success.
+ * @return  -1 on failure.
  */
-int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group,
-                                    const WOLFSSL_EC_POINT *point)
+int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
 {
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity");
+    int ret = 1;
 
-    if (group == NULL || point == NULL || point->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error");
-        return 0;
-    }
+    WOLFSSL_ENTER("SetECKeyInternal");
 
-    if (setupPoint(point) != 1) {
-        return 0;
-    }
-    #ifndef WOLF_CRYPTO_CB_ONLY_ECC
-    ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal);
-    if (ret < 0) {
-        WOLFSSL_MSG("ecc_point_is_at_infinity failure");
-        return 0;
+    /* Validate parameter. */
+    if ((eckey == NULL) || (eckey->internal == NULL) ||
+            (eckey->group == NULL)) {
+        WOLFSSL_MSG("ec key NULL error");
+        ret = -1;
     }
-    #else
-        WOLFSSL_MSG("ecc_point_is_at_infinitiy compiled out");
-        return 0;
-    #endif
-    return ret;
-}
+    else {
+        ecc_key* key = (ecc_key*)eckey->internal;
+        int pubSet = 0;
 
-/* End EC_POINT */
+        /* Validate group. */
+        if ((eckey->group->curve_idx < 0) ||
+            (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) {
+            WOLFSSL_MSG("invalid curve idx");
+            ret = -1;
+        }
 
-#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
-size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *r, size_t nitems)
-{
-    size_t i, min_nitems;
-#ifdef HAVE_SELFTEST
-    size_t ecc_sets_count;
-    for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++);
-    ecc_sets_count = i;
-#endif
+        if (ret == 1) {
+            /* Set group (idx of curve and corresponding domain parameters). */
+            key->idx = eckey->group->curve_idx;
+            key->dp = &ecc_sets[key->idx];
+            pubSet = (eckey->pub_key != NULL);
+        }
+        /* Set public key (point). */
+        if ((ret == 1) && pubSet) {
+            if (ec_point_internal_set(eckey->pub_key) != 1) {
+                WOLFSSL_MSG("ec key pub error");
+                ret = -1;
+            }
+            /* Copy public point to key. */
+            if ((ret == 1) && (wc_ecc_copy_point(
+                    (ecc_point*)eckey->pub_key->internal, &key->pubkey) !=
+                    MP_OKAY)) {
+                WOLFSSL_MSG("wc_ecc_copy_point error");
+                ret = -1;
+            }
 
-    if (r == NULL || nitems == 0)
-        return ecc_sets_count;
+            if (ret == 1) {
+                /* Set that the internal key is a public key */
+                key->type = ECC_PUBLICKEY;
+            }
+        }
 
-    min_nitems = nitems < ecc_sets_count ? nitems : ecc_sets_count;
+        /* set privkey */
+        if ((ret == 1) && (eckey->priv_key != NULL)) {
+            if (SetIndividualInternal(eckey->priv_key, &key->k) != 1) {
+                WOLFSSL_MSG("ec key priv error");
+                ret = -1;
+            }
+            /* private key */
+            if ((ret == 1) && (!mp_iszero(&key->k))) {
+                if (pubSet) {
+                    key->type = ECC_PRIVATEKEY;
+                }
+                else {
+                    key->type = ECC_PRIVATEKEY_ONLY;
+                }
+            }
+        }
 
-    for (i = 0; i < min_nitems; i++) {
-        r[i].nid = EccEnumToNID(ecc_sets[i].id);
-        r[i].comment = wolfSSL_OBJ_nid2sn(r[i].nid);
+        /* Internal values set when operations succeeded. */
+        eckey->inSet = (ret == 1);
     }
 
-    return min_nitems;
+    return ret;
 }
-#endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */
 
-/* Start ECDSA_SIG */
-void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig)
+/* Get point conversion format of EC key.
+ *
+ * @param [in] key  EC key.
+ * @return  Point conversion format on success.
+ * @return  -1 on error.
+ */
+point_conversion_form_t wolfSSL_EC_KEY_get_conv_form(const WOLFSSL_EC_KEY* key)
 {
-    WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free");
-
-    if (sig) {
-        wolfSSL_BN_free(sig->r);
-        wolfSSL_BN_free(sig->s);
+    int ret = -1;
 
-        XFREE(sig, NULL, DYNAMIC_TYPE_ECC);
+    if (key != NULL) {
+        ret = key->form;
     }
+
+    return ret;
 }
 
-WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void)
+/* Set point conversion format into EC key.
+ *
+ * @param [in, out] key   EC key to set format into.
+ * @param [in]      form  Point conversion format. Valid values:
+ *                          POINT_CONVERSION_UNCOMPRESSED,
+ *                          POINT_CONVERSION_COMPRESSED (when HAVE_COMP_KEY)
+ */
+void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *key, int form)
 {
-    WOLFSSL_ECDSA_SIG *sig;
-
-    WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new");
-
-    sig = (WOLFSSL_ECDSA_SIG*) XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL,
-                                       DYNAMIC_TYPE_ECC);
-    if (sig == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure");
-        return NULL;
+    if (key == NULL) {
+        WOLFSSL_MSG("Key passed in NULL");
     }
-
-    sig->s = NULL;
-    sig->r = wolfSSL_BN_new();
-    if (sig->r == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure");
-        wolfSSL_ECDSA_SIG_free(sig);
-        return NULL;
+    else if (form == POINT_CONVERSION_UNCOMPRESSED
+#ifdef HAVE_COMP_KEY
+          || form == POINT_CONVERSION_COMPRESSED
+#endif
+             ) {
+        key->form = (char)form;
     }
-
-    sig->s = wolfSSL_BN_new();
-    if (sig->s == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure");
-        wolfSSL_ECDSA_SIG_free(sig);
-        return NULL;
+    else {
+        WOLFSSL_MSG("Incorrect form or HAVE_COMP_KEY not compiled in");
     }
-
-    return sig;
 }
 
-void wolfSSL_ECDSA_SIG_get0(const WOLFSSL_ECDSA_SIG* sig,
-    const WOLFSSL_BIGNUM** r, const WOLFSSL_BIGNUM** s)
+/* Get the EC group object that is in EC key.
+ *
+ * @param [in] key  EC key.
+ * @return  EC group object on success.
+ * @return  NULL when key is NULL.
+ */
+const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key)
 {
-    if (sig == NULL) {
-        return;
-    }
+    WOLFSSL_EC_GROUP* group = NULL;
 
-    if (r != NULL) {
-        *r = sig->r;
-    }
-    if (s != NULL) {
-        *s = sig->s;
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group");
+
+    if (key != NULL) {
+        group = key->group;
     }
+
+    return group;
 }
 
-int wolfSSL_ECDSA_SIG_set0(WOLFSSL_ECDSA_SIG* sig, WOLFSSL_BIGNUM* r,
-    WOLFSSL_BIGNUM* s)
+/* Set the group in WOLFSSL_EC_KEY
+ *
+ * @param [in, out] key    EC key to update.
+ * @param [in]      group  EC group to copy.
+ * @return  1 on success
+ * @return  0 on failure.
+ */
+int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group)
 {
-    if (sig == NULL || r == NULL || s == NULL) {
-        return 0;
-    }
+    int ret = 1;
 
-    wolfSSL_BN_free(sig->r);
-    wolfSSL_BN_free(sig->s);
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group");
 
-    sig->r = r;
-    sig->s = s;
+    /* Validate parameters. */
+    if ((key == NULL) || (group == NULL)) {
+        ret = 0;
+    }
 
-    return 1;
+    if (ret == 1) {
+        /* Dispose of the current group. */
+        if (key->group != NULL) {
+            wolfSSL_EC_GROUP_free(key->group);
+        }
+        /* Duplicate the passed in group into EC key. */
+        key->group = wolfSSL_EC_GROUP_dup(group);
+        if (key->group == NULL) {
+            ret = 0;
+        }
+    }
+
+    return ret;
 }
 
-/* return signature structure on success, NULL otherwise */
-WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen,
-                                         WOLFSSL_EC_KEY *key)
+/* Get the BN object that is the private key in the EC key.
+ *
+ * @param [in] key  EC key.
+ * @return  BN object on success.
+ * @return  NULL when key is NULL or private key is not set.
+ */
+WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key)
 {
-    WOLFSSL_ECDSA_SIG *sig = NULL;
-    int     initTmpRng = 0;
-    WC_RNG* rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG* tmpRng = NULL;
-    byte*   out = NULL;
-    mp_int* sig_r = NULL;
-    mp_int* sig_s = NULL;
-#else
-    WC_RNG  tmpRng[1];
-    byte    out[ECC_BUFSIZE];
-    mp_int sig_r[1], sig_s[1];
-#endif
-    word32 outlen = ECC_BUFSIZE;
+    WOLFSSL_BIGNUM* priv_key = NULL;
 
-    WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign");
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key");
 
-    if (d == NULL || key == NULL || key->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments");
-        return NULL;
+    /* Validate parameter. */
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments");
+    }
+    /* Only return private key if it is not 0. */
+    else if (!wolfSSL_BN_is_zero(key->priv_key)) {
+        priv_key = key->priv_key;
     }
 
-    /* set internal key if not done */
-    if (key->inSet == 0)
-    {
-        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it");
+    return priv_key;
+}
 
-        if (SetECKeyInternal(key) != 1) {
-            WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed");
-            return NULL;
-        }
-    }
+/* Sets the private key value into EC key.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in, out] key       EC key to set.
+ * @param [in]      priv_key  Private key value in a BN.
+ * @return  1 on success
+ * @return  0 on failure.
+ */
+int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key,
+                                   const WOLFSSL_BIGNUM *priv_key)
+{
+    int ret = 1;
 
-#ifdef WOLFSSL_SMALL_STACK
-    tmpRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    if (tmpRng == NULL)
-        return NULL;
-    out = (byte*)XMALLOC(outlen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (out == NULL) {
-        XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-        return NULL;
-    }
-    sig_r = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
-    if (sig_r == NULL) {
-        XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-        return NULL;
-    }
-    sig_s = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
-    if (sig_s == NULL) {
-        XFREE(sig_r, NULL, DYNAMIC_TYPE_BIGINT);
-        XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-        return NULL;
-    }
-#endif
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key");
 
-    if (wc_InitRng(tmpRng) == 0) {
-        rng = tmpRng;
-        initTmpRng = 1;
-    }
-    else {
-        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad RNG Init, trying global");
-        rng = wolfssl_get_global_rng();
+    /* Validate parameters. */
+    if ((key == NULL) || (priv_key == NULL)) {
+        WOLFSSL_MSG("Bad arguments");
+        ret = 0;
     }
 
-    if (rng) {
-        /* use wc_ecc_sign_hash because it supports crypto callbacks */
-        if (wc_ecc_sign_hash(d, dlen, out, &outlen, rng,
-                                                (ecc_key*)key->internal) == 0) {
-            if (mp_init_multi(sig_r, sig_s, NULL, NULL, NULL, NULL) == MP_OKAY) {
-               /* put signature blob in ECDSA structure */
-                if (DecodeECC_DSA_Sig(out, outlen, sig_r, sig_s) == 0) {
-                    sig = wolfSSL_ECDSA_SIG_new();
-                    if (sig == NULL) {
-                        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new failed");
-                    }
-                    else if (SetIndividualExternal(&sig->r, sig_r)
-                            != 1) {
-                        WOLFSSL_MSG("ecdsa r key error");
-                        wolfSSL_ECDSA_SIG_free(sig);
-                        sig = NULL;
-                    }
-                    else if (SetIndividualExternal(&sig->s, sig_s)
-                            != 1) {
-                        WOLFSSL_MSG("ecdsa s key error");
-                        wolfSSL_ECDSA_SIG_free(sig);
-                        sig = NULL;
-                    }
-                }
-                mp_free(sig_r);
-                mp_free(sig_s);
-            }
+    if (ret == 1) {
+        /* Free key if previously set. */
+        if (key->priv_key != NULL) {
+            wolfSSL_BN_free(key->priv_key);
         }
-        else {
-            WOLFSSL_MSG("wc_ecc_sign_hash failed");
+
+        /* Duplicate the BN passed in. */
+        key->priv_key = wolfSSL_BN_dup(priv_key);
+        if (key->priv_key == NULL) {
+            WOLFSSL_MSG("key ecc priv key NULL");
+            ret = 0;
         }
     }
+    /* Set the external values into internal EC key. */
+    if ((ret == 1) && (SetECKeyInternal(key) != 1)) {
+        WOLFSSL_MSG("SetECKeyInternal failed");
+        /* Dispose of new private key on error. */
+        wolfSSL_BN_free(key->priv_key);
+        key->priv_key = NULL;
+        ret = 0;
+    }
 
-    if (initTmpRng)
-        wc_FreeRng(tmpRng);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(sig_s, NULL, DYNAMIC_TYPE_BIGINT);
-    XFREE(sig_r, NULL, DYNAMIC_TYPE_BIGINT);
-    XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-#endif
-
-    return sig;
+    return ret;
 }
 
-/* return code compliant with OpenSSL :
- *   1 for a valid signature, 0 for an invalid signature and -1 on error
+/* Get the public key EC point object that is in EC key.
+ *
+ * @param [in] key  EC key.
+ * @return  EC point object that is the public key on success.
+ * @return  NULL when key is NULL.
  */
-int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen,
-                            const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key)
+WOLFSSL_EC_POINT* wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key)
 {
-    int check_sign = 0;
-#ifdef WOLF_CRYPTO_CB_ONLY_ECC
-    byte signature[ECC_MAX_SIG_SIZE];
-    word32 signaturelen = (word32)sizeof(signature);
-    char* r;
-    char* s;
-    int ret = 0;
-#endif
+    WOLFSSL_EC_POINT* pub_key = NULL;
 
-    WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify");
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key");
 
-    if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments");
-        return -1;
+    if (key != NULL) {
+        pub_key = key->pub_key;
     }
 
-    /* set internal key if not done */
-    if (key->inSet == 0)
-    {
-        WOLFSSL_MSG("No EC key internal set, do it");
+    return pub_key;
+}
 
-        if (SetECKeyInternal(key) != 1) {
-            WOLFSSL_MSG("SetECKeyInternal failed");
-            return -1;
-        }
-    }
+/*
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in, out] key  EC key.
+ * @param [in]      pub  Public key as an EC point.
+ * @return  1 on success
+ * @return  0 on failure.
+ */
+int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key,
+    const WOLFSSL_EC_POINT *pub)
+{
+    int ret = 1;
+    ecc_point *pub_p = NULL;
+    ecc_point *key_p = NULL;
 
-#ifndef WOLF_CRYPTO_CB_ONLY_ECC
-    if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal,
-                              (mp_int*)sig->s->internal, d, dlen, &check_sign,
-                              (ecc_key *)key->internal) != MP_OKAY) {
-        WOLFSSL_MSG("wc_ecc_verify_hash failed");
-        return -1;
-    }
-    else if (check_sign == 0) {
-        WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
-        return 0;
-    }
-#else
-    /* convert big number to hex */
-    r = wolfSSL_BN_bn2hex(sig->r);
-    s = wolfSSL_BN_bn2hex(sig->s);
-    /* get DER-encoded ECDSA signature */
-    ret = wc_ecc_rs_to_sig((const char*)r, (const char*)s,
-                                        signature, &signaturelen);
-    /* free r and s */
-    if (r)
-        XFREE(r, NULL, DYNAMIC_TYPE_OPENSSL);
-    if (s)
-        XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL);
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key");
 
-    if (ret != MP_OKAY) {
-        WOLFSSL_MSG("wc_ecc_verify_hash failed");
-        return -1;
+    /* Validate parameters. */
+    if ((key == NULL) || (key->internal == NULL) || (pub == NULL) ||
+            (pub->internal == NULL)) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_set_public_key Bad arguments");
+        ret = 0;
     }
-    /* verify hash. expects to call wc_CryptoCb_EccVerify internally */
-    ret = wc_ecc_verify_hash(signature, signaturelen, d, dlen, &check_sign,
-                        (ecc_key*)key->internal);
 
-    if (ret != MP_OKAY) {
-        WOLFSSL_MSG("wc_ecc_verify_hash failed");
-        return -1;
+    /* Ensure the internal EC key is set. */
+    if ((ret == 1) && (key->inSet == 0) && (SetECKeyInternal(key) != 1)) {
+        WOLFSSL_MSG("SetECKeyInternal failed");
+        ret = 0;
     }
-    else if (check_sign == 0) {
-        WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
-        return 0;
+
+    /* Ensure the internal EC point of pub is setup. */
+    if ((ret == 1) && (ec_point_setup(pub) != 1)) {
+        ret = 0;
     }
-#endif /* WOLF_CRYPTO_CB_ONLY_ECC */
 
-    return 1;
-}
+    if (ret == 1) {
+        /* Get the internal point of pub and the public key in key. */
+        pub_p = (ecc_point*)pub->internal;
+        key_p = (ecc_point*)key->pub_key->internal;
+
+        /* Create new point if required. */
+        if (key_p == NULL) {
+            key_p = wc_ecc_new_point();
+            key->pub_key->internal = (void*)key_p;
+        }
+        /* Check point available. */
+        if (key_p == NULL) {
+            WOLFSSL_MSG("key ecc point NULL");
+            ret = 0;
+        }
+    }
 
-WOLFSSL_ECDSA_SIG *wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG **sig,
-                                         const unsigned char **pp, long len)
-{
-    WOLFSSL_ECDSA_SIG *s = NULL;
+    /* Copy the internal pub point into internal key point. */
+    if ((ret == 1) && (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY)) {
+        WOLFSSL_MSG("ecc_copy_point failure");
+        ret = 0;
+    }
 
-    if (pp == NULL)
-        return NULL;
-    if (sig != NULL)
-        s = *sig;
-    if (s == NULL) {
-        s = wolfSSL_ECDSA_SIG_new();
-        if (s == NULL)
-            return NULL;
+    /* Copy the internal point data into external. */
+    if ((ret == 1) && (ec_point_external_set(key->pub_key) != 1)) {
+        WOLFSSL_MSG("SetECKeyInternal failed");
+        ret = 0;
     }
 
-    /* DecodeECC_DSA_Sig calls mp_init, so free these */
-    mp_free((mp_int*)s->r->internal);
-    mp_free((mp_int*)s->s->internal);
+    /* Copy the internal key into external. */
+    if ((ret == 1) && (SetECKeyInternal(key) != 1)) {
+        WOLFSSL_MSG("SetECKeyInternal failed");
+        ret = 0;
+    }
 
-    if (DecodeECC_DSA_Sig(*pp, (word32)len, (mp_int*)s->r->internal,
-                                          (mp_int*)s->s->internal) != MP_OKAY) {
-        if (sig == NULL || *sig == NULL)
-            wolfSSL_ECDSA_SIG_free(s);
-        return NULL;
+    if (ret == 1) {
+        /* Dump out the point and the key's public key for debug. */
+        wolfSSL_EC_POINT_dump("pub", pub);
+        wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key);
     }
 
-    *pp += len;
-    if (sig != NULL)
-        *sig = s;
-    return s;
+    return ret;
 }
 
-int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp)
+#ifndef NO_WOLFSSL_STUB
+/* Set the ASN.1 encoding flag against the EC key.
+ *
+ * No implementation as only named curves supported for encoding.
+ *
+ * @param [in, out] key   EC key.
+ * @param [in]      flag  ASN.1 flag to set. Valid values:
+ *                        OPENSSL_EC_EXPLICIT_CURVE, OPENSSL_EC_NAMED_CURVE
+ */
+void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag)
 {
-    word32 len;
-
-    if (sig == NULL)
-        return 0;
-
-    /* ASN.1: SEQ + INT + INT
-     *   ASN.1 Integer must be a positive value - prepend zero if number has
-     *   top bit set.
-     */
-    len = 2 + mp_leading_bit((mp_int*)sig->r->internal) +
-              mp_unsigned_bin_size((mp_int*)sig->r->internal) +
-          2 + mp_leading_bit((mp_int*)sig->s->internal) +
-              mp_unsigned_bin_size((mp_int*)sig->s->internal);
-    /* Two bytes required for length if ASN.1 SEQ data greater than 127 bytes
-     * and less than 256 bytes.
-     */
-    len = 1 + ((len > 127) ? 2 : 1) + len;
-    if (pp != NULL && *pp != NULL) {
-        if (StoreECC_DSA_Sig(*pp, &len, (mp_int*)sig->r->internal,
-                                        (mp_int*)sig->s->internal) != MP_OKAY) {
-            len = 0;
-        }
-        else
-            *pp += len;
-    }
+    (void)key;
+    (void)asn1_flag;
 
-    return (int)len;
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag");
+    WOLFSSL_STUB("EC_KEY_set_asn1_flag");
 }
-/* End ECDSA_SIG */
+#endif
 
-#ifndef WOLF_CRYPTO_CB_ONLY_ECC
-/* Start ECDH */
-/* return code compliant with OpenSSL :
- *   length of computed key if success, -1 if error
+/*
+ * EC key generate key APIs
+ */
+
+/* Generate an EC key.
+ *
+ * Uses the internal curve index set in the EC key or the default.
+ *
+ * @param [in, out] key  EC key.
+ * @return  1 on success
+ * @return  0 on failure.
  */
-int wolfSSL_ECDH_compute_key(void *out, size_t outlen,
-                             const WOLFSSL_EC_POINT *pub_key,
-                             WOLFSSL_EC_KEY *ecdh,
-                             void *(*KDF) (const void *in, size_t inlen,
-                                           void *out, size_t *outlen))
+int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key)
 {
-    word32 len;
-    ecc_key* key;
-    int ret;
-#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
-    (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
-    int setGlobalRNG = 0;
+    int res = 1;
+    int initTmpRng = 0;
+    WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRng = NULL;
+#else
+    WC_RNG  tmpRng[1];
 #endif
-    (void)KDF;
 
-    WOLFSSL_ENTER("wolfSSL_ECDH_compute_key");
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key");
 
-    if (out == NULL || pub_key == NULL || pub_key->internal == NULL ||
-        ecdh == NULL || ecdh->internal == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return -1;
+    /* Validate parameters. */
+    if ((key == NULL) || (key->internal == NULL) || (key->group == NULL)) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments");
+        res = 0;
     }
+    if (res == 1) {
+        /* Check if we know which internal curve index to use. */
+        if (key->group->curve_idx < 0) {
+            /* Generate key using the default curve. */
+            key->group->curve_idx = ECC_CURVE_DEF;
+        }
 
-    /* set internal key if not done */
-    if (ecdh->inSet == 0)
-    {
-        WOLFSSL_MSG("No EC key internal set, do it");
-
-        if (SetECKeyInternal(ecdh) != 1) {
-            WOLFSSL_MSG("SetECKeyInternal failed");
-            return -1;
+        /* Create a random number generator. */
+        rng = wolfssl_make_rng(tmpRng, &initTmpRng);
+        if (rng == NULL) {
+            WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG");
+            res = 0;
         }
     }
-
-    len = (word32)outlen;
-    key = (ecc_key*)ecdh->internal;
-
-#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
-    (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
-    if (key->rng == NULL) {
-        if ((key->rng = wolfssl_get_global_rng()) == NULL) {
-            if (wolfSSL_RAND_Init() != 1) {
-                WOLFSSL_MSG("No RNG to use");
-                return -1;
-            }
-            key->rng = wolfssl_get_global_rng();
+    if (res == 1) {
+        /* NIDToEccEnum returns -1 for invalid NID so if key->group->curve_nid
+         * is 0 then pass ECC_CURVE_DEF as arg */
+        int eccEnum = key->group->curve_nid ?
+            NIDToEccEnum(key->group->curve_nid) : ECC_CURVE_DEF;
+        /* Get the internal EC key. */
+        ecc_key* ecKey = (ecc_key*)key->internal;
+        /* Make the key using internal API. */
+        int ret = wc_ecc_make_key_ex(rng, 0, ecKey, eccEnum);
+    #if defined(WOLFSSL_ASYNC_CRYPT)
+        /* Wait on asynchronouse operation. */
+        ret = wc_AsyncWait(ret, &ecKey->asyncDev, WC_ASYNC_FLAG_NONE);
+    #endif
+        if (ret != 0) {
+            WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed");
+            res = 0;
         }
-        setGlobalRNG = 1;
     }
-#endif
-    PRIVATE_KEY_UNLOCK();
-    ret = wc_ecc_shared_secret_ssh(key, (ecc_point*)pub_key->internal,
-            (byte *)out, &len);
-    PRIVATE_KEY_LOCK();
-#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
-    (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
-    if (setGlobalRNG)
-        key->rng = NULL;
-#endif
-    if (ret != MP_OKAY) {
-        WOLFSSL_MSG("wc_ecc_shared_secret failed");
-        return -1;
+
+    /* Dispose of local random number generator if initialized. */
+    if (initTmpRng) {
+        wc_FreeRng(rng);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+    #endif
     }
 
-    return len;
+    /* Set the external key from new internal key values. */
+    if ((res == 1) && (SetECKeyExternal(key) != 1)) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed");
+        res = 0;
+    }
+
+    return res;
 }
-#endif /* WOLF_CRYPTO_CB_ONLY_ECC */
-/* End ECDH */
-#if !defined(NO_FILESYSTEM)
 
-#ifndef NO_BIO
+/*
+ * EC key check key APIs
+ */
 
-#ifdef WOLFSSL_KEY_GEN
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
+/* Check that the EC key is valid.
+ *
+ * @param [in] key  EC key.
+ * @return  1 on valid.
+ * @return  0 on invalid or error.
  */
-int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key)
+int wolfSSL_EC_KEY_check_key(const WOLFSSL_EC_KEY *key)
 {
     int ret = 1;
-    WOLFSSL_BIO* bio = NULL;
 
-    WOLFSSL_ENTER("wolfSSL_PEM_write_EC_PUBKEY");
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_check_key");
 
-    if (fp == XBADFILE || key == NULL) {
-        WOLFSSL_MSG("Bad argument.");
+    /* Validate parameter. */
+    if ((key == NULL) || (key->internal == NULL)) {
+        WOLFSSL_MSG("Bad parameter");
         ret = 0;
     }
 
-    if (ret == 1) {
-        bio = wolfSSL_BIO_new_fp(fp, BIO_NOCLOSE);
-        if (bio == NULL) {
-            WOLFSSL_MSG("wolfSSL_BIO_new failed.");
-            ret = 0;
-        }
-    }
-    if (ret == 1 && wolfSSL_PEM_write_bio_EC_PUBKEY(bio, key)
-        != 1) {
-        WOLFSSL_MSG("wolfSSL_PEM_write_bio_EC_PUBKEY failed.");
+    /* Set the external EC key values into internal if not already. */
+    if ((ret == 1) && (key->inSet == 0) && (SetECKeyInternal(
+            (WOLFSSL_EC_KEY*)key) != 1)) {
+        WOLFSSL_MSG("SetECKeyInternal failed");
         ret = 0;
     }
 
-    if (bio != NULL) {
-        wolfSSL_BIO_free(bio);
+    if (ret == 1) {
+        /* Have internal EC implementation check key. */
+        ret = wc_ecc_check_key((ecc_key*)key->internal) == 0;
     }
 
-    WOLFSSL_LEAVE("wolfSSL_PEM_write_EC_PUBKEY", ret);
-
     return ret;
 }
-#endif
 
-/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects
- * the results to be an EC key.
- *
- * bio  structure to read EC private key from
- * ec   if not null is then set to the result
- * cb   password callback for reading PEM
- * pass password string
+/* End EC_KEY */
+
+#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
+/* Get the supported, built-in EC curves
  *
- * returns a pointer to a new WOLFSSL_EC_KEY struct on success and NULL on fail
+ * @param [in, out] curves  Pre-allocated list to put supported curves into.
+ * @param [in]      len     Maximum number of items to place in list.
+ * @return  Number of built-in EC curves when curves is NULL or len is 0.
+ * @return  Number of items placed in list otherwise.
  */
-
-WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio,
-                                               WOLFSSL_EC_KEY** ec,
-                                               wc_pem_password_cb* cb,
-                                               void *pass)
+size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *curves,
+    size_t len)
 {
-    WOLFSSL_EVP_PKEY* pkey;
-    WOLFSSL_EC_KEY* local;
-
-    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY");
+    size_t i;
+    size_t cnt;
+#ifdef HAVE_SELFTEST
+    /* Defined in ecc.h when available. */
+    size_t ecc_sets_count;
 
-    pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass);
-    if (pkey == NULL) {
-        return NULL;
+    /* Count the pre-defined curves since global not available. */
+    for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++) {
+        /* Do nothing. */
     }
+    ecc_sets_count = i;
+#endif
 
-    /* Since the WOLFSSL_EC_KEY structure is being taken from WOLFSSL_EVP_PKEY the
-     * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE
-     * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE
-     * to avoid having it free'd */
-    pkey->ownEcc = 0;
-    local = pkey->ecc;
-    if (ec != NULL) {
-        *ec = local;
+    /* Assume we are going to return total count. */
+    cnt = ecc_sets_count;
+    /* Check we have a list that can hold data. */
+    if ((curves != NULL) && (len != 0)) {
+        /* Limit count to length of list. */
+        if (cnt > len) {
+            cnt = len;
+        }
+
+        /* Put in built-in EC curve nid and short name. */
+        for (i = 0; i < cnt; i++) {
+            curves[i].nid = EccEnumToNID(ecc_sets[i].id);
+            curves[i].comment = wolfSSL_OBJ_nid2sn(curves[i].nid);
+        }
     }
 
-    wolfSSL_EVP_PKEY_free(pkey);
-    return local;
+    return cnt;
 }
+#endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */
 
-/* Reads a private EC key from a WOLFSSL_BIO into a WOLFSSL_EC_KEY.
- * Returns 1 or 0
+/* Start ECDSA_SIG */
+
+/* Allocate a new ECDSA signature object.
+ *
+ * @return  New, allocated ECDSA signature object on success.
+ * @return  NULL on error.
  */
-WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio,
-                                                  WOLFSSL_EC_KEY** ec,
-                                                  wc_pem_password_cb* cb,
-                                                  void *pass)
+WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void)
 {
-    WOLFSSL_EVP_PKEY* pkey;
-    WOLFSSL_EC_KEY* local;
+    int err = 0;
+    WOLFSSL_ECDSA_SIG *sig;
 
-    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_ECPrivateKey");
+    WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new");
 
-    pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
-    if (pkey == NULL) {
-        return NULL;
+    /* Allocate memory for ECDSA signature object. */
+    sig = (WOLFSSL_ECDSA_SIG*)XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL,
+        DYNAMIC_TYPE_ECC);
+    if (sig == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure");
+        err = 1;
     }
 
-    /* Since the WOLFSSL_EC_KEY structure is being taken from WOLFSSL_EVP_PKEY the
-     * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE
-     * to avoid having it free'd */
-    pkey->ownEcc = 0;
-    local = pkey->ecc;
-    if (ec != NULL) {
-        *ec = local;
+    if (!err) {
+        /* Set s to NULL in case of error. */
+        sig->s = NULL;
+        /* Allocate BN into r. */
+        sig->r = wolfSSL_BN_new();
+        if (sig->r == NULL) {
+            WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure");
+            err = 1;
+        }
+    }
+    if (!err) {
+        /* Allocate BN into s. */
+        sig->s = wolfSSL_BN_new();
+        if (sig->s == NULL) {
+            WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure");
+            err = 1;
+        }
     }
 
-    wolfSSL_EVP_PKEY_free(pkey);
-    return local;
+    if (err && (sig != NULL)) {
+        /* Dispose of allocated memory. */
+        wolfSSL_ECDSA_SIG_free(sig);
+        sig = NULL;
+    }
+    return sig;
 }
-#endif /* !NO_BIO */
-#endif /* NO_FILESYSTEM */
 
-#if defined(WOLFSSL_KEY_GEN)
-#ifndef NO_BIO
-/* Takes a public WOLFSSL_EC_KEY and writes it out to WOLFSSL_BIO
- * Returns 1 or 0
+/* Dispose of ECDSA signature object.
+ *
+ * Cannot use object after this call.
+ *
+ * @param [in] sig  ECDSA signature object to free.
  */
-int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec)
+void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig)
 {
-    int ret = 0;
-    WOLFSSL_EVP_PKEY* pkey;
+    WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free");
 
-    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_EC_PUBKEY");
+    if (sig != NULL) {
+        /* Dispose of BNs allocated for r and s. */
+        wolfSSL_BN_free(sig->r);
+        wolfSSL_BN_free(sig->s);
 
-    if (bio == NULL || ec == NULL) {
-        WOLFSSL_MSG("Bad Function Arguments");
-        return 0;
+        /* Dispose of memory associated with ECDSA signature object. */
+        XFREE(sig, NULL, DYNAMIC_TYPE_ECC);
     }
+}
 
-    /* Initialize pkey structure */
-    pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
-    if (pkey == NULL) {
-        WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
-        return 0;
+/* Create an ECDSA signature from the DER encoding.
+ *
+ * @param [in, out] sig  Reference to ECDSA signature object. May be NULL.
+ * @param [in, out] pp   On in, reference to buffer containing DER encoding.
+ *                       On out, reference to buffer after signature data.
+ * @param [in]      len  Length of the data in the buffer. May be more than
+ *                       the length of the signature.
+ * @return  ECDSA signature object on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_ECDSA_SIG* wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG** sig,
+    const unsigned char** pp, long len)
+{
+    int err = 0;
+    /* ECDSA signature object to return. */
+    WOLFSSL_ECDSA_SIG *s = NULL;
+
+    /* Validate parameter. */
+    if (pp == NULL) {
+        err = 1;
+    }
+    if (!err) {
+        if (sig != NULL) {
+            /* Use the ECDSA signature object passed in. */
+            s = *sig;
+        }
+        if (s == NULL) {
+            /* No ECDSA signature object passed in - create a new one. */
+            s = wolfSSL_ECDSA_SIG_new();
+            if (s == NULL) {
+                err = 1;
+            }
+        }
     }
+    if (!err) {
+        /* DecodeECC_DSA_Sig calls mp_init, so free these. */
+        mp_free((mp_int*)s->r->internal);
+        mp_free((mp_int*)s->s->internal);
 
-    /* Set pkey info */
-    pkey->ecc    = ec;
-    pkey->ownEcc = 0; /* pkey does not own ECC */
-    pkey->type = EVP_PKEY_EC;
+        /* Decode the signature into internal r and s fields. */
+        if (DecodeECC_DSA_Sig(*pp, (word32)len, (mp_int*)s->r->internal,
+                (mp_int*)s->s->internal) != MP_OKAY) {
+            err = 1;
+        }
+    }
 
-    if ((ret = pem_write_bio_pubkey(bio, pkey)) != 1) {
-        WOLFSSL_MSG("wolfSSL_PEM_write_bio_PUBKEY failed");
+    if (!err) {
+        /* Move pointer passed signature data successfully decoded. */
+        *pp += wolfssl_der_length(*pp, (int)len);
+        if (sig != NULL) {
+            /* Update reference to ECDSA signature object. */
+            *sig = s;
+        }
     }
-    wolfSSL_EVP_PKEY_free(pkey);
 
-    return ret;
+    /* Dispose of newly allocated object on error. */
+    if (err) {
+        if ((s != NULL) && ((sig == NULL) || (*sig != s))) {
+            wolfSSL_ECDSA_SIG_free(s);
+        }
+        /* Return NULL for object on error. */
+        s = NULL;
+    }
+    return s;
 }
 
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
+/* Encode the ECDSA signature as DER.
+ *
+ * @param [in]      sig  ECDSA signature object.
+ * @param [in, out] pp   On in, reference to buffer in which to place encoding.
+ *                       On out, reference to buffer after encoding.
+ *                       May be NULL or point to NULL in which case no encoding
+ *                       is done.
+ * @return  Length of encoding on success.
+ * @return  0 on error.
  */
-int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec,
-                                       const EVP_CIPHER* cipher,
-                                       unsigned char* passwd, int len,
-                                       wc_pem_password_cb* cb, void* arg)
+int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp)
 {
-    int ret = 0, der_max_len = 0, derSz = 0;
-    byte *derBuf;
-    WOLFSSL_EVP_PKEY* pkey;
-    WOLFSSL_ENTER("WOLFSSL_PEM_write_bio_ECPrivateKey");
+    word32 rLen;
+    word32 sLen;
+    word32 len = 0;
 
-    if (bio == NULL || ec == NULL) {
-        WOLFSSL_MSG("Bad Function Arguments");
-        return 0;
-    }
+    /* Validate parameter. */
+    if (sig != NULL) {
+        /* ASN.1: SEQ + INT + INT
+         *   ASN.1 Integer must be a positive value - prepend zero if number has
+         *   top bit set.
+         */
+        /* Get total length of r including any prepended zero. */
+        rLen = mp_leading_bit((mp_int*)sig->r->internal) +
+               mp_unsigned_bin_size((mp_int*)sig->r->internal);
+        /* Get total length of s including any prepended zero. */
+        sLen = mp_leading_bit((mp_int*)sig->s->internal) +
+               mp_unsigned_bin_size((mp_int*)sig->s->internal);
+        /* Calculate length of data in sequence. */
+        len = 1 + ASN_LEN_SIZE(rLen) + rLen +
+              1 + ASN_LEN_SIZE(sLen) + sLen;
+        /* Add in the length of the SEQUENCE. */
+        len += 1 + ASN_LEN_SIZE(len);
 
-    /* Initialize pkey structure */
-    pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
-    if (pkey == NULL) {
-        WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
-        return 0;
+        /* Encode only if there is a buffer to encode into. */
+        if ((pp != NULL) && (*pp != NULL)) {
+            /* Encode using the internal representations of r and s. */
+            if (StoreECC_DSA_Sig(*pp, &len, (mp_int*)sig->r->internal,
+                    (mp_int*)sig->s->internal) != MP_OKAY) {
+                /* No bytes encoded. */
+                len = 0;
+            }
+            else {
+                /* Update pointer to after encoding. */
+                *pp += len;
+            }
+        }
     }
 
-    /* Set pkey info */
-    pkey->ecc    = ec;
-    pkey->ownEcc = 0; /* pkey does not own ECC */
-    pkey->type = EVP_PKEY_EC;
-
-    /* 4 > size of pub, priv + ASN.1 additional informations
-     */
-    der_max_len = 4 * wc_ecc_size((ecc_key*)ec->internal) + AES_BLOCK_SIZE;
+    return (int)len;
+}
 
-    derBuf = (byte*)XMALLOC(der_max_len, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (derBuf == NULL) {
-        WOLFSSL_MSG("Malloc failed");
-        wolfSSL_EVP_PKEY_free(pkey);
-        return 0;
+/* Get the pointer to the feilds of the ECDSA signature.
+ *
+ * r and s untouched when sig is NULL.
+ *
+ * @param [in]  sig  ECDSA signature object.
+ * @param [out] r    R field of ECDSA siganture as a BN. May be NULL.
+ * @param [out] s    S field of ECDSA siganture as a BN. May be NULL.
+ */
+void wolfSSL_ECDSA_SIG_get0(const WOLFSSL_ECDSA_SIG* sig,
+    const WOLFSSL_BIGNUM** r, const WOLFSSL_BIGNUM** s)
+{
+    /* Validate parameter. */
+    if (sig != NULL) {
+        /* Return the r BN when pointer to return through. */
+        if (r != NULL) {
+            *r = sig->r;
+        }
+        /* Return the s BN when pointer to return through. */
+        if (s != NULL) {
+            *s = sig->s;
+        }
     }
+}
 
-    /* convert key to der format */
-    derSz = wc_EccKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len);
-    if (derSz < 0) {
-        WOLFSSL_MSG("wc_EccKeyToDer failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        wolfSSL_EVP_PKEY_free(pkey);
-        return 0;
-    }
+/* Set the pointers to the fields of the ECDSA signature.
+ *
+ * @param [in, out] sig  ECDSA signature object to update.
+ * @param [in]      r    R field of ECDSA siganture as a BN.
+ * @param [in]      s    S field of ECDSA siganture as a BN.
+ * @return  1 on success.
+ * @return  0 on error.
+ */
+int wolfSSL_ECDSA_SIG_set0(WOLFSSL_ECDSA_SIG* sig, WOLFSSL_BIGNUM* r,
+    WOLFSSL_BIGNUM* s)
+{
+    int ret = 1;
 
-    pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (pkey->pkey.ptr == NULL) {
-        WOLFSSL_MSG("key malloc failed");
-        XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        wolfSSL_EVP_PKEY_free(pkey);
-        return 0;
+    /* Validate parameters. */
+    if ((sig == NULL) || (r == NULL) || (s == NULL)) {
+        ret = 0;
     }
 
-    /* add der info to the evp key */
-    pkey->pkey_sz = derSz;
-    XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
-    XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (ret == 1) {
+        /* Dispose of old BN objects. */
+        wolfSSL_BN_free(sig->r);
+        wolfSSL_BN_free(sig->s);
 
-    ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len,
-                                        cb, arg);
-    wolfSSL_EVP_PKEY_free(pkey);
+        /* Assign new BN objects. */
+        sig->r = r;
+        sig->s = s;
+    }
 
     return ret;
 }
 
-#endif /* !NO_BIO */
+/* End ECDSA_SIG */
 
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
+/* Start ECDSA */
+
+/* Calculate maximum size of the DER encoded ECDSA signature for the curve.
+ *
+ * @param [in] key  EC key.
+ * @return  Size of DER encoded signature on success.
+ * @return  0 on error.
  */
-int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc,
-                                       const EVP_CIPHER* cipher,
-                                       unsigned char* passwd, int passwdSz,
-                                       unsigned char **pem, int *plen)
+int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key)
 {
-#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
-    byte *derBuf, *tmp, *cipherInfo = NULL;
-    int  der_max_len = 0, derSz = 0;
-    const int type = ECC_PRIVATEKEY_TYPE;
-    const char* header = NULL;
-    const char* footer = NULL;
+    int err = 0;
+    int len = 0;
+    const EC_GROUP *group = NULL;
+    int bits = 0;
 
-    WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey");
-    if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return 0;
+    /* Validate parameter. */
+    if (key == NULL) {
+        err = 1;
     }
 
-    if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
-        return 0;
+    /* Get group from key to get order bits. */
+    if ((!err) && ((group = wolfSSL_EC_KEY_get0_group(key)) == NULL)) {
+        err = 1;
+    }
+    /* Get order bits of group. */
+    if ((!err) && ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0)) {
+        /* Group is not set. */
+        err = 1;
+    }
+
+    if (!err) {
+        /* r and s are mod order. */
+        int bytes = (bits + 7) / 8;  /* Bytes needed to hold bits. */
+        len = SIG_HEADER_SZ + /* 2*ASN_TAG + 2*LEN(ENUM) */
+            ECC_MAX_PAD_SZ +  /* possible leading zeroes in r and s */
+            bytes + bytes;    /* max r and s in bytes */
+    }
+
+    return len;
+}
+
+/* Create ECDSA signature by signing digest with key.
+ *
+ * @param [in] dgst  Digest to sign.
+ * @param [in] dLen  Length of digest in bytes.
+ * @param [in] key   EC key to sign with.
+ * @return  ECDSA signature object on success.
+ * @return  NULL on error.
+ */
+WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *dgst, int dLen,
+    WOLFSSL_EC_KEY *key)
+{
+    int err = 0;
+    WOLFSSL_ECDSA_SIG *sig = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    byte*   out = NULL;
+#else
+    byte    out[ECC_BUFSIZE];
+#endif
+    unsigned int outLen = ECC_BUFSIZE;
+
+    WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign");
+
+    /* Validate parameters. */
+    if ((dgst == NULL) || (key == NULL) || (key->internal == NULL)) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments");
+        err = 1;
+    }
 
-    if (ecc->inSet == 0) {
-        WOLFSSL_MSG("No ECC internal set, do it");
+    /* Ensure internal EC key is set from external. */
+    if ((!err) && (key->inSet == 0)) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it");
 
-        if (SetECKeyInternal(ecc) != 1) {
-            WOLFSSL_MSG("SetECKeyInternal failed");
-            return 0;
+        if (SetECKeyInternal(key) != 1) {
+            WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed");
+            err = 1;
         }
     }
 
-    /* 4 > size of pub, priv + ASN.1 additional information */
-    der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE;
+#ifdef WOLFSSL_SMALL_STACK
+    if (!err) {
+        /* Allocate buffer to hold encoded signature. */
+        out = (byte*)XMALLOC(outLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (out == NULL) {
+            err = 1;
+        }
+    }
+#endif
 
-    derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
-    if (derBuf == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        return 0;
+    /* Sign the digest with the key to create encoded ECDSA signature. */
+    if ((!err) && (wolfSSL_ECDSA_sign(0, dgst, dLen, out, &outLen, key) != 1)) {
+        err = 1;
     }
 
-    /* Key to DER */
-    derSz = wc_EccKeyToDer((ecc_key*)ecc->internal, derBuf, der_max_len);
-    if (derSz < 0) {
-        WOLFSSL_MSG("wc_EccKeyToDer failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        return 0;
+    if (!err) {
+        const byte* p = out;
+        /* Decode the ECDSA signature into a new object. */
+        sig = wolfSSL_d2i_ECDSA_SIG(NULL, &p, outLen);
     }
 
-    /* encrypt DER buffer if required */
-    if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
-        int ret;
+#ifdef WOLFSSL_SMALL_STACK
+    /* Dispose of any temporary dynamically allocated data. */
+    XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
 
-        ret = EncryptDerKey(derBuf, &derSz, cipher,
-                            passwd, passwdSz, &cipherInfo, der_max_len);
-        if (ret != 1) {
-            WOLFSSL_MSG("EncryptDerKey failed");
-            XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-            return ret;
-        }
+    return sig;
+}
 
-        /* tmp buffer with a max size */
-        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
-            (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
-    }
-    else { /* tmp buffer with a max size */
-        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
-            (int)XSTRLEN(footer) + 1;
-    }
+/* Verify ECDSA signature in the object using digest and key.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] dgst  Digest to verify.
+ * @param [in] dLen  Length of the digest in bytes.
+ * @param [in] sig   ECDSA signature object.
+ * @param [in] key   EC key containing public key.
+ * @return  1 when signature is valid.
+ * @return  0 when signature is invalid.
+ * @return  -1 on error.
+ */
+int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen,
+    const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key)
+{
+    int ret = 1;
+    int verified = 0;
+#ifdef WOLF_CRYPTO_CB_ONLY_ECC
+    byte signature[ECC_MAX_SIG_SIZE];
+    int signatureLen;
+    byte* p = signature;
+#endif
 
-    tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
-    if (tmp == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        if (cipherInfo != NULL)
-            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-        return 0;
-    }
+    WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify");
 
-    /* DER to PEM */
-    *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
-    if (*plen <= 0) {
-        WOLFSSL_MSG("wc_DerToPemEx failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        if (cipherInfo != NULL)
-            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-        return 0;
+    /* Validate parameters. */
+    if ((dgst == NULL) || (sig == NULL) || (key == NULL) ||
+            (key->internal == NULL)) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments");
+        ret = -1;
     }
-    XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-    if (cipherInfo != NULL)
-        XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
 
-    *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
-    if (*pem == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        return 0;
-    }
-    XMEMSET(*pem, 0, (*plen)+1);
+    /* Ensure internal EC key is set from external. */
+    if ((ret == 1) && (key->inSet == 0)) {
+        WOLFSSL_MSG("No EC key internal set, do it");
 
-    if (XMEMCPY(*pem, tmp, *plen) == NULL) {
-        WOLFSSL_MSG("XMEMCPY failed");
-        XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        return 0;
+        if (SetECKeyInternal(key) != 1) {
+            WOLFSSL_MSG("SetECKeyInternal failed");
+            ret = -1;
+        }
     }
-    XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
 
-    return 1;
+    if (ret == 1) {
+#ifndef WOLF_CRYPTO_CB_ONLY_ECC
+        /* Verify hash using digest, r and s as MP ints and internal EC key. */
+        if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal,
+                (mp_int*)sig->s->internal, dgst, dLen, &verified,
+                (ecc_key *)key->internal) != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_verify_hash failed");
+            ret = -1;
+        }
+        else if (verified == 0) {
+            WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
+            ret = 0;
+        }
 #else
-    (void)ecc;
-    (void)cipher;
-    (void)passwd;
-    (void)passwdSz;
-    (void)pem;
-    (void)plen;
-    return 0;
-#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+        signatureLen = i2d_ECDSA_SIG(sig, &p);
+        if (signatureLen > 0) {
+            /* verify hash. expects to call wc_CryptoCb_EccVerify internally */
+            ret = wc_ecc_verify_hash(signature, signatureLen, dgst, dLen,
+                &verified, (ecc_key*)key->internal);
+            if (ret != MP_OKAY) {
+                WOLFSSL_MSG("wc_ecc_verify_hash failed");
+                ret = -1;
+            }
+            else if (verified == 0) {
+                WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
+                ret = 0;
+            }
+        }
+#endif /* WOLF_CRYPTO_CB_ONLY_ECC */
+    }
+
+    return ret;
 }
 
-#ifndef NO_FILESYSTEM
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
+/* Sign the digest with the key to produce a DER encode signature.
+ *
+ * @param [in]      type      Digest algorithm used to create digest. Unused.
+ * @param [in]      digest    Digest of the message to sign.
+ * @param [in]      digestSz  Size of the digest in bytes.
+ * @param [out]     sig       Buffer to hold signature.
+ * @param [in, out] sigSz     On in, size of buffer in bytes.
+ *                            On out, size of signatre in bytes.
+ * @param [in]      key       EC key containing private key.
+ * @return  1 on success.
+ * @return  0 on error.
  */
-int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ecc,
-                                   const EVP_CIPHER *enc,
-                                   unsigned char *kstr, int klen,
-                                   wc_pem_password_cb *cb, void *u)
+int wolfSSL_ECDSA_sign(int type, const unsigned char *digest, int digestSz,
+    unsigned char *sig, unsigned int *sigSz, WOLFSSL_EC_KEY *key)
 {
-    byte *pem;
-    int  plen, ret;
+    int ret = 1;
+    WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRng = NULL;
+#else
+    WC_RNG  tmpRng[1];
+#endif
+    int initTmpRng = 0;
 
-    (void)cb;
-    (void)u;
+    WOLFSSL_ENTER("wolfSSL_ECDSA_sign");
 
-    WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey");
+    /* Digest algorithm not used in DER encoding. */
+    (void)type;
 
-    if (fp == XBADFILE || ecc == NULL || ecc->internal == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return 0;
+    /* Validate parameters. */
+    if (key == NULL) {
+        ret = 0;
     }
 
-    ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen);
-    if (ret != 1) {
-        WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed");
-        return 0;
+    if (ret == 1) {
+        /* Make an RNG - create local or get global. */
+        rng = wolfssl_make_rng(tmpRng, &initTmpRng);
+        if (rng == NULL) {
+            ret = 0;
+        }
+    }
+    /* Sign the digest with the key using the RNG and put signature into buffer
+     * update sigSz to be actual length.
+     */
+    if ((ret == 1) && (wc_ecc_sign_hash(digest, digestSz, sig, sigSz, rng,
+            (ecc_key*)key->internal) != 0)) {
+        ret = 0;
     }
 
-    ret = (int)XFWRITE(pem, plen, 1, fp);
-    if (ret != 1) {
-        WOLFSSL_MSG("ECC private key file write failed");
-        return 0;
+    if (initTmpRng) {
+        wc_FreeRng(rng);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+    #endif
     }
 
-    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
-    return 1;
+    return ret;
 }
 
-#endif /* NO_FILESYSTEM */
-#endif /* defined(WOLFSSL_KEY_GEN) */
+/* Verify the signature with the digest and key.
+ *
+ * @param [in] type      Digest algorithm used to create digest. Unused.
+ * @param [in] digest    Digest of the message to verify.
+ * @param [in] digestSz  Size of the digest in bytes.
+ * @param [in] sig       Buffer holding signature.
+ * @param [in] sigSz     Size of signature data in bytes.
+ * @param [in] key       EC key containing public key.
+ * @return  1 when signature is valid.
+ * @return  0 when signature is invalid or error.
+ */
+int wolfSSL_ECDSA_verify(int type, const unsigned char *digest, int digestSz,
+    const unsigned char *sig, int sigSz, WOLFSSL_EC_KEY *key)
+{
+    int ret = 1;
+    int verify = 0;
 
-#ifndef NO_BIO
+    WOLFSSL_ENTER("wolfSSL_ECDSA_verify");
 
-/* returns a new WOLFSSL_EC_GROUP structure on success and NULL on fail */
-WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio,
-        WOLFSSL_EC_GROUP** group, wc_pem_password_cb* cb, void* pass)
-{
-    WOLFSSL_EVP_PKEY* pkey;
-    WOLFSSL_EC_GROUP* ret = NULL;
+    /* Digest algorithm not used in DER encoding. */
+    (void)type;
 
-    /* check on if bio is null is done in wolfSSL_PEM_read_bio_PrivateKey */
-    pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
-    if (pkey != NULL) {
-        if (pkey->type != EVP_PKEY_EC) {
-            WOLFSSL_MSG("Unexpected key type");
-        }
-        else {
-            ret = (WOLFSSL_EC_GROUP*)wolfSSL_EC_KEY_get0_group(pkey->ecc);
+    /* Validate parameters. */
+    if (key == NULL) {
+        ret = 0;
+    }
 
-            /* set ecc group to null so it is not free'd when pkey is free'd */
-            pkey->ecc->group = NULL;
-        }
+    /* Verify signature using digest and key. */
+    if ((ret == 1) && (wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verify,
+            (ecc_key*)key->internal) != 0)) {
+        ret = 0;
+    }
+    /* When no error, verification may still have failed - check now. */
+    if ((ret == 1) && (verify != 1)) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_verify failed");
+        ret = 0;
     }
 
-    (void)group;
-    wolfSSL_EVP_PKEY_free(pkey);
     return ret;
 }
 
-#endif /* !NO_BIO */
+/* End ECDSA */
 
-/* return 1 if success, -1 if error */
-int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
-                           int derSz)
-{
-    return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz,
-                                     WOLFSSL_EC_KEY_LOAD_PRIVATE);
-}
+/* Start ECDH */
 
-int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
-                              int derSz, int opt)
+#ifndef WOLF_CRYPTO_CB_ONLY_ECC
+/* Compute the shared secret (key) using ECDH.
+ *
+ * KDF not supported.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [out] out      Buffer to hold key.
+ * @param [in]  outLen   Length of buffer in bytes.
+ * @param [in]  pubKey   Public key as an EC point.
+ * @param [in]  privKey  EC key holding a private key.
+ * @param [in]  kdf      Key derivation function to apply to secret.
+ * @return  Length of computed key on success
+ * @return  0 on error.
+ */
+int wolfSSL_ECDH_compute_key(void *out, size_t outLen,
+    const WOLFSSL_EC_POINT *pubKey, WOLFSSL_EC_KEY *privKey,
+    void *(*kdf) (const void *in, size_t inlen, void *out, size_t *outLen))
 {
+    int err = 0;
+    word32 len = 0;
+    ecc_key* key = NULL;
     int ret;
-    word32 idx = 0;
-    word32 algId;
+#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
+    (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
+    int setGlobalRNG = 0;
+#endif
 
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer");
+    /* TODO: support using the KDF. */
+    (void)kdf;
+
+    WOLFSSL_ENTER("wolfSSL_ECDH_compute_key");
 
-    if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) {
+    /* Validate parameters. */
+    if ((out == NULL) || (pubKey == NULL) || (pubKey->internal == NULL) ||
+        (privKey == NULL) || (privKey->internal == NULL)) {
         WOLFSSL_MSG("Bad function arguments");
-        return -1;
+        err = 1;
     }
 
-    key->pkcs8HeaderSz = 0;
+    /* Ensure internal EC key is set from external. */
+    if ((!err) && (privKey->inSet == 0)) {
+        WOLFSSL_MSG("No EC key internal set, do it");
 
-    /* Check if input buffer has PKCS8 header. In the case that it does not
-     * have a PKCS8 header then do not error out. */
-    if ((ret = ToTraditionalInline_ex((const byte*)derBuf, &idx, (word32)derSz,
-                                                                 &algId)) > 0) {
-        WOLFSSL_MSG("Found PKCS8 header");
-        key->pkcs8HeaderSz = (word16)idx;
-    }
-    else {
-        if (ret != ASN_PARSE_E) {
-            WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header");
-            return -1;
+        if (SetECKeyInternal(privKey) != 1) {
+            WOLFSSL_MSG("SetECKeyInternal failed");
+            err = 1;
         }
     }
 
-    if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
-        ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
-                                     derSz);
-    }
-    else {
-        ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
-                                    derSz);
-    }
-    if (ret < 0) {
-        if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
-            WOLFSSL_MSG("wc_EccPrivateKeyDecode failed");
+    if (!err) {
+        /* Get the internal key. */
+        key = (ecc_key*)privKey->internal;
+        /* Set length into variable of type suitable for wolfSSL API. */
+        len = (word32)outLen;
+
+    #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
+        (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
+        /* An RNG is needed. */
+        if (key->rng == NULL) {
+            key->rng = wolfssl_make_global_rng();
+            /* RNG set and needs to be unset. */
+            setGlobalRNG = 1;
         }
-        else {
-            WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
+    #endif
+
+        PRIVATE_KEY_UNLOCK();
+        /* Create secret using wolfSSL. */
+        ret = wc_ecc_shared_secret_ex(key, (ecc_point*)pubKey->internal,
+            (byte *)out, &len);
+        PRIVATE_KEY_LOCK();
+        if (ret != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_shared_secret failed");
+            err = 1;
         }
-        return -1;
     }
 
-    if (SetECKeyExternal(key) != 1) {
-        WOLFSSL_MSG("SetECKeyExternal failed");
-        return -1;
+#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
+    (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
+    /* Remove global from key. */
+    if (setGlobalRNG) {
+        key->rng = NULL;
     }
+#endif
 
-    key->inSet = 1;
-
-    return 1;
+    if (err) {
+        /* Make returned value zero. */
+        len = 0;
+    }
+    return (int)len;
 }
+#endif /* WOLF_CRYPTO_CB_ONLY_ECC */
+
+/* End ECDH */
 
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL*/
+#endif /* OPENSSL_EXTRA */
 
 #endif /* HAVE_ECC */
 

+ 141 - 42
src/ssl.c

@@ -90,9 +90,7 @@
     #include <wolfssl/openssl/dh.h>
     #include <wolfssl/openssl/rsa.h>
     #include <wolfssl/openssl/fips_rand.h>
-#ifndef WOLFCRYPT_ONLY
     #include <wolfssl/openssl/pem.h>
-#endif
     #include <wolfssl/openssl/ec.h>
     #include <wolfssl/openssl/ec25519.h>
     #include <wolfssl/openssl/ed25519.h>
@@ -204,10 +202,148 @@
 #define WOLFSSL_EVP_INCLUDED
 #include "wolfcrypt/src/evp.c"
 
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+    !defined(WOLFCRYPT_ONLY)
+/* Convert shortname to NID.
+ *
+ * For OpenSSL compatability.
+ *
+ * This function shouldn't exist!
+ * Uses defines in wolfssl/openssl/evp.h.
+ * Uses EccEnumToNID which uses defines in wolfssl/openssl/ec.h.
+ *
+ * @param [in] sn  Short name of OID.
+ * @return  NID corresponding to shortname on success.
+ * @return  NID_undef when not recognized.
+ */
+int wc_OBJ_sn2nid(const char *sn)
+{
+    const struct {
+        const char *sn;
+        int  nid;
+    } sn2nid[] = {
+#ifndef NO_CERTS
+        {WOLFSSL_COMMON_NAME, NID_commonName},
+        {WOLFSSL_COUNTRY_NAME, NID_countryName},
+        {WOLFSSL_LOCALITY_NAME, NID_localityName},
+        {WOLFSSL_STATE_NAME, NID_stateOrProvinceName},
+        {WOLFSSL_ORG_NAME, NID_organizationName},
+        {WOLFSSL_ORGUNIT_NAME, NID_organizationalUnitName},
+    #ifdef WOLFSSL_CERT_NAME_ALL
+        {WOLFSSL_NAME, NID_name},
+        {WOLFSSL_INITIALS, NID_initials},
+        {WOLFSSL_GIVEN_NAME, NID_givenName},
+        {WOLFSSL_DNQUALIFIER, NID_dnQualifier},
+    #endif
+        {WOLFSSL_EMAIL_ADDR, NID_emailAddress},
+#endif
+        {"SHA1", NID_sha1},
+        {NULL, -1}};
+    int i;
+#ifdef HAVE_ECC
+    char curveName[ECC_MAXNAME + 1];
+    int eccEnum;
+#endif
+    WOLFSSL_ENTER("OBJ_sn2nid");
+    for(i=0; sn2nid[i].sn != NULL; i++) {
+        if (XSTRCMP(sn, sn2nid[i].sn) == 0) {
+            return sn2nid[i].nid;
+        }
+    }
+#ifdef HAVE_ECC
+
+    if (XSTRLEN(sn) > ECC_MAXNAME)
+        return NID_undef;
+
+    /* Nginx uses this OpenSSL string. */
+    if (XSTRCMP(sn, "prime256v1") == 0)
+        sn = "SECP256R1";
+    /* OpenSSL allows lowercase curve names */
+    for (i = 0; i < (int)(sizeof(curveName) - 1) && *sn; i++) {
+        curveName[i] = (char)XTOUPPER((unsigned char) *sn++);
+    }
+    curveName[i] = '\0';
+    /* find based on name and return NID */
+    for (i = 0;
+#ifndef WOLFSSL_ECC_CURVE_STATIC
+         ecc_sets[i].size != 0 && ecc_sets[i].name != NULL;
+#else
+         ecc_sets[i].size != 0;
+#endif
+         i++) {
+        if (XSTRCMP(curveName, ecc_sets[i].name) == 0) {
+            eccEnum = ecc_sets[i].id;
+            /* Convert enum value in ecc_curve_id to OpenSSL NID */
+            return EccEnumToNID(eccEnum);
+        }
+    }
+#endif /* HAVE_ECC */
+
+    return NID_undef;
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
 #ifndef WOLFCRYPT_ONLY
 
+#ifndef OPENSSL_EXTRA_NO_PK
 #define WOLFSSL_PK_INCLUDED
 #include "src/pk.c"
+#endif
+
+#if !defined(NO_RSA) || !defined(NO_DH) || defined(HAVE_ECC)
+
+#define HAVE_GLOBAL_RNG /* consolidate flags for using globalRNG */
+static WC_RNG globalRNG;
+static int initGlobalRNG = 0;
+#ifndef WOLFCRYPT_ONLY
+static wolfSSL_Mutex globalRNGMutex;
+static int globalRNGMutex_valid = 0;
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG)
+static WOLFSSL_DRBG_CTX* gDrbgDefCtx = NULL;
+#endif
+#endif
+
+WC_RNG* wolfssl_get_global_rng(void)
+{
+    WC_RNG* ret = NULL;
+
+    if (initGlobalRNG == 0)
+        WOLFSSL_MSG("Global RNG no Init");
+    else
+        ret = &globalRNG;
+
+    return ret;
+}
+
+/* Make a global RNG and return.
+ *
+ * @return  Global RNG on success.
+ * @return  NULL on error.
+ */
+WC_RNG* wolfssl_make_global_rng()
+{
+    WC_RNG* ret;
+
+#ifdef HAVE_GLOBAL_RNG
+    /* Get the global random number generator instead. */
+    ret = wolfssl_get_global_rng();
+#ifdef OPENSSL_EXTRA
+    if (ret == NULL) {
+        /* Create a global random if possible. */
+        (void)wolfSSL_RAND_Init();
+        ret = wolfssl_get_global_rng();
+    }
+#endif
+#else
+    WOLFSSL_ERROR_MSG("Bad RNG Init");
+    ret = NULL;
+#endif
+
+    return ret;
+}
+
+#endif
 
 #ifdef OPENSSL_EXTRA
     /* Global pointer to constant BN on */
@@ -6119,33 +6255,6 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
 
 #endif /* !NO_SESSION_CACHE */
 
-#if !defined(WC_NO_RNG) && (defined(OPENSSL_EXTRA) || \
-    (defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA)) || \
-    (defined(OPENSSL_ALL) && !defined(NO_DH)))
-
-    #define HAVE_GLOBAL_RNG /* consolidate flags for using globalRNG */
-    static WC_RNG globalRNG;
-    static int initGlobalRNG = 0;
-    static wolfSSL_Mutex globalRNGMutex;
-    static int globalRNGMutex_valid = 0;
-
-    #if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG)
-    static WOLFSSL_DRBG_CTX* gDrbgDefCtx = NULL;
-    #endif
-
-    WC_RNG* wolfssl_get_global_rng(void)
-    {
-        WC_RNG* ret = NULL;
-
-        if (initGlobalRNG == 0)
-            WOLFSSL_MSG("Global RNG no Init");
-        else
-            ret = &globalRNG;
-
-        return ret;
-    }
-#endif
-
 #if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB)
 static int wolfSSL_RAND_InitMutex(void);
 #endif
@@ -28624,19 +28733,9 @@ static int pem_write_pubkey(WOLFSSL_EVP_PKEY* key, void* heap, byte** derBuf,
                 WOLFSSL_MSG("key->ecc is null");
                 break;
             }
-            sz = wc_EccPublicKeyDerSize((ecc_key*)key->ecc->internal, 1);
-            if (sz <= 0) {
-                WOLFSSL_MSG("wc_EccPublicKeyDerSize failed");
-                break;
-            }
-            buf = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER);
-            if (buf == NULL) {
-                WOLFSSL_MSG("malloc failed");
-                break;
-            }
-            sz = wc_EccPublicKeyToDer((ecc_key*)key->ecc->internal, buf, sz, 1);
-            if (sz < 0) {
-                WOLFSSL_MSG("wc_EccPublicKeyToDer failed");
+            if ((sz = wolfssl_ec_key_to_pubkey_der(key->ecc, &buf, heap)) <=
+                    0) {
+                WOLFSSL_MSG("wolfssl_ec_key_to_pubkey_der failed");
                 break;
             }
             break;

+ 1 - 1
src/x509.c

@@ -8909,7 +8909,7 @@ int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key)
             goto error;
 
         nid = wolfSSL_EC_GROUP_get_curve_name(group);
-        if (nid == WOLFSSL_FAILURE) {
+        if (nid <= 0) {
             /* TODO: Add support for no nid case */
             WOLFSSL_MSG("nid not found");
             goto error;

File diff suppressed because it is too large
+ 1413 - 566
tests/api.c


+ 22 - 150
wolfcrypt/src/asn.c

@@ -11753,156 +11753,6 @@ static int GetCertKey(DecodedCert* cert, const byte* source, word32* inOutIdx,
     return ret;
 }
 
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-#if defined(HAVE_ECC)
-/* Converts ECC curve enum values in ecc_curve_id to the associated OpenSSL NID
- * value.
- *
- * @param [in] n  ECC curve id.
- * @return  ECC curve NID (OpenSSL compatable value).
- */
-WOLFSSL_API int EccEnumToNID(int n)
-{
-    WOLFSSL_ENTER("EccEnumToNID()");
-
-    switch(n) {
-        case ECC_SECP192R1:
-            return NID_X9_62_prime192v1;
-        case ECC_PRIME192V2:
-            return NID_X9_62_prime192v2;
-        case ECC_PRIME192V3:
-            return NID_X9_62_prime192v3;
-        case ECC_PRIME239V1:
-            return NID_X9_62_prime239v1;
-        case ECC_PRIME239V2:
-            return NID_X9_62_prime239v2;
-        case ECC_PRIME239V3:
-            return NID_X9_62_prime239v3;
-        case ECC_SECP256R1:
-            return NID_X9_62_prime256v1;
-        case ECC_SECP112R1:
-            return NID_secp112r1;
-        case ECC_SECP112R2:
-            return NID_secp112r2;
-        case ECC_SECP128R1:
-            return NID_secp128r1;
-        case ECC_SECP128R2:
-            return NID_secp128r2;
-        case ECC_SECP160R1:
-            return NID_secp160r1;
-        case ECC_SECP160R2:
-            return NID_secp160r2;
-        case ECC_SECP224R1:
-            return NID_secp224r1;
-        case ECC_SECP384R1:
-            return NID_secp384r1;
-        case ECC_SECP521R1:
-            return NID_secp521r1;
-        case ECC_SECP160K1:
-            return NID_secp160k1;
-        case ECC_SECP192K1:
-            return NID_secp192k1;
-        case ECC_SECP224K1:
-            return NID_secp224k1;
-        case ECC_SECP256K1:
-            return NID_secp256k1;
-        case ECC_BRAINPOOLP160R1:
-            return NID_brainpoolP160r1;
-        case ECC_BRAINPOOLP192R1:
-            return NID_brainpoolP192r1;
-        case ECC_BRAINPOOLP224R1:
-            return NID_brainpoolP224r1;
-        case ECC_BRAINPOOLP256R1:
-            return NID_brainpoolP256r1;
-        case ECC_BRAINPOOLP320R1:
-            return NID_brainpoolP320r1;
-        case ECC_BRAINPOOLP384R1:
-            return NID_brainpoolP384r1;
-        case ECC_BRAINPOOLP512R1:
-            return NID_brainpoolP512r1;
-        default:
-            WOLFSSL_MSG("NID not found");
-            return -1;
-    }
-}
-#endif /* HAVE_ECC */
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
-    && !defined(WOLFCRYPT_ONLY)
-/* Convert shortname to NID.
- *
- * For OpenSSL compatability.
- *
- * @param [in] sn  Short name of OID.
- * @return  NID corresponding to shortname on success.
- * @return  NID_undef when not recognized.
- */
-int wc_OBJ_sn2nid(const char *sn)
-{
-    const struct {
-        const char *sn;
-        int  nid;
-    } sn2nid[] = {
-        {WOLFSSL_COMMON_NAME, NID_commonName},
-        {WOLFSSL_COUNTRY_NAME, NID_countryName},
-        {WOLFSSL_LOCALITY_NAME, NID_localityName},
-        {WOLFSSL_STATE_NAME, NID_stateOrProvinceName},
-        {WOLFSSL_ORG_NAME, NID_organizationName},
-        {WOLFSSL_ORGUNIT_NAME, NID_organizationalUnitName},
-    #ifdef WOLFSSL_CERT_NAME_ALL
-        {WOLFSSL_NAME, NID_name},
-        {WOLFSSL_INITIALS, NID_initials},
-        {WOLFSSL_GIVEN_NAME, NID_givenName},
-        {WOLFSSL_DNQUALIFIER, NID_dnQualifier},
-    #endif
-        {WOLFSSL_EMAIL_ADDR, NID_emailAddress},
-        {"SHA1", NID_sha1},
-        {NULL, -1}};
-    int i;
-#ifdef HAVE_ECC
-    char curveName[ECC_MAXNAME + 1];
-    int eccEnum;
-#endif
-    WOLFSSL_ENTER("OBJ_sn2nid");
-    for(i=0; sn2nid[i].sn != NULL; i++) {
-        if (XSTRCMP(sn, sn2nid[i].sn) == 0) {
-            return sn2nid[i].nid;
-        }
-    }
-#ifdef HAVE_ECC
-
-    if (XSTRLEN(sn) > ECC_MAXNAME)
-        return NID_undef;
-
-    /* Nginx uses this OpenSSL string. */
-    if (XSTRCMP(sn, "prime256v1") == 0)
-        sn = "SECP256R1";
-    /* OpenSSL allows lowercase curve names */
-    for (i = 0; i < (int)(sizeof(curveName) - 1) && *sn; i++) {
-        curveName[i] = (char)XTOUPPER((unsigned char) *sn++);
-    }
-    curveName[i] = '\0';
-    /* find based on name and return NID */
-    for (i = 0;
-#ifndef WOLFSSL_ECC_CURVE_STATIC
-         ecc_sets[i].size != 0 && ecc_sets[i].name != NULL;
-#else
-         ecc_sets[i].size != 0;
-#endif
-         i++) {
-        if (XSTRCMP(curveName, ecc_sets[i].name) == 0) {
-            eccEnum = ecc_sets[i].id;
-            /* Convert enum value in ecc_curve_id to OpenSSL NID */
-            return EccEnumToNID(eccEnum);
-        }
-    }
-#endif /* HAVE_ECC */
-
-    return NID_undef;
-}
-#endif
-
 /* Calculate hash of the id using the SHA-1 or SHA-256.
  *
  * @param [in]  data  Data to hash.
@@ -22296,6 +22146,10 @@ wcchar END_ENC_PRIV_KEY     = "-----END ENCRYPTED PRIVATE KEY-----";
 #ifdef HAVE_ECC
     wcchar BEGIN_EC_PRIV    = "-----BEGIN EC PRIVATE KEY-----";
     wcchar END_EC_PRIV      = "-----END EC PRIVATE KEY-----";
+#ifdef OPENSSL_EXTRA
+    wcchar BEGIN_EC_PARAM   = "-----BEGIN EC PARAMETERS-----";
+    wcchar END_EC_PARAM     = "-----END EC PARAMETERS-----";
+#endif
 #endif
 #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
                                                                 !defined(NO_DSA)
@@ -22420,6 +22274,13 @@ int wc_PemGetHeaderFooter(int type, const char** header, const char** footer)
             if (footer) *footer = END_EC_PRIV;
             ret = 0;
             break;
+    #ifdef OPENSSL_EXTRA
+        case ECC_PARAM_TYPE:
+            if (header) *header = BEGIN_EC_PARAM;
+            if (footer) *footer = END_EC_PARAM;
+            ret = 0;
+            break;
+    #endif
     #endif
         case RSA_TYPE:
         case PRIVATEKEY_TYPE:
@@ -22985,6 +22846,17 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
                 break;
             }
         }
+#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
+        else if (type == ECC_PARAM_TYPE) {
+            if (header == BEGIN_EC_PARAM) {
+                header = BEGIN_EC_PARAM;
+                footer = END_EC_PARAM;
+            }
+            else {
+                break;
+            }
+        }
+#endif
 #ifdef HAVE_CRL
         else if ((type == CRL_TYPE) && (header != BEGIN_X509_CRL)) {
             header =  BEGIN_X509_CRL;

+ 1 - 3
wolfssl/internal.h

@@ -6084,10 +6084,8 @@ WOLFSSL_LOCAL int GetX509Error(int e);
 WOLFSSL_LOCAL int wolfssl_get_ex_new_index(int class_index);
 #endif
 
-#if !defined(WC_NO_RNG) && (defined(OPENSSL_EXTRA) || \
-    (defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA)))
 WOLFSSL_LOCAL WC_RNG* wolfssl_get_global_rng(void);
-#endif
+WOLFSSL_LOCAL WC_RNG* wolfssl_make_global_rng(void);
 
 #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA)
 #if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_PEM_TO_DER)

+ 12 - 10
wolfssl/openssl/ec.h

@@ -121,13 +121,10 @@ struct WOLFSSL_EC_KEY {
     word16 pkcs8HeaderSz;
 
     /* option bits */
-    byte inSet:1;        /* internal set from external ? */
-    byte exSet:1;        /* external set from internal ? */
+    byte inSet:1;                /* internal set from external ? */
+    byte exSet:1;                /* external set from internal ? */
 
-#ifndef SINGLE_THREADED
-    wolfSSL_Mutex    refMutex;                       /* ref count mutex */
-#endif
-    int              refCount;                       /* reference count */
+    wolfSSL_Ref ref;             /* Reference count information. */
 };
 
 struct WOLFSSL_EC_BUILTIN_CURVE {
@@ -153,12 +150,12 @@ int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *curve,
                         const WOLFSSL_EC_POINT *p,
                         unsigned char *out, unsigned int *len);
 WOLFSSL_API
-int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len,
+int wolfSSL_ECPoint_d2i(const unsigned char *in, unsigned int len,
                         const WOLFSSL_EC_GROUP *curve, WOLFSSL_EC_POINT *p);
 WOLFSSL_API
 size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
                                   const WOLFSSL_EC_POINT *p,
-                                  char form,
+                                  int form,
                                   byte *buf, size_t len, WOLFSSL_BN_CTX *ctx);
 WOLFSSL_API
 int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group,
@@ -175,13 +172,13 @@ WOLFSSL_EC_KEY *wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY **key, const unsigned ch
 WOLFSSL_API
 int wolfSSL_i2d_ECPrivateKey(const WOLFSSL_EC_KEY *in, unsigned char **out);
 WOLFSSL_API
-void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *eckey, char form);
+void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *eckey, int form);
 WOLFSSL_API
 point_conversion_form_t wolfSSL_EC_KEY_get_conv_form(const WOLFSSL_EC_KEY* key);
 WOLFSSL_API
 WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP *group,
                                           const WOLFSSL_EC_POINT *p,
-                                          char form,
+                                          int form,
                                           WOLFSSL_BIGNUM *in, WOLFSSL_BN_CTX *ctx);
 WOLFSSL_API
 int wolfSSL_EC_POINT_is_on_curve(const WOLFSSL_EC_GROUP *group,
@@ -235,6 +232,11 @@ WOLFSSL_API int wolfSSL_ECDSA_verify(int type, const unsigned char *digest,
                                    int digestSz, const unsigned char *sig,
                                    int sigSz, WOLFSSL_EC_KEY *key);
 
+
+#if defined HAVE_ECC && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+WOLFSSL_API int EccEnumToNID(int n);
+#endif
+
 WOLFSSL_API
 void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag);
 WOLFSSL_API

+ 3 - 1
wolfssl/openssl/pem.h

@@ -157,13 +157,15 @@ int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *key,
                                    wc_pem_password_cb *cb, void *u);
 WOLFSSL_API
 int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key);
+#endif
 
+#ifndef NO_BIO
 WOLFSSL_API
 WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio,
                                                WOLFSSL_EC_KEY** ec,
                                                wc_pem_password_cb* cb,
                                                void *pass);
-#endif /* NO_FILESYSTEM */
+#endif /* !NO_BIO */
 
 /* EVP_KEY */
 WOLFSSL_API

+ 5 - 0
wolfssl/ssl.h

@@ -4144,6 +4144,11 @@ enum {
 };
 
 /* Object functions */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Do not use - use wolfSSL_OBJ_sn2nid instead. */
+WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn);
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
 WOLFSSL_API const char* wolfSSL_OBJ_nid2sn(int n);
 WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o);
 WOLFSSL_API int wolfSSL_OBJ_get_type(const WOLFSSL_ASN1_OBJECT *o);

+ 0 - 4
wolfssl/wolfcrypt/asn.h

@@ -2082,7 +2082,6 @@ WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format,
                                                  wolfssl_tm* certTime, int* idx);
 WOLFSSL_LOCAL int DateGreaterThan(const struct tm* a, const struct tm* b);
 WOLFSSL_LOCAL int wc_ValidateDate(const byte* date, byte format, int dateType);
-WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn);
 
 /* ASN.1 helper functions */
 #ifdef WOLFSSL_CERT_GEN
@@ -2193,9 +2192,6 @@ WOLFSSL_LOCAL int wc_EncodeNameCanonical(EncodedName* name, const char* nameStr,
 WOLFSSL_LOCAL int StoreDSAParams(byte*, word32*, const mp_int*, const mp_int*,
     const mp_int*);
 #endif
-#if defined HAVE_ECC && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
-WOLFSSL_API int EccEnumToNID(int n);
-#endif
 
 WOLFSSL_LOCAL void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId);
 WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx);

+ 1 - 1
wolfssl/wolfcrypt/asn_public.h

@@ -154,7 +154,7 @@ enum CertType {
     SPHINCS_SMALL_LEVEL1_TYPE,
     SPHINCS_SMALL_LEVEL3_TYPE,
     SPHINCS_SMALL_LEVEL5_TYPE,
-
+    ECC_PARAM_TYPE,
 };
 
 

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