Add EVP_PKEY_gettable_params support for accessing EVP_PKEY key data fields
authorShane Lontis <shane.lontis@oracle.com>
Wed, 1 Apr 2020 05:51:18 +0000 (15:51 +1000)
committerShane Lontis <shane.lontis@oracle.com>
Wed, 1 Apr 2020 05:51:18 +0000 (15:51 +1000)
Currently only RSA, EC and ECX are supported (DH and DSA need to be added to the keygen
PR's seperately because the fields supported have changed significantly).

The API's require the keys to be provider based.

Made the keymanagement export and get_params functions share the same code by supplying
support functions that work for both a OSSL_PARAM_BLD as well as a OSSL_PARAM[].
This approach means that complex code is not required to build an
empty OSSL_PARAM[] with the correct sized fields before then doing a second
pass to populate the array.

The RSA factor arrays have been changed to use unique key names to simplify the interface
needed by the user.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11365)

22 files changed:
crypto/build.info
crypto/evp/p_lib.c
crypto/param_build_set.c [new file with mode: 0644]
crypto/rsa/build.info
crypto/rsa/rsa_ameth.c
crypto/rsa/rsa_backend.c
crypto/rsa/rsa_mp_names.c [new file with mode: 0644]
doc/man3/EVP_PKEY_fromdata.pod
doc/man3/EVP_PKEY_gettable_params.pod [new file with mode: 0644]
doc/man7/provider-keymgmt.pod
include/crypto/rsa.h
include/internal/param_build_set.h [new file with mode: 0644]
include/openssl/core_names.h
include/openssl/evp.h
providers/implementations/keymgmt/build.info
providers/implementations/keymgmt/ec_kmgmt.c
providers/implementations/keymgmt/ecx_kmgmt.c
providers/implementations/keymgmt/rsa_kmgmt.c
providers/implementations/serializers/serializer_rsa.c
test/evp_pkey_provided_test.c
test/keymgmt_internal_test.c
util/libcrypto.num

index a688248..baa31ee 100644 (file)
@@ -70,7 +70,8 @@ SOURCE[../providers/libfips.a]=$CORE_COMMON
 $UTIL_COMMON=\
         cryptlib.c params.c params_from_text.c bsearch.c ex_data.c o_str.c \
         ctype.c threads_pthread.c threads_win.c threads_none.c initthread.c \
-        context.c sparse_array.c asn1_dsa.c packet.c param_build.c $CPUIDASM
+        context.c sparse_array.c asn1_dsa.c packet.c param_build.c $CPUIDASM \
+        param_build_set.c
 $UTIL_DEFINE=$CPUIDDEF
 
 SOURCE[../libcrypto]=$UTIL_COMMON \
index 9ed238e..b176f10 100644 (file)
@@ -1459,3 +1459,163 @@ int evp_pkey_downgrade(EVP_PKEY *pk)
     return 0;     /* No downgrade, but at least the key is restored */
 }
 #endif  /* FIPS_MODE */
+
+const OSSL_PARAM *EVP_PKEY_gettable_params(EVP_PKEY *pkey)
+{
+    if (pkey == NULL
+        || pkey->keymgmt == NULL
+        || pkey->keydata == NULL)
+        return 0;
+    return evp_keymgmt_gettable_params(pkey->keymgmt);
+}
+
+/*
+ * For the following methods param->return_size is set to a value
+ * larger than can be returned by the call to evp_keymgmt_get_params().
+ * If it is still this value then the parameter was ignored - and in this
+ * case it returns an error..
+ */
+
+int EVP_PKEY_get_bn_param(EVP_PKEY *pkey, const char *key_name, BIGNUM **bn)
+{
+    int ret = 0;
+    OSSL_PARAM params[2];
+    unsigned char buffer[2048];
+    /*
+     * Use -1 as the terminator here instead of sizeof(buffer) + 1 since
+     * -1 is less likely to be a valid value.
+     */
+    const size_t not_set = (size_t)-1;
+    unsigned char *buf = NULL;
+    size_t buf_sz = 0;
+
+    if (pkey == NULL
+        || pkey->keymgmt == NULL
+        || pkey->keydata == NULL
+        || key_name == NULL
+        || bn == NULL)
+        return 0;
+
+    memset(buffer, 0, sizeof(buffer));
+    params[0] = OSSL_PARAM_construct_BN(key_name, buffer, sizeof(buffer));
+    /* If the return_size is still not_set then we know it was not found */
+    params[0].return_size = not_set;
+    params[1] = OSSL_PARAM_construct_end();
+    if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params)) {
+        if (params[0].return_size == not_set
+            || params[0].return_size == 0)
+            return 0;
+        buf_sz = params[0].return_size;
+        /*
+         * If it failed because the buffer was too small then allocate the
+         * required buffer size and retry.
+         */
+        buf = OPENSSL_zalloc(buf_sz);
+        if (buf == NULL)
+            return 0;
+        params[0].data = buf;
+        params[0].data_size = buf_sz;
+
+        if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
+            goto err;
+    }
+    /* Fail if the param was not found */
+    if (params[0].return_size == not_set)
+        goto err;
+    ret = OSSL_PARAM_get_BN(params, bn);
+err:
+    OPENSSL_free(buf);
+    return ret;
+}
+
+int EVP_PKEY_get_octet_string_param(EVP_PKEY *pkey, const char *key_name,
+                                    unsigned char *buf, size_t max_buf_sz,
+                                    size_t *out_sz)
+{
+    OSSL_PARAM params[2];
+    const size_t not_set = max_buf_sz + 1;
+
+    if (pkey == NULL
+        || pkey->keymgmt == NULL
+        || pkey->keydata == NULL
+        || key_name == NULL)
+        return 0;
+
+    params[0] = OSSL_PARAM_construct_octet_string(key_name, buf, max_buf_sz);
+    params[0].return_size = not_set;
+    params[1] = OSSL_PARAM_construct_end();
+    if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
+        return 0;
+    if (params[0].return_size == not_set)
+        return 0;
+    if (out_sz != NULL)
+        *out_sz = params[0].return_size;
+    return 1;
+}
+
+int EVP_PKEY_get_utf8_string_param(EVP_PKEY *pkey, const char *key_name,
+                                    char *str, size_t max_buf_sz,
+                                    size_t *out_sz)
+{
+    OSSL_PARAM params[2];
+    const size_t not_set = max_buf_sz + 1;
+
+    if (pkey == NULL
+        || pkey->keymgmt == NULL
+        || pkey->keydata == NULL
+        || key_name == NULL)
+        return 0;
+
+    params[0] = OSSL_PARAM_construct_utf8_string(key_name, str, max_buf_sz);
+    params[0].return_size = not_set;
+    params[1] = OSSL_PARAM_construct_end();
+    if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
+        return 0;
+    if (params[0].return_size == not_set)
+        return 0;
+    if (out_sz != NULL)
+        *out_sz = params[0].return_size;
+    return 1;
+}
+
+int EVP_PKEY_get_int_param(EVP_PKEY *pkey, const char *key_name, int *out)
+{
+    OSSL_PARAM params[2];
+    const size_t not_set = sizeof(int) + 1;
+
+    if (pkey == NULL
+        || pkey->keymgmt == NULL
+        || pkey->keydata == NULL
+        || key_name == NULL)
+        return 0;
+
+    params[0] = OSSL_PARAM_construct_int(key_name, out);
+    params[0].return_size = not_set;
+    params[1] = OSSL_PARAM_construct_end();
+    if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
+        return 0;
+    if (params[0].return_size == not_set)
+        return 0;
+    return 1;
+}
+
+int EVP_PKEY_get_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t *out)
+{
+    OSSL_PARAM params[2];
+    const size_t not_set = sizeof(size_t) + 1;
+
+    if (pkey == NULL
+        || pkey->keymgmt == NULL
+        || pkey->keydata == NULL
+        || key_name == NULL)
+        return 0;
+
+    params[0] = OSSL_PARAM_construct_size_t(key_name, out);
+    params[0].return_size = not_set;
+    params[1] = OSSL_PARAM_construct_end();
+    if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
+        return 0;
+    if (params[0].return_size == not_set)
+        return 0;
+    return 1;
+}
diff --git a/crypto/param_build_set.c b/crypto/param_build_set.c
new file mode 100644 (file)
index 0000000..b74b0d5
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Key Management utility functions to share functionality between the export()
+ * and get_params() methods.
+ * export() uses OSSL_PARAM_BLD, and get_params() used the OSSL_PARAM[] to
+ * fill in parameter data for the same key and data fields.
+ */
+
+#include <openssl/core_names.h>
+#include "internal/param_build_set.h"
+
+DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
+
+int ossl_param_build_set_int(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+                             const char *key, int num)
+{
+    if (bld != NULL)
+        return OSSL_PARAM_BLD_push_int(bld, key, num);
+    p = OSSL_PARAM_locate(p, key);
+    if (p != NULL)
+        return OSSL_PARAM_set_int(p, num);
+    return 1;
+}
+
+int ossl_param_build_set_utf8_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+                                     const char *key, const char *buf)
+{
+    if (bld != NULL)
+        return OSSL_PARAM_BLD_push_utf8_string(bld, key, buf, 0);
+    p = OSSL_PARAM_locate(p, key);
+    if (p != NULL)
+        return OSSL_PARAM_set_utf8_string(p, buf);
+    return 1;
+}
+
+int ossl_param_build_set_octet_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+                                      const char *key,
+                                      const unsigned char *data,
+                                      size_t data_len)
+{
+    if (bld != NULL)
+        return OSSL_PARAM_BLD_push_octet_string(bld, key, data, data_len);
+
+    p = OSSL_PARAM_locate(p, key);
+    if (p != NULL)
+        return OSSL_PARAM_set_octet_string(p, data, data_len);
+    return 1;
+}
+
+int ossl_param_build_set_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+                                const char *key, const BIGNUM *bn,  size_t sz)
+{
+    if (bld != NULL)
+        return OSSL_PARAM_BLD_push_BN_pad(bld, key, bn, sz);
+    p = OSSL_PARAM_locate(p, key);
+    if (p != NULL) {
+        if (sz > p->data_size)
+            return 0;
+        /* TODO(3.0) Change to use OSSL_PARAM_set_BN_pad */
+        p->data_size = sz;
+        return OSSL_PARAM_set_BN(p, bn);
+    }
+    return 1;
+}
+
+int ossl_param_build_set_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+                            const char *key, const BIGNUM *bn)
+{
+    if (bld != NULL)
+        return OSSL_PARAM_BLD_push_BN(bld, key, bn);
+
+    p = OSSL_PARAM_locate(p, key);
+    if (p != NULL)
+        return OSSL_PARAM_set_BN(p, bn) > 0;
+    return 1;
+}
+
+int ossl_param_build_set_multi_key_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *params,
+                                      const char *names[],
+                                      STACK_OF(BIGNUM_const) *stk)
+{
+    int i, sz = sk_BIGNUM_const_num(stk);
+    OSSL_PARAM *p;
+
+
+    if (bld != NULL) {
+        for (i = 0; i < sz && names[i] != NULL; ++i) {
+            if (!OSSL_PARAM_BLD_push_BN(bld, names[i],
+                                        sk_BIGNUM_const_value(stk, i)))
+                return 0;
+        }
+        return 1;
+    }
+
+    for (i = 0; i < sz && names[i] != NULL; ++i) {
+        p = OSSL_PARAM_locate(params, names[i]);
+        if (p != NULL) {
+            if (!OSSL_PARAM_set_BN(p, sk_BIGNUM_const_value(stk, i)))
+                return 0;
+        }
+    }
+    return 1;
+}
index c1d1a37..7921202 100644 (file)
@@ -2,7 +2,8 @@ LIBS=../../libcrypto
 
 $COMMON=rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_aid.c rsa_pk1.c \
         rsa_none.c rsa_oaep.c rsa_chk.c rsa_pss.c rsa_x931.c rsa_crpt.c \
-        rsa_x931g.c rsa_sp800_56b_gen.c rsa_sp800_56b_check.c rsa_backend.c
+        rsa_x931g.c rsa_sp800_56b_gen.c rsa_sp800_56b_check.c rsa_backend.c \
+        rsa_mp_names.c
 
 SOURCE[../../libcrypto]=$COMMON\
         rsa_saos.c rsa_err.c rsa_asn1.c rsa_depr.c rsa_ameth.c rsa_prn.c \
index ec8df4a..fb378ae 100644 (file)
@@ -20,7 +20,7 @@
 #include <openssl/bn.h>
 #include <openssl/cms.h>
 #include <openssl/core_names.h>
-#include "openssl/param_build.h"
+#include <openssl/param_build.h>
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
 #include "crypto/rsa.h"
@@ -1142,27 +1142,24 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
             goto err;
         selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
 
-        for (i = 0; i < numprimes; i++) {
+        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, OSSL_PKEY_PARAM_RSA_FACTOR,
-                                        num))
+            if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_factor_names[i], num))
                 goto err;
         }
 
-        for (i = 0; i < numexps; i++) {
+        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, OSSL_PKEY_PARAM_RSA_EXPONENT,
-                                        num))
+            if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_exp_names[i], num))
                 goto err;
         }
 
-        for (i = 0; i < numcoeffs; i++) {
+        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, OSSL_PKEY_PARAM_RSA_COEFFICIENT,
-                                        num))
+            if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_coeff_names[i], num))
                 goto err;
         }
     }
index f68d38c..57a539c 100644 (file)
 DEFINE_STACK_OF(BIGNUM)
 
 static int collect_numbers(STACK_OF(BIGNUM) *numbers,
-                           const OSSL_PARAM params[], const char *key)
+                           const OSSL_PARAM params[], const char *names[])
 {
     const OSSL_PARAM *p = NULL;
+    int i;
 
     if (numbers == NULL)
         return 0;
 
-    for (p = params; (p = OSSL_PARAM_locate_const(p, key)) != NULL; p++) {
-        BIGNUM *tmp = NULL;
+    for (i = 0; names[i] != NULL; i++){
+        p = OSSL_PARAM_locate_const(params, names[i]);
+        if (p != NULL) {
+            BIGNUM *tmp = NULL;
 
-        if (!OSSL_PARAM_get_BN(p, &tmp)
-            || sk_BIGNUM_push(numbers, tmp) == 0)
-            return 0;
+            if (!OSSL_PARAM_get_BN(p, &tmp)
+                || sk_BIGNUM_push(numbers, tmp) == 0)
+                return 0;
+        }
     }
 
     return 1;
@@ -65,11 +69,11 @@ int rsa_fromdata(RSA *rsa, const OSSL_PARAM params[])
 
     if (is_private) {
         if (!collect_numbers(factors = sk_BIGNUM_new_null(), params,
-                             OSSL_PKEY_PARAM_RSA_FACTOR)
+                             rsa_mp_factor_names)
             || !collect_numbers(exps = sk_BIGNUM_new_null(), params,
-                                OSSL_PKEY_PARAM_RSA_EXPONENT)
+                                rsa_mp_exp_names)
             || !collect_numbers(coeffs = sk_BIGNUM_new_null(), params,
-                                OSSL_PKEY_PARAM_RSA_COEFFICIENT))
+                                rsa_mp_coeff_names))
             goto err;
 
         /* It's ok if this private key just has n, e and d */
diff --git a/crypto/rsa/rsa_mp_names.c b/crypto/rsa/rsa_mp_names.c
new file mode 100644 (file)
index 0000000..e69321a
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_names.h>
+#include "crypto/rsa.h"
+
+/*
+ * The following tables are constants used during RSA parameter building
+ * operations. It is easier to point to one of these fixed strings than have
+ * to dynamically add and generate the names on the fly.
+ */
+
+/*
+ * A fixed table of names for the RSA prime factors starting with
+ * P,Q and up to 8 additional primes.
+ */
+const char *rsa_mp_factor_names[] = {
+    OSSL_PKEY_PARAM_RSA_FACTOR1,
+    OSSL_PKEY_PARAM_RSA_FACTOR2,
+#ifndef FIPS_MODE
+    OSSL_PKEY_PARAM_RSA_FACTOR3,
+    OSSL_PKEY_PARAM_RSA_FACTOR4,
+    OSSL_PKEY_PARAM_RSA_FACTOR5,
+    OSSL_PKEY_PARAM_RSA_FACTOR6,
+    OSSL_PKEY_PARAM_RSA_FACTOR7,
+    OSSL_PKEY_PARAM_RSA_FACTOR8,
+    OSSL_PKEY_PARAM_RSA_FACTOR9,
+    OSSL_PKEY_PARAM_RSA_FACTOR10,
+#endif
+    NULL
+};
+
+/*
+ * A fixed table of names for the RSA exponents starting with
+ * DP,DQ and up to 8 additional exponents.
+ */
+const char *rsa_mp_exp_names[] = {
+    OSSL_PKEY_PARAM_RSA_EXPONENT1,
+    OSSL_PKEY_PARAM_RSA_EXPONENT2,
+#ifndef FIPS_MODE
+    OSSL_PKEY_PARAM_RSA_EXPONENT3,
+    OSSL_PKEY_PARAM_RSA_EXPONENT4,
+    OSSL_PKEY_PARAM_RSA_EXPONENT5,
+    OSSL_PKEY_PARAM_RSA_EXPONENT6,
+    OSSL_PKEY_PARAM_RSA_EXPONENT7,
+    OSSL_PKEY_PARAM_RSA_EXPONENT8,
+    OSSL_PKEY_PARAM_RSA_EXPONENT9,
+    OSSL_PKEY_PARAM_RSA_EXPONENT10,
+#endif
+    NULL
+};
+
+/*
+ * A fixed table of names for the RSA coefficients starting with
+ * QINV and up to 8 additional exponents.
+ */
+const char *rsa_mp_coeff_names[] = {
+    OSSL_PKEY_PARAM_RSA_COEFFICIENT1,
+    OSSL_PKEY_PARAM_RSA_COEFFICIENT2,
+#ifndef FIPS_MODE
+    OSSL_PKEY_PARAM_RSA_COEFFICIENT3,
+    OSSL_PKEY_PARAM_RSA_COEFFICIENT4,
+    OSSL_PKEY_PARAM_RSA_COEFFICIENT5,
+    OSSL_PKEY_PARAM_RSA_COEFFICIENT6,
+    OSSL_PKEY_PARAM_RSA_COEFFICIENT7,
+    OSSL_PKEY_PARAM_RSA_COEFFICIENT8,
+    OSSL_PKEY_PARAM_RSA_COEFFICIENT9,
+#endif
+    NULL
+};
index 2d0059d..e3ddf68 100644 (file)
@@ -52,7 +52,7 @@ not supported by the public key algorithm.
 
 =head1 SEE ALSO
 
-L<EVP_PKEY_CTX_new(3)>, L<provider(7)>
+L<EVP_PKEY_CTX_new(3)>, L<provider(7)>, L<EVP_PKEY_gettable_params(3)>
 
 =head1 HISTORY
 
diff --git a/doc/man3/EVP_PKEY_gettable_params.pod b/doc/man3/EVP_PKEY_gettable_params.pod
new file mode 100644 (file)
index 0000000..87d25c7
--- /dev/null
@@ -0,0 +1,108 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_gettable_params, EVP_PKEY_get_int_param, EVP_PKEY_get_size_t_param,
+EVP_PKEY_get_bn_param, EVP_PKEY_get_utf8_string_param,
+EVP_PKEY_get_octet_string_param
+- retrieve key parameters from a key
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ const OSSL_PARAM *EVP_PKEY_gettable_params(EVP_PKEY *pkey);
+ int EVP_PKEY_get_int_param(EVP_PKEY *pkey, const char *key_name, int *out);
+ int EVP_PKEY_get_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t *out);
+ int EVP_PKEY_get_bn_param(EVP_PKEY *pkey, const char *key_name, BIGNUM **bn);
+ int EVP_PKEY_get_utf8_string_param(EVP_PKEY *pkey, const char *key_name,
+                                    char *str, size_t max_buf_sz, size_t *out_sz);
+ int EVP_PKEY_get_octet_string_param(EVP_PKEY *pkey, const char *key_name,
+                                    unsigned char *buf, size_t max_buf_sz,
+                                    size_t *out_sz);
+
+=head1 DESCRIPTION
+
+EVP_PKEY_gettable_params() returns a constant list of I<params> indicating
+the names and types of key parameters that can be retrieved.
+See L<OSSL_PARAM(3)> for information about parameters.
+
+EVP_PKEY_get_int_param() retrieves a key I<pkey> integer value I<*out>
+associated with a name of I<key_name>.
+
+EVP_PKEY_get_size_t_param() retrieves a key I<pkey> size_t value I<*out>
+associated with a name of I<key_name>.
+
+EVP_PKEY_get_bn_param() retrieves a key I<pkey> BIGNUM value I<**bn>
+associated with a name of I<key_name>. If I<*bn> is NULL then the BIGNUM
+is allocated by the method.
+
+EVP_PKEY_get_utf8_string_param() get a key I<pkey> UTF8 string value int a buffer
+I<str> of maximum size I<max_buf_sz> associated with a name of I<key_name>.
+I<*out_sz> is the returned size of the string if it is not NULL.
+
+EVP_PKEY_get_octet_string_param() copy a I<pkey>'s octet string value into a buffer
+I<buf> of maximum size I<max_buf_sz> associated with a name of I<key_name>.
+I<*out_sz> is the returned size of the buffer if it is not NULL.
+
+=head1 NOTES
+
+These functions only work for B<EVP_PKEY>s that contain a provider side key.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_gettable_params() returns NULL on error or if it is not supported,
+
+All other methods return 1 if a value associated with the key's I<key_name> was
+successfully returned, or 0 if there was an error.
+An error may be returned by methods EVP_PKEY_get_utf8_string_param() and
+EVP_PKEY_get_octet_string_param() if I<max_buf_sz> is not big enough to hold the
+value.
+
+=head1 EXAMPLES
+
+ #include <openssl/evp.h>
+
+ char *curve_name[64];
+ unsigned char pub[256];
+ BIGNUM *bn_priv = NULL;
+
+ /*
+  * NB: assumes 'key' is set up before the next step. In this example the key
+  * is an EC key.
+  */
+
+ if (!EVP_PKEY_get_utf8_string_param(key, OSSL_PKEY_PARAM_EC_NAME,
+                                     curve_name, sizeof(curve_name), &len)) {
+   /* Error */
+ }
+ if (!EVP_PKEY_get_octet_string_param(key, OSSL_PKEY_PARAM_PUB_KEY,
+                                      pub, sizeof(pub), &len)) {
+     /* Error */
+ }
+ if (!EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_PRIV_KEY, &bn_priv)) {
+     /* Error */
+ }
+
+
+ BN_clear_free(bn_priv);
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>, L<provider-keymgmt(7)>, L<OSSL_PARAM(3)>
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 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
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
index 59e538d..00596a0 100644 (file)
@@ -334,20 +334,74 @@ The RSA "e" value.
 
 The RSA "d" value.
 
-=item "rsa-factor" (B<OSSL_PKEY_PARAM_RSA_FACTOR>) <unsigned integer>
+=item "rsa-factor1" (B<OSSL_PKEY_PARAM_RSA_FACTOR1>) <unsigned integer>
 
-An RSA factor. In 2 prime RSA these are often known as "p" or "q". This value
-may be repeated up to 10 times in a single key.
+=item "rsa-factor2" (B<OSSL_PKEY_PARAM_RSA_FACTOR2>) <unsigned integer>
 
-=item "rsa-exponent" (B<OSSL_PKEY_PARAM_RSA_EXPONENT>) <unsigned integer>
+=item "rsa-factor3" (B<OSSL_PKEY_PARAM_RSA_FACTOR3>) <unsigned integer>
 
-An RSA CRT (Chinese Remainder Theorem) exponent. This value may be repeated up
-to 10 times in a single key.
+=item "rsa-factor4" (B<OSSL_PKEY_PARAM_RSA_FACTOR4>) <unsigned integer>
 
-=item "rsa-coefficient" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT>) <unsigned integer>
+=item "rsa-factor5" (B<OSSL_PKEY_PARAM_RSA_FACTOR5>) <unsigned integer>
 
-An RSA CRT (Chinese Remainder Theorem) coefficient. This value may be repeated
-up to 9 times in a single key.
+=item "rsa-factor6" (B<OSSL_PKEY_PARAM_RSA_FACTOR6>) <unsigned integer>
+
+=item "rsa-factor7" (B<OSSL_PKEY_PARAM_RSA_FACTOR7>) <unsigned integer>
+
+=item "rsa-factor8" (B<OSSL_PKEY_PARAM_RSA_FACTOR8>) <unsigned integer>
+
+=item "rsa-factor9" (B<OSSL_PKEY_PARAM_RSA_FACTOR9>) <unsigned integer>
+
+=item "rsa-factor10" (B<OSSL_PKEY_PARAM_RSA_FACTOR10>) <unsigned integer>
+
+RSA prime factors. The factors are known as "p", "q" and "r_i" in RFC8017.
+Up to eight additional "r_i" prime factors are supported.
+
+=item "rsa-exponent1" (B<OSSL_PKEY_PARAM_RSA_EXPONENT1>) <unsigned integer>
+
+=item "rsa-exponent2" (B<OSSL_PKEY_PARAM_RSA_EXPONENT2>) <unsigned integer>
+
+=item "rsa-exponent3" (B<OSSL_PKEY_PARAM_RSA_EXPONENT3>) <unsigned integer>
+
+=item "rsa-exponent4" (B<OSSL_PKEY_PARAM_RSA_EXPONENT4>) <unsigned integer>
+
+=item "rsa-exponent5" (B<OSSL_PKEY_PARAM_RSA_EXPONENT5>) <unsigned integer>
+
+=item "rsa-exponent6" (B<OSSL_PKEY_PARAM_RSA_EXPONENT6>) <unsigned integer>
+
+=item "rsa-exponent7" (B<OSSL_PKEY_PARAM_RSA_EXPONENT7>) <unsigned integer>
+
+=item "rsa-exponent8" (B<OSSL_PKEY_PARAM_RSA_EXPONENT8>) <unsigned integer>
+
+=item "rsa-exponent9" (B<OSSL_PKEY_PARAM_RSA_EXPONENT9>) <unsigned integer>
+
+=item "rsa-exponent10" (B<OSSL_PKEY_PARAM_RSA_EXPONENT10>) <unsigned integer>
+
+RSA CRT (Chinese Remainder Theorem) exponents. The exponents are known
+as "dP", "dQ" and "d_i in RFC8017".
+Up to eight additional "d_i" exponents are supported.
+
+=item "rsa-coefficient1" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT1>) <unsigned integer>
+
+=item "rsa-coefficient2" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT2>) <unsigned integer>
+
+=item "rsa-coefficient3" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT3>) <unsigned integer>
+
+=item "rsa-coefficient4" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT4>) <unsigned integer>
+
+=item "rsa-coefficient5" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT5>) <unsigned integer>
+
+=item "rsa-coefficient6" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT6>) <unsigned integer>
+
+=item "rsa-coefficient7" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT7>) <unsigned integer>
+
+=item "rsa-coefficient8" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT8>) <unsigned integer>
+
+=item "rsa-coefficient9" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT9>) <unsigned integer>
+
+RSA CRT (Chinese Remainder Theorem) coefficients. The coefficients are known as
+"qInv" and "t_i".
+Up to eight additional "t_i" exponents are supported.
 
 =back
 
@@ -427,11 +481,13 @@ The private key value.
 
 See L<OSSL_PARAM(3)> for further details on the parameters structure.
 
-Parameters currently recognised by built-in keymgmt algorithms
-are as follows.
+The Built-in Import/Export Types listed above are also Information Parameters.
 Not all parameters are relevant to, or are understood by all keymgmt
 algorithms:
 
+Parameters currently recognised by built-in keymgmt algorithms
+also include the following.
+
 =over 4
 
 =item "bits" (B<OSSL_PKEY_PARAM_BITS>) <integer>
index a92e666..3a85510 100644 (file)
@@ -40,4 +40,8 @@ int int_rsa_verify(int dtype, const unsigned char *m,
 const unsigned char *rsa_digestinfo_encoding(int md_nid, size_t *len);
 const unsigned char *rsa_algorithmidentifier_encoding(int md_nid, size_t *len);
 
+extern const char *rsa_mp_factor_names[];
+extern const char *rsa_mp_exp_names[];
+extern const char *rsa_mp_coeff_names[];
+
 #endif
diff --git a/include/internal/param_build_set.h b/include/internal/param_build_set.h
new file mode 100644 (file)
index 0000000..36d3b91
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/safestack.h>
+#include <openssl/param_build.h>
+
+int ossl_param_build_set_int(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+                             const char *key, int num);
+int ossl_param_build_set_utf8_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+                                     const char *key, const char *buf);
+int ossl_param_build_set_octet_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+                                      const char *key,
+                                      const unsigned char *data,
+                                      size_t data_len);
+int ossl_param_build_set_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+                            const char *key, const BIGNUM *bn);
+int ossl_param_build_set_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+                                const char *key, const BIGNUM *bn,  size_t sz);
+int ossl_param_build_set_multi_key_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+                                      const char *names[],
+                                      STACK_OF(BIGNUM_const) *stk);
index 2d48f00..c8a8828 100644 (file)
@@ -220,6 +220,37 @@ extern "C" {
 #define OSSL_PKEY_PARAM_RSA_FACTOR      "rsa-factor"
 #define OSSL_PKEY_PARAM_RSA_EXPONENT    "rsa-exponent"
 #define OSSL_PKEY_PARAM_RSA_COEFFICIENT "rsa-coefficient"
+#define OSSL_PKEY_PARAM_RSA_FACTOR1      OSSL_PKEY_PARAM_RSA_FACTOR"1"
+#define OSSL_PKEY_PARAM_RSA_FACTOR2      OSSL_PKEY_PARAM_RSA_FACTOR"2"
+#define OSSL_PKEY_PARAM_RSA_FACTOR3      OSSL_PKEY_PARAM_RSA_FACTOR"3"
+#define OSSL_PKEY_PARAM_RSA_FACTOR4      OSSL_PKEY_PARAM_RSA_FACTOR"4"
+#define OSSL_PKEY_PARAM_RSA_FACTOR5      OSSL_PKEY_PARAM_RSA_FACTOR"5"
+#define OSSL_PKEY_PARAM_RSA_FACTOR6      OSSL_PKEY_PARAM_RSA_FACTOR"6"
+#define OSSL_PKEY_PARAM_RSA_FACTOR7      OSSL_PKEY_PARAM_RSA_FACTOR"7"
+#define OSSL_PKEY_PARAM_RSA_FACTOR8      OSSL_PKEY_PARAM_RSA_FACTOR"8"
+#define OSSL_PKEY_PARAM_RSA_FACTOR9      OSSL_PKEY_PARAM_RSA_FACTOR"9"
+#define OSSL_PKEY_PARAM_RSA_FACTOR10     OSSL_PKEY_PARAM_RSA_FACTOR"10"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT1    OSSL_PKEY_PARAM_RSA_EXPONENT"1"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT2    OSSL_PKEY_PARAM_RSA_EXPONENT"2"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT3    OSSL_PKEY_PARAM_RSA_EXPONENT"3"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT4    OSSL_PKEY_PARAM_RSA_EXPONENT"4"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT5    OSSL_PKEY_PARAM_RSA_EXPONENT"5"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT6    OSSL_PKEY_PARAM_RSA_EXPONENT"6"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT7    OSSL_PKEY_PARAM_RSA_EXPONENT"7"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT8    OSSL_PKEY_PARAM_RSA_EXPONENT"8"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT9    OSSL_PKEY_PARAM_RSA_EXPONENT"9"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT10   OSSL_PKEY_PARAM_RSA_EXPONENT"10"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT1 OSSL_PKEY_PARAM_RSA_COEFFICIENT"1"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT2 OSSL_PKEY_PARAM_RSA_COEFFICIENT"2"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT3 OSSL_PKEY_PARAM_RSA_COEFFICIENT"3"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT4 OSSL_PKEY_PARAM_RSA_COEFFICIENT"4"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT5 OSSL_PKEY_PARAM_RSA_COEFFICIENT"5"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT6 OSSL_PKEY_PARAM_RSA_COEFFICIENT"6"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT7 OSSL_PKEY_PARAM_RSA_COEFFICIENT"7"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT8 OSSL_PKEY_PARAM_RSA_COEFFICIENT"8"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT9 OSSL_PKEY_PARAM_RSA_COEFFICIENT"9"
+
+
 /* Key generation parameters */
 #define OSSL_PKEY_PARAM_RSA_BITS        OSSL_PKEY_PARAM_BITS
 #define OSSL_PKEY_PARAM_RSA_PRIMES      "primes"
index d461f24..4903fc5 100644 (file)
@@ -1593,6 +1593,16 @@ int EVP_PKEY_key_fromdata_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, OSSL_PARAM param[]);
 const OSSL_PARAM *EVP_PKEY_param_fromdata_settable(EVP_PKEY_CTX *ctx);
 const OSSL_PARAM *EVP_PKEY_key_fromdata_settable(EVP_PKEY_CTX *ctx);
+const OSSL_PARAM *EVP_PKEY_gettable_params(EVP_PKEY *pkey);
+int EVP_PKEY_get_int_param(EVP_PKEY *pkey, const char *key_name, int *out);
+int EVP_PKEY_get_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t *out);
+int EVP_PKEY_get_bn_param(EVP_PKEY *pkey, const char *key_name, BIGNUM **bn);
+int EVP_PKEY_get_utf8_string_param(EVP_PKEY *pkey, const char *key_name,
+                                    char *str, size_t max_buf_sz, size_t *out_sz);
+int EVP_PKEY_get_octet_string_param(EVP_PKEY *pkey, const char *key_name,
+                                    unsigned char *buf, size_t max_buf_sz,
+                                    size_t *out_sz);
+
 int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
 int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx);
index 89d33e3..92cac52 100644 (file)
@@ -4,7 +4,6 @@
 $DH_GOAL=../../libimplementations.a
 $DSA_GOAL=../../libimplementations.a
 $EC_GOAL=../../libimplementations.a
-$RSA_GOAL=../../libimplementations.a
 $ECX_GOAL=../../libimplementations.a
 
 IF[{- !$disabled{dh} -}]
@@ -16,7 +15,9 @@ ENDIF
 IF[{- !$disabled{ec} -}]
   SOURCE[$EC_GOAL]=ec_kmgmt.c
 ENDIF
-SOURCE[$RSA_GOAL]=rsa_kmgmt.c
 IF[{- !$disabled{ec} -}]
   SOURCE[$ECX_GOAL]=ecx_kmgmt.c
 ENDIF
+
+SOURCE[../../libfips.a]=rsa_kmgmt.c
+SOURCE[../../libnonfips.a]=rsa_kmgmt.c
index 82ef3d3..77d4753 100644 (file)
 #include <openssl/core_names.h>
 #include <openssl/bn.h>
 #include <openssl/objects.h>
-#include <openssl/params.h>
 #include "crypto/bn.h"
 #include "crypto/ec.h"
-#include "openssl/param_build.h"
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
 #include "prov/provider_ctx.h"
+#include "internal/param_build_set.h"
 
 static OSSL_OP_keymgmt_new_fn ec_newdata;
 static OSSL_OP_keymgmt_free_fn ec_freedata;
@@ -40,8 +39,8 @@ static OSSL_OP_keymgmt_export_fn ec_export;
 static OSSL_OP_keymgmt_export_types_fn ec_export_types;
 static OSSL_OP_keymgmt_query_operation_name_fn ec_query_operation_name;
 
-#define EC_POSSIBLE_SELECTIONS                 \
-    (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS )
+#define EC_POSSIBLE_SELECTIONS                                                 \
+    (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)
 
 static
 const char *ec_query_operation_name(int operation_id)
@@ -56,7 +55,8 @@ const char *ec_query_operation_name(int operation_id)
 }
 
 static ossl_inline
-int domparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
+int domparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl,
+                        OSSL_PARAM params[])
 {
     const EC_GROUP *ecg;
     int curve_nid;
@@ -71,11 +71,7 @@ int domparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
     curve_nid = EC_GROUP_get_curve_name(ecg);
 
     if (curve_nid == NID_undef) {
-        /* explicit parameters */
-
-        /*
-         * TODO(3.0): should we support explicit parameters curves?
-         */
+        /* TODO(3.0): should we support explicit parameters curves? */
         return 0;
     } else {
         /* named curve */
@@ -83,9 +79,10 @@ 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_build_set_utf8_string(tmpl, params,
+                                              OSSL_PKEY_PARAM_EC_NAME,
+                                              curve_name))
 
-        if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME,
-                                             curve_name, 0))
             return 0;
     }
 
@@ -100,12 +97,13 @@ int domparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
  * parameters are exported separately.
  */
 static ossl_inline
-int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, int include_private)
+int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl,
+                  OSSL_PARAM params[], int include_private,
+                  unsigned char **pub_key)
 {
     const BIGNUM *priv_key = NULL;
     const EC_POINT *pub_point = NULL;
     const EC_GROUP *ecg = NULL;
-    unsigned char *pub_key = NULL;
     size_t pub_key_len = 0;
     int ret = 0;
 
@@ -120,10 +118,10 @@ int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, int include_private
         /* convert pub_point to a octet string according to the SECG standard */
         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_PKEY_PARAM_PUB_KEY,
-                                                 pub_key, pub_key_len))
+                                              pub_key, NULL)) == 0
+            || !ossl_param_build_set_octet_string(tmpl, params,
+                                                  OSSL_PKEY_PARAM_PUB_KEY,
+                                                  *pub_key, pub_key_len))
             goto err;
     }
 
@@ -168,21 +166,20 @@ 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,
-                                        OSSL_PKEY_PARAM_PRIV_KEY,
-                                        priv_key, sz))
+
+        if (!ossl_param_build_set_bn_pad(tmpl, params,
+                                         OSSL_PKEY_PARAM_PRIV_KEY,
+                                         priv_key, sz))
             goto err;
     }
-
     ret = 1;
-
  err:
-    OPENSSL_free(pub_key);
     return ret;
 }
 
 static ossl_inline
-int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
+int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl,
+                          OSSL_PARAM params[])
 {
     int ecdh_cofactor_mode = 0;
 
@@ -191,12 +188,9 @@ 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,
-                OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
-                ecdh_cofactor_mode))
-        return 0;
-
-    return 1;
+    return ossl_param_build_set_int(tmpl, params,
+                                    OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
+                                    ecdh_cofactor_mode);
 }
 
 static
@@ -314,6 +308,7 @@ int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
     EC_KEY *ec = keydata;
     OSSL_PARAM_BLD *tmpl;
     OSSL_PARAM *params = NULL;
+    unsigned char *pub_key = NULL;
     int ok = 1;
 
     if (ec == NULL)
@@ -346,15 +341,16 @@ int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
         return 0;
 
     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
-        ok = ok && domparams_to_params(ec, tmpl);
+        ok = ok && domparams_to_params(ec, tmpl, NULL);
+
     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, NULL, include_private, &pub_key);
     }
     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
-        ok = ok && otherparams_to_params(ec, tmpl);
+        ok = ok && otherparams_to_params(ec, tmpl, NULL);
 
     if (!ok
         || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
@@ -364,6 +360,7 @@ int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
     OSSL_PARAM_BLD_free_params(params);
 err:
     OSSL_PARAM_BLD_free(tmpl);
+    OPENSSL_free(pub_key);
     return ok;
 }
 
@@ -423,9 +420,11 @@ const OSSL_PARAM *ec_export_types(int selection)
 static
 int ec_get_params(void *key, OSSL_PARAM params[])
 {
+    int ret;
     EC_KEY *eck = key;
     const EC_GROUP *ecg = NULL;
     OSSL_PARAM *p;
+    unsigned char *pub_key = NULL;
 
     ecg = EC_KEY_get0_group(eck);
     if (ecg == NULL)
@@ -485,15 +484,21 @@ int ec_get_params(void *key, OSSL_PARAM params[])
         if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))
             return 0;
     }
-
-    return 1;
+    ret = domparams_to_params(eck, NULL, params)
+          && key_to_params(eck, NULL, params, 1, &pub_key)
+          && otherparams_to_params(eck, NULL, params);
+    OPENSSL_free(pub_key);
+    return ret;
 }
 
 static const OSSL_PARAM ec_known_gettable_params[] = {
     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
-    OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
+    EC_IMEXPORTABLE_DOM_PARAMETERS,
+    EC_IMEXPORTABLE_PUBLIC_KEY,
+    EC_IMEXPORTABLE_PRIVATE_KEY,
+    EC_IMEXPORTABLE_OTHER_PARAMETERS,
     OSSL_PARAM_END
 };
 
index be11f0b..ca53a93 100644 (file)
 #include <assert.h>
 #include <openssl/core_numbers.h>
 #include <openssl/core_names.h>
-#include <openssl/params.h>
-#include "openssl/param_build.h"
 #include "crypto/ecx.h"
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
+#include "internal/param_build_set.h"
 
 static OSSL_OP_keymgmt_new_fn x25519_new_key;
 static OSSL_OP_keymgmt_new_fn x448_new_key;
@@ -90,18 +89,21 @@ static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
     return ok;
 }
 
-static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl)
+static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
+                         OSSL_PARAM params[])
 {
     if (key == NULL)
         return 0;
 
-    if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
-                                          key->pubkey, key->keylen))
+    if (!ossl_param_build_set_octet_string(tmpl, params,
+                                           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,
-                                             key->privkey, key->keylen))
+        && !ossl_param_build_set_octet_string(tmpl, params,
+                                              OSSL_PKEY_PARAM_PRIV_KEY,
+                                              key->privkey, key->keylen))
         return 0;
 
     return 1;
@@ -113,7 +115,7 @@ static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
     ECX_KEY *key = keydata;
     OSSL_PARAM_BLD *tmpl;
     OSSL_PARAM *params = NULL;
-    int ret;
+    int ret = 0;
 
     if (key == NULL)
         return 0;
@@ -123,24 +125,30 @@ static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
         return 0;
 
     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
-            && !key_to_params(key, tmpl)) {
-        OSSL_PARAM_BLD_free(tmpl);
-        return 0;
-    }
+         && !key_to_params(key, tmpl, NULL))
+        goto err;
+
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
+         && !key_to_params(key, tmpl, NULL))
+        goto err;
 
     params = OSSL_PARAM_BLD_to_param(tmpl);
-    OSSL_PARAM_BLD_free(tmpl);
     if (params == NULL)
-        return 0;
+        goto err;
 
     ret = param_cb(params, cbarg);
     OSSL_PARAM_BLD_free_params(params);
+err:
+    OSSL_PARAM_BLD_free(tmpl);
     return ret;
 }
 
+#define ECX_KEY_TYPES()                                                        \
+OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),                     \
+OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
+
 static const OSSL_PARAM ecx_key_types[] = {
-    OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),
-    OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
+    ECX_KEY_TYPES(),
     OSSL_PARAM_END
 };
 static const OSSL_PARAM *ecx_imexport_types(int selection)
@@ -150,9 +158,10 @@ static const OSSL_PARAM *ecx_imexport_types(int selection)
     return NULL;
 }
 
-static int ecx_get_params(OSSL_PARAM params[], int bits, int secbits,
+static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
                           int size)
 {
+    ECX_KEY *ecx = key;
     OSSL_PARAM *p;
 
     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
@@ -164,33 +173,38 @@ static int ecx_get_params(OSSL_PARAM params[], int bits, int secbits,
     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
         && !OSSL_PARAM_set_int(p, size))
         return 0;
-    return 1;
+    return key_to_params(ecx, NULL, params);
 }
 
 static int x25519_get_params(void *key, OSSL_PARAM params[])
 {
-    return ecx_get_params(params, X25519_BITS, X25519_SECURITY_BITS, X25519_KEYLEN);
+    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
+                          X25519_KEYLEN);
 }
 
 static int x448_get_params(void *key, OSSL_PARAM params[])
 {
-    return ecx_get_params(params, X448_BITS, X448_SECURITY_BITS, X448_KEYLEN);
+    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
+                          X448_KEYLEN);
 }
 
 static int ed25519_get_params(void *key, OSSL_PARAM params[])
 {
-    return ecx_get_params(params, ED25519_BITS, ED25519_SECURITY_BITS, ED25519_KEYLEN);
+    return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
+                          ED25519_KEYLEN);
 }
 
 static int ed448_get_params(void *key, OSSL_PARAM params[])
 {
-    return ecx_get_params(params, ED448_BITS, ED448_SECURITY_BITS, ED448_KEYLEN);
+    return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
+                          ED448_KEYLEN);
 }
 
 static const OSSL_PARAM ecx_params[] = {
     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
+    ECX_KEY_TYPES(),
     OSSL_PARAM_END
 };
 
index 50647eb..8ea3941 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
 #include <openssl/err.h>
 #include <openssl/rsa.h>
 #include <openssl/evp.h>
-#include <openssl/params.h>
-#include <openssl/types.h>
-#include "openssl/param_build.h"
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
 #include "prov/provider_ctx.h"
 #include "crypto/rsa.h"
+#include "internal/param_build_set.h"
 
 static OSSL_OP_keymgmt_new_fn rsa_newdata;
 static OSSL_OP_keymgmt_gen_init_fn rsa_gen_init;
@@ -45,32 +43,13 @@ static OSSL_OP_keymgmt_export_fn rsa_export;
 static OSSL_OP_keymgmt_export_types_fn rsa_export_types;
 
 #define RSA_DEFAULT_MD "SHA256"
-#define RSA_POSSIBLE_SELECTIONS                 \
+#define RSA_POSSIBLE_SELECTIONS                                                \
     (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS)
 
 DEFINE_STACK_OF(BIGNUM)
 DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
 
-static int export_numbers(OSSL_PARAM_BLD *tmpl, const char *key,
-                          STACK_OF(BIGNUM_const) *numbers)
-{
-    int i, nnum;
-
-    if (numbers == NULL)
-        return 0;
-
-    nnum = sk_BIGNUM_const_num(numbers);
-
-    for (i = 0; i < nnum; i++) {
-        if (!OSSL_PARAM_BLD_push_BN(tmpl, key,
-                                    sk_BIGNUM_const_value(numbers, i)))
-            return 0;
-    }
-
-    return 1;
-}
-
-static int key_to_params(RSA *rsa, OSSL_PARAM_BLD *tmpl)
+static int key_to_params(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
 {
     int ret = 0;
     const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL;
@@ -84,21 +63,16 @@ static int key_to_params(RSA *rsa, OSSL_PARAM_BLD *tmpl)
     RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
     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))
-        goto err;
-    if (rsa_e != NULL
-        && !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))
-        goto err;
-
-    if (!export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_FACTOR, factors)
-        || !export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT, exps)
-        || !export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT, coeffs))
+    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);
@@ -189,20 +163,70 @@ static int rsa_export(void *keydata, int selection,
         return 0;
 
     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
-        ok = ok && key_to_params(rsa, tmpl);
+        ok = ok && key_to_params(rsa, tmpl, NULL);
 
     if (!ok
-        || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
-        OSSL_PARAM_BLD_free(tmpl);
-        return 0;
-    }
-    OSSL_PARAM_BLD_free(tmpl);
+        || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
+        goto err;
 
     ok = param_callback(params, cbarg);
     OSSL_PARAM_BLD_free_params(params);
+err:
+    OSSL_PARAM_BLD_free(tmpl);
     return ok;
 }
 
+#ifdef FIPS_MODE
+/* In fips mode there are no multi-primes. */
+# define RSA_KEY_MP_TYPES()                                                    \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, NULL, 0),                           \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, NULL, 0),                           \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, NULL, 0),                         \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, NULL, 0),                         \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, NULL, 0),
+#else
+/*
+ * We allow up to 10 prime factors (starting with p, q).
+ * NOTE: there is only 9 OSSL_PKEY_PARAM_RSA_COEFFICIENT
+ */
+# define RSA_KEY_MP_TYPES()                                                    \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, NULL, 0),                           \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, NULL, 0),                           \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR3, NULL, 0),                           \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR4, NULL, 0),                           \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR5, NULL, 0),                           \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR6, NULL, 0),                           \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR7, NULL, 0),                           \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR8, NULL, 0),                           \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR9, NULL, 0),                           \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR10, NULL, 0),                          \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, NULL, 0),                         \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, NULL, 0),                         \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT3, NULL, 0),                         \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT4, NULL, 0),                         \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT5, NULL, 0),                         \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT6, NULL, 0),                         \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT7, NULL, 0),                         \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT8, NULL, 0),                         \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT9, NULL, 0),                         \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT10, NULL, 0),                        \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, NULL, 0),                      \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT2, NULL, 0),                      \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT3, NULL, 0),                      \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT4, NULL, 0),                      \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT5, NULL, 0),                      \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT6, NULL, 0),                      \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT7, NULL, 0),                      \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT8, NULL, 0),                      \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT9, NULL, 0),
+#endif
+
+#define 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),                                 \
+RSA_KEY_MP_TYPES()
+
 /*
  * 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
@@ -211,41 +235,8 @@ static int rsa_export(void *keydata, int selection,
  * 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),
+    RSA_KEY_TYPES()
+    OSSL_PARAM_END
 };
 /*
  * We lied about the amount of factors, exponents and coefficients, the
@@ -266,7 +257,6 @@ static const OSSL_PARAM *rsa_import_types(int selection)
     return rsa_imexport_types(selection);
 }
 
-
 static const OSSL_PARAM *rsa_export_types(int selection)
 {
     return rsa_imexport_types(selection);
@@ -312,8 +302,7 @@ static int rsa_get_params(void *key, OSSL_PARAM params[])
         if (!OSSL_PARAM_set_utf8_string(p, RSA_DEFAULT_MD))
             return 0;
     }
-
-    return 1;
+    return key_to_params(rsa, NULL, params);
 }
 
 static const OSSL_PARAM rsa_params[] = {
@@ -321,6 +310,7 @@ static const OSSL_PARAM rsa_params[] = {
     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
+    RSA_KEY_TYPES()
     OSSL_PARAM_END
 };
 
index ddc7074..21898f9 100644 (file)
@@ -116,4 +116,3 @@ int ossl_prov_print_rsa(BIO *out, RSA *rsa, int priv)
     sk_BIGNUM_const_free(coeffs);
     return ret;
 }
-
index 6ba61c3..9f8d008 100644 (file)
@@ -7,6 +7,7 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include <string.h> /* memset */
 #include <openssl/evp.h>
 #include <openssl/pem.h>
 #include <openssl/serializer.h>
@@ -260,7 +261,7 @@ static int test_print_key_using_serializer(const char *alg, const EVP_PKEY *pk)
 
 static int test_fromdata_rsa(void)
 {
-    int ret = 0;
+    int ret = 0, i;
     EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
     EVP_PKEY *pk = NULL, *copy_pk = NULL;
     /*
@@ -283,13 +284,15 @@ static int test_fromdata_rsa(void)
         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_N, &key_numbers[N]),
         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_E, &key_numbers[E]),
         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_D, &key_numbers[D]),
-        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &key_numbers[P]),
-        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &key_numbers[Q]),
-        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &key_numbers[DP]),
-        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &key_numbers[DQ]),
-        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_COEFFICIENT, &key_numbers[QINV]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR1, &key_numbers[P]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR2, &key_numbers[Q]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT1, &key_numbers[DP]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT2, &key_numbers[DQ]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, &key_numbers[QINV]),
         OSSL_PARAM_END
     };
+    BIGNUM *bn = BN_new();
+    BIGNUM *bn_from = BN_new();
 
     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)))
         goto err;
@@ -315,10 +318,17 @@ static int test_fromdata_rsa(void)
         || !TEST_false(EVP_PKEY_copy_parameters(copy_pk, pk)))
         goto err;
 
+    for (i = 0; fromdata_params[i].key != NULL; ++i) {
+        if (!TEST_true(BN_set_word(bn_from, key_numbers[i]))
+            || !TEST_true(EVP_PKEY_get_bn_param(pk, fromdata_params[i].key, &bn))
+            || !TEST_BN_eq(bn, bn_from))
+            goto err;
+    }
     ret = test_print_key_using_pem("RSA", pk)
           && test_print_key_using_serializer("RSA", pk);
-
  err:
+    BN_free(bn_from);
+    BN_free(bn);
     EVP_PKEY_free(pk);
     EVP_PKEY_free(copy_pk);
     EVP_PKEY_CTX_free(key_ctx);
@@ -327,6 +337,59 @@ static int test_fromdata_rsa(void)
     return ret;
 }
 
+static int test_evp_pkey_get_bn_param_large(void)
+{
+    int ret = 0;
+    EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
+    EVP_PKEY *pk = NULL;
+    OSSL_PARAM_BLD *bld = NULL;
+    OSSL_PARAM *fromdata_params = NULL;
+    BIGNUM *n = NULL, *e = NULL, *d = NULL, *n_out = NULL;
+    /*
+     * The buffer size chosen here for n_data larger than the buffer used
+     * internally in EVP_PKEY_get_bn_param.
+     */
+    static unsigned char n_data[2050];
+    static const unsigned char e_data[] = {
+        0x1, 0x00, 0x01
+    };
+    static const unsigned char d_data[]= {
+       0x99, 0x33, 0x13, 0x7b
+    };
+
+    /* N is a large buffer */
+    memset(n_data, 0xCE, sizeof(n_data));
+
+    if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
+        || !TEST_ptr(n = BN_bin2bn(n_data, sizeof(n_data), NULL))
+        || !TEST_ptr(e = BN_bin2bn(e_data, sizeof(e_data), NULL))
+        || !TEST_ptr(d = BN_bin2bn(d_data, sizeof(d_data), NULL))
+        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, n))
+        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, e))
+        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_D, d))
+        || !TEST_ptr(fromdata_params = OSSL_PARAM_BLD_to_param(bld))
+        || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL))
+        || !TEST_true(EVP_PKEY_key_fromdata_init(ctx))
+        || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
+        || !TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, ""))
+        || !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_RSA_N, &n_out))
+        || !TEST_BN_eq(n, n_out))
+        goto err;
+    ret = 1;
+ err:
+    BN_free(n_out);
+    BN_free(n);
+    BN_free(e);
+    BN_free(d);
+    EVP_PKEY_free(pk);
+    EVP_PKEY_CTX_free(key_ctx);
+    EVP_PKEY_CTX_free(ctx);
+    OSSL_PARAM_BLD_free_params(fromdata_params);
+    OSSL_PARAM_BLD_free(bld);
+    return ret;
+}
+
+
 #ifndef OPENSSL_NO_DH
 /* Array indexes used in test_fromdata_dh */
 #define PRIV_KEY        0
@@ -412,6 +475,9 @@ static int test_fromdata_ecx(int tst)
     EVP_PKEY_CTX *ctx = NULL;
     EVP_PKEY *pk = NULL, *copy_pk = NULL;
     const char *alg = NULL;
+    size_t len;
+    unsigned char out_pub[ED448_KEYLEN];
+    unsigned char out_priv[ED448_KEYLEN];
 
     /* ED448_KEYLEN > X448_KEYLEN > X25519_KEYLEN == ED25519_KEYLEN */
     static unsigned char key_numbers[4][2][ED448_KEYLEN] = {
@@ -580,6 +646,20 @@ static int test_fromdata_ecx(int tst)
         || !TEST_false(EVP_PKEY_copy_parameters(copy_pk, pk)))
         goto err;
 
+    if (!TEST_true(EVP_PKEY_get_octet_string_param(
+                       pk, fromdata_params[PRIV_KEY].key,
+                       out_priv, sizeof(out_priv), &len))
+        || !TEST_mem_eq(out_priv, len,
+                        fromdata_params[PRIV_KEY].data,
+                        fromdata_params[PRIV_KEY].data_size)
+        || !TEST_true(EVP_PKEY_get_octet_string_param(
+                          pk, fromdata_params[PUB_KEY].key,
+                          out_pub, sizeof(out_pub), &len))
+        || !TEST_mem_eq(out_pub, len,
+                        fromdata_params[PUB_KEY].data,
+                        fromdata_params[PUB_KEY].data_size))
+        goto err;
+
     ret = test_print_key_using_pem(alg, pk)
           && test_print_key_using_serializer(alg, pk);
 
@@ -591,6 +671,8 @@ err:
     return ret;
 }
 
+#define CURVE_NAME 2
+
 static int test_fromdata_ec(void)
 {
     int ret = 0;
@@ -598,10 +680,13 @@ static int test_fromdata_ec(void)
     EVP_PKEY *pk = NULL, *copy_pk = NULL;
     OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
     BIGNUM *ec_priv_bn = NULL;
+    BIGNUM *bn_priv = NULL;
     OSSL_PARAM *fromdata_params = NULL;
     const char *alg = "EC";
+    const char *curve = "prime256v1";
+    /* UNCOMPRESSED FORMAT */
     static const unsigned char ec_pub_keydata[] = {
-       0x04,
+       POINT_CONVERSION_UNCOMPRESSED,
        0x1b, 0x93, 0x67, 0x55, 0x1c, 0x55, 0x9f, 0x63,
        0xd1, 0x22, 0xa4, 0xd8, 0xd1, 0x0a, 0x60, 0x6d,
        0x02, 0xa5, 0x77, 0x57, 0xc8, 0xa3, 0x47, 0x73,
@@ -617,6 +702,12 @@ static int test_fromdata_ec(void)
         0xcc, 0x0d, 0x9a, 0x24, 0x6c, 0x86, 0x1b, 0x2e,
         0xdc, 0x4b, 0x4d, 0x35, 0x43, 0xe1, 0x1b, 0xad
     };
+    const int compressed_sz = 1 + (sizeof(ec_pub_keydata) - 1) / 2;
+    unsigned char out_pub[sizeof(ec_pub_keydata)];
+    char out_curve_name[80];
+    const OSSL_PARAM *gettable = NULL;
+    size_t len;
+
 
     if (!TEST_ptr(bld))
         goto err;
@@ -625,7 +716,7 @@ static int test_fromdata_ec(void)
         goto err;
 
     if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_NAME,
-                                        "prime256v1", 0) <= 0)
+                                        curve, 0) <= 0)
         goto err;
     if (OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY,
                                          ec_pub_keydata,
@@ -650,9 +741,30 @@ static int test_fromdata_ec(void)
         || !TEST_true(EVP_PKEY_copy_parameters(copy_pk, pk)))
         goto err;
 
+    if (!TEST_ptr(gettable = EVP_PKEY_gettable_params(pk))
+        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_NAME))
+        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_PUB_KEY))
+        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_PRIV_KEY)))
+        goto err;
+
+    if (!EVP_PKEY_get_utf8_string_param(pk, OSSL_PKEY_PARAM_EC_NAME,
+                                        out_curve_name, sizeof(out_curve_name),
+                                        &len)
+        || !TEST_str_eq(out_curve_name, curve)
+        || !EVP_PKEY_get_octet_string_param(pk, OSSL_PKEY_PARAM_PUB_KEY,
+                                            out_pub, sizeof(out_pub), &len)
+        || !TEST_true(out_pub[0] == (POINT_CONVERSION_COMPRESSED + 1))
+        || !TEST_mem_eq(out_pub + 1, len - 1,
+                        ec_pub_keydata + 1, compressed_sz - 1)
+        || !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_PRIV_KEY,
+                                            &bn_priv))
+        || !TEST_BN_eq(ec_priv_bn, bn_priv))
+        goto err;
+
     ret = test_print_key_using_pem(alg, pk)
           && test_print_key_using_serializer(alg, pk);
 err:
+    BN_free(bn_priv);
     BN_free(ec_priv_bn);
     OSSL_PARAM_BLD_free_params(fromdata_params);
     OSSL_PARAM_BLD_free(bld);
@@ -674,6 +786,7 @@ int setup_tests(void)
     if (!TEST_ptr(datadir = test_get_argument(0)))
         return 0;
 
+    ADD_TEST(test_evp_pkey_get_bn_param_large);
     ADD_TEST(test_fromdata_rsa);
 #ifndef OPENSSL_NO_DH
     ADD_TEST(test_fromdata_dh);
index fd60893..d30b3a7 100644 (file)
@@ -66,7 +66,7 @@ static FIXTURE *set_up(const char *testcase_name)
 #define DQ      7
 #define E3      8                /* Extra exponent */
 #define QINV    9
-#define C3      10               /* Extra coefficient */
+#define C2      10               /* Extra coefficient */
 
 /*
  * We have to do this because OSSL_PARAM_get_ulong() can't handle params
@@ -92,10 +92,6 @@ static int export_cb(const OSSL_PARAM *params, void *arg)
 {
     unsigned long *keydata = arg;
     const OSSL_PARAM *p = NULL;
-    int factors_idx;
-    int exponents_idx;
-    int coefficients_idx;
-    int ret = 1;                 /* Ever so hopeful */
 
     if (keydata == NULL)
         return 0;
@@ -106,35 +102,31 @@ static int export_cb(const OSSL_PARAM *params, void *arg)
         || !TEST_true(get_ulong_via_BN(p, &keydata[E]))
         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D))
         || !TEST_true(get_ulong_via_BN(p, &keydata[D])))
-        ret = 0;
+        return 0;
 
-    for (p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR),
-             factors_idx = P;
-         p != NULL && factors_idx <= F3;
-         p = OSSL_PARAM_locate_const(p + 1, OSSL_PKEY_PARAM_RSA_FACTOR),
-         factors_idx++)
-        if (!TEST_true(get_ulong_via_BN(p, &keydata[factors_idx])))
-            ret = 0;
-    for (p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT),
-             exponents_idx = DP;
-         p != NULL && exponents_idx <= E3;
-         p = OSSL_PARAM_locate_const(p + 1, OSSL_PKEY_PARAM_RSA_EXPONENT),
-         exponents_idx++)
-        if (!TEST_true(get_ulong_via_BN(p, &keydata[exponents_idx])))
-            ret = 0;
-    for (p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT),
-             coefficients_idx = QINV;
-         p != NULL && coefficients_idx <= C3;
-         p = OSSL_PARAM_locate_const(p + 1, OSSL_PKEY_PARAM_RSA_COEFFICIENT),
-         coefficients_idx++)
-        if (!TEST_true(get_ulong_via_BN(p, &keydata[coefficients_idx])))
-            ret = 0;
-
-    if (!TEST_int_le(factors_idx, F3)
-        || !TEST_int_le(exponents_idx, E3)
-        || !TEST_int_le(coefficients_idx, C3))
-        ret = 0;
-    return ret;
+    if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR1))
+        || !TEST_true(get_ulong_via_BN(p, &keydata[P]))
+        || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR2))
+        || !TEST_true(get_ulong_via_BN(p, &keydata[Q]))
+        || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR3))
+        || !TEST_true(get_ulong_via_BN(p, &keydata[F3])))
+        return 0;
+
+    if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT1))
+        || !TEST_true(get_ulong_via_BN(p, &keydata[DP]))
+        || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT2))
+        || !TEST_true(get_ulong_via_BN(p, &keydata[DQ]))
+        || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT3))
+        || !TEST_true(get_ulong_via_BN(p, &keydata[E3])))
+        return 0;
+
+    if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT1))
+        || !TEST_true(get_ulong_via_BN(p, &keydata[QINV]))
+        || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT2))
+        || !TEST_true(get_ulong_via_BN(p, &keydata[C2])))
+        return 0;
+
+    return 1;
 }
 
 static int test_pass_rsa(FIXTURE *fixture)
@@ -146,9 +138,13 @@ static int test_pass_rsa(FIXTURE *fixture)
     EVP_PKEY *pk = NULL;
     EVP_KEYMGMT *km1 = NULL, *km2 = NULL;
     void *provkey = NULL;
+    BIGNUM *bn_primes[1] = { NULL };
+    BIGNUM *bn_exps[1] = { NULL };
+    BIGNUM *bn_coeffs[1] = { NULL };
     /*
      * 32-bit RSA key, extracted from this command,
      * executed with OpenSSL 1.0.2:
+     * An extra factor was added just for testing purposes.
      *
      * openssl genrsa 32 | openssl rsa -text
      */
@@ -158,12 +154,12 @@ static int test_pass_rsa(FIXTURE *fixture)
         0x7b133399,              /* D */
         0xe963,                  /* P */
         0xceb7,                  /* Q */
-        0,                       /* F3 */
+        1,                       /* F3 */
         0x8599,                  /* DP */
         0xbd87,                  /* DQ */
-        0,                       /* E3 */
+        2,                       /* E3 */
         0xcc3b,                  /* QINV */
-        0,                       /* C3 */
+        3,                       /* C3 */
         0                        /* Extra, should remain zero */
     };
     static unsigned long keydata[OSSL_NELEM(expected)] = { 0, };
@@ -197,6 +193,16 @@ static int test_pass_rsa(FIXTURE *fixture)
         goto err;
     bn1 = bn2 = bn3 = NULL;
 
+    if (!TEST_ptr(bn_primes[0] = BN_new())
+        || !TEST_true(BN_set_word(bn_primes[0], expected[F3]))
+        || !TEST_ptr(bn_exps[0] = BN_new())
+        || !TEST_true(BN_set_word(bn_exps[0], expected[E3]))
+        || !TEST_ptr(bn_coeffs[0] = BN_new())
+        || !TEST_true(BN_set_word(bn_coeffs[0], expected[C2]))
+        || !TEST_true(RSA_set0_multi_prime_params(rsa, bn_primes, bn_exps,
+                                                  bn_coeffs, 1)))
+        goto err;
+
     if (!TEST_ptr(pk = EVP_PKEY_new())
         || !TEST_true(EVP_PKEY_assign_RSA(pk, rsa)))
         goto err;
index 9fc7cfc..cd0a7d8 100644 (file)
@@ -5030,3 +5030,9 @@ SRP_Calc_u_ex                           ? 3_0_0   EXIST::FUNCTION:SRP
 SRP_Calc_x_ex                           ?      3_0_0   EXIST::FUNCTION:SRP
 SRP_Calc_client_key_ex                  ?      3_0_0   EXIST::FUNCTION:SRP
 X509v3_cache_extensions                 ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_gettable_params                ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_get_int_param                  ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_get_size_t_param               ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_get_bn_param                   ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_get_utf8_string_param          ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_get_octet_string_param         ?      3_0_0   EXIST::FUNCTION: