Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:25
erlang
0381-crypto-Fix-generate_key-3-for-ecdh-to-only...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0381-crypto-Fix-generate_key-3-for-ecdh-to-only-use-OpenS.patch of Package erlang
From 8581ac6df171dcaeb4b201cc9340d6cdd17ce0a7 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson <sverker@erlang.org> Date: Wed, 7 Jun 2023 18:52:46 +0200 Subject: [PATCH 01/14] crypto: Fix generate_key/3 for ecdh to only use OpenSSL 3.0 API to prepare for using FIPS on OpenSSL 3.0 --- lib/crypto/c_src/Makefile.in | 6 +- lib/crypto/c_src/ec.c | 130 +++++++++++++++++++---------------- 2 files changed, 72 insertions(+), 64 deletions(-) diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in index 25167a8a3a..280d48674a 100644 --- a/lib/crypto/c_src/Makefile.in +++ b/lib/crypto/c_src/Makefile.in @@ -205,9 +205,9 @@ $(LIBDIR)/otp_test_engine$(TYPEMARKER).dll: $(TEST_ENGINE_OBJS) $(V_LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(TEST_ENGINE_OBJS) -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME) $(SSL_EXTRA_LIBS) endif -$(OBJDIR)/ec$(TYPEMARKER).o: ec.c - $(V_at)$(INSTALL_DIR) $(OBJDIR) - $(V_CC) -c -o $@ $(ALL_CFLAGS) $(CRYPTO_NO_DEPRECATE_WARN) $< +# $(OBJDIR)/ec$(TYPEMARKER).o: ec.c +# $(V_at)$(INSTALL_DIR) $(OBJDIR) +# $(V_CC) -c -o $@ $(ALL_CFLAGS) $(CRYPTO_NO_DEPRECATE_WARN) $< $(OBJDIR)/%$(TYPEMARKER).o: %.c $(V_at)$(INSTALL_DIR) $(OBJDIR) diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c index 124582c4f8..852f3ba79c 100644 --- a/lib/crypto/c_src/ec.c +++ b/lib/crypto/c_src/ec.c @@ -24,6 +24,8 @@ #ifdef HAVE_EC # if defined(HAS_3_0_API) +# include <openssl/core_names.h> + int get_curve_definition(ErlNifEnv* env, ERL_NIF_TERM *ret, ERL_NIF_TERM def, OSSL_PARAM params[], int *i, size_t *order_size) @@ -253,13 +255,7 @@ int get_ec_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) } -int get_ec_private_key_2(ErlNifEnv* env, - ERL_NIF_TERM curve, ERL_NIF_TERM key, - EVP_PKEY **pkey, - ERL_NIF_TERM *ret, - size_t *order_size); - -int get_ec_private_key_2(ErlNifEnv* env, +static int get_ec_private_key_2(ErlNifEnv* env, ERL_NIF_TERM curve, ERL_NIF_TERM key, EVP_PKEY **pkey, ERL_NIF_TERM *ret, @@ -319,7 +315,8 @@ int get_ec_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) return 0; } -int mk_pub_key_binary(ErlNifEnv* env, EVP_PKEY **peer_pkey, ErlNifBinary *pubkey_bin, ERL_NIF_TERM *ret); +static int mk_pub_key_binary(ErlNifEnv* env, EVP_PKEY *peer_pkey, + ErlNifBinary *pubkey_bin, ERL_NIF_TERM *ret); ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* (Curve, PrivKey|undefined) */ @@ -339,9 +336,8 @@ ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar /* Get the two keys, pub as binary and priv as BN. Since the private key is explicitly given, it must be calculated. - I haven't found any way to do that with the pure 3.0 interface yet. */ - if (!mk_pub_key_binary(env, &peer_pkey, &pubkey_bin, &ret)) + if (!mk_pub_key_binary(env, peer_pkey, &pubkey_bin, &ret)) goto err; if (!EVP_PKEY_get_bn_param(peer_pkey, "priv", &priv_bn)) @@ -398,67 +394,81 @@ ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar return ret; } -int mk_pub_key_binary(ErlNifEnv* env, EVP_PKEY **peer_pkey, ErlNifBinary *pubkey_bin, ERL_NIF_TERM *ret) +static int mk_pub_key_binary(ErlNifEnv* env, EVP_PKEY *peer_pkey, + ErlNifBinary *pubkey_bin, ERL_NIF_TERM *ret) { - EC_KEY *ec_key = NULL; - EC_POINT *public_key = NULL; - EC_GROUP *group = NULL; - BIGNUM *priv_bn = NULL; - - *ret = atom_undefined; - - /* Use the deprecated interface to get the curve and - private key in pre 3.0 form: */ - if ((ec_key = EVP_PKEY_get1_EC_KEY(*peer_pkey)) == NULL) - assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get EC key")); - - if ((group = EC_GROUP_dup(EC_KEY_get0_group(ec_key))) == NULL) + size_t pub_key_size = 0; + size_t group_name_size = 0; + char group_name_buf[20]; + char* group_name = group_name_buf; + int group_nid; + EC_GROUP* ec_group = NULL; + EC_POINT* pub_key = NULL; + BIGNUM* priv_bn = NULL; + int ok = 0; + + /* This code was inspired by + * https://github.com/openssl/openssl/issues/18437 + * which first tried to get public key directly with + * EVP_PKEY_get_octet_string_param(peer_pkey, OSSL_PKEY_PARAM_PUB_KEY,..) + * + * I removed that since I don't know what key format that will produce + * if it succeeds. That is, we go directly to the "fallback" and calculate + * the public key. + */ + + if (!EVP_PKEY_get_utf8_string_param(peer_pkey, OSSL_PKEY_PARAM_GROUP_NAME, + NULL, 0, &group_name_size)) + assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get EC group name size")); + + if (group_name_size >= sizeof(group_name_buf)) + group_name = enif_alloc(group_name_size + 1); + if (!EVP_PKEY_get_utf8_string_param(peer_pkey, OSSL_PKEY_PARAM_GROUP_NAME, + group_name, group_name_size+1, + NULL)) + assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get EC group name")); + + group_nid = OBJ_sn2nid(group_name); + if (group_nid == NID_undef) + assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get EC group nid")); + + ec_group = EC_GROUP_new_by_curve_name(group_nid); + if (ec_group == NULL) assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get EC_GROUP")); - if ((public_key = EC_POINT_new(group)) == NULL) + pub_key = EC_POINT_new(ec_group); + if (pub_key == NULL) assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't create POINT")); - if (!EC_POINT_copy(public_key, EC_GROUP_get0_generator(group))) - assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't copy POINT")); - - /* Make the corresponding public key */ - if (!EVP_PKEY_get_bn_param(*peer_pkey, "priv", &priv_bn)) + if (!EVP_PKEY_get_bn_param(peer_pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv_bn)) assign_goto(*ret, err, EXCP_BADARG_N(env, 1, "Couldn't get peer priv key bytes")); - if (BN_is_zero(priv_bn)) - assign_goto(*ret, err, EXCP_BADARG_N(env, 1, "peer priv key must not be 0")); - - if (!EC_POINT_mul(group, public_key, priv_bn, NULL, NULL, NULL)) + if (!EC_POINT_mul(ec_group, pub_key, priv_bn, NULL, NULL, NULL)) assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't multiply POINT")); - if (!EC_KEY_set_public_key(ec_key, public_key)) - assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't set EC_KEY")); - - if (!EVP_PKEY_assign_EC_KEY(*peer_pkey, ec_key)) - assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't assign EC_KEY to PKEY")); - - /* And now get the binary representation (by some reason we can't read it from - peer_pubkey in the calling function with 3.0-functions.) - */ - { - point_conversion_form_t form = EC_KEY_get_conv_form(ec_key); - size_t dlen = EC_POINT_point2oct(group, public_key, form, NULL, 0, NULL); - - if (!enif_alloc_binary(dlen, pubkey_bin) || - !EC_POINT_point2oct(group, public_key, form, pubkey_bin->data, pubkey_bin->size, NULL) - ) - assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get public key")); + pub_key_size = EC_POINT_point2oct(ec_group, pub_key, + POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); + if (pub_key_size == 0) + assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get pub_key_size")); + + enif_alloc_binary(pub_key_size, pubkey_bin); + if (!EC_POINT_point2oct(ec_group, pub_key, POINT_CONVERSION_UNCOMPRESSED, + pubkey_bin->data, + pubkey_bin->size, NULL)) { + enif_release_binary(pubkey_bin); + assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get pub key bytes")); } - err: - if (public_key) EC_POINT_free(public_key); - if (group) EC_GROUP_free(group); + *ret = enif_make_binary(env, pubkey_bin); + ok = 1; + +err: + if (group_name != group_name_buf) enif_free(group_name); + if (pub_key) EC_POINT_free(pub_key); + if (ec_group) EC_GROUP_free(ec_group); if (priv_bn) BN_free(priv_bn); - if (*ret == atom_undefined) - return 1; - else - return 0; + return ok; } # endif /* HAS_3_0_API */ @@ -908,10 +918,8 @@ ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar # endif /* ! HAS_3_0_API */ -#endif /* HAVE_EC */ - +#else /* ifndef HAVE_EC */ -#if ! defined(HAVE_EC) ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* (Curve, PrivKey) */ return EXCP_NOTSUP_N(env, 0, "EC not supported"); -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor