aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Schultz <[email protected]>2014-11-16 18:45:53 +0100
committerAndreas Schultz <[email protected]>2014-11-17 10:56:52 +0100
commit08753545c4b08b191234f60efe65f78ed113f0d2 (patch)
tree2594398f7cca3a3c9110249031e7b8a9b2c545bf
parent30e5a5b28f3f4c5ba69d536aec30d1fae4e1f2fb (diff)
downloadotp-08753545c4b08b191234f60efe65f78ed113f0d2.tar.gz
otp-08753545c4b08b191234f60efe65f78ed113f0d2.tar.bz2
otp-08753545c4b08b191234f60efe65f78ed113f0d2.zip
[crypto] enhance generate_key for ECC keys
enhance generate_key to calculate ECC public keys from private keys
-rw-r--r--lib/crypto/c_src/crypto.c47
-rw-r--r--lib/crypto/doc/src/crypto.xml2
-rw-r--r--lib/crypto/src/crypto.erl7
-rw-r--r--lib/crypto/test/crypto_SUITE.erl40
4 files changed, 68 insertions, 28 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index a42de9adb1..005f4a964b 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -410,7 +410,7 @@ static ErlNifFunc nif_funcs[] = {
{"bf_ecb_crypt", 3, bf_ecb_crypt},
{"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt},
- {"ec_key_generate", 1, ec_key_generate},
+ {"ec_key_generate", 2, ec_key_generate},
{"ecdsa_sign_nif", 4, ecdsa_sign_nif},
{"ecdsa_verify_nif", 5, ecdsa_verify_nif},
{"ecdh_compute_key_nif", 3, ecdh_compute_key_nif},
@@ -3689,32 +3689,37 @@ out:
static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
#if defined(HAVE_EC)
- EC_KEY *key = ec_key_new(env, argv[0]);
+ EC_KEY *key;
+ const EC_GROUP *group;
+ const EC_POINT *public_key;
+ ERL_NIF_TERM priv_key;
+ ERL_NIF_TERM pub_key = atom_undefined;
CHECK_OSE_CRYPTO();
- if (key && EC_KEY_generate_key(key)) {
- const EC_GROUP *group;
- const EC_POINT *public_key;
- ERL_NIF_TERM priv_key;
- ERL_NIF_TERM pub_key = atom_undefined;
-
- group = EC_KEY_get0_group(key);
- public_key = EC_KEY_get0_public_key(key);
+ if (!get_ec_key(env, argv[0], argv[1], atom_undefined, &key))
+ goto badarg;
- if (group && public_key) {
- pub_key = point2term(env, group, public_key,
- EC_KEY_get_conv_form(key));
- }
- priv_key = bn2term(env, EC_KEY_get0_private_key(key));
- EC_KEY_free(key);
- return enif_make_tuple2(env, pub_key, priv_key);
+ if (argv[1] == atom_undefined) {
+ if (!EC_KEY_generate_key(key))
+ goto badarg;
}
- else {
- if (key)
- EC_KEY_free(key);
- return enif_make_badarg(env);
+
+ group = EC_KEY_get0_group(key);
+ public_key = EC_KEY_get0_public_key(key);
+
+ if (group && public_key) {
+ pub_key = point2term(env, group, public_key,
+ EC_KEY_get_conv_form(key));
}
+ priv_key = bn2term(env, EC_KEY_get0_private_key(key));
+ EC_KEY_free(key);
+ return enif_make_tuple2(env, pub_key, priv_key);
+
+badarg:
+ if (key)
+ EC_KEY_free(key);
+ return enif_make_badarg(env);
#else
return atom_notsup;
#endif
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 271130a9e6..bad60adfe7 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -269,7 +269,7 @@
<v>SrpUserParams = {user, [Generator::binary(), Prime::binary(), Version::atom()]}</v>
<v>SrpHostParams = {host, [Verifier::binary(), Generator::binary(), Prime::binary(), Version::atom()]}</v>
<v>PublicKey = dh_public() | ecdh_public() | srp_public() </v>
- <v>PrivKeyIn = undefined | dh_private() | srp_private() </v>
+ <v>PrivKeyIn = undefined | dh_private() | ecdh_private() | srp_private() </v>
<v>PrivKeyOut = dh_private() | ecdh_private() | srp_private() </v>
</type>
<desc>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 7f82fa83fd..92da8efba4 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -588,9 +588,8 @@ generate_key(srp, {user, [Generator, Prime, Version]}, PrivateArg)
end,
user_srp_gen_key(Private, Generator, Prime);
-generate_key(ecdh, Curve, undefined) ->
- ec_key_generate(nif_curve_params(Curve)).
-
+generate_key(ecdh, Curve, PrivKey) ->
+ ec_key_generate(nif_curve_params(Curve), ensure_int_as_bin(PrivKey)).
compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
@@ -1555,7 +1554,7 @@ dh_compute_key(OthersPublicKey, MyPrivateKey, DHParameters) ->
dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub.
-ec_key_generate(_Key) -> ?nif_stub.
+ec_key_generate(_Curve, _Key) -> ?nif_stub.
ecdh_compute_key_nif(_Others, _Curve, _My) -> ?nif_stub.
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 1031e6403f..3a0c6d7b1e 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -84,7 +84,7 @@ groups() ->
{dss, [], [sign_verify]},
{ecdsa, [], [sign_verify]},
{dh, [], [generate_compute]},
- {ecdh, [], [compute]},
+ {ecdh, [], [compute, generate]},
{srp, [], [generate_compute]},
{des_cbc, [], [block]},
{des_cfb, [], [block]},
@@ -243,6 +243,12 @@ compute(Config) when is_list(Config) ->
Gen = proplists:get_value(compute, Config),
lists:foreach(fun do_compute/1, Gen).
%%--------------------------------------------------------------------
+generate() ->
+ [{doc, " Test crypto:generate_key"}].
+generate(Config) when is_list(Config) ->
+ Gen = proplists:get_value(generate, Config),
+ lists:foreach(fun do_generate/1, Gen).
+%%--------------------------------------------------------------------
mod_pow() ->
[{doc, "mod_pow testing (A ^ M % P with bignums)"}].
mod_pow(Config) when is_list(Config) ->
@@ -494,6 +500,14 @@ 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}) ->
+ case crypto:generate_key(Type, Curve, Priv) of
+ {Pub, _} ->
+ ok;
+ {Other, _} ->
+ ct:fail({{crypto, generate_key, [Type, Priv, Curve]}, {expected, Pub}, {got, Other}})
+ end.
+
hexstr2point(X, Y) ->
<<4:8, (hexstr2bin(X))/binary, (hexstr2bin(Y))/binary>>.
@@ -721,7 +735,8 @@ group_config(srp, Config) ->
[{generate_compute, GenerateCompute} | Config];
group_config(ecdh, Config) ->
Compute = ecdh(),
- [{compute, Compute} | Config];
+ Generate = ecc(),
+ [{compute, Compute}, {generate, Generate} | Config];
group_config(dh, Config) ->
GenerateCompute = [dh()],
[{generate_compute, GenerateCompute} | Config];
@@ -1968,6 +1983,27 @@ rsa_oaep() ->
Msg = hexstr2bin("750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5"),
{rsa, Public, Private, Msg, rsa_pkcs1_oaep_padding}.
+ecc() ->
+%% http://point-at-infinity.org/ecc/nisttv
+%%
+%% Test vectors for the NIST elliptic curves P192, P224, P256, P384, P521,
+%% B163, B233, B283, B409, B571, K163, K233, K283, K409 and K571. For more
+%% information about the curves see
+%% http://csrc.nist.gov/encryption/dss/ecdsa/NISTReCur.pdf
+%%
+ [{ecdh,secp192r1,1,
+ hexstr2point("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
+ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")},
+ {ecdh,secp192r1,2,
+ hexstr2point("DAFEBF5828783F2AD35534631588A3F629A70FB16982A888",
+ "DD6BDA0D993DA0FA46B27BBC141B868F59331AFA5C7E93AB")},
+ {ecdh,secp192r1,3,
+ hexstr2point("76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA",
+ "782C37E372BA4520AA62E0FED121D49EF3B543660CFD05FD")},
+ {ecdh,secp192r1,4,
+ hexstr2point("35433907297CC378B0015703374729D7A4FE46647084E4BA",
+ "A2649984F2135C301EA3ACB0776CD4F125389B311DB3BE32")}].
+
no_padding() ->
Public = [_, Mod] = rsa_public(),
Private = rsa_private(),