aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/crypto/c_src/atoms.c4
-rw-r--r--lib/crypto/c_src/atoms.h2
-rw-r--r--lib/crypto/c_src/crypto.c2
-rw-r--r--lib/crypto/c_src/evp.c27
-rw-r--r--lib/crypto/src/crypto.erl22
-rw-r--r--lib/crypto/test/crypto_SUITE.erl42
6 files changed, 73 insertions, 26 deletions
diff --git a/lib/crypto/c_src/atoms.c b/lib/crypto/c_src/atoms.c
index bbeb329fa2..fc983ec03b 100644
--- a/lib/crypto/c_src/atoms.c
+++ b/lib/crypto/c_src/atoms.c
@@ -89,6 +89,8 @@ ERL_NIF_TERM atom_ecdsa;
#ifdef HAVE_ED_CURVE_DH
ERL_NIF_TERM atom_x25519;
ERL_NIF_TERM atom_x448;
+ERL_NIF_TERM atom_ed25519;
+ERL_NIF_TERM atom_ed448;
#endif
ERL_NIF_TERM atom_eddsa;
@@ -219,6 +221,8 @@ int init_atoms(ErlNifEnv *env, const ERL_NIF_TERM fips_mode, const ERL_NIF_TERM
#ifdef HAVE_ED_CURVE_DH
atom_x25519 = enif_make_atom(env,"x25519");
atom_x448 = enif_make_atom(env,"x448");
+ atom_ed25519 = enif_make_atom(env,"ed25519");
+ atom_ed448 = enif_make_atom(env,"ed448");
#endif
atom_eddsa = enif_make_atom(env,"eddsa");
#ifdef HAVE_EDDSA
diff --git a/lib/crypto/c_src/atoms.h b/lib/crypto/c_src/atoms.h
index 0e2f1a0022..956aab93eb 100644
--- a/lib/crypto/c_src/atoms.h
+++ b/lib/crypto/c_src/atoms.h
@@ -93,6 +93,8 @@ extern ERL_NIF_TERM atom_ecdsa;
#ifdef HAVE_ED_CURVE_DH
extern ERL_NIF_TERM atom_x25519;
extern ERL_NIF_TERM atom_x448;
+extern ERL_NIF_TERM atom_ed25519;
+extern ERL_NIF_TERM atom_ed448;
#endif
extern ERL_NIF_TERM atom_eddsa;
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 802818541b..2ea7b7c329 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -95,7 +95,7 @@ static ErlNifFunc nif_funcs[] = {
{"dh_generate_key_nif", 4, dh_generate_key_nif, 0},
{"dh_compute_key_nif", 3, dh_compute_key_nif, 0},
{"evp_compute_key_nif", 3, evp_compute_key_nif, 0},
- {"evp_generate_key_nif", 1, evp_generate_key_nif, 0},
+ {"evp_generate_key_nif", 2, evp_generate_key_nif, 0},
{"privkey_to_pubkey_nif", 2, privkey_to_pubkey_nif, 0},
{"srp_value_B_nif", 5, srp_value_B_nif, 0},
{"srp_user_secret_nif", 7, srp_user_secret_nif, 0},
diff --git a/lib/crypto/c_src/evp.c b/lib/crypto/c_src/evp.c
index 3bf66bfffe..19dbd234f6 100644
--- a/lib/crypto/c_src/evp.c
+++ b/lib/crypto/c_src/evp.c
@@ -106,25 +106,34 @@ ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
ERL_NIF_TERM ret_pub, ret_prv, ret;
+ ErlNifBinary prv_key;
size_t key_len;
unsigned char *out_pub = NULL, *out_priv = NULL;
- ASSERT(argc == 1);
-
if (argv[0] == atom_x25519)
type = EVP_PKEY_X25519;
else if (argv[0] == atom_x448)
type = EVP_PKEY_X448;
+ else if (argv[0] == atom_ed25519)
+ type = EVP_PKEY_ED25519;
+ else if (argv[0] == atom_ed448)
+ type = EVP_PKEY_ED448;
else
goto bad_arg;
- if ((ctx = EVP_PKEY_CTX_new_id(type, NULL)) == NULL)
- goto bad_arg;
-
- if (EVP_PKEY_keygen_init(ctx) != 1)
- goto err;
- if (EVP_PKEY_keygen(ctx, &pkey) != 1)
- goto err;
+ if (argv[1] == atom_undefined) {
+ if ((ctx = EVP_PKEY_CTX_new_id(type, NULL)) == NULL)
+ goto bad_arg;
+ if (EVP_PKEY_keygen_init(ctx) != 1)
+ goto bad_arg;
+ if (EVP_PKEY_keygen(ctx, &pkey) != 1)
+ goto bad_arg;
+ } else {
+ if (!enif_inspect_binary(env, argv[1], &prv_key))
+ goto bad_arg;
+ if ((pkey = EVP_PKEY_new_raw_private_key(type, NULL, prv_key.data, prv_key.size)) == NULL)
+ goto bad_arg;
+ }
if (EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len) != 1)
goto err;
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 965697578d..1c32895dbf 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -1761,21 +1761,21 @@ pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_
-spec generate_key(Type, Params)
-> {PublicKey, PrivKeyOut}
- when Type :: dh | ecdh | rsa | srp,
+ when Type :: dh | ecdh | eddsa | rsa | srp,
PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
- Params :: dh_params() | ecdh_params() | rsa_params() | srp_gen_params()
+ Params :: dh_params() | ecdh_params() | eddsa_params() | rsa_params() | srp_gen_params()
.
generate_key(Type, Params) ->
generate_key(Type, Params, undefined).
-spec generate_key(Type, Params, PrivKeyIn)
-> {PublicKey, PrivKeyOut}
- when Type :: dh | ecdh | rsa | srp,
+ when Type :: dh | ecdh | eddsa | rsa | srp,
PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
PrivKeyIn :: undefined | dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
- Params :: dh_params() | ecdh_params() | rsa_params() | srp_comp_params()
+ Params :: dh_params() | ecdh_params() | eddsa_params() | rsa_params() | srp_comp_params()
.
generate_key(dh, DHParameters0, PrivateKey) ->
@@ -1813,15 +1813,17 @@ generate_key(rsa, {ModulusSize, PublicExponent}, undefined) ->
{lists:sublist(Private, 2), Private}
end;
-
-generate_key(ecdh, Curve, undefined) when Curve == x448 ;
- Curve == x25519 ->
- evp_generate_key_nif(Curve);
+generate_key(ecdh, Curve, PrivKey) when Curve == x448 ;
+ Curve == x25519 ->
+ evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey));
generate_key(ecdh, Curve, PrivKey) ->
- ec_key_generate(nif_curve_params(Curve), ensure_int_as_bin(PrivKey)).
+ ec_key_generate(nif_curve_params(Curve), ensure_int_as_bin(PrivKey));
+generate_key(eddsa, Curve, PrivKey) when Curve == ed448 ;
+ Curve == ed25519 ->
+ evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey)).
-evp_generate_key_nif(_Curve) -> ?nif_stub.
+evp_generate_key_nif(_Curve, _PrivKey) -> ?nif_stub.
-spec compute_key(Type, OthersPublicKey, MyPrivateKey, Params)
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 0da70d5592..6436b5b86d 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -202,11 +202,13 @@ groups() ->
{ecdsa, [], [sign_verify
%% Does not work yet: ,public_encrypt, private_encrypt
]},
- {ed25519, [], [sign_verify
+ {ed25519, [], [sign_verify,
%% Does not work yet: ,public_encrypt, private_encrypt
+ generate
]},
- {ed448, [], [sign_verify
+ {ed448, [], [sign_verify,
%% Does not work yet: ,public_encrypt, private_encrypt
+ generate
]},
{dh, [], [generate_compute, compute_bug]},
{ecdh, [], [use_all_elliptic_curves, compute, generate]},
@@ -1429,7 +1431,7 @@ do_compute({ecdh = Type, Pub, Priv, Curve, SharedSecret}) ->
ct:fail({{crypto, compute_key, [Type, Pub, Priv, Curve]}, {expected, SharedSecret}, {got, Other}})
end.
-do_generate({ecdh = Type, Curve, Priv, Pub}) ->
+do_generate({Type, Curve, Priv, Pub}) when Type == ecdh ; Type == eddsa ->
case crypto:generate_key(Type, Curve, Priv) of
{Pub, _} ->
ok;
@@ -1854,13 +1856,16 @@ group_config(ecdsa = Type, Config) ->
[{sign_verify, SignVerify}, {pub_priv_encrypt, PubPrivEnc} | Config];
group_config(Type, Config) when Type == ed25519 ; Type == ed448 ->
TestVectors = eddsa(Type),
- [{sign_verify,TestVectors} | Config];
+ Generate = lists:map(fun({Curve, _Hash, Priv, Pub, _Msg, _Signature}) ->
+ {eddsa, Curve, Priv, Pub}
+ end, TestVectors),
+ [{sign_verify,TestVectors}, {generate, Generate} | Config];
group_config(srp, Config) ->
GenerateCompute = [srp3(), srp6(), srp6a(), srp6a_smaller_prime()],
[{generate_compute, GenerateCompute} | Config];
group_config(ecdh, Config) ->
Compute = ecdh(),
- Generate = ecc(),
+ Generate = ecc() ++ ecc(x25519) ++ ecc(x448),
[{compute, Compute}, {generate, Generate} | Config];
group_config(dh, Config) ->
GenerateCompute = [dh()],
@@ -3351,7 +3356,7 @@ srp(ClientPrivate, Generator, Prime, Version, Verifier, ServerPublic, ServerPriv
eddsa(ed25519) ->
%% https://tools.ietf.org/html/rfc8032#section-7.1
- %% {ALGORITHM, (SHA)}, SECRET KEY, PUBLIC KEY, MESSAGE, SIGNATURE}
+ %% {ALGORITHM, (SHA), SECRET KEY, PUBLIC KEY, MESSAGE, SIGNATURE}
[
%% TEST 1
{ed25519, undefined,
@@ -3923,6 +3928,31 @@ ecc() ->
end,
TestCases).
+ecc(x25519) ->
+ %% RFC 7748, 6.1
+ [{ecdh, x25519,
+ hexstr2bin("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"),
+ hexstr2bin("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a")},
+ {ecdh, x25519,
+ hexstr2bin("5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb"),
+ hexstr2bin("de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f")}
+ ];
+
+ecc(x448) ->
+ %% RFC 7748, 6.2
+ [{ecdh, x448,
+ hexstr2bin("9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28d"
+ "d9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b"),
+ hexstr2bin("9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c"
+ "22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0")},
+ {ecdh, x448,
+ hexstr2bin("1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d"
+ "6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d"),
+ hexstr2bin("3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b430"
+ "27d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609")}
+ ].
+
+
int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []);
int_to_bin(X) -> int_to_bin_pos(X, []).