From d3c033c4e64912db68c52690e9aa3a8f17ff3161 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Mon, 20 Jan 2020 14:38:20 +0100 Subject: [PATCH] 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