diff --git a/crypto/build.info b/crypto/build.info index a688248acf..baa31ee8e1 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -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 \ diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 9ed238e366..b176f100e8 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -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 index 0000000000..b74b0d59ee --- /dev/null +++ b/crypto/param_build_set.c @@ -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 +#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; +} diff --git a/crypto/rsa/build.info b/crypto/rsa/build.info index c1d1a3769b..7921202739 100644 --- a/crypto/rsa/build.info +++ b/crypto/rsa/build.info @@ -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 \ diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index ec8df4a718..fb378ae039 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -20,7 +20,7 @@ #include #include #include -#include "openssl/param_build.h" +#include #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; } } diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c index f68d38cc1a..57a539c051 100644 --- a/crypto/rsa/rsa_backend.c +++ b/crypto/rsa/rsa_backend.c @@ -20,19 +20,23 @@ 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 index 0000000000..e69321a4b7 --- /dev/null +++ b/crypto/rsa/rsa_mp_names.c @@ -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 +#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 +}; diff --git a/doc/man3/EVP_PKEY_fromdata.pod b/doc/man3/EVP_PKEY_fromdata.pod index 2d0059d32f..e3ddf68058 100644 --- a/doc/man3/EVP_PKEY_fromdata.pod +++ b/doc/man3/EVP_PKEY_fromdata.pod @@ -52,7 +52,7 @@ not supported by the public key algorithm. =head1 SEE ALSO -L, L +L, L, L =head1 HISTORY diff --git a/doc/man3/EVP_PKEY_gettable_params.pod b/doc/man3/EVP_PKEY_gettable_params.pod new file mode 100644 index 0000000000..87d25c7b99 --- /dev/null +++ b/doc/man3/EVP_PKEY_gettable_params.pod @@ -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 + + 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 indicating +the names and types of key parameters that can be retrieved. +See L for information about parameters. + +EVP_PKEY_get_int_param() retrieves a key I integer value I<*out> +associated with a name of I. + +EVP_PKEY_get_size_t_param() retrieves a key I size_t value I<*out> +associated with a name of I. + +EVP_PKEY_get_bn_param() retrieves a key I BIGNUM value I<**bn> +associated with a name of I. If I<*bn> is NULL then the BIGNUM +is allocated by the method. + +EVP_PKEY_get_utf8_string_param() get a key I UTF8 string value int a buffer +I of maximum size I associated with a name of I. +I<*out_sz> is the returned size of the string if it is not NULL. + +EVP_PKEY_get_octet_string_param() copy a I's octet string value into a buffer +I of maximum size I associated with a name of I. +I<*out_sz> is the returned size of the buffer if it is not NULL. + +=head1 NOTES + +These functions only work for Bs 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 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 is not big enough to hold the +value. + +=head1 EXAMPLES + + #include + + 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, L, L + +=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. + +=cut + diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod index 59e538dbac..00596a0a4b 100644 --- a/doc/man7/provider-keymgmt.pod +++ b/doc/man7/provider-keymgmt.pod @@ -334,20 +334,74 @@ The RSA "e" value. The RSA "d" value. -=item "rsa-factor" (B) +=item "rsa-factor1" (B) -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) -=item "rsa-exponent" (B) +=item "rsa-factor3" (B) -An RSA CRT (Chinese Remainder Theorem) exponent. This value may be repeated up -to 10 times in a single key. +=item "rsa-factor4" (B) -=item "rsa-coefficient" (B) +=item "rsa-factor5" (B) -An RSA CRT (Chinese Remainder Theorem) coefficient. This value may be repeated -up to 9 times in a single key. +=item "rsa-factor6" (B) + +=item "rsa-factor7" (B) + +=item "rsa-factor8" (B) + +=item "rsa-factor9" (B) + +=item "rsa-factor10" (B) + +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) + +=item "rsa-exponent2" (B) + +=item "rsa-exponent3" (B) + +=item "rsa-exponent4" (B) + +=item "rsa-exponent5" (B) + +=item "rsa-exponent6" (B) + +=item "rsa-exponent7" (B) + +=item "rsa-exponent8" (B) + +=item "rsa-exponent9" (B) + +=item "rsa-exponent10" (B) + +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) + +=item "rsa-coefficient2" (B) + +=item "rsa-coefficient3" (B) + +=item "rsa-coefficient4" (B) + +=item "rsa-coefficient5" (B) + +=item "rsa-coefficient6" (B) + +=item "rsa-coefficient7" (B) + +=item "rsa-coefficient8" (B) + +=item "rsa-coefficient9" (B) + +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 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) diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h index a92e666a3d..3a85510be0 100644 --- a/include/crypto/rsa.h +++ b/include/crypto/rsa.h @@ -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 index 0000000000..36d3b914d9 --- /dev/null +++ b/include/internal/param_build_set.h @@ -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 +#include + +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); diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index 2d48f00da2..c8a88285d8 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -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" diff --git a/include/openssl/evp.h b/include/openssl/evp.h index d461f24999..4903fc5f42 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -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); diff --git a/providers/implementations/keymgmt/build.info b/providers/implementations/keymgmt/build.info index 89d33e32f0..92cac52e11 100644 --- a/providers/implementations/keymgmt/build.info +++ b/providers/implementations/keymgmt/build.info @@ -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 diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index 82ef3d3a67..77d4753723 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -17,13 +17,12 @@ #include #include #include -#include #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 }; diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c index be11f0b85e..ca53a93f5e 100644 --- a/providers/implementations/keymgmt/ecx_kmgmt.c +++ b/providers/implementations/keymgmt/ecx_kmgmt.c @@ -10,11 +10,10 @@ #include #include #include -#include -#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 }; diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c index 50647eb6f5..8ea394115b 100644 --- a/providers/implementations/keymgmt/rsa_kmgmt.c +++ b/providers/implementations/keymgmt/rsa_kmgmt.c @@ -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 @@ -19,13 +19,11 @@ #include #include #include -#include -#include -#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 }; diff --git a/providers/implementations/serializers/serializer_rsa.c b/providers/implementations/serializers/serializer_rsa.c index ddc7074927..21898f9e3d 100644 --- a/providers/implementations/serializers/serializer_rsa.c +++ b/providers/implementations/serializers/serializer_rsa.c @@ -116,4 +116,3 @@ int ossl_prov_print_rsa(BIO *out, RSA *rsa, int priv) sk_BIGNUM_const_free(coeffs); return ret; } - diff --git a/test/evp_pkey_provided_test.c b/test/evp_pkey_provided_test.c index 6ba61c3cda..9f8d0086f7 100644 --- a/test/evp_pkey_provided_test.c +++ b/test/evp_pkey_provided_test.c @@ -7,6 +7,7 @@ * https://www.openssl.org/source/license.html */ +#include /* memset */ #include #include #include @@ -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); diff --git a/test/keymgmt_internal_test.c b/test/keymgmt_internal_test.c index fd60893a45..d30b3a70af 100644 --- a/test/keymgmt_internal_test.c +++ b/test/keymgmt_internal_test.c @@ -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; diff --git a/util/libcrypto.num b/util/libcrypto.num index 9fc7cfcf18..cd0a7d806e 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -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: