Merge pull request #16 from xaptum/fix_mips32_warnings_QC

Fix mips32 warnings and add support for compiling enacl_eqc with EQC mini
This commit is contained in:
Jesper Louis Andersen 2017-08-27 13:06:38 +02:00 committed by GitHub
commit 5a48c66b07
7 changed files with 615 additions and 113 deletions

View File

@ -1,9 +1,26 @@
REBAR=rebar3
RUN_EQC=erl -pa _build/default/lib/enacl/ebin -noshell -s enacl_eqc -s init stop
.PHONY: compile
compile:
$(REBAR) compile | sed -e 's|_build/default/lib/enacl/||g'
eqc_compile: compile
erlc -o _build/default/lib/enacl/ebin eqc_test/enacl_eqc.erl
eqc_mini_compile: compile
erlc -Dmini -o _build/default/lib/enacl/ebin eqc_test/enacl_eqc.erl
eqc_run: eqc_compile
$(RUN_EQC)
eqc_mini_run: eqc_mini_compile
$(RUN_EQC)
.PHONE: console
console: compile
$(REBAR) shell
.PHONY: clean
clean:
$(REBAR) clean

View File

@ -30,6 +30,14 @@ or
rebar compile
To build and run licensed eqc test execute:
make eqc_run
To build and run eqc-mini version of test execute:
make eqc_mini_run
## Features:
* Complete NaCl library, implementing all default functionality.

View File

@ -10,7 +10,7 @@ C_SRC_DIR = $(CURDIR)
C_SRC_OUTPUT ?= $(CURDIR)/../priv/$(PROJECT).so
# System type and C compiler/flags.
MACHINE_SYS := $(shell uname -m)
UNAME_SYS := $(shell uname -s)
ifeq ($(UNAME_SYS), Darwin)
CC ?= cc

View File

@ -4,7 +4,25 @@
#include <sodium.h>
#define ATOM_OK "ok"
#define ATOM_ERROR "error"
#define ATOM_TRUE "true"
#define ATOM_FALSE "false"
#define CRYPTO_GENERICHASH_STATE_RESOURCE "crypto_generichash_state"
#ifdef ERL_NIF_DIRTY_JOB_CPU_BOUND
#define erl_nif_dirty_job_cpu_bound_macro(a,b,c) {a,b,c,ERL_NIF_DIRTY_JOB_CPU_BOUND}
#else
#define erl_nif_dirty_job_cpu_bound_macro(a,b,c) {a,b,c}
#endif
//{"crypto_box_keypair", 0, enif_crypto_box_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND}
/* Errors */
/* This is a global variable for resource type */
static ErlNifResourceType *generichash_state_type = NULL;
static
ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) {
return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, error_atom));
@ -13,8 +31,12 @@ ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *env, char *error_atom) {
/* Initialization */
static
int enif_crypto_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info) {
sodium_init();
return 0;
// Create a new resource type for crypto_generichash_state
if( !(generichash_state_type = enif_open_resource_type(env, NULL, CRYPTO_GENERICHASH_STATE_RESOURCE, NULL, ERL_NIF_RT_CREATE, NULL)) ) {
return -1;
}
return sodium_init();
}
/* Low-level functions (Hashing, String Equality, ...) */
@ -282,7 +304,9 @@ ERL_NIF_TERM enif_crypto_box(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]
return nacl_error_tuple(env, "alloc_failed");
}
crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data, pk.data, sk.data);
if( 0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data, pk.data, sk.data) ) {
return nacl_error_tuple(env, "box_error");
}
return enif_make_sub_binary(
env,
@ -347,7 +371,10 @@ ERL_NIF_TERM enif_crypto_box_beforenm(ErlNifEnv *env, int argc, ERL_NIF_TERM con
return nacl_error_tuple(env, "alloc_failed");
}
crypto_box_beforenm(k.data, pk.data, sk.data);
if( 0 != crypto_box_beforenm(k.data, pk.data, sk.data) ) {
// error
return nacl_error_tuple(env, "error_gen_shared_secret");
}
return enif_make_binary(env, &k);
}
@ -1012,10 +1039,10 @@ ERL_NIF_TERM enif_crypto_onetimeauth_verify(ErlNifEnv *env, int argc, ERL_NIF_TE
static
ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[])
{
size_t req_size;
unsigned req_size;
ErlNifBinary result;
if ((argc != 1) || (!enif_get_uint64(env, argv[0], &req_size))) {
if ((argc != 1) || (!enif_get_uint(env, argv[0], &req_size))) {
return enif_make_badarg(env);
}
@ -1090,7 +1117,10 @@ ERL_NIF_TERM enif_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, ERL_NI
return nacl_error_tuple(env, "alloc_failed");
}
crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data, server_sk.data, client_pk.data);
if( 0 != crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data, server_sk.data, client_pk.data) ) {
// suspicious client public key
return nacl_error_tuple(env, "invalid_client_public_key");
}
return enif_make_tuple2(env, enif_make_binary(env, &rx), enif_make_binary(env, &tx));
}
@ -1118,7 +1148,10 @@ ERL_NIF_TERM enif_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, ERL_NI
return nacl_error_tuple(env, "alloc_failed");
}
crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data, client_sk.data, server_pk.data);
if( 0 != crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data, client_sk.data, server_pk.data) ) {
// suspicious server public key
return nacl_error_tuple(env, "invalid_server_public_key");
}
return enif_make_tuple2(env, enif_make_binary(env, &rx), enif_make_binary(env, &tx));
}
@ -1198,6 +1231,293 @@ ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, ERL_NIF_TERM const
return enif_make_binary(env, &out);
}
static
ERL_NIF_TERM enif_crypto_pwhash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
ErlNifBinary h, p, s;
// Validate the arguments
if( (argc != 2) ||
(!enif_inspect_iolist_as_binary(env, argv[0], &p)) ||
(!enif_inspect_binary(env, argv[1], &s)) ) {
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,
crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE, 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 enif_crypto_pwhash_str(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
ErlNifBinary h, p;
// Validate the arguments
if( (argc != 1) ||
(!enif_inspect_iolist_as_binary(env, argv[0], &p)) ) {
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,
crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE) != 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 enif_crypto_pwhash_str_verify(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
ErlNifBinary h, p;
// Validate the arguments
if( (argc != 2) ||
(!enif_inspect_binary(env, argv[0], &h)) ||
(!enif_inspect_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;
}
/*
* Generic hash
*/
static
ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_generichash_BYTES);
}
static
ERL_NIF_TERM enif_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_generichash_BYTES_MIN);
}
static
ERL_NIF_TERM enif_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_generichash_BYTES_MAX);
}
static
ERL_NIF_TERM enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_generichash_KEYBYTES);
}
static
ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_generichash_KEYBYTES_MIN);
}
static
ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_generichash_KEYBYTES_MAX);
}
static
ERL_NIF_TERM enif_crypto_generichash(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
ErlNifBinary hash, message, key;
unsigned hashSize;
// Validate the arguments
if( (argc != 3) ||
(!enif_get_uint(env, argv[0], &hashSize)) ||
(!enif_inspect_binary(env, argv[1], &message)) ||
(!enif_inspect_binary(env, argv[2], &key)) ) {
return enif_make_badarg(env);
}
// Verify that hash size is crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
if( (hashSize < crypto_generichash_BYTES_MIN) ||
(hashSize > crypto_generichash_BYTES_MAX) ) {
return nacl_error_tuple(env, "invalid_hash_size");
}
// validate key size
unsigned char *k = key.data;
if( 0 == key.size ) {
k = NULL;
} else if( key.size < crypto_generichash_KEYBYTES_MIN || key.size > crypto_generichash_KEYBYTES_MAX ) {
return nacl_error_tuple(env, "invalid_key_size");
}
// allocate memory for hash
if( !enif_alloc_binary(hashSize, &hash) ) {
return nacl_error_tuple(env, "alloc_failed");
}
// calculate hash
if( 0 != crypto_generichash(hash.data, hash.size, message.data, message.size, k, key.size) ) {
enif_release_binary(&hash);
return nacl_error_tuple(env, "hash_error");
}
ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK);
ERL_NIF_TERM ret = enif_make_binary(env, &hash);
return enif_make_tuple2(env, ok, ret);
}
static
ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
ErlNifBinary key;
unsigned hashSize;
// Validate the arguments
if( (argc != 2) ||
(!enif_get_uint(env, argv[0], &hashSize)) ||
(!enif_inspect_binary(env, argv[1], &key)) ) {
return enif_make_badarg(env);
}
// Verify that hash size is crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
if( (hashSize < crypto_generichash_BYTES_MIN) ||
(hashSize > crypto_generichash_BYTES_MAX) ) {
return nacl_error_tuple(env, "invalid_hash_size");
}
// validate key size
unsigned char *k = key.data;
if( 0 == key.size ) {
k = NULL;
} else if( key.size < crypto_generichash_KEYBYTES_MIN || key.size > crypto_generichash_KEYBYTES_MAX ) {
return nacl_error_tuple(env, "invalid_key_size");
}
// Create a resource for hash state
crypto_generichash_state *state = (crypto_generichash_state *)enif_alloc_resource(generichash_state_type, crypto_generichash_statebytes());
if( !state ) {
return nacl_error_tuple(env, "alloc_failed");
}
// Call the library function
if( 0 != crypto_generichash_init(state, k, key.size, hashSize) ) {
return nacl_error_tuple(env, "hash_init_error");
}
// Create return values
ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate");
ERL_NIF_TERM e2 = argv[0];
ERL_NIF_TERM e3 = enif_make_resource(env, state);
// release dynamically allocated memory to erlang to mange
enif_release_resource(state);
// return a tuple
return enif_make_tuple3(env, e1, e2, e3);
}
static
ERL_NIF_TERM enif_crypto_generichash_update(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
ErlNifBinary message;
unsigned hashSize;
crypto_generichash_state *state;
// Validate the arguments
if( (argc != 3) ||
(!enif_get_uint(env, argv[0], &hashSize)) ||
(!enif_get_resource(env, argv[1], generichash_state_type, (void **)&state)) ||
(!enif_inspect_binary(env, argv[2], &message)) ) {
return enif_make_badarg(env);
}
// Verify that hash size is crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
if( (hashSize < crypto_generichash_BYTES_MIN) ||
(hashSize > crypto_generichash_BYTES_MAX) ) {
return nacl_error_tuple(env, "invalid_hash_size");
}
// Update hash state
if( 0 != crypto_generichash_update(state, message.data, message.size) ) {
return nacl_error_tuple(env, "hash_update_error");
}
// Generate return value
ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate");
ERL_NIF_TERM e2 = argv[0];
ERL_NIF_TERM e3 = enif_make_resource(env, state);
// return a tuple
return enif_make_tuple3(env, e1, e2, e3);
}
static
ERL_NIF_TERM enif_crypto_generichash_final(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
ErlNifBinary hash;
unsigned hashSize;
crypto_generichash_state *state;
// Validate the arguments
if( (argc != 2) ||
(!enif_get_uint(env, argv[0], &hashSize)) ||
(!enif_get_resource(env, argv[1], generichash_state_type, (void **)&state)) ) {
return enif_make_badarg(env);
}
// Verify that hash size is crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
if( (hashSize < crypto_generichash_BYTES_MIN) ||
(hashSize > crypto_generichash_BYTES_MAX) ) {
return nacl_error_tuple(env, "invalid_hash_size");
}
// allocate memory for hash
if( !enif_alloc_binary(hashSize, &hash) ) {
return nacl_error_tuple(env, "alloc_failed");
}
// calculate hash
if( 0 != crypto_generichash_final(state, hash.data, hash.size) ) {
enif_release_binary(&hash);
return nacl_error_tuple(env, "hash_error");
}
ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK);
ERL_NIF_TERM ret = enif_make_binary(env, &hash);
return enif_make_tuple2(env, ok, ret);
}
/* Tie the knot to the Erlang world */
static ErlNifFunc nif_funcs[] = {
{"crypto_box_NONCEBYTES", 0, enif_crypto_box_NONCEBYTES},
@ -1207,97 +1527,114 @@ static ErlNifFunc nif_funcs[] = {
{"crypto_box_SECRETKEYBYTES", 0, enif_crypto_box_SECRETKEYBYTES},
{"crypto_box_BEFORENMBYTES", 0, enif_crypto_box_BEFORENMBYTES},
{"crypto_box_keypair", 0, enif_crypto_box_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_box_keypair", 0, enif_crypto_box_keypair),
{"crypto_box", 4, enif_crypto_box, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"crypto_box_open", 4, enif_crypto_box_open, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_box", 4, enif_crypto_box),
erl_nif_dirty_job_cpu_bound_macro("crypto_box_open", 4, enif_crypto_box_open),
{"crypto_box_beforenm", 2, enif_crypto_box_beforenm},
{"crypto_box_afternm_b", 3, enif_crypto_box_afternm},
{"crypto_box_afternm", 3, enif_crypto_box_afternm, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_box_afternm", 3, enif_crypto_box_afternm),
{"crypto_box_open_afternm_b", 3, enif_crypto_box_open_afternm},
{"crypto_box_open_afternm", 3, enif_crypto_box_open_afternm, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_box_open_afternm", 3, enif_crypto_box_open_afternm),
{"crypto_sign_PUBLICKEYBYTES", 0, enif_crypto_sign_PUBLICKEYBYTES},
{"crypto_sign_SECRETKEYBYTES", 0, enif_crypto_sign_SECRETKEYBYTES},
{"crypto_sign_keypair", 0, enif_crypto_sign_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_sign_keypair", 0, enif_crypto_sign_keypair),
{"crypto_sign", 2, enif_crypto_sign, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"crypto_sign_open", 2, enif_crypto_sign_open, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_sign", 2, enif_crypto_sign),
erl_nif_dirty_job_cpu_bound_macro("crypto_sign_open", 2, enif_crypto_sign_open),
{"crypto_sign_detached", 2, enif_crypto_sign_detached, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"crypto_sign_verify_detached", 3, enif_crypto_sign_verify_detached, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_sign_detached", 2, enif_crypto_sign_detached),
erl_nif_dirty_job_cpu_bound_macro("crypto_sign_verify_detached", 3, enif_crypto_sign_verify_detached),
{"crypto_box_SEALBYTES", 0, enif_crypto_box_SEALBYTES},
{"crypto_box_seal", 2, enif_crypto_box_seal, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"crypto_box_seal_open", 3, enif_crypto_box_seal_open, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_box_seal", 2, enif_crypto_box_seal),
erl_nif_dirty_job_cpu_bound_macro("crypto_box_seal_open", 3, enif_crypto_box_seal_open),
{"crypto_secretbox_NONCEBYTES", 0, enif_crypto_secretbox_NONCEBYTES},
{"crypto_secretbox_ZEROBYTES", 0, enif_crypto_secretbox_ZEROBYTES},
{"crypto_secretbox_BOXZEROBYTES", 0, enif_crypto_secretbox_BOXZEROBYTES},
{"crypto_secretbox_KEYBYTES", 0, enif_crypto_secretbox_KEYBYTES},
{"crypto_secretbox_b", 3, enif_crypto_secretbox},
{"crypto_secretbox", 3, enif_crypto_secretbox, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_secretbox", 3, enif_crypto_secretbox),
{"crypto_secretbox_open_b", 3, enif_crypto_secretbox_open},
{"crypto_secretbox_open", 3, enif_crypto_secretbox_open, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_secretbox_open", 3, enif_crypto_secretbox_open),
{"crypto_stream_chacha20_KEYBYTES", 0, enif_crypto_stream_chacha20_KEYBYTES},
{"crypto_stream_chacha20_NONCEBYTES", 0, enif_crypto_stream_chacha20_NONCEBYTES},
{"crypto_stream_chacha20_b", 3, enif_crypto_stream_chacha20},
{"crypto_stream_chacha20", 3, enif_crypto_stream_chacha20, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_stream_chacha20", 3, enif_crypto_stream_chacha20),
{"crypto_stream_chacha20_xor_b", 3, enif_crypto_stream_chacha20_xor},
{"crypto_stream_chacha20_xor", 3, enif_crypto_stream_chacha20_xor, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_stream_chacha20_xor", 3, enif_crypto_stream_chacha20_xor),
{"crypto_stream_KEYBYTES", 0, enif_crypto_stream_KEYBYTES},
{"crypto_stream_NONCEBYTES", 0, enif_crypto_stream_NONCEBYTES},
{"crypto_stream_b", 3, enif_crypto_stream},
{"crypto_stream", 3, enif_crypto_stream, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_stream", 3, enif_crypto_stream),
{"crypto_stream_xor_b", 3, enif_crypto_stream_xor},
{"crypto_stream_xor", 3, enif_crypto_stream_xor, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_stream_xor", 3, enif_crypto_stream_xor),
{"crypto_auth_BYTES", 0, enif_crypto_auth_BYTES},
{"crypto_auth_KEYBYTES", 0, enif_crypto_auth_KEYBYTES},
{"crypto_auth_b", 2, enif_crypto_auth},
{"crypto_auth", 2, enif_crypto_auth, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_auth", 2, enif_crypto_auth),
{"crypto_auth_verify_b", 3, enif_crypto_auth_verify},
{"crypto_auth_verify", 3, enif_crypto_auth_verify, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_auth_verify", 3, enif_crypto_auth_verify),
{"crypto_shorthash_BYTES", 0, enif_crypto_auth_BYTES},
{"crypto_shorthash_BYTES", 0, enif_crypto_shorthash_BYTES},
{"crypto_shorthash_KEYBYTES", 0, enif_crypto_shorthash_KEYBYTES},
{"crypto_shorthash", 2, enif_crypto_shorthash},
{"crypto_onetimeauth_BYTES", 0, enif_crypto_onetimeauth_BYTES},
{"crypto_onetimeauth_KEYBYTES", 0, enif_crypto_onetimeauth_KEYBYTES},
{"crypto_onetimeauth_b", 2, enif_crypto_onetimeauth},
{"crypto_onetimeauth", 2, enif_crypto_onetimeauth, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_onetimeauth", 2, enif_crypto_onetimeauth),
{"crypto_onetimeauth_verify_b", 3, enif_crypto_onetimeauth_verify},
{"crypto_onetimeauth_verify", 3, enif_crypto_onetimeauth_verify, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_onetimeauth_verify", 3, enif_crypto_onetimeauth_verify),
{"crypto_hash_b", 1, enif_crypto_hash},
{"crypto_hash", 1, enif_crypto_hash, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_hash", 1, enif_crypto_hash),
{"crypto_verify_16", 2, enif_crypto_verify_16},
{"crypto_verify_32", 2, enif_crypto_verify_32},
{"sodium_memzero", 1, enif_sodium_memzero},
{"crypto_curve25519_scalarmult", 2, enif_crypto_curve25519_scalarmult, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"crypto_pwhash", 2, enif_crypto_pwhash},
{"crypto_pwhash_str", 1, enif_crypto_pwhash_str},
{"crypto_pwhash_str_verify", 2, enif_crypto_pwhash_str_verify},
{"crypto_sign_ed25519_keypair", 0, enif_crypto_sign_ed25519_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_curve25519_scalarmult", 2, enif_crypto_curve25519_scalarmult),
erl_nif_dirty_job_cpu_bound_macro("crypto_sign_ed25519_keypair", 0, enif_crypto_sign_ed25519_keypair),
{"crypto_sign_ed25519_public_to_curve25519", 1, enif_crypto_sign_ed25519_public_to_curve25519},
{"crypto_sign_ed25519_secret_to_curve25519", 1, enif_crypto_sign_ed25519_secret_to_curve25519},
{"crypto_sign_ed25519_PUBLICKEYBYTES", 0, enif_crypto_sign_ed25519_PUBLICKEYBYTES},
{"crypto_sign_ed25519_SECRETKEYBYTES", 0, enif_crypto_sign_ed25519_SECRETKEYBYTES},
{"randombytes", 1, enif_randombytes, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("randombytes", 1, enif_randombytes),
{"crypto_kx_keypair", 0, enif_crypto_kx_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"crypto_kx_client_session_keys", 3, enif_crypto_kx_client_session_keys, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"crypto_kx_server_session_keys", 3, enif_crypto_kx_server_session_keys, ERL_NIF_DIRTY_JOB_CPU_BOUND},
erl_nif_dirty_job_cpu_bound_macro("crypto_kx_keypair", 0, enif_crypto_kx_keypair),
erl_nif_dirty_job_cpu_bound_macro("crypto_kx_client_session_keys", 3, enif_crypto_kx_client_session_keys),
erl_nif_dirty_job_cpu_bound_macro("crypto_kx_server_session_keys", 3, enif_crypto_kx_server_session_keys),
{"crypto_kx_PUBLICKEYBYTES", 0, enif_crypto_kx_PUBLICKEYBYTES},
{"crypto_kx_SECRETKEYBYTES", 0, enif_crypto_kx_SECRETKEYBYTES},
{"crypto_kx_SESSIONKEYBYTES", 0, enif_crypto_kx_SESSIONKEYBYTES},
{"scramble_block_16", 2, enif_scramble_block_16}
{"scramble_block_16", 2, enif_scramble_block_16},
{"crypto_generichash_BYTES", 0, enif_crypto_generichash_BYTES},
{"crypto_generichash_BYTES_MIN", 0, enif_crypto_generichash_BYTES_MIN},
{"crypto_generichash_BYTES_MAX", 0, enif_crypto_generichash_BYTES_MAX},
{"crypto_generichash_KEYBYTES", 0, enif_crypto_generichash_KEYBYTES},
{"crypto_generichash_KEYBYTES_MIN", 0, enif_crypto_generichash_KEYBYTES_MIN},
{"crypto_generichash_KEYBYTES_MAX", 0, enif_crypto_generichash_KEYBYTES_MAX},
{"crypto_generichash", 3, enif_crypto_generichash},
{"crypto_generichash_init", 2, enif_crypto_generichash_init},
{"crypto_generichash_update", 3, enif_crypto_generichash_update},
{"crypto_generichash_final", 2, enif_crypto_generichash_final}
};
ERL_NIF_INIT(enacl_nif, nif_funcs, enif_crypto_load, NULL, NULL, NULL);

View File

@ -2,7 +2,21 @@
-include_lib("eqc/include/eqc.hrl").
-compile(export_all).
-ifndef(mini).
-compile({parse_transform, eqc_parallelize}).
-define(FAULT(Arg1, Arg2), fault(Arg1, Arg2)).
-define(FAULT_RATE(Arg1, Arg2, Arg3), fault_rate(Arg1, Arg2, Arg3)).
-else.
-define(FAULT(Arg1, Arg2), noop_fault(Arg1, Arg2)).
-define(FAULT_RATE(Arg1, Arg2, Arg3), noop_fault_rate(Arg1, Arg2, Arg3)).
-endif.
start()->
eqc:module(?MODULE).
noop_fault(_Bad, Good) -> Good.
noop_fault_rate(_1, _2, Gen) -> Gen.
non_byte_int() ->
oneof([
@ -14,7 +28,7 @@ g_iolist() ->
?SIZED(Sz, g_iolist(Sz)).
g_iolist(0) ->
fault(
?FAULT(
oneof([
elements([a,b,c]),
real(),
@ -22,7 +36,7 @@ g_iolist(0) ->
]),
return([]));
g_iolist(N) ->
fault(
?FAULT(
oneof([
elements([a,b,c]),
real(),
@ -34,7 +48,7 @@ g_iolist(N) ->
])).
g_iodata() ->
fault(
?FAULT(
oneof([elements([a,b,c]), real()]),
oneof([binary(), g_iolist(), eqc_gen:largebinary(64*1024)])).
@ -50,7 +64,7 @@ v_iodata(Structure) -> v_iolist(Structure).
%% Generator for binaries of a given size with different properties and fault injection:
g_binary(Sz) ->
fault(g_binary_bad(Sz), g_binary_good(Sz)).
?FAULT(g_binary_bad(Sz), g_binary_good(Sz)).
g_binary_good(Sz) when Sz =< 32 -> binary(Sz);
g_binary_good(Sz) -> eqc_gen:largebinary(Sz).
@ -74,7 +88,7 @@ nonce_valid(N) -> v_binary(enacl:box_nonce_size(), N).
%% Generator of natural numbers
g_nat() ->
fault(g_nat_bad(), nat()).
?FAULT(g_nat_bad(), nat()).
g_nat_bad() ->
oneof([
@ -106,7 +120,7 @@ keypair_bad() ->
end).
keypair() ->
fault(keypair_bad(), keypair_good()).
?FAULT(keypair_bad(), keypair_good()).
%% CRYPTO BOX
%% ---------------------------
@ -158,10 +172,10 @@ failure(X) -> {failure, X}.
prop_box_correct() ->
?FORALL({Msg, Nonce, {PK1, SK1}, {PK2, SK2}},
{fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, nonce()),
fault_rate(1, 40, keypair()),
fault_rate(1, 40, keypair())},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, nonce()),
?FAULT_RATE(1, 40, keypair()),
?FAULT_RATE(1, 40, keypair())},
begin
case v_iodata(Msg) andalso nonce_valid(Nonce) andalso keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of
true ->
@ -182,10 +196,10 @@ prop_box_correct() ->
prop_box_failure_integrity() ->
?FORALL({Msg, Nonce, {PK1, SK1}, {PK2, SK2}},
{fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, nonce()),
fault_rate(1, 40, keypair()),
fault_rate(1, 40, keypair())},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, nonce()),
?FAULT_RATE(1, 40, keypair()),
?FAULT_RATE(1, 40, keypair())},
begin
case v_iodata(Msg)
andalso nonce_valid(Nonce)
@ -207,7 +221,7 @@ prop_box_failure_integrity() ->
end).
prop_seal_box_failure_integrity() ->
?FORALL({Msg, {PK1, SK1}}, {fault_rate(1,40,g_iodata()), fault_rate(1,40,keypair())},
?FORALL({Msg, {PK1, SK1}}, {?FAULT_RATE(1,40,g_iodata()), ?FAULT_RATE(1,40,keypair())},
begin
case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of
true ->
@ -225,8 +239,8 @@ prop_seal_box_failure_integrity() ->
prop_seal_box_correct() ->
?FORALL({Msg, {PK1, SK1}},
{fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, keypair())},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, keypair())},
begin
case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of
true ->
@ -243,7 +257,7 @@ prop_seal_box_correct() ->
%% PRECOMPUTATIONS
beforenm_key() ->
?LET([{PK1, SK1}, {PK2, SK2}], [fault_rate(1, 40, keypair()), fault_rate(1, 40, keypair())],
?LET([{PK1, SK1}, {PK2, SK2}], [?FAULT_RATE(1, 40, keypair()), ?FAULT_RATE(1, 40, keypair())],
case keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of
true ->
enacl:box_beforenm(PK1, SK2);
@ -259,7 +273,7 @@ v_key(K) when is_binary(K) -> byte_size(K) == enacl:box_beforenm_bytes();
v_key(_) -> false.
prop_beforenm_correct() ->
?FORALL([{PK1, SK1}, {PK2, SK2}], [fault_rate(1, 40, keypair()), fault_rate(1, 40, keypair())],
?FORALL([{PK1, SK1}, {PK2, SK2}], [?FAULT_RATE(1, 40, keypair()), ?FAULT_RATE(1, 40, keypair())],
case keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of
true ->
equals(enacl:box_beforenm(PK1, SK2), enacl:box_beforenm(PK2, SK1));
@ -272,9 +286,9 @@ prop_beforenm_correct() ->
prop_afternm_correct() ->
?FORALL([Msg, Nonce, Key],
[fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, nonce()),
fault_rate(1, 40, beforenm_key())],
[?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, nonce()),
?FAULT_RATE(1, 40, beforenm_key())],
begin
case v_iodata(Msg) andalso nonce_valid(Nonce) andalso v_key(Key) of
true ->
@ -325,7 +339,7 @@ sign_keypair_good() ->
return(enacl:sign_keypair()).
sign_keypair() ->
fault(sign_keypair_bad(), sign_keypair_good()).
?FAULT(sign_keypair_bad(), sign_keypair_good()).
sign_keypair_public_valid(#{ public := Public })
when is_binary(Public) ->
@ -342,8 +356,8 @@ sign_keypair_valid(KP) ->
prop_sign_detached() ->
?FORALL({Msg, KeyPair},
{fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, sign_keypair())},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, sign_keypair())},
begin
case v_iodata(Msg) andalso sign_keypair_secret_valid(KeyPair) of
true ->
@ -358,8 +372,8 @@ prop_sign_detached() ->
prop_sign() ->
?FORALL({Msg, KeyPair},
{fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, sign_keypair())},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, sign_keypair())},
begin
case v_iodata(Msg) andalso sign_keypair_secret_valid(KeyPair) of
true ->
@ -403,10 +417,10 @@ signed_message_bad_d() ->
{binary(), oneof([a, int(), ?SUCHTHAT(B, binary(Sz), byte_size(B) /= Sz)])}.
signed_message(M) ->
fault(signed_message_bad(), signed_message_good(M)).
?FAULT(signed_message_bad(), signed_message_good(M)).
signed_message_d(M) ->
fault(signed_message_bad(), signed_message_good(M)).
?FAULT(signed_message_bad(), signed_message_good(M)).
signed_message_valid({valid, _}, _) -> true;
signed_message_valid({invalid, _}, _) -> true;
@ -451,18 +465,18 @@ prop_sign_open() ->
key_sz(Sz) ->
equals(enacl:secretbox_key_size(), Sz).
prop_key_sizes() ->
conjunction([{secret, key_sz(enacl:secretbox_key_size())},
{stream, key_sz(enacl:stream_key_size())},
{auth, key_sz(enacl:auth_key_size())},
{onetimeauth, key_sz(enacl:onetime_auth_key_size())}]).
%% prop_key_sizes() ->
%% conjunction([{secret, key_sz(enacl:secretbox_key_size())},
%% {stream, key_sz(enacl:stream_key_size())},
%% {auth, key_sz(enacl:auth_key_size())},
%% {onetimeauth, key_sz(enacl:onetime_auth_key_size())}]).
nonce_sz(Sz) ->
equals(enacl:secretbox_nonce_size(), Sz).
prop_nonce_sizes() ->
conjunction([{secret, nonce_sz(enacl:secretbox_nonce_size())},
{stream, nonce_sz(enacl:stream_nonce_size())}]).
%% prop_nonce_sizes() ->
%% conjunction([{secret, nonce_sz(enacl:secretbox_nonce_size())},
%% {stream, nonce_sz(enacl:stream_nonce_size())}]).
secret_key_good() ->
Sz = enacl:secretbox_key_size(),
@ -474,7 +488,7 @@ secret_key_bad() ->
?SUCHTHAT(B, binary(), byte_size(B) /= enacl:secretbox_key_size())]).
secret_key() ->
fault(secret_key_bad(), secret_key_good()).
?FAULT(secret_key_bad(), secret_key_good()).
secret_key_valid(SK) when is_binary(SK) ->
Sz = enacl:secretbox_key_size(),
@ -497,9 +511,9 @@ secretbox_open(Msg, Nonce, Key) ->
prop_secretbox_correct() ->
?FORALL({Msg, Nonce, Key},
{fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, nonce()),
fault_rate(1, 40, secret_key())},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, nonce()),
?FAULT_RATE(1, 40, secret_key())},
begin
case v_iodata(Msg) andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of
true ->
@ -527,8 +541,8 @@ prop_secretbox_failure_integrity() ->
prop_stream_correct() ->
?FORALL({Len, Nonce, Key},
{int(),
fault_rate(1, 40, nonce()),
fault_rate(1, 40, secret_key())},
?FAULT_RATE(1, 40, nonce()),
?FAULT_RATE(1, 40, secret_key())},
case Len >= 0 andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of
true ->
CipherStream = enacl:stream(Len, Nonce, Key),
@ -541,29 +555,29 @@ xor_bytes(<<A, As/binary>>, <<B, Bs/binary>>) ->
[A bxor B | xor_bytes(As, Bs)];
xor_bytes(<<>>, <<>>) -> [].
prop_stream_xor_correct() ->
?FORALL({Msg, Nonce, Key},
{fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, nonce()),
fault_rate(1, 40, secret_key())},
case v_iodata(Msg) andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of
true ->
Stream = enacl:stream(iolist_size(Msg), Nonce, Key),
CipherText = enacl:stream_xor(Msg, Nonce, Key),
StreamXor = enacl:stream_xor(CipherText, Nonce, Key),
conjunction([
{'xor', equals(iolist_to_binary(Msg), StreamXor)},
{stream, equals(iolist_to_binary(xor_bytes(Stream, iolist_to_binary(Msg))), CipherText)}
]);
false ->
badargs(fun() -> enacl:stream_xor(Msg, Nonce, Key) end)
end).
%% prop_stream_xor_correct() ->
%% ?FORALL({Msg, Nonce, Key},
%% {?FAULT_RATE(1, 40, g_iodata()),
%% ?FAULT_RATE(1, 40, nonce()),
%% ?FAULT_RATE(1, 40, secret_key())},
%% case v_iodata(Msg) andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of
%% true ->
%% Stream = enacl:stream(iolist_size(Msg), Nonce, Key),
%% CipherText = enacl:stream_xor(Msg, Nonce, Key),
%% StreamXor = enacl:stream_xor(CipherText, Nonce, Key),
%% conjunction([
%% {'xor', equals(iolist_to_binary(Msg), StreamXor)},
%% {stream, equals(iolist_to_binary(xor_bytes(Stream, iolist_to_binary(Msg))), CipherText)}
%% ]);
%% false ->
%% badargs(fun() -> enacl:stream_xor(Msg, Nonce, Key) end)
%% end).
%% CRYPTO AUTH
prop_auth_correct() ->
?FORALL({Msg, Key},
{fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, secret_key())},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, secret_key())},
case v_iodata(Msg) andalso secret_key_valid(Key) of
true ->
Authenticator = enacl:auth(Msg, Key),
@ -588,7 +602,7 @@ authenticator_good(_Msg, _Key) ->
binary(enacl:auth_size()).
authenticator(Msg, Key) ->
fault(authenticator_bad(), authenticator_good(Msg, Key)).
?FAULT(authenticator_bad(), authenticator_good(Msg, Key)).
authenticator_valid({valid, _}) -> true;
authenticator_valid({invalid, _}) -> true;
@ -596,8 +610,8 @@ authenticator_valid(_) -> false.
prop_auth_verify_correct() ->
?FORALL({Msg, Key},
{fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, secret_key())},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, secret_key())},
?FORALL(Authenticator, authenticator(Msg, Key),
case v_iodata(Msg) andalso secret_key_valid(Key) andalso authenticator_valid(Authenticator) of
true ->
@ -614,8 +628,8 @@ prop_auth_verify_correct() ->
%% CRYPTO ONETIME AUTH
prop_onetimeauth_correct() ->
?FORALL({Msg, Key},
{fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, secret_key())},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, secret_key())},
case v_iodata(Msg) andalso secret_key_valid(Key) of
true ->
Authenticator = enacl:onetime_auth(Msg, Key),
@ -640,7 +654,7 @@ ot_authenticator_good(_Msg, _Key) ->
binary(enacl:auth_size()).
ot_authenticator(Msg, Key) ->
fault(ot_authenticator_bad(), ot_authenticator_good(Msg, Key)).
?FAULT(ot_authenticator_bad(), ot_authenticator_good(Msg, Key)).
ot_authenticator_valid({valid, _}) -> true;
ot_authenticator_valid({invalid, _}) -> true;
@ -648,8 +662,8 @@ ot_authenticator_valid(_) -> false.
prop_onetime_auth_verify_correct() ->
?FORALL({Msg, Key},
{fault_rate(1, 40, g_iodata()),
fault_rate(1, 40, secret_key())},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, secret_key())},
?FORALL(Authenticator, ot_authenticator(Msg, Key),
case v_iodata(Msg) andalso secret_key_valid(Key) andalso ot_authenticator_valid(Authenticator) of
true ->
@ -706,7 +720,7 @@ verify_pair_good(Sz) ->
?SUCHTHAT({X, Y}, {binary(Sz), binary(Sz)}, X /= Y)]).
verify_pair(Sz) ->
fault(verify_pair_bad(Sz), verify_pair_good(Sz)).
?FAULT(verify_pair_bad(Sz), verify_pair_good(Sz)).
verify_pair_valid(Sz, X, Y) ->
byte_size(X) == Sz andalso byte_size(Y) == Sz.

View File

@ -106,6 +106,23 @@
kx_session_key_size/0
]).
%% Password Hashing - Argon2 Algorithm
-export([
pwhash/2,
pwhash_str/1,
pwhash_str_verify/2
]).
%% Generic hash functions
-export([
generichash/3,
generichash/2,
generichash_init/2,
generichash_update/2,
generichash_final/1
]).
%% Libsodium specific functions (which are also part of the "undocumented" interface to NaCl
-export([
randombytes/1
@ -153,6 +170,13 @@
-define(CRYPTO_KX_SECRETKEYBYTES, 32).
-define(CRYPTO_KX_SESSIONKEYBYTES, 32).
-define(CRYPTO_GENERICHASH_BYTES_MIN, 16).
-define(CRYPTO_GENERICHASH_BYTES_MAX, 64).
-define(CRYPTO_GENERICHASH_BYTES, 32).
-define(CRYPTO_GENERICHASH_KEYBYTES_MIN, 16).
-define(CRYPTO_GENERICHASH_KEYBYTES_MAX, 64).
-define(CRYPTO_GENERICHASH_KEYBYTES, 32).
%% @doc Verify makes sure the constants defined in libsodium matches ours
verify() ->
true = equals(binary:copy(<<0>>, enacl_nif:crypto_box_ZEROBYTES()), ?P_ZEROBYTES),
@ -173,7 +197,13 @@ verify() ->
{crypto_secretbox_BOXZEROBYTES, ?CRYPTO_SECRETBOX_BOXZEROBYTES},
{crypto_kx_SESSIONKEYBYTES, ?CRYPTO_KX_SESSIONKEYBYTES},
{crypto_kx_PUBLICKEYBYTES, ?CRYPTO_KX_PUBLICKEYBYTES},
{crypto_kx_SECRETKEYBYTES, ?CRYPTO_KX_SECRETKEYBYTES}
{crypto_kx_SECRETKEYBYTES, ?CRYPTO_KX_SECRETKEYBYTES},
{crypto_generichash_BYTES, ?CRYPTO_GENERICHASH_BYTES},
{crypto_generichash_BYTES_MIN, ?CRYPTO_GENERICHASH_BYTES_MIN},
{crypto_generichash_BYTES_MAX, ?CRYPTO_GENERICHASH_BYTES_MAX},
{crypto_generichash_KEYBYTES, ?CRYPTO_GENERICHASH_KEYBYTES},
{crypto_generichash_KEYBYTES_MIN, ?CRYPTO_GENERICHASH_KEYBYTES_MIN},
{crypto_generichash_KEYBYTES_MAX, ?CRYPTO_GENERICHASH_KEYBYTES_MAX}
],
run_verifiers(Verifiers).
@ -249,6 +279,59 @@ unsafe_memzero(X) when is_binary(X) ->
unsafe_memzero(_) ->
error(badarg).
%% @doc generichash/3 creates a hash of the message using a key.
%%
%% This function generates a hash of the message using a key. The hash size is
%% either 16, 32 or 64 bytes
%% @end
-spec generichash(iodata(), binary()) -> {ok, binary()} | {error, term()}.
generichash(HashSize, Message, Key) ->
enacl_nif:crypto_generichash(HashSize, Message, Key).
%% @doc generichash/2 creates a hash of the message.
%%
%% This function generates a hash of the message. The hash size is
%% either 16, 32 or 64 bytes
%% @end
generichash(HashSize, Message) ->
enacl_nif:crypto_generichash(HashSize, Message, <<>>).
generichash_init(HashSize, Key) ->
enacl_nif:crypto_generichash_init(HashSize, Key).
generichash_update({hashstate, HashSize, HashState}, Message) ->
enacl_nif:crypto_generichash_update(HashSize, HashState, Message).
generichash_final({hashstate, HashSize, HashState}) ->
enacl_nif:crypto_generichash_final(HashSize, HashState).
%% @doc pwhash/2 hash a password
%%
%% This function generates a fixed size salted hash of a user defined password.
%% @end
-spec pwhash(iodata(), binary()) -> {ok, binary()} | {error, term()}.
pwhash(Password, Salt) ->
enacl_nif:crypto_pwhash(Password, Salt).
%% @doc pwhash_str_verify/2 generates a ASCII encoded hash of a password
%%
%% This function generates a fixed size, salted, ASCII encoded hash of a user defined password.
%% @end
-spec pwhash_str(iodata()) -> {ok, iodata()} | {error, term()}.
pwhash_str(Password) ->
enacl_nif:crypto_pwhash_str(Password).
%% @doc pwhash_str_verify/2 compares a password with a hash
%%
%% This function verifies that the hash is generated from the password. The
%% function returns true if the verifcate succeeds, false otherwise
%% @end
-spec pwhash_str_verify(binary(), iodata()) -> boolean().
pwhash_str_verify(HashPassword, Password) ->
enacl_nif:crypto_pwhash_str_verify(HashPassword, Password).
%% Public Key Crypto
%% ---------------------
%% @doc box_keypair/0 creates a new Public/Secret keypair.
@ -913,6 +996,8 @@ kx_public_key_size() ->
kx_secret_key_size() ->
enacl_nif:crypto_kx_SECRETKEYBYTES().
%% Obtaining random bytes
%% @doc randombytes/1 produces a stream of random bytes of the given size

View File

@ -122,6 +122,28 @@
sodium_memzero/1
]).
%% Password Hashing - Argon2 Algorithm
-export([
crypto_pwhash/2,
crypto_pwhash_str/1,
crypto_pwhash_str_verify/2
]).
%% Generic hash
-export([
crypto_generichash_BYTES/0,
crypto_generichash_BYTES_MIN/0,
crypto_generichash_BYTES_MAX/0,
crypto_generichash_KEYBYTES/0,
crypto_generichash_KEYBYTES_MIN/0,
crypto_generichash_KEYBYTES_MAX/0,
crypto_generichash/3,
crypto_generichash_init/2,
crypto_generichash_update/3,
crypto_generichash_final/2
]).
%% Access to the RNG
-export([
randombytes/1
@ -146,6 +168,25 @@ init() ->
SoName = filename:join(Dir, atom_to_list(?MODULE)),
erlang:load_nif(SoName, 0).
crypto_generichash_BYTES() -> erlang:nif_error(nif_not_loaded).
crypto_generichash_BYTES_MIN() -> erlang:nif_error(nif_not_loaded).
crypto_generichash_BYTES_MAX() -> erlang:nif_error(nif_not_loaded).
crypto_generichash_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
crypto_generichash_KEYBYTES_MIN() -> erlang:nif_error(nif_not_loaded).
crypto_generichash_KEYBYTES_MAX() -> erlang:nif_error(nif_not_loaded).
crypto_generichash(_HashSize, _Message, _Key) -> erlang:nif_error(nif_not_loaded).
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_str(_Password) -> erlang:nif_error(nif_not_loaded).
crypto_pwhash_str_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded).
crypto_box_NONCEBYTES() -> erlang:nif_error(nif_not_loaded).
crypto_box_ZEROBYTES() -> erlang:nif_error(nif_not_loaded).
crypto_box_BOXZEROBYTES() -> erlang:nif_error(nif_not_loaded).