saltywitch/c_src/secretbox.c

261 lines
6.0 KiB
C

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