summaryrefslogtreecommitdiffstats
path: root/crypto/evp/pmeth_lib.c
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2020-09-02 09:30:42 +0200
committerRichard Levitte <levitte@openssl.org>2020-09-08 06:25:27 +0200
commit509144964ba69b69a90269da52a2dc3acb3149e6 (patch)
tree0dacf1c9eb45dd8bf460288ef08f2b410b1f8ae7 /crypto/evp/pmeth_lib.c
parent884baafba4a5fec6502b828a73188d7133b9179b (diff)
EVP: Preserve the EVP_PKEY id in a few more spots
As long as there are internal legacy keys for EVP_PKEY, we need to preserve the EVP_PKEY numeric identity when generating a key, and when creating the EVP_PKEY_CTX. For added consistency, the EVP_PKEY_CTX contructor tries a little harder to find a EVP_PKEY_METHOD. Otherwise, we may run into situations where the EVP_PKEY_CTX ends up having no associated methods at all. Reviewed-by: Paul Yang <kaishen.yy@antfin.com> (Merged from https://github.com/openssl/openssl/pull/12785)
Diffstat (limited to 'crypto/evp/pmeth_lib.c')
-rw-r--r--crypto/evp/pmeth_lib.c136
1 files changed, 89 insertions, 47 deletions
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index aef7c39a20..7f144b0afc 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -121,22 +121,36 @@ EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
return pmeth;
}
+
+static void help_get_legacy_alg_type_from_keymgmt(const char *keytype,
+ void *arg)
+{
+ int *type = arg;
+
+ if (*type == NID_undef)
+ *type = evp_pkey_name2type(keytype);
+}
+
+static int get_legacy_alg_type_from_keymgmt(const EVP_KEYMGMT *keymgmt)
+{
+ int type = NID_undef;
+
+ EVP_KEYMGMT_names_do_all(keymgmt, help_get_legacy_alg_type_from_keymgmt,
+ &type);
+ return type;
+}
#endif /* FIPS_MODULE */
static int is_legacy_alg(int id, const char *keytype)
{
#ifndef FIPS_MODULE
/* Certain EVP_PKEY keytypes are only available in legacy form */
- if (id == -1) {
- id = OBJ_sn2nid(keytype);
- if (id == NID_undef)
- id = OBJ_ln2nid(keytype);
- if (id == NID_undef)
- return 0;
- }
+ if (id == -1)
+ id = evp_pkey_name2type(keytype);
+
switch (id) {
/*
- * TODO(3.0): Remove SM2 and DHX when they are converted to have provider
+ * TODO(3.0): Remove SM2 when they are converted to have provider
* support
*/
case EVP_PKEY_SM2:
@@ -155,19 +169,12 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
int id)
{
- EVP_PKEY_CTX *ret;
+ EVP_PKEY_CTX *ret = NULL;
const EVP_PKEY_METHOD *pmeth = NULL;
EVP_KEYMGMT *keymgmt = NULL;
/*
- * When using providers, the context is bound to the algo implementation
- * later.
- */
- if (pkey == NULL && e == NULL && id == -1)
- goto common;
-
- /*
- * If the internal key is provided, we extract the keytype from its
+ * If the given |pkey| is provided, we extract the keytype from its
* keymgmt and skip over the legacy code.
*/
if (pkey != NULL && evp_pkey_is_provided(pkey)) {
@@ -177,14 +184,24 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
keytype = evp_first_name(pkey->keymgmt->prov, pkey->keymgmt->name_id);
goto common;
}
+
#ifndef FIPS_MODULE
- /* TODO(3.0) Legacy code should be removed when all is provider based */
+ /*
+ * TODO(3.0) This legacy code section should be removed when we stop
+ * supporting engines
+ */
/* BEGIN legacy */
if (id == -1) {
- if (pkey == NULL)
- return NULL;
- id = pkey->type;
+ if (pkey != NULL)
+ id = pkey->type;
+ else if (keytype != NULL)
+ id = evp_pkey_name2type(keytype);
+ if (id == NID_undef)
+ id = -1;
}
+ /* If no ID was found here, we can only resort to find a keymgmt */
+ if (id == -1)
+ goto common;
/*
* Here, we extract what information we can for the purpose of
@@ -219,24 +236,11 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
* If an ENGINE handled this method look it up. Otherwise use internal
* tables.
*/
- if (e != NULL) {
+ if (e != NULL)
pmeth = ENGINE_get_pkey_meth(e, id);
- /*
- * We are supposed to use an engine, so no point in looking for a
- * provided implementation. If pmeth is NULL here we just fail.
- */
- if (pmeth == NULL) {
- ENGINE_finish(e);
- EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM);
- return NULL;
- }
- } else
+ else
# endif
pmeth = EVP_PKEY_meth_find(id);
- /*
- * if pmeth is NULL here we can keep trying to see if we have a provided
- * implementation below.
- */
/* END legacy */
#endif /* FIPS_MODULE */
@@ -248,33 +252,71 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
if (e == NULL && keytype != NULL) {
int legacy = is_legacy_alg(id, keytype);
- if (legacy) {
- /* This could fail so ignore errors */
+ /* This could fail so ignore errors */
+ if (legacy)
ERR_set_mark();
- }
keymgmt = EVP_KEYMGMT_fetch(libctx, keytype, propquery);
- if (legacy) {
+ if (legacy)
ERR_pop_to_mark();
- } else if (keymgmt == NULL) {
- EVPerr(EVP_F_INT_CTX_NEW, EVP_R_FETCH_FAILED);
- return NULL;
+ else if (keymgmt == NULL)
+ return NULL; /* EVP_KEYMGMT_fetch() recorded an error */
+
+#ifndef FIPS_MODULE
+ /*
+ * Chase down the legacy NID, as that might be needed for diverse
+ * purposes, such as ensure that EVP_PKEY_type() can return sensible
+ * values, or that there's a better chance to "downgrade" a key when
+ * needed. We go through all keymgmt names, because the keytype
+ * that's passed to this function doesn't necessarily translate
+ * directly.
+ * TODO: Remove this when #legacy keys are gone.
+ */
+ if (keymgmt != NULL) {
+ int tmp_id = get_legacy_alg_type_from_keymgmt(keymgmt);
+
+ if (tmp_id != NID_undef) {
+ if (id == -1) {
+ id = tmp_id;
+ } else {
+ /*
+ * It really really shouldn't differ. If it still does,
+ * something is very wrong.
+ */
+ if (!ossl_assert(id == tmp_id)) {
+ EVPerr(EVP_F_INT_CTX_NEW, ERR_R_INTERNAL_ERROR);
+ EVP_KEYMGMT_free(keymgmt);
+ return NULL;
+ }
+ }
+ }
}
+#endif
+ }
+
+ if (pmeth == NULL && keymgmt == NULL) {
+ EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM);
+ } else {
+ ret = OPENSSL_zalloc(sizeof(*ret));
+ if (ret == NULL)
+ EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE);
}
- ret = OPENSSL_zalloc(sizeof(*ret));
- if (ret == NULL) {
- EVP_KEYMGMT_free(keymgmt);
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ if ((ret == NULL || pmeth == NULL) && e != NULL)
ENGINE_finish(e);
#endif
- EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE);
+
+ if (ret == NULL) {
+ EVP_KEYMGMT_free(keymgmt);
return NULL;
}
+
ret->libctx = libctx;
ret->propquery = propquery;
ret->keytype = keytype;
ret->keymgmt = keymgmt;
+ ret->legacy_keytype = id; /* TODO: Remove when #legacy key are gone */
ret->engine = e;
ret->pmeth = pmeth;
ret->operation = EVP_PKEY_OP_UNDEFINED;