EC: Refactor EVP_PKEY_CTX curve setting macros for param generation
authorRichard Levitte <levitte@openssl.org>
Thu, 19 Mar 2020 13:02:42 +0000 (14:02 +0100)
committerRichard Levitte <levitte@openssl.org>
Wed, 15 Apr 2020 09:04:28 +0000 (11:04 +0200)
The macros are converted to functions, and are modified to support
provider implementations.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/11328)

crypto/ec/build.info
crypto/ec/ec_ctrl.c [new file with mode: 0644]
crypto/ec/ec_evp_lib.c [deleted file]
crypto/evp/pmeth_lib.c
doc/man3/EVP_PKEY_CTX_ctrl.pod
include/openssl/ec.h
util/libcrypto.num

index 8f12e2e39e84b764ad321603d9eee0fe76289c38..590bbbde5377f80ffa639594fa7c7affcb8a0d64 100644 (file)
@@ -53,7 +53,7 @@ $COMMON=ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
         curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \
         $ECASM ec_backend.c ecx_backend.c
 SOURCE[../../libcrypto]=$COMMON ec_ameth.c ec_pmeth.c ecx_meth.c ecx_key.c \
-                        ec_err.c ecdh_kdf.c eck_prn.c ec_evp_lib.c
+                        ec_err.c ecdh_kdf.c eck_prn.c ec_ctrl.c
 SOURCE[../../providers/libfips.a]=$COMMON
 
 # Implementations are now spread across several libraries, so the defines
diff --git a/crypto/ec/ec_ctrl.c b/crypto/ec/ec_ctrl.c
new file mode 100644 (file)
index 0000000..314ebe6
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ * 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 <string.h>
+
+#include <openssl/err.h>
+#include <openssl/opensslv.h>
+
+#include <openssl/core_names.h>
+#include "crypto/evp.h"
+
+#include "ec_local.h"
+
+/*
+ * This file is meant to contain functions to provide EVP_PKEY support for EC
+ * keys.
+ */
+
+static ossl_inline
+int evp_pkey_ctx_getset_ecdh_param_checks(const EVP_PKEY_CTX *ctx)
+{
+    if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    /* If key type not EC return error */
+    if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC)
+        return -1;
+
+    return 1;
+}
+
+int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode)
+{
+    int ret;
+    OSSL_PARAM params[2], *p = params;
+
+    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+    if (ret != 1)
+        return ret;
+
+    /*
+     * Valid input values are:
+     *  * 0 for disable
+     *  * 1 for enable
+     *  * -1 for reset to default for associated priv key
+     */
+    if (cofactor_mode < -1 || cofactor_mode > 1) {
+        /* Uses the same return value of pkey_ec_ctrl() */
+        return -2;
+    }
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
+                                 EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_EC_ECDH_COFACTOR,
+                                 cofactor_mode, NULL);
+
+    *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
+                                    &cofactor_mode);
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_set_params_strict(ctx, params);
+    if (ret == -2) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    return ret;
+}
+
+int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx)
+{
+    int ret, mode;
+    OSSL_PARAM params[2], *p = params;
+
+    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+    if (ret != 1)
+        return ret;
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
+                                 EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL);
+
+    *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
+                                    &mode);
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_get_params_strict(ctx, params);
+    if (ret == -2) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    } else if (ret != 1) {
+        return -1;
+    }
+
+    if (mode < 0 || mode > 1) {
+        /*
+         * The provider should return either 0 or 1, any other value is a
+         * provider error.
+         */
+        return -1;
+    }
+
+    return mode;
+}
+
+int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
+{
+    int ret;
+    const char *kdf_type;
+    OSSL_PARAM params[2], *p = params;
+
+    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+    if (ret != 1)
+        return ret;
+
+    switch (kdf) {
+        case EVP_PKEY_ECDH_KDF_NONE:
+            kdf_type = "";
+            break;
+        case EVP_PKEY_ECDH_KDF_X9_63:
+            kdf_type = OSSL_KDF_NAME_X963KDF;
+            break;
+        default:
+            return -2;
+    }
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
+                                 EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL);
+
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE,
+                                            /*
+                                             * Cast away the const. This is read
+                                             * only so should be safe
+                                             */
+                                            (char *)kdf_type, 0);
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_set_params_strict(ctx, params);
+    if (ret == -2) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    return ret;
+}
+
+int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx)
+{
+    int ret;
+    /* 80 should be big enough */
+    char kdf_type[80];
+    OSSL_PARAM params[2], *p = params;
+
+    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+    if (ret != 1)
+        return ret;
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
+                                 EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL);
+
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE,
+                                            kdf_type, sizeof(kdf_type));
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_get_params_strict(ctx, params);
+    if (ret == -2) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    } else if (ret != 1) {
+        return -1;
+    }
+
+    if (kdf_type[0] == '\0')
+        return EVP_PKEY_ECDH_KDF_NONE;
+    else if (strcmp(kdf_type, OSSL_KDF_NAME_X963KDF) == 0)
+        return EVP_PKEY_ECDH_KDF_X9_63;
+
+    return -1;
+}
+
+int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+    int ret;
+    OSSL_PARAM params[2], *p = params;
+    const char *md_name = NULL;
+
+    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+    if (ret != 1)
+        return ret;
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
+                                 EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md));
+
+    md_name = (md == NULL) ? "" : EVP_MD_name(md);
+
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST,
+                                            /*
+                                             * Cast away the const. This is read
+                                             * only so should be safe
+                                             */
+                                            (char *)md_name, 0);
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_set_params_strict(ctx, params);
+    if (ret == -2) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+    return ret;
+}
+
+int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
+{
+    /* 80 should be big enough */
+    char name[80] = "";
+    int ret;
+    OSSL_PARAM params[2], *p = params;
+
+    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+    if (ret != 1)
+        return ret;
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
+                                 EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd));
+
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST,
+                                            name, sizeof(name));
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_get_params_strict(ctx, params);
+    if (ret == -2) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    } else if (ret != 1) {
+        return -1;
+    }
+
+    /* May be NULL meaning "unknown" */
+    *pmd = EVP_get_digestbyname(name);
+
+    return 1;
+}
+
+int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int in)
+{
+    int ret;
+    size_t len = in;
+    OSSL_PARAM params[2], *p = params;
+
+    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+    if (ret != 1)
+        return ret;
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
+                                 EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_EC_KDF_OUTLEN, in, NULL);
+
+    if (in <= 0) {
+        /*
+         * This would ideally be -1 or 0, but we have to retain compatibility
+         * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
+         * in <= 0
+         */
+        return -2;
+    }
+
+    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
+                                       &len);
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_set_params_strict(ctx, params);
+    if (ret == -2) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+    return ret;
+}
+
+int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
+{
+    size_t len = UINT_MAX;
+    int ret;
+    OSSL_PARAM params[2], *p = params;
+
+    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+    if (ret != 1)
+        return ret;
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
+                                 EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0,
+                                 (void *)(plen));
+
+    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
+                                       &len);
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_get_params_strict(ctx, params);
+    if (ret == -2) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    } else if (ret != 1) {
+        return -1;
+    }
+
+    if (len > INT_MAX)
+        return -1;
+
+    *plen = (int)len;
+
+    return 1;
+}
+
+int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
+{
+    int ret;
+    OSSL_PARAM params[2], *p = params;
+
+    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+    if (ret != 1)
+        return ret;
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
+                                 EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_EC_KDF_UKM, len, (void *)(ukm));
+
+    *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
+                                            /*
+                                             * Cast away the const. This is read
+                                             * only so should be safe
+                                             */
+                                            (void *)ukm,
+                                            (size_t)len);
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_set_params_strict(ctx, params);
+    if (ret == -2) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+    if (ret == 1)
+        OPENSSL_free(ukm);
+    return ret;
+}
+
+int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
+{
+    size_t ukmlen;
+    int ret;
+    OSSL_PARAM params[3], *p = params;
+
+    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+    if (ret != 1)
+        return ret;
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
+                                 EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0,
+                                 (void *)(pukm));
+
+    *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
+                                          (void **)pukm, 0);
+    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_UKM_LEN,
+                                       &ukmlen);
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_get_params_strict(ctx, params);
+    if (ret == -2) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    } else if (ret != 1) {
+        return -1;
+    }
+
+    if (ukmlen > INT_MAX)
+        return -1;
+
+    return (int)ukmlen;
+}
+
+int EVP_PKEY_CTX_set_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
+                                            const char *name)
+{
+    OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+    OSSL_PARAM *p = params;
+
+    if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    if (name == NULL)
+        return -1;
+
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_NAME,
+                                            (char *)name, 0);
+    return EVP_PKEY_CTX_set_params(ctx, params);
+}
+
+int EVP_PKEY_CTX_get_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
+                                            char *name, size_t namelen)
+{
+    OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+    OSSL_PARAM *p = params;
+
+    if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    if (name == NULL)
+        return -1;
+
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_NAME,
+                                            name, namelen);
+    if (!EVP_PKEY_CTX_get_params(ctx, params))
+        return -1;
+    return 1;
+}
+
+#ifndef FIPS_MODE
+int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid)
+{
+    if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    /* Legacy: if key type not EC return error */
+    if (ctx->pmeth != NULL
+        && EVP_PKEY_type(ctx->pmeth->pkey_id) != EVP_PKEY_EC)
+        return -1;
+
+    if (ctx->op.keymgmt.genctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
+                                 EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN,
+                                 EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID,
+                                 nid, NULL);
+
+    return EVP_PKEY_CTX_set_ec_paramgen_curve_name(ctx, OBJ_nid2sn(nid));
+}
+#endif
diff --git a/crypto/ec/ec_evp_lib.c b/crypto/ec/ec_evp_lib.c
deleted file mode 100644 (file)
index e4d7815..0000000
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * 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 <string.h>
-
-#include <openssl/err.h>
-#include <openssl/opensslv.h>
-
-#include <openssl/core_names.h>
-#include "crypto/evp.h"
-
-#include "ec_local.h"
-
-/*
- * This file is meant to contain functions to provide EVP_PKEY support for EC
- * keys.
- */
-
-static ossl_inline
-int evp_pkey_ctx_getset_ecdh_param_checks(const EVP_PKEY_CTX *ctx)
-{
-    if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-        return -2;
-    }
-
-    /* If key type not EC return error */
-    if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC)
-        return -1;
-
-    return 1;
-}
-
-int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode)
-{
-    int ret;
-    OSSL_PARAM params[2], *p = params;
-
-    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
-    if (ret != 1)
-        return ret;
-
-    /*
-     * Valid input values are:
-     *  * 0 for disable
-     *  * 1 for enable
-     *  * -1 for reset to default for associated priv key
-     */
-    if (cofactor_mode < -1 || cofactor_mode > 1) {
-        /* Uses the same return value of pkey_ec_ctrl() */
-        return -2;
-    }
-
-    /* TODO(3.0): Remove this eventually when no more legacy */
-    if (ctx->op.kex.exchprovctx == NULL)
-        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
-                                 EVP_PKEY_OP_DERIVE,
-                                 EVP_PKEY_CTRL_EC_ECDH_COFACTOR,
-                                 cofactor_mode, NULL);
-
-    *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
-                                    &cofactor_mode);
-    *p++ = OSSL_PARAM_construct_end();
-
-    ret = evp_pkey_ctx_set_params_strict(ctx, params);
-    if (ret == -2) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-        return -2;
-    }
-
-    return ret;
-}
-
-int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx)
-{
-    int ret, mode;
-    OSSL_PARAM params[2], *p = params;
-
-    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
-    if (ret != 1)
-        return ret;
-
-    /* TODO(3.0): Remove this eventually when no more legacy */
-    if (ctx->op.kex.exchprovctx == NULL)
-        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
-                                 EVP_PKEY_OP_DERIVE,
-                                 EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL);
-
-    *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
-                                    &mode);
-    *p++ = OSSL_PARAM_construct_end();
-
-    ret = evp_pkey_ctx_get_params_strict(ctx, params);
-    if (ret == -2) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-        return -2;
-    } else if (ret != 1) {
-        return -1;
-    }
-
-    if (mode < 0 || mode > 1) {
-        /*
-         * The provider should return either 0 or 1, any other value is a
-         * provider error.
-         */
-        return -1;
-    }
-
-    return mode;
-}
-
-int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
-{
-    int ret;
-    const char *kdf_type;
-    OSSL_PARAM params[2], *p = params;
-
-    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
-    if (ret != 1)
-        return ret;
-
-    switch (kdf) {
-        case EVP_PKEY_ECDH_KDF_NONE:
-            kdf_type = "";
-            break;
-        case EVP_PKEY_ECDH_KDF_X9_63:
-            kdf_type = OSSL_KDF_NAME_X963KDF;
-            break;
-        default:
-            return -2;
-    }
-
-    /* TODO(3.0): Remove this eventually when no more legacy */
-    if (ctx->op.kex.exchprovctx == NULL)
-        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
-                                 EVP_PKEY_OP_DERIVE,
-                                 EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL);
-
-    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE,
-                                            /*
-                                             * Cast away the const. This is read
-                                             * only so should be safe
-                                             */
-                                            (char *)kdf_type, 0);
-    *p++ = OSSL_PARAM_construct_end();
-
-    ret = evp_pkey_ctx_set_params_strict(ctx, params);
-    if (ret == -2) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-        return -2;
-    }
-
-    return ret;
-}
-
-int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx)
-{
-    int ret;
-    /* 80 should be big enough */
-    char kdf_type[80];
-    OSSL_PARAM params[2], *p = params;
-
-    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
-    if (ret != 1)
-        return ret;
-
-    /* TODO(3.0): Remove this eventually when no more legacy */
-    if (ctx->op.kex.exchprovctx == NULL)
-        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
-                                 EVP_PKEY_OP_DERIVE,
-                                 EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL);
-
-    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE,
-                                            kdf_type, sizeof(kdf_type));
-    *p++ = OSSL_PARAM_construct_end();
-
-    ret = evp_pkey_ctx_get_params_strict(ctx, params);
-    if (ret == -2) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-        return -2;
-    } else if (ret != 1) {
-        return -1;
-    }
-
-    if (kdf_type[0] == '\0')
-        return EVP_PKEY_ECDH_KDF_NONE;
-    else if (strcmp(kdf_type, OSSL_KDF_NAME_X963KDF) == 0)
-        return EVP_PKEY_ECDH_KDF_X9_63;
-
-    return -1;
-}
-
-int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
-{
-    int ret;
-    OSSL_PARAM params[2], *p = params;
-    const char *md_name = NULL;
-
-    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
-    if (ret != 1)
-        return ret;
-
-    /* TODO(3.0): Remove this eventually when no more legacy */
-    if (ctx->op.kex.exchprovctx == NULL)
-        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
-                                 EVP_PKEY_OP_DERIVE,
-                                 EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md));
-
-    md_name = (md == NULL) ? "" : EVP_MD_name(md);
-
-    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST,
-                                            /*
-                                             * Cast away the const. This is read
-                                             * only so should be safe
-                                             */
-                                            (char *)md_name, 0);
-    *p++ = OSSL_PARAM_construct_end();
-
-    ret = evp_pkey_ctx_set_params_strict(ctx, params);
-    if (ret == -2) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-        return -2;
-    }
-    return ret;
-}
-
-int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
-{
-    /* 80 should be big enough */
-    char name[80] = "";
-    int ret;
-    OSSL_PARAM params[2], *p = params;
-
-    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
-    if (ret != 1)
-        return ret;
-
-    /* TODO(3.0): Remove this eventually when no more legacy */
-    if (ctx->op.kex.exchprovctx == NULL)
-        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
-                                 EVP_PKEY_OP_DERIVE,
-                                 EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd));
-
-    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST,
-                                            name, sizeof(name));
-    *p++ = OSSL_PARAM_construct_end();
-
-    ret = evp_pkey_ctx_get_params_strict(ctx, params);
-    if (ret == -2) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-        return -2;
-    } else if (ret != 1) {
-        return -1;
-    }
-
-    /* May be NULL meaning "unknown" */
-    *pmd = EVP_get_digestbyname(name);
-
-    return 1;
-}
-
-int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int in)
-{
-    int ret;
-    size_t len = in;
-    OSSL_PARAM params[2], *p = params;
-
-    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
-    if (ret != 1)
-        return ret;
-
-    /* TODO(3.0): Remove this eventually when no more legacy */
-    if (ctx->op.kex.exchprovctx == NULL)
-        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
-                                 EVP_PKEY_OP_DERIVE,
-                                 EVP_PKEY_CTRL_EC_KDF_OUTLEN, in, NULL);
-
-    if (in <= 0) {
-        /*
-         * This would ideally be -1 or 0, but we have to retain compatibility
-         * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
-         * in <= 0
-         */
-        return -2;
-    }
-
-    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
-                                       &len);
-    *p++ = OSSL_PARAM_construct_end();
-
-    ret = evp_pkey_ctx_set_params_strict(ctx, params);
-    if (ret == -2) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-        return -2;
-    }
-    return ret;
-}
-
-int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
-{
-    size_t len = UINT_MAX;
-    int ret;
-    OSSL_PARAM params[2], *p = params;
-
-    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
-    if (ret != 1)
-        return ret;
-
-    /* TODO(3.0): Remove this eventually when no more legacy */
-    if (ctx->op.kex.exchprovctx == NULL)
-        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
-                                 EVP_PKEY_OP_DERIVE,
-                                 EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0,
-                                 (void *)(plen));
-
-    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
-                                       &len);
-    *p++ = OSSL_PARAM_construct_end();
-
-    ret = evp_pkey_ctx_get_params_strict(ctx, params);
-    if (ret == -2) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-        return -2;
-    } else if (ret != 1) {
-        return -1;
-    }
-
-    if (len > INT_MAX)
-        return -1;
-
-    *plen = (int)len;
-
-    return 1;
-}
-
-int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
-{
-    int ret;
-    OSSL_PARAM params[2], *p = params;
-
-    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
-    if (ret != 1)
-        return ret;
-
-    /* TODO(3.0): Remove this eventually when no more legacy */
-    if (ctx->op.kex.exchprovctx == NULL)
-        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
-                                 EVP_PKEY_OP_DERIVE,
-                                 EVP_PKEY_CTRL_EC_KDF_UKM, len, (void *)(ukm));
-
-    *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
-                                            /*
-                                             * Cast away the const. This is read
-                                             * only so should be safe
-                                             */
-                                            (void *)ukm,
-                                            (size_t)len);
-    *p++ = OSSL_PARAM_construct_end();
-
-    ret = evp_pkey_ctx_set_params_strict(ctx, params);
-    if (ret == -2) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-        return -2;
-    }
-    if (ret == 1)
-        OPENSSL_free(ukm);
-    return ret;
-}
-
-int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
-{
-    size_t ukmlen;
-    int ret;
-    OSSL_PARAM params[3], *p = params;
-
-    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
-    if (ret != 1)
-        return ret;
-
-    /* TODO(3.0): Remove this eventually when no more legacy */
-    if (ctx->op.kex.exchprovctx == NULL)
-        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
-                                 EVP_PKEY_OP_DERIVE,
-                                 EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0,
-                                 (void *)(pukm));
-
-    *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
-                                          (void **)pukm, 0);
-    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_UKM_LEN,
-                                       &ukmlen);
-    *p++ = OSSL_PARAM_construct_end();
-
-    ret = evp_pkey_ctx_get_params_strict(ctx, params);
-    if (ret == -2) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
-        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-        return -2;
-    } else if (ret != 1) {
-        return -1;
-    }
-
-    if (ukmlen > INT_MAX)
-        return -1;
-
-    return (int)ukmlen;
-}
index dffc2dd5d1563d3b4548faf064b08a5a8ab74ce3..6a86b26ded844ff48e226c61d146408c94d5db3b 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
@@ -820,6 +819,8 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
 # ifndef OPENSSL_NO_EC
     if (keytype == EVP_PKEY_EC) {
         switch (cmd) {
+        case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
+            return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, p1);
         case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
             if (p1 == -2) {
                 return EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx);
@@ -965,6 +966,24 @@ int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
 static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
                                     const char *value)
 {
+
+    /* Special cases that we intercept */
+# ifndef OPENSSL_NO_EC
+    /*
+     * We don't support encoding settings for providers, i.e. the only
+     * possible encoding is "named_curve", so we simply fail when something
+     * else is given, and otherwise just pretend all is fine.
+     */
+    if (strcmp(name, "ec_param_enc") == 0) {
+        if (strcmp(value, "named_curve") == 0) {
+            return 1;
+        } else {
+            ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+            return -2;
+        }
+    }
+# endif
+
     if (strcmp(name, "rsa_padding_mode") == 0)
         name = OSSL_ASYM_CIPHER_PARAM_PAD_MODE;
     else if (strcmp(name, "rsa_mgf1_md") == 0)
@@ -986,6 +1005,8 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
         name = OSSL_EXCHANGE_PARAM_PAD;
 # endif
 # ifndef OPENSSL_NO_EC
+    else if (strcmp(name, "ec_paramgen_curve") == 0)
+        name = OSSL_PKEY_PARAM_EC_NAME;
     else if (strcmp(name, "ecdh_cofactor_mode") == 0)
         name = OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE;
     else if (strcmp(name, "ecdh_kdf_md") == 0)
index ca1b1fa8b9967e08950c8b957d7f170a0ea49215..829bdb9e3d1eb0e316c2e720b2526c8283754250 100644 (file)
@@ -51,6 +51,8 @@ EVP_PKEY_CTX_set_dh_kdf_outlen,
 EVP_PKEY_CTX_get_dh_kdf_outlen,
 EVP_PKEY_CTX_set0_dh_kdf_ukm,
 EVP_PKEY_CTX_get0_dh_kdf_ukm,
+EVP_PKEY_CTX_set_ec_paramgen_curve_name,
+EVP_PKEY_CTX_get_ec_paramgen_curve_name,
 EVP_PKEY_CTX_set_ec_paramgen_curve_nid,
 EVP_PKEY_CTX_set_ec_param_enc,
 EVP_PKEY_CTX_set_ecdh_cofactor_mode,
@@ -143,6 +145,10 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len
 
  #include <openssl/ec.h>
 
+ int EVP_PKEY_CTX_set_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
+                                             const char *name);
+ int EVP_PKEY_CTX_get_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
+                                             char *name, size_t namelen);
  int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid);
  int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc);
  int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode);
@@ -513,12 +519,24 @@ by the library and should not be freed by the caller.
 
 =head2 EC parameters
 
-The EVP_PKEY_CTX_set_ec_paramgen_curve_nid() sets the EC curve for EC parameter
-generation to I<nid>. For EC parameter generation this macro must be called
-or an error occurs because there is no default curve.
-This function can also be called to set the curve explicitly when
+EVP_PKEY_CTX_set_ec_paramgen_curve_name() sets the EC curve to I<name> for EC
+parameter generation.
+
+EVP_PKEY_CTX_set_ec_paramgen_curve_nid() does the same as
+EVP_PKEY_CTX_set_ec_paramgen_curve_name(), but uses a I<nid> rather than a
+name string.
+
+For EC parameter generation, one of EVP_PKEY_CTX_set_ec_paramgen_curve_name()
+or EVP_PKEY_CTX_set_ec_paramgen_curve_nid() must be called or an error occurs
+because there is no default curve.
+These function can also be called to set the curve explicitly when
 generating an EC key.
 
+EVP_PKEY_CTX_get_ec_paramgen_curve_name() finds the curve name that's currently
+set with I<ctx>, and writes it to the location that I<name> points at, as long
+as its size I<namelen> is large enough to store that name, including a
+terminating NUL byte.
+
 The EVP_PKEY_CTX_set_ec_param_enc() macro sets the EC parameter encoding to
 I<param_enc> when generating EC parameters or an EC key. The encoding can be
 B<OPENSSL_EC_EXPLICIT_CURVE> for explicit parameters (the default in versions
index c5d5fc04fe10a24d87838fd6d6e90523f20c9335..de3698a06f0e0db33431a2f33705f0d572317003 100644 (file)
@@ -1450,10 +1450,11 @@ DEPRECATEDIN_3_0(void EC_KEY_METHOD_get_verify
 #   endif
 #  endif
 
-#  define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \
-        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
-                          EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \
-                          EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL)
+int EVP_PKEY_CTX_set_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
+                                            const char *name);
+int EVP_PKEY_CTX_get_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
+                                            char *name, size_t namelen);
+int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid);
 
 #  define EVP_PKEY_CTX_set_ec_param_enc(ctx, flag) \
         EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
index 983c74a6bf97e37d61d0211d9c54d48cdde8d23e..60202b90089157765e11600c847fd17eadfe22fb 100644 (file)
@@ -5047,3 +5047,6 @@ CTLOG_new_from_base64_with_libctx       ? 3_0_0   EXIST::FUNCTION:CT
 CTLOG_STORE_new_with_libctx             ?      3_0_0   EXIST::FUNCTION:CT
 EVP_PKEY_set_ex_data                    ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_get_ex_data                    ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_CTX_set_ec_paramgen_curve_name ?      3_0_0   EXIST::FUNCTION:EC
+EVP_PKEY_CTX_get_ec_paramgen_curve_name ?      3_0_0   EXIST::FUNCTION:EC
+EVP_PKEY_CTX_set_ec_paramgen_curve_nid  ?      3_0_0   EXIST::FUNCTION:EC