[openssl] master update

Richard Levitte levitte at openssl.org
Thu Oct 17 16:07:52 UTC 2019


The branch master has been updated
       via  651101e18d66b2ae89851ce8906299e9d2a871e0 (commit)
       via  5a02d13d3e274748c695bfe19238f885489e021e (commit)
       via  29be60235b9bf86bb38f28349b405bb112250d4b (commit)
       via  c3a4fa4cb849ba300d4691154c0c12ac19d24710 (commit)
      from  b75d6310857bc44ef2851bde68a1979c18bb4807 (commit)


- Log -----------------------------------------------------------------
commit 651101e18d66b2ae89851ce8906299e9d2a871e0
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Oct 17 00:32:20 2019 +0200

    evp_keymgmt_export_to_provider(): adjust OSSL_PARAM array for transfer
    
    It may be that the OSSL_PARAM array we used for getting parameter
    values for a key had a few too many entries.  These are detected by
    their return_size == 0.  Before making second export call, we prune
    away these items so we only ask for parameters that exist.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/10190)

commit 5a02d13d3e274748c695bfe19238f885489e021e
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Oct 17 00:26:44 2019 +0200

    test/keymgmt_internal_test.c: New test of keymgmt internals
    
    This tests diverse internal KEYMGMT features.  The current existing
    test checks that evp_keymgmt_export_to_provider() passes the key data
    correctly through two instances of the default provider, and that the
    resulting numbers at the end match the initial numbers.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/10190)

commit 29be60235b9bf86bb38f28349b405bb112250d4b
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Oct 15 21:31:45 2019 +0200

    New RSA keymgmt implementation to handle import / export of RSA keys
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/10190)

commit c3a4fa4cb849ba300d4691154c0c12ac19d24710
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Oct 15 20:28:02 2019 +0200

    Added internal functions for easy getting and setting all RSA parameters.
    
    rsa_set0_all_params() is used to set all the primes, exponents and
    coefficients.  rsa_get0_all_params() is used to get all the primes,
    exponents and coefficients.
    
    "All" includes p, q, dP, dQ and qInv without making them separate.
    
    All arrays of numbers are implemented as stacks to make dynamic use
    easier.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/10190)

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

Summary of changes:
 crypto/evp/keymgmt_lib.c                           |  29 ++-
 crypto/rsa/rsa_ameth.c                             | 127 ++++++++-
 crypto/rsa/rsa_gen.c                               |   2 +
 crypto/rsa/rsa_lib.c                               | 120 +++++++++
 crypto/rsa/rsa_local.h                             |   2 +
 crypto/rsa/rsa_sp800_56b_gen.c                     |   2 +
 crypto/rsa/rsa_x931g.c                             |   2 +
 include/crypto/rsa.h                               |  21 ++
 include/openssl/core_names.h                       |  21 ++
 include/openssl/rsa.h                              |   2 +
 include/openssl/types.h                            |   4 +
 providers/defltprov.c                              |   1 +
 .../implementations/include/prov/implementations.h |   1 +
 providers/implementations/keymgmt/build.info       |   2 +
 providers/implementations/keymgmt/rsa_kmgmt.c      | 249 ++++++++++++++++++
 test/build.info                                    |   9 +-
 test/keymgmt_internal_test.c                       | 198 ++++++++++++++
 ...-test_provider.t => 02-test_internal_keymgmt.t} |   6 +-
 test/rsa_mp_test.c                                 | 290 +++++++++++++--------
 19 files changed, 965 insertions(+), 123 deletions(-)
 create mode 100644 include/crypto/rsa.h
 create mode 100644 providers/implementations/keymgmt/rsa_kmgmt.c
 create mode 100644 test/keymgmt_internal_test.c
 copy test/recipes/{04-test_provider.t => 02-test_internal_keymgmt.t} (76%)

diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c
index 87629157e2..a14decd280 100644
--- a/crypto/evp/keymgmt_lib.c
+++ b/crypto/evp/keymgmt_lib.c
@@ -37,6 +37,28 @@ static OSSL_PARAM *paramdefs_to_params(const OSSL_PARAM *paramdefs)
     return params;
 }
 
+static OSSL_PARAM *reduce_params(OSSL_PARAM *params)
+{
+    OSSL_PARAM *curr, *next;
+    size_t cnt;
+
+    for (cnt = 0, curr = next = params; next->key != NULL; next++) {
+        if (next->return_size == 0)
+            continue;
+        if (curr != next)
+            *curr = *next;
+        curr++;
+        cnt++;
+    }
+    *curr = *next;               /* Terminating record */
+    cnt++;
+
+    curr = OPENSSL_realloc(params, cnt * sizeof(*params));
+    if (curr == NULL)
+        return params;
+    return curr;
+}
+
 typedef union align_block_un {
     OSSL_UNION_ALIGN;
 } ALIGN_BLOCK;
@@ -157,10 +179,11 @@ void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
                 exportfn(pk->pkeys[j].provdata, params);
 
                 /*
-                 * Allocate space and assign 'data' to point into the
-                 * data block.
-                 * If something goes wrong, go to the next cached key.
+                 * Reduce the params by removing any entry that got return
+                 * size zero, then allocate space and assign 'data' to point
+                 * into the data block
                  */
+                params = reduce_params(params);
                 if ((data = allocate_params_space(params)) == NULL)
                     goto cont;
 
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 69e7c5ea1a..d2f976f681 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -13,8 +13,11 @@
 #include <openssl/x509.h>
 #include <openssl/bn.h>
 #include <openssl/cms.h>
+#include <openssl/core_names.h>
+#include "internal/param_build.h"
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
+#include "crypto/rsa.h"
 #include "rsa_local.h"
 
 #ifndef OPENSSL_NO_CMS
@@ -1045,6 +1048,114 @@ static int rsa_pkey_check(const EVP_PKEY *pkey)
     return RSA_check_key_ex(pkey->pkey.rsa, NULL);
 }
 
+static size_t rsa_pkey_dirty_cnt(const EVP_PKEY *pkey)
+{
+    return pkey->pkey.rsa->dirty_cnt;
+}
+
+DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
+
+static void *rsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
+                                int want_domainparams)
+{
+    RSA *rsa = pk->pkey.rsa;
+    OSSL_PARAM_BLD tmpl;
+    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;
+    int numprimes = 0, numexps = 0, numcoeffs = 0;
+    OSSL_PARAM *params = NULL;
+    void *provkey = NULL;
+
+    /*
+     * There are no domain parameters for RSA keys, or rather, they are
+     * included in the key data itself.
+     */
+    if (want_domainparams)
+        goto err;
+
+    /* Get all the primes and CRT params */
+    if ((primes = sk_BIGNUM_const_new_null()) == NULL
+        || (exps = sk_BIGNUM_const_new_null()) == NULL
+        || (coeffs = sk_BIGNUM_const_new_null()) == NULL)
+        goto err;
+
+    if (!rsa_get0_all_params(rsa, primes, exps, coeffs))
+        goto err;
+
+    /* Public parameters must always be present */
+    if (n == NULL || e == NULL)
+        goto err;
+
+    if (d != NULL) {
+        /* It's a private key, so we should have everything else too */
+        numprimes = sk_BIGNUM_const_num(primes);
+        numexps = sk_BIGNUM_const_num(exps);
+        numcoeffs = sk_BIGNUM_const_num(coeffs);
+
+        if (numprimes < 2 || numexps < 2 || numcoeffs < 1)
+            goto err;
+
+        /*
+         * assert that an OSSL_PARAM_BLD has enough space.
+         * (the current 10 places doesn't have space for multi-primes)
+         */
+        if (!ossl_assert(/* n, e */ 2 + /* d */ 1 + /* numprimes */ 1
+                         + numprimes + numexps + numcoeffs
+                         <= OSSL_PARAM_BLD_MAX))
+            goto err;
+    }
+
+    ossl_param_bld_init(&tmpl);
+    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_N, n)
+        || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_E, e))
+        goto err;
+
+    if (d != NULL) {
+        int i;
+
+        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_D, d))
+            goto err;
+
+        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,
+                                        num))
+                goto err;
+        }
+
+        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,
+                                        num))
+                goto err;
+        }
+
+        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,
+                                        num))
+                goto err;
+        }
+    }
+
+    if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
+        goto err;
+
+    /* We export, the provider imports */
+    provkey = evp_keymgmt_importkey(keymgmt, params);
+
+ err:
+    sk_BIGNUM_const_free(primes);
+    sk_BIGNUM_const_free(exps);
+    sk_BIGNUM_const_free(coeffs);
+    ossl_param_bld_free(params);
+    return provkey;
+}
+
 const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
     {
      EVP_PKEY_RSA,
@@ -1077,7 +1188,13 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
      rsa_item_verify,
      rsa_item_sign,
      rsa_sig_info_set,
-     rsa_pkey_check
+     rsa_pkey_check,
+
+     0, 0,
+     0, 0, 0, 0,
+
+     rsa_pkey_dirty_cnt,
+     rsa_pkey_export_to
     },
 
     {
@@ -1116,5 +1233,11 @@ const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = {
      rsa_item_verify,
      rsa_item_sign,
      0,
-     rsa_pkey_check
+     rsa_pkey_check,
+
+     0, 0,
+     0, 0, 0, 0,
+
+     rsa_pkey_dirty_cnt,
+     rsa_pkey_export_to
 };
diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c
index c87b709722..cb2abff6a1 100644
--- a/crypto/rsa/rsa_gen.c
+++ b/crypto/rsa/rsa_gen.c
@@ -108,6 +108,8 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
     for (i = 0; i < primes; i++)
         bitsr[i] = (i < rmd) ? quo + 1 : quo;
 
+    rsa->dirty_cnt++;
+
     /* We need the RSA components non-NULL */
     if (!rsa->n && ((rsa->n = BN_new()) == NULL))
         goto err;
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index abdabfb45a..353b9d8725 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -15,6 +15,7 @@
 #include <openssl/engine.h>
 #include <openssl/evp.h>
 #include "crypto/evp.h"
+#include "crypto/rsa.h"
 #include "rsa_local.h"
 
 RSA *RSA_new(void)
@@ -327,6 +328,7 @@ int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
         r->d = d;
         BN_set_flags(r->d, BN_FLG_CONSTTIME);
     }
+    r->dirty_cnt++;
 
     return 1;
 }
@@ -350,6 +352,7 @@ int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
         r->q = q;
         BN_set_flags(r->q, BN_FLG_CONSTTIME);
     }
+    r->dirty_cnt++;
 
     return 1;
 }
@@ -379,6 +382,7 @@ int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
         r->iqmp = iqmp;
         BN_set_flags(r->iqmp, BN_FLG_CONSTTIME);
     }
+    r->dirty_cnt++;
 
     return 1;
 }
@@ -443,6 +447,7 @@ int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
     }
 
     r->version = RSA_ASN1_VERSION_MULTI;
+    r->dirty_cnt++;
 
     return 1;
  err:
@@ -613,3 +618,118 @@ int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2)
         return -1;
      return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, p1, p2);
 }
+
+DEFINE_STACK_OF(BIGNUM)
+
+int rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes,
+                        const STACK_OF(BIGNUM) *exps,
+                        const STACK_OF(BIGNUM) *coeffs)
+{
+    STACK_OF(RSA_PRIME_INFO) *prime_infos, *old_infos = NULL;
+    int pnum;
+
+    if (primes == NULL || exps == NULL || coeffs == NULL)
+        return 0;
+
+    pnum = sk_BIGNUM_num(primes);
+    if (pnum < 2
+        || pnum != sk_BIGNUM_num(exps)
+        || pnum != sk_BIGNUM_num(coeffs) + 1)
+        return 0;
+
+    if (!RSA_set0_factors(r, sk_BIGNUM_value(primes, 0),
+                          sk_BIGNUM_value(primes, 1))
+        || !RSA_set0_crt_params(r, sk_BIGNUM_value(exps, 0),
+                                sk_BIGNUM_value(exps, 1),
+                                sk_BIGNUM_value(coeffs, 0)))
+        return 0;
+
+    old_infos = r->prime_infos;
+
+    if (pnum > 2) {
+        int i;
+
+        prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum);
+        if (prime_infos == NULL)
+            return 0;
+
+        for (i = 2; i < pnum; i++) {
+            BIGNUM *prime = sk_BIGNUM_value(primes, i);
+            BIGNUM *exp = sk_BIGNUM_value(exps, i);
+            BIGNUM *coeff = sk_BIGNUM_value(coeffs, i - 1);
+            RSA_PRIME_INFO *pinfo = NULL;
+
+            if (!ossl_assert(prime != NULL && exp != NULL && coeff != NULL))
+                goto err;
+
+            /* Using rsa_multip_info_new() is wasteful, so allocate directly */
+            if ((pinfo = OPENSSL_zalloc(sizeof(*pinfo))) == NULL) {
+                ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
+                goto err;
+            }
+
+            pinfo->r = prime;
+            pinfo->d = exp;
+            pinfo->t = coeff;
+            BN_set_flags(pinfo->r, BN_FLG_CONSTTIME);
+            BN_set_flags(pinfo->d, BN_FLG_CONSTTIME);
+            BN_set_flags(pinfo->t, BN_FLG_CONSTTIME);
+            (void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo);
+        }
+
+        r->prime_infos = prime_infos;
+
+        if (!rsa_multip_calc_product(r)) {
+            r->prime_infos = old_infos;
+            goto err;
+        }
+    }
+
+    if (old_infos != NULL) {
+        /*
+         * This is hard to deal with, since the old infos could
+         * also be set by this function and r, d, t should not
+         * be freed in that case. So currently, stay consistent
+         * with other *set0* functions: just free it...
+         */
+        sk_RSA_PRIME_INFO_pop_free(old_infos, rsa_multip_info_free);
+    }
+
+    r->version = pnum > 2 ? RSA_ASN1_VERSION_MULTI : RSA_ASN1_VERSION_DEFAULT;
+    r->dirty_cnt++;
+
+    return 1;
+ err:
+    /* r, d, t should not be freed */
+    sk_RSA_PRIME_INFO_pop_free(prime_infos, rsa_multip_info_free_ex);
+    return 0;
+}
+
+DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
+
+int rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes,
+                        STACK_OF(BIGNUM_const) *exps,
+                        STACK_OF(BIGNUM_const) *coeffs)
+{
+    RSA_PRIME_INFO *pinfo;
+    int i, pnum;
+
+    if (r == NULL)
+        return 0;
+
+    pnum = RSA_get_multi_prime_extra_count(r);
+
+    sk_BIGNUM_const_push(primes, RSA_get0_p(r));
+    sk_BIGNUM_const_push(primes, RSA_get0_q(r));
+    sk_BIGNUM_const_push(exps, RSA_get0_dmp1(r));
+    sk_BIGNUM_const_push(exps, RSA_get0_dmq1(r));
+    sk_BIGNUM_const_push(coeffs, RSA_get0_iqmp(r));
+    for (i = 0; i < pnum; i++) {
+        pinfo = sk_RSA_PRIME_INFO_value(r->prime_infos, i);
+        sk_BIGNUM_const_push(primes, pinfo->r);
+        sk_BIGNUM_const_push(exps, pinfo->d);
+        sk_BIGNUM_const_push(coeffs, pinfo->t);
+    }
+
+    return 1;
+}
diff --git a/crypto/rsa/rsa_local.h b/crypto/rsa/rsa_local.h
index 204fde29fa..ae71567f7a 100644
--- a/crypto/rsa/rsa_local.h
+++ b/crypto/rsa/rsa_local.h
@@ -66,6 +66,8 @@ struct rsa_st {
     BN_BLINDING *blinding;
     BN_BLINDING *mt_blinding;
     CRYPTO_RWLOCK *lock;
+
+    int dirty_cnt;
 };
 
 struct rsa_meth_st {
diff --git a/crypto/rsa/rsa_sp800_56b_gen.c b/crypto/rsa/rsa_sp800_56b_gen.c
index c22b10cfbd..5474aaa4b5 100644
--- a/crypto/rsa/rsa_sp800_56b_gen.c
+++ b/crypto/rsa/rsa_sp800_56b_gen.c
@@ -118,6 +118,7 @@ int rsa_fips186_4_gen_prob_primes(RSA *rsa, BIGNUM *p1, BIGNUM *p2,
             continue;
         break; /* successfully finished */
     }
+    rsa->dirty_cnt++;
     ret = 1;
 err:
     /* Zeroize any internally generated values that are not returned */
@@ -239,6 +240,7 @@ int rsa_sp800_56b_derive_params_from_pq(RSA *rsa, int nbits,
             || BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx) == NULL)
         goto err;
 
+    rsa->dirty_cnt++;
     ret = 1;
 err:
     if (ret != 1) {
diff --git a/crypto/rsa/rsa_x931g.c b/crypto/rsa/rsa_x931g.c
index 3798d02b55..1f6042a3d2 100644
--- a/crypto/rsa/rsa_x931g.c
+++ b/crypto/rsa/rsa_x931g.c
@@ -131,6 +131,7 @@ int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1,
     if (rsa->iqmp == NULL)
         goto err;
 
+    rsa->dirty_cnt++;
     ret = 1;
  err:
     BN_CTX_end(ctx);
@@ -184,6 +185,7 @@ int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e,
                             NULL, NULL, NULL, NULL, NULL, NULL, e, cb))
         goto error;
 
+    rsa->dirty_cnt++;
     ok = 1;
 
  error:
diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h
new file mode 100644
index 0000000000..6d2e7ffb53
--- /dev/null
+++ b/include/crypto/rsa.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2019 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_RSA_H
+# define OSSL_INTERNAL_RSA_H
+
+#include <openssl/rsa.h>
+
+int rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes,
+                        const STACK_OF(BIGNUM) *exps,
+                        const STACK_OF(BIGNUM) *coeffs);
+int rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes,
+                        STACK_OF(BIGNUM_const) *exps,
+                        STACK_OF(BIGNUM_const) *coeffs);
+#endif
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
index f0e6334d89..e7e5ea060e 100644
--- a/include/openssl/core_names.h
+++ b/include/openssl/core_names.h
@@ -159,6 +159,27 @@ extern "C" {
 #define OSSL_PKEY_PARAM_DSA_PUB_KEY  "pub"
 #define OSSL_PKEY_PARAM_DSA_PRIV_KEY "priv"
 
+/* RSA Keys */
+/*
+ * n, e, d are the usual public and private key components
+ *
+ * rsa-num is the number of factors, including p and q
+ * rsa-factor is used for each factor: p, q, r_i (i = 3, ...)
+ * rsa-exponent is used for each exponent: dP, dQ, d_i (i = 3, ...)
+ * rsa-coefficient is used for each coefficient: qInv, t_i (i = 3, ...)
+ *
+ * The number of rsa-factor items must be equal to the number of rsa-exponent
+ * items, and the number of rsa-coefficients must be one less.
+ * (the base i for the coefficients is 2, not 1, at least as implied by
+ * RFC 8017)
+ */
+#define OSSL_PKEY_PARAM_RSA_N           "n"
+#define OSSL_PKEY_PARAM_RSA_E           "e"
+#define OSSL_PKEY_PARAM_RSA_D           "d"
+#define OSSL_PKEY_PARAM_RSA_FACTOR      "rsa-factor"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT    "rsa-exponent"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT "rsa-coefficient"
+
 /* Key Exchange parameters */
 
 #define OSSL_EXCHANGE_PARAM_PAD      "pad" /* uint */
diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
index 8ddc970396..9214efd499 100644
--- a/include/openssl/rsa.h
+++ b/include/openssl/rsa.h
@@ -27,6 +27,8 @@
 #  include <openssl/bn.h>
 # endif
 # include <openssl/rsaerr.h>
+# include <openssl/safestack.h>
+
 # ifdef  __cplusplus
 extern "C" {
 # endif
diff --git a/include/openssl/types.h b/include/openssl/types.h
index 73bf88d92d..8cfeb6ee22 100644
--- a/include/openssl/types.h
+++ b/include/openssl/types.h
@@ -17,6 +17,7 @@ extern "C" {
 #endif
 
 # include <openssl/e_os2.h>
+# include <openssl/safestack.h>
 
 typedef struct ossl_provider_st OSSL_PROVIDER; /* Provider Object */
 
@@ -88,6 +89,9 @@ typedef struct bn_gencb_st BN_GENCB;
 
 typedef struct buf_mem_st BUF_MEM;
 
+STACK_OF(BIGNUM);
+STACK_OF(BIGNUM_const);
+
 typedef struct err_state_st ERR_STATE;
 
 typedef struct evp_cipher_st EVP_CIPHER;
diff --git a/providers/defltprov.c b/providers/defltprov.c
index 2d457ae53f..8104227fff 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -364,6 +364,7 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = {
 #ifndef OPENSSL_NO_DSA
     { "DSA", "default=yes", dsa_keymgmt_functions },
 #endif
+    { "RSA", "default=yes", rsa_keymgmt_functions },
     { NULL, NULL, NULL }
 };
 
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index 44b0a6fbc2..16f2129115 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -241,6 +241,7 @@ extern const OSSL_DISPATCH kdf_x942_kdf_functions[];
 /* Key management */
 extern const OSSL_DISPATCH dh_keymgmt_functions[];
 extern const OSSL_DISPATCH dsa_keymgmt_functions[];
+extern const OSSL_DISPATCH rsa_keymgmt_functions[];
 
 /* Key Exchange */
 extern const OSSL_DISPATCH dh_keyexch_functions[];
diff --git a/providers/implementations/keymgmt/build.info b/providers/implementations/keymgmt/build.info
index dc6039b02d..f4a9d1a5de 100644
--- a/providers/implementations/keymgmt/build.info
+++ b/providers/implementations/keymgmt/build.info
@@ -3,6 +3,7 @@
 
 $DH_GOAL=../../libimplementations.a
 $DSA_GOAL=../../libimplementations.a
+$RSA_GOAL=../../libimplementations.a
 
 IF[{- !$disabled{dh} -}]
   SOURCE[$DH_GOAL]=dh_kmgmt.c
@@ -10,3 +11,4 @@ ENDIF
 IF[{- !$disabled{dsa} -}]
   SOURCE[$DSA_GOAL]=dsa_kmgmt.c
 ENDIF
+SOURCE[$RSA_GOAL]=rsa_kmgmt.c
diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c
new file mode 100644
index 0000000000..aaa9815aa9
--- /dev/null
+++ b/providers/implementations/keymgmt/rsa_kmgmt.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2019 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/params.h>
+#include <openssl/types.h>
+#include "prov/implementations.h"
+#include "crypto/rsa.h"
+
+static OSSL_OP_keymgmt_importkey_fn rsa_importkey;
+static OSSL_OP_keymgmt_exportkey_fn rsa_exportkey;
+
+DEFINE_STACK_OF(BIGNUM)
+DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
+
+static int collect_numbers(STACK_OF(BIGNUM) *numbers,
+                           const OSSL_PARAM params[], const char *key)
+{
+    const OSSL_PARAM *p = NULL;
+
+    if (numbers == NULL)
+        return 0;
+
+    for (p = params; (p = OSSL_PARAM_locate_const(p, key)) != NULL; p++) {
+        BIGNUM *tmp = NULL;
+
+        if (!OSSL_PARAM_get_BN(p, &tmp))
+            return 0;
+        sk_BIGNUM_push(numbers, tmp);
+    }
+
+    return 1;
+}
+
+static int params_to_key(RSA *rsa, const OSSL_PARAM params[])
+{
+    const OSSL_PARAM *param_n, *param_e,  *param_d;
+    BIGNUM *n = NULL, *e = NULL, *d = NULL;
+    STACK_OF(BIGNUM) *factors = NULL, *exps = NULL, *coeffs = NULL;
+    int is_private = 0;
+
+    if (rsa == NULL)
+        return 0;
+
+    param_n = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N);
+    param_e = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E);
+    param_d = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D);
+
+    if ((param_n != NULL && !OSSL_PARAM_get_BN(param_n, &n))
+        || (param_e != NULL && !OSSL_PARAM_get_BN(param_e, &e))
+        || (param_d != NULL && !OSSL_PARAM_get_BN(param_d, &d)))
+        goto err;
+
+    is_private = (d != NULL);
+
+    if (!RSA_set0_key(rsa, n, e, d))
+        goto err;
+    n = e = d = NULL;
+
+    if (is_private) {
+        if (!collect_numbers(factors = sk_BIGNUM_new_null(), params,
+                             OSSL_PKEY_PARAM_RSA_FACTOR)
+            || !collect_numbers(exps = sk_BIGNUM_new_null(), params,
+                                OSSL_PKEY_PARAM_RSA_EXPONENT)
+            || !collect_numbers(coeffs = sk_BIGNUM_new_null(), params,
+                                OSSL_PKEY_PARAM_RSA_COEFFICIENT))
+            goto err;
+
+        /* It's ok if this private key just has n, e and d */
+        if (sk_BIGNUM_num(factors) != 0
+            && !rsa_set0_all_params(rsa, factors, exps, coeffs))
+            goto err;
+    }
+
+    sk_BIGNUM_free(factors);
+    sk_BIGNUM_free(exps);
+    sk_BIGNUM_free(coeffs);
+    return 1;
+
+ err:
+    BN_free(n);
+    BN_free(e);
+    BN_free(d);
+    sk_BIGNUM_pop_free(factors, BN_free);
+    sk_BIGNUM_pop_free(exps, BN_free);
+    sk_BIGNUM_pop_free(coeffs, BN_free);
+    return 0;
+}
+
+static int export_numbers(OSSL_PARAM params[], const char *key,
+                          STACK_OF(BIGNUM_const) *numbers)
+{
+    OSSL_PARAM *p = NULL;
+    int i, nnum;
+
+    if (numbers == NULL)
+        return 0;
+
+    nnum = sk_BIGNUM_const_num(numbers);
+
+    for (p = params, i = 0;
+         i < nnum && (p = OSSL_PARAM_locate(p, key)) != NULL;
+         p++, i++) {
+        if (!OSSL_PARAM_set_BN(p, sk_BIGNUM_const_value(numbers, i)))
+            return 0;
+    }
+
+    /*
+     * If we didn't export the amount of numbers we have, the caller didn't
+     * specify enough OSSL_PARAM entries named |key|.
+     */
+    return i == nnum;
+}
+
+static int key_to_params(RSA *rsa, OSSL_PARAM params[])
+{
+    int ret = 0;
+    OSSL_PARAM *p;
+    const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL;
+    STACK_OF(BIGNUM_const) *factors = sk_BIGNUM_const_new_null();
+    STACK_OF(BIGNUM_const) *exps = sk_BIGNUM_const_new_null();
+    STACK_OF(BIGNUM_const) *coeffs = sk_BIGNUM_const_new_null();
+
+    if (rsa == NULL || factors == NULL || exps == NULL || coeffs == NULL)
+        goto err;
+
+    RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
+    rsa_get0_all_params(rsa, factors, exps, coeffs);
+
+    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_N)) != NULL
+        && !OSSL_PARAM_set_BN(p, rsa_n))
+        goto err;
+    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_E)) != NULL
+        && !OSSL_PARAM_set_BN(p, rsa_e))
+        goto err;
+    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_D)) != NULL
+        && !OSSL_PARAM_set_BN(p, rsa_d))
+        goto err;
+
+    if (!export_numbers(params, OSSL_PKEY_PARAM_RSA_FACTOR, factors)
+        || !export_numbers(params, OSSL_PKEY_PARAM_RSA_EXPONENT, exps)
+        || !export_numbers(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT, coeffs))
+        goto err;
+
+    ret = 1;
+ err:
+    sk_BIGNUM_const_free(factors);
+    sk_BIGNUM_const_free(exps);
+    sk_BIGNUM_const_free(coeffs);
+    return ret;
+}
+
+static void *rsa_importkey(void *provctx, const OSSL_PARAM params[])
+{
+    RSA *rsa;
+
+    if ((rsa = RSA_new()) == NULL
+        || !params_to_key(rsa, params)) {
+        RSA_free(rsa);
+        rsa = NULL;
+    }
+    return rsa;
+}
+
+static int rsa_exportkey(void *key, OSSL_PARAM params[])
+{
+    RSA *rsa = key;
+
+    return rsa != NULL && key_to_params(rsa, params);
+}
+
+/*
+ * This provider can export everything in an RSA key, so we use the exact
+ * same type description for export as for import.  Other providers might
+ * choose to import full keys, but only export the public parts, and will
+ * therefore have the importkey_types and importkey_types functions return
+ * different arrays.
+ */
+static const OSSL_PARAM rsa_key_types[] = {
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_D, NULL, 0),
+    /* We tolerate up to 10 factors... */
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0),
+    /* ..., up to 10 CRT exponents... */
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0),
+    /* ..., and up to 9 CRT coefficients */
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0),
+};
+/*
+ * We lied about the amount of factors, exponents and coefficients, the
+ * export and import functions can really deal with an infinite amount
+ * of these numbers.  However, RSA keys with too many primes are futile,
+ * so we at least pretend to have some limits.
+ */
+
+static const OSSL_PARAM *rsa_exportkey_types(void)
+{
+    return rsa_key_types;
+}
+
+static const OSSL_PARAM *rsa_importkey_types(void)
+{
+    return rsa_key_types;
+}
+
+const OSSL_DISPATCH rsa_keymgmt_functions[] = {
+    { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))rsa_importkey },
+    { OSSL_FUNC_KEYMGMT_IMPORTKEY_TYPES, (void (*)(void))rsa_importkey_types },
+    { OSSL_FUNC_KEYMGMT_EXPORTKEY, (void (*)(void))rsa_exportkey },
+    { OSSL_FUNC_KEYMGMT_EXPORTKEY_TYPES, (void (*)(void))rsa_exportkey_types },
+    { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))RSA_free },
+    { 0, NULL }
+};
diff --git a/test/build.info b/test/build.info
index 7328641243..f50c2eaa40 100644
--- a/test/build.info
+++ b/test/build.info
@@ -56,7 +56,8 @@ IF[{- !$disabled{tests} -}]
           time_offset_test pemtest ssl_cert_table_internal_test ciphername_test \
           servername_test ocspapitest rsa_mp_test fatalerrtest tls13ccstest \
           sysdefaulttest errtest gosttest \
-          context_internal_test aesgcmtest params_test evp_pkey_dparams_test
+          context_internal_test aesgcmtest params_test evp_pkey_dparams_test \
+          keymgmt_internal_test
 
   SOURCE[versions]=versions.c
   INCLUDE[versions]=../include ../apps/include
@@ -175,7 +176,7 @@ IF[{- !$disabled{tests} -}]
 
   SOURCE[rsa_mp_test]=rsa_mp_test.c
   INCLUDE[rsa_mp_test]=../include ../apps/include
-  DEPEND[rsa_mp_test]=../libcrypto libtestutil.a
+  DEPEND[rsa_mp_test]=../libcrypto.a libtestutil.a
 
   SOURCE[fatalerrtest]=fatalerrtest.c ssltestlib.c
   INCLUDE[fatalerrtest]=../include ../apps/include
@@ -588,6 +589,10 @@ IF[{- !$disabled{tests} -}]
     SOURCE[asn1_dsa_internal_test]=asn1_dsa_internal_test.c
     INCLUDE[asn1_dsa_internal_test]=.. ../include ../apps/include ../crypto/include
     DEPEND[asn1_dsa_internal_test]=../libcrypto.a libtestutil.a
+
+    SOURCE[keymgmt_internal_test]=keymgmt_internal_test.c
+    INCLUDE[keymgmt_internal_test]=.. ../include ../apps/include
+    DEPEND[keymgmt_internal_test]=../libcrypto.a libtestutil.a
   ENDIF
 
   IF[{- !$disabled{mdc2} -}]
diff --git a/test/keymgmt_internal_test.c b/test/keymgmt_internal_test.c
new file mode 100644
index 0000000000..1fd831d72f
--- /dev/null
+++ b/test/keymgmt_internal_test.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2019 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/provider.h>
+#include <openssl/core_names.h>
+#include "internal/nelem.h"
+#include "crypto/evp.h"          /* For the internal API */
+#include "testutil.h"
+
+typedef struct {
+    OPENSSL_CTX *ctx1;
+    OSSL_PROVIDER *prov1;
+    OPENSSL_CTX *ctx2;
+    OSSL_PROVIDER *prov2;
+} FIXTURE;
+
+static void tear_down(FIXTURE *fixture)
+{
+    if (fixture != NULL) {
+        OSSL_PROVIDER_unload(fixture->prov1);
+        OSSL_PROVIDER_unload(fixture->prov2);
+        OPENSSL_CTX_free(fixture->ctx1);
+        OPENSSL_CTX_free(fixture->ctx2);
+        OPENSSL_free(fixture);
+    }
+}
+
+static FIXTURE *set_up(const char *testcase_name)
+{
+    FIXTURE *fixture;
+
+    if (!TEST_ptr(fixture = OPENSSL_zalloc(sizeof(*fixture)))
+        || !TEST_ptr(fixture->ctx1 = OPENSSL_CTX_new())
+        || !TEST_ptr(fixture->prov1 = OSSL_PROVIDER_load(fixture->ctx1,
+                                                         "default"))
+        || !TEST_ptr(fixture->ctx2 = OPENSSL_CTX_new())
+        || !TEST_ptr(fixture->prov2 = OSSL_PROVIDER_load(fixture->ctx2,
+                                                         "default"))) {
+        tear_down(fixture);
+        return NULL;
+    }
+    return fixture;
+}
+
+static int test_pass_rsa(FIXTURE *fixture)
+{
+    /* Array indexes */
+#define N       0
+#define E       1
+#define D       2
+#define P       3
+#define Q       4
+#define F3      5                /* Extra factor */
+#define DP      6
+#define DQ      7
+#define E3      8                /* Extra exponent */
+#define QINV    9
+#define C3      10               /* Extra coefficient */
+
+    size_t i;
+    int ret = 0;
+    RSA *rsa = NULL;
+    BIGNUM *bn1 = NULL, *bn2 = NULL, *bn3 = NULL;
+    EVP_PKEY *pk = NULL;
+    EVP_KEYMGMT *km1 = NULL, *km2 = NULL;
+    void *provdata = NULL;
+    /*
+     * 32-bit RSA key, extracted from this command,
+     * executed with OpenSSL 1.0.2:
+     *
+     * openssl genrsa 32 | openssl rsa -text
+     */
+    static BN_ULONG expected[] = {
+        0xbc747fc5,              /* N */
+        0x10001,                 /* E */
+        0x7b133399,              /* D */
+        0xe963,                  /* P */
+        0xceb7,                  /* Q */
+        0,                       /* F3 */
+        0x8599,                  /* DP */
+        0xbd87,                  /* DQ */
+        0,                       /* E3 */
+        0xcc3b,                  /* QINV */
+        0,                       /* C3 */
+        0                        /* Extra, should remain zero */
+    };
+    static unsigned long keydata[OSSL_NELEM(expected)] = { 0, };
+    OSSL_PARAM params[] = {
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_N, &keydata[N]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_E, &keydata[E]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_D, &keydata[D]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &keydata[P]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &keydata[Q]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &keydata[F3]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &keydata[DP]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &keydata[DQ]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &keydata[E3]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_COEFFICIENT, &keydata[QINV]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_COEFFICIENT, &keydata[C3]),
+        OSSL_PARAM_END
+    };
+
+    if (!TEST_ptr(rsa = RSA_new()))
+        goto err;
+
+    if (!TEST_ptr(bn1 = BN_new())
+        || !TEST_true(BN_set_word(bn1, expected[N]))
+        || !TEST_ptr(bn2 = BN_new())
+        || !TEST_true(BN_set_word(bn2, expected[E]))
+        || !TEST_ptr(bn3 = BN_new())
+        || !TEST_true(BN_set_word(bn3, expected[D]))
+        || !TEST_true(RSA_set0_key(rsa, bn1, bn2, bn3)))
+        goto err;
+
+    if (!TEST_ptr(bn1 = BN_new())
+        || !TEST_true(BN_set_word(bn1, expected[P]))
+        || !TEST_ptr(bn2 = BN_new())
+        || !TEST_true(BN_set_word(bn2, expected[Q]))
+        || !TEST_true(RSA_set0_factors(rsa, bn1, bn2)))
+        goto err;
+
+    if (!TEST_ptr(bn1 = BN_new())
+        || !TEST_true(BN_set_word(bn1, expected[DP]))
+        || !TEST_ptr(bn2 = BN_new())
+        || !TEST_true(BN_set_word(bn2, expected[DQ]))
+        || !TEST_ptr(bn3 = BN_new())
+        || !TEST_true(BN_set_word(bn3, expected[QINV]))
+        || !TEST_true(RSA_set0_crt_params(rsa, bn1, bn2, bn3)))
+        goto err;
+    bn1 = bn2 = bn3 = NULL;
+
+    if (!TEST_ptr(pk = EVP_PKEY_new())
+        || !TEST_true(EVP_PKEY_assign_RSA(pk, rsa)))
+        goto err;
+    rsa = NULL;
+
+    if (!TEST_ptr(km1 = EVP_KEYMGMT_fetch(fixture->ctx1, "RSA", NULL))
+        || !TEST_ptr(km2 = EVP_KEYMGMT_fetch(fixture->ctx2, "RSA", NULL))
+        || !TEST_ptr_ne(km1, km2))
+        goto err;
+
+    if (!TEST_ptr(evp_keymgmt_export_to_provider(pk, km1, 0))
+        || !TEST_ptr(provdata = evp_keymgmt_export_to_provider(pk, km2, 0)))
+        goto err;
+
+    if (!TEST_true(evp_keymgmt_exportkey(km2, provdata, params)))
+        goto err;
+
+    /*
+     * At this point, the hope is that keydata will have all the numbers
+     * from the key.
+     */
+
+    for (i = 0; i < OSSL_NELEM(expected); i++)
+        ret += !! TEST_int_eq(expected[i], keydata[i]);
+
+    ret = (ret == OSSL_NELEM(expected));
+
+ err:
+    RSA_free(rsa);
+    BN_free(bn1);
+    BN_free(bn2);
+    BN_free(bn3);
+    EVP_PKEY_free(pk);
+    EVP_KEYMGMT_free(km1);
+    EVP_KEYMGMT_free(km2);
+
+    return ret;
+}
+
+static int (*tests[])(FIXTURE *) = {
+    test_pass_rsa
+};
+
+static int test_pass_key(int n)
+{
+    SETUP_TEST_FIXTURE(FIXTURE, set_up);
+    EXECUTE_TEST(tests[n], tear_down);
+    return result;
+}
+
+int setup_tests(void)
+{
+    ADD_ALL_TESTS(test_pass_key, 1);
+    return 1;
+}
diff --git a/test/recipes/04-test_provider.t b/test/recipes/02-test_internal_keymgmt.t
similarity index 76%
copy from test/recipes/04-test_provider.t
copy to test/recipes/02-test_internal_keymgmt.t
index 9195a424cd..f7b2eb3f1c 100644
--- a/test/recipes/04-test_provider.t
+++ b/test/recipes/02-test_internal_keymgmt.t
@@ -11,8 +11,8 @@ use OpenSSL::Test qw(:DEFAULT bldtop_dir);
 use OpenSSL::Test::Simple;
 use OpenSSL::Test::Utils;
 
-setup("test_provider");
+setup("test_internal_provider");
 
-$ENV{"OPENSSL_MODULES"} = bldtop_dir("test");
+$ENV{OPENSSL_MODULES} = bldtop_dir("test");
 
-simple_test("test_provider", "provider_test");
+simple_test("test_internal_keymgmt", "keymgmt_internal_test");
diff --git a/test/rsa_mp_test.c b/test/rsa_mp_test.c
index 79557082f2..baa9dd2272 100644
--- a/test/rsa_mp_test.c
+++ b/test/rsa_mp_test.c
@@ -8,7 +8,7 @@
  * https://www.openssl.org/source/license.html
  */
 
-/* This aims to test the setting functions */
+/* This aims to test the setting functions, including internal ones */
 
 #include <stdio.h>
 #include <string.h>
@@ -22,122 +22,131 @@
 
 #ifndef OPENSSL_NO_RSA
 # include <openssl/rsa.h>
+# include "crypto/rsa.h"
 
 #define NUM_EXTRA_PRIMES 1
 
-static int key2048p3(RSA *key)
+DEFINE_STACK_OF(BIGNUM)
+
+/* C90 requires string should <= 509 bytes */
+static const unsigned char n[] =
+    "\x92\x60\xd0\x75\x0a\xe1\x17\xee\xe5\x5c\x3f\x3d\xea\xba\x74\x91"
+    "\x75\x21\xa2\x62\xee\x76\x00\x7c\xdf\x8a\x56\x75\x5a\xd7\x3a\x15"
+    "\x98\xa1\x40\x84\x10\xa0\x14\x34\xc3\xf5\xbc\x54\xa8\x8b\x57\xfa"
+    "\x19\xfc\x43\x28\xda\xea\x07\x50\xa4\xc4\x4e\x88\xcf\xf3\xb2\x38"
+    "\x26\x21\xb8\x0f\x67\x04\x64\x43\x3e\x43\x36\xe6\xd0\x03\xe8\xcd"
+    "\x65\xbf\xf2\x11\xda\x14\x4b\x88\x29\x1c\x22\x59\xa0\x0a\x72\xb7"
+    "\x11\xc1\x16\xef\x76\x86\xe8\xfe\xe3\x4e\x4d\x93\x3c\x86\x81\x87"
+    "\xbd\xc2\x6f\x7b\xe0\x71\x49\x3c\x86\xf7\xa5\x94\x1c\x35\x10\x80"
+    "\x6a\xd6\x7b\x0f\x94\xd8\x8f\x5c\xf5\xc0\x2a\x09\x28\x21\xd8\x62"
+    "\x6e\x89\x32\xb6\x5c\x5b\xd8\xc9\x20\x49\xc2\x10\x93\x2b\x7a\xfa"
+    "\x7a\xc5\x9c\x0e\x88\x6a\xe5\xc1\xed\xb0\x0d\x8c\xe2\xc5\x76\x33"
+    "\xdb\x26\xbd\x66\x39\xbf\xf7\x3c\xee\x82\xbe\x92\x75\xc4\x02\xb4"
+    "\xcf\x2a\x43\x88\xda\x8c\xf8\xc6\x4e\xef\xe1\xc5\xa0\xf5\xab\x80"
+    "\x57\xc3\x9f\xa5\xc0\x58\x9c\x3e\x25\x3f\x09\x60\x33\x23\x00\xf9"
+    "\x4b\xea\x44\x87\x7b\x58\x8e\x1e\xdb\xde\x97\xcf\x23\x60\x72\x7a"
+    "\x09\xb7\x75\x26\x2d\x7e\xe5\x52\xb3\x31\x9b\x92\x66\xf0\x5a\x25";
+
+static const unsigned char e[] = "\x01\x00\x01";
+
+static const unsigned char d[] =
+    "\x6a\x7d\xf2\xca\x63\xea\xd4\xdd\xa1\x91\xd6\x14\xb6\xb3\x85\xe0"
+    "\xd9\x05\x6a\x3d\x6d\x5c\xfe\x07\xdb\x1d\xaa\xbe\xe0\x22\xdb\x08"
+    "\x21\x2d\x97\x61\x3d\x33\x28\xe0\x26\x7c\x9d\xd2\x3d\x78\x7a\xbd"
+    "\xe2\xaf\xcb\x30\x6a\xeb\x7d\xfc\xe6\x92\x46\xcc\x73\xf5\xc8\x7f"
+    "\xdf\x06\x03\x01\x79\xa2\x11\x4b\x76\x7d\xb1\xf0\x83\xff\x84\x1c"
+    "\x02\x5d\x7d\xc0\x0c\xd8\x24\x35\xb9\xa9\x0f\x69\x53\x69\xe9\x4d"
+    "\xf2\x3d\x2c\xe4\x58\xbc\x3b\x32\x83\xad\x8b\xba\x2b\x8f\xa1\xba"
+    "\x62\xe2\xdc\xe9\xac\xcf\xf3\x79\x9a\xae\x7c\x84\x00\x16\xf3\xba"
+    "\x8e\x00\x48\xc0\xb6\xcc\x43\x39\xaf\x71\x61\x00\x3a\x5b\xeb\x86"
+    "\x4a\x01\x64\xb2\xc1\xc9\x23\x7b\x64\xbc\x87\x55\x69\x94\x35\x1b"
+    "\x27\x50\x6c\x33\xd4\xbc\xdf\xce\x0f\x9c\x49\x1a\x7d\x6b\x06\x28"
+    "\xc7\xc8\x52\xbe\x4f\x0a\x9c\x31\x32\xb2\xed\x3a\x2c\x88\x81\xe9"
+    "\xaa\xb0\x7e\x20\xe1\x7d\xeb\x07\x46\x91\xbe\x67\x77\x76\xa7\x8b"
+    "\x5c\x50\x2e\x05\xd9\xbd\xde\x72\x12\x6b\x37\x38\x69\x5e\x2d\xd1"
+    "\xa0\xa9\x8a\x14\x24\x7c\x65\xd8\xa7\xee\x79\x43\x2a\x09\x2c\xb0"
+    "\x72\x1a\x12\xdf\x79\x8e\x44\xf7\xcf\xce\x0c\x49\x81\x47\xa9\xb1";
+
+static const unsigned char p[] =
+    "\x06\x77\xcd\xd5\x46\x9b\xc1\xd5\x58\x00\x81\xe2\xf3\x0a\x36\xb1"
+    "\x6e\x29\x89\xd5\x2f\x31\x5f\x92\x22\x3b\x9b\x75\x30\x82\xfa\xc5"
+    "\xf5\xde\x8a\x36\xdb\xc6\xe5\x8f\xef\x14\x37\xd6\x00\xf9\xab\x90"
+    "\x9b\x5d\x57\x4c\xf5\x1f\x77\xc4\xbb\x8b\xdd\x9b\x67\x11\x45\xb2"
+    "\x64\xe8\xac\xa8\x03\x0f\x16\x0d\x5d\x2d\x53\x07\x23\xfb\x62\x0d"
+    "\xe6\x16\xd3\x23\xe8\xb3";
+
+static const unsigned char q[] =
+    "\x06\x66\x9a\x70\x53\xd6\x72\x74\xfd\xea\x45\xc3\xc0\x17\xae\xde"
+    "\x79\x17\xae\x79\xde\xfc\x0e\xf7\xa4\x3a\x8c\x43\x8f\xc7\x8a\xa2"
+    "\x2c\x51\xc4\xd0\x72\x89\x73\x5c\x61\xbe\xfd\x54\x3f\x92\x65\xde"
+    "\x4d\x65\x71\x70\xf6\xf2\xe5\x98\xb9\x0f\xd1\x0b\xe6\x95\x09\x4a"
+    "\x7a\xdf\xf3\x10\x16\xd0\x60\xfc\xa5\x10\x34\x97\x37\x6f\x0a\xd5"
+    "\x5d\x8f\xd4\xc3\xa0\x5b";
+
+static const unsigned char dmp1[] =
+    "\x05\x7c\x9e\x1c\xbd\x90\x25\xe7\x40\x86\xf5\xa8\x3b\x7a\x3f\x99"
+    "\x56\x95\x60\x3a\x7b\x95\x4b\xb8\xa0\xd7\xa5\xf1\xcc\xdc\x5f\xb5"
+    "\x8c\xf4\x62\x95\x54\xed\x2e\x12\x62\xc2\xe8\xf6\xde\xce\xed\x8e"
+    "\x77\x6d\xc0\x40\x25\x74\xb3\x5a\x2d\xaa\xe1\xac\x11\xcb\xe2\x2f"
+    "\x0a\x51\x23\x1e\x47\xb2\x05\x88\x02\xb2\x0f\x4b\xf0\x67\x30\xf0"
+    "\x0f\x6e\xef\x5f\xf7\xe7";
+
+static const unsigned char dmq1[] =
+    "\x01\xa5\x6b\xbc\xcd\xe3\x0e\x46\xc6\x72\xf5\x04\x56\x28\x01\x22"
+    "\x58\x74\x5d\xbc\x1c\x3c\x29\x41\x49\x6c\x81\x5c\x72\xe2\xf7\xe5"
+    "\xa3\x8e\x58\x16\xe0\x0e\x37\xac\x1f\xbb\x75\xfd\xaf\xe7\xdf\xe9"
+    "\x1f\x70\xa2\x8f\x52\x03\xc0\x46\xd9\xf9\x96\x63\x00\x27\x7e\x5f"
+    "\x38\x60\xd6\x6b\x61\xe2\xaf\xbe\xea\x58\xd3\x9d\xbc\x75\x03\x8d"
+    "\x42\x65\xd6\x6b\x85\x97";
+
+static const unsigned char iqmp[] =
+    "\x03\xa1\x8b\x80\xe4\xd8\x87\x25\x17\x5d\xcc\x8d\xa9\x8a\x22\x2b"
+    "\x6c\x15\x34\x6f\x80\xcc\x1c\x44\x04\x68\xbc\x03\xcd\x95\xbb\x69"
+    "\x37\x61\x48\xb4\x23\x13\x08\x16\x54\x6a\xa1\x7c\xf5\xd4\x3a\xe1"
+    "\x4f\xa4\x0c\xf5\xaf\x80\x85\x27\x06\x0d\x70\xc0\xc5\x19\x28\xfe"
+    "\xee\x8e\x86\x21\x98\x8a\x37\xb7\xe5\x30\x25\x70\x93\x51\x2d\x49"
+    "\x85\x56\xb3\x0c\x2b\x96";
+
+static const unsigned char ex_prime[] =
+    "\x03\x89\x22\xa0\xb7\x3a\x91\xcb\x5e\x0c\xfd\x73\xde\xa7\x38\xa9"
+    "\x47\x43\xd6\x02\xbf\x2a\xb9\x3c\x48\xf3\x06\xd6\x58\x35\x50\x56"
+    "\x16\x5c\x34\x9b\x61\x87\xc8\xaa\x0a\x5d\x8a\x0a\xcd\x9c\x41\xd9"
+    "\x96\x24\xe0\xa9\x9b\x26\xb7\xa8\x08\xc9\xea\xdc\xa7\x15\xfb\x62"
+    "\xa0\x2d\x90\xe6\xa7\x55\x6e\xc6\x6c\xff\xd6\x10\x6d\xfa\x2e\x04"
+    "\x50\xec\x5c\x66\xe4\x05";
+
+static const unsigned char ex_exponent[] =
+    "\x02\x0a\xcd\xc3\x82\xd2\x03\xb0\x31\xac\xd3\x20\x80\x34\x9a\x57"
+    "\xbc\x60\x04\x57\x25\xd0\x29\x9a\x16\x90\xb9\x1c\x49\x6a\xd1\xf2"
+    "\x47\x8c\x0e\x9e\xc9\x20\xc2\xd8\xe4\x8f\xce\xd2\x1a\x9c\xec\xb4"
+    "\x1f\x33\x41\xc8\xf5\x62\xd1\xa5\xef\x1d\xa1\xd8\xbd\x71\xc6\xf7"
+    "\xda\x89\x37\x2e\xe2\xec\x47\xc5\xb8\xe3\xb4\xe3\x5c\x82\xaa\xdd"
+    "\xb7\x58\x2e\xaf\x07\x79";
+
+static const unsigned char ex_coefficient[] =
+    "\x00\x9c\x09\x88\x9b\xc8\x57\x08\x69\x69\xab\x2d\x9e\x29\x1c\x3c"
+    "\x6d\x59\x33\x12\x0d\x2b\x09\x2e\xaf\x01\x2c\x27\x01\xfc\xbd\x26"
+    "\x13\xf9\x2d\x09\x22\x4e\x49\x11\x03\x82\x88\x87\xf4\x43\x1d\xac"
+    "\xca\xec\x86\xf7\x23\xf1\x64\xf3\xf5\x81\xf0\x37\x36\xcf\x67\xff"
+    "\x1a\xff\x7a\xc7\xf9\xf9\x67\x2d\xa0\x9d\x61\xf8\xf6\x47\x5c\x2f"
+    "\xe7\x66\xe8\x3c\x3a\xe8";
+
+static int key2048_key(RSA *key)
 {
-    /* C90 requires string should <= 509 bytes */
-    static const unsigned char n[] =
-        "\x92\x60\xd0\x75\x0a\xe1\x17\xee\xe5\x5c\x3f\x3d\xea\xba\x74\x91"
-        "\x75\x21\xa2\x62\xee\x76\x00\x7c\xdf\x8a\x56\x75\x5a\xd7\x3a\x15"
-        "\x98\xa1\x40\x84\x10\xa0\x14\x34\xc3\xf5\xbc\x54\xa8\x8b\x57\xfa"
-        "\x19\xfc\x43\x28\xda\xea\x07\x50\xa4\xc4\x4e\x88\xcf\xf3\xb2\x38"
-        "\x26\x21\xb8\x0f\x67\x04\x64\x43\x3e\x43\x36\xe6\xd0\x03\xe8\xcd"
-        "\x65\xbf\xf2\x11\xda\x14\x4b\x88\x29\x1c\x22\x59\xa0\x0a\x72\xb7"
-        "\x11\xc1\x16\xef\x76\x86\xe8\xfe\xe3\x4e\x4d\x93\x3c\x86\x81\x87"
-        "\xbd\xc2\x6f\x7b\xe0\x71\x49\x3c\x86\xf7\xa5\x94\x1c\x35\x10\x80"
-        "\x6a\xd6\x7b\x0f\x94\xd8\x8f\x5c\xf5\xc0\x2a\x09\x28\x21\xd8\x62"
-        "\x6e\x89\x32\xb6\x5c\x5b\xd8\xc9\x20\x49\xc2\x10\x93\x2b\x7a\xfa"
-        "\x7a\xc5\x9c\x0e\x88\x6a\xe5\xc1\xed\xb0\x0d\x8c\xe2\xc5\x76\x33"
-        "\xdb\x26\xbd\x66\x39\xbf\xf7\x3c\xee\x82\xbe\x92\x75\xc4\x02\xb4"
-        "\xcf\x2a\x43\x88\xda\x8c\xf8\xc6\x4e\xef\xe1\xc5\xa0\xf5\xab\x80"
-        "\x57\xc3\x9f\xa5\xc0\x58\x9c\x3e\x25\x3f\x09\x60\x33\x23\x00\xf9"
-        "\x4b\xea\x44\x87\x7b\x58\x8e\x1e\xdb\xde\x97\xcf\x23\x60\x72\x7a"
-        "\x09\xb7\x75\x26\x2d\x7e\xe5\x52\xb3\x31\x9b\x92\x66\xf0\x5a\x25";
-
-    static const unsigned char e[] = "\x01\x00\x01";
-
-    static const unsigned char d[] =
-        "\x6a\x7d\xf2\xca\x63\xea\xd4\xdd\xa1\x91\xd6\x14\xb6\xb3\x85\xe0"
-        "\xd9\x05\x6a\x3d\x6d\x5c\xfe\x07\xdb\x1d\xaa\xbe\xe0\x22\xdb\x08"
-        "\x21\x2d\x97\x61\x3d\x33\x28\xe0\x26\x7c\x9d\xd2\x3d\x78\x7a\xbd"
-        "\xe2\xaf\xcb\x30\x6a\xeb\x7d\xfc\xe6\x92\x46\xcc\x73\xf5\xc8\x7f"
-        "\xdf\x06\x03\x01\x79\xa2\x11\x4b\x76\x7d\xb1\xf0\x83\xff\x84\x1c"
-        "\x02\x5d\x7d\xc0\x0c\xd8\x24\x35\xb9\xa9\x0f\x69\x53\x69\xe9\x4d"
-        "\xf2\x3d\x2c\xe4\x58\xbc\x3b\x32\x83\xad\x8b\xba\x2b\x8f\xa1\xba"
-        "\x62\xe2\xdc\xe9\xac\xcf\xf3\x79\x9a\xae\x7c\x84\x00\x16\xf3\xba"
-        "\x8e\x00\x48\xc0\xb6\xcc\x43\x39\xaf\x71\x61\x00\x3a\x5b\xeb\x86"
-        "\x4a\x01\x64\xb2\xc1\xc9\x23\x7b\x64\xbc\x87\x55\x69\x94\x35\x1b"
-        "\x27\x50\x6c\x33\xd4\xbc\xdf\xce\x0f\x9c\x49\x1a\x7d\x6b\x06\x28"
-        "\xc7\xc8\x52\xbe\x4f\x0a\x9c\x31\x32\xb2\xed\x3a\x2c\x88\x81\xe9"
-        "\xaa\xb0\x7e\x20\xe1\x7d\xeb\x07\x46\x91\xbe\x67\x77\x76\xa7\x8b"
-        "\x5c\x50\x2e\x05\xd9\xbd\xde\x72\x12\x6b\x37\x38\x69\x5e\x2d\xd1"
-        "\xa0\xa9\x8a\x14\x24\x7c\x65\xd8\xa7\xee\x79\x43\x2a\x09\x2c\xb0"
-        "\x72\x1a\x12\xdf\x79\x8e\x44\xf7\xcf\xce\x0c\x49\x81\x47\xa9\xb1";
-
-    static const unsigned char p[] =
-        "\x06\x77\xcd\xd5\x46\x9b\xc1\xd5\x58\x00\x81\xe2\xf3\x0a\x36\xb1"
-        "\x6e\x29\x89\xd5\x2f\x31\x5f\x92\x22\x3b\x9b\x75\x30\x82\xfa\xc5"
-        "\xf5\xde\x8a\x36\xdb\xc6\xe5\x8f\xef\x14\x37\xd6\x00\xf9\xab\x90"
-        "\x9b\x5d\x57\x4c\xf5\x1f\x77\xc4\xbb\x8b\xdd\x9b\x67\x11\x45\xb2"
-        "\x64\xe8\xac\xa8\x03\x0f\x16\x0d\x5d\x2d\x53\x07\x23\xfb\x62\x0d"
-        "\xe6\x16\xd3\x23\xe8\xb3";
-
-    static const unsigned char q[] =
-        "\x06\x66\x9a\x70\x53\xd6\x72\x74\xfd\xea\x45\xc3\xc0\x17\xae\xde"
-        "\x79\x17\xae\x79\xde\xfc\x0e\xf7\xa4\x3a\x8c\x43\x8f\xc7\x8a\xa2"
-        "\x2c\x51\xc4\xd0\x72\x89\x73\x5c\x61\xbe\xfd\x54\x3f\x92\x65\xde"
-        "\x4d\x65\x71\x70\xf6\xf2\xe5\x98\xb9\x0f\xd1\x0b\xe6\x95\x09\x4a"
-        "\x7a\xdf\xf3\x10\x16\xd0\x60\xfc\xa5\x10\x34\x97\x37\x6f\x0a\xd5"
-        "\x5d\x8f\xd4\xc3\xa0\x5b";
-
-    static const unsigned char dmp1[] =
-        "\x05\x7c\x9e\x1c\xbd\x90\x25\xe7\x40\x86\xf5\xa8\x3b\x7a\x3f\x99"
-        "\x56\x95\x60\x3a\x7b\x95\x4b\xb8\xa0\xd7\xa5\xf1\xcc\xdc\x5f\xb5"
-        "\x8c\xf4\x62\x95\x54\xed\x2e\x12\x62\xc2\xe8\xf6\xde\xce\xed\x8e"
-        "\x77\x6d\xc0\x40\x25\x74\xb3\x5a\x2d\xaa\xe1\xac\x11\xcb\xe2\x2f"
-        "\x0a\x51\x23\x1e\x47\xb2\x05\x88\x02\xb2\x0f\x4b\xf0\x67\x30\xf0"
-        "\x0f\x6e\xef\x5f\xf7\xe7";
-
-    static const unsigned char dmq1[] =
-        "\x01\xa5\x6b\xbc\xcd\xe3\x0e\x46\xc6\x72\xf5\x04\x56\x28\x01\x22"
-        "\x58\x74\x5d\xbc\x1c\x3c\x29\x41\x49\x6c\x81\x5c\x72\xe2\xf7\xe5"
-        "\xa3\x8e\x58\x16\xe0\x0e\x37\xac\x1f\xbb\x75\xfd\xaf\xe7\xdf\xe9"
-        "\x1f\x70\xa2\x8f\x52\x03\xc0\x46\xd9\xf9\x96\x63\x00\x27\x7e\x5f"
-        "\x38\x60\xd6\x6b\x61\xe2\xaf\xbe\xea\x58\xd3\x9d\xbc\x75\x03\x8d"
-        "\x42\x65\xd6\x6b\x85\x97";
-
-    static const unsigned char iqmp[] =
-        "\x03\xa1\x8b\x80\xe4\xd8\x87\x25\x17\x5d\xcc\x8d\xa9\x8a\x22\x2b"
-        "\x6c\x15\x34\x6f\x80\xcc\x1c\x44\x04\x68\xbc\x03\xcd\x95\xbb\x69"
-        "\x37\x61\x48\xb4\x23\x13\x08\x16\x54\x6a\xa1\x7c\xf5\xd4\x3a\xe1"
-        "\x4f\xa4\x0c\xf5\xaf\x80\x85\x27\x06\x0d\x70\xc0\xc5\x19\x28\xfe"
-        "\xee\x8e\x86\x21\x98\x8a\x37\xb7\xe5\x30\x25\x70\x93\x51\x2d\x49"
-        "\x85\x56\xb3\x0c\x2b\x96";
-
-    static const unsigned char ex_prime[] =
-        "\x03\x89\x22\xa0\xb7\x3a\x91\xcb\x5e\x0c\xfd\x73\xde\xa7\x38\xa9"
-        "\x47\x43\xd6\x02\xbf\x2a\xb9\x3c\x48\xf3\x06\xd6\x58\x35\x50\x56"
-        "\x16\x5c\x34\x9b\x61\x87\xc8\xaa\x0a\x5d\x8a\x0a\xcd\x9c\x41\xd9"
-        "\x96\x24\xe0\xa9\x9b\x26\xb7\xa8\x08\xc9\xea\xdc\xa7\x15\xfb\x62"
-        "\xa0\x2d\x90\xe6\xa7\x55\x6e\xc6\x6c\xff\xd6\x10\x6d\xfa\x2e\x04"
-        "\x50\xec\x5c\x66\xe4\x05";
-
-    static const unsigned char ex_exponent[] =
-        "\x02\x0a\xcd\xc3\x82\xd2\x03\xb0\x31\xac\xd3\x20\x80\x34\x9a\x57"
-        "\xbc\x60\x04\x57\x25\xd0\x29\x9a\x16\x90\xb9\x1c\x49\x6a\xd1\xf2"
-        "\x47\x8c\x0e\x9e\xc9\x20\xc2\xd8\xe4\x8f\xce\xd2\x1a\x9c\xec\xb4"
-        "\x1f\x33\x41\xc8\xf5\x62\xd1\xa5\xef\x1d\xa1\xd8\xbd\x71\xc6\xf7"
-        "\xda\x89\x37\x2e\xe2\xec\x47\xc5\xb8\xe3\xb4\xe3\x5c\x82\xaa\xdd"
-        "\xb7\x58\x2e\xaf\x07\x79";
-
-    static const unsigned char ex_coefficient[] =
-        "\x00\x9c\x09\x88\x9b\xc8\x57\x08\x69\x69\xab\x2d\x9e\x29\x1c\x3c"
-        "\x6d\x59\x33\x12\x0d\x2b\x09\x2e\xaf\x01\x2c\x27\x01\xfc\xbd\x26"
-        "\x13\xf9\x2d\x09\x22\x4e\x49\x11\x03\x82\x88\x87\xf4\x43\x1d\xac"
-        "\xca\xec\x86\xf7\x23\xf1\x64\xf3\xf5\x81\xf0\x37\x36\xcf\x67\xff"
-        "\x1a\xff\x7a\xc7\xf9\xf9\x67\x2d\xa0\x9d\x61\xf8\xf6\x47\x5c\x2f"
-        "\xe7\x66\xe8\x3c\x3a\xe8";
-
-    BIGNUM **pris = NULL, **exps = NULL, **coeffs = NULL;
-    int rv = 256; /* public key length */
-
     if (!TEST_int_eq(RSA_set0_key(key,
                                   BN_bin2bn(n, sizeof(n) - 1, NULL),
                                   BN_bin2bn(e, sizeof(e) - 1, NULL),
                                   BN_bin2bn(d, sizeof(d) - 1, NULL)), 1))
-        goto err;
+        return 0;
+
+    return RSA_size(key);
+}
+
+static int key2048p3_v1(RSA *key)
+{
+    BIGNUM **pris = NULL, **exps = NULL, **coeffs = NULL;
+    int rv = RSA_size(key);
+
 
     if (!TEST_int_eq(RSA_set0_factors(key,
                                       BN_bin2bn(p, sizeof(p) - 1, NULL),
@@ -183,7 +192,57 @@ static int key2048p3(RSA *key)
     goto ret;
 }
 
-static int test_rsa_mp(void)
+static int key2048p3_v2(RSA *key)
+{
+    STACK_OF(BIGNUM) *primes = NULL, *exps = NULL, *coeffs = NULL;
+    BIGNUM *num = NULL;
+    int rv = RSA_size(key);
+
+    if (!TEST_ptr(primes = sk_BIGNUM_new_null())
+        || !TEST_ptr(exps = sk_BIGNUM_new_null())
+        || !TEST_ptr(coeffs = sk_BIGNUM_new_null()))
+        goto err;
+
+    if (!TEST_ptr(num = BN_bin2bn(p, sizeof(p) - 1, NULL))
+        || !TEST_int_ne(sk_BIGNUM_push(primes, num), 0)
+        || !TEST_ptr(num = BN_bin2bn(q, sizeof(q) - 1, NULL))
+        || !TEST_int_ne(sk_BIGNUM_push(primes, num), 0)
+        || !TEST_ptr(num = BN_bin2bn(ex_prime, sizeof(ex_prime) - 1, NULL))
+        || !TEST_int_ne(sk_BIGNUM_push(primes, num), 0))
+        goto err;
+
+    if (!TEST_ptr(num = BN_bin2bn(dmp1, sizeof(dmp1) - 1, NULL))
+        || !TEST_int_ne(sk_BIGNUM_push(exps, num), 0)
+        || !TEST_ptr(num = BN_bin2bn(dmq1, sizeof(dmq1) - 1, NULL))
+        || !TEST_int_ne(sk_BIGNUM_push(exps, num), 0)
+        || !TEST_ptr(num = BN_bin2bn(ex_exponent, sizeof(ex_exponent) - 1, NULL))
+        || !TEST_int_ne(sk_BIGNUM_push(exps, num), 0))
+        goto err;
+
+    if (!TEST_ptr(num = BN_bin2bn(iqmp, sizeof(iqmp) - 1, NULL))
+        || !TEST_int_ne(sk_BIGNUM_push(coeffs, num), 0)
+        || !TEST_ptr(num = BN_bin2bn(ex_coefficient, sizeof(ex_coefficient) - 1, NULL))
+        || !TEST_int_ne(sk_BIGNUM_push(coeffs, num), 0))
+        goto err;
+
+    if (!TEST_true(rsa_set0_all_params(key, primes, exps, coeffs)))
+        goto err;
+
+ ret:
+    sk_BIGNUM_free(primes);
+    sk_BIGNUM_free(exps);
+    sk_BIGNUM_free(coeffs);
+    return rv;
+ err:
+    sk_BIGNUM_pop_free(primes, BN_free);
+    sk_BIGNUM_pop_free(exps, BN_free);
+    sk_BIGNUM_pop_free(coeffs, BN_free);
+    primes = exps = coeffs = NULL;
+    rv = 0;
+    goto ret;
+}
+
+static int test_rsa_mp(int i)
 {
     int ret = 0;
     RSA *key;
@@ -193,13 +252,18 @@ static int test_rsa_mp(void)
     int plen;
     int clen = 0;
     int num;
+    static int (*param_set[])(RSA *) = {
+        key2048p3_v1,
+        key2048p3_v2,
+    };
 
     plen = sizeof(ptext_ex) - 1;
     key = RSA_new();
     if (!TEST_ptr(key))
         goto err;
-    clen = key2048p3(key);
-    if (!TEST_int_eq(clen, 256))
+
+    if (!TEST_int_eq((clen = key2048_key(key)), 256)
+        || !TEST_int_eq((clen = param_set[i](key)), 256))
         goto err;
 
     if (!TEST_true(RSA_check_key_ex(key, NULL)))
@@ -224,7 +288,7 @@ err:
 int setup_tests(void)
 {
 #ifndef OPENSSL_NO_RSA
-    ADD_TEST(test_rsa_mp);
+    ADD_ALL_TESTS(test_rsa_mp, 2);
 #endif
     return 1;
 }


More information about the openssl-commits mailing list