initial commit
commit
2982515f2e
|
@ -0,0 +1,4 @@
|
|||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
|
@ -0,0 +1,28 @@
|
|||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
saltywitch-*.tar
|
||||
|
||||
# Temporary files, for example, from tests.
|
||||
/tmp/
|
||||
|
||||
*.o
|
|
@ -0,0 +1,47 @@
|
|||
cmake_minimum_required(VERSION 3.26)
|
||||
|
||||
project(saltywitch)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set(CMAKE_LINK_WHAT_YOU_USE ON)
|
||||
|
||||
if(CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
|
||||
set(CMAKE_C_FLAGS "-O3 -shared ${CMAKE_C_FLAGS}")
|
||||
endif()
|
||||
|
||||
check_ipo_supported(RESULT has_ipo OUTPUT error)
|
||||
if(has_ipo)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
|
||||
endif()
|
||||
|
||||
set(SALTYWITCH_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/c_src/saltywitch.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/c_src/atoms.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/c_src/auth.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/c_src/generichash.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/c_src/pwhash.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/c_src/saltywitch.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/c_src/saltywitch.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/c_src/secretbox.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/c_src/shorthash.c
|
||||
)
|
||||
|
||||
set(INCLUDE_DIRS
|
||||
${ERTS_INCLUDE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/c_src
|
||||
)
|
||||
|
||||
find_package(libsodium REQUIRED)
|
||||
|
||||
add_library(saltywitch SHARED ${SALTYWITCH_SOURCES})
|
||||
|
||||
target_compile_definitions(saltywitch PUBLIC "$<$<CONFIG:RELEASE>:NDEBUG>")
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(saltywitch PRIVATE libsodium)
|
|
@ -0,0 +1,7 @@
|
|||
.POSIX:
|
||||
|
||||
build:
|
||||
busybox sh ./build.sh
|
||||
|
||||
clean:
|
||||
sh ./clean.sh
|
|
@ -0,0 +1,41 @@
|
|||
# SaltyWitch
|
||||
|
||||
Another NIF library for libsodium.
|
||||
|
||||
## Roadmap
|
||||
|
||||
Easy cross-compiling the NIF.
|
||||
|
||||
## Building
|
||||
|
||||
On UNIX-like systems:
|
||||
- Shell (tested on bash and busybox ash)
|
||||
- Make
|
||||
- A GCC-like C99 compiler.
|
||||
- `meson` _(optional but **recommended**)_
|
||||
- `pkgconf` *(if directly building)*
|
||||
|
||||
`SALTYWITCH_BUILD_SYSTEM`: By default `direct` is used for UNIX systems.
|
||||
- **meson** _(recommended)_: Use meson to build the NIF.
|
||||
- **cmake**: Use CMake to build the NIF
|
||||
- **direct**: Build the NIF in a single compiler invocation like a lunatic.
|
||||
|
||||
`SALTYWITCH_MESON_ARGS`: extra arguments for meson
|
||||
- do not specify `--prefix`
|
||||
|
||||
## Installation
|
||||
|
||||
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
||||
by adding `saltywitch` to your list of dependencies in `mix.exs`:
|
||||
|
||||
```elixir
|
||||
def deps do
|
||||
[
|
||||
{:saltywitch, "~> 0.0.1"}
|
||||
]
|
||||
end
|
||||
```
|
||||
|
||||
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
||||
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
||||
be found at <https://hexdocs.pm/saltywitch>.
|
|
@ -0,0 +1,17 @@
|
|||
# C Style used
|
||||
|
||||
|
||||
- Macros are to be avoided.
|
||||
- Any macro defined must be defined before its used and `undef`'d after done.
|
||||
|
||||
Exception part must be as following at bare minimum:
|
||||
|
||||
|
||||
If there are more than 1 points of exception, they all must be deduplicated through `goto`'s.
|
||||
The variables `err` and `reason` must be used with the following initial values.
|
||||
|
||||
```c
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
```
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
if [ -z $SALTYWITCH_BUILD_SYSTEM ]; then
|
||||
printf "[build.sh] trying to detect better build systems... "
|
||||
|
||||
# if [ -x "$(command -v cmake)" ]; then
|
||||
# printf "cmake "
|
||||
# SALTYWITCH_BUILD_SYSTEM="cmake"
|
||||
# fi
|
||||
|
||||
if [ -x "$(command -v meson)" ]; then
|
||||
printf "meson "
|
||||
SALTYWITCH_BUILD_SYSTEM="meson"
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
fi
|
||||
|
||||
case ${SALTYWITCH_BUILD_SYSTEM:-direct} in
|
||||
meson)
|
||||
echo "[build.sh] using meson to build nif"
|
||||
if ! [ -d "./build-meson" ]; then
|
||||
meson setup build-meson \
|
||||
--prefix=$MIX_APP_PATH \
|
||||
-Dmix_target=$MIX_TARGET \
|
||||
-Derts_include_dir=$ERTS_INCLUDE_DIR \
|
||||
-Derl_interface_lib_dir=$ERL_INTERFACE_LIB_DIR \
|
||||
-Derl_interface_include_dir=$ERL_INTERFACE_INCLUDE_DIR \
|
||||
$SALTYWITCH_MESON_ARGS
|
||||
fi
|
||||
|
||||
meson compile -C build-meson
|
||||
meson install -C build-meson
|
||||
;;
|
||||
|
||||
# cmake)
|
||||
# echo "[build.sh] using cmake to build nif"
|
||||
# ;;
|
||||
|
||||
direct)
|
||||
echo "[build.sh] directly building the nif"
|
||||
${CC:-cc} c_src/*.c \
|
||||
-shared \
|
||||
${CFLAGS:--O3 -fPIC -fstack-protector -fvisibility=hidden} \
|
||||
$LDFLAGS \
|
||||
-I $ERTS_INCLUDE_DIR \
|
||||
-I $ERL_EI_INCLUDE_DIR \
|
||||
-I $ERL_INTERFACE_INCLUDE_DIR \
|
||||
-L $ERL_EI_LIBDIR \
|
||||
-lei \
|
||||
$(pkgconf --libs --cflags libsodium) \
|
||||
-o $MIX_APP_PATH/priv/saltywitch.so
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "[build.sh] invalid build backend"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,66 @@
|
|||
#include "saltywitch.h"
|
||||
|
||||
ERL_NIF_TERM atom_badarg;
|
||||
ERL_NIF_TERM atom_error;
|
||||
ERL_NIF_TERM atom_ok;
|
||||
|
||||
ERL_NIF_TERM atom_err_opaque;
|
||||
|
||||
ERL_NIF_TERM atom_err_invalid_type;
|
||||
ERL_NIF_TERM atom_err_nif_alloc;
|
||||
|
||||
ERL_NIF_TERM atom_err_invalid_key_size;
|
||||
ERL_NIF_TERM atom_err_invalid_nonce_size;
|
||||
ERL_NIF_TERM atom_err_invalid_salt_size;
|
||||
ERL_NIF_TERM atom_err_invalid_seed_size;
|
||||
ERL_NIF_TERM atom_err_invalid_tag_size;
|
||||
ERL_NIF_TERM atom_err_verification_failed;
|
||||
|
||||
ERL_NIF_TERM atom_err_ciphertext_too_small;
|
||||
ERL_NIF_TERM atom_err_key_too_large;
|
||||
ERL_NIF_TERM atom_err_key_too_small;
|
||||
ERL_NIF_TERM atom_err_output_too_large;
|
||||
ERL_NIF_TERM atom_err_output_too_small;
|
||||
|
||||
ERL_NIF_TERM atom_err_pwhash_too_long;
|
||||
ERL_NIF_TERM atom_err_pwhash_needs_rehash;
|
||||
ERL_NIF_TERM atom_err_pwhash_mem_too_large;
|
||||
ERL_NIF_TERM atom_err_pwhash_mem_too_small;
|
||||
ERL_NIF_TERM atom_err_pwhash_ops_too_large;
|
||||
ERL_NIF_TERM atom_err_pwhash_ops_too_small;
|
||||
|
||||
#define DEFERROR(name) atom_err_##name = enif_make_atom(env, #name)
|
||||
|
||||
void saltywitch_nif_init_atoms(ErlNifEnv *env)
|
||||
{
|
||||
atom_error = enif_make_atom(env, "error");
|
||||
atom_badarg = enif_make_atom(env, "badarg");
|
||||
atom_ok = enif_make_atom(env, "ok");
|
||||
|
||||
DEFERROR(opaque);
|
||||
|
||||
DEFERROR(invalid_type);
|
||||
DEFERROR(nif_alloc);
|
||||
|
||||
DEFERROR(invalid_key_size);
|
||||
DEFERROR(invalid_nonce_size);
|
||||
DEFERROR(invalid_salt_size);
|
||||
DEFERROR(invalid_seed_size);
|
||||
DEFERROR(invalid_tag_size);
|
||||
DEFERROR(verification_failed);
|
||||
|
||||
DEFERROR(ciphertext_too_small);
|
||||
DEFERROR(key_too_large);
|
||||
DEFERROR(key_too_small);
|
||||
DEFERROR(output_too_large);
|
||||
DEFERROR(output_too_small);
|
||||
|
||||
DEFERROR(pwhash_too_long);
|
||||
DEFERROR(pwhash_needs_rehash);
|
||||
DEFERROR(pwhash_mem_too_large);
|
||||
DEFERROR(pwhash_mem_too_small);
|
||||
DEFERROR(pwhash_ops_too_large);
|
||||
DEFERROR(pwhash_ops_too_small);
|
||||
}
|
||||
|
||||
#undef DEFERROR
|
|
@ -0,0 +1,102 @@
|
|||
#include "saltywitch.h"
|
||||
|
||||
/* auth */
|
||||
ERL_NIF_TERM saltywitch_auth_keygen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
unsigned char *key = enif_make_new_binary(env, crypto_auth_KEYBYTES, &term);
|
||||
if (key == NULL) {
|
||||
return saltywitch_exception(env, atom_error, atom_err_nif_alloc);
|
||||
}
|
||||
|
||||
crypto_auth_keygen(key);
|
||||
|
||||
return term;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_auth(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ErlNifBinary message, key;
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
unsigned char *mac;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
if (enif_inspect_binary(env, argv[0], &message) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[1], &key) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (key.size != crypto_auth_KEYBYTES) {
|
||||
reason = atom_err_invalid_key_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
mac = enif_make_new_binary(env, crypto_auth_BYTES, &term);
|
||||
if (mac == NULL) {
|
||||
reason = atom_err_nif_alloc;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
crypto_auth(mac, message.data, message.size, key.data);
|
||||
|
||||
return term;
|
||||
|
||||
error_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_auth_verify(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ErlNifBinary tag, message, key;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
if (enif_inspect_binary(env, argv[0], &tag) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (tag.size != crypto_auth_BYTES) {
|
||||
reason = atom_err_invalid_tag_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[1], &message) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[2], &key) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (key.size != crypto_auth_KEYBYTES) {
|
||||
reason = atom_err_invalid_key_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (crypto_auth_verify(tag.data, message.data, message.size, key.data) != 0) {
|
||||
reason = atom_err_verification_failed;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
return atom_ok;
|
||||
|
||||
error_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
|
@ -0,0 +1,262 @@
|
|||
#include "saltywitch.h"
|
||||
|
||||
struct saltywitch_generichash_context {
|
||||
uint64_t outlen;
|
||||
ErlNifMutex *mutex;
|
||||
crypto_generichash_state *state;
|
||||
};
|
||||
|
||||
static ErlNifResourceType *_generichash_context_rtype = NULL;
|
||||
|
||||
static void _generichash_dtor(ErlNifEnv *env, void *context)
|
||||
{
|
||||
struct saltywitch_generichash_context *ctx = context;
|
||||
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->state != NULL) {
|
||||
sodium_free(ctx->state);
|
||||
ctx->state = NULL;
|
||||
}
|
||||
|
||||
if (ctx->mutex != NULL) {
|
||||
enif_mutex_destroy(ctx->mutex);
|
||||
ctx->mutex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int saltywitch_nif_init_generichash(ErlNifEnv *env)
|
||||
{
|
||||
_generichash_context_rtype = enif_open_resource_type(env,
|
||||
NULL,
|
||||
"generichash_context",
|
||||
_generichash_dtor,
|
||||
ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER,
|
||||
NULL);
|
||||
|
||||
if (_generichash_context_rtype == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_generichash_keygen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
unsigned char *key = enif_make_new_binary(env, crypto_generichash_KEYBYTES, &term);
|
||||
if (key == NULL) {
|
||||
return saltywitch_exception(env, atom_error, atom_err_nif_alloc);
|
||||
}
|
||||
|
||||
crypto_generichash_keygen(key);
|
||||
|
||||
return term;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_generichash(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
unsigned char *hash = NULL;
|
||||
ERL_NIF_TERM term;
|
||||
ErlNifBinary bin;
|
||||
|
||||
ErlNifBinary key = {
|
||||
.size = 0,
|
||||
.data = NULL,
|
||||
};
|
||||
|
||||
uint64_t len = crypto_generichash_BYTES;
|
||||
|
||||
if (enif_inspect_binary(env, argv[0], &bin) == false) {
|
||||
return enif_make_badarg(env);
|
||||
}
|
||||
|
||||
switch (argc) {
|
||||
case 3:
|
||||
if (enif_get_uint64(env, argv[2], &len) == false) {
|
||||
return enif_make_badarg(env);
|
||||
}
|
||||
/* fallthrough */
|
||||
case 2:
|
||||
if (enif_inspect_binary(env, argv[1], &key) == false) {
|
||||
return enif_make_badarg(env);
|
||||
}
|
||||
}
|
||||
|
||||
hash = enif_make_new_binary(env, len, &term);
|
||||
if (hash == NULL) {
|
||||
return enif_raise_exception(env, enif_make_atom(env, "opaque"));
|
||||
}
|
||||
|
||||
crypto_generichash(hash, len, bin.data, bin.size, key.data, key.size);
|
||||
|
||||
return term;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_generichash_init(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
struct saltywitch_generichash_context *ctx;
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
ErlNifBinary key = {
|
||||
.size = 0,
|
||||
.data = NULL,
|
||||
};
|
||||
|
||||
uint64_t len = crypto_generichash_BYTES;
|
||||
|
||||
switch (argc) {
|
||||
case 2:
|
||||
if (enif_get_uint64(env, argv[1], &len) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (len < crypto_generichash_BYTES_MIN) {
|
||||
reason = atom_err_output_too_small;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (len > crypto_generichash_BYTES_MAX) {
|
||||
reason = atom_err_output_too_large;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
if (enif_inspect_binary(env, argv[0], &key) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (key.size < crypto_generichash_KEYBYTES_MIN) {
|
||||
reason = atom_err_key_too_small;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (key.size > crypto_generichash_KEYBYTES_MAX) {
|
||||
reason = atom_err_key_too_large;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
ctx = enif_alloc_resource(_generichash_context_rtype, sizeof(struct saltywitch_generichash_context));
|
||||
if (ctx == NULL) {
|
||||
reason = atom_err_nif_alloc;
|
||||
goto resource_alloc_FAULT;
|
||||
}
|
||||
|
||||
ctx->outlen = len;
|
||||
|
||||
ctx->mutex = enif_mutex_create("saltywitch.generichash");
|
||||
if (ctx->mutex == NULL) {
|
||||
reason = atom_err_nif_alloc;
|
||||
goto mutex_FAULT;
|
||||
}
|
||||
|
||||
ctx->state = sodium_malloc(sizeof(crypto_generichash_state));
|
||||
if (ctx->state == NULL) {
|
||||
goto state_alloc_FAULT;
|
||||
}
|
||||
|
||||
crypto_generichash_init(ctx->state, key.data, key.size, len);
|
||||
|
||||
term = enif_make_resource(env, ctx);
|
||||
|
||||
enif_release_resource(ctx);
|
||||
|
||||
return term;
|
||||
|
||||
state_alloc_FAULT:
|
||||
enif_mutex_destroy(ctx->mutex);
|
||||
mutex_FAULT:
|
||||
enif_release_resource(ctx);
|
||||
resource_alloc_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_generichash_update(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
struct saltywitch_generichash_context *ctx = NULL;
|
||||
ErlNifBinary message;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
if (enif_get_resource(env, argv[0], _generichash_context_rtype, (void **) &ctx) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (ctx->mutex == NULL || ctx->state == NULL) {
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_iolist_as_binary(env, argv[1], &message) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
enif_mutex_lock(ctx->mutex);
|
||||
crypto_generichash_update(ctx->state, message.data, message.size);
|
||||
enif_mutex_unlock(ctx->mutex);
|
||||
|
||||
return atom_ok;
|
||||
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_generichash_final(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
struct saltywitch_generichash_context *ctx = NULL;
|
||||
unsigned char *hash;
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
if (enif_get_resource(env, argv[0], _generichash_context_rtype, (void **) &ctx) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (ctx->mutex == NULL || ctx->state == NULL) {
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
hash = enif_make_new_binary(env, ctx->outlen, &term);
|
||||
if (hash == NULL) {
|
||||
reason = atom_err_nif_alloc;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
enif_mutex_lock(ctx->mutex);
|
||||
crypto_generichash_final(ctx->state, hash, ctx->outlen);
|
||||
sodium_free(ctx->state);
|
||||
ctx->state = NULL;
|
||||
ctx->outlen = 0;
|
||||
enif_mutex_unlock(ctx->mutex);
|
||||
|
||||
return term;
|
||||
|
||||
error_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
#include "saltywitch.h"
|
|
@ -0,0 +1,199 @@
|
|||
#include "saltywitch.h"
|
||||
|
||||
ERL_NIF_TERM saltywitch_pwhash(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ErlNifBinary pass, salt;
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
uint64_t len, ops, mem;
|
||||
unsigned char *out;
|
||||
int alg;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
if (enif_get_uint64(env, argv[0], &len) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_iolist_as_binary(env, argv[1], &pass) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[2], &salt) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (salt.size != crypto_pwhash_SALTBYTES) {
|
||||
reason = atom_err_invalid_salt_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_get_uint64(env, argv[3], &ops) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (ops > crypto_pwhash_OPSLIMIT_MAX) {
|
||||
reason = atom_err_pwhash_ops_too_large;
|
||||
goto badarg_FAULT;
|
||||
} else if (ops < crypto_pwhash_OPSLIMIT_MIN) {
|
||||
reason = atom_err_pwhash_ops_too_small;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_get_uint64(env, argv[4], &mem) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (mem > crypto_pwhash_OPSLIMIT_MAX) {
|
||||
reason = atom_err_pwhash_mem_too_large;
|
||||
goto badarg_FAULT;
|
||||
} else if (mem < crypto_pwhash_OPSLIMIT_MIN) {
|
||||
reason = atom_err_pwhash_mem_too_small;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_get_int(env, argv[5], &alg) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
out = enif_make_new_binary(env, len, &term);
|
||||
if (out == NULL) {
|
||||
reason = atom_err_nif_alloc;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
if (crypto_pwhash(out, len, (char *) pass.data, pass.size, salt.data, ops, mem, alg) != 0) {
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
return term;
|
||||
|
||||
error_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_pwhash_str(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
char out[crypto_pwhash_STRBYTES];
|
||||
uint64_t ops, mem;
|
||||
ErlNifBinary pass;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
(void) argc;
|
||||
|
||||
if (enif_inspect_iolist_as_binary(env, argv[0], &pass) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_get_uint64(env, argv[1], &ops) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_get_uint64(env, argv[2], &mem) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (crypto_pwhash_str(out, (char *) pass.data, pass.size, ops, mem) != 0) {
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
return enif_make_string(env, out, ERL_NIF_LATIN1);
|
||||
|
||||
error_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
ERL_NIF_TERM saltywitch_pwhash_str_verify(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ErlNifBinary hash, pass;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
(void) argc;
|
||||
|
||||
if (enif_inspect_iolist_as_binary(env, argv[0], &hash) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (hash.size > crypto_pwhash_STRBYTES) {
|
||||
reason = atom_err_pwhash_too_long;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_iolist_as_binary(env, argv[1], &pass) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (crypto_pwhash_str_verify((char *) hash.data, (char *) pass.data, pass.size) != 0) {
|
||||
reason = atom_err_verification_failed;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
return atom_ok;
|
||||
|
||||
error_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_pwhash_str_needs_rehash(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ErlNifBinary hash;
|
||||
uint64_t ops, mem;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
if (enif_inspect_binary(env, argv[0], &hash) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (hash.size > crypto_pwhash_STRBYTES) {
|
||||
reason = atom_err_pwhash_too_long;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_get_uint64(env, argv[1], &ops) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_get_uint64(env, argv[2], &mem) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
switch (crypto_pwhash_str_needs_rehash((char *) hash.data, ops, mem)) {
|
||||
case 0:
|
||||
return atom_ok;
|
||||
case 1:
|
||||
reason = atom_err_pwhash_needs_rehash;
|
||||
}
|
||||
|
||||
err = atom_error;
|
||||
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#include "saltywitch.h"
|
||||
|
||||
_Static_assert(sizeof(unsigned int) >= sizeof(uint32_t), "unsigned int must be greated than 32 bits");
|
||||
|
||||
ERL_NIF_TERM saltywitch_randombytes_random(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
return enif_make_uint(env, randombytes_random());
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_randombytes_uniform(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
uint32_t upper;
|
||||
|
||||
(void) argc;
|
||||
|
||||
if (enif_get_uint(env, argv[0], &upper) == false) {
|
||||
return saltywitch_exception(env, atom_badarg, atom_err_invalid_type);
|
||||
}
|
||||
|
||||
return enif_make_uint(env, randombytes_uniform(upper));
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_randombytes_buf(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
unsigned char *buf;
|
||||
ERL_NIF_TERM term;
|
||||
uint64_t len;
|
||||
|
||||
(void) argc;
|
||||
|
||||
if (enif_get_uint64(env, argv[0], &len) == false) {
|
||||
return saltywitch_exception(env, atom_badarg, atom_err_invalid_type);
|
||||
}
|
||||
|
||||
buf = enif_make_new_binary(env, len, &term);
|
||||
if (buf == NULL) {
|
||||
return saltywitch_exception(env, atom_error, atom_err_nif_alloc);
|
||||
}
|
||||
|
||||
randombytes_buf(buf, len);
|
||||
|
||||
return term;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_randombytes_buf_deterministic(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
unsigned char *buf;
|
||||
ErlNifBinary seed;
|
||||
ERL_NIF_TERM term;
|
||||
uint64_t len;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
(void) argc;
|
||||
|
||||
if (enif_get_uint64(env, argv[0], &len) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[1], &seed) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (seed.size != randombytes_SEEDBYTES) {
|
||||
reason = atom_err_invalid_seed_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
buf = enif_make_new_binary(env, len, &term);
|
||||
if (buf == NULL) {
|
||||
reason = atom_err_nif_alloc;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
randombytes_buf_deterministic(buf, len, seed.data);
|
||||
|
||||
return term;
|
||||
|
||||
error_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_randombytes_seedbytes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
return enif_make_uint64(env, randombytes_SEEDBYTES);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
#include "saltywitch.h"
|
||||
|
||||
_Static_assert((sizeof(size_t) >= sizeof(uint64_t)), "size_t must be at least 64-bits");
|
||||
|
||||
ERL_NIF_TERM saltywitch_exception(ErlNifEnv *env, ERL_NIF_TERM type, ERL_NIF_TERM reason)
|
||||
{
|
||||
ERL_NIF_TERM exception = enif_make_tuple2(env, type, reason);
|
||||
|
||||
return enif_raise_exception(env, exception);
|
||||
}
|
||||
|
||||
static int saltywitch_load(ErlNifEnv *env, void **data, ERL_NIF_TERM info)
|
||||
{
|
||||
(void) data;
|
||||
(void) info;
|
||||
|
||||
if (sodium_init() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
saltywitch_nif_init_atoms(env);
|
||||
|
||||
if (saltywitch_nif_init_generichash(env) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ERL_NIF_TERM saltywitch_info(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
return enif_make_tuple3(env,
|
||||
enif_make_string(env, SODIUM_VERSION_STRING, ERL_NIF_LATIN1),
|
||||
enif_make_int(env, SODIUM_LIBRARY_VERSION_MAJOR),
|
||||
enif_make_int(env, SODIUM_LIBRARY_VERSION_MINOR));
|
||||
}
|
||||
|
||||
static ErlNifFunc nif_funcs[] = {
|
||||
{"info", 0, saltywitch_info},
|
||||
|
||||
/* random data */
|
||||
{"randombytes_random", 0, saltywitch_randombytes_random},
|
||||
{"randombytes_uniform", 1, saltywitch_randombytes_uniform},
|
||||
{"randombytes_buf", 1, saltywitch_randombytes_buf},
|
||||
{"randombytes_buf_deterministic", 2, saltywitch_randombytes_buf_deterministic},
|
||||
{"randombytes_seedbytes", 0, saltywitch_randombytes_seedbytes},
|
||||
|
||||
/* secretstream */
|
||||
/*
|
||||
{"secretstream_xchacha20poly1305_keygen", 0, saltywitch_secretstream_xchacha20poly1305_keygen},
|
||||
{"secretstream_xchacha20poly1305_init_push", 1, saltywitch_secretstream_xchacha20poly1305_init_push},
|
||||
*/
|
||||
|
||||
/* secretbox */
|
||||
{"secretbox_keygen", 0, saltywitch_secretbox_keygen},
|
||||
|
||||
{"secretbox_easy", 3, saltywitch_secretbox_easy},
|
||||
{"secretbox_open_easy", 3, saltywitch_secretbox_open_easy},
|
||||
|
||||
{"secretbox_detached", 3, saltywitch_secretbox_detached},
|
||||
{"secretbox_open_detached", 4, saltywitch_secretbox_open_detached},
|
||||
|
||||
{"secretbox_keybytes", 0, saltywitch_secretbox_keybytes},
|
||||
{"secretbox_macbytes", 0, saltywitch_secretbox_macbytes},
|
||||
{"secretbox_noncebytes", 0, saltywitch_secretbox_noncebytes},
|
||||
|
||||
/* generichash */
|
||||
{"generichash", 1, saltywitch_generichash},
|
||||
{"generichash", 2, saltywitch_generichash},
|
||||
|
||||
{"generichash_keygen", 0, saltywitch_generichash_keygen},
|
||||
|
||||
{"generichash_init", 0, saltywitch_generichash_init},
|
||||
{"generichash_init", 1, saltywitch_generichash_init},
|
||||
{"generichash_init", 2, saltywitch_generichash_init},
|
||||
{"generichash_update", 2, saltywitch_generichash_update, ERL_NIF_DIRTY_JOB_CPU_BOUND},
|
||||
{"generichash_final", 1, saltywitch_generichash_final},
|
||||
|
||||
/* shorthash */
|
||||
{"shorthash_keygen", 0, saltywitch_shorthash_keygen},
|
||||
{"shorthash", 2, saltywitch_shorthash},
|
||||
|
||||
/* pwhash */
|
||||
//{"pwhash", 6, saltywitch_pwhash, ERL_NIF_DIRTY_JOB_CPU_BOUND},
|
||||
{"pwhash_str", 3, saltywitch_pwhash_str, ERL_NIF_DIRTY_JOB_CPU_BOUND},
|
||||
{"pwhash_str_verify", 2, saltywitch_pwhash_str_verify, ERL_NIF_DIRTY_JOB_CPU_BOUND},
|
||||
{"pwhash_str_needs_rehash", 3, saltywitch_pwhash_str_needs_rehash},
|
||||
};
|
||||
|
||||
ERL_NIF_INIT(Elixir.SaltyWitch.NIF, nif_funcs, saltywitch_load, NULL, NULL, NULL)
|
|
@ -0,0 +1,113 @@
|
|||
#pragma once
|
||||
|
||||
#include <erl_nif.h>
|
||||
#include <sodium.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if __STDC_VERSION__ < 202300L
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
extern ERL_NIF_TERM atom_badarg;
|
||||
extern ERL_NIF_TERM atom_error;
|
||||
extern ERL_NIF_TERM atom_ok;
|
||||
|
||||
extern ERL_NIF_TERM atom_err_opaque;
|
||||
|
||||
extern ERL_NIF_TERM atom_err_invalid_type;
|
||||
extern ERL_NIF_TERM atom_err_nif_alloc;
|
||||
|
||||
extern ERL_NIF_TERM atom_err_invalid_key_size;
|
||||
extern ERL_NIF_TERM atom_err_invalid_nonce_size;
|
||||
extern ERL_NIF_TERM atom_err_invalid_salt_size;
|
||||
extern ERL_NIF_TERM atom_err_invalid_seed_size;
|
||||
extern ERL_NIF_TERM atom_err_invalid_tag_size;
|
||||
extern ERL_NIF_TERM atom_err_verification_failed;
|
||||
|
||||
extern ERL_NIF_TERM atom_err_ciphertext_too_small;
|
||||
extern ERL_NIF_TERM atom_err_key_too_large;
|
||||
extern ERL_NIF_TERM atom_err_key_too_small;
|
||||
extern ERL_NIF_TERM atom_err_output_too_large;
|
||||
extern ERL_NIF_TERM atom_err_output_too_small;
|
||||
|
||||
extern ERL_NIF_TERM atom_err_pwhash_too_long;
|
||||
extern ERL_NIF_TERM atom_err_pwhash_needs_rehash;
|
||||
extern ERL_NIF_TERM atom_err_pwhash_mem_too_large;
|
||||
extern ERL_NIF_TERM atom_err_pwhash_mem_too_small;
|
||||
extern ERL_NIF_TERM atom_err_pwhash_ops_too_large;
|
||||
extern ERL_NIF_TERM atom_err_pwhash_ops_too_small;
|
||||
|
||||
/* init */
|
||||
void saltywitch_nif_init_atoms(ErlNifEnv *env);
|
||||
int saltywitch_nif_init_generichash(ErlNifEnv *env);
|
||||
|
||||
/* helpers */
|
||||
ERL_NIF_TERM saltywitch_exception(ErlNifEnv *env, ERL_NIF_TERM type, ERL_NIF_TERM reason);
|
||||
|
||||
/* random */
|
||||
ERL_NIF_TERM saltywitch_randombytes_random(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_randombytes_uniform(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_randombytes_buf(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_randombytes_buf_deterministic(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_randombytes_seedbytes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
/* generichash */
|
||||
ERL_NIF_TERM saltywitch_generichash(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
ERL_NIF_TERM saltywitch_generichash_keygen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
ERL_NIF_TERM saltywitch_generichash_init(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_generichash_update(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_generichash_final(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
/* secretbox*/
|
||||
ERL_NIF_TERM saltywitch_secretbox_keygen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
ERL_NIF_TERM saltywitch_secretbox_easy(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_secretbox_open_easy(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
ERL_NIF_TERM saltywitch_secretbox_detached(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_secretbox_open_detached(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
ERL_NIF_TERM saltywitch_secretbox_keybytes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_secretbox_macbytes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_secretbox_noncebytes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
/* auth */
|
||||
ERL_NIF_TERM saltywitch_auth_keygen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_auth(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_auth_verify(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
ERL_NIF_TERM saltywitch_auth_hmacsha256_keygen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_auth_hmacsha256(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_auth_hmacsha256_verify(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
ERL_NIF_TERM saltywitch_auth_hmacsha512_keygen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_auth_hmacsha512(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_auth_hmacsha512_verify(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
ERL_NIF_TERM saltywitch_auth_hmacsha512256_keygen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_auth_hmacsha512256(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_auth_hmacsha512256_verify(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
/* pwhash */
|
||||
ERL_NIF_TERM saltywitch_pwhash(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_pwhash_str(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_pwhash_str_verify(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_pwhash_str_needs_rehash(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
/* shorthash */
|
||||
ERL_NIF_TERM saltywitch_shorthash_keygen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_shorthash(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
/* key exchange */
|
||||
/*
|
||||
ERL_NIF_TERM saltywitch_kx_keypair(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_kx_seed_keypair(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_kx_client_session_keys(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_kx_server_session_keys(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
|
||||
ERL_NIF_TERM saltywitch_kx_publickeybytes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM saltywitch_kx_publickeybytes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
*/
|
|
@ -0,0 +1,260 @@
|
|||
#include "saltywitch.h"
|
||||
|
||||
ERL_NIF_TERM saltywitch_secretbox_keygen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
unsigned char *key = enif_make_new_binary(env, crypto_secretbox_KEYBYTES, &term);
|
||||
if (key == NULL) {
|
||||
return saltywitch_exception(env, atom_error, atom_err_nif_alloc);
|
||||
}
|
||||
|
||||
crypto_secretbox_keygen(key);
|
||||
|
||||
return term;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_secretbox_easy(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ErlNifBinary key, nonce, message;
|
||||
unsigned char *cipher;
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
if (enif_inspect_binary(env, argv[0], &key) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (key.size != crypto_secretbox_KEYBYTES) {
|
||||
reason = atom_err_invalid_key_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[1], &nonce) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (nonce.size != crypto_secretbox_NONCEBYTES) {
|
||||
reason = atom_err_invalid_nonce_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[2], &message) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
cipher = enif_make_new_binary(env, message.size + crypto_secretbox_MACBYTES, &term);
|
||||
if (cipher == NULL) {
|
||||
reason = atom_err_nif_alloc;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
crypto_secretbox_easy(cipher, message.data, message.size, nonce.data, key.data);
|
||||
|
||||
return term;
|
||||
|
||||
error_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_secretbox_open_easy(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ErlNifBinary key, nonce, cipher;
|
||||
unsigned char *message;
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
(void) argc;
|
||||
|
||||
if (enif_inspect_binary(env, argv[0], &key) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (key.size != crypto_secretbox_KEYBYTES) {
|
||||
reason = atom_err_invalid_key_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[1], &nonce) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (nonce.size != crypto_secretbox_NONCEBYTES) {
|
||||
reason = atom_err_invalid_nonce_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[2], &cipher) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (cipher.size <= crypto_secretbox_MACBYTES) {
|
||||
reason = atom_err_ciphertext_too_small;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
message = enif_make_new_binary(env, cipher.size - crypto_secretbox_MACBYTES, &term);
|
||||
if (message == NULL) {
|
||||
reason = atom_err_nif_alloc;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
if (crypto_secretbox_open_easy(message, cipher.data, cipher.size, nonce.data, key.data) != 0) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
return term;
|
||||
|
||||
error_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_secretbox_detached(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ERL_NIF_TERM cipher_term, mac_term;
|
||||
ErlNifBinary key, message, nonce;
|
||||
unsigned char *cipher, *mac;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
if (enif_inspect_binary(env, argv[0], &key) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (key.size != crypto_secretbox_KEYBYTES) {
|
||||
reason = atom_err_invalid_key_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[1], &nonce) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (nonce.size != crypto_secretbox_NONCEBYTES) {
|
||||
reason = atom_err_invalid_nonce_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[2], &message) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
cipher = enif_make_new_binary(env, message.size, &cipher_term);
|
||||
if (cipher == NULL) {
|
||||
reason = atom_err_nif_alloc;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
mac = enif_make_new_binary(env, crypto_secretbox_MACBYTES, &mac_term);
|
||||
if (mac == NULL) {
|
||||
reason = atom_err_nif_alloc;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
crypto_secretbox_detached(cipher, mac, message.data, message.size, nonce.data, key.data);
|
||||
|
||||
return enif_make_tuple2(env, cipher_term, mac_term);
|
||||
|
||||
error_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_secretbox_open_detached(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ErlNifBinary key, nonce, cipher, mac;
|
||||
unsigned char *message;
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
if (enif_inspect_binary(env, argv[0], &key) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto FAULT;
|
||||
}
|
||||
|
||||
if (key.size != crypto_secretbox_KEYBYTES) {
|
||||
goto FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[1], &nonce) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto FAULT;
|
||||
}
|
||||
|
||||
if (nonce.size != crypto_secretbox_NONCEBYTES) {
|
||||
goto FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[2], &cipher) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[3], &mac) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto FAULT;
|
||||
}
|
||||
|
||||
if (mac.size != crypto_secretbox_MACBYTES) {
|
||||
goto FAULT;
|
||||
}
|
||||
|
||||
message = enif_make_new_binary(env, cipher.size, &term);
|
||||
|
||||
if (crypto_secretbox_open_detached(message, cipher.data, mac.data, cipher.size, nonce.data, key.data) != 0) {
|
||||
err = atom_error;
|
||||
goto FAULT;
|
||||
}
|
||||
|
||||
return term;
|
||||
|
||||
FAULT:
|
||||
term = saltywitch_exception(env, err, reason);
|
||||
return term;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_secretbox_keybytes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
return enif_make_uint(env, crypto_secretbox_KEYBYTES);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_secretbox_macbytes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
return enif_make_uint(env, crypto_secretbox_MACBYTES);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_secretbox_noncebytes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
return enif_make_uint(env, crypto_secretbox_NONCEBYTES);
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
#include "saltywitch.h"
|
||||
|
||||
ERL_NIF_TERM saltywitch_shorthash_keygen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
unsigned char *key = enif_make_new_binary(env, crypto_shorthash_KEYBYTES, &term);
|
||||
if (key == NULL) {
|
||||
return saltywitch_exception(env, atom_error, atom_err_opaque);
|
||||
}
|
||||
|
||||
crypto_shorthash_keygen(key);
|
||||
|
||||
return term;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM saltywitch_shorthash(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ErlNifBinary key, message;
|
||||
unsigned char *hash;
|
||||
ERL_NIF_TERM term;
|
||||
|
||||
ERL_NIF_TERM err = atom_badarg;
|
||||
ERL_NIF_TERM reason = atom_err_opaque;
|
||||
|
||||
(void) argc;
|
||||
|
||||
if (enif_inspect_binary(env, argv[0], &key) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (key.size != crypto_shorthash_KEYBYTES) {
|
||||
reason = atom_err_invalid_key_size;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
if (enif_inspect_binary(env, argv[1], &message) == false) {
|
||||
reason = atom_err_invalid_type;
|
||||
goto badarg_FAULT;
|
||||
}
|
||||
|
||||
hash = enif_make_new_binary(env, crypto_shorthash_BYTES, &term);
|
||||
if (hash == NULL) {
|
||||
reason = atom_err_nif_alloc;
|
||||
goto error_FAULT;
|
||||
}
|
||||
|
||||
crypto_shorthash(hash, message.data, message.size, key.data);
|
||||
|
||||
return term;
|
||||
|
||||
error_FAULT:
|
||||
err = atom_error;
|
||||
badarg_FAULT:
|
||||
return saltywitch_exception(env, err, reason);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
for dir in ./build-*; do
|
||||
[ -d $dir ] && rm -r $dir
|
||||
done
|
|
@ -0,0 +1,18 @@
|
|||
defmodule SaltyWitch do
|
||||
|
||||
@moduledoc """
|
||||
Documentation for `SaltyWitch`.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Returns version information
|
||||
|
||||
iex> SaltyWitch.info
|
||||
{'1.0.18', 10, 3}
|
||||
|
||||
"""
|
||||
|
||||
def info do
|
||||
SaltyWitch.NIF.info()
|
||||
end
|
||||
end
|
|
@ -0,0 +1,74 @@
|
|||
defmodule SaltyWitch.NIF do
|
||||
@compile {:autoload, false}
|
||||
@on_load :__on_load__
|
||||
|
||||
def __on_load__() do
|
||||
path = :filename.join(:code.priv_dir(:saltywitch), ~c"saltywitch")
|
||||
:erlang.load_nif(path, 0)
|
||||
end
|
||||
|
||||
def info, do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def randombytes_random, do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
# random
|
||||
def randombytes_random, do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def randombytes_uniform(upper)
|
||||
def randombytes_uniform(_), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def randombytes_buf(len)
|
||||
def randombytes_buf(_), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def randombytes_buf_deterministic(len, seed)
|
||||
def randombytes_buf_deterministic(_, _), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def randombytes_seedbytes, do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
# secretbox
|
||||
def secretbox_keygen, do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def secretbox_easy(message, nonce, key)
|
||||
def secretbox_easy(_, _, _), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def secretbox_open_easy(ciphertext, nonce, key)
|
||||
def secretbox_open_easy(_, _, _), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def secretbox_detached(message, nonce, key)
|
||||
def secretbox_detached(_, _, _), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def secretbox_open_detached(ciphertext, mac, nonce, key)
|
||||
def secretbox_open_detached(_, _, _, _), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def secretbox_keybytes, do: :erlang.nif_error(:not_loaded)
|
||||
def secretbox_macbytes, do: :erlang.nif_error(:not_loaded)
|
||||
def secretbox_noncebytes, do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
# generichash
|
||||
def generichash(_), do: :erlang.nif_error(:not_loaded)
|
||||
def generichash(_, _), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def generichash_keygen, do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def generichash_init, do: :erlang.nif_error(:not_loaded)
|
||||
def generichash_init(_), do: :erlang.nif_error(:not_loaded)
|
||||
def generichash_init(_, _), do: :erlang.nif_error(:not_loaded)
|
||||
def generichash_update(_, _), do: :erlang.nif_error(:not_loaded)
|
||||
def generichash_final(_), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
# shorthash
|
||||
def shorthash_keygen, do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def shorthash(key, message)
|
||||
def shorthash(_, _), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
# pwhash
|
||||
def pwhash_str(pass, ops, mem)
|
||||
def pwhash_str(_, _, _), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def pwhash_str_verify(pwhash, pass)
|
||||
def pwhash_str_verify(_, _), do: :erlang.nif_error(:not_loaded)
|
||||
|
||||
def pwhash_str_needs_rehash(pwhash, ops, mem)
|
||||
def pwhash_str_needs_rehash(_, _, _), do: :erlang.nif_error(:not_loaded)
|
||||
end
|
|
@ -0,0 +1,11 @@
|
|||
defmodule SaltyWitch.PasswordHash do
|
||||
alias SaltyWitch.NIF, as: N
|
||||
|
||||
def string(pass, ops, mem) do
|
||||
N.pwhash_str(pass, ops, mem)
|
||||
end
|
||||
|
||||
def verify(pwhash, pass) do
|
||||
N.pwhash_str_verify(pwhash, pass)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
defmodule SaltyWitch.Random do
|
||||
alias SaltyWitch.NIF, as: N
|
||||
|
||||
def seedbytes do
|
||||
N.randombytes_seedbytes()
|
||||
end
|
||||
|
||||
def uint32 do
|
||||
N.randombytes_random()
|
||||
end
|
||||
|
||||
def bytes(size) when size > 0 do
|
||||
N.randombytes_buf(size)
|
||||
end
|
||||
|
||||
def deterministic(size, seed) when size > 0 do
|
||||
N.randombytes_buf_deterministic(size, seed)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
defmodule SaltyWitch.SecretBox do
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
defmodule SaltyWitch.ShortHash do
|
||||
def keygen do
|
||||
SaltyWitch.NIF.shorthash_keygen()
|
||||
end
|
||||
|
||||
def shorthash(key, message) do
|
||||
SaltyWitch.NIF.shorthash(key, message)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,169 @@
|
|||
project('saltywitch', 'c',
|
||||
version: 'trunk',
|
||||
license: 'BSD-3-Clause',
|
||||
meson_version: '>=1.1.0',
|
||||
default_options: [
|
||||
'c_std=c99',
|
||||
'b_asneeded=true',
|
||||
'b_lto=true',
|
||||
'b_lundef=false',
|
||||
'b_ndebug=if-release',
|
||||
'b_pie=true',
|
||||
'b_staticpic=true',
|
||||
'warning_level=2',
|
||||
'werror=false',
|
||||
],
|
||||
)
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
# Default Flags
|
||||
add_project_arguments(
|
||||
cc.get_supported_arguments([
|
||||
'-Walloca',
|
||||
'-Warith-conversion',
|
||||
'-Warray-bounds-pointer-arithmetic',
|
||||
'-Warray-bounds=2',
|
||||
'-Wbad-function-cast',
|
||||
'-Wbitwise-instead-of-logical',
|
||||
'-Wcast-align=strict',
|
||||
'-Wcomma',
|
||||
'-Wconditional-uninitialized',
|
||||
'-Wconversion',
|
||||
'-Wdate-time',
|
||||
'-Wduplicated-branches',
|
||||
'-Wduplicated-cond',
|
||||
'-Wendif-labels',
|
||||
'-Wenum-int-mismatch',
|
||||
'-Wfloat-equal',
|
||||
'-Wformat-overflow=2',
|
||||
'-Wformat-security',
|
||||
'-Wformat-truncation=2',
|
||||
'-Wformat-type-confusion',
|
||||
'-Wformat=2',
|
||||
'-Wimplicit-fallthrough=5',
|
||||
'-Wimplicit-int',
|
||||
'-Winit-self',
|
||||
'-Wjump-misses-init',
|
||||
'-Wliteral-range',
|
||||
'-Wlogical-op',
|
||||
'-Wloop-analysis',
|
||||
'-Wmaybe-unitialized',
|
||||
'-Wmisleading-indentation',
|
||||
'-Wmissing-include-dirs',
|
||||
'-Wmissing-noreturn',
|
||||
'-Wmissing-prototypes',
|
||||
'-Wnested-externs',
|
||||
'-Wno-format-nonliteral',
|
||||
'-Wno-missing-braces',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-typedef-redefinition',
|
||||
'-Wnull-dereference',
|
||||
'-Woverflow',
|
||||
'-Wredundant-decls',
|
||||
'-Wshadow',
|
||||
'-Wshift-sign-overflow',
|
||||
'-Wshorten-64-to-32',
|
||||
'-Wsign-conversion',
|
||||
'-Wsizeof-pointer-memaccess',
|
||||
'-Wstack-usage=1000000',
|
||||
'-Wstrict-overflow=3',
|
||||
'-Wstrict-prototypes',
|
||||
'-Wswitch-enum',
|
||||
'-Wtautological-constant-in-range-compare',
|
||||
'-Wthread-safety',
|
||||
'-Wtraditional-conversion',
|
||||
'-Wtrampolines',
|
||||
'-Wundef',
|
||||
'-Wuninitialized',
|
||||
'-Wunused-but-set-variable',
|
||||
'-Wuse-after-free=3',
|
||||
'-Wvla',
|
||||
'-Wwrite-strings',
|
||||
|
||||
'-Wno-error=#warnings',
|
||||
'-Wno-error=attribute-warning',
|
||||
'-Wno-error=unknown-attributes',
|
||||
'-Wno-error=unknown-pragmas',
|
||||
'-Wno-error=unused-parameter',
|
||||
|
||||
'-fcf-protection=full',
|
||||
'-fno-common',
|
||||
'-fno-delete-null-pointer-checks',
|
||||
'-fno-strict-aliasing',
|
||||
'-fstack-clash-protection',
|
||||
'-fstack-protector',
|
||||
'-fstack-protector-strong',
|
||||
'-fwrapv',
|
||||
'-fzero-call-used-regs=all',
|
||||
]), language: 'c'
|
||||
)
|
||||
|
||||
if get_option('buildtype') != 'debug'
|
||||
add_project_arguments(
|
||||
cc.get_supported_arguments([
|
||||
'-ffunction-sections',
|
||||
'-fdata-sections',
|
||||
]), language: 'c'
|
||||
)
|
||||
|
||||
add_project_link_arguments(
|
||||
cc.get_supported_link_arguments([
|
||||
'-Wl,--gc-sections',
|
||||
'-Wl,-z,noexecstack',
|
||||
'-Wl,-z,noexecheap',
|
||||
'-Wl,-z,now',
|
||||
'-Wl,-z,relro',
|
||||
'-Wl,-z,separate-code',
|
||||
]), language: 'c'
|
||||
)
|
||||
|
||||
add_project_arguments([
|
||||
'-D_FORTIFY_SOURCE=3',
|
||||
], language: 'c'
|
||||
)
|
||||
endif
|
||||
|
||||
add_project_arguments([
|
||||
'-D_DEFAULT_SOURCE',
|
||||
], language: 'c'
|
||||
)
|
||||
|
||||
erts_inc = get_option('erts_include_dir')
|
||||
erl_interface_inc = get_option('erl_interface_include_dir')
|
||||
erl_interface_lib_dir = get_option('erl_interface_lib_dir')
|
||||
|
||||
erl_interface_dep = cc.find_library('ei', dirs: [erl_interface_lib_dir], static: true, required: true)
|
||||
|
||||
sodium_dep = dependency('libsodium', version: '1.0.18', required: true)
|
||||
|
||||
saltywitch_src = files([
|
||||
'c_src/saltywitch.c',
|
||||
|
||||
'c_src/atoms.c',
|
||||
'c_src/auth.c',
|
||||
'c_src/generichash.c',
|
||||
'c_src/kx.c',
|
||||
'c_src/pwhash.c',
|
||||
'c_src/random.c',
|
||||
'c_src/secretbox.c',
|
||||
'c_src/shorthash.c',
|
||||
])
|
||||
|
||||
saltywitch = shared_library(
|
||||
'saltywitch',
|
||||
saltywitch_src,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
include_directories: [ erl_interface_inc, erts_inc ],
|
||||
dependencies: [ erl_interface_dep, sodium_dep ],
|
||||
name_prefix: '',
|
||||
install: true,
|
||||
install_dir: 'priv',
|
||||
)
|
||||
|
||||
summary(
|
||||
{
|
||||
'C compiler' : cc.get_id(),
|
||||
'C linker' : cc.get_linker_id(),
|
||||
}, bool_yn: true
|
||||
)
|
|
@ -0,0 +1,4 @@
|
|||
option('mix_target', type: 'string', description: '')
|
||||
option('erts_include_dir', type: 'string', description: '')
|
||||
option('erl_interface_lib_dir', type: 'string', description: '')
|
||||
option('erl_interface_include_dir', type: 'string', description: '')
|
|
@ -0,0 +1,45 @@
|
|||
defmodule SaltyWitch.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
@version "0.0.1"
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :saltywitch,
|
||||
version: @version,
|
||||
elixir: "~> 1.14",
|
||||
compilers: [:elixir_make] ++ Mix.compilers(),
|
||||
make_clean: ["clean"],
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
defp deps do
|
||||
[
|
||||
{:elixir_make, "~> 0.7", runtime: false}
|
||||
]
|
||||
end
|
||||
|
||||
defp package do
|
||||
[
|
||||
maintainers: ["Aydin Mercan"],
|
||||
licenses: ["BSD-3-Clause"],
|
||||
files: [
|
||||
# Sources
|
||||
"c_src",
|
||||
"lib",
|
||||
"mix.exs",
|
||||
# Build
|
||||
"CMakeLists.txt",
|
||||
"Makefile",
|
||||
"build.sh",
|
||||
"clean.sh",
|
||||
"meson.build",
|
||||
# Meta
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
]
|
||||
]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
%{
|
||||
"elixir_make": {:hex, :elixir_make, "0.7.6", "67716309dc5d43e16b5abbd00c01b8df6a0c2ab54a8f595468035a50189f9169", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5a0569756b0f7873a77687800c164cca6dfc03a09418e6fcf853d78991f49940"},
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
defmodule SaltyWitchTest do
|
||||
use ExUnit.Case
|
||||
doctest SaltyWitch
|
||||
|
||||
test "greets the world" do
|
||||
assert SaltyWitch.hello() == :world
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
ExUnit.start()
|
Loading…
Reference in New Issue