Deprecate EC_KEY + Update ec apps to use EVP_PKEY

Co-author: Richard Levitte <levitte@openssl.org>
Co-author: Tomas Mraz <tmraz@openssl.org>

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/13139)
master
Shane Lontis 2020-10-15 13:41:59 +10:00 committed by Tomas Mraz
parent 98dbf2c1c8
commit 5b5eea4b60
51 changed files with 1411 additions and 955 deletions

View File

@ -69,6 +69,49 @@ OpenSSL 3.0
*Dmitry Belyavskiy*
* All of the low level EC_KEY functions have been deprecated including:
EC_KEY_OpenSSL, EC_KEY_get_default_method, EC_KEY_set_default_method,
EC_KEY_get_method, EC_KEY_set_method, EC_KEY_new_method
EC_KEY_METHOD_new, EC_KEY_METHOD_free, EC_KEY_METHOD_set_init,
EC_KEY_METHOD_set_keygen, EC_KEY_METHOD_set_compute_key,
EC_KEY_METHOD_set_sign, EC_KEY_METHOD_set_verify,
EC_KEY_METHOD_get_init, EC_KEY_METHOD_get_keygen,
EC_KEY_METHOD_get_compute_key, EC_KEY_METHOD_get_sign,
EC_KEY_METHOD_get_verify,
EC_KEY_new_ex, EC_KEY_new, EC_KEY_get_flags, EC_KEY_set_flags,
EC_KEY_clear_flags, EC_KEY_decoded_from_explicit_params,
EC_KEY_new_by_curve_name_ex, EC_KEY_new_by_curve_name, EC_KEY_free,
EC_KEY_copy, EC_KEY_dup, EC_KEY_up_ref, EC_KEY_get0_engine,
EC_KEY_get0_group, EC_KEY_set_group, EC_KEY_get0_private_key,
EC_KEY_set_private_key, EC_KEY_get0_public_key, EC_KEY_set_public_key,
EC_KEY_get_enc_flags, EC_KEY_set_enc_flags, EC_KEY_get_conv_form,
EC_KEY_set_conv_form, EC_KEY_set_ex_data, EC_KEY_get_ex_data,
EC_KEY_set_asn1_flag, EC_KEY_generate_key, EC_KEY_check_key, EC_KEY_can_sign,
EC_KEY_set_public_key_affine_coordinates, EC_KEY_key2buf, EC_KEY_oct2key,
EC_KEY_oct2priv, EC_KEY_priv2oct and EC_KEY_priv2buf.
Applications that need to implement an EC_KEY_METHOD need to consider
implementation of the functionality in a special provider.
For replacement of the functions manipulating the EC_KEY objects
see the EVP_PKEY-EC(7) manual page.
Additionally functions that read and write EC_KEY objects such as
o2i_ECPublicKey, i2o_ECPublicKey, ECParameters_print_fp, EC_KEY_print_fp,
d2i_ECPKParameters, d2i_ECParameters, d2i_ECPrivateKey, d2i_ECPrivateKey_bio,
d2i_ECPrivateKey_fp, d2i_EC_PUBKEY, d2i_EC_PUBKEY_bio, d2i_EC_PUBKEY_fp,
i2d_ECPKParameters, i2d_ECParameters, i2d_ECPrivateKey, i2d_ECPrivateKey_bio,
i2d_ECPrivateKey_fp, i2d_EC_PUBKEY, i2d_EC_PUBKEY_bio and i2d_EC_PUBKEY_fp
have also been deprecated. Applications should instead use the
OSSL_DECODER and OSSL_ENCODER APIs to read and write EC files.
Finally functions that assign or obtain EC_KEY objects from an EVP_PKEY such as
EVP_PKEY_assign_EC_KEY, EVP_PKEY_get0_EC_KEY, EVP_PKEY_get1_EC_KEY and
EVP_PKEY_set1_EC_KEY are also deprecated. Applications should instead either
read or write an EVP_PKEY directly using the OSSL_DECODER and OSSL_ENCODER
APIs. Or load an EVP_PKEY directly from EC data using EVP_PKEY_fromdata().
*Shane Lontis, Paul Dale, Richard Levitte, and Tomas Mraz*
* Deprecated all the libcrypto and libssl error string loading
functions: ERR_load_ASN1_strings(), ERR_load_ASYNC_strings(),
ERR_load_BIO_strings(), ERR_load_BN_strings(), ERR_load_BUF_strings(),
@ -594,19 +637,6 @@ OpenSSL 3.0
*Paul Dale*
* Deprecated the EC_KEY_METHOD functions. These include:
EC_KEY_METHOD_new, EC_KEY_METHOD_free, EC_KEY_METHOD_set_init,
EC_KEY_METHOD_set_keygen, EC_KEY_METHOD_set_compute_key,
EC_KEY_METHOD_set_sign, EC_KEY_METHOD_set_verify,
EC_KEY_METHOD_get_init, EC_KEY_METHOD_get_keygen,
EC_KEY_METHOD_get_compute_key, EC_KEY_METHOD_get_sign and
EC_KEY_METHOD_get_verify.
Instead applications and extension writers should use the OSSL_PROVIDER APIs.
*Paul Dale*
* Deprecated EVP_PKEY_decrypt_old(), please use EVP_PKEY_decrypt_init()
and EVP_PKEY_decrypt() instead.
Deprecated EVP_PKEY_encrypt_old(), please use EVP_PKEY_encrypt_init()

209
apps/ec.c
View File

@ -8,29 +8,17 @@
*/
#include <openssl/opensslconf.h>
#include <openssl/evp.h>
#include <openssl/encoder.h>
#include <openssl/decoder.h>
#include <openssl/core_names.h>
#include <openssl/core_dispatch.h>
#include <openssl/params.h>
#include <openssl/err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "apps.h"
#include "progs.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
static OPT_PAIR conv_forms[] = {
{"compressed", POINT_CONVERSION_COMPRESSED},
{"uncompressed", POINT_CONVERSION_UNCOMPRESSED},
{"hybrid", POINT_CONVERSION_HYBRID},
{NULL}
};
static OPT_PAIR param_enc[] = {
{"named_curve", OPENSSL_EC_NAMED_CURVE},
{"explicit", 0},
{NULL}
};
#include "ec_common.h"
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
@ -74,19 +62,22 @@ const OPTIONS ec_options[] = {
int ec_main(int argc, char **argv)
{
OSSL_ENCODER_CTX *ectx = NULL;
OSSL_DECODER_CTX *dctx = NULL;
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *eckey = NULL;
BIO *in = NULL, *out = NULL;
ENGINE *e = NULL;
EC_KEY *eckey = NULL;
const EC_GROUP *group;
const EVP_CIPHER *enc = NULL;
point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
char *infile = NULL, *outfile = NULL, *prog;
char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL;
OPTION_CHOICE o;
int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_form = 0, new_asn1_flag = 0;
int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0;
int pubin = 0, pubout = 0, param_out = 0, i, ret = 1, private = 0;
int no_public = 0, check = 0;
int pubin = 0, pubout = 0, param_out = 0, ret = 1, private = 0;
int check = 0;
char *asn1_encoding = NULL;
char *point_format = NULL;
int no_public = 0;
prog = opt_init(argc, argv, ec_options);
while ((o = opt_next()) != OPT_EOF) {
@ -143,16 +134,14 @@ int ec_main(int argc, char **argv)
goto opthelp;
break;
case OPT_CONV_FORM:
if (!opt_pair(opt_arg(), conv_forms, &i))
point_format = opt_arg();
if (!opt_string(point_format, point_format_options))
goto opthelp;
new_form = 1;
form = i;
break;
case OPT_PARAM_ENC:
if (!opt_pair(opt_arg(), param_enc, &i))
asn1_encoding = opt_arg();
if (!opt_string(asn1_encoding, asn1_encoding_options))
goto opthelp;
new_asn1_flag = 1;
asn1_flag = i;
break;
case OPT_NO_PUBLIC:
no_public = 1;
@ -188,30 +177,14 @@ int ec_main(int argc, char **argv)
}
BIO_printf(bio_err, "read EC key\n");
if (informat == FORMAT_ASN1) {
if (pubin)
eckey = d2i_EC_PUBKEY_bio(in, NULL);
else
eckey = d2i_ECPrivateKey_bio(in, NULL);
} else if (informat == FORMAT_ENGINE) {
EVP_PKEY *pkey;
if (pubin)
pkey = load_pubkey(infile, informat, 1, passin, e, "public key");
else
pkey = load_key(infile, informat, 1, passin, e, "private key");
if (pkey != NULL) {
eckey = EVP_PKEY_get1_EC_KEY(pkey);
EVP_PKEY_free(pkey);
}
} else {
if (pubin)
eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
else
eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, passin);
}
if (pubin)
eckey = load_pubkey(infile, informat, 1, passin, e, "public key");
else
eckey = load_key(infile, informat, 1, passin, e, "private key");
if (eckey == NULL) {
BIO_printf(bio_err, "unable to load Key\n");
ERR_print_errors(bio_err);
goto end;
}
@ -219,74 +192,96 @@ int ec_main(int argc, char **argv)
if (out == NULL)
goto end;
group = EC_KEY_get0_group(eckey);
if (point_format
&& !EVP_PKEY_set_utf8_string_param(
eckey, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
point_format)) {
BIO_printf(bio_err, "unable to set point conversion format\n");
goto end;
}
if (new_form)
EC_KEY_set_conv_form(eckey, form);
if (asn1_encoding != NULL
&& !EVP_PKEY_set_utf8_string_param(
eckey, OSSL_PKEY_PARAM_EC_ENCODING, asn1_encoding)) {
BIO_printf(bio_err, "unable to set asn1 encoding format\n");
goto end;
}
if (new_asn1_flag)
EC_KEY_set_asn1_flag(eckey, asn1_flag);
if (no_public)
EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
if (no_public
&& !EVP_PKEY_set_int_param(eckey, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0)) {
BIO_printf(bio_err, "unable to disable public key encoding\n");
goto end;
}
if (text) {
assert(pubin || private);
if (!EC_KEY_print(out, eckey, 0)) {
perror(outfile);
ERR_print_errors(bio_err);
if ((pubin && EVP_PKEY_print_public(out, eckey, 0, NULL) <= 0)
|| (!pubin && EVP_PKEY_print_private(out, eckey, 0, NULL) <= 0)) {
BIO_printf(bio_err, "unable to print EC key\n");
goto end;
}
}
if (check) {
if (EC_KEY_check_key(eckey) == 1) {
BIO_printf(bio_err, "EC Key valid.\n");
} else {
pctx = EVP_PKEY_CTX_new_from_pkey(NULL, eckey, NULL);
if (pctx == NULL) {
BIO_printf(bio_err, "unable to check EC key\n");
goto end;
}
if (!EVP_PKEY_check(pctx))
BIO_printf(bio_err, "EC Key Invalid!\n");
ERR_print_errors(bio_err);
}
}
if (noout) {
ret = 0;
goto end;
}
BIO_printf(bio_err, "writing EC key\n");
if (outformat == FORMAT_ASN1) {
if (param_out) {
i = i2d_ECPKParameters_bio(out, group);
} else if (pubin || pubout) {
i = i2d_EC_PUBKEY_bio(out, eckey);
} else {
assert(private);
i = i2d_ECPrivateKey_bio(out, eckey);
}
} else {
if (param_out) {
i = PEM_write_bio_ECPKParameters(out, group);
} else if (pubin || pubout) {
i = PEM_write_bio_EC_PUBKEY(out, eckey);
} else {
assert(private);
i = PEM_write_bio_ECPrivateKey(out, eckey, enc,
NULL, 0, NULL, passout);
}
}
if (!i) {
BIO_printf(bio_err, "unable to write private key\n");
else
BIO_printf(bio_err, "EC Key valid.\n");
ERR_print_errors(bio_err);
} else {
ret = 0;
}
end:
if (!noout) {
int selection;
const char *output_type = outformat == FORMAT_ASN1 ? "DER" : "PEM";
const char *output_structure = "type-specific";
BIO_printf(bio_err, "writing EC key\n");
if (param_out) {
selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
} else if (pubin || pubout) {
selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
| OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
output_structure = "SubjectPublicKeyInfo";
} else {
selection = OSSL_KEYMGMT_SELECT_ALL;
assert(private);
}
ectx = OSSL_ENCODER_CTX_new_by_EVP_PKEY(eckey, selection,
output_type, output_structure,
NULL);
if (enc != NULL) {
OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_name(enc), NULL);
if (passout != NULL)
OSSL_ENCODER_CTX_set_passphrase(ectx,
(const unsigned char *)passout,
strlen(passout));
}
if (!OSSL_ENCODER_to_bio(ectx, out)) {
BIO_printf(bio_err, "unable to write EC key\n");
goto end;
}
}
ret = 0;
end:
if (ret != 0)
ERR_print_errors(bio_err);
BIO_free(in);
BIO_free_all(out);
EC_KEY_free(eckey);
EVP_PKEY_free(eckey);
OSSL_ENCODER_CTX_free(ectx);
OSSL_DECODER_CTX_free(dctx);
EVP_PKEY_CTX_free(pctx);
release_engine(e);
OPENSSL_free(passin);
OPENSSL_free(passout);
if (passin != NULL)
OPENSSL_clear_free(passin, strlen(passin));
if (passout != NULL)
OPENSSL_clear_free(passout, strlen(passout));
return ret;
}

View File

@ -9,19 +9,16 @@
*/
#include <openssl/opensslconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/encoder.h>
#include <openssl/decoder.h>
#include <openssl/core_names.h>
#include <openssl/core_dispatch.h>
#include <openssl/params.h>
#include <openssl/err.h>
#include "apps.h"
#include "progs.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include "ec_common.h"
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
@ -67,36 +64,51 @@ const OPTIONS ecparam_options[] = {
{NULL}
};
static OPT_PAIR forms[] = {
{"compressed", POINT_CONVERSION_COMPRESSED},
{"uncompressed", POINT_CONVERSION_UNCOMPRESSED},
{"hybrid", POINT_CONVERSION_HYBRID},
{NULL}
};
static int list_builtin_curves(BIO *out)
{
int ret = 0;
EC_builtin_curve *curves = NULL;
size_t n, crv_len = EC_get_builtin_curves(NULL, 0);
static OPT_PAIR encodings[] = {
{"named_curve", OPENSSL_EC_NAMED_CURVE},
{"explicit", 0},
{NULL}
};
curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves");
if (!EC_get_builtin_curves(curves, crv_len))
goto end;
for (n = 0; n < crv_len; n++) {
const char *comment = curves[n].comment;
const char *sname = OBJ_nid2sn(curves[n].nid);
if (comment == NULL)
comment = "CURVE DESCRIPTION NOT AVAILABLE";
if (sname == NULL)
sname = "";
BIO_printf(out, " %-10s: ", sname);
BIO_printf(out, "%s\n", comment);
}
ret = 1;
end:
OPENSSL_free(curves);
return ret;
}
int ecparam_main(int argc, char **argv)
{
EVP_PKEY_CTX *gctx_params = NULL, *gctx_key = NULL, *pctx = NULL;
EVP_PKEY *params_key = NULL, *key = NULL;
OSSL_ENCODER_CTX *ectx_key = NULL, *ectx_params = NULL;
OSSL_DECODER_CTX *dctx_params = NULL;
ENGINE *e = NULL;
BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL;
BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL;
BIO *in = NULL, *out = NULL;
EC_GROUP *group = NULL;
point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
char *curve_name = NULL;
char *asn1_encoding = NULL;
char *point_format = NULL;
char *infile = NULL, *outfile = NULL, *prog;
unsigned char *buffer = NULL;
OPTION_CHOICE o;
int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0;
int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0;
int ret = 1, private = 0;
int list_curves = 0, no_seed = 0, check = 0, new_form = 0;
int text = 0, i, genkey = 0, check_named = 0;
int no_seed = 0, check = 0, check_named = 0, text = 0, genkey = 0;
int list_curves = 0;
prog = opt_init(argc, argv, ecparam_options);
while ((o = opt_next()) != OPT_EOF) {
@ -146,15 +158,14 @@ int ecparam_main(int argc, char **argv)
curve_name = opt_arg();
break;
case OPT_CONV_FORM:
if (!opt_pair(opt_arg(), forms, &new_form))
point_format = opt_arg();
if (!opt_string(point_format, point_format_options))
goto opthelp;
form = new_form;
new_form = 1;
break;
case OPT_PARAM_ENC:
if (!opt_pair(opt_arg(), encodings, &asn1_flag))
asn1_encoding = opt_arg();
if (!opt_string(asn1_encoding, asn1_encoding_options))
goto opthelp;
new_asn1_flag = 1;
break;
case OPT_GENKEY:
genkey = 1;
@ -188,111 +199,88 @@ int ecparam_main(int argc, char **argv)
goto end;
if (list_curves) {
EC_builtin_curve *curves = NULL;
size_t crv_len = EC_get_builtin_curves(NULL, 0);
size_t n;
curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves");
if (!EC_get_builtin_curves(curves, crv_len)) {
OPENSSL_free(curves);
goto end;
}
for (n = 0; n < crv_len; n++) {
const char *comment;
const char *sname;
comment = curves[n].comment;
sname = OBJ_nid2sn(curves[n].nid);
if (comment == NULL)
comment = "CURVE DESCRIPTION NOT AVAILABLE";
if (sname == NULL)
sname = "";
BIO_printf(out, " %-10s: ", sname);
BIO_printf(out, "%s\n", comment);
}
OPENSSL_free(curves);
ret = 0;
if (list_builtin_curves(out))
ret = 0;
goto end;
}
if (curve_name != NULL) {
int nid;
OSSL_PARAM params[4];
OSSL_PARAM *p = params;
/*
* workaround for the SECG curve names secp192r1 and secp256r1 (which
* are the same as the curves prime192v1 and prime256v1 defined in
* X9.62)
*/
if (strcmp(curve_name, "secp192r1") == 0) {
BIO_printf(bio_err, "using curve name prime192v1 "
"instead of secp192r1\n");
nid = NID_X9_62_prime192v1;
BIO_printf(bio_err,
"using curve name prime192v1 instead of secp192r1\n");
curve_name = SN_X9_62_prime192v1;
} else if (strcmp(curve_name, "secp256r1") == 0) {
BIO_printf(bio_err, "using curve name prime256v1 "
"instead of secp256r1\n");
nid = NID_X9_62_prime256v1;
} else {
nid = OBJ_sn2nid(curve_name);
BIO_printf(bio_err,
"using curve name prime256v1 instead of secp256r1\n");
curve_name = SN_X9_62_prime256v1;
}
if (nid == 0)
nid = EC_curve_nist2nid(curve_name);
if (nid == 0) {
BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
curve_name, 0);
if (asn1_encoding != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING,
asn1_encoding, 0);
if (point_format != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(
OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
point_format, 0);
*p = OSSL_PARAM_construct_end();
gctx_params = EVP_PKEY_CTX_new_from_name(NULL, "ec", NULL);
if (gctx_params == NULL
|| EVP_PKEY_keygen_init(gctx_params) <= 0
|| EVP_PKEY_CTX_set_params(gctx_params, params) <= 0
|| EVP_PKEY_keygen(gctx_params, &params_key) <= 0) {
BIO_printf(bio_err, "unable to generate key\n");
goto end;
}
group = EC_GROUP_new_by_curve_name(nid);
if (group == NULL) {
BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name);
goto end;
}
EC_GROUP_set_asn1_flag(group, asn1_flag);
EC_GROUP_set_point_conversion_form(group, form);
} else if (informat == FORMAT_ASN1) {
group = d2i_ECPKParameters_bio(in, NULL);
} else {
group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
params_key = load_keyparams(infile, 1, "EC", "EC parameters");
if (!EVP_PKEY_is_a(params_key, "EC"))
goto end;
if (point_format
&& !EVP_PKEY_set_utf8_string_param(
params_key, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
point_format)) {
BIO_printf(bio_err, "unable to set point conversion format\n");
goto end;
}
if (asn1_encoding != NULL
&& !EVP_PKEY_set_utf8_string_param(
params_key, OSSL_PKEY_PARAM_EC_ENCODING, asn1_encoding)) {
BIO_printf(bio_err, "unable to set asn1 encoding format\n");
goto end;
}
}
if (group == NULL) {
BIO_printf(bio_err, "unable to load elliptic curve parameters\n");
ERR_print_errors(bio_err);
if (no_seed
&& !EVP_PKEY_set_octet_string_param(params_key, OSSL_PKEY_PARAM_EC_SEED,
NULL, 0)) {
BIO_printf(bio_err, "unable to clear seed\n");
goto end;
}
if (new_form)
EC_GROUP_set_point_conversion_form(group, form);
if (new_asn1_flag)
EC_GROUP_set_asn1_flag(group, asn1_flag);
if (no_seed) {
EC_GROUP_set_seed(group, NULL, 0);
if (text
&& !EVP_PKEY_print_params(out, params_key, 0, NULL)) {
BIO_printf(bio_err, "unable to print params\n");
goto end;
}
if (text) {
if (!ECPKParameters_print(out, group, 0))
goto end;
}
if (check_named) {
BIO_printf(bio_err, "validating named elliptic curve parameters: ");
if (EC_GROUP_check_named_curve(group, 0, NULL) <= 0) {
BIO_printf(bio_err, "failed\n");
ERR_print_errors(bio_err);
goto end;
}
BIO_printf(bio_err, "ok\n");
}
if (check) {
if (check || check_named) {
BIO_printf(bio_err, "checking elliptic curve parameters: ");
if (!EC_GROUP_check(group, NULL)) {
if (check_named
&& !EVP_PKEY_set_utf8_string_param(params_key,
OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE,
OSSL_PKEY_EC_GROUP_CHECK_NAMED)) {
BIO_printf(bio_err, "unable to set check_type\n");
goto end;
}
pctx = EVP_PKEY_CTX_new_from_pkey(NULL, params_key, NULL);
if (pctx == NULL || !EVP_PKEY_param_check(pctx)) {
BIO_printf(bio_err, "failed\n");
ERR_print_errors(bio_err);
goto end;
}
BIO_printf(bio_err, "ok\n");
@ -302,60 +290,54 @@ int ecparam_main(int argc, char **argv)
noout = 1;
if (!noout) {
if (outformat == FORMAT_ASN1)
i = i2d_ECPKParameters_bio(out, group);
else
i = PEM_write_bio_ECPKParameters(out, group);
if (!i) {
BIO_printf(bio_err, "unable to write elliptic "
"curve parameters\n");
ERR_print_errors(bio_err);
ectx_params = OSSL_ENCODER_CTX_new_by_EVP_PKEY(
params_key, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
outformat == FORMAT_ASN1 ? "DER" : "PEM", NULL, NULL);
if (!OSSL_ENCODER_to_bio(ectx_params, out)) {
BIO_printf(bio_err, "unable to write elliptic curve parameters\n");
goto end;
}
}
if (genkey) {
EC_KEY *eckey = EC_KEY_new();
if (eckey == NULL)
goto end;
if (EC_KEY_set_group(eckey, group) == 0) {
BIO_printf(bio_err, "unable to set group when generating key\n");
EC_KEY_free(eckey);
ERR_print_errors(bio_err);
goto end;
}
if (new_form)
EC_KEY_set_conv_form(eckey, form);
if (!EC_KEY_generate_key(eckey)) {
/*
* NOTE: EC keygen does not normally need to pass in the param_key
* for named curves. This can be achieved using:
* gctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
* EVP_PKEY_keygen_init(gctx);
* EVP_PKEY_CTX_set_group_name(gctx, curvename);
* EVP_PKEY_keygen(gctx, &key) <= 0)
*/
gctx_key = EVP_PKEY_CTX_new_from_pkey(NULL, params_key, NULL);
if (EVP_PKEY_keygen_init(gctx_key) <= 0
|| EVP_PKEY_keygen(gctx_key, &key) <= 0) {
BIO_printf(bio_err, "unable to generate key\n");
EC_KEY_free(eckey);
ERR_print_errors(bio_err);
goto end;
}
assert(private);
if (outformat == FORMAT_ASN1)
i = i2d_ECPrivateKey_bio(out, eckey);
else
i = PEM_write_bio_ECPrivateKey(out, eckey, NULL,
NULL, 0, NULL, NULL);
EC_KEY_free(eckey);
ectx_key = OSSL_ENCODER_CTX_new_by_EVP_PKEY(
key, OSSL_KEYMGMT_SELECT_ALL,
outformat == FORMAT_ASN1 ? "DER" : "PEM", NULL, NULL);
if (!OSSL_ENCODER_to_bio(ectx_key, out)) {
BIO_printf(bio_err, "unable to write elliptic "
"curve parameters\n");
goto end;
}
}
ret = 0;
end:
BN_free(ec_p);
BN_free(ec_a);
BN_free(ec_b);
BN_free(ec_gen);
BN_free(ec_order);
BN_free(ec_cofactor);
OPENSSL_free(buffer);
EC_GROUP_free(group);
end:
if (ret != 0)
ERR_print_errors(bio_err);
release_engine(e);
EVP_PKEY_free(params_key);
EVP_PKEY_free(key);
EVP_PKEY_CTX_free(pctx);
EVP_PKEY_CTX_free(gctx_params);
EVP_PKEY_CTX_free(gctx_key);
OSSL_DECODER_CTX_free(dctx_params);
OSSL_ENCODER_CTX_free(ectx_params);
OSSL_ENCODER_CTX_free(ectx_key);
BIO_free(in);
BIO_free_all(out);
return ret;

23
apps/include/ec_common.h Normal file
View File

@ -0,0 +1,23 @@
/*
* 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
*/
#ifndef OPENSSL_NO_EC
static const char *point_format_options[] = {
"uncompressed",
"compressed",
"hybrid",
NULL
};
static const char *asn1_encoding_options[] = {
"named_curve",
"explicit",
NULL
};
#endif

View File

@ -363,6 +363,7 @@ int opt_umax(const char *arg, uintmax_t *result);
# define uintmax_t unsigned long
#endif
int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result);
int opt_string(const char *name, const char **options);
int opt_cipher(const char *name, const EVP_CIPHER **cipherp);
int opt_md(const char *name, const EVP_MD **mdp);
char *opt_arg(void);

View File

@ -391,6 +391,20 @@ int opt_pair(const char *name, const OPT_PAIR* pairs, int *result)
return 0;
}
/* Look through a list of valid names */
int opt_string(const char *name, const char **options)
{
const char **p;
for (p = options; *p != NULL; p++)
if (strcmp(*p, name) == 0)
return 1;
opt_printf_stderr("%s: Value must be one of:\n", prog);
for (p = options; *p != NULL; p++)
opt_printf_stderr("\t%s\n", *p);
return 0;
}
/* Parse an int, put it into *result; return 0 on failure, else 1. */
int opt_int(const char *value, int *result)
{

View File

@ -397,15 +397,13 @@ int ssl_print_tmp_key(BIO *out, SSL *s)
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
{
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
int nid;
const char *cname;
nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
EC_KEY_free(ec);
cname = EC_curve_nid2nist(nid);
if (cname == NULL)
cname = OBJ_nid2sn(nid);
BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(key));
char name[80];
size_t name_len;
if (!EVP_PKEY_get_utf8_string_param(key, OSSL_PKEY_PARAM_GROUP_NAME,
name, sizeof(name), &name_len))
strcpy(name, "?");
BIO_printf(out, "ECDH, %s, %d bits\n", name, EVP_PKEY_bits(key));
}
break;
#endif

View File

@ -11,26 +11,11 @@
#include <string.h>
#include "apps.h"
#include "progs.h"
#include "ec_common.h"
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#ifndef OPENSSL_NO_EC
# include <openssl/ec.h>
static OPT_PAIR ec_conv_forms[] = {
{"compressed", POINT_CONVERSION_COMPRESSED},
{"uncompressed", POINT_CONVERSION_UNCOMPRESSED},
{"hybrid", POINT_CONVERSION_HYBRID},
{NULL}
};
static OPT_PAIR ec_param_enc[] = {
{"named_curve", OPENSSL_EC_NAMED_CURVE},
{"explicit", 0},
{NULL}
};
#endif
#include <openssl/core_names.h>
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
@ -94,10 +79,8 @@ int pkey_main(int argc, char **argv)
int pubin = 0, pubout = 0, text_pub = 0, text = 0, noout = 0, ret = 1;
int private = 0, traditional = 0, check = 0, pub_check = 0;
#ifndef OPENSSL_NO_EC
EC_KEY *eckey;
int ec_asn1_flag = OPENSSL_EC_NAMED_CURVE, new_ec_asn1_flag = 0;
int i, new_ec_form = 0;
point_conversion_form_t ec_form = POINT_CONVERSION_UNCOMPRESSED;
char *asn1_encoding = NULL;
char *point_format = NULL;
#endif
prog = opt_init(argc, argv, pkey_options);
@ -167,20 +150,18 @@ int pkey_main(int argc, char **argv)
#ifdef OPENSSL_NO_EC
goto opthelp;
#else
if (!opt_pair(opt_arg(), ec_conv_forms, &i))
point_format = opt_arg();
if (!opt_string(point_format, point_format_options))
goto opthelp;
new_ec_form = 1;
ec_form = i;
break;
#endif
case OPT_EC_PARAM_ENC:
#ifdef OPENSSL_NO_EC
goto opthelp;
#else
if (!opt_pair(opt_arg(), ec_param_enc, &i))
asn1_encoding = opt_arg();
if (!opt_string(asn1_encoding, asn1_encoding_options))
goto opthelp;
new_ec_asn1_flag = 1;
ec_asn1_flag = i;
break;
#endif
case OPT_PROV_CASES:
@ -234,20 +215,22 @@ int pkey_main(int argc, char **argv)
goto end;
#ifndef OPENSSL_NO_EC
/*
* TODO: remove this and use a set params call with a 'pkeyopt' command
* line option instead.
*/
if (new_ec_form || new_ec_asn1_flag) {
if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if (new_ec_form)
EC_KEY_set_conv_form(eckey, ec_form);
if (asn1_encoding != NULL || point_format != NULL) {
OSSL_PARAM params[3], *p = params;
if (new_ec_asn1_flag)
EC_KEY_set_asn1_flag(eckey, ec_asn1_flag);
if (!EVP_PKEY_is_a(pkey, "EC"))
goto end;
if (asn1_encoding != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING,
asn1_encoding, 0);
if (point_format != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(
OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
point_format, 0);
*p = OSSL_PARAM_construct_end();
if (EVP_PKEY_set_params(pkey, params) <= 0)
goto end;
}
#endif

View File

@ -583,7 +583,9 @@ typedef struct loopargs_st {
DSA *dsa_key[DSA_NUM];
#endif
#ifndef OPENSSL_NO_EC
# ifndef OPENSSL_NO_DEPRECATED_3_0
EC_KEY *ecdsa[ECDSA_NUM];
# endif
EVP_PKEY_CTX *ecdh_ctx[EC_NUM];
EVP_MD_CTX *eddsa_ctx[EdDSA_NUM];
EVP_MD_CTX *eddsa_ctx2[EdDSA_NUM];
@ -4082,8 +4084,10 @@ int speed_main(int argc, char **argv)
DSA_free(loopargs[i].dsa_key[k]);
#endif
#ifndef OPENSSL_NO_EC
# if !defined(OPENSSL_NO_DEPRECATED_3_0)
for (k = 0; k < ECDSA_NUM; k++)
EC_KEY_free(loopargs[i].ecdsa[k]);
# endif
for (k = 0; k < EC_NUM; k++)
EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]);
for (k = 0; k < EdDSA_NUM; k++) {

View File

@ -63,8 +63,10 @@ static ASN1_ITEM_EXP *asn1_item_list[] = {
ASN1_ITEM_ref(DIST_POINT_NAME),
ASN1_ITEM_ref(DIST_POINT),
#ifndef OPENSSL_NO_EC
# ifndef OPENSSL_NO_DEPRECATED_3_0
ASN1_ITEM_ref(ECPARAMETERS),
ASN1_ITEM_ref(ECPKPARAMETERS),
# endif
#endif
ASN1_ITEM_ref(EDIPARTYNAME),
ASN1_ITEM_ref(EXTENDED_KEY_USAGE),

View File

@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* Low level APIs related to EC_KEY are deprecated for public use,
* but still ok for internal use.
*/
#include "internal/deprecated.h"
#include <openssl/core_names.h>
#include <openssl/objects.h>
#include <openssl/params.h>
@ -23,6 +29,18 @@ static const OSSL_ITEM encoding_nameid_map[] = {
{ OPENSSL_EC_NAMED_CURVE, OSSL_PKEY_EC_ENCODING_GROUP },
};
static const OSSL_ITEM check_group_type_nameid_map[] = {
{ 0, OSSL_PKEY_EC_GROUP_CHECK_DEFAULT },
{ EC_FLAG_CHECK_NAMED_GROUP, OSSL_PKEY_EC_GROUP_CHECK_NAMED },
{ EC_FLAG_CHECK_NAMED_GROUP_NIST, OSSL_PKEY_EC_GROUP_CHECK_NAMED_NIST },
};
static const OSSL_ITEM format_nameid_map[] = {
{ (int)POINT_CONVERSION_UNCOMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED },
{ (int)POINT_CONVERSION_COMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED },
{ (int)POINT_CONVERSION_HYBRID, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID },
};
int ec_encoding_name2id(const char *name)
{
size_t i, sz;
@ -49,13 +67,95 @@ static char *ec_param_encoding_id2name(int id)
return NULL;
}
char *ec_check_group_type_id2name(int id)
{
size_t i, sz;
for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) {
if (id == (int)check_group_type_nameid_map[i].id)
return check_group_type_nameid_map[i].ptr;
}
return NULL;
}
static int ec_check_group_type_name2id(const char *name)
{
size_t i, sz;
/* Return the default value if there is no name */
if (name == NULL)
return 0;
for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) {
if (strcasecmp(name, check_group_type_nameid_map[i].ptr) == 0)
return check_group_type_nameid_map[i].id;
}
return -1;
}
int ec_set_check_group_type_from_name(EC_KEY *ec, const char *name)
{
int flags = ec_check_group_type_name2id(name);
if (flags == -1)
return 0;
EC_KEY_clear_flags(ec, EC_FLAG_CHECK_NAMED_GROUP_MASK);
EC_KEY_set_flags(ec, flags);
return 1;
}
static int ec_set_check_group_type_from_param(EC_KEY *ec, const OSSL_PARAM *p)
{
const char *name = NULL;
int status = 0;
switch (p->data_type) {
case OSSL_PARAM_UTF8_STRING:
name = p->data;
status = (name != NULL);
break;
case OSSL_PARAM_UTF8_PTR:
status = OSSL_PARAM_get_utf8_ptr(p, &name);
break;
}
if (status)
return ec_set_check_group_type_from_name(ec, name);
return 0;
}
int ec_pt_format_name2id(const char *name)
{
size_t i, sz;
/* Return the default value if there is no name */
if (name == NULL)
return (int)POINT_CONVERSION_UNCOMPRESSED;
for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) {
if (strcasecmp(name, format_nameid_map[i].ptr) == 0)
return format_nameid_map[i].id;
}
return -1;
}
char *ec_pt_format_id2name(int id)
{
size_t i, sz;
for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) {
if (id == (int)format_nameid_map[i].id)
return format_nameid_map[i].ptr;
}
return NULL;
}
int ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl,
OSSL_PARAM params[], OSSL_LIB_CTX *libctx,
const char *propq,
BN_CTX *bnctx, unsigned char **genbuf)
{
int ret = 0, curve_nid, encoding_flag;
const char *field_type, *encoding_name;
const char *field_type, *encoding_name, *pt_form_name;
const BIGNUM *cofactor, *order;
BIGNUM *p = NULL, *a = NULL, *b = NULL;
point_conversion_form_t genform;
@ -68,6 +168,15 @@ int ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl,
return 0;
}
genform = EC_GROUP_get_point_conversion_form(group);
pt_form_name = ec_pt_format_id2name(genform);
if (pt_form_name == NULL
|| !ossl_param_build_set_utf8_string(
tmpl, params,
OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, pt_form_name)) {
ECerr(0, EC_R_INVALID_FORM);
return 0;
}
encoding_flag = EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE;
encoding_name = ec_param_encoding_id2name(encoding_flag);
if (encoding_name == NULL
@ -115,7 +224,6 @@ int ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl,
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
goto err;
}
genform = EC_GROUP_get_point_conversion_form(group);
genbuf_len = EC_POINT_point2buf(group, genpt, genform, genbuf, bnctx);
if (genbuf_len == 0) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
@ -336,17 +444,50 @@ int ec_group_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
if (!EC_KEY_set_group(ec, group))
goto err;
/*
* TODO(3.0): if the group has changed, should we invalidate the private and
* public key?
*/
ok = 1;
err:
EC_GROUP_free(group);
return ok;
}
static int ec_key_point_format_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
int format = -1;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT);
if (p != NULL) {
if (!ec_pt_format_param2id(p, &format)) {
ECerr(0, EC_R_INVALID_FORM);
return 0;
}
EC_KEY_set_conv_form(ec, format);
}
return 1;
}
static int ec_key_group_check_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE);
if (p != NULL)
return ec_set_check_group_type_from_param(ec, p);
return 1;
}
static int ec_set_include_public(EC_KEY *ec, int include)
{
int flags = EC_KEY_get_enc_flags(ec);
if (!include)
flags |= EC_PKEY_NO_PUBKEY;
else
flags &= ~EC_PKEY_NO_PUBKEY;
EC_KEY_set_enc_flags(ec, flags);
return 1;
}
int ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
@ -363,5 +504,69 @@ int ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
return 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC);
if (p != NULL) {
int include = 1;
if (!OSSL_PARAM_get_int(p, &include)
|| !ec_set_include_public(ec, include))
return 0;
}
if (!ec_key_point_format_fromdata(ec, params))
return 0;
if (!ec_key_group_check_fromdata(ec, params))
return 0;
return 1;
}
int ec_encoding_param2id(const OSSL_PARAM *p, int *id)
{
const char *name = NULL;
int status = 0;
switch (p->data_type) {
case OSSL_PARAM_UTF8_STRING:
/* The OSSL_PARAM functions have no support for this */
name = p->data;
status = (name != NULL);
break;
case OSSL_PARAM_UTF8_PTR:
status = OSSL_PARAM_get_utf8_ptr(p, &name);
break;
}
if (status) {
int i = ec_encoding_name2id(name);
if (i >= 0) {
*id = i;
return 1;
}
}
return 0;
}
int ec_pt_format_param2id(const OSSL_PARAM *p, int *id)
{
const char *name = NULL;
int status = 0;
switch (p->data_type) {
case OSSL_PARAM_UTF8_STRING:
/* The OSSL_PARAM functions have no support for this */
name = p->data;
status = (name != NULL);
break;
case OSSL_PARAM_UTF8_PTR:
status = OSSL_PARAM_get_utf8_ptr(p, &name);
break;
}
if (status) {
int i = ec_pt_format_name2id(name);
if (i >= 0) {
*id = i;
return 1;
}
}
return 0;
}

View File

@ -9,7 +9,7 @@
*/
/*
* ECDSA low level APIs are deprecated for public use, but still ok for
* EC_KEY low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"

View File

@ -9,7 +9,7 @@
*/
/*
* ECDSA low level APIs are deprecated for public use, but still ok for
* EC_GROUP low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
@ -1461,32 +1461,6 @@ err:
return NULL;
}
static int ec_encoding_param2id(const OSSL_PARAM *p, int *id)
{
const char *name = NULL;
int status = 0;
switch (p->data_type) {
case OSSL_PARAM_UTF8_STRING:
/* The OSSL_PARAM functions have no support for this */
name = p->data;
status = (name != NULL);
break;
case OSSL_PARAM_UTF8_PTR:
status = OSSL_PARAM_get_utf8_ptr(p, &name);
break;
}
if (status) {
int i = ec_encoding_name2id(name);
if (i >= 0) {
*id = i;
return 1;
}
}
return 0;
}
static EC_GROUP *group_new_from_name(const OSSL_PARAM *p,
OSSL_LIB_CTX *libctx, const char *propq)
{
@ -1516,6 +1490,42 @@ static EC_GROUP *group_new_from_name(const OSSL_PARAM *p,
return NULL;
}
/* These parameters can be set directly into an EC_GROUP */
int ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[])
{
int encoding_flag = -1, format = -1;
const OSSL_PARAM *p;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT);
if (p != NULL) {
if (!ec_pt_format_param2id(p, &format)) {
ECerr(0, EC_R_INVALID_FORM);
return 0;
}
EC_GROUP_set_point_conversion_form(group, format);
}
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING);
if (p != NULL) {
if (!ec_encoding_param2id(p, &encoding_flag)) {
ECerr(0, EC_R_INVALID_FORM);
return 0;
}
EC_GROUP_set_asn1_flag(group, encoding_flag);
}
/* Optional seed */
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
if (p != NULL) {
/* The seed is allowed to be NULL */
if (p->data_type != OSSL_PARAM_OCTET_STRING
|| !EC_GROUP_set_seed(group, p->data, p->data_size)) {
ECerr(0, EC_R_INVALID_SEED);
return 0;
}
}
return 1;
}
EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
OSSL_LIB_CTX *libctx, const char *propq)
{
@ -1530,19 +1540,19 @@ EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
const unsigned char *buf = NULL;
int encoding_flag = -1;
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING);
if (ptmp != NULL && !ec_encoding_param2id(ptmp, &encoding_flag)) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
/* This is the simple named group case */
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
if (ptmp != NULL) {
group = group_new_from_name(ptmp, libctx, propq);
if (group != NULL)
EC_GROUP_set_asn1_flag(group, encoding_flag);
if (group != NULL) {
if (!ec_group_set_params(group, params)) {
EC_GROUP_free(group);
group = NULL;
}
}
return group;
}
/* If it gets here then we are trying explicit parameters */
bnctx = BN_CTX_new_ex(libctx);
if (bnctx == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
@ -1690,6 +1700,12 @@ EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
* If we did not find a named group then the encoding should be explicit
* if it was specified
*/
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING);
if (ptmp != NULL
&& !ec_encoding_param2id(ptmp, &encoding_flag)) {
ECerr(0, EC_R_INVALID_ENCODING);
return 0;
}
if (encoding_flag == OPENSSL_EC_NAMED_CURVE) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
goto err;

View File

@ -8,13 +8,16 @@
* https://www.openssl.org/source/license.html
*/