RSA: Extract much of the rsa_pkey_export_to() code to a separate function
authorRichard Levitte <levitte@openssl.org>
Sat, 2 May 2020 11:02:29 +0000 (13:02 +0200)
committerRichard Levitte <levitte@openssl.org>
Thu, 14 May 2020 10:16:34 +0000 (12:16 +0200)
The resulting function, rsa_todata(), is designed to be usable by
providers as well.

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11710)

crypto/rsa/rsa_ameth.c
crypto/rsa/rsa_backend.c
include/crypto/rsa.h

index b530754..95350f5 100644 (file)
@@ -1100,10 +1100,6 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
 {
     RSA *rsa = from->pkey.rsa;
     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;
-    int numprimes = 0, numexps = 0, numcoeffs = 0;
     OSSL_PARAM *params = NULL;
     int selection = 0;
     int rv = 0;
@@ -1118,65 +1114,16 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
         goto err;
 
     /* Public parameters must always be present */
-    if (n == NULL || e == NULL)
+    if (RSA_get0_n(rsa) == NULL || RSA_get0_e(rsa) == NULL)
         goto err;
 
-    /* |e| and |n| are always present */
-    if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, e))
+    if (!rsa_todata(rsa, tmpl, NULL))
         goto err;
-    if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, n))
-        goto err;
-    selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
-
-    if (d != NULL) {
-        int i;
-
-        /* 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;
-
-        numprimes = sk_BIGNUM_const_num(primes);
-        numexps = sk_BIGNUM_const_num(exps);
-        numcoeffs = sk_BIGNUM_const_num(coeffs);
-
-        /*
-         * It's permisssible to have zero primes, i.e. no CRT params.
-         * Otherwise, there must be at least two, as many exponents,
-         * and one coefficient less.
-         */
-        if (numprimes != 0
-            && (numprimes < 2 || numexps < 2 || numcoeffs < 1))
-            goto err;
-
-        if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, d))
-            goto err;
+    selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+    if (RSA_get0_d(rsa) != NULL)
         selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
 
-        for (i = 0; i < numprimes  && rsa_mp_factor_names[i] != NULL; i++) {
-            const BIGNUM *num = sk_BIGNUM_const_value(primes, i);
-
-            if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_factor_names[i], num))
-                goto err;
-        }
-
-        for (i = 0; i < numexps && rsa_mp_exp_names[i] != NULL; i++) {
-            const BIGNUM *num = sk_BIGNUM_const_value(exps, i);
-
-            if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_exp_names[i], num))
-                goto err;
-        }
-
-        for (i = 0; i < numcoeffs && rsa_mp_coeff_names[i] != NULL; i++) {
-            const BIGNUM *num = sk_BIGNUM_const_value(coeffs, i);
-
-            if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_coeff_names[i], num))
-                goto err;
-        }
     }
 
     if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
index 57a539c..cf0bff0 100644 (file)
@@ -97,3 +97,52 @@ int rsa_fromdata(RSA *rsa, const OSSL_PARAM params[])
     return 0;
 }
 
+DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
+
+int rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
+{
+    int ret = 0;
+    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);
+
+    /* Check private key data integrity */
+    if (rsa_d != NULL) {
+        int numprimes = sk_BIGNUM_const_num(factors);
+        int numexps = sk_BIGNUM_const_num(exps);
+        int numcoeffs = sk_BIGNUM_const_num(coeffs);
+
+        /*
+         * It's permisssible to have zero primes, i.e. no CRT params.
+         * Otherwise, there must be at least two, as many exponents,
+         * and one coefficient less.
+         */
+        if (numprimes != 0
+            && (numprimes < 2 || numexps < 2 || numcoeffs < 1))
+            goto err;
+    }
+
+    if (!ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_RSA_N, rsa_n)
+        || !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_RSA_E, rsa_e)
+        || !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_RSA_D, rsa_d)
+        || !ossl_param_build_set_multi_key_bn(bld, params, rsa_mp_factor_names,
+                                              factors)
+        || !ossl_param_build_set_multi_key_bn(bld, params, rsa_mp_exp_names,
+                                              exps)
+        || !ossl_param_build_set_multi_key_bn(bld, params, rsa_mp_coeff_names,
+                                              coeffs))
+        goto err;
+    ret = 1;
+ err:
+    sk_BIGNUM_const_free(factors);
+    sk_BIGNUM_const_free(exps);
+    sk_BIGNUM_const_free(coeffs);
+    return ret;
+}
index 7ce1fdb..321c7f8 100644 (file)
@@ -21,6 +21,8 @@ int rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes,
 int rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes,
                         STACK_OF(BIGNUM_const) *exps,
                         STACK_OF(BIGNUM_const) *coeffs);
+
+int rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]);
 int rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]);
 
 int rsa_padding_check_PKCS1_type_2_TLS(OPENSSL_CTX *ctx, unsigned char *to,