From 944f822aadc88b2e25f7695366810c73a53a00c8 Mon Sep 17 00:00:00 2001 From: slontis Date: Mon, 6 Dec 2021 09:27:12 +1000 Subject: [PATCH] Fix EVP todata and fromdata when used with selection of EVP_PKEY_PUBLIC_KEY. The private key for rsa, dsa, dh and ecx was being included when the selector was just the public key. (ec was working correctly). This matches the documented behaviour. Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/17200) --- crypto/dh/dh_ameth.c | 2 +- crypto/dh/dh_backend.c | 17 +- crypto/dsa/dsa_ameth.c | 2 +- crypto/dsa/dsa_backend.c | 11 +- crypto/rsa/rsa_ameth.c | 4 +- crypto/rsa/rsa_backend.c | 12 +- include/crypto/dh.h | 5 +- include/crypto/dsa.h | 3 +- include/crypto/rsa.h | 5 +- providers/implementations/keymgmt/dh_kmgmt.c | 19 ++- providers/implementations/keymgmt/dsa_kmgmt.c | 24 ++- providers/implementations/keymgmt/ecx_kmgmt.c | 20 ++- providers/implementations/keymgmt/rsa_kmgmt.c | 18 ++- test/evp_extra_test2.c | 152 ++++++++++++++++++ 14 files changed, 245 insertions(+), 49 deletions(-) diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index 38d8e7a38f..6a004ff2e4 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -511,7 +511,7 @@ static int dh_pkey_import_from_type(const OSSL_PARAM params[], void *vpctx, DH_set_flags(dh, type == EVP_PKEY_DH ? DH_FLAG_TYPE_DH : DH_FLAG_TYPE_DHX); if (!ossl_dh_params_fromdata(dh, params) - || !ossl_dh_key_fromdata(dh, params) + || !ossl_dh_key_fromdata(dh, params, 1) || !EVP_PKEY_assign(pkey, type, dh)) { DH_free(dh); return 0; diff --git a/crypto/dh/dh_backend.c b/crypto/dh/dh_backend.c index 7bd5c617de..98881a75f9 100644 --- a/crypto/dh/dh_backend.c +++ b/crypto/dh/dh_backend.c @@ -63,7 +63,7 @@ int ossl_dh_params_fromdata(DH *dh, const OSSL_PARAM params[]) return 1; } -int ossl_dh_key_fromdata(DH *dh, const OSSL_PARAM params[]) +int ossl_dh_key_fromdata(DH *dh, const OSSL_PARAM params[], int include_private) { const OSSL_PARAM *param_priv_key, *param_pub_key; BIGNUM *priv_key = NULL, *pub_key = NULL; @@ -74,10 +74,13 @@ int ossl_dh_key_fromdata(DH *dh, const OSSL_PARAM params[]) param_priv_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); - if ((param_priv_key != NULL - && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) - || (param_pub_key != NULL - && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))) + if (include_private + && param_priv_key != NULL + && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) + goto err; + + if (param_pub_key != NULL + && !OSSL_PARAM_get_BN(param_pub_key, &pub_key)) goto err; if (!DH_set0_key(dh, pub_key, priv_key)) @@ -103,7 +106,8 @@ int ossl_dh_params_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) return 1; } -int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) +int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[], + int include_private) { const BIGNUM *priv = NULL, *pub = NULL; @@ -112,6 +116,7 @@ int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) DH_get0_key(dh, &pub, &priv); if (priv != NULL + && include_private && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PRIV_KEY, priv)) return 0; if (pub != NULL diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index 53417bff6a..f0a2bdb149 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -485,7 +485,7 @@ static int dsa_pkey_import_from(const OSSL_PARAM params[], void *vpctx) } if (!ossl_dsa_ffc_params_fromdata(dsa, params) - || !ossl_dsa_key_fromdata(dsa, params) + || !ossl_dsa_key_fromdata(dsa, params, 1) || !EVP_PKEY_assign_DSA(pkey, dsa)) { DSA_free(dsa); return 0; diff --git a/crypto/dsa/dsa_backend.c b/crypto/dsa/dsa_backend.c index 5e3ff85154..9c3cede91a 100644 --- a/crypto/dsa/dsa_backend.c +++ b/crypto/dsa/dsa_backend.c @@ -27,16 +27,19 @@ * implementations alike. */ -int ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[]) +int ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[], + int include_private) { - const OSSL_PARAM *param_priv_key, *param_pub_key; + const OSSL_PARAM *param_priv_key = NULL, *param_pub_key; BIGNUM *priv_key = NULL, *pub_key = NULL; if (dsa == NULL) return 0; - param_priv_key = - OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); + if (include_private) { + param_priv_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); + } param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index 55b7216d63..83714b8856 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -748,7 +748,7 @@ static int rsa_int_export_to(const EVP_PKEY *from, int rsa_type, if (RSA_get0_n(rsa) == NULL || RSA_get0_e(rsa) == NULL) goto err; - if (!ossl_rsa_todata(rsa, tmpl, NULL)) + if (!ossl_rsa_todata(rsa, tmpl, NULL, 1)) goto err; selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; @@ -841,7 +841,7 @@ static int rsa_int_import_from(const OSSL_PARAM params[], void *vpctx, goto err; } - if (!ossl_rsa_fromdata(rsa, params)) + if (!ossl_rsa_fromdata(rsa, params, 1)) goto err; switch (rsa_type) { diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c index ae071f18bf..4385dd0135 100644 --- a/crypto/rsa/rsa_backend.c +++ b/crypto/rsa/rsa_backend.c @@ -60,9 +60,9 @@ static int collect_numbers(STACK_OF(BIGNUM) *numbers, return 1; } -int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]) +int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[], int include_private) { - const OSSL_PARAM *param_n, *param_e, *param_d; + const OSSL_PARAM *param_n, *param_e, *param_d = NULL; BIGNUM *n = NULL, *e = NULL, *d = NULL; STACK_OF(BIGNUM) *factors = NULL, *exps = NULL, *coeffs = NULL; int is_private = 0; @@ -72,7 +72,8 @@ int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]) param_n = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N); param_e = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E); - param_d = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D); + if (include_private) + param_d = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D); if ((param_n != NULL && !OSSL_PARAM_get_BN(param_n, &n)) || (param_e != NULL && !OSSL_PARAM_get_BN(param_e, &e)) @@ -118,7 +119,8 @@ int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]) DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM) -int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) +int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[], + int include_private) { int ret = 0; const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL; @@ -137,7 +139,7 @@ int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) goto err; /* Check private key data integrity */ - if (rsa_d != NULL) { + if (include_private && rsa_d != NULL) { int numprimes = sk_BIGNUM_const_num(factors); int numexps = sk_BIGNUM_const_num(exps); int numcoeffs = sk_BIGNUM_const_num(coeffs); diff --git a/include/crypto/dh.h b/include/crypto/dh.h index f6be4ae006..504050abf7 100644 --- a/include/crypto/dh.h +++ b/include/crypto/dh.h @@ -32,9 +32,10 @@ int ossl_dh_is_named_safe_prime_group(const DH *dh); FFC_PARAMS *ossl_dh_get0_params(DH *dh); int ossl_dh_get0_nid(const DH *dh); int ossl_dh_params_fromdata(DH *dh, const OSSL_PARAM params[]); -int ossl_dh_key_fromdata(DH *dh, const OSSL_PARAM params[]); +int ossl_dh_key_fromdata(DH *dh, const OSSL_PARAM params[], int include_private); int ossl_dh_params_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]); -int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]); +int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[], + int include_private); DH *ossl_dh_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, OSSL_LIB_CTX *libctx, const char *propq); int ossl_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); diff --git a/include/crypto/dsa.h b/include/crypto/dsa.h index e6b879b27b..275187c1b5 100644 --- a/include/crypto/dsa.h +++ b/include/crypto/dsa.h @@ -30,7 +30,8 @@ int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen, FFC_PARAMS *ossl_dsa_get0_params(DSA *dsa); int ossl_dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[]); -int ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[]); +int ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[], + int include_private); DSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, OSSL_LIB_CTX *libctx, const char *propq); diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h index 100e7ceb05..eab306b1db 100644 --- a/include/crypto/rsa.h +++ b/include/crypto/rsa.h @@ -65,8 +65,9 @@ int ossl_rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes, int ossl_rsa_is_foreign(const RSA *rsa); RSA *ossl_rsa_dup(const RSA *rsa, int selection); -int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]); -int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]); +int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[], + int include_private); +int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[], int include_private); int ossl_rsa_pss_params_30_todata(const RSA_PSS_PARAMS_30 *pss, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]); int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params, diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index b49cfd5291..a2de357798 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -201,8 +201,12 @@ static int dh_import(void *keydata, int selection, const OSSL_PARAM params[]) if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) ok = ok && ossl_dh_params_fromdata(dh, params); - if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) - ok = ok && ossl_dh_key_fromdata(dh, params); + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int include_private = + selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; + + ok = ok && ossl_dh_key_fromdata(dh, params, include_private); + } return ok; } @@ -224,8 +228,13 @@ static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) ok = ok && ossl_dh_params_todata(dh, tmpl, NULL); - if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) - ok = ok && ossl_dh_key_todata(dh, tmpl, NULL); + + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int include_private = + selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; + + ok = ok && ossl_dh_key_todata(dh, tmpl, NULL, include_private); + } if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) { @@ -323,7 +332,7 @@ static ossl_inline int dh_get_params(void *key, OSSL_PARAM params[]) } return ossl_dh_params_todata(dh, NULL, params) - && ossl_dh_key_todata(dh, NULL, params); + && ossl_dh_key_todata(dh, NULL, params, 1); } static const OSSL_PARAM dh_params[] = { diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c index b327a3a783..cf6daa4715 100644 --- a/providers/implementations/keymgmt/dsa_kmgmt.c +++ b/providers/implementations/keymgmt/dsa_kmgmt.c @@ -96,7 +96,8 @@ static int dsa_gen_type_name2id(const char *name) return -1; } -static int dsa_key_todata(DSA *dsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) +static int dsa_key_todata(DSA *dsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[], + int include_private) { const BIGNUM *priv = NULL, *pub = NULL; @@ -104,7 +105,8 @@ static int dsa_key_todata(DSA *dsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) return 0; DSA_get0_key(dsa, &pub, &priv); - if (priv != NULL + if (include_private + && priv != NULL && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PRIV_KEY, priv)) return 0; if (pub != NULL @@ -200,8 +202,12 @@ static int dsa_import(void *keydata, int selection, const OSSL_PARAM params[]) if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) ok = ok && ossl_dsa_ffc_params_fromdata(dsa, params); - if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) - ok = ok && ossl_dsa_key_fromdata(dsa, params); + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int include_private = + selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; + + ok = ok && ossl_dsa_key_fromdata(dsa, params, include_private); + } return ok; } @@ -223,8 +229,12 @@ static int dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) ok = ok && ossl_ffc_params_todata(ossl_dsa_get0_params(dsa), tmpl, NULL); - if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) - ok = ok && dsa_key_todata(dsa, tmpl, NULL); + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int include_private = + selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; + + ok = ok && dsa_key_todata(dsa, tmpl, NULL, include_private); + } if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) @@ -313,7 +323,7 @@ static ossl_inline int dsa_get_params(void *key, OSSL_PARAM params[]) && !OSSL_PARAM_set_utf8_string(p, DSA_DEFAULT_MD)) return 0; return ossl_ffc_params_todata(ossl_dsa_get0_params(dsa), NULL, params) - && dsa_key_todata(dsa, NULL, params); + && dsa_key_todata(dsa, NULL, params, 1); } static const OSSL_PARAM dsa_params[] = { diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c index 2be9508692..42ae565429 100644 --- a/providers/implementations/keymgmt/ecx_kmgmt.c +++ b/providers/implementations/keymgmt/ecx_kmgmt.c @@ -194,7 +194,7 @@ static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[]) { ECX_KEY *key = keydata; int ok = 1; - int include_private = 0; + int include_private; if (!ossl_prov_is_running() || key == NULL) return 0; @@ -202,14 +202,14 @@ static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[]) if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) return 0; - include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0); + include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; ok = ok && ossl_ecx_key_fromdata(key, params, include_private); return ok; } static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl, - OSSL_PARAM params[]) + OSSL_PARAM params[], int include_private) { if (key == NULL) return 0; @@ -219,7 +219,8 @@ static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl, key->pubkey, key->keylen)) return 0; - if (key->privkey != NULL + if (include_private + && key->privkey != NULL && !ossl_param_build_set_octet_string(tmpl, params, OSSL_PKEY_PARAM_PRIV_KEY, key->privkey, key->keylen)) @@ -243,9 +244,12 @@ static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, if (tmpl == NULL) return 0; - if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 - && !key_to_params(key, tmpl, NULL)) - goto err; + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0); + + if (!key_to_params(key, tmpl, NULL, include_private)) + goto err; + } params = OSSL_PARAM_BLD_to_param(tmpl); if (params == NULL) @@ -295,7 +299,7 @@ static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits, return 0; } - return key_to_params(ecx, NULL, params); + return key_to_params(ecx, NULL, params, 1); } static int ed_get_params(void *key, OSSL_PARAM params[]) diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c index 29e5d10813..2a9607e2f6 100644 --- a/providers/implementations/keymgmt/rsa_kmgmt.c +++ b/providers/implementations/keymgmt/rsa_kmgmt.c @@ -190,8 +190,12 @@ static int rsa_import(void *keydata, int selection, const OSSL_PARAM params[]) &pss_defaults_set, params, rsa_type, ossl_rsa_get0_libctx(rsa)); - if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) - ok = ok && ossl_rsa_fromdata(rsa, params); + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int include_private = + selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; + + ok = ok && ossl_rsa_fromdata(rsa, params, include_private); + } return ok; } @@ -218,8 +222,12 @@ static int rsa_export(void *keydata, int selection, if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) ok = ok && (ossl_rsa_pss_params_30_is_unrestricted(pss_params) || ossl_rsa_pss_params_30_todata(pss_params, tmpl, NULL)); - if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) - ok = ok && ossl_rsa_todata(rsa, tmpl, NULL); + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + int include_private = + selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; + + ok = ok && ossl_rsa_todata(rsa, tmpl, NULL, include_private); + } if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) @@ -363,7 +371,7 @@ static int rsa_get_params(void *key, OSSL_PARAM params[]) } return (rsa_type != RSA_FLAG_TYPE_RSASSAPSS || ossl_rsa_pss_params_30_todata(pss_params, NULL, params)) - && ossl_rsa_todata(rsa, NULL, params); + && ossl_rsa_todata(rsa, NULL, params, 1); } static const OSSL_PARAM rsa_params[] = { diff --git a/test/evp_extra_test2.c b/test/evp_extra_test2.c index 287f3d1443..00ed69af21 100644 --- a/test/evp_extra_test2.c +++ b/test/evp_extra_test2.c @@ -255,6 +255,136 @@ static APK_DATA keydata[] = { #endif }; +static int pkey_has_private(EVP_PKEY *key, const char *privtag, + int use_octstring) +{ + int ret = 0; + + if (use_octstring) { + unsigned char buf[64]; + + ret = EVP_PKEY_get_octet_string_param(key, privtag, buf, sizeof(buf), + NULL); + } else { + BIGNUM *bn = NULL; + + ret = EVP_PKEY_get_bn_param(key, privtag, &bn); + BN_free(bn); + } + return ret; +} + +static int do_pkey_tofrom_data_select(EVP_PKEY *key, const char *keytype) +{ + int ret = 0; + OSSL_PARAM *pub_params = NULL, *keypair_params = NULL; + EVP_PKEY *fromkey = NULL, *fromkeypair = NULL; + EVP_PKEY_CTX *fromctx = NULL; + const char *privtag = strcmp(keytype, "RSA") == 0 ? "d" : "priv"; + const int use_octstring = strcmp(keytype, "X25519") == 0; + + /* + * Select only the public key component when using EVP_PKEY_todata() and + * check that the resulting param array does not contain a private key. + */ + if (!TEST_int_eq(EVP_PKEY_todata(key, EVP_PKEY_PUBLIC_KEY, &pub_params), 1) + || !TEST_ptr_null(OSSL_PARAM_locate(pub_params, privtag))) + goto end; + /* + * Select the keypair when using EVP_PKEY_todata() and check that + * the param array contains a private key. + */ + if (!TEST_int_eq(EVP_PKEY_todata(key, EVP_PKEY_KEYPAIR, &keypair_params), 1) + || !TEST_ptr(OSSL_PARAM_locate(keypair_params, privtag))) + goto end; + + /* + * Select only the public key when using EVP_PKEY_fromdata() and check that + * the resulting key does not contain a private key. + */ + if (!TEST_ptr(fromctx = EVP_PKEY_CTX_new_from_name(mainctx, keytype, NULL)) + || !TEST_int_eq(EVP_PKEY_fromdata_init(fromctx), 1) + || !TEST_int_eq(EVP_PKEY_fromdata(fromctx, &fromkey, EVP_PKEY_PUBLIC_KEY, + keypair_params), 1) + || !TEST_false(pkey_has_private(fromkey, privtag, use_octstring))) + goto end; + /* + * Select the keypair when using EVP_PKEY_fromdata() and check that + * the resulting key contains a private key. + */ + if (!TEST_int_eq(EVP_PKEY_fromdata(fromctx, &fromkeypair, + EVP_PKEY_KEYPAIR, keypair_params), 1) + || !TEST_true(pkey_has_private(fromkeypair, privtag, use_octstring))) + goto end; + ret = 1; +end: + EVP_PKEY_free(fromkeypair); + EVP_PKEY_free(fromkey); + EVP_PKEY_CTX_free(fromctx); + OSSL_PARAM_free(keypair_params); + OSSL_PARAM_free(pub_params); + return ret; +} + +#ifndef OPENSSL_NO_DH +static int test_dh_tofrom_data_select(void) +{ + int ret; + OSSL_PARAM params[2]; + EVP_PKEY *key = NULL; + EVP_PKEY_CTX *gctx = NULL; + + params[0] = OSSL_PARAM_construct_utf8_string("group", "ffdhe2048", 0); + params[1] = OSSL_PARAM_construct_end(); + ret = TEST_ptr(gctx = EVP_PKEY_CTX_new_from_name(mainctx, "DHX", NULL)) + && TEST_int_gt(EVP_PKEY_keygen_init(gctx), 0) + && TEST_true(EVP_PKEY_CTX_set_params(gctx, params)) + && TEST_int_gt(EVP_PKEY_generate(gctx, &key), 0) + && TEST_true(do_pkey_tofrom_data_select(key, "DHX")); + EVP_PKEY_free(key); + EVP_PKEY_CTX_free(gctx); + return ret; +} +#endif + +#ifndef OPENSSL_NO_EC +static int test_ec_tofrom_data_select(void) +{ + int ret; + EVP_PKEY *key = NULL; + + ret = TEST_ptr(key = EVP_PKEY_Q_keygen(mainctx, NULL, "EC", "P-256")) + && TEST_true(do_pkey_tofrom_data_select(key, "EC")); + EVP_PKEY_free(key); + return ret; +} + +static int test_ecx_tofrom_data_select(void) +{ + int ret; + EVP_PKEY *key = NULL; + + ret = TEST_ptr(key = EVP_PKEY_Q_keygen(mainctx, NULL, "X25519")) + && TEST_true(do_pkey_tofrom_data_select(key, "X25519")); + EVP_PKEY_free(key); + return ret; +} +#endif + +static int test_rsa_tofrom_data_select(void) +{ + int ret; + EVP_PKEY *key = NULL; + const unsigned char *pdata = kExampleRSAKeyDER; + int pdata_len = sizeof(kExampleRSAKeyDER); + + ret = TEST_ptr(key = d2i_AutoPrivateKey_ex(NULL, &pdata, pdata_len, + mainctx, NULL)) + && TEST_true(do_pkey_tofrom_data_select(key, "RSA")); + EVP_PKEY_free(key); + return ret; +} + /* This is the equivalent of test_d2i_AutoPrivateKey in evp_extra_test */ static int test_d2i_AutoPrivateKey_ex(int i) { @@ -661,6 +791,20 @@ static int do_check_int(OSSL_PARAM params[], const char *key, int expected) && TEST_int_eq(val, expected); } +static int test_dsa_tofrom_data_select(void) +{ + int ret; + EVP_PKEY *key = NULL; + const unsigned char *pkeydata = dsa_key; + + ret = TEST_ptr(key = d2i_AutoPrivateKey_ex(NULL, &pkeydata, sizeof(dsa_key), + mainctx, NULL)) + && TEST_true(do_pkey_tofrom_data_select(key, "DSA")); + + EVP_PKEY_free(key); + return ret; +} + static int test_dsa_todata(void) { EVP_PKEY *pkey = NULL; @@ -896,12 +1040,20 @@ int setup_tests(void) ADD_ALL_TESTS(test_d2i_AutoPrivateKey_ex, OSSL_NELEM(keydata)); #ifndef OPENSSL_NO_EC ADD_ALL_TESTS(test_d2i_PrivateKey_ex, 2); + ADD_TEST(test_ec_tofrom_data_select); + ADD_TEST(test_ecx_tofrom_data_select); #else ADD_ALL_TESTS(test_d2i_PrivateKey_ex, 1); #endif #ifndef OPENSSL_NO_DSA ADD_TEST(test_dsa_todata); + ADD_TEST(test_dsa_tofrom_data_select); +#endif +#ifndef OPENSSL_NO_DH + ADD_TEST(test_dh_tofrom_data_select); #endif + ADD_TEST(test_rsa_tofrom_data_select); + ADD_TEST(test_pkey_todata_null); ADD_TEST(test_pkey_export_null); ADD_TEST(test_pkey_export); -- 2.39.2