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:
commit
5a48c66b07
17
Makefile
17
Makefile
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -4,17 +4,39 @@
|
||||
|
||||
#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));
|
||||
return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, 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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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).
|
||||
|
Loading…
x
Reference in New Issue
Block a user