Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
2638-crypto-Try-generate-ec-key-by-name-if-poss...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 2638-crypto-Try-generate-ec-key-by-name-if-possible.patch of Package erlang
From af5756898331afd1fa55df8c38e134dc8be52af6 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson <sverker@erlang.org> Date: Wed, 14 Jun 2023 22:00:35 +0200 Subject: [PATCH 08/14] crypto: Try generate ec key by name if possible OpenSSL 3 FIPS does only accept named ec curves. So we try that first, and if it fails we retry with the params passed down by crypto.erl. --- lib/crypto/c_src/ec.c | 90 +++++++++++++++++++++++++------- lib/crypto/c_src/ec.h | 10 +++- lib/crypto/c_src/ecdh.c | 19 +++++-- lib/crypto/test/crypto_SUITE.erl | 2 +- 4 files changed, 94 insertions(+), 27 deletions(-) diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c index af5f5d6f4a..49e1da4fe4 100644 --- a/lib/crypto/c_src/ec.c +++ b/lib/crypto/c_src/ec.c @@ -28,7 +28,8 @@ int get_curve_definition(ErlNifEnv* env, ERL_NIF_TERM *ret, ERL_NIF_TERM def, OSSL_PARAM params[], int *i, - size_t *order_size) + size_t *order_size, + struct get_curve_def_ctx* gcd) { const ERL_NIF_TERM* curve; int c_arity = -1; @@ -40,6 +41,7 @@ int get_curve_definition(ErlNifEnv* env, ERL_NIF_TERM *ret, ERL_NIF_TERM def, int arity = -1; const ERL_NIF_TERM* curve_tuple; + /* Here are two random curve definition examples, one prime_field and one characteristic_two_field. Both are from the crypto/src/crypto_ec_curves.erl. @@ -79,6 +81,23 @@ int get_curve_definition(ErlNifEnv* env, ERL_NIF_TERM *ret, ERL_NIF_TERM def, c_arity != 5) assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad curve def. Expect 5-tuple.")); + if (gcd->use_curve_name + && curve_tuple[1] != atom_undefined + && enif_get_atom(env, curve_tuple[1], gcd->curve_name, + sizeof(gcd->curve_name), ERL_NIF_LATIN1)) { + ErlNifBinary order_bin; + params[(*i)++] = OSSL_PARAM_construct_utf8_string("group", gcd->curve_name, 0); + + if (order_size) { + if (!enif_inspect_binary(env, curve[3], &order_bin)) + assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad order")); + *order_size = order_bin.size; + } + gcd->use_curve_name = 1; + return 1; + } + gcd->use_curve_name = 0; + if (!get_ossl_octet_string_param_from_bin(env, "generator", curve[2], ¶ms[(*i)++])) assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad Generator (Point)")); @@ -211,6 +230,7 @@ int get_ec_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) int tpl_arity; int i = 0; OSSL_PARAM params[15]; + struct get_curve_def_ctx gcd; EVP_PKEY_CTX *pctx = NULL; if (!enif_get_tuple(env, key, &tpl_arity, &tpl_terms) || @@ -222,19 +242,27 @@ int get_ec_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) if (!get_ossl_octet_string_param_from_bin(env, "pub", tpl_terms[1], ¶ms[i++])) assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Bad public key")); - if (!get_curve_definition(env, &ret, tpl_terms[0], params, &i, NULL)) + if (!(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL))) + assign_goto(ret, err, EXCP_ERROR(env, "Can't make EVP_PKEY_CTX")); + + gcd.use_curve_name = 1; +retry_without_name: + if (!get_curve_definition(env, &ret, tpl_terms[0], params, &i, NULL, &gcd)) goto err; params[i++] = OSSL_PARAM_construct_end(); - if (!(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL))) - assign_goto(ret, err, EXCP_ERROR(env, "Can't make EVP_PKEY_CTX")); - if (EVP_PKEY_fromdata_init(pctx) <= 0) assign_goto(ret, err, EXCP_ERROR(env, "Can't init fromdata")); - if (EVP_PKEY_fromdata(pctx, pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) + if (EVP_PKEY_fromdata(pctx, pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + if (gcd.use_curve_name) { + gcd.use_curve_name = 0; + i = 1; + goto retry_without_name; + } assign_goto(ret, err, EXCP_ERROR(env, "Can't do fromdata")); + } if (!*pkey) assign_goto(ret, err, EXCP_ERROR(env, "Couldn't get a public key")); @@ -256,24 +284,33 @@ static int get_ec_private_key_2(ErlNifEnv* env, { int i = 0; OSSL_PARAM params[15]; + struct get_curve_def_ctx gcd; EVP_PKEY_CTX *pctx = NULL; if (!get_ossl_BN_param_from_bin(env, "priv", key, ¶ms[i++])) assign_goto(*ret, err, EXCP_BADARG_N(env, 0, "Bad private key")); - if (!get_curve_definition(env, ret, curve, params, &i, order_size)) + if (!(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL))) + assign_goto(*ret, err, EXCP_ERROR(env, "Can't make EVP_PKEY_CTX")); + + gcd.use_curve_name = 1; +retry_without_name: + if (!get_curve_definition(env, ret, curve, params, &i, order_size, &gcd)) goto err; params[i++] = OSSL_PARAM_construct_end(); - if (!(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL))) - assign_goto(*ret, err, EXCP_ERROR(env, "Can't make EVP_PKEY_CTX")); - if (EVP_PKEY_fromdata_init(pctx) <= 0) assign_goto(*ret, err, EXCP_ERROR(env, "Can't init fromdata")); - if (EVP_PKEY_fromdata(pctx, pkey, EVP_PKEY_KEYPAIR, params) <= 0) + if (EVP_PKEY_fromdata(pctx, pkey, EVP_PKEY_KEYPAIR, params) <= 0) { + if (gcd.use_curve_name) { + gcd.use_curve_name = 0; + i = 1; + goto retry_without_name; + } assign_goto(*ret, err, EXCP_ERROR(env, "Can't do fromdata")); + } if (!*pkey) assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get a private key")); @@ -316,9 +353,10 @@ ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar ERL_NIF_TERM ret = atom_undefined; int i = 0; OSSL_PARAM params[15]; + struct get_curve_def_ctx gcd; EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *pkey = NULL, *peer_pkey = NULL; - size_t sz, order_size; + size_t sz, order_size = 0; BIGNUM *priv_bn = NULL; ErlNifBinary pubkey_bin; @@ -338,26 +376,36 @@ ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar } else { + /* Neither the private nor the public key is known, so we generate the pair: */ + if (!(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL))) + assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_new_from_name")); + + gcd.use_curve_name = 1; + retry_without_name: /* PrivKey (that is, argv[1]) == atom_undefined */ - if (!get_curve_definition(env, &ret, argv[0], params, &i, &order_size)) + if (!get_curve_definition(env, &ret, argv[0], params, &i, + &order_size, &gcd)) // INSERT "ret" parameter in get_curve_definition !! assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Couldn't get Curve definition")); params[i++] = OSSL_PARAM_construct_end(); - /* Neither the private nor the public key is known, so we generate the pair: */ - if (!(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL))) - assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_new_from_name")); - if (EVP_PKEY_keygen_init(pctx) <= 0) assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_keygen_init")); if (!EVP_PKEY_CTX_set_params(pctx, params)) assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_set_params")); - - if (!EVP_PKEY_generate(pctx, &pkey)) + + if (!EVP_PKEY_generate(pctx, &pkey)) { + if (gcd.use_curve_name) { + gcd.use_curve_name = 0; + i = 0; + goto retry_without_name; + } assign_goto(ret, err, EXCP_ERROR(env, "Couldn't generate EC key")); - + } + + /* Get the two keys, pub as binary and priv as BN */ if (!EVP_PKEY_get_octet_string_param(pkey, "encoded-pub-key", NULL, 0, &sz)) assign_goto(ret, err, EXCP_ERROR(env, "Can't get pub octet string size")); @@ -375,6 +423,8 @@ ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Couldn't get priv key bytes")); } + if (order_size == 0) + order_size = BN_num_bytes(priv_bn); ret = enif_make_tuple2(env, enif_make_binary(env, &pubkey_bin), bn2term(env, order_size, priv_bn)); diff --git a/lib/crypto/c_src/ec.h b/lib/crypto/c_src/ec.h index e53986d64e..f0b0b96207 100644 --- a/lib/crypto/c_src/ec.h +++ b/lib/crypto/c_src/ec.h @@ -26,9 +26,17 @@ #if defined(HAVE_EC) # if defined(HAS_3_0_API) + +struct get_curve_def_ctx +{ + char curve_name[20]; + int use_curve_name; +}; + int get_curve_definition(ErlNifEnv* env, ERL_NIF_TERM *ret, ERL_NIF_TERM def, OSSL_PARAM params[], int *i, - size_t *order_size); + size_t *order_size, + struct get_curve_def_ctx*); # endif /* HAS_3_0_API */ # if ! defined(HAS_3_0_API) diff --git a/lib/crypto/c_src/ecdh.c b/lib/crypto/c_src/ecdh.c index 7509d9cb84..f1b0f7eb28 100644 --- a/lib/crypto/c_src/ecdh.c +++ b/lib/crypto/c_src/ecdh.c @@ -42,6 +42,7 @@ ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a int ret_bin_alloc = 0; int i = 0, i_key = 0; OSSL_PARAM params[15]; + struct get_curve_def_ctx gcd; EVP_PKEY_CTX *own_pctx = NULL, *peer_pctx = NULL, *pctx_gen = NULL; EVP_PKEY *own_pkey = NULL, *peer_pkey = NULL; int err; @@ -53,21 +54,29 @@ ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a if (!get_ossl_octet_string_param_from_bin(env, "pub", argv[0], ¶ms[i++])) assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Bad peer public key; binary expected")); + /* Build the remote public key in peer_pkey */ + peer_pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + + gcd.use_curve_name = 1; +retry_without_name: /* Curve definition/name */ - if (!get_curve_definition(env, &ret, argv[1], params, &i, NULL)) + if (!get_curve_definition(env, &ret, argv[1], params, &i, NULL, &gcd)) goto err; /* End of params */ params[i++] = OSSL_PARAM_construct_end(); - /* Build the remote public key in peer_pkey */ - peer_pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); - if (EVP_PKEY_fromdata_init(peer_pctx) <= 0) assign_goto(ret, err, EXCP_ERROR(env, "Can't init fromdata")); - if (EVP_PKEY_fromdata(peer_pctx, &peer_pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) + if (EVP_PKEY_fromdata(peer_pctx, &peer_pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + if (gcd.use_curve_name) { + gcd.use_curve_name = 0; + i = 1; + goto retry_without_name; + } assign_goto(ret, err, EXCP_ERROR(env, "Can't do fromdata")); + } if (!peer_pkey) assign_goto(ret, err, EXCP_ERROR(env, "No peer_pkey")); diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 915a07a39e..f59aa277ca 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -3565,7 +3565,7 @@ dss_params() -> 16#e3a93c09da6f560e4d483a382a4c546f2335c36a4c35ac1463c08a3e6dd415df56fdc537f25fd5372be63e4f5300780b782f1acd01c8b4eb33414615fd0ea82573acba7ef83f5a943854151afc2d7dfe121fb8cd03335b065b549c5dcc606be9052483bc284e12ac3c8dba09b426e08402030e70bc1cc2bf8957c4ba0630f3f32ad689389ac47443176063f247d9e2296b3ea5b5bc2335828ea1a080ed35918dee212fd031279d1b894f01afec523833669eac031a420e540ba1320a59c424a3e5849a460a56bcb001647885b1433c4f992971746bfe2977ce7259c550b551a6c35761e4a41af764e8d92132fcc0a59d1684eab90d863f29f41cf7578faa908c]. ec_key_named() -> - Curve = hd(crypto:ec_curves()), + Curve = secp224r1, %hd(crypto:ec_curves()), {D2_pub, D2_priv} = crypto:generate_key(ecdh, Curve), {[D2_priv, Curve], [D2_pub, Curve]}. -- 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