summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--c_src/monocypher_nif.c152
-rw-r--r--src/monocypher.erl23
3 files changed, 177 insertions, 3 deletions
diff --git a/README.md b/README.md
index fff1c2b..ba948b5 100644
--- a/README.md
+++ b/README.md
@@ -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>>.