diff options
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | c_src/monocypher_nif.c | 152 | ||||
-rw-r--r-- | src/monocypher.erl | 23 |
3 files changed, 177 insertions, 3 deletions
@@ -36,6 +36,11 @@ See also the [Monocypher documentation](https://monocypher.org/manual/). - [ ] `crypto_blake2b_update` - [ ] `crypto_blake2b_final` +#### Password hashing and key derivation + +- [X] `crypto_argon2i` +- [X] `crypto_argon2i_general` + #### IETF ChaCha20 - [X] `crypto_ietf_chacha20` diff --git a/c_src/monocypher_nif.c b/c_src/monocypher_nif.c index c8390e2..f44219b 100644 --- a/c_src/monocypher_nif.c +++ b/c_src/monocypher_nif.c @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2020 pukkamustard <pukkamustard@posteo.net> +// SPDX-FileCopyrightText: 2020-2021 pukkamustard <pukkamustard@posteo.net> +// SPDX-FileCopyrightText: 2020-2021 rustra <rustra@disroot.org> // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -156,6 +157,153 @@ static ERL_NIF_TERM crypto_blake2b_general_nif(ErlNifEnv* env, int argc, const E return hash_term; } +/* Password hashing and key derivation */ + +static ERL_NIF_TERM crypto_argon2i_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + size_t hash_size; + if (!enif_get_ulong(env, argv[0], &hash_size)) { + return enif_make_badarg(env); + } + + // hash size must be exactly 32 or 64 bytes + if(!(hash_size == 32 || hash_size == 64)) { + return enif_make_badarg(env); + } + + ERL_NIF_TERM hash_term; + unsigned char* hash = enif_make_new_binary(env, hash_size, &hash_term); + + size_t nb_blocks; + if(!enif_get_ulong(env, argv[1], &nb_blocks)) { + return enif_make_badarg(env); + } + + // number of blocks must at least 8 + if(nb_blocks < 8) { + return enif_make_badarg(env); + } + + ERL_NIF_TERM work_area_term; + unsigned char* work_area = enif_make_new_binary(env, nb_blocks * 1024, &work_area_term); + + size_t nb_iterations; + if(!enif_get_ulong(env, argv[2], &nb_iterations)) { + return enif_make_badarg(env); + } + + // number of iterations must at least 1 + if(nb_iterations < 1) { + return enif_make_badarg(env); + } + + ErlNifBinary password; + if(!enif_inspect_binary(env, argv[3], &password)) { + return enif_make_badarg(env); + } + + // length of password must at least 1 + if(password.size < 1) { + return enif_make_badarg(env); + } + + ErlNifBinary salt; + if(!enif_inspect_binary(env, argv[4], &salt)) { + return enif_make_badarg(env); + } + + // length of salt must at least 8 + if(salt.size < 8) { + return enif_make_badarg(env); + } + + crypto_argon2i(hash, hash_size, work_area, nb_blocks, nb_iterations, password.data, password.size, salt.data, salt.size); + + return hash_term; +} + +static ERL_NIF_TERM crypto_argon2i_general_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + size_t hash_size; + if (!enif_get_ulong(env, argv[0], &hash_size)) { + return enif_make_badarg(env); + } + + // hash size must be exactly 32 or 64 bytes + if(!(hash_size == 32 || hash_size == 64)) { + return enif_make_badarg(env); + } + + ERL_NIF_TERM hash_term; + unsigned char* hash = enif_make_new_binary(env, hash_size, &hash_term); + + size_t nb_blocks; + if(!enif_get_ulong(env, argv[1], &nb_blocks)) { + return enif_make_badarg(env); + } + + // number of blocks must at least 8 + if(nb_blocks < 8) { + return enif_make_badarg(env); + } + + ERL_NIF_TERM work_area_term; + unsigned char* work_area = enif_make_new_binary(env, nb_blocks * 1024, &work_area_term); + + size_t nb_iterations; + if(!enif_get_ulong(env, argv[2], &nb_iterations)) { + return enif_make_badarg(env); + } + + // number of iterations must at least 1 + if(nb_iterations < 1) { + return enif_make_badarg(env); + } + + ErlNifBinary password; + if(!enif_inspect_binary(env, argv[3], &password)) { + return enif_make_badarg(env); + } + + // length of password must at least 1 + if(password.size < 1) { + return enif_make_badarg(env); + } + + ErlNifBinary salt; + if(!enif_inspect_binary(env, argv[4], &salt)) { + return enif_make_badarg(env); + } + + // length of salt must at least 8 + if(salt.size < 8) { + return enif_make_badarg(env); + } + + ErlNifBinary key; + if(!enif_inspect_binary(env, argv[5], &key)) { + return enif_make_badarg(env); + } + + // length of key must at least 0 + if(key.size < 0) { + return enif_make_badarg(env); + } + + ErlNifBinary ad; + if(!enif_inspect_binary(env, argv[6], &ad)) { + return enif_make_badarg(env); + } + + // length of additional data must at least 0 + if(ad.size < 0) { + return enif_make_badarg(env); + } + + crypto_argon2i_general(hash, hash_size, work_area, nb_blocks, nb_iterations, password.data, password.size, salt.data, salt.size, key.data, key.size, ad.data, ad.size); + + return hash_term; +} /* IETF ChaCha20 */ @@ -326,6 +474,8 @@ static ErlNifFunc nif_funs[] = {"crypto_unlock", 4, crypto_unlock_nif}, {"crypto_blake2b", 1, crypto_blake2b_nif}, {"crypto_blake2b_general", 3, crypto_blake2b_general_nif}, + {"crypto_argon2i", 5, crypto_argon2i_nif}, + {"crypto_argon2i_general", 7, crypto_argon2i_general_nif}, {"crypto_ietf_chacha20", 3, crypto_ietf_chacha20_nif}, {"crypto_ietf_chacha20_ctr", 4, crypto_ietf_chacha20_ctr_nif}, {"crypto_ed25519_public_key", 1, crypto_ed25519_public_key_nif}, diff --git a/src/monocypher.erl b/src/monocypher.erl index eca8fc4..1788694 100644 --- a/src/monocypher.erl +++ b/src/monocypher.erl @@ -1,4 +1,5 @@ -% SPDX-FileCopyrightText: 2020 pukkamustard <pukkamustard@posteo.net> +% SPDX-FileCopyrightText: 2020-2021 pukkamustard <pukkamustard@posteo.net> +% SPDX-FileCopyrightText: 2020-2021 rustra <rustra@disroot.org> % % SPDX-License-Identifier: LGPL-3.0-or-later @@ -7,6 +8,8 @@ crypto_unlock/4]). -export([crypto_blake2b/1, crypto_blake2b_general/3]). +-export([crypto_argon2i/5, + crypto_argon2i_general/7]). -export([crypto_ietf_chacha20/3, crypto_ietf_chacha20_ctr/4]). -export([crypto_ed25519_public_key/1, @@ -36,13 +39,29 @@ crypto_unlock(_,_,_,_) -> crypto_blake2b(_) -> not_loaded(?LINE). - -type crypto_blake2b_hash_size() :: 1..64. -type crypto_blake2b_key() :: <<_:_*8>>. -spec crypto_blake2b_general(crypto_blake2b_hash_size(), crypto_blake2b_key(), binary()) -> binary(). crypto_blake2b_general(_,_,_) -> not_loaded(?LINE). +%% Password hashing and key derivation + +-type crypto_argon2i_hash_size() :: 32..64. +-type crypto_argon2i_nb_blocks() :: pos_integer(). +-type crypto_argon2i_nb_iterations() :: pos_integer(). +-type crypto_argon2i_password() :: <<_:_*8>>. +-type crypto_argon2i_salt() :: <<_:_*8>>. +-spec crypto_argon2i(crypto_argon2i_hash_size(), crypto_argon2i_nb_blocks(), crypto_argon2i_nb_iterations(), crypto_argon2i_password(), crypto_argon2i_salt()) -> binary(). +crypto_argon2i(_,_,_,_,_) -> + not_loaded(?LINE). + +-type crypto_argon2i_key() :: <<_:_*8>>. +-type crypto_argon2i_ad() :: <<_:_*8>>. +-spec crypto_argon2i_general(crypto_argon2i_hash_size(), crypto_argon2i_nb_blocks(), crypto_argon2i_nb_iterations(), crypto_argon2i_password(), crypto_argon2i_salt(), crypto_argon2i_key(), crypto_argon2i_ad()) -> binary(). +crypto_argon2i_general(_,_,_,_,_,_,_) -> + not_loaded(?LINE). + %% IETF ChaCha20 -type crypto_ietf_chacha20_key() :: <<_:256>>. |