Start splitting the library into its parts

This commit is contained in:
Jesper Louis Andersen 2020-01-17 15:46:38 +01:00
parent a25b9a2684
commit d5bb24e671
8 changed files with 393 additions and 263 deletions

3
.gitignore vendored
View File

@ -15,4 +15,5 @@ _build
priv/enacl_nif.dll
priv/enacl_nif.exp
priv/enacl_nif.lib
c_src/enacl_nif.d
c_src/*.d

7
c_src/enacl.c Normal file
View File

@ -0,0 +1,7 @@
#include "enacl.h"
#include "erl_nif.h"
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
c_src/enacl.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef ENACL_H
#define ENACL_H
#include "erl_nif.h"
#define ATOM_OK "ok"
#define ATOM_ERROR "error"
#define ATOM_TRUE "true"
#define ATOM_FALSE "false"
ERL_NIF_TERM nacl_error_tuple(ErlNifEnv *, char *);
#endif

View File

@ -1,15 +1,11 @@
#include "erl_nif.h"
#include <sodium.h>
#include <string.h>
#include <sodium.h>
#include "enacl.h"
#include "generichash.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"
#define CRYPTO_SIGN_STATE_RESOURCE "crypto_sign_state"
#ifdef ERL_NIF_DIRTY_JOB_CPU_BOUND
@ -25,21 +21,13 @@
/* Errors */
/* These are global variables for resource types */
static ErlNifResourceType *generichash_state_type = NULL;
static ErlNifResourceType *sign_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));
}
/* Initialization */
static int enif_crypto_load(ErlNifEnv *env, void **priv_data,
ERL_NIF_TERM load_info) {
// 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))) {
if (!enacl_init_generic_hash_ctx(env)) {
return -1;
}
// Create a new resource type for crypto_sign_state
@ -52,25 +40,6 @@ static int enif_crypto_load(ErlNifEnv *env, void **priv_data,
return sodium_init();
}
/* Low-level functions (Hashing, String Equality, ...) */
static ERL_NIF_TERM enif_crypto_hash(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ErlNifBinary input;
ErlNifBinary result;
if ((argc != 1) || (!enif_inspect_iolist_as_binary(env, argv[0], &input))) {
return enif_make_badarg(env);
}
if (!enif_alloc_binary(crypto_hash_BYTES, &result)) {
return nacl_error_tuple(env, "alloc_failed");
}
crypto_hash(result.data, input.data, input.size);
return enif_make_binary(env, &result);
}
static ERL_NIF_TERM enif_crypto_verify_16(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ErlNifBinary x, y;
@ -1764,227 +1733,6 @@ enif_crypto_aead_xchacha20poly1305_decrypt(ErlNifEnv *env, int argc,
return enif_make_binary(env, &message);
}
/*
* 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 crypto_generichash_state *align64(void *ptr) {
if ((unsigned long)ptr % 64 == 0)
return ptr;
return (unsigned long)ptr + (64 - ((unsigned long)ptr % 64));
}
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 (+ 60 to make room for 64-byte alignment)
void *state = enif_alloc_resource(generichash_state_type,
crypto_generichash_statebytes() + 60);
if (!state) {
return nacl_error_tuple(env, "alloc_failed");
}
// Call the library function
if (0 != crypto_generichash_init(align64(state), k, key.size, hashSize)) {
enif_release_resource(state);
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;
void *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(align64(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;
void *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(align64(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},
@ -2091,8 +1839,8 @@ static ErlNifFunc nif_funcs[] = {
erl_nif_dirty_job_cpu_bound_macro("crypto_onetimeauth_verify", 3,
enif_crypto_onetimeauth_verify),
{"crypto_hash_b", 1, enif_crypto_hash},
erl_nif_dirty_job_cpu_bound_macro("crypto_hash", 1, enif_crypto_hash),
{"crypto_hash_b", 1, enacl_crypto_hash},
erl_nif_dirty_job_cpu_bound_macro("crypto_hash", 1, enacl_crypto_hash),
{"crypto_verify_16", 2, enif_crypto_verify_16},
{"crypto_verify_32", 2, enif_crypto_verify_32},
{"sodium_memzero", 1, enif_sodium_memzero},
@ -2178,10 +1926,10 @@ static ErlNifFunc nif_funcs[] = {
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}
{"crypto_generichash", 3, enacl_crypto_generichash},
{"crypto_generichash_init", 2, enacl_crypto_generichash_init},
{"crypto_generichash_update", 3, enacl_crypto_generichash_update},
{"crypto_generichash_final", 2, enacl_crypto_generichash_final}
};

295
c_src/generichash.c Normal file
View File

@ -0,0 +1,295 @@
#include "erl_nif.h"
#include <sodium.h>
#include "enacl.h"
#include "generichash.h"
typedef struct enacl_generichash_ctx {
// The hash state
crypto_generichash_state *ctx;
// Is the context alive?
int alive;
} enacl_generichash_ctx;
static ErlNifResourceType *enacl_generic_hash_ctx_rtype;
static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env,
enacl_generichash_ctx *);
int enacl_init_generic_hash_ctx(ErlNifEnv *env) {
enacl_generic_hash_ctx_rtype =
enif_open_resource_type(env, NULL, "enacl_generichash_context",
(ErlNifResourceDtor *)enacl_generic_hash_ctx_dtor,
ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL);
if (enacl_generic_hash_ctx_rtype == NULL)
goto err;
return 1;
err:
return 0;
}
static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env,
enacl_generichash_ctx *obj) {
if (!obj->alive) {
return;
}
sodium_free(obj->ctx);
return;
}
/*
* Generic hash
*/
ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_generichash_BYTES);
}
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);
}
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);
}
ERL_NIF_TERM enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_generichash_KEYBYTES);
}
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);
}
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);
}
ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ErlNifBinary hash, message, key;
unsigned hashSize;
ERL_NIF_TERM ret;
// 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)))
goto bad_arg;
// 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)) {
ret = nacl_error_tuple(env, "invalid_hash_size");
goto done;
}
// 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) {
ret = nacl_error_tuple(env, "invalid_key_size");
goto done;
}
// allocate memory for hash
if (!enif_alloc_binary(hashSize, &hash)) {
ret = nacl_error_tuple(env, "alloc_failed");
goto done;
}
// calculate hash
if (0 != crypto_generichash(hash.data, hash.size, message.data, message.size,
k, key.size)) {
ret = nacl_error_tuple(env, "hash_error");
goto release;
}
ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK);
ERL_NIF_TERM ret_hash = enif_make_binary(env, &hash);
ret = enif_make_tuple2(env, ok, ret_hash);
goto done;
bad_arg:
return enif_make_badarg(env);
release:
enif_release_binary(&hash);
done:
return ret;
}
ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ErlNifBinary key;
unsigned hash_size;
enacl_generichash_ctx *obj = NULL;
ERL_NIF_TERM ret;
// Validate the arguments
if ((argc != 2) || (!enif_get_uint(env, argv[0], &hash_size)) ||
(!enif_inspect_binary(env, argv[1], &key))) {
goto bad_arg;
}
// Verify that hash size is
// crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
if ((hash_size <= crypto_generichash_BYTES_MIN) ||
(hash_size >= crypto_generichash_BYTES_MAX)) {
ret = nacl_error_tuple(env, "invalid_hash_size");
goto done;
}
// 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) {
ret = nacl_error_tuple(env, "invalid_key_size");
goto done;
}
// Create the resource
if ((obj = enif_alloc_resource(enacl_generic_hash_ctx_rtype,
sizeof(enacl_generichash_ctx))) == NULL) {
goto err;
}
// Allocate the state context via libsodium
// Note that this ensures a 64byte alignment for the resource
// And also protects the resource via guardpages
obj->ctx = NULL;
obj->alive = 0;
obj->ctx = (crypto_generichash_state *)sodium_malloc(
crypto_generichash_statebytes());
if (obj->ctx == NULL) {
goto err;
}
obj->alive = 1;
// Call the library function
if (0 != crypto_generichash_init(obj->ctx, k, key.size, hash_size)) {
ret = nacl_error_tuple(env, "hash_init_error");
goto done;
}
// 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, obj);
ret = enif_make_tuple3(env, e1, e2, e3);
goto done;
bad_arg:
return enif_make_badarg(env);
err:
ret = nacl_error_tuple(env, "internal_error");
if (obj != NULL) {
if (obj->alive) {
sodium_free(obj->ctx);
}
}
done:
if (obj != NULL) {
enif_release_resource(obj);
}
return ret;
}
ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ERL_NIF_TERM ret;
ErlNifBinary data;
unsigned int data_size;
enacl_generichash_ctx *obj = NULL;
// Validate the arguments
if (argc != 3)
goto bad_arg;
if (!enif_get_uint(env, argv[0], &data_size))
goto bad_arg;
if (!enif_get_resource(env, argv[1],
(ErlNifResourceType *)enacl_generic_hash_ctx_rtype,
(void **)&obj))
goto bad_arg;
if (!enif_inspect_binary(env, argv[2], &data))
goto bad_arg;
// Update hash state
if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) {
ret = nacl_error_tuple(env, "hash_update_error");
goto done;
}
ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate");
ERL_NIF_TERM e2 = argv[0];
ERL_NIF_TERM e3 = argv[1];
ret = enif_make_tuple3(env, e1, e2, e3);
goto done;
bad_arg:
return enif_make_badarg(env);
done:
return ret;
}
ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ERL_NIF_TERM ret;
ErlNifBinary hash;
unsigned int hash_size;
enacl_generichash_ctx *obj = NULL;
if (argc != 2)
goto bad_arg;
if (!enif_get_uint(env, argv[0], &hash_size))
goto bad_arg;
if (!enif_get_resource(env, argv[1], enacl_generic_hash_ctx_rtype,
(void **)&obj))
goto bad_arg;
if ((hash_size <= crypto_generichash_BYTES_MIN) ||
(hash_size >= crypto_generichash_BYTES_MAX)) {
ret = nacl_error_tuple(env, "invalid_hash_size");
goto done;
}
if (!enif_alloc_binary(hash_size, &hash)) {
ret = nacl_error_tuple(env, "alloc_failed");
goto done;
}
if (0 != crypto_generichash_final(obj->ctx, hash.data, hash.size)) {
ret = nacl_error_tuple(env, "hash_error");
goto release;
}
ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK);
ERL_NIF_TERM h = enif_make_binary(env, &hash);
ret = enif_make_tuple2(env, ok, h);
goto done;
bad_arg:
return enif_make_badarg(env);
release:
enif_release_binary(&hash);
done:
return ret;
}

30
c_src/generichash.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef ENACL_GENERICHASH_H
#define ENACL_GENERICHASH_H
int enacl_init_generic_hash_ctx(ErlNifEnv *env);
ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);
ERL_NIF_TERM enif_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);
ERL_NIF_TERM enif_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);
ERL_NIF_TERM enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);
ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);
ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);
ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);
ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);
ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);
ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);
#endif

30
c_src/hash.c Normal file
View File

@ -0,0 +1,30 @@
#include "erl_nif.h"
#include <sodium.h>
#include "hash.h"
ERL_NIF_TERM enacl_crypto_hash_nif(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ErlNifBinary input;
ErlNifBinary result;
ERL_NIF_TERM ret;
if ((argc != 1) || (!enif_inspect_iolist_as_binary(env, argv[0], &input)))
goto bad_arg;
if (!enif_alloc_binary(crypto_hash_BYTES, &result))
goto err;
crypto_hash(result.data, input.data, input.size);
ret = enif_make_binary(env, &result);
goto done;
bad_arg:
return enif_make_badarg(env);
err:
ret = nacl_error_tuple(env, "alloc_failed");
done:
return ret;
}

6
c_src/hash.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef ENACL_HASH_H
#define ENACL_HASH_H
ERL_NIF_TERM enacl_crypto_hash(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);
#endif