From e594146f67f4dc46e53f3b8d83fb72a55f046a55 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Wed, 17 Dec 2014 12:46:54 +0100 Subject: [PATCH] Implement the beforenm/afternm calls at the NIF layer. --- c_src/enacl_nif.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++ src/enacl_nif.erl | 10 ++++++ 2 files changed, 102 insertions(+) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index c3ae882..d81027d 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -106,6 +106,11 @@ ERL_NIF_TERM enif_crypto_box_SECRETKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TE return enif_make_int64(env, crypto_box_SECRETKEYBYTES); } +static +ERL_NIF_TERM enif_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + return enif_make_int64(env, crypto_box_BEFORENMBYTES); +} + static ERL_NIF_TERM enif_crypto_box_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary pk, sk; @@ -198,6 +203,89 @@ ERL_NIF_TERM enif_crypto_box_open(ErlNifEnv *env, int argc, ERL_NIF_TERM const a padded_ciphertext.size - crypto_box_ZEROBYTES); } +/* Precomputed crypto boxes */ + +static +ERL_NIF_TERM enif_crypto_box_beforenm(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + ErlNifBinary k, pk, sk; + + if ( + (argc != 2) || + (!enif_inspect_binary(env, argv[0], &pk)) || + (!enif_inspect_binary(env, argv[1], &sk)) || + (pk.size != crypto_box_PUBLICKEYBYTES) || + (sk.size != crypto_box_SECRETKEYBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(crypto_box_BEFORENMBYTES, &k)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_box_beforenm(k.data, pk.data, sk.data); + + return enif_make_binary(env, &k); +} + +static +ERL_NIF_TERM enif_crypto_box_afternm(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + ErlNifBinary result, m, nonce, k; + + if ( + (argc != 3) || + (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &k)) || + (m.size < crypto_box_ZEROBYTES) || + (nonce.size != crypto_box_NONCEBYTES) || + (k.size != crypto_box_BEFORENMBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(m.size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data); + + return enif_make_sub_binary( + env, + enif_make_binary(env, &result), + crypto_box_BOXZEROBYTES, + m.size - crypto_box_BOXZEROBYTES); +} + +static +ERL_NIF_TERM enif_crypto_box_open_afternm(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + ErlNifBinary result, m, nonce, k; + + if ( + (argc != 3) || + (!enif_inspect_iolist_as_binary(env, argv[0], &m)) || + (!enif_inspect_binary(env, argv[1], &nonce)) || + (!enif_inspect_binary(env, argv[2], &k)) || + (m.size < crypto_box_BOXZEROBYTES) || + (nonce.size != crypto_box_NONCEBYTES) || + (k.size != crypto_box_BEFORENMBYTES)) { + return enif_make_badarg(env); + } + + if (!enif_alloc_binary(m.size, &result)) { + return nacl_error_tuple(env, "alloc_failed"); + } + + if (crypto_box_open_afternm(result.data, m.data, m.size, nonce.data, k.data)) { + enif_release_binary(&result); + return nacl_error_tuple(env, "failed_verification"); + } + + return enif_make_sub_binary( + env, + enif_make_binary(env, &result), + crypto_box_ZEROBYTES, + m.size - crypto_box_ZEROBYTES); +} + /* Signing */ static ERL_NIF_TERM enif_crypto_sign_PUBLICKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { @@ -664,11 +752,15 @@ static ErlNifFunc nif_funcs[] = { {"crypto_box_BOXZEROBYTES", 0, enif_crypto_box_BOXZEROBYTES}, {"crypto_box_PUBLICKEYBYTES", 0, enif_crypto_box_PUBLICKEYBYTES}, {"crypto_box_SECRETKEYBYTES", 0, enif_crypto_box_SECRETKEYBYTES}, + {"crypto_box_BEFORENMBYTES", 0, enif_crypto_box_BEFORENMBYTES}, {"crypto_box_keypair", 0, enif_crypto_box_keypair}, {"crypto_box_b", 4, enif_crypto_box}, {"crypto_box", 4, enif_crypto_box, ERL_NIF_DIRTY_JOB_CPU_BOUND}, {"crypto_box_open_b", 4, enif_crypto_box_open}, {"crypto_box_open", 4, enif_crypto_box_open, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"crypto_box_beforenm", 2, enif_crypto_box_beforenm}, + {"crypto_box_afternm", 3, enif_crypto_box_afternm}, + {"crypto_box_open_afternm", 3, enif_crypto_box_open_afternm}, {"crypto_sign_PUBLICKEYBYTES", 0, enif_crypto_sign_PUBLICKEYBYTES}, {"crypto_sign_SECRETKEYBYTES", 0, enif_crypto_sign_SECRETKEYBYTES}, diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 8eb6525..8cd69a4 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -10,6 +10,7 @@ crypto_box_PUBLICKEYBYTES/0, crypto_box_SECRETKEYBYTES/0, crypto_box_ZEROBYTES/0, + crypto_box_BEFORENMBYTES/0, crypto_box/4, crypto_box_b/4, @@ -17,6 +18,10 @@ crypto_box_open/4, crypto_box_open_b/4, + crypto_box_beforenm/2, + crypto_box_afternm/3, + crypto_box_open_afternm/3, + crypto_sign_PUBLICKEYBYTES/0, crypto_sign_SECRETKEYBYTES/0, @@ -100,6 +105,7 @@ crypto_box_ZEROBYTES() -> erlang:nif_error(nif_not_loaded). crypto_box_BOXZEROBYTES() -> erlang:nif_error(nif_not_loaded). crypto_box_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded). crypto_box_SECRETKEYBYTES() -> erlang:nif_error(nif_not_loaded). +crypto_box_BEFORENMBYTES() -> erlang:nif_error(nif_not_loaded). crypto_box_keypair() -> erlang:nif_error(nif_not_loaded). crypto_box(_PaddedMsg, _Nonce, _PK, _SK) -> erlang:nif_error(nif_not_loaded). @@ -107,6 +113,10 @@ crypto_box_b(_PaddedMsg, _Nonce, _PK, _SK) -> erlang:nif_error(nif_not_loaded). crypto_box_open(_CipherText, _Nonce, _PK, _SK) -> erlang:nif_error(nif_not_loaded). crypto_box_open_b(_CipherText, _Nonce, _PK, _SK) -> erlang:nif_error(nif_not_loaded). +crypto_box_beforenm(_PK, _SK) -> erlang:nif_error(nif_not_loaded). +crypto_box_afternm(_M, _Nonce, _K) -> erlang:nif_error(nif_not_loaded). +crypto_box_open_afternm(_CipherText, _Nonce, _K) -> erlang:nif_error(nif_not_loaded). + crypto_sign_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded). crypto_sign_SECRETKEYBYTES() -> erlang:nif_error(nif_not_loaded).