[openssl] master update

Dr. Paul Dale pauli at openssl.org
Sun Mar 29 10:31:26 UTC 2020


The branch master has been updated
       via  20c98cd45399423f760dbd75d8912769c6b7b10e (commit)
       via  6d4e6009d27712a405e1e3a4c33fb8a8566f134a (commit)
       via  be19d3caf0724b786ecc97ec4207c07cff63c745 (commit)
       via  110bff618b5bd3c700f2f0a290612ca642672ce6 (commit)
      from  9e885a707d604e9528b5491b78fb9c00f41193fc (commit)


- Log -----------------------------------------------------------------
commit 20c98cd45399423f760dbd75d8912769c6b7b10e
Author: Pauli <paul.dale at oracle.com>
Date:   Fri Mar 27 10:33:46 2020 +1000

    Param builder: Remove the static size limit.
    
    Prior to this, the param builder had a statically sized array internally.
    This changes it so that it uses a stack instead.
    
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/11390)

commit 6d4e6009d27712a405e1e3a4c33fb8a8566f134a
Author: Pauli <paul.dale at oracle.com>
Date:   Thu Mar 26 09:28:01 2020 +1000

    Param build: make structures opaque.
    
    Since this is public, it is best to make the underlying structure opaque.
    This means converting from stack allocation to dynamic allocation for all
    usages.
    
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/11390)

commit be19d3caf0724b786ecc97ec4207c07cff63c745
Author: Pauli <paul.dale at oracle.com>
Date:   Tue Mar 24 15:08:00 2020 +1000

    NEWS: note OSSL_PARAM_BLD API as public.
    
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/11390)

commit 110bff618b5bd3c700f2f0a290612ca642672ce6
Author: Pauli <paul.dale at oracle.com>
Date:   Tue Mar 24 14:58:57 2020 +1000

    Param builder: make the OSSL_PARAM_BLD APIs public.
    
    The catalyst for this is the difficult of passing BNs through the other
    OSSL_PARAM APIs.
    
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/11390)

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

Summary of changes:
 CHANGES.md                                         |   8 ++
 NEWS.md                                            |   1 +
 crypto/dh/dh_ameth.c                               |  37 +++---
 crypto/dsa/dsa_ameth.c                             |  34 +++---
 crypto/ec/ec_ameth.c                               |  23 ++--
 crypto/ec/ecx_meth.c                               |  16 +--
 crypto/param_build.c                               | 129 +++++++++++++++-----
 crypto/rsa/rsa_ameth.c                             |  33 +++---
 crypto/rsa/rsa_lib.c                               |  16 ++-
 .../OSSL_PARAM_BLD.pod}                            | 130 ++++++++++-----------
 include/internal/param_build.h                     |  76 ------------
 include/openssl/param_build.h                      |  49 ++++++++
 include/openssl/types.h                            |   1 +
 providers/fips/fipsprov.c                          |  62 +++++-----
 providers/implementations/keymgmt/dh_kmgmt.c       |  27 +++--
 providers/implementations/keymgmt/dsa_kmgmt.c      |  30 ++---
 providers/implementations/keymgmt/ec_kmgmt.c       |  30 ++---
 providers/implementations/keymgmt/ecx_kmgmt.c      |  26 +++--
 providers/implementations/keymgmt/rsa_kmgmt.c      |  25 ++--
 test/evp_pkey_provided_test.c                      |  19 +--
 test/param_build_test.c                            |  96 +++++++++++----
 util/libcrypto.num                                 |  20 ++++
 22 files changed, 518 insertions(+), 370 deletions(-)
 rename doc/{internal/man3/ossl_param_bld_init.pod => man3/OSSL_PARAM_BLD.pod} (52%)
 delete mode 100644 include/internal/param_build.h
 create mode 100644 include/openssl/param_build.h

diff --git a/CHANGES.md b/CHANGES.md
index 82c186a6cd..8f7d7ee195 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -24,6 +24,14 @@ OpenSSL 3.0
 
 ### Changes between 1.1.1 and 3.0 [xx XXX xxxx] ###
 
+ * Added OSSL_PARAM_BLD to the public interface.  This allows OSSL_PARAM
+   arrays to be more easily constructed via a series of utility functions.
+   Create a parameter builder using OSSL_PARAM_BLD_new(), add parameters using
+   the various push functions and finally convert to a passable OSSL_PARAM
+   array using OSSL_PARAM_BLD_to_param().
+
+   * Paul Dale *
+
  * EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_DH(), and
    EVP_PKEY_get0_EC_KEY() can now handle EVP_PKEYs with provider side
    internal keys, if they correspond to one of those built in types.
diff --git a/NEWS.md b/NEWS.md
index 10a38b2aaf..9f29a59323 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -31,6 +31,7 @@ OpenSSL 3.0
   * enable-crypto-mdebug and enable-crypto-mdebug-backtrace were mostly
     disabled; the project uses address sanitize/leak-detect instead.
   * Added OSSL_SERIALIZER, a generic serializer API.
+  * Added OSSL_PARAM_BLD, an easier to use API to OSSL_PARAM.
   * Added error raising macros, ERR_raise() and ERR_raise_data().
   * Deprecated ERR_put_error().
   * Added OSSL_PROVIDER_available(), to check provider availibility.
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c
index d0eaceccb4..86e78aaf6c 100644
--- a/crypto/dh/dh_ameth.c
+++ b/crypto/dh/dh_ameth.c
@@ -24,7 +24,7 @@
 #include "crypto/evp.h"
 #include <openssl/cms.h>
 #include <openssl/core_names.h>
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "internal/ffc.h"
 
 /*
@@ -494,13 +494,13 @@ static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
                              EVP_KEYMGMT *to_keymgmt)
 {
     DH *dh = from->pkey.dh;
-    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM_BLD *tmpl;
     const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh);
     const BIGNUM *pub_key = DH_get0_pub_key(dh);
     const BIGNUM *priv_key = DH_get0_priv_key(dh);
-    OSSL_PARAM *params;
+    OSSL_PARAM *params = NULL;
     int selection = 0;
-    int rv;
+    int rv = 0;
 
     /*
      * If the DH method is foreign, then we can't be sure of anything, and
@@ -512,35 +512,38 @@ static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     if (p == NULL || g == NULL)
         return 0;
 
-    ossl_param_bld_init(&tmpl);
-    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p)
-        || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g))
+    tmpl = OSSL_PARAM_BLD_new();
+    if (tmpl == NULL)
         return 0;
+    if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
+        || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g))
+        goto err;
     if (q != NULL) {
-        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
-            return 0;
+        if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
+            goto err;
     }
     selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
     if (pub_key != NULL) {
-        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
-            return 0;
+        if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
+            goto err;
         selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
     }
     if (priv_key != NULL) {
-        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
+        if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
                                     priv_key))
-            return 0;
+            goto err;
         selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
     }
 
-    if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
-        return 0;
+    if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
+        goto err;
 
     /* We export, the provider imports */
     rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
 
-    ossl_param_bld_free(params);
-
+    OSSL_PARAM_BLD_free_params(params);
+err:
+    OSSL_PARAM_BLD_free(tmpl);
     return rv;
 }
 
diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c
index 53daf33d30..cc72189cdb 100644
--- a/crypto/dsa/dsa_ameth.c
+++ b/crypto/dsa/dsa_ameth.c
@@ -23,7 +23,7 @@
 #include "crypto/asn1.h"
 #include "crypto/dsa.h"
 #include "crypto/evp.h"
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "internal/ffc.h"
 #include "dsa_local.h"
 
@@ -523,13 +523,13 @@ static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
                               EVP_KEYMGMT *to_keymgmt)
 {
     DSA *dsa = from->pkey.dsa;
-    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM_BLD *tmpl;
     const BIGNUM *p = DSA_get0_p(dsa), *g = DSA_get0_g(dsa);
     const BIGNUM *q = DSA_get0_q(dsa), *pub_key = DSA_get0_pub_key(dsa);
     const BIGNUM *priv_key = DSA_get0_priv_key(dsa);
     OSSL_PARAM *params;
     int selection = 0;
-    int rv;
+    int rv = 0;
 
     /*
      * If the DSA method is foreign, then we can't be sure of anything, and
@@ -541,33 +541,37 @@ static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     if (p == NULL || q == NULL || g == NULL)
         return 0;
 
-    ossl_param_bld_init(&tmpl);
-    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p)
-        || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q)
-        || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g))
+    tmpl = OSSL_PARAM_BLD_new();
+    if (tmpl == NULL)
         return 0;
+
+    if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
+        || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q)
+        || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g))
+        goto err;
     selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
     if (pub_key != NULL) {
-        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PUB_KEY,
+        if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
                                     pub_key))
-            return 0;
+            goto err;
         selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
     }
     if (priv_key != NULL) {
-        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
+        if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
                                     priv_key))
-            return 0;
+            goto err;
         selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
     }
 
-    if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
-        return 0;
+    if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
+        goto err;
 
     /* We export, the provider imports */
     rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
 
-    ossl_param_bld_free(params);
-
+    OSSL_PARAM_BLD_free_params(params);
+err:
+    OSSL_PARAM_BLD_free(tmpl);
     return rv;
 }
 
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
index f3812e46b5..65af8cc3c5 100644
--- a/crypto/ec/ec_ameth.c
+++ b/crypto/ec/ec_ameth.c
@@ -23,7 +23,7 @@
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
 #include <openssl/core_names.h>
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "ec_local.h"
 
 #ifndef OPENSSL_NO_CMS
@@ -611,7 +611,7 @@ int ecparams_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl)
         if ((curve_name = OBJ_nid2sn(curve_nid)) == NULL)
             return 0;
 
-        if (!ossl_param_bld_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0))
+        if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0))
             return 0;
     }
 
@@ -626,7 +626,7 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     const EC_GROUP *ecg = NULL;
     unsigned char *pub_key_buf = NULL;
     size_t pub_key_buflen;
-    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM_BLD *tmpl;
     OSSL_PARAM *params = NULL;
     const BIGNUM *priv_key = NULL;
     const EC_POINT *pub_point = NULL;
@@ -645,10 +645,12 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     if (EC_KEY_get_method(eckey) != EC_KEY_OpenSSL())
         return 0;
 
-    ossl_param_bld_init(&tmpl);
+    tmpl = OSSL_PARAM_BLD_new();
+    if (tmpl == NULL)
+        return 0;
 
     /* export the domain parameters */
-    if (!ecparams_to_params(eckey, &tmpl))
+    if (!ecparams_to_params(eckey, tmpl))
         goto err;
     selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
 
@@ -660,7 +662,7 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
         if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point,
                                                  POINT_CONVERSION_COMPRESSED,
                                                  &pub_key_buf, NULL)) == 0
-            || !ossl_param_bld_push_octet_string(&tmpl,
+            || !OSSL_PARAM_BLD_push_octet_string(tmpl,
                                                  OSSL_PKEY_PARAM_PUB_KEY,
                                                  pub_key_buf,
                                                  pub_key_buflen))
@@ -711,7 +713,7 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
             goto err;
 
         sz = (ecbits + 7 ) / 8;
-        if (!ossl_param_bld_push_BN_pad(&tmpl,
+        if (!OSSL_PARAM_BLD_push_BN_pad(tmpl,
                                         OSSL_PKEY_PARAM_PRIV_KEY,
                                         priv_key, sz))
             goto err;
@@ -726,20 +728,21 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
             (EC_KEY_get_flags(eckey) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
 
         /* Export the ECDH_COFACTOR_MODE parameter */
-        if (!ossl_param_bld_push_int(&tmpl,
+        if (!OSSL_PARAM_BLD_push_int(tmpl,
                                      OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
                                      ecdh_cofactor_mode))
             goto err;
         selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
     }
 
-    params = ossl_param_bld_to_param(&tmpl);
+    params = OSSL_PARAM_BLD_to_param(tmpl);
 
     /* We export, the provider imports */
     rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
 
  err:
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free(tmpl);
+    OSSL_PARAM_BLD_free_params(params);
     OPENSSL_free(pub_key_buf);
     return rv;
 }
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index 97d1b13f5a..c142552b29 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -19,7 +19,7 @@
 #include <openssl/ec.h>
 #include <openssl/rand.h>
 #include <openssl/core_names.h>
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
 #include "crypto/ecx.h"
@@ -409,34 +409,36 @@ static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
                               EVP_KEYMGMT *to_keymgmt)
 {
     const ECX_KEY *key = from->pkey.ecx;
-    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
     OSSL_PARAM *params = NULL;
     int selection = 0;
     int rv = 0;
 
-    ossl_param_bld_init(&tmpl);
+    if (tmpl == NULL)
+        return 0;
 
     /* A key must at least have a public part */
-    if (!ossl_param_bld_push_octet_string(&tmpl, OSSL_PKEY_PARAM_PUB_KEY,
+    if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
                                           key->pubkey, key->keylen))
         goto err;
     selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
 
     if (key->privkey != NULL) {
-        if (!ossl_param_bld_push_octet_string(&tmpl,
+        if (!OSSL_PARAM_BLD_push_octet_string(tmpl,
                                               OSSL_PKEY_PARAM_PRIV_KEY,
                                               key->privkey, key->keylen))
             goto err;
         selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
     }
 
-    params = ossl_param_bld_to_param(&tmpl);
+    params = OSSL_PARAM_BLD_to_param(tmpl);
 
     /* We export, the provider imports */
     rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
 
  err:
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free(tmpl);
+    OSSL_PARAM_BLD_free_params(params);
     return rv;
 }
 
diff --git a/crypto/param_build.c b/crypto/param_build.c
index 7c3b1a597a..4f999678cb 100644
--- a/crypto/param_build.c
+++ b/crypto/param_build.c
@@ -12,11 +12,44 @@
 #include <openssl/err.h>
 #include <openssl/cryptoerr.h>
 #include <openssl/params.h>
+#include <openssl/types.h>
+#include <openssl/safestack.h>
 #include "internal/cryptlib.h"
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 
+/*
+ * Special internal param type to indicate the end of an allocate OSSL_PARAM
+ * array.
+ */
 #define OSSL_PARAM_ALLOCATED_END    127
 
+typedef struct {
+    const char *key;
+    int type;
+    int secure;
+    size_t size;
+    size_t alloc_blocks;
+    const BIGNUM *bn;
+    const void *string;
+    union {
+        /*
+         * These fields are never directly addressed, but their sizes are
+         * imporant so that all native types can be copied here without overrun.
+         */
+        ossl_intmax_t i;
+        ossl_uintmax_t u;
+        double d;
+    } num;
+} OSSL_PARAM_BLD_DEF;
+
+DEFINE_STACK_OF(OSSL_PARAM_BLD_DEF)
+
+struct ossl_param_bld_st {
+    size_t total_blocks;
+    size_t secure_blocks;
+    STACK_OF(OSSL_PARAM_BLD_DEF) *params;
+};
+
 typedef union {
     OSSL_UNION_ALIGN;
 } OSSL_PARAM_BLD_BLOCK;
@@ -32,14 +65,12 @@ static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key,
                                       int size, size_t alloc, int type,
                                       int secure)
 {
-    OSSL_PARAM_BLD_DEF *pd;
+    OSSL_PARAM_BLD_DEF *pd = OPENSSL_zalloc(sizeof(*pd));
 
-    if (bld->curr >= OSSL_PARAM_BLD_MAX) {
-        CRYPTOerr(CRYPTO_F_PARAM_PUSH, CRYPTO_R_TOO_MANY_RECORDS);
+    if (pd == NULL) {
+        CRYPTOerr(CRYPTO_F_PARAM_PUSH, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
-    pd = bld->params + bld->curr++;
-    memset(pd, 0, sizeof(*pd));
     pd->key = key;
     pd->type = type;
     pd->size = size;
@@ -48,6 +79,10 @@ static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key,
         bld->secure_blocks += pd->alloc_blocks;
     else
         bld->total_blocks += pd->alloc_blocks;
+    if (sk_OSSL_PARAM_BLD_DEF_push(bld->params, pd) <= 0) {
+        OPENSSL_free(pd);
+        pd = NULL;
+    }
     return pd;
 }
 
@@ -66,83 +101,107 @@ static int param_push_num(OSSL_PARAM_BLD *bld, const char *key,
     return 1;
 }
 
-void ossl_param_bld_init(OSSL_PARAM_BLD *bld)
+OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void)
+{
+    OSSL_PARAM_BLD *r = OPENSSL_zalloc(sizeof(OSSL_PARAM_BLD));
+
+    if (r != NULL) {
+        r->params = sk_OSSL_PARAM_BLD_DEF_new_null();
+        if (r->params == NULL) {
+            OPENSSL_free(r);
+            r = NULL;
+        }
+    }
+    return r;
+}
+
+static void free_all_params(OSSL_PARAM_BLD *bld)
+{
+    int i, n = sk_OSSL_PARAM_BLD_DEF_num(bld->params);
+
+    for (i = 0; i < n; i++)
+        OPENSSL_free(sk_OSSL_PARAM_BLD_DEF_pop(bld->params));
+}
+
+void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld)
 {
-    memset(bld, 0, sizeof(*bld));
+    free_all_params(bld);
+    sk_OSSL_PARAM_BLD_DEF_free(bld->params);
+    OPENSSL_free(bld);
 }
 
-int ossl_param_bld_push_int(OSSL_PARAM_BLD *bld, const char *key, int num)
+int OSSL_PARAM_BLD_push_int(OSSL_PARAM_BLD *bld, const char *key, int num)
 {
     return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
 }
 
-int ossl_param_bld_push_uint(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_uint(OSSL_PARAM_BLD *bld, const char *key,
                              unsigned int num)
 {
     return param_push_num(bld, key, &num, sizeof(num),
                           OSSL_PARAM_UNSIGNED_INTEGER);
 }
 
-int ossl_param_bld_push_long(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_long(OSSL_PARAM_BLD *bld, const char *key,
                              long int num)
 {
     return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
 }
 
-int ossl_param_bld_push_ulong(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_ulong(OSSL_PARAM_BLD *bld, const char *key,
                               unsigned long int num)
 {
     return param_push_num(bld, key, &num, sizeof(num),
                           OSSL_PARAM_UNSIGNED_INTEGER);
 }
 
-int ossl_param_bld_push_int32(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_int32(OSSL_PARAM_BLD *bld, const char *key,
                               int32_t num)
 {
     return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
 }
 
-int ossl_param_bld_push_uint32(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_uint32(OSSL_PARAM_BLD *bld, const char *key,
                                uint32_t num)
 {
     return param_push_num(bld, key, &num, sizeof(num),
                           OSSL_PARAM_UNSIGNED_INTEGER);
 }
 
-int ossl_param_bld_push_int64(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_int64(OSSL_PARAM_BLD *bld, const char *key,
                               int64_t num)
 {
     return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
 }
 
-int ossl_param_bld_push_uint64(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_uint64(OSSL_PARAM_BLD *bld, const char *key,
                                uint64_t num)
 {
     return param_push_num(bld, key, &num, sizeof(num),
                           OSSL_PARAM_UNSIGNED_INTEGER);
 }
 
-int ossl_param_bld_push_size_t(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_size_t(OSSL_PARAM_BLD *bld, const char *key,
                                size_t num)
 {
     return param_push_num(bld, key, &num, sizeof(num),
                           OSSL_PARAM_UNSIGNED_INTEGER);
 }
 
-int ossl_param_bld_push_double(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_double(OSSL_PARAM_BLD *bld, const char *key,
                                double num)
 {
     return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_REAL);
 }
 
-int ossl_param_bld_push_BN(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key,
                            const BIGNUM *bn)
 {
-    return ossl_param_bld_push_BN_pad(bld, key, bn,
+    return OSSL_PARAM_BLD_push_BN_pad(bld, key, bn,
                                       bn == NULL ? 0 : BN_num_bytes(bn));
 }
 
-int ossl_param_bld_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
                                const BIGNUM *bn, size_t sz)
 {
     int n, secure = 0;
@@ -168,7 +227,7 @@ int ossl_param_bld_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
     return 1;
 }
 
-int ossl_param_bld_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
                                     const char *buf, size_t bsize)
 {
     OSSL_PARAM_BLD_DEF *pd;
@@ -187,7 +246,7 @@ int ossl_param_bld_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
     return 1;
 }
 
-int ossl_param_bld_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
                                  char *buf, size_t bsize)
 {
     OSSL_PARAM_BLD_DEF *pd;
@@ -206,7 +265,7 @@ int ossl_param_bld_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
     return 1;
 }
 
-int ossl_param_bld_push_octet_string(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key,
                                      const void *buf, size_t bsize)
 {
     OSSL_PARAM_BLD_DEF *pd;
@@ -223,7 +282,7 @@ int ossl_param_bld_push_octet_string(OSSL_PARAM_BLD *bld, const char *key,
     return 1;
 }
 
-int ossl_param_bld_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key,
+int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key,
                                   void *buf, size_t bsize)
 {
     OSSL_PARAM_BLD_DEF *pd;
@@ -244,12 +303,12 @@ static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param,
                                      OSSL_PARAM_BLD_BLOCK *blk,
                                      OSSL_PARAM_BLD_BLOCK *secure)
 {
-    size_t i;
+    int i, num = sk_OSSL_PARAM_BLD_DEF_num(bld->params);
     OSSL_PARAM_BLD_DEF *pd;
     void *p;
 
-    for (i = 0; i < bld->curr; i++) {
-        pd = bld->params + i;
+    for (i = 0; i < num; i++) {
+        pd = sk_OSSL_PARAM_BLD_DEF_value(bld->params, i);
         param[i].key = pd->key;
         param[i].data_type = pd->type;
         param[i].data_size = pd->size;
@@ -288,11 +347,12 @@ static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param,
     return param + i;
 }
 
-OSSL_PARAM *ossl_param_bld_to_param(OSSL_PARAM_BLD *bld)
+OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld)
 {
     OSSL_PARAM_BLD_BLOCK *blk, *s = NULL;
     OSSL_PARAM *params, *last;
-    const size_t p_blks = bytes_to_blocks((1 + bld->curr) * sizeof(*params));
+    const int num = sk_OSSL_PARAM_BLD_DEF_num(bld->params);
+    const size_t p_blks = bytes_to_blocks((1 + num) * sizeof(*params));
     const size_t total = ALIGN_SIZE * (p_blks + bld->total_blocks);
     const size_t ss = ALIGN_SIZE * bld->secure_blocks;
 
@@ -301,12 +361,14 @@ OSSL_PARAM *ossl_param_bld_to_param(OSSL_PARAM_BLD *bld)
         if (s == NULL) {
             CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_TO_PARAM,
                       CRYPTO_R_SECURE_MALLOC_FAILURE);
+            OPENSSL_free(bld);
             return NULL;
         }
     }
     params = OPENSSL_malloc(total);
     if (params == NULL) {
         CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_TO_PARAM, ERR_R_MALLOC_FAILURE);
+        OPENSSL_free(bld);
         OPENSSL_secure_free(s);
         return NULL;
     }
@@ -315,10 +377,15 @@ OSSL_PARAM *ossl_param_bld_to_param(OSSL_PARAM_BLD *bld)
     last->data_size = ss;
     last->data = s;
     last->data_type = OSSL_PARAM_ALLOCATED_END;
+
+    /* Reset builder for reuse */
+    bld->total_blocks = 0;
+    bld->secure_blocks = 0;
+    free_all_params(bld);
     return params;
 }
 
-void ossl_param_bld_free(OSSL_PARAM *params)
+void OSSL_PARAM_BLD_free_params(OSSL_PARAM *params)
 {
     if (params != NULL) {
         OSSL_PARAM *p;
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 58341a928a..ec8df4a718 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -20,7 +20,7 @@
 #include <openssl/bn.h>
 #include <openssl/cms.h>
 #include <openssl/core_names.h>
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
 #include "crypto/rsa.h"
@@ -1084,7 +1084,7 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
                               EVP_KEYMGMT *to_keymgmt)
 {
     RSA *rsa = from->pkey.rsa;
-    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
     const BIGNUM *n = RSA_get0_n(rsa), *e = RSA_get0_e(rsa);
     const BIGNUM *d = RSA_get0_d(rsa);
     STACK_OF(BIGNUM_const) *primes = NULL, *exps = NULL, *coeffs = NULL;
@@ -1093,23 +1093,23 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     int selection = 0;
     int rv = 0;
 
+    if (tmpl == NULL)
+        return 0;
     /*
      * If the RSA method is foreign, then we can't be sure of anything, and
      * can therefore not export or pretend to export.
      */
     if (RSA_get_method(rsa) != RSA_PKCS1_OpenSSL())
-        return 0;
+        goto err;
 
     /* Public parameters must always be present */
     if (n == NULL || e == NULL)
         goto err;
 
-    ossl_param_bld_init(&tmpl);
-
     /* |e| and |n| are always present */
-    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_E, e))
+    if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, e))
         goto err;
-    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_N, n))
+    if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, n))
         goto err;
     selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
 
@@ -1138,20 +1138,14 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
             && (numprimes < 2 || numexps < 2 || numcoeffs < 1))
             goto err;
 
-        /* assert that an OSSL_PARAM_BLD has enough space. */
-        if (!ossl_assert(/* n, e */ 2 + /* d */ 1 + /* numprimes */ 1
-                         + numprimes + numexps + numcoeffs
-                         <= OSSL_PARAM_BLD_MAX))
-            goto err;
-
-        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_D, d))
+        if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, d))
             goto err;
         selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
 
         for (i = 0; i < numprimes; i++) {
             const BIGNUM *num = sk_BIGNUM_const_value(primes, i);
 
-            if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_FACTOR,
+            if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_FACTOR,
                                         num))
                 goto err;
         }
@@ -1159,7 +1153,7 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
         for (i = 0; i < numexps; i++) {
             const BIGNUM *num = sk_BIGNUM_const_value(exps, i);
 
-            if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT,
+            if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT,
                                         num))
                 goto err;
         }
@@ -1167,13 +1161,13 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
         for (i = 0; i < numcoeffs; i++) {
             const BIGNUM *num = sk_BIGNUM_const_value(coeffs, i);
 
-            if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT,
+            if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT,
                                         num))
                 goto err;
         }
     }
 
-    if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
+    if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
         goto err;
 
     /* We export, the provider imports */
@@ -1183,7 +1177,8 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     sk_BIGNUM_const_free(primes);
     sk_BIGNUM_const_free(exps);
     sk_BIGNUM_const_free(coeffs);
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free_params(params);
+    OSSL_PARAM_BLD_free(tmpl);
     return rv;
 }
 
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index 08365708a6..e9a5b48fbc 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -20,7 +20,7 @@
 #include <openssl/evp.h>
 #include "internal/cryptlib.h"
 #include "internal/refcount.h"
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "crypto/bn.h"
 #include "crypto/evp.h"
 #include "crypto/rsa.h"
@@ -1296,7 +1296,7 @@ int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits)
 
 int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp)
 {
-    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM_BLD *tmpl;
     OSSL_PARAM *params;
     int ret;
 
@@ -1315,13 +1315,17 @@ int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp)
         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN,
                                  EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp);
 
-    ossl_param_bld_init(&tmpl);
-    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_E, pubexp)
-        || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
+    if ((tmpl = OSSL_PARAM_BLD_new()) == NULL)
         return 0;
+    if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, pubexp)
+        || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
+        OSSL_PARAM_BLD_free(tmpl);
+        return 0;
+    }
+    OSSL_PARAM_BLD_free(tmpl);
 
     ret = EVP_PKEY_CTX_set_params(ctx, params);
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free_params(params);
     return ret;
 }
 
diff --git a/doc/internal/man3/ossl_param_bld_init.pod b/doc/man3/OSSL_PARAM_BLD.pod
similarity index 52%
rename from doc/internal/man3/ossl_param_bld_init.pod
rename to doc/man3/OSSL_PARAM_BLD.pod
index 8ae0dccb73..ed82e32073 100644
--- a/doc/internal/man3/ossl_param_bld_init.pod
+++ b/doc/man3/OSSL_PARAM_BLD.pod
@@ -2,44 +2,45 @@
 
 =head1 NAME
 
-ossl_param_bld_init, ossl_param_bld_to_param,
-ossl_param_bld_free, ossl_param_bld_push_int, ossl_param_bld_push_uint,
-ossl_param_bld_push_long, ossl_param_bld_push_ulong,
-ossl_param_bld_push_int32, ossl_param_bld_push_uint32,
-ossl_param_bld_push_int64, ossl_param_bld_push_uint64,
-ossl_param_bld_push_size_t, ossl_param_bld_push_double,
-ossl_param_bld_push_BN, ossl_param_bld_push_BN_pad,
-ossl_param_bld_push_utf8_string, ossl_param_bld_push_utf8_ptr,
-ossl_param_bld_push_octet_string, ossl_param_bld_push_octet_ptr
+OSSL_PARAM_BLD, OSSL_PARAM_BLD_new, OSSL_PARAM_BLD_to_param,
+OSSL_PARAM_BLD_free_params, OSSL_PARAM_BLD_free, OSSL_PARAM_BLD_push_int,
+OSSL_PARAM_BLD_push_uint, OSSL_PARAM_BLD_push_long,
+OSSL_PARAM_BLD_push_ulong, OSSL_PARAM_BLD_push_int32,
+OSSL_PARAM_BLD_push_uint32, OSSL_PARAM_BLD_push_int64,
+OSSL_PARAM_BLD_push_uint64, OSSL_PARAM_BLD_push_size_t,
+OSSL_PARAM_BLD_push_double, OSSL_PARAM_BLD_push_BN,
+OSSL_PARAM_BLD_push_BN_pad, OSSL_PARAM_BLD_push_utf8_string,
+OSSL_PARAM_BLD_push_utf8_ptr, OSSL_PARAM_BLD_push_octet_string,
+OSSL_PARAM_BLD_push_octet_ptr
 - functions to assist in the creation of OSSL_PARAM arrays
 
 =head1 SYNOPSIS
 
 =for openssl generic
 
- #include "internal/params_build.h"
+ #include "openssl/param_build.h"
 
- #define OSSL_PARAM_BLD_MAX 10
- typedef struct { ... } OSSL_PARAM_BLD;
+ typedef struct OSSL_PARAM_BLD;
 
- void ossl_param_bld_init(OSSL_PARAM_BLD *bld);
- OSSL_PARAM *ossl_param_bld_to_param(OSSL_PARAM_BLD *bld);
- void ossl_param_bld_free(OSSL_PARAM *params);
+ OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void);
+ OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld);
+ void OSSL_PARAM_BLD_free_params(OSSL_PARAM *params);
+ void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld);
 
- int ossl_param_bld_push_TYPE(OSSL_PARAM_BLD *bld, const char *key, TYPE val);
+ int OSSL_PARAM_BLD_push_TYPE(OSSL_PARAM_BLD *bld, const char *key, TYPE val);
 
- int ossl_param_bld_push_BN(OSSL_PARAM_BLD *bld, const char *key,
+ int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key,
                             const BIGNUM *bn);
- int ossl_param_bld_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
+ int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
                                 const BIGNUM *bn, size_t sz);
 
- int ossl_param_bld_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
+ int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
                                      const char *buf, size_t bsize);
- int ossl_param_bld_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
+ int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
                                   char *buf, size_t bsize);
- int ossl_param_bld_push_octet_string(OSSL_PARAM_BLD *bld, const char *key,
+ int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key,
                                       const void *buf, size_t bsize);
- int ossl_param_bld_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key,
+ int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key,
                                    void *buf, size_t bsize);
 
 
@@ -48,17 +49,20 @@ ossl_param_bld_push_octet_string, ossl_param_bld_push_octet_ptr
 A collection of utility functions that simplify the creation of OSSL_PARAM
 arrays.  The B<I<TYPE>> names are as per L<OSSL_PARAM_int(3)>.
 
-ossl_param_bld_init() initialises the OSSL_PARAM_BLD structure so that values
-can be added.
+OSSL_PARAM_BLD_new() allocates and initialises a new OSSL_PARAM_BLD structure
+so that values can be added.
 Any existing values are cleared.
 
-ossl_param_bld_to_param() converts a built up OSSL_PARAM_BLD structure
+OSSL_PARAM_BLD_free() deallocates the memory allocates by OSSL_PARAM_BLD_new().
+
+OSSL_PARAM_BLD_to_param() converts a built up OSSL_PARAM_BLD structure
 I<bld> into an allocated OSSL_PARAM array.
 The OSSL_PARAM array and all associated storage must be freed by calling
-ossl_param_bld_free() with the functions return value.
+OSSL_PARAM_BLD_free_params() with the functions return value.
+OSSL_PARAM_BLD_free() can safely be called any time after this function is.
 
-ossl_param_bld_free() deallocates the memory allocated by
-ossl_param_bld_to_param().
+OSSL_PARAM_BLD_free_params() deallocates the memory allocated by
+OSSL_PARAM_BLD_to_param().
 
 =begin comment
 
@@ -68,65 +72,59 @@ the processor along
 
 =end comment
 
-B<ossl_param_bld_push_I<TYPE>>() are a series of functions which will create
+B<OSSL_PARAM_BLD_push_I<TYPE>>() are a series of functions which will create
 OSSL_PARAM objects of the specified size and correct type for the I<val>
 argument.
 I<val> is stored by value and an expression or auto variable can be used.
 
-ossl_param_bld_push_BN() is a function that will create an OSSL_PARAM object
+OSSL_PARAM_BLD_push_BN() is a function that will create an OSSL_PARAM object
 that holds the specified BIGNUM I<bn>.
 If I<bn> is marked as being securely allocated, its OSSL_PARAM representation
 will also be securely allocated.
 The I<bn> argument is stored by reference and the underlying BIGNUM object
-must exist until after ossl_param_bld_to_param() has been called.
+must exist until after OSSL_PARAM_BLD_to_param() has been called.
 
-ossl_param_bld_push_BN_pad() is a function that will create an OSSL_PARAM object
+OSSL_PARAM_BLD_push_BN_pad() is a function that will create an OSSL_PARAM object
 that holds the specified BIGNUM I<bn>.
 The object will be padded to occupy exactly I<sz> bytes, if insufficient space
 is specified an error results.
 If I<bn> is marked as being securely allocated, its OSSL_PARAM representation
 will also be securely allocated.
 The I<bn> argument is stored by reference and the underlying BIGNUM object
-must exist until after ossl_param_bld_to_param() has been called.
+must exist until after OSSL_PARAM_BLD_to_param() has been called.
 
-ossl_param_bld_push_utf8_string() is a function that will create an OSSL_PARAM
+OSSL_PARAM_BLD_push_utf8_string() is a function that will create an OSSL_PARAM
 object that references the UTF8 string specified by I<buf>.
 If the length of the string, I<bsize>, is zero then it will be calculated.
 The string that I<buf> points to is stored by reference and must remain in
-scope until after ossl_param_bld_to_param() has been called.
+scope until after OSSL_PARAM_BLD_to_param() has been called.
 
-ossl_param_bld_push_octet_string() is a function that will create an OSSL_PARAM
+OSSL_PARAM_BLD_push_octet_string() is a function that will create an OSSL_PARAM
 object that references the octet string specified by I<buf> and <bsize>.
 The memory that I<buf> points to is stored by reference and must remain in
-scope until after ossl_param_bld_to_param() has been called.
+scope until after OSSL_PARAM_BLD_to_param() has been called.
 
-ossl_param_bld_push_utf8_ptr() is a function that will create an OSSL_PARAM
+OSSL_PARAM_BLD_push_utf8_ptr() is a function that will create an OSSL_PARAM
 object that references the UTF8 string specified by I<buf>.
 If the length of the string, I<bsize>, is zero then it will be calculated.
 The string I<buf> points to is stored by reference and must remain in
 scope until the OSSL_PARAM array is freed.
 
-ossl_param_bld_push_octet_ptr() is a function that will create an OSSL_PARAM
+OSSL_PARAM_BLD_push_octet_ptr() is a function that will create an OSSL_PARAM
 object that references the octet string specified by I<buf>.
 The memory I<buf> points to is stored by reference and must remain in
 scope until the OSSL_PARAM array is freed.
 
 =head1 RETURN VALUES
 
-ossl_param_bld_to_param() returns the allocated OSSL_PARAM array, or NULL
+OSSL_PARAM_BLD_new() returns the allocated OSSL_PARAM_BLD structure, or NULL
 on error.
 
-All of the ossl_param_bld_push_TYPE functions return 1 on success and 0
+OSSL_PARAM_BLD_to_param() returns the allocated OSSL_PARAM array, or NULL
 on error.
 
-=head1 NOTES
-
-The constant B<OSSL_PARAM_BLD_MAX> specifies the maximum number of parameters
-that can be added.
-Exceeding this will result in the push functions returning errors.
-
-The structure B<OSSL_PARAM_BLD> should be considered opaque and subject to
-change between versions.
+All of the OSSL_PARAM_BLD_push_TYPE functions return 1 on success and 0
+on error.
 
 =head1 EXAMPLES
 
@@ -143,37 +141,39 @@ For both, the predefined key variables are:
 This example shows how to create an OSSL_PARAM array that contains an RSA
 private key.
 
-    OSSL_PARAM_BLD bld;
+    OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
     OSSL_PARAM *params;
 
-    ossl_param_bld_init(&bld, &secure);
-    if (!ossl_param_bld_push_BN(&bld, "p", p)
-        || !ossl_param_bld_push_BN(&bld, "q", q)
-        || !ossl_param_bld_push_uint(&bld, "e", e)
-        || !ossl_param_bld_push_BN(&bld, "n", n)
-        || !ossl_param_bld_push_BN(&bld, "d", d)
-        || (params = ossl_param_bld_to_param(&bld)) == NULL)
+    if (bld == NULL
+        || !OSSL_PARAM_BLD_push_BN(&bld, "p", p)
+        || !OSSL_PARAM_BLD_push_BN(&bld, "q", q)
+        || !OSSL_PARAM_BLD_push_uint(&bld, "e", e)
+        || !OSSL_PARAM_BLD_push_BN(&bld, "n", n)
+        || !OSSL_PARAM_BLD_push_BN(&bld, "d", d)
+        || (params = OSSL_PARAM_BLD_to_param(&bld)) == NULL)
         goto err;
+    OSSL_PARAM_BLD_free(bld);
     /* Use params */
     ...
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free_params(params);
 
 =head2 Example 2
 
 This example shows how to create an OSSL_PARAM array that contains an RSA
 public key.
 
-    OSSL_PARAM_BLD bld;
+    OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
     OSSL_PARAM *params;
 
-    ossl_param_bld_init(&bld, &secure);
-    if (!ossl_param_bld_push_BN(&bld, "n", n)
-        || !ossl_param_bld_push_BN(&bld, "d", d)
-        || (params = ossl_param_bld_to_param(&bld)) == NULL)
+    if (nld == NULL
+        || !OSSL_PARAM_BLD_push_BN(bld, "n", n)
+        || !OSSL_PARAM_BLD_push_BN(bld, "d", d)
+        || (params = OSSL_PARAM_BLD_to_param(bld)) == NULL)
         goto err;
+    OSSL_PARAM_BLD_free(bld);
     /* Use params */
     ...
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free_params(params);
 
 =head1 SEE ALSO
 
@@ -185,7 +185,7 @@ The functions described here were all added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
-Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/include/internal/param_build.h b/include/internal/param_build.h
deleted file mode 100644
index 59104b93aa..0000000000
--- a/include/internal/param_build.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2019, Oracle and/or its affiliates.  All rights reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <openssl/params.h>
-#include <openssl/types.h>
-
-#define OSSL_PARAM_BLD_MAX 25
-
-typedef struct {
-    const char *key;
-    int type;
-    int secure;
-    size_t size;
-    size_t alloc_blocks;
-    const BIGNUM *bn;
-    const void *string;
-    union {
-        /*
-         * These fields are never directly addressed, but their sizes are
-         * imporant so that all native types can be copied here without overrun.
-         */
-        ossl_intmax_t i;
-        ossl_uintmax_t u;
-        double d;
-    } num;
-} OSSL_PARAM_BLD_DEF;
-
-typedef struct {
-    size_t curr;
-    size_t total_blocks;
-    size_t secure_blocks;
-    OSSL_PARAM_BLD_DEF params[OSSL_PARAM_BLD_MAX];
-} OSSL_PARAM_BLD;
-
-void ossl_param_bld_init(OSSL_PARAM_BLD *bld);
-OSSL_PARAM *ossl_param_bld_to_param(OSSL_PARAM_BLD *bld);
-void ossl_param_bld_free(OSSL_PARAM *params);
-
-int ossl_param_bld_push_int(OSSL_PARAM_BLD *bld, const char *key, int val);
-int ossl_param_bld_push_uint(OSSL_PARAM_BLD *bld, const char *key,
-                             unsigned int val);
-int ossl_param_bld_push_long(OSSL_PARAM_BLD *bld, const char *key,
-                             long int val);
-int ossl_param_bld_push_ulong(OSSL_PARAM_BLD *bld, const char *key,
-                              unsigned long int val);
-int ossl_param_bld_push_int32(OSSL_PARAM_BLD *bld, const char *key,
-                              int32_t val);
-int ossl_param_bld_push_uint32(OSSL_PARAM_BLD *bld, const char *key,
-                               uint32_t val);
-int ossl_param_bld_push_int64(OSSL_PARAM_BLD *bld, const char *key,
-                              int64_t val);
-int ossl_param_bld_push_uint64(OSSL_PARAM_BLD *bld, const char *key,
-                               uint64_t val);
-int ossl_param_bld_push_size_t(OSSL_PARAM_BLD *bld, const char *key,
-                               size_t val);
-int ossl_param_bld_push_double(OSSL_PARAM_BLD *bld, const char *key,
-                               double val);
-int ossl_param_bld_push_BN(OSSL_PARAM_BLD *bld, const char *key,
-                           const BIGNUM *bn);
-int ossl_param_bld_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
-                               const BIGNUM *bn, size_t sz);
-int ossl_param_bld_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
-                                    const char *buf, size_t bsize);
-int ossl_param_bld_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
-                                 char *buf, size_t bsize);
-int ossl_param_bld_push_octet_string(OSSL_PARAM_BLD *bld, const char *key,
-                                     const void *buf, size_t bsize);
-int ossl_param_bld_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key,
-                                  void *buf, size_t bsize);
diff --git a/include/openssl/param_build.h b/include/openssl/param_build.h
new file mode 100644
index 0000000000..edccd01758
--- /dev/null
+++ b/include/openssl/param_build.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates.  All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/params.h>
+#include <openssl/types.h>
+
+OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void);
+OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld);
+void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld);
+void OSSL_PARAM_BLD_free_params(OSSL_PARAM *params);
+
+int OSSL_PARAM_BLD_push_int(OSSL_PARAM_BLD *bld, const char *key, int val);
+int OSSL_PARAM_BLD_push_uint(OSSL_PARAM_BLD *bld, const char *key,
+                             unsigned int val);
+int OSSL_PARAM_BLD_push_long(OSSL_PARAM_BLD *bld, const char *key,
+                             long int val);
+int OSSL_PARAM_BLD_push_ulong(OSSL_PARAM_BLD *bld, const char *key,
+                              unsigned long int val);
+int OSSL_PARAM_BLD_push_int32(OSSL_PARAM_BLD *bld, const char *key,
+                              int32_t val);
+int OSSL_PARAM_BLD_push_uint32(OSSL_PARAM_BLD *bld, const char *key,
+                               uint32_t val);
+int OSSL_PARAM_BLD_push_int64(OSSL_PARAM_BLD *bld, const char *key,
+                              int64_t val);
+int OSSL_PARAM_BLD_push_uint64(OSSL_PARAM_BLD *bld, const char *key,
+                               uint64_t val);
+int OSSL_PARAM_BLD_push_size_t(OSSL_PARAM_BLD *bld, const char *key,
+                               size_t val);
+int OSSL_PARAM_BLD_push_double(OSSL_PARAM_BLD *bld, const char *key,
+                               double val);
+int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key,
+                           const BIGNUM *bn);
+int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
+                               const BIGNUM *bn, size_t sz);
+int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
+                                    const char *buf, size_t bsize);
+int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
+                                 char *buf, size_t bsize);
+int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key,
+                                     const void *buf, size_t bsize);
+int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key,
+                                  void *buf, size_t bsize);
diff --git a/include/openssl/types.h b/include/openssl/types.h
index e7078df6d0..6520fbfaf8 100644
--- a/include/openssl/types.h
+++ b/include/openssl/types.h
@@ -203,6 +203,7 @@ typedef struct ossl_dispatch_st OSSL_DISPATCH;
 typedef struct ossl_item_st OSSL_ITEM;
 typedef struct ossl_algorithm_st OSSL_ALGORITHM;
 typedef struct ossl_param_st OSSL_PARAM;
+typedef struct ossl_param_bld_st OSSL_PARAM_BLD;
 
 typedef int pem_password_cb (char *buf, int size, int rwflag, void *userdata);
 
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index b5bf5aa1fc..8fbb618527 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -26,7 +26,7 @@
 #include "internal/cryptlib.h"
 #include "internal/property.h"
 #include "internal/nelem.h"
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "crypto/evp.h"
 #include "prov/implementations.h"
 #include "prov/provider_ctx.h"
@@ -194,7 +194,7 @@ static int dsa_key_signature_test(OPENSSL_CTX *libctx)
     BIGNUM *p = NULL, *q = NULL, *g = NULL;
     BIGNUM *pub = NULL, *priv = NULL;
     OSSL_PARAM *params = NULL, *params_sig = NULL;
-    OSSL_PARAM_BLD bld;
+    OSSL_PARAM_BLD *bld = NULL;
     EVP_PKEY_CTX *sctx = NULL, *kctx = NULL;
     EVP_PKEY *pkey = NULL;
     unsigned char sig[64];
@@ -255,14 +255,15 @@ static int dsa_key_signature_test(OPENSSL_CTX *libctx)
         || !hextobn(dsa_priv_hex, &priv))
         goto err;
 
-    ossl_param_bld_init(&bld);
-    if (!ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_FFC_P, p)
-        || !ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_FFC_Q, q)
-        || !ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_FFC_G, g)
-        || !ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_PUB_KEY, pub)
-        || !ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_PRIV_KEY, priv))
+    bld = OSSL_PARAM_BLD_new();
+    if (bld == NULL
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p)
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q)
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g)
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub)
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv))
         goto err;
-    params = ossl_param_bld_to_param(&bld);
+    params = OSSL_PARAM_BLD_to_param(bld);
 
     /* Create a EVP_PKEY_CTX to load the DSA key into */
     kctx = EVP_PKEY_CTX_new_from_name(libctx, SN_dsa, "");
@@ -279,11 +280,10 @@ static int dsa_key_signature_test(OPENSSL_CTX *libctx)
         goto err;
 
     /* set signature parameters */
-    ossl_param_bld_init(&bld);
-    if (!ossl_param_bld_push_utf8_string(&bld, OSSL_SIGNATURE_PARAM_DIGEST,
+    if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_SIGNATURE_PARAM_DIGEST,
                                          SN_sha256,strlen(SN_sha256) + 1))
         goto err;
-    params_sig = ossl_param_bld_to_param(&bld);
+    params_sig = OSSL_PARAM_BLD_to_param(bld);
     if (EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0)
         goto err;
 
@@ -293,8 +293,9 @@ static int dsa_key_signature_test(OPENSSL_CTX *libctx)
         goto err;
     ret = 1;
 err:
-    ossl_param_bld_free(params);
-    ossl_param_bld_free(params_sig);
+    OSSL_PARAM_BLD_free_params(params);
+    OSSL_PARAM_BLD_free_params(params_sig);
+    OSSL_PARAM_BLD_free(bld);
     BN_free(p);
     BN_free(q);
     BN_free(g);
@@ -320,7 +321,7 @@ static int dh_key_exchange_test(OPENSSL_CTX *libctx)
     OSSL_PARAM *params_peer = NULL;
     unsigned char secret[256];
     size_t secret_len, kat_secret_len = 0;
-    OSSL_PARAM_BLD bld;
+    OSSL_PARAM_BLD *bld = NULL;
 
     /* DH KAT */
     static const char *dh_p_hex[] = {
@@ -404,23 +405,23 @@ static int dh_key_exchange_test(OPENSSL_CTX *libctx)
         || !hextobin(dh_secret_exptd_hex, &kat_secret, &kat_secret_len))
         goto err;
 
-    ossl_param_bld_init(&bld);
-    if (!ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_FFC_P, p)
-        || !ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_FFC_Q, q)
-        || !ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_FFC_G, g)
-        || !ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_PUB_KEY, pub)
-        || !ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_PRIV_KEY, priv))
+    bld = OSSL_PARAM_BLD_new();
+    if (bld == NULL
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p)
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q)
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g)
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub)
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv))
         goto err;
-    params = ossl_param_bld_to_param(&bld);
+    params = OSSL_PARAM_BLD_to_param(bld);
 
-    ossl_param_bld_init(&bld);
-    if (!ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_FFC_P, p)
-        || !ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_FFC_Q, q)
-        || !ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_FFC_G, g)
-        || !ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_PUB_KEY, pub_peer))
+    if (!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p)
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q)
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g)
+        || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub_peer))
         goto err;
 
-    params_peer = ossl_param_bld_to_param(&bld);
+    params_peer = OSSL_PARAM_BLD_to_param(bld);
     if (params == NULL || params_peer == NULL)
         goto err;
 
@@ -450,8 +451,9 @@ static int dh_key_exchange_test(OPENSSL_CTX *libctx)
         goto err;
     ret = 1;
 err:
-    ossl_param_bld_free(params_peer);
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free(bld);
+    OSSL_PARAM_BLD_free_params(params_peer);
+    OSSL_PARAM_BLD_free_params(params);
     BN_free(p);
     BN_free(q);
     BN_free(g);
diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c
index 4ec48feee7..6514d8f066 100644
--- a/providers/implementations/keymgmt/dh_kmgmt.c
+++ b/providers/implementations/keymgmt/dh_kmgmt.c
@@ -22,7 +22,7 @@
 #include "prov/providercommon.h"
 #include "prov/provider_ctx.h"
 #include "crypto/dh.h"
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 
 static OSSL_OP_keymgmt_new_fn dh_newdata;
 static OSSL_OP_keymgmt_free_fn dh_freedata;
@@ -48,10 +48,10 @@ static int domparams_to_params(DH *dh, OSSL_PARAM_BLD *tmpl)
 
     DH_get0_pqg(dh, &dh_p, NULL, &dh_g);
     if (dh_p != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, dh_p))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, dh_p))
         return 0;
     if (dh_g != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, dh_g))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, dh_g))
         return 0;
 
     return 1;
@@ -68,10 +68,10 @@ static int key_to_params(DH *dh, OSSL_PARAM_BLD *tmpl)
 
     DH_get0_key(dh, &pub_key, &priv_key);
     if (priv_key != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, priv_key))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, priv_key))
         return 0;
     if (pub_key != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
         return 0;
 
     return 1;
@@ -148,26 +148,31 @@ static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
                      void *cbarg)
 {
     DH *dh = keydata;
-    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM_BLD *tmpl;
     OSSL_PARAM *params = NULL;
     int ok = 1;
 
     if (dh == NULL)
         return 0;
 
-    ossl_param_bld_init(&tmpl);
+    tmpl = OSSL_PARAM_BLD_new();
+    if (tmpl == NULL)
+        return 0;
 
     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
-        ok = ok && domparams_to_params(dh, &tmpl);
+        ok = ok && domparams_to_params(dh, tmpl);
     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
-        ok = ok && key_to_params(dh, &tmpl);
+        ok = ok && key_to_params(dh, tmpl);
 
     if (!ok
-        || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
+        || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
+        OSSL_PARAM_BLD_free(tmpl);
         return 0;
+    }
+    OSSL_PARAM_BLD_free(tmpl);
 
     ok = param_cb(params, cbarg);
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free_params(params);
     return ok;
 }
 
diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c
index 080ba743da..78edcaa9d4 100644
--- a/providers/implementations/keymgmt/dsa_kmgmt.c
+++ b/providers/implementations/keymgmt/dsa_kmgmt.c
@@ -21,7 +21,7 @@
 #include "prov/providercommon.h"
 #include "prov/provider_ctx.h"
 #include "crypto/dsa.h"
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 
 static OSSL_OP_keymgmt_new_fn dsa_newdata;
 static OSSL_OP_keymgmt_free_fn dsa_freedata;
@@ -48,13 +48,13 @@ static int domparams_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl)
 
     DSA_get0_pqg(dsa, &dsa_p, &dsa_q, &dsa_g);
     if (dsa_p != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, dsa_p))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, dsa_p))
         return 0;
     if (dsa_q != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, dsa_q))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, dsa_q))
         return 0;
     if (dsa_g != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, dsa_g))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, dsa_g))
         return 0;
 
     return 1;
@@ -71,10 +71,10 @@ static int key_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl)
 
     DSA_get0_key(dsa, &pub_key, &priv_key);
     if (priv_key != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, priv_key))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, priv_key))
         return 0;
     if (pub_key != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
         return 0;
 
     return 1;
@@ -153,26 +153,26 @@ static int dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
                       void *cbarg)
 {
     DSA *dsa = keydata;
-    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
     OSSL_PARAM *params = NULL;
     int ok = 1;
 
     if (dsa == NULL)
-        return 0;
-
-    ossl_param_bld_init(&tmpl);
+        goto err;;
 
     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
-        ok = ok && domparams_to_params(dsa, &tmpl);
+        ok = ok && domparams_to_params(dsa, tmpl);
     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
-        ok = ok && key_to_params(dsa, &tmpl);
+        ok = ok && key_to_params(dsa, tmpl);
 
     if (!ok
-        || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
-        return 0;
+        || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
+        goto err;;
 
     ok = param_cb(params, cbarg);
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free_params(params);
+err:
+    OSSL_PARAM_BLD_free(tmpl);
     return ok;
 }
 
diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c
index e2cc9ca7ed..82ef3d3a67 100644
--- a/providers/implementations/keymgmt/ec_kmgmt.c
+++ b/providers/implementations/keymgmt/ec_kmgmt.c
@@ -20,7 +20,7 @@
 #include <openssl/params.h>
 #include "crypto/bn.h"
 #include "crypto/ec.h"
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
 #include "prov/provider_ctx.h"
@@ -84,7 +84,7 @@ int domparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
         if ((curve_name = ec_curve_nid2name(curve_nid)) == NULL)
             return 0;
 
-        if (!ossl_param_bld_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME,
+        if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME,
                                              curve_name, 0))
             return 0;
     }
@@ -121,7 +121,7 @@ int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, int include_private
         if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point,
                                               POINT_CONVERSION_COMPRESSED,
                                               &pub_key, NULL)) == 0
-            || !ossl_param_bld_push_octet_string(tmpl,
+            || !OSSL_PARAM_BLD_push_octet_string(tmpl,
                                                  OSSL_PKEY_PARAM_PUB_KEY,
                                                  pub_key, pub_key_len))
             goto err;
@@ -168,7 +168,7 @@ int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, int include_private
         if (ecbits <= 0)
             goto err;
         sz = (ecbits + 7 ) / 8;
-        if (!ossl_param_bld_push_BN_pad(tmpl,
+        if (!OSSL_PARAM_BLD_push_BN_pad(tmpl,
                                         OSSL_PKEY_PARAM_PRIV_KEY,
                                         priv_key, sz))
             goto err;
@@ -191,7 +191,7 @@ int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
 
     ecdh_cofactor_mode =
         (EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
-    if (!ossl_param_bld_push_int(tmpl,
+    if (!OSSL_PARAM_BLD_push_int(tmpl,
                 OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
                 ecdh_cofactor_mode))
         return 0;
@@ -312,7 +312,7 @@ int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
               void *cbarg)
 {
     EC_KEY *ec = keydata;
-    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM_BLD *tmpl;
     OSSL_PARAM *params = NULL;
     int ok = 1;
 
@@ -341,25 +341,29 @@ int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
             && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
         return 0;
 
-    ossl_param_bld_init(&tmpl);
+    tmpl = OSSL_PARAM_BLD_new();
+    if (tmpl == NULL)
+        return 0;
 
     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
-        ok = ok && domparams_to_params(ec, &tmpl);
+        ok = ok && domparams_to_params(ec, tmpl);
     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
         int include_private =
             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
 
-        ok = ok && key_to_params(ec, &tmpl, include_private);
+        ok = ok && key_to_params(ec, tmpl, include_private);
     }
     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
-        ok = ok && otherparams_to_params(ec, &tmpl);
+        ok = ok && otherparams_to_params(ec, tmpl);
 
     if (!ok
-        || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
-        return 0;
+        || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
+        goto err;
 
     ok = param_cb(params, cbarg);
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free_params(params);
+err:
+    OSSL_PARAM_BLD_free(tmpl);
     return ok;
 }
 
diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c
index 221287bff2..be11f0b85e 100644
--- a/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -11,7 +11,7 @@
 #include <openssl/core_numbers.h>
 #include <openssl/core_names.h>
 #include <openssl/params.h>
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "crypto/ecx.h"
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
@@ -95,12 +95,12 @@ static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl)
     if (key == NULL)
         return 0;
 
-    if (!ossl_param_bld_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
+    if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
                                           key->pubkey, key->keylen))
         return 0;
 
     if (key->privkey != NULL
-        && !ossl_param_bld_push_octet_string(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
+        && !OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
                                              key->privkey, key->keylen))
         return 0;
 
@@ -111,26 +111,30 @@ static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
                       void *cbarg)
 {
     ECX_KEY *key = keydata;
-    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM_BLD *tmpl;
     OSSL_PARAM *params = NULL;
     int ret;
 
     if (key == NULL)
         return 0;
 
-    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
-            && !key_to_params(key, &tmpl))
+    tmpl = OSSL_PARAM_BLD_new();
+    if (tmpl == NULL)
         return 0;
 
-    ossl_param_bld_init(&tmpl);
-    params = ossl_param_bld_to_param(&tmpl);
-    if (params == NULL) {
-        ossl_param_bld_free(params);
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
+            && !key_to_params(key, tmpl)) {
+        OSSL_PARAM_BLD_free(tmpl);
         return 0;
     }
 
+    params = OSSL_PARAM_BLD_to_param(tmpl);
+    OSSL_PARAM_BLD_free(tmpl);
+    if (params == NULL)
+        return 0;
+
     ret = param_cb(params, cbarg);
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free_params(params);
     return ret;
 }
 
diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c
index 176cf34e0a..50647eb6f5 100644
--- a/providers/implementations/keymgmt/rsa_kmgmt.c
+++ b/providers/implementations/keymgmt/rsa_kmgmt.c
@@ -21,7 +21,7 @@
 #include <openssl/evp.h>
 #include <openssl/params.h>
 #include <openssl/types.h>
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
 #include "prov/provider_ctx.h"
@@ -62,7 +62,7 @@ static int export_numbers(OSSL_PARAM_BLD *tmpl, const char *key,
     nnum = sk_BIGNUM_const_num(numbers);
 
     for (i = 0; i < nnum; i++) {
-        if (!ossl_param_bld_push_BN(tmpl, key,
+        if (!OSSL_PARAM_BLD_push_BN(tmpl, key,
                                     sk_BIGNUM_const_value(numbers, i)))
             return 0;
     }
@@ -85,13 +85,13 @@ static int key_to_params(RSA *rsa, OSSL_PARAM_BLD *tmpl)
     rsa_get0_all_params(rsa, factors, exps, coeffs);
 
     if (rsa_n != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, rsa_n))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, rsa_n))
         goto err;
     if (rsa_e != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, rsa_e))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, rsa_e))
         goto err;
     if (rsa_d != NULL
-        && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, rsa_d))
+        && !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, rsa_d))
         goto err;
 
     if (!export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_FACTOR, factors)
@@ -175,7 +175,7 @@ static int rsa_export(void *keydata, int selection,
                       OSSL_CALLBACK *param_callback, void *cbarg)
 {
     RSA *rsa = keydata;
-    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM_BLD *tmpl;
     OSSL_PARAM *params = NULL;
     int ok = 1;
 
@@ -184,17 +184,22 @@ static int rsa_export(void *keydata, int selection,
 
     /* TODO(3.0) PSS and OAEP should bring on parameters */
 
-    ossl_param_bld_init(&tmpl);
+    tmpl = OSSL_PARAM_BLD_new();
+    if (tmpl == NULL)
+        return 0;
 
     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
-        ok = ok && key_to_params(rsa, &tmpl);
+        ok = ok && key_to_params(rsa, tmpl);
 
     if (!ok
-        || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
+        || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
+        OSSL_PARAM_BLD_free(tmpl);
         return 0;
+    }
+    OSSL_PARAM_BLD_free(tmpl);
 
     ok = param_callback(params, cbarg);
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free_params(params);
     return ok;
 }
 
diff --git a/test/evp_pkey_provided_test.c b/test/evp_pkey_provided_test.c
index 589261a060..6ba61c3cda 100644
--- a/test/evp_pkey_provided_test.c
+++ b/test/evp_pkey_provided_test.c
@@ -15,7 +15,7 @@
 #include <openssl/core_names.h>
 #include "crypto/ecx.h"
 #include "internal/nelem.h"
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "crypto/evp.h"          /* For the internal API */
 #include "testutil.h"
 
@@ -596,7 +596,7 @@ static int test_fromdata_ec(void)
     int ret = 0;
     EVP_PKEY_CTX *ctx = NULL;
     EVP_PKEY *pk = NULL, *copy_pk = NULL;
-    OSSL_PARAM_BLD bld;
+    OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
     BIGNUM *ec_priv_bn = NULL;
     OSSL_PARAM *fromdata_params = NULL;
     const char *alg = "EC";
@@ -618,22 +618,22 @@ static int test_fromdata_ec(void)
         0xdc, 0x4b, 0x4d, 0x35, 0x43, 0xe1, 0x1b, 0xad
     };
 
-    ossl_param_bld_init(&bld);
-
+    if (!TEST_ptr(bld))
+        goto err;
     if (!TEST_ptr(ec_priv_bn = BN_bin2bn(ec_priv_keydata,
                                          sizeof(ec_priv_keydata), NULL)))
         goto err;
 
-    if (ossl_param_bld_push_utf8_string(&bld, OSSL_PKEY_PARAM_EC_NAME,
+    if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_NAME,
                                         "prime256v1", 0) <= 0)
         goto err;
-    if (ossl_param_bld_push_octet_string(&bld, OSSL_PKEY_PARAM_PUB_KEY,
+    if (OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY,
                                          ec_pub_keydata,
                                          sizeof(ec_pub_keydata)) <= 0)
         goto err;
-    if (ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_PRIV_KEY, ec_priv_bn) <= 0)
+    if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, ec_priv_bn) <= 0)
         goto err;
-    if (!TEST_ptr(fromdata_params = ossl_param_bld_to_param(&bld)))
+    if (!TEST_ptr(fromdata_params = OSSL_PARAM_BLD_to_param(bld)))
         goto err;
     ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
     if (!TEST_ptr(ctx))
@@ -654,7 +654,8 @@ static int test_fromdata_ec(void)
           && test_print_key_using_serializer(alg, pk);
 err:
     BN_free(ec_priv_bn);
-    ossl_param_bld_free(fromdata_params);
+    OSSL_PARAM_BLD_free_params(fromdata_params);
+    OSSL_PARAM_BLD_free(bld);
     EVP_PKEY_free(pk);
     EVP_PKEY_free(copy_pk);
     EVP_PKEY_CTX_free(ctx);
diff --git a/test/param_build_test.c b/test/param_build_test.c
index 9ac76d0115..c5fcc70a66 100644
--- a/test/param_build_test.c
+++ b/test/param_build_test.c
@@ -10,13 +10,13 @@
 
 #include <string.h>
 #include <openssl/params.h>
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
 #include "internal/nelem.h"
 #include "testutil.h"
 
 static int template_public_test(void)
 {
-    OSSL_PARAM_BLD bld;
+    OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
     OSSL_PARAM *params = NULL, *p;
     BIGNUM *bn = NULL, *bn_res = NULL;
     int i;
@@ -28,20 +28,20 @@ static int template_public_test(void)
     const char *cutf;
     int res = 0;
 
-    ossl_param_bld_init(&bld);
-    if (!TEST_true(ossl_param_bld_push_int(&bld, "i", -6))
-        || !TEST_true(ossl_param_bld_push_long(&bld, "l", 42))
-        || !TEST_true(ossl_param_bld_push_int32(&bld, "i32", 1532))
-        || !TEST_true(ossl_param_bld_push_int64(&bld, "i64", -9999999))
-        || !TEST_true(ossl_param_bld_push_double(&bld, "d", 1.61803398875))
+    if (!TEST_ptr(bld)
+        || !TEST_true(OSSL_PARAM_BLD_push_int(bld, "i", -6))
+        || !TEST_true(OSSL_PARAM_BLD_push_long(bld, "l", 42))
+        || !TEST_true(OSSL_PARAM_BLD_push_int32(bld, "i32", 1532))
+        || !TEST_true(OSSL_PARAM_BLD_push_int64(bld, "i64", -9999999))
+        || !TEST_true(OSSL_PARAM_BLD_push_double(bld, "d", 1.61803398875))
         || !TEST_ptr(bn = BN_new())
         || !TEST_true(BN_set_word(bn, 1729))
-        || !TEST_true(ossl_param_bld_push_BN(&bld, "bignumber", bn))
-        || !TEST_true(ossl_param_bld_push_utf8_string(&bld, "utf8_s", "foo",
+        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, "bignumber", bn))
+        || !TEST_true(OSSL_PARAM_BLD_push_utf8_string(bld, "utf8_s", "foo",
                                                       sizeof("foo")))
-        || !TEST_true(ossl_param_bld_push_utf8_ptr(&bld, "utf8_p", "bar-boom",
+        || !TEST_true(OSSL_PARAM_BLD_push_utf8_ptr(bld, "utf8_p", "bar-boom",
                                                    0))
-        || !TEST_ptr(params = ossl_param_bld_to_param(&bld))
+        || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
         /* Check int */
         || !TEST_ptr(p = OSSL_PARAM_locate(params, "i"))
         || !TEST_true(OSSL_PARAM_get_int(p, &i))
@@ -95,7 +95,8 @@ static int template_public_test(void)
         goto err;
     res = 1;
 err:
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free_params(params);
+    OSSL_PARAM_BLD_free(bld);
     OPENSSL_free(utf);
     BN_free(bn);
     BN_free(bn_res);
@@ -106,7 +107,7 @@ static int template_private_test(void)
 {
     static int data1[] = { 2, 3, 5, 7, 11, 15, 17 };
     static unsigned char data2[] = { 2, 4, 6, 8, 10 };
-    OSSL_PARAM_BLD bld;
+    OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
     OSSL_PARAM *params = NULL, *p;
     unsigned int i;
     unsigned long int l;
@@ -116,20 +117,20 @@ static int template_private_test(void)
     BIGNUM *bn = NULL, *bn_res = NULL;
     int res = 0;
 
-    ossl_param_bld_init(&bld);
-    if (!TEST_true(ossl_param_bld_push_uint(&bld, "i", 6))
-        || !TEST_true(ossl_param_bld_push_ulong(&bld, "l", 42))
-        || !TEST_true(ossl_param_bld_push_uint32(&bld, "i32", 1532))
-        || !TEST_true(ossl_param_bld_push_uint64(&bld, "i64", 9999999))
-        || !TEST_true(ossl_param_bld_push_size_t(&bld, "st", 65537))
+    if (!TEST_ptr(bld)
+        || !TEST_true(OSSL_PARAM_BLD_push_uint(bld, "i", 6))
+        || !TEST_true(OSSL_PARAM_BLD_push_ulong(bld, "l", 42))
+        || !TEST_true(OSSL_PARAM_BLD_push_uint32(bld, "i32", 1532))
+        || !TEST_true(OSSL_PARAM_BLD_push_uint64(bld, "i64", 9999999))
+        || !TEST_true(OSSL_PARAM_BLD_push_size_t(bld, "st", 65537))
         || !TEST_ptr(bn = BN_secure_new())
         || !TEST_true(BN_set_word(bn, 1729))
-        || !TEST_true(ossl_param_bld_push_BN(&bld, "bignumber", bn))
-        || !TEST_true(ossl_param_bld_push_octet_string(&bld, "oct_s", data1,
+        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, "bignumber", bn))
+        || !TEST_true(OSSL_PARAM_BLD_push_octet_string(bld, "oct_s", data1,
                                                        sizeof(data1)))
-        || !TEST_true(ossl_param_bld_push_octet_ptr(&bld, "oct_p", data2,
+        || !TEST_true(OSSL_PARAM_BLD_push_octet_ptr(bld, "oct_p", data2,
                                                     sizeof(data2)))
-        || !TEST_ptr(params = ossl_param_bld_to_param(&bld))
+        || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
         /* Check unsigned int */
         || !TEST_ptr(p = OSSL_PARAM_locate(params, "i"))
         || !TEST_true(OSSL_PARAM_get_uint(p, &i))
@@ -184,15 +185,60 @@ static int template_private_test(void)
         goto err;
     res = 1;
 err:
-    ossl_param_bld_free(params);
+    OSSL_PARAM_BLD_free_params(params);
+    OSSL_PARAM_BLD_free(bld);
     BN_free(bn);
     BN_free(bn_res);
     return res;
 }
 
+static int builder_limit_test(void)
+{
+    const int n = 100;
+    char names[100][3];
+    OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
+    OSSL_PARAM *params = NULL;
+    int i, res = 0;
+
+    if (!TEST_ptr(bld))
+        goto err;
+    
+    for (i = 0; i < n; i++) {
+        names[i][0] = 'A' + (i / 26) - 1;
+        names[i][0] = 'a' + (i % 26) - 1;
+        names[i][2] = '\0';
+        if (!TEST_true(OSSL_PARAM_BLD_push_int(bld, names[i], 3 * i + 1)))
+            goto err;
+    }
+    if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)))
+        goto err;
+    /* Count the elements in the params arrary, expecting n */
+    for (i = 0; params[i].key != NULL; i++);
+    if (!TEST_int_eq(i, n))
+        goto err;
+
+    /* Verify that the build, cleared the builder structure */
+    OSSL_PARAM_BLD_free_params(params);
+    params = NULL;
+
+    if (!TEST_true(OSSL_PARAM_BLD_push_int(bld, "g", 2))
+        || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)))
+        goto err;
+    /* Count the elements in the params arrary, expecting 1 */
+    for (i = 0; params[i].key != NULL; i++);
+    if (!TEST_int_eq(i, 1))
+        goto err;
+    res = 1;
+err:
+    OSSL_PARAM_BLD_free_params(params);
+    OSSL_PARAM_BLD_free(bld);
+    return res;
+}
+
 int setup_tests(void)
 {
     ADD_TEST(template_public_test);
     ADD_TEST(template_private_test);
+    ADD_TEST(builder_limit_test);
     return 1;
 }
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 1650884ffe..fe6d69c2c5 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5000,6 +5000,26 @@ EVP_PKEY_CTX_set_rsa_keygen_primes      ?	3_0_0	EXIST::FUNCTION:RSA
 NCONF_new_with_libctx                   ?	3_0_0	EXIST::FUNCTION:
 CONF_modules_load_file_with_libctx      ?	3_0_0	EXIST::FUNCTION:
 OPENSSL_CTX_load_config                 ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_to_param                 ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_free_params              ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_int                 ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_uint                ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_long                ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_ulong               ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_int32               ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_uint32              ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_int64               ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_uint64              ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_size_t              ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_double              ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_BN                  ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_BN_pad              ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_utf8_string         ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_utf8_ptr            ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_octet_string        ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_push_octet_ptr           ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_new                      ?	3_0_0	EXIST::FUNCTION:
+OSSL_PARAM_BLD_free                     ?	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_set_type_by_keymgmt            ?	3_0_0	EXIST::FUNCTION:
 OCSP_RESPID_set_by_key_ex               ?	3_0_0	EXIST::FUNCTION:OCSP
 OCSP_RESPID_match_ex                    ?	3_0_0	EXIST::FUNCTION:OCSP


More information about the openssl-commits mailing list