X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fevp%2Fp_lib.c;h=9eb9f4937b2215c798c7b786f1f6c28277cb18be;hp=b176f100e8d945784fcea2f0976ab4919b7e0005;hb=c19d89785075393d27287c90086fa2aeaa842e62;hpb=96ebe52e897dea29664683e138877fb5eb995e4d diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index b176f100e8..9eb9f4937b 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-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 @@ -24,22 +24,31 @@ #include #include #include +#include #include #include #include +#include #include #include #include "crypto/asn1.h" #include "crypto/evp.h" +#include "internal/evp.h" #include "internal/provider.h" #include "evp_local.h" +DEFINE_STACK_OF(X509_ATTRIBUTE) + +#include "crypto/ec.h" + +/* TODO remove this when the EVP_PKEY_is_a() #legacy support hack is removed */ +#include "e_os.h" /* strcasecmp on Windows */ static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, int len, EVP_KEYMGMT *keymgmt); static void evp_pkey_free_it(EVP_PKEY *key); -#ifndef FIPS_MODE +#ifndef FIPS_MODULE /* The type of parameters selected in key parameter functions */ # define SELECT_PARAMETERS OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS @@ -89,6 +98,16 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) return 0; } +int EVP_PKEY_set_ex_data(EVP_PKEY *key, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&key->ex_data, idx, arg); +} + +void *EVP_PKEY_get_ex_data(const EVP_PKEY *key, int idx) +{ + return CRYPTO_get_ex_data(&key->ex_data, idx); +} + int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { /* @@ -212,9 +231,11 @@ static int evp_pkey_cmp_any(const EVP_PKEY *a, const EVP_PKEY *b, * us to compare types using legacy NIDs. */ if ((a->type != EVP_PKEY_NONE - && !EVP_KEYMGMT_is_a(b->keymgmt, OBJ_nid2sn(a->type))) + && (b->keymgmt == NULL + || !EVP_KEYMGMT_is_a(b->keymgmt, OBJ_nid2sn(a->type)))) || (b->type != EVP_PKEY_NONE - && !EVP_KEYMGMT_is_a(a->keymgmt, OBJ_nid2sn(b->type)))) + && (a->keymgmt == NULL + || !EVP_KEYMGMT_is_a(a->keymgmt, OBJ_nid2sn(b->type))))) return -1; /* not the same key type */ /* @@ -300,78 +321,213 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) return -2; } -EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e, - const unsigned char *priv, - size_t len) + +static EVP_PKEY *new_raw_key_int(OPENSSL_CTX *libctx, + const char *strtype, + const char *propq, + int nidtype, + ENGINE *e, + const unsigned char *key, + size_t len, + int key_is_priv) { - EVP_PKEY *ret = EVP_PKEY_new(); + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + const EVP_PKEY_ASN1_METHOD *ameth = NULL; + int result = 0; - if (ret == NULL - || !pkey_set_type(ret, e, type, NULL, -1, NULL)) { - /* EVPerr already called */ - goto err; +# ifndef OPENSSL_NO_ENGINE + /* Check if there is an Engine for this type */ + if (e == NULL) { + ENGINE *tmpe = NULL; + + if (strtype != NULL) + ameth = EVP_PKEY_asn1_find_str(&tmpe, strtype, -1); + else if (nidtype != EVP_PKEY_NONE) + ameth = EVP_PKEY_asn1_find(&tmpe, nidtype); + + /* If tmpe is NULL then no engine is claiming to support this type */ + if (tmpe == NULL) + ameth = NULL; + + ENGINE_finish(tmpe); } +# endif - if (ret->ameth->set_priv_key == NULL) { - EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + if (e == NULL && ameth == NULL) { + /* + * No engine is claiming to support this type, so lets see if we have + * a provider. + */ + ctx = EVP_PKEY_CTX_new_from_name(libctx, + strtype != NULL ? strtype + : OBJ_nid2sn(nidtype), + propq); + if (ctx == NULL) { + EVPerr(0, ERR_R_MALLOC_FAILURE); + goto err; + } + /* May fail if no provider available */ + ERR_set_mark(); + if (EVP_PKEY_key_fromdata_init(ctx) == 1) { + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + ERR_clear_last_mark(); + params[0] = OSSL_PARAM_construct_octet_string( + key_is_priv ? OSSL_PKEY_PARAM_PRIV_KEY + : OSSL_PKEY_PARAM_PUB_KEY, + (void *)key, len); + + if (EVP_PKEY_fromdata(ctx, &pkey, params) != 1) { + EVPerr(0, EVP_R_KEY_SETUP_FAILED); + goto err; + } + + EVP_PKEY_CTX_free(ctx); + + return pkey; + } + ERR_pop_to_mark(); + /* else not supported so fallback to legacy */ + } + + /* Legacy code path */ + + pkey = EVP_PKEY_new(); + if (pkey == NULL) { + EVPerr(0, ERR_R_MALLOC_FAILURE); goto err; } - if (!ret->ameth->set_priv_key(ret, priv, len)) { - EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, EVP_R_KEY_SETUP_FAILED); + if (!pkey_set_type(pkey, e, nidtype, strtype, -1, NULL)) { + /* EVPerr already called */ goto err; } - return ret; + if (!ossl_assert(pkey->ameth != NULL)) + goto err; + + if (key_is_priv) { + if (pkey->ameth->set_priv_key == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + goto err; + } + + if (!pkey->ameth->set_priv_key(pkey, key, len)) { + EVPerr(0, EVP_R_KEY_SETUP_FAILED); + goto err; + } + } else { + if (pkey->ameth->set_pub_key == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + goto err; + } + + if (!pkey->ameth->set_pub_key(pkey, key, len)) { + EVPerr(0, EVP_R_KEY_SETUP_FAILED); + goto err; + } + } + result = 1; err: - EVP_PKEY_free(ret); - return NULL; + if (!result) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + EVP_PKEY_CTX_free(ctx); + return pkey; +} + +EVP_PKEY *EVP_PKEY_new_raw_private_key_with_libctx(OPENSSL_CTX *libctx, + const char *keytype, + const char *propq, + const unsigned char *priv, + size_t len) +{ + return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, priv, + len, 1); +} + +EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e, + const unsigned char *priv, + size_t len) +{ + return new_raw_key_int(NULL, NULL, NULL, type, e, priv, len, 1); +} + +EVP_PKEY *EVP_PKEY_new_raw_public_key_with_libctx(OPENSSL_CTX *libctx, + const char *keytype, + const char *propq, + const unsigned char *pub, + size_t len) +{ + return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, pub, + len, 0); } EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e, const unsigned char *pub, size_t len) { - EVP_PKEY *ret = EVP_PKEY_new(); + return new_raw_key_int(NULL, NULL, NULL, type, e, pub, len, 0); +} - if (ret == NULL - || !pkey_set_type(ret, e, type, NULL, -1, NULL)) { - /* EVPerr already called */ - goto err; - } +struct raw_key_details_st +{ + unsigned char **key; + size_t *len; + int selection; +}; - if (ret->ameth->set_pub_key == NULL) { - EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - goto err; - } +static OSSL_CALLBACK get_raw_key_details; +static int get_raw_key_details(const OSSL_PARAM params[], void *arg) +{ + const OSSL_PARAM *p = NULL; + struct raw_key_details_st *raw_key = arg; - if (!ret->ameth->set_pub_key(ret, pub, len)) { - EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, EVP_R_KEY_SETUP_FAILED); - goto err; + if (raw_key->selection == OSSL_KEYMGMT_SELECT_PRIVATE_KEY) { + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY)) + != NULL) + return OSSL_PARAM_get_octet_string(p, (void **)raw_key->key, + SIZE_MAX, raw_key->len); + } else if (raw_key->selection == OSSL_KEYMGMT_SELECT_PUBLIC_KEY) { + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY)) + != NULL) + return OSSL_PARAM_get_octet_string(p, (void **)raw_key->key, + SIZE_MAX, raw_key->len); } - return ret; - - err: - EVP_PKEY_free(ret); - return NULL; + return 0; } int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv, size_t *len) { - /* TODO(3.0) Do we need to do anything about provider side keys? */ - if (pkey->ameth->get_priv_key == NULL) { - EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + if (pkey->keymgmt != NULL) { + struct raw_key_details_st raw_key; + + raw_key.key = priv == NULL ? NULL : &priv; + raw_key.len = len; + raw_key.selection = OSSL_KEYMGMT_SELECT_PRIVATE_KEY; + + return evp_keymgmt_export(pkey->keymgmt, pkey->keydata, + OSSL_KEYMGMT_SELECT_PRIVATE_KEY, + get_raw_key_details, &raw_key); + } + + if (pkey->ameth == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + + if (pkey->ameth->get_priv_key == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return 0; } if (!pkey->ameth->get_priv_key(pkey, priv, len)) { - EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, EVP_R_GET_RAW_KEY_FAILED); + EVPerr(0, EVP_R_GET_RAW_KEY_FAILED); return 0; } @@ -381,7 +537,23 @@ int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv, int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub, size_t *len) { - /* TODO(3.0) Do we need to do anything about provider side keys? */ + if (pkey->keymgmt != NULL) { + struct raw_key_details_st raw_key; + + raw_key.key = pub == NULL ? NULL : &pub; + raw_key.len = len; + raw_key.selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + + return evp_keymgmt_export(pkey->keymgmt, pkey->keydata, + OSSL_KEYMGMT_SELECT_PUBLIC_KEY, + get_raw_key_details, &raw_key); + } + + if (pkey->ameth == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (pkey->ameth->get_pub_key == NULL) { EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); @@ -610,14 +782,6 @@ RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) # endif # ifndef OPENSSL_NO_DSA -int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) -{ - int ret = EVP_PKEY_assign_DSA(pkey, key); - if (ret) - DSA_up_ref(key); - return ret; -} - DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey) { if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) { @@ -631,6 +795,13 @@ DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey) return pkey->pkey.dsa; } +int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) +{ + int ret = EVP_PKEY_assign_DSA(pkey, key); + if (ret) + DSA_up_ref(key); + return ret; +} DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) { DSA *ret = EVP_PKEY_get0_DSA(pkey); @@ -638,10 +809,11 @@ DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) DSA_up_ref(ret); return ret; } -# endif +# endif /* OPENSSL_NO_DSA */ +#endif /* FIPS_MODULE */ +#ifndef FIPS_MODULE # ifndef OPENSSL_NO_EC - int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) { int ret = EVP_PKEY_assign_EC_KEY(pkey, key); @@ -732,6 +904,119 @@ int EVP_PKEY_base_id(const EVP_PKEY *pkey) return EVP_PKEY_type(pkey->type); } +int EVP_PKEY_is_a(const EVP_PKEY *pkey, const char *name) +{ +#ifndef FIPS_MODULE + if (pkey->keymgmt == NULL) { + /* + * These hard coded cases are pure hackery to get around the fact + * that names in crypto/objects/objects.txt are a mess. There is + * no "EC", and "RSA" leads to the NID for 2.5.8.1.1, an OID that's + * fallen out in favor of { pkcs-1 1 }, i.e. 1.2.840.113549.1.1.1, + * the NID of which is used for EVP_PKEY_RSA. Strangely enough, + * "DSA" is accurate... but still, better be safe and hard-code + * names that we know. + * TODO Clean this away along with all other #legacy support. + */ + int type; + + if (strcasecmp(name, "RSA") == 0) + type = EVP_PKEY_RSA; +#ifndef OPENSSL_NO_EC + else if (strcasecmp(name, "EC") == 0) + type = EVP_PKEY_EC; +#endif +#ifndef OPENSSL_NO_DSA + else if (strcasecmp(name, "DSA") == 0) + type = EVP_PKEY_DSA; +#endif + else + type = EVP_PKEY_type(OBJ_sn2nid(name)); + return EVP_PKEY_type(pkey->type) == type; + } +#endif + return EVP_KEYMGMT_is_a(pkey->keymgmt, name); +} + +int EVP_PKEY_can_sign(const EVP_PKEY *pkey) +{ + if (pkey->keymgmt == NULL) { + switch (EVP_PKEY_base_id(pkey)) { + case EVP_PKEY_RSA: + return 1; +#ifndef OPENSSL_NO_DSA + case EVP_PKEY_DSA: + return 1; +#endif +#ifndef OPENSSL_NO_EC + case EVP_PKEY_ED25519: + case EVP_PKEY_ED448: + return 1; + case EVP_PKEY_EC: /* Including SM2 */ + return EC_KEY_can_sign(pkey->pkey.ec); +#endif + default: + break; + } + } else { + const OSSL_PROVIDER *prov = EVP_KEYMGMT_provider(pkey->keymgmt); + OPENSSL_CTX *libctx = ossl_provider_library_context(prov); + const char *supported_sig = + pkey->keymgmt->query_operation_name != NULL + ? pkey->keymgmt->query_operation_name(OSSL_OP_SIGNATURE) + : evp_first_name(prov, pkey->keymgmt->name_id); + EVP_SIGNATURE *signature = NULL; + + signature = EVP_SIGNATURE_fetch(libctx, supported_sig, NULL); + if (signature != NULL) { + EVP_SIGNATURE_free(signature); + return 1; + } + } + return 0; +} + +#ifndef OPENSSL_NO_EC +/* + * TODO rewrite when we have proper data extraction functions + * Note: an octet pointer would be desirable! + */ +static OSSL_CALLBACK get_ec_curve_name_cb; +static int get_ec_curve_name_cb(const OSSL_PARAM params[], void *arg) +{ + const OSSL_PARAM *p = NULL; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_NAME)) != NULL) + return OSSL_PARAM_get_utf8_string(p, arg, 0); + + /* If there is no curve name, this is not an EC key */ + return 0; +} + +int evp_pkey_get_EC_KEY_curve_nid(const EVP_PKEY *pkey) +{ + int ret = NID_undef; + + if (pkey->keymgmt == NULL) { + if (EVP_PKEY_base_id(pkey) == EVP_PKEY_EC) { + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey); + + ret = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); + } + } else if (EVP_PKEY_is_a(pkey, "EC") || EVP_PKEY_is_a(pkey, "SM2")) { + char *curve_name = NULL; + + ret = evp_keymgmt_export(pkey->keymgmt, pkey->keydata, + OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, + get_ec_curve_name_cb, &curve_name); + if (ret) + ret = ec_curve_name2nid(curve_name); + OPENSSL_free(curve_name); + } + + return ret; +} +#endif static int print_reset_indent(BIO **out, int pop_f_prefix, long saved_indent) { @@ -877,28 +1162,10 @@ int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid) int EVP_PKEY_get_default_digest_name(EVP_PKEY *pkey, char *mdname, size_t mdname_sz) { - if (pkey->ameth == NULL) { - OSSL_PARAM params[3]; - char mddefault[100] = ""; - char mdmandatory[100] = ""; - - params[0] = - OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, - mddefault, sizeof(mddefault)); - params[1] = - OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, - mdmandatory, - sizeof(mdmandatory)); - params[2] = OSSL_PARAM_construct_end(); - if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params)) - return 0; - if (mdmandatory[0] != '\0') { - OPENSSL_strlcpy(mdname, mdmandatory, mdname_sz); - return 2; - } - OPENSSL_strlcpy(mdname, mddefault, mdname_sz); - return 1; - } + if (pkey->ameth == NULL) + return evp_keymgmt_util_get_deflt_digest_name(pkey->keymgmt, + pkey->keydata, + mdname, mdname_sz); { int nid = NID_undef; @@ -951,9 +1218,9 @@ size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt) return rv; } -#endif /* FIPS_MODE */ +#endif /* FIPS_MODULE */ -/*- All methods below can also be used in FIPS_MODE */ +/*- All methods below can also be used in FIPS_MODULE */ EVP_PKEY *EVP_PKEY_new(void) { @@ -970,10 +1237,20 @@ EVP_PKEY *EVP_PKEY_new(void) ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); - OPENSSL_free(ret); - return NULL; + goto err; + } +#ifndef FIPS_MODULE + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, ret, &ret->ex_data)) { + EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); + goto err; } +#endif return ret; + + err: + CRYPTO_THREAD_lock_free(ret->lock); + OPENSSL_free(ret); + return NULL; } /* @@ -992,7 +1269,7 @@ EVP_PKEY *EVP_PKEY_new(void) static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, int len, EVP_KEYMGMT *keymgmt) { -#ifndef FIPS_MODE +#ifndef FIPS_MODULE const EVP_PKEY_ASN1_METHOD *ameth = NULL; ENGINE **eptr = (e == NULL) ? &e : NULL; #endif @@ -1010,13 +1287,13 @@ static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, if (pkey != NULL) { int free_it = 0; -#ifndef FIPS_MODE +#ifndef FIPS_MODULE free_it = free_it || pkey->pkey.ptr != NULL; #endif free_it = free_it || pkey->keydata != NULL; if (free_it) evp_pkey_free_it(pkey); -#ifndef FIPS_MODE +#ifndef FIPS_MODULE /* * If key type matches and a method exists then this lookup has * succeeded once so just indicate success. @@ -1034,7 +1311,7 @@ static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, # endif #endif } -#ifndef FIPS_MODE +#ifndef FIPS_MODULE if (str != NULL) ameth = EVP_PKEY_asn1_find_str(eptr, str, len); else if (type != EVP_PKEY_NONE) @@ -1049,7 +1326,7 @@ static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, { int check = 1; -#ifndef FIPS_MODE +#ifndef FIPS_MODULE check = check && ameth == NULL; #endif check = check && keymgmt == NULL; @@ -1069,7 +1346,7 @@ static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, pkey->save_type = type; pkey->type = type; -#ifndef FIPS_MODE +#ifndef FIPS_MODULE /* * If the internal "origin" key is provider side, don't save |ameth|. * The main reason is that |ameth| is one factor to detect that the @@ -1087,16 +1364,18 @@ static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, * to the |save_type| field, because |type| is supposed to be set * to EVP_PKEY_NONE in that case. */ - if (keymgmt != NULL) - pkey->save_type = ameth->pkey_id; - else if (pkey->ameth != NULL) - pkey->type = ameth->pkey_id; + if (ameth != NULL) { + if (keymgmt != NULL) + pkey->save_type = ameth->pkey_id; + else if (pkey->ameth != NULL) + pkey->type = ameth->pkey_id; + } #endif } return 1; } -#ifndef FIPS_MODE +#ifndef FIPS_MODULE static void find_ameth(const char *name, void *data) { const char **str = data; @@ -1121,7 +1400,7 @@ static void find_ameth(const char *name, void *data) int EVP_PKEY_set_type_by_keymgmt(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt) { -#ifndef FIPS_MODE +#ifndef FIPS_MODULE # define EVP_PKEY_TYPE_STR str[0] # define EVP_PKEY_TYPE_STRLEN (str[0] == NULL ? -1 : (int)strlen(str[0])) /* @@ -1160,7 +1439,7 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey) return ((i > 1) ? 1 : 0); } -#ifndef FIPS_MODE +#ifndef FIPS_MODULE void evp_pkey_free_legacy(EVP_PKEY *x) { if (x->ameth != NULL) { @@ -1176,14 +1455,14 @@ void evp_pkey_free_legacy(EVP_PKEY *x) # endif x->type = EVP_PKEY_NONE; } -#endif /* FIPS_MODE */ +#endif /* FIPS_MODULE */ static void evp_pkey_free_it(EVP_PKEY *x) { /* internal function; x is never NULL */ evp_keymgmt_util_clear_operation_cache(x); -#ifndef FIPS_MODE +#ifndef FIPS_MODULE evp_pkey_free_legacy(x); #endif @@ -1208,8 +1487,11 @@ void EVP_PKEY_free(EVP_PKEY *x) return; REF_ASSERT_ISNT(i < 0); evp_pkey_free_it(x); +#ifndef FIPS_MODULE + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, x, &x->ex_data); +#endif CRYPTO_THREAD_lock_free(x->lock); -#ifndef FIPS_MODE +#ifndef FIPS_MODULE sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); #endif OPENSSL_free(x); @@ -1221,7 +1503,7 @@ int EVP_PKEY_size(const EVP_PKEY *pkey) if (pkey != NULL) { size = pkey->cache.size; -#ifndef FIPS_MODE +#ifndef FIPS_MODULE if (pkey->ameth != NULL && pkey->ameth->pkey_size != NULL) size = pkey->ameth->pkey_size(pkey); #endif @@ -1243,14 +1525,14 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, /* No key data => nothing to export */ check = 1; -#ifndef FIPS_MODE +#ifndef FIPS_MODULE check = check && pk->pkey.ptr == NULL; #endif check = check && pk->keydata == NULL; if (check) return NULL; -#ifndef FIPS_MODE +#ifndef FIPS_MODULE if (pk->pkey.ptr != NULL) { /* * If the legacy key doesn't have an dirty counter or export function, @@ -1282,7 +1564,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, if (tmp_keymgmt == NULL) goto end; -#ifndef FIPS_MODE +#ifndef FIPS_MODULE if (pk->pkey.ptr != NULL) { size_t i = 0; @@ -1322,7 +1604,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, if ((keydata = evp_keymgmt_newdata(tmp_keymgmt)) == NULL) goto end; - if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt)) { + if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt, libctx, propquery)) { evp_keymgmt_freedata(tmp_keymgmt, keydata); keydata = NULL; goto end; @@ -1354,7 +1636,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk); goto end; } -#endif /* FIPS_MODE */ +#endif /* FIPS_MODULE */ keydata = evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt); @@ -1374,7 +1656,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, return keydata; } -#ifndef FIPS_MODE +#ifndef FIPS_MODULE int evp_pkey_downgrade(EVP_PKEY *pk) { EVP_KEYMGMT *keymgmt = pk->keymgmt; @@ -1416,27 +1698,47 @@ int evp_pkey_downgrade(EVP_PKEY *pk) evp_pkey_free_it(pk); if (EVP_PKEY_set_type(pk, type)) { /* If the key is typed but empty, we're done */ - if (keydata == NULL) + if (keydata == NULL) { + /* We're dropping the EVP_KEYMGMT */ + EVP_KEYMGMT_free(keymgmt); return 1; + } if (pk->ameth->import_from == NULL) { ERR_raise_data(ERR_LIB_EVP, EVP_R_NO_IMPORT_FUNCTION, "key type = %s", keytype); - } else if (evp_keymgmt_export(keymgmt, keydata, - OSSL_KEYMGMT_SELECT_ALL, - pk->ameth->import_from, pk)) { + } else { /* - * Save the provider side data in the operation cache, so they'll - * find it again. evp_pkey_free_it() cleared the cache, so it's - * safe to assume slot zero is free. - * Note that evp_keymgmt_util_cache_keydata() increments keymgmt's - * reference count. + * We perform the export in the same libctx as the keymgmt that we + * are using. */ - evp_keymgmt_util_cache_keydata(pk, 0, keymgmt, keydata); - - /* Synchronize the dirty count */ - pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk); - return 1; + OPENSSL_CTX *libctx = ossl_provider_library_context(keymgmt->prov); + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, NULL); + if (pctx == NULL) + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + + if (pctx != NULL + && evp_keymgmt_export(keymgmt, keydata, + OSSL_KEYMGMT_SELECT_ALL, + pk->ameth->import_from, pctx)) { + /* + * Save the provider side data in the operation cache, so they'll + * find it again. evp_pkey_free_it() cleared the cache, so it's + * safe to assume slot zero is free. + * Note that evp_keymgmt_util_cache_keydata() increments keymgmt's + * reference count. + */ + evp_keymgmt_util_cache_keydata(pk, 0, keymgmt, keydata); + EVP_PKEY_CTX_free(pctx); + + /* Synchronize the dirty count */ + pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk); + + /* evp_keymgmt_export() increased the refcount... */ + EVP_KEYMGMT_free(keymgmt); + return 1; + } + EVP_PKEY_CTX_free(pctx); } ERR_raise_data(ERR_LIB_EVP, EVP_R_KEYMGMT_EXPORT_FAILURE, @@ -1454,11 +1756,13 @@ int evp_pkey_downgrade(EVP_PKEY *pk) ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); return 0; } + /* EVP_PKEY_set_type_by_keymgmt() increased the refcount... */ + EVP_KEYMGMT_free(keymgmt); pk->keydata = keydata; evp_keymgmt_util_cache_keyinfo(pk); return 0; /* No downgrade, but at least the key is restored */ } -#endif /* FIPS_MODE */ +#endif /* FIPS_MODULE */ const OSSL_PARAM *EVP_PKEY_gettable_params(EVP_PKEY *pkey) { @@ -1469,23 +1773,11 @@ const OSSL_PARAM *EVP_PKEY_gettable_params(EVP_PKEY *pkey) 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; @@ -1498,12 +1790,9 @@ int EVP_PKEY_get_bn_param(EVP_PKEY *pkey, const char *key_name, BIGNUM **bn) 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) + if (!OSSL_PARAM_modified(params) || params[0].return_size == 0) return 0; buf_sz = params[0].return_size; /* @@ -1520,7 +1809,7 @@ int EVP_PKEY_get_bn_param(EVP_PKEY *pkey, const char *key_name, BIGNUM **bn) goto err; } /* Fail if the param was not found */ - if (params[0].return_size == not_set) + if (!OSSL_PARAM_modified(params)) goto err; ret = OSSL_PARAM_get_BN(params, bn); err: @@ -1533,7 +1822,6 @@ int EVP_PKEY_get_octet_string_param(EVP_PKEY *pkey, const char *key_name, size_t *out_sz) { OSSL_PARAM params[2]; - const size_t not_set = max_buf_sz + 1; if (pkey == NULL || pkey->keymgmt == NULL @@ -1542,11 +1830,9 @@ int EVP_PKEY_get_octet_string_param(EVP_PKEY *pkey, const char *key_name, 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) + if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params) + || !OSSL_PARAM_modified(params)) return 0; if (out_sz != NULL) *out_sz = params[0].return_size; @@ -1558,7 +1844,6 @@ int EVP_PKEY_get_utf8_string_param(EVP_PKEY *pkey, const char *key_name, size_t *out_sz) { OSSL_PARAM params[2]; - const size_t not_set = max_buf_sz + 1; if (pkey == NULL || pkey->keymgmt == NULL @@ -1567,11 +1852,9 @@ int EVP_PKEY_get_utf8_string_param(EVP_PKEY *pkey, const char *key_name, 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) + if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params) + || !OSSL_PARAM_modified(params)) return 0; if (out_sz != NULL) *out_sz = params[0].return_size; @@ -1581,7 +1864,6 @@ int EVP_PKEY_get_utf8_string_param(EVP_PKEY *pkey, const char *key_name, 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 @@ -1590,11 +1872,9 @@ int EVP_PKEY_get_int_param(EVP_PKEY *pkey, const char *key_name, int *out) 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) + if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params) + || !OSSL_PARAM_modified(params)) return 0; return 1; } @@ -1602,7 +1882,6 @@ 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) { OSSL_PARAM params[2]; - const size_t not_set = sizeof(size_t) + 1; if (pkey == NULL || pkey->keymgmt == NULL @@ -1611,11 +1890,9 @@ int EVP_PKEY_get_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t *out) 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) + if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params) + || !OSSL_PARAM_modified(params)) return 0; return 1; }