summaryrefslogtreecommitdiff
path: root/c_src/monocypher_nif.c
diff options
context:
space:
mode:
Diffstat (limited to 'c_src/monocypher_nif.c')
-rw-r--r--c_src/monocypher_nif.c152
1 files changed, 151 insertions, 1 deletions
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},