From 04b8fa3ecbef2017a14342157c0f3e41afb3a091 Mon Sep 17 00:00:00 2001 From: Thomas Arts Date: Tue, 12 Jun 2018 14:26:14 +0200 Subject: [PATCH 001/162] Dangerous use of constant --- c_src/enacl_nif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 1046af7..29862c3 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -131,7 +131,7 @@ ERL_NIF_TERM enif_crypto_curve25519_scalarmult(ErlNifEnv *env, int argc, ERL_NIF memcpy(bp, basepoint.data, crypto_scalarmult_curve25519_BYTES); /* Clear the high-bit. Better safe than sorry. */ - bp[31] &= 0x7f; + bp[crypto_scalarmult_curve25519_BYTES - 1] &= 0x7f; do { From 40fde1807b49e11007112c49186d2afb4cb085d8 Mon Sep 17 00:00:00 2001 From: Thomas Arts Date: Wed, 13 Jun 2018 07:03:04 +0200 Subject: [PATCH 002/162] Variable is assigned but never used This is just a warning, but elliminating warnings makes the code go cleanly through clang static code analyzer. --- c_src/enacl_nif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 29862c3..5b1cf58 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1167,7 +1167,7 @@ void uint64_pack(unsigned char *y, ErlNifUInt64 x) *y++ = x; x >>= 8; *y++ = x; x >>= 8; *y++ = x; x >>= 8; - *y++ = x; x >>= 8; + *y++ = x; } static From b3bbb2a9103d0fd7a58cba4612ec50de0d9ad69e Mon Sep 17 00:00:00 2001 From: Thomas Arts Date: Wed, 13 Jun 2018 07:04:01 +0200 Subject: [PATCH 003/162] Add tests for scalarmult There appeared to be no tests for this function. The typical property for it is that scalarmultiplication is commutitative. --- eqc_test/enacl_eqc.erl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 3bc2987..bc7211e 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -1,6 +1,6 @@ -module(enacl_eqc). -include_lib("eqc/include/eqc.hrl"). --compile(export_all). +-compile([export_all, nowarn_export_all]). -ifndef(mini). -compile({parse_transform, eqc_parallelize}). @@ -774,6 +774,16 @@ prop_scramble_block() -> ?FORALL({Block, Key}, {binary(16), eqc_gen:largebinary(32)}, is_binary(enacl_ext:scramble_block_16(Block, Key))). +%% Scala multiplication +prop_scalarmult() -> + Bytes = 32, + ?FORALL({S1, S2, Basepoint}, {binary(Bytes), binary(Bytes), binary(Bytes)}, + equals(enacl:curve25519_scalarmult(S1, + enacl:curve25519_scalarmult(S2, Basepoint)), + enacl:curve25519_scalarmult(S2, + enacl:curve25519_scalarmult(S1, Basepoint))) + ). + %% HELPERS badargs(Thunk) -> try From d77907128507828316c9a6c06572d7893717e655 Mon Sep 17 00:00:00 2001 From: ECrownofFire Date: Sat, 27 Oct 2018 17:23:06 -0400 Subject: [PATCH 004/162] Add choice of ops and mem limits to pwhash_str It natively checks atoms, which is kinda messy, but it avoids having to export the libsodium pwhash constants, which is nice. --- c_src/enacl_nif.c | 67 +++++++++++++++++++++++++++++++++++++++++++---- src/enacl.erl | 20 +++++++++++++- src/enacl_nif.erl | 4 +-- 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 364a47d..f2018f1 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1259,6 +1259,61 @@ ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, ERL_NIF_TERM const return enif_make_binary(env, &out); } +static +size_t enacl_pwhash_opslimit(ErlNifEnv *env, ERL_NIF_TERM arg) { + ERL_NIF_TERM a; + size_t r; + + if (enif_is_atom(env, arg)) { + a = enif_make_atom(env, "interactive"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_OPSLIMIT_INTERACTIVE; + } + + a = enif_make_atom(env, "moderate"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_OPSLIMIT_MODERATE; + } + + a = enif_make_atom(env, "sensitive"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_OPSLIMIT_SENSITIVE; + } + } else if (enif_get_ulong(env, arg, &r)) { + return r; + } + + return 0; +} + +static +size_t enacl_pwhash_memlimit(ErlNifEnv *env, ERL_NIF_TERM arg) { + ERL_NIF_TERM a; + size_t r; + + if (enif_is_atom(env, arg)) { + a = enif_make_atom(env, "interactive"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_MEMLIMIT_INTERACTIVE; + } + + a = enif_make_atom(env, "moderate"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_MEMLIMIT_MODERATE; + } + + a = enif_make_atom(env, "sensitive"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_MEMLIMIT_SENSITIVE; + } + } else if (enif_get_ulong(env, arg, &r)) { + return r; + } + + return 0; +} + + static ERL_NIF_TERM enif_crypto_pwhash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary h, p, s; @@ -1296,10 +1351,13 @@ ERL_NIF_TERM enif_crypto_pwhash(ErlNifEnv *env, int argc, ERL_NIF_TERM const arg static ERL_NIF_TERM enif_crypto_pwhash_str(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary h, p; + size_t o, m; // Validate the arguments - if( (argc != 1) || - (!enif_inspect_iolist_as_binary(env, argv[0], &p)) ) { + if( (argc != 3) || + (!enif_inspect_iolist_as_binary(env, argv[0], &p)) || + !(o = enacl_pwhash_opslimit(env, argv[1])) || + !(m = enacl_pwhash_memlimit(env, argv[2])) ) { return enif_make_badarg(env); } @@ -1308,8 +1366,7 @@ ERL_NIF_TERM enif_crypto_pwhash_str(ErlNifEnv *env, int argc, ERL_NIF_TERM const return nacl_error_tuple(env, "alloc_failed"); } - if( crypto_pwhash_str((char *)h.data, (char *)p.data, p.size, - crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE) != 0) { + if( crypto_pwhash_str((char *)h.data, (char *)p.data, p.size, o, m) != 0) { /* out of memory */ enif_release_binary(&h); return nacl_error_tuple(env, "out_of_memory"); @@ -1722,7 +1779,7 @@ static ErlNifFunc nif_funcs[] = { {"sodium_memzero", 1, enif_sodium_memzero}, {"crypto_pwhash", 2, enif_crypto_pwhash}, - {"crypto_pwhash_str", 1, enif_crypto_pwhash_str}, + {"crypto_pwhash_str", 3, enif_crypto_pwhash_str}, {"crypto_pwhash_str_verify", 2, enif_crypto_pwhash_str_verify}, erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult", 2, enif_crypto_curve25519_scalarmult), diff --git a/src/enacl.erl b/src/enacl.erl index 15ea2c2..ffcc959 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -101,6 +101,9 @@ shorthash_size/0, shorthash/2, + %% No Tests! + pwhash_str/3, + %% EQC pwhash/2, pwhash_str/1, @@ -336,6 +339,7 @@ generichash_final({hashstate, HashSize, HashState}) -> enacl_nif:crypto_generichash_final(HashSize, HashState). +-type pwhash_limit() :: interactive | moderate | sensitive | pos_integer(). %% @doc pwhash/2 hash a password %% %% This function generates a fixed size salted hash of a user defined password. @@ -347,10 +351,24 @@ pwhash(Password, Salt) -> %% @doc pwhash_str/1 generates a ASCII encoded hash of a password %% %% This function generates a fixed size, salted, ASCII encoded hash of a user defined password. +%% Defaults to interactive/interactive limits. %% @end -spec pwhash_str(iodata()) -> {ok, iodata()} | {error, term()}. pwhash_str(Password) -> - case enacl_nif:crypto_pwhash_str(Password) of + pwhash_str(Password, interactive, interactive). + +%% @doc pwhash_str/3 generates a ASCII encoded hash of a password +%% +%% This function generates a fixed size, salted, ASCII encoded hash of a user defined password +%% given Ops and Mem limits. +%% @end +-spec pwhash_str(Password, Ops, Mem) -> {ok, iodata()} | {error, term()} + when + Password :: iodata(), + Ops :: pwhash_limit(), + Mem :: pwhash_limit(). +pwhash_str(Password, Ops, Mem) -> + case enacl_nif:crypto_pwhash_str(Password, Ops, Mem) of {ok, ASCII} -> {ok, strip_null_terminate(ASCII)}; {error, Reason} -> diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 798ef53..4e2a50c 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -133,7 +133,7 @@ %% Password Hashing - Argon2 Algorithm -export([ crypto_pwhash/2, - crypto_pwhash_str/1, + crypto_pwhash_str/3, crypto_pwhash_str_verify/2 ]). @@ -189,7 +189,7 @@ crypto_generichash_update(_HashSize, _HashState, _Message) -> erlang:nif_error( crypto_generichash_final(_HashSize, _HashState) -> erlang:nif_error(nif_not_loaded). crypto_pwhash(_Password, _Salt) -> erlang:nif_error(nif_not_loaded). -crypto_pwhash_str(_Password) -> erlang:nif_error(nif_not_loaded). +crypto_pwhash_str(_Password, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded). crypto_box_NONCEBYTES() -> erlang:nif_error(nif_not_loaded). From 07bcd872940c2788d7c633e627e35ad1799c6199 Mon Sep 17 00:00:00 2001 From: ECrownofFire Date: Sat, 27 Oct 2018 18:00:09 -0400 Subject: [PATCH 005/162] Add choice of ops and mem limits to pwhash --- c_src/enacl_nif.c | 13 ++++++++----- src/enacl.erl | 18 +++++++++++++++++- src/enacl_nif.erl | 4 ++-- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index f2018f1..4291c0a 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1317,11 +1317,14 @@ size_t enacl_pwhash_memlimit(ErlNifEnv *env, ERL_NIF_TERM arg) { static ERL_NIF_TERM enif_crypto_pwhash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary h, p, s; + size_t o, m; // Validate the arguments - if( (argc != 2) || + if( (argc != 4) || (!enif_inspect_iolist_as_binary(env, argv[0], &p)) || - (!enif_inspect_binary(env, argv[1], &s)) ) { + (!enif_inspect_binary(env, argv[1], &s)) || + !(o = enacl_pwhash_opslimit(env, argv[2])) || + !(m = enacl_pwhash_memlimit(env, argv[3])) ) { return enif_make_badarg(env); } @@ -1335,8 +1338,8 @@ ERL_NIF_TERM enif_crypto_pwhash(ErlNifEnv *env, int argc, ERL_NIF_TERM const arg return nacl_error_tuple(env, "alloc_failed"); } - if( crypto_pwhash(h.data, h.size, (char *)p.data, p.size, s.data, - crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE, crypto_pwhash_ALG_DEFAULT) != 0) { + if( crypto_pwhash(h.data, h.size, (char *)p.data, p.size, s.data, o, m, + crypto_pwhash_ALG_DEFAULT) != 0) { /* out of memory */ enif_release_binary(&h); return nacl_error_tuple(env, "out_of_memory"); @@ -1778,7 +1781,7 @@ static ErlNifFunc nif_funcs[] = { {"crypto_verify_32", 2, enif_crypto_verify_32}, {"sodium_memzero", 1, enif_sodium_memzero}, - {"crypto_pwhash", 2, enif_crypto_pwhash}, + {"crypto_pwhash", 4, enif_crypto_pwhash}, {"crypto_pwhash_str", 3, enif_crypto_pwhash_str}, {"crypto_pwhash_str_verify", 2, enif_crypto_pwhash_str_verify}, diff --git a/src/enacl.erl b/src/enacl.erl index ffcc959..ee4f767 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -102,6 +102,7 @@ shorthash/2, %% No Tests! + pwhash/4, pwhash_str/3, %% EQC @@ -343,10 +344,25 @@ generichash_final({hashstate, HashSize, HashState}) -> %% @doc pwhash/2 hash a password %% %% This function generates a fixed size salted hash of a user defined password. +%% Defaults to interactive/interactive limits. %% @end -spec pwhash(iodata(), binary()) -> {ok, binary()} | {error, term()}. pwhash(Password, Salt) -> - enacl_nif:crypto_pwhash(Password, Salt). + pwhash(Password, Salt, interactive, interactive). + +%% @doc pwhash/4 hash a password +%% +%% This function generates a fixed size salted hash of a user defined password given Ops and Mem +%% limits. +%% @end +-spec pwhash(Password, Salt, Ops, Mem) -> {ok, binary()} | {error, term()} + when + Password :: iodata(), + Salt :: binary(), + Ops :: pwhash_limit(), + Mem :: pwhash_limit(). +pwhash(Password, Salt, Ops, Mem) -> + enacl_nif:crypto_pwhash(Password, Salt, Ops, Mem). %% @doc pwhash_str/1 generates a ASCII encoded hash of a password %% diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 4e2a50c..0f48852 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -132,7 +132,7 @@ %% Password Hashing - Argon2 Algorithm -export([ - crypto_pwhash/2, + crypto_pwhash/4, crypto_pwhash_str/3, crypto_pwhash_str_verify/2 ]). @@ -188,7 +188,7 @@ crypto_generichash_init(_HashSize, _Key) -> erlang:nif_error(nif_not_loaded). crypto_generichash_update(_HashSize, _HashState, _Message) -> erlang:nif_error(nif_not_loaded). crypto_generichash_final(_HashSize, _HashState) -> erlang:nif_error(nif_not_loaded). -crypto_pwhash(_Password, _Salt) -> erlang:nif_error(nif_not_loaded). +crypto_pwhash(_Password, _Salt, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str(_Password, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded). From 26f4a40eb42e39931f2746a589ad857f81d65be9 Mon Sep 17 00:00:00 2001 From: ECrownofFire Date: Sat, 27 Oct 2018 18:03:12 -0400 Subject: [PATCH 006/162] Mark pwhash functions as CPU bound --- c_src/enacl_nif.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 4291c0a..0ab1e61 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1781,9 +1781,9 @@ static ErlNifFunc nif_funcs[] = { {"crypto_verify_32", 2, enif_crypto_verify_32}, {"sodium_memzero", 1, enif_sodium_memzero}, - {"crypto_pwhash", 4, enif_crypto_pwhash}, - {"crypto_pwhash_str", 3, enif_crypto_pwhash_str}, - {"crypto_pwhash_str_verify", 2, enif_crypto_pwhash_str_verify}, + erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash", 4, enif_crypto_pwhash), + erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash_str", 3, enif_crypto_pwhash_str), + erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash_str_verify", 2, enif_crypto_pwhash_str_verify), erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult", 2, enif_crypto_curve25519_scalarmult), erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult_base", 1, enif_crypto_curve25519_scalarmult_base), From 4afa6fc0930fe68cdab0ebd0ef1bb34f4b111d8f Mon Sep 17 00:00:00 2001 From: ECrownofFire Date: Sat, 27 Oct 2018 18:10:48 -0400 Subject: [PATCH 007/162] Add checks for ops/mem limit sizes --- c_src/enacl_nif.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 0ab1e61..ac4a13d 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1328,6 +1328,14 @@ ERL_NIF_TERM enif_crypto_pwhash(ErlNifEnv *env, int argc, ERL_NIF_TERM const arg return enif_make_badarg(env); } + // Check limits + if( (o < crypto_pwhash_OPSLIMIT_MIN) || + (o > crypto_pwhash_OPSLIMIT_MAX) || + (m < crypto_pwhash_MEMLIMIT_MIN) || + (m > crypto_pwhash_MEMLIMIT_MAX) ) { + return enif_make_badarg(env); + } + // Check Salt size if(s.size != crypto_pwhash_SALTBYTES) { return nacl_error_tuple(env, "invalid_salt_size"); @@ -1364,6 +1372,14 @@ ERL_NIF_TERM enif_crypto_pwhash_str(ErlNifEnv *env, int argc, ERL_NIF_TERM const return enif_make_badarg(env); } + // Check limits + if( (o < crypto_pwhash_OPSLIMIT_MIN) || + (o > crypto_pwhash_OPSLIMIT_MAX) || + (m < crypto_pwhash_MEMLIMIT_MIN) || + (m > crypto_pwhash_MEMLIMIT_MAX) ) { + return enif_make_badarg(env); + } + // Allocate memory for return binary if( !enif_alloc_binary(crypto_pwhash_STRBYTES, &h) ) { return nacl_error_tuple(env, "alloc_failed"); From 3442655c5b253699317a73ea36b9de66a3e3d118 Mon Sep 17 00:00:00 2001 From: alsdiufgoaiwuegflweuvflasjkdhvlajhsdfg666272727asfgfdsagdlsafg Date: Thu, 22 Nov 2018 13:04:24 +0000 Subject: [PATCH 008/162] add crypto_sign_ed25519_sk_to_pk --- c_src/enacl_nif.c | 22 ++++++++++++++++++++++ src/enacl.erl | 7 +++++++ src/enacl_nif.erl | 2 ++ 3 files changed, 31 insertions(+) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 1497215..e71830b 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -203,6 +203,27 @@ ERL_NIF_TERM enif_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc, ERL_NIF_ return enif_make_tuple2(env, enif_make_binary(env, &pk), enif_make_binary(env, &sk)); } +static +ERL_NIF_TERM enif_crypto_sign_ed25519_sk_to_pk(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk; + + if ((argc != 1) + || (!enif_inspect_binary(env, argv[0], &sk)) + || (sk.size != crypto_sign_ed25519_SECRETKEYBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_sign_ed25519_sk_to_pk(pk.data, sk.data) != 0) { + return nacl_error_tuple(env, "crypto_sign_ed25519_sk_to_pk_failed"); + } + + return enif_make_binary(env, &pk); +} + static ERL_NIF_TERM enif_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary curve25519_pk, ed25519_pk; @@ -1735,6 +1756,7 @@ static ErlNifFunc nif_funcs[] = { erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult_base", 1, enif_crypto_curve25519_scalarmult_base), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_ed25519_keypair", 0, enif_crypto_sign_ed25519_keypair), + {"crypto_sign_ed25519_sk_to_pk", 1, enif_crypto_sign_ed25519_sk_to_pk}, {"crypto_sign_ed25519_public_to_curve25519", 1, enif_crypto_sign_ed25519_public_to_curve25519}, {"crypto_sign_ed25519_secret_to_curve25519", 1, enif_crypto_sign_ed25519_secret_to_curve25519}, {"crypto_sign_ed25519_PUBLICKEYBYTES", 0, enif_crypto_sign_ed25519_PUBLICKEYBYTES}, diff --git a/src/enacl.erl b/src/enacl.erl index 15ea2c2..f8b3366 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -137,6 +137,7 @@ -export([ %% No Tests! crypto_sign_ed25519_keypair/0, + crypto_sign_ed25519_sk_to_pk/1, crypto_sign_ed25519_public_to_curve25519/1, crypto_sign_ed25519_secret_to_curve25519/1, crypto_sign_ed25519_public_size/0, @@ -957,6 +958,12 @@ crypto_sign_ed25519_keypair() -> {PK, SK} = enacl_nif:crypto_sign_ed25519_keypair(), #{ public => PK, secret => SK }. +%% @doc TODO +%% @end +-spec crypto_sign_ed25519_sk_to_pk(Secret :: binary()) -> binary(). +crypto_sign_ed25519_sk_to_pk(Secret) -> + enacl_nif:crypto_sign_ed25519_sk_to_pk(Secret). + %% @doc crypto_sign_ed25519_public_to_curve25519/1 converts a given Ed 25519 public %% key to a Curve 25519 public key. %% @end diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 798ef53..45c39aa 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -105,6 +105,7 @@ %% Ed 25519 -export([ crypto_sign_ed25519_keypair/0, + crypto_sign_ed25519_sk_to_pk/1, crypto_sign_ed25519_public_to_curve25519/1, crypto_sign_ed25519_secret_to_curve25519/1, crypto_sign_ed25519_PUBLICKEYBYTES/0, @@ -277,6 +278,7 @@ crypto_curve25519_scalarmult(_Secret, _BasePoint) -> erlang:nif_error(nif_not_lo crypto_curve25519_scalarmult_base(_Secret) -> erlang:nif_error(nif_not_loaded). crypto_sign_ed25519_keypair() -> erlang:nif_error(nif_not_loaded). +crypto_sign_ed25519_sk_to_pk(_SecretKey) -> erlang:nif_error(nif_not_loaded). crypto_sign_ed25519_public_to_curve25519(_PublicKey) -> erlang:nif_error(nif_not_loaded). crypto_sign_ed25519_secret_to_curve25519(_SecretKey) -> erlang:nif_error(nif_not_loaded). crypto_sign_ed25519_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded). From 2b183e197405cab1761c5ffb0a4c8942d8a02f15 Mon Sep 17 00:00:00 2001 From: ECrownofFire Date: Sun, 25 Nov 2018 09:44:57 -0500 Subject: [PATCH 009/162] Add support for aead_xchacha20poly1305 --- c_src/enacl_nif.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++ src/enacl.erl | 63 +++++++++++++++++++++++++++++++++++ src/enacl_nif.erl | 14 ++++++++ 3 files changed, 160 insertions(+) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 364a47d..4d6b3d0 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1433,6 +1433,81 @@ ERL_NIF_TERM enif_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, } +/* + * AEAD XChaCha20 Poly1305 + */ +static +ERL_NIF_TERM enif_crypto_aead_xchacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_KEYBYTES); +} + +static +ERL_NIF_TERM enif_crypto_aead_xchacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES); +} + +static +ERL_NIF_TERM enif_crypto_aead_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_ABYTES); +} + +static +ERL_NIF_TERM enif_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX); +} + +static +ERL_NIF_TERM enif_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + ErlNifBinary key, nonce, ad, message, ciphertext; + + if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) + || (!enif_inspect_binary(env, argv[1], &nonce)) + || (!enif_inspect_binary(env, argv[2], &ad)) + || (!enif_inspect_binary(env, argv[3], &message)) + || (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES) + || (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(message.size + crypto_aead_xchacha20poly1305_ietf_ABYTES, &ciphertext)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_aead_xchacha20poly1305_ietf_encrypt(ciphertext.data, NULL, message.data, message.size, + ad.data, ad.size, NULL, nonce.data, key.data) < 0) { + return nacl_error_tuple(env, "aead_xchacha20poly1305_ietf_encrypt_failed"); + } + + return enif_make_binary(env, &ciphertext); +} + +static +ERL_NIF_TERM enif_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + ErlNifBinary key, nonce, ad, message, ciphertext; + + if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) + || (!enif_inspect_binary(env, argv[1], &nonce)) + || (!enif_inspect_binary(env, argv[2], &ad)) + || (!enif_inspect_binary(env, argv[3], &ciphertext)) + || (ciphertext.size < crypto_aead_xchacha20poly1305_ietf_ABYTES) + || (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES) + || (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(ciphertext.size - crypto_aead_xchacha20poly1305_ietf_ABYTES, &message)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_aead_xchacha20poly1305_ietf_decrypt(message.data, NULL, NULL, ciphertext.data, ciphertext.size, + ad.data, ad.size, nonce.data, key.data) < 0) { + return nacl_error_tuple(env, "aead_xchacha20poly1305_ietf_decrypt_failed"); + } + + return enif_make_binary(env, &message); +} + + /* * Generic hash */ @@ -1752,6 +1827,14 @@ static ErlNifFunc nif_funcs[] = { erl_nif_dirty_job_cpu_bound_macro("crypto_aead_chacha20poly1305_encrypt", 4, enif_crypto_aead_chacha20poly1305_encrypt), erl_nif_dirty_job_cpu_bound_macro("crypto_aead_chacha20poly1305_decrypt", 4, enif_crypto_aead_chacha20poly1305_decrypt), + {"crypto_aead_xchacha20poly1305_KEYBYTES", 0, enif_crypto_aead_xchacha20poly1305_KEYBYTES}, + {"crypto_aead_xchacha20poly1305_NPUBBYTES", 0, enif_crypto_aead_xchacha20poly1305_NPUBBYTES}, + {"crypto_aead_xchacha20poly1305_ABYTES", 0, enif_crypto_aead_xchacha20poly1305_ABYTES}, + {"crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX", 0, enif_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX}, + erl_nif_dirty_job_cpu_bound_macro("crypto_aead_xchacha20poly1305_encrypt", 4, enif_crypto_aead_xchacha20poly1305_encrypt), + erl_nif_dirty_job_cpu_bound_macro("crypto_aead_xchacha20poly1305_decrypt", 4, enif_crypto_aead_xchacha20poly1305_decrypt), + + {"crypto_generichash_BYTES", 0, enif_crypto_generichash_BYTES}, {"crypto_generichash_BYTES_MIN", 0, enif_crypto_generichash_BYTES_MIN}, {"crypto_generichash_BYTES_MAX", 0, enif_crypto_generichash_BYTES_MAX}, diff --git a/src/enacl.erl b/src/enacl.erl index 15ea2c2..8256482 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -66,6 +66,14 @@ aead_chacha20poly1305_ABYTES/0, aead_chacha20poly1305_MESSAGEBYTES_MAX/0, + %% No Tests! + aead_xchacha20poly1305_encrypt/4, + aead_xchacha20poly1305_decrypt/4, + aead_xchacha20poly1305_KEYBYTES/0, + aead_xchacha20poly1305_NONCEBYTES/0, + aead_xchacha20poly1305_ABYTES/0, + aead_xchacha20poly1305_MESSAGEBYTES_MAX/0, + %% EQC stream_key_size/0, stream_nonce_size/0, @@ -1101,6 +1109,61 @@ aead_chacha20poly1305_ABYTES() -> aead_chacha20poly1305_MESSAGEBYTES_MAX() -> enacl_nif:crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(). +%% AEAD XChaCha20 Poly1305 +%% ---------------------- +%% @doc aead_xchacha20poly1305_encrypt/4 encrypts `Message' with additional data +%% `AD' using `Key' and `Nonce'. Returns the encrypted message followed by +%% `aead_xchacha20poly1305_ABYTES/0' bytes of MAC. +%% @end +-spec aead_xchacha20poly1305_encrypt(Key, Nonce, AD, Msg) -> binary() | {error, term()} + when Key :: binary(), + Nonce :: binary(), + AD :: binary(), + Msg :: binary(). +aead_xchacha20poly1305_encrypt(Key, Nonce, AD, Msg) -> + enacl_nif:crypto_aead_xchacha20poly1305_encrypt(Key, Nonce, AD, Msg). + +%% @doc aead_xchacha20poly1305_decrypt/4 decrypts ciphertext `CT' with additional +%% data `AD' using `Key' and `Nonce'. Note: `CipherText' should contain +%% `aead_xchacha20poly1305_ABYTES/0' bytes that is the MAC. Returns the decrypted +%% message. +%% @end +-spec aead_xchacha20poly1305_decrypt(Key, Nonce, AD, CT) -> binary() | {error, term()} + when Key :: binary(), + Nonce :: binary(), + AD :: binary(), + CT :: binary(). +aead_xchacha20poly1305_decrypt(Key, Nonce, AD, CT) -> + enacl_nif:crypto_aead_xchacha20poly1305_decrypt(Key, Nonce, AD, CT). + +%% @doc aead_xchacha20poly1305_KEYBYTES/0 returns the number of bytes +%% of the key used in AEAD XChaCha20 Poly1305 encryption/decryption. +%% @end +-spec aead_xchacha20poly1305_KEYBYTES() -> pos_integer(). +aead_xchacha20poly1305_KEYBYTES() -> + enacl_nif:crypto_aead_xchacha20poly1305_KEYBYTES(). + +%% @doc aead_xchacha20poly1305_NONCEBYTES/0 returns the number of bytes +%% of the Nonce in AEAD XChaCha20 Poly1305 encryption/decryption. +%% @end +-spec aead_xchacha20poly1305_NONCEBYTES() -> pos_integer(). +aead_xchacha20poly1305_NONCEBYTES() -> + enacl_nif:crypto_aead_xchacha20poly1305_NPUBBYTES(). + +%% @doc aead_xchacha20poly1305_ABYTES/0 returns the number of bytes +%% of the MAC in AEAD XChaCha20 Poly1305 encryption/decryption. +%% @end +-spec aead_xchacha20poly1305_ABYTES() -> pos_integer(). +aead_xchacha20poly1305_ABYTES() -> + enacl_nif:crypto_aead_xchacha20poly1305_ABYTES(). + +%% @doc aead_xchacha20poly1305_MESSAGEBYTES_MAX/0 returns the max number of bytes +%% allowed in a message in AEAD XChaCha20 Poly1305 encryption/decryption. +%% @end +-spec aead_xchacha20poly1305_MESSAGEBYTES_MAX() -> pos_integer(). +aead_xchacha20poly1305_MESSAGEBYTES_MAX() -> + enacl_nif:crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX(). + %% Obtaining random bytes %% @doc randombytes/1 produces a stream of random bytes of the given size diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 798ef53..3ce7a62 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -74,6 +74,13 @@ crypto_aead_chacha20poly1305_ABYTES/0, crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX/0, + crypto_aead_xchacha20poly1305_encrypt/4, + crypto_aead_xchacha20poly1305_decrypt/4, + crypto_aead_xchacha20poly1305_KEYBYTES/0, + crypto_aead_xchacha20poly1305_NPUBBYTES/0, + crypto_aead_xchacha20poly1305_ABYTES/0, + crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX/0, + crypto_auth_BYTES/0, crypto_auth_KEYBYTES/0, @@ -255,6 +262,13 @@ crypto_aead_chacha20poly1305_NPUBBYTES() -> erlang:nif_ crypto_aead_chacha20poly1305_ABYTES() -> erlang:nif_error(nif_not_loaded). crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_encrypt(_Key, _Nonce, _AD, _Message) -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_decrypt(_Key, _Nonce, _AD, _Message) -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_KEYBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_NPUBBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_ABYTES() -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded). + crypto_auth_BYTES() -> erlang:nif_error(nif_not_loaded). crypto_auth_KEYBYTES() -> erlang:nif_error(nif_not_loaded). crypto_auth(_Msg, _Key) -> erlang:nif_error(nif_not_loaded). From 6f4a0c2521a2f20dec9b2db76e8bb77dbbfb743b Mon Sep 17 00:00:00 2001 From: Ole Andre Birkedal Date: Sat, 8 Jun 2019 18:19:44 +0200 Subject: [PATCH 010/162] Added bindings for crypto_sign_seed_keypair in libsodium --- c_src/enacl_nif.c | 30 ++++++++++++++++++++++++++++++ src/enacl.erl | 17 +++++++++++++++++ src/enacl_nif.erl | 4 ++++ 3 files changed, 51 insertions(+) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 1497215..dbc3393 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -477,6 +477,11 @@ ERL_NIF_TERM enif_crypto_sign_SECRETKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_T return enif_make_int64(env, crypto_sign_SECRETKEYBYTES); } +static +ERL_NIF_TERM enif_crypto_sign_SEEDBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_sign_SEEDBYTES); +} + static ERL_NIF_TERM enif_crypto_sign_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary pk, sk; @@ -498,6 +503,29 @@ ERL_NIF_TERM enif_crypto_sign_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM con return enif_make_tuple2(env, enif_make_binary(env, &pk), enif_make_binary(env, &sk)); } +static +ERL_NIF_TERM enif_crypto_sign_seed_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk, seed; + + if ( + (argc != 1) || + (!enif_inspect_binary(env, argv[0], &seed))) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_sign_seed_keypair(pk.data, sk.data, seed.data); + + return enif_make_tuple2(env, enif_make_binary(env, &pk), enif_make_binary(env, &sk)); +} + /* int crypto_sign(unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen, @@ -1667,7 +1695,9 @@ static ErlNifFunc nif_funcs[] = { {"crypto_sign_PUBLICKEYBYTES", 0, enif_crypto_sign_PUBLICKEYBYTES}, {"crypto_sign_SECRETKEYBYTES", 0, enif_crypto_sign_SECRETKEYBYTES}, + {"crypto_sign_SEEDBYTES", 0, enif_crypto_sign_SEEDBYTES}, erl_nif_dirty_job_cpu_bound_macro("crypto_sign_keypair", 0, enif_crypto_sign_keypair), + erl_nif_dirty_job_cpu_bound_macro("crypto_sign_seed_keypair", 1, enif_crypto_sign_seed_keypair), erl_nif_dirty_job_cpu_bound_macro("crypto_sign", 2, enif_crypto_sign), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_open", 2, enif_crypto_sign_open), diff --git a/src/enacl.erl b/src/enacl.erl index 15ea2c2..d6e811d 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -33,7 +33,9 @@ %% EQC sign_keypair_public_size/0, sign_keypair_secret_size/0, + sign_keypair_seed_size/0, sign_keypair/0, + sign_seed_keypair/1, sign/2, sign_open/2, sign_detached/2, @@ -513,6 +515,10 @@ sign_keypair_public_size() -> sign_keypair_secret_size() -> enacl_nif:crypto_sign_SECRETKEYBYTES(). +%% @private +sign_keypair_seed_size() -> + enacl_nif:crypto_sign_SEEDBYTES(). + %% @doc sign_keypair/0 returns a signature keypair for signing %% %% The returned value is a map in order to make it harder to misuse keys. @@ -522,6 +528,17 @@ sign_keypair() -> {PK, SK} = enacl_nif:crypto_sign_keypair(), #{ public => PK, secret => SK}. +%% @doc sign_seed_keypair/1 returns a signature keypair based on seed for signing +%% +%% The returned value is a map in order to make it harder to misuse keys. +%% @end +-spec sign_seed_keypair(S) -> #{ atom() => binary() } + when + S :: binary(). +sign_seed_keypair(S) -> + {PK, SK} = enacl_nif:crypto_sign_seed_keypair(S), + #{ public => PK, secret => SK}. + %% @doc sign/2 signs a message with a digital signature identified by a secret key. %% %% Given a message `M' and a secret key `SK' the function will sign the message and return a signed message `SM'. diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 798ef53..0675615 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -25,8 +25,10 @@ crypto_sign_PUBLICKEYBYTES/0, crypto_sign_SECRETKEYBYTES/0, + crypto_sign_SEEDBYTES/0, crypto_sign_keypair/0, + crypto_sign_seed_keypair/1, crypto_sign/2, crypto_sign_open/2, @@ -211,8 +213,10 @@ crypto_box_open_afternm_b(_CipherText, _Nonce, _K) -> erlang:nif_error(nif_not_l crypto_sign_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded). crypto_sign_SECRETKEYBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_sign_SEEDBYTES() -> erlang:nif_error(nif_not_loaded). crypto_sign_keypair() -> erlang:nif_error(nif_not_loaded). +crypto_sign_seed_keypair(_S) -> erlang:nif_error(nif_not_loaded). crypto_sign(_M, _SK) -> erlang:nif_error(nif_not_loaded). crypto_sign_open(_SignedMessage, _PK) -> erlang:nif_error(nif_not_loaded). From 279c2c32c83cbe97ad92ec3c183d1ffbeb05de15 Mon Sep 17 00:00:00 2001 From: Garry Hill Date: Wed, 20 Nov 2019 12:11:21 +0000 Subject: [PATCH 011/162] Add support for multi-part signatures --- c_src/enacl_nif.c | 146 +++++++++++++++++++++++++++++++++++++++++++++- src/enacl.erl | 46 +++++++++++++++ src/enacl_nif.erl | 10 ++++ 3 files changed, 201 insertions(+), 1 deletion(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 1497215..da8535d 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -10,6 +10,7 @@ #define ATOM_FALSE "false" #define CRYPTO_GENERICHASH_STATE_RESOURCE "crypto_generichash_state" +#define CRYPTO_SIGN_STATE_RESOURCE "crypto_sign_state" #ifdef ERL_NIF_DIRTY_JOB_CPU_BOUND #define erl_nif_dirty_job_cpu_bound_macro(a,b,c) {a,b,c,ERL_NIF_DIRTY_JOB_CPU_BOUND} @@ -20,8 +21,9 @@ //{"crypto_box_keypair", 0, enif_crypto_box_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND} /* Errors */ -/* This is a global variable for resource type */ +/* These are global variables for resource types */ static ErlNifResourceType *generichash_state_type = NULL; +static ErlNifResourceType *sign_state_type = NULL; static ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) { @@ -35,6 +37,10 @@ int enif_crypto_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info) { if( !(generichash_state_type = enif_open_resource_type(env, NULL, CRYPTO_GENERICHASH_STATE_RESOURCE, NULL, ERL_NIF_RT_CREATE, NULL)) ) { return -1; } + // Create a new resource type for crypto_sign_state + if( !(sign_state_type = enif_open_resource_type(env, NULL, CRYPTO_SIGN_STATE_RESOURCE, NULL, ERL_NIF_RT_CREATE, NULL)) ) { + return -1; + } return sodium_init(); } @@ -620,6 +626,139 @@ ERL_NIF_TERM enif_crypto_sign_verify_detached(ErlNifEnv* env, int argc, ERL_NIF_ } } +/* + int crypto_sign_init(crypto_sign_state *state) + */ + +static +ERL_NIF_TERM enif_crypto_sign_init(ErlNifEnv* env, int argc, ERL_NIF_TERM const argv[]) { + if( (argc != 0) ) { + return enif_make_badarg(env); + } + + void* state = enif_alloc_resource(sign_state_type, crypto_sign_statebytes()); + + if( !state ) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if( 0 != crypto_sign_init(state) ) { + return nacl_error_tuple(env, "sign_init_error"); + } + + // Create return values + ERL_NIF_TERM e1 = enif_make_atom(env, "signstate"); + ERL_NIF_TERM e2 = enif_make_resource(env, state); + + // release dynamically allocated memory to erlang to mange + enif_release_resource(state); + + // return a tuple + return enif_make_tuple2(env, e1, e2); +} + +/* + int crypto_sign_update(crypto_sign_state *state, + const unsigned char *m, + unsigned long long mlen); + */ + +static +ERL_NIF_TERM enif_crypto_sign_update(ErlNifEnv* env, int argc, ERL_NIF_TERM const argv[]) { + ErlNifBinary data; + + void *state; + + // Validate the arguments + if( (argc != 2) || + (!enif_get_resource(env, argv[0], sign_state_type, (void **)&state)) || + (!enif_inspect_binary(env, argv[1], &data)) ) { + return enif_make_badarg(env); + } + + if( 0 != crypto_sign_update(state, data.data, data.size) ) { + return nacl_error_tuple(env, "sign_update_error"); + } + + // Generate return value + ERL_NIF_TERM e1 = enif_make_atom(env, "signstate"); + ERL_NIF_TERM e2 = enif_make_resource(env, state); + + // return a tuple + return enif_make_tuple2(env, e1, e2); +} + +/* + int crypto_sign_final_create(crypto_sign_state *state, + unsigned char *sig, + unsigned long long *siglen_p, + const unsigned char *sk); + */ + +static +ERL_NIF_TERM enif_crypto_sign_final_create(ErlNifEnv* env, int argc, ERL_NIF_TERM const argv[]) { + ErlNifBinary sk, sig; + + void *state; + + unsigned long long siglen; + + if( (argc != 2) || + (!enif_get_resource(env, argv[0], sign_state_type, (void **)&state)) || + (!enif_inspect_binary(env, argv[1], &sk)) ) { + return enif_make_badarg(env); + } + + if( sk.size != crypto_sign_SECRETKEYBYTES ) { + return enif_make_badarg(env); + } + + if( !enif_alloc_binary(crypto_sign_BYTES, &sig) ) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if( 0 != crypto_sign_final_create(state, sig.data, &siglen, sk.data) ) { + enif_release_binary(&sig); + return nacl_error_tuple(env, "sign_error"); + } + + ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret = enif_make_binary(env, &sig); + + return enif_make_tuple2(env, ok, ret); +} + +/* + int crypto_sign_final_verify(crypto_sign_state *state, + unsigned char *sig, + const unsigned char *pk); + */ + +static +ERL_NIF_TERM enif_crypto_sign_final_verify(ErlNifEnv* env, int argc, ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sig; + + void *state; + + if( (argc != 3) || + (!enif_get_resource(env, argv[0], sign_state_type, (void **)&state)) || + (!enif_inspect_binary(env, argv[1], &sig)) || + (!enif_inspect_binary(env, argv[2], &pk)) ) { + return enif_make_badarg(env); + } + + if( pk.size != crypto_sign_PUBLICKEYBYTES ) { + return enif_make_badarg(env); + } + + if( 0 == crypto_sign_final_verify(state, sig.data, pk.data) ) { + return enif_make_atom(env, ATOM_OK); + } + + return nacl_error_tuple(env, "failed_verification"); +} + + /* Sealed box functions */ static @@ -1675,6 +1814,11 @@ static ErlNifFunc nif_funcs[] = { erl_nif_dirty_job_cpu_bound_macro("crypto_sign_detached", 2, enif_crypto_sign_detached), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_verify_detached", 3, enif_crypto_sign_verify_detached), + {"crypto_sign_init", 0, enif_crypto_sign_init}, + {"crypto_sign_update", 2, enif_crypto_sign_update}, + erl_nif_dirty_job_cpu_bound_macro("crypto_sign_final_create", 2, enif_crypto_sign_final_create), + erl_nif_dirty_job_cpu_bound_macro("crypto_sign_final_verify", 3, enif_crypto_sign_final_verify), + {"crypto_box_SEALBYTES", 0, enif_crypto_box_SEALBYTES}, erl_nif_dirty_job_cpu_bound_macro("crypto_box_seal", 2, enif_crypto_box_seal), diff --git a/src/enacl.erl b/src/enacl.erl index 15ea2c2..7af1790 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -39,6 +39,11 @@ sign_detached/2, sign_verify_detached/3, + sign_init/0, + sign_update/2, + sign_final_create/2, + sign_final_verify/3, + %% EQC box_seal/2, box_seal_open/3 @@ -579,6 +584,47 @@ sign_verify_detached(SIG, M, PK) -> false -> {error, failed_verification} end. +-type sign_state() :: {signstate, reference()}. + +%% @doc sign_init/0 initialize a multi-part signature state. +%% +%% This state must be passed to all future calls to `sign_update/2`, +%% `sign_final_create/2` and `sign_final_verify/3`. +%% @end +-spec sign_init() -> sign_state(). +sign_init() -> + enacl_nif:crypto_sign_init(). + +%% @doc sign_update/2 update the signature state `S` with a new chunk of data `M`. +%% @end +-spec sign_update(S, M) -> sign_state() | {error, sign_update_error} + when S :: sign_state(), + M :: iodata(). +sign_update({signstate, SignState}, M) -> + enacl_nif:crypto_sign_update(SignState, M). + + +%% @doc sign_final_create/2 computes the signature for the previously supplied +%% message(s) using the secret key `SK`. +%% @end +-spec sign_final_create(S, SK) -> {ok, binary()} | {error, atom()} + when S :: sign_state(), + SK :: iodata(). +sign_final_create({signstate, SignState}, SK) -> + enacl_nif:crypto_sign_final_create(SignState, SK). + +%% @doc sign_final_verify/3 verify a chunked signature +%% +%% Verifies that `SIG` is a valid signature for the message whose content has +%% been previously supplied using `sign_update/2` using the public key `PK.` +%% @end +-spec sign_final_verify(S, SIG, PK) -> ok | {error, failed_verification} + when S :: sign_state(), + SIG :: binary(), + PK :: iodata(). +sign_final_verify({signstate, SignState}, SIG, PK) -> + enacl_nif:crypto_sign_final_verify(SignState, SIG, PK). + %% @private -spec box_secret_key_bytes() -> pos_integer(). box_secret_key_bytes() -> diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 798ef53..c6a9771 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -34,6 +34,11 @@ crypto_sign_detached/2, crypto_sign_verify_detached/3, + crypto_sign_init/0, + crypto_sign_update/2, + crypto_sign_final_create/2, + crypto_sign_final_verify/3, + crypto_box_seal/2, crypto_box_seal_open/3, crypto_box_SEALBYTES/0 @@ -220,6 +225,11 @@ crypto_sign_detached(_M, _SK) -> erlang:nif_error(nif_not_loaded). crypto_sign_verify_detached(_Sig, _M, _PK) -> erlang:nif_error(nif_not_loaded). +crypto_sign_init() -> erlang:nif_error(nif_not_loaded). +crypto_sign_update(_S, _M) -> erlang:nif_error(nif_not_loaded). +crypto_sign_final_create(_S, _SK) -> erlang:nif_error(nif_not_loaded). +crypto_sign_final_verify(_S, _S, _PK) -> erlang:nif_error(nif_not_loaded). + crypto_box_seal(_Msg, _PK) -> erlang:nif_error(nif_not_loaded). crypto_box_seal_open(_CipherText, _PK, _SK) -> erlang:nif_error(nif_not_loaded). crypto_box_SEALBYTES() -> erlang:nif_error(nif_not_loaded). From 885bc16374f265bd968268408b4849c2766ee390 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 14 Jan 2020 13:08:56 +0100 Subject: [PATCH 012/162] Drop in a nix shell for easier handling. --- shell.nix | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 shell.nix diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..a59c99b --- /dev/null +++ b/shell.nix @@ -0,0 +1,16 @@ +{ pkgs ? import {} }: + +with pkgs; + +let + inherit (lib) optional optionals; + + erlang_wx = erlangR22.override { + wxSupport = true; + }; +in + +mkShell { + buildInputs = [ erlang_wx git libsodium ] + ++ optional stdenv.isLinux inotify-tools; +} \ No newline at end of file From e66855c0295f07a551bab150ea0bab447bc1ac76 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 15 Jan 2020 13:21:51 +0100 Subject: [PATCH 013/162] Use LLVM style C-formattting --- c_src/enacl_nif.c | 2288 +++++++++++++++++++++++---------------------- 1 file changed, 1151 insertions(+), 1137 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 1497215..4eb5d2b 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -12,27 +12,32 @@ #define CRYPTO_GENERICHASH_STATE_RESOURCE "crypto_generichash_state" #ifdef ERL_NIF_DIRTY_JOB_CPU_BOUND -#define erl_nif_dirty_job_cpu_bound_macro(a,b,c) {a,b,c,ERL_NIF_DIRTY_JOB_CPU_BOUND} +#define erl_nif_dirty_job_cpu_bound_macro(a, b, c) \ + { a, b, c, ERL_NIF_DIRTY_JOB_CPU_BOUND } #else -#define erl_nif_dirty_job_cpu_bound_macro(a,b,c) {a,b,c} +#define erl_nif_dirty_job_cpu_bound_macro(a, b, c) \ + { a, b, c } #endif -//{"crypto_box_keypair", 0, enif_crypto_box_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND} +//{"crypto_box_keypair", 0, enif_crypto_box_keypair, +// ERL_NIF_DIRTY_JOB_CPU_BOUND} /* Errors */ /* This is a global variable for resource type */ static ErlNifResourceType *generichash_state_type = NULL; -static -ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) { - return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, error_atom)); +static ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) { + return enif_make_tuple2(env, enif_make_atom(env, "error"), + enif_make_atom(env, error_atom)); } /* Initialization */ -static -int enif_crypto_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info) { - // Create a new resource type for crypto_generichash_state - if( !(generichash_state_type = enif_open_resource_type(env, NULL, CRYPTO_GENERICHASH_STATE_RESOURCE, NULL, ERL_NIF_RT_CREATE, NULL)) ) { +static int enif_crypto_load(ErlNifEnv *env, void **priv_data, + ERL_NIF_TERM load_info) { + // Create a new resource type for crypto_generichash_state + if (!(generichash_state_type = enif_open_resource_type( + env, NULL, CRYPTO_GENERICHASH_STATE_RESOURCE, NULL, + ERL_NIF_RT_CREATE, NULL))) { return -1; } @@ -40,462 +45,456 @@ int enif_crypto_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info) { } /* Low-level functions (Hashing, String Equality, ...) */ +static ERL_NIF_TERM enif_crypto_hash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary input; + ErlNifBinary result; -static -ERL_NIF_TERM enif_crypto_hash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary input; - ErlNifBinary result; + if ((argc != 1) || (!enif_inspect_iolist_as_binary(env, argv[0], &input))) { + return enif_make_badarg(env); + } - if ((argc != 1) || (!enif_inspect_iolist_as_binary(env, argv[0], &input))) { - return enif_make_badarg(env); - } + if (!enif_alloc_binary(crypto_hash_BYTES, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (!enif_alloc_binary(crypto_hash_BYTES, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } + crypto_hash(result.data, input.data, input.size); - crypto_hash(result.data, input.data, input.size); - - return enif_make_binary(env, &result); + return enif_make_binary(env, &result); } -static -ERL_NIF_TERM enif_crypto_verify_16(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary x,y; +static ERL_NIF_TERM enif_crypto_verify_16(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary x, y; - if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &x)) - || (!enif_inspect_binary(env, argv[1], &y))) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &x)) || + (!enif_inspect_binary(env, argv[1], &y))) { + return enif_make_badarg(env); + } - if (x.size != 16 || y.size != 16) { - return enif_make_badarg(env); - } + if (x.size != 16 || y.size != 16) { + return enif_make_badarg(env); + } - if (0 == crypto_verify_16(x.data, y.data)) { - return enif_make_atom(env, "true"); - } else { - return enif_make_atom(env, "false"); - } + if (0 == crypto_verify_16(x.data, y.data)) { + return enif_make_atom(env, "true"); + } else { + return enif_make_atom(env, "false"); + } } -static -ERL_NIF_TERM enif_crypto_verify_32(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary x,y; +static ERL_NIF_TERM enif_crypto_verify_32(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary x, y; - if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &x)) - || (!enif_inspect_binary(env, argv[1], &y))) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &x)) || + (!enif_inspect_binary(env, argv[1], &y))) { + return enif_make_badarg(env); + } - if (x.size != 32 || y.size != 32) { - return enif_make_badarg(env); - } + if (x.size != 32 || y.size != 32) { + return enif_make_badarg(env); + } - if (0 == crypto_verify_32(x.data, y.data)) { - return enif_make_atom(env, "true"); - } else { - return enif_make_atom(env, "false"); - } + if (0 == crypto_verify_32(x.data, y.data)) { + return enif_make_atom(env, "true"); + } else { + return enif_make_atom(env, "false"); + } } -/* This is very unsafe. It will not affect things that have been binary_copy()'ed - Use this for destroying key material from ram but nothing more. Be careful! */ -static -ERL_NIF_TERM enif_sodium_memzero(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary x; +/* This is very unsafe. It will not affect things that have been + binary_copy()'ed Use this for destroying key material from ram but nothing + more. Be careful! */ +static ERL_NIF_TERM enif_sodium_memzero(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary x; - if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &x))) { - return enif_make_badarg(env); - } + if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &x))) { + return enif_make_badarg(env); + } - sodium_memzero(x.data,x.size); + sodium_memzero(x.data, x.size); return enif_make_atom(env, "ok"); } /* Curve 25519 */ -static -ERL_NIF_TERM enif_crypto_curve25519_scalarmult(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ERL_NIF_TERM result; - ErlNifBinary secret, basepoint, output; - uint8_t bp[crypto_scalarmult_curve25519_BYTES]; +static ERL_NIF_TERM +enif_crypto_curve25519_scalarmult(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ERL_NIF_TERM result; + ErlNifBinary secret, basepoint, output; + uint8_t bp[crypto_scalarmult_curve25519_BYTES]; - if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &secret)) - || (!enif_inspect_binary(env, argv[1], &basepoint)) - || (secret.size != crypto_scalarmult_curve25519_BYTES) - || (basepoint.size != crypto_scalarmult_curve25519_BYTES)) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &secret)) || + (!enif_inspect_binary(env, argv[1], &basepoint)) || + (secret.size != crypto_scalarmult_curve25519_BYTES) || + (basepoint.size != crypto_scalarmult_curve25519_BYTES)) { + return enif_make_badarg(env); + } - memcpy(bp, basepoint.data, crypto_scalarmult_curve25519_BYTES); + memcpy(bp, basepoint.data, crypto_scalarmult_curve25519_BYTES); - /* Clear the high-bit. Better safe than sorry. */ - bp[31] &= 0x7f; + /* Clear the high-bit. Better safe than sorry. */ + bp[31] &= 0x7f; - do - { - if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) { - result = nacl_error_tuple(env, "alloc_failed"); - continue; - } + do { + if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) { + result = nacl_error_tuple(env, "alloc_failed"); + continue; + } - if (crypto_scalarmult_curve25519(output.data, secret.data, bp) < 0) { - result = nacl_error_tuple(env, "scalarmult_curve25519_failed"); - continue; - } + if (crypto_scalarmult_curve25519(output.data, secret.data, bp) < 0) { + result = nacl_error_tuple(env, "scalarmult_curve25519_failed"); + continue; + } - result = enif_make_binary(env, &output); - } while (0); + result = enif_make_binary(env, &output); + } while (0); - sodium_memzero(bp, crypto_scalarmult_curve25519_BYTES); + sodium_memzero(bp, crypto_scalarmult_curve25519_BYTES); - return result; + return result; } -static -ERL_NIF_TERM enif_crypto_curve25519_scalarmult_base(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ERL_NIF_TERM result; - ErlNifBinary secret, output; +static ERL_NIF_TERM +enif_crypto_curve25519_scalarmult_base(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ERL_NIF_TERM result; + ErlNifBinary secret, output; - if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &secret)) - || (secret.size != crypto_scalarmult_curve25519_BYTES)) { - return enif_make_badarg(env); - } + if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &secret)) || + (secret.size != crypto_scalarmult_curve25519_BYTES)) { + return enif_make_badarg(env); + } - do - { - if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) { - result = nacl_error_tuple(env, "alloc_failed"); - continue; - } + do { + if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) { + result = nacl_error_tuple(env, "alloc_failed"); + continue; + } - if (crypto_scalarmult_curve25519_base(output.data, secret.data) < 0) { - result = nacl_error_tuple(env, "scalarmult_curve25519_base_failed"); - continue; - } + if (crypto_scalarmult_curve25519_base(output.data, secret.data) < 0) { + result = nacl_error_tuple(env, "scalarmult_curve25519_base_failed"); + continue; + } - result = enif_make_binary(env, &output); - } while (0); + result = enif_make_binary(env, &output); + } while (0); - return result; + return result; } /* Ed 25519 */ -static -ERL_NIF_TERM enif_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sk; +static ERL_NIF_TERM +enif_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk; - if (argc != 0) { - return enif_make_badarg(env); - } + if (argc != 0) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (!enif_alloc_binary(crypto_sign_ed25519_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_sign_ed25519_SECRETKEYBYTES, &sk)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_sign_ed25519_keypair(pk.data, sk.data); + crypto_sign_ed25519_keypair(pk.data, sk.data); - return enif_make_tuple2(env, enif_make_binary(env, &pk), enif_make_binary(env, &sk)); + return enif_make_tuple2(env, enif_make_binary(env, &pk), + enif_make_binary(env, &sk)); } -static -ERL_NIF_TERM enif_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary curve25519_pk, ed25519_pk; +static ERL_NIF_TERM +enif_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary curve25519_pk, ed25519_pk; - if ((argc != 1) - || (!enif_inspect_binary(env, argv[0], &ed25519_pk)) - || (ed25519_pk.size != crypto_sign_ed25519_PUBLICKEYBYTES)) { - return enif_make_badarg(env); - } + if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &ed25519_pk)) || + (ed25519_pk.size != crypto_sign_ed25519_PUBLICKEYBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (crypto_sign_ed25519_pk_to_curve25519(curve25519_pk.data, ed25519_pk.data) != 0) { - return nacl_error_tuple(env, "ed25519_public_to_curve25519_failed"); - } + if (crypto_sign_ed25519_pk_to_curve25519(curve25519_pk.data, + ed25519_pk.data) != 0) { + return nacl_error_tuple(env, "ed25519_public_to_curve25519_failed"); + } - return enif_make_binary(env, &curve25519_pk); + return enif_make_binary(env, &curve25519_pk); } -static -ERL_NIF_TERM enif_crypto_sign_ed25519_secret_to_curve25519(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary curve25519_sk, ed25519_sk; +static ERL_NIF_TERM +enif_crypto_sign_ed25519_secret_to_curve25519(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary curve25519_sk, ed25519_sk; - if ((argc != 1) - || (!enif_inspect_binary(env, argv[0], &ed25519_sk)) - || (ed25519_sk.size != crypto_sign_ed25519_SECRETKEYBYTES)) { - return enif_make_badarg(env); - } + if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &ed25519_sk)) || + (ed25519_sk.size != crypto_sign_ed25519_SECRETKEYBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_sk)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_sk)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (crypto_sign_ed25519_sk_to_curve25519(curve25519_sk.data, ed25519_sk.data) != 0) { - return nacl_error_tuple(env, "ed25519_secret_to_curve25519_failed"); - } + if (crypto_sign_ed25519_sk_to_curve25519(curve25519_sk.data, + ed25519_sk.data) != 0) { + return nacl_error_tuple(env, "ed25519_secret_to_curve25519_failed"); + } - return enif_make_binary(env, &curve25519_sk); + return enif_make_binary(env, &curve25519_sk); } -static -ERL_NIF_TERM enif_crypto_sign_ed25519_PUBLICKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_sign_ed25519_PUBLICKEYBYTES); +static ERL_NIF_TERM +enif_crypto_sign_ed25519_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_sign_ed25519_PUBLICKEYBYTES); } -static -ERL_NIF_TERM enif_crypto_sign_ed25519_SECRETKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_sign_ed25519_SECRETKEYBYTES); +static ERL_NIF_TERM +enif_crypto_sign_ed25519_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_sign_ed25519_SECRETKEYBYTES); } /* Public-key cryptography */ -static -ERL_NIF_TERM enif_crypto_box_NONCEBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_NONCEBYTES); +static ERL_NIF_TERM enif_crypto_box_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_NONCEBYTES); } -static -ERL_NIF_TERM enif_crypto_box_ZEROBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_ZEROBYTES); +static ERL_NIF_TERM enif_crypto_box_ZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_ZEROBYTES); } -static -ERL_NIF_TERM enif_crypto_box_BOXZEROBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_BOXZEROBYTES); +static ERL_NIF_TERM enif_crypto_box_BOXZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_BOXZEROBYTES); } -static -ERL_NIF_TERM enif_crypto_box_PUBLICKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_PUBLICKEYBYTES); +static ERL_NIF_TERM enif_crypto_box_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_PUBLICKEYBYTES); } -static -ERL_NIF_TERM enif_crypto_box_SECRETKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_SECRETKEYBYTES); +static ERL_NIF_TERM enif_crypto_box_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_SECRETKEYBYTES); } -static -ERL_NIF_TERM enif_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_BEFORENMBYTES); +static ERL_NIF_TERM enif_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_BEFORENMBYTES); } -static -ERL_NIF_TERM enif_crypto_box_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sk; +static ERL_NIF_TERM enif_crypto_box_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk; - if (argc != 0) { - return enif_make_badarg(env); - } + if (argc != 0) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_box_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_box_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (!enif_alloc_binary(crypto_box_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_box_SECRETKEYBYTES, &sk)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_box_keypair(pk.data, sk.data); + crypto_box_keypair(pk.data, sk.data); - return enif_make_tuple2(env, enif_make_binary(env, &pk), enif_make_binary(env, &sk)); + return enif_make_tuple2(env, enif_make_binary(env, &pk), + enif_make_binary(env, &sk)); } -static -ERL_NIF_TERM enif_crypto_box(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary padded_msg, nonce, pk, sk, result; +static ERL_NIF_TERM enif_crypto_box(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary padded_msg, nonce, pk, sk, result; - if ( - (argc != 4) || - (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &pk)) || - (!enif_inspect_binary(env, argv[3], &sk))) { - return enif_make_badarg(env); - } + if ((argc != 4) || + (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &pk)) || + (!enif_inspect_binary(env, argv[3], &sk))) { + return enif_make_badarg(env); + } - if ( - (nonce.size != crypto_box_NONCEBYTES) || - (pk.size != crypto_box_PUBLICKEYBYTES) || - (sk.size != crypto_box_SECRETKEYBYTES) || - (padded_msg.size < crypto_box_ZEROBYTES)) { - return enif_make_badarg(env); - } + if ((nonce.size != crypto_box_NONCEBYTES) || + (pk.size != crypto_box_PUBLICKEYBYTES) || + (sk.size != crypto_box_SECRETKEYBYTES) || + (padded_msg.size < crypto_box_ZEROBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(padded_msg.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(padded_msg.size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if( 0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data, pk.data, sk.data) ) { - return nacl_error_tuple(env, "box_error"); - } + if (0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data, + pk.data, sk.data)) { + return nacl_error_tuple(env, "box_error"); + } - return enif_make_sub_binary( - env, - enif_make_binary(env, &result), - crypto_box_BOXZEROBYTES, - padded_msg.size - crypto_box_BOXZEROBYTES); + return enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_BOXZEROBYTES, + padded_msg.size - crypto_box_BOXZEROBYTES); } -static -ERL_NIF_TERM enif_crypto_box_open(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary padded_ciphertext, nonce, pk, sk, result; +static ERL_NIF_TERM enif_crypto_box_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary padded_ciphertext, nonce, pk, sk, result; - if ( - (argc != 4) || - (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &pk)) || - (!enif_inspect_binary(env, argv[3], &sk))) { - return enif_make_badarg(env); - } + if ((argc != 4) || + (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &pk)) || + (!enif_inspect_binary(env, argv[3], &sk))) { + return enif_make_badarg(env); + } - if ( - (nonce.size != crypto_box_NONCEBYTES) || - (pk.size != crypto_box_PUBLICKEYBYTES) || - (sk.size != crypto_box_SECRETKEYBYTES) || - (padded_ciphertext.size < crypto_box_BOXZEROBYTES)) { - return enif_make_badarg(env); - } + if ((nonce.size != crypto_box_NONCEBYTES) || + (pk.size != crypto_box_PUBLICKEYBYTES) || + (sk.size != crypto_box_SECRETKEYBYTES) || + (padded_ciphertext.size < crypto_box_BOXZEROBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(padded_ciphertext.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(padded_ciphertext.size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (0 != crypto_box_open(result.data, padded_ciphertext.data, padded_ciphertext.size, nonce.data, pk.data, sk.data)) { - enif_release_binary(&result); - return nacl_error_tuple(env, "failed_verification"); - } + if (0 != crypto_box_open(result.data, padded_ciphertext.data, + padded_ciphertext.size, nonce.data, pk.data, + sk.data)) { + enif_release_binary(&result); + return nacl_error_tuple(env, "failed_verification"); + } - return enif_make_sub_binary( - env, - enif_make_binary(env, &result), - crypto_box_ZEROBYTES, - padded_ciphertext.size - crypto_box_ZEROBYTES); + return enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_ZEROBYTES, + padded_ciphertext.size - crypto_box_ZEROBYTES); } /* Precomputed crypto boxes */ -static -ERL_NIF_TERM enif_crypto_box_beforenm(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary k, pk, sk; +static ERL_NIF_TERM enif_crypto_box_beforenm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary k, pk, sk; - if ( - (argc != 2) || - (!enif_inspect_binary(env, argv[0], &pk)) || - (!enif_inspect_binary(env, argv[1], &sk)) || - (pk.size != crypto_box_PUBLICKEYBYTES) || - (sk.size != crypto_box_SECRETKEYBYTES)) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &pk)) || + (!enif_inspect_binary(env, argv[1], &sk)) || + (pk.size != crypto_box_PUBLICKEYBYTES) || + (sk.size != crypto_box_SECRETKEYBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_box_BEFORENMBYTES, &k)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_box_BEFORENMBYTES, &k)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if( 0 != crypto_box_beforenm(k.data, pk.data, sk.data) ) { - // error - return nacl_error_tuple(env, "error_gen_shared_secret"); - } + if (0 != crypto_box_beforenm(k.data, pk.data, sk.data)) { + // error + return nacl_error_tuple(env, "error_gen_shared_secret"); + } - return enif_make_binary(env, &k); + return enif_make_binary(env, &k); } -static -ERL_NIF_TERM enif_crypto_box_afternm(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary result, m, nonce, k; +static ERL_NIF_TERM enif_crypto_box_afternm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary result, m, nonce, k; - if ( - (argc != 3) || - (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &k)) || - (m.size < crypto_box_ZEROBYTES) || - (nonce.size != crypto_box_NONCEBYTES) || - (k.size != crypto_box_BEFORENMBYTES)) { - return enif_make_badarg(env); - } + if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &k)) || + (m.size < crypto_box_ZEROBYTES) || + (nonce.size != crypto_box_NONCEBYTES) || + (k.size != crypto_box_BEFORENMBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(m.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(m.size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data); + crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data); - return enif_make_sub_binary( - env, - enif_make_binary(env, &result), - crypto_box_BOXZEROBYTES, - m.size - crypto_box_BOXZEROBYTES); + return enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_BOXZEROBYTES, + m.size - crypto_box_BOXZEROBYTES); } -static -ERL_NIF_TERM enif_crypto_box_open_afternm(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary result, m, nonce, k; +static ERL_NIF_TERM enif_crypto_box_open_afternm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary result, m, nonce, k; - if ( - (argc != 3) || - (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &k)) || - (m.size < crypto_box_BOXZEROBYTES) || - (nonce.size != crypto_box_NONCEBYTES) || - (k.size != crypto_box_BEFORENMBYTES)) { - return enif_make_badarg(env); - } + if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &k)) || + (m.size < crypto_box_BOXZEROBYTES) || + (nonce.size != crypto_box_NONCEBYTES) || + (k.size != crypto_box_BEFORENMBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(m.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(m.size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (0 != crypto_box_open_afternm(result.data, m.data, m.size, nonce.data, k.data)) { - enif_release_binary(&result); - return nacl_error_tuple(env, "failed_verification"); - } + if (0 != crypto_box_open_afternm(result.data, m.data, m.size, nonce.data, + k.data)) { + enif_release_binary(&result); + return nacl_error_tuple(env, "failed_verification"); + } - return enif_make_sub_binary( - env, - enif_make_binary(env, &result), - crypto_box_ZEROBYTES, - m.size - crypto_box_ZEROBYTES); + return enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_ZEROBYTES, + m.size - crypto_box_ZEROBYTES); } /* Signing */ -static -ERL_NIF_TERM enif_crypto_sign_PUBLICKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_sign_PUBLICKEYBYTES); +static ERL_NIF_TERM enif_crypto_sign_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_sign_PUBLICKEYBYTES); } -static -ERL_NIF_TERM enif_crypto_sign_SECRETKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_sign_SECRETKEYBYTES); +static ERL_NIF_TERM enif_crypto_sign_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_sign_SECRETKEYBYTES); } -static -ERL_NIF_TERM enif_crypto_sign_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sk; +static ERL_NIF_TERM enif_crypto_sign_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk; - if (argc != 0) { - return enif_make_badarg(env); - } + if (argc != 0) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_sign_keypair(pk.data, sk.data); + crypto_sign_keypair(pk.data, sk.data); - return enif_make_tuple2(env, enif_make_binary(env, &pk), enif_make_binary(env, &sk)); + return enif_make_tuple2(env, enif_make_binary(env, &pk), + enif_make_binary(env, &sk)); } /* @@ -503,29 +502,27 @@ int crypto_sign(unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen, const unsigned char *sk); */ -static -ERL_NIF_TERM enif_crypto_sign(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary m, sk, sm; - unsigned long long smlen; +static ERL_NIF_TERM enif_crypto_sign(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary m, sk, sm; + unsigned long long smlen; - if ( - (argc != 2) || - (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &sk))) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &sk))) { + return enif_make_badarg(env); + } - if (sk.size != crypto_sign_SECRETKEYBYTES) { - return enif_make_badarg(env); - } + if (sk.size != crypto_sign_SECRETKEYBYTES) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(m.size + crypto_sign_BYTES, &sm)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(m.size + crypto_sign_BYTES, &sm)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_sign(sm.data, &smlen, m.data, m.size, sk.data); + crypto_sign(sm.data, &smlen, m.data, m.size, sk.data); - return enif_make_sub_binary(env, enif_make_binary(env, &sm), 0, smlen); + return enif_make_sub_binary(env, enif_make_binary(env, &sm), 0, smlen); } /* @@ -533,32 +530,30 @@ int crypto_sign_open(unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk); */ -static -ERL_NIF_TERM enif_crypto_sign_open(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary m, sm, pk; - unsigned long long mlen; +static ERL_NIF_TERM enif_crypto_sign_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary m, sm, pk; + unsigned long long mlen; - if ( - (argc != 2) || - (!enif_inspect_iolist_as_binary(env, argv[0], &sm)) || - (!enif_inspect_binary(env, argv[1], &pk))) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &sm)) || + (!enif_inspect_binary(env, argv[1], &pk))) { + return enif_make_badarg(env); + } - if (pk.size != crypto_sign_PUBLICKEYBYTES) { - return enif_make_badarg(env); - } + if (pk.size != crypto_sign_PUBLICKEYBYTES) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(sm.size, &m)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(sm.size, &m)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (0 == crypto_sign_open(m.data, &mlen, sm.data, sm.size, pk.data)) { - return enif_make_sub_binary(env, enif_make_binary(env, &m), 0, mlen); - } else { - enif_release_binary(&m); - return nacl_error_tuple(env, "failed_verification"); - } + if (0 == crypto_sign_open(m.data, &mlen, sm.data, sm.size, pk.data)) { + return enif_make_sub_binary(env, enif_make_binary(env, &m), 0, mlen); + } else { + enif_release_binary(&m); + return nacl_error_tuple(env, "failed_verification"); + } } /* @@ -566,29 +561,27 @@ int crypto_sign_detached(unsigned char *sig, unsigned long long *siglen, const unsigned char *m, unsigned long long mlen, const unsigned char *sk); */ -static -ERL_NIF_TERM enif_crypto_sign_detached(ErlNifEnv* env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary m, sk, sig; - unsigned long long siglen; +static ERL_NIF_TERM enif_crypto_sign_detached(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary m, sk, sig; + unsigned long long siglen; - if ( - (argc != 2) || - (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &sk))) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &sk))) { + return enif_make_badarg(env); + } - if (sk.size != crypto_sign_SECRETKEYBYTES) { - return enif_make_badarg(env); - } + if (sk.size != crypto_sign_SECRETKEYBYTES) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_sign_detached(sig.data, &siglen, m.data, m.size, sk.data); + crypto_sign_detached(sig.data, &siglen, m.data, m.size, sk.data); - return enif_make_binary(env, &sig); + return enif_make_binary(env, &sig); } /* @@ -597,743 +590,705 @@ int crypto_sign_verify_detached(const unsigned char *sig, unsigned long long mlen, const unsigned char *pk); */ -static -ERL_NIF_TERM enif_crypto_sign_verify_detached(ErlNifEnv* env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary m, sig, pk; +static ERL_NIF_TERM +enif_crypto_sign_verify_detached(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary m, sig, pk; - if ( - (argc != 3) || - (!enif_inspect_binary(env, argv[0], &sig)) || - (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || - (!enif_inspect_binary(env, argv[2], &pk))) { - return enif_make_badarg(env); - } + if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &sig)) || + (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || + (!enif_inspect_binary(env, argv[2], &pk))) { + return enif_make_badarg(env); + } - if (pk.size != crypto_sign_PUBLICKEYBYTES) { - return enif_make_badarg(env); - } + if (pk.size != crypto_sign_PUBLICKEYBYTES) { + return enif_make_badarg(env); + } - if (0 == crypto_sign_verify_detached(sig.data, m.data, m.size, pk.data)) { - return enif_make_atom(env, "true"); - } else { - return enif_make_atom(env, "false"); - } + if (0 == crypto_sign_verify_detached(sig.data, m.data, m.size, pk.data)) { + return enif_make_atom(env, "true"); + } else { + return enif_make_atom(env, "false"); + } } /* Sealed box functions */ -static -ERL_NIF_TERM enif_crypto_box_SEALBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_SEALBYTES); +static ERL_NIF_TERM enif_crypto_box_SEALBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_SEALBYTES); } -static -ERL_NIF_TERM enif_crypto_box_seal(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary key, msg, ciphertext; +static ERL_NIF_TERM enif_crypto_box_seal(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary key, msg, ciphertext; - if ( - (argc != 2) || - (!enif_inspect_iolist_as_binary(env, argv[0], &msg)) || - (!enif_inspect_binary(env, argv[1], &key))) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &msg)) || + (!enif_inspect_binary(env, argv[1], &key))) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(msg.size + crypto_box_SEALBYTES, &ciphertext)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(msg.size + crypto_box_SEALBYTES, &ciphertext)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_box_seal( - ciphertext.data, - msg.data, - msg.size, - key.data); + crypto_box_seal(ciphertext.data, msg.data, msg.size, key.data); - return enif_make_binary(env, &ciphertext); + return enif_make_binary(env, &ciphertext); } +static ERL_NIF_TERM enif_crypto_box_seal_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk, ciphertext, msg; -static -ERL_NIF_TERM enif_crypto_box_seal_open(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sk, ciphertext, msg; + if ((argc != 3) || + (!enif_inspect_iolist_as_binary(env, argv[0], &ciphertext)) || + (!enif_inspect_binary(env, argv[1], &pk)) || + (!enif_inspect_binary(env, argv[2], &sk))) { + return enif_make_badarg(env); + } - if ( - (argc != 3) || - (!enif_inspect_iolist_as_binary(env, argv[0], &ciphertext)) || - (!enif_inspect_binary(env, argv[1], &pk)) || - (!enif_inspect_binary(env, argv[2], &sk))) { - return enif_make_badarg(env); - } + if (ciphertext.size < crypto_box_SEALBYTES) { + return enif_make_badarg(env); + } - if (ciphertext.size < crypto_box_SEALBYTES) { - return enif_make_badarg(env); - } + if (!enif_alloc_binary(ciphertext.size - crypto_box_SEALBYTES, &msg)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (!enif_alloc_binary(ciphertext.size - crypto_box_SEALBYTES, &msg)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (crypto_box_seal_open(msg.data, ciphertext.data, ciphertext.size, pk.data, + sk.data) != 0) { + enif_release_binary(&msg); + return nacl_error_tuple(env, "failed_verification"); + } - if (crypto_box_seal_open( - msg.data, - ciphertext.data, - ciphertext.size, - pk.data, - sk.data) != 0) { - enif_release_binary(&msg); - return nacl_error_tuple(env, "failed_verification"); - } - - return enif_make_binary(env, &msg); + return enif_make_binary(env, &msg); } /* Secret key cryptography */ -static -ERL_NIF_TERM enif_crypto_secretbox_NONCEBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_secretbox_NONCEBYTES); +static ERL_NIF_TERM +enif_crypto_secretbox_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_secretbox_NONCEBYTES); } -static -ERL_NIF_TERM enif_crypto_secretbox_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_secretbox_KEYBYTES); +static ERL_NIF_TERM enif_crypto_secretbox_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_secretbox_KEYBYTES); } -static -ERL_NIF_TERM enif_crypto_secretbox_ZEROBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_secretbox_ZEROBYTES); +static ERL_NIF_TERM enif_crypto_secretbox_ZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_secretbox_ZEROBYTES); } -static -ERL_NIF_TERM enif_crypto_secretbox_BOXZEROBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_secretbox_BOXZEROBYTES); +static ERL_NIF_TERM +enif_crypto_secretbox_BOXZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_secretbox_BOXZEROBYTES); } -static -ERL_NIF_TERM enif_crypto_stream_chacha20_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_stream_chacha20_KEYBYTES); +static ERL_NIF_TERM +enif_crypto_stream_chacha20_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_stream_chacha20_KEYBYTES); } -static -ERL_NIF_TERM enif_crypto_stream_chacha20_NONCEBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_stream_chacha20_NONCEBYTES); +static ERL_NIF_TERM +enif_crypto_stream_chacha20_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_stream_chacha20_NONCEBYTES); } -static -ERL_NIF_TERM enif_crypto_stream_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_stream_KEYBYTES); +static ERL_NIF_TERM enif_crypto_stream_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_stream_KEYBYTES); } -static -ERL_NIF_TERM enif_crypto_stream_NONCEBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_stream_NONCEBYTES); +static ERL_NIF_TERM enif_crypto_stream_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_stream_NONCEBYTES); } -static -ERL_NIF_TERM enif_crypto_auth_BYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_auth_BYTES); +static ERL_NIF_TERM enif_crypto_auth_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_auth_BYTES); } -static -ERL_NIF_TERM enif_crypto_auth_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_auth_KEYBYTES); +static ERL_NIF_TERM enif_crypto_auth_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_auth_KEYBYTES); } -static -ERL_NIF_TERM enif_crypto_shorthash_BYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_shorthash_BYTES); +static ERL_NIF_TERM enif_crypto_shorthash_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_shorthash_BYTES); } -static -ERL_NIF_TERM enif_crypto_shorthash_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_shorthash_KEYBYTES); +static ERL_NIF_TERM enif_crypto_shorthash_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_shorthash_KEYBYTES); } -static -ERL_NIF_TERM enif_crypto_onetimeauth_BYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_onetimeauth_BYTES); +static ERL_NIF_TERM enif_crypto_onetimeauth_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_onetimeauth_BYTES); } -static -ERL_NIF_TERM enif_crypto_onetimeauth_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_onetimeauth_KEYBYTES); +static ERL_NIF_TERM +enif_crypto_onetimeauth_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_onetimeauth_KEYBYTES); } -static -ERL_NIF_TERM enif_crypto_secretbox(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary key, nonce, padded_msg, padded_ciphertext; +static ERL_NIF_TERM enif_crypto_secretbox(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary key, nonce, padded_msg, padded_ciphertext; - if ( - (argc != 3) || - (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &key))) { - return enif_make_badarg(env); - } + if ((argc != 3) || + (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &key))) { + return enif_make_badarg(env); + } - if ( - (key.size != crypto_secretbox_KEYBYTES) || - (nonce.size != crypto_secretbox_NONCEBYTES) || - (padded_msg.size < crypto_secretbox_ZEROBYTES)) { - return enif_make_badarg(env); - } + if ((key.size != crypto_secretbox_KEYBYTES) || + (nonce.size != crypto_secretbox_NONCEBYTES) || + (padded_msg.size < crypto_secretbox_ZEROBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(padded_msg.size, &padded_ciphertext)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(padded_msg.size, &padded_ciphertext)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_secretbox( - padded_ciphertext.data, - padded_msg.data, padded_msg.size, - nonce.data, - key.data); + crypto_secretbox(padded_ciphertext.data, padded_msg.data, padded_msg.size, + nonce.data, key.data); - return enif_make_sub_binary(env, - enif_make_binary(env, &padded_ciphertext), - crypto_secretbox_BOXZEROBYTES, - padded_msg.size - crypto_secretbox_BOXZEROBYTES); + return enif_make_sub_binary(env, enif_make_binary(env, &padded_ciphertext), + crypto_secretbox_BOXZEROBYTES, + padded_msg.size - crypto_secretbox_BOXZEROBYTES); } -static -ERL_NIF_TERM enif_crypto_secretbox_open(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary key, nonce, padded_ciphertext, padded_msg; +static ERL_NIF_TERM enif_crypto_secretbox_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary key, nonce, padded_ciphertext, padded_msg; - if ( - (argc != 3) || - (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &key))) { - return enif_make_badarg(env); - } + if ((argc != 3) || + (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &key))) { + return enif_make_badarg(env); + } - if ( - (key.size != crypto_secretbox_KEYBYTES) || - (nonce.size != crypto_secretbox_NONCEBYTES) || - (padded_ciphertext.size < crypto_secretbox_BOXZEROBYTES)) { - return enif_make_badarg(env); - } + if ((key.size != crypto_secretbox_KEYBYTES) || + (nonce.size != crypto_secretbox_NONCEBYTES) || + (padded_ciphertext.size < crypto_secretbox_BOXZEROBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(padded_ciphertext.size, &padded_msg)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(padded_ciphertext.size, &padded_msg)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (crypto_secretbox_open( - padded_msg.data, - padded_ciphertext.data, - padded_ciphertext.size, - nonce.data, - key.data) != 0) { - enif_release_binary(&padded_msg); - return nacl_error_tuple(env, "failed_verification"); - } + if (crypto_secretbox_open(padded_msg.data, padded_ciphertext.data, + padded_ciphertext.size, nonce.data, + key.data) != 0) { + enif_release_binary(&padded_msg); + return nacl_error_tuple(env, "failed_verification"); + } - return enif_make_sub_binary( - env, - enif_make_binary(env, &padded_msg), - crypto_secretbox_ZEROBYTES, - padded_ciphertext.size - crypto_secretbox_ZEROBYTES); + return enif_make_sub_binary( + env, enif_make_binary(env, &padded_msg), crypto_secretbox_ZEROBYTES, + padded_ciphertext.size - crypto_secretbox_ZEROBYTES); } -static -ERL_NIF_TERM enif_crypto_stream_chacha20(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary c, n, k; - ErlNifUInt64 clen; +static ERL_NIF_TERM enif_crypto_stream_chacha20(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary c, n, k; + ErlNifUInt64 clen; - if ( - (argc != 3) || - (!enif_get_uint64(env, argv[0], &clen)) || - (!enif_inspect_binary(env, argv[1], &n)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } + if ((argc != 3) || (!enif_get_uint64(env, argv[0], &clen)) || + (!enif_inspect_binary(env, argv[1], &n)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } - if ( - (k.size != crypto_stream_chacha20_KEYBYTES) || - (n.size != crypto_stream_chacha20_NONCEBYTES)) { - return enif_make_badarg(env); - } + if ((k.size != crypto_stream_chacha20_KEYBYTES) || + (n.size != crypto_stream_chacha20_NONCEBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(clen, &c)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(clen, &c)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_stream_chacha20(c.data, c.size, n.data, k.data); + crypto_stream_chacha20(c.data, c.size, n.data, k.data); - return enif_make_binary(env, &c); + return enif_make_binary(env, &c); } -static -ERL_NIF_TERM enif_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary c, m, n, k; +static ERL_NIF_TERM enif_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary c, m, n, k; - if ( - (argc != 3) || - (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &n)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } + if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &n)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } - if ( - (k.size != crypto_stream_chacha20_KEYBYTES) || - (n.size != crypto_stream_chacha20_NONCEBYTES)) { - return enif_make_badarg(env); - } + if ((k.size != crypto_stream_chacha20_KEYBYTES) || + (n.size != crypto_stream_chacha20_NONCEBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(m.size, &c)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(m.size, &c)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_stream_chacha20_xor(c.data, m.data, m.size, n.data, k.data); + crypto_stream_chacha20_xor(c.data, m.data, m.size, n.data, k.data); - return enif_make_binary(env, &c); + return enif_make_binary(env, &c); } -static -ERL_NIF_TERM enif_crypto_stream(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary c, n, k; - ErlNifUInt64 clen; +static ERL_NIF_TERM enif_crypto_stream(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary c, n, k; + ErlNifUInt64 clen; - if ( - (argc != 3) || - (!enif_get_uint64(env, argv[0], &clen)) || - (!enif_inspect_binary(env, argv[1], &n)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } + if ((argc != 3) || (!enif_get_uint64(env, argv[0], &clen)) || + (!enif_inspect_binary(env, argv[1], &n)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } - if ( - (k.size != crypto_stream_KEYBYTES) || - (n.size != crypto_stream_NONCEBYTES)) { - return enif_make_badarg(env); - } + if ((k.size != crypto_stream_KEYBYTES) || + (n.size != crypto_stream_NONCEBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(clen, &c)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(clen, &c)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_stream(c.data, c.size, n.data, k.data); + crypto_stream(c.data, c.size, n.data, k.data); - return enif_make_binary(env, &c); + return enif_make_binary(env, &c); } -static -ERL_NIF_TERM enif_crypto_stream_xor(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary c, m, n, k; +static ERL_NIF_TERM enif_crypto_stream_xor(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary c, m, n, k; - if ( - (argc != 3) || - (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &n)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } + if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &n)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } - if ( - (k.size != crypto_stream_KEYBYTES) || - (n.size != crypto_stream_NONCEBYTES)) { - return enif_make_badarg(env); - } + if ((k.size != crypto_stream_KEYBYTES) || + (n.size != crypto_stream_NONCEBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(m.size, &c)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(m.size, &c)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_stream_xor(c.data, m.data, m.size, n.data, k.data); + crypto_stream_xor(c.data, m.data, m.size, n.data, k.data); - return enif_make_binary(env, &c); + return enif_make_binary(env, &c); } -static -ERL_NIF_TERM enif_crypto_auth(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary a,m,k; +static ERL_NIF_TERM enif_crypto_auth(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary a, m, k; - if ( - (argc != 2) || - (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &k))) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &k))) { + return enif_make_badarg(env); + } - if (k.size != crypto_auth_KEYBYTES) { - return enif_make_badarg(env); - } + if (k.size != crypto_auth_KEYBYTES) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_auth_BYTES, &a)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_auth_BYTES, &a)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_auth(a.data, m.data, m.size, k.data); + crypto_auth(a.data, m.data, m.size, k.data); - return enif_make_binary(env, &a); + return enif_make_binary(env, &a); } -static -ERL_NIF_TERM enif_crypto_auth_verify(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary a, m, k; +static ERL_NIF_TERM enif_crypto_auth_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary a, m, k; - if ( - (argc != 3) || - (!enif_inspect_binary(env, argv[0], &a)) || - (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } + if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &a)) || + (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } - if ( - (k.size != crypto_auth_KEYBYTES) || - (a.size != crypto_auth_BYTES)) { - return enif_make_badarg(env); - } + if ((k.size != crypto_auth_KEYBYTES) || (a.size != crypto_auth_BYTES)) { + return enif_make_badarg(env); + } - if (0 == crypto_auth_verify(a.data, m.data, m.size, k.data)) { - return enif_make_atom(env, "true"); - } else { - return enif_make_atom(env, "false"); - } + if (0 == crypto_auth_verify(a.data, m.data, m.size, k.data)) { + return enif_make_atom(env, "true"); + } else { + return enif_make_atom(env, "false"); + } } -static -ERL_NIF_TERM enif_crypto_shorthash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary a,m,k; +static ERL_NIF_TERM enif_crypto_shorthash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary a, m, k; - if ( - (argc != 2) || - (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &k))) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &k))) { + return enif_make_badarg(env); + } - if (k.size != crypto_shorthash_KEYBYTES) { - return enif_make_badarg(env); - } + if (k.size != crypto_shorthash_KEYBYTES) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_shorthash_BYTES, &a)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_shorthash_BYTES, &a)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_shorthash(a.data, m.data, m.size, k.data); + crypto_shorthash(a.data, m.data, m.size, k.data); - return enif_make_binary(env, &a); + return enif_make_binary(env, &a); } -static -ERL_NIF_TERM enif_crypto_onetimeauth(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary a,m,k; +static ERL_NIF_TERM enif_crypto_onetimeauth(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary a, m, k; - if ( - (argc != 2) || - (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &k))) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &k))) { + return enif_make_badarg(env); + } - if (k.size != crypto_onetimeauth_KEYBYTES) { - return enif_make_badarg(env); - } + if (k.size != crypto_onetimeauth_KEYBYTES) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_onetimeauth_BYTES, &a)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_onetimeauth_BYTES, &a)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_onetimeauth(a.data, m.data, m.size, k.data); + crypto_onetimeauth(a.data, m.data, m.size, k.data); - return enif_make_binary(env, &a); + return enif_make_binary(env, &a); } -static -ERL_NIF_TERM enif_crypto_onetimeauth_verify(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary a, m, k; +static ERL_NIF_TERM enif_crypto_onetimeauth_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary a, m, k; - if ( - (argc != 3) || - (!enif_inspect_binary(env, argv[0], &a)) || - (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } + if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &a)) || + (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } - if ( - (k.size != crypto_onetimeauth_KEYBYTES) || - (a.size != crypto_onetimeauth_BYTES)) { - return enif_make_badarg(env); - } + if ((k.size != crypto_onetimeauth_KEYBYTES) || + (a.size != crypto_onetimeauth_BYTES)) { + return enif_make_badarg(env); + } - if (0 == crypto_onetimeauth_verify(a.data, m.data, m.size, k.data)) { - return enif_make_atom(env, "true"); - } else { - return enif_make_atom(env, "false"); - } + if (0 == crypto_onetimeauth_verify(a.data, m.data, m.size, k.data)) { + return enif_make_atom(env, "true"); + } else { + return enif_make_atom(env, "false"); + } } -static -ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) -{ - unsigned req_size; - ErlNifBinary result; +static ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + unsigned req_size; + ErlNifBinary result; - if ((argc != 1) || (!enif_get_uint(env, argv[0], &req_size))) { - return enif_make_badarg(env); - } + if ((argc != 1) || (!enif_get_uint(env, argv[0], &req_size))) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(req_size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(req_size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } - randombytes(result.data, result.size); + randombytes(result.data, result.size); - return enif_make_binary(env, &result); + return enif_make_binary(env, &result); } /* Key exchange */ -static -ERL_NIF_TERM enif_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_kx_SECRETKEYBYTES); +static ERL_NIF_TERM enif_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_kx_SECRETKEYBYTES); } -static -ERL_NIF_TERM enif_crypto_kx_PUBLICKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_kx_PUBLICKEYBYTES); +static ERL_NIF_TERM enif_crypto_kx_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_kx_PUBLICKEYBYTES); } -static -ERL_NIF_TERM enif_crypto_kx_SESSIONKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_kx_SESSIONKEYBYTES); +static ERL_NIF_TERM enif_crypto_kx_SESSIONKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_kx_SESSIONKEYBYTES); } -static -ERL_NIF_TERM enif_crypto_kx_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) -{ - ErlNifBinary pk, sk; +static ERL_NIF_TERM enif_crypto_kx_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk; - if (argc != 0) { - return enif_make_badarg(env); - } + if (argc != 0) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_kx_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_kx_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (!enif_alloc_binary(crypto_kx_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_kx_SECRETKEYBYTES, &sk)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_kx_keypair(pk.data, sk.data); + crypto_kx_keypair(pk.data, sk.data); - return enif_make_tuple2(env, enif_make_binary(env, &pk), enif_make_binary(env, &sk)); + return enif_make_tuple2(env, enif_make_binary(env, &pk), + enif_make_binary(env, &sk)); } -static -ERL_NIF_TERM enif_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) -{ - ErlNifBinary rx, tx, server_pk, server_sk, client_pk; +static ERL_NIF_TERM +enif_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary rx, tx, server_pk, server_sk, client_pk; - if ((argc != 3) || - (!enif_inspect_binary(env, argv[0], &server_pk)) || - (!enif_inspect_binary(env, argv[1], &server_sk)) || - (!enif_inspect_binary(env, argv[2], &client_pk)) || - (server_pk.size != crypto_kx_PUBLICKEYBYTES) || - (server_sk.size != crypto_kx_SECRETKEYBYTES) || - (client_pk.size != crypto_kx_PUBLICKEYBYTES)) { - return enif_make_badarg(env); - } + if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &server_pk)) || + (!enif_inspect_binary(env, argv[1], &server_sk)) || + (!enif_inspect_binary(env, argv[2], &client_pk)) || + (server_pk.size != crypto_kx_PUBLICKEYBYTES) || + (server_sk.size != crypto_kx_SECRETKEYBYTES) || + (client_pk.size != crypto_kx_PUBLICKEYBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if( 0 != crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data, server_sk.data, client_pk.data) ) { - // suspicious client public key - return nacl_error_tuple(env, "invalid_client_public_key"); - } + if (0 != crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data, + server_sk.data, client_pk.data)) { + // suspicious client public key + return nacl_error_tuple(env, "invalid_client_public_key"); + } - return enif_make_tuple2(env, enif_make_binary(env, &rx), enif_make_binary(env, &tx)); + return enif_make_tuple2(env, enif_make_binary(env, &rx), + enif_make_binary(env, &tx)); } -static -ERL_NIF_TERM enif_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) -{ - ErlNifBinary rx, tx, client_pk, client_sk, server_pk; +static ERL_NIF_TERM +enif_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary rx, tx, client_pk, client_sk, server_pk; - if ((argc != 3) || - (!enif_inspect_binary(env, argv[0], &client_pk)) || - (!enif_inspect_binary(env, argv[1], &client_sk)) || - (!enif_inspect_binary(env, argv[2], &server_pk)) || - (client_pk.size != crypto_kx_PUBLICKEYBYTES) || - (client_sk.size != crypto_kx_SECRETKEYBYTES) || - (server_pk.size != crypto_kx_PUBLICKEYBYTES)) { - return enif_make_badarg(env); - } + if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &client_pk)) || + (!enif_inspect_binary(env, argv[1], &client_sk)) || + (!enif_inspect_binary(env, argv[2], &server_pk)) || + (client_pk.size != crypto_kx_PUBLICKEYBYTES) || + (client_sk.size != crypto_kx_SECRETKEYBYTES) || + (server_pk.size != crypto_kx_PUBLICKEYBYTES)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { + return nacl_error_tuple(env, "alloc_failed"); + } - if( 0 != crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data, client_sk.data, server_pk.data) ) { - // suspicious server public key - return nacl_error_tuple(env, "invalid_server_public_key"); - } + if (0 != crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data, + client_sk.data, server_pk.data)) { + // suspicious server public key + return nacl_error_tuple(env, "invalid_server_public_key"); + } - return enif_make_tuple2(env, enif_make_binary(env, &rx), enif_make_binary(env, &tx)); + return enif_make_tuple2(env, enif_make_binary(env, &rx), + enif_make_binary(env, &tx)); } /* Various other helper functions */ -static -void uint64_pack(unsigned char *y, ErlNifUInt64 x) -{ - *y++ = x; x >>= 8; - *y++ = x; x >>= 8; - *y++ = x; x >>= 8; - *y++ = x; x >>= 8; - *y++ = x; x >>= 8; - *y++ = x; x >>= 8; - *y++ = x; x >>= 8; - *y++ = x; x >>= 8; +static void uint64_pack(unsigned char *y, ErlNifUInt64 x) { + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; } -static -ErlNifUInt64 uint64_unpack(const unsigned char *x) -{ - ErlNifUInt64 result; +static ErlNifUInt64 uint64_unpack(const unsigned char *x) { + ErlNifUInt64 result; - result = x[7]; - result <<= 8; result |= x[6]; - result <<= 8; result |= x[5]; - result <<= 8; result |= x[4]; - result <<= 8; result |= x[3]; - result <<= 8; result |= x[2]; - result <<= 8; result |= x[1]; - result <<= 8; result |= x[0]; - return result; + result = x[7]; + result <<= 8; + result |= x[6]; + result <<= 8; + result |= x[5]; + result <<= 8; + result |= x[4]; + result <<= 8; + result |= x[3]; + result <<= 8; + result |= x[2]; + result <<= 8; + result |= x[1]; + result <<= 8; + result |= x[0]; + return result; } -static -int crypto_block(unsigned char *out, const unsigned char *in, const unsigned char *k) -{ - ErlNifUInt64 v0 = uint64_unpack(in + 0); - ErlNifUInt64 v1 = uint64_unpack(in + 8); - ErlNifUInt64 k0 = uint64_unpack(k + 0); - ErlNifUInt64 k1 = uint64_unpack(k + 8); - ErlNifUInt64 k2 = uint64_unpack(k + 16); - ErlNifUInt64 k3 = uint64_unpack(k + 24); - ErlNifUInt64 sum = 0; - ErlNifUInt64 delta = 0x9e3779b97f4a7c15; - int i; - for (i = 0;i < 32;++i) { - sum += delta; - v0 += ((v1<<7) + k0) ^ (v1 + sum) ^ ((v1>>12) + k1); - v1 += ((v0<<16) + k2) ^ (v0 + sum) ^ ((v0>>8) + k3); - } - uint64_pack(out + 0,v0); - uint64_pack(out + 8,v1); +static int crypto_block(unsigned char *out, const unsigned char *in, + const unsigned char *k) { + ErlNifUInt64 v0 = uint64_unpack(in + 0); + ErlNifUInt64 v1 = uint64_unpack(in + 8); + ErlNifUInt64 k0 = uint64_unpack(k + 0); + ErlNifUInt64 k1 = uint64_unpack(k + 8); + ErlNifUInt64 k2 = uint64_unpack(k + 16); + ErlNifUInt64 k3 = uint64_unpack(k + 24); + ErlNifUInt64 sum = 0; + ErlNifUInt64 delta = 0x9e3779b97f4a7c15; + int i; + for (i = 0; i < 32; ++i) { + sum += delta; + v0 += ((v1 << 7) + k0) ^ (v1 + sum) ^ ((v1 >> 12) + k1); + v1 += ((v0 << 16) + k2) ^ (v0 + sum) ^ ((v0 >> 8) + k3); + } + uint64_pack(out + 0, v0); + uint64_pack(out + 8, v1); - return 0; + return 0; } -static -ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) -{ - ErlNifBinary in, out, key; +static ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary in, out, key; - if ( - (argc != 2) || - (!enif_inspect_binary(env, argv[0], &in)) || - (!enif_inspect_binary(env, argv[1], &key)) || - (in.size != 16) || (key.size != 32)) { - return enif_make_badarg(env); - } + if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &in)) || + (!enif_inspect_binary(env, argv[1], &key)) || (in.size != 16) || + (key.size != 32)) { + return enif_make_badarg(env); + } - if (!enif_alloc_binary(in.size, &out)) { - return nacl_error_tuple(env, "alloc_failed"); - } + if (!enif_alloc_binary(in.size, &out)) { + return nacl_error_tuple(env, "alloc_failed"); + } - crypto_block(out.data, in.data, key.data); + crypto_block(out.data, in.data, key.data); - return enif_make_binary(env, &out); + return enif_make_binary(env, &out); } -static -ERL_NIF_TERM enif_crypto_pwhash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enif_crypto_pwhash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary h, p, s; // Validate the arguments - if( (argc != 2) || - (!enif_inspect_iolist_as_binary(env, argv[0], &p)) || - (!enif_inspect_binary(env, argv[1], &s)) ) { + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &p)) || + (!enif_inspect_binary(env, argv[1], &s))) { return enif_make_badarg(env); } // Check Salt size - if(s.size != crypto_pwhash_SALTBYTES) { + if (s.size != crypto_pwhash_SALTBYTES) { return nacl_error_tuple(env, "invalid_salt_size"); } // Allocate memory for return binary - if( !enif_alloc_binary(crypto_box_SEEDBYTES, &h) ) { + if (!enif_alloc_binary(crypto_box_SEEDBYTES, &h)) { return nacl_error_tuple(env, "alloc_failed"); } - if( crypto_pwhash(h.data, h.size, (char *)p.data, p.size, s.data, - crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE, crypto_pwhash_ALG_DEFAULT) != 0) { + if (crypto_pwhash(h.data, h.size, (char *)p.data, p.size, s.data, + crypto_pwhash_OPSLIMIT_INTERACTIVE, + crypto_pwhash_MEMLIMIT_INTERACTIVE, + crypto_pwhash_ALG_DEFAULT) != 0) { /* out of memory */ enif_release_binary(&h); return nacl_error_tuple(env, "out_of_memory"); } - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); ERL_NIF_TERM ret = enif_make_binary(env, &h); return enif_make_tuple2(env, ok, ret); } -static -ERL_NIF_TERM enif_crypto_pwhash_str(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enif_crypto_pwhash_str(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary h, p; // Validate the arguments - if( (argc != 1) || - (!enif_inspect_iolist_as_binary(env, argv[0], &p)) ) { + if ((argc != 1) || (!enif_inspect_iolist_as_binary(env, argv[0], &p))) { return enif_make_badarg(env); } // Allocate memory for return binary - if( !enif_alloc_binary(crypto_pwhash_STRBYTES, &h) ) { + if (!enif_alloc_binary(crypto_pwhash_STRBYTES, &h)) { return nacl_error_tuple(env, "alloc_failed"); } - if( crypto_pwhash_str((char *)h.data, (char *)p.data, p.size, - crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE) != 0) { + if (crypto_pwhash_str((char *)h.data, (char *)p.data, p.size, + crypto_pwhash_OPSLIMIT_INTERACTIVE, + crypto_pwhash_MEMLIMIT_INTERACTIVE) != 0) { /* out of memory */ enif_release_binary(&h); return nacl_error_tuple(env, "out_of_memory"); } - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); ERL_NIF_TERM ret = enif_make_binary(env, &h); return enif_make_tuple2(env, ok, ret); } -static -ERL_NIF_TERM enif_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ErlNifBinary h, p; +static ERL_NIF_TERM enif_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary h, p; // Validate the arguments - if( (argc != 2) || - (!enif_inspect_iolist_as_binary(env, argv[0], &h)) || - (!enif_inspect_iolist_as_binary(env, argv[1], &p)) ) { + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &h)) || + (!enif_inspect_iolist_as_binary(env, argv[1], &p))) { return enif_make_badarg(env); } ERL_NIF_TERM retVal = enif_make_atom(env, ATOM_TRUE); - if( crypto_pwhash_str_verify((char *)h.data, (char *)p.data, p.size) != 0) { + if (crypto_pwhash_str_verify((char *)h.data, (char *)p.data, p.size) != 0) { /* wrong password */ retVal = enif_make_atom(env, ATOM_FALSE); } @@ -1344,225 +1299,242 @@ ERL_NIF_TERM enif_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, ERL_NIF_TER /* * AEAD ChaCha20 Poly1305 */ -static -ERL_NIF_TERM enif_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_KEYBYTES); } -static -ERL_NIF_TERM enif_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_NPUBBYTES); } -static -ERL_NIF_TERM enif_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_ABYTES); } -static -ERL_NIF_TERM enif_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX); +static ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, + crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX); } -static -ERL_NIF_TERM enif_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ERL_NIF_TERM result; ErlNifBinary key, nonce, ad, message, ciphertext; - if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) - || (!enif_inspect_binary(env, argv[1], &nonce)) - || (!enif_inspect_binary(env, argv[2], &ad)) - || (!enif_inspect_binary(env, argv[3], &message)) - || (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) - || (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)) { - return enif_make_badarg(env); + if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &ad)) || + (!enif_inspect_binary(env, argv[3], &message)) || + (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) || + (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)) { + return enif_make_badarg(env); } - do - { - if (!enif_alloc_binary(message.size + crypto_aead_chacha20poly1305_ietf_ABYTES, &ciphertext)) { - result = nacl_error_tuple(env, "alloc_failed"); - continue; - } + do { + if (!enif_alloc_binary(message.size + + crypto_aead_chacha20poly1305_ietf_ABYTES, + &ciphertext)) { + result = nacl_error_tuple(env, "alloc_failed"); + continue; + } - if (crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext.data, NULL, message.data, message.size, - ad.data, ad.size, NULL, nonce.data, key.data) < 0) { - result = nacl_error_tuple(env, "aead_chacha20poly1305_ietf_encrypt_failed"); - continue; - } + if (crypto_aead_chacha20poly1305_ietf_encrypt( + ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, + NULL, nonce.data, key.data) < 0) { + result = + nacl_error_tuple(env, "aead_chacha20poly1305_ietf_encrypt_failed"); + continue; + } - result = enif_make_binary(env, &ciphertext); + result = enif_make_binary(env, &ciphertext); } while (0); return result; - } -static -ERL_NIF_TERM enif_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ERL_NIF_TERM result; ErlNifBinary key, nonce, ad, message, ciphertext; - if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) - || (!enif_inspect_binary(env, argv[1], &nonce)) - || (!enif_inspect_binary(env, argv[2], &ad)) - || (!enif_inspect_binary(env, argv[3], &ciphertext)) - || (ciphertext.size < crypto_aead_chacha20poly1305_ietf_ABYTES) - || (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) - || (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)) { - return enif_make_badarg(env); + if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &ad)) || + (!enif_inspect_binary(env, argv[3], &ciphertext)) || + (ciphertext.size < crypto_aead_chacha20poly1305_ietf_ABYTES) || + (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) || + (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)) { + return enif_make_badarg(env); } - do - { - if (!enif_alloc_binary(ciphertext.size - crypto_aead_chacha20poly1305_ietf_ABYTES, &message)) { - result = nacl_error_tuple(env, "alloc_failed"); - continue; - } + do { + if (!enif_alloc_binary(ciphertext.size - + crypto_aead_chacha20poly1305_ietf_ABYTES, + &message)) { + result = nacl_error_tuple(env, "alloc_failed"); + continue; + } - if (crypto_aead_chacha20poly1305_ietf_decrypt(message.data, NULL, NULL, ciphertext.data, ciphertext.size, - ad.data, ad.size, nonce.data, key.data) < 0) { - result = nacl_error_tuple(env, "aead_chacha20poly1305_ietf_decrypt_failed"); - continue; - } + if (crypto_aead_chacha20poly1305_ietf_decrypt( + message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, + ad.size, nonce.data, key.data) < 0) { + result = + nacl_error_tuple(env, "aead_chacha20poly1305_ietf_decrypt_failed"); + continue; + } - result = enif_make_binary(env, &message); + result = enif_make_binary(env, &message); } while (0); return result; - } /* * Generic hash */ -static -ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_BYTES); +static ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_BYTES); } -static -ERL_NIF_TERM enif_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_BYTES_MIN); +static ERL_NIF_TERM +enif_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_BYTES_MIN); } -static -ERL_NIF_TERM enif_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_BYTES_MAX); +static ERL_NIF_TERM +enif_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_BYTES_MAX); } -static -ERL_NIF_TERM enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_KEYBYTES); +static ERL_NIF_TERM +enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_KEYBYTES); } -static -ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_KEYBYTES_MIN); +static ERL_NIF_TERM +enif_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_KEYBYTES_MIN); } -static -ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_KEYBYTES_MAX); +static ERL_NIF_TERM +enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_KEYBYTES_MAX); } -static -ERL_NIF_TERM enif_crypto_generichash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enif_crypto_generichash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary hash, message, key; unsigned hashSize; - // Validate the arguments - if( (argc != 3) || - (!enif_get_uint(env, argv[0], &hashSize)) || + // Validate the arguments + if ((argc != 3) || (!enif_get_uint(env, argv[0], &hashSize)) || (!enif_inspect_binary(env, argv[1], &message)) || - (!enif_inspect_binary(env, argv[2], &key)) ) { + (!enif_inspect_binary(env, argv[2], &key))) { return enif_make_badarg(env); } - // Verify that hash size is crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX - if( (hashSize < crypto_generichash_BYTES_MIN) || - (hashSize > crypto_generichash_BYTES_MAX) ) { + // Verify that hash size is + // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX + if ((hashSize < crypto_generichash_BYTES_MIN) || + (hashSize > crypto_generichash_BYTES_MAX)) { return nacl_error_tuple(env, "invalid_hash_size"); } // validate key size unsigned char *k = key.data; - if( 0 == key.size ) { + if (0 == key.size) { k = NULL; - } else if( key.size < crypto_generichash_KEYBYTES_MIN || key.size > crypto_generichash_KEYBYTES_MAX ) { + } else if (key.size < crypto_generichash_KEYBYTES_MIN || + key.size > crypto_generichash_KEYBYTES_MAX) { return nacl_error_tuple(env, "invalid_key_size"); } // allocate memory for hash - if( !enif_alloc_binary(hashSize, &hash) ) { + if (!enif_alloc_binary(hashSize, &hash)) { return nacl_error_tuple(env, "alloc_failed"); } // calculate hash - if( 0 != crypto_generichash(hash.data, hash.size, message.data, message.size, k, key.size) ) { + if (0 != crypto_generichash(hash.data, hash.size, message.data, message.size, + k, key.size)) { enif_release_binary(&hash); return nacl_error_tuple(env, "hash_error"); } - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); ERL_NIF_TERM ret = enif_make_binary(env, &hash); return enif_make_tuple2(env, ok, ret); } -static -crypto_generichash_state *align64(void *ptr){ - if((unsigned long)ptr % 64 == 0) +static crypto_generichash_state *align64(void *ptr) { + if ((unsigned long)ptr % 64 == 0) return ptr; return ptr + (64 - ((unsigned long)ptr % 64)); } -static -ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary key; unsigned hashSize; - // Validate the arguments - if( (argc != 2) || - (!enif_get_uint(env, argv[0], &hashSize)) || - (!enif_inspect_binary(env, argv[1], &key)) ) { + // Validate the arguments + if ((argc != 2) || (!enif_get_uint(env, argv[0], &hashSize)) || + (!enif_inspect_binary(env, argv[1], &key))) { return enif_make_badarg(env); } - // Verify that hash size is crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX - if( (hashSize < crypto_generichash_BYTES_MIN) || - (hashSize > crypto_generichash_BYTES_MAX) ) { + // Verify that hash size is + // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX + if ((hashSize < crypto_generichash_BYTES_MIN) || + (hashSize > crypto_generichash_BYTES_MAX)) { return nacl_error_tuple(env, "invalid_hash_size"); } // validate key size unsigned char *k = key.data; - if( 0 == key.size ) { + if (0 == key.size) { k = NULL; - } else if( key.size < crypto_generichash_KEYBYTES_MIN || key.size > crypto_generichash_KEYBYTES_MAX ) { + } else if (key.size < crypto_generichash_KEYBYTES_MIN || + key.size > crypto_generichash_KEYBYTES_MAX) { return nacl_error_tuple(env, "invalid_key_size"); } // Create a resource for hash state (+ 60 to make room for 64-byte alignment) - void *state = enif_alloc_resource(generichash_state_type, crypto_generichash_statebytes() + 60); - if( !state ) { + void *state = enif_alloc_resource(generichash_state_type, + crypto_generichash_statebytes() + 60); + if (!state) { return nacl_error_tuple(env, "alloc_failed"); } // Call the library function - if( 0 != crypto_generichash_init(align64(state), k, key.size, hashSize) ) { + if (0 != crypto_generichash_init(align64(state), k, key.size, hashSize)) { return nacl_error_tuple(env, "hash_init_error"); } - // Create return values ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate"); ERL_NIF_TERM e2 = argv[0]; ERL_NIF_TERM e3 = enif_make_resource(env, state); - // release dynamically allocated memory to erlang to mange enif_release_resource(state); @@ -1570,30 +1542,32 @@ ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, ERL_NIF_TERM return enif_make_tuple3(env, e1, e2, e3); } -static -ERL_NIF_TERM enif_crypto_generichash_update(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enif_crypto_generichash_update(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary message; unsigned hashSize; void *state; - // Validate the arguments - if( (argc != 3) || - (!enif_get_uint(env, argv[0], &hashSize)) || - (!enif_get_resource(env, argv[1], generichash_state_type, (void **)&state)) || - (!enif_inspect_binary(env, argv[2], &message)) ) { + // Validate the arguments + if ((argc != 3) || (!enif_get_uint(env, argv[0], &hashSize)) || + (!enif_get_resource(env, argv[1], generichash_state_type, + (void **)&state)) || + (!enif_inspect_binary(env, argv[2], &message))) { return enif_make_badarg(env); } - // Verify that hash size is crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX - if( (hashSize < crypto_generichash_BYTES_MIN) || - (hashSize > crypto_generichash_BYTES_MAX) ) { + // Verify that hash size is + // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX + if ((hashSize < crypto_generichash_BYTES_MIN) || + (hashSize > crypto_generichash_BYTES_MAX)) { return nacl_error_tuple(env, "invalid_hash_size"); } // Update hash state - if( 0 != crypto_generichash_update(align64(state), message.data, message.size) ) { + if (0 != + crypto_generichash_update(align64(state), message.data, message.size)) { return nacl_error_tuple(env, "hash_update_error"); } @@ -1606,39 +1580,40 @@ ERL_NIF_TERM enif_crypto_generichash_update(ErlNifEnv *env, int argc, ERL_NIF_TE return enif_make_tuple3(env, e1, e2, e3); } -static -ERL_NIF_TERM enif_crypto_generichash_final(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enif_crypto_generichash_final(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary hash; unsigned hashSize; void *state; - // Validate the arguments - if( (argc != 2) || - (!enif_get_uint(env, argv[0], &hashSize)) || - (!enif_get_resource(env, argv[1], generichash_state_type, (void **)&state)) ) { + // Validate the arguments + if ((argc != 2) || (!enif_get_uint(env, argv[0], &hashSize)) || + (!enif_get_resource(env, argv[1], generichash_state_type, + (void **)&state))) { return enif_make_badarg(env); } - // Verify that hash size is crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX - if( (hashSize < crypto_generichash_BYTES_MIN) || - (hashSize > crypto_generichash_BYTES_MAX) ) { + // Verify that hash size is + // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX + if ((hashSize < crypto_generichash_BYTES_MIN) || + (hashSize > crypto_generichash_BYTES_MAX)) { return nacl_error_tuple(env, "invalid_hash_size"); } - // allocate memory for hash - if( !enif_alloc_binary(hashSize, &hash) ) { + // allocate memory for hash + if (!enif_alloc_binary(hashSize, &hash)) { return nacl_error_tuple(env, "alloc_failed"); } - // calculate hash - if( 0 != crypto_generichash_final(align64(state), hash.data, hash.size) ) { + // calculate hash + if (0 != crypto_generichash_final(align64(state), hash.data, hash.size)) { enif_release_binary(&hash); return nacl_error_tuple(env, "hash_error"); } - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); ERL_NIF_TERM ret = enif_make_binary(env, &hash); return enif_make_tuple2(env, ok, ret); @@ -1646,128 +1621,167 @@ ERL_NIF_TERM enif_crypto_generichash_final(ErlNifEnv *env, int argc, ERL_NIF_TER /* Tie the knot to the Erlang world */ static ErlNifFunc nif_funcs[] = { - {"crypto_box_NONCEBYTES", 0, enif_crypto_box_NONCEBYTES}, - {"crypto_box_ZEROBYTES", 0, enif_crypto_box_ZEROBYTES}, - {"crypto_box_BOXZEROBYTES", 0, enif_crypto_box_BOXZEROBYTES}, - {"crypto_box_PUBLICKEYBYTES", 0, enif_crypto_box_PUBLICKEYBYTES}, - {"crypto_box_SECRETKEYBYTES", 0, enif_crypto_box_SECRETKEYBYTES}, - {"crypto_box_BEFORENMBYTES", 0, enif_crypto_box_BEFORENMBYTES}, + {"crypto_box_NONCEBYTES", 0, enif_crypto_box_NONCEBYTES}, + {"crypto_box_ZEROBYTES", 0, enif_crypto_box_ZEROBYTES}, + {"crypto_box_BOXZEROBYTES", 0, enif_crypto_box_BOXZEROBYTES}, + {"crypto_box_PUBLICKEYBYTES", 0, enif_crypto_box_PUBLICKEYBYTES}, + {"crypto_box_SECRETKEYBYTES", 0, enif_crypto_box_SECRETKEYBYTES}, + {"crypto_box_BEFORENMBYTES", 0, enif_crypto_box_BEFORENMBYTES}, - erl_nif_dirty_job_cpu_bound_macro("crypto_box_keypair", 0, enif_crypto_box_keypair), + erl_nif_dirty_job_cpu_bound_macro("crypto_box_keypair", 0, + enif_crypto_box_keypair), + erl_nif_dirty_job_cpu_bound_macro("crypto_box", 4, enif_crypto_box), + erl_nif_dirty_job_cpu_bound_macro("crypto_box_open", 4, + enif_crypto_box_open), - erl_nif_dirty_job_cpu_bound_macro("crypto_box", 4, enif_crypto_box), - erl_nif_dirty_job_cpu_bound_macro("crypto_box_open", 4, enif_crypto_box_open), + {"crypto_box_beforenm", 2, enif_crypto_box_beforenm}, + {"crypto_box_afternm_b", 3, enif_crypto_box_afternm}, + erl_nif_dirty_job_cpu_bound_macro("crypto_box_afternm", 3, + enif_crypto_box_afternm), + {"crypto_box_open_afternm_b", 3, enif_crypto_box_open_afternm}, + erl_nif_dirty_job_cpu_bound_macro("crypto_box_open_afternm", 3, + enif_crypto_box_open_afternm), - {"crypto_box_beforenm", 2, enif_crypto_box_beforenm}, - {"crypto_box_afternm_b", 3, enif_crypto_box_afternm}, - erl_nif_dirty_job_cpu_bound_macro("crypto_box_afternm", 3, enif_crypto_box_afternm), - {"crypto_box_open_afternm_b", 3, enif_crypto_box_open_afternm}, - erl_nif_dirty_job_cpu_bound_macro("crypto_box_open_afternm", 3, enif_crypto_box_open_afternm), + {"crypto_sign_PUBLICKEYBYTES", 0, enif_crypto_sign_PUBLICKEYBYTES}, + {"crypto_sign_SECRETKEYBYTES", 0, enif_crypto_sign_SECRETKEYBYTES}, + erl_nif_dirty_job_cpu_bound_macro("crypto_sign_keypair", 0, + enif_crypto_sign_keypair), - {"crypto_sign_PUBLICKEYBYTES", 0, enif_crypto_sign_PUBLICKEYBYTES}, - {"crypto_sign_SECRETKEYBYTES", 0, enif_crypto_sign_SECRETKEYBYTES}, - erl_nif_dirty_job_cpu_bound_macro("crypto_sign_keypair", 0, enif_crypto_sign_keypair), + erl_nif_dirty_job_cpu_bound_macro("crypto_sign", 2, enif_crypto_sign), + erl_nif_dirty_job_cpu_bound_macro("crypto_sign_open", 2, + enif_crypto_sign_open), - erl_nif_dirty_job_cpu_bound_macro("crypto_sign", 2, enif_crypto_sign), - erl_nif_dirty_job_cpu_bound_macro("crypto_sign_open", 2, enif_crypto_sign_open), + erl_nif_dirty_job_cpu_bound_macro("crypto_sign_detached", 2, + enif_crypto_sign_detached), + erl_nif_dirty_job_cpu_bound_macro("crypto_sign_verify_detached", 3, + enif_crypto_sign_verify_detached), - erl_nif_dirty_job_cpu_bound_macro("crypto_sign_detached", 2, enif_crypto_sign_detached), - erl_nif_dirty_job_cpu_bound_macro("crypto_sign_verify_detached", 3, enif_crypto_sign_verify_detached), + {"crypto_box_SEALBYTES", 0, enif_crypto_box_SEALBYTES}, - {"crypto_box_SEALBYTES", 0, enif_crypto_box_SEALBYTES}, + erl_nif_dirty_job_cpu_bound_macro("crypto_box_seal", 2, + enif_crypto_box_seal), + erl_nif_dirty_job_cpu_bound_macro("crypto_box_seal_open", 3, + enif_crypto_box_seal_open), - erl_nif_dirty_job_cpu_bound_macro("crypto_box_seal", 2, enif_crypto_box_seal), - erl_nif_dirty_job_cpu_bound_macro("crypto_box_seal_open", 3, enif_crypto_box_seal_open), + {"crypto_secretbox_NONCEBYTES", 0, enif_crypto_secretbox_NONCEBYTES}, + {"crypto_secretbox_ZEROBYTES", 0, enif_crypto_secretbox_ZEROBYTES}, + {"crypto_secretbox_BOXZEROBYTES", 0, enif_crypto_secretbox_BOXZEROBYTES}, + {"crypto_secretbox_KEYBYTES", 0, enif_crypto_secretbox_KEYBYTES}, + {"crypto_secretbox_b", 3, enif_crypto_secretbox}, + erl_nif_dirty_job_cpu_bound_macro("crypto_secretbox", 3, + enif_crypto_secretbox), + {"crypto_secretbox_open_b", 3, enif_crypto_secretbox_open}, + erl_nif_dirty_job_cpu_bound_macro("crypto_secretbox_open", 3, + enif_crypto_secretbox_open), - {"crypto_secretbox_NONCEBYTES", 0, enif_crypto_secretbox_NONCEBYTES}, - {"crypto_secretbox_ZEROBYTES", 0, enif_crypto_secretbox_ZEROBYTES}, - {"crypto_secretbox_BOXZEROBYTES", 0, enif_crypto_secretbox_BOXZEROBYTES}, - {"crypto_secretbox_KEYBYTES", 0, enif_crypto_secretbox_KEYBYTES}, - {"crypto_secretbox_b", 3, enif_crypto_secretbox}, - erl_nif_dirty_job_cpu_bound_macro("crypto_secretbox", 3, enif_crypto_secretbox), - {"crypto_secretbox_open_b", 3, enif_crypto_secretbox_open}, - erl_nif_dirty_job_cpu_bound_macro("crypto_secretbox_open", 3, enif_crypto_secretbox_open), + {"crypto_stream_chacha20_KEYBYTES", 0, + enif_crypto_stream_chacha20_KEYBYTES}, + {"crypto_stream_chacha20_NONCEBYTES", 0, + enif_crypto_stream_chacha20_NONCEBYTES}, + {"crypto_stream_chacha20_b", 3, enif_crypto_stream_chacha20}, + erl_nif_dirty_job_cpu_bound_macro("crypto_stream_chacha20", 3, + enif_crypto_stream_chacha20), + {"crypto_stream_chacha20_xor_b", 3, enif_crypto_stream_chacha20_xor}, + erl_nif_dirty_job_cpu_bound_macro("crypto_stream_chacha20_xor", 3, + enif_crypto_stream_chacha20_xor), - {"crypto_stream_chacha20_KEYBYTES", 0, enif_crypto_stream_chacha20_KEYBYTES}, - {"crypto_stream_chacha20_NONCEBYTES", 0, enif_crypto_stream_chacha20_NONCEBYTES}, - {"crypto_stream_chacha20_b", 3, enif_crypto_stream_chacha20}, - erl_nif_dirty_job_cpu_bound_macro("crypto_stream_chacha20", 3, enif_crypto_stream_chacha20), - {"crypto_stream_chacha20_xor_b", 3, enif_crypto_stream_chacha20_xor}, - erl_nif_dirty_job_cpu_bound_macro("crypto_stream_chacha20_xor", 3, enif_crypto_stream_chacha20_xor), + {"crypto_stream_KEYBYTES", 0, enif_crypto_stream_KEYBYTES}, + {"crypto_stream_NONCEBYTES", 0, enif_crypto_stream_NONCEBYTES}, + {"crypto_stream_b", 3, enif_crypto_stream}, + erl_nif_dirty_job_cpu_bound_macro("crypto_stream", 3, enif_crypto_stream), + {"crypto_stream_xor_b", 3, enif_crypto_stream_xor}, + erl_nif_dirty_job_cpu_bound_macro("crypto_stream_xor", 3, + enif_crypto_stream_xor), - {"crypto_stream_KEYBYTES", 0, enif_crypto_stream_KEYBYTES}, - {"crypto_stream_NONCEBYTES", 0, enif_crypto_stream_NONCEBYTES}, - {"crypto_stream_b", 3, enif_crypto_stream}, - erl_nif_dirty_job_cpu_bound_macro("crypto_stream", 3, enif_crypto_stream), - {"crypto_stream_xor_b", 3, enif_crypto_stream_xor}, - erl_nif_dirty_job_cpu_bound_macro("crypto_stream_xor", 3, enif_crypto_stream_xor), + {"crypto_auth_BYTES", 0, enif_crypto_auth_BYTES}, + {"crypto_auth_KEYBYTES", 0, enif_crypto_auth_KEYBYTES}, + {"crypto_auth_b", 2, enif_crypto_auth}, + erl_nif_dirty_job_cpu_bound_macro("crypto_auth", 2, enif_crypto_auth), + {"crypto_auth_verify_b", 3, enif_crypto_auth_verify}, + erl_nif_dirty_job_cpu_bound_macro("crypto_auth_verify", 3, + enif_crypto_auth_verify), - {"crypto_auth_BYTES", 0, enif_crypto_auth_BYTES}, - {"crypto_auth_KEYBYTES", 0, enif_crypto_auth_KEYBYTES}, - {"crypto_auth_b", 2, enif_crypto_auth}, - erl_nif_dirty_job_cpu_bound_macro("crypto_auth", 2, enif_crypto_auth), - {"crypto_auth_verify_b", 3, enif_crypto_auth_verify}, - erl_nif_dirty_job_cpu_bound_macro("crypto_auth_verify", 3, enif_crypto_auth_verify), + {"crypto_shorthash_BYTES", 0, enif_crypto_shorthash_BYTES}, + {"crypto_shorthash_KEYBYTES", 0, enif_crypto_shorthash_KEYBYTES}, + {"crypto_shorthash", 2, enif_crypto_shorthash}, - {"crypto_shorthash_BYTES", 0, enif_crypto_shorthash_BYTES}, - {"crypto_shorthash_KEYBYTES", 0, enif_crypto_shorthash_KEYBYTES}, - {"crypto_shorthash", 2, enif_crypto_shorthash}, + {"crypto_onetimeauth_BYTES", 0, enif_crypto_onetimeauth_BYTES}, + {"crypto_onetimeauth_KEYBYTES", 0, enif_crypto_onetimeauth_KEYBYTES}, + {"crypto_onetimeauth_b", 2, enif_crypto_onetimeauth}, + erl_nif_dirty_job_cpu_bound_macro("crypto_onetimeauth", 2, + enif_crypto_onetimeauth), + {"crypto_onetimeauth_verify_b", 3, enif_crypto_onetimeauth_verify}, + erl_nif_dirty_job_cpu_bound_macro("crypto_onetimeauth_verify", 3, + enif_crypto_onetimeauth_verify), - {"crypto_onetimeauth_BYTES", 0, enif_crypto_onetimeauth_BYTES}, - {"crypto_onetimeauth_KEYBYTES", 0, enif_crypto_onetimeauth_KEYBYTES}, - {"crypto_onetimeauth_b", 2, enif_crypto_onetimeauth}, - erl_nif_dirty_job_cpu_bound_macro("crypto_onetimeauth", 2, enif_crypto_onetimeauth), - {"crypto_onetimeauth_verify_b", 3, enif_crypto_onetimeauth_verify}, - erl_nif_dirty_job_cpu_bound_macro("crypto_onetimeauth_verify", 3, enif_crypto_onetimeauth_verify), + {"crypto_hash_b", 1, enif_crypto_hash}, + erl_nif_dirty_job_cpu_bound_macro("crypto_hash", 1, enif_crypto_hash), + {"crypto_verify_16", 2, enif_crypto_verify_16}, + {"crypto_verify_32", 2, enif_crypto_verify_32}, + {"sodium_memzero", 1, enif_sodium_memzero}, - {"crypto_hash_b", 1, enif_crypto_hash}, - erl_nif_dirty_job_cpu_bound_macro("crypto_hash", 1, enif_crypto_hash), - {"crypto_verify_16", 2, enif_crypto_verify_16}, - {"crypto_verify_32", 2, enif_crypto_verify_32}, - {"sodium_memzero", 1, enif_sodium_memzero}, + {"crypto_pwhash", 2, enif_crypto_pwhash}, + {"crypto_pwhash_str", 1, enif_crypto_pwhash_str}, + {"crypto_pwhash_str_verify", 2, enif_crypto_pwhash_str_verify}, - {"crypto_pwhash", 2, enif_crypto_pwhash}, - {"crypto_pwhash_str", 1, enif_crypto_pwhash_str}, - {"crypto_pwhash_str_verify", 2, enif_crypto_pwhash_str_verify}, + erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult", 2, + enif_crypto_curve25519_scalarmult), + erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult_base", 1, + enif_crypto_curve25519_scalarmult_base), - erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult", 2, enif_crypto_curve25519_scalarmult), - erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult_base", 1, enif_crypto_curve25519_scalarmult_base), + erl_nif_dirty_job_cpu_bound_macro("crypto_sign_ed25519_keypair", 0, + enif_crypto_sign_ed25519_keypair), + {"crypto_sign_ed25519_public_to_curve25519", 1, + enif_crypto_sign_ed25519_public_to_curve25519}, + {"crypto_sign_ed25519_secret_to_curve25519", 1, + enif_crypto_sign_ed25519_secret_to_curve25519}, + {"crypto_sign_ed25519_PUBLICKEYBYTES", 0, + enif_crypto_sign_ed25519_PUBLICKEYBYTES}, + {"crypto_sign_ed25519_SECRETKEYBYTES", 0, + enif_crypto_sign_ed25519_SECRETKEYBYTES}, - erl_nif_dirty_job_cpu_bound_macro("crypto_sign_ed25519_keypair", 0, enif_crypto_sign_ed25519_keypair), - {"crypto_sign_ed25519_public_to_curve25519", 1, enif_crypto_sign_ed25519_public_to_curve25519}, - {"crypto_sign_ed25519_secret_to_curve25519", 1, enif_crypto_sign_ed25519_secret_to_curve25519}, - {"crypto_sign_ed25519_PUBLICKEYBYTES", 0, enif_crypto_sign_ed25519_PUBLICKEYBYTES}, - {"crypto_sign_ed25519_SECRETKEYBYTES", 0, enif_crypto_sign_ed25519_SECRETKEYBYTES}, + erl_nif_dirty_job_cpu_bound_macro("randombytes", 1, enif_randombytes), - erl_nif_dirty_job_cpu_bound_macro("randombytes", 1, enif_randombytes), + erl_nif_dirty_job_cpu_bound_macro("crypto_kx_keypair", 0, + enif_crypto_kx_keypair), + erl_nif_dirty_job_cpu_bound_macro("crypto_kx_client_session_keys", 3, + enif_crypto_kx_client_session_keys), + erl_nif_dirty_job_cpu_bound_macro("crypto_kx_server_session_keys", 3, + enif_crypto_kx_server_session_keys), + {"crypto_kx_PUBLICKEYBYTES", 0, enif_crypto_kx_PUBLICKEYBYTES}, + {"crypto_kx_SECRETKEYBYTES", 0, enif_crypto_kx_SECRETKEYBYTES}, + {"crypto_kx_SESSIONKEYBYTES", 0, enif_crypto_kx_SESSIONKEYBYTES}, - erl_nif_dirty_job_cpu_bound_macro("crypto_kx_keypair", 0, enif_crypto_kx_keypair), - erl_nif_dirty_job_cpu_bound_macro("crypto_kx_client_session_keys", 3, enif_crypto_kx_client_session_keys), - erl_nif_dirty_job_cpu_bound_macro("crypto_kx_server_session_keys", 3, enif_crypto_kx_server_session_keys), - {"crypto_kx_PUBLICKEYBYTES", 0, enif_crypto_kx_PUBLICKEYBYTES}, - {"crypto_kx_SECRETKEYBYTES", 0, enif_crypto_kx_SECRETKEYBYTES}, - {"crypto_kx_SESSIONKEYBYTES", 0, enif_crypto_kx_SESSIONKEYBYTES}, + {"scramble_block_16", 2, enif_scramble_block_16}, - {"scramble_block_16", 2, enif_scramble_block_16}, + {"crypto_aead_chacha20poly1305_KEYBYTES", 0, + enif_crypto_aead_chacha20poly1305_KEYBYTES}, + {"crypto_aead_chacha20poly1305_NPUBBYTES", 0, + enif_crypto_aead_chacha20poly1305_NPUBBYTES}, + {"crypto_aead_chacha20poly1305_ABYTES", 0, + enif_crypto_aead_chacha20poly1305_ABYTES}, + {"crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX", 0, + enif_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX}, + erl_nif_dirty_job_cpu_bound_macro( + "crypto_aead_chacha20poly1305_encrypt", 4, + enif_crypto_aead_chacha20poly1305_encrypt), + erl_nif_dirty_job_cpu_bound_macro( + "crypto_aead_chacha20poly1305_decrypt", 4, + enif_crypto_aead_chacha20poly1305_decrypt), - {"crypto_aead_chacha20poly1305_KEYBYTES", 0, enif_crypto_aead_chacha20poly1305_KEYBYTES}, - {"crypto_aead_chacha20poly1305_NPUBBYTES", 0, enif_crypto_aead_chacha20poly1305_NPUBBYTES}, - {"crypto_aead_chacha20poly1305_ABYTES", 0, enif_crypto_aead_chacha20poly1305_ABYTES}, - {"crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX", 0, enif_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX}, - erl_nif_dirty_job_cpu_bound_macro("crypto_aead_chacha20poly1305_encrypt", 4, enif_crypto_aead_chacha20poly1305_encrypt), - erl_nif_dirty_job_cpu_bound_macro("crypto_aead_chacha20poly1305_decrypt", 4, enif_crypto_aead_chacha20poly1305_decrypt), - - {"crypto_generichash_BYTES", 0, enif_crypto_generichash_BYTES}, - {"crypto_generichash_BYTES_MIN", 0, enif_crypto_generichash_BYTES_MIN}, - {"crypto_generichash_BYTES_MAX", 0, enif_crypto_generichash_BYTES_MAX}, - {"crypto_generichash_KEYBYTES", 0, enif_crypto_generichash_KEYBYTES}, - {"crypto_generichash_KEYBYTES_MIN", 0, enif_crypto_generichash_KEYBYTES_MIN}, - {"crypto_generichash_KEYBYTES_MAX", 0, enif_crypto_generichash_KEYBYTES_MAX}, - {"crypto_generichash", 3, enif_crypto_generichash}, - {"crypto_generichash_init", 2, enif_crypto_generichash_init}, - {"crypto_generichash_update", 3, enif_crypto_generichash_update}, - {"crypto_generichash_final", 2, enif_crypto_generichash_final} + {"crypto_generichash_BYTES", 0, enif_crypto_generichash_BYTES}, + {"crypto_generichash_BYTES_MIN", 0, enif_crypto_generichash_BYTES_MIN}, + {"crypto_generichash_BYTES_MAX", 0, enif_crypto_generichash_BYTES_MAX}, + {"crypto_generichash_KEYBYTES", 0, enif_crypto_generichash_KEYBYTES}, + {"crypto_generichash_KEYBYTES_MIN", 0, + enif_crypto_generichash_KEYBYTES_MIN}, + {"crypto_generichash_KEYBYTES_MAX", 0, + enif_crypto_generichash_KEYBYTES_MAX}, + {"crypto_generichash", 3, enif_crypto_generichash}, + {"crypto_generichash_init", 2, enif_crypto_generichash_init}, + {"crypto_generichash_update", 3, enif_crypto_generichash_update}, + {"crypto_generichash_final", 2, enif_crypto_generichash_final} }; From 6a30dc2825015b38caf85978987a8a260d6a9879 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 15 Jan 2020 13:23:01 +0100 Subject: [PATCH 014/162] Dump in some vscode helpers/settings --- .vscode/c_cpp_properties.json | 16 ++++++++++++++++ .vscode/settings.json | 3 +++ 2 files changed, 19 insertions(+) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/settings.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..162adb4 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,16 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [], + "compilerPath": "/nix/store/a9hbzlkdfvpr4r8mjwcxcda9smjp5v1i-gcc-wrapper-9.2.0/bin/gcc", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "clang-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..691a8f6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "C_Cpp.errorSquiggles": "Disabled" +} \ No newline at end of file From bc1af327e527aac786f14bd8d971712375b9a22e Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 15 Jan 2020 13:23:08 +0100 Subject: [PATCH 015/162] Bump .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 76e43f3..e69ad79 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ doc/*.png doc/*.css _build /.eqc-info +c_src/enacl_nif.d From f9d6034e846bf20699af5f6bf256b33bd5f724de Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 15 Jan 2020 13:55:02 +0100 Subject: [PATCH 016/162] Implement missing random functions* enacl:randombytes_int32/0* enacl:randombytes_uniform/1 --- CHANGELOG.md | 8 ++++++++ c_src/enacl_nif.c | 32 ++++++++++++++++++++++++++++++++ src/enacl.erl | 21 +++++++++++++++++++-- src/enacl_nif.erl | 6 +++++- 4 files changed, 64 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb0bec4..4b0d3c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] +- Implement enacl:randombytes_int32/0. Returns a random 32bit unsigned + integer, by means of the underlying random source. +- Implement enacl:randombytes_uniform/1. Takes up to a 32bit unsigned + integer and produces a uniform integer in the range [0..N). Note + that the implementation avoids the typical non-uniformness which + would be present on a modulus operation on the nearest power-of-two + integer. +- Added a nix shell for easier development ## [0.17.2] diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 4eb5d2b..870478c 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1029,6 +1029,31 @@ static ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, return enif_make_binary(env, &result); } +static ERL_NIF_TERM enif_randombytes_int32(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifUInt64 result; + + if (argc != 0) { + return enif_make_badarg(env); + } + + result = randombytes_random(); + return enif_make_uint64(env, result); +} + +static ERL_NIF_TERM enif_randombytes_uniform(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + unsigned upper_bound; + ErlNifUInt64 result; + + if ((argc != 1) || (!enif_get_uint(env, argv[0], &upper_bound))) { + return enif_make_badarg(env); + } + + result = randombytes_uniform(upper_bound); + return enif_make_uint64(env, result); +} + /* Key exchange */ static ERL_NIF_TERM enif_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc, @@ -1741,7 +1766,14 @@ static ErlNifFunc nif_funcs[] = { {"crypto_sign_ed25519_SECRETKEYBYTES", 0, enif_crypto_sign_ed25519_SECRETKEYBYTES}, + // Linux might block here if early in the boot sequence, so get it off the + // main scheduler. Otherwise, it it would probably be fine to run on the + // main scheduler. This plays it safe, albeit with a performance hit. erl_nif_dirty_job_cpu_bound_macro("randombytes", 1, enif_randombytes), + erl_nif_dirty_job_cpu_bound_macro("randombytes_int32", 0, + enif_randombytes_int32), + erl_nif_dirty_job_cpu_bound_macro("randombytes_uniform", 1, + enif_randombytes_uniform), erl_nif_dirty_job_cpu_bound_macro("crypto_kx_keypair", 0, enif_crypto_kx_keypair), diff --git a/src/enacl.erl b/src/enacl.erl index 15ea2c2..d1bd28d 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -114,7 +114,7 @@ hash/1, verify_16/2, verify_32/2, - + %% No Tests! unsafe_memzero/1 ]). @@ -122,7 +122,9 @@ %% Randomness -export([ %% EQC - randombytes/1 + randombytes/1, + randombytes_int32/0, + randombytes_uniform/1 ]). %%% Specific primitives @@ -204,6 +206,9 @@ -define(CRYPTO_GENERICHASH_KEYBYTES_MAX, 64). -define(CRYPTO_GENERICHASH_KEYBYTES, 32). +%% Size limits +-define(MAX_32BIT_INT, 1 bsl 32). + %% @doc Verify makes sure the constants defined in libsodium matches ours verify() -> true = equals(binary:copy(<<0>>, enacl_nif:crypto_box_ZEROBYTES()), ?P_ZEROBYTES), @@ -1119,6 +1124,18 @@ aead_chacha20poly1305_MESSAGEBYTES_MAX() -> randombytes(N) -> enacl_nif:randombytes(N). +%% @doc randombytes_int32/0 produces an integer in the 32bit range +%% @end +-spec randombytes_int32() -> integer(). +randombytes_int32() -> + enacl_nif:randombytes_int32(). + +%% @doc randombytes_uniform/1 produces a random integer in the space [0..N) +%% That is with the upper bound excluded. Fails for integers above 32bit size +%% @end +randombytes_uniform(N) when N < ?MAX_32BIT_INT -> + enacl_nif:randombytes_uniform(N). + %% Helpers %% @doc bump/4 bumps a reduction budget linearly before returning the result diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 798ef53..7b48252 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -153,7 +153,9 @@ %% Access to the RNG -export([ - randombytes/1 + randombytes/1, + randombytes_int32/0, + randombytes_uniform/1 ]). %% Undocumented features :> @@ -296,5 +298,7 @@ crypto_kx_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded). crypto_kx_SECRETKEYBYTES() -> erlang:nif_error(nif_not_loaded). randombytes(_RequestedSize) -> erlang:nif_error(nif_not_loaded). +randombytes_int32() -> erlang:nif_error(nif_not_loaded). +randombytes_uniform(_UpperBound) -> erlang:nif_error(nif_not_loaded). scramble_block_16(_Block, _Key) -> erlang:nif_error(nif_not_loaded). From 97ee4bbdcf900b8ee09fdec70d808da5c4b0761a Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 15 Jan 2020 14:05:25 +0100 Subject: [PATCH 017/162] Use randombytes_uint32 Better name. Says what you are getting. --- CHANGELOG.md | 2 +- c_src/enacl_nif.c | 8 ++++---- src/enacl.erl | 10 +++++----- src/enacl_nif.erl | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b0d3c2..dc42b33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] -- Implement enacl:randombytes_int32/0. Returns a random 32bit unsigned +- Implement enacl:randombytes_uint32/0. Returns a random 32bit unsigned integer, by means of the underlying random source. - Implement enacl:randombytes_uniform/1. Takes up to a 32bit unsigned integer and produces a uniform integer in the range [0..N). Note diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index c66193a..93c69a3 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1029,8 +1029,8 @@ static ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, return enif_make_binary(env, &result); } -static ERL_NIF_TERM enif_randombytes_int32(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enif_randombytes_uint32(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifUInt64 result; if (argc != 0) { @@ -1770,8 +1770,8 @@ static ErlNifFunc nif_funcs[] = { // main scheduler. Otherwise, it it would probably be fine to run on the // main scheduler. This plays it safe, albeit with a performance hit. erl_nif_dirty_job_cpu_bound_macro("randombytes", 1, enif_randombytes), - erl_nif_dirty_job_cpu_bound_macro("randombytes_int32", 0, - enif_randombytes_int32), + erl_nif_dirty_job_cpu_bound_macro("randombytes_uint32", 0, + enif_randombytes_uint32), erl_nif_dirty_job_cpu_bound_macro("randombytes_uniform", 1, enif_randombytes_uniform), diff --git a/src/enacl.erl b/src/enacl.erl index d1bd28d..3ea4ede 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -123,7 +123,7 @@ -export([ %% EQC randombytes/1, - randombytes_int32/0, + randombytes_uint32/0, randombytes_uniform/1 ]). @@ -1124,11 +1124,11 @@ aead_chacha20poly1305_MESSAGEBYTES_MAX() -> randombytes(N) -> enacl_nif:randombytes(N). -%% @doc randombytes_int32/0 produces an integer in the 32bit range +%% @doc randombytes_uint32/0 produces an integer in the 32bit range %% @end --spec randombytes_int32() -> integer(). -randombytes_int32() -> - enacl_nif:randombytes_int32(). +-spec randombytes_uint32() -> integer(). +randombytes_uint32() -> + enacl_nif:randombytes_uint32(). %% @doc randombytes_uniform/1 produces a random integer in the space [0..N) %% That is with the upper bound excluded. Fails for integers above 32bit size diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 7b48252..9b4c7ce 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -154,7 +154,7 @@ %% Access to the RNG -export([ randombytes/1, - randombytes_int32/0, + randombytes_uint32/0, randombytes_uniform/1 ]). @@ -298,7 +298,7 @@ crypto_kx_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded). crypto_kx_SECRETKEYBYTES() -> erlang:nif_error(nif_not_loaded). randombytes(_RequestedSize) -> erlang:nif_error(nif_not_loaded). -randombytes_int32() -> erlang:nif_error(nif_not_loaded). +randombytes_uint32() -> erlang:nif_error(nif_not_loaded). randombytes_uniform(_UpperBound) -> erlang:nif_error(nif_not_loaded). scramble_block_16(_Block, _Key) -> erlang:nif_error(nif_not_loaded). From bb703d0c35a3b9d0c19de5cc246a7529af4ad5db Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 15 Jan 2020 16:17:00 +0100 Subject: [PATCH 018/162] Bump CONTRIBUTORS --- CONTRIBUTORS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 2bac1c5..5e1015b 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -3,9 +3,13 @@ List of people who have contributed to the eNaCl source code: Alexander Færøy Alexander Malaev Amir Ghassemi Nasr +GitHub/ECrownofFire Geller Bedoya Jesper Louis Andersen Joel Stanley Konrad Zemek Parnell Springmeyer Ricardo Lanziano +Tino Breddin +Venkatakumar Srinivasan + From aaa58276131b1fc30372ccd149c5f1481914d595 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 15 Jan 2020 16:17:44 +0100 Subject: [PATCH 019/162] Maintain CHANGELOG a bit --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc42b33..41d081b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] + +### Added +- The Password Hashfunctions now support memory and operations limits, + thanks to Github/ECrownofFire. - Implement enacl:randombytes_uint32/0. Returns a random 32bit unsigned integer, by means of the underlying random source. - Implement enacl:randombytes_uniform/1. Takes up to a 32bit unsigned @@ -13,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. that the implementation avoids the typical non-uniformness which would be present on a modulus operation on the nearest power-of-two integer. +- Added Win32 build support (Tino Breddin) - Added a nix shell for easier development ## [0.17.2] From 288d51ace7e4a18257fa9146a3b1e02aa5b2dc1d Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 16 Jan 2020 13:42:19 +0100 Subject: [PATCH 020/162] Bump changelog --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41d081b..aa53643 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added -- The Password Hashfunctions now support memory and operations limits, +- Added AEAD XChaCha20-Poly1305 support, thanks to Github/ECrownofFire. +- The Password Hash Generation functions now support memory and operations limits, thanks to Github/ECrownofFire. - Implement enacl:randombytes_uint32/0. Returns a random 32bit unsigned integer, by means of the underlying random source. @@ -20,6 +21,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added Win32 build support (Tino Breddin) - Added a nix shell for easier development +### Fixes +- Clang static analysis warnings (Thomas Arts) +- Replace a constant 31 with a computation from libsodium (Thomas Arts, from a security review) + ## [0.17.2] ### Fixed From 6032b5839d20bc85f6106e5786afc4043b6a1ec3 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 16 Jan 2020 13:47:41 +0100 Subject: [PATCH 021/162] Provide documentation --- src/enacl.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/enacl.erl b/src/enacl.erl index 3dde78d..5071578 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -1005,7 +1005,9 @@ crypto_sign_ed25519_keypair() -> {PK, SK} = enacl_nif:crypto_sign_ed25519_keypair(), #{ public => PK, secret => SK }. -%% @doc TODO +%% @doc crypto_sign_ed25519_sk_to_pk/1 derives an ed25519 public key from a secret key +%% The ed25519 signatures secret keys contains enough information to dervice its corresponding +%% public key. This function extracts the public key from the secret if needed. %% @end -spec crypto_sign_ed25519_sk_to_pk(Secret :: binary()) -> binary(). crypto_sign_ed25519_sk_to_pk(Secret) -> From 03bf3b30a1d93ef35d2ce0ea9acfbc4ec9fb24e5 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 16 Jan 2020 13:48:35 +0100 Subject: [PATCH 022/162] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa53643..3c257e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added +- Implement enacl:crypto_sign_ed25519_sk_to_pk/1, by an anonymous contribution. - Added AEAD XChaCha20-Poly1305 support, thanks to Github/ECrownofFire. - The Password Hash Generation functions now support memory and operations limits, thanks to Github/ECrownofFire. From 0cfa88be3248b081b9868d177a81dc1e47851e8c Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 16 Jan 2020 15:22:43 +0100 Subject: [PATCH 023/162] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c257e6..157fbf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added +- Implement enacl:crypto_sign_seed_keypair/1, by Ole Andre Birkedal. - Implement enacl:crypto_sign_ed25519_sk_to_pk/1, by an anonymous contribution. - Added AEAD XChaCha20-Poly1305 support, thanks to Github/ECrownofFire. - The Password Hash Generation functions now support memory and operations limits, From b7533d3b9cd3ef4d66e4e71fdb2a3f34936964d6 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 16 Jan 2020 15:45:42 +0100 Subject: [PATCH 024/162] Release resources under failure sign and generichash failed to release their resources under failure. This can lead to subtle memory leaks in the very unlikely event we can't initialize. --- c_src/enacl_nif.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index a1028df..079246f 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -685,6 +685,7 @@ static ERL_NIF_TERM enif_crypto_sign_init(ErlNifEnv *env, int argc, } if (0 != crypto_sign_init(state)) { + enif_release_resource(state); return nacl_error_tuple(env, "sign_init_error"); } @@ -1891,6 +1892,7 @@ static ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, // Call the library function if (0 != crypto_generichash_init(align64(state), k, key.size, hashSize)) { + enif_release_resource(state); return nacl_error_tuple(env, "hash_init_error"); } From a25b9a26843fa4cef7cc60a7a0ac3f5ad830c82d Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 16 Jan 2020 15:55:59 +0100 Subject: [PATCH 025/162] Bump CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 157fbf7..ef4421d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added +- Implement multipart signature support, by Garry Hill. - Implement enacl:crypto_sign_seed_keypair/1, by Ole Andre Birkedal. - Implement enacl:crypto_sign_ed25519_sk_to_pk/1, by an anonymous contribution. - Added AEAD XChaCha20-Poly1305 support, thanks to Github/ECrownofFire. @@ -24,6 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added a nix shell for easier development ### Fixes +- Fix a resource leak in generichash/sign init/update/final. - Clang static analysis warnings (Thomas Arts) - Replace a constant 31 with a computation from libsodium (Thomas Arts, from a security review) From d5bb24e671851f217842258b951ab4f1a52766ca Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 17 Jan 2020 15:46:38 +0100 Subject: [PATCH 026/162] Start splitting the library into its parts --- .gitignore | 3 +- c_src/enacl.c | 7 ++ c_src/enacl.h | 13 ++ c_src/enacl_nif.c | 272 ++-------------------------------------- c_src/generichash.c | 295 ++++++++++++++++++++++++++++++++++++++++++++ c_src/generichash.h | 30 +++++ c_src/hash.c | 30 +++++ c_src/hash.h | 6 + 8 files changed, 393 insertions(+), 263 deletions(-) create mode 100644 c_src/enacl.c create mode 100644 c_src/enacl.h create mode 100644 c_src/generichash.c create mode 100644 c_src/generichash.h create mode 100644 c_src/hash.c create mode 100644 c_src/hash.h diff --git a/.gitignore b/.gitignore index a0ca3ba..870be65 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ _build priv/enacl_nif.dll priv/enacl_nif.exp priv/enacl_nif.lib -c_src/enacl_nif.d +c_src/*.d + diff --git a/c_src/enacl.c b/c_src/enacl.c new file mode 100644 index 0000000..e762bb4 --- /dev/null +++ b/c_src/enacl.c @@ -0,0 +1,7 @@ +#include "enacl.h" +#include "erl_nif.h" + +ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) { + return enif_make_tuple2(env, enif_make_atom(env, "error"), + enif_make_atom(env, error_atom)); +} diff --git a/c_src/enacl.h b/c_src/enacl.h new file mode 100644 index 0000000..e1fc1af --- /dev/null +++ b/c_src/enacl.h @@ -0,0 +1,13 @@ +#ifndef ENACL_H +#define ENACL_H + +#include "erl_nif.h" + +#define ATOM_OK "ok" +#define ATOM_ERROR "error" +#define ATOM_TRUE "true" +#define ATOM_FALSE "false" + +ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *, char *); + +#endif diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 079246f..ccc6ebe 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1,15 +1,11 @@ #include "erl_nif.h" +#include #include -#include +#include "enacl.h" +#include "generichash.h" -#define ATOM_OK "ok" -#define ATOM_ERROR "error" -#define ATOM_TRUE "true" -#define ATOM_FALSE "false" - -#define CRYPTO_GENERICHASH_STATE_RESOURCE "crypto_generichash_state" #define CRYPTO_SIGN_STATE_RESOURCE "crypto_sign_state" #ifdef ERL_NIF_DIRTY_JOB_CPU_BOUND @@ -25,21 +21,13 @@ /* Errors */ /* These are global variables for resource types */ -static ErlNifResourceType *generichash_state_type = NULL; static ErlNifResourceType *sign_state_type = NULL; -static ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) { - return enif_make_tuple2(env, enif_make_atom(env, "error"), - enif_make_atom(env, error_atom)); -} - /* Initialization */ static int enif_crypto_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info) { // Create a new resource type for crypto_generichash_state - if (!(generichash_state_type = enif_open_resource_type( - env, NULL, CRYPTO_GENERICHASH_STATE_RESOURCE, NULL, - ERL_NIF_RT_CREATE, NULL))) { + if (!enacl_init_generic_hash_ctx(env)) { return -1; } // Create a new resource type for crypto_sign_state @@ -52,25 +40,6 @@ static int enif_crypto_load(ErlNifEnv *env, void **priv_data, return sodium_init(); } -/* Low-level functions (Hashing, String Equality, ...) */ -static ERL_NIF_TERM enif_crypto_hash(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary input; - ErlNifBinary result; - - if ((argc != 1) || (!enif_inspect_iolist_as_binary(env, argv[0], &input))) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_hash_BYTES, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_hash(result.data, input.data, input.size); - - return enif_make_binary(env, &result); -} - static ERL_NIF_TERM enif_crypto_verify_16(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary x, y; @@ -1764,227 +1733,6 @@ enif_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, return enif_make_binary(env, &message); } -/* - * Generic hash - */ -static ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_BYTES); -} - -static ERL_NIF_TERM -enif_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_BYTES_MIN); -} - -static ERL_NIF_TERM -enif_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_BYTES_MAX); -} - -static ERL_NIF_TERM -enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_KEYBYTES); -} - -static ERL_NIF_TERM -enif_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_KEYBYTES_MIN); -} - -static ERL_NIF_TERM -enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_generichash_KEYBYTES_MAX); -} - -static ERL_NIF_TERM enif_crypto_generichash(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary hash, message, key; - - unsigned hashSize; - - // Validate the arguments - if ((argc != 3) || (!enif_get_uint(env, argv[0], &hashSize)) || - (!enif_inspect_binary(env, argv[1], &message)) || - (!enif_inspect_binary(env, argv[2], &key))) { - return enif_make_badarg(env); - } - - // Verify that hash size is - // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX - if ((hashSize < crypto_generichash_BYTES_MIN) || - (hashSize > crypto_generichash_BYTES_MAX)) { - return nacl_error_tuple(env, "invalid_hash_size"); - } - - // validate key size - unsigned char *k = key.data; - if (0 == key.size) { - k = NULL; - } else if (key.size < crypto_generichash_KEYBYTES_MIN || - key.size > crypto_generichash_KEYBYTES_MAX) { - return nacl_error_tuple(env, "invalid_key_size"); - } - - // allocate memory for hash - if (!enif_alloc_binary(hashSize, &hash)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - // calculate hash - if (0 != crypto_generichash(hash.data, hash.size, message.data, message.size, - k, key.size)) { - enif_release_binary(&hash); - return nacl_error_tuple(env, "hash_error"); - } - - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret = enif_make_binary(env, &hash); - - return enif_make_tuple2(env, ok, ret); -} - -static crypto_generichash_state *align64(void *ptr) { - if ((unsigned long)ptr % 64 == 0) - return ptr; - return (unsigned long)ptr + (64 - ((unsigned long)ptr % 64)); -} - -static ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary key; - - unsigned hashSize; - - // Validate the arguments - if ((argc != 2) || (!enif_get_uint(env, argv[0], &hashSize)) || - (!enif_inspect_binary(env, argv[1], &key))) { - return enif_make_badarg(env); - } - - // Verify that hash size is - // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX - if ((hashSize < crypto_generichash_BYTES_MIN) || - (hashSize > crypto_generichash_BYTES_MAX)) { - return nacl_error_tuple(env, "invalid_hash_size"); - } - - // validate key size - unsigned char *k = key.data; - if (0 == key.size) { - k = NULL; - } else if (key.size < crypto_generichash_KEYBYTES_MIN || - key.size > crypto_generichash_KEYBYTES_MAX) { - return nacl_error_tuple(env, "invalid_key_size"); - } - - // Create a resource for hash state (+ 60 to make room for 64-byte alignment) - void *state = enif_alloc_resource(generichash_state_type, - crypto_generichash_statebytes() + 60); - if (!state) { - return nacl_error_tuple(env, "alloc_failed"); - } - - // Call the library function - if (0 != crypto_generichash_init(align64(state), k, key.size, hashSize)) { - enif_release_resource(state); - return nacl_error_tuple(env, "hash_init_error"); - } - - // Create return values - ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate"); - ERL_NIF_TERM e2 = argv[0]; - ERL_NIF_TERM e3 = enif_make_resource(env, state); - - // release dynamically allocated memory to erlang to mange - enif_release_resource(state); - - // return a tuple - return enif_make_tuple3(env, e1, e2, e3); -} - -static ERL_NIF_TERM enif_crypto_generichash_update(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary message; - - unsigned hashSize; - - void *state; - - // Validate the arguments - if ((argc != 3) || (!enif_get_uint(env, argv[0], &hashSize)) || - (!enif_get_resource(env, argv[1], generichash_state_type, - (void **)&state)) || - (!enif_inspect_binary(env, argv[2], &message))) { - return enif_make_badarg(env); - } - - // Verify that hash size is - // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX - if ((hashSize < crypto_generichash_BYTES_MIN) || - (hashSize > crypto_generichash_BYTES_MAX)) { - return nacl_error_tuple(env, "invalid_hash_size"); - } - - // Update hash state - if (0 != - crypto_generichash_update(align64(state), message.data, message.size)) { - return nacl_error_tuple(env, "hash_update_error"); - } - - // Generate return value - ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate"); - ERL_NIF_TERM e2 = argv[0]; - ERL_NIF_TERM e3 = enif_make_resource(env, state); - - // return a tuple - return enif_make_tuple3(env, e1, e2, e3); -} - -static ERL_NIF_TERM enif_crypto_generichash_final(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary hash; - - unsigned hashSize; - - void *state; - - // Validate the arguments - if ((argc != 2) || (!enif_get_uint(env, argv[0], &hashSize)) || - (!enif_get_resource(env, argv[1], generichash_state_type, - (void **)&state))) { - return enif_make_badarg(env); - } - - // Verify that hash size is - // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX - if ((hashSize < crypto_generichash_BYTES_MIN) || - (hashSize > crypto_generichash_BYTES_MAX)) { - return nacl_error_tuple(env, "invalid_hash_size"); - } - - // allocate memory for hash - if (!enif_alloc_binary(hashSize, &hash)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - // calculate hash - if (0 != crypto_generichash_final(align64(state), hash.data, hash.size)) { - enif_release_binary(&hash); - return nacl_error_tuple(env, "hash_error"); - } - - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret = enif_make_binary(env, &hash); - - return enif_make_tuple2(env, ok, ret); -} - /* Tie the knot to the Erlang world */ static ErlNifFunc nif_funcs[] = { {"crypto_box_NONCEBYTES", 0, enif_crypto_box_NONCEBYTES}, @@ -2091,8 +1839,8 @@ static ErlNifFunc nif_funcs[] = { erl_nif_dirty_job_cpu_bound_macro("crypto_onetimeauth_verify", 3, enif_crypto_onetimeauth_verify), - {"crypto_hash_b", 1, enif_crypto_hash}, - erl_nif_dirty_job_cpu_bound_macro("crypto_hash", 1, enif_crypto_hash), + {"crypto_hash_b", 1, enacl_crypto_hash}, + erl_nif_dirty_job_cpu_bound_macro("crypto_hash", 1, enacl_crypto_hash), {"crypto_verify_16", 2, enif_crypto_verify_16}, {"crypto_verify_32", 2, enif_crypto_verify_32}, {"sodium_memzero", 1, enif_sodium_memzero}, @@ -2178,10 +1926,10 @@ static ErlNifFunc nif_funcs[] = { enif_crypto_generichash_KEYBYTES_MIN}, {"crypto_generichash_KEYBYTES_MAX", 0, enif_crypto_generichash_KEYBYTES_MAX}, - {"crypto_generichash", 3, enif_crypto_generichash}, - {"crypto_generichash_init", 2, enif_crypto_generichash_init}, - {"crypto_generichash_update", 3, enif_crypto_generichash_update}, - {"crypto_generichash_final", 2, enif_crypto_generichash_final} + {"crypto_generichash", 3, enacl_crypto_generichash}, + {"crypto_generichash_init", 2, enacl_crypto_generichash_init}, + {"crypto_generichash_update", 3, enacl_crypto_generichash_update}, + {"crypto_generichash_final", 2, enacl_crypto_generichash_final} }; diff --git a/c_src/generichash.c b/c_src/generichash.c new file mode 100644 index 0000000..8823adf --- /dev/null +++ b/c_src/generichash.c @@ -0,0 +1,295 @@ +#include "erl_nif.h" + +#include + +#include "enacl.h" +#include "generichash.h" + +typedef struct enacl_generichash_ctx { + // The hash state + crypto_generichash_state *ctx; + // Is the context alive? + int alive; +} enacl_generichash_ctx; + +static ErlNifResourceType *enacl_generic_hash_ctx_rtype; + +static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env, + enacl_generichash_ctx *); + +int enacl_init_generic_hash_ctx(ErlNifEnv *env) { + enacl_generic_hash_ctx_rtype = + enif_open_resource_type(env, NULL, "enacl_generichash_context", + (ErlNifResourceDtor *)enacl_generic_hash_ctx_dtor, + ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL); + + if (enacl_generic_hash_ctx_rtype == NULL) + goto err; + + return 1; + +err: + return 0; +} + +static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env, + enacl_generichash_ctx *obj) { + if (!obj->alive) { + return; + } + + sodium_free(obj->ctx); + return; +} + +/* + * Generic hash + */ +ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_BYTES); +} + +ERL_NIF_TERM enif_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_BYTES_MIN); +} + +ERL_NIF_TERM enif_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_BYTES_MAX); +} + +ERL_NIF_TERM enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_KEYBYTES); +} + +ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_KEYBYTES_MIN); +} + +ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_generichash_KEYBYTES_MAX); +} + +ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary hash, message, key; + unsigned hashSize; + ERL_NIF_TERM ret; + + // Validate the arguments + if ((argc != 3) || (!enif_get_uint(env, argv[0], &hashSize)) || + (!enif_inspect_binary(env, argv[1], &message)) || + (!enif_inspect_binary(env, argv[2], &key))) + goto bad_arg; + + // Verify that hash size is + // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX + if ((hashSize < crypto_generichash_BYTES_MIN) || + (hashSize > crypto_generichash_BYTES_MAX)) { + ret = nacl_error_tuple(env, "invalid_hash_size"); + goto done; + } + + // validate key size + unsigned char *k = key.data; + if (0 == key.size) { + k = NULL; + } else if (key.size < crypto_generichash_KEYBYTES_MIN || + key.size > crypto_generichash_KEYBYTES_MAX) { + ret = nacl_error_tuple(env, "invalid_key_size"); + goto done; + } + + // allocate memory for hash + if (!enif_alloc_binary(hashSize, &hash)) { + ret = nacl_error_tuple(env, "alloc_failed"); + goto done; + } + + // calculate hash + if (0 != crypto_generichash(hash.data, hash.size, message.data, message.size, + k, key.size)) { + ret = nacl_error_tuple(env, "hash_error"); + goto release; + } + + ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret_hash = enif_make_binary(env, &hash); + + ret = enif_make_tuple2(env, ok, ret_hash); + goto done; + +bad_arg: + return enif_make_badarg(env); +release: + enif_release_binary(&hash); +done: + return ret; +} + +ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary key; + unsigned hash_size; + enacl_generichash_ctx *obj = NULL; + ERL_NIF_TERM ret; + + // Validate the arguments + if ((argc != 2) || (!enif_get_uint(env, argv[0], &hash_size)) || + (!enif_inspect_binary(env, argv[1], &key))) { + goto bad_arg; + } + + // Verify that hash size is + // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX + if ((hash_size <= crypto_generichash_BYTES_MIN) || + (hash_size >= crypto_generichash_BYTES_MAX)) { + ret = nacl_error_tuple(env, "invalid_hash_size"); + goto done; + } + + // validate key size + unsigned char *k = key.data; + if (0 == key.size) { + k = NULL; + } else if (key.size <= crypto_generichash_KEYBYTES_MIN || + key.size >= crypto_generichash_KEYBYTES_MAX) { + ret = nacl_error_tuple(env, "invalid_key_size"); + goto done; + } + + // Create the resource + if ((obj = enif_alloc_resource(enacl_generic_hash_ctx_rtype, + sizeof(enacl_generichash_ctx))) == NULL) { + goto err; + } + + // Allocate the state context via libsodium + // Note that this ensures a 64byte alignment for the resource + // And also protects the resource via guardpages + obj->ctx = NULL; + obj->alive = 0; + obj->ctx = (crypto_generichash_state *)sodium_malloc( + crypto_generichash_statebytes()); + if (obj->ctx == NULL) { + goto err; + } + obj->alive = 1; + + // Call the library function + if (0 != crypto_generichash_init(obj->ctx, k, key.size, hash_size)) { + ret = nacl_error_tuple(env, "hash_init_error"); + goto done; + } + + // Create return values + ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate"); + ERL_NIF_TERM e2 = argv[0]; + ERL_NIF_TERM e3 = enif_make_resource(env, obj); + + ret = enif_make_tuple3(env, e1, e2, e3); + goto done; +bad_arg: + return enif_make_badarg(env); + +err: + ret = nacl_error_tuple(env, "internal_error"); + if (obj != NULL) { + if (obj->alive) { + sodium_free(obj->ctx); + } + } +done: + if (obj != NULL) { + enif_release_resource(obj); + } + return ret; +} + +ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ERL_NIF_TERM ret; + ErlNifBinary data; + unsigned int data_size; + enacl_generichash_ctx *obj = NULL; + + // Validate the arguments + if (argc != 3) + goto bad_arg; + if (!enif_get_uint(env, argv[0], &data_size)) + goto bad_arg; + if (!enif_get_resource(env, argv[1], + (ErlNifResourceType *)enacl_generic_hash_ctx_rtype, + (void **)&obj)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &data)) + goto bad_arg; + + // Update hash state + if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) { + ret = nacl_error_tuple(env, "hash_update_error"); + goto done; + } + + ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate"); + ERL_NIF_TERM e2 = argv[0]; + ERL_NIF_TERM e3 = argv[1]; + + ret = enif_make_tuple3(env, e1, e2, e3); + goto done; + +bad_arg: + return enif_make_badarg(env); +done: + return ret; +} + +ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ERL_NIF_TERM ret; + ErlNifBinary hash; + unsigned int hash_size; + enacl_generichash_ctx *obj = NULL; + + if (argc != 2) + goto bad_arg; + if (!enif_get_uint(env, argv[0], &hash_size)) + goto bad_arg; + if (!enif_get_resource(env, argv[1], enacl_generic_hash_ctx_rtype, + (void **)&obj)) + goto bad_arg; + + if ((hash_size <= crypto_generichash_BYTES_MIN) || + (hash_size >= crypto_generichash_BYTES_MAX)) { + ret = nacl_error_tuple(env, "invalid_hash_size"); + goto done; + } + + if (!enif_alloc_binary(hash_size, &hash)) { + ret = nacl_error_tuple(env, "alloc_failed"); + goto done; + } + + if (0 != crypto_generichash_final(obj->ctx, hash.data, hash.size)) { + ret = nacl_error_tuple(env, "hash_error"); + goto release; + } + + ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM h = enif_make_binary(env, &hash); + + ret = enif_make_tuple2(env, ok, h); + goto done; + +bad_arg: + return enif_make_badarg(env); +release: + enif_release_binary(&hash); +done: + return ret; +} diff --git a/c_src/generichash.h b/c_src/generichash.h new file mode 100644 index 0000000..a348893 --- /dev/null +++ b/c_src/generichash.h @@ -0,0 +1,30 @@ +#ifndef ENACL_GENERICHASH_H +#define ENACL_GENERICHASH_H + +int enacl_init_generic_hash_ctx(ErlNifEnv *env); + +ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enif_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enif_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); + +ERL_NIF_TERM enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); + +ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); + +ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); + +#endif \ No newline at end of file diff --git a/c_src/hash.c b/c_src/hash.c new file mode 100644 index 0000000..5f9be56 --- /dev/null +++ b/c_src/hash.c @@ -0,0 +1,30 @@ +#include "erl_nif.h" + +#include + +#include "hash.h" + +ERL_NIF_TERM enacl_crypto_hash_nif(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary input; + ErlNifBinary result; + ERL_NIF_TERM ret; + + if ((argc != 1) || (!enif_inspect_iolist_as_binary(env, argv[0], &input))) + goto bad_arg; + + if (!enif_alloc_binary(crypto_hash_BYTES, &result)) + goto err; + + crypto_hash(result.data, input.data, input.size); + ret = enif_make_binary(env, &result); + goto done; + +bad_arg: + return enif_make_badarg(env); + +err: + ret = nacl_error_tuple(env, "alloc_failed"); +done: + return ret; +} diff --git a/c_src/hash.h b/c_src/hash.h new file mode 100644 index 0000000..7ade398 --- /dev/null +++ b/c_src/hash.h @@ -0,0 +1,6 @@ +#ifndef ENACL_HASH_H +#define ENACL_HASH_H + +ERL_NIF_TERM enacl_crypto_hash(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); +#endif \ No newline at end of file From 6e057cbd484e62a60fd14247c08b383b2ae89d29 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 17 Jan 2020 15:47:51 +0100 Subject: [PATCH 027/162] The sodium MIN/MAX values are incusive --- c_src/generichash.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/c_src/generichash.c b/c_src/generichash.c index 8823adf..d89e546 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -89,8 +89,8 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, // Verify that hash size is // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX - if ((hashSize < crypto_generichash_BYTES_MIN) || - (hashSize > crypto_generichash_BYTES_MAX)) { + if ((hashSize <= crypto_generichash_BYTES_MIN) || + (hashSize >= crypto_generichash_BYTES_MAX)) { ret = nacl_error_tuple(env, "invalid_hash_size"); goto done; } @@ -99,8 +99,8 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, unsigned char *k = key.data; if (0 == key.size) { k = NULL; - } else if (key.size < crypto_generichash_KEYBYTES_MIN || - key.size > crypto_generichash_KEYBYTES_MAX) { + } else if (key.size <= crypto_generichash_KEYBYTES_MIN || + key.size >= crypto_generichash_KEYBYTES_MAX) { ret = nacl_error_tuple(env, "invalid_key_size"); goto done; } From 463cae05d511315f587829dc796e29802d85c46f Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 17 Jan 2020 16:03:16 +0100 Subject: [PATCH 028/162] Bump for first additions --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef4421d..6727dd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added Win32 build support (Tino Breddin) - Added a nix shell for easier development +### Changed +- Split the C code over multiple files for easier maintenance. +- Rewrote the generichash routines to be more consistent. We are now more-or-less + following the style of the Erlang/OTP `crypto` library. While here, make sure + we clean up correctly and that we don't accidentally mis-ref-count data. The + code is a bit more goto heavy, but this style is surprisingly common in C code. + ### Fixes - Fix a resource leak in generichash/sign init/update/final. - Clang static analysis warnings (Thomas Arts) From f5918c015680fe108fc037e1ade517b465d128ff Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 17 Jan 2020 16:03:30 +0100 Subject: [PATCH 029/162] Fix compilation --- c_src/enacl_nif.c | 1 + 1 file changed, 1 insertion(+) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index ccc6ebe..ed4f310 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -5,6 +5,7 @@ #include "enacl.h" #include "generichash.h" +#include "hash.h" #define CRYPTO_SIGN_STATE_RESOURCE "crypto_sign_state" From df1b134f73e7b318cc9609d8323f878498bcb5d5 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 17 Jan 2020 16:06:15 +0100 Subject: [PATCH 030/162] Track liveness stateReject updates to finalized generichash states. --- CHANGELOG.md | 1 + c_src/generichash.c | 47 ++++++++++++++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6727dd2..58371f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. following the style of the Erlang/OTP `crypto` library. While here, make sure we clean up correctly and that we don't accidentally mis-ref-count data. The code is a bit more goto heavy, but this style is surprisingly common in C code. +- The code now rejects updates to generichash states which were already finalized. ### Fixes - Fix a resource leak in generichash/sign init/update/final. diff --git a/c_src/generichash.c b/c_src/generichash.c index d89e546..a8a6642 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -78,19 +78,23 @@ ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc, ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary hash, message, key; - unsigned hashSize; + unsigned hash_size; ERL_NIF_TERM ret; // Validate the arguments - if ((argc != 3) || (!enif_get_uint(env, argv[0], &hashSize)) || - (!enif_inspect_binary(env, argv[1], &message)) || - (!enif_inspect_binary(env, argv[2], &key))) + if (argc != 3) + goto bad_arg; + if (!enif_get_uint(env, argv[0], &hash_size)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &message)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &key)) goto bad_arg; // Verify that hash size is // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX - if ((hashSize <= crypto_generichash_BYTES_MIN) || - (hashSize >= crypto_generichash_BYTES_MAX)) { + if ((hash_size <= crypto_generichash_BYTES_MIN) || + (hash_size >= crypto_generichash_BYTES_MAX)) { ret = nacl_error_tuple(env, "invalid_hash_size"); goto done; } @@ -106,7 +110,7 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, } // allocate memory for hash - if (!enif_alloc_binary(hashSize, &hash)) { + if (!enif_alloc_binary(hash_size, &hash)) { ret = nacl_error_tuple(env, "alloc_failed"); goto done; } @@ -140,13 +144,14 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, ERL_NIF_TERM ret; // Validate the arguments - if ((argc != 2) || (!enif_get_uint(env, argv[0], &hash_size)) || - (!enif_inspect_binary(env, argv[1], &key))) { + if (argc != 2) + goto bad_arg; + if (!enif_get_uint(env, argv[0], &hash_size)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &key)) goto bad_arg; - } - // Verify that hash size is - // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX + // Verify that hash size is valid if ((hash_size <= crypto_generichash_BYTES_MIN) || (hash_size >= crypto_generichash_BYTES_MAX)) { ret = nacl_error_tuple(env, "invalid_hash_size"); @@ -184,7 +189,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, // Call the library function if (0 != crypto_generichash_init(obj->ctx, k, key.size, hash_size)) { ret = nacl_error_tuple(env, "hash_init_error"); - goto done; + goto err; } // Create return values @@ -202,6 +207,7 @@ err: if (obj != NULL) { if (obj->alive) { sodium_free(obj->ctx); + obj->alive = 0; // Maintain the invariant consistently } } done: @@ -230,6 +236,11 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, if (!enif_inspect_binary(env, argv[2], &data)) goto bad_arg; + if (!obj->alive) { + ret = nacl_error_tuple(env, "finalized"); + goto done; + } + // Update hash state if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) { ret = nacl_error_tuple(env, "hash_update_error"); @@ -264,6 +275,11 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, (void **)&obj)) goto bad_arg; + if (!obj->alive) { + ret = nacl_error_tuple(env, "finalized"); + goto done; + } + if ((hash_size <= crypto_generichash_BYTES_MIN) || (hash_size >= crypto_generichash_BYTES_MAX)) { ret = nacl_error_tuple(env, "invalid_hash_size"); @@ -280,6 +296,11 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, goto release; } + // Finalize the object such that it cannot be reused by accident + if (obj->ctx) + sodium_free(obj->ctx); + obj->alive = 0; + ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); ERL_NIF_TERM h = enif_make_binary(env, &hash); From d7e83dd56943c1d034558dcc3c8fbd86f7c898ca Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 17 Jan 2020 16:24:51 +0100 Subject: [PATCH 031/162] Track outlen inside the generichash wrapper --- CHANGELOG.md | 3 +++ c_src/enacl_nif.c | 4 ++-- c_src/generichash.c | 55 +++++++++++++++------------------------------ src/enacl.erl | 8 +++---- src/enacl_nif.erl | 8 +++---- 5 files changed, 31 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58371f0..30e5f4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. we clean up correctly and that we don't accidentally mis-ref-count data. The code is a bit more goto heavy, but this style is surprisingly common in C code. - The code now rejects updates to generichash states which were already finalized. +- We now track the desired outlen of a generichash operation in the opaque NIF + resource rather than on the Erlang side. This avoids some checks in the code, + and streamlines a good deal of the interface. ### Fixes - Fix a resource leak in generichash/sign init/update/final. diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index ed4f310..22bf062 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1929,8 +1929,8 @@ static ErlNifFunc nif_funcs[] = { enif_crypto_generichash_KEYBYTES_MAX}, {"crypto_generichash", 3, enacl_crypto_generichash}, {"crypto_generichash_init", 2, enacl_crypto_generichash_init}, - {"crypto_generichash_update", 3, enacl_crypto_generichash_update}, - {"crypto_generichash_final", 2, enacl_crypto_generichash_final} + {"crypto_generichash_update", 2, enacl_crypto_generichash_update}, + {"crypto_generichash_final", 1, enacl_crypto_generichash_final} }; diff --git a/c_src/generichash.c b/c_src/generichash.c index a8a6642..f422578 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -6,10 +6,9 @@ #include "generichash.h" typedef struct enacl_generichash_ctx { - // The hash state - crypto_generichash_state *ctx; - // Is the context alive? - int alive; + crypto_generichash_state *ctx; // Underlying hash state from sodium + int alive; // Is the context still valid for updates/finalizes? + int outlen; // Final size of the hash } enacl_generichash_ctx; static ErlNifResourceType *enacl_generic_hash_ctx_rtype; @@ -24,12 +23,9 @@ int enacl_init_generic_hash_ctx(ErlNifEnv *env) { ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL); if (enacl_generic_hash_ctx_rtype == NULL) - goto err; + return 0; return 1; - -err: - return 0; } static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env, @@ -38,7 +34,9 @@ static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env, return; } - sodium_free(obj->ctx); + if (obj->ctx) + sodium_free(obj->ctx); + return; } @@ -179,25 +177,23 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, // And also protects the resource via guardpages obj->ctx = NULL; obj->alive = 0; + obj->outlen = 0; + obj->ctx = (crypto_generichash_state *)sodium_malloc( crypto_generichash_statebytes()); if (obj->ctx == NULL) { goto err; } obj->alive = 1; + obj->outlen = hash_size; // Call the library function - if (0 != crypto_generichash_init(obj->ctx, k, key.size, hash_size)) { + if (0 != crypto_generichash_init(obj->ctx, k, key.size, obj->outlen)) { ret = nacl_error_tuple(env, "hash_init_error"); goto err; } - // Create return values - ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate"); - ERL_NIF_TERM e2 = argv[0]; - ERL_NIF_TERM e3 = enif_make_resource(env, obj); - - ret = enif_make_tuple3(env, e1, e2, e3); + ret = enif_make_resource(env, obj); goto done; bad_arg: return enif_make_badarg(env); @@ -225,15 +221,13 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, enacl_generichash_ctx *obj = NULL; // Validate the arguments - if (argc != 3) + if (argc != 2) goto bad_arg; - if (!enif_get_uint(env, argv[0], &data_size)) - goto bad_arg; - if (!enif_get_resource(env, argv[1], + if (!enif_get_resource(env, argv[0], (ErlNifResourceType *)enacl_generic_hash_ctx_rtype, (void **)&obj)) goto bad_arg; - if (!enif_inspect_binary(env, argv[2], &data)) + if (!enif_inspect_binary(env, argv[1], &data)) goto bad_arg; if (!obj->alive) { @@ -247,11 +241,7 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, goto done; } - ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate"); - ERL_NIF_TERM e2 = argv[0]; - ERL_NIF_TERM e3 = argv[1]; - - ret = enif_make_tuple3(env, e1, e2, e3); + ret = argv[0]; goto done; bad_arg: @@ -264,12 +254,9 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ERL_NIF_TERM ret; ErlNifBinary hash; - unsigned int hash_size; enacl_generichash_ctx *obj = NULL; - if (argc != 2) - goto bad_arg; - if (!enif_get_uint(env, argv[0], &hash_size)) + if (argc != 1) goto bad_arg; if (!enif_get_resource(env, argv[1], enacl_generic_hash_ctx_rtype, (void **)&obj)) @@ -280,13 +267,7 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, goto done; } - if ((hash_size <= crypto_generichash_BYTES_MIN) || - (hash_size >= crypto_generichash_BYTES_MAX)) { - ret = nacl_error_tuple(env, "invalid_hash_size"); - goto done; - } - - if (!enif_alloc_binary(hash_size, &hash)) { + if (!enif_alloc_binary(obj->outlen, &hash)) { ret = nacl_error_tuple(env, "alloc_failed"); goto done; } diff --git a/src/enacl.erl b/src/enacl.erl index 3a9daf8..d2ab386 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -354,11 +354,11 @@ generichash(HashSize, Message) -> generichash_init(HashSize, Key) -> enacl_nif:crypto_generichash_init(HashSize, Key). -generichash_update({hashstate, HashSize, HashState}, Message) -> - enacl_nif:crypto_generichash_update(HashSize, HashState, Message). +generichash_update(State, Message) -> + enacl_nif:crypto_generichash_update(State, Message). -generichash_final({hashstate, HashSize, HashState}) -> - enacl_nif:crypto_generichash_final(HashSize, HashState). +generichash_final(State) -> + enacl_nif:crypto_generichash_final(State). -type pwhash_limit() :: interactive | moderate | sensitive | pos_integer(). diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index b971c7f..a6d6ec5 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -162,8 +162,8 @@ crypto_generichash_KEYBYTES_MAX/0, crypto_generichash/3, crypto_generichash_init/2, - crypto_generichash_update/3, - crypto_generichash_final/2 + crypto_generichash_update/2, + crypto_generichash_final/1 ]). %% Access to the RNG @@ -202,8 +202,8 @@ crypto_generichash_KEYBYTES_MAX() -> erlang:nif_error(nif_not_loaded). crypto_generichash(_HashSize, _Message, _Key) -> erlang:nif_error(nif_not_loaded). crypto_generichash_init(_HashSize, _Key) -> erlang:nif_error(nif_not_loaded). -crypto_generichash_update(_HashSize, _HashState, _Message) -> erlang:nif_error(nif_not_loaded). -crypto_generichash_final(_HashSize, _HashState) -> erlang:nif_error(nif_not_loaded). +crypto_generichash_update(_HashState, _Message) -> erlang:nif_error(nif_not_loaded). +crypto_generichash_final(_HashState) -> erlang:nif_error(nif_not_loaded). crypto_pwhash(_Password, _Salt, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str(_Password, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). From 0f39bae64c385bd61ff7fb52d11be70545270b7c Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sun, 19 Jan 2020 12:07:18 +0100 Subject: [PATCH 032/162] Fix name of C function The name of the generichash function was wrong, so it was not possible to find it when loading the NIF. --- c_src/hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c_src/hash.c b/c_src/hash.c index 5f9be56..21d6aa8 100644 --- a/c_src/hash.c +++ b/c_src/hash.c @@ -4,8 +4,8 @@ #include "hash.h" -ERL_NIF_TERM enacl_crypto_hash_nif(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +ERL_NIF_TERM enacl_crypto_hash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary input; ErlNifBinary result; ERL_NIF_TERM ret; From 61345d0b6e06a5ce64a7145276355824eba5094d Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sun, 19 Jan 2020 12:08:05 +0100 Subject: [PATCH 033/162] Fix argument handling in generichash_final If supplying 1 argument, it is in argv[0], not argv[1] --- c_src/generichash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c_src/generichash.c b/c_src/generichash.c index f422578..9993bf7 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -258,7 +258,7 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, if (argc != 1) goto bad_arg; - if (!enif_get_resource(env, argv[1], enacl_generic_hash_ctx_rtype, + if (!enif_get_resource(env, argv[0], enacl_generic_hash_ctx_rtype, (void **)&obj)) goto bad_arg; From 0047af286f73b05b5438fefa2d8de8a9cbdf72f2 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sun, 19 Jan 2020 12:08:17 +0100 Subject: [PATCH 034/162] Provide a test suite for Generichash --- CHANGELOG.md | 2 +- test/enacl_SUITE.erl | 86 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 test/enacl_SUITE.erl diff --git a/CHANGELOG.md b/CHANGELOG.md index 30e5f4e..904b78d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added a nix shell for easier development ### Changed -- Split the C code over multiple files for easier maintenance. +- Started a split the C code over multiple files for easier maintenance. - Rewrote the generichash routines to be more consistent. We are now more-or-less following the style of the Erlang/OTP `crypto` library. While here, make sure we clean up correctly and that we don't accidentally mis-ref-count data. The diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl new file mode 100644 index 0000000..3470b3e --- /dev/null +++ b/test/enacl_SUITE.erl @@ -0,0 +1,86 @@ +-module(enacl_SUITE). +-include_lib("common_test/include/ct.hrl"). + +-compile([export_all, nowarn_export_all]). + +suite() -> + [{timetrap, {seconds, 30}}]. + +init_per_group(_Group, Config) -> + Config. + +end_per_group(_Group, _Config) -> + ok. + +init_per_suite(Config) -> + application:ensure_all_started(enacl), + Config. + +end_per_suite(_Config) -> + application:stop(enacl), + ok. + +init_per_testcase(x, Config) -> + {ok, _} = dbg:tracer(), + dbg:p(all, c), + dbg:tpl(graphql_execute, lookup_field, '_', cx), + Config; +init_per_testcase(_Case, Config) -> + Config. + +end_per_testcase(x, _Config) -> + dbg:stop_clear(), + ok; +end_per_testcase(_Case, _Config) -> + ok. + +groups() -> + GenericHashNeg = {generichash_neg, [shuffle, parallel], + [generichash_basic_neg]}, + GenericHash = {generichash, [shuffle, parallel, {repeat, 100}], + [generichash_basic_pos, + generichash_chunked]}, + + [GenericHashNeg, GenericHash]. + +all() -> + [{group, generichash}]. + +%% -- BASIC -------------------------------------- +generichash_basic_neg(_Config) -> + %% Negative generichash invocations + Msg = <<"I've seen things you people wouldn't believe: attack ships on fire off the shoulder of Orion. " + "I've watched C-beams glitter in the dark near the Tannhäuser Gate. " + "All those... moments... will be lost... in time, like... tears... in rain">>, + Key = <<"Hash Key 123456789">>, + {error, invalid_hash_size} = enacl:generichash(9, Msg, Key), + {error, invalid_hash_size} = enacl:generichash(65, Msg, Key), + {error, invalid_key_size} = enacl:generichash(32, Msg, <<"Small">>), + ok. + +generichash_basic_pos(_Config) -> + Msg = <<"I've seen things you people wouldn't believe: attack ships on fire off the shoulder of Orion. " + "I've watched C-beams glitter in the dark near the Tannhäuser Gate. " + "All those... moments... will be lost... in time, like... tears... in rain">>, + Key = <<"Hash Key 123456789">>, + {ok,<<189,104,45,187,170,229,212,4,121,43,137,74,241,173,181,77, + 67,211,133,70,196,6,128,97>>} = enacl:generichash(24, Msg, Key), + ok. + +generichash_chunked(_Config) -> + Msg = <<"I've seen things you people wouldn't believe: attack ships on fire off the shoulder of Orion. " + "I've watched C-beams glitter in the dark near the Tannhäuser Gate. " + "All those... moments... will be lost... in time, like... tears... in rain">>, + Key = <<"Hash Key 123456789">>, + State = enacl:generichash_init(24, Key), + State = generichash_chunked(State, Msg, 10000), + Expected = <<46,49,32,18,13,186,182,105,106,122,253,139,89,176,169,141, + 73,93,99,6,41,216,110,41>>, + {ok, Expected} = enacl:generichash_final(State), + ok. + +generichash_chunked(State, Msg, 0) -> State; +generichash_chunked(State, Msg, N) -> + State2 = enacl:generichash_update(State, Msg), + generichash_chunked(State2, Msg, N-1). + From 3ee5a94cafe36657568f6cffe1a442cbd53a162d Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sun, 19 Jan 2020 13:29:32 +0100 Subject: [PATCH 035/162] Split off AEAD functions to a separate file --- CHANGELOG.md | 5 ++ c_src/aead.c | 195 +++++++++++++++++++++++++++++++++++++++++++ c_src/aead.h | 46 ++++++++++ c_src/enacl_nif.c | 191 +----------------------------------------- test/enacl_SUITE.erl | 2 +- 5 files changed, 248 insertions(+), 191 deletions(-) create mode 100644 c_src/aead.c create mode 100644 c_src/aead.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 904b78d..a0b5343 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,10 +30,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. following the style of the Erlang/OTP `crypto` library. While here, make sure we clean up correctly and that we don't accidentally mis-ref-count data. The code is a bit more goto heavy, but this style is surprisingly common in C code. +- Use sodium's dynamic memory allocators. These guarantee 64bit alignment, and also + provide guard pages around the allocation, somewhat protecting it. It adds some + page table pressure compared to the current code, but is easier to maintain and + much cleaner code. - The code now rejects updates to generichash states which were already finalized. - We now track the desired outlen of a generichash operation in the opaque NIF resource rather than on the Erlang side. This avoids some checks in the code, and streamlines a good deal of the interface. +- Split AEAD routines off from the main enacl_nif.c file ### Fixes - Fix a resource leak in generichash/sign init/update/final. diff --git a/c_src/aead.c b/c_src/aead.c new file mode 100644 index 0000000..58f432a --- /dev/null +++ b/c_src/aead.c @@ -0,0 +1,195 @@ +#include "aead.h" +#include "enacl.h" +#include "erl_nif.h" + +#include + +/* + * AEAD ChaCha20 Poly1305 + */ +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_KEYBYTES); +} + +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_NPUBBYTES); +} + +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_ABYTES); +} + +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, + crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX); +} + +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ERL_NIF_TERM result; + ErlNifBinary key, nonce, ad, message, ciphertext; + + if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &ad)) || + (!enif_inspect_binary(env, argv[3], &message)) || + (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) || + (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)) { + return enif_make_badarg(env); + } + + do { + if (!enif_alloc_binary(message.size + + crypto_aead_chacha20poly1305_ietf_ABYTES, + &ciphertext)) { + result = nacl_error_tuple(env, "alloc_failed"); + continue; + } + + if (crypto_aead_chacha20poly1305_ietf_encrypt( + ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, + NULL, nonce.data, key.data) < 0) { + result = + nacl_error_tuple(env, "aead_chacha20poly1305_ietf_encrypt_failed"); + continue; + } + + result = enif_make_binary(env, &ciphertext); + } while (0); + + return result; +} + +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ERL_NIF_TERM result; + ErlNifBinary key, nonce, ad, message, ciphertext; + + if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &ad)) || + (!enif_inspect_binary(env, argv[3], &ciphertext)) || + (ciphertext.size < crypto_aead_chacha20poly1305_ietf_ABYTES) || + (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) || + (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)) { + return enif_make_badarg(env); + } + + do { + if (!enif_alloc_binary(ciphertext.size - + crypto_aead_chacha20poly1305_ietf_ABYTES, + &message)) { + result = nacl_error_tuple(env, "alloc_failed"); + continue; + } + + if (crypto_aead_chacha20poly1305_ietf_decrypt( + message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, + ad.size, nonce.data, key.data) < 0) { + result = + nacl_error_tuple(env, "aead_chacha20poly1305_ietf_decrypt_failed"); + continue; + } + + result = enif_make_binary(env, &message); + } while (0); + + return result; +} + +/* + * AEAD XChaCha20 Poly1305 + */ +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_KEYBYTES); +} + +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES); +} + +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_ABYTES); +} + +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, + crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX); +} + +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary key, nonce, ad, message, ciphertext; + + if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &ad)) || + (!enif_inspect_binary(env, argv[3], &message)) || + (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES) || + (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(message.size + + crypto_aead_xchacha20poly1305_ietf_ABYTES, + &ciphertext)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_aead_xchacha20poly1305_ietf_encrypt( + ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, + NULL, nonce.data, key.data) < 0) { + return nacl_error_tuple(env, "aead_xchacha20poly1305_ietf_encrypt_failed"); + } + + return enif_make_binary(env, &ciphertext); +} + +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary key, nonce, ad, message, ciphertext; + + if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &ad)) || + (!enif_inspect_binary(env, argv[3], &ciphertext)) || + (ciphertext.size < crypto_aead_xchacha20poly1305_ietf_ABYTES) || + (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES) || + (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(ciphertext.size - + crypto_aead_xchacha20poly1305_ietf_ABYTES, + &message)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_aead_xchacha20poly1305_ietf_decrypt( + message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, + ad.size, nonce.data, key.data) < 0) { + return nacl_error_tuple(env, "aead_xchacha20poly1305_ietf_decrypt_failed"); + } + + return enif_make_binary(env, &message); +} diff --git a/c_src/aead.h b/c_src/aead.h new file mode 100644 index 0000000..a342c6d --- /dev/null +++ b/c_src/aead.h @@ -0,0 +1,46 @@ +#ifndef ENACL_AEAD_H +#define ENACL_AEAD_H + +#include "erl_nif.h" + +/* AEAD ChaCha20 Poly1305 */ +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enif_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +/* AEAD XChaCha20 Poly1305 */ +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enif_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +#endif diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 22bf062..31a4ade 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -3,6 +3,7 @@ #include #include +#include "aead.h" #include "enacl.h" #include "generichash.h" #include "hash.h" @@ -1544,196 +1545,6 @@ static ERL_NIF_TERM enif_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, return retVal; } -/* - * AEAD ChaCha20 Poly1305 - */ -static ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_KEYBYTES); -} - -static ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_NPUBBYTES); -} - -static ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_ABYTES); -} - -static ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, - crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX); -} - -static ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ERL_NIF_TERM result; - ErlNifBinary key, nonce, ad, message, ciphertext; - - if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &ad)) || - (!enif_inspect_binary(env, argv[3], &message)) || - (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) || - (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)) { - return enif_make_badarg(env); - } - - do { - if (!enif_alloc_binary(message.size + - crypto_aead_chacha20poly1305_ietf_ABYTES, - &ciphertext)) { - result = nacl_error_tuple(env, "alloc_failed"); - continue; - } - - if (crypto_aead_chacha20poly1305_ietf_encrypt( - ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, - NULL, nonce.data, key.data) < 0) { - result = - nacl_error_tuple(env, "aead_chacha20poly1305_ietf_encrypt_failed"); - continue; - } - - result = enif_make_binary(env, &ciphertext); - } while (0); - - return result; -} - -static ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ERL_NIF_TERM result; - ErlNifBinary key, nonce, ad, message, ciphertext; - - if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &ad)) || - (!enif_inspect_binary(env, argv[3], &ciphertext)) || - (ciphertext.size < crypto_aead_chacha20poly1305_ietf_ABYTES) || - (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) || - (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)) { - return enif_make_badarg(env); - } - - do { - if (!enif_alloc_binary(ciphertext.size - - crypto_aead_chacha20poly1305_ietf_ABYTES, - &message)) { - result = nacl_error_tuple(env, "alloc_failed"); - continue; - } - - if (crypto_aead_chacha20poly1305_ietf_decrypt( - message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, - ad.size, nonce.data, key.data) < 0) { - result = - nacl_error_tuple(env, "aead_chacha20poly1305_ietf_decrypt_failed"); - continue; - } - - result = enif_make_binary(env, &message); - } while (0); - - return result; -} - -/* - * AEAD XChaCha20 Poly1305 - */ -static ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_KEYBYTES); -} - -static ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES); -} - -static ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_ABYTES); -} - -static ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, - crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX); -} - -static ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary key, nonce, ad, message, ciphertext; - - if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &ad)) || - (!enif_inspect_binary(env, argv[3], &message)) || - (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES) || - (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(message.size + - crypto_aead_xchacha20poly1305_ietf_ABYTES, - &ciphertext)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (crypto_aead_xchacha20poly1305_ietf_encrypt( - ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, - NULL, nonce.data, key.data) < 0) { - return nacl_error_tuple(env, "aead_xchacha20poly1305_ietf_encrypt_failed"); - } - - return enif_make_binary(env, &ciphertext); -} - -static ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary key, nonce, ad, message, ciphertext; - - if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &ad)) || - (!enif_inspect_binary(env, argv[3], &ciphertext)) || - (ciphertext.size < crypto_aead_xchacha20poly1305_ietf_ABYTES) || - (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES) || - (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(ciphertext.size - - crypto_aead_xchacha20poly1305_ietf_ABYTES, - &message)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (crypto_aead_xchacha20poly1305_ietf_decrypt( - message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, - ad.size, nonce.data, key.data) < 0) { - return nacl_error_tuple(env, "aead_xchacha20poly1305_ietf_decrypt_failed"); - } - - return enif_make_binary(env, &message); -} - /* Tie the knot to the Erlang world */ static ErlNifFunc nif_funcs[] = { {"crypto_box_NONCEBYTES", 0, enif_crypto_box_NONCEBYTES}, diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index 3470b3e..14326c1 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -79,7 +79,7 @@ generichash_chunked(_Config) -> {ok, Expected} = enacl:generichash_final(State), ok. -generichash_chunked(State, Msg, 0) -> State; +generichash_chunked(State, _Msg, 0) -> State; generichash_chunked(State, Msg, N) -> State2 = enacl:generichash_update(State, Msg), generichash_chunked(State2, Msg, N-1). From 4eaef57a7687282f77ac7f3eb6fa820cdb14fc13 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sun, 19 Jan 2020 13:32:15 +0100 Subject: [PATCH 036/162] Rename AEAD routines from enif_* to enacl_* --- c_src/aead.c | 48 +++++++++++++++++++++++------------------------ c_src/aead.h | 48 +++++++++++++++++++++++------------------------ c_src/enacl_nif.c | 24 ++++++++++++------------ 3 files changed, 60 insertions(+), 60 deletions(-) diff --git a/c_src/aead.c b/c_src/aead.c index 58f432a..5fa11e4 100644 --- a/c_src/aead.c +++ b/c_src/aead.c @@ -8,33 +8,33 @@ * AEAD ChaCha20 Poly1305 */ ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_KEYBYTES); } ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_NPUBBYTES); } ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_ABYTES); } ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX); } ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ERL_NIF_TERM result; ErlNifBinary key, nonce, ad, message, ciphertext; @@ -70,8 +70,8 @@ enif_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, } ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ERL_NIF_TERM result; ErlNifBinary key, nonce, ad, message, ciphertext; @@ -111,33 +111,33 @@ enif_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, * AEAD XChaCha20 Poly1305 */ ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_xchacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_KEYBYTES); } ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_xchacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES); } ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_ABYTES); } ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX( + ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX); } ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary key, nonce, ad, message, ciphertext; if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || @@ -165,8 +165,8 @@ enif_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, } ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary key, nonce, ad, message, ciphertext; if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || diff --git a/c_src/aead.h b/c_src/aead.h index a342c6d..8f2ce5b 100644 --- a/c_src/aead.h +++ b/c_src/aead.h @@ -5,42 +5,42 @@ /* AEAD ChaCha20 Poly1305 */ ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); -ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, +enacl_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); -ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, +enacl_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enif_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enacl_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enacl_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); /* AEAD XChaCha20 Poly1305 */ ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); -ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, +enacl_crypto_aead_xchacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_xchacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); -ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, +enacl_crypto_aead_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enif_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enacl_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +ERL_NIF_TERM +enacl_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); #endif diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 31a4ade..b1610c1 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1701,34 +1701,34 @@ static ErlNifFunc nif_funcs[] = { {"scramble_block_16", 2, enif_scramble_block_16}, {"crypto_aead_chacha20poly1305_KEYBYTES", 0, - enif_crypto_aead_chacha20poly1305_KEYBYTES}, + enacl_crypto_aead_chacha20poly1305_KEYBYTES}, {"crypto_aead_chacha20poly1305_NPUBBYTES", 0, - enif_crypto_aead_chacha20poly1305_NPUBBYTES}, + enacl_crypto_aead_chacha20poly1305_NPUBBYTES}, {"crypto_aead_chacha20poly1305_ABYTES", 0, - enif_crypto_aead_chacha20poly1305_ABYTES}, + enacl_crypto_aead_chacha20poly1305_ABYTES}, {"crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX", 0, - enif_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX}, + enacl_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX}, erl_nif_dirty_job_cpu_bound_macro( "crypto_aead_chacha20poly1305_encrypt", 4, - enif_crypto_aead_chacha20poly1305_encrypt), + enacl_crypto_aead_chacha20poly1305_encrypt), erl_nif_dirty_job_cpu_bound_macro( "crypto_aead_chacha20poly1305_decrypt", 4, - enif_crypto_aead_chacha20poly1305_decrypt), + enacl_crypto_aead_chacha20poly1305_decrypt), {"crypto_aead_xchacha20poly1305_KEYBYTES", 0, - enif_crypto_aead_xchacha20poly1305_KEYBYTES}, + enacl_crypto_aead_xchacha20poly1305_KEYBYTES}, {"crypto_aead_xchacha20poly1305_NPUBBYTES", 0, - enif_crypto_aead_xchacha20poly1305_NPUBBYTES}, + enacl_crypto_aead_xchacha20poly1305_NPUBBYTES}, {"crypto_aead_xchacha20poly1305_ABYTES", 0, - enif_crypto_aead_xchacha20poly1305_ABYTES}, + enacl_crypto_aead_xchacha20poly1305_ABYTES}, {"crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX", 0, - enif_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX}, + enacl_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX}, erl_nif_dirty_job_cpu_bound_macro( "crypto_aead_xchacha20poly1305_encrypt", 4, - enif_crypto_aead_xchacha20poly1305_encrypt), + enacl_crypto_aead_xchacha20poly1305_encrypt), erl_nif_dirty_job_cpu_bound_macro( "crypto_aead_xchacha20poly1305_decrypt", 4, - enif_crypto_aead_xchacha20poly1305_decrypt), + enacl_crypto_aead_xchacha20poly1305_decrypt), {"crypto_generichash_BYTES", 0, enif_crypto_generichash_BYTES}, {"crypto_generichash_BYTES_MIN", 0, enif_crypto_generichash_BYTES_MIN}, From f5b8a8eb3b78a97c0372b6143af6ca6d6be1f0d5 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sun, 19 Jan 2020 17:38:42 +0100 Subject: [PATCH 037/162] Pull signing out to its own module --- CHANGELOG.md | 3 + c_src/enacl_nif.c | 155 ++------------------------------- c_src/sign.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++ c_src/sign.h | 19 ++++ 4 files changed, 245 insertions(+), 148 deletions(-) create mode 100644 c_src/sign.c create mode 100644 c_src/sign.h diff --git a/CHANGELOG.md b/CHANGELOG.md index a0b5343..4a42ea2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. resource rather than on the Erlang side. This avoids some checks in the code, and streamlines a good deal of the interface. - Split AEAD routines off from the main enacl_nif.c file +- Renamed many routines from enif_* to enacl_*. This better reflects where they live + in the code base, and avoids pollution of the enif_* "namespace". +- Split Sign Public Key routines from the rest. Modernize the handling of contexts. ### Fixes - Fix a resource leak in generichash/sign init/update/final. diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index b1610c1..1dae63f 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -7,6 +7,7 @@ #include "enacl.h" #include "generichash.h" #include "hash.h" +#include "sign.h" #define CRYPTO_SIGN_STATE_RESOURCE "crypto_sign_state" @@ -18,13 +19,6 @@ { a, b, c } #endif -//{"crypto_box_keypair", 0, enif_crypto_box_keypair, -// ERL_NIF_DIRTY_JOB_CPU_BOUND} -/* Errors */ - -/* These are global variables for resource types */ -static ErlNifResourceType *sign_state_type = NULL; - /* Initialization */ static int enif_crypto_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info) { @@ -32,10 +26,8 @@ static int enif_crypto_load(ErlNifEnv *env, void **priv_data, if (!enacl_init_generic_hash_ctx(env)) { return -1; } - // Create a new resource type for crypto_sign_state - if (!(sign_state_type = - enif_open_resource_type(env, NULL, CRYPTO_SIGN_STATE_RESOURCE, NULL, - ERL_NIF_RT_CREATE, NULL))) { + + if (!enacl_init_sign_ctx(env)) { return -1; } @@ -639,139 +631,6 @@ enif_crypto_sign_verify_detached(ErlNifEnv *env, int argc, } } -/* - int crypto_sign_init(crypto_sign_state *state) - */ - -static ERL_NIF_TERM enif_crypto_sign_init(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - if ((argc != 0)) { - return enif_make_badarg(env); - } - - void *state = enif_alloc_resource(sign_state_type, crypto_sign_statebytes()); - - if (!state) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (0 != crypto_sign_init(state)) { - enif_release_resource(state); - return nacl_error_tuple(env, "sign_init_error"); - } - - // Create return values - ERL_NIF_TERM e1 = enif_make_atom(env, "signstate"); - ERL_NIF_TERM e2 = enif_make_resource(env, state); - - // release dynamically allocated memory to erlang to mange - enif_release_resource(state); - - // return a tuple - return enif_make_tuple2(env, e1, e2); -} - -/* - int crypto_sign_update(crypto_sign_state *state, - const unsigned char *m, - unsigned long long mlen); - */ - -static ERL_NIF_TERM enif_crypto_sign_update(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary data; - - void *state; - - // Validate the arguments - if ((argc != 2) || - (!enif_get_resource(env, argv[0], sign_state_type, (void **)&state)) || - (!enif_inspect_binary(env, argv[1], &data))) { - return enif_make_badarg(env); - } - - if (0 != crypto_sign_update(state, data.data, data.size)) { - return nacl_error_tuple(env, "sign_update_error"); - } - - // Generate return value - ERL_NIF_TERM e1 = enif_make_atom(env, "signstate"); - ERL_NIF_TERM e2 = enif_make_resource(env, state); - - // return a tuple - return enif_make_tuple2(env, e1, e2); -} - -/* - int crypto_sign_final_create(crypto_sign_state *state, - unsigned char *sig, - unsigned long long *siglen_p, - const unsigned char *sk); - */ - -static ERL_NIF_TERM enif_crypto_sign_final_create(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary sk, sig; - - void *state; - - unsigned long long siglen; - - if ((argc != 2) || - (!enif_get_resource(env, argv[0], sign_state_type, (void **)&state)) || - (!enif_inspect_binary(env, argv[1], &sk))) { - return enif_make_badarg(env); - } - - if (sk.size != crypto_sign_SECRETKEYBYTES) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (0 != crypto_sign_final_create(state, sig.data, &siglen, sk.data)) { - enif_release_binary(&sig); - return nacl_error_tuple(env, "sign_error"); - } - - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret = enif_make_binary(env, &sig); - - return enif_make_tuple2(env, ok, ret); -} - -/* - int crypto_sign_final_verify(crypto_sign_state *state, - unsigned char *sig, - const unsigned char *pk); - */ - -static ERL_NIF_TERM enif_crypto_sign_final_verify(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sig; - - void *state; - - if ((argc != 3) || - (!enif_get_resource(env, argv[0], sign_state_type, (void **)&state)) || - (!enif_inspect_binary(env, argv[1], &sig)) || - (!enif_inspect_binary(env, argv[2], &pk))) { - return enif_make_badarg(env); - } - - if (pk.size != crypto_sign_PUBLICKEYBYTES) { - return enif_make_badarg(env); - } - - if (0 == crypto_sign_final_verify(state, sig.data, pk.data)) { - return enif_make_atom(env, ATOM_OK); - } - - return nacl_error_tuple(env, "failed_verification"); -} - /* Sealed box functions */ static ERL_NIF_TERM enif_crypto_box_SEALBYTES(ErlNifEnv *env, int argc, @@ -1584,12 +1443,12 @@ static ErlNifFunc nif_funcs[] = { enif_crypto_sign_detached), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_verify_detached", 3, enif_crypto_sign_verify_detached), - {"crypto_sign_init", 0, enif_crypto_sign_init}, - {"crypto_sign_update", 2, enif_crypto_sign_update}, + {"crypto_sign_init", 0, enacl_crypto_sign_init}, + {"crypto_sign_update", 2, enacl_crypto_sign_update}, erl_nif_dirty_job_cpu_bound_macro("crypto_sign_final_create", 2, - enif_crypto_sign_final_create), + enacl_crypto_sign_final_create), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_final_verify", 3, - enif_crypto_sign_final_verify), + enacl_crypto_sign_final_verify), {"crypto_sign_ed25519_sk_to_pk", 1, enif_crypto_sign_ed25519_sk_to_pk}, diff --git a/c_src/sign.c b/c_src/sign.c new file mode 100644 index 0000000..bb82f65 --- /dev/null +++ b/c_src/sign.c @@ -0,0 +1,216 @@ +#include "erl_nif.h" + +#include + +#include "enacl.h" +#include "sign.h" + +typedef struct enacl_sign_ctx { + crypto_sign_state *state; // The underlying signature state + int alive; // Is the context still valid for updates/finalization +} enacl_sign_ctx; + +static ErlNifResourceType *enacl_sign_ctx_rtype = NULL; + +static void enacl_sign_ctx_dtor(ErlNifEnv *env, enacl_sign_ctx *); + +int enacl_init_sign_ctx(ErlNifEnv *env) { + enacl_sign_ctx_rtype = + enif_open_resource_type(env, NULL, "enacl_sign_context", + (ErlNifResourceDtor *)enacl_sign_ctx_dtor, + ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL); + + if (enacl_sign_ctx_rtype == NULL) + return 0; + + return 1; +} + +static void enacl_sign_ctx_dtor(ErlNifEnv *env, enacl_sign_ctx *obj) { + if (!obj->alive) + return; + + if (obj->state) { + sodium_memzero(obj->state, crypto_sign_statebytes()); + enif_free(obj->state); + } + + return; +} + +/* + int crypto_sign_init(crypto_sign_state *state) + */ + +ERL_NIF_TERM enacl_crypto_sign_init(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ERL_NIF_TERM ret; + enacl_sign_ctx *obj = NULL; + + if (argc != 0) + goto bad_arg; + + if ((obj = enif_alloc_resource(enacl_sign_ctx_rtype, + sizeof(enacl_sign_ctx))) == NULL) { + ret = nacl_error_tuple(env, "alloc_failed"); + goto done; + } + obj->alive = 0; + obj->state = enif_alloc(crypto_sign_statebytes()); + if (obj->state == NULL) { + ret = nacl_error_tuple(env, "state_malloc"); + goto release; + } + obj->alive = 1; + + if (0 != crypto_sign_init(obj->state)) { + ret = nacl_error_tuple(env, "sign_init_error"); + goto free; + } + + // Create return values + ret = enif_make_resource(env, obj); + + goto release; + +bad_arg: + return enif_make_badarg(env); +free: + if (obj->alive) + if (obj->state != NULL) { + sodium_memzero(obj->state, crypto_sign_statebytes()); + enif_free(obj->state); + obj->state = NULL; + } +release: + enif_release_resource(obj); +done: + return ret; +} + +/* + int crypto_sign_update(crypto_sign_state *state, + const unsigned char *m, + unsigned long long mlen); + */ + +ERL_NIF_TERM enacl_crypto_sign_update(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ERL_NIF_TERM ret; + enacl_sign_ctx *obj = NULL; + ErlNifBinary data; + + // Validate the arguments + if (argc != 2) + goto bad_arg; + + if (!enif_get_resource(env, argv[0], enacl_sign_ctx_rtype, (void **)&obj)) + goto bad_arg; + + if (!enif_inspect_binary(env, argv[1], &data)) + goto bad_arg; + + if (!obj->alive) { + ret = nacl_error_tuple(env, "finalized"); + goto done; + } + + if (0 != crypto_sign_update(obj->state, data.data, data.size)) { + ret = nacl_error_tuple(env, "sign_update_error"); + goto done; + } + + ret = argv[0]; + goto done; + +bad_arg: + return enif_make_badarg(env); +done: + return ret; +} + +ERL_NIF_TERM enacl_crypto_sign_final_create(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ERL_NIF_TERM ret; + enacl_sign_ctx *obj = NULL; + ErlNifBinary sk, sig; + unsigned long long siglen; + + if (argc != 2) + goto bad_arg; + if (!enif_get_resource(env, argv[0], enacl_sign_ctx_rtype, (void **)&obj)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &sk)) + goto bad_arg; + if (sk.size != crypto_sign_SECRETKEYBYTES) + goto bad_arg; + + if (!obj->alive) { + ret = nacl_error_tuple(env, "finalized"); + goto done; + } + + if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { + ret = nacl_error_tuple(env, "alloc_failed"); + goto done; + } + + if (0 != crypto_sign_final_create(obj->state, sig.data, &siglen, sk.data)) { + ret = nacl_error_tuple(env, "sign_error"); + goto release; + } + + ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM signature = enif_make_binary(env, &sig); + + ret = enif_make_tuple2(env, ok, signature); + goto cleanup; +bad_arg: + return enif_make_badarg(env); +release: + enif_release_binary(&sig); +cleanup: + obj->alive = 0; + sodium_memzero(obj->state, crypto_sign_statebytes()); + enif_free(obj->state); + obj->state = NULL; +done: + return ret; +} + +ERL_NIF_TERM enacl_crypto_sign_final_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sig; + enacl_sign_ctx *obj = NULL; + ERL_NIF_TERM ret; + + if (argc != 3) + goto bad_arg; + if (!enif_get_resource(env, argv[0], enacl_sign_ctx_rtype, (void **)&obj)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &sig)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &pk)) + goto bad_arg; + if (pk.size != crypto_sign_PUBLICKEYBYTES) + goto bad_arg; + + if (0 == crypto_sign_final_verify(obj->state, sig.data, pk.data)) { + ret = enif_make_atom(env, ATOM_OK); + } else { + ret = nacl_error_tuple(env, "failed_verification"); + } + // Mark as done + goto cleanup; + +bad_arg: + return enif_make_badarg(env); +cleanup: + // Get rid of the context and mark it as dead + obj->alive = 0; + sodium_memzero(obj->state, crypto_sign_statebytes()); + enif_free(obj->state); + obj->state = NULL; + + return ret; +} diff --git a/c_src/sign.h b/c_src/sign.h new file mode 100644 index 0000000..5b91ce3 --- /dev/null +++ b/c_src/sign.h @@ -0,0 +1,19 @@ +#ifndef ENACL_SIGN_H +#define ENACL_SIGN_H + +#include "erl_nif.h" + +int enacl_init_sign_ctx(ErlNifEnv *env); + +ERL_NIF_TERM enacl_crypto_sign_init(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_update(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_final_create(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_final_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); +#endif \ No newline at end of file From 0427fa42ee98e6bd9d2dde82f714863dad0bed59 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sun, 19 Jan 2020 17:56:31 +0100 Subject: [PATCH 038/162] Rename enif_crypto_ to enacl_crypto_ This is a better name which spits stuff appropriately. We don't pollute the enif_ namespace. --- c_src/enacl_nif.c | 666 +++++++++++++------------------------------- c_src/generichash.c | 24 +- c_src/generichash.h | 24 +- c_src/sign.c | 281 ++++++++++++++++++- c_src/sign.h | 51 ++++ 5 files changed, 549 insertions(+), 497 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 1dae63f..8065cd2 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -20,8 +20,8 @@ #endif /* Initialization */ -static int enif_crypto_load(ErlNifEnv *env, void **priv_data, - ERL_NIF_TERM load_info) { +static int enacl_crypto_load(ErlNifEnv *env, void **priv_data, + ERL_NIF_TERM load_info) { // Create a new resource type for crypto_generichash_state if (!enacl_init_generic_hash_ctx(env)) { return -1; @@ -34,8 +34,8 @@ static int enif_crypto_load(ErlNifEnv *env, void **priv_data, return sodium_init(); } -static ERL_NIF_TERM enif_crypto_verify_16(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_verify_16(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary x, y; if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &x)) || @@ -54,8 +54,8 @@ static ERL_NIF_TERM enif_crypto_verify_16(ErlNifEnv *env, int argc, } } -static ERL_NIF_TERM enif_crypto_verify_32(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_verify_32(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary x, y; if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &x)) || @@ -92,8 +92,8 @@ static ERL_NIF_TERM enif_sodium_memzero(ErlNifEnv *env, int argc, /* Curve 25519 */ static ERL_NIF_TERM -enif_crypto_curve25519_scalarmult(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_curve25519_scalarmult(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ERL_NIF_TERM result; ErlNifBinary secret, basepoint, output; uint8_t bp[crypto_scalarmult_curve25519_BYTES]; @@ -130,8 +130,8 @@ enif_crypto_curve25519_scalarmult(ErlNifEnv *env, int argc, } static ERL_NIF_TERM -enif_crypto_curve25519_scalarmult_base(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_curve25519_scalarmult_base(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ERL_NIF_TERM result; ErlNifBinary secret, output; @@ -157,140 +157,39 @@ enif_crypto_curve25519_scalarmult_base(ErlNifEnv *env, int argc, return result; } -/* Ed 25519 */ -static ERL_NIF_TERM -enif_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sk; - - if (argc != 0) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (!enif_alloc_binary(crypto_sign_ed25519_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_sign_ed25519_keypair(pk.data, sk.data); - - return enif_make_tuple2(env, enif_make_binary(env, &pk), - enif_make_binary(env, &sk)); -} - -static ERL_NIF_TERM -enif_crypto_sign_ed25519_sk_to_pk(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sk; - - if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &sk)) || - (sk.size != crypto_sign_ed25519_SECRETKEYBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (crypto_sign_ed25519_sk_to_pk(pk.data, sk.data) != 0) { - return nacl_error_tuple(env, "crypto_sign_ed25519_sk_to_pk_failed"); - } - - return enif_make_binary(env, &pk); -} - -static ERL_NIF_TERM -enif_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary curve25519_pk, ed25519_pk; - - if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &ed25519_pk)) || - (ed25519_pk.size != crypto_sign_ed25519_PUBLICKEYBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (crypto_sign_ed25519_pk_to_curve25519(curve25519_pk.data, - ed25519_pk.data) != 0) { - return nacl_error_tuple(env, "ed25519_public_to_curve25519_failed"); - } - - return enif_make_binary(env, &curve25519_pk); -} - -static ERL_NIF_TERM -enif_crypto_sign_ed25519_secret_to_curve25519(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary curve25519_sk, ed25519_sk; - - if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &ed25519_sk)) || - (ed25519_sk.size != crypto_sign_ed25519_SECRETKEYBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_sk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (crypto_sign_ed25519_sk_to_curve25519(curve25519_sk.data, - ed25519_sk.data) != 0) { - return nacl_error_tuple(env, "ed25519_secret_to_curve25519_failed"); - } - - return enif_make_binary(env, &curve25519_sk); -} - -static ERL_NIF_TERM -enif_crypto_sign_ed25519_PUBLICKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_sign_ed25519_PUBLICKEYBYTES); -} - -static ERL_NIF_TERM -enif_crypto_sign_ed25519_SECRETKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_sign_ed25519_SECRETKEYBYTES); -} - /* Public-key cryptography */ -static ERL_NIF_TERM enif_crypto_box_NONCEBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_box_NONCEBYTES); } -static ERL_NIF_TERM enif_crypto_box_ZEROBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_ZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_box_ZEROBYTES); } -static ERL_NIF_TERM enif_crypto_box_BOXZEROBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_BOXZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_box_BOXZEROBYTES); } -static ERL_NIF_TERM enif_crypto_box_PUBLICKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_box_PUBLICKEYBYTES); } -static ERL_NIF_TERM enif_crypto_box_SECRETKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_box_SECRETKEYBYTES); } -static ERL_NIF_TERM enif_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_box_BEFORENMBYTES); } -static ERL_NIF_TERM enif_crypto_box_keypair(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary pk, sk; if (argc != 0) { @@ -311,8 +210,8 @@ static ERL_NIF_TERM enif_crypto_box_keypair(ErlNifEnv *env, int argc, enif_make_binary(env, &sk)); } -static ERL_NIF_TERM enif_crypto_box(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary padded_msg, nonce, pk, sk, result; if ((argc != 4) || @@ -344,8 +243,8 @@ static ERL_NIF_TERM enif_crypto_box(ErlNifEnv *env, int argc, padded_msg.size - crypto_box_BOXZEROBYTES); } -static ERL_NIF_TERM enif_crypto_box_open(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary padded_ciphertext, nonce, pk, sk, result; if ((argc != 4) || @@ -381,8 +280,8 @@ static ERL_NIF_TERM enif_crypto_box_open(ErlNifEnv *env, int argc, /* Precomputed crypto boxes */ -static ERL_NIF_TERM enif_crypto_box_beforenm(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary k, pk, sk; if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &pk)) || @@ -404,8 +303,8 @@ static ERL_NIF_TERM enif_crypto_box_beforenm(ErlNifEnv *env, int argc, return enif_make_binary(env, &k); } -static ERL_NIF_TERM enif_crypto_box_afternm(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary result, m, nonce, k; if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || @@ -428,8 +327,8 @@ static ERL_NIF_TERM enif_crypto_box_afternm(ErlNifEnv *env, int argc, m.size - crypto_box_BOXZEROBYTES); } -static ERL_NIF_TERM enif_crypto_box_open_afternm(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary result, m, nonce, k; if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || @@ -456,190 +355,15 @@ static ERL_NIF_TERM enif_crypto_box_open_afternm(ErlNifEnv *env, int argc, m.size - crypto_box_ZEROBYTES); } -/* Signing */ -static ERL_NIF_TERM enif_crypto_sign_PUBLICKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_sign_PUBLICKEYBYTES); -} - -static ERL_NIF_TERM enif_crypto_sign_SECRETKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_sign_SECRETKEYBYTES); -} - -static ERL_NIF_TERM enif_crypto_sign_SEEDBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_sign_SEEDBYTES); -} - -static ERL_NIF_TERM enif_crypto_sign_keypair(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sk; - - if (argc != 0) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_sign_keypair(pk.data, sk.data); - - return enif_make_tuple2(env, enif_make_binary(env, &pk), - enif_make_binary(env, &sk)); -} - -static ERL_NIF_TERM enif_crypto_sign_seed_keypair(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sk, seed; - - if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &seed))) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_sign_seed_keypair(pk.data, sk.data, seed.data); - - return enif_make_tuple2(env, enif_make_binary(env, &pk), - enif_make_binary(env, &sk)); -} - -/* -int crypto_sign(unsigned char *sm, unsigned long long *smlen, - const unsigned char *m, unsigned long long mlen, - const unsigned char *sk); - */ -static ERL_NIF_TERM enif_crypto_sign(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary m, sk, sm; - unsigned long long smlen; - - if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &sk))) { - return enif_make_badarg(env); - } - - if (sk.size != crypto_sign_SECRETKEYBYTES) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(m.size + crypto_sign_BYTES, &sm)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_sign(sm.data, &smlen, m.data, m.size, sk.data); - - return enif_make_sub_binary(env, enif_make_binary(env, &sm), 0, smlen); -} - -/* -int crypto_sign_open(unsigned char *m, unsigned long long *mlen, - const unsigned char *sm, unsigned long long smlen, - const unsigned char *pk); - */ -static ERL_NIF_TERM enif_crypto_sign_open(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary m, sm, pk; - unsigned long long mlen; - - if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &sm)) || - (!enif_inspect_binary(env, argv[1], &pk))) { - return enif_make_badarg(env); - } - - if (pk.size != crypto_sign_PUBLICKEYBYTES) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(sm.size, &m)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (0 == crypto_sign_open(m.data, &mlen, sm.data, sm.size, pk.data)) { - return enif_make_sub_binary(env, enif_make_binary(env, &m), 0, mlen); - } else { - enif_release_binary(&m); - return nacl_error_tuple(env, "failed_verification"); - } -} - -/* -int crypto_sign_detached(unsigned char *sig, unsigned long long *siglen, - const unsigned char *m, unsigned long long mlen, - const unsigned char *sk); - */ -static ERL_NIF_TERM enif_crypto_sign_detached(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary m, sk, sig; - unsigned long long siglen; - - if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &sk))) { - return enif_make_badarg(env); - } - - if (sk.size != crypto_sign_SECRETKEYBYTES) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_sign_detached(sig.data, &siglen, m.data, m.size, sk.data); - - return enif_make_binary(env, &sig); -} - -/* -int crypto_sign_verify_detached(const unsigned char *sig, - const unsigned char *m, - unsigned long long mlen, - const unsigned char *pk); - */ -static ERL_NIF_TERM -enif_crypto_sign_verify_detached(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary m, sig, pk; - - if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &sig)) || - (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || - (!enif_inspect_binary(env, argv[2], &pk))) { - return enif_make_badarg(env); - } - - if (pk.size != crypto_sign_PUBLICKEYBYTES) { - return enif_make_badarg(env); - } - - if (0 == crypto_sign_verify_detached(sig.data, m.data, m.size, pk.data)) { - return enif_make_atom(env, "true"); - } else { - return enif_make_atom(env, "false"); - } -} - /* Sealed box functions */ -static ERL_NIF_TERM enif_crypto_box_SEALBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_SEALBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_box_SEALBYTES); } -static ERL_NIF_TERM enif_crypto_box_seal(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary key, msg, ciphertext; if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &msg)) || @@ -656,8 +380,8 @@ static ERL_NIF_TERM enif_crypto_box_seal(ErlNifEnv *env, int argc, return enif_make_binary(env, &ciphertext); } -static ERL_NIF_TERM enif_crypto_box_seal_open(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary pk, sk, ciphertext, msg; if ((argc != 3) || @@ -687,82 +411,83 @@ static ERL_NIF_TERM enif_crypto_box_seal_open(ErlNifEnv *env, int argc, /* Secret key cryptography */ static ERL_NIF_TERM -enif_crypto_secretbox_NONCEBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_secretbox_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_secretbox_NONCEBYTES); } -static ERL_NIF_TERM enif_crypto_secretbox_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_secretbox_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_secretbox_KEYBYTES); } -static ERL_NIF_TERM enif_crypto_secretbox_ZEROBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM +enacl_crypto_secretbox_ZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_secretbox_ZEROBYTES); } static ERL_NIF_TERM -enif_crypto_secretbox_BOXZEROBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_secretbox_BOXZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_secretbox_BOXZEROBYTES); } static ERL_NIF_TERM -enif_crypto_stream_chacha20_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_stream_chacha20_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_stream_chacha20_KEYBYTES); } static ERL_NIF_TERM -enif_crypto_stream_chacha20_NONCEBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_stream_chacha20_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_stream_chacha20_NONCEBYTES); } -static ERL_NIF_TERM enif_crypto_stream_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_stream_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_stream_KEYBYTES); } -static ERL_NIF_TERM enif_crypto_stream_NONCEBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_stream_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_stream_NONCEBYTES); } -static ERL_NIF_TERM enif_crypto_auth_BYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_auth_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_auth_BYTES); } -static ERL_NIF_TERM enif_crypto_auth_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_auth_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_auth_KEYBYTES); } -static ERL_NIF_TERM enif_crypto_shorthash_BYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_shorthash_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_shorthash_BYTES); } -static ERL_NIF_TERM enif_crypto_shorthash_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_shorthash_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_shorthash_KEYBYTES); } -static ERL_NIF_TERM enif_crypto_onetimeauth_BYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_onetimeauth_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_onetimeauth_BYTES); } static ERL_NIF_TERM -enif_crypto_onetimeauth_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_onetimeauth_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_onetimeauth_KEYBYTES); } -static ERL_NIF_TERM enif_crypto_secretbox(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_secretbox(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary key, nonce, padded_msg, padded_ciphertext; if ((argc != 3) || @@ -790,8 +515,8 @@ static ERL_NIF_TERM enif_crypto_secretbox(ErlNifEnv *env, int argc, padded_msg.size - crypto_secretbox_BOXZEROBYTES); } -static ERL_NIF_TERM enif_crypto_secretbox_open(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_secretbox_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary key, nonce, padded_ciphertext, padded_msg; if ((argc != 3) || @@ -823,8 +548,8 @@ static ERL_NIF_TERM enif_crypto_secretbox_open(ErlNifEnv *env, int argc, padded_ciphertext.size - crypto_secretbox_ZEROBYTES); } -static ERL_NIF_TERM enif_crypto_stream_chacha20(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_stream_chacha20(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary c, n, k; ErlNifUInt64 clen; @@ -848,8 +573,9 @@ static ERL_NIF_TERM enif_crypto_stream_chacha20(ErlNifEnv *env, int argc, return enif_make_binary(env, &c); } -static ERL_NIF_TERM enif_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM +enacl_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary c, m, n, k; if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || @@ -872,8 +598,8 @@ static ERL_NIF_TERM enif_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc, return enif_make_binary(env, &c); } -static ERL_NIF_TERM enif_crypto_stream(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_stream(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary c, n, k; ErlNifUInt64 clen; @@ -897,8 +623,8 @@ static ERL_NIF_TERM enif_crypto_stream(ErlNifEnv *env, int argc, return enif_make_binary(env, &c); } -static ERL_NIF_TERM enif_crypto_stream_xor(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_stream_xor(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary c, m, n, k; if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || @@ -921,8 +647,8 @@ static ERL_NIF_TERM enif_crypto_stream_xor(ErlNifEnv *env, int argc, return enif_make_binary(env, &c); } -static ERL_NIF_TERM enif_crypto_auth(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_auth(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary a, m, k; if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || @@ -943,8 +669,8 @@ static ERL_NIF_TERM enif_crypto_auth(ErlNifEnv *env, int argc, return enif_make_binary(env, &a); } -static ERL_NIF_TERM enif_crypto_auth_verify(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_auth_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary a, m, k; if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &a)) || @@ -964,8 +690,8 @@ static ERL_NIF_TERM enif_crypto_auth_verify(ErlNifEnv *env, int argc, } } -static ERL_NIF_TERM enif_crypto_shorthash(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_shorthash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary a, m, k; if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || @@ -986,8 +712,8 @@ static ERL_NIF_TERM enif_crypto_shorthash(ErlNifEnv *env, int argc, return enif_make_binary(env, &a); } -static ERL_NIF_TERM enif_crypto_onetimeauth(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_onetimeauth(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary a, m, k; if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || @@ -1008,8 +734,8 @@ static ERL_NIF_TERM enif_crypto_onetimeauth(ErlNifEnv *env, int argc, return enif_make_binary(env, &a); } -static ERL_NIF_TERM enif_crypto_onetimeauth_verify(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_onetimeauth_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary a, m, k; if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &a)) || @@ -1075,23 +801,23 @@ static ERL_NIF_TERM enif_randombytes_uniform(ErlNifEnv *env, int argc, /* Key exchange */ -static ERL_NIF_TERM enif_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_kx_SECRETKEYBYTES); } -static ERL_NIF_TERM enif_crypto_kx_PUBLICKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_kx_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_kx_PUBLICKEYBYTES); } -static ERL_NIF_TERM enif_crypto_kx_SESSIONKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_kx_SESSIONKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_kx_SESSIONKEYBYTES); } -static ERL_NIF_TERM enif_crypto_kx_keypair(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary pk, sk; if (argc != 0) { @@ -1113,8 +839,8 @@ static ERL_NIF_TERM enif_crypto_kx_keypair(ErlNifEnv *env, int argc, } static ERL_NIF_TERM -enif_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary rx, tx, server_pk, server_sk, client_pk; if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &server_pk)) || @@ -1145,8 +871,8 @@ enif_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, } static ERL_NIF_TERM -enif_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary rx, tx, client_pk, client_sk, server_pk; if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &client_pk)) || @@ -1308,8 +1034,8 @@ static size_t enacl_pwhash_memlimit(ErlNifEnv *env, ERL_NIF_TERM arg) { return 0; } -static ERL_NIF_TERM enif_crypto_pwhash(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary h, p, s; size_t o, m; @@ -1350,8 +1076,8 @@ static ERL_NIF_TERM enif_crypto_pwhash(ErlNifEnv *env, int argc, return enif_make_tuple2(env, ok, ret); } -static ERL_NIF_TERM enif_crypto_pwhash_str(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_pwhash_str(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary h, p; size_t o, m; @@ -1385,8 +1111,8 @@ static ERL_NIF_TERM enif_crypto_pwhash_str(ErlNifEnv *env, int argc, return enif_make_tuple2(env, ok, ret); } -static ERL_NIF_TERM enif_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +static ERL_NIF_TERM enacl_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary h, p; // Validate the arguments @@ -1406,43 +1132,43 @@ static ERL_NIF_TERM enif_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, /* Tie the knot to the Erlang world */ static ErlNifFunc nif_funcs[] = { - {"crypto_box_NONCEBYTES", 0, enif_crypto_box_NONCEBYTES}, - {"crypto_box_ZEROBYTES", 0, enif_crypto_box_ZEROBYTES}, - {"crypto_box_BOXZEROBYTES", 0, enif_crypto_box_BOXZEROBYTES}, - {"crypto_box_PUBLICKEYBYTES", 0, enif_crypto_box_PUBLICKEYBYTES}, - {"crypto_box_SECRETKEYBYTES", 0, enif_crypto_box_SECRETKEYBYTES}, - {"crypto_box_BEFORENMBYTES", 0, enif_crypto_box_BEFORENMBYTES}, + {"crypto_box_NONCEBYTES", 0, enacl_crypto_box_NONCEBYTES}, + {"crypto_box_ZEROBYTES", 0, enacl_crypto_box_ZEROBYTES}, + {"crypto_box_BOXZEROBYTES", 0, enacl_crypto_box_BOXZEROBYTES}, + {"crypto_box_PUBLICKEYBYTES", 0, enacl_crypto_box_PUBLICKEYBYTES}, + {"crypto_box_SECRETKEYBYTES", 0, enacl_crypto_box_SECRETKEYBYTES}, + {"crypto_box_BEFORENMBYTES", 0, enacl_crypto_box_BEFORENMBYTES}, erl_nif_dirty_job_cpu_bound_macro("crypto_box_keypair", 0, - enif_crypto_box_keypair), + enacl_crypto_box_keypair), - erl_nif_dirty_job_cpu_bound_macro("crypto_box", 4, enif_crypto_box), + erl_nif_dirty_job_cpu_bound_macro("crypto_box", 4, enacl_crypto_box), erl_nif_dirty_job_cpu_bound_macro("crypto_box_open", 4, - enif_crypto_box_open), + enacl_crypto_box_open), - {"crypto_box_beforenm", 2, enif_crypto_box_beforenm}, - {"crypto_box_afternm_b", 3, enif_crypto_box_afternm}, + {"crypto_box_beforenm", 2, enacl_crypto_box_beforenm}, + {"crypto_box_afternm_b", 3, enacl_crypto_box_afternm}, erl_nif_dirty_job_cpu_bound_macro("crypto_box_afternm", 3, - enif_crypto_box_afternm), - {"crypto_box_open_afternm_b", 3, enif_crypto_box_open_afternm}, + enacl_crypto_box_afternm), + {"crypto_box_open_afternm_b", 3, enacl_crypto_box_open_afternm}, erl_nif_dirty_job_cpu_bound_macro("crypto_box_open_afternm", 3, - enif_crypto_box_open_afternm), + enacl_crypto_box_open_afternm), - {"crypto_sign_PUBLICKEYBYTES", 0, enif_crypto_sign_PUBLICKEYBYTES}, - {"crypto_sign_SECRETKEYBYTES", 0, enif_crypto_sign_SECRETKEYBYTES}, + {"crypto_sign_PUBLICKEYBYTES", 0, enacl_crypto_sign_PUBLICKEYBYTES}, + {"crypto_sign_SECRETKEYBYTES", 0, enacl_crypto_sign_SECRETKEYBYTES}, erl_nif_dirty_job_cpu_bound_macro("crypto_sign_keypair", 0, - enif_crypto_sign_keypair), + enacl_crypto_sign_keypair), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_seed_keypair", 1, - enif_crypto_sign_seed_keypair), + enacl_crypto_sign_seed_keypair), - erl_nif_dirty_job_cpu_bound_macro("crypto_sign", 2, enif_crypto_sign), + erl_nif_dirty_job_cpu_bound_macro("crypto_sign", 2, enacl_crypto_sign), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_open", 2, - enif_crypto_sign_open), + enacl_crypto_sign_open), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_detached", 2, - enif_crypto_sign_detached), + enacl_crypto_sign_detached), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_verify_detached", 3, - enif_crypto_sign_verify_detached), + enacl_crypto_sign_verify_detached), {"crypto_sign_init", 0, enacl_crypto_sign_init}, {"crypto_sign_update", 2, enacl_crypto_sign_update}, erl_nif_dirty_job_cpu_bound_macro("crypto_sign_final_create", 2, @@ -1450,93 +1176,93 @@ static ErlNifFunc nif_funcs[] = { erl_nif_dirty_job_cpu_bound_macro("crypto_sign_final_verify", 3, enacl_crypto_sign_final_verify), - {"crypto_sign_ed25519_sk_to_pk", 1, enif_crypto_sign_ed25519_sk_to_pk}, + {"crypto_sign_ed25519_sk_to_pk", 1, enacl_crypto_sign_ed25519_sk_to_pk}, - {"crypto_box_SEALBYTES", 0, enif_crypto_box_SEALBYTES}, + {"crypto_box_SEALBYTES", 0, enacl_crypto_box_SEALBYTES}, erl_nif_dirty_job_cpu_bound_macro("crypto_box_seal", 2, - enif_crypto_box_seal), + enacl_crypto_box_seal), erl_nif_dirty_job_cpu_bound_macro("crypto_box_seal_open", 3, - enif_crypto_box_seal_open), + enacl_crypto_box_seal_open), - {"crypto_secretbox_NONCEBYTES", 0, enif_crypto_secretbox_NONCEBYTES}, - {"crypto_secretbox_ZEROBYTES", 0, enif_crypto_secretbox_ZEROBYTES}, - {"crypto_secretbox_BOXZEROBYTES", 0, enif_crypto_secretbox_BOXZEROBYTES}, - {"crypto_secretbox_KEYBYTES", 0, enif_crypto_secretbox_KEYBYTES}, - {"crypto_secretbox_b", 3, enif_crypto_secretbox}, + {"crypto_secretbox_NONCEBYTES", 0, enacl_crypto_secretbox_NONCEBYTES}, + {"crypto_secretbox_ZEROBYTES", 0, enacl_crypto_secretbox_ZEROBYTES}, + {"crypto_secretbox_BOXZEROBYTES", 0, enacl_crypto_secretbox_BOXZEROBYTES}, + {"crypto_secretbox_KEYBYTES", 0, enacl_crypto_secretbox_KEYBYTES}, + {"crypto_secretbox_b", 3, enacl_crypto_secretbox}, erl_nif_dirty_job_cpu_bound_macro("crypto_secretbox", 3, - enif_crypto_secretbox), - {"crypto_secretbox_open_b", 3, enif_crypto_secretbox_open}, + enacl_crypto_secretbox), + {"crypto_secretbox_open_b", 3, enacl_crypto_secretbox_open}, erl_nif_dirty_job_cpu_bound_macro("crypto_secretbox_open", 3, - enif_crypto_secretbox_open), + enacl_crypto_secretbox_open), {"crypto_stream_chacha20_KEYBYTES", 0, - enif_crypto_stream_chacha20_KEYBYTES}, + enacl_crypto_stream_chacha20_KEYBYTES}, {"crypto_stream_chacha20_NONCEBYTES", 0, - enif_crypto_stream_chacha20_NONCEBYTES}, - {"crypto_stream_chacha20_b", 3, enif_crypto_stream_chacha20}, + enacl_crypto_stream_chacha20_NONCEBYTES}, + {"crypto_stream_chacha20_b", 3, enacl_crypto_stream_chacha20}, erl_nif_dirty_job_cpu_bound_macro("crypto_stream_chacha20", 3, - enif_crypto_stream_chacha20), - {"crypto_stream_chacha20_xor_b", 3, enif_crypto_stream_chacha20_xor}, + enacl_crypto_stream_chacha20), + {"crypto_stream_chacha20_xor_b", 3, enacl_crypto_stream_chacha20_xor}, erl_nif_dirty_job_cpu_bound_macro("crypto_stream_chacha20_xor", 3, - enif_crypto_stream_chacha20_xor), + enacl_crypto_stream_chacha20_xor), - {"crypto_stream_KEYBYTES", 0, enif_crypto_stream_KEYBYTES}, - {"crypto_stream_NONCEBYTES", 0, enif_crypto_stream_NONCEBYTES}, - {"crypto_stream_b", 3, enif_crypto_stream}, - erl_nif_dirty_job_cpu_bound_macro("crypto_stream", 3, enif_crypto_stream), - {"crypto_stream_xor_b", 3, enif_crypto_stream_xor}, + {"crypto_stream_KEYBYTES", 0, enacl_crypto_stream_KEYBYTES}, + {"crypto_stream_NONCEBYTES", 0, enacl_crypto_stream_NONCEBYTES}, + {"crypto_stream_b", 3, enacl_crypto_stream}, + erl_nif_dirty_job_cpu_bound_macro("crypto_stream", 3, enacl_crypto_stream), + {"crypto_stream_xor_b", 3, enacl_crypto_stream_xor}, erl_nif_dirty_job_cpu_bound_macro("crypto_stream_xor", 3, - enif_crypto_stream_xor), + enacl_crypto_stream_xor), - {"crypto_auth_BYTES", 0, enif_crypto_auth_BYTES}, - {"crypto_auth_KEYBYTES", 0, enif_crypto_auth_KEYBYTES}, - {"crypto_auth_b", 2, enif_crypto_auth}, - erl_nif_dirty_job_cpu_bound_macro("crypto_auth", 2, enif_crypto_auth), - {"crypto_auth_verify_b", 3, enif_crypto_auth_verify}, + {"crypto_auth_BYTES", 0, enacl_crypto_auth_BYTES}, + {"crypto_auth_KEYBYTES", 0, enacl_crypto_auth_KEYBYTES}, + {"crypto_auth_b", 2, enacl_crypto_auth}, + erl_nif_dirty_job_cpu_bound_macro("crypto_auth", 2, enacl_crypto_auth), + {"crypto_auth_verify_b", 3, enacl_crypto_auth_verify}, erl_nif_dirty_job_cpu_bound_macro("crypto_auth_verify", 3, - enif_crypto_auth_verify), + enacl_crypto_auth_verify), - {"crypto_shorthash_BYTES", 0, enif_crypto_shorthash_BYTES}, - {"crypto_shorthash_KEYBYTES", 0, enif_crypto_shorthash_KEYBYTES}, - {"crypto_shorthash", 2, enif_crypto_shorthash}, + {"crypto_shorthash_BYTES", 0, enacl_crypto_shorthash_BYTES}, + {"crypto_shorthash_KEYBYTES", 0, enacl_crypto_shorthash_KEYBYTES}, + {"crypto_shorthash", 2, enacl_crypto_shorthash}, - {"crypto_onetimeauth_BYTES", 0, enif_crypto_onetimeauth_BYTES}, - {"crypto_onetimeauth_KEYBYTES", 0, enif_crypto_onetimeauth_KEYBYTES}, - {"crypto_onetimeauth_b", 2, enif_crypto_onetimeauth}, + {"crypto_onetimeauth_BYTES", 0, enacl_crypto_onetimeauth_BYTES}, + {"crypto_onetimeauth_KEYBYTES", 0, enacl_crypto_onetimeauth_KEYBYTES}, + {"crypto_onetimeauth_b", 2, enacl_crypto_onetimeauth}, erl_nif_dirty_job_cpu_bound_macro("crypto_onetimeauth", 2, - enif_crypto_onetimeauth), - {"crypto_onetimeauth_verify_b", 3, enif_crypto_onetimeauth_verify}, + enacl_crypto_onetimeauth), + {"crypto_onetimeauth_verify_b", 3, enacl_crypto_onetimeauth_verify}, erl_nif_dirty_job_cpu_bound_macro("crypto_onetimeauth_verify", 3, - enif_crypto_onetimeauth_verify), + enacl_crypto_onetimeauth_verify), {"crypto_hash_b", 1, enacl_crypto_hash}, erl_nif_dirty_job_cpu_bound_macro("crypto_hash", 1, enacl_crypto_hash), - {"crypto_verify_16", 2, enif_crypto_verify_16}, - {"crypto_verify_32", 2, enif_crypto_verify_32}, + {"crypto_verify_16", 2, enacl_crypto_verify_16}, + {"crypto_verify_32", 2, enacl_crypto_verify_32}, {"sodium_memzero", 1, enif_sodium_memzero}, - erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash", 4, enif_crypto_pwhash), + erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash", 4, enacl_crypto_pwhash), erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash_str", 3, - enif_crypto_pwhash_str), + enacl_crypto_pwhash_str), erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash_str_verify", 2, - enif_crypto_pwhash_str_verify), + enacl_crypto_pwhash_str_verify), erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult", 2, - enif_crypto_curve25519_scalarmult), + enacl_crypto_curve25519_scalarmult), erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult_base", 1, - enif_crypto_curve25519_scalarmult_base), + enacl_crypto_curve25519_scalarmult_base), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_ed25519_keypair", 0, - enif_crypto_sign_ed25519_keypair), + enacl_crypto_sign_ed25519_keypair), {"crypto_sign_ed25519_public_to_curve25519", 1, - enif_crypto_sign_ed25519_public_to_curve25519}, + enacl_crypto_sign_ed25519_public_to_curve25519}, {"crypto_sign_ed25519_secret_to_curve25519", 1, - enif_crypto_sign_ed25519_secret_to_curve25519}, + enacl_crypto_sign_ed25519_secret_to_curve25519}, {"crypto_sign_ed25519_PUBLICKEYBYTES", 0, - enif_crypto_sign_ed25519_PUBLICKEYBYTES}, + enacl_crypto_sign_ed25519_PUBLICKEYBYTES}, {"crypto_sign_ed25519_SECRETKEYBYTES", 0, - enif_crypto_sign_ed25519_SECRETKEYBYTES}, + enacl_crypto_sign_ed25519_SECRETKEYBYTES}, // Linux might block here if early in the boot sequence, so get it off the // main scheduler. Otherwise, it it would probably be fine to run on the @@ -1548,14 +1274,14 @@ static ErlNifFunc nif_funcs[] = { enif_randombytes_uniform), erl_nif_dirty_job_cpu_bound_macro("crypto_kx_keypair", 0, - enif_crypto_kx_keypair), + enacl_crypto_kx_keypair), erl_nif_dirty_job_cpu_bound_macro("crypto_kx_client_session_keys", 3, - enif_crypto_kx_client_session_keys), + enacl_crypto_kx_client_session_keys), erl_nif_dirty_job_cpu_bound_macro("crypto_kx_server_session_keys", 3, - enif_crypto_kx_server_session_keys), - {"crypto_kx_PUBLICKEYBYTES", 0, enif_crypto_kx_PUBLICKEYBYTES}, - {"crypto_kx_SECRETKEYBYTES", 0, enif_crypto_kx_SECRETKEYBYTES}, - {"crypto_kx_SESSIONKEYBYTES", 0, enif_crypto_kx_SESSIONKEYBYTES}, + enacl_crypto_kx_server_session_keys), + {"crypto_kx_PUBLICKEYBYTES", 0, enacl_crypto_kx_PUBLICKEYBYTES}, + {"crypto_kx_SECRETKEYBYTES", 0, enacl_crypto_kx_SECRETKEYBYTES}, + {"crypto_kx_SESSIONKEYBYTES", 0, enacl_crypto_kx_SESSIONKEYBYTES}, {"scramble_block_16", 2, enif_scramble_block_16}, @@ -1589,14 +1315,14 @@ static ErlNifFunc nif_funcs[] = { "crypto_aead_xchacha20poly1305_decrypt", 4, enacl_crypto_aead_xchacha20poly1305_decrypt), - {"crypto_generichash_BYTES", 0, enif_crypto_generichash_BYTES}, - {"crypto_generichash_BYTES_MIN", 0, enif_crypto_generichash_BYTES_MIN}, - {"crypto_generichash_BYTES_MAX", 0, enif_crypto_generichash_BYTES_MAX}, - {"crypto_generichash_KEYBYTES", 0, enif_crypto_generichash_KEYBYTES}, + {"crypto_generichash_BYTES", 0, enacl_crypto_generichash_BYTES}, + {"crypto_generichash_BYTES_MIN", 0, enacl_crypto_generichash_BYTES_MIN}, + {"crypto_generichash_BYTES_MAX", 0, enacl_crypto_generichash_BYTES_MAX}, + {"crypto_generichash_KEYBYTES", 0, enacl_crypto_generichash_KEYBYTES}, {"crypto_generichash_KEYBYTES_MIN", 0, - enif_crypto_generichash_KEYBYTES_MIN}, + enacl_crypto_generichash_KEYBYTES_MIN}, {"crypto_generichash_KEYBYTES_MAX", 0, - enif_crypto_generichash_KEYBYTES_MAX}, + enacl_crypto_generichash_KEYBYTES_MAX}, {"crypto_generichash", 3, enacl_crypto_generichash}, {"crypto_generichash_init", 2, enacl_crypto_generichash_init}, {"crypto_generichash_update", 2, enacl_crypto_generichash_update}, @@ -1604,4 +1330,4 @@ static ErlNifFunc nif_funcs[] = { }; -ERL_NIF_INIT(enacl_nif, nif_funcs, enif_crypto_load, NULL, NULL, NULL); +ERL_NIF_INIT(enacl_nif, nif_funcs, enacl_crypto_load, NULL, NULL, NULL); diff --git a/c_src/generichash.c b/c_src/generichash.c index 9993bf7..82afd32 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -43,33 +43,33 @@ static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env, /* * Generic hash */ -ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +ERL_NIF_TERM enacl_crypto_generichash_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_generichash_BYTES); } -ERL_NIF_TERM enif_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +ERL_NIF_TERM enacl_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_generichash_BYTES_MIN); } -ERL_NIF_TERM enif_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +ERL_NIF_TERM enacl_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_generichash_BYTES_MAX); } -ERL_NIF_TERM enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_generichash_KEYBYTES); } -ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_generichash_KEYBYTES_MIN); } -ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_generichash_KEYBYTES_MAX); } diff --git a/c_src/generichash.h b/c_src/generichash.h index a348893..aaa9c66 100644 --- a/c_src/generichash.h +++ b/c_src/generichash.h @@ -3,19 +3,19 @@ int enacl_init_generic_hash_ctx(ErlNifEnv *env); -ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]); -ERL_NIF_TERM enif_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]); -ERL_NIF_TERM enif_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enacl_crypto_generichash_BYTES(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enacl_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enacl_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); -ERL_NIF_TERM enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]); -ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]); -ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enacl_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); diff --git a/c_src/sign.c b/c_src/sign.c index bb82f65..1413873 100644 --- a/c_src/sign.c +++ b/c_src/sign.c @@ -10,9 +10,9 @@ typedef struct enacl_sign_ctx { int alive; // Is the context still valid for updates/finalization } enacl_sign_ctx; -static ErlNifResourceType *enacl_sign_ctx_rtype = NULL; +ErlNifResourceType *enacl_sign_ctx_rtype = NULL; -static void enacl_sign_ctx_dtor(ErlNifEnv *env, enacl_sign_ctx *); +void enacl_sign_ctx_dtor(ErlNifEnv *env, enacl_sign_ctx *); int enacl_init_sign_ctx(ErlNifEnv *env) { enacl_sign_ctx_rtype = @@ -26,7 +26,7 @@ int enacl_init_sign_ctx(ErlNifEnv *env) { return 1; } -static void enacl_sign_ctx_dtor(ErlNifEnv *env, enacl_sign_ctx *obj) { +void enacl_sign_ctx_dtor(ErlNifEnv *env, enacl_sign_ctx *obj) { if (!obj->alive) return; @@ -214,3 +214,278 @@ cleanup: return ret; } + +/* Ed 25519 */ +ERL_NIF_TERM +enacl_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk; + + if (argc != 0) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (!enif_alloc_binary(crypto_sign_ed25519_SECRETKEYBYTES, &sk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_sign_ed25519_keypair(pk.data, sk.data); + + return enif_make_tuple2(env, enif_make_binary(env, &pk), + enif_make_binary(env, &sk)); +} + +ERL_NIF_TERM +enacl_crypto_sign_ed25519_sk_to_pk(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk; + + if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &sk)) || + (sk.size != crypto_sign_ed25519_SECRETKEYBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_sign_ed25519_sk_to_pk(pk.data, sk.data) != 0) { + return nacl_error_tuple(env, "crypto_sign_ed25519_sk_to_pk_failed"); + } + + return enif_make_binary(env, &pk); +} + +ERL_NIF_TERM +enacl_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary curve25519_pk, ed25519_pk; + + if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &ed25519_pk)) || + (ed25519_pk.size != crypto_sign_ed25519_PUBLICKEYBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_sign_ed25519_pk_to_curve25519(curve25519_pk.data, + ed25519_pk.data) != 0) { + return nacl_error_tuple(env, "ed25519_public_to_curve25519_failed"); + } + + return enif_make_binary(env, &curve25519_pk); +} + +ERL_NIF_TERM +enacl_crypto_sign_ed25519_secret_to_curve25519(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary curve25519_sk, ed25519_sk; + + if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &ed25519_sk)) || + (ed25519_sk.size != crypto_sign_ed25519_SECRETKEYBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_sk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_sign_ed25519_sk_to_curve25519(curve25519_sk.data, + ed25519_sk.data) != 0) { + return nacl_error_tuple(env, "ed25519_secret_to_curve25519_failed"); + } + + return enif_make_binary(env, &curve25519_sk); +} + +ERL_NIF_TERM +enacl_crypto_sign_ed25519_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_sign_ed25519_PUBLICKEYBYTES); +} + +ERL_NIF_TERM +enacl_crypto_sign_ed25519_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_sign_ed25519_SECRETKEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_sign_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_sign_PUBLICKEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_sign_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_sign_SECRETKEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_sign_SEEDBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_sign_SEEDBYTES); +} + +ERL_NIF_TERM enacl_crypto_sign_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk; + + if (argc != 0) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_sign_keypair(pk.data, sk.data); + + return enif_make_tuple2(env, enif_make_binary(env, &pk), + enif_make_binary(env, &sk)); +} + +ERL_NIF_TERM enacl_crypto_sign_seed_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk, seed; + + if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &seed))) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_sign_seed_keypair(pk.data, sk.data, seed.data); + + return enif_make_tuple2(env, enif_make_binary(env, &pk), + enif_make_binary(env, &sk)); +} + +/* +int crypto_sign(unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sk); + */ +ERL_NIF_TERM enacl_crypto_sign(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary m, sk, sm; + unsigned long long smlen; + + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &sk))) { + return enif_make_badarg(env); + } + + if (sk.size != crypto_sign_SECRETKEYBYTES) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(m.size + crypto_sign_BYTES, &sm)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_sign(sm.data, &smlen, m.data, m.size, sk.data); + + return enif_make_sub_binary(env, enif_make_binary(env, &sm), 0, smlen); +} + +/* +int crypto_sign_open(unsigned char *m, unsigned long long *mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk); + */ +ERL_NIF_TERM enacl_crypto_sign_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary m, sm, pk; + unsigned long long mlen; + + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &sm)) || + (!enif_inspect_binary(env, argv[1], &pk))) { + return enif_make_badarg(env); + } + + if (pk.size != crypto_sign_PUBLICKEYBYTES) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(sm.size, &m)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (0 == crypto_sign_open(m.data, &mlen, sm.data, sm.size, pk.data)) { + return enif_make_sub_binary(env, enif_make_binary(env, &m), 0, mlen); + } else { + enif_release_binary(&m); + return nacl_error_tuple(env, "failed_verification"); + } +} + +/* +int crypto_sign_detached(unsigned char *sig, unsigned long long *siglen, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sk); + */ +ERL_NIF_TERM enacl_crypto_sign_detached(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary m, sk, sig; + unsigned long long siglen; + + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &sk))) { + return enif_make_badarg(env); + } + + if (sk.size != crypto_sign_SECRETKEYBYTES) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_sign_detached(sig.data, &siglen, m.data, m.size, sk.data); + + return enif_make_binary(env, &sig); +} + +/* +int crypto_sign_verify_detached(const unsigned char *sig, + const unsigned char *m, + unsigned long long mlen, + const unsigned char *pk); + */ +ERL_NIF_TERM +enacl_crypto_sign_verify_detached(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary m, sig, pk; + + if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &sig)) || + (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || + (!enif_inspect_binary(env, argv[2], &pk))) { + return enif_make_badarg(env); + } + + if (pk.size != crypto_sign_PUBLICKEYBYTES) { + return enif_make_badarg(env); + } + + if (0 == crypto_sign_verify_detached(sig.data, m.data, m.size, pk.data)) { + return enif_make_atom(env, "true"); + } else { + return enif_make_atom(env, "false"); + } +} diff --git a/c_src/sign.h b/c_src/sign.h index 5b91ce3..fced63a 100644 --- a/c_src/sign.h +++ b/c_src/sign.h @@ -16,4 +16,55 @@ ERL_NIF_TERM enacl_crypto_sign_final_create(ErlNifEnv *env, int argc, ERL_NIF_TERM enacl_crypto_sign_final_verify(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_ed25519_sk_to_pk(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM +enacl_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM +enacl_crypto_sign_ed25519_secret_to_curve25519(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM +enacl_crypto_sign_ed25519_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM +enacl_crypto_sign_ed25519_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_SEEDBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_seed_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_sign_detached(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM +enacl_crypto_sign_verify_detached(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + #endif \ No newline at end of file From 2ea36a7352577f4f77abf8433f7a0ba8d500049c Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 20 Jan 2020 14:37:47 +0100 Subject: [PATCH 039/162] Start an "Upcoming changes" list We want to fix a number of problems in the library. So we write down what we are going to do in order to make it clearer to people. --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a42ea2..fe0d620 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [Upcoming changes] + +Over time, a number of bad things have snuck themselves into these bindings. This +is a list of changes which are planned for a 1.0 release. + +- The argument order in some of the AEAD constructions doesn't follow those of + sodium. They should. +- The AEAD_chacha20_poly1305 construction does the nonce wrong. It assumes a 64bit + integer, though the real underlying construction accepts 12 bytes. The key isn't + generated like this. The AEAD_xchacha20_poly1305 construction does it correctly. + ## [Unreleased] ### Added From fddbefeabd86ba3e389f35831980abb38b7186b3 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 20 Jan 2020 14:38:09 +0100 Subject: [PATCH 040/162] Simple AEAD unit tests --- test/enacl_SUITE.erl | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index 14326c1..9b3bfec 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -35,16 +35,19 @@ end_per_testcase(_Case, _Config) -> ok. groups() -> - GenericHashNeg = {generichash_neg, [shuffle, parallel], + Neg = {negative, [shuffle, parallel], [generichash_basic_neg]}, - GenericHash = {generichash, [shuffle, parallel, {repeat, 100}], + Pos = {positive, [shuffle, parallel], [generichash_basic_pos, - generichash_chunked]}, + generichash_chunked, + aead_xchacha20poly1305, + aead_chacha20poly1305]}, - [GenericHashNeg, GenericHash]. + [Neg, Pos]. all() -> - [{group, generichash}]. + [{group, negative}, + {group, positive}]. %% -- BASIC -------------------------------------- generichash_basic_neg(_Config) -> @@ -84,3 +87,25 @@ generichash_chunked(State, Msg, N) -> State2 = enacl:generichash_update(State, Msg), generichash_chunked(State2, Msg, N-1). +aead_xchacha20poly1305(_Config) -> + NonceLen = enacl:aead_xchacha20poly1305_NONCEBYTES(), + KLen = enacl:aead_xchacha20poly1305_KEYBYTES(), + Key = binary:copy(<<"K">>, KLen), + Msg = <<"test">>, + AD = <<1,2,3,4,5,6>>, + Nonce = binary:copy(<<"N">>, NonceLen), + + CipherText = enacl:aead_xchacha20poly1305_encrypt(Key, Nonce, AD, Msg), + Msg = enacl:aead_xchacha20poly1305_decrypt(Key, Nonce, AD, CipherText), + ok. + +aead_chacha20poly1305(_Config) -> + KLen = enacl:aead_chacha20poly1305_KEYBYTES(), + Key = binary:copy(<<"K">>, KLen), + Msg = <<"test">>, + AD = <<1,2,3,4,5,6>>, + Nonce = 1337, + + CipherText = enacl:aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg), + Msg = enacl:aead_chacha20poly1305_decrypt(Key, Nonce, AD, CipherText), + ok. From d3c033c4e64912db68c52690e9aa3a8f17ff3161 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 20 Jan 2020 14:38:20 +0100 Subject: [PATCH 041/162] Split off password hashing --- c_src/enacl_nif.c | 153 +--------------------------------------------- c_src/pwhash.c | 152 +++++++++++++++++++++++++++++++++++++++++++++ c_src/pwhash.h | 15 +++++ 3 files changed, 170 insertions(+), 150 deletions(-) create mode 100644 c_src/pwhash.c create mode 100644 c_src/pwhash.h diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 8065cd2..7eacd77 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1,12 +1,13 @@ -#include "erl_nif.h" - #include #include +#include "erl_nif.h" + #include "aead.h" #include "enacl.h" #include "generichash.h" #include "hash.h" +#include "pwhash.h" #include "sign.h" #define CRYPTO_SIGN_STATE_RESOURCE "crypto_sign_state" @@ -982,154 +983,6 @@ static ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, return enif_make_binary(env, &out); } -static size_t enacl_pwhash_opslimit(ErlNifEnv *env, ERL_NIF_TERM arg) { - ERL_NIF_TERM a; - size_t r; - - if (enif_is_atom(env, arg)) { - a = enif_make_atom(env, "interactive"); - if (enif_is_identical(a, arg)) { - return crypto_pwhash_OPSLIMIT_INTERACTIVE; - } - - a = enif_make_atom(env, "moderate"); - if (enif_is_identical(a, arg)) { - return crypto_pwhash_OPSLIMIT_MODERATE; - } - - a = enif_make_atom(env, "sensitive"); - if (enif_is_identical(a, arg)) { - return crypto_pwhash_OPSLIMIT_SENSITIVE; - } - } else if (enif_get_ulong(env, arg, &r)) { - return r; - } - - return 0; -} - -static size_t enacl_pwhash_memlimit(ErlNifEnv *env, ERL_NIF_TERM arg) { - ERL_NIF_TERM a; - size_t r; - - if (enif_is_atom(env, arg)) { - a = enif_make_atom(env, "interactive"); - if (enif_is_identical(a, arg)) { - return crypto_pwhash_MEMLIMIT_INTERACTIVE; - } - - a = enif_make_atom(env, "moderate"); - if (enif_is_identical(a, arg)) { - return crypto_pwhash_MEMLIMIT_MODERATE; - } - - a = enif_make_atom(env, "sensitive"); - if (enif_is_identical(a, arg)) { - return crypto_pwhash_MEMLIMIT_SENSITIVE; - } - } else if (enif_get_ulong(env, arg, &r)) { - return r; - } - - return 0; -} - -static ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary h, p, s; - size_t o, m; - - // Validate the arguments - if ((argc != 4) || (!enif_inspect_iolist_as_binary(env, argv[0], &p)) || - (!enif_inspect_binary(env, argv[1], &s)) || - !(o = enacl_pwhash_opslimit(env, argv[2])) || - !(m = enacl_pwhash_memlimit(env, argv[3]))) { - return enif_make_badarg(env); - } - - // Check limits - if ((o < crypto_pwhash_OPSLIMIT_MIN) || (o > crypto_pwhash_OPSLIMIT_MAX) || - (m < crypto_pwhash_MEMLIMIT_MIN) || (m > crypto_pwhash_MEMLIMIT_MAX)) { - return enif_make_badarg(env); - } - - // Check Salt size - if (s.size != crypto_pwhash_SALTBYTES) { - return nacl_error_tuple(env, "invalid_salt_size"); - } - - // Allocate memory for return binary - if (!enif_alloc_binary(crypto_box_SEEDBYTES, &h)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (crypto_pwhash(h.data, h.size, (char *)p.data, p.size, s.data, o, m, - crypto_pwhash_ALG_DEFAULT) != 0) { - /* out of memory */ - enif_release_binary(&h); - return nacl_error_tuple(env, "out_of_memory"); - } - - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret = enif_make_binary(env, &h); - - return enif_make_tuple2(env, ok, ret); -} - -static ERL_NIF_TERM enacl_crypto_pwhash_str(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary h, p; - size_t o, m; - - // Validate the arguments - if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &p)) || - !(o = enacl_pwhash_opslimit(env, argv[1])) || - !(m = enacl_pwhash_memlimit(env, argv[2]))) { - return enif_make_badarg(env); - } - - // Check limits - if ((o < crypto_pwhash_OPSLIMIT_MIN) || (o > crypto_pwhash_OPSLIMIT_MAX) || - (m < crypto_pwhash_MEMLIMIT_MIN) || (m > crypto_pwhash_MEMLIMIT_MAX)) { - return enif_make_badarg(env); - } - - // Allocate memory for return binary - if (!enif_alloc_binary(crypto_pwhash_STRBYTES, &h)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (crypto_pwhash_str((char *)h.data, (char *)p.data, p.size, o, m) != 0) { - /* out of memory */ - enif_release_binary(&h); - return nacl_error_tuple(env, "out_of_memory"); - } - - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret = enif_make_binary(env, &h); - - return enif_make_tuple2(env, ok, ret); -} - -static ERL_NIF_TERM enacl_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary h, p; - - // Validate the arguments - if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &h)) || - (!enif_inspect_iolist_as_binary(env, argv[1], &p))) { - return enif_make_badarg(env); - } - - ERL_NIF_TERM retVal = enif_make_atom(env, ATOM_TRUE); - if (crypto_pwhash_str_verify((char *)h.data, (char *)p.data, p.size) != 0) { - /* wrong password */ - retVal = enif_make_atom(env, ATOM_FALSE); - } - - return retVal; -} - /* Tie the knot to the Erlang world */ static ErlNifFunc nif_funcs[] = { {"crypto_box_NONCEBYTES", 0, enacl_crypto_box_NONCEBYTES}, diff --git a/c_src/pwhash.c b/c_src/pwhash.c new file mode 100644 index 0000000..29b7f5c --- /dev/null +++ b/c_src/pwhash.c @@ -0,0 +1,152 @@ +#include + +#include "enacl.h" +#include "erl_nif.h" +#include "pwhash.h" + +static size_t enacl_pwhash_opslimit(ErlNifEnv *env, ERL_NIF_TERM arg) { + ERL_NIF_TERM a; + size_t r; + + if (enif_is_atom(env, arg)) { + a = enif_make_atom(env, "interactive"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_OPSLIMIT_INTERACTIVE; + } + + a = enif_make_atom(env, "moderate"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_OPSLIMIT_MODERATE; + } + + a = enif_make_atom(env, "sensitive"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_OPSLIMIT_SENSITIVE; + } + } else if (enif_get_ulong(env, arg, &r)) { + return r; + } + + return 0; +} + +static size_t enacl_pwhash_memlimit(ErlNifEnv *env, ERL_NIF_TERM arg) { + ERL_NIF_TERM a; + size_t r; + + if (enif_is_atom(env, arg)) { + a = enif_make_atom(env, "interactive"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_MEMLIMIT_INTERACTIVE; + } + + a = enif_make_atom(env, "moderate"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_MEMLIMIT_MODERATE; + } + + a = enif_make_atom(env, "sensitive"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_MEMLIMIT_SENSITIVE; + } + } else if (enif_get_ulong(env, arg, &r)) { + return r; + } + + return 0; +} + +ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary h, p, s; + size_t o, m; + + // Validate the arguments + if ((argc != 4) || (!enif_inspect_iolist_as_binary(env, argv[0], &p)) || + (!enif_inspect_binary(env, argv[1], &s)) || + !(o = enacl_pwhash_opslimit(env, argv[2])) || + !(m = enacl_pwhash_memlimit(env, argv[3]))) { + return enif_make_badarg(env); + } + + // Check limits + if ((o < crypto_pwhash_OPSLIMIT_MIN) || (o > crypto_pwhash_OPSLIMIT_MAX) || + (m < crypto_pwhash_MEMLIMIT_MIN) || (m > crypto_pwhash_MEMLIMIT_MAX)) { + return enif_make_badarg(env); + } + + // Check Salt size + if (s.size != crypto_pwhash_SALTBYTES) { + return nacl_error_tuple(env, "invalid_salt_size"); + } + + // Allocate memory for return binary + if (!enif_alloc_binary(crypto_box_SEEDBYTES, &h)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_pwhash(h.data, h.size, (char *)p.data, p.size, s.data, o, m, + crypto_pwhash_ALG_DEFAULT) != 0) { + /* out of memory */ + enif_release_binary(&h); + return nacl_error_tuple(env, "out_of_memory"); + } + + ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret = enif_make_binary(env, &h); + + return enif_make_tuple2(env, ok, ret); +} + +ERL_NIF_TERM enacl_crypto_pwhash_str(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary h, p; + size_t o, m; + + // Validate the arguments + if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &p)) || + !(o = enacl_pwhash_opslimit(env, argv[1])) || + !(m = enacl_pwhash_memlimit(env, argv[2]))) { + return enif_make_badarg(env); + } + + // Check limits + if ((o < crypto_pwhash_OPSLIMIT_MIN) || (o > crypto_pwhash_OPSLIMIT_MAX) || + (m < crypto_pwhash_MEMLIMIT_MIN) || (m > crypto_pwhash_MEMLIMIT_MAX)) { + return enif_make_badarg(env); + } + + // Allocate memory for return binary + if (!enif_alloc_binary(crypto_pwhash_STRBYTES, &h)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_pwhash_str((char *)h.data, (char *)p.data, p.size, o, m) != 0) { + /* out of memory */ + enif_release_binary(&h); + return nacl_error_tuple(env, "out_of_memory"); + } + + ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret = enif_make_binary(env, &h); + + return enif_make_tuple2(env, ok, ret); +} + +ERL_NIF_TERM enacl_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary h, p; + // Validate the arguments + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &h)) || + (!enif_inspect_iolist_as_binary(env, argv[1], &p))) { + return enif_make_badarg(env); + } + + ERL_NIF_TERM ret = enif_make_atom(env, ATOM_TRUE); + if (crypto_pwhash_str_verify((char *)h.data, (char *)p.data, p.size) != 0) { + /* wrong password */ + ret = enif_make_atom(env, ATOM_FALSE); + } + + return ret; +} diff --git a/c_src/pwhash.h b/c_src/pwhash.h new file mode 100644 index 0000000..8ba8c5d --- /dev/null +++ b/c_src/pwhash.h @@ -0,0 +1,15 @@ +#ifndef ENACL_PWHASH_H +#define ENACL_PWHASH_H + +#include "erl_nif.h" + +ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_pwhash_str(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +#endif From 460c5bddfda32f8d2f2b5c13a2ef62dc242c1d35 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 20 Jan 2020 14:45:52 +0100 Subject: [PATCH 042/162] Rudimentary test of pwhash --- test/enacl_SUITE.erl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index 9b3bfec..eb4d5fa 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -41,7 +41,8 @@ groups() -> [generichash_basic_pos, generichash_chunked, aead_xchacha20poly1305, - aead_chacha20poly1305]}, + aead_chacha20poly1305, + pwhash]}, [Neg, Pos]. @@ -109,3 +110,14 @@ aead_chacha20poly1305(_Config) -> CipherText = enacl:aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg), Msg = enacl:aead_chacha20poly1305_decrypt(Key, Nonce, AD, CipherText), ok. + +pwhash(_Config) -> + PW = <<"XYZZY">>, + Salt = <<"1234567890abcdef">>, + Hash1 = <<164,75,127,151,168,101,55,77,48,77,240,204,64,20,43,23,88, + 18,133,11,53,151,2,113,232,95,84,165,50,7,60,20>>, + {ok, Hash1} = enacl:pwhash(PW, Salt), + {ok, Str1} = enacl:pwhash_str(PW), + true = enacl:pwhash_str_verify(Str1, PW), + false = enacl:pwhash_str_verify(Str1, <>), + ok. From fe478ea2530ef2c1bf16860f367403416b8d067b Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 20 Jan 2020 14:57:11 +0100 Subject: [PATCH 043/162] Header file fixupUse since it is a system header.Also rearrange headers to be consistent. --- c_src/aead.c | 7 ++++--- c_src/aead.h | 2 +- c_src/enacl.c | 3 ++- c_src/enacl.h | 2 +- c_src/enacl_nif.c | 46 ++---------------------------------------- c_src/generichash.c | 4 ++-- c_src/generichash.h | 2 ++ c_src/hash.c | 4 ++-- c_src/hash.h | 2 ++ c_src/pwhash.c | 3 ++- c_src/pwhash.h | 2 +- c_src/randombytes.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ c_src/randombytes.h | 15 ++++++++++++++ c_src/sign.c | 4 ++-- c_src/sign.h | 2 +- 15 files changed, 88 insertions(+), 59 deletions(-) create mode 100644 c_src/randombytes.c create mode 100644 c_src/randombytes.h diff --git a/c_src/aead.c b/c_src/aead.c index 5fa11e4..bf97c7b 100644 --- a/c_src/aead.c +++ b/c_src/aead.c @@ -1,8 +1,9 @@ +#include + +#include + #include "aead.h" #include "enacl.h" -#include "erl_nif.h" - -#include /* * AEAD ChaCha20 Poly1305 diff --git a/c_src/aead.h b/c_src/aead.h index 8f2ce5b..5188c9f 100644 --- a/c_src/aead.h +++ b/c_src/aead.h @@ -1,7 +1,7 @@ #ifndef ENACL_AEAD_H #define ENACL_AEAD_H -#include "erl_nif.h" +#include /* AEAD ChaCha20 Poly1305 */ ERL_NIF_TERM diff --git a/c_src/enacl.c b/c_src/enacl.c index e762bb4..8d3007b 100644 --- a/c_src/enacl.c +++ b/c_src/enacl.c @@ -1,5 +1,6 @@ +#include + #include "enacl.h" -#include "erl_nif.h" ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) { return enif_make_tuple2(env, enif_make_atom(env, "error"), diff --git a/c_src/enacl.h b/c_src/enacl.h index e1fc1af..3d9008a 100644 --- a/c_src/enacl.h +++ b/c_src/enacl.h @@ -1,7 +1,7 @@ #ifndef ENACL_H #define ENACL_H -#include "erl_nif.h" +#include #define ATOM_OK "ok" #define ATOM_ERROR "error" diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 7eacd77..60142d3 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1,13 +1,14 @@ #include #include -#include "erl_nif.h" +#include #include "aead.h" #include "enacl.h" #include "generichash.h" #include "hash.h" #include "pwhash.h" +#include "randombytes.h" #include "sign.h" #define CRYPTO_SIGN_STATE_RESOURCE "crypto_sign_state" @@ -757,49 +758,6 @@ static ERL_NIF_TERM enacl_crypto_onetimeauth_verify(ErlNifEnv *env, int argc, } } -static ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - unsigned req_size; - ErlNifBinary result; - - if ((argc != 1) || (!enif_get_uint(env, argv[0], &req_size))) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(req_size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - randombytes(result.data, result.size); - - return enif_make_binary(env, &result); -} - -static ERL_NIF_TERM enif_randombytes_uint32(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifUInt64 result; - - if (argc != 0) { - return enif_make_badarg(env); - } - - result = randombytes_random(); - return enif_make_uint64(env, result); -} - -static ERL_NIF_TERM enif_randombytes_uniform(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - unsigned upper_bound; - ErlNifUInt64 result; - - if ((argc != 1) || (!enif_get_uint(env, argv[0], &upper_bound))) { - return enif_make_badarg(env); - } - - result = randombytes_uniform(upper_bound); - return enif_make_uint64(env, result); -} - /* Key exchange */ static ERL_NIF_TERM enacl_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc, diff --git a/c_src/generichash.c b/c_src/generichash.c index 82afd32..f74bbb2 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -1,7 +1,7 @@ -#include "erl_nif.h" - #include +#include + #include "enacl.h" #include "generichash.h" diff --git a/c_src/generichash.h b/c_src/generichash.h index aaa9c66..26fb317 100644 --- a/c_src/generichash.h +++ b/c_src/generichash.h @@ -1,6 +1,8 @@ #ifndef ENACL_GENERICHASH_H #define ENACL_GENERICHASH_H +#include + int enacl_init_generic_hash_ctx(ErlNifEnv *env); ERL_NIF_TERM enacl_crypto_generichash_BYTES(ErlNifEnv *env, int argc, diff --git a/c_src/hash.c b/c_src/hash.c index 21d6aa8..ac08f45 100644 --- a/c_src/hash.c +++ b/c_src/hash.c @@ -1,7 +1,7 @@ -#include "erl_nif.h" - #include +#include + #include "hash.h" ERL_NIF_TERM enacl_crypto_hash(ErlNifEnv *env, int argc, diff --git a/c_src/hash.h b/c_src/hash.h index 7ade398..9f5b721 100644 --- a/c_src/hash.h +++ b/c_src/hash.h @@ -1,6 +1,8 @@ #ifndef ENACL_HASH_H #define ENACL_HASH_H +#include + ERL_NIF_TERM enacl_crypto_hash(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); #endif \ No newline at end of file diff --git a/c_src/pwhash.c b/c_src/pwhash.c index 29b7f5c..3ee5bd5 100644 --- a/c_src/pwhash.c +++ b/c_src/pwhash.c @@ -1,7 +1,8 @@ #include +#include + #include "enacl.h" -#include "erl_nif.h" #include "pwhash.h" static size_t enacl_pwhash_opslimit(ErlNifEnv *env, ERL_NIF_TERM arg) { diff --git a/c_src/pwhash.h b/c_src/pwhash.h index 8ba8c5d..76a882f 100644 --- a/c_src/pwhash.h +++ b/c_src/pwhash.h @@ -1,7 +1,7 @@ #ifndef ENACL_PWHASH_H #define ENACL_PWHASH_H -#include "erl_nif.h" +#include ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]); diff --git a/c_src/randombytes.c b/c_src/randombytes.c new file mode 100644 index 0000000..bea290f --- /dev/null +++ b/c_src/randombytes.c @@ -0,0 +1,49 @@ +#include + +#include + +#include "enacl.h" +#include "randombytes.h" + +ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + unsigned req_size; + ErlNifBinary result; + + if ((argc != 1) || (!enif_get_uint(env, argv[0], &req_size))) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(req_size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + randombytes(result.data, result.size); + + return enif_make_binary(env, &result); +} + +ERL_NIF_TERM enif_randombytes_uint32(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifUInt64 result; + + if (argc != 0) { + return enif_make_badarg(env); + } + + result = randombytes_random(); + return enif_make_uint64(env, result); +} + +ERL_NIF_TERM enif_randombytes_uniform(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + unsigned upper_bound; + ErlNifUInt64 result; + + if ((argc != 1) || (!enif_get_uint(env, argv[0], &upper_bound))) { + return enif_make_badarg(env); + } + + result = randombytes_uniform(upper_bound); + return enif_make_uint64(env, result); +} diff --git a/c_src/randombytes.h b/c_src/randombytes.h new file mode 100644 index 0000000..bc8cedf --- /dev/null +++ b/c_src/randombytes.h @@ -0,0 +1,15 @@ +#ifndef ENACL_RANDOMBYTES_H +#define ENACL_RANDOMBYTES_H + +#include + +ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enif_randombytes_uint32(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enif_randombytes_uniform(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +#endif \ No newline at end of file diff --git a/c_src/sign.c b/c_src/sign.c index 1413873..ecba65a 100644 --- a/c_src/sign.c +++ b/c_src/sign.c @@ -1,7 +1,7 @@ -#include "erl_nif.h" - #include +#include + #include "enacl.h" #include "sign.h" diff --git a/c_src/sign.h b/c_src/sign.h index fced63a..48f8e01 100644 --- a/c_src/sign.h +++ b/c_src/sign.h @@ -1,7 +1,7 @@ #ifndef ENACL_SIGN_H #define ENACL_SIGN_H -#include "erl_nif.h" +#include int enacl_init_sign_ctx(ErlNifEnv *env); From bf6fb6cf7b78e71941db0ecd00da4642d2e15510 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 20 Jan 2020 15:31:44 +0100 Subject: [PATCH 044/162] Split the remaining operations --- CHANGELOG.md | 2 + c_src/enacl_nif.c | 715 +--------------------------------------------- c_src/hash.c | 32 +++ c_src/hash.h | 9 + c_src/kx.c | 110 +++++++ c_src/kx.h | 24 ++ c_src/public.c | 257 +++++++++++++++++ c_src/public.h | 49 ++++ c_src/secret.c | 322 +++++++++++++++++++++ c_src/secret.h | 70 +++++ 10 files changed, 888 insertions(+), 702 deletions(-) create mode 100644 c_src/kx.c create mode 100644 c_src/kx.h create mode 100644 c_src/public.c create mode 100644 c_src/public.h create mode 100644 c_src/secret.c create mode 100644 c_src/secret.h diff --git a/CHANGELOG.md b/CHANGELOG.md index fe0d620..c192c35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ is a list of changes which are planned for a 1.0 release. - The AEAD_chacha20_poly1305 construction does the nonce wrong. It assumes a 64bit integer, though the real underlying construction accepts 12 bytes. The key isn't generated like this. The AEAD_xchacha20_poly1305 construction does it correctly. +- Plug some subtle allocation leaks in the kx code. +- Plug some subtle memory leaks in the public API. ## [Unreleased] diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 60142d3..8655eb9 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -7,8 +7,11 @@ #include "enacl.h" #include "generichash.h" #include "hash.h" +#include "kx.h" +#include "public.h" #include "pwhash.h" #include "randombytes.h" +#include "secret.h" #include "sign.h" #define CRYPTO_SIGN_STATE_RESOURCE "crypto_sign_state" @@ -36,6 +39,12 @@ static int enacl_crypto_load(ErlNifEnv *env, void **priv_data, return sodium_init(); } +/* GENERAL ROUTINES + * + * These don't generally fit somewhere else nicely, so we keep them in the main + * file + * + */ static ERL_NIF_TERM enacl_crypto_verify_16(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary x, y; @@ -159,708 +168,6 @@ enacl_crypto_curve25519_scalarmult_base(ErlNifEnv *env, int argc, return result; } -/* Public-key cryptography */ -static ERL_NIF_TERM enacl_crypto_box_NONCEBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_NONCEBYTES); -} - -static ERL_NIF_TERM enacl_crypto_box_ZEROBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_ZEROBYTES); -} - -static ERL_NIF_TERM enacl_crypto_box_BOXZEROBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_BOXZEROBYTES); -} - -static ERL_NIF_TERM enacl_crypto_box_PUBLICKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_PUBLICKEYBYTES); -} - -static ERL_NIF_TERM enacl_crypto_box_SECRETKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_SECRETKEYBYTES); -} - -static ERL_NIF_TERM enacl_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_BEFORENMBYTES); -} - -static ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sk; - - if (argc != 0) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_box_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (!enif_alloc_binary(crypto_box_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_box_keypair(pk.data, sk.data); - - return enif_make_tuple2(env, enif_make_binary(env, &pk), - enif_make_binary(env, &sk)); -} - -static ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary padded_msg, nonce, pk, sk, result; - - if ((argc != 4) || - (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &pk)) || - (!enif_inspect_binary(env, argv[3], &sk))) { - return enif_make_badarg(env); - } - - if ((nonce.size != crypto_box_NONCEBYTES) || - (pk.size != crypto_box_PUBLICKEYBYTES) || - (sk.size != crypto_box_SECRETKEYBYTES) || - (padded_msg.size < crypto_box_ZEROBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(padded_msg.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data, - pk.data, sk.data)) { - return nacl_error_tuple(env, "box_error"); - } - - return enif_make_sub_binary(env, enif_make_binary(env, &result), - crypto_box_BOXZEROBYTES, - padded_msg.size - crypto_box_BOXZEROBYTES); -} - -static ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary padded_ciphertext, nonce, pk, sk, result; - - if ((argc != 4) || - (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &pk)) || - (!enif_inspect_binary(env, argv[3], &sk))) { - return enif_make_badarg(env); - } - - if ((nonce.size != crypto_box_NONCEBYTES) || - (pk.size != crypto_box_PUBLICKEYBYTES) || - (sk.size != crypto_box_SECRETKEYBYTES) || - (padded_ciphertext.size < crypto_box_BOXZEROBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(padded_ciphertext.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (0 != crypto_box_open(result.data, padded_ciphertext.data, - padded_ciphertext.size, nonce.data, pk.data, - sk.data)) { - enif_release_binary(&result); - return nacl_error_tuple(env, "failed_verification"); - } - - return enif_make_sub_binary(env, enif_make_binary(env, &result), - crypto_box_ZEROBYTES, - padded_ciphertext.size - crypto_box_ZEROBYTES); -} - -/* Precomputed crypto boxes */ - -static ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary k, pk, sk; - - if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &pk)) || - (!enif_inspect_binary(env, argv[1], &sk)) || - (pk.size != crypto_box_PUBLICKEYBYTES) || - (sk.size != crypto_box_SECRETKEYBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_box_BEFORENMBYTES, &k)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (0 != crypto_box_beforenm(k.data, pk.data, sk.data)) { - // error - return nacl_error_tuple(env, "error_gen_shared_secret"); - } - - return enif_make_binary(env, &k); -} - -static ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary result, m, nonce, k; - - if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &k)) || - (m.size < crypto_box_ZEROBYTES) || - (nonce.size != crypto_box_NONCEBYTES) || - (k.size != crypto_box_BEFORENMBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(m.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data); - - return enif_make_sub_binary(env, enif_make_binary(env, &result), - crypto_box_BOXZEROBYTES, - m.size - crypto_box_BOXZEROBYTES); -} - -static ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary result, m, nonce, k; - - if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &k)) || - (m.size < crypto_box_BOXZEROBYTES) || - (nonce.size != crypto_box_NONCEBYTES) || - (k.size != crypto_box_BEFORENMBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(m.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (0 != crypto_box_open_afternm(result.data, m.data, m.size, nonce.data, - k.data)) { - enif_release_binary(&result); - return nacl_error_tuple(env, "failed_verification"); - } - - return enif_make_sub_binary(env, enif_make_binary(env, &result), - crypto_box_ZEROBYTES, - m.size - crypto_box_ZEROBYTES); -} - -/* Sealed box functions */ - -static ERL_NIF_TERM enacl_crypto_box_SEALBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_SEALBYTES); -} - -static ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary key, msg, ciphertext; - - if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &msg)) || - (!enif_inspect_binary(env, argv[1], &key))) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(msg.size + crypto_box_SEALBYTES, &ciphertext)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_box_seal(ciphertext.data, msg.data, msg.size, key.data); - - return enif_make_binary(env, &ciphertext); -} - -static ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sk, ciphertext, msg; - - if ((argc != 3) || - (!enif_inspect_iolist_as_binary(env, argv[0], &ciphertext)) || - (!enif_inspect_binary(env, argv[1], &pk)) || - (!enif_inspect_binary(env, argv[2], &sk))) { - return enif_make_badarg(env); - } - - if (ciphertext.size < crypto_box_SEALBYTES) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(ciphertext.size - crypto_box_SEALBYTES, &msg)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (crypto_box_seal_open(msg.data, ciphertext.data, ciphertext.size, pk.data, - sk.data) != 0) { - enif_release_binary(&msg); - return nacl_error_tuple(env, "failed_verification"); - } - - return enif_make_binary(env, &msg); -} - -/* Secret key cryptography */ - -static ERL_NIF_TERM -enacl_crypto_secretbox_NONCEBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_secretbox_NONCEBYTES); -} - -static ERL_NIF_TERM enacl_crypto_secretbox_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_secretbox_KEYBYTES); -} - -static ERL_NIF_TERM -enacl_crypto_secretbox_ZEROBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_secretbox_ZEROBYTES); -} - -static ERL_NIF_TERM -enacl_crypto_secretbox_BOXZEROBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_secretbox_BOXZEROBYTES); -} - -static ERL_NIF_TERM -enacl_crypto_stream_chacha20_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_stream_chacha20_KEYBYTES); -} - -static ERL_NIF_TERM -enacl_crypto_stream_chacha20_NONCEBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_stream_chacha20_NONCEBYTES); -} - -static ERL_NIF_TERM enacl_crypto_stream_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_stream_KEYBYTES); -} - -static ERL_NIF_TERM enacl_crypto_stream_NONCEBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_stream_NONCEBYTES); -} - -static ERL_NIF_TERM enacl_crypto_auth_BYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_auth_BYTES); -} - -static ERL_NIF_TERM enacl_crypto_auth_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_auth_KEYBYTES); -} - -static ERL_NIF_TERM enacl_crypto_shorthash_BYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_shorthash_BYTES); -} - -static ERL_NIF_TERM enacl_crypto_shorthash_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_shorthash_KEYBYTES); -} - -static ERL_NIF_TERM enacl_crypto_onetimeauth_BYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_onetimeauth_BYTES); -} - -static ERL_NIF_TERM -enacl_crypto_onetimeauth_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_onetimeauth_KEYBYTES); -} - -static ERL_NIF_TERM enacl_crypto_secretbox(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary key, nonce, padded_msg, padded_ciphertext; - - if ((argc != 3) || - (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &key))) { - return enif_make_badarg(env); - } - - if ((key.size != crypto_secretbox_KEYBYTES) || - (nonce.size != crypto_secretbox_NONCEBYTES) || - (padded_msg.size < crypto_secretbox_ZEROBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(padded_msg.size, &padded_ciphertext)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_secretbox(padded_ciphertext.data, padded_msg.data, padded_msg.size, - nonce.data, key.data); - - return enif_make_sub_binary(env, enif_make_binary(env, &padded_ciphertext), - crypto_secretbox_BOXZEROBYTES, - padded_msg.size - crypto_secretbox_BOXZEROBYTES); -} - -static ERL_NIF_TERM enacl_crypto_secretbox_open(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary key, nonce, padded_ciphertext, padded_msg; - - if ((argc != 3) || - (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &key))) { - return enif_make_badarg(env); - } - - if ((key.size != crypto_secretbox_KEYBYTES) || - (nonce.size != crypto_secretbox_NONCEBYTES) || - (padded_ciphertext.size < crypto_secretbox_BOXZEROBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(padded_ciphertext.size, &padded_msg)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (crypto_secretbox_open(padded_msg.data, padded_ciphertext.data, - padded_ciphertext.size, nonce.data, - key.data) != 0) { - enif_release_binary(&padded_msg); - return nacl_error_tuple(env, "failed_verification"); - } - - return enif_make_sub_binary( - env, enif_make_binary(env, &padded_msg), crypto_secretbox_ZEROBYTES, - padded_ciphertext.size - crypto_secretbox_ZEROBYTES); -} - -static ERL_NIF_TERM enacl_crypto_stream_chacha20(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary c, n, k; - ErlNifUInt64 clen; - - if ((argc != 3) || (!enif_get_uint64(env, argv[0], &clen)) || - (!enif_inspect_binary(env, argv[1], &n)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } - - if ((k.size != crypto_stream_chacha20_KEYBYTES) || - (n.size != crypto_stream_chacha20_NONCEBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(clen, &c)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_stream_chacha20(c.data, c.size, n.data, k.data); - - return enif_make_binary(env, &c); -} - -static ERL_NIF_TERM -enacl_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary c, m, n, k; - - if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &n)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } - - if ((k.size != crypto_stream_chacha20_KEYBYTES) || - (n.size != crypto_stream_chacha20_NONCEBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(m.size, &c)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_stream_chacha20_xor(c.data, m.data, m.size, n.data, k.data); - - return enif_make_binary(env, &c); -} - -static ERL_NIF_TERM enacl_crypto_stream(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary c, n, k; - ErlNifUInt64 clen; - - if ((argc != 3) || (!enif_get_uint64(env, argv[0], &clen)) || - (!enif_inspect_binary(env, argv[1], &n)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } - - if ((k.size != crypto_stream_KEYBYTES) || - (n.size != crypto_stream_NONCEBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(clen, &c)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_stream(c.data, c.size, n.data, k.data); - - return enif_make_binary(env, &c); -} - -static ERL_NIF_TERM enacl_crypto_stream_xor(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary c, m, n, k; - - if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &n)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } - - if ((k.size != crypto_stream_KEYBYTES) || - (n.size != crypto_stream_NONCEBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(m.size, &c)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_stream_xor(c.data, m.data, m.size, n.data, k.data); - - return enif_make_binary(env, &c); -} - -static ERL_NIF_TERM enacl_crypto_auth(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary a, m, k; - - if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &k))) { - return enif_make_badarg(env); - } - - if (k.size != crypto_auth_KEYBYTES) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_auth_BYTES, &a)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_auth(a.data, m.data, m.size, k.data); - - return enif_make_binary(env, &a); -} - -static ERL_NIF_TERM enacl_crypto_auth_verify(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary a, m, k; - - if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &a)) || - (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } - - if ((k.size != crypto_auth_KEYBYTES) || (a.size != crypto_auth_BYTES)) { - return enif_make_badarg(env); - } - - if (0 == crypto_auth_verify(a.data, m.data, m.size, k.data)) { - return enif_make_atom(env, "true"); - } else { - return enif_make_atom(env, "false"); - } -} - -static ERL_NIF_TERM enacl_crypto_shorthash(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary a, m, k; - - if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &k))) { - return enif_make_badarg(env); - } - - if (k.size != crypto_shorthash_KEYBYTES) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_shorthash_BYTES, &a)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_shorthash(a.data, m.data, m.size, k.data); - - return enif_make_binary(env, &a); -} - -static ERL_NIF_TERM enacl_crypto_onetimeauth(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary a, m, k; - - if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || - (!enif_inspect_binary(env, argv[1], &k))) { - return enif_make_badarg(env); - } - - if (k.size != crypto_onetimeauth_KEYBYTES) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_onetimeauth_BYTES, &a)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_onetimeauth(a.data, m.data, m.size, k.data); - - return enif_make_binary(env, &a); -} - -static ERL_NIF_TERM enacl_crypto_onetimeauth_verify(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary a, m, k; - - if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &a)) || - (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || - (!enif_inspect_binary(env, argv[2], &k))) { - return enif_make_badarg(env); - } - - if ((k.size != crypto_onetimeauth_KEYBYTES) || - (a.size != crypto_onetimeauth_BYTES)) { - return enif_make_badarg(env); - } - - if (0 == crypto_onetimeauth_verify(a.data, m.data, m.size, k.data)) { - return enif_make_atom(env, "true"); - } else { - return enif_make_atom(env, "false"); - } -} - -/* Key exchange */ - -static ERL_NIF_TERM enacl_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_kx_SECRETKEYBYTES); -} - -static ERL_NIF_TERM enacl_crypto_kx_PUBLICKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_kx_PUBLICKEYBYTES); -} - -static ERL_NIF_TERM enacl_crypto_kx_SESSIONKEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_kx_SESSIONKEYBYTES); -} - -static ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary pk, sk; - - if (argc != 0) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_kx_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (!enif_alloc_binary(crypto_kx_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - crypto_kx_keypair(pk.data, sk.data); - - return enif_make_tuple2(env, enif_make_binary(env, &pk), - enif_make_binary(env, &sk)); -} - -static ERL_NIF_TERM -enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary rx, tx, server_pk, server_sk, client_pk; - - if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &server_pk)) || - (!enif_inspect_binary(env, argv[1], &server_sk)) || - (!enif_inspect_binary(env, argv[2], &client_pk)) || - (server_pk.size != crypto_kx_PUBLICKEYBYTES) || - (server_sk.size != crypto_kx_SECRETKEYBYTES) || - (client_pk.size != crypto_kx_PUBLICKEYBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (0 != crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data, - server_sk.data, client_pk.data)) { - // suspicious client public key - return nacl_error_tuple(env, "invalid_client_public_key"); - } - - return enif_make_tuple2(env, enif_make_binary(env, &rx), - enif_make_binary(env, &tx)); -} - -static ERL_NIF_TERM -enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary rx, tx, client_pk, client_sk, server_pk; - - if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &client_pk)) || - (!enif_inspect_binary(env, argv[1], &client_sk)) || - (!enif_inspect_binary(env, argv[2], &server_pk)) || - (client_pk.size != crypto_kx_PUBLICKEYBYTES) || - (client_sk.size != crypto_kx_SECRETKEYBYTES) || - (server_pk.size != crypto_kx_PUBLICKEYBYTES)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - return nacl_error_tuple(env, "alloc_failed"); - } - - if (0 != crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data, - client_sk.data, server_pk.data)) { - // suspicious server public key - return nacl_error_tuple(env, "invalid_server_public_key"); - } - - return enif_make_tuple2(env, enif_make_binary(env, &rx), - enif_make_binary(env, &tx)); -} - /* Various other helper functions */ static void uint64_pack(unsigned char *y, ErlNifUInt64 x) { *y++ = x; @@ -1078,6 +385,10 @@ static ErlNifFunc nif_funcs[] = { // Linux might block here if early in the boot sequence, so get it off the // main scheduler. Otherwise, it it would probably be fine to run on the // main scheduler. This plays it safe, albeit with a performance hit. + // + // However: you shouldn't use a CSPRNG unless you need one. So it is + // probably fine to do the dirty-scheduler dance. Using the random + // material should dwarf the extraction of random material. erl_nif_dirty_job_cpu_bound_macro("randombytes", 1, enif_randombytes), erl_nif_dirty_job_cpu_bound_macro("randombytes_uint32", 0, enif_randombytes_uint32), diff --git a/c_src/hash.c b/c_src/hash.c index ac08f45..6475596 100644 --- a/c_src/hash.c +++ b/c_src/hash.c @@ -4,6 +4,38 @@ #include "hash.h" +ERL_NIF_TERM enacl_crypto_shorthash_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_shorthash_BYTES); +} + +ERL_NIF_TERM enacl_crypto_shorthash_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_shorthash_KEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_shorthash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary a, m, k; + + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &k))) { + return enif_make_badarg(env); + } + + if (k.size != crypto_shorthash_KEYBYTES) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_shorthash_BYTES, &a)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_shorthash(a.data, m.data, m.size, k.data); + + return enif_make_binary(env, &a); +} + ERL_NIF_TERM enacl_crypto_hash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary input; diff --git a/c_src/hash.h b/c_src/hash.h index 9f5b721..080b7bf 100644 --- a/c_src/hash.h +++ b/c_src/hash.h @@ -3,6 +3,15 @@ #include +ERL_NIF_TERM enacl_crypto_shorthash_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_shorthash_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_shorthash(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + ERL_NIF_TERM enacl_crypto_hash(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); #endif \ No newline at end of file diff --git a/c_src/kx.c b/c_src/kx.c new file mode 100644 index 0000000..283328b --- /dev/null +++ b/c_src/kx.c @@ -0,0 +1,110 @@ +#include + +#include + +#include "enacl.h" +#include "kx.h" + +/* Key exchange */ + +ERL_NIF_TERM enacl_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_kx_SECRETKEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_kx_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_kx_PUBLICKEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_kx_SESSIONKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_kx_SESSIONKEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk; + + if (argc != 0) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_kx_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (!enif_alloc_binary(crypto_kx_SECRETKEYBYTES, &sk)) { + enif_release_binary(&pk); + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_kx_keypair(pk.data, sk.data); + + return enif_make_tuple2(env, enif_make_binary(env, &pk), + enif_make_binary(env, &sk)); +} + +ERL_NIF_TERM +enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary rx, tx, server_pk, server_sk, client_pk; + + if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &server_pk)) || + (!enif_inspect_binary(env, argv[1], &server_sk)) || + (!enif_inspect_binary(env, argv[2], &client_pk)) || + (server_pk.size != crypto_kx_PUBLICKEYBYTES) || + (server_sk.size != crypto_kx_SECRETKEYBYTES) || + (client_pk.size != crypto_kx_PUBLICKEYBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (0 != crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data, + server_sk.data, client_pk.data)) { + // suspicious client public key + return nacl_error_tuple(env, "invalid_client_public_key"); + } + + return enif_make_tuple2(env, enif_make_binary(env, &rx), + enif_make_binary(env, &tx)); +} + +ERL_NIF_TERM +enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary rx, tx, client_pk, client_sk, server_pk; + + if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &client_pk)) || + (!enif_inspect_binary(env, argv[1], &client_sk)) || + (!enif_inspect_binary(env, argv[2], &server_pk)) || + (client_pk.size != crypto_kx_PUBLICKEYBYTES) || + (client_sk.size != crypto_kx_SECRETKEYBYTES) || + (server_pk.size != crypto_kx_PUBLICKEYBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (0 != crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data, + client_sk.data, server_pk.data)) { + // suspicious server public key + return nacl_error_tuple(env, "invalid_server_public_key"); + } + + return enif_make_tuple2(env, enif_make_binary(env, &rx), + enif_make_binary(env, &tx)); +} \ No newline at end of file diff --git a/c_src/kx.h b/c_src/kx.h new file mode 100644 index 0000000..79a7c21 --- /dev/null +++ b/c_src/kx.h @@ -0,0 +1,24 @@ +#ifndef ENACL_KX_H +#define ENACL_KX_H + +#include + +ERL_NIF_TERM enacl_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_kx_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_kx_SESSIONKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +#endif diff --git a/c_src/public.c b/c_src/public.c new file mode 100644 index 0000000..ef83f7e --- /dev/null +++ b/c_src/public.c @@ -0,0 +1,257 @@ +#include + +#include + +#include "enacl.h" +#include "public.h" + +/* Public-key cryptography */ +ERL_NIF_TERM enacl_crypto_box_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_NONCEBYTES); +} + +ERL_NIF_TERM enacl_crypto_box_ZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_ZEROBYTES); +} + +ERL_NIF_TERM enacl_crypto_box_BOXZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_BOXZEROBYTES); +} + +ERL_NIF_TERM enacl_crypto_box_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_PUBLICKEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_box_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_SECRETKEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_BEFORENMBYTES); +} + +ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk; + + if (argc != 0) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_box_PUBLICKEYBYTES, &pk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (!enif_alloc_binary(crypto_box_SECRETKEYBYTES, &sk)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_box_keypair(pk.data, sk.data); + + return enif_make_tuple2(env, enif_make_binary(env, &pk), + enif_make_binary(env, &sk)); +} + +ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary padded_msg, nonce, pk, sk, result; + + if ((argc != 4) || + (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &pk)) || + (!enif_inspect_binary(env, argv[3], &sk))) { + return enif_make_badarg(env); + } + + if ((nonce.size != crypto_box_NONCEBYTES) || + (pk.size != crypto_box_PUBLICKEYBYTES) || + (sk.size != crypto_box_SECRETKEYBYTES) || + (padded_msg.size < crypto_box_ZEROBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(padded_msg.size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data, + pk.data, sk.data)) { + return nacl_error_tuple(env, "box_error"); + } + + return enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_BOXZEROBYTES, + padded_msg.size - crypto_box_BOXZEROBYTES); +} + +ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary padded_ciphertext, nonce, pk, sk, result; + + if ((argc != 4) || + (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &pk)) || + (!enif_inspect_binary(env, argv[3], &sk))) { + return enif_make_badarg(env); + } + + if ((nonce.size != crypto_box_NONCEBYTES) || + (pk.size != crypto_box_PUBLICKEYBYTES) || + (sk.size != crypto_box_SECRETKEYBYTES) || + (padded_ciphertext.size < crypto_box_BOXZEROBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(padded_ciphertext.size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (0 != crypto_box_open(result.data, padded_ciphertext.data, + padded_ciphertext.size, nonce.data, pk.data, + sk.data)) { + enif_release_binary(&result); + return nacl_error_tuple(env, "failed_verification"); + } + + return enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_ZEROBYTES, + padded_ciphertext.size - crypto_box_ZEROBYTES); +} + +/* Precomputed crypto boxes */ + +ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary k, pk, sk; + + if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &pk)) || + (!enif_inspect_binary(env, argv[1], &sk)) || + (pk.size != crypto_box_PUBLICKEYBYTES) || + (sk.size != crypto_box_SECRETKEYBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_box_BEFORENMBYTES, &k)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (0 != crypto_box_beforenm(k.data, pk.data, sk.data)) { + // error + return nacl_error_tuple(env, "error_gen_shared_secret"); + } + + return enif_make_binary(env, &k); +} + +ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary result, m, nonce, k; + + if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &k)) || + (m.size < crypto_box_ZEROBYTES) || + (nonce.size != crypto_box_NONCEBYTES) || + (k.size != crypto_box_BEFORENMBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(m.size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data); + + return enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_BOXZEROBYTES, + m.size - crypto_box_BOXZEROBYTES); +} + +ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary result, m, nonce, k; + + if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &k)) || + (m.size < crypto_box_BOXZEROBYTES) || + (nonce.size != crypto_box_NONCEBYTES) || + (k.size != crypto_box_BEFORENMBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(m.size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (0 != crypto_box_open_afternm(result.data, m.data, m.size, nonce.data, + k.data)) { + enif_release_binary(&result); + return nacl_error_tuple(env, "failed_verification"); + } + + return enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_ZEROBYTES, + m.size - crypto_box_ZEROBYTES); +} + +/* Sealed box functions */ + +ERL_NIF_TERM enacl_crypto_box_SEALBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_SEALBYTES); +} + +ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary key, msg, ciphertext; + + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &msg)) || + (!enif_inspect_binary(env, argv[1], &key))) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(msg.size + crypto_box_SEALBYTES, &ciphertext)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_box_seal(ciphertext.data, msg.data, msg.size, key.data); + + return enif_make_binary(env, &ciphertext); +} + +ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary pk, sk, ciphertext, msg; + + if ((argc != 3) || + (!enif_inspect_iolist_as_binary(env, argv[0], &ciphertext)) || + (!enif_inspect_binary(env, argv[1], &pk)) || + (!enif_inspect_binary(env, argv[2], &sk))) { + return enif_make_badarg(env); + } + + if (ciphertext.size < crypto_box_SEALBYTES) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(ciphertext.size - crypto_box_SEALBYTES, &msg)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_box_seal_open(msg.data, ciphertext.data, ciphertext.size, pk.data, + sk.data) != 0) { + enif_release_binary(&msg); + return nacl_error_tuple(env, "failed_verification"); + } + + return enif_make_binary(env, &msg); +} diff --git a/c_src/public.h b/c_src/public.h new file mode 100644 index 0000000..b750eb1 --- /dev/null +++ b/c_src/public.h @@ -0,0 +1,49 @@ +#ifndef ENACL_PUBLIC_H +#define ENACL_PUBLIC_H + +ERL_NIF_TERM enacl_crypto_box_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_ZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_BOXZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_PUBLICKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_SECRETKEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_SEALBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +#endif \ No newline at end of file diff --git a/c_src/secret.c b/c_src/secret.c new file mode 100644 index 0000000..dc72a92 --- /dev/null +++ b/c_src/secret.c @@ -0,0 +1,322 @@ +#include + +#include + +#include "enacl.h" +#include "secret.h" + +/* Secret key cryptography */ + +ERL_NIF_TERM +enacl_crypto_secretbox_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_secretbox_NONCEBYTES); +} + +ERL_NIF_TERM enacl_crypto_secretbox_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_secretbox_KEYBYTES); +} + +ERL_NIF_TERM +enacl_crypto_secretbox_ZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_secretbox_ZEROBYTES); +} + +ERL_NIF_TERM +enacl_crypto_secretbox_BOXZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_secretbox_BOXZEROBYTES); +} + +ERL_NIF_TERM +enacl_crypto_stream_chacha20_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_stream_chacha20_KEYBYTES); +} + +ERL_NIF_TERM +enacl_crypto_stream_chacha20_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_stream_chacha20_NONCEBYTES); +} + +ERL_NIF_TERM enacl_crypto_stream_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_stream_KEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_stream_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_stream_NONCEBYTES); +} + +ERL_NIF_TERM enacl_crypto_auth_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_auth_BYTES); +} + +ERL_NIF_TERM enacl_crypto_auth_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_auth_KEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_onetimeauth_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_onetimeauth_BYTES); +} + +ERL_NIF_TERM +enacl_crypto_onetimeauth_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_onetimeauth_KEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_secretbox(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary key, nonce, padded_msg, padded_ciphertext; + + if ((argc != 3) || + (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &key))) { + return enif_make_badarg(env); + } + + if ((key.size != crypto_secretbox_KEYBYTES) || + (nonce.size != crypto_secretbox_NONCEBYTES) || + (padded_msg.size < crypto_secretbox_ZEROBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(padded_msg.size, &padded_ciphertext)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_secretbox(padded_ciphertext.data, padded_msg.data, padded_msg.size, + nonce.data, key.data); + + return enif_make_sub_binary(env, enif_make_binary(env, &padded_ciphertext), + crypto_secretbox_BOXZEROBYTES, + padded_msg.size - crypto_secretbox_BOXZEROBYTES); +} + +ERL_NIF_TERM enacl_crypto_secretbox_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary key, nonce, padded_ciphertext, padded_msg; + + if ((argc != 3) || + (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &key))) { + return enif_make_badarg(env); + } + + if ((key.size != crypto_secretbox_KEYBYTES) || + (nonce.size != crypto_secretbox_NONCEBYTES) || + (padded_ciphertext.size < crypto_secretbox_BOXZEROBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(padded_ciphertext.size, &padded_msg)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_secretbox_open(padded_msg.data, padded_ciphertext.data, + padded_ciphertext.size, nonce.data, + key.data) != 0) { + enif_release_binary(&padded_msg); + return nacl_error_tuple(env, "failed_verification"); + } + + return enif_make_sub_binary( + env, enif_make_binary(env, &padded_msg), crypto_secretbox_ZEROBYTES, + padded_ciphertext.size - crypto_secretbox_ZEROBYTES); +} + +ERL_NIF_TERM enacl_crypto_stream_chacha20(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary c, n, k; + ErlNifUInt64 clen; + + if ((argc != 3) || (!enif_get_uint64(env, argv[0], &clen)) || + (!enif_inspect_binary(env, argv[1], &n)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } + + if ((k.size != crypto_stream_chacha20_KEYBYTES) || + (n.size != crypto_stream_chacha20_NONCEBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(clen, &c)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_stream_chacha20(c.data, c.size, n.data, k.data); + + return enif_make_binary(env, &c); +} + +ERL_NIF_TERM +enacl_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary c, m, n, k; + + if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &n)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } + + if ((k.size != crypto_stream_chacha20_KEYBYTES) || + (n.size != crypto_stream_chacha20_NONCEBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(m.size, &c)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_stream_chacha20_xor(c.data, m.data, m.size, n.data, k.data); + + return enif_make_binary(env, &c); +} + +ERL_NIF_TERM enacl_crypto_stream(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary c, n, k; + ErlNifUInt64 clen; + + if ((argc != 3) || (!enif_get_uint64(env, argv[0], &clen)) || + (!enif_inspect_binary(env, argv[1], &n)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } + + if ((k.size != crypto_stream_KEYBYTES) || + (n.size != crypto_stream_NONCEBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(clen, &c)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_stream(c.data, c.size, n.data, k.data); + + return enif_make_binary(env, &c); +} + +ERL_NIF_TERM enacl_crypto_stream_xor(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary c, m, n, k; + + if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &n)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } + + if ((k.size != crypto_stream_KEYBYTES) || + (n.size != crypto_stream_NONCEBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(m.size, &c)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_stream_xor(c.data, m.data, m.size, n.data, k.data); + + return enif_make_binary(env, &c); +} + +ERL_NIF_TERM enacl_crypto_auth(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary a, m, k; + + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &k))) { + return enif_make_badarg(env); + } + + if (k.size != crypto_auth_KEYBYTES) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_auth_BYTES, &a)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_auth(a.data, m.data, m.size, k.data); + + return enif_make_binary(env, &a); +} + +ERL_NIF_TERM enacl_crypto_auth_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary a, m, k; + + if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &a)) || + (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } + + if ((k.size != crypto_auth_KEYBYTES) || (a.size != crypto_auth_BYTES)) { + return enif_make_badarg(env); + } + + if (0 == crypto_auth_verify(a.data, m.data, m.size, k.data)) { + return enif_make_atom(env, "true"); + } else { + return enif_make_atom(env, "false"); + } +} + +ERL_NIF_TERM enacl_crypto_onetimeauth(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary a, m, k; + + if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &k))) { + return enif_make_badarg(env); + } + + if (k.size != crypto_onetimeauth_KEYBYTES) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_onetimeauth_BYTES, &a)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_onetimeauth(a.data, m.data, m.size, k.data); + + return enif_make_binary(env, &a); +} + +ERL_NIF_TERM enacl_crypto_onetimeauth_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary a, m, k; + + if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &a)) || + (!enif_inspect_iolist_as_binary(env, argv[1], &m)) || + (!enif_inspect_binary(env, argv[2], &k))) { + return enif_make_badarg(env); + } + + if ((k.size != crypto_onetimeauth_KEYBYTES) || + (a.size != crypto_onetimeauth_BYTES)) { + return enif_make_badarg(env); + } + + if (0 == crypto_onetimeauth_verify(a.data, m.data, m.size, k.data)) { + return enif_make_atom(env, "true"); + } else { + return enif_make_atom(env, "false"); + } +} diff --git a/c_src/secret.h b/c_src/secret.h new file mode 100644 index 0000000..6c0a4c8 --- /dev/null +++ b/c_src/secret.h @@ -0,0 +1,70 @@ +#ifndef ENACL_SECRET_H +#define ENACL_SECRET_H + +ERL_NIF_TERM enacl_crypto_secretbox_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_secretbox_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_secretbox_ZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_secretbox_BOXZEROBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_stream_chacha20_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_stream_chacha20_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_stream_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_stream_NONCEBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_auth_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_auth_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_onetimeauth_BYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_onetimeauth_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_secretbox(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_secretbox_open(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_stream_chacha20(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_stream(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_stream_xor(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_auth(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_auth_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_onetimeauth(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_onetimeauth_verify(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +#endif From a5e66ff20420c0917bb76ce801979bf2dc695d6b Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 20 Jan 2020 15:38:42 +0100 Subject: [PATCH 045/162] Reap a #define --- c_src/enacl_nif.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 8655eb9..52bbc7d 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -14,8 +14,6 @@ #include "secret.h" #include "sign.h" -#define CRYPTO_SIGN_STATE_RESOURCE "crypto_sign_state" - #ifdef ERL_NIF_DIRTY_JOB_CPU_BOUND #define erl_nif_dirty_job_cpu_bound_macro(a, b, c) \ { a, b, c, ERL_NIF_DIRTY_JOB_CPU_BOUND } From d850b16d1baf5b0a2354e5fee556f3b7c52227a2 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 20 Jan 2020 15:52:38 +0100 Subject: [PATCH 046/162] Fix multi-part signatures Remove the signstate wrapper as it is not needed anyore. --- src/enacl.erl | 8 ++++---- test/enacl_SUITE.erl | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/enacl.erl b/src/enacl.erl index d2ab386..6cb0770 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -649,7 +649,7 @@ sign_verify_detached(SIG, M, PK) -> false -> {error, failed_verification} end. --type sign_state() :: {signstate, reference()}. +-type sign_state() :: reference(). %% @doc sign_init/0 initialize a multi-part signature state. %% @@ -665,7 +665,7 @@ sign_init() -> -spec sign_update(S, M) -> sign_state() | {error, sign_update_error} when S :: sign_state(), M :: iodata(). -sign_update({signstate, SignState}, M) -> +sign_update(SignState, M) -> enacl_nif:crypto_sign_update(SignState, M). @@ -675,7 +675,7 @@ sign_update({signstate, SignState}, M) -> -spec sign_final_create(S, SK) -> {ok, binary()} | {error, atom()} when S :: sign_state(), SK :: iodata(). -sign_final_create({signstate, SignState}, SK) -> +sign_final_create(SignState, SK) -> enacl_nif:crypto_sign_final_create(SignState, SK). %% @doc sign_final_verify/3 verify a chunked signature @@ -687,7 +687,7 @@ sign_final_create({signstate, SignState}, SK) -> when S :: sign_state(), SIG :: binary(), PK :: iodata(). -sign_final_verify({signstate, SignState}, SIG, PK) -> +sign_final_verify(SignState, SIG, PK) -> enacl_nif:crypto_sign_final_verify(SignState, SIG, PK). %% @private diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index eb4d5fa..0cb6f97 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -42,7 +42,8 @@ groups() -> generichash_chunked, aead_xchacha20poly1305, aead_chacha20poly1305, - pwhash]}, + pwhash, + sign]}, [Neg, Pos]. @@ -121,3 +122,20 @@ pwhash(_Config) -> true = enacl:pwhash_str_verify(Str1, PW), false = enacl:pwhash_str_verify(Str1, <>), ok. + +sign(_Config) -> + #{public := PK, secret := SK} = enacl:sign_keypair(), + Msg = <<"Test">>, + State = enacl:sign_init(), + Create = sign_chunked(State, Msg, 10000), + {ok, Signature} = enacl:sign_final_create(Create, SK), + StateVerify = enacl:sign_init(), + Verify = sign_chunked(StateVerify, Msg, 10000), + ok = enacl:sign_final_verify(Verify, Signature, PK), + ok. + +sign_chunked(S, _M, 0) -> S; +sign_chunked(S, M, N) -> + S2 = enacl:sign_update(S, M), + sign_chunked(S2, M, N-1). + From 899fbeefd3ca0e8322fba3f7b22334edb09fd58a Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 21 Jan 2020 13:01:48 +0100 Subject: [PATCH 047/162] Plug memory leaks in kx_ functions If we, for some reason, fail to the error-path, then binaries allocated are not being released properly back to the erlang runtime. Fix this in the usual fashion by using a stack of undo-operations, and thread them via goto. --- c_src/kx.c | 93 +++++++++++++++++++++++++++++++------------- test/enacl_SUITE.erl | 12 +++++- 2 files changed, 78 insertions(+), 27 deletions(-) diff --git a/c_src/kx.c b/c_src/kx.c index 283328b..e4d9a6d 100644 --- a/c_src/kx.c +++ b/c_src/kx.c @@ -48,63 +48,104 @@ ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + ERL_NIF_TERM ret; ErlNifBinary rx, tx, server_pk, server_sk, client_pk; - if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &server_pk)) || - (!enif_inspect_binary(env, argv[1], &server_sk)) || - (!enif_inspect_binary(env, argv[2], &client_pk)) || - (server_pk.size != crypto_kx_PUBLICKEYBYTES) || - (server_sk.size != crypto_kx_SECRETKEYBYTES) || - (client_pk.size != crypto_kx_PUBLICKEYBYTES)) { - return enif_make_badarg(env); - } + if (argc != 3) + goto bad_arg; + if (!enif_inspect_binary(env, argv[0], &server_pk)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &server_sk)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &client_pk)) + goto bad_arg; + + if (server_pk.size != crypto_kx_PUBLICKEYBYTES) + goto bad_arg; + if (server_sk.size != crypto_kx_SECRETKEYBYTES) + goto bad_arg; + if (client_pk.size != crypto_kx_PUBLICKEYBYTES) + goto bad_arg; if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - return nacl_error_tuple(env, "alloc_failed"); + ret = nacl_error_tuple(env, "alloc_failed"); + goto done; } if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - return nacl_error_tuple(env, "alloc_failed"); + ret = nacl_error_tuple(env, "alloc_failed"); + goto release_rx; } if (0 != crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data, server_sk.data, client_pk.data)) { // suspicious client public key - return nacl_error_tuple(env, "invalid_client_public_key"); + ret = nacl_error_tuple(env, "invalid_client_public_key"); + goto release_tx; } - return enif_make_tuple2(env, enif_make_binary(env, &rx), - enif_make_binary(env, &tx)); + ret = enif_make_tuple2(env, enif_make_binary(env, &rx), + enif_make_binary(env, &tx)); + goto done; + +bad_arg: + return enif_make_badarg(env); +release_tx: + enif_release_binary(&tx); +release_rx: + enif_release_binary(&rx); +done: + return ret; } ERL_NIF_TERM enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary rx, tx, client_pk, client_sk, server_pk; + ERL_NIF_TERM ret; - if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &client_pk)) || - (!enif_inspect_binary(env, argv[1], &client_sk)) || - (!enif_inspect_binary(env, argv[2], &server_pk)) || - (client_pk.size != crypto_kx_PUBLICKEYBYTES) || - (client_sk.size != crypto_kx_SECRETKEYBYTES) || - (server_pk.size != crypto_kx_PUBLICKEYBYTES)) { - return enif_make_badarg(env); - } + if (argc != 3) + goto bad_arg; + if (!enif_inspect_binary(env, argv[0], &client_pk)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &client_sk)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &server_pk)) + goto bad_arg; + + if (client_pk.size != crypto_kx_PUBLICKEYBYTES) + goto bad_arg; + if (client_sk.size != crypto_kx_SECRETKEYBYTES) + goto bad_arg; + if (server_pk.size != crypto_kx_PUBLICKEYBYTES) + goto bad_arg; if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - return nacl_error_tuple(env, "alloc_failed"); + ret = nacl_error_tuple(env, "alloc_failed"); + goto done; } if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - return nacl_error_tuple(env, "alloc_failed"); + ret = nacl_error_tuple(env, "alloc_failed"); + goto release_rx; } if (0 != crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data, client_sk.data, server_pk.data)) { // suspicious server public key - return nacl_error_tuple(env, "invalid_server_public_key"); + ret = nacl_error_tuple(env, "invalid_server_public_key"); + goto release_tx; } - return enif_make_tuple2(env, enif_make_binary(env, &rx), - enif_make_binary(env, &tx)); + ret = enif_make_tuple2(env, enif_make_binary(env, &rx), + enif_make_binary(env, &tx)); + goto done; +bad_arg: + return enif_make_badarg(env); +release_tx: + enif_release_binary(&tx); +release_rx: + enif_release_binary(&rx); +done: + return ret; } \ No newline at end of file diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index 0cb6f97..8ff5b5c 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -43,7 +43,8 @@ groups() -> aead_xchacha20poly1305, aead_chacha20poly1305, pwhash, - sign]}, + sign, + kx]}, [Neg, Pos]. @@ -139,3 +140,12 @@ sign_chunked(S, M, N) -> S2 = enacl:sign_update(S, M), sign_chunked(S2, M, N-1). +kx(_Config) -> + #{ public := CPK, secret := CSK} = enacl:kx_keypair(), + #{ public := SPK, secret := SSK} = enacl:kx_keypair(), + #{ client_tx := CTX, client_rx := CRX} = enacl:kx_client_session_keys(CPK, CSK, SPK), + #{ server_tx := STX, server_rx := SRX} = enacl:kx_server_session_keys(SPK, SSK, CPK), + %% Verify we got a shared keypair + CTX = SRX, + STX = CRX, + ok. From fec24995d19f7c550fd4b4da7f40b0eb9662061d Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 21 Jan 2020 13:39:08 +0100 Subject: [PATCH 048/162] Clean up aead construction, plug mem-leak --- c_src/aead.c | 127 +++++++++++++++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 54 deletions(-) diff --git a/c_src/aead.c b/c_src/aead.c index bf97c7b..d4d6c8a 100644 --- a/c_src/aead.c +++ b/c_src/aead.c @@ -36,76 +36,95 @@ enacl_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, ERL_NIF_TERM enacl_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ERL_NIF_TERM result; + ERL_NIF_TERM ret; ErlNifBinary key, nonce, ad, message, ciphertext; - if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &ad)) || - (!enif_inspect_binary(env, argv[3], &message)) || - (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) || - (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)) { - return enif_make_badarg(env); + if (argc != 4) + goto bad_arg; + if (!enif_inspect_binary(env, argv[0], &key)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &nonce)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &ad)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[3], &message)) + goto bad_arg; + if (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) + goto bad_arg; + if (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES) + goto bad_arg; + + if (!enif_alloc_binary(message.size + + crypto_aead_chacha20poly1305_ietf_ABYTES, + &ciphertext)) { + ret = nacl_error_tuple(env, "alloc_failed"); + goto done; } - do { - if (!enif_alloc_binary(message.size + - crypto_aead_chacha20poly1305_ietf_ABYTES, - &ciphertext)) { - result = nacl_error_tuple(env, "alloc_failed"); - continue; - } + if (crypto_aead_chacha20poly1305_ietf_encrypt( + ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, + NULL, nonce.data, key.data) < 0) { + ret = nacl_error_tuple(env, "aead_chacha20poly1305_ietf_encrypt_failed"); + goto release; + } - if (crypto_aead_chacha20poly1305_ietf_encrypt( - ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, - NULL, nonce.data, key.data) < 0) { - result = - nacl_error_tuple(env, "aead_chacha20poly1305_ietf_encrypt_failed"); - continue; - } + ret = enif_make_binary(env, &ciphertext); + goto done; - result = enif_make_binary(env, &ciphertext); - } while (0); - - return result; +bad_arg: + return enif_make_badarg(env); +release: + enif_release_binary(&ciphertext); +done: + return ret; } ERL_NIF_TERM enacl_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - ERL_NIF_TERM result; + ERL_NIF_TERM ret; ErlNifBinary key, nonce, ad, message, ciphertext; - if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &ad)) || - (!enif_inspect_binary(env, argv[3], &ciphertext)) || - (ciphertext.size < crypto_aead_chacha20poly1305_ietf_ABYTES) || - (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) || - (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES)) { - return enif_make_badarg(env); + if (argc != 4) + goto bad_arg; + if (!enif_inspect_binary(env, argv[0], &key)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &nonce)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &ad)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[3], &ciphertext)) + goto bad_arg; + + if (ciphertext.size < crypto_aead_chacha20poly1305_ietf_ABYTES) + goto bad_arg; + if (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) + goto bad_arg; + if (nonce.size != crypto_aead_chacha20poly1305_ietf_NPUBBYTES) + goto bad_arg; + + if (!enif_alloc_binary(ciphertext.size - + crypto_aead_chacha20poly1305_ietf_ABYTES, + &message)) { + ret = nacl_error_tuple(env, "alloc_failed"); + goto done; } - do { - if (!enif_alloc_binary(ciphertext.size - - crypto_aead_chacha20poly1305_ietf_ABYTES, - &message)) { - result = nacl_error_tuple(env, "alloc_failed"); - continue; - } + if (crypto_aead_chacha20poly1305_ietf_decrypt( + message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, + ad.size, nonce.data, key.data) < 0) { + ret = nacl_error_tuple(env, "aead_chacha20poly1305_ietf_decrypt_failed"); + goto release; + } - if (crypto_aead_chacha20poly1305_ietf_decrypt( - message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, - ad.size, nonce.data, key.data) < 0) { - result = - nacl_error_tuple(env, "aead_chacha20poly1305_ietf_decrypt_failed"); - continue; - } - - result = enif_make_binary(env, &message); - } while (0); - - return result; + ret = enif_make_binary(env, &message); + goto done; +bad_arg: + return enif_make_badarg(env); +release: + enif_release_binary(&message); +done: + return ret; } /* From 92b91bd806bed74e46c079e803250e7c570cae71 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 21 Jan 2020 13:40:35 +0100 Subject: [PATCH 049/162] Rename "nacl_error_tuple" -> "enacl_error_tuple" The new name is consistent where the old name was not. --- c_src/aead.c | 16 +++++++-------- c_src/enacl.c | 2 +- c_src/enacl.h | 2 +- c_src/enacl_nif.c | 10 ++++----- c_src/generichash.c | 26 +++++++++++------------ c_src/kx.c | 16 +++++++-------- c_src/public.c | 28 ++++++++++++------------- c_src/pwhash.c | 10 ++++----- c_src/randombytes.c | 2 +- c_src/secret.c | 18 ++++++++-------- c_src/sign.c | 50 ++++++++++++++++++++++----------------------- 11 files changed, 90 insertions(+), 90 deletions(-) diff --git a/c_src/aead.c b/c_src/aead.c index d4d6c8a..fc4f0de 100644 --- a/c_src/aead.c +++ b/c_src/aead.c @@ -57,14 +57,14 @@ enacl_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, if (!enif_alloc_binary(message.size + crypto_aead_chacha20poly1305_ietf_ABYTES, &ciphertext)) { - ret = nacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); goto done; } if (crypto_aead_chacha20poly1305_ietf_encrypt( ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, NULL, nonce.data, key.data) < 0) { - ret = nacl_error_tuple(env, "aead_chacha20poly1305_ietf_encrypt_failed"); + ret = enacl_error_tuple(env, "aead_chacha20poly1305_ietf_encrypt_failed"); goto release; } @@ -106,14 +106,14 @@ enacl_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, if (!enif_alloc_binary(ciphertext.size - crypto_aead_chacha20poly1305_ietf_ABYTES, &message)) { - ret = nacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); goto done; } if (crypto_aead_chacha20poly1305_ietf_decrypt( message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, ad.size, nonce.data, key.data) < 0) { - ret = nacl_error_tuple(env, "aead_chacha20poly1305_ietf_decrypt_failed"); + ret = enacl_error_tuple(env, "aead_chacha20poly1305_ietf_decrypt_failed"); goto release; } @@ -172,13 +172,13 @@ enacl_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, if (!enif_alloc_binary(message.size + crypto_aead_xchacha20poly1305_ietf_ABYTES, &ciphertext)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (crypto_aead_xchacha20poly1305_ietf_encrypt( ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, NULL, nonce.data, key.data) < 0) { - return nacl_error_tuple(env, "aead_xchacha20poly1305_ietf_encrypt_failed"); + return enacl_error_tuple(env, "aead_xchacha20poly1305_ietf_encrypt_failed"); } return enif_make_binary(env, &ciphertext); @@ -202,13 +202,13 @@ enacl_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, if (!enif_alloc_binary(ciphertext.size - crypto_aead_xchacha20poly1305_ietf_ABYTES, &message)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (crypto_aead_xchacha20poly1305_ietf_decrypt( message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, ad.size, nonce.data, key.data) < 0) { - return nacl_error_tuple(env, "aead_xchacha20poly1305_ietf_decrypt_failed"); + return enacl_error_tuple(env, "aead_xchacha20poly1305_ietf_decrypt_failed"); } return enif_make_binary(env, &message); diff --git a/c_src/enacl.c b/c_src/enacl.c index 8d3007b..b505331 100644 --- a/c_src/enacl.c +++ b/c_src/enacl.c @@ -2,7 +2,7 @@ #include "enacl.h" -ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) { +ERL_NIF_TERM enacl_error_tuplee(ErlNifEnv *env, char *error_atom) { return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, error_atom)); } diff --git a/c_src/enacl.h b/c_src/enacl.h index 3d9008a..a343aba 100644 --- a/c_src/enacl.h +++ b/c_src/enacl.h @@ -8,6 +8,6 @@ #define ATOM_TRUE "true" #define ATOM_FALSE "false" -ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *, char *); +ERL_NIF_TERM enacl_error_tuplee(ErlNifEnv *, char *); #endif diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 52bbc7d..afa56da 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -121,12 +121,12 @@ enacl_crypto_curve25519_scalarmult(ErlNifEnv *env, int argc, do { if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) { - result = nacl_error_tuple(env, "alloc_failed"); + result = enacl_error_tuple(env, "alloc_failed"); continue; } if (crypto_scalarmult_curve25519(output.data, secret.data, bp) < 0) { - result = nacl_error_tuple(env, "scalarmult_curve25519_failed"); + result = enacl_error_tuple(env, "scalarmult_curve25519_failed"); continue; } @@ -151,12 +151,12 @@ enacl_crypto_curve25519_scalarmult_base(ErlNifEnv *env, int argc, do { if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) { - result = nacl_error_tuple(env, "alloc_failed"); + result = enacl_error_tuple(env, "alloc_failed"); continue; } if (crypto_scalarmult_curve25519_base(output.data, secret.data) < 0) { - result = nacl_error_tuple(env, "scalarmult_curve25519_base_failed"); + result = enacl_error_tuple(env, "scalarmult_curve25519_base_failed"); continue; } @@ -238,7 +238,7 @@ static ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(in.size, &out)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_block(out.data, in.data, key.data); diff --git a/c_src/generichash.c b/c_src/generichash.c index f74bbb2..2c0a77b 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -93,7 +93,7 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX if ((hash_size <= crypto_generichash_BYTES_MIN) || (hash_size >= crypto_generichash_BYTES_MAX)) { - ret = nacl_error_tuple(env, "invalid_hash_size"); + ret = enacl_error_tuplee(env, "invalid_hash_size"); goto done; } @@ -103,20 +103,20 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, k = NULL; } else if (key.size <= crypto_generichash_KEYBYTES_MIN || key.size >= crypto_generichash_KEYBYTES_MAX) { - ret = nacl_error_tuple(env, "invalid_key_size"); + ret = enacl_error_tuplee(env, "invalid_key_size"); goto done; } // allocate memory for hash if (!enif_alloc_binary(hash_size, &hash)) { - ret = nacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuplee(env, "alloc_failed"); goto done; } // calculate hash if (0 != crypto_generichash(hash.data, hash.size, message.data, message.size, k, key.size)) { - ret = nacl_error_tuple(env, "hash_error"); + ret = enacl_error_tuplee(env, "hash_error"); goto release; } @@ -152,7 +152,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, // Verify that hash size is valid if ((hash_size <= crypto_generichash_BYTES_MIN) || (hash_size >= crypto_generichash_BYTES_MAX)) { - ret = nacl_error_tuple(env, "invalid_hash_size"); + ret = enacl_error_tuplee(env, "invalid_hash_size"); goto done; } @@ -162,7 +162,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, k = NULL; } else if (key.size <= crypto_generichash_KEYBYTES_MIN || key.size >= crypto_generichash_KEYBYTES_MAX) { - ret = nacl_error_tuple(env, "invalid_key_size"); + ret = enacl_error_tuplee(env, "invalid_key_size"); goto done; } @@ -189,7 +189,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, // Call the library function if (0 != crypto_generichash_init(obj->ctx, k, key.size, obj->outlen)) { - ret = nacl_error_tuple(env, "hash_init_error"); + ret = enacl_error_tuplee(env, "hash_init_error"); goto err; } @@ -199,7 +199,7 @@ bad_arg: return enif_make_badarg(env); err: - ret = nacl_error_tuple(env, "internal_error"); + ret = enacl_error_tuplee(env, "internal_error"); if (obj != NULL) { if (obj->alive) { sodium_free(obj->ctx); @@ -231,13 +231,13 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, goto bad_arg; if (!obj->alive) { - ret = nacl_error_tuple(env, "finalized"); + ret = enacl_error_tuplee(env, "finalized"); goto done; } // Update hash state if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) { - ret = nacl_error_tuple(env, "hash_update_error"); + ret = enacl_error_tuplee(env, "hash_update_error"); goto done; } @@ -263,17 +263,17 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, goto bad_arg; if (!obj->alive) { - ret = nacl_error_tuple(env, "finalized"); + ret = enacl_error_tuplee(env, "finalized"); goto done; } if (!enif_alloc_binary(obj->outlen, &hash)) { - ret = nacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuplee(env, "alloc_failed"); goto done; } if (0 != crypto_generichash_final(obj->ctx, hash.data, hash.size)) { - ret = nacl_error_tuple(env, "hash_error"); + ret = enacl_error_tuplee(env, "hash_error"); goto release; } diff --git a/c_src/kx.c b/c_src/kx.c index e4d9a6d..a344321 100644 --- a/c_src/kx.c +++ b/c_src/kx.c @@ -31,12 +31,12 @@ ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_kx_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (!enif_alloc_binary(crypto_kx_SECRETKEYBYTES, &sk)) { enif_release_binary(&pk); - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_kx_keypair(pk.data, sk.data); @@ -68,19 +68,19 @@ enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, goto bad_arg; if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - ret = nacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); goto done; } if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - ret = nacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); goto release_rx; } if (0 != crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data, server_sk.data, client_pk.data)) { // suspicious client public key - ret = nacl_error_tuple(env, "invalid_client_public_key"); + ret = enacl_error_tuple(env, "invalid_client_public_key"); goto release_tx; } @@ -121,19 +121,19 @@ enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, goto bad_arg; if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - ret = nacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); goto done; } if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - ret = nacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); goto release_rx; } if (0 != crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data, client_sk.data, server_pk.data)) { // suspicious server public key - ret = nacl_error_tuple(env, "invalid_server_public_key"); + ret = enacl_error_tuple(env, "invalid_server_public_key"); goto release_tx; } diff --git a/c_src/public.c b/c_src/public.c index ef83f7e..62f6a03 100644 --- a/c_src/public.c +++ b/c_src/public.c @@ -45,11 +45,11 @@ ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_box_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (!enif_alloc_binary(crypto_box_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } crypto_box_keypair(pk.data, sk.data); @@ -78,12 +78,12 @@ ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(padded_msg.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data, pk.data, sk.data)) { - return nacl_error_tuple(env, "box_error"); + return enacl_error_tuplee(env, "box_error"); } return enif_make_sub_binary(env, enif_make_binary(env, &result), @@ -111,14 +111,14 @@ ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(padded_ciphertext.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (0 != crypto_box_open(result.data, padded_ciphertext.data, padded_ciphertext.size, nonce.data, pk.data, sk.data)) { enif_release_binary(&result); - return nacl_error_tuple(env, "failed_verification"); + return enacl_error_tuplee(env, "failed_verification"); } return enif_make_sub_binary(env, enif_make_binary(env, &result), @@ -140,12 +140,12 @@ ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_box_BEFORENMBYTES, &k)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (0 != crypto_box_beforenm(k.data, pk.data, sk.data)) { // error - return nacl_error_tuple(env, "error_gen_shared_secret"); + return enacl_error_tuplee(env, "error_gen_shared_secret"); } return enif_make_binary(env, &k); @@ -165,7 +165,7 @@ ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data); @@ -189,13 +189,13 @@ ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (0 != crypto_box_open_afternm(result.data, m.data, m.size, nonce.data, k.data)) { enif_release_binary(&result); - return nacl_error_tuple(env, "failed_verification"); + return enacl_error_tuplee(env, "failed_verification"); } return enif_make_sub_binary(env, enif_make_binary(env, &result), @@ -220,7 +220,7 @@ ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(msg.size + crypto_box_SEALBYTES, &ciphertext)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } crypto_box_seal(ciphertext.data, msg.data, msg.size, key.data); @@ -244,13 +244,13 @@ ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(ciphertext.size - crypto_box_SEALBYTES, &msg)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (crypto_box_seal_open(msg.data, ciphertext.data, ciphertext.size, pk.data, sk.data) != 0) { enif_release_binary(&msg); - return nacl_error_tuple(env, "failed_verification"); + return enacl_error_tuplee(env, "failed_verification"); } return enif_make_binary(env, &msg); diff --git a/c_src/pwhash.c b/c_src/pwhash.c index 3ee5bd5..5f33dda 100644 --- a/c_src/pwhash.c +++ b/c_src/pwhash.c @@ -78,19 +78,19 @@ ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, // Check Salt size if (s.size != crypto_pwhash_SALTBYTES) { - return nacl_error_tuple(env, "invalid_salt_size"); + return enacl_error_tuplee(env, "invalid_salt_size"); } // Allocate memory for return binary if (!enif_alloc_binary(crypto_box_SEEDBYTES, &h)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (crypto_pwhash(h.data, h.size, (char *)p.data, p.size, s.data, o, m, crypto_pwhash_ALG_DEFAULT) != 0) { /* out of memory */ enif_release_binary(&h); - return nacl_error_tuple(env, "out_of_memory"); + return enacl_error_tuplee(env, "out_of_memory"); } ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); @@ -119,13 +119,13 @@ ERL_NIF_TERM enacl_crypto_pwhash_str(ErlNifEnv *env, int argc, // Allocate memory for return binary if (!enif_alloc_binary(crypto_pwhash_STRBYTES, &h)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (crypto_pwhash_str((char *)h.data, (char *)p.data, p.size, o, m) != 0) { /* out of memory */ enif_release_binary(&h); - return nacl_error_tuple(env, "out_of_memory"); + return enacl_error_tuplee(env, "out_of_memory"); } ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); diff --git a/c_src/randombytes.c b/c_src/randombytes.c index bea290f..015781e 100644 --- a/c_src/randombytes.c +++ b/c_src/randombytes.c @@ -15,7 +15,7 @@ ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(req_size, &result)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } randombytes(result.data, result.size); diff --git a/c_src/secret.c b/c_src/secret.c index dc72a92..95b1b04 100644 --- a/c_src/secret.c +++ b/c_src/secret.c @@ -91,7 +91,7 @@ ERL_NIF_TERM enacl_crypto_secretbox(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(padded_msg.size, &padded_ciphertext)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_secretbox(padded_ciphertext.data, padded_msg.data, padded_msg.size, @@ -120,14 +120,14 @@ ERL_NIF_TERM enacl_crypto_secretbox_open(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(padded_ciphertext.size, &padded_msg)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (crypto_secretbox_open(padded_msg.data, padded_ciphertext.data, padded_ciphertext.size, nonce.data, key.data) != 0) { enif_release_binary(&padded_msg); - return nacl_error_tuple(env, "failed_verification"); + return enacl_error_tuple(env, "failed_verification"); } return enif_make_sub_binary( @@ -152,7 +152,7 @@ ERL_NIF_TERM enacl_crypto_stream_chacha20(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(clen, &c)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_stream_chacha20(c.data, c.size, n.data, k.data); @@ -177,7 +177,7 @@ enacl_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size, &c)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_stream_chacha20_xor(c.data, m.data, m.size, n.data, k.data); @@ -202,7 +202,7 @@ ERL_NIF_TERM enacl_crypto_stream(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(clen, &c)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_stream(c.data, c.size, n.data, k.data); @@ -226,7 +226,7 @@ ERL_NIF_TERM enacl_crypto_stream_xor(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size, &c)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_stream_xor(c.data, m.data, m.size, n.data, k.data); @@ -248,7 +248,7 @@ ERL_NIF_TERM enacl_crypto_auth(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_auth_BYTES, &a)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_auth(a.data, m.data, m.size, k.data); @@ -291,7 +291,7 @@ ERL_NIF_TERM enacl_crypto_onetimeauth(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_onetimeauth_BYTES, &a)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_onetimeauth(a.data, m.data, m.size, k.data); diff --git a/c_src/sign.c b/c_src/sign.c index ecba65a..0dc7d30 100644 --- a/c_src/sign.c +++ b/c_src/sign.c @@ -52,19 +52,19 @@ ERL_NIF_TERM enacl_crypto_sign_init(ErlNifEnv *env, int argc, if ((obj = enif_alloc_resource(enacl_sign_ctx_rtype, sizeof(enacl_sign_ctx))) == NULL) { - ret = nacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuplee(env, "alloc_failed"); goto done; } obj->alive = 0; obj->state = enif_alloc(crypto_sign_statebytes()); if (obj->state == NULL) { - ret = nacl_error_tuple(env, "state_malloc"); + ret = enacl_error_tuplee(env, "state_malloc"); goto release; } obj->alive = 1; if (0 != crypto_sign_init(obj->state)) { - ret = nacl_error_tuple(env, "sign_init_error"); + ret = enacl_error_tuplee(env, "sign_init_error"); goto free; } @@ -111,12 +111,12 @@ ERL_NIF_TERM enacl_crypto_sign_update(ErlNifEnv *env, int argc, goto bad_arg; if (!obj->alive) { - ret = nacl_error_tuple(env, "finalized"); + ret = enacl_error_tuplee(env, "finalized"); goto done; } if (0 != crypto_sign_update(obj->state, data.data, data.size)) { - ret = nacl_error_tuple(env, "sign_update_error"); + ret = enacl_error_tuplee(env, "sign_update_error"); goto done; } @@ -146,17 +146,17 @@ ERL_NIF_TERM enacl_crypto_sign_final_create(ErlNifEnv *env, int argc, goto bad_arg; if (!obj->alive) { - ret = nacl_error_tuple(env, "finalized"); + ret = enacl_error_tuplee(env, "finalized"); goto done; } if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { - ret = nacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuplee(env, "alloc_failed"); goto done; } if (0 != crypto_sign_final_create(obj->state, sig.data, &siglen, sk.data)) { - ret = nacl_error_tuple(env, "sign_error"); + ret = enacl_error_tuplee(env, "sign_error"); goto release; } @@ -198,7 +198,7 @@ ERL_NIF_TERM enacl_crypto_sign_final_verify(ErlNifEnv *env, int argc, if (0 == crypto_sign_final_verify(obj->state, sig.data, pk.data)) { ret = enif_make_atom(env, ATOM_OK); } else { - ret = nacl_error_tuple(env, "failed_verification"); + ret = enacl_error_tuplee(env, "failed_verification"); } // Mark as done goto cleanup; @@ -226,11 +226,11 @@ enacl_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (!enif_alloc_binary(crypto_sign_ed25519_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } crypto_sign_ed25519_keypair(pk.data, sk.data); @@ -250,11 +250,11 @@ enacl_crypto_sign_ed25519_sk_to_pk(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (crypto_sign_ed25519_sk_to_pk(pk.data, sk.data) != 0) { - return nacl_error_tuple(env, "crypto_sign_ed25519_sk_to_pk_failed"); + return enacl_error_tuplee(env, "crypto_sign_ed25519_sk_to_pk_failed"); } return enif_make_binary(env, &pk); @@ -271,12 +271,12 @@ enacl_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_pk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (crypto_sign_ed25519_pk_to_curve25519(curve25519_pk.data, ed25519_pk.data) != 0) { - return nacl_error_tuple(env, "ed25519_public_to_curve25519_failed"); + return enacl_error_tuplee(env, "ed25519_public_to_curve25519_failed"); } return enif_make_binary(env, &curve25519_pk); @@ -293,12 +293,12 @@ enacl_crypto_sign_ed25519_secret_to_curve25519(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_sk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (crypto_sign_ed25519_sk_to_curve25519(curve25519_sk.data, ed25519_sk.data) != 0) { - return nacl_error_tuple(env, "ed25519_secret_to_curve25519_failed"); + return enacl_error_tuplee(env, "ed25519_secret_to_curve25519_failed"); } return enif_make_binary(env, &curve25519_sk); @@ -340,11 +340,11 @@ ERL_NIF_TERM enacl_crypto_sign_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } crypto_sign_keypair(pk.data, sk.data); @@ -362,11 +362,11 @@ ERL_NIF_TERM enacl_crypto_sign_seed_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } crypto_sign_seed_keypair(pk.data, sk.data, seed.data); @@ -395,7 +395,7 @@ ERL_NIF_TERM enacl_crypto_sign(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size + crypto_sign_BYTES, &sm)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } crypto_sign(sm.data, &smlen, m.data, m.size, sk.data); @@ -423,14 +423,14 @@ ERL_NIF_TERM enacl_crypto_sign_open(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(sm.size, &m)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } if (0 == crypto_sign_open(m.data, &mlen, sm.data, sm.size, pk.data)) { return enif_make_sub_binary(env, enif_make_binary(env, &m), 0, mlen); } else { enif_release_binary(&m); - return nacl_error_tuple(env, "failed_verification"); + return enacl_error_tuplee(env, "failed_verification"); } } @@ -454,7 +454,7 @@ ERL_NIF_TERM enacl_crypto_sign_detached(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuplee(env, "alloc_failed"); } crypto_sign_detached(sig.data, &siglen, m.data, m.size, sk.data); From ab40d5bbf8d971c09f2e7eec4273426f44f3779f Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 21 Jan 2020 13:56:17 +0100 Subject: [PATCH 050/162] Rename fixups --- c_src/enacl.c | 2 +- c_src/enacl.h | 2 +- c_src/generichash.c | 26 +++++++++++------------ c_src/hash.c | 4 ++-- c_src/public.c | 28 ++++++++++++------------- c_src/pwhash.c | 10 ++++----- c_src/randombytes.c | 2 +- c_src/sign.c | 50 ++++++++++++++++++++++----------------------- 8 files changed, 62 insertions(+), 62 deletions(-) diff --git a/c_src/enacl.c b/c_src/enacl.c index b505331..3b39796 100644 --- a/c_src/enacl.c +++ b/c_src/enacl.c @@ -2,7 +2,7 @@ #include "enacl.h" -ERL_NIF_TERM enacl_error_tuplee(ErlNifEnv *env, char *error_atom) { +ERL_NIF_TERM enacl_error_tuple(ErlNifEnv *env, char *error_atom) { return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, error_atom)); } diff --git a/c_src/enacl.h b/c_src/enacl.h index a343aba..e772d1d 100644 --- a/c_src/enacl.h +++ b/c_src/enacl.h @@ -8,6 +8,6 @@ #define ATOM_TRUE "true" #define ATOM_FALSE "false" -ERL_NIF_TERM enacl_error_tuplee(ErlNifEnv *, char *); +ERL_NIF_TERM enacl_error_tuple(ErlNifEnv *, char *); #endif diff --git a/c_src/generichash.c b/c_src/generichash.c index 2c0a77b..eb72791 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -93,7 +93,7 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX if ((hash_size <= crypto_generichash_BYTES_MIN) || (hash_size >= crypto_generichash_BYTES_MAX)) { - ret = enacl_error_tuplee(env, "invalid_hash_size"); + ret = enacl_error_tuple(env, "invalid_hash_size"); goto done; } @@ -103,20 +103,20 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, k = NULL; } else if (key.size <= crypto_generichash_KEYBYTES_MIN || key.size >= crypto_generichash_KEYBYTES_MAX) { - ret = enacl_error_tuplee(env, "invalid_key_size"); + ret = enacl_error_tuple(env, "invalid_key_size"); goto done; } // allocate memory for hash if (!enif_alloc_binary(hash_size, &hash)) { - ret = enacl_error_tuplee(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); goto done; } // calculate hash if (0 != crypto_generichash(hash.data, hash.size, message.data, message.size, k, key.size)) { - ret = enacl_error_tuplee(env, "hash_error"); + ret = enacl_error_tuple(env, "hash_error"); goto release; } @@ -152,7 +152,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, // Verify that hash size is valid if ((hash_size <= crypto_generichash_BYTES_MIN) || (hash_size >= crypto_generichash_BYTES_MAX)) { - ret = enacl_error_tuplee(env, "invalid_hash_size"); + ret = enacl_error_tuple(env, "invalid_hash_size"); goto done; } @@ -162,7 +162,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, k = NULL; } else if (key.size <= crypto_generichash_KEYBYTES_MIN || key.size >= crypto_generichash_KEYBYTES_MAX) { - ret = enacl_error_tuplee(env, "invalid_key_size"); + ret = enacl_error_tuple(env, "invalid_key_size"); goto done; } @@ -189,7 +189,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, // Call the library function if (0 != crypto_generichash_init(obj->ctx, k, key.size, obj->outlen)) { - ret = enacl_error_tuplee(env, "hash_init_error"); + ret = enacl_error_tuple(env, "hash_init_error"); goto err; } @@ -199,7 +199,7 @@ bad_arg: return enif_make_badarg(env); err: - ret = enacl_error_tuplee(env, "internal_error"); + ret = enacl_error_tuple(env, "internal_error"); if (obj != NULL) { if (obj->alive) { sodium_free(obj->ctx); @@ -231,13 +231,13 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, goto bad_arg; if (!obj->alive) { - ret = enacl_error_tuplee(env, "finalized"); + ret = enacl_error_tuple(env, "finalized"); goto done; } // Update hash state if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) { - ret = enacl_error_tuplee(env, "hash_update_error"); + ret = enacl_error_tuple(env, "hash_update_error"); goto done; } @@ -263,17 +263,17 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, goto bad_arg; if (!obj->alive) { - ret = enacl_error_tuplee(env, "finalized"); + ret = enacl_error_tuple(env, "finalized"); goto done; } if (!enif_alloc_binary(obj->outlen, &hash)) { - ret = enacl_error_tuplee(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); goto done; } if (0 != crypto_generichash_final(obj->ctx, hash.data, hash.size)) { - ret = enacl_error_tuplee(env, "hash_error"); + ret = enacl_error_tuple(env, "hash_error"); goto release; } diff --git a/c_src/hash.c b/c_src/hash.c index 6475596..5820a24 100644 --- a/c_src/hash.c +++ b/c_src/hash.c @@ -28,7 +28,7 @@ ERL_NIF_TERM enacl_crypto_shorthash(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_shorthash_BYTES, &a)) { - return nacl_error_tuple(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_shorthash(a.data, m.data, m.size, k.data); @@ -56,7 +56,7 @@ bad_arg: return enif_make_badarg(env); err: - ret = nacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); done: return ret; } diff --git a/c_src/public.c b/c_src/public.c index 62f6a03..05ae0c7 100644 --- a/c_src/public.c +++ b/c_src/public.c @@ -45,11 +45,11 @@ ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_box_PUBLICKEYBYTES, &pk)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (!enif_alloc_binary(crypto_box_SECRETKEYBYTES, &sk)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_box_keypair(pk.data, sk.data); @@ -78,12 +78,12 @@ ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(padded_msg.size, &result)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data, pk.data, sk.data)) { - return enacl_error_tuplee(env, "box_error"); + return enacl_error_tuple(env, "box_error"); } return enif_make_sub_binary(env, enif_make_binary(env, &result), @@ -111,14 +111,14 @@ ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(padded_ciphertext.size, &result)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (0 != crypto_box_open(result.data, padded_ciphertext.data, padded_ciphertext.size, nonce.data, pk.data, sk.data)) { enif_release_binary(&result); - return enacl_error_tuplee(env, "failed_verification"); + return enacl_error_tuple(env, "failed_verification"); } return enif_make_sub_binary(env, enif_make_binary(env, &result), @@ -140,12 +140,12 @@ ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_box_BEFORENMBYTES, &k)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (0 != crypto_box_beforenm(k.data, pk.data, sk.data)) { // error - return enacl_error_tuplee(env, "error_gen_shared_secret"); + return enacl_error_tuple(env, "error_gen_shared_secret"); } return enif_make_binary(env, &k); @@ -165,7 +165,7 @@ ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size, &result)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data); @@ -189,13 +189,13 @@ ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size, &result)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (0 != crypto_box_open_afternm(result.data, m.data, m.size, nonce.data, k.data)) { enif_release_binary(&result); - return enacl_error_tuplee(env, "failed_verification"); + return enacl_error_tuple(env, "failed_verification"); } return enif_make_sub_binary(env, enif_make_binary(env, &result), @@ -220,7 +220,7 @@ ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(msg.size + crypto_box_SEALBYTES, &ciphertext)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_box_seal(ciphertext.data, msg.data, msg.size, key.data); @@ -244,13 +244,13 @@ ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(ciphertext.size - crypto_box_SEALBYTES, &msg)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (crypto_box_seal_open(msg.data, ciphertext.data, ciphertext.size, pk.data, sk.data) != 0) { enif_release_binary(&msg); - return enacl_error_tuplee(env, "failed_verification"); + return enacl_error_tuple(env, "failed_verification"); } return enif_make_binary(env, &msg); diff --git a/c_src/pwhash.c b/c_src/pwhash.c index 5f33dda..be5df5d 100644 --- a/c_src/pwhash.c +++ b/c_src/pwhash.c @@ -78,19 +78,19 @@ ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, // Check Salt size if (s.size != crypto_pwhash_SALTBYTES) { - return enacl_error_tuplee(env, "invalid_salt_size"); + return enacl_error_tuple(env, "invalid_salt_size"); } // Allocate memory for return binary if (!enif_alloc_binary(crypto_box_SEEDBYTES, &h)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (crypto_pwhash(h.data, h.size, (char *)p.data, p.size, s.data, o, m, crypto_pwhash_ALG_DEFAULT) != 0) { /* out of memory */ enif_release_binary(&h); - return enacl_error_tuplee(env, "out_of_memory"); + return enacl_error_tuple(env, "out_of_memory"); } ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); @@ -119,13 +119,13 @@ ERL_NIF_TERM enacl_crypto_pwhash_str(ErlNifEnv *env, int argc, // Allocate memory for return binary if (!enif_alloc_binary(crypto_pwhash_STRBYTES, &h)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (crypto_pwhash_str((char *)h.data, (char *)p.data, p.size, o, m) != 0) { /* out of memory */ enif_release_binary(&h); - return enacl_error_tuplee(env, "out_of_memory"); + return enacl_error_tuple(env, "out_of_memory"); } ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); diff --git a/c_src/randombytes.c b/c_src/randombytes.c index 015781e..5c978a8 100644 --- a/c_src/randombytes.c +++ b/c_src/randombytes.c @@ -15,7 +15,7 @@ ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(req_size, &result)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } randombytes(result.data, result.size); diff --git a/c_src/sign.c b/c_src/sign.c index 0dc7d30..56e1b48 100644 --- a/c_src/sign.c +++ b/c_src/sign.c @@ -52,19 +52,19 @@ ERL_NIF_TERM enacl_crypto_sign_init(ErlNifEnv *env, int argc, if ((obj = enif_alloc_resource(enacl_sign_ctx_rtype, sizeof(enacl_sign_ctx))) == NULL) { - ret = enacl_error_tuplee(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); goto done; } obj->alive = 0; obj->state = enif_alloc(crypto_sign_statebytes()); if (obj->state == NULL) { - ret = enacl_error_tuplee(env, "state_malloc"); + ret = enacl_error_tuple(env, "state_malloc"); goto release; } obj->alive = 1; if (0 != crypto_sign_init(obj->state)) { - ret = enacl_error_tuplee(env, "sign_init_error"); + ret = enacl_error_tuple(env, "sign_init_error"); goto free; } @@ -111,12 +111,12 @@ ERL_NIF_TERM enacl_crypto_sign_update(ErlNifEnv *env, int argc, goto bad_arg; if (!obj->alive) { - ret = enacl_error_tuplee(env, "finalized"); + ret = enacl_error_tuple(env, "finalized"); goto done; } if (0 != crypto_sign_update(obj->state, data.data, data.size)) { - ret = enacl_error_tuplee(env, "sign_update_error"); + ret = enacl_error_tuple(env, "sign_update_error"); goto done; } @@ -146,17 +146,17 @@ ERL_NIF_TERM enacl_crypto_sign_final_create(ErlNifEnv *env, int argc, goto bad_arg; if (!obj->alive) { - ret = enacl_error_tuplee(env, "finalized"); + ret = enacl_error_tuple(env, "finalized"); goto done; } if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { - ret = enacl_error_tuplee(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); goto done; } if (0 != crypto_sign_final_create(obj->state, sig.data, &siglen, sk.data)) { - ret = enacl_error_tuplee(env, "sign_error"); + ret = enacl_error_tuple(env, "sign_error"); goto release; } @@ -198,7 +198,7 @@ ERL_NIF_TERM enacl_crypto_sign_final_verify(ErlNifEnv *env, int argc, if (0 == crypto_sign_final_verify(obj->state, sig.data, pk.data)) { ret = enif_make_atom(env, ATOM_OK); } else { - ret = enacl_error_tuplee(env, "failed_verification"); + ret = enacl_error_tuple(env, "failed_verification"); } // Mark as done goto cleanup; @@ -226,11 +226,11 @@ enacl_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (!enif_alloc_binary(crypto_sign_ed25519_SECRETKEYBYTES, &sk)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_sign_ed25519_keypair(pk.data, sk.data); @@ -250,11 +250,11 @@ enacl_crypto_sign_ed25519_sk_to_pk(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (crypto_sign_ed25519_sk_to_pk(pk.data, sk.data) != 0) { - return enacl_error_tuplee(env, "crypto_sign_ed25519_sk_to_pk_failed"); + return enacl_error_tuple(env, "crypto_sign_ed25519_sk_to_pk_failed"); } return enif_make_binary(env, &pk); @@ -271,12 +271,12 @@ enacl_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_pk)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (crypto_sign_ed25519_pk_to_curve25519(curve25519_pk.data, ed25519_pk.data) != 0) { - return enacl_error_tuplee(env, "ed25519_public_to_curve25519_failed"); + return enacl_error_tuple(env, "ed25519_public_to_curve25519_failed"); } return enif_make_binary(env, &curve25519_pk); @@ -293,12 +293,12 @@ enacl_crypto_sign_ed25519_secret_to_curve25519(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_sk)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (crypto_sign_ed25519_sk_to_curve25519(curve25519_sk.data, ed25519_sk.data) != 0) { - return enacl_error_tuplee(env, "ed25519_secret_to_curve25519_failed"); + return enacl_error_tuple(env, "ed25519_secret_to_curve25519_failed"); } return enif_make_binary(env, &curve25519_sk); @@ -340,11 +340,11 @@ ERL_NIF_TERM enacl_crypto_sign_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_sign_keypair(pk.data, sk.data); @@ -362,11 +362,11 @@ ERL_NIF_TERM enacl_crypto_sign_seed_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_sign_seed_keypair(pk.data, sk.data, seed.data); @@ -395,7 +395,7 @@ ERL_NIF_TERM enacl_crypto_sign(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size + crypto_sign_BYTES, &sm)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_sign(sm.data, &smlen, m.data, m.size, sk.data); @@ -423,14 +423,14 @@ ERL_NIF_TERM enacl_crypto_sign_open(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(sm.size, &m)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } if (0 == crypto_sign_open(m.data, &mlen, sm.data, sm.size, pk.data)) { return enif_make_sub_binary(env, enif_make_binary(env, &m), 0, mlen); } else { enif_release_binary(&m); - return enacl_error_tuplee(env, "failed_verification"); + return enacl_error_tuple(env, "failed_verification"); } } @@ -454,7 +454,7 @@ ERL_NIF_TERM enacl_crypto_sign_detached(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { - return enacl_error_tuplee(env, "alloc_failed"); + return enacl_error_tuple(env, "alloc_failed"); } crypto_sign_detached(sig.data, &siglen, m.data, m.size, sk.data); From bdb4719f6dfb41a6e298f8a91f9d5b1fc56bfa17 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 21 Jan 2020 13:57:39 +0100 Subject: [PATCH 051/162] Fix AEAD parameter order / naming. The order of parameters were in the wrong order. Make them equal to the official order of libsodium. While here, rename NONCEBYTES to NPUBBYTES so it reflects the underlying names as well. --- c_src/aead.c | 16 ++++++++-------- src/enacl.erl | 26 ++++++++++++-------------- src/enacl_nif.erl | 8 ++++---- test/enacl_SUITE.erl | 7 ++++--- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/c_src/aead.c b/c_src/aead.c index fc4f0de..4339c99 100644 --- a/c_src/aead.c +++ b/c_src/aead.c @@ -41,13 +41,13 @@ enacl_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, if (argc != 4) goto bad_arg; - if (!enif_inspect_binary(env, argv[0], &key)) + if (!enif_inspect_binary(env, argv[0], &message)) goto bad_arg; - if (!enif_inspect_binary(env, argv[1], &nonce)) + if (!enif_inspect_binary(env, argv[1], &ad)) goto bad_arg; - if (!enif_inspect_binary(env, argv[2], &ad)) + if (!enif_inspect_binary(env, argv[2], &nonce)) goto bad_arg; - if (!enif_inspect_binary(env, argv[3], &message)) + if (!enif_inspect_binary(env, argv[3], &key)) goto bad_arg; if (key.size != crypto_aead_chacha20poly1305_ietf_KEYBYTES) goto bad_arg; @@ -87,13 +87,13 @@ enacl_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, if (argc != 4) goto bad_arg; - if (!enif_inspect_binary(env, argv[0], &key)) + if (!enif_inspect_binary(env, argv[0], &ciphertext)) goto bad_arg; - if (!enif_inspect_binary(env, argv[1], &nonce)) + if (!enif_inspect_binary(env, argv[1], &ad)) goto bad_arg; - if (!enif_inspect_binary(env, argv[2], &ad)) + if (!enif_inspect_binary(env, argv[2], &nonce)) goto bad_arg; - if (!enif_inspect_binary(env, argv[3], &ciphertext)) + if (!enif_inspect_binary(env, argv[3], &message)) goto bad_arg; if (ciphertext.size < crypto_aead_chacha20poly1305_ietf_ABYTES) diff --git a/src/enacl.erl b/src/enacl.erl index 6cb0770..2a3d032 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -69,7 +69,7 @@ aead_chacha20poly1305_encrypt/4, aead_chacha20poly1305_decrypt/4, aead_chacha20poly1305_KEYBYTES/0, - aead_chacha20poly1305_NONCEBYTES/0, + aead_chacha20poly1305_NPUBBYTES/0, aead_chacha20poly1305_ABYTES/0, aead_chacha20poly1305_MESSAGEBYTES_MAX/0, @@ -1169,28 +1169,26 @@ kx_secret_key_size() -> %% `AD' using `Key' and `Nonce'. Returns the encrypted message followed by %% `aead_chacha20poly1305_ABYTES/0' bytes of MAC. %% @end --spec aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg) -> binary() | {error, term()} +-spec aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key) -> binary() | {error, term()} when Key :: binary(), - Nonce :: pos_integer(), + Nonce :: binary(), AD :: binary(), Msg :: binary(). -aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg) -> - NonceBin = <<0:32, Nonce:64/little-unsigned-integer>>, - enacl_nif:crypto_aead_chacha20poly1305_encrypt(Key, NonceBin, AD, Msg). +aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key) -> + enacl_nif:crypto_aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key). %% @doc aead_chacha20poly1305_decrypt/4 decrypts ciphertext `CT' with additional %% data `AD' using `Key' and `Nonce'. Note: `CipherText' should contain %% `aead_chacha20poly1305_ABYTES/0' bytes that is the MAC. Returns the decrypted %% message. %% @end --spec aead_chacha20poly1305_decrypt(Key, Nonce, AD, CT) -> binary() | {error, term()} +-spec aead_chacha20poly1305_decrypt(CT, AD, Nonce, Key) -> binary() | {error, term()} when Key :: binary(), - Nonce :: pos_integer(), + Nonce :: binary(), AD :: binary(), CT :: binary(). -aead_chacha20poly1305_decrypt(Key, Nonce, AD, CT) -> - NonceBin = <<0:32, Nonce:64/little-unsigned-integer>>, - enacl_nif:crypto_aead_chacha20poly1305_decrypt(Key, NonceBin, AD, CT). +aead_chacha20poly1305_decrypt(CT, AD, Nonce, Key) -> + enacl_nif:crypto_aead_chacha20poly1305_decrypt(CT, AD, Nonce, Key). %% @doc aead_chacha20poly1305_KEYBYTES/0 returns the number of bytes %% of the key used in AEAD ChaCha20 Poly1305 encryption/decryption. @@ -1199,11 +1197,11 @@ aead_chacha20poly1305_decrypt(Key, Nonce, AD, CT) -> aead_chacha20poly1305_KEYBYTES() -> enacl_nif:crypto_aead_chacha20poly1305_KEYBYTES(). -%% @doc aead_chacha20poly1305_NONCEBYTES/0 returns the number of bytes +%% @doc aead_chacha20poly1305_NPUBBYTES/0 returns the number of bytes %% of the Nonce in AEAD ChaCha20 Poly1305 encryption/decryption. %% @end --spec aead_chacha20poly1305_NONCEBYTES() -> pos_integer(). -aead_chacha20poly1305_NONCEBYTES() -> +-spec aead_chacha20poly1305_NPUBBYTES() -> pos_integer(). +aead_chacha20poly1305_NPUBBYTES() -> enacl_nif:crypto_aead_chacha20poly1305_NPUBBYTES(). %% @doc aead_chacha20poly1305_ABYTES/0 returns the number of bytes diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index a6d6ec5..dfa7b97 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -272,15 +272,15 @@ crypto_stream_b(_Bytes, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). crypto_stream_xor(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). crypto_stream_xor_b(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). -crypto_aead_chacha20poly1305_encrypt(_Key, _Nonce, _AD, _Message) -> erlang:nif_error(nif_not_loaded). -crypto_aead_chacha20poly1305_decrypt(_Key, _Nonce, _AD, _Message) -> erlang:nif_error(nif_not_loaded). +crypto_aead_chacha20poly1305_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). +crypto_aead_chacha20poly1305_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). crypto_aead_chacha20poly1305_KEYBYTES() -> erlang:nif_error(nif_not_loaded). crypto_aead_chacha20poly1305_NPUBBYTES() -> erlang:nif_error(nif_not_loaded). crypto_aead_chacha20poly1305_ABYTES() -> erlang:nif_error(nif_not_loaded). crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded). -crypto_aead_xchacha20poly1305_encrypt(_Key, _Nonce, _AD, _Message) -> erlang:nif_error(nif_not_loaded). -crypto_aead_xchacha20poly1305_decrypt(_Key, _Nonce, _AD, _Message) -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). crypto_aead_xchacha20poly1305_KEYBYTES() -> erlang:nif_error(nif_not_loaded). crypto_aead_xchacha20poly1305_NPUBBYTES() -> erlang:nif_error(nif_not_loaded). crypto_aead_xchacha20poly1305_ABYTES() -> erlang:nif_error(nif_not_loaded). diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index 8ff5b5c..b752bba 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -103,14 +103,15 @@ aead_xchacha20poly1305(_Config) -> ok. aead_chacha20poly1305(_Config) -> + NonceLen = enacl:aead_chacha20poly1305_NPUBBYTES(), KLen = enacl:aead_chacha20poly1305_KEYBYTES(), Key = binary:copy(<<"K">>, KLen), Msg = <<"test">>, AD = <<1,2,3,4,5,6>>, - Nonce = 1337, + Nonce = binary:copy(<<"N">>, NonceLen), - CipherText = enacl:aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg), - Msg = enacl:aead_chacha20poly1305_decrypt(Key, Nonce, AD, CipherText), + CipherText = enacl:aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key), + Msg = enacl:aead_chacha20poly1305_decrypt(CipherText, AD, Nonce, Key), ok. pwhash(_Config) -> From 7f857115bbd0d38ea78fd84adc5bdd30a550a7ee Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 21 Jan 2020 14:16:24 +0100 Subject: [PATCH 052/162] Add aead IETF constructions Since the chacha20poly1305 constructions were the IETF variants, we renamed those so they follow the official library better. While here, we also fixed the argument order of the files. --- CHANGELOG.md | 24 ++++++++++++++-------- c_src/aead.c | 24 +++++++++++----------- c_src/aead.h | 24 +++++++++++----------- c_src/enacl_nif.c | 24 +++++++++++----------- src/enacl.erl | 48 ++++++++++++++++++++++---------------------- src/enacl_nif.erl | 24 +++++++++++----------- test/enacl_SUITE.erl | 12 +++++------ 7 files changed, 94 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c192c35..9dbff29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,17 +10,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. Over time, a number of bad things have snuck themselves into these bindings. This is a list of changes which are planned for a 1.0 release. -- The argument order in some of the AEAD constructions doesn't follow those of - sodium. They should. -- The AEAD_chacha20_poly1305 construction does the nonce wrong. It assumes a 64bit - integer, though the real underlying construction accepts 12 bytes. The key isn't - generated like this. The AEAD_xchacha20_poly1305 construction does it correctly. -- Plug some subtle allocation leaks in the kx code. - Plug some subtle memory leaks in the public API. ## [Unreleased] +### Compatibility +- If you used `aead_chacha20poly1305_*` functions, please read through the changelog + carefully as we have made changes to these functions. TL;DR: look for + `aead_chacha20poly1305_ietf_*` but note it is *not* just a simple substitution + into your code. + +### Removed +- The functions of the form `aead_chacha20poly1305_*` were removed. They implement + the IETF variant, and the argument order for them were wrong. Also, they used + severely limited nonce values, which is somewhat dangerous. The `..._NONCEBYTES` + name was changed to the consistent `..._NPUBBYTES`. + ### Added +- Added `aead_chacha20poly1305_ietf_*` variants. - Implement multipart signature support, by Garry Hill. - Implement enacl:crypto_sign_seed_keypair/1, by Ole Andre Birkedal. - Implement enacl:crypto_sign_ed25519_sk_to_pk/1, by an anonymous contribution. @@ -58,8 +65,9 @@ is a list of changes which are planned for a 1.0 release. ### Fixes - Fix a resource leak in generichash/sign init/update/final. -- Clang static analysis warnings (Thomas Arts) -- Replace a constant 31 with a computation from libsodium (Thomas Arts, from a security review) +- Clang static analysis warnings (Thomas Arts). +- Replace a constant 31 with a computation from libsodium (Thomas Arts, from a security review). +- Some subtle memory leaks in the error path for kx operations were plugged. ## [0.17.2] diff --git a/c_src/aead.c b/c_src/aead.c index 4339c99..24a71f1 100644 --- a/c_src/aead.c +++ b/c_src/aead.c @@ -9,33 +9,33 @@ * AEAD ChaCha20 Poly1305 */ ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_ietf_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_KEYBYTES); } ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_ietf_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_NPUBBYTES); } ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_ietf_ABYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_ABYTES); } ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX( + ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX); } ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ERL_NIF_TERM ret; ErlNifBinary key, nonce, ad, message, ciphertext; @@ -80,8 +80,8 @@ done: } ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_chacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ERL_NIF_TERM ret; ErlNifBinary key, nonce, ad, message, ciphertext; diff --git a/c_src/aead.h b/c_src/aead.h index 5188c9f..948cc3d 100644 --- a/c_src/aead.h +++ b/c_src/aead.h @@ -5,23 +5,23 @@ /* AEAD ChaCha20 Poly1305 */ ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_chacha20poly1305_ietf_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_chacha20poly1305_ietf_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_chacha20poly1305_ietf_ABYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX( + ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_chacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_chacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); /* AEAD XChaCha20 Poly1305 */ ERL_NIF_TERM diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index afa56da..cdf6e7d 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -405,20 +405,20 @@ static ErlNifFunc nif_funcs[] = { {"scramble_block_16", 2, enif_scramble_block_16}, - {"crypto_aead_chacha20poly1305_KEYBYTES", 0, - enacl_crypto_aead_chacha20poly1305_KEYBYTES}, - {"crypto_aead_chacha20poly1305_NPUBBYTES", 0, - enacl_crypto_aead_chacha20poly1305_NPUBBYTES}, - {"crypto_aead_chacha20poly1305_ABYTES", 0, - enacl_crypto_aead_chacha20poly1305_ABYTES}, - {"crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX", 0, - enacl_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX}, + {"crypto_aead_chacha20poly1305_ietf_KEYBYTES", 0, + enacl_crypto_aead_chacha20poly1305_ietf_KEYBYTES}, + {"crypto_aead_chacha20poly1305_ietf_NPUBBYTES", 0, + enacl_crypto_aead_chacha20poly1305_ietf_NPUBBYTES}, + {"crypto_aead_chacha20poly1305_ietf_ABYTES", 0, + enacl_crypto_aead_chacha20poly1305_ietf_ABYTES}, + {"crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX", 0, + enacl_crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX}, erl_nif_dirty_job_cpu_bound_macro( - "crypto_aead_chacha20poly1305_encrypt", 4, - enacl_crypto_aead_chacha20poly1305_encrypt), + "crypto_aead_chacha20poly1305_ietf_encrypt", 4, + enacl_crypto_aead_chacha20poly1305_ietf_encrypt), erl_nif_dirty_job_cpu_bound_macro( - "crypto_aead_chacha20poly1305_decrypt", 4, - enacl_crypto_aead_chacha20poly1305_decrypt), + "crypto_aead_chacha20poly1305_ietf_decrypt", 4, + enacl_crypto_aead_chacha20poly1305_ietf_decrypt), {"crypto_aead_xchacha20poly1305_KEYBYTES", 0, enacl_crypto_aead_xchacha20poly1305_KEYBYTES}, diff --git a/src/enacl.erl b/src/enacl.erl index 2a3d032..d00256a 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -66,12 +66,12 @@ stream_chacha20_xor/3, %% EQC - aead_chacha20poly1305_encrypt/4, - aead_chacha20poly1305_decrypt/4, - aead_chacha20poly1305_KEYBYTES/0, - aead_chacha20poly1305_NPUBBYTES/0, - aead_chacha20poly1305_ABYTES/0, - aead_chacha20poly1305_MESSAGEBYTES_MAX/0, + aead_chacha20poly1305_ietf_encrypt/4, + aead_chacha20poly1305_ietf_decrypt/4, + aead_chacha20poly1305_ietf_KEYBYTES/0, + aead_chacha20poly1305_ietf_NPUBBYTES/0, + aead_chacha20poly1305_ietf_ABYTES/0, + aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX/0, %% No Tests! aead_xchacha20poly1305_encrypt/4, @@ -1169,54 +1169,54 @@ kx_secret_key_size() -> %% `AD' using `Key' and `Nonce'. Returns the encrypted message followed by %% `aead_chacha20poly1305_ABYTES/0' bytes of MAC. %% @end --spec aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key) -> binary() | {error, term()} +-spec aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) -> binary() | {error, term()} when Key :: binary(), Nonce :: binary(), AD :: binary(), Msg :: binary(). -aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key) -> - enacl_nif:crypto_aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key). +aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) -> + enacl_nif:crypto_aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key). %% @doc aead_chacha20poly1305_decrypt/4 decrypts ciphertext `CT' with additional %% data `AD' using `Key' and `Nonce'. Note: `CipherText' should contain %% `aead_chacha20poly1305_ABYTES/0' bytes that is the MAC. Returns the decrypted %% message. %% @end --spec aead_chacha20poly1305_decrypt(CT, AD, Nonce, Key) -> binary() | {error, term()} +-spec aead_chacha20poly1305_ietf_decrypt(CT, AD, Nonce, Key) -> binary() | {error, term()} when Key :: binary(), Nonce :: binary(), AD :: binary(), CT :: binary(). -aead_chacha20poly1305_decrypt(CT, AD, Nonce, Key) -> - enacl_nif:crypto_aead_chacha20poly1305_decrypt(CT, AD, Nonce, Key). +aead_chacha20poly1305_ietf_decrypt(CT, AD, Nonce, Key) -> + enacl_nif:crypto_aead_chacha20poly1305_ietf_decrypt(CT, AD, Nonce, Key). %% @doc aead_chacha20poly1305_KEYBYTES/0 returns the number of bytes %% of the key used in AEAD ChaCha20 Poly1305 encryption/decryption. %% @end --spec aead_chacha20poly1305_KEYBYTES() -> pos_integer(). -aead_chacha20poly1305_KEYBYTES() -> - enacl_nif:crypto_aead_chacha20poly1305_KEYBYTES(). +-spec aead_chacha20poly1305_ietf_KEYBYTES() -> pos_integer(). +aead_chacha20poly1305_ietf_KEYBYTES() -> + enacl_nif:crypto_aead_chacha20poly1305_ietf_KEYBYTES(). %% @doc aead_chacha20poly1305_NPUBBYTES/0 returns the number of bytes %% of the Nonce in AEAD ChaCha20 Poly1305 encryption/decryption. %% @end --spec aead_chacha20poly1305_NPUBBYTES() -> pos_integer(). -aead_chacha20poly1305_NPUBBYTES() -> - enacl_nif:crypto_aead_chacha20poly1305_NPUBBYTES(). +-spec aead_chacha20poly1305_ietf_NPUBBYTES() -> pos_integer(). +aead_chacha20poly1305_ietf_NPUBBYTES() -> + enacl_nif:crypto_aead_chacha20poly1305_ietf_NPUBBYTES(). %% @doc aead_chacha20poly1305_ABYTES/0 returns the number of bytes %% of the MAC in AEAD ChaCha20 Poly1305 encryption/decryption. %% @end --spec aead_chacha20poly1305_ABYTES() -> pos_integer(). -aead_chacha20poly1305_ABYTES() -> - enacl_nif:crypto_aead_chacha20poly1305_ABYTES(). +-spec aead_chacha20poly1305_ietf_ABYTES() -> pos_integer(). +aead_chacha20poly1305_ietf_ABYTES() -> + enacl_nif:crypto_aead_chacha20poly1305_ietf_ABYTES(). %% @doc aead_chacha20poly1305_MESSAGEBYTES_MAX/0 returns the max number of bytes %% allowed in a message in AEAD ChaCha20 Poly1305 encryption/decryption. %% @end --spec aead_chacha20poly1305_MESSAGEBYTES_MAX() -> pos_integer(). -aead_chacha20poly1305_MESSAGEBYTES_MAX() -> - enacl_nif:crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(). +-spec aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX() -> pos_integer(). +aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX() -> + enacl_nif:crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX(). %% AEAD XChaCha20 Poly1305 %% ---------------------- diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index dfa7b97..97816a0 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -74,12 +74,12 @@ crypto_stream_xor/3, crypto_stream_xor_b/3, - crypto_aead_chacha20poly1305_encrypt/4, - crypto_aead_chacha20poly1305_decrypt/4, - crypto_aead_chacha20poly1305_KEYBYTES/0, - crypto_aead_chacha20poly1305_NPUBBYTES/0, - crypto_aead_chacha20poly1305_ABYTES/0, - crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX/0, + crypto_aead_chacha20poly1305_ietf_encrypt/4, + crypto_aead_chacha20poly1305_ietf_decrypt/4, + crypto_aead_chacha20poly1305_ietf_KEYBYTES/0, + crypto_aead_chacha20poly1305_ietf_NPUBBYTES/0, + crypto_aead_chacha20poly1305_ietf_ABYTES/0, + crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX/0, crypto_aead_xchacha20poly1305_encrypt/4, crypto_aead_xchacha20poly1305_decrypt/4, @@ -272,12 +272,12 @@ crypto_stream_b(_Bytes, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). crypto_stream_xor(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). crypto_stream_xor_b(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). -crypto_aead_chacha20poly1305_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). -crypto_aead_chacha20poly1305_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). -crypto_aead_chacha20poly1305_KEYBYTES() -> erlang:nif_error(nif_not_loaded). -crypto_aead_chacha20poly1305_NPUBBYTES() -> erlang:nif_error(nif_not_loaded). -crypto_aead_chacha20poly1305_ABYTES() -> erlang:nif_error(nif_not_loaded). -crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded). +crypto_aead_chacha20poly1305_ietf_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). +crypto_aead_chacha20poly1305_ietf_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). +crypto_aead_chacha20poly1305_ietf_KEYBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_aead_chacha20poly1305_ietf_NPUBBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_aead_chacha20poly1305_ietf_ABYTES() -> erlang:nif_error(nif_not_loaded). +crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded). crypto_aead_xchacha20poly1305_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). crypto_aead_xchacha20poly1305_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index b752bba..5798b7f 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -41,7 +41,7 @@ groups() -> [generichash_basic_pos, generichash_chunked, aead_xchacha20poly1305, - aead_chacha20poly1305, + aead_chacha20poly1305_ietf, pwhash, sign, kx]}, @@ -102,16 +102,16 @@ aead_xchacha20poly1305(_Config) -> Msg = enacl:aead_xchacha20poly1305_decrypt(Key, Nonce, AD, CipherText), ok. -aead_chacha20poly1305(_Config) -> - NonceLen = enacl:aead_chacha20poly1305_NPUBBYTES(), - KLen = enacl:aead_chacha20poly1305_KEYBYTES(), +aead_chacha20poly1305_ietf(_Config) -> + NonceLen = enacl:aead_chacha20poly1305_ietf_NPUBBYTES(), + KLen = enacl:aead_chacha20poly1305_ietf_KEYBYTES(), Key = binary:copy(<<"K">>, KLen), Msg = <<"test">>, AD = <<1,2,3,4,5,6>>, Nonce = binary:copy(<<"N">>, NonceLen), - CipherText = enacl:aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key), - Msg = enacl:aead_chacha20poly1305_decrypt(CipherText, AD, Nonce, Key), + CipherText = enacl:aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key), + Msg = enacl:aead_chacha20poly1305_ietf_decrypt(CipherText, AD, Nonce, Key), ok. pwhash(_Config) -> From e67619a4030fcc6667f66c4057947b27ed42137a Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 22 Jan 2020 19:41:58 +0100 Subject: [PATCH 053/162] Update the naming scheme of AEAD xchacha20... Since this AEAD construction variant is an IETF variant, reflect this in the names of the functions. This streamlines the API with the libsodium API. --- c_src/aead.c | 105 +++++++++++++++++++++++++++++-------------- c_src/aead.h | 24 +++++----- c_src/enacl_nif.c | 24 +++++----- src/enacl.erl | 50 ++++++++++----------- src/enacl_nif.erl | 24 +++++----- test/enacl_SUITE.erl | 8 ++-- 6 files changed, 136 insertions(+), 99 deletions(-) diff --git a/c_src/aead.c b/c_src/aead.c index 24a71f1..055c222 100644 --- a/c_src/aead.c +++ b/c_src/aead.c @@ -131,85 +131,122 @@ done: * AEAD XChaCha20 Poly1305 */ ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_xchacha20poly1305_ietf_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_KEYBYTES); } ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_xchacha20poly1305_ietf_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES); } ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_xchacha20poly1305_ietf_ABYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_ABYTES); } ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX( +enacl_crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX( ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { return enif_make_int64(env, crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX); } ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_xchacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary key, nonce, ad, message, ciphertext; + ERL_NIF_TERM ret; - if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &ad)) || - (!enif_inspect_binary(env, argv[3], &message)) || - (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES) || - (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)) { - return enif_make_badarg(env); - } + if (argc != 4) + goto bad_arg; + if (!enif_inspect_binary(env, argv[0], &message)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &ad)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &nonce)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[3], &key)) + goto bad_arg; + + if (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES) + goto bad_arg; + if (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES) + goto bad_arg; if (!enif_alloc_binary(message.size + crypto_aead_xchacha20poly1305_ietf_ABYTES, &ciphertext)) { - return enacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); + goto done; } if (crypto_aead_xchacha20poly1305_ietf_encrypt( ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, NULL, nonce.data, key.data) < 0) { - return enacl_error_tuple(env, "aead_xchacha20poly1305_ietf_encrypt_failed"); + ret = enacl_error_tuple(env, "aead_xchacha20poly1305_ietf_encrypt_failed"); + goto release; } - return enif_make_binary(env, &ciphertext); + ret = enif_make_binary(env, &ciphertext); + goto done; + +bad_arg: + return enif_make_badarg(env); +release: + enif_release_binary(&ciphertext); +done: + return ret; } ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +enacl_crypto_aead_xchacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { ErlNifBinary key, nonce, ad, message, ciphertext; + ERL_NIF_TERM ret; - if ((argc != 4) || (!enif_inspect_binary(env, argv[0], &key)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &ad)) || - (!enif_inspect_binary(env, argv[3], &ciphertext)) || - (ciphertext.size < crypto_aead_xchacha20poly1305_ietf_ABYTES) || - (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES) || - (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)) { - return enif_make_badarg(env); - } + if (argc != 4) + goto bad_arg; + if (!enif_inspect_binary(env, argv[0], &ciphertext)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &ad)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &nonce)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[3], &key)) + goto bad_arg; + + if (ciphertext.size < crypto_aead_xchacha20poly1305_ietf_ABYTES) + goto bad_arg; + if (key.size != crypto_aead_xchacha20poly1305_ietf_KEYBYTES) + goto bad_arg; + if (nonce.size != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES) + goto bad_arg; if (!enif_alloc_binary(ciphertext.size - crypto_aead_xchacha20poly1305_ietf_ABYTES, &message)) { - return enacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); + goto done; } if (crypto_aead_xchacha20poly1305_ietf_decrypt( message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, ad.size, nonce.data, key.data) < 0) { - return enacl_error_tuple(env, "aead_xchacha20poly1305_ietf_decrypt_failed"); + ret = enacl_error_tuple(env, "aead_xchacha20poly1305_ietf_decrypt_failed"); + goto release; } - return enif_make_binary(env, &message); + ret = enif_make_binary(env, &message); + goto done; + +bad_arg: + return enif_make_badarg(env); +release: + enif_release_binary(&message); +done: + return ret; } diff --git a/c_src/aead.h b/c_src/aead.h index 948cc3d..1591b24 100644 --- a/c_src/aead.h +++ b/c_src/aead.h @@ -25,22 +25,22 @@ enacl_crypto_aead_chacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc, /* AEAD XChaCha20 Poly1305 */ ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_xchacha20poly1305_ietf_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_xchacha20poly1305_ietf_NPUBBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_xchacha20poly1305_ietf_ABYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX( + ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_encrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_xchacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enacl_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_xchacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); #endif diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index cdf6e7d..5e33df3 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -420,20 +420,20 @@ static ErlNifFunc nif_funcs[] = { "crypto_aead_chacha20poly1305_ietf_decrypt", 4, enacl_crypto_aead_chacha20poly1305_ietf_decrypt), - {"crypto_aead_xchacha20poly1305_KEYBYTES", 0, - enacl_crypto_aead_xchacha20poly1305_KEYBYTES}, - {"crypto_aead_xchacha20poly1305_NPUBBYTES", 0, - enacl_crypto_aead_xchacha20poly1305_NPUBBYTES}, - {"crypto_aead_xchacha20poly1305_ABYTES", 0, - enacl_crypto_aead_xchacha20poly1305_ABYTES}, - {"crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX", 0, - enacl_crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX}, + {"crypto_aead_xchacha20poly1305_ietf_KEYBYTES", 0, + enacl_crypto_aead_xchacha20poly1305_ietf_KEYBYTES}, + {"crypto_aead_xchacha20poly1305_ietf_NPUBBYTES", 0, + enacl_crypto_aead_xchacha20poly1305_ietf_NPUBBYTES}, + {"crypto_aead_xchacha20poly1305_ietf_ABYTES", 0, + enacl_crypto_aead_xchacha20poly1305_ietf_ABYTES}, + {"crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX", 0, + enacl_crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX}, erl_nif_dirty_job_cpu_bound_macro( - "crypto_aead_xchacha20poly1305_encrypt", 4, - enacl_crypto_aead_xchacha20poly1305_encrypt), + "crypto_aead_xchacha20poly1305_ietf_encrypt", 4, + enacl_crypto_aead_xchacha20poly1305_ietf_encrypt), erl_nif_dirty_job_cpu_bound_macro( - "crypto_aead_xchacha20poly1305_decrypt", 4, - enacl_crypto_aead_xchacha20poly1305_decrypt), + "crypto_aead_xchacha20poly1305_ietf_decrypt", 4, + enacl_crypto_aead_xchacha20poly1305_ietf_decrypt), {"crypto_generichash_BYTES", 0, enacl_crypto_generichash_BYTES}, {"crypto_generichash_BYTES_MIN", 0, enacl_crypto_generichash_BYTES_MIN}, diff --git a/src/enacl.erl b/src/enacl.erl index d00256a..cdfd578 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -74,12 +74,12 @@ aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX/0, %% No Tests! - aead_xchacha20poly1305_encrypt/4, - aead_xchacha20poly1305_decrypt/4, - aead_xchacha20poly1305_KEYBYTES/0, - aead_xchacha20poly1305_NONCEBYTES/0, - aead_xchacha20poly1305_ABYTES/0, - aead_xchacha20poly1305_MESSAGEBYTES_MAX/0, + aead_xchacha20poly1305_ietf_encrypt/4, + aead_xchacha20poly1305_ietf_decrypt/4, + aead_xchacha20poly1305_ietf_KEYBYTES/0, + aead_xchacha20poly1305_ietf_NPUBBYTES/0, + aead_xchacha20poly1305_ietf_ABYTES/0, + aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX/0, %% EQC stream_key_size/0, @@ -1224,54 +1224,54 @@ aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX() -> %% `AD' using `Key' and `Nonce'. Returns the encrypted message followed by %% `aead_xchacha20poly1305_ABYTES/0' bytes of MAC. %% @end --spec aead_xchacha20poly1305_encrypt(Key, Nonce, AD, Msg) -> binary() | {error, term()} +-spec aead_xchacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) -> binary() | {error, term()} when Key :: binary(), Nonce :: binary(), AD :: binary(), Msg :: binary(). -aead_xchacha20poly1305_encrypt(Key, Nonce, AD, Msg) -> - enacl_nif:crypto_aead_xchacha20poly1305_encrypt(Key, Nonce, AD, Msg). +aead_xchacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) -> + enacl_nif:crypto_aead_xchacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key). %% @doc aead_xchacha20poly1305_decrypt/4 decrypts ciphertext `CT' with additional %% data `AD' using `Key' and `Nonce'. Note: `CipherText' should contain %% `aead_xchacha20poly1305_ABYTES/0' bytes that is the MAC. Returns the decrypted %% message. %% @end --spec aead_xchacha20poly1305_decrypt(Key, Nonce, AD, CT) -> binary() | {error, term()} +-spec aead_xchacha20poly1305_ietf_decrypt(CT, AD, Nonce, Key) -> binary() | {error, term()} when Key :: binary(), Nonce :: binary(), AD :: binary(), CT :: binary(). -aead_xchacha20poly1305_decrypt(Key, Nonce, AD, CT) -> - enacl_nif:crypto_aead_xchacha20poly1305_decrypt(Key, Nonce, AD, CT). +aead_xchacha20poly1305_ietf_decrypt(CT, AD, Nonce, Key) -> + enacl_nif:crypto_aead_xchacha20poly1305_ietf_decrypt(CT, AD, Nonce, Key). %% @doc aead_xchacha20poly1305_KEYBYTES/0 returns the number of bytes %% of the key used in AEAD XChaCha20 Poly1305 encryption/decryption. %% @end --spec aead_xchacha20poly1305_KEYBYTES() -> pos_integer(). -aead_xchacha20poly1305_KEYBYTES() -> - enacl_nif:crypto_aead_xchacha20poly1305_KEYBYTES(). +-spec aead_xchacha20poly1305_ietf_KEYBYTES() -> pos_integer(). +aead_xchacha20poly1305_ietf_KEYBYTES() -> + enacl_nif:crypto_aead_xchacha20poly1305_ietf_KEYBYTES(). -%% @doc aead_xchacha20poly1305_NONCEBYTES/0 returns the number of bytes +%% @doc aead_xchacha20poly1305_NPUBBYTES/0 returns the number of bytes %% of the Nonce in AEAD XChaCha20 Poly1305 encryption/decryption. %% @end --spec aead_xchacha20poly1305_NONCEBYTES() -> pos_integer(). -aead_xchacha20poly1305_NONCEBYTES() -> - enacl_nif:crypto_aead_xchacha20poly1305_NPUBBYTES(). +-spec aead_xchacha20poly1305_ietf_NPUBBYTES() -> pos_integer(). +aead_xchacha20poly1305_ietf_NPUBBYTES() -> + enacl_nif:crypto_aead_xchacha20poly1305_ietf_NPUBBYTES(). %% @doc aead_xchacha20poly1305_ABYTES/0 returns the number of bytes %% of the MAC in AEAD XChaCha20 Poly1305 encryption/decryption. %% @end --spec aead_xchacha20poly1305_ABYTES() -> pos_integer(). -aead_xchacha20poly1305_ABYTES() -> - enacl_nif:crypto_aead_xchacha20poly1305_ABYTES(). +-spec aead_xchacha20poly1305_ietf_ABYTES() -> pos_integer(). +aead_xchacha20poly1305_ietf_ABYTES() -> + enacl_nif:crypto_aead_xchacha20poly1305_ietf_ABYTES(). %% @doc aead_xchacha20poly1305_MESSAGEBYTES_MAX/0 returns the max number of bytes %% allowed in a message in AEAD XChaCha20 Poly1305 encryption/decryption. %% @end --spec aead_xchacha20poly1305_MESSAGEBYTES_MAX() -> pos_integer(). -aead_xchacha20poly1305_MESSAGEBYTES_MAX() -> - enacl_nif:crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX(). +-spec aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX() -> pos_integer(). +aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX() -> + enacl_nif:crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX(). %% Obtaining random bytes diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 97816a0..1309a11 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -81,12 +81,12 @@ crypto_aead_chacha20poly1305_ietf_ABYTES/0, crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX/0, - crypto_aead_xchacha20poly1305_encrypt/4, - crypto_aead_xchacha20poly1305_decrypt/4, - crypto_aead_xchacha20poly1305_KEYBYTES/0, - crypto_aead_xchacha20poly1305_NPUBBYTES/0, - crypto_aead_xchacha20poly1305_ABYTES/0, - crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX/0, + crypto_aead_xchacha20poly1305_ietf_encrypt/4, + crypto_aead_xchacha20poly1305_ietf_decrypt/4, + crypto_aead_xchacha20poly1305_ietf_KEYBYTES/0, + crypto_aead_xchacha20poly1305_ietf_NPUBBYTES/0, + crypto_aead_xchacha20poly1305_ietf_ABYTES/0, + crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX/0, crypto_auth_BYTES/0, crypto_auth_KEYBYTES/0, @@ -279,12 +279,12 @@ crypto_aead_chacha20poly1305_ietf_NPUBBYTES() -> erlang crypto_aead_chacha20poly1305_ietf_ABYTES() -> erlang:nif_error(nif_not_loaded). crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded). -crypto_aead_xchacha20poly1305_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). -crypto_aead_xchacha20poly1305_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). -crypto_aead_xchacha20poly1305_KEYBYTES() -> erlang:nif_error(nif_not_loaded). -crypto_aead_xchacha20poly1305_NPUBBYTES() -> erlang:nif_error(nif_not_loaded). -crypto_aead_xchacha20poly1305_ABYTES() -> erlang:nif_error(nif_not_loaded). -crypto_aead_xchacha20poly1305_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_ietf_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_ietf_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_ietf_KEYBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_ietf_NPUBBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_ietf_ABYTES() -> erlang:nif_error(nif_not_loaded). +crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded). crypto_auth_BYTES() -> erlang:nif_error(nif_not_loaded). crypto_auth_KEYBYTES() -> erlang:nif_error(nif_not_loaded). diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index 5798b7f..d36ba83 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -91,15 +91,15 @@ generichash_chunked(State, Msg, N) -> generichash_chunked(State2, Msg, N-1). aead_xchacha20poly1305(_Config) -> - NonceLen = enacl:aead_xchacha20poly1305_NONCEBYTES(), - KLen = enacl:aead_xchacha20poly1305_KEYBYTES(), + NonceLen = enacl:aead_xchacha20poly1305_ietf_NPUBBYTES(), + KLen = enacl:aead_xchacha20poly1305_ietf_KEYBYTES(), Key = binary:copy(<<"K">>, KLen), Msg = <<"test">>, AD = <<1,2,3,4,5,6>>, Nonce = binary:copy(<<"N">>, NonceLen), - CipherText = enacl:aead_xchacha20poly1305_encrypt(Key, Nonce, AD, Msg), - Msg = enacl:aead_xchacha20poly1305_decrypt(Key, Nonce, AD, CipherText), + CipherText = enacl:aead_xchacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key), + Msg = enacl:aead_xchacha20poly1305_ietf_decrypt(CipherText, AD, Nonce, Key), ok. aead_chacha20poly1305_ietf(_Config) -> From 018bf0f6fccac843698fd7da5677490991b98fc2 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 22 Jan 2020 22:22:29 +0100 Subject: [PATCH 054/162] Plug a large set of memory leaks in signing If you fail, there are cases where binaries are not properly released. This patch fixes them all in signing. --- c_src/generichash.c | 2 +- c_src/sign.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/c_src/generichash.c b/c_src/generichash.c index eb72791..5909ad6 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -195,9 +195,9 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, ret = enif_make_resource(env, obj); goto done; + bad_arg: return enif_make_badarg(env); - err: ret = enacl_error_tuple(env, "internal_error"); if (obj != NULL) { diff --git a/c_src/sign.c b/c_src/sign.c index 56e1b48..d836a54 100644 --- a/c_src/sign.c +++ b/c_src/sign.c @@ -103,10 +103,8 @@ ERL_NIF_TERM enacl_crypto_sign_update(ErlNifEnv *env, int argc, // Validate the arguments if (argc != 2) goto bad_arg; - if (!enif_get_resource(env, argv[0], enacl_sign_ctx_rtype, (void **)&obj)) goto bad_arg; - if (!enif_inspect_binary(env, argv[1], &data)) goto bad_arg; @@ -165,6 +163,7 @@ ERL_NIF_TERM enacl_crypto_sign_final_create(ErlNifEnv *env, int argc, ret = enif_make_tuple2(env, ok, signature); goto cleanup; + bad_arg: return enif_make_badarg(env); release: @@ -230,6 +229,7 @@ enacl_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_ed25519_SECRETKEYBYTES, &sk)) { + enif_release_binary(&pk); return enacl_error_tuple(env, "alloc_failed"); } @@ -254,6 +254,7 @@ enacl_crypto_sign_ed25519_sk_to_pk(ErlNifEnv *env, int argc, } if (crypto_sign_ed25519_sk_to_pk(pk.data, sk.data) != 0) { + enif_release_binary(&pk); return enacl_error_tuple(env, "crypto_sign_ed25519_sk_to_pk_failed"); } @@ -276,6 +277,7 @@ enacl_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc, if (crypto_sign_ed25519_pk_to_curve25519(curve25519_pk.data, ed25519_pk.data) != 0) { + enif_release_binary(&curve25519_pk); return enacl_error_tuple(env, "ed25519_public_to_curve25519_failed"); } @@ -298,6 +300,7 @@ enacl_crypto_sign_ed25519_secret_to_curve25519(ErlNifEnv *env, int argc, if (crypto_sign_ed25519_sk_to_curve25519(curve25519_sk.data, ed25519_sk.data) != 0) { + enif_release_binary(&curve25519_sk); return enacl_error_tuple(env, "ed25519_secret_to_curve25519_failed"); } @@ -344,6 +347,7 @@ ERL_NIF_TERM enacl_crypto_sign_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { + enif_release_binary(&pk); return enacl_error_tuple(env, "alloc_failed"); } @@ -366,6 +370,7 @@ ERL_NIF_TERM enacl_crypto_sign_seed_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { + enif_release_binary(&pk); return enacl_error_tuple(env, "alloc_failed"); } @@ -484,8 +489,8 @@ enacl_crypto_sign_verify_detached(ErlNifEnv *env, int argc, } if (0 == crypto_sign_verify_detached(sig.data, m.data, m.size, pk.data)) { - return enif_make_atom(env, "true"); + return enif_make_atom(env, ATOM_TRUE); } else { - return enif_make_atom(env, "false"); + return enif_make_atom(env, ATOM_FALSE); } } From 49a437347ef3a9dd61c8540dc0ca071c62f69879 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 22 Jan 2020 22:22:53 +0100 Subject: [PATCH 055/162] Improve release naming Make it obvious you are releasing both tx and rx. --- c_src/kx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/c_src/kx.c b/c_src/kx.c index a344321..6d5b39b 100644 --- a/c_src/kx.c +++ b/c_src/kx.c @@ -81,7 +81,7 @@ enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, server_sk.data, client_pk.data)) { // suspicious client public key ret = enacl_error_tuple(env, "invalid_client_public_key"); - goto release_tx; + goto release_tx_rx; } ret = enif_make_tuple2(env, enif_make_binary(env, &rx), @@ -90,7 +90,7 @@ enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); -release_tx: +release_tx_rx: enif_release_binary(&tx); release_rx: enif_release_binary(&rx); @@ -134,7 +134,7 @@ enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, client_sk.data, server_pk.data)) { // suspicious server public key ret = enacl_error_tuple(env, "invalid_server_public_key"); - goto release_tx; + goto release_tx_rx; } ret = enif_make_tuple2(env, enif_make_binary(env, &rx), @@ -142,7 +142,7 @@ enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, goto done; bad_arg: return enif_make_badarg(env); -release_tx: +release_tx_rx: enif_release_binary(&tx); release_rx: enif_release_binary(&rx); From e4b35a7035b999ca40ee24818b51cec581b97984 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 22 Jan 2020 22:23:23 +0100 Subject: [PATCH 056/162] Flesh out changelog some more This is a sort-of TODO list at the top of the list, but we use it to keep track of what we need to do. --- CHANGELOG.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dbff29..d104d59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. Over time, a number of bad things have snuck themselves into these bindings. This is a list of changes which are planned for a 1.0 release. -- Plug some subtle memory leaks in the public API. +- Plug some subtle memory leaks in API: + - Public + - Secret + +Under errors, the current code can leak binaries. I don't want that to happen, so we +are going to use a better cleanup scheme in the code base. + +- Play the mutex game with: + - Generic Hash multi-part types + - Sign multi-part types + +The resource-variant structs need to be mutex-protected. Otherwise we run the risk of +having multiple simultaneous updates to the hash state without having proper critical +sections applied. The current code is subtly in error! ## [Unreleased] From 7d8fdf69c0f8d0f58318e9ee22bd23b6d8b8aa60 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 24 Jan 2020 14:48:21 +0100 Subject: [PATCH 057/162] Protect generichash by a mutex While sodium is thread-safe, our resources are not. Furthermore, we might have an update call going when someone decides to call finalize and so on. It is not clever to do so, but on the other hand I want to protect against this. While here, mark the mutexed calls as dirty CPU. This avoids them blocking the main scheduler and only messes with the background dirty threads, which is somewhat more safe. The consequence is that order access to the resource is now serialized. I don't think you should do it, but it is now possible. --- CHANGELOG.md | 2 +- c_src/enacl_nif.c | 6 ++++-- c_src/generichash.c | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d104d59..5096bda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,6 @@ Under errors, the current code can leak binaries. I don't want that to happen, s are going to use a better cleanup scheme in the code base. - Play the mutex game with: - - Generic Hash multi-part types - Sign multi-part types The resource-variant structs need to be mutex-protected. Otherwise we run the risk of @@ -81,6 +80,7 @@ sections applied. The current code is subtly in error! - Clang static analysis warnings (Thomas Arts). - Replace a constant 31 with a computation from libsodium (Thomas Arts, from a security review). - Some subtle memory leaks in the error path for kx operations were plugged. +- The multi-part generichash interface is now properly process/thread safe. ## [0.17.2] diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 5e33df3..6993db9 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -445,8 +445,10 @@ static ErlNifFunc nif_funcs[] = { enacl_crypto_generichash_KEYBYTES_MAX}, {"crypto_generichash", 3, enacl_crypto_generichash}, {"crypto_generichash_init", 2, enacl_crypto_generichash_init}, - {"crypto_generichash_update", 2, enacl_crypto_generichash_update}, - {"crypto_generichash_final", 1, enacl_crypto_generichash_final} + erl_nif_dirty_job_cpu_bound_macro("crypto_generichash_update", 2, + enacl_crypto_generichash_update), + erl_nif_dirty_job_cpu_bound_macro("crypto_generichash_final", 1, + enacl_crypto_generichash_final) }; diff --git a/c_src/generichash.c b/c_src/generichash.c index 5909ad6..222dd82 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -6,9 +6,11 @@ #include "generichash.h" typedef struct enacl_generichash_ctx { + ErlNifMutex *mtx; crypto_generichash_state *ctx; // Underlying hash state from sodium int alive; // Is the context still valid for updates/finalizes? int outlen; // Final size of the hash + } enacl_generichash_ctx; static ErlNifResourceType *enacl_generic_hash_ctx_rtype; @@ -37,6 +39,9 @@ static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env, if (obj->ctx) sodium_free(obj->ctx); + if (obj->mtx != NULL) + enif_mutex_destroy(obj->mtx); + return; } @@ -175,6 +180,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, // Allocate the state context via libsodium // Note that this ensures a 64byte alignment for the resource // And also protects the resource via guardpages + obj->mtx = NULL; obj->ctx = NULL; obj->alive = 0; obj->outlen = 0; @@ -187,6 +193,11 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, obj->alive = 1; obj->outlen = hash_size; + if ((obj->mtx = enif_mutex_create("enacl.generichash")) == NULL) { + ret = enacl_error_tuple(env, "generichash_mutex_error"); + goto err; + } + // Call the library function if (0 != crypto_generichash_init(obj->ctx, k, key.size, obj->outlen)) { ret = enacl_error_tuple(env, "hash_init_error"); @@ -230,6 +241,8 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, if (!enif_inspect_binary(env, argv[1], &data)) goto bad_arg; + enif_mutex_lock(obj->mtx); + if (!obj->alive) { ret = enacl_error_tuple(env, "finalized"); goto done; @@ -247,6 +260,7 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); done: + enif_mutex_unlock(obj->mtx); return ret; } @@ -262,6 +276,7 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, (void **)&obj)) goto bad_arg; + enif_mutex_lock(obj->mtx); if (!obj->alive) { ret = enacl_error_tuple(env, "finalized"); goto done; @@ -293,5 +308,6 @@ bad_arg: release: enif_release_binary(&hash); done: + enif_mutex_unlock(obj->mtx); return ret; } From 4939f7bb233b1d96d281214d6e7c99e82c82e288 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 24 Jan 2020 15:18:04 +0100 Subject: [PATCH 058/162] Protect the signature ctx with a mutex This is the same game as with the generichash construction. We want to protect it with a mutex so different processes can safely do work on the same resource. While here, also move the _update function onto the dirty scheduler. It is by far the most expensive operation, and why it wasn't there in the first place is odd. This should unblock the scheduler on long sign-checks. It also move the possible mutex block onto the dirty scheduler thread, away from the core schedulers, improving latency in the system as a result. --- CHANGELOG.md | 7 ------- c_src/enacl_nif.c | 3 ++- c_src/generichash.c | 2 +- c_src/sign.c | 23 ++++++++++++++++++++++- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5096bda..490c006 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,13 +17,6 @@ is a list of changes which are planned for a 1.0 release. Under errors, the current code can leak binaries. I don't want that to happen, so we are going to use a better cleanup scheme in the code base. -- Play the mutex game with: - - Sign multi-part types - -The resource-variant structs need to be mutex-protected. Otherwise we run the risk of -having multiple simultaneous updates to the hash state without having proper critical -sections applied. The current code is subtly in error! - ## [Unreleased] ### Compatibility diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 6993db9..1e47712 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -286,7 +286,8 @@ static ErlNifFunc nif_funcs[] = { erl_nif_dirty_job_cpu_bound_macro("crypto_sign_verify_detached", 3, enacl_crypto_sign_verify_detached), {"crypto_sign_init", 0, enacl_crypto_sign_init}, - {"crypto_sign_update", 2, enacl_crypto_sign_update}, + erl_nif_dirty_job_cpu_bound_macro("crypto_sign_update", 2, + enacl_crypto_sign_update), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_final_create", 2, enacl_crypto_sign_final_create), erl_nif_dirty_job_cpu_bound_macro("crypto_sign_final_verify", 3, diff --git a/c_src/generichash.c b/c_src/generichash.c index 222dd82..524def8 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -194,7 +194,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, obj->outlen = hash_size; if ((obj->mtx = enif_mutex_create("enacl.generichash")) == NULL) { - ret = enacl_error_tuple(env, "generichash_mutex_error"); + ret = enacl_error_tuple(env, "mutex_create"); goto err; } diff --git a/c_src/sign.c b/c_src/sign.c index d836a54..07f1446 100644 --- a/c_src/sign.c +++ b/c_src/sign.c @@ -6,6 +6,7 @@ #include "sign.h" typedef struct enacl_sign_ctx { + ErlNifMutex *mtx; crypto_sign_state *state; // The underlying signature state int alive; // Is the context still valid for updates/finalization } enacl_sign_ctx; @@ -35,6 +36,9 @@ void enacl_sign_ctx_dtor(ErlNifEnv *env, enacl_sign_ctx *obj) { enif_free(obj->state); } + if (obj->mtx != NULL) + enif_mutex_destroy(obj->mtx); + return; } @@ -63,6 +67,11 @@ ERL_NIF_TERM enacl_crypto_sign_init(ErlNifEnv *env, int argc, } obj->alive = 1; + if ((obj->mtx = enif_mutex_create("enacl.sign")) == NULL) { + ret = enacl_error_tuple(env, "mutex_create"); + goto free; + } + if (0 != crypto_sign_init(obj->state)) { ret = enacl_error_tuple(env, "sign_init_error"); goto free; @@ -83,6 +92,7 @@ free: obj->state = NULL; } release: + // This also frees the mutex via the destructor enif_release_resource(obj); done: return ret; @@ -108,6 +118,7 @@ ERL_NIF_TERM enacl_crypto_sign_update(ErlNifEnv *env, int argc, if (!enif_inspect_binary(env, argv[1], &data)) goto bad_arg; + enif_mutex_lock(obj->mtx); if (!obj->alive) { ret = enacl_error_tuple(env, "finalized"); goto done; @@ -124,6 +135,7 @@ ERL_NIF_TERM enacl_crypto_sign_update(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); done: + enif_mutex_unlock(obj->mtx); return ret; } @@ -143,6 +155,7 @@ ERL_NIF_TERM enacl_crypto_sign_final_create(ErlNifEnv *env, int argc, if (sk.size != crypto_sign_SECRETKEYBYTES) goto bad_arg; + enif_mutex_lock(obj->mtx); if (!obj->alive) { ret = enacl_error_tuple(env, "finalized"); goto done; @@ -174,6 +187,7 @@ cleanup: enif_free(obj->state); obj->state = NULL; done: + enif_mutex_unlock(obj->mtx); return ret; } @@ -194,6 +208,12 @@ ERL_NIF_TERM enacl_crypto_sign_final_verify(ErlNifEnv *env, int argc, if (pk.size != crypto_sign_PUBLICKEYBYTES) goto bad_arg; + enif_mutex_lock(obj->mtx); + if (!obj->alive) { + ret = enacl_error_tuple(env, "finalized"); + goto done; + } + if (0 == crypto_sign_final_verify(obj->state, sig.data, pk.data)) { ret = enif_make_atom(env, ATOM_OK); } else { @@ -210,7 +230,8 @@ cleanup: sodium_memzero(obj->state, crypto_sign_statebytes()); enif_free(obj->state); obj->state = NULL; - +done: + enif_mutex_unlock(obj->mtx); return ret; } From 2b8b6224d804174b077a29b85c1e22216f5226ec Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 24 Jan 2020 22:14:23 +0100 Subject: [PATCH 059/162] Plug some memory leaks in the public API. The problem is, like the other recent patches, about properly releasing binaries we have allocated but not given to the VM for it to use. --- CHANGELOG.md | 6 ++--- c_src/public.c | 64 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 490c006..e740418 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,9 @@ Over time, a number of bad things have snuck themselves into these bindings. Thi is a list of changes which are planned for a 1.0 release. - Plug some subtle memory leaks in API: - - Public - Secret -Under errors, the current code can leak binaries. I don't want that to happen, so we +Under failure, the current code can leak binaries. I don't want that to happen, so we are going to use a better cleanup scheme in the code base. ## [Unreleased] @@ -68,12 +67,13 @@ are going to use a better cleanup scheme in the code base. in the code base, and avoids pollution of the enif_* "namespace". - Split Sign Public Key routines from the rest. Modernize the handling of contexts. -### Fixes +### Fixed - Fix a resource leak in generichash/sign init/update/final. - Clang static analysis warnings (Thomas Arts). - Replace a constant 31 with a computation from libsodium (Thomas Arts, from a security review). - Some subtle memory leaks in the error path for kx operations were plugged. - The multi-part generichash interface is now properly process/thread safe. +- The sign interface is now properly process/thread safe. ## [0.17.2] diff --git a/c_src/public.c b/c_src/public.c index 05ae0c7..a160b35 100644 --- a/c_src/public.c +++ b/c_src/public.c @@ -36,6 +36,11 @@ ERL_NIF_TERM enacl_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc, return enif_make_int64(env, crypto_box_BEFORENMBYTES); } +ERL_NIF_TERM enacl_crypto_box_SEALBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_SEALBYTES); +} + ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary pk, sk; @@ -49,6 +54,7 @@ ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_box_SECRETKEYBYTES, &sk)) { + enif_release_binary(&pk); return enacl_error_tuple(env, "alloc_failed"); } @@ -61,34 +67,50 @@ ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary padded_msg, nonce, pk, sk, result; + ERL_NIF_TERM ret; - if ((argc != 4) || - (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg)) || - (!enif_inspect_binary(env, argv[1], &nonce)) || - (!enif_inspect_binary(env, argv[2], &pk)) || - (!enif_inspect_binary(env, argv[3], &sk))) { - return enif_make_badarg(env); - } + if (argc != 4) + goto bad_arg; + if (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &nonce)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &pk)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[3], &sk)) + goto bad_arg; - if ((nonce.size != crypto_box_NONCEBYTES) || - (pk.size != crypto_box_PUBLICKEYBYTES) || - (sk.size != crypto_box_SECRETKEYBYTES) || - (padded_msg.size < crypto_box_ZEROBYTES)) { - return enif_make_badarg(env); - } + if (nonce.size != crypto_box_NONCEBYTES) + goto bad_arg; + if (pk.size != crypto_box_PUBLICKEYBYTES) + goto bad_arg; + if (sk.size != crypto_box_SECRETKEYBYTES) + goto bad_arg; + if (padded_msg.size < crypto_box_ZEROBYTES) + goto bad_arg; if (!enif_alloc_binary(padded_msg.size, &result)) { - return enacl_error_tuple(env, "alloc_failed"); + ret = enacl_error_tuple(env, "alloc_failed"); + goto done; } if (0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data, pk.data, sk.data)) { - return enacl_error_tuple(env, "box_error"); + ret = enacl_error_tuple(env, "box_error"); + goto release; } - return enif_make_sub_binary(env, enif_make_binary(env, &result), - crypto_box_BOXZEROBYTES, - padded_msg.size - crypto_box_BOXZEROBYTES); + ret = enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_BOXZEROBYTES, + padded_msg.size - crypto_box_BOXZEROBYTES); + goto done; + +bad_arg: + return enif_make_badarg(env); +release: + enif_release_binary(&result); +done: + return ret; } ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc, @@ -145,6 +167,7 @@ ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc, if (0 != crypto_box_beforenm(k.data, pk.data, sk.data)) { // error + enif_release_binary(&k); return enacl_error_tuple(env, "error_gen_shared_secret"); } @@ -205,11 +228,6 @@ ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc, /* Sealed box functions */ -ERL_NIF_TERM enacl_crypto_box_SEALBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - return enif_make_int64(env, crypto_box_SEALBYTES); -} - ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary key, msg, ciphertext; From fc943a19c7527c6af7f2ece948b42dcc1f2882d4 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 24 Jan 2020 22:17:24 +0100 Subject: [PATCH 060/162] Go through the secret API as well --- CHANGELOG.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e740418..808b0f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,17 +5,6 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Upcoming changes] - -Over time, a number of bad things have snuck themselves into these bindings. This -is a list of changes which are planned for a 1.0 release. - -- Plug some subtle memory leaks in API: - - Secret - -Under failure, the current code can leak binaries. I don't want that to happen, so we -are going to use a better cleanup scheme in the code base. - ## [Unreleased] ### Compatibility From 8ed8663dfe3a1ce2fc37cec036cc08450a846b24 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 3 Feb 2020 14:57:42 +0100 Subject: [PATCH 061/162] Correct ietf_decrypt EQC Found a bug where parameters where incorrectly passed. The CT test suite passed, but randomized tests found an error. --- c_src/aead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c_src/aead.c b/c_src/aead.c index 055c222..997e3ac 100644 --- a/c_src/aead.c +++ b/c_src/aead.c @@ -93,7 +93,7 @@ enacl_crypto_aead_chacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc, goto bad_arg; if (!enif_inspect_binary(env, argv[2], &nonce)) goto bad_arg; - if (!enif_inspect_binary(env, argv[3], &message)) + if (!enif_inspect_binary(env, argv[3], &key)) goto bad_arg; if (ciphertext.size < crypto_aead_chacha20poly1305_ietf_ABYTES) From 2041cec2e842220387ae194e72eba84172f5cf5a Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 3 Feb 2020 14:58:52 +0100 Subject: [PATCH 062/162] Update the eqc suite. Parameter order in chacha20poly1305_ietf changed. Fix this in the EQC tests. While here, also do the Nonce changes. --- eqc_test/enacl_eqc.erl | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index b0f4859..66781bb 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -525,20 +525,22 @@ prop_secretbox_failure_integrity() -> %% ------------------------------------------------------------ %% * aead_chacha20poly1305_encrypt/4, %% * aead_chacha20poly1305_decrypt/4, -prop_aead_chacha20poly1305() -> +prop_aead_chacha20poly1305_ietf() -> + NPubBytes = enacl:aead_chacha20poly1305_ietf_NPUBBYTES(), ?FORALL({Key, Msg, AD, Nonce}, - {binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), largeint()}, + {binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), binary(NPubBytes)}, begin - EncryptMsg = enacl:aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg), - equals(enacl:aead_chacha20poly1305_decrypt(Key, Nonce, AD, EncryptMsg), Msg) + EncryptMsg = enacl:aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key), + equals(enacl:aead_chacha20poly1305_ietf_decrypt(EncryptMsg, AD, Nonce, Key), Msg) end). -prop_aead_chacha20poly1305_fail() -> +prop_aead_chacha20poly1305_ietf_fail() -> + NPubBytes = enacl:aead_chacha20poly1305_ietf_NPUBBYTES(), ?FORALL({Key, Msg, AD, Nonce}, - {binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), largeint()}, + {binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), binary(NPubBytes)}, begin - EncryptMsg = enacl:aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg), - case enacl:aead_chacha20poly1305_decrypt(Key, Nonce, AD, <<0:8, EncryptMsg/binary>>) of + EncryptMsg = enacl:aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key), + case enacl:aead_chacha20poly1305_ietf_decrypt(<<0:8, EncryptMsg/binary>>, AD, Nonce, Key) of {error, _} -> true; _ -> false end From c791f602e940ebc31b169f6b1ec07171e0b4cb80 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 4 Feb 2020 12:38:02 +0100 Subject: [PATCH 063/162] Streamline returns in the public key API --- CHANGELOG.md | 17 +++++++++++++++++ c_src/public.c | 38 +++++++++++++++++++++++++------------- eqc_test/enacl_eqc.erl | 12 ++++++------ src/enacl.erl | 28 ++++++---------------------- 4 files changed, 54 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 808b0f3..c0d569a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,26 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [TODO] + +- Go through all calls and make them return {ok, _} | {error, _} if applicable. + Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. + - AEAD + - enacl + - generichash + - hash + - kx + - public + - pwhash + - randombytes + - secret + - sign + ## [Unreleased] ### Compatibility +- Many functions returned the type `value() | {error, term()}`. They have been + updated to return the more erlang-idiomatic `{ok, value()} | {error, term()}`. - If you used `aead_chacha20poly1305_*` functions, please read through the changelog carefully as we have made changes to these functions. TL;DR: look for `aead_chacha20poly1305_ietf_*` but note it is *not* just a simple substitution diff --git a/c_src/public.c b/c_src/public.c index a160b35..cc1925b 100644 --- a/c_src/public.c +++ b/c_src/public.c @@ -100,9 +100,12 @@ ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc, goto release; } - ret = enif_make_sub_binary(env, enif_make_binary(env, &result), - crypto_box_BOXZEROBYTES, - padded_msg.size - crypto_box_BOXZEROBYTES); + ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret_bin = enif_make_sub_binary( + env, enif_make_binary(env, &result), crypto_box_BOXZEROBYTES, + padded_msg.size - crypto_box_BOXZEROBYTES); + ret = enif_make_tuple2(env, ret_ok, ret_bin); + goto done; bad_arg: @@ -143,9 +146,12 @@ ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc, return enacl_error_tuple(env, "failed_verification"); } - return enif_make_sub_binary(env, enif_make_binary(env, &result), - crypto_box_ZEROBYTES, - padded_ciphertext.size - crypto_box_ZEROBYTES); + ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret_bin = enif_make_sub_binary( + env, enif_make_binary(env, &result), crypto_box_ZEROBYTES, + padded_ciphertext.size - crypto_box_ZEROBYTES); + + return enif_make_tuple2(env, ret_ok, ret_bin); } /* Precomputed crypto boxes */ @@ -171,7 +177,9 @@ ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc, return enacl_error_tuple(env, "error_gen_shared_secret"); } - return enif_make_binary(env, &k); + ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret_bin = enif_make_binary(env, &k); + return enif_make_tuple2(env, ret_ok, ret_bin); } ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc, @@ -193,9 +201,11 @@ ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc, crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data); - return enif_make_sub_binary(env, enif_make_binary(env, &result), - crypto_box_BOXZEROBYTES, - m.size - crypto_box_BOXZEROBYTES); + ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret_bin = enif_make_sub_binary( + env, enif_make_binary(env, &result), crypto_box_BOXZEROBYTES, + m.size - crypto_box_BOXZEROBYTES); + return enif_make_tuple2(env, ret_ok, ret_bin); } ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc, @@ -221,9 +231,11 @@ ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc, return enacl_error_tuple(env, "failed_verification"); } - return enif_make_sub_binary(env, enif_make_binary(env, &result), - crypto_box_ZEROBYTES, - m.size - crypto_box_ZEROBYTES); + ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret_bin = + enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_ZEROBYTES, m.size - crypto_box_ZEROBYTES); + return enif_make_tuple2(env, ret_ok, ret_bin); } /* Sealed box functions */ diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 66781bb..2a1a9f0 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -183,10 +183,10 @@ prop_box_correct() -> begin case v_iodata(Msg) andalso nonce_valid(Nonce) andalso keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of true -> - Key = enacl:box_beforenm(PK2, SK1), - Key = enacl:box_beforenm(PK1, SK2), - CipherText = enacl:box(Msg, Nonce, PK2, SK1), - CipherText = enacl:box_afternm(Msg, Nonce, Key), + {ok, Key} = enacl:box_beforenm(PK2, SK1), + {ok, Key} = enacl:box_beforenm(PK1, SK2), + {ok, CipherText} = enacl:box(Msg, Nonce, PK2, SK1), + {ok, CipherText} = enacl:box_afternm(Msg, Nonce, Key), {ok, DecodedMsg} = enacl:box_open(CipherText, Nonce, PK1, SK2), {ok, DecodedMsg} = enacl:box_open_afternm(CipherText, Nonce, Key), equals(iolist_to_binary(Msg), DecodedMsg); @@ -210,8 +210,8 @@ prop_box_failure_integrity() -> andalso keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of true -> - Key = enacl:box_beforenm(PK2, SK1), - CipherText = enacl:box(Msg, Nonce, PK2, SK1), + {ok, Key} = enacl:box_beforenm(PK2, SK1), + {ok, CipherText} = enacl:box(Msg, Nonce, PK2, SK1), Err = enacl:box_open([<<"x">>, CipherText], Nonce, PK1, SK2), Err = enacl:box_open_afternm([<<"x">>, CipherText], Nonce, Key), equals(Err, {error, failed_verification}); diff --git a/src/enacl.erl b/src/enacl.erl index cdfd578..5a2375a 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -446,7 +446,7 @@ box_keypair() -> %% Encrypt a `Msg' to the party identified by public key `PK' using your own secret key `SK' to %% authenticate yourself. Requires a `Nonce' in addition. Returns the ciphered message. %% @end --spec box(Msg, Nonce, PK, SK) -> CipherText +-spec box(Msg, Nonce, PK, SK) -> {ok, CipherText} | {error, term()} when Msg :: iodata(), Nonce :: binary(), @@ -470,14 +470,11 @@ box(Msg, Nonce, PK, SK) -> SK :: binary(), Msg :: binary(). box_open(CipherText, Nonce, PK, SK) -> - case enacl_nif:crypto_box_open([?P_BOXZEROBYTES, CipherText], Nonce, PK, SK) of - {error, Err} -> {error, Err}; - Bin when is_binary(Bin) -> {ok, Bin} - end. + enacl_nif:crypto_box_open([?P_BOXZEROBYTES, CipherText], Nonce, PK, SK). %% @doc box_beforenm/2 precomputes a box shared key for a PK/SK keypair %% @end --spec box_beforenm(PK, SK) -> binary() +-spec box_beforenm(PK, SK) -> {ok, binary()} | {error, term()} when PK :: binary(), SK :: binary(). @@ -492,7 +489,7 @@ box_beforenm(PK, SK) -> %% if you had called `box(M, Nonce, PK, SK)'. Except that it avoids computations in the elliptic curve Curve25519, %% and thus is a much faster operation. %% @end --spec box_afternm(Msg, Nonce, K) -> CipherText +-spec box_afternm(Msg, Nonce, K) -> {ok, CipherText} | {error, term()} when Msg :: iodata(), Nonce :: binary(), @@ -522,23 +519,10 @@ box_afternm(Msg, Nonce, Key) -> box_open_afternm(CipherText, Nonce, Key) -> case iolist_size(CipherText) of K when K =< ?BOX_AFTERNM_SIZE -> - R = - case enacl_nif:crypto_box_open_afternm_b( - [?P_BOXZEROBYTES, CipherText], Nonce, Key) of - {error, Err} -> - {error, Err}; - Bin when is_binary(Bin) -> - {ok, Bin} - end, + R = enacl_nif:crypto_box_open_afternm_b([?P_BOXZEROBYTES, CipherText], Nonce, Key), bump(R, ?BOX_AFTERNM_REDUCTIONS, ?BOX_AFTERNM_SIZE, K); _ -> - case enacl_nif:crypto_box_open_afternm( - [?P_BOXZEROBYTES, CipherText], Nonce, Key) of - {error, Err} -> - {error, Err}; - Bin when is_binary(Bin) -> - {ok, Bin} - end + enacl_nif:crypto_box_open_afternm([?P_BOXZEROBYTES, CipherText], Nonce, Key) end. %% @doc box_nonce_size/0 return the byte-size of the nonce From 71832cce4c822576b40e999c9d9bd97df239bb3b Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 4 Feb 2020 12:44:47 +0100 Subject: [PATCH 064/162] Streamline sealed boxes --- CHANGELOG.md | 1 - c_src/public.c | 9 +++++++-- eqc_test/enacl_eqc.erl | 4 ++-- src/enacl.erl | 7 ++----- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d569a..a79fe7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - generichash - hash - kx - - public - pwhash - randombytes - secret diff --git a/c_src/public.c b/c_src/public.c index cc1925b..3c47bcf 100644 --- a/c_src/public.c +++ b/c_src/public.c @@ -255,7 +255,9 @@ ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc, crypto_box_seal(ciphertext.data, msg.data, msg.size, key.data); - return enif_make_binary(env, &ciphertext); + ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret_bin = enif_make_binary(env, &ciphertext); + return enif_make_tuple2(env, ret_ok, ret_bin); } ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc, @@ -283,5 +285,8 @@ ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc, return enacl_error_tuple(env, "failed_verification"); } - return enif_make_binary(env, &msg); + ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret_bin = enif_make_binary(env, &msg); + + return enif_make_tuple2(env, ret_ok, ret_bin); } diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 2a1a9f0..6a43dcf 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -431,7 +431,7 @@ prop_seal_box_failure_integrity() -> begin case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of true -> - CT = enacl:box_seal(Msg, PK1), + {ok, CT} = enacl:box_seal(Msg, PK1), Err = enacl:box_seal_open([<<"x">>, CT], PK1, SK1), equals(Err, {error, failed_verification}); false -> @@ -450,7 +450,7 @@ prop_seal_box_correct() -> begin case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of true -> - SealedCipherText = enacl:box_seal(Msg, PK1), + {ok, SealedCipherText} = enacl:box_seal(Msg, PK1), {ok, DecodedMsg} = enacl:box_seal_open(SealedCipherText, PK1, SK1), equals(iolist_to_binary(Msg), DecodedMsg); false -> diff --git a/src/enacl.erl b/src/enacl.erl index 5a2375a..037bafb 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -685,7 +685,7 @@ box_secret_key_bytes() -> %% keypair and then uses `box'. Ephemeral public key will sent to other party. Returns the %% enciphered message `SealedCipherText' which includes ephemeral public key at head. %% @end --spec box_seal(Msg, PK) -> SealedCipherText +-spec box_seal(Msg, PK) -> {ok, SealedCipherText} | {error, term()} when Msg :: iodata(), PK :: binary(), @@ -706,10 +706,7 @@ box_seal(Msg, PK) -> SK :: binary(), Msg :: binary(). box_seal_open(SealedCipherText, PK, SK) -> - case enacl_nif:crypto_box_seal_open(SealedCipherText, PK, SK) of - {error, Err} -> {error, Err}; - Bin when is_binary(Bin) -> {ok, Bin} - end. + enacl_nif:crypto_box_seal_open(SealedCipherText, PK, SK). %% @doc secretbox/3 encrypts a message with a key %% From aa2c69529a3de5bcc550e4123542796e6e10f980 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 4 Feb 2020 12:59:18 +0100 Subject: [PATCH 065/162] Streamlines generichashThe multi-part hash API is nowreflecting the same crypto modulefunctions in style. This is easierto use for people, I believe. --- CHANGELOG.md | 7 ++++++- c_src/generichash.c | 23 ++++++++++------------- src/enacl.erl | 9 ++++++++- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a79fe7e..43e395c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - AEAD - enacl - - generichash - hash - kx - pwhash @@ -19,6 +18,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - secret - sign +- Implement missing EQC tests + - Generichash + - Multi-part generic hash + ## [Unreleased] ### Compatibility @@ -71,6 +74,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed many routines from enif_* to enacl_*. This better reflects where they live in the code base, and avoids pollution of the enif_* "namespace". - Split Sign Public Key routines from the rest. Modernize the handling of contexts. +- The multi-part generic hash routines now follow the structure of the crypto + modules multi-part constructions in API and style. ### Fixed - Fix a resource leak in generichash/sign init/update/final. diff --git a/c_src/generichash.c b/c_src/generichash.c index 524def8..05794bc 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -157,8 +157,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, // Verify that hash size is valid if ((hash_size <= crypto_generichash_BYTES_MIN) || (hash_size >= crypto_generichash_BYTES_MAX)) { - ret = enacl_error_tuple(env, "invalid_hash_size"); - goto done; + goto bad_arg; } // validate key size @@ -167,8 +166,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, k = NULL; } else if (key.size <= crypto_generichash_KEYBYTES_MIN || key.size >= crypto_generichash_KEYBYTES_MAX) { - ret = enacl_error_tuple(env, "invalid_key_size"); - goto done; + goto bad_arg; } // Create the resource @@ -210,7 +208,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); err: - ret = enacl_error_tuple(env, "internal_error"); + ret = enif_make_atom(env, "notsup"); if (obj != NULL) { if (obj->alive) { sodium_free(obj->ctx); @@ -244,14 +242,12 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, enif_mutex_lock(obj->mtx); if (!obj->alive) { - ret = enacl_error_tuple(env, "finalized"); - goto done; + goto err; } // Update hash state if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) { - ret = enacl_error_tuple(env, "hash_update_error"); - goto done; + goto err; } ret = argv[0]; @@ -259,6 +255,8 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); +err: + ret = enif_make_badarg(env); done: enif_mutex_unlock(obj->mtx); return ret; @@ -278,17 +276,14 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, enif_mutex_lock(obj->mtx); if (!obj->alive) { - ret = enacl_error_tuple(env, "finalized"); - goto done; + goto err; } if (!enif_alloc_binary(obj->outlen, &hash)) { - ret = enacl_error_tuple(env, "alloc_failed"); goto done; } if (0 != crypto_generichash_final(obj->ctx, hash.data, hash.size)) { - ret = enacl_error_tuple(env, "hash_error"); goto release; } @@ -305,6 +300,8 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); +err: + ret = enif_make_badarg(env); release: enif_release_binary(&hash); done: diff --git a/src/enacl.erl b/src/enacl.erl index 037bafb..4ee0e73 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -351,16 +351,23 @@ generichash(HashSize, Message, Key) -> generichash(HashSize, Message) -> enacl_nif:crypto_generichash(HashSize, Message, <<>>). +%% @doc generichash_init/2 initializes a multi-part hash. +%% @end +-spec generichash_init(generichash_bytes(), binary()) -> reference() | notsup. generichash_init(HashSize, Key) -> enacl_nif:crypto_generichash_init(HashSize, Key). +%% @doc generichash_update/2 updates a multi-part hash with new data. +%% @end +-spec generichash_update(reference(), iodata()) -> reference(). generichash_update(State, Message) -> enacl_nif:crypto_generichash_update(State, Message). +%% @doc generichash_final/1 finalizes a multi-part hash. +-spec generichash_final(reference()) -> binary(). generichash_final(State) -> enacl_nif:crypto_generichash_final(State). - -type pwhash_limit() :: interactive | moderate | sensitive | pos_integer(). %% @doc pwhash/2 hash a password %% From 59b94439d1e118b1d7d8e3dbfced646aa8d06fcb Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 4 Feb 2020 14:00:02 +0100 Subject: [PATCH 066/162] Decide on an even better API --- CHANGELOG.md | 10 +++++++--- c_src/enacl.c | 4 ++++ c_src/enacl.h | 1 + c_src/public.c | 44 ++++++++++++++++++------------------------ c_src/randombytes.c | 2 +- eqc_test/enacl_eqc.erl | 16 +++++++-------- src/enacl.erl | 8 ++++---- 7 files changed, 44 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43e395c..614b015 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [TODO] -- Go through all calls and make them return {ok, _} | {error, _} if applicable. +- Go through all calls and make them return streamlined exceptions if applicable. Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - AEAD - enacl - hash - kx + - generichash - pwhash - randombytes - secret @@ -25,8 +26,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Compatibility -- Many functions returned the type `value() | {error, term()}`. They have been - updated to return the more erlang-idiomatic `{ok, value()} | {error, term()}`. +- Some functions have been streamlined to badarg in certain cases where it made more + sense to do so than returning back an error to the caller. +- Functions generally don't return error values for internal errors. They now raise + exceptions when this happens. If you can't allocate a binary, there is usually not + much the programmer can do with that information, sans crashing. - If you used `aead_chacha20poly1305_*` functions, please read through the changelog carefully as we have made changes to these functions. TL;DR: look for `aead_chacha20poly1305_ietf_*` but note it is *not* just a simple substitution diff --git a/c_src/enacl.c b/c_src/enacl.c index 3b39796..fa8a71b 100644 --- a/c_src/enacl.c +++ b/c_src/enacl.c @@ -6,3 +6,7 @@ ERL_NIF_TERM enacl_error_tuple(ErlNifEnv *env, char *error_atom) { return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, error_atom)); } + +ERL_NIF_TERM enacl_internal_error(ErlNifEnv *env) { + return enif_raise_exception(env, enif_make_atom(env, "internal_error")); +} \ No newline at end of file diff --git a/c_src/enacl.h b/c_src/enacl.h index e772d1d..3dc3a59 100644 --- a/c_src/enacl.h +++ b/c_src/enacl.h @@ -9,5 +9,6 @@ #define ATOM_FALSE "false" ERL_NIF_TERM enacl_error_tuple(ErlNifEnv *, char *); +ERL_NIF_TERM enacl_internal_error(ErlNifEnv *); #endif diff --git a/c_src/public.c b/c_src/public.c index 3c47bcf..f2113a8 100644 --- a/c_src/public.c +++ b/c_src/public.c @@ -90,21 +90,17 @@ ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc, goto bad_arg; if (!enif_alloc_binary(padded_msg.size, &result)) { - ret = enacl_error_tuple(env, "alloc_failed"); goto done; } if (0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data, pk.data, sk.data)) { - ret = enacl_error_tuple(env, "box_error"); goto release; } - ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret_bin = enif_make_sub_binary( - env, enif_make_binary(env, &result), crypto_box_BOXZEROBYTES, - padded_msg.size - crypto_box_BOXZEROBYTES); - ret = enif_make_tuple2(env, ret_ok, ret_bin); + ret = enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_BOXZEROBYTES, + padded_msg.size - crypto_box_BOXZEROBYTES); goto done; @@ -112,6 +108,8 @@ bad_arg: return enif_make_badarg(env); release: enif_release_binary(&result); +err: + ret = enacl_internal_error(env); done: return ret; } @@ -136,7 +134,7 @@ ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(padded_ciphertext.size, &result)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } if (0 != crypto_box_open(result.data, padded_ciphertext.data, @@ -168,18 +166,18 @@ ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_box_BEFORENMBYTES, &k)) { - return enacl_error_tuple(env, "alloc_failed"); + goto err; } if (0 != crypto_box_beforenm(k.data, pk.data, sk.data)) { // error enif_release_binary(&k); - return enacl_error_tuple(env, "error_gen_shared_secret"); + goto err; } - ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret_bin = enif_make_binary(env, &k); - return enif_make_tuple2(env, ret_ok, ret_bin); + return enif_make_binary(env, &k); +err: + return enacl_internal_error(env); } ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc, @@ -196,16 +194,14 @@ ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size, &result)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data); - ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret_bin = enif_make_sub_binary( - env, enif_make_binary(env, &result), crypto_box_BOXZEROBYTES, - m.size - crypto_box_BOXZEROBYTES); - return enif_make_tuple2(env, ret_ok, ret_bin); + return enif_make_sub_binary(env, enif_make_binary(env, &result), + crypto_box_BOXZEROBYTES, + m.size - crypto_box_BOXZEROBYTES); } ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc, @@ -222,7 +218,7 @@ ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size, &result)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } if (0 != crypto_box_open_afternm(result.data, m.data, m.size, nonce.data, @@ -250,14 +246,12 @@ ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(msg.size + crypto_box_SEALBYTES, &ciphertext)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_box_seal(ciphertext.data, msg.data, msg.size, key.data); - ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret_bin = enif_make_binary(env, &ciphertext); - return enif_make_tuple2(env, ret_ok, ret_bin); + return enif_make_binary(env, &ciphertext); } ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc, @@ -276,7 +270,7 @@ ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(ciphertext.size - crypto_box_SEALBYTES, &msg)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } if (crypto_box_seal_open(msg.data, ciphertext.data, ciphertext.size, pk.data, diff --git a/c_src/randombytes.c b/c_src/randombytes.c index 5c978a8..209f5b7 100644 --- a/c_src/randombytes.c +++ b/c_src/randombytes.c @@ -15,7 +15,7 @@ ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(req_size, &result)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } randombytes(result.data, result.size); diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 6a43dcf..66781bb 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -183,10 +183,10 @@ prop_box_correct() -> begin case v_iodata(Msg) andalso nonce_valid(Nonce) andalso keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of true -> - {ok, Key} = enacl:box_beforenm(PK2, SK1), - {ok, Key} = enacl:box_beforenm(PK1, SK2), - {ok, CipherText} = enacl:box(Msg, Nonce, PK2, SK1), - {ok, CipherText} = enacl:box_afternm(Msg, Nonce, Key), + Key = enacl:box_beforenm(PK2, SK1), + Key = enacl:box_beforenm(PK1, SK2), + CipherText = enacl:box(Msg, Nonce, PK2, SK1), + CipherText = enacl:box_afternm(Msg, Nonce, Key), {ok, DecodedMsg} = enacl:box_open(CipherText, Nonce, PK1, SK2), {ok, DecodedMsg} = enacl:box_open_afternm(CipherText, Nonce, Key), equals(iolist_to_binary(Msg), DecodedMsg); @@ -210,8 +210,8 @@ prop_box_failure_integrity() -> andalso keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of true -> - {ok, Key} = enacl:box_beforenm(PK2, SK1), - {ok, CipherText} = enacl:box(Msg, Nonce, PK2, SK1), + Key = enacl:box_beforenm(PK2, SK1), + CipherText = enacl:box(Msg, Nonce, PK2, SK1), Err = enacl:box_open([<<"x">>, CipherText], Nonce, PK1, SK2), Err = enacl:box_open_afternm([<<"x">>, CipherText], Nonce, Key), equals(Err, {error, failed_verification}); @@ -431,7 +431,7 @@ prop_seal_box_failure_integrity() -> begin case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of true -> - {ok, CT} = enacl:box_seal(Msg, PK1), + CT = enacl:box_seal(Msg, PK1), Err = enacl:box_seal_open([<<"x">>, CT], PK1, SK1), equals(Err, {error, failed_verification}); false -> @@ -450,7 +450,7 @@ prop_seal_box_correct() -> begin case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of true -> - {ok, SealedCipherText} = enacl:box_seal(Msg, PK1), + SealedCipherText = enacl:box_seal(Msg, PK1), {ok, DecodedMsg} = enacl:box_seal_open(SealedCipherText, PK1, SK1), equals(iolist_to_binary(Msg), DecodedMsg); false -> diff --git a/src/enacl.erl b/src/enacl.erl index 4ee0e73..f54eeaa 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -453,7 +453,7 @@ box_keypair() -> %% Encrypt a `Msg' to the party identified by public key `PK' using your own secret key `SK' to %% authenticate yourself. Requires a `Nonce' in addition. Returns the ciphered message. %% @end --spec box(Msg, Nonce, PK, SK) -> {ok, CipherText} | {error, term()} +-spec box(Msg, Nonce, PK, SK) -> CipherText when Msg :: iodata(), Nonce :: binary(), @@ -481,7 +481,7 @@ box_open(CipherText, Nonce, PK, SK) -> %% @doc box_beforenm/2 precomputes a box shared key for a PK/SK keypair %% @end --spec box_beforenm(PK, SK) -> {ok, binary()} | {error, term()} +-spec box_beforenm(PK, SK) -> binary() when PK :: binary(), SK :: binary(). @@ -496,7 +496,7 @@ box_beforenm(PK, SK) -> %% if you had called `box(M, Nonce, PK, SK)'. Except that it avoids computations in the elliptic curve Curve25519, %% and thus is a much faster operation. %% @end --spec box_afternm(Msg, Nonce, K) -> {ok, CipherText} | {error, term()} +-spec box_afternm(Msg, Nonce, K) -> CipherText when Msg :: iodata(), Nonce :: binary(), @@ -692,7 +692,7 @@ box_secret_key_bytes() -> %% keypair and then uses `box'. Ephemeral public key will sent to other party. Returns the %% enciphered message `SealedCipherText' which includes ephemeral public key at head. %% @end --spec box_seal(Msg, PK) -> {ok, SealedCipherText} | {error, term()} +-spec box_seal(Msg, PK) -> SealedCipherText when Msg :: iodata(), PK :: binary(), From b637ba307b224052ab378b596674ad280b81a9dc Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 4 Feb 2020 17:50:56 +0100 Subject: [PATCH 067/162] Streamline generichash and pwhash --- CHANGELOG.md | 6 +++--- c_src/generichash.c | 34 +++++++++++++--------------------- c_src/pwhash.c | 20 +++++++------------- eqc_test/enacl_eqc.erl | 2 +- src/enacl.erl | 21 ++++++++------------- test/enacl_SUITE.erl | 16 ++++++++-------- 6 files changed, 40 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 614b015..dac3c6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,18 +10,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Go through all calls and make them return streamlined exceptions if applicable. Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - AEAD - - enacl - hash - kx - - generichash - - pwhash - randombytes - secret - sign + - enacl_nif - Implement missing EQC tests - Generichash - Multi-part generic hash + - pwhash + - Extend with limit for ops and memory as well. ## [Unreleased] diff --git a/c_src/generichash.c b/c_src/generichash.c index 05794bc..4da2c80 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -98,8 +98,7 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX if ((hash_size <= crypto_generichash_BYTES_MIN) || (hash_size >= crypto_generichash_BYTES_MAX)) { - ret = enacl_error_tuple(env, "invalid_hash_size"); - goto done; + goto bad_arg; } // validate key size @@ -108,33 +107,29 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, k = NULL; } else if (key.size <= crypto_generichash_KEYBYTES_MIN || key.size >= crypto_generichash_KEYBYTES_MAX) { - ret = enacl_error_tuple(env, "invalid_key_size"); - goto done; + goto bad_arg; } // allocate memory for hash if (!enif_alloc_binary(hash_size, &hash)) { - ret = enacl_error_tuple(env, "alloc_failed"); - goto done; + goto err; } // calculate hash if (0 != crypto_generichash(hash.data, hash.size, message.data, message.size, k, key.size)) { - ret = enacl_error_tuple(env, "hash_error"); goto release; } - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret_hash = enif_make_binary(env, &hash); - - ret = enif_make_tuple2(env, ok, ret_hash); + ret = enif_make_binary(env, &hash); goto done; bad_arg: return enif_make_badarg(env); release: enif_release_binary(&hash); +err: + ret = enacl_internal_error(env); done: return ret; } @@ -208,7 +203,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); err: - ret = enif_make_atom(env, "notsup"); + ret = enacl_internal_error(env); if (obj != NULL) { if (obj->alive) { sodium_free(obj->ctx); @@ -256,7 +251,7 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); err: - ret = enif_make_badarg(env); + ret = enacl_internal_error(env); done: enif_mutex_unlock(obj->mtx); return ret; @@ -276,11 +271,11 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, enif_mutex_lock(obj->mtx); if (!obj->alive) { - goto err; + goto bad_arg; } if (!enif_alloc_binary(obj->outlen, &hash)) { - goto done; + goto err; } if (0 != crypto_generichash_final(obj->ctx, hash.data, hash.size)) { @@ -292,18 +287,15 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, sodium_free(obj->ctx); obj->alive = 0; - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM h = enif_make_binary(env, &hash); - - ret = enif_make_tuple2(env, ok, h); + ret = enif_make_binary(env, &hash); goto done; bad_arg: return enif_make_badarg(env); -err: - ret = enif_make_badarg(env); release: enif_release_binary(&hash); +err: + ret = enif_make_badarg(env); done: enif_mutex_unlock(obj->mtx); return ret; diff --git a/c_src/pwhash.c b/c_src/pwhash.c index be5df5d..be74851 100644 --- a/c_src/pwhash.c +++ b/c_src/pwhash.c @@ -78,25 +78,22 @@ ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, // Check Salt size if (s.size != crypto_pwhash_SALTBYTES) { - return enacl_error_tuple(env, "invalid_salt_size"); + return enif_make_badarg(env); } // Allocate memory for return binary if (!enif_alloc_binary(crypto_box_SEEDBYTES, &h)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } if (crypto_pwhash(h.data, h.size, (char *)p.data, p.size, s.data, o, m, crypto_pwhash_ALG_DEFAULT) != 0) { /* out of memory */ enif_release_binary(&h); - return enacl_error_tuple(env, "out_of_memory"); + return enacl_internal_error(env); } - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret = enif_make_binary(env, &h); - - return enif_make_tuple2(env, ok, ret); + return enif_make_binary(env, &h); } ERL_NIF_TERM enacl_crypto_pwhash_str(ErlNifEnv *env, int argc, @@ -119,19 +116,16 @@ ERL_NIF_TERM enacl_crypto_pwhash_str(ErlNifEnv *env, int argc, // Allocate memory for return binary if (!enif_alloc_binary(crypto_pwhash_STRBYTES, &h)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } if (crypto_pwhash_str((char *)h.data, (char *)p.data, p.size, o, m) != 0) { /* out of memory */ enif_release_binary(&h); - return enacl_error_tuple(env, "out_of_memory"); + return enacl_internal_error(env); } - ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); - ERL_NIF_TERM ret = enif_make_binary(env, &h); - - return enif_make_tuple2(env, ok, ret); + return enif_make_binary(env, &h); } ERL_NIF_TERM enacl_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 66781bb..bef5da2 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -726,7 +726,7 @@ prop_pwhash_str_verify() -> begin case v_iodata(Passwd) of true -> - {ok, Ascii} = enacl:pwhash_str(Passwd), + Ascii = enacl:pwhash_str(Passwd), S = enacl:pwhash_str_verify(Ascii, Passwd), equals(S, true); false -> diff --git a/src/enacl.erl b/src/enacl.erl index f54eeaa..658472c 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -338,7 +338,7 @@ unsafe_memzero(_) -> %% either 16, 32 or 64 bytes %% @end -type generichash_bytes() :: 10..64. --spec generichash(generichash_bytes(), iodata(), binary()) -> {ok, binary()} | {error, term()}. +-spec generichash(generichash_bytes(), iodata(), binary()) -> binary(). generichash(HashSize, Message, Key) -> enacl_nif:crypto_generichash(HashSize, Message, Key). @@ -347,13 +347,13 @@ generichash(HashSize, Message, Key) -> %% This function generates a hash of the message. The hash size is %% either 16, 32 or 64 bytes %% @end --spec generichash(generichash_bytes(), iodata()) -> {ok, binary()} | {error, term()}. +-spec generichash(generichash_bytes(), iodata()) -> binary(). generichash(HashSize, Message) -> enacl_nif:crypto_generichash(HashSize, Message, <<>>). %% @doc generichash_init/2 initializes a multi-part hash. %% @end --spec generichash_init(generichash_bytes(), binary()) -> reference() | notsup. +-spec generichash_init(generichash_bytes(), binary()) -> reference(). generichash_init(HashSize, Key) -> enacl_nif:crypto_generichash_init(HashSize, Key). @@ -374,7 +374,7 @@ generichash_final(State) -> %% This function generates a fixed size salted hash of a user defined password. %% Defaults to interactive/interactive limits. %% @end --spec pwhash(iodata(), binary()) -> {ok, binary()} | {error, term()}. +-spec pwhash(iodata(), binary()) -> binary(). pwhash(Password, Salt) -> pwhash(Password, Salt, interactive, interactive). @@ -383,7 +383,7 @@ pwhash(Password, Salt) -> %% This function generates a fixed size salted hash of a user defined password given Ops and Mem %% limits. %% @end --spec pwhash(Password, Salt, Ops, Mem) -> {ok, binary()} | {error, term()} +-spec pwhash(Password, Salt, Ops, Mem) -> binary() when Password :: iodata(), Salt :: binary(), @@ -397,7 +397,7 @@ pwhash(Password, Salt, Ops, Mem) -> %% This function generates a fixed size, salted, ASCII encoded hash of a user defined password. %% Defaults to interactive/interactive limits. %% @end --spec pwhash_str(iodata()) -> {ok, iodata()} | {error, term()}. +-spec pwhash_str(iodata()) -> iodata(). pwhash_str(Password) -> pwhash_str(Password, interactive, interactive). @@ -406,18 +406,13 @@ pwhash_str(Password) -> %% This function generates a fixed size, salted, ASCII encoded hash of a user defined password %% given Ops and Mem limits. %% @end --spec pwhash_str(Password, Ops, Mem) -> {ok, iodata()} | {error, term()} +-spec pwhash_str(Password, Ops, Mem) -> iodata() when Password :: iodata(), Ops :: pwhash_limit(), Mem :: pwhash_limit(). pwhash_str(Password, Ops, Mem) -> - case enacl_nif:crypto_pwhash_str(Password, Ops, Mem) of - {ok, ASCII} -> - {ok, strip_null_terminate(ASCII)}; - {error, Reason} -> - {error, Reason} - end. + strip_null_terminate(enacl_nif:crypto_pwhash_str(Password, Ops, Mem)). strip_null_terminate(Binary) -> [X, _] = binary:split(Binary, <<0>>), diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index d36ba83..dec7371 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -59,9 +59,9 @@ generichash_basic_neg(_Config) -> "I've watched C-beams glitter in the dark near the Tannhäuser Gate. " "All those... moments... will be lost... in time, like... tears... in rain">>, Key = <<"Hash Key 123456789">>, - {error, invalid_hash_size} = enacl:generichash(9, Msg, Key), - {error, invalid_hash_size} = enacl:generichash(65, Msg, Key), - {error, invalid_key_size} = enacl:generichash(32, Msg, <<"Small">>), + {'EXIT', {badarg, _}} = (catch enacl:generichash(9, Msg, Key)), + {'EXIT', {badarg, _}} = (catch enacl:generichash(65, Msg, Key)), + {'EXIT', {badarg, _}} = (catch enacl:generichash(32, Msg, <<"Small">>)), ok. generichash_basic_pos(_Config) -> @@ -69,8 +69,8 @@ generichash_basic_pos(_Config) -> "I've watched C-beams glitter in the dark near the Tannhäuser Gate. " "All those... moments... will be lost... in time, like... tears... in rain">>, Key = <<"Hash Key 123456789">>, - {ok,<<189,104,45,187,170,229,212,4,121,43,137,74,241,173,181,77, - 67,211,133,70,196,6,128,97>>} = enacl:generichash(24, Msg, Key), + <<189,104,45,187,170,229,212,4,121,43,137,74,241,173,181,77, + 67,211,133,70,196,6,128,97>> = enacl:generichash(24, Msg, Key), ok. generichash_chunked(_Config) -> @@ -82,7 +82,7 @@ generichash_chunked(_Config) -> State = generichash_chunked(State, Msg, 10000), Expected = <<46,49,32,18,13,186,182,105,106,122,253,139,89,176,169,141, 73,93,99,6,41,216,110,41>>, - {ok, Expected} = enacl:generichash_final(State), + Expected = enacl:generichash_final(State), ok. generichash_chunked(State, _Msg, 0) -> State; @@ -119,8 +119,8 @@ pwhash(_Config) -> Salt = <<"1234567890abcdef">>, Hash1 = <<164,75,127,151,168,101,55,77,48,77,240,204,64,20,43,23,88, 18,133,11,53,151,2,113,232,95,84,165,50,7,60,20>>, - {ok, Hash1} = enacl:pwhash(PW, Salt), - {ok, Str1} = enacl:pwhash_str(PW), + Hash1 = enacl:pwhash(PW, Salt), + Str1 = enacl:pwhash_str(PW), true = enacl:pwhash_str_verify(Str1, PW), false = enacl:pwhash_str_verify(Str1, <>), ok. From c7720e6ab845faa8f66259f4b8dac00be0a240b0 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 5 Feb 2020 10:56:18 +0100 Subject: [PATCH 068/162] Streamline the AEAD API --- CHANGELOG.md | 1 - c_src/aead.c | 46 +++++++++++++++++------------------------- eqc_test/enacl_eqc.erl | 23 +++++++++++++++++++++ src/enacl.erl | 4 ++-- 4 files changed, 43 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dac3c6f..3edd931 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Go through all calls and make them return streamlined exceptions if applicable. Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - - AEAD - hash - kx - randombytes diff --git a/c_src/aead.c b/c_src/aead.c index 997e3ac..75851fd 100644 --- a/c_src/aead.c +++ b/c_src/aead.c @@ -57,24 +57,20 @@ enacl_crypto_aead_chacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc, if (!enif_alloc_binary(message.size + crypto_aead_chacha20poly1305_ietf_ABYTES, &ciphertext)) { - ret = enacl_error_tuple(env, "alloc_failed"); - goto done; + goto err; } - if (crypto_aead_chacha20poly1305_ietf_encrypt( - ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, - NULL, nonce.data, key.data) < 0) { - ret = enacl_error_tuple(env, "aead_chacha20poly1305_ietf_encrypt_failed"); - goto release; - } + crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext.data, NULL, message.data, + message.size, ad.data, ad.size, + NULL, nonce.data, key.data); ret = enif_make_binary(env, &ciphertext); goto done; bad_arg: return enif_make_badarg(env); -release: - enif_release_binary(&ciphertext); +err: + ret = enacl_internal_error(env); done: return ret; } @@ -106,14 +102,13 @@ enacl_crypto_aead_chacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc, if (!enif_alloc_binary(ciphertext.size - crypto_aead_chacha20poly1305_ietf_ABYTES, &message)) { - ret = enacl_error_tuple(env, "alloc_failed"); - goto done; + return enacl_internal_error(env); } if (crypto_aead_chacha20poly1305_ietf_decrypt( message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, - ad.size, nonce.data, key.data) < 0) { - ret = enacl_error_tuple(env, "aead_chacha20poly1305_ietf_decrypt_failed"); + ad.size, nonce.data, key.data) != 0) { + ret = enacl_error_tuple(env, "failed_verification"); goto release; } @@ -180,24 +175,20 @@ enacl_crypto_aead_xchacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc, if (!enif_alloc_binary(message.size + crypto_aead_xchacha20poly1305_ietf_ABYTES, &ciphertext)) { - ret = enacl_error_tuple(env, "alloc_failed"); - goto done; + goto err; } - if (crypto_aead_xchacha20poly1305_ietf_encrypt( - ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, - NULL, nonce.data, key.data) < 0) { - ret = enacl_error_tuple(env, "aead_xchacha20poly1305_ietf_encrypt_failed"); - goto release; - } + crypto_aead_xchacha20poly1305_ietf_encrypt( + ciphertext.data, NULL, message.data, message.size, ad.data, ad.size, NULL, + nonce.data, key.data); ret = enif_make_binary(env, &ciphertext); goto done; bad_arg: return enif_make_badarg(env); -release: - enif_release_binary(&ciphertext); +err: + ret = enacl_internal_error(env); done: return ret; } @@ -229,14 +220,13 @@ enacl_crypto_aead_xchacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc, if (!enif_alloc_binary(ciphertext.size - crypto_aead_xchacha20poly1305_ietf_ABYTES, &message)) { - ret = enacl_error_tuple(env, "alloc_failed"); - goto done; + return enacl_internal_error(env); } if (crypto_aead_xchacha20poly1305_ietf_decrypt( message.data, NULL, NULL, ciphertext.data, ciphertext.size, ad.data, - ad.size, nonce.data, key.data) < 0) { - ret = enacl_error_tuple(env, "aead_xchacha20poly1305_ietf_decrypt_failed"); + ad.size, nonce.data, key.data) != 0) { + ret = enacl_error_tuple(env, "failed_verification"); goto release; } diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index bef5da2..4a9640a 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -546,6 +546,29 @@ prop_aead_chacha20poly1305_ietf_fail() -> end end). +%% * aead_xchacha20poly1305_encrypt/4, +%% * aead_xchacha20poly1305_decrypt/4, +prop_aead_xchacha20poly1305_ietf() -> + NPubBytes = enacl:aead_xchacha20poly1305_ietf_NPUBBYTES(), + ?FORALL({Key, Msg, AD, Nonce}, + {binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), binary(NPubBytes)}, + begin + EncryptMsg = enacl:aead_xchacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key), + equals(enacl:aead_xchacha20poly1305_ietf_decrypt(EncryptMsg, AD, Nonce, Key), Msg) + end). + +prop_aead_xchacha20poly1305_ietf_fail() -> + NPubBytes = enacl:aead_xchacha20poly1305_ietf_NPUBBYTES(), + ?FORALL({Key, Msg, AD, Nonce}, + {binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), binary(NPubBytes)}, + begin + EncryptMsg = enacl:aead_xchacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key), + case enacl:aead_xchacha20poly1305_ietf_decrypt(<<0:8, EncryptMsg/binary>>, AD, Nonce, Key) of + {error, _} -> true; + _ -> false + end + end). + %% CRYPTO STREAM %% ------------------------------------------------------------ %% * stream/3 diff --git a/src/enacl.erl b/src/enacl.erl index 658472c..d618fae 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -1152,7 +1152,7 @@ kx_secret_key_size() -> %% `AD' using `Key' and `Nonce'. Returns the encrypted message followed by %% `aead_chacha20poly1305_ABYTES/0' bytes of MAC. %% @end --spec aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) -> binary() | {error, term()} +-spec aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) -> binary() when Key :: binary(), Nonce :: binary(), AD :: binary(), @@ -1207,7 +1207,7 @@ aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX() -> %% `AD' using `Key' and `Nonce'. Returns the encrypted message followed by %% `aead_xchacha20poly1305_ABYTES/0' bytes of MAC. %% @end --spec aead_xchacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) -> binary() | {error, term()} +-spec aead_xchacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) -> binary() when Key :: binary(), Nonce :: binary(), AD :: binary(), From d06fff489dc360b2fc13110095675c267a8c8dc7 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 5 Feb 2020 11:16:56 +0100 Subject: [PATCH 069/162] QuickCheck for randombytes There are some new randombytes functions. Implement these as EQC properties. --- CHANGELOG.md | 4 ++-- c_src/hash.c | 6 +++--- eqc_test/enacl_eqc.erl | 29 ++++++++++++++++++++++++++++- src/enacl.erl | 4 ++++ test/enacl_SUITE.erl | 3 ++- 5 files changed, 39 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3edd931..f8794ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Go through all calls and make them return streamlined exceptions if applicable. Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - - hash - kx - - randombytes - secret - sign - enacl_nif @@ -79,6 +77,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Split Sign Public Key routines from the rest. Modernize the handling of contexts. - The multi-part generic hash routines now follow the structure of the crypto modules multi-part constructions in API and style. +- The AEAD constructions have been streamlined so they follow the rules of libsodium + closer than before. In particular, some dead code has been removed as a result. ### Fixed - Fix a resource leak in generichash/sign init/update/final. diff --git a/c_src/hash.c b/c_src/hash.c index 5820a24..84bcded 100644 --- a/c_src/hash.c +++ b/c_src/hash.c @@ -2,6 +2,7 @@ #include +#include "enacl.h" #include "hash.h" ERL_NIF_TERM enacl_crypto_shorthash_BYTES(ErlNifEnv *env, int argc, @@ -28,7 +29,7 @@ ERL_NIF_TERM enacl_crypto_shorthash(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_shorthash_BYTES, &a)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_shorthash(a.data, m.data, m.size, k.data); @@ -54,9 +55,8 @@ ERL_NIF_TERM enacl_crypto_hash(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); - err: - ret = enacl_error_tuple(env, "alloc_failed"); + ret = enacl_internal_error(env); done: return ret; } diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 4a9640a..7eb1486 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -783,6 +783,25 @@ prop_crypto_hash_neq() -> enacl:hash(X) /= enacl:hash(Y) ). +prop_crypto_shorthash_eq() -> + ?FORALL(X, g_iodata(), + case v_iodata(X) of + true -> equals(enacl:hash(X), enacl:hash(X)); + false -> + try + enacl:hash(X), + false + catch + error:badarg -> true + end + end + ). + +prop_crypto_shorthash_neq() -> + ?FORALL({X, Y}, diff_pair(), + enacl:hash(X) /= enacl:hash(Y) + ). + %% STRING COMPARISON %% ------------------------- %% * verify_16/2, @@ -842,7 +861,8 @@ prop_randombytes() -> ?FORALL(X, g_nat(), case is_nat(X) of true -> - is_binary(enacl:randombytes(X)); + R = enacl:randombytes(X), + is_binary(R) andalso (byte_size(R) == X); false -> try enacl:randombytes(X), @@ -853,6 +873,13 @@ prop_randombytes() -> end end). +prop_randombytes_uint32() -> + ?FORALL(_, return(x), + begin + V = enacl:randombytes_uint32(), + is_integer(V) + end). + %% SCRAMBLING prop_scramble_block() -> ?FORALL({Block, Key}, {binary(16), eqc_gen:largebinary(32)}, diff --git a/src/enacl.erl b/src/enacl.erl index d618fae..2c81178 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -953,6 +953,10 @@ shorthash_size() -> %% %% Given a `Msg' and a `Key' produce a MAC/Authenticator for that message. The key can be reused for several such Msg/Authenticator pairs. %% An eavesdropper will not learn anything extra about the message structure. +%% +%% The intended use is to generate a random key and use it as a hash table or bloom filter function. +%% This avoids an enemy their ability to predict where a collision would occur in the data structure, +%% since they don't know the key. %% @end -spec shorthash(Msg, Key) -> Authenticator when diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index dec7371..a5633bd 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -44,7 +44,8 @@ groups() -> aead_chacha20poly1305_ietf, pwhash, sign, - kx]}, + kx, + randombytes]}, [Neg, Pos]. From 78621356ecd3624dd1cbab25f5b5698be56a40cf Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 5 Feb 2020 12:08:28 +0100 Subject: [PATCH 070/162] Split extension functions away --- c_src/enacl_ext.c | 86 ++++++++++++++++++++++++++++++++++++++++++++ c_src/enacl_ext.h | 9 +++++ c_src/enacl_nif.c | 91 ++++------------------------------------------- 3 files changed, 102 insertions(+), 84 deletions(-) create mode 100644 c_src/enacl_ext.c create mode 100644 c_src/enacl_ext.h diff --git a/c_src/enacl_ext.c b/c_src/enacl_ext.c new file mode 100644 index 0000000..44cc4ef --- /dev/null +++ b/c_src/enacl_ext.c @@ -0,0 +1,86 @@ +#include + +#include + +#include "enacl.h" +#include "enacl_ext.h" + +static void uint64_pack(unsigned char *y, ErlNifUInt64 x) { + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; + x >>= 8; + *y++ = x; +} + +static ErlNifUInt64 uint64_unpack(const unsigned char *x) { + ErlNifUInt64 result; + + result = x[7]; + result <<= 8; + result |= x[6]; + result <<= 8; + result |= x[5]; + result <<= 8; + result |= x[4]; + result <<= 8; + result |= x[3]; + result <<= 8; + result |= x[2]; + result <<= 8; + result |= x[1]; + result <<= 8; + result |= x[0]; + return result; +} + +static int crypto_block(unsigned char *out, const unsigned char *in, + const unsigned char *k) { + ErlNifUInt64 v0 = uint64_unpack(in + 0); + ErlNifUInt64 v1 = uint64_unpack(in + 8); + ErlNifUInt64 k0 = uint64_unpack(k + 0); + ErlNifUInt64 k1 = uint64_unpack(k + 8); + ErlNifUInt64 k2 = uint64_unpack(k + 16); + ErlNifUInt64 k3 = uint64_unpack(k + 24); + ErlNifUInt64 sum = 0; + ErlNifUInt64 delta = 0x9e3779b97f4a7c15; + int i; + for (i = 0; i < 32; ++i) { + sum += delta; + v0 += ((v1 << 7) + k0) ^ (v1 + sum) ^ ((v1 >> 12) + k1); + v1 += ((v0 << 16) + k2) ^ (v0 + sum) ^ ((v0 >> 8) + k3); + } + uint64_pack(out + 0, v0); + uint64_pack(out + 8, v1); + + return 0; +} + +ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary in, out, key; + + if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &in)) || + (!enif_inspect_binary(env, argv[1], &key)) || (in.size != 16) || + (key.size != 32)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(in.size, &out)) { + return enacl_error_tuple(env, "alloc_failed"); + } + + crypto_block(out.data, in.data, key.data); + + return enif_make_binary(env, &out); +} \ No newline at end of file diff --git a/c_src/enacl_ext.h b/c_src/enacl_ext.h new file mode 100644 index 0000000..c0e5a5a --- /dev/null +++ b/c_src/enacl_ext.h @@ -0,0 +1,9 @@ +#ifndef ENACL_EXT_H +#define ENACL_EXT_H + +#include + +ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +#endif diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 1e47712..acf1ba6 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -5,6 +5,7 @@ #include "aead.h" #include "enacl.h" +#include "enacl_ext.h" #include "generichash.h" #include "hash.h" #include "kx.h" @@ -121,11 +122,12 @@ enacl_crypto_curve25519_scalarmult(ErlNifEnv *env, int argc, do { if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) { - result = enacl_error_tuple(env, "alloc_failed"); + result = enacl_internal_error(env); continue; } - if (crypto_scalarmult_curve25519(output.data, secret.data, bp) < 0) { + if (crypto_scalarmult_curve25519(output.data, secret.data, bp) != 0) { + enif_release_binary(&output); result = enacl_error_tuple(env, "scalarmult_curve25519_failed"); continue; } @@ -151,11 +153,12 @@ enacl_crypto_curve25519_scalarmult_base(ErlNifEnv *env, int argc, do { if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) { - result = enacl_error_tuple(env, "alloc_failed"); + result = enacl_internal_error(env); continue; } - if (crypto_scalarmult_curve25519_base(output.data, secret.data) < 0) { + if (crypto_scalarmult_curve25519_base(output.data, secret.data) != 0) { + enif_release_binary(&output); result = enacl_error_tuple(env, "scalarmult_curve25519_base_failed"); continue; } @@ -166,86 +169,6 @@ enacl_crypto_curve25519_scalarmult_base(ErlNifEnv *env, int argc, return result; } -/* Various other helper functions */ -static void uint64_pack(unsigned char *y, ErlNifUInt64 x) { - *y++ = x; - x >>= 8; - *y++ = x; - x >>= 8; - *y++ = x; - x >>= 8; - *y++ = x; - x >>= 8; - *y++ = x; - x >>= 8; - *y++ = x; - x >>= 8; - *y++ = x; - x >>= 8; - *y++ = x; -} - -static ErlNifUInt64 uint64_unpack(const unsigned char *x) { - ErlNifUInt64 result; - - result = x[7]; - result <<= 8; - result |= x[6]; - result <<= 8; - result |= x[5]; - result <<= 8; - result |= x[4]; - result <<= 8; - result |= x[3]; - result <<= 8; - result |= x[2]; - result <<= 8; - result |= x[1]; - result <<= 8; - result |= x[0]; - return result; -} -static int crypto_block(unsigned char *out, const unsigned char *in, - const unsigned char *k) { - ErlNifUInt64 v0 = uint64_unpack(in + 0); - ErlNifUInt64 v1 = uint64_unpack(in + 8); - ErlNifUInt64 k0 = uint64_unpack(k + 0); - ErlNifUInt64 k1 = uint64_unpack(k + 8); - ErlNifUInt64 k2 = uint64_unpack(k + 16); - ErlNifUInt64 k3 = uint64_unpack(k + 24); - ErlNifUInt64 sum = 0; - ErlNifUInt64 delta = 0x9e3779b97f4a7c15; - int i; - for (i = 0; i < 32; ++i) { - sum += delta; - v0 += ((v1 << 7) + k0) ^ (v1 + sum) ^ ((v1 >> 12) + k1); - v1 += ((v0 << 16) + k2) ^ (v0 + sum) ^ ((v0 >> 8) + k3); - } - uint64_pack(out + 0, v0); - uint64_pack(out + 8, v1); - - return 0; -} - -static ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { - ErlNifBinary in, out, key; - - if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &in)) || - (!enif_inspect_binary(env, argv[1], &key)) || (in.size != 16) || - (key.size != 32)) { - return enif_make_badarg(env); - } - - if (!enif_alloc_binary(in.size, &out)) { - return enacl_error_tuple(env, "alloc_failed"); - } - - crypto_block(out.data, in.data, key.data); - - return enif_make_binary(env, &out); -} - /* Tie the knot to the Erlang world */ static ErlNifFunc nif_funcs[] = { {"crypto_box_NONCEBYTES", 0, enacl_crypto_box_NONCEBYTES}, From c26aeee41375a51961d630b68358a46af903f241 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 5 Feb 2020 12:10:02 +0100 Subject: [PATCH 071/162] Use an exit condition --- c_src/enacl_ext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c_src/enacl_ext.c b/c_src/enacl_ext.c index 44cc4ef..167b784 100644 --- a/c_src/enacl_ext.c +++ b/c_src/enacl_ext.c @@ -77,7 +77,7 @@ ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(in.size, &out)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_block(out.data, in.data, key.data); From 5d245797d2b61a8281e9f11753b5380ab0dfd1ff Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 5 Feb 2020 13:15:54 +0100 Subject: [PATCH 072/162] Parallelize the ext tests --- eqc_test/enacl_ext_eqc.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eqc_test/enacl_ext_eqc.erl b/eqc_test/enacl_ext_eqc.erl index 8174f43..8eced40 100644 --- a/eqc_test/enacl_ext_eqc.erl +++ b/eqc_test/enacl_ext_eqc.erl @@ -1,7 +1,8 @@ -module(enacl_ext_eqc). -include_lib("eqc/include/eqc.hrl"). --compile(export_all). +-compile({parse_transform, eqc_parallelize}). +-compile([export_all, nowarn_export_all]). public_keypair() -> ?LET(#{ public := PK, secret := SK}, enacl_ext:curve25519_keypair(), From 41045fed85270d3a620bae830e07ee4b559aa3ba Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 5 Feb 2020 13:16:35 +0100 Subject: [PATCH 073/162] Partially stream kx Also while here, implement some EQC tests for it. --- CHANGELOG.md | 3 ++- c_src/enacl.c | 2 +- c_src/kx.c | 14 +++++++------- eqc_test/enacl_eqc.erl | 29 +++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8794ff..39211d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,15 +10,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Go through all calls and make them return streamlined exceptions if applicable. Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - kx + - Rename the key sizes so they follow libsodium. - secret - sign - - enacl_nif - Implement missing EQC tests - Generichash - Multi-part generic hash - pwhash - Extend with limit for ops and memory as well. + - kx ## [Unreleased] diff --git a/c_src/enacl.c b/c_src/enacl.c index fa8a71b..5497180 100644 --- a/c_src/enacl.c +++ b/c_src/enacl.c @@ -8,5 +8,5 @@ ERL_NIF_TERM enacl_error_tuple(ErlNifEnv *env, char *error_atom) { } ERL_NIF_TERM enacl_internal_error(ErlNifEnv *env) { - return enif_raise_exception(env, enif_make_atom(env, "internal_error")); + return enif_raise_exception(env, enif_make_atom(env, "enacl_internal_error")); } \ No newline at end of file diff --git a/c_src/kx.c b/c_src/kx.c index 6d5b39b..6020e6f 100644 --- a/c_src/kx.c +++ b/c_src/kx.c @@ -31,12 +31,12 @@ ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_kx_PUBLICKEYBYTES, &pk)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } if (!enif_alloc_binary(crypto_kx_SECRETKEYBYTES, &sk)) { enif_release_binary(&pk); - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_kx_keypair(pk.data, sk.data); @@ -68,12 +68,12 @@ enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, goto bad_arg; if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - ret = enacl_error_tuple(env, "alloc_failed"); + ret = enacl_internal_error(env); goto done; } if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - ret = enacl_error_tuple(env, "alloc_failed"); + ret = enacl_internal_error(env); goto release_rx; } @@ -121,12 +121,12 @@ enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, goto bad_arg; if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - ret = enacl_error_tuple(env, "alloc_failed"); + ret = enacl_internal_error(env); goto done; } if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - ret = enacl_error_tuple(env, "alloc_failed"); + ret = enacl_internal_error(env); goto release_rx; } @@ -148,4 +148,4 @@ release_rx: enif_release_binary(&rx); done: return ret; -} \ No newline at end of file +} diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 7eb1486..4b6f4ac 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -122,6 +122,24 @@ keypair_bad() -> keypair() -> ?FAULT(keypair_bad(), keypair_good()). +kx_keypair_good() -> + #{ public := PK, secret := SK} = enacl:kx_keypair(), + {PK, SK}. + +kx_keypair_bad() -> + ?LET(X, elements([pk, sk]), + begin + #{ public := PK, secret := SK} = enacl:box_keypair(), + case X of + pk -> + PKBytes = enacl:kx_public_key_size(), + {oneof([return(a), nat(), ?SUCHTHAT(B, binary(), byte_size(B) /= PKBytes)]), SK}; + sk -> + SKBytes = enacl:kx_secret_key_size(), + {PK, oneof([return(a), nat(), ?SUCHTHAT(B, binary(), byte_size(B) /= SKBytes)])} + end + end). + %% CRYPTO BOX %% --------------------------- %% * box/4 @@ -880,6 +898,17 @@ prop_randombytes_uint32() -> is_integer(V) end). +%% KX +%% --------------------------- +prop_kx() -> + ?FORALL({{CPK, CSK}, {SPK, SSK}}, {kx_keypair_good(), kx_keypair_good()}, + begin + #{ client_tx := CTX, client_rx := CRX} = enacl:kx_client_session_keys(CPK, CSK, SPK), + #{ server_tx := STX, server_rx := SRX} = enacl:kx_server_session_keys(SPK, SSK, CPK), + %% This keypair must be shared in both directions + conjunction([{ctx_srx, equals(CTX, SRX)}, {stx_crx, equals(STX, CRX)}]) + end). + %% SCRAMBLING prop_scramble_block() -> ?FORALL({Block, Key}, {binary(16), eqc_gen:largebinary(32)}, From dea9ce62eddfda37f87b48fc5736d6f3b045578b Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 5 Feb 2020 13:34:27 +0100 Subject: [PATCH 074/162] Rename constant to be in line with libsodium --- CHANGELOG.md | 4 +--- src/enacl.erl | 24 ++++++++++++------------ test/enacl_SUITE.erl | 3 +-- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39211d8..c8b4fcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Go through all calls and make them return streamlined exceptions if applicable. Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - - kx - - Rename the key sizes so they follow libsodium. - secret - sign @@ -19,7 +17,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Multi-part generic hash - pwhash - Extend with limit for ops and memory as well. - - kx ## [Unreleased] @@ -33,6 +30,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. carefully as we have made changes to these functions. TL;DR: look for `aead_chacha20poly1305_ietf_*` but note it is *not* just a simple substitution into your code. +- The `kx` constants have been renamed to follow libsodium one-to-one. ### Removed - The functions of the form `aead_chacha20poly1305_*` were removed. They implement diff --git a/src/enacl.erl b/src/enacl.erl index 2c81178..5b1ace5 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -171,9 +171,9 @@ kx_keypair/0, kx_client_session_keys/3, kx_server_session_keys/3, - kx_public_key_size/0, - kx_secret_key_size/0, - kx_session_key_size/0 + kx_PUBLICKEYBYTES/0, + kx_SECRETKEYBYTES/0, + kx_SESSIONKEYBYTES/0 ]). %% Internal verification of the system @@ -1132,22 +1132,22 @@ kx_server_session_keys(ServerPk, ServerSk, ClientPk) -> {Rx, Tx} = enacl_nif:crypto_kx_server_session_keys(ServerPk, ServerSk, ClientPk), #{ server_rx => Rx, server_tx => Tx}. -%% @doc kx_session_key_size/0 returns the number of bytes of the generated during key exchange session key. +%% @doc kx_SESSIONKEYBYTES/0 returns the number of bytes of the generated during key exchange session key. %% @end --spec kx_session_key_size() -> pos_integer(). -kx_session_key_size() -> +-spec kx_SESSIONKEYBYTES() -> pos_integer(). +kx_SESSIONKEYBYTES() -> enacl_nif:crypto_kx_SESSIONKEYBYTES(). -%% @doc kx_public_key_size/0 returns the number of bytes of the public key used in key exchange. +%% @doc kx_PUBLICKEYBYTES/0 returns the number of bytes of the public key used in key exchange. %% @end --spec kx_public_key_size() -> pos_integer(). -kx_public_key_size() -> +-spec kx_PUBLICKEYBYTES() -> pos_integer(). +kx_PUBLICKEYBYTES() -> enacl_nif:crypto_kx_PUBLICKEYBYTES(). -%% @doc kx_secret_key_size/0 returns the number of bytes of the secret key used in key exchange. +%% @doc kx_SECRETKEYBYTES/0 returns the number of bytes of the secret key used in key exchange. %% @end --spec kx_secret_key_size() -> pos_integer(). -kx_secret_key_size() -> +-spec kx_SECRETKEYBYTES() -> pos_integer(). +kx_SECRETKEYBYTES() -> enacl_nif:crypto_kx_SECRETKEYBYTES(). %% AEAD ChaCha20 Poly1305 diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index a5633bd..dec7371 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -44,8 +44,7 @@ groups() -> aead_chacha20poly1305_ietf, pwhash, sign, - kx, - randombytes]}, + kx]}, [Neg, Pos]. From 1cb2c3a2a2a6fa462b6ccd7c4cf260df0f1d8f71 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 5 Feb 2020 13:41:19 +0100 Subject: [PATCH 075/162] Extend pwhashing with limits In the EQC tests, we generate limits at random and verify things work. --- CHANGELOG.md | 4 ---- eqc_test/enacl_eqc.erl | 8 +++++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8b4fcc..85dece2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,10 +13,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - sign - Implement missing EQC tests - - Generichash - - Multi-part generic hash - - pwhash - - Extend with limit for ops and memory as well. ## [Unreleased] diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 4b6f4ac..b449c32 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -762,12 +762,14 @@ pwhash_str_verify(PasswdHash, Passwd) -> end. prop_pwhash_str_verify() -> - ?FORALL({Passwd}, - {?FAULT_RATE(1, 40, g_iodata())}, + ?FORALL({Passwd, OLimit, MLimit}, + {?FAULT_RATE(1, 40, g_iodata()), + elements([interactive, moderate, sensitive]), + elements([interactive, moderate, sensitive])}, begin case v_iodata(Passwd) of true -> - Ascii = enacl:pwhash_str(Passwd), + Ascii = enacl:pwhash_str(Passwd, OLimit, MLimit), S = enacl:pwhash_str_verify(Ascii, Passwd), equals(S, true); false -> From 7999d08e9d734350c35c8aae2c20937f7adf8596 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 6 Feb 2020 11:12:32 +0100 Subject: [PATCH 076/162] Streamlining of secret and _verify The secret key API is now streamlined. Also, all verify-type functions are now returning boolean() values. This makes the API consistent. --- CHANGELOG.md | 3 ++- c_src/secret.c | 16 ++++++++-------- c_src/sign.c | 4 ++-- eqc_test/enacl_eqc.erl | 4 ++-- src/enacl.erl | 11 ++++------- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85dece2..576310d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Go through all calls and make them return streamlined exceptions if applicable. Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - - secret - sign - Implement missing EQC tests @@ -27,6 +26,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. `aead_chacha20poly1305_ietf_*` but note it is *not* just a simple substitution into your code. - The `kx` constants have been renamed to follow libsodium one-to-one. +- All calls with `verify` now returns booleans. See `sign_verify_detached`, which + were changed by this. ### Removed - The functions of the form `aead_chacha20poly1305_*` were removed. They implement diff --git a/c_src/secret.c b/c_src/secret.c index 95b1b04..fb7b11a 100644 --- a/c_src/secret.c +++ b/c_src/secret.c @@ -91,7 +91,7 @@ ERL_NIF_TERM enacl_crypto_secretbox(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(padded_msg.size, &padded_ciphertext)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_secretbox(padded_ciphertext.data, padded_msg.data, padded_msg.size, @@ -120,7 +120,7 @@ ERL_NIF_TERM enacl_crypto_secretbox_open(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(padded_ciphertext.size, &padded_msg)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } if (crypto_secretbox_open(padded_msg.data, padded_ciphertext.data, @@ -152,7 +152,7 @@ ERL_NIF_TERM enacl_crypto_stream_chacha20(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(clen, &c)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_stream_chacha20(c.data, c.size, n.data, k.data); @@ -177,7 +177,7 @@ enacl_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size, &c)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_stream_chacha20_xor(c.data, m.data, m.size, n.data, k.data); @@ -202,7 +202,7 @@ ERL_NIF_TERM enacl_crypto_stream(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(clen, &c)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_stream(c.data, c.size, n.data, k.data); @@ -226,7 +226,7 @@ ERL_NIF_TERM enacl_crypto_stream_xor(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size, &c)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_stream_xor(c.data, m.data, m.size, n.data, k.data); @@ -248,7 +248,7 @@ ERL_NIF_TERM enacl_crypto_auth(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_auth_BYTES, &a)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_auth(a.data, m.data, m.size, k.data); @@ -291,7 +291,7 @@ ERL_NIF_TERM enacl_crypto_onetimeauth(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_onetimeauth_BYTES, &a)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_onetimeauth(a.data, m.data, m.size, k.data); diff --git a/c_src/sign.c b/c_src/sign.c index 07f1446..c37cf63 100644 --- a/c_src/sign.c +++ b/c_src/sign.c @@ -215,9 +215,9 @@ ERL_NIF_TERM enacl_crypto_sign_final_verify(ErlNifEnv *env, int argc, } if (0 == crypto_sign_final_verify(obj->state, sig.data, pk.data)) { - ret = enif_make_atom(env, ATOM_OK); + ret = enif_make_atom(env, "true"); } else { - ret = enacl_error_tuple(env, "failed_verification"); + ret = enif_make_atom(env, "false"); } // Mark as done goto cleanup; diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index b449c32..210e4d0 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -421,9 +421,9 @@ prop_sign_detached_open() -> true -> case SignMsg of {valid, Sig} -> - equals({ok, Msg}, enacl:sign_verify_detached(Sig, Msg, PK)); + equals(true, enacl:sign_verify_detached(Sig, Msg, PK)); {invalid, Sig} -> - equals({error, failed_verification}, enacl:sign_verify_detached(Sig, Msg, PK)) + equals(false, enacl:sign_verify_detached(Sig, Msg, PK)) end; false -> badargs(fun() -> enacl:sign_verify_detached(SignMsg, Msg, PK) end) diff --git a/src/enacl.erl b/src/enacl.erl index 5b1ace5..d94013f 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -623,17 +623,14 @@ sign_detached(M, SK) -> %% message for the given public key. %% %% Given a signature `SIG', a message `M', and a public key `PK', the function computes -%% true iff the `SIG' is valid for `M' and `PK'. --spec sign_verify_detached(SIG, M, PK) -> {ok, M} | {error, failed_verification} +%% true iff the `SIG' is valid for `M' and `PK'; false otherwise. +-spec sign_verify_detached(SIG, M, PK) -> boolean() when SIG :: binary(), M :: iodata(), PK :: binary(). sign_verify_detached(SIG, M, PK) -> - case enacl_nif:crypto_sign_verify_detached(SIG, M, PK) of - true -> {ok, M}; - false -> {error, failed_verification} - end. + enacl_nif:crypto_sign_verify_detached(SIG, M, PK). -type sign_state() :: reference(). @@ -669,7 +666,7 @@ sign_final_create(SignState, SK) -> %% Verifies that `SIG` is a valid signature for the message whose content has %% been previously supplied using `sign_update/2` using the public key `PK.` %% @end --spec sign_final_verify(S, SIG, PK) -> ok | {error, failed_verification} +-spec sign_final_verify(S, SIG, PK) -> boolean() when S :: sign_state(), SIG :: binary(), PK :: iodata(). From f580f6525b6d40c879f1594d187be5d5238f4da9 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 6 Feb 2020 11:48:57 +0100 Subject: [PATCH 077/162] Streamline _open style calls Those now return {ok, Msg} or {error, term()} so you are kind of forced to match on them. This is likely to help with correctnes. --- CHANGELOG.md | 5 ++- c_src/enacl.c | 4 ++ c_src/enacl.h | 1 + c_src/secret.c | 4 +- c_src/sign.c | 92 +++++++++++++----------------------------- eqc_test/enacl_eqc.erl | 18 --------- src/enacl.erl | 24 +++-------- 7 files changed, 45 insertions(+), 103 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 576310d..1b6adab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Go through all calls and make them return streamlined exceptions if applicable. Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - - sign + - Generichashes must support the finalized state - Implement missing EQC tests + - stream_chacha20... + - stream_xor... + - generichash... ## [Unreleased] diff --git a/c_src/enacl.c b/c_src/enacl.c index 5497180..a27dd35 100644 --- a/c_src/enacl.c +++ b/c_src/enacl.c @@ -9,4 +9,8 @@ ERL_NIF_TERM enacl_error_tuple(ErlNifEnv *env, char *error_atom) { ERL_NIF_TERM enacl_internal_error(ErlNifEnv *env) { return enif_raise_exception(env, enif_make_atom(env, "enacl_internal_error")); +} + +ERL_NIF_TERM enacl_error_finalized(ErlNifEnv *env) { + return enif_raise_exception(env, enif_make_atom(env, "enacl_finalized")); } \ No newline at end of file diff --git a/c_src/enacl.h b/c_src/enacl.h index 3dc3a59..ef84b9e 100644 --- a/c_src/enacl.h +++ b/c_src/enacl.h @@ -9,6 +9,7 @@ #define ATOM_FALSE "false" ERL_NIF_TERM enacl_error_tuple(ErlNifEnv *, char *); +ERL_NIF_TERM enacl_error_finalized(ErlNifEnv *); ERL_NIF_TERM enacl_internal_error(ErlNifEnv *); #endif diff --git a/c_src/secret.c b/c_src/secret.c index fb7b11a..627d444 100644 --- a/c_src/secret.c +++ b/c_src/secret.c @@ -130,9 +130,11 @@ ERL_NIF_TERM enacl_crypto_secretbox_open(ErlNifEnv *env, int argc, return enacl_error_tuple(env, "failed_verification"); } - return enif_make_sub_binary( + ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret_bin = enif_make_sub_binary( env, enif_make_binary(env, &padded_msg), crypto_secretbox_ZEROBYTES, padded_ciphertext.size - crypto_secretbox_ZEROBYTES); + return enif_make_tuple2(env, ret_ok, ret_bin); } ERL_NIF_TERM enacl_crypto_stream_chacha20(ErlNifEnv *env, int argc, diff --git a/c_src/sign.c b/c_src/sign.c index c37cf63..6a4e00a 100644 --- a/c_src/sign.c +++ b/c_src/sign.c @@ -56,24 +56,20 @@ ERL_NIF_TERM enacl_crypto_sign_init(ErlNifEnv *env, int argc, if ((obj = enif_alloc_resource(enacl_sign_ctx_rtype, sizeof(enacl_sign_ctx))) == NULL) { - ret = enacl_error_tuple(env, "alloc_failed"); - goto done; + goto err; } obj->alive = 0; obj->state = enif_alloc(crypto_sign_statebytes()); if (obj->state == NULL) { - ret = enacl_error_tuple(env, "state_malloc"); goto release; } obj->alive = 1; if ((obj->mtx = enif_mutex_create("enacl.sign")) == NULL) { - ret = enacl_error_tuple(env, "mutex_create"); goto free; } if (0 != crypto_sign_init(obj->state)) { - ret = enacl_error_tuple(env, "sign_init_error"); goto free; } @@ -94,6 +90,8 @@ free: release: // This also frees the mutex via the destructor enif_release_resource(obj); +err: + ret = enacl_internal_error(env); done: return ret; } @@ -120,12 +118,12 @@ ERL_NIF_TERM enacl_crypto_sign_update(ErlNifEnv *env, int argc, enif_mutex_lock(obj->mtx); if (!obj->alive) { - ret = enacl_error_tuple(env, "finalized"); + ret = enacl_error_finalized(env); goto done; } if (0 != crypto_sign_update(obj->state, data.data, data.size)) { - ret = enacl_error_tuple(env, "sign_update_error"); + ret = enacl_internal_error(env); // This should never be hit goto done; } @@ -157,19 +155,16 @@ ERL_NIF_TERM enacl_crypto_sign_final_create(ErlNifEnv *env, int argc, enif_mutex_lock(obj->mtx); if (!obj->alive) { - ret = enacl_error_tuple(env, "finalized"); + ret = enacl_error_finalized(env); goto done; } if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { - ret = enacl_error_tuple(env, "alloc_failed"); + ret = enacl_internal_error(env); goto done; } - if (0 != crypto_sign_final_create(obj->state, sig.data, &siglen, sk.data)) { - ret = enacl_error_tuple(env, "sign_error"); - goto release; - } + crypto_sign_final_create(obj->state, sig.data, &siglen, sk.data); ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK); ERL_NIF_TERM signature = enif_make_binary(env, &sig); @@ -179,8 +174,6 @@ ERL_NIF_TERM enacl_crypto_sign_final_create(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); -release: - enif_release_binary(&sig); cleanup: obj->alive = 0; sodium_memzero(obj->state, crypto_sign_statebytes()); @@ -210,7 +203,7 @@ ERL_NIF_TERM enacl_crypto_sign_final_verify(ErlNifEnv *env, int argc, enif_mutex_lock(obj->mtx); if (!obj->alive) { - ret = enacl_error_tuple(env, "finalized"); + ret = enacl_error_finalized(env); goto done; } @@ -246,12 +239,12 @@ enacl_crypto_sign_ed25519_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } if (!enif_alloc_binary(crypto_sign_ed25519_SECRETKEYBYTES, &sk)) { enif_release_binary(&pk); - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_sign_ed25519_keypair(pk.data, sk.data); @@ -271,13 +264,10 @@ enacl_crypto_sign_ed25519_sk_to_pk(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_ed25519_PUBLICKEYBYTES, &pk)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } - if (crypto_sign_ed25519_sk_to_pk(pk.data, sk.data) != 0) { - enif_release_binary(&pk); - return enacl_error_tuple(env, "crypto_sign_ed25519_sk_to_pk_failed"); - } + crypto_sign_ed25519_sk_to_pk(pk.data, sk.data); return enif_make_binary(env, &pk); } @@ -293,14 +283,10 @@ enacl_crypto_sign_ed25519_public_to_curve25519(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_pk)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } - if (crypto_sign_ed25519_pk_to_curve25519(curve25519_pk.data, - ed25519_pk.data) != 0) { - enif_release_binary(&curve25519_pk); - return enacl_error_tuple(env, "ed25519_public_to_curve25519_failed"); - } + crypto_sign_ed25519_pk_to_curve25519(curve25519_pk.data, ed25519_pk.data); return enif_make_binary(env, &curve25519_pk); } @@ -316,14 +302,10 @@ enacl_crypto_sign_ed25519_secret_to_curve25519(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &curve25519_sk)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } - if (crypto_sign_ed25519_sk_to_curve25519(curve25519_sk.data, - ed25519_sk.data) != 0) { - enif_release_binary(&curve25519_sk); - return enacl_error_tuple(env, "ed25519_secret_to_curve25519_failed"); - } + crypto_sign_ed25519_sk_to_curve25519(curve25519_sk.data, ed25519_sk.data); return enif_make_binary(env, &curve25519_sk); } @@ -364,12 +346,12 @@ ERL_NIF_TERM enacl_crypto_sign_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { enif_release_binary(&pk); - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_sign_keypair(pk.data, sk.data); @@ -387,12 +369,12 @@ ERL_NIF_TERM enacl_crypto_sign_seed_keypair(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } if (!enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { enif_release_binary(&pk); - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_sign_seed_keypair(pk.data, sk.data, seed.data); @@ -401,11 +383,6 @@ ERL_NIF_TERM enacl_crypto_sign_seed_keypair(ErlNifEnv *env, int argc, enif_make_binary(env, &sk)); } -/* -int crypto_sign(unsigned char *sm, unsigned long long *smlen, - const unsigned char *m, unsigned long long mlen, - const unsigned char *sk); - */ ERL_NIF_TERM enacl_crypto_sign(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary m, sk, sm; @@ -421,7 +398,7 @@ ERL_NIF_TERM enacl_crypto_sign(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(m.size + crypto_sign_BYTES, &sm)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_sign(sm.data, &smlen, m.data, m.size, sk.data); @@ -429,11 +406,6 @@ ERL_NIF_TERM enacl_crypto_sign(ErlNifEnv *env, int argc, return enif_make_sub_binary(env, enif_make_binary(env, &sm), 0, smlen); } -/* -int crypto_sign_open(unsigned char *m, unsigned long long *mlen, - const unsigned char *sm, unsigned long long smlen, - const unsigned char *pk); - */ ERL_NIF_TERM enacl_crypto_sign_open(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary m, sm, pk; @@ -449,22 +421,20 @@ ERL_NIF_TERM enacl_crypto_sign_open(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(sm.size, &m)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } if (0 == crypto_sign_open(m.data, &mlen, sm.data, sm.size, pk.data)) { - return enif_make_sub_binary(env, enif_make_binary(env, &m), 0, mlen); + ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK); + ERL_NIF_TERM ret_bin = + enif_make_sub_binary(env, enif_make_binary(env, &m), 0, mlen); + return enif_make_tuple2(env, ret_ok, ret_bin); } else { enif_release_binary(&m); return enacl_error_tuple(env, "failed_verification"); } } -/* -int crypto_sign_detached(unsigned char *sig, unsigned long long *siglen, - const unsigned char *m, unsigned long long mlen, - const unsigned char *sk); - */ ERL_NIF_TERM enacl_crypto_sign_detached(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary m, sk, sig; @@ -480,7 +450,7 @@ ERL_NIF_TERM enacl_crypto_sign_detached(ErlNifEnv *env, int argc, } if (!enif_alloc_binary(crypto_sign_BYTES, &sig)) { - return enacl_error_tuple(env, "alloc_failed"); + return enacl_internal_error(env); } crypto_sign_detached(sig.data, &siglen, m.data, m.size, sk.data); @@ -488,12 +458,6 @@ ERL_NIF_TERM enacl_crypto_sign_detached(ErlNifEnv *env, int argc, return enif_make_binary(env, &sig); } -/* -int crypto_sign_verify_detached(const unsigned char *sig, - const unsigned char *m, - unsigned long long mlen, - const unsigned char *pk); - */ ERL_NIF_TERM enacl_crypto_sign_verify_detached(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 210e4d0..4371ff8 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -607,24 +607,6 @@ xor_bytes(<>, <>) -> [A bxor B | xor_bytes(As, Bs)]; xor_bytes(<<>>, <<>>) -> []. -%% prop_stream_xor_correct() -> -%% ?FORALL({Msg, Nonce, Key}, -%% {?FAULT_RATE(1, 40, g_iodata()), -%% ?FAULT_RATE(1, 40, nonce()), -%% ?FAULT_RATE(1, 40, secret_key())}, -%% case v_iodata(Msg) andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of -%% true -> -%% Stream = enacl:stream(iolist_size(Msg), Nonce, Key), -%% CipherText = enacl:stream_xor(Msg, Nonce, Key), -%% StreamXor = enacl:stream_xor(CipherText, Nonce, Key), -%% conjunction([ -%% {'xor', equals(iolist_to_binary(Msg), StreamXor)}, -%% {stream, equals(iolist_to_binary(xor_bytes(Stream, iolist_to_binary(Msg))), CipherText)} -%% ]); -%% false -> -%% badargs(fun() -> enacl:stream_xor(Msg, Nonce, Key) end) -%% end). - %% CRYPTO AUTH %% ------------------------------------------------------------ %% * auth/2 diff --git a/src/enacl.erl b/src/enacl.erl index d94013f..7b712ad 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -30,7 +30,6 @@ box_secret_key_bytes/0, box_beforenm_bytes/0, - %% EQC sign_keypair_public_size/0, sign_keypair_secret_size/0, sign_keypair_seed_size/0, @@ -46,7 +45,6 @@ sign_final_create/2, sign_final_verify/3, - %% EQC box_seal/2, box_seal_open/3 ]). @@ -73,7 +71,6 @@ aead_chacha20poly1305_ietf_ABYTES/0, aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX/0, - %% No Tests! aead_xchacha20poly1305_ietf_encrypt/4, aead_xchacha20poly1305_ietf_decrypt/4, aead_xchacha20poly1305_ietf_KEYBYTES/0, @@ -111,16 +108,14 @@ generichash_update/2, generichash_final/1, - %% No Tests! + %% EQC! shorthash_key_size/0, shorthash_size/0, shorthash/2, - %% No Tests! pwhash/4, pwhash_str/3, - %% EQC pwhash/2, pwhash_str/1, pwhash_str_verify/2 @@ -602,10 +597,7 @@ sign(M, SK) -> PK :: binary(), M :: binary(). sign_open(SM, PK) -> - case enacl_nif:crypto_sign_open(SM, PK) of - M when is_binary(M) -> {ok, M}; - {error, Err} -> {error, Err} - end. + enacl_nif:crypto_sign_open(SM, PK). %% @doc sign_detached/2 computes a digital signature given a message and a secret key. %% @@ -742,17 +734,11 @@ secretbox(Msg, Nonce, Key) -> secretbox_open(CipherText, Nonce, Key) -> case iolist_size(CipherText) of K when K =< ?SECRETBOX_SIZE -> - R = case enacl_nif:crypto_secretbox_open_b([?S_BOXZEROBYTES, CipherText], - Nonce, Key) of - {error, Err} -> {error, Err}; - Bin when is_binary(Bin) -> {ok, Bin} - end, + R = enacl_nif:crypto_secretbox_open_b([?S_BOXZEROBYTES, CipherText], + Nonce, Key), bump(R, ?SECRETBOX_OPEN_REDUCTIONS, ?SECRETBOX_SIZE, K); _ -> - case enacl_nif:crypto_secretbox_open([?S_BOXZEROBYTES, CipherText], Nonce, Key) of - {error, Err} -> {error, Err}; - Bin when is_binary(Bin) -> {ok, Bin} - end + enacl_nif:crypto_secretbox_open([?S_BOXZEROBYTES, CipherText], Nonce, Key) end. %% @doc secretbox_nonce_size/0 returns the size of the secretbox nonce From 014d50cf471914bf56f51fbed0e4b4e54f7ba36b Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 6 Feb 2020 12:18:47 +0100 Subject: [PATCH 078/162] Implement EQC for generic hashing, fix bug. Turns out the interval we had in the file were inverted and I was wrong in an earlier commit. However, EQC dutifully found the mistake, and it is now corrected. --- CHANGELOG.md | 1 - c_src/generichash.c | 16 ++++++++-------- eqc_test/enacl_eqc.erl | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b6adab..40caac7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Implement missing EQC tests - stream_chacha20... - stream_xor... - - generichash... ## [Unreleased] diff --git a/c_src/generichash.c b/c_src/generichash.c index 4da2c80..a554d43 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -96,8 +96,8 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, // Verify that hash size is // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX - if ((hash_size <= crypto_generichash_BYTES_MIN) || - (hash_size >= crypto_generichash_BYTES_MAX)) { + if ((hash_size < crypto_generichash_BYTES_MIN) || + (hash_size > crypto_generichash_BYTES_MAX)) { goto bad_arg; } @@ -105,8 +105,8 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc, unsigned char *k = key.data; if (0 == key.size) { k = NULL; - } else if (key.size <= crypto_generichash_KEYBYTES_MIN || - key.size >= crypto_generichash_KEYBYTES_MAX) { + } else if (key.size < crypto_generichash_KEYBYTES_MIN || + key.size > crypto_generichash_KEYBYTES_MAX) { goto bad_arg; } @@ -150,8 +150,8 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, goto bad_arg; // Verify that hash size is valid - if ((hash_size <= crypto_generichash_BYTES_MIN) || - (hash_size >= crypto_generichash_BYTES_MAX)) { + if ((hash_size < crypto_generichash_BYTES_MIN) || + (hash_size > crypto_generichash_BYTES_MAX)) { goto bad_arg; } @@ -159,8 +159,8 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, unsigned char *k = key.data; if (0 == key.size) { k = NULL; - } else if (key.size <= crypto_generichash_KEYBYTES_MIN || - key.size >= crypto_generichash_KEYBYTES_MAX) { + } else if (key.size < crypto_generichash_KEYBYTES_MIN || + key.size > crypto_generichash_KEYBYTES_MAX) { goto bad_arg; } diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 4371ff8..1610f4b 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -140,6 +140,17 @@ kx_keypair_bad() -> end end). +g_generichash_data() -> + binary(). + +g_generichash_key() -> + ?LET({Min, Max}, {return(enacl_nif:crypto_generichash_KEYBYTES_MIN()), return(enacl_nif:crypto_generichash_KEYBYTES_MAX())}, + largebinary({limit, Min, Max})). + +g_generichash_size() -> + ?LET({Min, Max}, {return(enacl_nif:crypto_generichash_BYTES_MIN()), return(enacl_nif:crypto_generichash_BYTES_MAX())}, + choose(Min, Max)). + %% CRYPTO BOX %% --------------------------- %% * box/4 @@ -798,6 +809,22 @@ prop_crypto_shorthash_eq() -> end end ). +prop_crypto_generichash_eq() -> + ?FORALL({Sz, X, Key}, {g_generichash_size(), g_generichash_data(), g_generichash_key()}, + equals(enacl:generichash(Sz, X, Key), enacl:generichash(Sz, X, Key))). + +generichash_loop(S, []) -> S; +generichash_loop(S, [M|Ms]) -> + S2 = enacl:generichash_update(S, M), + generichash_loop(S2, Ms). + +prop_crypto_generichash_multi_part_eq() -> + ?FORALL({Sz, Xs, Key}, {g_generichash_size(), list(g_generichash_data()), g_generichash_key()}, + begin + S1 = generichash_loop(enacl:generichash_init(Sz, Key), Xs), + S2 = generichash_loop(enacl:generichash_init(Sz, Key), Xs), + equals(enacl:generichash_final(S1), enacl:generichash_final(S2)) + end). prop_crypto_shorthash_neq() -> ?FORALL({X, Y}, diff_pair(), From cceef4530a01b6dc6f94d17ace6509dae8e607af Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 6 Feb 2020 13:57:07 +0100 Subject: [PATCH 079/162] Streamline naming More changes before 1.0 with a more direct naming scheme. --- CHANGELOG.md | 4 -- bench/timing.erl | 46 +++++++------- eqc_test/enacl_eqc.erl | 75 ++++++++++++++--------- src/enacl.erl | 132 ++++++++++++++++++++--------------------- test/enacl_SUITE.erl | 2 +- 5 files changed, 138 insertions(+), 121 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40caac7..3d7700a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - Generichashes must support the finalized state -- Implement missing EQC tests - - stream_chacha20... - - stream_xor... - ## [Unreleased] ### Compatibility diff --git a/bench/timing.erl b/bench/timing.erl index 4d004ea..0302e85 100644 --- a/bench/timing.erl +++ b/bench/timing.erl @@ -20,7 +20,7 @@ test() -> randombytes() -> randombytes(100*1000). - + randombytes(0) -> ok; randombytes(N) -> enacl:randombytes(1024), @@ -29,7 +29,7 @@ randombytes(N) -> hash() -> B = binary:copy(<<0>>, 4096), hash(B, 10*1000). - + hash(_B, 0) -> ok; hash(B, N) -> enacl:hash(B), @@ -37,7 +37,7 @@ hash(B, N) -> box_keypair() -> box_keypair(10*1000). - + box_keypair(0) -> ok; box_keypair(N) -> enacl:box_keypair(), @@ -47,9 +47,9 @@ box() -> #{ public := PK1} = enacl:box_keypair(), #{ secret := SK2} = enacl:box_keypair(), B = binary:copy(<<0>>, 1), - Nonce = binary:copy(<<0>>, enacl:box_nonce_size()), + Nonce = binary:copy(<<0>>, enacl:box_NONCEBYTES()()), box(B, Nonce, PK1, SK2, 10*1000). - + box(_B, _Nonce, _PK1, _SK2, 0) -> ok; box(B, Nonce, PK1, SK2, N) -> enacl:box(B, Nonce, PK1, SK2), @@ -62,15 +62,15 @@ box_before_after() -> box_beforenm(PK1, SK2, 10*1000), R = enacl:box_beforenm(PK1, SK2), B = binary:copy(<<0>>, 8192), - Nonce = binary:copy(<<0>>, enacl:box_nonce_size()), + Nonce = binary:copy(<<0>>, enacl:box_NONCEBYTES()()), box_afternm(B, Nonce, R, 10*1000), ok. - + box_beforenm(_PK, _SK, 0) -> ok; box_beforenm(PK, SK, N) -> enacl:box_beforenm(PK, SK), box_beforenm(PK, SK, N-1). - + box_afternm(_Msg, _Nonce, _Key, 0) -> ok; box_afternm(Msg, Nonce, Key, N) -> enacl:box_afternm(Msg, Nonce, Key), @@ -78,7 +78,7 @@ box_afternm(Msg, Nonce, Key, N) -> sign_keypair() -> sign_keypair(10*1000). - + sign_keypair(0) -> ok; sign_keypair(N) -> enacl:sign_keypair(), @@ -91,7 +91,7 @@ sign() -> Msg = binary:copy(<<0>>, 1024), #{ secret := SK } = enacl:sign_keypair(), sign(Msg, SK, 10*1000). - + sign(_Msg, _SK, 0) -> ok; sign(Msg, SK, N) -> enacl:sign(Msg, SK), @@ -100,10 +100,10 @@ sign(Msg, SK, N) -> secretbox() -> Msg = binary:copy(<<0>>, 8192), - Nonce = binary:copy(<<0>>, enacl:secretbox_nonce_size()), - Key = binary:copy(<<0>>, enacl:secretbox_key_size()), + Nonce = binary:copy(<<0>>, enacl:secretbox_NONCEBYTES()()), + Key = binary:copy(<<0>>, enacl:secretbox_KEYBYTES()), secretbox(Msg, Nonce, Key, 10*1000). - + secretbox(_Msg, _Nonce, _Key, 0) -> ok; secretbox(Msg, Nonce, Key, N) -> enacl:secretbox(Msg, Nonce, Key), @@ -111,8 +111,8 @@ secretbox(Msg, Nonce, Key, N) -> stream() -> - stream(16384, binary:copy(<<0>>, enacl:stream_nonce_size()), binary:copy(<<0>>, enacl:stream_key_size()), 10*1000). - + stream(16384, binary:copy(<<0>>, enacl:stream_NONCEBYTES()), binary:copy(<<0>>, enacl:stream_KEYBYTES()), 10*1000). + stream(_L, _Nonce, _K, 0) -> ok; stream(L, Nonce, K, N) -> enacl:stream(L, Nonce, K), @@ -120,31 +120,31 @@ stream(L, Nonce, K, N) -> auth() -> Msg = binary:copy(<<0>>, 4096), - Key = binary:copy(<<0>>, enacl:auth_key_size()), + Key = binary:copy(<<0>>, enacl:auth_KEYBYTES()), auth(Msg, Key, 10*1000). - + auth(_Msg, _Key, 0) -> ok; auth(Msg, Key, N) -> enacl:auth(Msg, Key), auth(Msg, Key, N-1). - + onetime_auth() -> Msg = binary:copy(<<0>>, 16384), - Key = binary:copy(<<0>>, enacl:onetime_auth_key_size()), + Key = binary:copy(<<0>>, enacl:onetime_auth_KEYBYTES()), onetime_auth(Msg, Key, 10*1000). - + onetime_auth(_Msg, _Key, 0) -> ok; onetime_auth(Msg, Key, N) -> enacl:onetime_auth(Msg, Key), onetime_auth(Msg, Key, N-1). - + scalarmult() -> Secret = binary:copy(<<0>>, 32), BasePoint = binary:copy(<<1>>, 32), scalarmult(Secret, BasePoint, 10*1000). - + scalarmult(_S, _B, 0) -> ok; scalarmult(S, B, N) -> enacl:curve25519_scalarmult(S, B), scalarmult(S, B, N-1). - + diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 1610f4b..24513b0 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -83,8 +83,8 @@ v_binary(_, _) -> false. %% Typical generators based on the binaries -nonce() -> g_binary(enacl:box_nonce_size()). -nonce_valid(N) -> v_binary(enacl:box_nonce_size(), N). +nonce() -> g_binary(enacl:box_NONCEBYTES()). +nonce_valid(N) -> v_binary(enacl:box_NONCEBYTES(), N). %% Generator of natural numbers g_nat() -> @@ -111,10 +111,10 @@ keypair_bad() -> #{ public := PK, secret := SK} = enacl:box_keypair(), case X of pk -> - PKBytes = enacl:box_public_key_bytes(), + PKBytes = enacl:box_PUBLICKEYBYTES(), {oneof([return(a), nat(), ?SUCHTHAT(B, binary(), byte_size(B) /= PKBytes)]), SK}; sk -> - SKBytes = enacl:box_secret_key_bytes(), + SKBytes = enacl:box_SECRETKEYBYTES(), {PK, oneof([return(a), nat(), ?SUCHTHAT(B, binary(), byte_size(B) /= SKBytes)])} end end). @@ -159,8 +159,8 @@ g_generichash_size() -> %% * box_afternm/3 %% * box_open_afternm/3 keypair_valid(PK, SK) when is_binary(PK), is_binary(SK) -> - PKBytes = enacl:box_public_key_bytes(), - SKBytes = enacl:box_secret_key_bytes(), + PKBytes = enacl:box_PUBLICKEYBYTES(), + SKBytes = enacl:box_SECRETKEYBYTES(), byte_size(PK) == PKBytes andalso byte_size(SK) == SKBytes; keypair_valid(_PK, _SK) -> false. @@ -264,11 +264,11 @@ beforenm_key() -> oneof([ elements([a,b,c]), real(), - ?SUCHTHAT(X, binary(), byte_size(X) /= enacl:box_beforenm_bytes()) + ?SUCHTHAT(X, binary(), byte_size(X) /= enacl:box_BEFORENMBYTES()) ]) end). -v_key(K) when is_binary(K) -> byte_size(K) == enacl:box_beforenm_bytes(); +v_key(K) when is_binary(K) -> byte_size(K) == enacl:box_BEFORENMBYTES(); v_key(_) -> false. prop_beforenm_correct() -> @@ -324,11 +324,11 @@ sign_keypair_bad() -> KP = enacl:sign_keypair(), case X of pk -> - Sz = enacl:sign_keypair_public_size(), + Sz = enacl:sign_PUBLICBYTES(), ?LET(Wrong, oneof([a, int(), ?SUCHTHAT(B, binary(), byte_size(B) /= Sz)]), KP#{ public := Wrong }); sk -> - Sz = enacl:sign_keypair_secret_size(), + Sz = enacl:sign_SECRETBYTES(), ?LET(Wrong, oneof([a, int(), ?SUCHTHAT(B, binary(), byte_size(B) /= Sz)]), KP#{ secret := Wrong }) end @@ -342,12 +342,12 @@ sign_keypair() -> sign_keypair_public_valid(#{ public := Public }) when is_binary(Public) -> - byte_size(Public) == enacl:sign_keypair_public_size(); + byte_size(Public) == enacl:sign_PUBLICBYTES(); sign_keypair_public_valid(_) -> false. sign_keypair_secret_valid(#{ secret := Secret }) when is_binary(Secret) -> - byte_size(Secret) == enacl:sign_keypair_secret_size(); + byte_size(Secret) == enacl:sign_SECRETBYTES(); sign_keypair_secret_valid(_) -> false. sign_keypair_valid(KP) -> @@ -408,11 +408,11 @@ signed_message_good_d(M) -> end)}]). signed_message_bad() -> - Sz = enacl:sign_keypair_public_size(), + Sz = enacl:sign_PUBLICBYTES(), {binary(), oneof([a, int(), ?SUCHTHAT(B, binary(Sz), byte_size(B) /= Sz)])}. signed_message_bad_d() -> - Sz = enacl:sign_keypair_public_size(), + Sz = enacl:sign_PUBLICBYTES(), {binary(), oneof([a, int(), ?SUCHTHAT(B, binary(Sz), byte_size(B) /= Sz)])}. signed_message(M) -> @@ -496,19 +496,19 @@ prop_seal_box_correct() -> %% * secretbox/3 %% * secretbo_open/3 secret_key_good() -> - Sz = enacl:secretbox_key_size(), + Sz = enacl:secretbox_KEYBYTES(), binary(Sz). secret_key_bad() -> oneof([return(a), nat(), - ?SUCHTHAT(B, binary(), byte_size(B) /= enacl:secretbox_key_size())]). + ?SUCHTHAT(B, binary(), byte_size(B) /= enacl:secretbox_KEYBYTES())]). secret_key() -> ?FAULT(secret_key_bad(), secret_key_good()). secret_key_valid(SK) when is_binary(SK) -> - Sz = enacl:secretbox_key_size(), + Sz = enacl:secretbox_KEYBYTES(), byte_size(SK) == Sz; secret_key_valid(_SK) -> false. @@ -618,6 +618,27 @@ xor_bytes(<>, <>) -> [A bxor B | xor_bytes(As, Bs)]; xor_bytes(<<>>, <<>>) -> []. +positive() -> + ?LET(N, nat(), N+1). + +chacha20_nonce() -> + Sz = enacl:stream_chacha20_NONCEBYTES(), + binary(Sz). + +chacha20_key() -> + Sz = enacl:stream_chacha20_KEYBYTES(), + binary(Sz). + +prop_stream_chacha20_correct() -> + ?FORALL(Len, positive(), + ?FORALL({Msg, Nonce, Key}, {binary(Len), chacha20_nonce(), chacha20_key()}, + begin + CT = enacl:stream_chacha20_xor(Msg, Nonce, Key), + Stream = enacl:stream_chacha20(Len, Nonce, Key), + CT2 = list_to_binary(xor_bytes(Stream, Msg)), + equals(CT, CT2) + end)). + %% CRYPTO AUTH %% ------------------------------------------------------------ %% * auth/2 @@ -635,19 +656,19 @@ prop_auth_correct() -> end). authenticator_bad() -> - oneof([a, int(), ?SUCHTHAT(X, binary(), byte_size(X) /= enacl:auth_size())]). + oneof([a, int(), ?SUCHTHAT(X, binary(), byte_size(X) /= enacl:auth_BYTES())]). authenticator_good(Msg, Key) when is_binary(Key) -> - Sz = enacl:secretbox_key_size(), + Sz = enacl:secretbox_KEYBYTES(), case v_iodata(Msg) andalso byte_size(Key) == Sz of true -> - frequency([{1, ?LAZY({invalid, binary(enacl:auth_size())})}, + frequency([{1, ?LAZY({invalid, binary(enacl:auth_BYTES())})}, {3, return({valid, enacl:auth(Msg, Key)})}]); false -> - binary(enacl:auth_size()) + binary(enacl:auth_BYTES()) end; authenticator_good(_Msg, _Key) -> - binary(enacl:auth_size()). + binary(enacl:auth_BYTES()). authenticator(Msg, Key) -> ?FAULT(authenticator_bad(), authenticator_good(Msg, Key)). @@ -690,19 +711,19 @@ prop_onetimeauth_correct() -> end). ot_authenticator_bad() -> - oneof([a, int(), ?SUCHTHAT(X, binary(), byte_size(X) /= enacl:onetime_auth_size())]). + oneof([a, int(), ?SUCHTHAT(X, binary(), byte_size(X) /= enacl:onetime_auth_BYTES())]). ot_authenticator_good(Msg, Key) when is_binary(Key) -> - Sz = enacl:secretbox_key_size(), + Sz = enacl:secretbox_KEYBYTES(), case v_iodata(Msg) andalso byte_size(Key) == Sz of true -> - frequency([{1, ?LAZY({invalid, binary(enacl:onetime_auth_size())})}, + frequency([{1, ?LAZY({invalid, binary(enacl:onetime_auth_BYTES())})}, {3, return({valid, enacl:onetime_auth(Msg, Key)})}]); false -> - binary(enacl:onetime_auth_size()) + binary(enacl:onetime_auth_BYTES()) end; ot_authenticator_good(_Msg, _Key) -> - binary(enacl:auth_size()). + binary(enacl:auth_BYTES()). ot_authenticator(Msg, Key) -> ?FAULT(ot_authenticator_bad(), ot_authenticator_good(Msg, Key)). diff --git a/src/enacl.erl b/src/enacl.erl index 7b712ad..5fe4714 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -25,14 +25,14 @@ box_beforenm/2, box_afternm/3, box_open_afternm/3, - box_nonce_size/0, - box_public_key_bytes/0, - box_secret_key_bytes/0, - box_beforenm_bytes/0, + box_NONCEBYTES/0, + box_PUBLICKEYBYTES/0, + box_SECRETKEYBYTES/0, + box_BEFORENMBYTES/0, - sign_keypair_public_size/0, - sign_keypair_secret_size/0, - sign_keypair_seed_size/0, + sign_PUBLICBYTES/0, + sign_SECRETBYTES/0, + sign_SEEDBYTES/0, sign_keypair/0, sign_seed_keypair/1, sign/2, @@ -52,14 +52,14 @@ %% Secret key crypto -export([ %% EQC - secretbox_key_size/0, - secretbox_nonce_size/0, + secretbox_KEYBYTES/0, + secretbox_NONCEBYTES/0, secretbox/3, secretbox_open/3, %% No Tests! - stream_chacha20_key_size/0, - stream_chacha20_nonce_size/0, + stream_chacha20_KEYBYTES/0, + stream_chacha20_NONCEBYTES/0, stream_chacha20/3, stream_chacha20_xor/3, @@ -79,22 +79,22 @@ aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX/0, %% EQC - stream_key_size/0, - stream_nonce_size/0, + stream_KEYBYTES/0, + stream_NONCEBYTES/0, stream/3, %% No Tests! stream_xor/3, %% EQC - auth_key_size/0, - auth_size/0, + auth_KEYBYTES/0, + auth_BYTES/0, auth/2, auth_verify/3, %% EQC - onetime_auth_key_size/0, - onetime_auth_size/0, + onetime_auth_KEYBYTES/0, + onetime_auth_BYTES/0, onetime_auth/2, onetime_auth_verify/3 ]). @@ -189,9 +189,9 @@ -define(SECRETBOX_OPEN_REDUCTIONS, 17 * 2). -define(STREAM_SIZE, 16 * 1024). -define(STREAM_REDUCTIONS, 17 * 2). --define(AUTH_SIZE, 4 * 1024). +-define(auth_BYTES, 4 * 1024). -define(AUTH_REDUCTIONS, 17 * 2). --define(ONETIME_AUTH_SIZE, 16 * 1024). +-define(ONETIME_auth_BYTES, 16 * 1024). -define(ONETIME_AUTH_REDUCTIONS, 16 * 2). -define(ED25519_PUBLIC_TO_CURVE_REDS, 20 * 2). -define(ED25519_SECRET_TO_CURVE_REDS, 20 * 2). @@ -522,35 +522,35 @@ box_open_afternm(CipherText, Nonce, Key) -> enacl_nif:crypto_box_open_afternm([?P_BOXZEROBYTES, CipherText], Nonce, Key) end. -%% @doc box_nonce_size/0 return the byte-size of the nonce +%% @doc box_NONCEBYTES()/0 return the byte-size of the nonce %% %% Used to obtain the size of the nonce. %% @end. --spec box_nonce_size() -> pos_integer(). -box_nonce_size() -> +-spec box_NONCEBYTES() -> pos_integer(). +box_NONCEBYTES() -> enacl_nif:crypto_box_NONCEBYTES(). %% @private --spec box_public_key_bytes() -> pos_integer(). -box_public_key_bytes() -> +-spec box_PUBLICKEYBYTES() -> pos_integer(). +box_PUBLICKEYBYTES() -> enacl_nif:crypto_box_PUBLICKEYBYTES(). %% @private -box_beforenm_bytes() -> +box_BEFORENMBYTES() -> enacl_nif:crypto_box_BEFORENMBYTES(). %% Signatures %% @private -sign_keypair_public_size() -> +sign_PUBLICBYTES() -> enacl_nif:crypto_sign_PUBLICKEYBYTES(). %% @private -sign_keypair_secret_size() -> +sign_SECRETBYTES() -> enacl_nif:crypto_sign_SECRETKEYBYTES(). %% @private -sign_keypair_seed_size() -> +sign_SEEDBYTES() -> enacl_nif:crypto_sign_SEEDBYTES(). %% @doc sign_keypair/0 returns a signature keypair for signing @@ -666,8 +666,8 @@ sign_final_verify(SignState, SIG, PK) -> enacl_nif:crypto_sign_final_verify(SignState, SIG, PK). %% @private --spec box_secret_key_bytes() -> pos_integer(). -box_secret_key_bytes() -> +-spec box_SECRETKEYBYTES() -> pos_integer(). +box_SECRETKEYBYTES() -> enacl_nif:crypto_box_SECRETKEYBYTES(). %% @doc seal_box/2 encrypts an anonymous message to another party. @@ -741,30 +741,30 @@ secretbox_open(CipherText, Nonce, Key) -> enacl_nif:crypto_secretbox_open([?S_BOXZEROBYTES, CipherText], Nonce, Key) end. -%% @doc secretbox_nonce_size/0 returns the size of the secretbox nonce +%% @doc secretbox_NONCEBYTES()/0 returns the size of the secretbox nonce %% %% When encrypting with a secretbox, the nonce must have this size %% @end -secretbox_nonce_size() -> +secretbox_NONCEBYTES() -> enacl_nif:crypto_secretbox_NONCEBYTES(). -%% @doc secretbox_key_size/0 returns the size of the secretbox key +%% @doc secretbox_KEYBYTES/0 returns the size of the secretbox key %% %% When encrypting with a secretbox, the key must have this size %% @end -secretbox_key_size() -> +secretbox_KEYBYTES() -> enacl_nif:crypto_secretbox_KEYBYTES(). -%% @doc stream_chacha20_nonce_size/0 returns the byte size of the nonce for streams +%% @doc stream_chacha20_NONCEBYTES/0 returns the byte size of the nonce for streams %% @end --spec stream_chacha20_nonce_size() -> ?CRYPTO_STREAM_CHACHA20_NONCEBYTES. -stream_chacha20_nonce_size() -> +-spec stream_chacha20_NONCEBYTES() -> ?CRYPTO_STREAM_CHACHA20_NONCEBYTES. +stream_chacha20_NONCEBYTES() -> ?CRYPTO_STREAM_CHACHA20_NONCEBYTES. -%% @doc stream_key_size/0 returns the byte size of the key for streams +%% @doc stream_chacha20_KEYBYTES/0 returns the byte size of the key for streams %% @end --spec stream_chacha20_key_size() -> ?CRYPTO_STREAM_CHACHA20_KEYBYTES. -stream_chacha20_key_size() -> +-spec stream_chacha20_KEYBYTES() -> ?CRYPTO_STREAM_CHACHA20_KEYBYTES. +stream_chacha20_KEYBYTES() -> ?CRYPTO_STREAM_CHACHA20_KEYBYTES. %% @doc stream_chacha20/3 produces a cryptographic stream suitable for secret-key encryption @@ -812,16 +812,16 @@ stream_chacha20_xor(Msg, Nonce, Key) -> enacl_nif:crypto_stream_chacha20_xor(Msg, Nonce, Key) end. -%% @doc stream_nonce_size/0 returns the byte size of the nonce for streams +%% @doc stream_NONCEBYTES/0 returns the byte size of the nonce for streams %% @end --spec stream_nonce_size() -> ?CRYPTO_STREAM_NONCEBYTES. -stream_nonce_size() -> +-spec stream_NONCEBYTES() -> ?CRYPTO_STREAM_NONCEBYTES. +stream_NONCEBYTES() -> ?CRYPTO_STREAM_NONCEBYTES. -%% @doc stream_key_size/0 returns the byte size of the key for streams +%% @doc stream_KEYBYTES/0 returns the byte size of the key for streams %% @end --spec stream_key_size() -> ?CRYPTO_STREAM_KEYBYTES. -stream_key_size() -> +-spec stream_KEYBYTES() -> ?CRYPTO_STREAM_KEYBYTES. +stream_KEYBYTES() -> ?CRYPTO_STREAM_KEYBYTES. %% @doc stream/3 produces a cryptographic stream suitable for secret-key encryption @@ -869,16 +869,16 @@ stream_xor(Msg, Nonce, Key) -> enacl_nif:crypto_stream_xor(Msg, Nonce, Key) end. -%% @doc auth_key_size/0 returns the byte-size of the authentication key +%% @doc auth_KEYBYTES/0 returns the byte-size of the authentication key %% @end --spec auth_key_size() -> pos_integer(). -auth_key_size() -> +-spec auth_KEYBYTES() -> pos_integer(). +auth_KEYBYTES() -> enacl_nif:crypto_auth_KEYBYTES(). -%% @doc auth_size/0 returns the byte-size of the authenticator +%% @doc auth_BYTES/0 returns the byte-size of the authenticator %% @end --spec auth_size() -> pos_integer(). -auth_size() -> +-spec auth_BYTES() -> pos_integer(). +auth_BYTES() -> enacl_nif:crypto_auth_BYTES(). %% @doc auth/2 produces an authenticator (MAC) for a message @@ -893,8 +893,8 @@ auth_size() -> Authenticator :: binary(). auth(Msg, Key) -> case iolist_size(Msg) of - K when K =< ?AUTH_SIZE -> - bump(enacl_nif:crypto_auth_b(Msg, Key), ?AUTH_REDUCTIONS, ?AUTH_SIZE, K); + K when K =< ?auth_BYTES -> + bump(enacl_nif:crypto_auth_b(Msg, Key), ?AUTH_REDUCTIONS, ?auth_BYTES, K); _ -> enacl_nif:crypto_auth(Msg, Key) end. @@ -911,10 +911,10 @@ auth(Msg, Key) -> Key :: binary(). auth_verify(A, M, K) -> case iolist_size(M) of - K when K =< ?AUTH_SIZE -> + K when K =< ?auth_BYTES -> bump(enacl_nif:crypto_auth_verify_b(A, M, K), ?AUTH_REDUCTIONS, - ?AUTH_SIZE, + ?auth_BYTES, K); _ -> enacl_nif:crypto_auth_verify(A, M, K) @@ -961,10 +961,10 @@ shorthash(Msg, Key) -> Authenticator :: binary(). onetime_auth(Msg, Key) -> case iolist_size(Msg) of - K when K =< ?ONETIME_AUTH_SIZE -> + K when K =< ?ONETIME_auth_BYTES -> bump(enacl_nif:crypto_onetimeauth_b(Msg, Key), ?ONETIME_AUTH_REDUCTIONS, - ?ONETIME_AUTH_SIZE, + ?ONETIME_auth_BYTES, K); _ -> enacl_nif:crypto_onetimeauth(Msg, Key) @@ -983,25 +983,25 @@ onetime_auth(Msg, Key) -> Key :: binary(). onetime_auth_verify(A, M, K) -> case iolist_size(M) of - K when K =< ?ONETIME_AUTH_SIZE -> + K when K =< ?ONETIME_auth_BYTES -> bump(enacl_nif:crypto_onetimeauth_verify_b(A, M, K), ?ONETIME_AUTH_REDUCTIONS, - ?ONETIME_AUTH_SIZE, + ?ONETIME_auth_BYTES, K); _ -> enacl_nif:crypto_onetimeauth_verify(A, M, K) end. -%% @doc onetime_auth_size/0 returns the number of bytes of the one-time authenticator +%% @doc onetime_auth_BYTES/0 returns the number of bytes of the one-time authenticator %% @end --spec onetime_auth_size() -> pos_integer(). -onetime_auth_size() -> +-spec onetime_auth_BYTES() -> pos_integer(). +onetime_auth_BYTES() -> enacl_nif:crypto_onetimeauth_BYTES(). -%% @doc onetime_auth_key_size/0 returns the byte-size of the onetime authentication key +%% @doc onetime_auth_KEYBYTES/0 returns the byte-size of the onetime authentication key %% @end --spec onetime_auth_key_size() -> pos_integer(). -onetime_auth_key_size() -> +-spec onetime_auth_KEYBYTES() -> pos_integer(). +onetime_auth_KEYBYTES() -> enacl_nif:crypto_onetimeauth_KEYBYTES(). %% Curve 25519 Crypto diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index dec7371..2d564d1 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -133,7 +133,7 @@ sign(_Config) -> {ok, Signature} = enacl:sign_final_create(Create, SK), StateVerify = enacl:sign_init(), Verify = sign_chunked(StateVerify, Msg, 10000), - ok = enacl:sign_final_verify(Verify, Signature, PK), + true = enacl:sign_final_verify(Verify, Signature, PK), ok. sign_chunked(S, _M, 0) -> S; From fd87b9da39ca1ade9a13802db65d60c4f5c47b31 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 6 Feb 2020 13:57:49 +0100 Subject: [PATCH 080/162] Fix a bug in sign_init/0 The code path was wrong in a lot of cases in sign_init/0 so even if it succeeded it would return a failure. Fixed by cleaning up the code. --- c_src/sign.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/c_src/sign.c b/c_src/sign.c index 6a4e00a..292e31c 100644 --- a/c_src/sign.c +++ b/c_src/sign.c @@ -56,7 +56,8 @@ ERL_NIF_TERM enacl_crypto_sign_init(ErlNifEnv *env, int argc, if ((obj = enif_alloc_resource(enacl_sign_ctx_rtype, sizeof(enacl_sign_ctx))) == NULL) { - goto err; + ret = enacl_internal_error(env); + goto done; } obj->alive = 0; obj->state = enif_alloc(crypto_sign_statebytes()); @@ -90,8 +91,6 @@ free: release: // This also frees the mutex via the destructor enif_release_resource(obj); -err: - ret = enacl_internal_error(env); done: return ret; } From d013a04a582ec96f1d3cb531893b794f11819574 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 6 Feb 2020 13:59:31 +0100 Subject: [PATCH 081/162] Manage the changelog. --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d7700a..72260ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [TODO] -- Go through all calls and make them return streamlined exceptions if applicable. - Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - - Generichashes must support the finalized state +- Generichashes must support the finalized state ## [Unreleased] @@ -26,6 +24,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - The `kx` constants have been renamed to follow libsodium one-to-one. - All calls with `verify` now returns booleans. See `sign_verify_detached`, which were changed by this. +- Many constants were changed to their underlying libsodium names. ### Removed - The functions of the form `aead_chacha20poly1305_*` were removed. They implement @@ -73,6 +72,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. modules multi-part constructions in API and style. - The AEAD constructions have been streamlined so they follow the rules of libsodium closer than before. In particular, some dead code has been removed as a result. +- Constants are now named by their libsodium counterpart. This should make it easier + to find the correct names given the libsodium documentation. ### Fixed - Fix a resource leak in generichash/sign init/update/final. From 96b883ceba28bca640a6b3964451c7ffd32c92a4 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 6 Feb 2020 16:04:23 +0100 Subject: [PATCH 082/162] generichash finalization Make sure we finalize properly in generichash and check the alive state of objects. If they are not alive, return the general finalized error. --- c_src/generichash.c | 8 ++++---- test/enacl_SUITE.erl | 12 ++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/c_src/generichash.c b/c_src/generichash.c index a554d43..8f184a3 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -235,7 +235,6 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, goto bad_arg; enif_mutex_lock(obj->mtx); - if (!obj->alive) { goto err; } @@ -251,7 +250,7 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); err: - ret = enacl_internal_error(env); + ret = enacl_error_finalized(env); done: enif_mutex_unlock(obj->mtx); return ret; @@ -271,7 +270,8 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, enif_mutex_lock(obj->mtx); if (!obj->alive) { - goto bad_arg; + ret = enacl_error_finalized(env); + goto done; } if (!enif_alloc_binary(obj->outlen, &hash)) { @@ -295,7 +295,7 @@ bad_arg: release: enif_release_binary(&hash); err: - ret = enif_make_badarg(env); + ret = enacl_internal_error(env); done: enif_mutex_unlock(obj->mtx); return ret; diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index 2d564d1..9d0adb6 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -83,6 +83,18 @@ generichash_chunked(_Config) -> Expected = <<46,49,32,18,13,186,182,105,106,122,253,139,89,176,169,141, 73,93,99,6,41,216,110,41>>, Expected = enacl:generichash_final(State), + try enacl:generichash_final(State) of + _ -> ct:fail(must_finalize) + catch + error:enacl_finalized -> + ok + end, + try enacl:generichash_update(State, <<"x">>) of + _ -> ct:fail(must_finalize) + catch + error:enacl_finalized -> + ok + end, ok. generichash_chunked(State, _Msg, 0) -> State; From a3f112607c151fce7c7dd898bcc6de5304daacf3 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 6 Feb 2020 16:06:02 +0100 Subject: [PATCH 083/162] Document the notion of finalization --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72260ba..6e65dfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. closer than before. In particular, some dead code has been removed as a result. - Constants are now named by their libsodium counterpart. This should make it easier to find the correct names given the libsodium documentation. +- Generichash now checks if a `_final` call has already happened and rejects further + hashing on the object. The rejection is an error: if you ever do this, your code + is definitely wrong and there is no recovery possible. ### Fixed - Fix a resource leak in generichash/sign init/update/final. From 8e628a61fc7d918c1fa8e930e4d14103e1b63cf9 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 6 Feb 2020 16:06:21 +0100 Subject: [PATCH 084/162] Clean todo list --- CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e65dfe..6ef9abe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,6 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [TODO] - -- Generichashes must support the finalized state - ## [Unreleased] ### Compatibility From 1f7d553f75f0cd56822ee0aea01783fd97395c61 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 6 Feb 2020 16:18:25 +0100 Subject: [PATCH 085/162] Delete this sentence. It serves no purpose. --- README.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 6855150..faebfaf 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,6 @@ Frank Denis took the source and made it far more portable in the libsodium library. The enacl project is somewhat misnamed, as it uses libsodium as the underlying driver. -Several Erlang ports of NaCl/libsodium exists, but this one is a -rewrite with the following foci: - ## INSTALL/Requirements: * Erlang/OTP 17.3. This library *needs* the newest dirty scheduler @@ -21,11 +18,11 @@ rewrite with the following foci: subpackages, make sure you also get the "-dev" package containing the header files necessary in order to compile software linking to libsodium. - + To build the software execute: make - + or rebar compile @@ -33,11 +30,11 @@ or To build and run licensed eqc test execute: make eqc_run - + To build and run eqc-mini version of test execute: make eqc_mini_run - + ## Features: * Complete NaCl library, implementing all default functionality. @@ -70,12 +67,12 @@ The original NaCl documentation is nowadays largely superceded by the libsodium documentation, but it is still worth a visit https://nacl.cr.yp.to - + but also note that our interface has full Edoc documentation, generated by executing rebar3 doc - + ## Hints In general, the primitives provided by NaCl are intermediate-level @@ -283,5 +280,5 @@ no leaks in the code. just the 3 main authors. Please see the page http://nacl.cr.yp.to - + for the full list of authors. From 24859776e46b17bc9fdf0af5512e6e4abad19156 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 8 Feb 2020 11:39:43 +0100 Subject: [PATCH 086/162] Ready publishing of 1.0.0 --- CHANGELOG.md | 2 +- rebar.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ef9abe..f5e9ca4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [1.0.0] ### Compatibility - Some functions have been streamlined to badarg in certain cases where it made more diff --git a/rebar.config b/rebar.config index 36c287a..5b644b3 100644 --- a/rebar.config +++ b/rebar.config @@ -1,6 +1,6 @@ {erl_opts, [debug_info]}. -{plugins, [pc]}. +{plugins, [pc, rebar3_hex]}. {provider_hooks, [ {pre, [ From 8c13fc682eac106658073424e9756306e69132bf Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 8 Feb 2020 11:39:51 +0100 Subject: [PATCH 087/162] v1.0.0 --- src/enacl.app.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/enacl.app.src b/src/enacl.app.src index d8c57e8..389f2bf 100644 --- a/src/enacl.app.src +++ b/src/enacl.app.src @@ -1,6 +1,6 @@ {application,enacl, [{description,"Erlang libsodium (NaCl) bindings"}, - {vsn,"0.17.2"}, + {vsn,"1.0.0"}, {registered,[]}, {applications,[kernel,stdlib]}, {env,[]}, From 2045ca8e09ebfd7914a1cbd0324cb5cf2d3461ae Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 10 Feb 2020 14:21:11 +0100 Subject: [PATCH 088/162] Slightly better wording in documentation --- src/enacl.erl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/enacl.erl b/src/enacl.erl index 5fe4714..c3cb393 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -8,9 +8,9 @@ %%% portable variant of the NaCl library. The C-level API is interchangeable so we can run %%% on any of these underlying libraries as seen from the Erlang world. We simply have to %%% restrict ourselves to the portion of the code base which is overlapping.

-%%%

Warning: The cryptographic strength of your implementation is no stronger than -%%% plaintext cryptography unless you take care in using these primitives correctly. Hence, -%%% implementors should use these primitives with that in mind.

+%%%

Warning: It is necessary to apply the primitives here correctly. Wrong +%%% application may result in severely reduced strength of the cryptography. Take some +%%% time to make sure this is the case before using.

%%%

Note: All functions will fail with a `badarg' error if given incorrect %%% parameters.

%%% @end. @@ -628,14 +628,14 @@ sign_verify_detached(SIG, M, PK) -> %% @doc sign_init/0 initialize a multi-part signature state. %% -%% This state must be passed to all future calls to `sign_update/2`, -%% `sign_final_create/2` and `sign_final_verify/3`. +%% This state must be passed to all future calls to `sign_update/2', +%% `sign_final_create/2' and `sign_final_verify/3'. %% @end -spec sign_init() -> sign_state(). sign_init() -> enacl_nif:crypto_sign_init(). -%% @doc sign_update/2 update the signature state `S` with a new chunk of data `M`. +%% @doc sign_update/2 update the signature state `S' with a new chunk of data `M'. %% @end -spec sign_update(S, M) -> sign_state() | {error, sign_update_error} when S :: sign_state(), @@ -645,7 +645,7 @@ sign_update(SignState, M) -> %% @doc sign_final_create/2 computes the signature for the previously supplied -%% message(s) using the secret key `SK`. +%% message(s) using the secret key `SK'. %% @end -spec sign_final_create(S, SK) -> {ok, binary()} | {error, atom()} when S :: sign_state(), @@ -655,8 +655,8 @@ sign_final_create(SignState, SK) -> %% @doc sign_final_verify/3 verify a chunked signature %% -%% Verifies that `SIG` is a valid signature for the message whose content has -%% been previously supplied using `sign_update/2` using the public key `PK.` +%% Verifies that `SIG' is a valid signature for the message whose content has +%% been previously supplied using `sign_update/2' using the public key `PK.' %% @end -spec sign_final_verify(S, SIG, PK) -> boolean() when S :: sign_state(), From 218a6db09c97f1c4f194953b4b0a08fd0c02b9eb Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 10 Feb 2020 14:23:28 +0100 Subject: [PATCH 089/162] More documentation. --- src/enacl.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/enacl.erl b/src/enacl.erl index c3cb393..25521b1 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -12,7 +12,10 @@ %%% application may result in severely reduced strength of the cryptography. Take some %%% time to make sure this is the case before using.

%%%

Note: All functions will fail with a `badarg' error if given incorrect -%%% parameters.

+%%% parameters. Also, if something is wrong internally, they will raise an error of +%%% the form `enacl_internal_error'. There is usually no way to continue gracefully +%%% from either of these. A third error is `enacl_finalized`, raised when you try +%%% re-using an already finalized state for multi-part messages.

%%% @end. -module(enacl). From 220ac6640a1b78160345256d76d18bcff744f536 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 10 Feb 2020 14:24:05 +0100 Subject: [PATCH 090/162] Fixup edoc compilation --- src/enacl.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/enacl.erl b/src/enacl.erl index 25521b1..7024e8f 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -14,7 +14,7 @@ %%%

Note: All functions will fail with a `badarg' error if given incorrect %%% parameters. Also, if something is wrong internally, they will raise an error of %%% the form `enacl_internal_error'. There is usually no way to continue gracefully -%%% from either of these. A third error is `enacl_finalized`, raised when you try +%%% from either of these. A third error is `enacl_finalized', raised when you try %%% re-using an already finalized state for multi-part messages.

%%% @end. -module(enacl). From e32c92382271eafd4af61942f1d47d0d02303fc4 Mon Sep 17 00:00:00 2001 From: Alexander Malaev Date: Fri, 21 Feb 2020 18:34:54 +0300 Subject: [PATCH 091/162] Add crypto_secretstream_* functions. --- c_src/enacl_nif.c | 23 ++- c_src/secretstream.c | 461 +++++++++++++++++++++++++++++++++++++++++++ c_src/secretstream.h | 78 ++++++++ src/enacl.erl | 195 +++++++++++++++++- src/enacl_nif.erl | 33 ++++ 5 files changed, 788 insertions(+), 2 deletions(-) create mode 100644 c_src/secretstream.c create mode 100644 c_src/secretstream.h diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index acf1ba6..2333c18 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -14,6 +14,7 @@ #include "randombytes.h" #include "secret.h" #include "sign.h" +#include "secretstream.h" #ifdef ERL_NIF_DIRTY_JOB_CPU_BOUND #define erl_nif_dirty_job_cpu_bound_macro(a, b, c) \ @@ -35,6 +36,10 @@ static int enacl_crypto_load(ErlNifEnv *env, void **priv_data, return -1; } + if (!enacl_init_secretstream_ctx(env)) { + return -1; + } + return sodium_init(); } @@ -372,8 +377,24 @@ static ErlNifFunc nif_funcs[] = { erl_nif_dirty_job_cpu_bound_macro("crypto_generichash_update", 2, enacl_crypto_generichash_update), erl_nif_dirty_job_cpu_bound_macro("crypto_generichash_final", 1, - enacl_crypto_generichash_final) + enacl_crypto_generichash_final), + {"crypto_secretstream_xchacha20poly1305_ABYTES", 0, enacl_crypto_secretstream_xchacha20poly1305_ABYTES}, + {"crypto_secretstream_xchacha20poly1305_HEADERBYTES", 0, enacl_crypto_secretstream_xchacha20poly1305_HEADERBYTES}, + {"crypto_secretstream_xchacha20poly1305_KEYBYTES", 0, enacl_crypto_secretstream_xchacha20poly1305_KEYBYTES}, + {"crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX", 0, enacl_crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX}, + {"crypto_secretstream_xchacha20poly1305_TAG_MESSAGE", 0, enacl_crypto_secretstream_xchacha20poly1305_TAG_MESSAGE}, + {"crypto_secretstream_xchacha20poly1305_TAG_PUSH", 0, enacl_crypto_secretstream_xchacha20poly1305_TAG_PUSH}, + {"crypto_secretstream_xchacha20poly1305_TAG_REKEY", 0, enacl_crypto_secretstream_xchacha20poly1305_TAG_REKEY}, + {"crypto_secretstream_xchacha20poly1305_TAG_FINAL", 0, enacl_crypto_secretstream_xchacha20poly1305_TAG_FINAL}, + {"crypto_secretstream_xchacha20poly1305_keygen", 0, enacl_crypto_secretstream_xchacha20poly1305_keygen}, + {"crypto_secretstream_xchacha20poly1305_init_push", 1, enacl_crypto_secretstream_xchacha20poly1305_init_push}, + {"crypto_secretstream_xchacha20poly1305_init_pull", 2, enacl_crypto_secretstream_xchacha20poly1305_init_pull}, + {"crypto_secretstream_xchacha20poly1305_rekey", 1, enacl_crypto_secretstream_xchacha20poly1305_rekey}, + erl_nif_dirty_job_cpu_bound_macro("crypto_secretstream_xchacha20poly1305_push", 4, + enacl_crypto_secretstream_xchacha20poly1305_push), + erl_nif_dirty_job_cpu_bound_macro("crypto_secretstream_xchacha20poly1305_pull", 3, + enacl_crypto_secretstream_xchacha20poly1305_pull) }; ERL_NIF_INIT(enacl_nif, nif_funcs, enacl_crypto_load, NULL, NULL, NULL); diff --git a/c_src/secretstream.c b/c_src/secretstream.c new file mode 100644 index 0000000..c29ec1b --- /dev/null +++ b/c_src/secretstream.c @@ -0,0 +1,461 @@ +#include +#include + +#include "enacl.h" +#include "secretstream.h" + +typedef struct enacl_secretstream_ctx { + ErlNifMutex *mtx; + crypto_secretstream_xchacha20poly1305_state *state; // The underlying secretstream state + int alive; // Is the context still valid for updates/finalization +} enacl_secretstream_ctx; + +ErlNifResourceType *enacl_secretstream_ctx_rtype = NULL; + +static void enacl_secretstream_ctx_dtor(ErlNifEnv *env, + enacl_secretstream_ctx *); + +int enacl_init_secretstream_ctx(ErlNifEnv *env) { + enacl_secretstream_ctx_rtype = + enif_open_resource_type(env, NULL, "enacl_secretstream_context", + (ErlNifResourceDtor *)enacl_secretstream_ctx_dtor, + ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL); + + if (enacl_secretstream_ctx_rtype == NULL) + return 0; + + return 1; +} + +static void enacl_secretstream_ctx_dtor(ErlNifEnv *env, + enacl_secretstream_ctx *obj) { + if (!obj->alive) { + return; + } + + if (obj->state) + sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes()); + enif_free(obj->state); + + if (obj->mtx != NULL) + enif_mutex_destroy(obj->mtx); + + return; +} + +/* + * Secretstream + */ + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_ABYTES( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_ABYTES); + +} + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_HEADERBYTES( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_HEADERBYTES); +} + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_KEYBYTES( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_KEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX); +} + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_MESSAGE( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + + return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_MESSAGE); +} + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_PUSH( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + + return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_PUSH); +} + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_REKEY( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + + return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_REKEY); +} + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_FINAL( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + + return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_FINAL); +} + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_keygen( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + + ErlNifBinary key; + + if (argc != 0) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_secretstream_xchacha20poly1305_KEYBYTES, &key)) { + return enacl_internal_error(env); + } + + crypto_secretstream_xchacha20poly1305_keygen(key.data); + + return enif_make_binary(env, &key); +} + +/* + int crypto_secretstream_xchacha20poly1305_init_push + (crypto_secretstream_xchacha20poly1305_state *state, + unsigned char out[crypto_secretstream_xchacha20poly1305_HEADERBYTES], + const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) +*/ +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_push( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ) { + ERL_NIF_TERM ret; + ErlNifBinary key, header; + enacl_secretstream_ctx *obj = NULL; + + if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &key))) { + goto bad_arg; + } + + if (key.size != crypto_secretstream_xchacha20poly1305_KEYBYTES) { + goto bad_arg; + } + + if (!enif_alloc_binary(crypto_secretstream_xchacha20poly1305_HEADERBYTES, &header)) { + ret = enacl_internal_error(env); + goto done; + } + + if((obj = enif_alloc_resource(enacl_secretstream_ctx_rtype, + sizeof(enacl_secretstream_ctx))) == NULL) { + ret = enacl_internal_error(env); + goto release_header; + } + obj->alive = 0; + obj->state = enif_alloc(crypto_secretstream_xchacha20poly1305_statebytes()); + + if (obj->state == NULL) { + goto release; + } + obj->alive = 1; + + if ((obj->mtx = enif_mutex_create("enacl.secretstream")) == NULL) { + goto free; + } + + crypto_secretstream_xchacha20poly1305_init_push(obj->state, header.data, key.data); + + ret = enif_make_tuple2(env, + enif_make_binary(env, &header), + enif_make_resource(env, obj) + ); + + goto release; + +bad_arg: + return enif_make_badarg(env); +free: + if (obj->alive) + if (obj->state != NULL) { + sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes()); + enif_free(obj->state); + obj->state = NULL; + } +release: + // This also frees the mutex via the destructor + enif_release_resource(obj); +release_header: + enif_release_binary(&header); +done: + return ret; +} + +/* +crypto_secretstream_xchacha20poly1305_init_pull + (crypto_secretstream_xchacha20poly1305_state *state, + const unsigned char in[crypto_secretstream_xchacha20poly1305_HEADERBYTES], + const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) +*/ +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_pull( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ) { + ERL_NIF_TERM ret; + ErlNifBinary header, key; + enacl_secretstream_ctx *obj = NULL; + + if (argc != 2) { + goto bad_arg; + } + + if(!enif_inspect_binary(env, argv[0], &header)) { + goto bad_arg; + } + + if(!enif_inspect_binary(env, argv[1], &key)) { + goto bad_arg; + } + + if ((key.size != crypto_secretstream_xchacha20poly1305_KEYBYTES) || + (header.size != crypto_secretstream_xchacha20poly1305_HEADERBYTES)) + { + goto bad_arg; + } + + if((obj = enif_alloc_resource(enacl_secretstream_ctx_rtype, + sizeof(enacl_secretstream_ctx))) == NULL) { + ret = enacl_internal_error(env); + goto done; + } + + obj->alive = 0; + obj->state = enif_alloc(crypto_secretstream_xchacha20poly1305_statebytes()); + + if (obj->state == NULL) { + goto release; + } + obj->alive = 1; + + if ((obj->mtx = enif_mutex_create("enacl.secretstream")) == NULL) { + goto free; + } + + crypto_secretstream_xchacha20poly1305_init_pull(obj->state, header.data, key.data); + + ret = enif_make_resource(env, obj); + + goto release; + +bad_arg: + return enif_make_badarg(env); +free: + if (obj->alive) + if (obj->state != NULL) { + sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes()); + enif_free(obj->state); + obj->state = NULL; + } +release: + // This also frees the mutex via the destructor + enif_release_resource(obj); +done: + return ret; +} + +/* +void +crypto_secretstream_xchacha20poly1305_rekey + (crypto_secretstream_xchacha20poly1305_state *state) +*/ +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_rekey( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ) { + ERL_NIF_TERM ret; + enacl_secretstream_ctx *obj = NULL; + + if (argc != 1) { + goto bad_arg; + } + + if(!enif_get_resource(env, argv[0], + (ErlNifResourceType *) enacl_secretstream_ctx_rtype, + (void **)&obj)) { + goto bad_arg; + } + + enif_mutex_lock(obj->mtx); + if (!obj->alive) { + goto err; + } + + crypto_secretstream_xchacha20poly1305_rekey(obj->state); + + ret = enif_make_atom(env, ATOM_OK); + + goto done; + +bad_arg: + return enif_make_badarg(env); +err: + ret = enacl_error_finalized(env); +done: + enif_mutex_unlock(obj->mtx); + return ret; +} + +/* +int +crypto_secretstream_xchacha20poly1305_push + (crypto_secretstream_xchacha20poly1305_state *state, + unsigned char *out, unsigned long long *outlen_p, + const unsigned char *m, unsigned long long mlen, + const unsigned char *ad, unsigned long long adlen, unsigned char tag) +*/ +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_push( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ) { + ERL_NIF_TERM ret; + ErlNifBinary m, ad, out; + ErlNifUInt64 tag; + enacl_secretstream_ctx *obj = NULL; + + if (argc != 4) { + goto bad_arg; + } + + if(!enif_get_resource(env, argv[0], + (ErlNifResourceType *) enacl_secretstream_ctx_rtype, + (void **)&obj)) { + goto bad_arg; + } + + if(!enif_inspect_binary(env, argv[1], &m)) { + goto bad_arg; + } + + if(!enif_inspect_binary(env, argv[2], &ad)) { + goto bad_arg; + } + + if(!enif_get_uint64(env, argv[3], &tag)) { + goto bad_arg; + } + + if (!enif_alloc_binary(m.size + crypto_secretstream_xchacha20poly1305_ABYTES, &out)) { + return enacl_internal_error(env); + } + + enif_mutex_lock(obj->mtx); + if (!obj->alive) { + goto err; + } + + crypto_secretstream_xchacha20poly1305_push(obj->state, out.data, NULL, m.data, m.size, ad.data, ad.size, tag); + + if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL) { + if(obj->state) { + obj->alive = 0; + sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes()); + enif_free(obj->state); + obj->state = NULL; + } + } + + ret = enif_make_binary(env, &out); + + goto done; + +bad_arg: + return enif_make_badarg(env); +err: + ret = enacl_error_finalized(env); + enif_release_binary(&out); +done: + enif_mutex_unlock(obj->mtx); + return ret; +} + +/* + crypto_secretstream_xchacha20poly1305_pull + (crypto_secretstream_xchacha20poly1305_state *state, + unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p, + const unsigned char *in, unsigned long long inlen, + const unsigned char *ad, unsigned long long adlen) + */ +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_pull( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ) { + ERL_NIF_TERM ret; + ErlNifBinary m, in, ad; + unsigned char tag; + enacl_secretstream_ctx *obj = NULL; + + if (argc != 3) { + goto bad_arg; + } + + if(!enif_get_resource(env, argv[0], + (ErlNifResourceType *) enacl_secretstream_ctx_rtype, + (void **)&obj)) { + goto bad_arg; + } + + if(!enif_inspect_binary(env, argv[1], &in)) { + goto bad_arg; + } + + if(in.size < crypto_secretstream_xchacha20poly1305_ABYTES) { + goto bad_arg; + } + + if(!enif_inspect_binary(env, argv[2], &ad)) { + goto bad_arg; + } + + if(in.size < crypto_secretstream_xchacha20poly1305_ABYTES) { + goto bad_arg; + } + + if (!enif_alloc_binary(in.size - crypto_secretstream_xchacha20poly1305_ABYTES, &m)) { + return enacl_internal_error(env); + } + + enif_mutex_lock(obj->mtx); + if(!obj->alive) { + goto err; + } + + if (0 != crypto_secretstream_xchacha20poly1305_pull(obj->state, m.data, NULL, &tag, in.data, in.size, ad.data, ad.size)) { + ret = enacl_error_tuple(env, "failed_verification"); + goto release; + } + + if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL) { + if(obj->state) { + obj->alive = 0; + sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes()); + enif_free(obj->state); + obj->state = NULL; + } + } + + ret = enif_make_tuple2(env, + enif_make_binary(env, &m), + enif_make_int64(env, tag) + ); + + goto done; + +bad_arg: + return enif_make_badarg(env); +err: + ret = enacl_error_finalized(env); +release: + enif_release_binary(&m); +done: + enif_mutex_unlock(obj->mtx); + return ret; +} diff --git a/c_src/secretstream.h b/c_src/secretstream.h new file mode 100644 index 0000000..4f1f4bd --- /dev/null +++ b/c_src/secretstream.h @@ -0,0 +1,78 @@ +#ifndef ENACL_SECRETSTREAM_H +#define ENACL_SECRETSTREAM_H + +#include + +int enacl_init_secretstream_ctx(ErlNifEnv *env); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_ABYTES( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_HEADERBYTES( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_KEYBYTES( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_MESSAGE( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_PUSH( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_REKEY( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_FINAL( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_keygen( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_push( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_pull( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_rekey( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_push( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_pull( + ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[] + ); + +#endif diff --git a/src/enacl.erl b/src/enacl.erl index 7024e8f..92f2605 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -174,6 +174,25 @@ kx_SESSIONKEYBYTES/0 ]). +%% Secretstream operations. +-export([ + %% No Tests! + secretstream_xchacha20poly1305_ABYTES/0, + secretstream_xchacha20poly1305_HEADERBYTES/0, + secretstream_xchacha20poly1305_KEYBYTES/0, + secretstream_xchacha20poly1305_MESSAGEBYTES_MAX/0, + secretstream_xchacha20poly1305_TAG_MESSAGE/0, + secretstream_xchacha20poly1305_TAG_PUSH/0, + secretstream_xchacha20poly1305_TAG_REKEY/0, + secretstream_xchacha20poly1305_TAG_FINAL/0, + secretstream_xchacha20poly1305_keygen/0, + secretstream_xchacha20poly1305_init_push/1, + secretstream_xchacha20poly1305_push/4, + secretstream_xchacha20poly1305_init_pull/2, + secretstream_xchacha20poly1305_pull/3, + secretstream_xchacha20poly1305_rekey/1 + ]). + %% Internal verification of the system -export([verify/0]). @@ -224,6 +243,11 @@ -define(CRYPTO_GENERICHASH_KEYBYTES_MAX, 64). -define(CRYPTO_GENERICHASH_KEYBYTES, 32). +-define(CRYPTO_SECRETSTREAM_TAG_MESSAGE, 0). +-define(CRYPTO_SECRETSTREAM_TAG_PUSH, 1). +-define(CRYPTO_SECRETSTREAM_TAG_REKEY, 2). +-define(CRYPTO_SECRETSTREAM_TAG_FINAL, 3). + %% Size limits -define(MAX_32BIT_INT, 1 bsl 32). @@ -253,7 +277,11 @@ verify() -> {crypto_generichash_BYTES_MAX, ?CRYPTO_GENERICHASH_BYTES_MAX}, {crypto_generichash_KEYBYTES, ?CRYPTO_GENERICHASH_KEYBYTES}, {crypto_generichash_KEYBYTES_MIN, ?CRYPTO_GENERICHASH_KEYBYTES_MIN}, - {crypto_generichash_KEYBYTES_MAX, ?CRYPTO_GENERICHASH_KEYBYTES_MAX} + {crypto_generichash_KEYBYTES_MAX, ?CRYPTO_GENERICHASH_KEYBYTES_MAX}, + {crypto_secretstream_xchacha20poly1305_TAG_MESSAGE, ?CRYPTO_SECRETSTREAM_TAG_MESSAGE}, + {crypto_secretstream_xchacha20poly1305_TAG_PUSH, ?CRYPTO_SECRETSTREAM_TAG_PUSH}, + {crypto_secretstream_xchacha20poly1305_TAG_REKEY, ?CRYPTO_SECRETSTREAM_TAG_REKEY}, + {crypto_secretstream_xchacha20poly1305_TAG_FINAL, ?CRYPTO_SECRETSTREAM_TAG_FINAL} ], run_verifiers(Verifiers). @@ -1246,7 +1274,172 @@ aead_xchacha20poly1305_ietf_ABYTES() -> aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX() -> enacl_nif:crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX(). +%% Secretstream +%% ---------------------- +%% @doc secretstream_xchacha20poly1305_ABYTES/0 returns the number of bytes +%% of the MAC used on secretstream encryption/decryption +%% @end +-spec secretstream_xchacha20poly1305_ABYTES() -> pos_integer(). +secretstream_xchacha20poly1305_ABYTES() -> + enacl_nif:crypto_secretstream_xchacha20poly1305_ABYTES(). + +%% @doc secretstream_xchacha20poly1305_HEADERBYTES/0 returns the number +%% of bytes for header used in secretstream encryption/decryption. +%% @end +-spec secretstream_xchacha20poly1305_HEADERBYTES() -> pos_integer(). +secretstream_xchacha20poly1305_HEADERBYTES() -> + enacl_nif:crypto_secretstream_xchacha20poly1305_HEADERBYTES(). + +%% @doc secretstream_xchacha20poly1305_KEYBYTES/0 returns the number +%% of bytes of the key used in secretstream encryption/decryption. +%% @end +-spec secretstream_xchacha20poly1305_KEYBYTES() -> pos_integer(). +secretstream_xchacha20poly1305_KEYBYTES() -> + enacl_nif:crypto_secretstream_xchacha20poly1305_KEYBYTES(). + +%% @doc secretstream_xchacha20poly1305_MESSAGEBYTES_MAX/0 returns the max +%% number of bytes allowed in a message in secretstream encryption/decryption. +%% @end +-spec secretstream_xchacha20poly1305_MESSAGEBYTES_MAX() -> pos_integer(). +secretstream_xchacha20poly1305_MESSAGEBYTES_MAX() -> + enacl_nif:crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX(). + +%% @doc secretstream_xchacha20poly1305_TAG_MESSAGE/0 returns integer value +%% of tag `message'. The most common tag, that doesn't add any information +%% about the nature of the message. +%% @end +-spec secretstream_xchacha20poly1305_TAG_MESSAGE() -> pos_integer(). +secretstream_xchacha20poly1305_TAG_MESSAGE() -> + enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_MESSAGE(). + +%% @doc secretstream_xchacha20poly1305_TAG_PUSH/0 returns integer value +%% of tag `push'. +%% +%% This tag indicates that the message marks the end +%% of a set of messages, but not the end of the stream. +%% +%% For example, a huge JSON string sent as multiple chunks can use +%% this tag to indicate to the application that the string is complete +%% and that it can be decoded. But the stream itself is not closed, +%% and more data may follow. +%% @end +-spec secretstream_xchacha20poly1305_TAG_PUSH() -> pos_integer(). +secretstream_xchacha20poly1305_TAG_PUSH() -> + enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_PUSH(). + +%% @doc secretstream_xchacha20poly1305_TAG_REKEY/0 returns integer value +%% of tag `rekey'. Indicates that next messages will derive new keys. +%% @end +-spec secretstream_xchacha20poly1305_TAG_REKEY() -> pos_integer(). +secretstream_xchacha20poly1305_TAG_REKEY() -> + enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_REKEY(). + +%% @doc secretstream_xchacha20poly1305_TAG_FINAL/0 returns integer value +%% of tag `final'. Indicates that the message is the last message in +%% the secretstream. +%% @end +-spec secretstream_xchacha20poly1305_TAG_FINAL() -> pos_integer(). +secretstream_xchacha20poly1305_TAG_FINAL() -> + enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_FINAL(). + +%% @doc secretstream_xchacha20poly1305_keygen/0 returns new random key +%% for secretsteam encryption. +%% @end +-spec secretstream_xchacha20poly1305_keygen() -> binary(). +secretstream_xchacha20poly1305_keygen() -> + enacl_nif:crypto_secretstream_xchacha20poly1305_keygen(). + +%% @doc secretstream_xchacha20poly1305_init_push/1 +%% initializes a secretstream encryption context using given `key'. +%% Returns `Header' and reference to encryption context. +%% @end +-spec secretstream_xchacha20poly1305_init_push(Key) -> {binary(), reference()} + when Key :: binary(). +secretstream_xchacha20poly1305_init_push(Key) -> + enacl_nif:crypto_secretstream_xchacha20poly1305_init_push(Key). + +-type secretstream_xchacha20poly1305_tag() :: message | rekey | final | push | pos_integer(). +%% @doc secretstream_xchacha20poly1305_push/4 returns encrypted chunk binary. +%% Updates a secretstream context referenced by `Ref' with `Message' data, +%% given `Tag' and additional data `AD'. +%% @end +-spec secretstream_xchacha20poly1305_push(Ref, Message, AD, Tag) -> binary() + when + Ref :: reference(), + Message :: binary(), + AD :: binary(), + Tag :: secretstream_xchacha20poly1305_tag(). +secretstream_xchacha20poly1305_push(Ref, Message, AD, Tag) -> + TagValue = secretstream_xchacha20poly1305_tag_value(Tag), + + enacl_nif:crypto_secretstream_xchacha20poly1305_push(Ref, Message, AD, TagValue). + +%% @doc secretstream_xchacha20poly1305_init_pull/3 +%% initializes a secretstream decryption context using `Header' and `Key'. +%% Returns reference to decryption context. +%% @end +-spec secretstream_xchacha20poly1305_init_pull(Header, Key) -> reference() + when + Header :: binary(), + Key :: binary(). +secretstream_xchacha20poly1305_init_pull(Header, Key) -> + enacl_nif:crypto_secretstream_xchacha20poly1305_init_pull(Header, Key). + +%% @doc secretstream_xchacha20poly1305_pull/3 decrypts `CipherText' +%% with additional data `AD' in referenced decryption context `Ref'. +%% @end +-spec secretstream_xchacha20poly1305_pull(Ref, CipherText, AD) -> + {binary(), secretstream_xchacha20poly1305_tag()} | {error, failed_verification} + when + Ref :: reference(), + CipherText :: binary(), + AD :: binary(). +secretstream_xchacha20poly1305_pull(Ref, CipherText, AD) -> + {Message, TagValue} = enacl_nif:crypto_secretstream_xchacha20poly1305_pull(Ref, CipherText, AD), + {Message, secretstream_xchacha20poly1305_tag(TagValue)}. + +%% @doc secretstream_xchacha20poly1305_rekey/1 updates encryption/decryption context state. +%% This doesn't add any information about key update to stream. +%% If this function is used to create an encrypted stream, +%% the decryption process must call that function at the exact same stream location. +%% @end +-spec secretstream_xchacha20poly1305_rekey(Ref) -> ok + when Ref :: reference(). +secretstream_xchacha20poly1305_rekey(Ref) -> + enacl_nif:crypto_secretstream_xchacha20poly1305_rekey(Ref). + +%% @doc secretstream_xchacha20poly1305_tag_value/1 returns integer value of tag. +%% @end +-spec secretstream_xchacha20poly1305_tag_value(TagName) -> pos_integer() + when TagName :: secretstream_xchacha20poly1305_tag(). +secretstream_xchacha20poly1305_tag_value(message) -> + enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_MESSAGE(); +secretstream_xchacha20poly1305_tag_value(rekey) -> + enacl_nif:crypto_secretstream_xcacha20poly1305_TAG_REKEY(); +secretstream_xchacha20poly1305_tag_value(push) -> + enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_PUSH(); +secretstream_xchacha20poly1305_tag_value(final) -> + enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_FINAL(); +secretstream_xchacha20poly1305_tag_value(Other) -> + Other. + +%% @doc secretstream_xchacha20poly1305_tag/1 returns tag name +%% @end +-spec secretstream_xchacha20poly1305_tag(TagValue) -> secretstream_xchacha20poly1305_tag() + when TagValue :: pos_integer(). +secretstream_xchacha20poly1305_tag(?CRYPTO_SECRETSTREAM_TAG_MESSAGE) -> + message; +secretstream_xchacha20poly1305_tag(?CRYPTO_SECRETSTREAM_TAG_PUSH) -> + push; +secretstream_xchacha20poly1305_tag(?CRYPTO_SECRETSTREAM_TAG_REKEY) -> + rekey; +secretstream_xchacha20poly1305_tag(?CRYPTO_SECRETSTREAM_TAG_FINAL) -> + final; +secretstream_xchacha20poly1305_tag(Other) -> + Other. + %% Obtaining random bytes +%% ---------------------- %% @doc randombytes/1 produces a stream of random bytes of the given size %% diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 1309a11..f2255f8 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -166,6 +166,24 @@ crypto_generichash_final/1 ]). +%% Secretstream +-export([ + crypto_secretstream_xchacha20poly1305_ABYTES/0, + crypto_secretstream_xchacha20poly1305_HEADERBYTES/0, + crypto_secretstream_xchacha20poly1305_KEYBYTES/0, + crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX/0, + crypto_secretstream_xchacha20poly1305_TAG_MESSAGE/0, + crypto_secretstream_xchacha20poly1305_TAG_PUSH/0, + crypto_secretstream_xchacha20poly1305_TAG_REKEY/0, + crypto_secretstream_xchacha20poly1305_TAG_FINAL/0, + crypto_secretstream_xchacha20poly1305_keygen/0, + crypto_secretstream_xchacha20poly1305_init_push/1, + crypto_secretstream_xchacha20poly1305_push/4, + crypto_secretstream_xchacha20poly1305_init_pull/2, + crypto_secretstream_xchacha20poly1305_pull/3, + crypto_secretstream_xchacha20poly1305_rekey/1 + ]). + %% Access to the RNG -export([ randombytes/1, @@ -205,6 +223,21 @@ crypto_generichash_init(_HashSize, _Key) -> erlang:nif_error(nif_not_loaded). crypto_generichash_update(_HashState, _Message) -> erlang:nif_error(nif_not_loaded). crypto_generichash_final(_HashState) -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_ABYTES() -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_HEADERBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_KEYBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_TAG_MESSAGE() -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_TAG_PUSH() -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_TAG_REKEY() -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_TAG_FINAL() -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_keygen() -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_init_push(_Key) -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_push(_Ref, _Message, _AD, _Tag) -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_init_pull(_Header, _Key) -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_pull(_Ref, _CipherText, _AD) -> erlang:nif_error(nif_not_loaded). +crypto_secretstream_xchacha20poly1305_rekey(_Ref) -> erlang:nif_error(nif_not_loaded). + crypto_pwhash(_Password, _Salt, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str(_Password, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded). From 67fe9c7863cc7ad699eebff4b1b2b74f115459cc Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 7 Mar 2020 11:33:11 +0100 Subject: [PATCH 092/162] Track we have added secretstream support --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5e9ca4..8c0b3ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [unreleased] + +### Added + +- Secretstream support was added to the API (Alexander Malaev) + ## [1.0.0] ### Compatibility From 8361450745bdb93312ba2a3356639dd27a94e116 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 7 Mar 2020 12:01:27 +0100 Subject: [PATCH 093/162] Format; release resources In the push path, release resources in a stack fashion. This avoids releasing a binary incorrectly. --- c_src/secretstream.c | 203 +++++++++++++++++++++---------------------- 1 file changed, 101 insertions(+), 102 deletions(-) diff --git a/c_src/secretstream.c b/c_src/secretstream.c index c29ec1b..51414e7 100644 --- a/c_src/secretstream.c +++ b/c_src/secretstream.c @@ -1,25 +1,26 @@ -#include #include +#include #include "enacl.h" #include "secretstream.h" typedef struct enacl_secretstream_ctx { ErlNifMutex *mtx; - crypto_secretstream_xchacha20poly1305_state *state; // The underlying secretstream state - int alive; // Is the context still valid for updates/finalization + crypto_secretstream_xchacha20poly1305_state + *state; // The underlying secretstream state + int alive; // Is the context still valid for updates/finalization } enacl_secretstream_ctx; ErlNifResourceType *enacl_secretstream_ctx_rtype = NULL; static void enacl_secretstream_ctx_dtor(ErlNifEnv *env, - enacl_secretstream_ctx *); + enacl_secretstream_ctx *); int enacl_init_secretstream_ctx(ErlNifEnv *env) { enacl_secretstream_ctx_rtype = - enif_open_resource_type(env, NULL, "enacl_secretstream_context", - (ErlNifResourceDtor *)enacl_secretstream_ctx_dtor, - ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL); + enif_open_resource_type(env, NULL, "enacl_secretstream_context", + (ErlNifResourceDtor *)enacl_secretstream_ctx_dtor, + ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL); if (enacl_secretstream_ctx_rtype == NULL) return 0; @@ -34,8 +35,9 @@ static void enacl_secretstream_ctx_dtor(ErlNifEnv *env, } if (obj->state) - sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes()); - enif_free(obj->state); + sodium_memzero(obj->state, + crypto_secretstream_xchacha20poly1305_statebytes()); + enif_free(obj->state); if (obj->mtx != NULL) enif_mutex_destroy(obj->mtx); @@ -47,62 +49,57 @@ static void enacl_secretstream_ctx_dtor(ErlNifEnv *env, * Secretstream */ -ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_ABYTES( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]) { +ERL_NIF_TERM +enacl_crypto_secretstream_xchacha20poly1305_ABYTES(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_ABYTES); - } ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_HEADERBYTES( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]) { - return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_HEADERBYTES); + ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { + return enif_make_int64(env, + crypto_secretstream_xchacha20poly1305_HEADERBYTES); } ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_KEYBYTES( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]) { + ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_KEYBYTES); } ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]) { - return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX); + ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { + return enif_make_int64( + env, crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX); } ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_MESSAGE( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]) { + ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_MESSAGE); + return enif_make_int64(env, + crypto_secretstream_xchacha20poly1305_TAG_MESSAGE); } ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_PUSH( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]) { + ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_PUSH); } ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_REKEY( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]) { + ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_REKEY); } ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_FINAL( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]) { + ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_FINAL); } -ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_keygen( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[]) { +ERL_NIF_TERM +enacl_crypto_secretstream_xchacha20poly1305_keygen(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { ErlNifBinary key; @@ -110,8 +107,9 @@ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_keygen( return enif_make_badarg(env); } - if (!enif_alloc_binary(crypto_secretstream_xchacha20poly1305_KEYBYTES, &key)) { - return enacl_internal_error(env); + if (!enif_alloc_binary(crypto_secretstream_xchacha20poly1305_KEYBYTES, + &key)) { + return enacl_internal_error(env); } crypto_secretstream_xchacha20poly1305_keygen(key.data); @@ -126,9 +124,7 @@ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_keygen( const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) */ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_push( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[] - ) { + ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM ret; ErlNifBinary key, header; enacl_secretstream_ctx *obj = NULL; @@ -141,13 +137,14 @@ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_push( goto bad_arg; } - if (!enif_alloc_binary(crypto_secretstream_xchacha20poly1305_HEADERBYTES, &header)) { + if (!enif_alloc_binary(crypto_secretstream_xchacha20poly1305_HEADERBYTES, + &header)) { ret = enacl_internal_error(env); goto done; } - if((obj = enif_alloc_resource(enacl_secretstream_ctx_rtype, - sizeof(enacl_secretstream_ctx))) == NULL) { + if ((obj = enif_alloc_resource(enacl_secretstream_ctx_rtype, + sizeof(enacl_secretstream_ctx))) == NULL) { ret = enacl_internal_error(env); goto release_header; } @@ -155,37 +152,38 @@ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_push( obj->state = enif_alloc(crypto_secretstream_xchacha20poly1305_statebytes()); if (obj->state == NULL) { + ret = enacl_internal_error(env); goto release; } obj->alive = 1; if ((obj->mtx = enif_mutex_create("enacl.secretstream")) == NULL) { + ret = enacl_internal_error(env); goto free; } - crypto_secretstream_xchacha20poly1305_init_push(obj->state, header.data, key.data); + crypto_secretstream_xchacha20poly1305_init_push(obj->state, header.data, + key.data); - ret = enif_make_tuple2(env, - enif_make_binary(env, &header), - enif_make_resource(env, obj) - ); + ret = enif_make_tuple2(env, enif_make_binary(env, &header), + enif_make_resource(env, obj)); goto release; - bad_arg: return enif_make_badarg(env); free: if (obj->alive) if (obj->state != NULL) { - sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes()); + sodium_memzero(obj->state, + crypto_secretstream_xchacha20poly1305_statebytes()); enif_free(obj->state); obj->state = NULL; } +release_header: + enif_release_binary(&header); release: // This also frees the mutex via the destructor enif_release_resource(obj); -release_header: - enif_release_binary(&header); done: return ret; } @@ -197,9 +195,7 @@ crypto_secretstream_xchacha20poly1305_init_pull const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) */ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_pull( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[] - ) { + ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM ret; ErlNifBinary header, key; enacl_secretstream_ctx *obj = NULL; @@ -208,22 +204,21 @@ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_pull( goto bad_arg; } - if(!enif_inspect_binary(env, argv[0], &header)) { + if (!enif_inspect_binary(env, argv[0], &header)) { goto bad_arg; } - if(!enif_inspect_binary(env, argv[1], &key)) { + if (!enif_inspect_binary(env, argv[1], &key)) { goto bad_arg; } if ((key.size != crypto_secretstream_xchacha20poly1305_KEYBYTES) || - (header.size != crypto_secretstream_xchacha20poly1305_HEADERBYTES)) - { + (header.size != crypto_secretstream_xchacha20poly1305_HEADERBYTES)) { goto bad_arg; } - if((obj = enif_alloc_resource(enacl_secretstream_ctx_rtype, - sizeof(enacl_secretstream_ctx))) == NULL) { + if ((obj = enif_alloc_resource(enacl_secretstream_ctx_rtype, + sizeof(enacl_secretstream_ctx))) == NULL) { ret = enacl_internal_error(env); goto done; } @@ -240,7 +235,8 @@ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_pull( goto free; } - crypto_secretstream_xchacha20poly1305_init_pull(obj->state, header.data, key.data); + crypto_secretstream_xchacha20poly1305_init_pull(obj->state, header.data, + key.data); ret = enif_make_resource(env, obj); @@ -251,7 +247,8 @@ bad_arg: free: if (obj->alive) if (obj->state != NULL) { - sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes()); + sodium_memzero(obj->state, + crypto_secretstream_xchacha20poly1305_statebytes()); enif_free(obj->state); obj->state = NULL; } @@ -267,10 +264,9 @@ void crypto_secretstream_xchacha20poly1305_rekey (crypto_secretstream_xchacha20poly1305_state *state) */ -ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_rekey( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[] - ) { +ERL_NIF_TERM +enacl_crypto_secretstream_xchacha20poly1305_rekey(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { ERL_NIF_TERM ret; enacl_secretstream_ctx *obj = NULL; @@ -278,9 +274,9 @@ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_rekey( goto bad_arg; } - if(!enif_get_resource(env, argv[0], - (ErlNifResourceType *) enacl_secretstream_ctx_rtype, - (void **)&obj)) { + if (!enif_get_resource(env, argv[0], + (ErlNifResourceType *)enacl_secretstream_ctx_rtype, + (void **)&obj)) { goto bad_arg; } @@ -312,10 +308,9 @@ crypto_secretstream_xchacha20poly1305_push const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, unsigned char tag) */ -ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_push( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[] - ) { +ERL_NIF_TERM +enacl_crypto_secretstream_xchacha20poly1305_push(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { ERL_NIF_TERM ret; ErlNifBinary m, ad, out; ErlNifUInt64 tag; @@ -325,25 +320,26 @@ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_push( goto bad_arg; } - if(!enif_get_resource(env, argv[0], - (ErlNifResourceType *) enacl_secretstream_ctx_rtype, - (void **)&obj)) { + if (!enif_get_resource(env, argv[0], + (ErlNifResourceType *)enacl_secretstream_ctx_rtype, + (void **)&obj)) { goto bad_arg; } - if(!enif_inspect_binary(env, argv[1], &m)) { + if (!enif_inspect_binary(env, argv[1], &m)) { goto bad_arg; } - if(!enif_inspect_binary(env, argv[2], &ad)) { + if (!enif_inspect_binary(env, argv[2], &ad)) { goto bad_arg; } - if(!enif_get_uint64(env, argv[3], &tag)) { + if (!enif_get_uint64(env, argv[3], &tag)) { goto bad_arg; } - if (!enif_alloc_binary(m.size + crypto_secretstream_xchacha20poly1305_ABYTES, &out)) { + if (!enif_alloc_binary(m.size + crypto_secretstream_xchacha20poly1305_ABYTES, + &out)) { return enacl_internal_error(env); } @@ -352,12 +348,14 @@ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_push( goto err; } - crypto_secretstream_xchacha20poly1305_push(obj->state, out.data, NULL, m.data, m.size, ad.data, ad.size, tag); + crypto_secretstream_xchacha20poly1305_push(obj->state, out.data, NULL, m.data, + m.size, ad.data, ad.size, tag); if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL) { - if(obj->state) { + if (obj->state) { obj->alive = 0; - sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes()); + sodium_memzero(obj->state, + crypto_secretstream_xchacha20poly1305_statebytes()); enif_free(obj->state); obj->state = NULL; } @@ -384,10 +382,9 @@ done: const unsigned char *in, unsigned long long inlen, const unsigned char *ad, unsigned long long adlen) */ -ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_pull( - ErlNifEnv *env, int argc, - const ERL_NIF_TERM argv[] - ) { +ERL_NIF_TERM +enacl_crypto_secretstream_xchacha20poly1305_pull(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { ERL_NIF_TERM ret; ErlNifBinary m, in, ad; unsigned char tag; @@ -397,55 +394,57 @@ ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_pull( goto bad_arg; } - if(!enif_get_resource(env, argv[0], - (ErlNifResourceType *) enacl_secretstream_ctx_rtype, - (void **)&obj)) { + if (!enif_get_resource(env, argv[0], + (ErlNifResourceType *)enacl_secretstream_ctx_rtype, + (void **)&obj)) { goto bad_arg; } - if(!enif_inspect_binary(env, argv[1], &in)) { + if (!enif_inspect_binary(env, argv[1], &in)) { goto bad_arg; } - if(in.size < crypto_secretstream_xchacha20poly1305_ABYTES) { + if (in.size < crypto_secretstream_xchacha20poly1305_ABYTES) { goto bad_arg; } - if(!enif_inspect_binary(env, argv[2], &ad)) { + if (!enif_inspect_binary(env, argv[2], &ad)) { goto bad_arg; } - if(in.size < crypto_secretstream_xchacha20poly1305_ABYTES) { + if (in.size < crypto_secretstream_xchacha20poly1305_ABYTES) { goto bad_arg; } - if (!enif_alloc_binary(in.size - crypto_secretstream_xchacha20poly1305_ABYTES, &m)) { + if (!enif_alloc_binary(in.size - crypto_secretstream_xchacha20poly1305_ABYTES, + &m)) { return enacl_internal_error(env); } enif_mutex_lock(obj->mtx); - if(!obj->alive) { + if (!obj->alive) { goto err; } - if (0 != crypto_secretstream_xchacha20poly1305_pull(obj->state, m.data, NULL, &tag, in.data, in.size, ad.data, ad.size)) { + if (0 != crypto_secretstream_xchacha20poly1305_pull(obj->state, m.data, NULL, + &tag, in.data, in.size, + ad.data, ad.size)) { ret = enacl_error_tuple(env, "failed_verification"); goto release; } if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL) { - if(obj->state) { + if (obj->state) { obj->alive = 0; - sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes()); + sodium_memzero(obj->state, + crypto_secretstream_xchacha20poly1305_statebytes()); enif_free(obj->state); obj->state = NULL; } } - ret = enif_make_tuple2(env, - enif_make_binary(env, &m), - enif_make_int64(env, tag) - ); + ret = enif_make_tuple2(env, enif_make_binary(env, &m), + enif_make_int64(env, tag)); goto done; From ec3af40ef88cd7a7463bdf3c85823bd304d49ed1 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 7 Mar 2020 12:24:31 +0100 Subject: [PATCH 094/162] Simple secretstream CT test case --- test/enacl_SUITE.erl | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index 9d0adb6..d27e424 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -44,7 +44,8 @@ groups() -> aead_chacha20poly1305_ietf, pwhash, sign, - kx]}, + kx, + secretstream]}, [Neg, Pos]. @@ -162,3 +163,23 @@ kx(_Config) -> CTX = SRX, STX = CRX, ok. + +secretstream(_Config) -> + Part1 = <<"Arbitrary data to encrypt">>, + Part2 = <<"split into">>, + Part3 = <<"three messages">>, + + Key = enacl:secretstream_xchacha20poly1305_keygen(), + + %% Encrypt + {Header, State} = enacl:secretstream_xchacha20poly1305_init_push(Key), + Block1 = enacl:secretstream_xchacha20poly1305_push(State, Part1, <<"AD1">>, message), + Block2 = enacl:secretstream_xchacha20poly1305_push(State, Part2, <<>>, message), + Block3 = enacl:secretstream_xchacha20poly1305_push(State, Part3, <<"AD3">>, final), + + %% Decrypt + DState = enacl:secretstream_xchacha20poly1305_init_pull(Header, Key), + {Part1, message} = enacl:secretstream_xchacha20poly1305_pull(DState, Block1, <<"AD1">>), + {Part2, message} = enacl:secretstream_xchacha20poly1305_pull(DState, Block2, <<>>), + {Part3, final} = enacl:secretstream_xchacha20poly1305_pull(DState, Block3, <<"AD3">>), + ok. From 061c3dfd65d674e45b58cf38ed6276ba9620cc34 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 7 Mar 2020 12:26:20 +0100 Subject: [PATCH 095/162] Mention we have unit tests for secretstream --- src/enacl.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/enacl.erl b/src/enacl.erl index 92f2605..20dc737 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -165,7 +165,7 @@ %% Key exchange functions -export([ - %% No Tests! + %% EQC kx_keypair/0, kx_client_session_keys/3, kx_server_session_keys/3, @@ -176,7 +176,7 @@ %% Secretstream operations. -export([ - %% No Tests! + %% Unit tests secretstream_xchacha20poly1305_ABYTES/0, secretstream_xchacha20poly1305_HEADERBYTES/0, secretstream_xchacha20poly1305_KEYBYTES/0, From bde03dc55797e687c09c009a5932ad9f7186801b Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 7 Mar 2020 14:21:52 +0100 Subject: [PATCH 096/162] Fix a dialyzer warning --- src/enacl.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/enacl.erl b/src/enacl.erl index 20dc737..d2a4fff 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -1415,7 +1415,7 @@ secretstream_xchacha20poly1305_rekey(Ref) -> secretstream_xchacha20poly1305_tag_value(message) -> enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_MESSAGE(); secretstream_xchacha20poly1305_tag_value(rekey) -> - enacl_nif:crypto_secretstream_xcacha20poly1305_TAG_REKEY(); + enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_REKEY(); secretstream_xchacha20poly1305_tag_value(push) -> enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_PUSH(); secretstream_xchacha20poly1305_tag_value(final) -> From 5f95ee314f4e68b47547532084e23d3991078ff4 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 7 Mar 2020 15:10:58 +0100 Subject: [PATCH 097/162] Implement EQC for secretstream --- eqc_test/enacl_eqc.erl | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 24513b0..70110eb 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -956,6 +956,46 @@ prop_scalarmult() -> enacl:curve25519_scalarmult(S1, Basepoint))) ). +%% Secretstream +secretstream_key() -> + ?LET(K, enacl:secretstream_xchacha20poly1305_keygen(), K). + +secretstream_msg() -> + ?LET({Tag, AD, Msg}, {oneof([message,rekey,push]), binary(), binary()}, + {Tag, AD, Msg}). + +secretstream_msgs() -> + ?LET({Ms, {_, AD, Msg}}, {list(secretstream_msg()), secretstream_msg()}, + Ms ++ [{final, AD, Msg}]). + +push_messages(_State, []) -> + []; +push_messages(State, [{Tag, AD, Msg}|Next]) -> + Block = enacl:secretstream_xchacha20poly1305_push(State, Msg, AD, Tag), + [Block|push_messages(State, Next)]. + +pull_messages(_State, [], []) -> + true; +pull_messages(State, [B|Bs], [{_Tag, AD, _Msg}=Expect|Next]) -> + {Msgx, Tagx} = enacl:secretstream_xchacha20poly1305_pull(State, B, AD), + case equals(Expect, {Tagx, AD, Msgx}) of + true -> + pull_messages(State, Bs, Next); + R -> + R + end. + +prop_secretstream() -> + ?FORALL({Key, Msgs}, {secretstream_key(), secretstream_msgs()}, + begin + %% Encrypt + {Header, State} = enacl:secretstream_xchacha20poly1305_init_push(Key), + Blocks = push_messages(State, Msgs), + %% Decrypt & Verify + DState = enacl:secretstream_xchacha20poly1305_init_pull(Header, Key), + pull_messages(DState, Blocks, Msgs) + end). + %% HELPERS %% INTERNAL FUNCTIONS From 812f05adcf5766275e293cb5145287f24c4e5e90 Mon Sep 17 00:00:00 2001 From: Bryan Paxton <39971740+starbelly@users.noreply.github.com> Date: Wed, 25 Mar 2020 23:07:55 -0500 Subject: [PATCH 098/162] Move rebar3_hex into project_plugins This change will prevent users from having to download rebar3_hex and all of it's dependencies. --- rebar.config | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index 5b644b3..e9d0ca5 100644 --- a/rebar.config +++ b/rebar.config @@ -1,6 +1,8 @@ {erl_opts, [debug_info]}. -{plugins, [pc, rebar3_hex]}. +{plugins, [pc]}. + +{project_plugins, [rebar3_hex]}. {provider_hooks, [ {pre, [ From a001404877bda8f7272b9af687531f0ea0f6307d Mon Sep 17 00:00:00 2001 From: Nicolas goy Date: Fri, 17 Apr 2020 13:52:33 +0200 Subject: [PATCH 099/162] Add pwhash_SALTBYTES/0 --- c_src/enacl_nif.c | 1 + c_src/pwhash.c | 6 ++++++ c_src/pwhash.h | 3 +++ src/enacl.erl | 8 ++++++++ src/enacl_nif.erl | 2 ++ test/enacl_SUITE.erl | 1 + 6 files changed, 21 insertions(+) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 2333c18..2119fa5 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -287,6 +287,7 @@ static ErlNifFunc nif_funcs[] = { {"crypto_verify_32", 2, enacl_crypto_verify_32}, {"sodium_memzero", 1, enif_sodium_memzero}, + {"crypto_pwhash_SALTBYTES", 0, enacl_crypto_pwhash_SALTBYTES}, erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash", 4, enacl_crypto_pwhash), erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash_str", 3, enacl_crypto_pwhash_str), diff --git a/c_src/pwhash.c b/c_src/pwhash.c index be74851..f4ae2dc 100644 --- a/c_src/pwhash.c +++ b/c_src/pwhash.c @@ -57,6 +57,12 @@ static size_t enacl_pwhash_memlimit(ErlNifEnv *env, ERL_NIF_TERM arg) { return 0; } + +ERL_NIF_TERM enacl_crypto_pwhash_SALTBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_pwhash_SALTBYTES); +} + ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary h, p, s; diff --git a/c_src/pwhash.h b/c_src/pwhash.h index 76a882f..66d0e89 100644 --- a/c_src/pwhash.h +++ b/c_src/pwhash.h @@ -3,6 +3,9 @@ #include +ERL_NIF_TERM enacl_crypto_pwhash_SALTBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]); diff --git a/src/enacl.erl b/src/enacl.erl index d2a4fff..91c29fd 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -116,6 +116,7 @@ shorthash_size/0, shorthash/2, + pwhash_SALTBYTES/0, pwhash/4, pwhash_str/3, @@ -395,6 +396,13 @@ generichash_final(State) -> enacl_nif:crypto_generichash_final(State). -type pwhash_limit() :: interactive | moderate | sensitive | pos_integer(). + +%% @doc pwhash_SALTBYTES/0 returns the number of bytes required for salt. +%% @end +-spec pwhash_SALTBYTES() -> pos_integer(). +pwhash_SALTBYTES() -> + enacl_nif:crypto_pwhash_SALTBYTES(). + %% @doc pwhash/2 hash a password %% %% This function generates a fixed size salted hash of a user defined password. diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index f2255f8..417ab25 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -147,6 +147,7 @@ %% Password Hashing - Argon2 Algorithm -export([ + crypto_pwhash_SALTBYTES/0, crypto_pwhash/4, crypto_pwhash_str/3, crypto_pwhash_str_verify/2 @@ -238,6 +239,7 @@ crypto_secretstream_xchacha20poly1305_init_pull(_Header, _Key) -> erlang:nif_err crypto_secretstream_xchacha20poly1305_pull(_Ref, _CipherText, _AD) -> erlang:nif_error(nif_not_loaded). crypto_secretstream_xchacha20poly1305_rekey(_Ref) -> erlang:nif_error(nif_not_loaded). +crypto_pwhash_SALTBYTES() -> erlang:nif_error(nif_not_loaded). crypto_pwhash(_Password, _Salt, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str(_Password, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded). diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index d27e424..c569214 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -136,6 +136,7 @@ pwhash(_Config) -> Str1 = enacl:pwhash_str(PW), true = enacl:pwhash_str_verify(Str1, PW), false = enacl:pwhash_str_verify(Str1, <>), + 16 = enacl:pwhash_SALTBYTES(), ok. sign(_Config) -> From 00f895b48882d4ba7cd37fb74faef231ce0c4cc3 Mon Sep 17 00:00:00 2001 From: Nicolas goy Date: Fri, 17 Apr 2020 14:31:35 +0200 Subject: [PATCH 100/162] Allow specifying algorithm for pwhash --- c_src/enacl_nif.c | 2 +- c_src/pwhash.c | 34 +++++++++++++++++++++++++++++++--- src/enacl.erl | 20 +++++++++++++++++++- src/enacl_nif.erl | 4 ++-- 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 2333c18..5fa1ff0 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -287,7 +287,7 @@ static ErlNifFunc nif_funcs[] = { {"crypto_verify_32", 2, enacl_crypto_verify_32}, {"sodium_memzero", 1, enif_sodium_memzero}, - erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash", 4, enacl_crypto_pwhash), + erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash", 5, enacl_crypto_pwhash), erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash_str", 3, enacl_crypto_pwhash_str), erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash_str_verify", 2, diff --git a/c_src/pwhash.c b/c_src/pwhash.c index be74851..9f2c5f5 100644 --- a/c_src/pwhash.c +++ b/c_src/pwhash.c @@ -57,16 +57,44 @@ static size_t enacl_pwhash_memlimit(ErlNifEnv *env, ERL_NIF_TERM arg) { return 0; } +static int enacl_pwhash_alg(ErlNifEnv *env, ERL_NIF_TERM arg) { + ERL_NIF_TERM a; + int r; + + if (enif_is_atom(env, arg)) { + a = enif_make_atom(env, "default"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_ALG_DEFAULT; + } + + a = enif_make_atom(env, "argon2i13"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_ALG_ARGON2I13; + } + + a = enif_make_atom(env, "argon2id13"); + if (enif_is_identical(a, arg)) { + return crypto_pwhash_ALG_ARGON2ID13; + } + } else if (enif_get_int(env, arg, &r)) { + return r; + } + + return 0; +} + ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary h, p, s; size_t o, m; + int alg; // Validate the arguments - if ((argc != 4) || (!enif_inspect_iolist_as_binary(env, argv[0], &p)) || + if ((argc != 5) || (!enif_inspect_iolist_as_binary(env, argv[0], &p)) || (!enif_inspect_binary(env, argv[1], &s)) || !(o = enacl_pwhash_opslimit(env, argv[2])) || - !(m = enacl_pwhash_memlimit(env, argv[3]))) { + !(m = enacl_pwhash_memlimit(env, argv[3])) || + !(alg = enacl_pwhash_alg(env, argv[4]))) { return enif_make_badarg(env); } @@ -87,7 +115,7 @@ ERL_NIF_TERM enacl_crypto_pwhash(ErlNifEnv *env, int argc, } if (crypto_pwhash(h.data, h.size, (char *)p.data, p.size, s.data, o, m, - crypto_pwhash_ALG_DEFAULT) != 0) { + alg) != 0) { /* out of memory */ enif_release_binary(&h); return enacl_internal_error(env); diff --git a/src/enacl.erl b/src/enacl.erl index d2a4fff..4e87286 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -116,6 +116,8 @@ shorthash_size/0, shorthash/2, + pwhash/5, + pwhash/4, pwhash_str/3, @@ -395,6 +397,7 @@ generichash_final(State) -> enacl_nif:crypto_generichash_final(State). -type pwhash_limit() :: interactive | moderate | sensitive | pos_integer(). +-type pwhash_alg() :: default | argon2i13 | argon2id13 | pos_integer(). %% @doc pwhash/2 hash a password %% %% This function generates a fixed size salted hash of a user defined password. @@ -416,7 +419,22 @@ pwhash(Password, Salt) -> Ops :: pwhash_limit(), Mem :: pwhash_limit(). pwhash(Password, Salt, Ops, Mem) -> - enacl_nif:crypto_pwhash(Password, Salt, Ops, Mem). + enacl_nif:crypto_pwhash(Password, Salt, Ops, Mem, default). + +%% @doc pwhash/5 hash a password +%% +%% This function generates a fixed size salted hash of a user defined password given Ops and Mem +%% limits. +%% @end +-spec pwhash(Password, Salt, Ops, Mem, Alg) -> binary() + when + Password :: iodata(), + Salt :: binary(), + Ops :: pwhash_limit(), + Mem :: pwhash_limit(), + Alg :: pwhash_alg(). +pwhash(Password, Salt, Ops, Mem, Alg) -> + enacl_nif:crypto_pwhash(Password, Salt, Ops, Mem, Alg). %% @doc pwhash_str/1 generates a ASCII encoded hash of a password %% diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index f2255f8..04dbb9a 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -147,7 +147,7 @@ %% Password Hashing - Argon2 Algorithm -export([ - crypto_pwhash/4, + crypto_pwhash/5, crypto_pwhash_str/3, crypto_pwhash_str_verify/2 ]). @@ -238,7 +238,7 @@ crypto_secretstream_xchacha20poly1305_init_pull(_Header, _Key) -> erlang:nif_err crypto_secretstream_xchacha20poly1305_pull(_Ref, _CipherText, _AD) -> erlang:nif_error(nif_not_loaded). crypto_secretstream_xchacha20poly1305_rekey(_Ref) -> erlang:nif_error(nif_not_loaded). -crypto_pwhash(_Password, _Salt, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). +crypto_pwhash(_Password, _Salt, _Ops, _Mem, _Alg) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str(_Password, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded). From 4775270d765cff4d2a9bca48c98a058883b52100 Mon Sep 17 00:00:00 2001 From: Nicolas goy Date: Sun, 19 Apr 2020 19:05:24 +0200 Subject: [PATCH 101/162] Basic KDF functions --- c_src/enacl_nif.c | 6 +++++ c_src/kdf.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ c_src/kdf.h | 15 ++++++++++++ src/enacl.erl | 30 ++++++++++++++++++++++++ src/enacl_nif.erl | 11 +++++++++ 5 files changed, 121 insertions(+) create mode 100644 c_src/kdf.c create mode 100644 c_src/kdf.h diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 2333c18..afd9def 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -11,6 +11,7 @@ #include "kx.h" #include "public.h" #include "pwhash.h" +#include "kdf.h" #include "randombytes.h" #include "secret.h" #include "sign.h" @@ -293,6 +294,11 @@ static ErlNifFunc nif_funcs[] = { erl_nif_dirty_job_cpu_bound_macro("crypto_pwhash_str_verify", 2, enacl_crypto_pwhash_str_verify), + {"crypto_kdf_KEYBYTES", 0, enacl_crypto_kdf_KEYBYTES}, + {"crypto_kdf_CONTEXTBYTES", 0, enacl_crypto_kdf_CONTEXTBYTES}, + erl_nif_dirty_job_cpu_bound_macro("crypto_kdf_derive_from_key", 3, + enacl_crypto_kdf_derive_from_key), + erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult", 2, enacl_crypto_curve25519_scalarmult), erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult_base", 1, diff --git a/c_src/kdf.c b/c_src/kdf.c new file mode 100644 index 0000000..5290513 --- /dev/null +++ b/c_src/kdf.c @@ -0,0 +1,59 @@ +#include + +#include + +#include "enacl.h" +#include "kdf.h" + + +ERL_NIF_TERM enacl_crypto_kdf_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_kdf_KEYBYTES); +} + +ERL_NIF_TERM enacl_crypto_kdf_CONTEXTBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_kdf_CONTEXTBYTES); +} + + +ERL_NIF_TERM enacl_crypto_kdf_derive_from_key(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]) { + ErlNifBinary m, c, r; + uint64_t id; + + // Validate the arguments + if ((argc != 3) || + (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &c)) || + (!enif_get_uint64(env, argv[2], &id))) { + return enif_make_badarg(env); + } + + // Check Master Key length + if (m.size != crypto_kdf_KEYBYTES) { + return enif_make_badarg(env); + } + + // Check Context Key length + if (c.size != crypto_kdf_CONTEXTBYTES) { + return enif_make_badarg(env); + } + + // Allocate memory for return binary + if (!enif_alloc_binary(crypto_kdf_KEYBYTES, &r)) { + return enacl_internal_error(env); + } + + if (crypto_kdf_derive_from_key(r.data, r.size, + id, + (const char *)c.data, + m.data) != 0) { + /* out of memory */ + enif_release_binary(&r); + return enacl_internal_error(env); + } + + return enif_make_binary(env, &r); +} + diff --git a/c_src/kdf.h b/c_src/kdf.h new file mode 100644 index 0000000..56b654b --- /dev/null +++ b/c_src/kdf.h @@ -0,0 +1,15 @@ +#ifndef ENACL_KDF_H +#define ENACL_KDF_H + +#include + +ERL_NIF_TERM enacl_crypto_kdf_KEYBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_kdf_CONTEXTBYTES(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +ERL_NIF_TERM enacl_crypto_kdf_derive_from_key(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); + +#endif diff --git a/src/enacl.erl b/src/enacl.erl index d2a4fff..40749e9 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -125,6 +125,13 @@ ]). +%% Key derivation +-export([ + kdf_KEYBYTES/0, + kdf_CONTEXTBYTES/0, + kdf_derive_from_key/3 +]). + %% Low-level subtle functions which are hard to get correct -export([ %% EQC @@ -456,6 +463,29 @@ null_terminate(ASCII) -> pwhash_str_verify(HashPassword, Password) -> enacl_nif:crypto_pwhash_str_verify(null_terminate(HashPassword), Password). +%% Key Derivation +%% @doc kdf_KEYBYTES/0 returns the number of bytes required for master key. +%% @end +-spec kdf_KEYBYTES() -> pos_integer(). +kdf_KEYBYTES() -> + enacl_nif:crypto_kdf_KEYBYTES(). + +%% @doc kdf_CONTEXTBYTES/0 returns the number of bytes required for context. +%% @end +-spec kdf_CONTEXTBYTES() -> pos_integer(). +kdf_CONTEXTBYTES() -> + enacl_nif:crypto_kdf_CONTEXTBYTES(). + +%% @doc kdf_derive_from_key/3 derive a key from a single high entropy key +%% @end. +-spec kdf_derive_from_key(MasterKey, Context, Id) -> binary() + when + MasterKey :: iodata(), + Context :: binary(), + Id :: pos_integer(). +kdf_derive_from_key(MasterKey, Context, Id) -> + enacl_nif:crypto_kdf_derive_from_key(MasterKey, Context, Id). + %% Public Key Crypto %% --------------------- %% @doc box_keypair/0 creates a new Public/Secret keypair. diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index f2255f8..1e1d671 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -152,6 +152,13 @@ crypto_pwhash_str_verify/2 ]). +%% Key Derivation +-export([ + crypto_kdf_KEYBYTES/0, + crypto_kdf_CONTEXTBYTES/0, + crypto_kdf_derive_from_key/3 + ]). + %% Generic hash -export([ crypto_generichash_BYTES/0, @@ -242,6 +249,10 @@ crypto_pwhash(_Password, _Salt, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str(_Password, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded). +crypto_kdf_KEYBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_kdf_CONTEXTBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_kdf_derive_from_key(_MasterKey, _Context, _Id) -> erlang:nif_error(nif_not_loaded). + crypto_box_NONCEBYTES() -> erlang:nif_error(nif_not_loaded). crypto_box_ZEROBYTES() -> erlang:nif_error(nif_not_loaded). crypto_box_BOXZEROBYTES() -> erlang:nif_error(nif_not_loaded). From 42fd03cde0df7cadd5f906ad5d6d8f7c1e6664e2 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 9 Jun 2020 12:14:39 +0200 Subject: [PATCH 102/162] Update CONTRIBUTORS, CHANGELOG --- CHANGELOG.md | 8 +++++++- CONTRIBUTORS | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c0b3ce..feddc01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [unreleased] +## [Unreleased] ### Added - Secretstream support was added to the API (Alexander Malaev) +- Add KDF functions (Nicolas Goy, @kuon) +- Add pwhash/5 specifying what algorithm to use for older compatibility (Nicolas Goy, @kuon) + +### Changed + +- Remove rebar3_hex as a direct dependency (Bryan Paxton, @starbelly) ## [1.0.0] diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 5e1015b..cfe84e4 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -3,11 +3,13 @@ List of people who have contributed to the eNaCl source code: Alexander Færøy Alexander Malaev Amir Ghassemi Nasr +Bryan Paxton GitHub/ECrownofFire Geller Bedoya Jesper Louis Andersen Joel Stanley Konrad Zemek +Nicolas Goy Parnell Springmeyer Ricardo Lanziano Tino Breddin From 23bd40a4b3f8360e4943ba62e4a273a1cf5c2eb5 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 9 Jun 2020 12:16:59 +0200 Subject: [PATCH 103/162] Netpick the include path order --- c_src/enacl_nif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 8104976..d4bd73c 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -8,10 +8,10 @@ #include "enacl_ext.h" #include "generichash.h" #include "hash.h" +#include "kdf.h" #include "kx.h" #include "public.h" #include "pwhash.h" -#include "kdf.h" #include "randombytes.h" #include "secret.h" #include "secretstream.h" From 90be3aa2ddf9fd629daf90c6024173c79031c32b Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 9 Jun 2020 12:17:23 +0200 Subject: [PATCH 104/162] Use GCC 9.3.0 from nix --- .vscode/c_cpp_properties.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 162adb4..b844a05 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -6,7 +6,7 @@ "${workspaceFolder}/**" ], "defines": [], - "compilerPath": "/nix/store/a9hbzlkdfvpr4r8mjwcxcda9smjp5v1i-gcc-wrapper-9.2.0/bin/gcc", + "compilerPath": "/nix/store/fb30zc52va0g99q8qgv7kx4ngq163pii-gcc-wrapper-9.3.0/bin/gcc", "cStandard": "c11", "cppStandard": "c++17", "intelliSenseMode": "clang-x64" From 7f7c667b281bcb44bfd9142a1f834571d3099302 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 9 Jun 2020 12:27:47 +0200 Subject: [PATCH 105/162] Update the README a bit The world-order is new, so update the README. to reflect reality a bit more. --- README.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index faebfaf..6e5522d 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,17 @@ libsodium as the underlying driver. ## INSTALL/Requirements: -* Erlang/OTP 17.3. This library *needs* the newest dirty scheduler - implementation. The library relies on dirty scheduler support in - order to handle long-running cryptography jobs, by moving them off - the main Erlang scheduler and letting the dirty schedulers handle - the work. This keeps the Erlang VM responsive. -* *Requires* the libsodium library, and at least in version 1.0.12. +* Erlang/OTP above 17.3. This library *needs* the dirty scheduler + implementation from 17.3 and onwards. The library relies on dirty + scheduler support in order to handle long-running cryptography jobs, + by moving them off the main Erlang scheduler and letting the dirty + schedulers handle the work. This keeps the Erlang VM responsive while + doing large amounts of cryptographic processing. +* Is tested with Erlang 22.3. Erlang version 21 *may* work, but that isn't + the current testing target. +* *Requires* the libsodium library, and has been tested with version + 1.0.18. Lower versions might work, or they might fail to compile, + due to missing functionality. *Note:* If installing on systems which cuts packages into subpackages, make sure you also get the "-dev" package containing the header files necessary in order to compile software linking to @@ -38,7 +43,7 @@ To build and run eqc-mini version of test execute: ## Features: * Complete NaCl library, implementing all default functionality. -* Implements a small set of additional functionality from libsodium. +* Implements a large set of additional functionality from libsodium. Most notably access to a proper CSPRNG random source * Tests created by aggressive use of Erlang QuickCheck. * NaCl is a very fast cryptographic library. That is, From 4b4ec373b1bf2cab5bebc928e7ef3fc662883c85 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 9 Jun 2020 13:34:03 +0200 Subject: [PATCH 106/162] Test pwhash in EQC. --- eqc_test/enacl_eqc.erl | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 70110eb..38464b4 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -761,6 +761,13 @@ pwhash(Passwd, Salt) -> error:badarg -> badarg end. +pwhash(Password, Salt, Ops, Mem, Alg) -> + try + enacl:pwhsah(Password, Salt, Ops, Mem, Alg) + catch + error:badarg -> badarg + end. + pwhash_str(Passwd) -> try enacl:pwhash_str(Passwd) @@ -775,11 +782,25 @@ pwhash_str_verify(PasswdHash, Passwd) -> error:badarg -> badarg end. +prop_pwhash() -> + ?FORALL({Password, Salt, OLimit, MLimit, Alg}, + {binary(16), + binary(16), + elements([interactive, moderate]), %% These could add senstitive, but are too runtime-expensive + elements([interactive, moderate]), %% And that is for a reason. + elements([default, 'argon2id13'])}, %% Argon2I13 uses different limits, so it is kept out as + %% this would otherwise fail + begin + Bin1 = enacl:pwhash(Password, Salt, OLimit, MLimit, Alg), + Bin2 = enacl:pwhash(Password, Salt, OLimit, MLimit, Alg), + equals(Bin1, Bin2) + end). + prop_pwhash_str_verify() -> ?FORALL({Passwd, OLimit, MLimit}, {?FAULT_RATE(1, 40, g_iodata()), - elements([interactive, moderate, sensitive]), - elements([interactive, moderate, sensitive])}, + elements([interactive, moderate]), + elements([interactive, moderate])}, begin case v_iodata(Passwd) of true -> From 025b83a14bfa0a3f1216c09b3b23127b64b913db Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 9 Jun 2020 13:35:43 +0200 Subject: [PATCH 107/162] Prepare 1.1.0. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index feddc01..3788e11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +## [1.1.0] + ### Added - Secretstream support was added to the API (Alexander Malaev) From b2c70ef6a33dd4594a65137e3fc843ab9e22871b Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 9 Jun 2020 13:37:05 +0200 Subject: [PATCH 108/162] v1.1.0 --- src/enacl.app.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/enacl.app.src b/src/enacl.app.src index 389f2bf..2238df5 100644 --- a/src/enacl.app.src +++ b/src/enacl.app.src @@ -1,6 +1,6 @@ {application,enacl, [{description,"Erlang libsodium (NaCl) bindings"}, - {vsn,"1.0.0"}, + {vsn,"1.1.0"}, {registered,[]}, {applications,[kernel,stdlib]}, {env,[]}, From e18f9b7337bf666f7c8ace22103c3734f345fd63 Mon Sep 17 00:00:00 2001 From: Bryan Paxton Date: Sun, 26 Jul 2020 14:25:24 -0500 Subject: [PATCH 109/162] Ensure we never return 1 from sodium_init() onload sodium_init() will return 0 on success, -1 on failure, and 1 if sodium is already loaded and initialized (which is not an error). In the case where libsodium is already initialized and the system is restarted we may return 1 from onload nif function resulting in a crash. - change the call to sodium_init() to check for an error return (-1) and return -1 explicitly in this case, otherwise always return zero at the end of our onload function. --- c_src/enacl_nif.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index d4bd73c..b62f746 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -41,7 +41,11 @@ static int enacl_crypto_load(ErlNifEnv *env, void **priv_data, return -1; } - return sodium_init(); + if (sodium_init() == -1) { + return -1; + } + + return 0; } /* GENERAL ROUTINES From 0351de9882927e03c6611e077cb753463bff7525 Mon Sep 17 00:00:00 2001 From: Bryan Paxton Date: Tue, 28 Jul 2020 18:30:59 -0500 Subject: [PATCH 110/162] add upgrade and unload handlers --- c_src/enacl_nif.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index b62f746..268096a 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -48,6 +48,17 @@ static int enacl_crypto_load(ErlNifEnv *env, void **priv_data, return 0; } +static int enacl_crypto_upgrade(ErlNifEnv* env, void **priv_data, + void **old_priv_data, + ERL_NIF_TERM load_info) { + return 0; +} + +static int enacl_crypto_unload(ErlNifEnv* env, void **priv_data, + ERL_NIF_TERM load_info) { + return 0; +} + /* GENERAL ROUTINES * * These don't generally fit somewhere else nicely, so we keep them in the main @@ -421,4 +432,4 @@ static ErlNifFunc nif_funcs[] = { "crypto_secretstream_xchacha20poly1305_pull", 3, enacl_crypto_secretstream_xchacha20poly1305_pull)}; -ERL_NIF_INIT(enacl_nif, nif_funcs, enacl_crypto_load, NULL, NULL, NULL); +ERL_NIF_INIT(enacl_nif, nif_funcs, enacl_crypto_load, NULL, enacl_crypto_upgrade, enacl_crypto_unload); From 6ca6b0b22ea959daa4688cbc24b7ddc5d250ccae Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 27 Aug 2020 14:08:00 +0200 Subject: [PATCH 111/162] Say hello to Erlang/OTP v23 --- shell.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell.nix b/shell.nix index a59c99b..7c2ad6e 100644 --- a/shell.nix +++ b/shell.nix @@ -5,7 +5,7 @@ with pkgs; let inherit (lib) optional optionals; - erlang_wx = erlangR22.override { + erlang_wx = erlangR23.override { wxSupport = true; }; in @@ -13,4 +13,4 @@ in mkShell { buildInputs = [ erlang_wx git libsodium ] ++ optional stdenv.isLinux inotify-tools; -} \ No newline at end of file +} From 44f22205325e3deecf23632625aaffe2b409e765 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 27 Aug 2020 14:19:50 +0200 Subject: [PATCH 112/162] Markdownlint nitpicking --- CHANGELOG.md | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3788e11..0d28df5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [1.0.0] ### Compatibility + - Some functions have been streamlined to badarg in certain cases where it made more sense to do so than returning back an error to the caller. - Functions generally don't return error values for internal errors. They now raise @@ -37,12 +38,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Many constants were changed to their underlying libsodium names. ### Removed + - The functions of the form `aead_chacha20poly1305_*` were removed. They implement the IETF variant, and the argument order for them were wrong. Also, they used severely limited nonce values, which is somewhat dangerous. The `..._NONCEBYTES` name was changed to the consistent `..._NPUBBYTES`. ### Added + - Added `aead_chacha20poly1305_ietf_*` variants. - Implement multipart signature support, by Garry Hill. - Implement enacl:crypto_sign_seed_keypair/1, by Ole Andre Birkedal. @@ -61,6 +64,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added a nix shell for easier development ### Changed + - Started a split the C code over multiple files for easier maintenance. - Rewrote the generichash routines to be more consistent. We are now more-or-less following the style of the Erlang/OTP `crypto` library. While here, make sure @@ -89,6 +93,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. is definitely wrong and there is no recovery possible. ### Fixed + - Fix a resource leak in generichash/sign init/update/final. - Clang static analysis warnings (Thomas Arts). - Replace a constant 31 with a computation from libsodium (Thomas Arts, from a security review). @@ -99,11 +104,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.17.2] ### Fixed + - Work around `rebar3 hex` publishing .so files ## [0.17.1] ### Fixed + - Provide a fix for the `pwhash_str/x` functions. The C strings were not properly handled wrt. NULL-termination and what the libsodium library expects. @@ -111,6 +118,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.17.0] ### Added + - Expose the AEAD ChaCha20 Poly1305 (IETF) functionality (Hans Svensson / Quviq). - Expose Curve25519 Scalar Multiplication over a base point in the @@ -123,10 +131,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Support generichash functions (Venkatakumar Srinivasan / Xaptum) ### Fixed + - The type specification of generichash/2 and generichash/3 was corrected (Technion) ### Changed + - Removed the experimental feature flag `ERL_NIF_DIRTY_JOB_CPU_BOUND`. This breaks compatibility with older Erlang releases of dirty schedulers, but prepares us correctly for the new releases where the @@ -151,11 +161,13 @@ access to implement these from libsodium. added (no attribution) ### Fixed + - Do not use the dirty-scheduler test macro as it is gone. ## [0.15.0] ### Fixed + - Using `enacl:sign_verify_detacted` on large iolists would fail to do the correct thing due to a typo. This has been corrected. Also the EQC tests have been extended to include large binary support to @@ -178,10 +190,13 @@ a better citizen to other libraries and other parts of the system. ## [0.14.0] ### Added + - Add support for libsodiums `box_seal` functions (Amir Ghassemi Nasr) - Add support for libsodiums `crypto_sign_detached` (Joel Stanley, Parnell Springmeyer) + ### Changed + - Switch the tag names to the form `0.14.0` rather than `v0.14.0`. For this release both tags are present, but from the next release on, it won't be the case. @@ -189,21 +204,25 @@ a better citizen to other libraries and other parts of the system. ## [0.13.0] ### Fixed + - Quell warnings from the C code ### Added + - Add Ed 25519 utility API (Alexander Færøy) - Add FreeBSD support for the NIF compilation (Ricardo Lanziano) ## [0.12.1] ### Changed + - Provide the `priv` directory for being able to properly build without manual intervention. ## [0.12.0] ### Added + - Introduce an extension interface for various necessary extensions to the eNaCl system for handling the Tor network, thanks to Alexander Færøy (ahf). @@ -214,11 +233,14 @@ a better citizen to other libraries and other parts of the system. ## [0.11.0] ### Added + - Introduce NIF layer beforenm/afternm calls. - Introduce the API for precomputed keys (beforenm/afternm calls). - Use test cases which tries to inject `iodata()` rather than binaries in all places where `iodata()` tend to be accepted. + ### Fixed + - Fix type for `enacl:box_open/4`. The specification was wrong which results in errors in other applications using enacl. @@ -227,6 +249,7 @@ a better citizen to other libraries and other parts of the system. Maintenance release. Fix some usability problems with the library. ### Fixed + - Do not compile the C NIF code if there are no dirty scheduler support in the Erlang system (Thanks to David N. Welton) - Fix dialyzer warnings (Thanks Anthony Ramine) @@ -262,9 +285,9 @@ Added the function `randombytes/1` to obtain randombytes from the operating system. The system uses the "best" applicable (P)RNG on the target system: -* Windows: `RtlGenRandom()` -* OpenBSD, Bitrig: `arc4random()` -* Unix in general: `/dev/urandom` +- Windows: `RtlGenRandom()` +- OpenBSD, Bitrig: `arc4random()` +- Unix in general: `/dev/urandom` Do note that on Linux and FreeBSD at the *least*, this is the best thing you can do. Relying on `/dev/random` is almost always wrong and @@ -278,4 +301,3 @@ Ultra-late beta. Code probably works, but it requires some real-world use before it is deemed entirely stable. Initial release. - From 57ad262ec88d818f3ba358cce830ce410c5ce186 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 27 Aug 2020 14:24:01 +0200 Subject: [PATCH 113/162] More Markdownlint nitpicking --- CHANGELOG.md | 58 ++++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d28df5..9d167f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,21 +7,25 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added + +- Introduce the ability to reload the enacl module (Bryan Paxton, @starbelly) + ## [1.1.0] -### Added +### Added [1.1.0] - Secretstream support was added to the API (Alexander Malaev) - Add KDF functions (Nicolas Goy, @kuon) - Add pwhash/5 specifying what algorithm to use for older compatibility (Nicolas Goy, @kuon) -### Changed +### Changed [1.1.0] - Remove rebar3_hex as a direct dependency (Bryan Paxton, @starbelly) ## [1.0.0] -### Compatibility +### Compatibility [1.0.0] - Some functions have been streamlined to badarg in certain cases where it made more sense to do so than returning back an error to the caller. @@ -37,14 +41,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. were changed by this. - Many constants were changed to their underlying libsodium names. -### Removed +### Removed [1.0.0] - The functions of the form `aead_chacha20poly1305_*` were removed. They implement the IETF variant, and the argument order for them were wrong. Also, they used severely limited nonce values, which is somewhat dangerous. The `..._NONCEBYTES` name was changed to the consistent `..._NPUBBYTES`. -### Added +### Added [1.0.0] - Added `aead_chacha20poly1305_ietf_*` variants. - Implement multipart signature support, by Garry Hill. @@ -63,7 +67,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added Win32 build support (Tino Breddin) - Added a nix shell for easier development -### Changed +### Changed [1.0.0] - Started a split the C code over multiple files for easier maintenance. - Rewrote the generichash routines to be more consistent. We are now more-or-less @@ -92,7 +96,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. hashing on the object. The rejection is an error: if you ever do this, your code is definitely wrong and there is no recovery possible. -### Fixed +### Fixed [1.0.0] - Fix a resource leak in generichash/sign init/update/final. - Clang static analysis warnings (Thomas Arts). @@ -103,13 +107,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.17.2] -### Fixed +### Fixed [0.17.2] - Work around `rebar3 hex` publishing .so files ## [0.17.1] -### Fixed +### Fixed [0.17.1] - Provide a fix for the `pwhash_str/x` functions. The C strings were not properly handled wrt. NULL-termination and what the libsodium @@ -117,7 +121,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.17.0] -### Added +### Added [0.17.0] - Expose the AEAD ChaCha20 Poly1305 (IETF) functionality (Hans Svensson / Quviq). @@ -130,12 +134,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. to verify the enacl library on embedded platforms and so on. - Support generichash functions (Venkatakumar Srinivasan / Xaptum) -### Fixed +### Fixed [0.17.0] - The type specification of generichash/2 and generichash/3 was corrected (Technion) -### Changed +### Changed [0.17.0] - Removed the experimental feature flag `ERL_NIF_DIRTY_JOB_CPU_BOUND`. This breaks compatibility with older Erlang releases of dirty @@ -154,26 +158,26 @@ Bump libsodium requirement to version 1.0.12. This gives us access to a number of functions which are added recently and thus gives us access to implement these from libsodium. -### Added +### Added [0.16.0] - Add kx_* functions (Alexander Malaev) - chacha stream functions added, siphash-2-4 added, unsafe_memzero/1 added (no attribution) -### Fixed +### Fixed [0.16.0] - Do not use the dirty-scheduler test macro as it is gone. ## [0.15.0] -### Fixed +### Fixed [0.15.0] - Using `enacl:sign_verify_detacted` on large iolists would fail to do the correct thing due to a typo. This has been corrected. Also the EQC tests have been extended to include large binary support to capture these kinds of errors in the future. -### Changed +### Changed [0.15.0] - Many dirty-scheduler tunings have been performed to make sure we won't block a scheduler ever. @@ -189,13 +193,13 @@ a better citizen to other libraries and other parts of the system. ## [0.14.0] -### Added +### Added [0.14.0] - Add support for libsodiums `box_seal` functions (Amir Ghassemi Nasr) - Add support for libsodiums `crypto_sign_detached` (Joel Stanley, Parnell Springmeyer) -### Changed +### Changed [0.14.0] - Switch the tag names to the form `0.14.0` rather than `v0.14.0`. For this release both tags are present, but from the next release on, it @@ -203,25 +207,25 @@ a better citizen to other libraries and other parts of the system. ## [0.13.0] -### Fixed +### Fixed [0.13.0] - Quell warnings from the C code -### Added +### Added [0.13.0] - Add Ed 25519 utility API (Alexander Færøy) - Add FreeBSD support for the NIF compilation (Ricardo Lanziano) ## [0.12.1] -### Changed +### Changed [0.12.1] - Provide the `priv` directory for being able to properly build without manual intervention. ## [0.12.0] -### Added +### Added [0.12.0] - Introduce an extension interface for various necessary extensions to the eNaCl system for handling the Tor network, thanks to Alexander @@ -232,14 +236,14 @@ a better citizen to other libraries and other parts of the system. ## [0.11.0] -### Added +### Added [0.11.0] - Introduce NIF layer beforenm/afternm calls. - Introduce the API for precomputed keys (beforenm/afternm calls). - Use test cases which tries to inject `iodata()` rather than binaries in all places where `iodata()` tend to be accepted. -### Fixed +### Fixed [0.11.0] - Fix type for `enacl:box_open/4`. The specification was wrong which results in errors in other applications using enacl. @@ -248,7 +252,7 @@ a better citizen to other libraries and other parts of the system. Maintenance release. Fix some usability problems with the library. -### Fixed +### Fixed [0.10.2] - Do not compile the C NIF code if there are no dirty scheduler support in the Erlang system (Thanks to David N. Welton) @@ -263,7 +267,7 @@ Maintenance release. Fix some usability problems with the library. ## [0.10.1] -### Added +### Added [0.10.1] - This small patch-release provides tests for the `randombytes/1` function call, and optimizes EQC tests to make it easier to implement @@ -279,7 +283,7 @@ included in this library. Ultra-late beta; tuning for the last couple of functions which could be nice to have. -### Added +### Added [0.10.0] Added the function `randombytes/1` to obtain randombytes from the operating system. The system uses the "best" applicable (P)RNG on the From 9bdb1ccf1b0ad6e0e200ae73aebd7e20e42e9ed1 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 29 Aug 2020 18:22:38 +0200 Subject: [PATCH 114/162] v1.1.1 --- CHANGELOG.md | 4 ++-- src/enacl.app.src | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d167f4..3b4e52f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [1.1.1] -### Added +### Added [1.1.1] - Introduce the ability to reload the enacl module (Bryan Paxton, @starbelly) diff --git a/src/enacl.app.src b/src/enacl.app.src index 2238df5..4cdecec 100644 --- a/src/enacl.app.src +++ b/src/enacl.app.src @@ -1,6 +1,6 @@ {application,enacl, [{description,"Erlang libsodium (NaCl) bindings"}, - {vsn,"1.1.0"}, + {vsn,"1.1.1"}, {registered,[]}, {applications,[kernel,stdlib]}, {env,[]}, From 9919871e5313df24497914bb50791f0690a3be97 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 29 Aug 2020 18:23:34 +0200 Subject: [PATCH 115/162] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b4e52f..c1afbab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## Unreleased + ## [1.1.1] ### Added [1.1.1] From 442094df0d8e9b8517f3953d213bade188c6f4e9 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 14 Jun 2021 16:17:19 +0200 Subject: [PATCH 116/162] Use lorri for development --- shell.nix | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/shell.nix b/shell.nix index 7c2ad6e..c252f46 100644 --- a/shell.nix +++ b/shell.nix @@ -1,16 +1,12 @@ { pkgs ? import {} }: -with pkgs; +pkgs.mkShell { + buildInputs = [ + pkgs.hello -let - inherit (lib) optional optionals; - - erlang_wx = erlangR23.override { - wxSupport = true; - }; -in - -mkShell { - buildInputs = [ erlang_wx git libsodium ] - ++ optional stdenv.isLinux inotify-tools; + # keep this line if you use bash + pkgs.bashInteractive + pkgs.erlang + pkgs.libsodium + ]; } From 1bb0d59c7f49bb1a6fbb49b42a6de78a1cf3e295 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 14 Jun 2021 16:17:28 +0200 Subject: [PATCH 117/162] Lorri direnv --- .envrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 .envrc diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..051d09d --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +eval "$(lorri direnv)" From 87282dc4f824d7e4e247ebd5f7c59f90fc34256f Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 14 Jun 2021 17:17:19 +0200 Subject: [PATCH 118/162] Fix signatures for final-verify --- src/enacl_nif.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index b90e11f..3ecb962 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -288,7 +288,7 @@ crypto_sign_verify_detached(_Sig, _M, _PK) -> erlang:nif_error(nif_not_loaded). crypto_sign_init() -> erlang:nif_error(nif_not_loaded). crypto_sign_update(_S, _M) -> erlang:nif_error(nif_not_loaded). crypto_sign_final_create(_S, _SK) -> erlang:nif_error(nif_not_loaded). -crypto_sign_final_verify(_S, _S, _PK) -> erlang:nif_error(nif_not_loaded). +crypto_sign_final_verify(_State, _Sig, _PK) -> erlang:nif_error(nif_not_loaded). crypto_box_seal(_Msg, _PK) -> erlang:nif_error(nif_not_loaded). crypto_box_seal_open(_CipherText, _PK, _SK) -> erlang:nif_error(nif_not_loaded). From 7f0667553335d0d6fd7ee3d46e08c4f9efb7f6e5 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 13:02:06 +0200 Subject: [PATCH 119/162] Add a CT for verify_detached --- test/enacl_SUITE.erl | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index c569214..cd8f229 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -38,14 +38,17 @@ groups() -> Neg = {negative, [shuffle, parallel], [generichash_basic_neg]}, Pos = {positive, [shuffle, parallel], - [generichash_basic_pos, - generichash_chunked, - aead_xchacha20poly1305, + [ aead_chacha20poly1305_ietf, - pwhash, - sign, + aead_xchacha20poly1305, + generichash_basic_pos, + generichash_chunked, kx, - secretstream]}, + pwhash, + secretstream, + sign, + verify_detached + ]}, [Neg, Pos]. @@ -184,3 +187,10 @@ secretstream(_Config) -> {Part2, message} = enacl:secretstream_xchacha20poly1305_pull(DState, Block2, <<>>), {Part3, final} = enacl:secretstream_xchacha20poly1305_pull(DState, Block3, <<"AD3">>), ok. + +verify_detached(_Config) -> + #{ public := PK, secret := SK} = enacl:sign_keypair(), + M = <<"Arbitrary data to encrypt">>, + Sig = enacl:sign_detached(M, SK), + true = enacl:sign_verify_detached(Sig, M, PK), + ok. From 0855ce2f5503ec3b3fb8f906b7f9e75e9f0f0b55 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 13:03:30 +0200 Subject: [PATCH 120/162] Small documentation fixups --- src/enacl.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/enacl.erl b/src/enacl.erl index c839585..5120f7c 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -1222,7 +1222,7 @@ kx_SECRETKEYBYTES() -> %% ---------------------- %% @doc aead_chacha20poly1305_encrypt/4 encrypts `Message' with additional data %% `AD' using `Key' and `Nonce'. Returns the encrypted message followed by -%% `aead_chacha20poly1305_ABYTES/0' bytes of MAC. +%% aead_chacha20poly1305_ABYTES/0 bytes of MAC. %% @end -spec aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) -> binary() when Key :: binary(), @@ -1234,7 +1234,7 @@ aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) -> %% @doc aead_chacha20poly1305_decrypt/4 decrypts ciphertext `CT' with additional %% data `AD' using `Key' and `Nonce'. Note: `CipherText' should contain -%% `aead_chacha20poly1305_ABYTES/0' bytes that is the MAC. Returns the decrypted +%% aead_chacha20poly1305_ABYTES/0 bytes that is the MAC. Returns the decrypted %% message. %% @end -spec aead_chacha20poly1305_ietf_decrypt(CT, AD, Nonce, Key) -> binary() | {error, term()} From d6bd999c820317b742d02b4297e7619d126d9203 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 13:05:48 +0200 Subject: [PATCH 121/162] sign_verify_detached: guard against size The code didn't properly do a size check on a detached signature. Now it does. While here, fix a problem with EQC tests, for the same piece of code. --- c_src/sign.c | 4 ++++ eqc_test/enacl_eqc.erl | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/c_src/sign.c b/c_src/sign.c index 292e31c..fb06203 100644 --- a/c_src/sign.c +++ b/c_src/sign.c @@ -468,6 +468,10 @@ enacl_crypto_sign_verify_detached(ErlNifEnv *env, int argc, return enif_make_badarg(env); } + if (sig.size != crypto_sign_BYTES) { + return enif_make_badarg(env); + } + if (pk.size != crypto_sign_PUBLICKEYBYTES) { return enif_make_badarg(env); } diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 38464b4..6093a5b 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -419,7 +419,7 @@ signed_message(M) -> ?FAULT(signed_message_bad(), signed_message_good(M)). signed_message_d(M) -> - ?FAULT(signed_message_bad(), signed_message_good(M)). + ?FAULT(signed_message_bad_d(), signed_message_good_d(M)). signed_message_valid({valid, _}, _) -> true; signed_message_valid({invalid, _}, _) -> true; From ea72835b50e3c7437fc6062c7982ba0b2db64182 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 13:10:51 +0200 Subject: [PATCH 122/162] Bump changelog --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1afbab..d53b6aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## Unreleased +## [1.2.0] + +### Fixed [1.2.0] + +- `sign_verify_detached/3` The code now verifies the size of signatures in detached mode. Before + this change, you could supply a larger binary and the code would only use the first `SIGNBYTES` + of the binary, assuming the signature were in there. Now, it fails with a badarg if the signature + doesn't match expectation in size. ## [1.1.1] From 3d9cc841eb2b0dc6b0d1d9c3412c1bdf511e6835 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 13:29:58 +0200 Subject: [PATCH 123/162] v1.2.0 --- src/enacl.app.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/enacl.app.src b/src/enacl.app.src index 4cdecec..2290594 100644 --- a/src/enacl.app.src +++ b/src/enacl.app.src @@ -1,6 +1,6 @@ {application,enacl, [{description,"Erlang libsodium (NaCl) bindings"}, - {vsn,"1.1.1"}, + {vsn,"1.2.0"}, {registered,[]}, {applications,[kernel,stdlib]}, {env,[]}, From 0b8abb95d56f2d9c684300f3a79b0c10a9dd5a26 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:24:45 +0200 Subject: [PATCH 124/162] Actions. --- .github/workflows/Makefile | 3 +++ .github/workflows/ci.cue | 23 +++++++++++++++++++++++ .github/workflows/ci.yaml | 31 +++++++++++++++++++++++++++++++ Makefile | 3 +++ 4 files changed, 60 insertions(+) create mode 100644 .github/workflows/Makefile create mode 100644 .github/workflows/ci.cue create mode 100644 .github/workflows/ci.yaml diff --git a/.github/workflows/Makefile b/.github/workflows/Makefile new file mode 100644 index 0000000..663cd71 --- /dev/null +++ b/.github/workflows/Makefile @@ -0,0 +1,3 @@ +all: + cue export --out yaml ci.cue > ci.yaml + diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue new file mode 100644 index 0000000..73c934c --- /dev/null +++ b/.github/workflows/ci.cue @@ -0,0 +1,23 @@ +name: "build" +on: { + push: branches: [ + "master", + ] + pull_request: branches: [ + "master", + ] +} +jobs: ci: { + name: "Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}}" + "runs-on": "${{matrix.os}}" + container: image: "erlang:${{matrix.otp_vsn}}" + strategy: matrix: { + otp_vsn: [18.3, 19.3, 20.3, 21.3, 22.3, 23.3, 24.0] + os: ["ubuntu-latest"] + } + steps: [ + {uses: "actions/checkout@v2"}, + {run: "sudo apt get instal libsodium-dev"}, + {run: "make compile"}, + {run: "make tests"}] +} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..951b4f3 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,31 @@ +name: build +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + ci: + name: Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}} + runs-on: ${{matrix.os}} + container: + image: erlang:${{matrix.otp_vsn}} + strategy: + matrix: + otp_vsn: + - 18.3 + - 19.3 + - 20.3 + - 21.3 + - 22.3 + - 23.3 + - 24.0 + os: + - ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: sudo apt get instal libsodium-dev + - run: make compile + - run: make tests diff --git a/Makefile b/Makefile index 481ed00..a9db92e 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,9 @@ RUN_EQC=erl -pa _build/default/lib/enacl/ebin -noshell -s enacl_eqc -s init stop compile: $(REBAR) compile +.PHONY: tests + $(REBAR) ct + eqc_compile: compile erlc -o _build/default/lib/enacl/ebin eqc_test/enacl_eqc.erl From 73a6462ef3a7b053c65a8cfcb4eae8b65ae7c97b Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:29:32 +0200 Subject: [PATCH 125/162] Fix apt-get install command, try without sudo. --- .github/workflows/ci.cue | 3 ++- .github/workflows/ci.yaml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 73c934c..8fd8532 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -17,7 +17,8 @@ jobs: ci: { } steps: [ {uses: "actions/checkout@v2"}, - {run: "sudo apt get instal libsodium-dev"}, + [{name: "Install libsodium"}, + {run: "apt-get install -y libsodium-dev"}], {run: "make compile"}, {run: "make tests"}] } diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 951b4f3..5058d4e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,6 +26,7 @@ jobs: - ubuntu-latest steps: - uses: actions/checkout@v2 - - run: sudo apt get instal libsodium-dev + - - name: Install libsodium + - run: apt-get install -y libsodium-dev - run: make compile - run: make tests From 3a4d000c56f842db3b17c320a28d372c760630c9 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:32:40 +0200 Subject: [PATCH 126/162] Start utilizing cue tooling. --- .github/workflows/ci.cue | 7 ++++++- .github/workflows/ci.yaml | 9 +-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 8fd8532..74d193c 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -1,3 +1,8 @@ +let OTP_Versions = { + latest: 24.0 + all: [18.3, 19.3, 20.3, 21.3, 22.3, 23.3, 24.0] +} + name: "build" on: { push: branches: [ @@ -12,7 +17,7 @@ jobs: ci: { "runs-on": "${{matrix.os}}" container: image: "erlang:${{matrix.otp_vsn}}" strategy: matrix: { - otp_vsn: [18.3, 19.3, 20.3, 21.3, 22.3, 23.3, 24.0] + otp_vsn: OTP_Versions.latest os: ["ubuntu-latest"] } steps: [ diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5058d4e..0c592de 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,14 +14,7 @@ jobs: image: erlang:${{matrix.otp_vsn}} strategy: matrix: - otp_vsn: - - 18.3 - - 19.3 - - 20.3 - - 21.3 - - 22.3 - - 23.3 - - 24.0 + otp_vsn: 24.0 os: - ubuntu-latest steps: From f99c8643f0baeb6bbd0d3999e71bee7404d9de30 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:34:31 +0200 Subject: [PATCH 127/162] Type correction. --- .github/workflows/ci.cue | 2 +- .github/workflows/ci.yaml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 74d193c..e491372 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -1,5 +1,5 @@ let OTP_Versions = { - latest: 24.0 + latest: [24.0] all: [18.3, 19.3, 20.3, 21.3, 22.3, 23.3, 24.0] } diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0c592de..7b518e8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,7 +14,8 @@ jobs: image: erlang:${{matrix.otp_vsn}} strategy: matrix: - otp_vsn: 24.0 + otp_vsn: + - 24.0 os: - ubuntu-latest steps: From e59656ebf68b436f98f93196f6d61164c245f5eb Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:35:37 +0200 Subject: [PATCH 128/162] fix sequence to dict. --- .github/workflows/ci.cue | 4 ++-- .github/workflows/ci.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index e491372..4f77f49 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -22,8 +22,8 @@ jobs: ci: { } steps: [ {uses: "actions/checkout@v2"}, - [{name: "Install libsodium"}, - {run: "apt-get install -y libsodium-dev"}], + {name: "Install libsodium", + run: "apt-get install -y libsodium-dev"}, {run: "make compile"}, {run: "make tests"}] } diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7b518e8..48144b0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,7 +20,7 @@ jobs: - ubuntu-latest steps: - uses: actions/checkout@v2 - - - name: Install libsodium - - run: apt-get install -y libsodium-dev + - name: Install libsodium + run: apt-get install -y libsodium-dev - run: make compile - run: make tests From 5f22892ce40cb897a1b5907910d0d1268988d2fd Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:36:55 +0200 Subject: [PATCH 129/162] More QoL interaction. --- .github/workflows/ci.cue | 6 ++++-- .github/workflows/ci.yaml | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 4f77f49..509a803 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -24,6 +24,8 @@ jobs: ci: { {uses: "actions/checkout@v2"}, {name: "Install libsodium", run: "apt-get install -y libsodium-dev"}, - {run: "make compile"}, - {run: "make tests"}] + {name: "Compile source code", + run: "make compile"}, + {name: "Run the tests", + run: "make tests"}] } diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 48144b0..182af0f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -22,5 +22,7 @@ jobs: - uses: actions/checkout@v2 - name: Install libsodium run: apt-get install -y libsodium-dev - - run: make compile - - run: make tests + - name: Compile source code + run: make compile + - name: Run the tests + run: make tests From aca072630ed7ee792623981e649e082d1f650bca Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:38:34 +0200 Subject: [PATCH 130/162] Need libsodium-dev and 23. --- .github/workflows/ci.cue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 509a803..632061c 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -23,7 +23,7 @@ jobs: ci: { steps: [ {uses: "actions/checkout@v2"}, {name: "Install libsodium", - run: "apt-get install -y libsodium-dev"}, + run: "apt-get install -y libsodium23 libsodium-dev"}, {name: "Compile source code", run: "make compile"}, {name: "Run the tests", From ef049c921f504f0ab3022f34679ec24c12ff5cbc Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:41:10 +0200 Subject: [PATCH 131/162] Lets try sudo again, shall we? --- .github/workflows/ci.cue | 2 +- .github/workflows/ci.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 632061c..d3c139e 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -23,7 +23,7 @@ jobs: ci: { steps: [ {uses: "actions/checkout@v2"}, {name: "Install libsodium", - run: "apt-get install -y libsodium23 libsodium-dev"}, + run: "sudo apt-get install -y libsodium23 libsodium-dev"}, {name: "Compile source code", run: "make compile"}, {name: "Run the tests", diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 182af0f..e319d64 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install libsodium - run: apt-get install -y libsodium-dev + run: sudo apt-get install -y libsodium23 libsodium-dev - name: Compile source code run: make compile - name: Run the tests From ba69139283bc22b911b0598da196f57758684b48 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:45:21 +0200 Subject: [PATCH 132/162] New try. --- .github/workflows/ci.cue | 2 +- .github/workflows/ci.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index d3c139e..bfdc078 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -23,7 +23,7 @@ jobs: ci: { steps: [ {uses: "actions/checkout@v2"}, {name: "Install libsodium", - run: "sudo apt-get install -y libsodium23 libsodium-dev"}, + run: "sudo apt-get install -y libsodium"}, {name: "Compile source code", run: "make compile"}, {name: "Run the tests", diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e319d64..6031b8b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install libsodium - run: sudo apt-get install -y libsodium23 libsodium-dev + run: sudo apt-get install -y libsodium - name: Compile source code run: make compile - name: Run the tests From f879ec00a7a25a53bbad4e18c31a958057c8d632 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:49:32 +0200 Subject: [PATCH 133/162] Image doesnt use libsodium. --- .github/workflows/ci.cue | 2 +- .github/workflows/ci.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index bfdc078..0703a92 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -23,7 +23,7 @@ jobs: ci: { steps: [ {uses: "actions/checkout@v2"}, {name: "Install libsodium", - run: "sudo apt-get install -y libsodium"}, + run: "apt-get install -y libsodium"}, {name: "Compile source code", run: "make compile"}, {name: "Run the tests", diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6031b8b..29de46f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install libsodium - run: sudo apt-get install -y libsodium + run: apt-get install -y libsodium - name: Compile source code run: make compile - name: Run the tests From e41634b75c2fa3d9a12abf6ea441736b9a69eb8a Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:53:42 +0200 Subject: [PATCH 134/162] Update apt-get database. --- .github/workflows/ci.cue | 4 +++- .github/workflows/ci.yaml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 0703a92..71c359e 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -22,8 +22,10 @@ jobs: ci: { } steps: [ {uses: "actions/checkout@v2"}, + {name: "Update apt-get database", + run: "apt-get update"}, {name: "Install libsodium", - run: "apt-get install -y libsodium"}, + run: "apt-get install -y libsodium-dev"}, {name: "Compile source code", run: "make compile"}, {name: "Run the tests", diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 29de46f..2ebce0e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,8 +20,10 @@ jobs: - ubuntu-latest steps: - uses: actions/checkout@v2 + - name: Update apt-get database + run: apt-get update - name: Install libsodium - run: apt-get install -y libsodium + run: apt-get install -y libsodium-dev - name: Compile source code run: make compile - name: Run the tests From c6f4e21c9ab0b03a74057a3bfbeb323dbc5ddcbc Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:55:17 +0200 Subject: [PATCH 135/162] Actually do test. --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index a9db92e..ce60591 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ compile: $(REBAR) compile .PHONY: tests +tests: $(REBAR) ct eqc_compile: compile From b7034392bd8e191d67736712f4d2b0ce9f8418da Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 14:55:52 +0200 Subject: [PATCH 136/162] Enable on all images. --- .github/workflows/ci.cue | 2 +- .github/workflows/ci.yaml | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 71c359e..0981f4f 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -17,7 +17,7 @@ jobs: ci: { "runs-on": "${{matrix.os}}" container: image: "erlang:${{matrix.otp_vsn}}" strategy: matrix: { - otp_vsn: OTP_Versions.latest + otp_vsn: OTP_Versions.all os: ["ubuntu-latest"] } steps: [ diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2ebce0e..5e2eb10 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,6 +15,12 @@ jobs: strategy: matrix: otp_vsn: + - 18.3 + - 19.3 + - 20.3 + - 21.3 + - 22.3 + - 23.3 - 24.0 os: - ubuntu-latest From fe33927fb354870e393b2f1bd0bc5208155324b8 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 15:00:22 +0200 Subject: [PATCH 137/162] Only run on 24.0 for now. --- .github/workflows/ci.cue | 2 +- .github/workflows/ci.yaml | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 0981f4f..71c359e 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -17,7 +17,7 @@ jobs: ci: { "runs-on": "${{matrix.os}}" container: image: "erlang:${{matrix.otp_vsn}}" strategy: matrix: { - otp_vsn: OTP_Versions.all + otp_vsn: OTP_Versions.latest os: ["ubuntu-latest"] } steps: [ diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5e2eb10..2ebce0e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,12 +15,6 @@ jobs: strategy: matrix: otp_vsn: - - 18.3 - - 19.3 - - 20.3 - - 21.3 - - 22.3 - - 23.3 - 24.0 os: - ubuntu-latest From 6cc2529023f0d4d8b2896f0667dbf7c187cb2f1b Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 15:00:59 +0200 Subject: [PATCH 138/162] Move more into base. --- .github/workflows/ci.cue | 3 ++- .github/workflows/ci.yaml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 71c359e..3a1ba08 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -1,6 +1,7 @@ let OTP_Versions = { latest: [24.0] all: [18.3, 19.3, 20.3, 21.3, 22.3, 23.3, 24.0] + test: [23.3, 24.0] } name: "build" @@ -17,7 +18,7 @@ jobs: ci: { "runs-on": "${{matrix.os}}" container: image: "erlang:${{matrix.otp_vsn}}" strategy: matrix: { - otp_vsn: OTP_Versions.latest + otp_vsn: OTP_Versions.test os: ["ubuntu-latest"] } steps: [ diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2ebce0e..2f506f3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,6 +15,7 @@ jobs: strategy: matrix: otp_vsn: + - 23.3 - 24.0 os: - ubuntu-latest From 61b83710b5add0e469a15219381dbce521df2e00 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 15:02:21 +0200 Subject: [PATCH 139/162] Test 22.3. --- .github/workflows/ci.cue | 2 +- .github/workflows/ci.yaml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 3a1ba08..326ff9a 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -1,7 +1,7 @@ let OTP_Versions = { latest: [24.0] all: [18.3, 19.3, 20.3, 21.3, 22.3, 23.3, 24.0] - test: [23.3, 24.0] + test: [22.3] } name: "build" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2f506f3..9ef1f27 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,8 +15,7 @@ jobs: strategy: matrix: otp_vsn: - - 23.3 - - 24.0 + - 22.3 os: - ubuntu-latest steps: From f8bd7f356569a7929e05a2bba100d0eec1db93b0 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 15:03:47 +0200 Subject: [PATCH 140/162] Older version check. --- .github/workflows/ci.cue | 2 +- .github/workflows/ci.yaml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 326ff9a..7344e55 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -1,7 +1,7 @@ let OTP_Versions = { latest: [24.0] all: [18.3, 19.3, 20.3, 21.3, 22.3, 23.3, 24.0] - test: [22.3] + test: [20.3, 21.3] } name: "build" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9ef1f27..54ae413 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,7 +15,8 @@ jobs: strategy: matrix: otp_vsn: - - 22.3 + - 20.3 + - 21.3 os: - ubuntu-latest steps: From 8ac26c8161ef4b0649dd8c63e2b09c07be92d946 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 15:10:13 +0200 Subject: [PATCH 141/162] Cleanup. --- .github/workflows/ci.cue | 10 ++++++---- .github/workflows/ci.yaml | 7 +++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 7344e55..9a11fea 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -1,7 +1,9 @@ let OTP_Versions = { latest: [24.0] - all: [18.3, 19.3, 20.3, 21.3, 22.3, 23.3, 24.0] - test: [20.3, 21.3] + // Older versions than 22.3 use Debian stretch, and it only has libsodium 0.18 + // In turn, we can't compile for the newer libsodium functions on this image, + // and it fails. Hence these versions. + all: [22.3, 23.3, 24.0] } name: "build" @@ -18,8 +20,8 @@ jobs: ci: { "runs-on": "${{matrix.os}}" container: image: "erlang:${{matrix.otp_vsn}}" strategy: matrix: { - otp_vsn: OTP_Versions.test - os: ["ubuntu-latest"] + otp_vsn: OTP_Versions.all + // os: ["ubuntu-latest"] // This is somewhat of a lie. } steps: [ {uses: "actions/checkout@v2"}, diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 54ae413..b606284 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,10 +15,9 @@ jobs: strategy: matrix: otp_vsn: - - 20.3 - - 21.3 - os: - - ubuntu-latest + - 22.3 + - 23.3 + - 24.0 steps: - uses: actions/checkout@v2 - name: Update apt-get database From 8b8fe9fa987104de9fac1c83da467a0da55fe4cc Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 15 Jun 2021 15:12:39 +0200 Subject: [PATCH 142/162] More updates and learning. --- .github/workflows/ci.cue | 4 +++- .github/workflows/ci.yaml | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 9a11fea..0e65c1b 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -21,7 +21,9 @@ jobs: ci: { container: image: "erlang:${{matrix.otp_vsn}}" strategy: matrix: { otp_vsn: OTP_Versions.all - // os: ["ubuntu-latest"] // This is somewhat of a lie. + // This entry is a lie. The container images are Debian containers, but + // one has to specify where those containers are hosted. + os: ["ubuntu-latest"] } steps: [ {uses: "actions/checkout@v2"}, diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b606284..fe87f85 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,6 +18,8 @@ jobs: - 22.3 - 23.3 - 24.0 + os: + - ubuntu-latest steps: - uses: actions/checkout@v2 - name: Update apt-get database From 529d8f603301e15c5b3cbd3c395d092bf529fc94 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 18 Jun 2021 14:32:47 +0200 Subject: [PATCH 143/162] Use types --- .github/workflows/ci.cue | 84 +++++++++++++++++++++++++++------------ .github/workflows/ci.yaml | 6 +-- 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 0e65c1b..f214a53 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -1,13 +1,40 @@ -let OTP_Versions = { - latest: [24.0] +// Versions for simplicity +_versions: { + latest: ["24.0"] // Older versions than 22.3 use Debian stretch, and it only has libsodium 0.18 // In turn, we can't compile for the newer libsodium functions on this image, // and it fails. Hence these versions. - all: [22.3, 23.3, 24.0] + all: ["22.3", "23.3", "24.0"] } -name: "build" -on: { +#Name: string +#Branches: branches: [string] + +#On: { + push: #Branches + pull_request: #Branches +} +#Steps: { + uses: "actions/checkout@v2" +} | { + name: string + run: string +} + +#Jobs: ci: { + name: string + "runs-on": string + container: image: string + strategy: + matrix: { + otp_vsn: [string, ...] + os: ["ubuntu-latest"] + } + steps: [#Steps, ...] +} + +name: #Name & "build" +on: #On & { push: branches: [ "master", ] @@ -15,24 +42,29 @@ on: { "master", ] } -jobs: ci: { - name: "Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}}" - "runs-on": "${{matrix.os}}" - container: image: "erlang:${{matrix.otp_vsn}}" - strategy: matrix: { - otp_vsn: OTP_Versions.all - // This entry is a lie. The container images are Debian containers, but - // one has to specify where those containers are hosted. - os: ["ubuntu-latest"] - } - steps: [ - {uses: "actions/checkout@v2"}, - {name: "Update apt-get database", - run: "apt-get update"}, - {name: "Install libsodium", - run: "apt-get install -y libsodium-dev"}, - {name: "Compile source code", - run: "make compile"}, - {name: "Run the tests", - run: "make tests"}] -} +jobs: #Jobs & { + ci: { + name: "Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}}" + "runs-on": "${{matrix.os}}" + container: image: "erlang:${{matrix.otp_vsn}}" + strategy: matrix: { + otp_vsn: _versions.all + // This entry is a lie. The container images are Debian containers, but + // one has to specify where those containers are hosted. + os: ["ubuntu-latest"] + } + steps: [ + {uses: "actions/checkout@v2"}, + {name: "Update apt-get database" + run: "apt-get update" + }, + {name: "Install libsodium" + run: "apt-get install -y libsodium-dev" + }, + {name: "Compile source code" + run: "make compile" + }, + {name: "Run the tests" + run: "make tests" + }] + }} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fe87f85..268479c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,9 +15,9 @@ jobs: strategy: matrix: otp_vsn: - - 22.3 - - 23.3 - - 24.0 + - "22.3" + - "23.3" + - "24.0" os: - ubuntu-latest steps: From f301929d758b61cc6f5e86157a2e6f40373d4565 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 18 Jun 2021 14:33:49 +0200 Subject: [PATCH 144/162] Formatting --- .github/workflows/ci.cue | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index f214a53..9c64229 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -55,16 +55,20 @@ jobs: #Jobs & { } steps: [ {uses: "actions/checkout@v2"}, - {name: "Update apt-get database" - run: "apt-get update" + { + name: "Update apt-get database" + run: "apt-get update" }, - {name: "Install libsodium" - run: "apt-get install -y libsodium-dev" + { + name: "Install libsodium" + run: "apt-get install -y libsodium-dev" }, - {name: "Compile source code" - run: "make compile" + { + name: "Compile source code" + run: "make compile" }, - {name: "Run the tests" - run: "make tests" + { + name: "Run the tests" + run: "make tests" }] }} From e748552809776863c99a64d45ab0ddb694049c04 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 18 Jun 2021 17:02:26 +0200 Subject: [PATCH 145/162] More CUE --- .github/workflows/ci.cue | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 9c64229..4aeba42 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -8,27 +8,33 @@ _versions: { } #Name: string -#Branches: branches: [string] +#Branches: branches: [string, ...] +#Tags: tags: [string, ...] #On: { - push: #Branches - pull_request: #Branches + push?: #Branches + pull_request?: #Branches + page_build?: #Branches } + +#Action: "actions/checkout@v2" #Steps: { - uses: "actions/checkout@v2" + uses: #Action } | { name: string run: string } +#OS_Version: "ubuntu-latest" | "macos-latest" | "windows_latest" + #Jobs: ci: { name: string "runs-on": string container: image: string strategy: matrix: { - otp_vsn: [string, ...] - os: ["ubuntu-latest"] + otp_vsn: [...string] + os: [...#OS_Version] } steps: [#Steps, ...] } From b81fa6f0d6ee1584b7f7667eb6bda2af5f129461 Mon Sep 17 00:00:00 2001 From: Paulo Oliveira Date: Fri, 18 Jun 2021 18:35:19 +0100 Subject: [PATCH 146/162] Allow for more flexibility in rebar3 version --- .github/workflows/ci.cue | 14 +++++++++++--- .github/workflows/ci.yaml | 7 +++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 4aeba42..0487bb0 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -5,6 +5,7 @@ _versions: { // In turn, we can't compile for the newer libsodium functions on this image, // and it fails. Hence these versions. all: ["22.3", "23.3", "24.0"] + rebar3: "3.16.1" } #Name: string @@ -17,9 +18,11 @@ _versions: { page_build?: #Branches } -#Action: "actions/checkout@v2" +#Action: "actions/checkout@v2" | "actions/setup-beam@v1" #Steps: { uses: #Action + with: + _: string } | { name: string run: string @@ -30,7 +33,6 @@ _versions: { #Jobs: ci: { name: string "runs-on": string - container: image: string strategy: matrix: { otp_vsn: [...string] @@ -52,7 +54,6 @@ jobs: #Jobs & { ci: { name: "Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}}" "runs-on": "${{matrix.os}}" - container: image: "erlang:${{matrix.otp_vsn}}" strategy: matrix: { otp_vsn: _versions.all // This entry is a lie. The container images are Debian containers, but @@ -65,6 +66,13 @@ jobs: #Jobs & { name: "Update apt-get database" run: "apt-get update" }, + { + uses: "actions/setup-beam@v1" + with: { + "otp-version": "${{matrix.otp_vsn}}" + "rebar3-version": _versions.rebar3 + } + }, { name: "Install libsodium" run: "apt-get install -y libsodium-dev" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 268479c..31c96c7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,8 +10,6 @@ jobs: ci: name: Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}} runs-on: ${{matrix.os}} - container: - image: erlang:${{matrix.otp_vsn}} strategy: matrix: otp_vsn: @@ -22,8 +20,13 @@ jobs: - ubuntu-latest steps: - uses: actions/checkout@v2 + with: {} - name: Update apt-get database run: apt-get update + - uses: actions/setup-beam@v1 + with: + otp-version: ${{matrix.otp_vsn}} + rebar3-version: 3.16.1 - name: Install libsodium run: apt-get install -y libsodium-dev - name: Compile source code From 36cab6aedb4d9f51079974b927b2fdaaa46c853d Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 18 Jun 2021 23:51:10 +0200 Subject: [PATCH 147/162] Update ci.yaml Hack in to push it forward --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 31c96c7..8495afa 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -23,7 +23,7 @@ jobs: with: {} - name: Update apt-get database run: apt-get update - - uses: actions/setup-beam@v1 + - uses: erlef/setup-beam@v1 with: otp-version: ${{matrix.otp_vsn}} rebar3-version: 3.16.1 From 129f5e2acffc5a038cefae275ec1e7c3db86df19 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 18 Jun 2021 23:53:34 +0200 Subject: [PATCH 148/162] Sudo apt-get update This verifies we are in a proper image where we need to sudo in updates, etc. --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8495afa..6a1c454 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v2 with: {} - name: Update apt-get database - run: apt-get update + run: sudo apt-get update - uses: erlef/setup-beam@v1 with: otp-version: ${{matrix.otp_vsn}} From 9331ef974e03a46e8d76cf9dc41c1415d7b4dca5 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 18 Jun 2021 23:56:11 +0200 Subject: [PATCH 149/162] Sudo the libsodium installation too --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6a1c454..bf74ac9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -28,7 +28,7 @@ jobs: otp-version: ${{matrix.otp_vsn}} rebar3-version: 3.16.1 - name: Install libsodium - run: apt-get install -y libsodium-dev + run: sudo apt-get install -y libsodium-dev - name: Compile source code run: make compile - name: Run the tests From d801018f2348a78f2af8ffa79078e9a1cd9555bf Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 19 Jun 2021 00:08:27 +0200 Subject: [PATCH 150/162] Strengthen Cue a bit --- .github/workflows/ci.cue | 33 +++++++++++++++++++-------------- .github/workflows/ci.yaml | 1 - 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 0487bb0..d7e01f8 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -18,15 +18,18 @@ _versions: { page_build?: #Branches } -#Action: "actions/checkout@v2" | "actions/setup-beam@v1" -#Steps: { +#Action: "actions/checkout@v2" | "erlef/setup-beam@v1" +#Uses : { uses: #Action - with: - _: string -} | { - name: string - run: string + with?: { + ... + } } +#Run: { + name: string + run: string +} +#Steps: #Uses | #Run #OS_Version: "ubuntu-latest" | "macos-latest" | "windows_latest" @@ -38,7 +41,7 @@ _versions: { otp_vsn: [...string] os: [...#OS_Version] } - steps: [#Steps, ...] + steps: [...#Steps] } name: #Name & "build" @@ -61,21 +64,23 @@ jobs: #Jobs & { os: ["ubuntu-latest"] } steps: [ - {uses: "actions/checkout@v2"}, { - name: "Update apt-get database" - run: "apt-get update" + uses: "actions/checkout@v2" }, { - uses: "actions/setup-beam@v1" + name: "Update apt-get database" + run: "sudo apt-get update" + }, + { + uses: "erlef/setup-beam@v1" with: { - "otp-version": "${{matrix.otp_vsn}}" + "otp-version": "${{matrix.otp_vsn}}" "rebar3-version": _versions.rebar3 } }, { name: "Install libsodium" - run: "apt-get install -y libsodium-dev" + run: "sudo apt-get install -y libsodium-dev" }, { name: "Compile source code" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index bf74ac9..365149f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,7 +20,6 @@ jobs: - ubuntu-latest steps: - uses: actions/checkout@v2 - with: {} - name: Update apt-get database run: sudo apt-get update - uses: erlef/setup-beam@v1 From 6242282bfdee16bd5c2c5bf3b2f68d6446d96419 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 19 Jun 2021 00:09:29 +0200 Subject: [PATCH 151/162] cue fmt --- .github/workflows/ci.cue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index d7e01f8..607970d 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -19,7 +19,7 @@ _versions: { } #Action: "actions/checkout@v2" | "erlef/setup-beam@v1" -#Uses : { +#Uses: { uses: #Action with?: { ... @@ -27,7 +27,7 @@ _versions: { } #Run: { name: string - run: string + run: string } #Steps: #Uses | #Run From 458c4ca9bc2afe739aa1cb684b51b3b547c53646 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 19 Jun 2021 00:17:19 +0200 Subject: [PATCH 152/162] Strengthen even more --- .github/workflows/ci.cue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 607970d..2683775 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -9,8 +9,8 @@ _versions: { } #Name: string -#Branches: branches: [string, ...] -#Tags: tags: [string, ...] +#Branches: branches: [...string] +#Tags: tags: [...string] #On: { push?: #Branches From a2717976416b67826c364315b85bcf08a0ab839d Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 19 Jun 2021 00:23:32 +0200 Subject: [PATCH 153/162] Update documentation. --- .github/workflows/ci.cue | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 2683775..e673e9d 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -1,9 +1,8 @@ // Versions for simplicity _versions: { latest: ["24.0"] - // Older versions than 22.3 use Debian stretch, and it only has libsodium 0.18 - // In turn, we can't compile for the newer libsodium functions on this image, - // and it fails. Hence these versions. + // The versions here have an underlying Debian/Ubuntu which support enough of + // libsodium to handle what enacl provides. Older versions will fail to compile all: ["22.3", "23.3", "24.0"] rebar3: "3.16.1" } @@ -59,8 +58,6 @@ jobs: #Jobs & { "runs-on": "${{matrix.os}}" strategy: matrix: { otp_vsn: _versions.all - // This entry is a lie. The container images are Debian containers, but - // one has to specify where those containers are hosted. os: ["ubuntu-latest"] } steps: [ From 756c222877f8403db847f0b80ad3eb0327c9af8d Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 19 Jun 2021 12:26:52 +0200 Subject: [PATCH 154/162] Reorder build a bit --- .github/workflows/ci.cue | 79 ++++++++++++++++++++------------------- .github/workflows/ci.yaml | 4 +- 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index e673e9d..2be84a7 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -7,6 +7,8 @@ _versions: { rebar3: "3.16.1" } +_branch: "master" + #Name: string #Branches: branches: [...string] #Tags: tags: [...string] @@ -30,7 +32,7 @@ _versions: { } #Steps: #Uses | #Run -#OS_Version: "ubuntu-latest" | "macos-latest" | "windows_latest" +#OS_Version: *"ubuntu-latest" | "macos-latest" | "windows_latest" #Jobs: ci: { name: string @@ -46,45 +48,46 @@ _versions: { name: #Name & "build" on: #On & { push: branches: [ - "master", + _branch, ] pull_request: branches: [ - "master", + _branch, ] } -jobs: #Jobs & { - ci: { - name: "Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}}" - "runs-on": "${{matrix.os}}" - strategy: matrix: { - otp_vsn: _versions.all - os: ["ubuntu-latest"] +jobs: #Jobs +jobs: ci: { + name: "Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}}" + "runs-on": "${{matrix.os}}" + strategy: matrix: { + otp_vsn: _versions.all + os: ["ubuntu-latest"] + } +} +jobs: ci: steps: +[ + { + uses: "actions/checkout@v2" + }, + { + uses: "erlef/setup-beam@v1" + with: { + "otp-version": "${{matrix.otp_vsn}}" + "rebar3-version": _versions.rebar3 } - steps: [ - { - uses: "actions/checkout@v2" - }, - { - name: "Update apt-get database" - run: "sudo apt-get update" - }, - { - uses: "erlef/setup-beam@v1" - with: { - "otp-version": "${{matrix.otp_vsn}}" - "rebar3-version": _versions.rebar3 - } - }, - { - name: "Install libsodium" - run: "sudo apt-get install -y libsodium-dev" - }, - { - name: "Compile source code" - run: "make compile" - }, - { - name: "Run the tests" - run: "make tests" - }] - }} + }, + { + name: "Update apt-get database" + run: "sudo apt-get update" + }, + { + name: "Install libsodium" + run: "sudo apt-get install -y libsodium-dev" + }, + { + name: "Compile source code" + run: "make compile" + }, + { + name: "Run the tests" + run: "make tests" + }] diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 365149f..0f20072 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,12 +20,12 @@ jobs: - ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Update apt-get database - run: sudo apt-get update - uses: erlef/setup-beam@v1 with: otp-version: ${{matrix.otp_vsn}} rebar3-version: 3.16.1 + - name: Update apt-get database + run: sudo apt-get update - name: Install libsodium run: sudo apt-get install -y libsodium-dev - name: Compile source code From 87f9270a6c73f5c6883c509ae45c05f882e30511 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 19 Jun 2021 12:33:43 +0200 Subject: [PATCH 155/162] Move actions to their own file. --- .github/workflows/Makefile | 2 +- .github/workflows/actions.cue | 37 +++++++++++++++++++++++++++++++++++ .github/workflows/ci.cue | 2 ++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/actions.cue diff --git a/.github/workflows/Makefile b/.github/workflows/Makefile index 663cd71..b60a0c4 100644 --- a/.github/workflows/Makefile +++ b/.github/workflows/Makefile @@ -1,3 +1,3 @@ all: - cue export --out yaml ci.cue > ci.yaml + cue export --out yaml > ci.yaml diff --git a/.github/workflows/actions.cue b/.github/workflows/actions.cue new file mode 100644 index 0000000..59482e6 --- /dev/null +++ b/.github/workflows/actions.cue @@ -0,0 +1,37 @@ +package actions + +#Name: string +#Branches: branches: [...string] +#Tags: tags: [...string] + +#On: { + push?: #Branches + pull_request?: #Branches + page_build?: #Branches +} + +#Action: "actions/checkout@v2" | "erlef/setup-beam@v1" +#Uses: { + uses: #Action + with?: { + ... + } +} +#Run: { + name: string + run: string +} +#Steps: #Uses | #Run + +#OS_Version: *"ubuntu-latest" | "macos-latest" | "windows_latest" + +#Jobs: ci: { + name: string + "runs-on": string + strategy: + matrix: { + otp_vsn: [...string] + os: [...#OS_Version] + } + steps: [...#Steps] +} \ No newline at end of file diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue index 2be84a7..1a6bf75 100644 --- a/.github/workflows/ci.cue +++ b/.github/workflows/ci.cue @@ -1,3 +1,5 @@ +package actions + // Versions for simplicity _versions: { latest: ["24.0"] From ec64b0de735c2bce70a4119b8d39554d51dc025c Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Sat, 19 Jun 2021 12:40:53 +0200 Subject: [PATCH 156/162] Split up configuration --- .github/workflows/ci.cue | 95 ------------------------------------- .github/workflows/setup.cue | 21 ++++++++ .github/workflows/steps.cue | 40 ++++++++++++++++ 3 files changed, 61 insertions(+), 95 deletions(-) delete mode 100644 .github/workflows/ci.cue create mode 100644 .github/workflows/setup.cue create mode 100644 .github/workflows/steps.cue diff --git a/.github/workflows/ci.cue b/.github/workflows/ci.cue deleted file mode 100644 index 1a6bf75..0000000 --- a/.github/workflows/ci.cue +++ /dev/null @@ -1,95 +0,0 @@ -package actions - -// Versions for simplicity -_versions: { - latest: ["24.0"] - // The versions here have an underlying Debian/Ubuntu which support enough of - // libsodium to handle what enacl provides. Older versions will fail to compile - all: ["22.3", "23.3", "24.0"] - rebar3: "3.16.1" -} - -_branch: "master" - -#Name: string -#Branches: branches: [...string] -#Tags: tags: [...string] - -#On: { - push?: #Branches - pull_request?: #Branches - page_build?: #Branches -} - -#Action: "actions/checkout@v2" | "erlef/setup-beam@v1" -#Uses: { - uses: #Action - with?: { - ... - } -} -#Run: { - name: string - run: string -} -#Steps: #Uses | #Run - -#OS_Version: *"ubuntu-latest" | "macos-latest" | "windows_latest" - -#Jobs: ci: { - name: string - "runs-on": string - strategy: - matrix: { - otp_vsn: [...string] - os: [...#OS_Version] - } - steps: [...#Steps] -} - -name: #Name & "build" -on: #On & { - push: branches: [ - _branch, - ] - pull_request: branches: [ - _branch, - ] -} -jobs: #Jobs -jobs: ci: { - name: "Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}}" - "runs-on": "${{matrix.os}}" - strategy: matrix: { - otp_vsn: _versions.all - os: ["ubuntu-latest"] - } -} -jobs: ci: steps: -[ - { - uses: "actions/checkout@v2" - }, - { - uses: "erlef/setup-beam@v1" - with: { - "otp-version": "${{matrix.otp_vsn}}" - "rebar3-version": _versions.rebar3 - } - }, - { - name: "Update apt-get database" - run: "sudo apt-get update" - }, - { - name: "Install libsodium" - run: "sudo apt-get install -y libsodium-dev" - }, - { - name: "Compile source code" - run: "make compile" - }, - { - name: "Run the tests" - run: "make tests" - }] diff --git a/.github/workflows/setup.cue b/.github/workflows/setup.cue new file mode 100644 index 0000000..7fdea62 --- /dev/null +++ b/.github/workflows/setup.cue @@ -0,0 +1,21 @@ +package actions + +name: #Name & "build" +on: #On & { + push: branches: [ + _branch, + ] + pull_request: branches: [ + _branch, + ] +} + +jobs: #Jobs +jobs: ci: { + name: "Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}}" + "runs-on": "${{matrix.os}}" + strategy: matrix: { + otp_vsn: _versions.otp + os: ["ubuntu-latest"] + } +} \ No newline at end of file diff --git a/.github/workflows/steps.cue b/.github/workflows/steps.cue new file mode 100644 index 0000000..840a6e5 --- /dev/null +++ b/.github/workflows/steps.cue @@ -0,0 +1,40 @@ +package actions + +// Versions for simplicity +_versions: { + // The versions here have an underlying Debian/Ubuntu which support enough of + // libsodium to handle what enacl provides. Older versions will fail to compile + otp: ["22.3", "23.3", "24.0"] + rebar3: "3.16.1" +} + +_branch: "master" + +jobs: ci: steps: +[ + { + uses: "actions/checkout@v2" + }, + { + uses: "erlef/setup-beam@v1" + with: { + "otp-version": "${{matrix.otp_vsn}}" + "rebar3-version": _versions.rebar3 + } + }, + { + name: "Update apt-get database" + run: "sudo apt-get update" + }, + { + name: "Install libsodium" + run: "sudo apt-get install -y libsodium-dev" + }, + { + name: "Compile source code" + run: "make compile" + }, + { + name: "Run the tests" + run: "make tests" + }] From 47ff11e956935acc4bc7a5e630110c0f225964b9 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 22 Jun 2021 14:03:50 +0200 Subject: [PATCH 157/162] Quick run over documentation --- README.md | 61 +++++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 6e5522d..2b1457e 100644 --- a/README.md +++ b/README.md @@ -6,41 +6,37 @@ Frank Denis took the source and made it far more portable in the libsodium library. The enacl project is somewhat misnamed, as it uses libsodium as the underlying driver. -## INSTALL/Requirements: +## INSTALL/Requirements -* Erlang/OTP above 17.3. This library *needs* the dirty scheduler - implementation from 17.3 and onwards. The library relies on dirty - scheduler support in order to handle long-running cryptography jobs, - by moving them off the main Erlang scheduler and letting the dirty - schedulers handle the work. This keeps the Erlang VM responsive while - doing large amounts of cryptographic processing. -* Is tested with Erlang 22.3. Erlang version 21 *may* work, but that isn't - the current testing target. +* New-ish Erlang installation. Tested back to version 22.3, but version 21 *may* + work as well. * *Requires* the libsodium library, and has been tested with version 1.0.18. Lower versions might work, or they might fail to compile, - due to missing functionality. - *Note:* If installing on systems which cuts packages into - subpackages, make sure you also get the "-dev" package containing - the header files necessary in order to compile software linking to - libsodium. + due to missing functionality. In particular, this means your libsodium installation + must be fairly recent as well. + +*Note:* If installing on systems which cuts packages into +subpackages, make sure you also get the "-dev" package containing +the header files necessary in order to compile software linking to +libsodium. To build the software execute: - make + make or - rebar compile + rebar compile To build and run licensed eqc test execute: - make eqc_run + make eqc_run To build and run eqc-mini version of test execute: - make eqc_mini_run + make eqc_mini_run -## Features: +## Features * Complete NaCl library, implementing all default functionality. * Implements a large set of additional functionality from libsodium. @@ -62,21 +58,17 @@ In addition, I would like to thank Steve Vinoski, Rickard Green, and Sverker Eriksson for providing the Dirty Scheduler API in the first place. -# USING: +## Usage -In general, consult the libsodium documentation at - - https://download.libsodium.org/doc/ +In general, consult the libsodium documentation at [Libsodium documentation](https://download.libsodium.org/doc/) The original NaCl documentation is nowadays largely superceded by the -libsodium documentation, but it is still worth a visit - - https://nacl.cr.yp.to +libsodium documentation, but it is still worth a visit [NaCl website](https://nacl.cr.yp.to) but also note that our interface has full Edoc documentation, generated by executing - rebar3 doc + rebar3 doc ## Hints @@ -134,11 +126,11 @@ However, their correct use is still needed in order to be secure: a foreign system as an oracle in order to learn the structure of a string, breaking the cryptograhic system in the process. -# Versions +## Versions See CHANGELOG.md -# Overview +## Overview The NaCl cryptographic library provides a number of different cryptographic primitives. In the following, we split up the different @@ -200,7 +192,7 @@ This implements cryptography where there is a shared secret key between parties. * *String comparison:* Implements guaranteed constant-time string comparisons to protect against timing attacks. -# Rationale +## Rationale Doing crypto right in Erlang is not that easy. For one, the crypto system has to be rather fast, which rules out Erlang as the main @@ -252,7 +244,7 @@ perhaps being able to switch faster. There are plans to rerun these tests on OSX and Illumos as well, in order to investigate the numbers on more platforms. -# Testing +## Testing Every primitive has been stress-tested through the use of Erlang QuickCheck with both *positive* and *negative* testing. This has been @@ -279,11 +271,8 @@ sure we have no memory leaks as they will show themselves under the extensive QuickCheck test cases we run. It has been verified there are no leaks in the code. -# Notes +## Notes [0] Other people have worked on bits and pieces of NaCl. These are -just the 3 main authors. Please see the page - - http://nacl.cr.yp.to - +just the 3 main authors. Please see the page [NaCl](http://nacl.cr.yp.to) for the full list of authors. From 20b230d693ba4c0053ab044be5442fdb6e6b61f0 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 6 Jul 2021 13:45:08 +0200 Subject: [PATCH 158/162] Export types from enacl A couple of types are useful from outside the enacl module. Export these. --- src/enacl.erl | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/enacl.erl b/src/enacl.erl index 5120f7c..378bb7b 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -204,6 +204,22 @@ %% Internal verification of the system -export([verify/0]). +%% Type specifications +-type generichash_bytes() :: 10..64. +-type sign_state() :: reference(). + +-type pwhash_alg() :: default | argon2i13 | argon2id13 | pos_integer(). +-type pwhash_limit() :: interactive | moderate | sensitive | pos_integer(). +-type secretstream_xchacha20poly1305_tag() :: message | rekey | final | push | pos_integer(). + +-export_type([ + generichash_bytes/0, + pwhash_alg/0, + pwhash_limit/0, + secretstream_xchacha20poly1305_tag/0, + sign_state/0 +]). + %% Definitions of system budgets @@ -371,7 +387,6 @@ unsafe_memzero(_) -> %% This function generates a hash of the message using a key. The hash size is %% either 16, 32 or 64 bytes %% @end --type generichash_bytes() :: 10..64. -spec generichash(generichash_bytes(), iodata(), binary()) -> binary(). generichash(HashSize, Message, Key) -> enacl_nif:crypto_generichash(HashSize, Message, Key). @@ -402,15 +417,12 @@ generichash_update(State, Message) -> generichash_final(State) -> enacl_nif:crypto_generichash_final(State). --type pwhash_limit() :: interactive | moderate | sensitive | pos_integer(). - %% @doc pwhash_SALTBYTES/0 returns the number of bytes required for salt. %% @end -spec pwhash_SALTBYTES() -> pos_integer(). pwhash_SALTBYTES() -> enacl_nif:crypto_pwhash_SALTBYTES(). --type pwhash_alg() :: default | argon2i13 | argon2id13 | pos_integer(). %% @doc pwhash/2 hash a password %% %% This function generates a fixed size salted hash of a user defined password. @@ -709,7 +721,6 @@ sign_detached(M, SK) -> sign_verify_detached(SIG, M, PK) -> enacl_nif:crypto_sign_verify_detached(SIG, M, PK). --type sign_state() :: reference(). %% @doc sign_init/0 initialize a multi-part signature state. %% @@ -1412,7 +1423,6 @@ secretstream_xchacha20poly1305_keygen() -> secretstream_xchacha20poly1305_init_push(Key) -> enacl_nif:crypto_secretstream_xchacha20poly1305_init_push(Key). --type secretstream_xchacha20poly1305_tag() :: message | rekey | final | push | pos_integer(). %% @doc secretstream_xchacha20poly1305_push/4 returns encrypted chunk binary. %% Updates a secretstream context referenced by `Ref' with `Message' data, %% given `Tag' and additional data `AD'. From c0afa5890d0708024a3da4ff61578cd0641c7d70 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 8 Jul 2021 11:42:18 +0200 Subject: [PATCH 159/162] v1.2.1 --- src/enacl.app.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/enacl.app.src b/src/enacl.app.src index 2290594..8c381cd 100644 --- a/src/enacl.app.src +++ b/src/enacl.app.src @@ -1,6 +1,6 @@ {application,enacl, [{description,"Erlang libsodium (NaCl) bindings"}, - {vsn,"1.2.0"}, + {vsn,"1.2.1"}, {registered,[]}, {applications,[kernel,stdlib]}, {env,[]}, From b229e9054beeee024030287d42e6fcba0c7c2009 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 8 Jul 2021 11:45:38 +0200 Subject: [PATCH 160/162] Document 1.2.1 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d53b6aa..2259d9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.2.1] + +### Fixed [1.2.1] + +- Export types from the `enacl` module so it can be referenced in other parts of your system (serokell.io) + ## [1.2.0] ### Fixed [1.2.0] From ddc5d1269d3a0ef17090902cc4157ac8c6ecdc1a Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 8 Jul 2021 11:50:01 +0200 Subject: [PATCH 161/162] Let us get macos into the build matrix --- .github/workflows/ci.yaml | 1 + .github/workflows/setup.cue | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0f20072..4a5c530 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,6 +18,7 @@ jobs: - "24.0" os: - ubuntu-latest + - macos-latest steps: - uses: actions/checkout@v2 - uses: erlef/setup-beam@v1 diff --git a/.github/workflows/setup.cue b/.github/workflows/setup.cue index 7fdea62..40c2879 100644 --- a/.github/workflows/setup.cue +++ b/.github/workflows/setup.cue @@ -16,6 +16,6 @@ jobs: ci: { "runs-on": "${{matrix.os}}" strategy: matrix: { otp_vsn: _versions.otp - os: ["ubuntu-latest"] + os: ["ubuntu-latest", "macos-latest"] } } \ No newline at end of file From 46e2754a50f4d9192ebf008bf80ea8242e7f7986 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Thu, 8 Jul 2021 11:51:56 +0200 Subject: [PATCH 162/162] Disable macos again. setup-beam only has ubuntu support... --- .github/workflows/ci.yaml | 1 - .github/workflows/setup.cue | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4a5c530..0f20072 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,7 +18,6 @@ jobs: - "24.0" os: - ubuntu-latest - - macos-latest steps: - uses: actions/checkout@v2 - uses: erlef/setup-beam@v1 diff --git a/.github/workflows/setup.cue b/.github/workflows/setup.cue index 40c2879..7fdea62 100644 --- a/.github/workflows/setup.cue +++ b/.github/workflows/setup.cue @@ -16,6 +16,6 @@ jobs: ci: { "runs-on": "${{matrix.os}}" strategy: matrix: { otp_vsn: _versions.otp - os: ["ubuntu-latest", "macos-latest"] + os: ["ubuntu-latest"] } } \ No newline at end of file