saltywitch/c_src/pwhash.c

200 lines
4.4 KiB
C

#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);
}