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