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).