From f395f65389ced95abf977929df1616469de12f41 Mon Sep 17 00:00:00 2001 From: Venkatakumar Srinivasan Date: Wed, 12 Oct 2016 11:45:29 -0500 Subject: [PATCH 01/16] Removed experimental feature flag ERL_NIF_DIRTY_JOB_CPU_BOUND --- c_src/enacl_nif.c | 52 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 8b9601a..e78f058 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1207,61 +1207,61 @@ static ErlNifFunc nif_funcs[] = { {"crypto_box_SECRETKEYBYTES", 0, enif_crypto_box_SECRETKEYBYTES}, {"crypto_box_BEFORENMBYTES", 0, enif_crypto_box_BEFORENMBYTES}, - {"crypto_box_keypair", 0, enif_crypto_box_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_box_keypair", 0, enif_crypto_box_keypair}, - {"crypto_box", 4, enif_crypto_box, ERL_NIF_DIRTY_JOB_CPU_BOUND}, - {"crypto_box_open", 4, enif_crypto_box_open, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_box", 4, enif_crypto_box}, + {"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}, - {"crypto_box_afternm", 3, enif_crypto_box_afternm, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_box_afternm", 3, enif_crypto_box_afternm}, {"crypto_box_open_afternm_b", 3, enif_crypto_box_open_afternm}, - {"crypto_box_open_afternm", 3, enif_crypto_box_open_afternm, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"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}, - {"crypto_sign_keypair", 0, enif_crypto_sign_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_sign_keypair", 0, enif_crypto_sign_keypair}, - {"crypto_sign", 2, enif_crypto_sign, ERL_NIF_DIRTY_JOB_CPU_BOUND}, - {"crypto_sign_open", 2, enif_crypto_sign_open, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_sign", 2, enif_crypto_sign}, + {"crypto_sign_open", 2, enif_crypto_sign_open}, - {"crypto_sign_detached", 2, enif_crypto_sign_detached, ERL_NIF_DIRTY_JOB_CPU_BOUND}, - {"crypto_sign_verify_detached", 3, enif_crypto_sign_verify_detached, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_sign_detached", 2, enif_crypto_sign_detached}, + {"crypto_sign_verify_detached", 3, enif_crypto_sign_verify_detached}, {"crypto_box_SEALBYTES", 0, enif_crypto_box_SEALBYTES}, - {"crypto_box_seal", 2, enif_crypto_box_seal, ERL_NIF_DIRTY_JOB_CPU_BOUND}, - {"crypto_box_seal_open", 3, enif_crypto_box_seal_open, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_box_seal", 2, enif_crypto_box_seal}, + {"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}, - {"crypto_secretbox", 3, enif_crypto_secretbox, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_secretbox", 3, enif_crypto_secretbox}, {"crypto_secretbox_open_b", 3, enif_crypto_secretbox_open}, - {"crypto_secretbox_open", 3, enif_crypto_secretbox_open, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"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}, - {"crypto_stream_chacha20", 3, enif_crypto_stream_chacha20, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_stream_chacha20", 3, enif_crypto_stream_chacha20}, {"crypto_stream_chacha20_xor_b", 3, enif_crypto_stream_chacha20_xor}, - {"crypto_stream_chacha20_xor", 3, enif_crypto_stream_chacha20_xor, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"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}, - {"crypto_stream", 3, enif_crypto_stream, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_stream", 3, enif_crypto_stream}, {"crypto_stream_xor_b", 3, enif_crypto_stream_xor}, - {"crypto_stream_xor", 3, enif_crypto_stream_xor, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"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}, - {"crypto_auth", 2, enif_crypto_auth, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_auth", 2, enif_crypto_auth}, {"crypto_auth_verify_b", 3, enif_crypto_auth_verify}, - {"crypto_auth_verify", 3, enif_crypto_auth_verify, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_auth_verify", 3, enif_crypto_auth_verify}, {"crypto_shorthash_BYTES", 0, enif_crypto_auth_BYTES}, {"crypto_shorthash_KEYBYTES", 0, enif_crypto_shorthash_KEYBYTES}, @@ -1270,25 +1270,25 @@ static ErlNifFunc nif_funcs[] = { {"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", 2, enif_crypto_onetimeauth, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_onetimeauth", 2, enif_crypto_onetimeauth}, {"crypto_onetimeauth_verify_b", 3, enif_crypto_onetimeauth_verify}, - {"crypto_onetimeauth_verify", 3, enif_crypto_onetimeauth_verify, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_onetimeauth_verify", 3, enif_crypto_onetimeauth_verify}, {"crypto_hash_b", 1, enif_crypto_hash}, - {"crypto_hash", 1, enif_crypto_hash, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"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_curve25519_scalarmult", 2, enif_crypto_curve25519_scalarmult, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_curve25519_scalarmult", 2, enif_crypto_curve25519_scalarmult}, - {"crypto_sign_ed25519_keypair", 0, enif_crypto_sign_ed25519_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"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}, - {"randombytes", 1, enif_randombytes, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"randombytes", 1, enif_randombytes}, {"crypto_kx_keypair", 0, enif_crypto_kx_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND}, {"crypto_kx_client_session_keys", 3, enif_crypto_kx_client_session_keys, ERL_NIF_DIRTY_JOB_CPU_BOUND}, From 43cae7c7eabf7ad9e434404dec4751344e0b61bc Mon Sep 17 00:00:00 2001 From: Venkatakumar Srinivasan Date: Fri, 17 Feb 2017 19:33:04 -0600 Subject: [PATCH 02/16] Implemented nif for crypto_pwhash() --- Makefile | 4 ++++ c_src/enacl_nif.c | 54 +++++++++++++++++++++++++++++++++++++++++++++-- src/enacl.erl | 35 ++++++++++++++++++++++++++++++ src/enacl_nif.erl | 11 ++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index aa3e984..d0c840b 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,10 @@ REBAR=rebar3 compile: $(REBAR) compile | sed -e 's|_build/default/lib/enacl/||g' +.PHONE: console +console: compile + $(REBAR) shell + .PHONY: clean clean: $(REBAR) clean diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index e78f058..191f2d5 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -4,6 +4,9 @@ #include +#define ATOM_OK "ok" +#define ATOM_ERROR "error" + /* Errors */ static ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) { @@ -13,8 +16,7 @@ ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) { /* Initialization */ static int enif_crypto_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info) { - sodium_init(); - return 0; + return sodium_init(); } /* Low-level functions (Hashing, String Equality, ...) */ @@ -1198,6 +1200,50 @@ ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, ERL_NIF_TERM const return enif_make_binary(env, &out); } +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)) ) { + 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, 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 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[]) { + return nacl_error_tuple(env, "not_implemented"); +} + +static +ERL_NIF_TERM enif_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + return nacl_error_tuple(env, "not_implemented"); +} + /* Tie the knot to the Erlang world */ static ErlNifFunc nif_funcs[] = { {"crypto_box_NONCEBYTES", 0, enif_crypto_box_NONCEBYTES}, @@ -1280,6 +1326,10 @@ 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_str", 1, enif_crypto_pwhash_str}, + {"crypto_pwhash_str_verify", 2, enif_crypto_pwhash_str_verify}, + {"crypto_curve25519_scalarmult", 2, enif_crypto_curve25519_scalarmult}, {"crypto_sign_ed25519_keypair", 0, enif_crypto_sign_ed25519_keypair}, diff --git a/src/enacl.erl b/src/enacl.erl index 04a3572..eb45248 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -106,6 +106,13 @@ kx_session_key_size/0 ]). +%% Password Hashing - Argon2 Algorithm +-export([ + pwhash/2, + pwhash_str/1, + pwhash_str_verify/2 +]). + %% Libsodium specific functions (which are also part of the "undocumented" interface to NaCl -export([ randombytes/1 @@ -249,6 +256,32 @@ unsafe_memzero(X) when is_binary(X) -> unsafe_memzero(_) -> error(badarg). + +%% @doc pwhash/2 hash a password +%% +%% This function generates a fixed size salted hash of a user defined password. +%% @end +-spec pwhash(iodata(), binary()) -> {ok, binary()} | {error, term()}. +pwhash(Password, Salt) -> + enacl_nif:crypto_pwhash(Password, Salt). + +%% @doc pwhash_str_verify/2 generates a ASCII encoded hash of a password +%% +%% This function generates a fixed size, salted, ASCII encoded hash of a user defined password. +%% @end +-spec pwhash_str(iodata()) -> {ok, iodata()} | {error, term()}. +pwhash_str(Password) -> + enacl_nif:crypto_pwhash_str(Password). + +%% @doc pwhash_str_verify/2 compares a password with a hash +%% +%% This function verifies that the hash is generated from the password. The +%% function returns true if the verifcate succeeds, false otherwise +%% @end +-spec pwhash_str_verify(binary(), iodata()) -> boolean(). +pwhash_str_verify(HashPassword, Password) -> + enacl_nif:crypto_pwhash_str_verify(HashPassword, Password). + %% Public Key Crypto %% --------------------- %% @doc box_keypair/0 creates a new Public/Secret keypair. @@ -913,6 +946,8 @@ kx_public_key_size() -> kx_secret_key_size() -> enacl_nif:crypto_kx_SECRETKEYBYTES(). + + %% 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 71e7cfa..a2e1908 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -122,6 +122,13 @@ sodium_memzero/1 ]). +%% Password Hashing - Argon2 Algorithm +-export([ + crypto_pwhash/2, + crypto_pwhash_str/1, + crypto_pwhash_str_verify/2 +]). + %% Access to the RNG -export([ randombytes/1 @@ -146,6 +153,10 @@ init() -> SoName = filename:join(Dir, atom_to_list(?MODULE)), erlang:load_nif(SoName, 0). +crypto_pwhash(Password, Salt) -> erlang:nif_error(nif_not_loaded). +crypto_pwhash_str(Password) -> 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). crypto_box_ZEROBYTES() -> erlang:nif_error(nif_not_loaded). crypto_box_BOXZEROBYTES() -> erlang:nif_error(nif_not_loaded). From ee0d800a9a5607a2298c589799e776dbc7772ff3 Mon Sep 17 00:00:00 2001 From: Venkatakumar Srinivasan Date: Fri, 17 Feb 2017 20:15:20 -0600 Subject: [PATCH 03/16] Implemented nif for crypto_pwhash_str(), crypto_pwhash_str_verify() --- c_src/enacl_nif.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 191f2d5..709267c 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -6,6 +6,8 @@ #define ATOM_OK "ok" #define ATOM_ERROR "error" +#define ATOM_TRUE "true" +#define ATOM_FALSE "false" /* Errors */ static @@ -1236,12 +1238,50 @@ 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[]) { - return nacl_error_tuple(env, "not_implemented"); + ErlNifBinary h, p; + + // Validate the arguments + 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) ) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if( crypto_pwhash_str(h.data, 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 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[]) { - return nacl_error_tuple(env, "not_implemented"); + 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(h.data, p.data, p.size) != 0) { + /* wrong password */ + retVal = enif_make_atom(env, ATOM_FALSE); + } + + return retVal; } /* Tie the knot to the Erlang world */ From c938d3c6e8889e819b52be7597bc1fcc910ccbac Mon Sep 17 00:00:00 2001 From: Venkatakumar Srinivasan Date: Sun, 19 Feb 2017 10:16:13 -0600 Subject: [PATCH 04/16] Fix to pwhash_str_verify() to accept only binary arguments --- c_src/enacl_nif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 709267c..3c72726 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1270,8 +1270,8 @@ ERL_NIF_TERM enif_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, ERL_NIF_TER // Validate the arguments if( (argc != 2) || - (!enif_inspect_iolist_as_binary(env, argv[0], &h)) || - (!enif_inspect_iolist_as_binary(env, argv[1], &p)) ) { + (!enif_inspect_binary(env, argv[0], &h)) || + (!enif_inspect_binary(env, argv[1], &p)) ) { return enif_make_badarg(env); } From 36eedc67519dc90d204cfab3d82726065a12fc10 Mon Sep 17 00:00:00 2001 From: Venkatakumar Srinivasan Date: Fri, 5 May 2017 14:25:17 -0500 Subject: [PATCH 05/16] Pulled in latest version of enacl. Added nif's for password hashing functions --- c_src/enacl_nif.c | 74 ++++++++++++++++++++++++++--------------------- src/enacl_nif.erl | 6 ++-- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 3c72726..71ebda2 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -9,6 +9,13 @@ #define ATOM_TRUE "true" #define ATOM_FALSE "false" +#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} +#else +#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} /* Errors */ static ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) { @@ -1223,7 +1230,7 @@ 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, p.data, p.size, s.data, + 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); @@ -1251,7 +1258,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(h.data, p.data, p.size, + 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); @@ -1276,7 +1283,7 @@ ERL_NIF_TERM enif_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, ERL_NIF_TER } ERL_NIF_TERM retVal = enif_make_atom(env, ATOM_TRUE); - if( crypto_pwhash_str_verify(h.data, 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); } @@ -1293,75 +1300,76 @@ static ErlNifFunc nif_funcs[] = { {"crypto_box_SECRETKEYBYTES", 0, enif_crypto_box_SECRETKEYBYTES}, {"crypto_box_BEFORENMBYTES", 0, enif_crypto_box_BEFORENMBYTES}, - {"crypto_box_keypair", 0, enif_crypto_box_keypair}, + erl_nif_dirty_job_cpu_bound_macro("crypto_box_keypair", 0, enif_crypto_box_keypair), - {"crypto_box", 4, enif_crypto_box}, - {"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}, - {"crypto_box_afternm", 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}, - {"crypto_box_open_afternm", 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}, - {"crypto_sign_keypair", 0, enif_crypto_sign_keypair}, + erl_nif_dirty_job_cpu_bound_macro("crypto_sign_keypair", 0, enif_crypto_sign_keypair), - {"crypto_sign", 2, enif_crypto_sign}, - {"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), - {"crypto_sign_detached", 2, enif_crypto_sign_detached}, - {"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_seal", 2, enif_crypto_box_seal}, - {"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}, - {"crypto_secretbox", 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}, - {"crypto_secretbox_open", 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}, - {"crypto_stream_chacha20", 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}, - {"crypto_stream_chacha20_xor", 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}, - {"crypto_stream", 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_xor", 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}, - {"crypto_auth", 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_verify", 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_auth_BYTES}, + {"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}, - {"crypto_onetimeauth", 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}, - {"crypto_onetimeauth_verify", 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}, - {"crypto_hash", 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}, @@ -1370,19 +1378,19 @@ static ErlNifFunc nif_funcs[] = { {"crypto_pwhash_str", 1, enif_crypto_pwhash_str}, {"crypto_pwhash_str_verify", 2, enif_crypto_pwhash_str_verify}, - {"crypto_curve25519_scalarmult", 2, enif_crypto_curve25519_scalarmult}, + erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult", 2, enif_crypto_curve25519_scalarmult), - {"crypto_sign_ed25519_keypair", 0, enif_crypto_sign_ed25519_keypair}, + 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}, - {"randombytes", 1, enif_randombytes}, + erl_nif_dirty_job_cpu_bound_macro("randombytes", 1, enif_randombytes), - {"crypto_kx_keypair", 0, enif_crypto_kx_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND}, - {"crypto_kx_client_session_keys", 3, enif_crypto_kx_client_session_keys, ERL_NIF_DIRTY_JOB_CPU_BOUND}, - {"crypto_kx_server_session_keys", 3, enif_crypto_kx_server_session_keys, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + 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}, diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index a2e1908..be82df6 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -153,9 +153,9 @@ init() -> SoName = filename:join(Dir, atom_to_list(?MODULE)), erlang:load_nif(SoName, 0). -crypto_pwhash(Password, Salt) -> erlang:nif_error(nif_not_loaded). -crypto_pwhash_str(Password) -> erlang:nif_error(nif_not_loaded). -crypto_pwhash_str_verify(HashedPassword, Password) -> 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_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded). crypto_box_NONCEBYTES() -> erlang:nif_error(nif_not_loaded). crypto_box_ZEROBYTES() -> erlang:nif_error(nif_not_loaded). From ba640b06595d8b7d02fc35c828cc7ed87dd82d28 Mon Sep 17 00:00:00 2001 From: Venkatakumar Srinivasan Date: Tue, 9 May 2017 12:31:20 -0500 Subject: [PATCH 06/16] Added generic hash NIF --- c_src/enacl_nif.c | 253 ++++++++++++++++++++++++++++++++++++++++++++-- src/enacl.erl | 52 +++++++++- src/enacl_nif.erl | 30 ++++++ 3 files changed, 327 insertions(+), 8 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 71ebda2..e2d9149 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -9,6 +9,8 @@ #define ATOM_TRUE "true" #define ATOM_FALSE "false" +#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} #else @@ -17,15 +19,24 @@ //{"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)); + 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) { - return sodium_init(); + // 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; + } + + return sodium_init(); } /* Low-level functions (Hashing, String Equality, ...) */ @@ -293,7 +304,9 @@ ERL_NIF_TERM enif_crypto_box(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[] return nacl_error_tuple(env, "alloc_failed"); } - crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data, pk.data, sk.data); + 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, @@ -358,7 +371,10 @@ ERL_NIF_TERM enif_crypto_box_beforenm(ErlNifEnv *env, int argc, ERL_NIF_TERM con return nacl_error_tuple(env, "alloc_failed"); } - crypto_box_beforenm(k.data, pk.data, sk.data); + 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); } @@ -1101,7 +1117,10 @@ ERL_NIF_TERM enif_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, ERL_NI return nacl_error_tuple(env, "alloc_failed"); } - crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data, server_sk.data, client_pk.data); + 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)); } @@ -1129,7 +1148,10 @@ ERL_NIF_TERM enif_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, ERL_NI return nacl_error_tuple(env, "alloc_failed"); } - crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data, client_sk.data, server_pk.data); + 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)); } @@ -1291,6 +1313,211 @@ ERL_NIF_TERM enif_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, ERL_NIF_TER return retVal; } +/* + * 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; + + size_t hashSize; + + // Validate the arguments + if( (argc != 3) || + (!enif_get_uint64(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 +ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + ErlNifBinary key; + + size_t hashSize; + + // Validate the arguments + if( (argc != 2) || + (!enif_get_uint64(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 + crypto_generichash_state *state = (crypto_generichash_state *)enif_alloc_resource(generichash_state_type, crypto_generichash_statebytes()); + if( !state ) { + return nacl_error_tuple(env, "alloc_failed"); + } + + // Call the library function + if( 0 != crypto_generichash_init(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); + + // 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; + + size_t hashSize; + + crypto_generichash_state *state; + + // Validate the arguments + if( (argc != 3) || + (!enif_get_uint64(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(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; + + size_t hashSize; + + crypto_generichash_state *state; + + // Validate the arguments + if( (argc != 2) || + (!enif_get_uint64(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(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}, @@ -1395,7 +1622,19 @@ static ErlNifFunc nif_funcs[] = { {"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_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} + }; ERL_NIF_INIT(enacl_nif, nif_funcs, enif_crypto_load, NULL, NULL, NULL); diff --git a/src/enacl.erl b/src/enacl.erl index eb45248..b19ae55 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -113,6 +113,16 @@ pwhash_str_verify/2 ]). +%% Generic hash functions +-export([ + generichash/3, + generichash/2, + + generichash_init/2, + generichash_update/2, + generichash_final/1 +]). + %% Libsodium specific functions (which are also part of the "undocumented" interface to NaCl -export([ randombytes/1 @@ -160,6 +170,13 @@ -define(CRYPTO_KX_SECRETKEYBYTES, 32). -define(CRYPTO_KX_SESSIONKEYBYTES, 32). +-define(CRYPTO_GENERICHASH_BYTES_MIN, 16). +-define(CRYPTO_GENERICHASH_BYTES_MAX, 64). +-define(CRYPTO_GENERICHASH_BYTES, 32). +-define(CRYPTO_GENERICHASH_KEYBYTES_MIN, 16). +-define(CRYPTO_GENERICHASH_KEYBYTES_MAX, 64). +-define(CRYPTO_GENERICHASH_KEYBYTES, 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), @@ -180,7 +197,13 @@ verify() -> {crypto_secretbox_BOXZEROBYTES, ?CRYPTO_SECRETBOX_BOXZEROBYTES}, {crypto_kx_SESSIONKEYBYTES, ?CRYPTO_KX_SESSIONKEYBYTES}, {crypto_kx_PUBLICKEYBYTES, ?CRYPTO_KX_PUBLICKEYBYTES}, - {crypto_kx_SECRETKEYBYTES, ?CRYPTO_KX_SECRETKEYBYTES} + {crypto_kx_SECRETKEYBYTES, ?CRYPTO_KX_SECRETKEYBYTES}, + {crypto_generichash_BYTES, ?CRYPTO_GENERICHASH_BYTES}, + {crypto_generichash_BYTES_MIN, ?CRYPTO_GENERICHASH_BYTES_MIN}, + {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} ], run_verifiers(Verifiers). @@ -257,6 +280,33 @@ unsafe_memzero(_) -> error(badarg). +%% @doc generichash/3 creates a hash of the message using a key. +%% +%% This function generates a hash of the message using a key. The hash size is +%% either 16, 32 or 64 bytes +%% @end +-spec generichash(iodata(), binary()) -> {ok, binary()} | {error, term()}. +generichash(HashSize, Message, Key) -> + enacl_nif:crypto_generichash(HashSize, Message, Key). + +%% @doc generichash/2 creates a hash of the message. +%% +%% This function generates a hash of the message. The hash size is +%% either 16, 32 or 64 bytes +%% @end +generichash(HashSize, Message) -> + enacl_nif:crypto_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_final({hashstate, HashSize, HashState}) -> + enacl_nif:crypto_generichash_final(HashSize, HashState). + + %% @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 be82df6..44196ba 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -129,6 +129,21 @@ crypto_pwhash_str_verify/2 ]). +%% Generic hash +-export([ + crypto_generichash_BYTES/0, + crypto_generichash_BYTES_MIN/0, + crypto_generichash_BYTES_MAX/0, + crypto_generichash_KEYBYTES/0, + crypto_generichash_KEYBYTES_MIN/0, + crypto_generichash_KEYBYTES_MAX/0, + + crypto_generichash/3, + crypto_generichash_init/2, + crypto_generichash_update/3, + crypto_generichash_final/2 +]). + %% Access to the RNG -export([ randombytes/1 @@ -153,6 +168,21 @@ init() -> SoName = filename:join(Dir, atom_to_list(?MODULE)), erlang:load_nif(SoName, 0). +crypto_generichash_BYTES() -> erlang:nif_error(nif_not_loaded). +crypto_generichash_BYTES_MIN() -> erlang:nif_error(nif_not_loaded). +crypto_generichash_BYTES_MAX() -> erlang:nif_error(nif_not_loaded). +crypto_generichash_KEYBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_generichash_KEYBYTES_MIN() -> erlang:nif_error(nif_not_loaded). +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_pwhash(_Password, _Salt) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str(_Password) -> erlang:nif_error(nif_not_loaded). crypto_pwhash_str_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded). From e524c2d5c84ca7fa1b7f67cba867ed02888b1cf1 Mon Sep 17 00:00:00 2001 From: Irina Guberman Date: Sat, 12 Aug 2017 16:46:47 -0500 Subject: [PATCH 07/16] Fix 32-bit arch warnings: replace enif_get_uint64 with enif_get_uint --- c_src/Makefile | 2 +- c_src/enacl_nif.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/c_src/Makefile b/c_src/Makefile index b762894..6fbe66e 100644 --- a/c_src/Makefile +++ b/c_src/Makefile @@ -10,7 +10,7 @@ C_SRC_DIR = $(CURDIR) C_SRC_OUTPUT ?= $(CURDIR)/../priv/$(PROJECT).so # System type and C compiler/flags. - +MACHINE_SYS := $(shell uname -m) UNAME_SYS := $(shell uname -s) ifeq ($(UNAME_SYS), Darwin) CC ?= cc diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index e2d9149..f4d54d9 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1042,7 +1042,7 @@ ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[ size_t req_size; ErlNifBinary result; - if ((argc != 1) || (!enif_get_uint64(env, argv[0], &req_size))) { + if ((argc != 1) || (!enif_get_uint(env, argv[0], &req_size))) { return enif_make_badarg(env); } @@ -1354,7 +1354,7 @@ ERL_NIF_TERM enif_crypto_generichash(ErlNifEnv *env, int argc, ERL_NIF_TERM cons // Validate the arguments if( (argc != 3) || - (!enif_get_uint64(env, argv[0], &hashSize)) || + (!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); @@ -1399,7 +1399,7 @@ ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, ERL_NIF_TERM // Validate the arguments if( (argc != 2) || - (!enif_get_uint64(env, argv[0], &hashSize)) || + (!enif_get_uint(env, argv[0], &hashSize)) || (!enif_inspect_binary(env, argv[1], &key)) ) { return enif_make_badarg(env); } @@ -1453,7 +1453,7 @@ ERL_NIF_TERM enif_crypto_generichash_update(ErlNifEnv *env, int argc, ERL_NIF_TE // Validate the arguments if( (argc != 3) || - (!enif_get_uint64(env, argv[0], &hashSize)) || + (!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); @@ -1490,7 +1490,7 @@ ERL_NIF_TERM enif_crypto_generichash_final(ErlNifEnv *env, int argc, ERL_NIF_TER // Validate the arguments if( (argc != 2) || - (!enif_get_uint64(env, argv[0], &hashSize)) || + (!enif_get_uint(env, argv[0], &hashSize)) || (!enif_get_resource(env, argv[1], generichash_state_type, (void **)&state)) ) { return enif_make_badarg(env); } From bf4d61680c7fc593fc8f83e9ea329f2f5ecfa786 Mon Sep 17 00:00:00 2001 From: Zane Beckwith Date: Mon, 14 Aug 2017 17:01:50 +0000 Subject: [PATCH 08/16] Change size_t variables to unsigned int's. These variables are being initialized via calls to `enif_get_uint`, so it's safer to declare them as unsigned int's rather than size_t's. Their being used in calls to `enif_alloc_binary`, which takes a size_t as its size. However, the resulting ErlNifBinary keeps its size as an unsigned int, so asking for a size that's an unsigned int should be safe. This would be problematic in the case where sizeof(size_t) < sizeof(unsigned), which would mean we're getting fewer bytes allocated than expected. Perhaps an explicit check for, for example, `hashSize > MAX_SIZE` would be good here? --- c_src/enacl_nif.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index f4d54d9..1046af7 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1039,7 +1039,7 @@ ERL_NIF_TERM enif_crypto_onetimeauth_verify(ErlNifEnv *env, int argc, ERL_NIF_TE static ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { - size_t req_size; + unsigned req_size; ErlNifBinary result; if ((argc != 1) || (!enif_get_uint(env, argv[0], &req_size))) { @@ -1350,7 +1350,7 @@ static ERL_NIF_TERM enif_crypto_generichash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary hash, message, key; - size_t hashSize; + unsigned hashSize; // Validate the arguments if( (argc != 3) || @@ -1395,7 +1395,7 @@ static ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary key; - size_t hashSize; + unsigned hashSize; // Validate the arguments if( (argc != 2) || @@ -1447,7 +1447,7 @@ static ERL_NIF_TERM enif_crypto_generichash_update(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary message; - size_t hashSize; + unsigned hashSize; crypto_generichash_state *state; @@ -1484,7 +1484,7 @@ static ERL_NIF_TERM enif_crypto_generichash_final(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary hash; - size_t hashSize; + unsigned hashSize; crypto_generichash_state *state; From 0e7ee5c6f057a4d39cf25ecd1e80ee82a7b6f6ad Mon Sep 17 00:00:00 2001 From: Irina Guberman Date: Tue, 15 Aug 2017 13:40:45 -0500 Subject: [PATCH 09/16] configure for QC testing on http://quickcheck-ci.com --- .eqc_ci | 2 ++ EQC_CI_LICENCE.txt | 34 ++++++++++++++++++++++++++++++++++ Makefile | 3 +++ 3 files changed, 39 insertions(+) create mode 100644 .eqc_ci create mode 100644 EQC_CI_LICENCE.txt diff --git a/.eqc_ci b/.eqc_ci new file mode 100644 index 0000000..e7c4c8a --- /dev/null +++ b/.eqc_ci @@ -0,0 +1,2 @@ +{build, "make eqc_compile"}. +{test_path, "_build/default/lib/enacl/ebin"}. \ No newline at end of file diff --git a/EQC_CI_LICENCE.txt b/EQC_CI_LICENCE.txt new file mode 100644 index 0000000..6d2a058 --- /dev/null +++ b/EQC_CI_LICENCE.txt @@ -0,0 +1,34 @@ +This file is an agreement between Quviq AB ("Quviq"), Sven Hultins +Gata 9, Gothenburg, Sweden, and the committers to the github +repository in which the file appears ("the owner"). By placing this +file in a github repository, the owner agrees to the terms below. + +The purpose of the agreement is to enable Quviq AB to provide a +continuous integration service to the owner, whereby the code in the +repository ("the source code") is tested using Quviq's test tools, and +the test results are made available on the web. The test results +include test output, generated test cases, and a copy of the source +code in the repository annotated with coverage information ("the test +results"). + +The owner agrees that Quviq may run the tests in the source code and +display the test results on the web, without obligation. + +The owner warrants that running the tests in the source code and +displaying the test results on the web violates no laws, licences or other +agreements. In the event of such a violation, the owner accepts full +responsibility. + +The owner warrants that the source code is not malicious, and will not +mount an attack on either Quviq's server or any other server--for +example by taking part in a denial of service attack, or by attempting +to send unsolicited emails. + +The owner warrants that the source code does not attempt to reverse +engineer Quviq's code. + +Quviq reserves the right to exclude repositories that break this +agreement from its continuous integration service. + +Any dispute arising from the use of Quviq's service will be resolved +under Swedish law. diff --git a/Makefile b/Makefile index d0c840b..61eb843 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,9 @@ REBAR=rebar3 compile: $(REBAR) compile | sed -e 's|_build/default/lib/enacl/||g' +eqc_compile: compile + erlc -o _build/default/lib/enacl/ebin eqc_test/enacl_eqc.erl + .PHONE: console console: compile $(REBAR) shell From b9f2895b4d7a646f36e8081867a5ba8db1e8dd11 Mon Sep 17 00:00:00 2001 From: Irina Guberman Date: Tue, 15 Aug 2017 13:47:46 -0500 Subject: [PATCH 10/16] configure for QC testing on http://quickcheck-ci.com --- .eqc_ci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eqc_ci b/.eqc_ci index e7c4c8a..48d727b 100644 --- a/.eqc_ci +++ b/.eqc_ci @@ -1,2 +1,2 @@ -{build, "make eqc_compile"}. +{build, "sudo apt-get update && sudo apt-get install libsodium-dev && make eqc_compile"}. {test_path, "_build/default/lib/enacl/ebin"}. \ No newline at end of file From 05420f8a6bc7494d96fa13da8136a78ef4f0a9c5 Mon Sep 17 00:00:00 2001 From: Irina Guberman Date: Tue, 15 Aug 2017 13:52:00 -0500 Subject: [PATCH 11/16] replace xrouter_clientd with xrouter_procd --- .eqc_ci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eqc_ci b/.eqc_ci index 48d727b..2fbf566 100644 --- a/.eqc_ci +++ b/.eqc_ci @@ -1,2 +1,2 @@ -{build, "sudo apt-get update && sudo apt-get install libsodium-dev && make eqc_compile"}. +{build, "apt-get update && apt-get install libsodium-dev && make eqc_compile"}. {test_path, "_build/default/lib/enacl/ebin"}. \ No newline at end of file From 207ec85f8c1578cbe1766ec53bdfc39bcc1f7eed Mon Sep 17 00:00:00 2001 From: Zane Beckwith Date: Wed, 16 Aug 2017 21:17:28 +0000 Subject: [PATCH 12/16] Modify QuickCheck tests to be runnable to eqc-mini. This involves: - Removing calls to conjunction function - Modifying fault* functions to _always_ return "Good" generator - Commenting-out the eqc_parallelize parse_transform --- eqc_test/enacl_eqc.erl | 148 +++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 72 deletions(-) diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 8b801c4..430939d 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -2,7 +2,11 @@ -include_lib("eqc/include/eqc.hrl"). -compile(export_all). --compile({parse_transform, eqc_parallelize}). +%% -compile({parse_transform, eqc_parallelize}). + +z_fault(_Bad, Good) -> Good. + +z_fault_rate(_1, _2, Gen) -> Gen. non_byte_int() -> oneof([ @@ -14,7 +18,7 @@ g_iolist() -> ?SIZED(Sz, g_iolist(Sz)). g_iolist(0) -> - fault( + z_fault( oneof([ elements([a,b,c]), real(), @@ -22,7 +26,7 @@ g_iolist(0) -> ]), return([])); g_iolist(N) -> - fault( + z_fault( oneof([ elements([a,b,c]), real(), @@ -34,7 +38,7 @@ g_iolist(N) -> ])). g_iodata() -> - fault( + z_fault( oneof([elements([a,b,c]), real()]), oneof([binary(), g_iolist(), eqc_gen:largebinary(64*1024)])). @@ -50,7 +54,7 @@ v_iodata(Structure) -> v_iolist(Structure). %% Generator for binaries of a given size with different properties and fault injection: g_binary(Sz) -> - fault(g_binary_bad(Sz), g_binary_good(Sz)). + z_fault(g_binary_bad(Sz), g_binary_good(Sz)). g_binary_good(Sz) when Sz =< 32 -> binary(Sz); g_binary_good(Sz) -> eqc_gen:largebinary(Sz). @@ -74,7 +78,7 @@ nonce_valid(N) -> v_binary(enacl:box_nonce_size(), N). %% Generator of natural numbers g_nat() -> - fault(g_nat_bad(), nat()). + z_fault(g_nat_bad(), nat()). g_nat_bad() -> oneof([ @@ -106,7 +110,7 @@ keypair_bad() -> end). keypair() -> - fault(keypair_bad(), keypair_good()). + z_fault(keypair_bad(), keypair_good()). %% CRYPTO BOX %% --------------------------- @@ -158,10 +162,10 @@ failure(X) -> {failure, X}. prop_box_correct() -> ?FORALL({Msg, Nonce, {PK1, SK1}, {PK2, SK2}}, - {fault_rate(1, 40, g_iodata()), - fault_rate(1, 40, nonce()), - fault_rate(1, 40, keypair()), - fault_rate(1, 40, keypair())}, + {z_fault_rate(1, 40, g_iodata()), + z_fault_rate(1, 40, nonce()), + z_fault_rate(1, 40, keypair()), + z_fault_rate(1, 40, keypair())}, begin case v_iodata(Msg) andalso nonce_valid(Nonce) andalso keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of true -> @@ -182,10 +186,10 @@ prop_box_correct() -> prop_box_failure_integrity() -> ?FORALL({Msg, Nonce, {PK1, SK1}, {PK2, SK2}}, - {fault_rate(1, 40, g_iodata()), - fault_rate(1, 40, nonce()), - fault_rate(1, 40, keypair()), - fault_rate(1, 40, keypair())}, + {z_fault_rate(1, 40, g_iodata()), + z_fault_rate(1, 40, nonce()), + z_fault_rate(1, 40, keypair()), + z_fault_rate(1, 40, keypair())}, begin case v_iodata(Msg) andalso nonce_valid(Nonce) @@ -207,7 +211,7 @@ prop_box_failure_integrity() -> end). prop_seal_box_failure_integrity() -> - ?FORALL({Msg, {PK1, SK1}}, {fault_rate(1,40,g_iodata()), fault_rate(1,40,keypair())}, + ?FORALL({Msg, {PK1, SK1}}, {z_fault_rate(1,40,g_iodata()), z_fault_rate(1,40,keypair())}, begin case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of true -> @@ -225,8 +229,8 @@ prop_seal_box_failure_integrity() -> prop_seal_box_correct() -> ?FORALL({Msg, {PK1, SK1}}, - {fault_rate(1, 40, g_iodata()), - fault_rate(1, 40, keypair())}, + {z_fault_rate(1, 40, g_iodata()), + z_fault_rate(1, 40, keypair())}, begin case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of true -> @@ -243,7 +247,7 @@ prop_seal_box_correct() -> %% PRECOMPUTATIONS beforenm_key() -> - ?LET([{PK1, SK1}, {PK2, SK2}], [fault_rate(1, 40, keypair()), fault_rate(1, 40, keypair())], + ?LET([{PK1, SK1}, {PK2, SK2}], [z_fault_rate(1, 40, keypair()), z_fault_rate(1, 40, keypair())], case keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of true -> enacl:box_beforenm(PK1, SK2); @@ -259,7 +263,7 @@ v_key(K) when is_binary(K) -> byte_size(K) == enacl:box_beforenm_bytes(); v_key(_) -> false. prop_beforenm_correct() -> - ?FORALL([{PK1, SK1}, {PK2, SK2}], [fault_rate(1, 40, keypair()), fault_rate(1, 40, keypair())], + ?FORALL([{PK1, SK1}, {PK2, SK2}], [z_fault_rate(1, 40, keypair()), z_fault_rate(1, 40, keypair())], case keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of true -> equals(enacl:box_beforenm(PK1, SK2), enacl:box_beforenm(PK2, SK1)); @@ -272,9 +276,9 @@ prop_beforenm_correct() -> prop_afternm_correct() -> ?FORALL([Msg, Nonce, Key], - [fault_rate(1, 40, g_iodata()), - fault_rate(1, 40, nonce()), - fault_rate(1, 40, beforenm_key())], + [z_fault_rate(1, 40, g_iodata()), + z_fault_rate(1, 40, nonce()), + z_fault_rate(1, 40, beforenm_key())], begin case v_iodata(Msg) andalso nonce_valid(Nonce) andalso v_key(Key) of true -> @@ -325,7 +329,7 @@ sign_keypair_good() -> return(enacl:sign_keypair()). sign_keypair() -> - fault(sign_keypair_bad(), sign_keypair_good()). + z_fault(sign_keypair_bad(), sign_keypair_good()). sign_keypair_public_valid(#{ public := Public }) when is_binary(Public) -> @@ -342,8 +346,8 @@ sign_keypair_valid(KP) -> prop_sign_detached() -> ?FORALL({Msg, KeyPair}, - {fault_rate(1, 40, g_iodata()), - fault_rate(1, 40, sign_keypair())}, + {z_fault_rate(1, 40, g_iodata()), + z_fault_rate(1, 40, sign_keypair())}, begin case v_iodata(Msg) andalso sign_keypair_secret_valid(KeyPair) of true -> @@ -358,8 +362,8 @@ prop_sign_detached() -> prop_sign() -> ?FORALL({Msg, KeyPair}, - {fault_rate(1, 40, g_iodata()), - fault_rate(1, 40, sign_keypair())}, + {z_fault_rate(1, 40, g_iodata()), + z_fault_rate(1, 40, sign_keypair())}, begin case v_iodata(Msg) andalso sign_keypair_secret_valid(KeyPair) of true -> @@ -403,10 +407,10 @@ signed_message_bad_d() -> {binary(), oneof([a, int(), ?SUCHTHAT(B, binary(Sz), byte_size(B) /= Sz)])}. signed_message(M) -> - fault(signed_message_bad(), signed_message_good(M)). + z_fault(signed_message_bad(), signed_message_good(M)). signed_message_d(M) -> - fault(signed_message_bad(), signed_message_good(M)). + z_fault(signed_message_bad(), signed_message_good(M)). signed_message_valid({valid, _}, _) -> true; signed_message_valid({invalid, _}, _) -> true; @@ -451,18 +455,18 @@ prop_sign_open() -> key_sz(Sz) -> equals(enacl:secretbox_key_size(), Sz). -prop_key_sizes() -> - conjunction([{secret, key_sz(enacl:secretbox_key_size())}, - {stream, key_sz(enacl:stream_key_size())}, - {auth, key_sz(enacl:auth_key_size())}, - {onetimeauth, key_sz(enacl:onetime_auth_key_size())}]). +%% prop_key_sizes() -> +%% conjunction([{secret, key_sz(enacl:secretbox_key_size())}, +%% {stream, key_sz(enacl:stream_key_size())}, +%% {auth, key_sz(enacl:auth_key_size())}, +%% {onetimeauth, key_sz(enacl:onetime_auth_key_size())}]). nonce_sz(Sz) -> equals(enacl:secretbox_nonce_size(), Sz). -prop_nonce_sizes() -> - conjunction([{secret, nonce_sz(enacl:secretbox_nonce_size())}, - {stream, nonce_sz(enacl:stream_nonce_size())}]). +%% prop_nonce_sizes() -> +%% conjunction([{secret, nonce_sz(enacl:secretbox_nonce_size())}, +%% {stream, nonce_sz(enacl:stream_nonce_size())}]). secret_key_good() -> Sz = enacl:secretbox_key_size(), @@ -474,7 +478,7 @@ secret_key_bad() -> ?SUCHTHAT(B, binary(), byte_size(B) /= enacl:secretbox_key_size())]). secret_key() -> - fault(secret_key_bad(), secret_key_good()). + z_fault(secret_key_bad(), secret_key_good()). secret_key_valid(SK) when is_binary(SK) -> Sz = enacl:secretbox_key_size(), @@ -497,9 +501,9 @@ secretbox_open(Msg, Nonce, Key) -> prop_secretbox_correct() -> ?FORALL({Msg, Nonce, Key}, - {fault_rate(1, 40, g_iodata()), - fault_rate(1, 40, nonce()), - fault_rate(1, 40, secret_key())}, + {z_fault_rate(1, 40, g_iodata()), + z_fault_rate(1, 40, nonce()), + z_fault_rate(1, 40, secret_key())}, begin case v_iodata(Msg) andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of true -> @@ -527,8 +531,8 @@ prop_secretbox_failure_integrity() -> prop_stream_correct() -> ?FORALL({Len, Nonce, Key}, {int(), - fault_rate(1, 40, nonce()), - fault_rate(1, 40, secret_key())}, + z_fault_rate(1, 40, nonce()), + z_fault_rate(1, 40, secret_key())}, case Len >= 0 andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of true -> CipherStream = enacl:stream(Len, Nonce, Key), @@ -541,29 +545,29 @@ 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). +%% prop_stream_xor_correct() -> +%% ?FORALL({Msg, Nonce, Key}, +%% {z_fault_rate(1, 40, g_iodata()), +%% z_fault_rate(1, 40, nonce()), +%% z_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 prop_auth_correct() -> ?FORALL({Msg, Key}, - {fault_rate(1, 40, g_iodata()), - fault_rate(1, 40, secret_key())}, + {z_fault_rate(1, 40, g_iodata()), + z_fault_rate(1, 40, secret_key())}, case v_iodata(Msg) andalso secret_key_valid(Key) of true -> Authenticator = enacl:auth(Msg, Key), @@ -588,7 +592,7 @@ authenticator_good(_Msg, _Key) -> binary(enacl:auth_size()). authenticator(Msg, Key) -> - fault(authenticator_bad(), authenticator_good(Msg, Key)). + z_fault(authenticator_bad(), authenticator_good(Msg, Key)). authenticator_valid({valid, _}) -> true; authenticator_valid({invalid, _}) -> true; @@ -596,8 +600,8 @@ authenticator_valid(_) -> false. prop_auth_verify_correct() -> ?FORALL({Msg, Key}, - {fault_rate(1, 40, g_iodata()), - fault_rate(1, 40, secret_key())}, + {z_fault_rate(1, 40, g_iodata()), + z_fault_rate(1, 40, secret_key())}, ?FORALL(Authenticator, authenticator(Msg, Key), case v_iodata(Msg) andalso secret_key_valid(Key) andalso authenticator_valid(Authenticator) of true -> @@ -614,8 +618,8 @@ prop_auth_verify_correct() -> %% CRYPTO ONETIME AUTH prop_onetimeauth_correct() -> ?FORALL({Msg, Key}, - {fault_rate(1, 40, g_iodata()), - fault_rate(1, 40, secret_key())}, + {z_fault_rate(1, 40, g_iodata()), + z_fault_rate(1, 40, secret_key())}, case v_iodata(Msg) andalso secret_key_valid(Key) of true -> Authenticator = enacl:onetime_auth(Msg, Key), @@ -640,7 +644,7 @@ ot_authenticator_good(_Msg, _Key) -> binary(enacl:auth_size()). ot_authenticator(Msg, Key) -> - fault(ot_authenticator_bad(), ot_authenticator_good(Msg, Key)). + z_fault(ot_authenticator_bad(), ot_authenticator_good(Msg, Key)). ot_authenticator_valid({valid, _}) -> true; ot_authenticator_valid({invalid, _}) -> true; @@ -648,8 +652,8 @@ ot_authenticator_valid(_) -> false. prop_onetime_auth_verify_correct() -> ?FORALL({Msg, Key}, - {fault_rate(1, 40, g_iodata()), - fault_rate(1, 40, secret_key())}, + {z_fault_rate(1, 40, g_iodata()), + z_fault_rate(1, 40, secret_key())}, ?FORALL(Authenticator, ot_authenticator(Msg, Key), case v_iodata(Msg) andalso secret_key_valid(Key) andalso ot_authenticator_valid(Authenticator) of true -> @@ -706,7 +710,7 @@ verify_pair_good(Sz) -> ?SUCHTHAT({X, Y}, {binary(Sz), binary(Sz)}, X /= Y)]). verify_pair(Sz) -> - fault(verify_pair_bad(Sz), verify_pair_good(Sz)). + z_fault(verify_pair_bad(Sz), verify_pair_good(Sz)). verify_pair_valid(Sz, X, Y) -> byte_size(X) == Sz andalso byte_size(Y) == Sz. From fd796440dbfb3d1faf50edc2b58df2316eb64034 Mon Sep 17 00:00:00 2001 From: Irina Guberman Date: Wed, 16 Aug 2017 18:42:30 -0500 Subject: [PATCH 13/16] replace xrouter_clientd with xrouter_procd --- Makefile | 3 ++ eqc_test/enacl_eqc.erl | 112 ++++++++++++++++++++++------------------- 2 files changed, 63 insertions(+), 52 deletions(-) diff --git a/Makefile b/Makefile index 61eb843..3b5f540 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,9 @@ compile: eqc_compile: compile erlc -o _build/default/lib/enacl/ebin eqc_test/enacl_eqc.erl +eqc_mini_compile: compile + erlc -Dmini -o _build/default/lib/enacl/ebin eqc_test/enacl_eqc.erl + .PHONE: console console: compile $(REBAR) shell diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index 430939d..e4efbfd 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -2,11 +2,19 @@ -include_lib("eqc/include/eqc.hrl"). -compile(export_all). -%% -compile({parse_transform, eqc_parallelize}). +-ifndef(mini). +-compile({parse_transform, eqc_parallelize}). +-define(FAULT(Arg1, Arg2), eqc:fault(Arg1, Arg2)). +-define(FAULT_RATE(Arg1, Arg2, Arg3), eqc:fault_rate(Arg1, Arg2, Arg3)). +-else. +-define(FAULT(Arg1, Arg2), noop_fault(Arg1, Arg2)). +-define(FAULT_RATE(Arg1, Arg2, Arg3), noop_fault_rate(Arg1, Arg2, Arg3)). +-endif. -z_fault(_Bad, Good) -> Good. -z_fault_rate(_1, _2, Gen) -> Gen. +noop_fault(_Bad, Good) -> Good. + +noop_fault_rate(_1, _2, Gen) -> Gen. non_byte_int() -> oneof([ @@ -18,7 +26,7 @@ g_iolist() -> ?SIZED(Sz, g_iolist(Sz)). g_iolist(0) -> - z_fault( + ?FAULT( oneof([ elements([a,b,c]), real(), @@ -26,7 +34,7 @@ g_iolist(0) -> ]), return([])); g_iolist(N) -> - z_fault( + ?FAULT( oneof([ elements([a,b,c]), real(), @@ -38,7 +46,7 @@ g_iolist(N) -> ])). g_iodata() -> - z_fault( + ?FAULT( oneof([elements([a,b,c]), real()]), oneof([binary(), g_iolist(), eqc_gen:largebinary(64*1024)])). @@ -54,7 +62,7 @@ v_iodata(Structure) -> v_iolist(Structure). %% Generator for binaries of a given size with different properties and fault injection: g_binary(Sz) -> - z_fault(g_binary_bad(Sz), g_binary_good(Sz)). + ?FAULT(g_binary_bad(Sz), g_binary_good(Sz)). g_binary_good(Sz) when Sz =< 32 -> binary(Sz); g_binary_good(Sz) -> eqc_gen:largebinary(Sz). @@ -78,7 +86,7 @@ nonce_valid(N) -> v_binary(enacl:box_nonce_size(), N). %% Generator of natural numbers g_nat() -> - z_fault(g_nat_bad(), nat()). + ?FAULT(g_nat_bad(), nat()). g_nat_bad() -> oneof([ @@ -110,7 +118,7 @@ keypair_bad() -> end). keypair() -> - z_fault(keypair_bad(), keypair_good()). + ?FAULT(keypair_bad(), keypair_good()). %% CRYPTO BOX %% --------------------------- @@ -162,10 +170,10 @@ failure(X) -> {failure, X}. prop_box_correct() -> ?FORALL({Msg, Nonce, {PK1, SK1}, {PK2, SK2}}, - {z_fault_rate(1, 40, g_iodata()), - z_fault_rate(1, 40, nonce()), - z_fault_rate(1, 40, keypair()), - z_fault_rate(1, 40, keypair())}, + {?FAULT_RATE(1, 40, g_iodata()), + ?FAULT_RATE(1, 40, nonce()), + ?FAULT_RATE(1, 40, keypair()), + ?FAULT_RATE(1, 40, keypair())}, begin case v_iodata(Msg) andalso nonce_valid(Nonce) andalso keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of true -> @@ -186,10 +194,10 @@ prop_box_correct() -> prop_box_failure_integrity() -> ?FORALL({Msg, Nonce, {PK1, SK1}, {PK2, SK2}}, - {z_fault_rate(1, 40, g_iodata()), - z_fault_rate(1, 40, nonce()), - z_fault_rate(1, 40, keypair()), - z_fault_rate(1, 40, keypair())}, + {?FAULT_RATE(1, 40, g_iodata()), + ?FAULT_RATE(1, 40, nonce()), + ?FAULT_RATE(1, 40, keypair()), + ?FAULT_RATE(1, 40, keypair())}, begin case v_iodata(Msg) andalso nonce_valid(Nonce) @@ -211,7 +219,7 @@ prop_box_failure_integrity() -> end). prop_seal_box_failure_integrity() -> - ?FORALL({Msg, {PK1, SK1}}, {z_fault_rate(1,40,g_iodata()), z_fault_rate(1,40,keypair())}, + ?FORALL({Msg, {PK1, SK1}}, {?FAULT_RATE(1,40,g_iodata()), ?FAULT_RATE(1,40,keypair())}, begin case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of true -> @@ -229,8 +237,8 @@ prop_seal_box_failure_integrity() -> prop_seal_box_correct() -> ?FORALL({Msg, {PK1, SK1}}, - {z_fault_rate(1, 40, g_iodata()), - z_fault_rate(1, 40, keypair())}, + {?FAULT_RATE(1, 40, g_iodata()), + ?FAULT_RATE(1, 40, keypair())}, begin case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of true -> @@ -247,7 +255,7 @@ prop_seal_box_correct() -> %% PRECOMPUTATIONS beforenm_key() -> - ?LET([{PK1, SK1}, {PK2, SK2}], [z_fault_rate(1, 40, keypair()), z_fault_rate(1, 40, keypair())], + ?LET([{PK1, SK1}, {PK2, SK2}], [?FAULT_RATE(1, 40, keypair()), ?FAULT_RATE(1, 40, keypair())], case keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of true -> enacl:box_beforenm(PK1, SK2); @@ -263,7 +271,7 @@ v_key(K) when is_binary(K) -> byte_size(K) == enacl:box_beforenm_bytes(); v_key(_) -> false. prop_beforenm_correct() -> - ?FORALL([{PK1, SK1}, {PK2, SK2}], [z_fault_rate(1, 40, keypair()), z_fault_rate(1, 40, keypair())], + ?FORALL([{PK1, SK1}, {PK2, SK2}], [?FAULT_RATE(1, 40, keypair()), ?FAULT_RATE(1, 40, keypair())], case keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of true -> equals(enacl:box_beforenm(PK1, SK2), enacl:box_beforenm(PK2, SK1)); @@ -276,9 +284,9 @@ prop_beforenm_correct() -> prop_afternm_correct() -> ?FORALL([Msg, Nonce, Key], - [z_fault_rate(1, 40, g_iodata()), - z_fault_rate(1, 40, nonce()), - z_fault_rate(1, 40, beforenm_key())], + [?FAULT_RATE(1, 40, g_iodata()), + ?FAULT_RATE(1, 40, nonce()), + ?FAULT_RATE(1, 40, beforenm_key())], begin case v_iodata(Msg) andalso nonce_valid(Nonce) andalso v_key(Key) of true -> @@ -329,7 +337,7 @@ sign_keypair_good() -> return(enacl:sign_keypair()). sign_keypair() -> - z_fault(sign_keypair_bad(), sign_keypair_good()). + ?FAULT(sign_keypair_bad(), sign_keypair_good()). sign_keypair_public_valid(#{ public := Public }) when is_binary(Public) -> @@ -346,8 +354,8 @@ sign_keypair_valid(KP) -> prop_sign_detached() -> ?FORALL({Msg, KeyPair}, - {z_fault_rate(1, 40, g_iodata()), - z_fault_rate(1, 40, sign_keypair())}, + {?FAULT_RATE(1, 40, g_iodata()), + ?FAULT_RATE(1, 40, sign_keypair())}, begin case v_iodata(Msg) andalso sign_keypair_secret_valid(KeyPair) of true -> @@ -362,8 +370,8 @@ prop_sign_detached() -> prop_sign() -> ?FORALL({Msg, KeyPair}, - {z_fault_rate(1, 40, g_iodata()), - z_fault_rate(1, 40, sign_keypair())}, + {?FAULT_RATE(1, 40, g_iodata()), + ?FAULT_RATE(1, 40, sign_keypair())}, begin case v_iodata(Msg) andalso sign_keypair_secret_valid(KeyPair) of true -> @@ -407,10 +415,10 @@ signed_message_bad_d() -> {binary(), oneof([a, int(), ?SUCHTHAT(B, binary(Sz), byte_size(B) /= Sz)])}. signed_message(M) -> - z_fault(signed_message_bad(), signed_message_good(M)). + ?FAULT(signed_message_bad(), signed_message_good(M)). signed_message_d(M) -> - z_fault(signed_message_bad(), signed_message_good(M)). + ?FAULT(signed_message_bad(), signed_message_good(M)). signed_message_valid({valid, _}, _) -> true; signed_message_valid({invalid, _}, _) -> true; @@ -478,7 +486,7 @@ secret_key_bad() -> ?SUCHTHAT(B, binary(), byte_size(B) /= enacl:secretbox_key_size())]). secret_key() -> - z_fault(secret_key_bad(), secret_key_good()). + ?FAULT(secret_key_bad(), secret_key_good()). secret_key_valid(SK) when is_binary(SK) -> Sz = enacl:secretbox_key_size(), @@ -501,9 +509,9 @@ secretbox_open(Msg, Nonce, Key) -> prop_secretbox_correct() -> ?FORALL({Msg, Nonce, Key}, - {z_fault_rate(1, 40, g_iodata()), - z_fault_rate(1, 40, nonce()), - z_fault_rate(1, 40, secret_key())}, + {?FAULT_RATE(1, 40, g_iodata()), + ?FAULT_RATE(1, 40, nonce()), + ?FAULT_RATE(1, 40, secret_key())}, begin case v_iodata(Msg) andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of true -> @@ -531,8 +539,8 @@ prop_secretbox_failure_integrity() -> prop_stream_correct() -> ?FORALL({Len, Nonce, Key}, {int(), - z_fault_rate(1, 40, nonce()), - z_fault_rate(1, 40, secret_key())}, + ?FAULT_RATE(1, 40, nonce()), + ?FAULT_RATE(1, 40, secret_key())}, case Len >= 0 andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of true -> CipherStream = enacl:stream(Len, Nonce, Key), @@ -547,9 +555,9 @@ xor_bytes(<<>>, <<>>) -> []. %% prop_stream_xor_correct() -> %% ?FORALL({Msg, Nonce, Key}, -%% {z_fault_rate(1, 40, g_iodata()), -%% z_fault_rate(1, 40, nonce()), -%% z_fault_rate(1, 40, secret_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), @@ -566,8 +574,8 @@ xor_bytes(<<>>, <<>>) -> []. %% CRYPTO AUTH prop_auth_correct() -> ?FORALL({Msg, Key}, - {z_fault_rate(1, 40, g_iodata()), - z_fault_rate(1, 40, secret_key())}, + {?FAULT_RATE(1, 40, g_iodata()), + ?FAULT_RATE(1, 40, secret_key())}, case v_iodata(Msg) andalso secret_key_valid(Key) of true -> Authenticator = enacl:auth(Msg, Key), @@ -592,7 +600,7 @@ authenticator_good(_Msg, _Key) -> binary(enacl:auth_size()). authenticator(Msg, Key) -> - z_fault(authenticator_bad(), authenticator_good(Msg, Key)). + ?FAULT(authenticator_bad(), authenticator_good(Msg, Key)). authenticator_valid({valid, _}) -> true; authenticator_valid({invalid, _}) -> true; @@ -600,8 +608,8 @@ authenticator_valid(_) -> false. prop_auth_verify_correct() -> ?FORALL({Msg, Key}, - {z_fault_rate(1, 40, g_iodata()), - z_fault_rate(1, 40, secret_key())}, + {?FAULT_RATE(1, 40, g_iodata()), + ?FAULT_RATE(1, 40, secret_key())}, ?FORALL(Authenticator, authenticator(Msg, Key), case v_iodata(Msg) andalso secret_key_valid(Key) andalso authenticator_valid(Authenticator) of true -> @@ -618,8 +626,8 @@ prop_auth_verify_correct() -> %% CRYPTO ONETIME AUTH prop_onetimeauth_correct() -> ?FORALL({Msg, Key}, - {z_fault_rate(1, 40, g_iodata()), - z_fault_rate(1, 40, secret_key())}, + {?FAULT_RATE(1, 40, g_iodata()), + ?FAULT_RATE(1, 40, secret_key())}, case v_iodata(Msg) andalso secret_key_valid(Key) of true -> Authenticator = enacl:onetime_auth(Msg, Key), @@ -644,7 +652,7 @@ ot_authenticator_good(_Msg, _Key) -> binary(enacl:auth_size()). ot_authenticator(Msg, Key) -> - z_fault(ot_authenticator_bad(), ot_authenticator_good(Msg, Key)). + ?FAULT(ot_authenticator_bad(), ot_authenticator_good(Msg, Key)). ot_authenticator_valid({valid, _}) -> true; ot_authenticator_valid({invalid, _}) -> true; @@ -652,8 +660,8 @@ ot_authenticator_valid(_) -> false. prop_onetime_auth_verify_correct() -> ?FORALL({Msg, Key}, - {z_fault_rate(1, 40, g_iodata()), - z_fault_rate(1, 40, secret_key())}, + {?FAULT_RATE(1, 40, g_iodata()), + ?FAULT_RATE(1, 40, secret_key())}, ?FORALL(Authenticator, ot_authenticator(Msg, Key), case v_iodata(Msg) andalso secret_key_valid(Key) andalso ot_authenticator_valid(Authenticator) of true -> @@ -710,7 +718,7 @@ verify_pair_good(Sz) -> ?SUCHTHAT({X, Y}, {binary(Sz), binary(Sz)}, X /= Y)]). verify_pair(Sz) -> - z_fault(verify_pair_bad(Sz), verify_pair_good(Sz)). + ?FAULT(verify_pair_bad(Sz), verify_pair_good(Sz)). verify_pair_valid(Sz, X, Y) -> byte_size(X) == Sz andalso byte_size(Y) == Sz. From cfd654c275f80952e9ee0df0fc48aea1fe20ab3c Mon Sep 17 00:00:00 2001 From: Irina Guberman Date: Wed, 16 Aug 2017 23:40:51 -0500 Subject: [PATCH 14/16] Add eqc_mini_run and eqc_run directives to Makefile --- Makefile | 7 +++++++ eqc_test/enacl_eqc.erl | 2 ++ 2 files changed, 9 insertions(+) diff --git a/Makefile b/Makefile index 3b5f540..1b167ab 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ REBAR=rebar3 +RUN_EQC=erl -pa _build/default/lib/enacl/ebin -noshell -s enacl_eqc -s init stop .PHONY: compile compile: @@ -10,6 +11,12 @@ eqc_compile: compile eqc_mini_compile: compile erlc -Dmini -o _build/default/lib/enacl/ebin eqc_test/enacl_eqc.erl +eqc_run: eqc_compile + $(RUN_EQC) + +eqc_mini_run: eqc_mini_compile + $(RUN_EQC) + .PHONE: console console: compile $(REBAR) shell diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index e4efbfd..b7cfb5f 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -11,6 +11,8 @@ -define(FAULT_RATE(Arg1, Arg2, Arg3), noop_fault_rate(Arg1, Arg2, Arg3)). -endif. +start()-> + eqc:module(?MODULE). noop_fault(_Bad, Good) -> Good. From 43835abafedf29d36a2ab5b968d5411df111ab34 Mon Sep 17 00:00:00 2001 From: Irina Guberman Date: Wed, 16 Aug 2017 23:52:31 -0500 Subject: [PATCH 15/16] fix EQC fault calls --- .eqc_ci | 2 +- eqc_test/enacl_eqc.erl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.eqc_ci b/.eqc_ci index 2fbf566..e7c4c8a 100644 --- a/.eqc_ci +++ b/.eqc_ci @@ -1,2 +1,2 @@ -{build, "apt-get update && apt-get install libsodium-dev && make eqc_compile"}. +{build, "make eqc_compile"}. {test_path, "_build/default/lib/enacl/ebin"}. \ No newline at end of file diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index b7cfb5f..3bc2987 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -4,8 +4,8 @@ -ifndef(mini). -compile({parse_transform, eqc_parallelize}). --define(FAULT(Arg1, Arg2), eqc:fault(Arg1, Arg2)). --define(FAULT_RATE(Arg1, Arg2, Arg3), eqc:fault_rate(Arg1, Arg2, Arg3)). +-define(FAULT(Arg1, Arg2), fault(Arg1, Arg2)). +-define(FAULT_RATE(Arg1, Arg2, Arg3), fault_rate(Arg1, Arg2, Arg3)). -else. -define(FAULT(Arg1, Arg2), noop_fault(Arg1, Arg2)). -define(FAULT_RATE(Arg1, Arg2, Arg3), noop_fault_rate(Arg1, Arg2, Arg3)). From bd80d1d79d6ce49b931a14b324a69858c924bac0 Mon Sep 17 00:00:00 2001 From: Irina Guberman Date: Thu, 17 Aug 2017 23:50:01 -0500 Subject: [PATCH 16/16] Add make eqc_mini_run and eqc_run instructions to README --- .eqc_ci | 2 -- EQC_CI_LICENCE.txt | 34 ---------------------------------- README.md | 8 ++++++++ 3 files changed, 8 insertions(+), 36 deletions(-) delete mode 100644 .eqc_ci delete mode 100644 EQC_CI_LICENCE.txt diff --git a/.eqc_ci b/.eqc_ci deleted file mode 100644 index e7c4c8a..0000000 --- a/.eqc_ci +++ /dev/null @@ -1,2 +0,0 @@ -{build, "make eqc_compile"}. -{test_path, "_build/default/lib/enacl/ebin"}. \ No newline at end of file diff --git a/EQC_CI_LICENCE.txt b/EQC_CI_LICENCE.txt deleted file mode 100644 index 6d2a058..0000000 --- a/EQC_CI_LICENCE.txt +++ /dev/null @@ -1,34 +0,0 @@ -This file is an agreement between Quviq AB ("Quviq"), Sven Hultins -Gata 9, Gothenburg, Sweden, and the committers to the github -repository in which the file appears ("the owner"). By placing this -file in a github repository, the owner agrees to the terms below. - -The purpose of the agreement is to enable Quviq AB to provide a -continuous integration service to the owner, whereby the code in the -repository ("the source code") is tested using Quviq's test tools, and -the test results are made available on the web. The test results -include test output, generated test cases, and a copy of the source -code in the repository annotated with coverage information ("the test -results"). - -The owner agrees that Quviq may run the tests in the source code and -display the test results on the web, without obligation. - -The owner warrants that running the tests in the source code and -displaying the test results on the web violates no laws, licences or other -agreements. In the event of such a violation, the owner accepts full -responsibility. - -The owner warrants that the source code is not malicious, and will not -mount an attack on either Quviq's server or any other server--for -example by taking part in a denial of service attack, or by attempting -to send unsolicited emails. - -The owner warrants that the source code does not attempt to reverse -engineer Quviq's code. - -Quviq reserves the right to exclude repositories that break this -agreement from its continuous integration service. - -Any dispute arising from the use of Quviq's service will be resolved -under Swedish law. diff --git a/README.md b/README.md index 464abae..0152985 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,14 @@ or rebar compile +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.