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 [moved from crypto/ec/ec_evp_lib.c with 85% similarity]
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
similarity index 85%
rename from crypto/ec/ec_evp_lib.c
rename to crypto/ec/ec_ctrl.c
index e4d7815993f1bd4a747bd4653662da4e34b7173e..314ebe61813e3a40fdcc29c489f550fe56e76b35 100644 (file)
@@ -420,3 +420,69 @@ int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
 
     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
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