[openssl] master update

Matt Caswell matt at openssl.org
Tue Aug 6 10:24:21 UTC 2019


The branch master has been updated
       via  f585cefc046409d04f26b73307e677625be26e5a (commit)
       via  04ca002703fec56a44fc8704336709a309189e2c (commit)
       via  a9612d6c034f47c4788c67d85651d0cd58c3faf7 (commit)
      from  c1a3f16f735057b45df1803d58f40e4e17b233e5 (commit)


- Log -----------------------------------------------------------------
commit f585cefc046409d04f26b73307e677625be26e5a
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Jul 15 15:54:08 2019 +0100

    Add documentation for new EC functions
    
    Document the new EC functions that are OPENSSL_CTX aware.
    
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/9380)

commit 04ca002703fec56a44fc8704336709a309189e2c
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Jul 4 15:01:48 2019 +0100

    Insert a dummy call to EC code in the FIPS provider
    
    Test that EC code works properly in the FIPS provider
    
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/9380)

commit a9612d6c034f47c4788c67d85651d0cd58c3faf7
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Jul 3 17:30:03 2019 +0100

    Make the EC code available from inside the FIPS provider
    
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/9380)

-----------------------------------------------------------------------

Summary of changes:
 apps/ecparam.c                    |  2 +-
 crypto/bn/bn_lcl.h                |  2 -
 crypto/buffer/build.info          |  1 +
 crypto/build.info                 |  4 +-
 crypto/ec/build.info              | 16 ++++---
 crypto/ec/curve448/curve448_lcl.h | 19 ++++----
 crypto/ec/curve448/ed448.h        | 20 ++++++---
 crypto/ec/curve448/eddsa.c        | 93 +++++++++++++++++++++++++--------------
 crypto/ec/ec2_oct.c               | 28 ++++++++++--
 crypto/ec/ec2_smpl.c              | 44 ++++++++++++++----
 crypto/ec/ec_asn1.c               |  6 +++
 crypto/ec/ec_check.c              | 25 +++++++++--
 crypto/ec/ec_curve.c              | 52 +++++++++++++++-------
 crypto/ec/ec_cvt.c                |  5 ++-
 crypto/ec/ec_key.c                | 50 +++++++++++++++------
 crypto/ec/ec_kmeth.c              | 28 ++++++++----
 crypto/ec/ec_lcl.h                |  9 +++-
 crypto/ec/ec_lib.c                | 70 ++++++++++++++++++++---------
 crypto/ec/ec_mult.c               | 15 ++++---
 crypto/ec/ecdh_ossl.c             |  2 +-
 crypto/ec/ecdsa_ossl.c            |  8 ++--
 crypto/ec/ecp_mont.c              |  5 ++-
 crypto/ec/ecp_nist.c              |  6 +--
 crypto/ec/ecp_nistp224.c          | 27 +++++++++---
 crypto/ec/ecp_nistp256.c          | 27 +++++++++---
 crypto/ec/ecp_nistp521.c          | 27 +++++++++---
 crypto/ec/ecp_nistz256.c          |  2 +-
 crypto/ec/ecp_oct.c               | 12 +++--
 crypto/ec/ecp_smpl.c              | 31 ++++++-------
 crypto/ec/ecx_meth.c              | 20 +++++++--
 crypto/err/openssl.txt            |  4 ++
 crypto/include/internal/bn_int.h  |  1 +
 crypto/ppccap.c                   |  6 +--
 doc/man3/EC_GROUP_copy.pod        |  5 ++-
 doc/man3/EC_GROUP_new.pod         | 29 +++++++++---
 doc/man3/EC_KEY_new.pod           | 43 +++++++++++++-----
 include/openssl/ec.h              | 63 +++++++++++++++++++++++---
 providers/fips/fipsprov.c         | 12 +++++
 test/curve448_internal_test.c     | 24 +++++-----
 test/ectest.c                     | 38 ++++++++--------
 util/libcrypto.num                |  4 ++
 41 files changed, 633 insertions(+), 252 deletions(-)

diff --git a/apps/ecparam.c b/apps/ecparam.c
index 0c893a3977..6796af6578 100644
--- a/apps/ecparam.c
+++ b/apps/ecparam.c
@@ -273,7 +273,7 @@ int ecparam_main(int argc, char **argv)
 
     if (check_named) {
         BIO_printf(bio_err, "validating named elliptic curve parameters: ");
-        if (EC_GROUP_check_named_curve(group, 0) <= 0) {
+        if (EC_GROUP_check_named_curve(group, 0, NULL) <= 0) {
             BIO_printf(bio_err, "failed\n");
             ERR_print_errors(bio_err);
             goto end;
diff --git a/crypto/bn/bn_lcl.h b/crypto/bn/bn_lcl.h
index 160f2f5a07..5ba96f2b19 100644
--- a/crypto/bn/bn_lcl.h
+++ b/crypto/bn/bn_lcl.h
@@ -668,6 +668,4 @@ static ossl_inline BIGNUM *bn_expand(BIGNUM *a, int bits)
     return bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2);
 }
 
-OPENSSL_CTX *bn_get_lib_ctx(BN_CTX *ctx);
-
 #endif
diff --git a/crypto/buffer/build.info b/crypto/buffer/build.info
index 54da1f92a8..63de1a570f 100644
--- a/crypto/buffer/build.info
+++ b/crypto/buffer/build.info
@@ -1,2 +1,3 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=buffer.c buf_err.c
+SOURCE[../../providers/fips]=buffer.c
diff --git a/crypto/build.info b/crypto/build.info
index fe49fa387d..0b203a7f93 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -69,14 +69,14 @@ SOURCE[../providers/fips]=$CORE_COMMON
 $UTIL_COMMON=\
         cryptlib.c params.c bsearch.c ex_data.c o_str.c \
         ctype.c threads_pthread.c threads_win.c threads_none.c initthread.c \
-        context.c sparse_array.c param_build.c $CPUIDASM
+        context.c sparse_array.c asn1_dsa.c packet.c param_build.c $CPUIDASM
 $UTIL_DEFINE=$CPUIDDEF
 
 SOURCE[../libcrypto]=$UTIL_COMMON \
         mem.c mem_sec.c mem_dbg.c \
         cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c o_dir.c \
         o_fopen.c getenv.c o_init.c o_fips.c init.c trace.c provider.c \
-        asn1_dsa.c packet.c $UPLINKSRC
+        $UPLINKSRC
 DEFINE[../libcrypto]=$UTIL_DEFINE $UPLINKDEF
 SOURCE[../providers/fips]=$UTIL_COMMON
 DEFINE[../providers/fips]=$UTIL_DEFINE
diff --git a/crypto/ec/build.info b/crypto/ec/build.info
index 5e9778d333..6bc04588e2 100644
--- a/crypto/ec/build.info
+++ b/crypto/ec/build.info
@@ -43,17 +43,21 @@ IF[{- !$disabled{asm} -}]
 ENDIF
 
 LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
-        ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
-        ec_err.c ec_curve.c ec_check.c ec_print.c ec_asn1.c ec_key.c \
-        ec2_smpl.c ec_ameth.c ec_pmeth.c eck_prn.c \
+
+$COMMON=ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
+        ec_curve.c ec_check.c ec_print.c ec_key.c ec_asn1.c \
+        ec2_smpl.c \
         ecp_nistp224.c ecp_nistp256.c ecp_nistp521.c ecp_nistputil.c \
-        ecp_oct.c ec2_oct.c ec_oct.c ec_kmeth.c ecdh_ossl.c ecdh_kdf.c \
-        ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c ecx_meth.c \
+        ecp_oct.c ec2_oct.c ec_oct.c ec_kmeth.c ecdh_ossl.c \
+        ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c \
         curve448/arch_32/f_impl.c curve448/f_generic.c curve448/scalar.c \
         curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \
         $ECASM
+SOURCE[../../libcrypto]=$COMMON ec_ameth.c ec_pmeth.c ecx_meth.c ec_err.c \
+                        ecdh_kdf.c eck_prn.c
 DEFINE[../../libcrypto]=$ECDEF
+SOURCE[../../providers/fips]=$COMMON
+DEFINE[../../providers/fips]=$ECDEF
 
 GENERATE[ecp_nistz256-x86.s]=asm/ecp_nistz256-x86.pl \
         $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
diff --git a/crypto/ec/curve448/curve448_lcl.h b/crypto/ec/curve448/curve448_lcl.h
index 3625e12a82..9459f002cb 100644
--- a/crypto/ec/curve448/curve448_lcl.h
+++ b/crypto/ec/curve448/curve448_lcl.h
@@ -16,23 +16,24 @@ int X448(uint8_t out_shared_key[56], const uint8_t private_key[56],
 void X448_public_from_private(uint8_t out_public_value[56],
                               const uint8_t private_key[56]);
 
-int ED448_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
-               const uint8_t public_key[57], const uint8_t private_key[57],
-               const uint8_t *context, size_t context_len);
+int ED448_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t *message,
+               size_t message_len, const uint8_t public_key[57],
+               const uint8_t private_key[57], const uint8_t *context,
+               size_t context_len);
 
-int ED448_verify(const uint8_t *message, size_t message_len,
+int ED448_verify(OPENSSL_CTX *ctx, const uint8_t *message, size_t message_len,
                  const uint8_t signature[114], const uint8_t public_key[57],
                  const uint8_t *context, size_t context_len);
 
-int ED448ph_sign(uint8_t *out_sig, const uint8_t hash[64],
+int ED448ph_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64],
                  const uint8_t public_key[57], const uint8_t private_key[57],
                  const uint8_t *context, size_t context_len);
 
-int ED448ph_verify(const uint8_t hash[64], const uint8_t signature[114],
-                   const uint8_t public_key[57], const uint8_t *context,
-                   size_t context_len);
+int ED448ph_verify(OPENSSL_CTX *ctx, const uint8_t hash[64],
+                   const uint8_t signature[114], const uint8_t public_key[57],
+                   const uint8_t *context, size_t context_len);
 
-int ED448_public_from_private(uint8_t out_public_key[57],
+int ED448_public_from_private(OPENSSL_CTX *ctx, uint8_t out_public_key[57],
                               const uint8_t private_key[57]);
 
 #endif              /* HEADER_CURVE448_LCL_H */
diff --git a/crypto/ec/curve448/ed448.h b/crypto/ec/curve448/ed448.h
index e66d3e38bb..b198f36e3a 100644
--- a/crypto/ec/curve448/ed448.h
+++ b/crypto/ec/curve448/ed448.h
@@ -38,6 +38,7 @@
  * privkey (in): The private key.
  */
 c448_error_t c448_ed448_derive_public_key(
+                        OPENSSL_CTX *ctx,
                         uint8_t pubkey [EDDSA_448_PUBLIC_BYTES],
                         const uint8_t privkey [EDDSA_448_PRIVATE_BYTES]);
 
@@ -59,6 +60,7 @@ c448_error_t c448_ed448_derive_public_key(
  * disambiguation.  For Ed448 it is safe.
  */
 c448_error_t c448_ed448_sign(
+                        OPENSSL_CTX *ctx,
                         uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
                         const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
                         const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
@@ -83,6 +85,7 @@ c448_error_t c448_ed448_sign(
  * disambiguation.  For Ed448 it is safe.
  */
 c448_error_t c448_ed448_sign_prehash(
+                        OPENSSL_CTX *ctx,
                         uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
                         const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
                         const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
@@ -108,13 +111,14 @@ c448_error_t c448_ed448_sign_prehash(
  * non-prehashed messages, at least without some very careful protocol-level
  * disambiguation.  For Ed448 it is safe.
  */
-c448_error_t c448_ed448_verify(const uint8_t
-                                 signature[EDDSA_448_SIGNATURE_BYTES],
-                                 const uint8_t
-                                 pubkey[EDDSA_448_PUBLIC_BYTES],
-                                 const uint8_t *message, size_t message_len,
-                                 uint8_t prehashed, const uint8_t *context,
-                                 uint8_t context_len);
+c448_error_t c448_ed448_verify(OPENSSL_CTX *ctx,
+                               const uint8_t
+                               signature[EDDSA_448_SIGNATURE_BYTES],
+                               const uint8_t
+                               pubkey[EDDSA_448_PUBLIC_BYTES],
+                               const uint8_t *message, size_t message_len,
+                               uint8_t prehashed, const uint8_t *context,
+                               uint8_t context_len);
 
 /*
  * EdDSA signature verification.
@@ -134,6 +138,7 @@ c448_error_t c448_ed448_verify(const uint8_t
  * disambiguation.  For Ed448 it is safe.
  */
 c448_error_t c448_ed448_verify_prehash(
+                    OPENSSL_CTX *ctx,
                     const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
                     const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
                     const uint8_t hash[64],
@@ -189,6 +194,7 @@ c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio(
  * ed (in): The EdDSA private key
  */
 c448_error_t c448_ed448_convert_private_key_to_x448(
+                            OPENSSL_CTX *ctx,
                             uint8_t x[X448_PRIVATE_BYTES],
                             const uint8_t ed[EDDSA_448_PRIVATE_BYTES]);
 
diff --git a/crypto/ec/curve448/eddsa.c b/crypto/ec/curve448/eddsa.c
index ba3623928c..58e9e92d4c 100644
--- a/crypto/ec/curve448/eddsa.c
+++ b/crypto/ec/curve448/eddsa.c
@@ -19,23 +19,30 @@
 
 #define COFACTOR 4
 
-static c448_error_t oneshot_hash(uint8_t *out, size_t outlen,
+static c448_error_t oneshot_hash(OPENSSL_CTX *ctx, uint8_t *out, size_t outlen,
                                  const uint8_t *in, size_t inlen)
 {
     EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
+    EVP_MD *shake256 = NULL;
+    c448_error_t ret = C448_FAILURE;
 
     if (hashctx == NULL)
         return C448_FAILURE;
 
-    if (!EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL)
+    shake256 = EVP_MD_fetch(ctx, "SHAKE256", NULL);
+    if (shake256 == NULL)
+        goto err;
+
+    if (!EVP_DigestInit_ex(hashctx, shake256, NULL)
             || !EVP_DigestUpdate(hashctx, in, inlen)
-            || !EVP_DigestFinalXOF(hashctx, out, outlen)) {
-        EVP_MD_CTX_free(hashctx);
-        return C448_FAILURE;
-    }
+            || !EVP_DigestFinalXOF(hashctx, out, outlen))
+        goto err;
 
+    ret = C448_SUCCESS;
+ err:
     EVP_MD_CTX_free(hashctx);
-    return C448_SUCCESS;
+    EVP_MD_meth_free(shake256);
+    return ret;
 }
 
 static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES])
@@ -45,13 +52,15 @@ static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES])
     secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 2] |= 0x80;
 }
 
-static c448_error_t hash_init_with_dom(EVP_MD_CTX *hashctx, uint8_t prehashed,
+static c448_error_t hash_init_with_dom(OPENSSL_CTX *ctx, EVP_MD_CTX *hashctx,
+                                       uint8_t prehashed,
                                        uint8_t for_prehash,
                                        const uint8_t *context,
                                        size_t context_len)
 {
     const char *dom_s = "SigEd448";
     uint8_t dom[2];
+    EVP_MD *shake256 = NULL;
 
     if (context_len > UINT8_MAX)
         return C448_FAILURE;
@@ -60,27 +69,36 @@ static c448_error_t hash_init_with_dom(EVP_MD_CTX *hashctx, uint8_t prehashed,
                        - (for_prehash == 0 ? 1 : 0));
     dom[1] = (uint8_t)context_len;
 
-    if (!EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL)
+    shake256 = EVP_MD_fetch(ctx, "SHAKE256", NULL);
+    if (shake256 == NULL)
+        return C448_FAILURE;
+
+    if (!EVP_DigestInit_ex(hashctx, shake256, NULL)
             || !EVP_DigestUpdate(hashctx, dom_s, strlen(dom_s))
             || !EVP_DigestUpdate(hashctx, dom, sizeof(dom))
-            || !EVP_DigestUpdate(hashctx, context, context_len))
+            || !EVP_DigestUpdate(hashctx, context, context_len)) {
+        EVP_MD_meth_free(shake256);
         return C448_FAILURE;
+    }
 
+    EVP_MD_meth_free(shake256);
     return C448_SUCCESS;
 }
 
 /* In this file because it uses the hash */
 c448_error_t c448_ed448_convert_private_key_to_x448(
+                            OPENSSL_CTX *ctx,
                             uint8_t x[X448_PRIVATE_BYTES],
                             const uint8_t ed [EDDSA_448_PRIVATE_BYTES])
 {
     /* pass the private key through oneshot_hash function */
     /* and keep the first X448_PRIVATE_BYTES bytes */
-    return oneshot_hash(x, X448_PRIVATE_BYTES, ed,
+    return oneshot_hash(ctx, x, X448_PRIVATE_BYTES, ed,
                         EDDSA_448_PRIVATE_BYTES);
 }
 
 c448_error_t c448_ed448_derive_public_key(
+                        OPENSSL_CTX *ctx,
                         uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
                         const uint8_t privkey[EDDSA_448_PRIVATE_BYTES])
 {
@@ -90,7 +108,8 @@ c448_error_t c448_ed448_derive_public_key(
     unsigned int c;
     curve448_point_t p;
 
-    if (!oneshot_hash(secret_scalar_ser, sizeof(secret_scalar_ser), privkey,
+    if (!oneshot_hash(ctx, secret_scalar_ser, sizeof(secret_scalar_ser),
+                      privkey,
                       EDDSA_448_PRIVATE_BYTES))
         return C448_FAILURE;
 
@@ -123,6 +142,7 @@ c448_error_t c448_ed448_derive_public_key(
 }
 
 c448_error_t c448_ed448_sign(
+                        OPENSSL_CTX *ctx,
                         uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
                         const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
                         const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
@@ -148,7 +168,7 @@ c448_error_t c448_ed448_sign(
          */
         uint8_t expanded[EDDSA_448_PRIVATE_BYTES * 2];
 
-        if (!oneshot_hash(expanded, sizeof(expanded), privkey,
+        if (!oneshot_hash(ctx, expanded, sizeof(expanded), privkey,
                           EDDSA_448_PRIVATE_BYTES))
             goto err;
         clamp(expanded);
@@ -156,7 +176,8 @@ c448_error_t c448_ed448_sign(
                                     EDDSA_448_PRIVATE_BYTES);
 
         /* Hash to create the nonce */
-        if (!hash_init_with_dom(hashctx, prehashed, 0, context, context_len)
+        if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
+                                context_len)
                 || !EVP_DigestUpdate(hashctx,
                                      expanded + EDDSA_448_PRIVATE_BYTES,
                                      EDDSA_448_PRIVATE_BYTES)
@@ -197,7 +218,7 @@ c448_error_t c448_ed448_sign(
         uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
 
         /* Compute the challenge */
-        if (!hash_init_with_dom(hashctx, prehashed, 0, context, context_len)
+        if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, context_len)
                 || !EVP_DigestUpdate(hashctx, nonce_point, sizeof(nonce_point))
                 || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
                 || !EVP_DigestUpdate(hashctx, message, message_len)
@@ -228,17 +249,19 @@ c448_error_t c448_ed448_sign(
 }
 
 c448_error_t c448_ed448_sign_prehash(
+                        OPENSSL_CTX *ctx,
                         uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
                         const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
                         const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
                         const uint8_t hash[64], const uint8_t *context,
                         size_t context_len)
 {
-    return c448_ed448_sign(signature, privkey, pubkey, hash, 64, 1, context,
-                           context_len);
+    return c448_ed448_sign(ctx, signature, privkey, pubkey, hash, 64, 1,
+                           context, context_len);
 }
 
 c448_error_t c448_ed448_verify(
+                    OPENSSL_CTX *ctx,
                     const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
                     const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
                     const uint8_t *message, size_t message_len,
@@ -291,7 +314,7 @@ c448_error_t c448_ed448_verify(
         uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
 
         if (hashctx == NULL
-                || !hash_init_with_dom(hashctx, prehashed, 0, context,
+                || !hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
                                        context_len)
                 || !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES)
                 || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
@@ -321,52 +344,54 @@ c448_error_t c448_ed448_verify(
 }
 
 c448_error_t c448_ed448_verify_prehash(
+                    OPENSSL_CTX *ctx,
                     const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
                     const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
                     const uint8_t hash[64], const uint8_t *context,
                     uint8_t context_len)
 {
-    return c448_ed448_verify(signature, pubkey, hash, 64, 1, context,
+    return c448_ed448_verify(ctx, signature, pubkey, hash, 64, 1, context,
                              context_len);
 }
 
-int ED448_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
-               const uint8_t public_key[57], const uint8_t private_key[57],
-               const uint8_t *context, size_t context_len)
+int ED448_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t *message,
+               size_t message_len, const uint8_t public_key[57],
+               const uint8_t private_key[57], const uint8_t *context,
+               size_t context_len)
 {
-    return c448_ed448_sign(out_sig, private_key, public_key, message,
+    return c448_ed448_sign(ctx, out_sig, private_key, public_key, message,
                            message_len, 0, context, context_len)
         == C448_SUCCESS;
 }
 
-int ED448_verify(const uint8_t *message, size_t message_len,
+int ED448_verify(OPENSSL_CTX *ctx, const uint8_t *message, size_t message_len,
                  const uint8_t signature[114], const uint8_t public_key[57],
                  const uint8_t *context, size_t context_len)
 {
-    return c448_ed448_verify(signature, public_key, message, message_len, 0,
-                             context, (uint8_t)context_len) == C448_SUCCESS;
+    return c448_ed448_verify(ctx, signature, public_key, message, message_len,
+                             0, context, (uint8_t)context_len) == C448_SUCCESS;
 }
 
-int ED448ph_sign(uint8_t *out_sig, const uint8_t hash[64],
+int ED448ph_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64],
                  const uint8_t public_key[57], const uint8_t private_key[57],
                  const uint8_t *context, size_t context_len)
 {
-    return c448_ed448_sign_prehash(out_sig, private_key, public_key, hash,
+    return c448_ed448_sign_prehash(ctx, out_sig, private_key, public_key, hash,
                                    context, context_len) == C448_SUCCESS;
 
 }
 
-int ED448ph_verify(const uint8_t hash[64], const uint8_t signature[114],
-                   const uint8_t public_key[57], const uint8_t *context,
-                   size_t context_len)
+int ED448ph_verify(OPENSSL_CTX *ctx, const uint8_t hash[64],
+                   const uint8_t signature[114], const uint8_t public_key[57],
+                   const uint8_t *context, size_t context_len)
 {
-    return c448_ed448_verify_prehash(signature, public_key, hash, context,
+    return c448_ed448_verify_prehash(ctx, signature, public_key, hash, context,
                                      (uint8_t)context_len) == C448_SUCCESS;
 }
 
-int ED448_public_from_private(uint8_t out_public_key[57],
+int ED448_public_from_private(OPENSSL_CTX *ctx, uint8_t out_public_key[57],
                               const uint8_t private_key[57])
 {
-    return c448_ed448_derive_public_key(out_public_key, private_key)
+    return c448_ed448_derive_public_key(ctx, out_public_key, private_key)
         == C448_SUCCESS;
 }
diff --git a/crypto/ec/ec2_oct.c b/crypto/ec/ec2_oct.c
index ca36bb1673..f9ee3be931 100644
--- a/crypto/ec/ec2_oct.c
+++ b/crypto/ec/ec2_oct.c
@@ -35,9 +35,10 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
                                               const BIGNUM *x_, int y_bit,
                                               BN_CTX *ctx)
 {
-    BN_CTX *new_ctx = NULL;
     BIGNUM *tmp, *x, *y, *z;
     int ret = 0, z0;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
 
     /* clear error queue */
     ERR_clear_error();
@@ -47,6 +48,7 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
         if (ctx == NULL)
             return 0;
     }
+#endif
 
     y_bit = (y_bit != 0) ? 1 : 0;
 
@@ -73,6 +75,7 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
         if (!BN_GF2m_add(tmp, x, tmp))
             goto err;
         if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) {
+#ifndef FIPS_MODE
             unsigned long err = ERR_peek_last_error();
 
             if (ERR_GET_LIB(err) == ERR_LIB_BN
@@ -81,8 +84,11 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
                 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
                       EC_R_INVALID_COMPRESSED_POINT);
             } else
+#endif
+            {
                 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
                       ERR_R_BN_LIB);
+            }
             goto err;
         }
         z0 = (BN_is_odd(z)) ? 1 : 0;
@@ -101,7 +107,9 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
 
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 
@@ -115,10 +123,12 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
                                 unsigned char *buf, size_t len, BN_CTX *ctx)
 {
     size_t ret;
-    BN_CTX *new_ctx = NULL;
     int used_ctx = 0;
     BIGNUM *x, *y, *yxi;
     size_t field_len, i, skip;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
+#endif
 
     if ((form != POINT_CONVERSION_COMPRESSED)
         && (form != POINT_CONVERSION_UNCOMPRESSED)
@@ -152,11 +162,13 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
             goto err;
         }
 
+#ifndef FIPS_MODE
         if (ctx == NULL) {
             ctx = new_ctx = BN_CTX_new();
             if (ctx == NULL)
                 return 0;
         }
+#endif
 
         BN_CTX_start(ctx);
         used_ctx = 1;
@@ -218,13 +230,17 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
 
     if (used_ctx)
         BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 
  err:
     if (used_ctx)
         BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return 0;
 }
 
@@ -238,10 +254,12 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
 {
     point_conversion_form_t form;
     int y_bit, m;
-    BN_CTX *new_ctx = NULL;
     BIGNUM *x, *y, *yxi;
     size_t field_len, enc_len;
     int ret = 0;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
+#endif
 
     if (len == 0) {
         ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
@@ -281,11 +299,13 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
         return 0;
     }
 
+#ifndef FIPS_MODE
     if (ctx == NULL) {
         ctx = new_ctx = BN_CTX_new();
         if (ctx == NULL)
             return 0;
     }
+#endif
 
     BN_CTX_start(ctx);
     x = BN_CTX_get(ctx);
@@ -332,7 +352,9 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
 
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 #endif
diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c
index ebd6f21eec..0cc9c893f8 100644
--- a/crypto/ec/ec2_smpl.c
+++ b/crypto/ec/ec2_smpl.c
@@ -176,6 +176,7 @@ int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
 {
     int ret = 0;
     BIGNUM *b;
+#ifndef FIPS_MODE
     BN_CTX *new_ctx = NULL;
 
     if (ctx == NULL) {
@@ -186,6 +187,7 @@ int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
             goto err;
         }
     }
+#endif
     BN_CTX_start(ctx);
     b = BN_CTX_get(ctx);
     if (b == NULL)
@@ -205,7 +207,9 @@ int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
 
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 
@@ -349,9 +353,11 @@ int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
 int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
                        const EC_POINT *b, BN_CTX *ctx)
 {
-    BN_CTX *new_ctx = NULL;
     BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
     int ret = 0;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
+#endif
 
     if (EC_POINT_is_at_infinity(group, a)) {
         if (!EC_POINT_copy(r, b))
@@ -365,11 +371,13 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
         return 1;
     }
 
+#ifndef FIPS_MODE
     if (ctx == NULL) {
         ctx = new_ctx = BN_CTX_new();
         if (ctx == NULL)
             return 0;
     }
+#endif
 
     BN_CTX_start(ctx);
     x0 = BN_CTX_get(ctx);
@@ -453,7 +461,9 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
 
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 
@@ -494,11 +504,13 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
                                BN_CTX *ctx)
 {
     int ret = -1;
-    BN_CTX *new_ctx = NULL;
     BIGNUM *lh, *y2;
     int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
                       const BIGNUM *, BN_CTX *);
     int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
+#endif
 
     if (EC_POINT_is_at_infinity(group, point))
         return 1;
@@ -510,11 +522,13 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
     if (!point->Z_is_one)
         return -1;
 
+#ifndef FIPS_MODE
     if (ctx == NULL) {
         ctx = new_ctx = BN_CTX_new();
         if (ctx == NULL)
             return -1;
     }
+#endif
 
     BN_CTX_start(ctx);
     y2 = BN_CTX_get(ctx);
@@ -546,7 +560,9 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
 
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 
@@ -561,8 +577,10 @@ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
                        const EC_POINT *b, BN_CTX *ctx)
 {
     BIGNUM *aX, *aY, *bX, *bY;
-    BN_CTX *new_ctx = NULL;
     int ret = -1;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
+#endif
 
     if (EC_POINT_is_at_infinity(group, a)) {
         return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
@@ -575,11 +593,13 @@ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
         return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1;
     }
 
+#ifndef FIPS_MODE
     if (ctx == NULL) {
         ctx = new_ctx = BN_CTX_new();
         if (ctx == NULL)
             return -1;
     }
+#endif
 
     BN_CTX_start(ctx);
     aX = BN_CTX_get(ctx);
@@ -597,7 +617,9 @@ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
 
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 
@@ -605,18 +627,22 @@ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
 int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
                                BN_CTX *ctx)
 {
-    BN_CTX *new_ctx = NULL;
     BIGNUM *x, *y;
     int ret = 0;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
+#endif
 
     if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
         return 1;
 
+#ifndef FIPS_MODE
     if (ctx == NULL) {
         ctx = new_ctx = BN_CTX_new();
         if (ctx == NULL)
             return 0;
     }
+#endif
 
     BN_CTX_start(ctx);
     x = BN_CTX_get(ctx);
@@ -638,7 +664,9 @@ int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
 
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 
@@ -696,8 +724,8 @@ int ec_GF2m_simple_ladder_pre(const EC_GROUP *group,
 
     /* s blinding: make sure lambda (s->Z here) is not zero */
     do {
-        if (!BN_priv_rand(s->Z, BN_num_bits(group->field) - 1,
-                          BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
+        if (!BN_priv_rand_ex(s->Z, BN_num_bits(group->field) - 1,
+                             BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, ctx)) {
             ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
             return 0;
         }
@@ -711,8 +739,8 @@ int ec_GF2m_simple_ladder_pre(const EC_GROUP *group,
 
     /* r blinding: make sure lambda (r->Y here for storage) is not zero */
     do {
-        if (!BN_priv_rand(r->Y, BN_num_bits(group->field) - 1,
-                          BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
+        if (!BN_priv_rand_ex(r->Y, BN_num_bits(group->field) - 1,
+                             BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, ctx)) {
             ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
             return 0;
         }
diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c
index c2f9679c0c..3a8128b755 100644
--- a/crypto/ec/ec_asn1.c
+++ b/crypto/ec/ec_asn1.c
@@ -15,6 +15,8 @@
 #include "internal/nelem.h"
 #include "internal/asn1_dsa.h"
 
+#ifndef FIPS_MODE
+
 int EC_GROUP_get_basis_type(const EC_GROUP *group)
 {
     int i;
@@ -1141,6 +1143,8 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out)
 DECLARE_ASN1_FUNCTIONS(ECDSA_SIG)
 DECLARE_ASN1_ENCODE_FUNCTIONS_name(ECDSA_SIG, ECDSA_SIG)
 
+#endif /* FIPS_MODE */
+
 ECDSA_SIG *ECDSA_SIG_new(void)
 {
     ECDSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig));
@@ -1255,6 +1259,7 @@ int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
     return 1;
 }
 
+#ifndef FIPS_MODE
 int ECDSA_size(const EC_KEY *r)
 {
     int ret, i;
@@ -1282,3 +1287,4 @@ int ECDSA_size(const EC_KEY *r)
     ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
     return ret;
 }
+#endif
diff --git a/crypto/ec/ec_check.c b/crypto/ec/ec_check.c
index 315b9fd4df..974fcb2446 100644
--- a/crypto/ec/ec_check.c
+++ b/crypto/ec/ec_check.c
@@ -10,13 +10,30 @@
 #include "ec_lcl.h"
 #include <openssl/err.h>
 
-int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only)
+int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only,
+                               BN_CTX *ctx)
 {
-    int nid;
+    int nid = NID_undef;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
+
+    if (ctx == NULL) {
+        ctx = new_ctx = BN_CTX_new();
+        if (ctx == NULL) {
+            ECerr(EC_F_EC_GROUP_CHECK_NAMED_CURVE, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+    }
+#endif
 
-    nid = ec_curve_nid_from_params(group);
+    nid = ec_curve_nid_from_params(group, ctx);
     if (nid > 0 && nist_only && EC_curve_nid2nist(nid) == NULL)
         nid = NID_undef;
+
+#ifndef FIPS_MODE
+ err:
+    BN_CTX_free(ctx);
+#endif
     return nid;
 }
 
@@ -27,7 +44,7 @@ int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
     * ECC domain parameter validation.
     * See SP800-56A R3 5.5.2 "Assurances of Domain-Parameter Validity" Part 1b.
     */
-    return EC_GROUP_check_named_curve(group, 1) >= 0 ? 1 : 0;
+    return EC_GROUP_check_named_curve(group, 1, ctx) >= 0 ? 1 : 0;
 #else
     int ret = 0;
     const BIGNUM *order;
diff --git a/crypto/ec/ec_curve.c b/crypto/ec/ec_curve.c
index 8b44c251ba..e9dac78224 100644
--- a/crypto/ec/ec_curve.c
+++ b/crypto/ec/ec_curve.c
@@ -193,6 +193,7 @@ static const struct {
     }
 };
 
+# ifndef FIPS_MODE
 /* the x9.62 prime curves (minus the nist prime curves) */
 static const struct {
     EC_CURVE_DATA h;
@@ -371,6 +372,7 @@ static const struct {
         0x43, 0x21, 0x46, 0x52, 0x65, 0x51
     }
 };
+#endif /* FIPS_MODE */
 
 static const struct {
     EC_CURVE_DATA h;
@@ -410,6 +412,7 @@ static const struct {
     }
 };
 
+#ifndef FIPS_MODE
 /* the secg prime curves (minus the nist and x9.62 prime curves) */
 static const struct {
     EC_CURVE_DATA h;
@@ -831,10 +834,13 @@ static const struct {
         0x5C, 0x5C, 0x2A, 0x3D
     }
 };
+#endif /* FIPS_MODE */
 
 #ifndef OPENSSL_NO_EC2M
 
 /* characteristic two curves */
+
+# ifndef FIPS_MODE
 static const struct {
     EC_CURVE_DATA h;
     unsigned char data[20 + 15 * 6];
@@ -962,6 +968,7 @@ static const struct {
         0x33, 0x04, 0x9B, 0xA9, 0x8F
     }
 };
+# endif /* FIPS_MODE */
 
 static const struct {
     EC_CURVE_DATA h;
@@ -993,6 +1000,7 @@ static const struct {
     }
 };
 
+# ifndef FIPS_MODE
 static const struct {
     EC_CURVE_DATA h;
     unsigned char data[0 + 21 * 6];
@@ -1021,6 +1029,7 @@ static const struct {
         0xAA, 0xB6, 0x89, 0xC2, 0x9C, 0xA7, 0x10, 0x27, 0x9B
     }
 };
+# endif /* FIPS_MODE */
 
 static const struct {
     EC_CURVE_DATA h;
@@ -1051,6 +1060,7 @@ static const struct {
     }
 };
 
+# ifndef FIPS_MODE
 static const struct {
     EC_CURVE_DATA h;
     unsigned char data[20 + 25 * 6];
@@ -1126,6 +1136,7 @@ static const struct {
         0xD5
     }
 };
+# endif /* FIPS_MODE */
 
 static const struct {
     EC_CURVE_DATA h;
@@ -1201,6 +1212,7 @@ static const struct {
     }
 };
 
+#ifndef FIPS_MODE
 static const struct {
     EC_CURVE_DATA h;
     unsigned char data[0 + 30 * 6];
@@ -1236,6 +1248,7 @@ static const struct {
         0x1D, 0xA8, 0x00, 0xE4, 0x78, 0xA5
     }
 };
+# endif /* FIPS_MODE */
 
 static const struct {
     EC_CURVE_DATA h;
@@ -1519,6 +1532,7 @@ static const struct {
     }
 };
 
+# ifndef FIPS_MODE
 static const struct {
     EC_CURVE_DATA h;
     unsigned char data[20 + 21 * 6];
@@ -2203,8 +2217,8 @@ static const struct {
         0xED, 0xF9, 0x7C, 0x44, 0xDB, 0x9F, 0x24, 0x20, 0xBA, 0xFC, 0xA7, 0x5E
     }
 };
-
-#endif
+# endif /* FIPS_MODE */
+#endif /* OPENSSL_NO_EC2M */
 
 /*
  * These curves were added by Annie Yousar.
@@ -2214,6 +2228,7 @@ static const struct {
  * generation mechanism is different from those defined in ANSI X9.62.
  */
 
+#ifndef FIPS_MODE
 static const struct {
     EC_CURVE_DATA h;
     unsigned char data[0 + 20 * 6];
@@ -2753,8 +2768,9 @@ static const struct {
         0x9C, 0xA9, 0x00, 0x69
     }
 };
+#endif /* FIPS_MODE */
 
-#ifndef OPENSSL_NO_SM2
+#if !defined(OPENSSL_NO_SM2) && !defined(FIPS_MODE)
 static const struct {
     EC_CURVE_DATA h;
     unsigned char data[0 + 32 * 6];
@@ -3075,7 +3091,8 @@ static const ec_list_element curve_list[] = {
 
 #define curve_list_length OSSL_NELEM(curve_list)
 
-static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
+static EC_GROUP *ec_group_new_from_data(OPENSSL_CTX *libctx,
+                                        const ec_list_element curve)
 {
     EC_GROUP *group = NULL;
     EC_POINT *P = NULL;
@@ -3090,9 +3107,10 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
 
     /* If no curve data curve method must handle everything */
     if (curve.data == NULL)
-        return EC_GROUP_new(curve.meth != NULL ? curve.meth() : NULL);
+        return EC_GROUP_new_ex(libctx,
+                               curve.meth != NULL ? curve.meth() : NULL);
 
-    if ((ctx = BN_CTX_new()) == NULL) {
+    if ((ctx = BN_CTX_new_ex(libctx)) == NULL) {
         ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE);
         goto err;
     }
@@ -3112,7 +3130,7 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
 
     if (curve.meth != 0) {
         meth = curve.meth();
-        if (((group = EC_GROUP_new(meth)) == NULL) ||
+        if (((group = EC_GROUP_new_ex(libctx, meth)) == NULL) ||
             (!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
             ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
             goto err;
@@ -3182,7 +3200,7 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
     return group;
 }
 
-EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
+EC_GROUP *EC_GROUP_new_by_curve_name_ex(OPENSSL_CTX *libctx, int nid)
 {
     size_t i;
     EC_GROUP *ret = NULL;
@@ -3201,18 +3219,25 @@ EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
 #endif /* FIPS_MODE */
     for (i = 0; i < curve_list_length; i++)
         if (curve_list[i].nid == nid) {
-            ret = ec_group_new_from_data(curve_list[i]);
+            ret = ec_group_new_from_data(libctx, curve_list[i]);
             break;
         }
 
     if (ret == NULL) {
-        ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP);
+        ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME_EX, EC_R_UNKNOWN_GROUP);
         return NULL;
     }
 
     return ret;
 }
 
+#ifndef FIPS_MODE
+EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
+{
+    return EC_GROUP_new_by_curve_name_ex(NULL, nid);
+}
+#endif
+
 size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems)
 {
     size_t i, min;
@@ -3284,7 +3309,7 @@ int EC_curve_nist2nid(const char *name)
  * Returns: The nid associated with the found named curve, or NID_undef
  *          if not found. If there was an error it returns -1.
  */
-int ec_curve_nid_from_params(const EC_GROUP *group)
+int ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx)
 {
     int ret = -1, nid, len, field_type, param_len;
     size_t i, seed_len;
@@ -3296,7 +3321,6 @@ int ec_curve_nid_from_params(const EC_GROUP *group)
     const BIGNUM *cofactor = NULL;
     /* An array of BIGNUMs for (p, a, b, x, y, order) */
     BIGNUM *bn[NUM_BN_FIELDS] = {NULL, NULL, NULL, NULL, NULL, NULL};
-    BN_CTX *ctx = NULL;
 
     meth = EC_GROUP_method_of(group);
     if (meth == NULL)
@@ -3308,9 +3332,6 @@ int ec_curve_nid_from_params(const EC_GROUP *group)
     seed = EC_GROUP_get0_seed(group);
     cofactor = EC_GROUP_get0_cofactor(group);
 
-    ctx = BN_CTX_new();
-    if (ctx == NULL)
-        return -1;
     BN_CTX_start(ctx);
 
     /*
@@ -3388,6 +3409,5 @@ int ec_curve_nid_from_params(const EC_GROUP *group)
 end:
     OPENSSL_free(param_bytes);
     BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
     return ret;
 }
diff --git a/crypto/ec/ec_cvt.c b/crypto/ec/ec_cvt.c
index 05d4d882ba..9b3087ed09 100644
--- a/crypto/ec/ec_cvt.c
+++ b/crypto/ec/ec_cvt.c
@@ -9,6 +9,7 @@
  */
 
 #include <openssl/err.h>
+#include "internal/bn_int.h"
 #include "ec_lcl.h"
 
 EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
@@ -47,7 +48,7 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
         meth = EC_GFp_mont_method();
 #endif
 
-    ret = EC_GROUP_new(meth);
+    ret = EC_GROUP_new_ex(bn_get_lib_ctx(ctx), meth);
     if (ret == NULL)
         return NULL;
 
@@ -68,7 +69,7 @@ EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a,
 
     meth = EC_GF2m_simple_method();
 
-    ret = EC_GROUP_new(meth);
+    ret = EC_GROUP_new_ex(bn_get_lib_ctx(ctx), meth);
     if (ret == NULL)
         return NULL;
 
diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c
index 47ccfd0aea..6a02a3bc86 100644
--- a/crypto/ec/ec_key.c
+++ b/crypto/ec/ec_key.c
@@ -15,17 +15,24 @@
 #include <openssl/err.h>
 #include <openssl/engine.h>
 
+#ifndef FIPS_MODE
 EC_KEY *EC_KEY_new(void)
 {
-    return EC_KEY_new_method(NULL);
+    return ec_key_new_method_int(NULL, NULL);
 }
+#endif
 
-EC_KEY *EC_KEY_new_by_curve_name(int nid)
+EC_KEY *EC_KEY_new_ex(OPENSSL_CTX *ctx)
+{
+    return ec_key_new_method_int(ctx, NULL);
+}
+
+EC_KEY *EC_KEY_new_by_curve_name_ex(OPENSSL_CTX *ctx, int nid)
 {
-    EC_KEY *ret = EC_KEY_new();
+    EC_KEY *ret = EC_KEY_new_ex(ctx);
     if (ret == NULL)
         return NULL;
-    ret->group = EC_GROUP_new_by_curve_name(nid);
+    ret->group = EC_GROUP_new_by_curve_name_ex(ctx, nid);
     if (ret->group == NULL) {
         EC_KEY_free(ret);
         return NULL;
@@ -38,6 +45,13 @@ EC_KEY *EC_KEY_new_by_curve_name(int nid)
     return ret;
 }
 
+#ifndef FIPS_MODE
+EC_KEY *EC_KEY_new_by_curve_name(int nid)
+{
+    return EC_KEY_new_by_curve_name_ex(NULL, nid);
+}
+#endif
+
 void EC_KEY_free(EC_KEY *r)
 {
     int i;
@@ -54,14 +68,16 @@ void EC_KEY_free(EC_KEY *r)
     if (r->meth != NULL && r->meth->finish != NULL)
         r->meth->finish(r);
 
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     ENGINE_finish(r->engine);
 #endif
 
     if (r->group && r->group->meth->keyfinish)
         r->group->meth->keyfinish(r);
 
+#ifndef FIPS_MODE
     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data);
+#endif
     CRYPTO_THREAD_lock_free(r->lock);
     EC_GROUP_free(r->group);
     EC_POINT_free(r->pub_key);
@@ -81,18 +97,19 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
             dest->meth->finish(dest);
         if (dest->group && dest->group->meth->keyfinish)
             dest->group->meth->keyfinish(dest);
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
         if (ENGINE_finish(dest->engine) == 0)
             return 0;
         dest->engine = NULL;
 #endif
     }
+    dest->libctx = src->libctx;
     /* copy the parameters */
     if (src->group != NULL) {
         const EC_METHOD *meth = EC_GROUP_method_of(src->group);
         /* clear the old group */
         EC_GROUP_free(dest->group);
-        dest->group = EC_GROUP_new(meth);
+        dest->group = EC_GROUP_new_ex(src->libctx, meth);
         if (dest->group == NULL)
             return NULL;
         if (!EC_GROUP_copy(dest->group, src->group))
@@ -128,12 +145,14 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
     dest->conv_form = src->conv_form;
     dest->version = src->version;
     dest->flags = src->flags;
+#ifndef FIPS_MODE
     if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY,
                             &dest->ex_data, &src->ex_data))
         return NULL;
+#endif
 
     if (src->meth != dest->meth) {
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
         if (src->engine != NULL && ENGINE_init(src->engine) == 0)
             return NULL;
         dest->engine = src->engine;
@@ -149,7 +168,7 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
 
 EC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
 {
-    EC_KEY *ret = EC_KEY_new_method(ec_key->engine);
+    EC_KEY *ret = ec_key_new_method_int(ec_key->libctx, ec_key->engine);
 
     if (ret == NULL)
         return NULL;
@@ -211,6 +230,10 @@ int ec_key_simple_generate_key(EC_KEY *eckey)
     const BIGNUM *order = NULL;
     EC_POINT *pub_key = NULL;
     const EC_GROUP *group = eckey->group;
+    BN_CTX *ctx = BN_CTX_secure_new_ex(eckey->libctx);
+
+    if (ctx == NULL)
+        goto err;
 
     if (eckey->priv_key == NULL) {
         priv_key = BN_secure_new();
@@ -238,7 +261,7 @@ int ec_key_simple_generate_key(EC_KEY *eckey)
      * rand so the simpler backward compatible method has been used here.
      */
     do
-        if (!BN_priv_rand_range(priv_key, order))
+        if (!BN_priv_rand_range_ex(priv_key, order, ctx))
             goto err;
     while (BN_is_zero(priv_key)) ;
 
@@ -250,7 +273,7 @@ int ec_key_simple_generate_key(EC_KEY *eckey)
         pub_key = eckey->pub_key;
 
     /* Step (8) : pub_key = priv_key * G (where G is a point on the curve) */
-    if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL))
+    if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
         goto err;
 
     eckey->priv_key = priv_key;
@@ -270,6 +293,7 @@ err:
 
     EC_POINT_free(pub_key);
     BN_clear_free(priv_key);
+    BN_CTX_free(ctx);
     return ok;
 }
 
@@ -368,7 +392,7 @@ int ec_key_simple_check_key(const EC_KEY *eckey)
         goto err;
     }
 
-    if ((ctx = BN_CTX_new()) == NULL)
+    if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL)
         goto err;
 
     if ((point = EC_POINT_new(eckey->group)) == NULL)
@@ -445,7 +469,7 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
               ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
-    ctx = BN_CTX_new();
+    ctx = BN_CTX_new_ex(key->libctx);
     if (ctx == NULL)
         return 0;
 
diff --git a/crypto/ec/ec_kmeth.c b/crypto/ec/ec_kmeth.c
index c3209bc5cc..036fec8726 100644
--- a/crypto/ec/ec_kmeth.c
+++ b/crypto/ec/ec_kmeth.c
@@ -59,7 +59,7 @@ int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth)
     if (finish != NULL)
         finish(key);
 
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     ENGINE_finish(key->engine);
     key->engine = NULL;
 #endif
@@ -70,28 +70,30 @@ int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth)
     return 1;
 }
 
-EC_KEY *EC_KEY_new_method(ENGINE *engine)
+EC_KEY *ec_key_new_method_int(OPENSSL_CTX *libctx, ENGINE *engine)
 {
     EC_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
 
     if (ret == NULL) {
-        ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+        ECerr(EC_F_EC_KEY_NEW_METHOD_INT, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
+    ret->libctx = libctx;
+
     ret->references = 1;
     ret->lock = CRYPTO_THREAD_lock_new();
     if (ret->lock == NULL) {
-        ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+        ECerr(EC_F_EC_KEY_NEW_METHOD_INT, ERR_R_MALLOC_FAILURE);
         OPENSSL_free(ret);
         return NULL;
     }
 
     ret->meth = EC_KEY_get_default_method();
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     if (engine != NULL) {
         if (!ENGINE_init(engine)) {
-            ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB);
+            ECerr(EC_F_EC_KEY_NEW_METHOD_INT, ERR_R_ENGINE_LIB);
             goto err;
         }
         ret->engine = engine;
@@ -100,7 +102,7 @@ EC_KEY *EC_KEY_new_method(ENGINE *engine)
     if (ret->engine != NULL) {
         ret->meth = ENGINE_get_EC(ret->engine);
         if (ret->meth == NULL) {
-            ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB);
+            ECerr(EC_F_EC_KEY_NEW_METHOD_INT, ERR_R_ENGINE_LIB);
             goto err;
         }
     }
@@ -109,12 +111,15 @@ EC_KEY *EC_KEY_new_method(ENGINE *engine)
     ret->version = 1;
     ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
 
+/* No ex_data inside the FIPS provider */
+#ifndef FIPS_MODE
     if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) {
         goto err;
     }
+#endif
 
     if (ret->meth->init != NULL && ret->meth->init(ret) == 0) {
-        ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_INIT_FAIL);
+        ECerr(EC_F_EC_KEY_NEW_METHOD_INT, ERR_R_INIT_FAIL);
         goto err;
     }
     return ret;
@@ -124,6 +129,13 @@ EC_KEY *EC_KEY_new_method(ENGINE *engine)
     return NULL;
 }
 
+#ifndef FIPS_MODE
+EC_KEY *EC_KEY_new_method(ENGINE *engine)
+{
+    return ec_key_new_method_int(NULL, engine);
+}
+#endif
+
 int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
                      const EC_KEY *eckey,
                      void *(*KDF) (const void *in, size_t inlen, void *out,
diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h
index 0b1697ec3a..2ff46b6ca6 100644
--- a/crypto/ec/ec_lcl.h
+++ b/crypto/ec/ec_lcl.h
@@ -268,6 +268,8 @@ struct ec_group_st {
         NISTZ256_PRE_COMP *nistz256;
         EC_PRE_COMP *ec;
     } pre_comp;
+
+    OPENSSL_CTX *libctx;
 };
 
 #define SETPRECOMP(g, type, pre) \
@@ -286,8 +288,11 @@ struct ec_key_st {
     point_conversion_form_t conv_form;
     CRYPTO_REF_COUNT references;
     int flags;
+#ifndef FIPS_MODE
     CRYPTO_EX_DATA ex_data;
+#endif
     CRYPTO_RWLOCK *lock;
+    OPENSSL_CTX *libctx;
 };
 
 struct ec_point_st {
@@ -592,7 +597,7 @@ int ec_key_simple_generate_key(EC_KEY *eckey);
 int ec_key_simple_generate_public_key(EC_KEY *eckey);
 int ec_key_simple_check_key(const EC_KEY *eckey);
 
-int ec_curve_nid_from_params(const EC_GROUP *group);
+int ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx);
 
 /* EC_METHOD definitions */
 
@@ -625,6 +630,8 @@ struct ec_key_method_st {
 
 #define EC_KEY_METHOD_DYNAMIC   1
 
+EC_KEY *ec_key_new_method_int(OPENSSL_CTX *libctx, ENGINE *engine);
+
 int ossl_ec_key_gen(EC_KEY *eckey);
 int ossl_ecdh_compute_key(unsigned char **pout, size_t *poutlen,
                           const EC_POINT *pub_key, const EC_KEY *ecdh);
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
index 762cac4feb..d30504de65 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -17,25 +17,26 @@
 
 /* functions for EC_GROUP objects */
 
-EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
+EC_GROUP *EC_GROUP_new_ex(OPENSSL_CTX *libctx, const EC_METHOD *meth)
 {
     EC_GROUP *ret;
 
     if (meth == NULL) {
-        ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
+        ECerr(EC_F_EC_GROUP_NEW_EX, EC_R_SLOT_FULL);
         return NULL;
     }
     if (meth->group_init == 0) {
-        ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        ECerr(EC_F_EC_GROUP_NEW_EX, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
         return NULL;
     }
 
     ret = OPENSSL_zalloc(sizeof(*ret));
     if (ret == NULL) {
-        ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
+        ECerr(EC_F_EC_GROUP_NEW_EX, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
+    ret->libctx = libctx;
     ret->meth = meth;
     if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
         ret->order = BN_new();
@@ -58,6 +59,13 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
     return NULL;
 }
 
+#ifndef FIPS_MODE
+EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
+{
+    return EC_GROUP_new_ex(NULL, meth);
+}
+#endif
+
 void EC_pre_comp_free(EC_GROUP *group)
 {
     switch (group->pre_comp_type) {
@@ -140,6 +148,7 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
     if (dest == src)
         return 1;
 
+    dest->libctx = src->libctx;
     dest->curve_name = src->curve_name;
 
     /* Copy precomputed */
@@ -238,7 +247,7 @@ EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
     if (a == NULL)
         return NULL;
 
-    if ((t = EC_GROUP_new(a->meth)) == NULL)
+    if ((t = EC_GROUP_new_ex(a->libctx, a->meth)) == NULL)
         return NULL;
     if (!EC_GROUP_copy(t, a))
         goto err;
@@ -493,8 +502,15 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
 {
     int r = 0;
     BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
+#ifndef FIPS_MODE
     BN_CTX *ctx_new = NULL;
 
+    if (ctx == NULL)
+        ctx_new = ctx = BN_CTX_new();
+#endif
+    if (ctx == NULL)
+        return -1;
+
     /* compare the field types */
     if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
         EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
@@ -506,11 +522,6 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
     if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE)
         return 0;
 
-    if (ctx == NULL)
-        ctx_new = ctx = BN_CTX_new();
-    if (ctx == NULL)
-        return -1;
-
     BN_CTX_start(ctx);
     a1 = BN_CTX_get(ctx);
     a2 = BN_CTX_get(ctx);
@@ -520,7 +531,9 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
     b3 = BN_CTX_get(ctx);
     if (b3 == NULL) {
         BN_CTX_end(ctx);
+#ifndef FIPS_MODE
         BN_CTX_free(ctx_new);
+#endif
         return -1;
     }
 
@@ -570,8 +583,9 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
     }
 end:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(ctx_new);
-
+#endif
     return r;
 }
 
@@ -936,8 +950,17 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
 {
     int ret = 0;
     size_t i = 0;
+#ifndef FIPS_MODE
     BN_CTX *new_ctx = NULL;
 
+    if (ctx == NULL)
+        ctx = new_ctx = BN_CTX_secure_new();
+#endif
+    if (ctx == NULL) {
+        ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
     if ((scalar == NULL) && (num == 0)) {
         return EC_POINT_set_to_infinity(group, r);
     }
@@ -953,18 +976,15 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
         }
     }
 
-    if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) {
-        ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR);
-        return 0;
-    }
-
     if (group->meth->mul != NULL)
         ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx);
     else
         /* use default */
         ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
 
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 
@@ -1015,7 +1035,7 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
  */
 static int ec_precompute_mont_data(EC_GROUP *group)
 {
-    BN_CTX *ctx = BN_CTX_new();
+    BN_CTX *ctx = BN_CTX_new_ex(group->libctx);
     int ret = 0;
 
     BN_MONT_CTX_free(group->mont_data);
@@ -1042,6 +1062,7 @@ static int ec_precompute_mont_data(EC_GROUP *group)
     return ret;
 }
 
+#ifndef FIPS_MODE
 int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
 {
     return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
@@ -1051,6 +1072,7 @@ void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
 {
     return CRYPTO_get_ex_data(&key->ex_data, idx);
 }
+#endif
 
 int ec_group_simple_order_bits(const EC_GROUP *group)
 {
@@ -1063,14 +1085,18 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
                                     const BIGNUM *x, BN_CTX *ctx)
 {
     BIGNUM *e = NULL;
-    BN_CTX *new_ctx = NULL;
     int ret = 0;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
 
-    if (group->mont_data == NULL)
+    if (ctx == NULL)
+        ctx = new_ctx = BN_CTX_secure_new();
+#endif
+    if (ctx == NULL)
         return 0;
 
-    if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
-        return 0;
+    if (group->mont_data == NULL)
+        goto err;
 
     BN_CTX_start(ctx);
     if ((e = BN_CTX_get(ctx)) == NULL)
@@ -1095,7 +1121,9 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
 
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 
diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c
index 968125f3cd..be4f230623 100644
--- a/crypto/ec/ec_mult.c
+++ b/crypto/ec/ec_mult.c
@@ -815,12 +815,14 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
 {
     const EC_POINT *generator;
     EC_POINT *tmp_point = NULL, *base = NULL, **var;
-    BN_CTX *new_ctx = NULL;
     const BIGNUM *order;
     size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;
     EC_POINT **points = NULL;
     EC_PRE_COMP *pre_comp;
     int ret = 0;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
+#endif
 
     /* if there is an old EC_PRE_COMP object, throw it away */
     EC_pre_comp_free(group);
@@ -833,11 +835,12 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
         goto err;
     }
 
-    if (ctx == NULL) {
+#ifndef FIPS_MODE
+    if (ctx == NULL)
         ctx = new_ctx = BN_CTX_new();
-        if (ctx == NULL)
-            goto err;
-    }
+#endif
+    if (ctx == NULL)
+        goto err;
 
     BN_CTX_start(ctx);
 
@@ -949,7 +952,9 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
 
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     EC_ec_pre_comp_free(pre_comp);
     if (points) {
         EC_POINT **p;
diff --git a/crypto/ec/ecdh_ossl.c b/crypto/ec/ecdh_ossl.c
index d1330d8a50..b3fb879246 100644
--- a/crypto/ec/ecdh_ossl.c
+++ b/crypto/ec/ecdh_ossl.c
@@ -47,7 +47,7 @@ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
     size_t buflen, len;
     unsigned char *buf = NULL;
 
-    if ((ctx = BN_CTX_new()) == NULL)
+    if ((ctx = BN_CTX_new_ex(ecdh->libctx)) == NULL)
         goto err;
     BN_CTX_start(ctx);
     x = BN_CTX_get(ctx);
diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c
index b5aba77a4f..86bdc87721 100644
--- a/crypto/ec/ecdsa_ossl.c
+++ b/crypto/ec/ecdsa_ossl.c
@@ -58,7 +58,7 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
     }
 
     if ((ctx = ctx_in) == NULL) {
-        if ((ctx = BN_CTX_new()) == NULL) {
+        if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL) {
             ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE);
             return 0;
         }
@@ -95,7 +95,7 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
                     goto err;
                 }
             } else {
-                if (!BN_priv_rand_range(k, order)) {
+                if (!BN_priv_rand_range_ex(k, order, ctx)) {
                     ECerr(EC_F_ECDSA_SIGN_SETUP,
                           EC_R_RANDOM_NUMBER_GENERATION_FAILED);
                     goto err;
@@ -193,7 +193,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
     }
     s = ret->s;
 
-    if ((ctx = BN_CTX_new()) == NULL
+    if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL
         || (m = BN_new()) == NULL) {
         ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
         goto err;
@@ -337,7 +337,7 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
         return -1;
     }
 
-    ctx = BN_CTX_new();
+    ctx = BN_CTX_new_ex(eckey->libctx);
     if (ctx == NULL) {
         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE);
         return -1;
diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c
index 1654d59513..308b30629d 100644
--- a/crypto/ec/ecp_mont.c
+++ b/crypto/ec/ecp_mont.c
@@ -146,7 +146,7 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
     group->field_data2 = NULL;
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return 0;
     }
@@ -222,7 +222,8 @@ int ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
     if (group->field_data1 == NULL)
         return 0;
 
-    if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
+    if (ctx == NULL
+            && (ctx = new_ctx = BN_CTX_secure_new_ex(group->libctx)) == NULL)
         return 0;
 
     BN_CTX_start(ctx);
diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c
index 9f9045b544..13249b52de 100644
--- a/crypto/ec/ecp_nist.c
+++ b/crypto/ec/ecp_nist.c
@@ -89,7 +89,7 @@ int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p,
     BN_CTX *new_ctx = NULL;
 
     if (ctx == NULL)
-        if ((ctx = new_ctx = BN_CTX_new()) == NULL)
+        if ((ctx = new_ctx = BN_CTX_new_ex(group->libctx)) == NULL)
             return 0;
 
     BN_CTX_start(ctx);
@@ -128,7 +128,7 @@ int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
         goto err;
     }
     if (!ctx)
-        if ((ctx_new = ctx = BN_CTX_new()) == NULL)
+        if ((ctx_new = ctx = BN_CTX_new_ex(group->libctx)) == NULL)
             goto err;
 
     if (!BN_mul(r, a, b, ctx))
@@ -153,7 +153,7 @@ int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
         goto err;
     }
     if (!ctx)
-        if ((ctx_new = ctx = BN_CTX_new()) == NULL)
+        if ((ctx_new = ctx = BN_CTX_new_ex(group->libctx)) == NULL)
             goto err;
 
     if (!BN_sqr(r, a, ctx))
diff --git a/crypto/ec/ecp_nistp224.c b/crypto/ec/ecp_nistp224.c
index e6f095e728..a9f40d09c7 100644
--- a/crypto/ec/ecp_nistp224.c
+++ b/crypto/ec/ecp_nistp224.c
@@ -1281,12 +1281,16 @@ int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
                                     BN_CTX *ctx)
 {
     int ret = 0;
-    BN_CTX *new_ctx = NULL;
     BIGNUM *curve_p, *curve_a, *curve_b;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
 
     if (ctx == NULL)
-        if ((ctx = new_ctx = BN_CTX_new()) == NULL)
-            return 0;
+        new_ctx = BN_CTX_new();
+#endif
+    if (ctx == NULL)
+        return 0;
+
     BN_CTX_start(ctx);
     curve_p = BN_CTX_get(ctx);
     curve_a = BN_CTX_get(ctx);
@@ -1305,7 +1309,9 @@ int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
     ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 
@@ -1588,16 +1594,23 @@ int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
     int ret = 0;
     NISTP224_PRE_COMP *pre = NULL;
     int i, j;
-    BN_CTX *new_ctx = NULL;
     BIGNUM *x, *y;
     EC_POINT *generator = NULL;
     felem tmp_felems[32];
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
+#endif
 
     /* throw away old precomputation */
     EC_pre_comp_free(group);
+
+#ifndef FIPS_MODE
     if (ctx == NULL)
-        if ((ctx = new_ctx = BN_CTX_new()) == NULL)
-            return 0;
+        new_ctx = BN_CTX_new();
+#endif
+    if (ctx == NULL)
+        return 0;
+
     BN_CTX_start(ctx);
     x = BN_CTX_get(ctx);
     y = BN_CTX_get(ctx);
@@ -1705,7 +1718,9 @@ int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
  err:
     BN_CTX_end(ctx);
     EC_POINT_free(generator);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     EC_nistp224_pre_comp_free(pre);
     return ret;
 }
diff --git a/crypto/ec/ecp_nistp256.c b/crypto/ec/ecp_nistp256.c
index ee5508fade..4fc589b913 100644
--- a/crypto/ec/ecp_nistp256.c
+++ b/crypto/ec/ecp_nistp256.c
@@ -1901,12 +1901,16 @@ int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
                                     BN_CTX *ctx)
 {
     int ret = 0;
-    BN_CTX *new_ctx = NULL;
     BIGNUM *curve_p, *curve_a, *curve_b;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
 
     if (ctx == NULL)
-        if ((ctx = new_ctx = BN_CTX_new()) == NULL)
-            return 0;
+        new_ctx = BN_CTX_new();
+#endif
+    if (ctx == NULL)
+        return 0;
+
     BN_CTX_start(ctx);
     curve_p = BN_CTX_get(ctx);
     curve_a = BN_CTX_get(ctx);
@@ -1925,7 +1929,9 @@ int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
     ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 
@@ -2215,17 +2221,24 @@ int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
     int ret = 0;
     NISTP256_PRE_COMP *pre = NULL;
     int i, j;
-    BN_CTX *new_ctx = NULL;
     BIGNUM *x, *y;
     EC_POINT *generator = NULL;
     smallfelem tmp_smallfelems[32];
     felem x_tmp, y_tmp, z_tmp;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
+#endif
 
     /* throw away old precomputation */
     EC_pre_comp_free(group);
+
+#ifndef FIPS_MODE
     if (ctx == NULL)
-        if ((ctx = new_ctx = BN_CTX_new()) == NULL)
-            return 0;
+        new_ctx = BN_CTX_new();
+#endif
+    if (ctx == NULL)
+        return 0;
+
     BN_CTX_start(ctx);
     x = BN_CTX_get(ctx);
     y = BN_CTX_get(ctx);
@@ -2343,7 +2356,9 @@ int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
  err:
     BN_CTX_end(ctx);
     EC_POINT_free(generator);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     EC_nistp256_pre_comp_free(pre);
     return ret;
 }
diff --git a/crypto/ec/ecp_nistp521.c b/crypto/ec/ecp_nistp521.c
index 06f1a6380f..ff5c2cfa64 100644
--- a/crypto/ec/ecp_nistp521.c
+++ b/crypto/ec/ecp_nistp521.c
@@ -1743,12 +1743,16 @@ int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
                                     BN_CTX *ctx)
 {
     int ret = 0;
-    BN_CTX *new_ctx = NULL;
     BIGNUM *curve_p, *curve_a, *curve_b;
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
 
     if (ctx == NULL)
-        if ((ctx = new_ctx = BN_CTX_new()) == NULL)
-            return 0;
+        new_ctx = BN_CTX_new();
+#endif
+    if (ctx == NULL)
+        return 0;
+
     BN_CTX_start(ctx);
     curve_p = BN_CTX_get(ctx);
     curve_a = BN_CTX_get(ctx);
@@ -1767,7 +1771,9 @@ int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
     ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
  err:
     BN_CTX_end(ctx);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     return ret;
 }
 
@@ -2054,16 +2060,23 @@ int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
     int ret = 0;
     NISTP521_PRE_COMP *pre = NULL;
     int i, j;
-    BN_CTX *new_ctx = NULL;
     BIGNUM *x, *y;
     EC_POINT *generator = NULL;
     felem tmp_felems[16];
+#ifndef FIPS_MODE
+    BN_CTX *new_ctx = NULL;
+#endif
 
     /* throw away old precomputation */
     EC_pre_comp_free(group);
+
+#ifndef FIPS_MODE
     if (ctx == NULL)
-        if ((ctx = new_ctx = BN_CTX_new()) == NULL)
-            return 0;
+        new_ctx = BN_CTX_new();
+#endif
+    if (ctx == NULL)
+        return 0;
+
     BN_CTX_start(ctx);
     x = BN_CTX_get(ctx);
     y = BN_CTX_get(ctx);
@@ -2151,7 +2164,9 @@ int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
  err:
     BN_CTX_end(ctx);
     EC_POINT_free(generator);
+#ifndef FIPS_MODE
     BN_CTX_free(new_ctx);
+#endif
     EC_nistp521_pre_comp_free(pre);
     return ret;
 }
diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c
index 66bf4ecb1e..df1724c385 100644
--- a/crypto/ec/ecp_nistz256.c
+++ b/crypto/ec/ecp_nistz256.c
@@ -813,7 +813,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
         return 0;
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             goto err;
     }
diff --git a/crypto/ec/ecp_oct.c b/crypto/ec/ecp_oct.c
index 9b430f9b94..a00eac35be 100644
--- a/crypto/ec/ecp_oct.c
+++ b/crypto/ec/ecp_oct.c
@@ -22,11 +22,13 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
     BIGNUM *tmp1, *tmp2, *x, *y;
     int ret = 0;
 
+#ifndef FIPS_MODE
     /* clear error queue */
     ERR_clear_error();
+#endif
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return 0;
     }
@@ -99,6 +101,7 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
     }
 
     if (!BN_mod_sqrt(y, tmp1, group->field, ctx)) {
+#ifndef FIPS_MODE
         unsigned long err = ERR_peek_last_error();
 
         if (ERR_GET_LIB(err) == ERR_LIB_BN
@@ -107,8 +110,11 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
             ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
                   EC_R_INVALID_COMPRESSED_POINT);
         } else
+#endif
+        {
             ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
                   ERR_R_BN_LIB);
+        }
         goto err;
     }
 
@@ -194,7 +200,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
         }
 
         if (ctx == NULL) {
-            ctx = new_ctx = BN_CTX_new();
+            ctx = new_ctx = BN_CTX_new_ex(group->libctx);
             if (ctx == NULL)
                 return 0;
         }
@@ -314,7 +320,7 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
     }
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return 0;
     }
diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c
index 2fd2ce46ea..e8295e636a 100644
--- a/crypto/ec/ecp_smpl.c
+++ b/crypto/ec/ecp_smpl.c
@@ -146,7 +146,7 @@ int ec_GFp_simple_group_set_curve(EC_GROUP *group,
     }
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return 0;
     }
@@ -204,7 +204,7 @@ int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
     if (a != NULL || b != NULL) {
         if (group->meth->field_decode) {
             if (ctx == NULL) {
-                ctx = new_ctx = BN_CTX_new();
+                ctx = new_ctx = BN_CTX_new_ex(group->libctx);
                 if (ctx == NULL)
                     return 0;
             }
@@ -248,7 +248,7 @@ int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
     BN_CTX *new_ctx = NULL;
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL) {
             ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT,
                   ERR_R_MALLOC_FAILURE);
@@ -376,7 +376,7 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
     int ret = 0;
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return 0;
     }
@@ -435,7 +435,7 @@ int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
 
     if (group->meth->field_decode != 0) {
         if (ctx == NULL) {
-            ctx = new_ctx = BN_CTX_new();
+            ctx = new_ctx = BN_CTX_new_ex(group->libctx);
             if (ctx == NULL)
                 return 0;
         }
@@ -509,7 +509,7 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
     }
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return 0;
     }
@@ -629,7 +629,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
     p = group->field;
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return 0;
     }
@@ -813,7 +813,7 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
     p = group->field;
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return 0;
     }
@@ -966,7 +966,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
     p = group->field;
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return -1;
     }
@@ -1083,7 +1083,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
     field_sqr = group->meth->field_sqr;
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return -1;
     }
@@ -1169,7 +1169,7 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
         return 1;
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return 0;
     }
@@ -1210,7 +1210,7 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
         return 1;
 
     if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
         if (ctx == NULL)
             return 0;
     }
@@ -1380,7 +1380,8 @@ int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
     BN_CTX *new_ctx = NULL;
     int ret = 0;
 
-    if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
+    if (ctx == NULL
+            && (ctx = new_ctx = BN_CTX_secure_new_ex(group->libctx)) == NULL)
         return 0;
 
     BN_CTX_start(ctx);
@@ -1388,7 +1389,7 @@ int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
         goto err;
 
     do {
-        if (!BN_priv_rand_range(e, group->field))
+        if (!BN_priv_rand_range_ex(e, group->field, ctx))
         goto err;
     } while (BN_is_zero(e));
 
@@ -1436,7 +1437,7 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
 
     /* make sure lambda is not zero */
     do {
-        if (!BN_priv_rand_range(lambda, group->field)) {
+        if (!BN_priv_rand_range_ex(lambda, group->field, ctx)) {
             ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_BN_LIB);
             goto err;
         }
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index 1958aa2610..75ea96754f 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -110,7 +110,11 @@ static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
             X448_public_from_private(pubkey, privkey);
             break;
         case EVP_PKEY_ED448:
-            ED448_public_from_private(pubkey, privkey);
+            /*
+             * TODO(3.0): We set the library context to NULL for now. This will
+             * need to change.
+             */
+            ED448_public_from_private(NULL, pubkey, privkey);
             break;
         }
     }
@@ -771,8 +775,12 @@ static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
         return 0;
     }
 
-    if (ED448_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
-                   0) == 0)
+    /*
+     * TODO(3.0): We use NULL for the library context for now. Will need to
+     * change later.
+     */
+    if (ED448_sign(NULL, sig, tbs, tbslen, edkey->pubkey, edkey->privkey,
+                   NULL, 0) == 0)
         return 0;
     *siglen = ED448_SIGSIZE;
     return 1;
@@ -799,7 +807,11 @@ static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
     if (siglen != ED448_SIGSIZE)
         return 0;
 
-    return ED448_verify(tbs, tbslen, sig, edkey->pubkey, NULL, 0);
+    /*
+     * TODO(3.0): We send NULL for the OPENSSL_CTX for now. This will need to
+     * change.
+     */
+    return ED448_verify(NULL, tbs, tbslen, sig, edkey->pubkey, NULL, 0);
 }
 
 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 9644323888..f6e5a7593e 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -627,6 +627,7 @@ EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES:169:\
 	ec_GFp_simple_set_compressed_coordinates
 EC_F_EC_GROUP_CHECK:170:EC_GROUP_check
 EC_F_EC_GROUP_CHECK_DISCRIMINANT:171:EC_GROUP_check_discriminant
+EC_F_EC_GROUP_CHECK_NAMED_CURVE:299:EC_GROUP_check_named_curve
 EC_F_EC_GROUP_COPY:106:EC_GROUP_copy
 EC_F_EC_GROUP_GET_CURVE:291:EC_GROUP_get_curve
 EC_F_EC_GROUP_GET_CURVE_GF2M:172:EC_GROUP_get_curve_GF2m
@@ -638,6 +639,8 @@ EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS:193:EC_GROUP_get_pentanomial_basis
 EC_F_EC_GROUP_GET_TRINOMIAL_BASIS:194:EC_GROUP_get_trinomial_basis
 EC_F_EC_GROUP_NEW:108:EC_GROUP_new
 EC_F_EC_GROUP_NEW_BY_CURVE_NAME:174:EC_GROUP_new_by_curve_name
+EC_F_EC_GROUP_NEW_BY_CURVE_NAME_EX:301:EC_GROUP_new_by_curve_name_ex
+EC_F_EC_GROUP_NEW_EX:302:EC_GROUP_new_ex
 EC_F_EC_GROUP_NEW_FROM_DATA:175:ec_group_new_from_data
 EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS:263:EC_GROUP_new_from_ecparameters
 EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS:264:EC_GROUP_new_from_ecpkparameters
@@ -651,6 +654,7 @@ EC_F_EC_KEY_COPY:178:EC_KEY_copy
 EC_F_EC_KEY_GENERATE_KEY:179:EC_KEY_generate_key
 EC_F_EC_KEY_NEW:182:EC_KEY_new
 EC_F_EC_KEY_NEW_METHOD:245:EC_KEY_new_method
+EC_F_EC_KEY_NEW_METHOD_INT:300:ec_key_new_method_int
 EC_F_EC_KEY_OCT2PRIV:255:EC_KEY_oct2priv
 EC_F_EC_KEY_PRINT:180:EC_KEY_print
 EC_F_EC_KEY_PRINT_FP:181:EC_KEY_print_fp
diff --git a/crypto/include/internal/bn_int.h b/crypto/include/internal/bn_int.h
index 4fcbb14502..cb8b17662a 100644
--- a/crypto/include/internal/bn_int.h
+++ b/crypto/include/internal/bn_int.h
@@ -110,4 +110,5 @@ int bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
                                   const BIGNUM *r1, const BIGNUM *r2, int nlen,
                                   const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb);
 
+OPENSSL_CTX *bn_get_lib_ctx(BN_CTX *ctx);
 #endif
diff --git a/crypto/ppccap.c b/crypto/ppccap.c
index 9109c4d3e4..e540db1441 100644
--- a/crypto/ppccap.c
+++ b/crypto/ppccap.c
@@ -145,8 +145,9 @@ int poly1305_init(void *ctx, const unsigned char key[16], void *func[2])
     return 1;
 }
 # endif
+#endif /* FIPS_MODE */
 
-# ifdef ECP_NISTZ256_ASM
+#ifdef ECP_NISTZ256_ASM
 void ecp_nistz256_mul_mont(unsigned long res[4], const unsigned long a[4],
                            const unsigned long b[4]);
 
@@ -168,8 +169,7 @@ void ecp_nistz256_from_mont(unsigned long res[4], const unsigned long in[4])
 
     ecp_nistz256_mul_mont(res, in, one);
 }
-# endif
-#endif /* FIPS_MODE */
+#endif
 
 static sigjmp_buf ill_jmp;
 static void ill_handler(int sig)
diff --git a/doc/man3/EC_GROUP_copy.pod b/doc/man3/EC_GROUP_copy.pod
index b62eaa959c..1a4d7c015f 100644
--- a/doc/man3/EC_GROUP_copy.pod
+++ b/doc/man3/EC_GROUP_copy.pod
@@ -51,7 +51,8 @@ EC_GROUP_get_pentanomial_basis, EC_GROUP_get0_field
  int EC_GROUP_get_degree(const EC_GROUP *group);
 
  int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);
- int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only);
+ int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only,
+                                BN_CTX *ctx);
 
  int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx);
 
@@ -152,6 +153,8 @@ then this method can be used to lookup the name of the curve that matches the gr
 aliases, so that multiple NID's can map to the same domain parameters. For such curves it is unspecified which of the aliases will be
 returned if the curve name of the given group is NID_undef.
 If B<nist_only> is 1 it will only look for NIST approved curves, otherwise it searches all built-in curves.
+This function may be passed a BN_CTX object in the B<ctx> parameter.
+The B<ctx> parameter may be NULL.
 
 EC_GROUP_cmp compares B<a> and B<b> to determine whether they represent the same curve or not.
 
diff --git a/doc/man3/EC_GROUP_new.pod b/doc/man3/EC_GROUP_new.pod
index 87c3adaf33..6ac8e4aa83 100644
--- a/doc/man3/EC_GROUP_new.pod
+++ b/doc/man3/EC_GROUP_new.pod
@@ -4,6 +4,7 @@
 
 EC_GROUP_get_ecparameters,
 EC_GROUP_get_ecpkparameters,
+EC_GROUP_new_ex,
 EC_GROUP_new,
 EC_GROUP_new_from_ecparameters,
 EC_GROUP_new_from_ecpkparameters,
@@ -11,6 +12,7 @@ EC_GROUP_free,
 EC_GROUP_clear_free,
 EC_GROUP_new_curve_GFp,
 EC_GROUP_new_curve_GF2m,
+EC_GROUP_new_by_curve_name_ex,
 EC_GROUP_new_by_curve_name,
 EC_GROUP_set_curve,
 EC_GROUP_get_curve,
@@ -25,6 +27,7 @@ objects
 
  #include <openssl/ec.h>
 
+ EC_GROUP *EC_GROUP_new_ex(OPENSSL_CTX *libctx, const EC_METHOD *meth);
  EC_GROUP *EC_GROUP_new(const EC_METHOD *meth);
  EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
  EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params)
@@ -35,6 +38,7 @@ objects
                                   const BIGNUM *b, BN_CTX *ctx);
  EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a,
                                    const BIGNUM *b, BN_CTX *ctx);
+ EC_GROUP *EC_GROUP_new_by_curve_name_ex(OPENSSL_CTX *libctx, int nid);
  EC_GROUP *EC_GROUP_new_by_curve_name(int nid);
 
  int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
@@ -71,12 +75,18 @@ y^2 + xy = x^3 + ax^2 + b (where b != 0)
 Operations in a binary field are performed relative to an B<irreducible polynomial>. All such curves with OpenSSL
 use a trinomial or a pentanomial for this parameter.
 
-A new curve can be constructed by calling EC_GROUP_new, using the implementation provided by B<meth> (see
-L<EC_GFp_simple_method(3)>). It is then necessary to call EC_GROUP_set_curve() to set the curve parameters.
+A new curve can be constructed by calling EC_GROUP_new_ex, using the implementation provided by B<meth> (see
+L<EC_GFp_simple_method(3)>) and associated with the library context B<ctx>
+(see L<OPENSSL_CTX(3)>).
+The B<ctx> parameter may be NULL in which case the default library context is used.
+It is then necessary to call EC_GROUP_set_curve() to set the curve parameters.
 EC_GROUP_new_from_ecparameters() will create a group from the
 specified B<params> and
 EC_GROUP_new_from_ecpkparameters() will create a group from the specific PK B<params>.
 
+EC_GROUP_new is the same as EC_GROUP_new_ex() except that the library context
+used is always the default library context.
+
 EC_GROUP_set_curve() sets the curve parameters B<p>, B<a> and B<b>. For a curve over Fp B<b>
 is the prime for the field. For a curve over F2^m B<p> represents the irreducible polynomial - each bit
 represents a term in the polynomial. Therefore there will either be three or five bits set dependent on whether
@@ -109,8 +119,12 @@ The EC_builtin_curve structure is defined as follows:
 
 Each EC_builtin_curve item has a unique integer id (B<nid>), and a human readable comment string describing the curve.
 
-In order to construct a builtin curve use the function EC_GROUP_new_by_curve_name and provide the B<nid> of the curve to
-be constructed.
+In order to construct a builtin curve use the function EC_GROUP_new_by_curve_name_ex and provide the B<nid> of the curve to
+be constructed and the associated library context to be used in B<ctx> (see L<OPENSSL_CTX(3)>).
+The B<ctx> value may be NULL in which case the default library context is used.
+
+EC_GROUP_new_by_curve_name is the same as EC_GROUP_new_by_curve_name_ex except
+that the default library context is always used.
 
 EC_GROUP_free frees the memory associated with the EC_GROUP.
 If B<group> is NULL nothing is done.
@@ -130,7 +144,12 @@ EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, EC_GROUP_set_curve_GF2m, EC_GROU
 
 L<crypto(7)>, L<EC_GROUP_copy(3)>,
 L<EC_POINT_new(3)>, L<EC_POINT_add(3)>, L<EC_KEY_new(3)>,
-L<EC_GFp_simple_method(3)>, L<d2i_ECPKParameters(3)>
+L<EC_GFp_simple_method(3)>, L<d2i_ECPKParameters(3)>,
+L<OPENSSL_CTX(3)>
+
+=head1 HISTORY
+
+EC_GROUP_new_ex and EC_GROUP_new_by_curve_name_ex were added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/doc/man3/EC_KEY_new.pod b/doc/man3/EC_KEY_new.pod
index 04ab2d5f57..ff4373ea35 100644
--- a/doc/man3/EC_KEY_new.pod
+++ b/doc/man3/EC_KEY_new.pod
@@ -2,10 +2,10 @@
 
 =head1 NAME
 
-EC_KEY_get_method, EC_KEY_set_method,
+EC_KEY_get_method, EC_KEY_set_method, EC_KEY_new_ex,
 EC_KEY_new, EC_KEY_get_flags, EC_KEY_set_flags, EC_KEY_clear_flags,
-EC_KEY_new_by_curve_name, EC_KEY_free, EC_KEY_copy, EC_KEY_dup, EC_KEY_up_ref,
-EC_KEY_get0_engine,
+EC_KEY_new_by_curve_name_ex, EC_KEY_new_by_curve_name, EC_KEY_free, EC_KEY_copy,
+EC_KEY_dup, EC_KEY_up_ref, EC_KEY_get0_engine,
 EC_KEY_get0_group, EC_KEY_set_group, EC_KEY_get0_private_key,
 EC_KEY_set_private_key, EC_KEY_get0_public_key, EC_KEY_set_public_key,
 EC_KEY_get_conv_form,
@@ -19,10 +19,12 @@ EC_KEY objects
 
  #include <openssl/ec.h>
 
+ EC_KEY *EC_KEY_new_ex(OPENSSL_CTX *ctx);
  EC_KEY *EC_KEY_new(void);
  int EC_KEY_get_flags(const EC_KEY *key);
  void EC_KEY_set_flags(EC_KEY *key, int flags);
  void EC_KEY_clear_flags(EC_KEY *key, int flags);
+ EC_KEY *EC_KEY_new_by_curve_name_ex(OPENSSL_CTX *ctx, int nid);
  EC_KEY *EC_KEY_new_by_curve_name(int nid);
  void EC_KEY_free(EC_KEY *key);
  EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src);
@@ -57,15 +59,31 @@ EC_KEY objects
 =head1 DESCRIPTION
 
 An EC_KEY represents a public key and, optionally, the associated private
-key. A new EC_KEY with no associated curve can be constructed by calling
-EC_KEY_new(). The reference count for the newly created EC_KEY is initially
-set to 1. A curve can be associated with the EC_KEY by calling
+key.
+A new EC_KEY with no associated curve can be constructed by calling
+EC_KEY_new_ex() and specifying the associated library context in B<ctx>
+(see L<OPENSSL_CTX(3)>).
+The B<ctx> parameter may be NULL in which case the default library context is
+used.
+The reference count for the newly created EC_KEY is initially
+set to 1.
+A curve can be associated with the EC_KEY by calling
 EC_KEY_set_group().
 
+EC_KEY_new() is the same as EC_KEY_new_ex() except that the default library
+context is always used.
+
 Alternatively a new EC_KEY can be constructed by calling
-EC_KEY_new_by_curve_name() and supplying the nid of the associated curve. See
-L<EC_GROUP_new(3)> for a description of curve names. This function simply
-wraps calls to EC_KEY_new() and EC_GROUP_new_by_curve_name().
+EC_KEY_new_by_curve_name_ex() and supplying the nid of the associated curve and
+the library context to be used B<ctx> (see L<OPENSSL_CTX(3)>).
+The B<ctx> parameter may be NULL in which case the default library context is
+used.
+See L<EC_GROUP_new(3)> for a description of curve names.
+This function simply wraps calls to EC_KEY_new_ex() and
+EC_GROUP_new_by_curve_name_ex().
+
+EC_KEY_new_by_curve_name() is the same as EC_KEY_new_by_curve_name_ex() except
+that the default library context is always used.
 
 Calling EC_KEY_free() decrements the reference count for the EC_KEY object,
 and if it has dropped to zero then frees the memory associated with it.  If
@@ -144,8 +162,8 @@ EC_KEY_priv2buf() converts an EC_KEY private key into an allocated buffer.
 
 =head1 RETURN VALUES
 
-EC_KEY_new(), EC_KEY_new_by_curve_name() and EC_KEY_dup() return a pointer to
-the newly created EC_KEY object, or NULL on error.
+EC_KEY_new_ex(), EC_KEY_new(), EC_KEY_new_by_curve_name() and EC_KEY_dup()
+return a pointer to the newly created EC_KEY object, or NULL on error.
 
 EC_KEY_get_flags() returns the flags associated with the EC_KEY object as an
 integer.
@@ -174,7 +192,8 @@ L<crypto(7)>, L<EC_GROUP_new(3)>,
 L<EC_GROUP_copy(3)>, L<EC_POINT_new(3)>,
 L<EC_POINT_add(3)>,
 L<EC_GFp_simple_method(3)>,
-L<d2i_ECPKParameters(3)>
+L<d2i_ECPKParameters(3)>,
+L<OPENSSL_CTX(3)>
 
 =head1 COPYRIGHT
 
diff --git a/include/openssl/ec.h b/include/openssl/ec.h
index e523d0d729..b53b2dc843 100644
--- a/include/openssl/ec.h
+++ b/include/openssl/ec.h
@@ -100,8 +100,21 @@ const EC_METHOD *EC_GF2m_simple_method(void);
 /*                   EC_GROUP functions                             */
 /********************************************************************/
 
-/** Creates a new EC_GROUP object
- *  \param   meth  EC_METHOD to use
+/**
+ *  Creates a new EC_GROUP object
+ *  \param   libctx The associated library context or NULL for the default
+ *                  library context
+ *  \param   meth   EC_METHOD to use
+ *  \return  newly created EC_GROUP object or NULL in case of an error.
+ */
+EC_GROUP *EC_GROUP_new_ex(OPENSSL_CTX *libctx, const EC_METHOD *meth);
+
+/**
+ *  Creates a new EC_GROUP object. Same as EC_GROUP_new_ex with NULL for the
+ *  library context.
+ *  \param   libctx The associated library context or NULL for the default
+ *                  library context
+ *  \param   meth   EC_METHOD to use
  *  \return  newly created EC_GROUP object or NULL in case of an error.
  */
 EC_GROUP *EC_GROUP_new(const EC_METHOD *meth);
@@ -364,8 +377,20 @@ EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a,
                                   const BIGNUM *b, BN_CTX *ctx);
 # endif
 
-/** Creates a EC_GROUP object with a curve specified by a NID
- *  \param  nid  NID of the OID of the curve name
+/**
+ * Creates a EC_GROUP object with a curve specified by a NID
+ *  \param  libctx The associated library context or NULL for the default
+ *                 context
+ *  \param  nid    NID of the OID of the curve name
+ *  \return newly created EC_GROUP object with specified curve or NULL
+ *          if an error occurred
+ */
+EC_GROUP *EC_GROUP_new_by_curve_name_ex(OPENSSL_CTX *libctx, int nid);
+
+/**
+ * Creates a EC_GROUP object with a curve specified by a NID. Same as
+ * EC_GROUP_new_by_curve_name_ex but the libctx is always NULL.
+ *  \param  nid    NID of the OID of the curve name
  *  \return newly created EC_GROUP object with specified curve or NULL
  *          if an error occurred
  */
@@ -422,7 +447,8 @@ size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
 
 const char *EC_curve_nid2nist(int nid);
 int EC_curve_nist2nid(const char *name);
-int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only);
+int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only,
+                               BN_CTX *ctx);
 
 /********************************************************************/
 /*                    EC_POINT functions                            */
@@ -825,7 +851,17 @@ int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
 # define EC_FLAG_FIPS_CHECKED    0x2
 # define EC_FLAG_COFACTOR_ECDH   0x1000
 
-/** Creates a new EC_KEY object.
+/**
+ *  Creates a new EC_KEY object.
+ *  \param  ctx  The library context for to use for this EC_KEY. May be NULL in
+ *               which case the default library context is used.
+ *  \return EC_KEY object or NULL if an error occurred.
+ */
+EC_KEY *EC_KEY_new_ex(OPENSSL_CTX *ctx);
+
+/**
+ *  Creates a new EC_KEY object. Same as calling EC_KEY_new_ex with a NULL
+ *  library context
  *  \return EC_KEY object or NULL if an error occurred.
  */
 EC_KEY *EC_KEY_new(void);
@@ -836,13 +872,26 @@ void EC_KEY_set_flags(EC_KEY *key, int flags);
 
 void EC_KEY_clear_flags(EC_KEY *key, int flags);
 
-/** Creates a new EC_KEY object using a named curve as underlying
+/**
+ *  Creates a new EC_KEY object using a named curve as underlying
  *  EC_GROUP object.
+ *  \param  ctx  The library context for to use for this EC_KEY. May be NULL in
+ *               which case the default library context is used.
+ *  \param  nid  NID of the named curve.
+ *  \return EC_KEY object or NULL if an error occurred.
+ */
+EC_KEY *EC_KEY_new_by_curve_name_ex(OPENSSL_CTX *ctx, int nid);
+
+/**
+ *  Creates a new EC_KEY object using a named curve as underlying
+ *  EC_GROUP object. Same as calling EC_KEY_new_by_curve_name_ex with a NULL
+ *  library context.
  *  \param  nid  NID of the named curve.
  *  \return EC_KEY object or NULL if an error occurred.
  */
 EC_KEY *EC_KEY_new_by_curve_name(int nid);
 
+
 /** Frees a EC_KEY object.
  *  \param  key  EC_KEY object to be freed.
  */
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index d82074fd20..eb587f9e1d 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -19,6 +19,7 @@
 /* TODO(3.0): Needed for dummy_evp_call(). To be removed */
 #include <openssl/sha.h>
 #include <openssl/rand_drbg.h>
+#include <openssl/ec.h>
 
 #include "internal/cryptlib.h"
 #include "internal/property.h"
@@ -103,6 +104,7 @@ static int dummy_evp_call(void *provctx)
     BIGNUM *a = NULL, *b = NULL;
     unsigned char randbuf[128];
     RAND_DRBG *drbg = OPENSSL_CTX_get0_public_drbg(libctx);
+    EC_KEY *key = NULL;
 
     if (ctx == NULL || sha256 == NULL || drbg == NULL)
         goto err;
@@ -136,6 +138,14 @@ static int dummy_evp_call(void *provctx)
     if (!BN_rand_ex(a, 256, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, bnctx))
         goto err;
 
+    /* Do some dummy EC calls */
+    key = EC_KEY_new_by_curve_name_ex(libctx, NID_X9_62_prime256v1);
+    if (key == NULL)
+        goto err;
+
+    if (!EC_KEY_generate_key(key))
+        goto err;
+
     ret = 1;
  err:
     BN_CTX_end(bnctx);
@@ -143,6 +153,8 @@ static int dummy_evp_call(void *provctx)
 
     EVP_MD_CTX_free(ctx);
     EVP_MD_meth_free(sha256);
+
+    EC_KEY_free(key);
     return ret;
 }
 
diff --git a/test/curve448_internal_test.c b/test/curve448_internal_test.c
index 85c0b0e880..d3e3abab83 100644
--- a/test/curve448_internal_test.c
+++ b/test/curve448_internal_test.c
@@ -600,38 +600,38 @@ static int test_ed448(void)
     EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
 
     if (!TEST_ptr(hashctx)
-            || !TEST_true(ED448_sign(outsig, NULL, 0, pubkey1, privkey1, NULL,
-                                     0))
+            || !TEST_true(ED448_sign(NULL, outsig, NULL, 0, pubkey1, privkey1,
+                                     NULL, 0))
             || !TEST_int_eq(memcmp(sig1, outsig, sizeof(sig1)), 0)
-            || !TEST_true(ED448_sign(outsig, msg2, sizeof(msg2), pubkey2,
+            || !TEST_true(ED448_sign(NULL, outsig, msg2, sizeof(msg2), pubkey2,
                                      privkey2, NULL, 0))
             || !TEST_int_eq(memcmp(sig2, outsig, sizeof(sig2)), 0)
-            || !TEST_true(ED448_sign(outsig, msg3, sizeof(msg3), pubkey3,
+            || !TEST_true(ED448_sign(NULL, outsig, msg3, sizeof(msg3), pubkey3,
                                      privkey3, context3, sizeof(context3)))
             || !TEST_int_eq(memcmp(sig3, outsig, sizeof(sig3)), 0)
-            || !TEST_true(ED448_sign(outsig, msg4, sizeof(msg4), pubkey4,
+            || !TEST_true(ED448_sign(NULL, outsig, msg4, sizeof(msg4), pubkey4,
                                      privkey4, NULL, 0))
             || !TEST_int_eq(memcmp(sig4, outsig, sizeof(sig4)), 0)
-            || !TEST_true(ED448_sign(outsig, msg5, sizeof(msg5), pubkey5,
+            || !TEST_true(ED448_sign(NULL, outsig, msg5, sizeof(msg5), pubkey5,
                                      privkey5, NULL, 0))
             || !TEST_int_eq(memcmp(sig5, outsig, sizeof(sig5)), 0)
-            || !TEST_true(ED448_sign(outsig, msg6, sizeof(msg6), pubkey6,
+            || !TEST_true(ED448_sign(NULL, outsig, msg6, sizeof(msg6), pubkey6,
                                      privkey6, NULL, 0))
             || !TEST_int_eq(memcmp(sig6, outsig, sizeof(sig6)), 0)
-            || !TEST_true(ED448_sign(outsig, msg7, sizeof(msg7), pubkey7,
+            || !TEST_true(ED448_sign(NULL, outsig, msg7, sizeof(msg7), pubkey7,
                                      privkey7, NULL, 0))
             || !TEST_int_eq(memcmp(sig7, outsig, sizeof(sig7)), 0)
-            || !TEST_true(ED448_sign(outsig, msg8, sizeof(msg8), pubkey8,
+            || !TEST_true(ED448_sign(NULL, outsig, msg8, sizeof(msg8), pubkey8,
                                      privkey8, NULL, 0))
             || !TEST_int_eq(memcmp(sig8, outsig, sizeof(sig8)), 0)
-            || !TEST_true(ED448_sign(outsig, msg9, sizeof(msg9), pubkey9,
+            || !TEST_true(ED448_sign(NULL, outsig, msg9, sizeof(msg9), pubkey9,
                                      privkey9, NULL, 0))
             || !TEST_int_eq(memcmp(sig9, outsig, sizeof(sig9)), 0)
-            || !TEST_true(ED448ph_sign(outsig, dohash(hashctx, phmsg1,
+            || !TEST_true(ED448ph_sign(NULL, outsig, dohash(hashctx, phmsg1,
                                        sizeof(phmsg1)), phpubkey1, phprivkey1,
                                        NULL, 0))
             || !TEST_int_eq(memcmp(phsig1, outsig, sizeof(phsig1)), 0)
-            || !TEST_true(ED448ph_sign(outsig, dohash(hashctx, phmsg2,
+            || !TEST_true(ED448ph_sign(NULL, outsig, dohash(hashctx, phmsg2,
                                        sizeof(phmsg2)), phpubkey2, phprivkey2,
                                        phcontext2, sizeof(phcontext2)))
             || !TEST_int_eq(memcmp(phsig2, outsig, sizeof(phsig2)), 0)) {
diff --git a/test/ectest.c b/test/ectest.c
index 43ac905a64..cfe6d869eb 100644
--- a/test/ectest.c
+++ b/test/ectest.c
@@ -1625,22 +1625,22 @@ static int check_named_curve_test(int id)
     }
 
     /* Passes because this is a valid curve */
-    if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0), nid)
+    if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid)
         /* Only NIST curves pass */
-        || !TEST_int_eq(EC_GROUP_check_named_curve(group, 1),
+        || !TEST_int_eq(EC_GROUP_check_named_curve(group, 1, NULL),
                         EC_curve_nid2nist(nid) != NULL ? nid : NID_undef))
         goto err;
 
     /* Fail if the curve name doesn't match the parameters */
     EC_GROUP_set_curve_name(group, nid + 1);
     ERR_set_mark();
-    if (!TEST_int_le(EC_GROUP_check_named_curve(group, 0), 0))
+    if (!TEST_int_le(EC_GROUP_check_named_curve(group, 0, NULL), 0))
         goto err;
     ERR_pop_to_mark();
 
     /* Restore curve name and ensure it's passing */
     EC_GROUP_set_curve_name(group, nid);
-    if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0), nid))
+    if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid))
         goto err;
 
     if (!TEST_int_eq(EC_GROUP_set_seed(group, invalid_seed, invalid_seed_len),
@@ -1652,47 +1652,47 @@ static int check_named_curve_test(int id)
          * If the built-in curve has a seed and we set the seed to another value
          * then it will fail the check.
          */
-        if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0), 0))
+        if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), 0))
             goto err;
     } else {
         /*
          * If the built-in curve does not have a seed then setting the seed will
          * pass the check (as the seed is optional).
          */
-        if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0), nid))
+        if (!TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid))
             goto err;
     }
     /* Pass if the seed is unknown (as it is optional) */
     if (!TEST_int_eq(EC_GROUP_set_seed(group, NULL, 0), 1)
-        || !TEST_int_eq(EC_GROUP_check_named_curve(group, 0), nid))
+        || !TEST_int_eq(EC_GROUP_check_named_curve(group, 0, NULL), nid))
         goto err;
 
     /* Check that a duped group passes */
-    if (!TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), nid))
+    if (!TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid))
         goto err;
 
     /* check that changing any generator parameter fails */
     if (!TEST_true(EC_GROUP_set_generator(gtest, other_gen, group_order,
                                           group_cofactor))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), 0)
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), 0)
         || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, other_order,
                                              group_cofactor))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), 0)
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), 0)
         /* The order is not an optional field, so this should fail */
         || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, NULL,
                                              group_cofactor))
-        || !TEST_int_le(EC_GROUP_check_named_curve(gtest, 0), 0)
+        || !TEST_int_le(EC_GROUP_check_named_curve(gtest, 0, NULL), 0)
         || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, group_order,
                                              other_cofactor))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), 0)
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), 0)
         /* Check that if the cofactor is not set then it still passes */
         || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, group_order,
                                              NULL))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), nid)
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid)
         /* check that restoring the generator passes */
         || !TEST_true(EC_GROUP_set_generator(gtest, group_gen, group_order,
                                              group_cofactor))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), nid))
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid))
         goto err;
 
     /*
@@ -1704,7 +1704,7 @@ static int check_named_curve_test(int id)
      */
     ERR_set_mark();
     if (EC_GROUP_set_curve(gtest, other_p, group_a, group_b, NULL)) {
-        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0), 0))
+        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0, NULL), 0))
             goto err;
     } else {
         /* clear the error stack if EC_GROUP_set_curve() failed */
@@ -1712,7 +1712,7 @@ static int check_named_curve_test(int id)
         ERR_set_mark();
     }
     if (EC_GROUP_set_curve(gtest, group_p, other_a, group_b, NULL)) {
-        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0), 0))
+        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0, NULL), 0))
             goto err;
     } else {
         /* clear the error stack if EC_GROUP_set_curve() failed */
@@ -1720,7 +1720,7 @@ static int check_named_curve_test(int id)
         ERR_set_mark();
     }
     if (EC_GROUP_set_curve(gtest, group_p, group_a, other_b, NULL)) {
-        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0), 0))
+        if (!TEST_int_le(EC_GROUP_check_named_curve(gtest, 0, NULL), 0))
             goto err;
     } else {
         /* clear the error stack if EC_GROUP_set_curve() failed */
@@ -1731,7 +1731,7 @@ static int check_named_curve_test(int id)
 
     /* Check that restoring the curve parameters passes */
     if (!TEST_true(EC_GROUP_set_curve(gtest, group_p, group_a, group_b, NULL))
-        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0), nid))
+        || !TEST_int_eq(EC_GROUP_check_named_curve(gtest, 0, NULL), nid))
         goto err;
 
     ret = 1;
@@ -1778,7 +1778,7 @@ static int check_named_curve_lookup_test(int id)
     if (!TEST_ptr(g = EC_GROUP_new_from_ecparameters(p)))
         goto err;
 
-    if (!TEST_int_gt(rv = EC_GROUP_check_named_curve(g, 0), 0))
+    if (!TEST_int_gt(rv = EC_GROUP_check_named_curve(g, 0, NULL), 0))
         goto err;
     if (rv != nid) {
         /*
diff --git a/util/libcrypto.num b/util/libcrypto.num
index e823aba5cf..c99a69ab22 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4702,3 +4702,7 @@ ERR_set_error                           4811	3_0_0	EXIST::FUNCTION:
 ERR_vset_error                          4812	3_0_0	EXIST::FUNCTION:
 X509_get0_authority_issuer              4813	3_0_0	EXIST::FUNCTION:
 X509_get0_authority_serial              4814	3_0_0	EXIST::FUNCTION:
+EC_GROUP_new_ex                         4815	3_0_0	EXIST::FUNCTION:EC
+EC_GROUP_new_by_curve_name_ex           4816	3_0_0	EXIST::FUNCTION:EC
+EC_KEY_new_ex                           4817	3_0_0	EXIST::FUNCTION:EC
+EC_KEY_new_by_curve_name_ex             4818	3_0_0	EXIST::FUNCTION:EC


More information about the openssl-commits mailing list