Added internal functions for easy getting and setting all RSA parameters.
authorRichard Levitte <levitte@openssl.org>
Tue, 15 Oct 2019 18:28:02 +0000 (20:28 +0200)
committerRichard Levitte <levitte@openssl.org>
Thu, 17 Oct 2019 16:07:45 +0000 (18:07 +0200)
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@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10190)

crypto/rsa/rsa_lib.c
include/crypto/rsa.h [new file with mode: 0644]
include/openssl/rsa.h
include/openssl/types.h
test/build.info
test/rsa_mp_test.c

index abdabfb45a341e4b6bb474e73c4e9d64062e8a4b..17ff7e76863554523cd0b113a7b38fd9b3241639 100644 (file)
@@ -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)
@@ -613,3 +614,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/include/crypto/rsa.h b/include/crypto/rsa.h
new file mode 100644 (file)
index 0000000..6d2e7ff
--- /dev/null
@@ -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
index 8ddc9703965a2a2eef7928fbfdd33a634c498163..9214efd49939e96fbbc0008d6acf6af97669d00a 100644 (file)
@@ -27,6 +27,8 @@
 #  include <openssl/bn.h>
 # endif
 # include <openssl/rsaerr.h>
+# include <openssl/safestack.h>
+
 # ifdef  __cplusplus
 extern "C" {
 # endif
index 73bf88d92d7666c1b975f543c48d3404f774e655..8cfeb6ee22e23719a7b8de374a79bd02fac7af1a 100644 (file)
@@ -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;
index 7328641243f41f0f220e1d3948fb17343167e7ad..2de9733bd58b2c86396891eccf78f6b9e0a33a56 100644 (file)
@@ -175,7 +175,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
index 79557082f2b21fa125392a32f3eb39d3412c30d7..baa9dd2272432c351b252c918a5ec843b4b3f0e6 100644 (file)
@@ -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>
 
 #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;
 }