Skip to content

Commit

Permalink
Deprecate EC_KEY + Update ec apps to use EVP_PKEY
Browse files Browse the repository at this point in the history
Co-author: Richard Levitte <[email protected]>
Co-author: Tomas Mraz <[email protected]>

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Tomas Mraz <[email protected]>
(Merged from openssl#13139)
  • Loading branch information
slontis authored and t8m committed Jan 26, 2021
1 parent 98dbf2c commit 5b5eea4
Show file tree
Hide file tree
Showing 51 changed files with 1,406 additions and 950 deletions.
56 changes: 43 additions & 13 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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()
Expand Down
189 changes: 92 additions & 97 deletions apps/ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -188,105 +177,111 @@ 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;
}

out = bio_open_owner(outfile, outformat, private);
if (out == NULL)
goto end;

group = EC_KEY_get0_group(eckey);

if (new_form)
EC_KEY_set_conv_form(eckey, form);
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_asn1_flag)
EC_KEY_set_asn1_flag(eckey, asn1_flag);
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 (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 {
BIO_printf(bio_err, "EC Key Invalid!\n");
ERR_print_errors(bio_err);
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");
else
BIO_printf(bio_err, "EC Key valid.\n");
ERR_print_errors(bio_err);
}

if (noout) {
ret = 0;
goto 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 (outformat == FORMAT_ASN1) {
BIO_printf(bio_err, "writing EC key\n");
if (param_out) {
i = i2d_ECPKParameters_bio(out, group);
selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
} else if (pubin || pubout) {
i = i2d_EC_PUBKEY_bio(out, eckey);
selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
| OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
output_structure = "SubjectPublicKeyInfo";
} else {
selection = OSSL_KEYMGMT_SELECT_ALL;
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);

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;
}
}

if (!i) {
BIO_printf(bio_err, "unable to write private key\n");
ret = 0;
end:
if (ret != 0)
ERR_print_errors(bio_err);
} else {
ret = 0;
}
end:
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;
}
Loading

0 comments on commit 5b5eea4

Please sign in to comment.