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
parent
98dbf2c1c8
commit
5b5eea4b60
56
CHANGES.md
56
CHANGES.md
|
@ -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
209
apps/ec.c
|
@ -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;
|
||||
}
|
||||
|
|
306
apps/ecparam.c
306
apps/ecparam.c
|
@ -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, ¶ms_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;
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
63
apps/pkey.c
63
apps/pkey.c
|
@ -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
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -8,13 +8,16 @@
|
|||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||