From aa2c69529a3de5bcc550e4123542796e6e10f980 Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 4 Feb 2020 12:59:18 +0100 Subject: [PATCH] Streamlines generichashThe multi-part hash API is nowreflecting the same crypto modulefunctions in style. This is easierto use for people, I believe. --- CHANGELOG.md | 7 ++++++- c_src/generichash.c | 23 ++++++++++------------- src/enacl.erl | 9 ++++++++- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a79fe7e..43e395c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. Pretty large change, but OTOH, this ought to happen before a 1.0 release as well. - AEAD - enacl - - generichash - hash - kx - pwhash @@ -19,6 +18,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - secret - sign +- Implement missing EQC tests + - Generichash + - Multi-part generic hash + ## [Unreleased] ### Compatibility @@ -71,6 +74,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed many routines from enif_* to enacl_*. This better reflects where they live in the code base, and avoids pollution of the enif_* "namespace". - Split Sign Public Key routines from the rest. Modernize the handling of contexts. +- The multi-part generic hash routines now follow the structure of the crypto + modules multi-part constructions in API and style. ### Fixed - Fix a resource leak in generichash/sign init/update/final. diff --git a/c_src/generichash.c b/c_src/generichash.c index 524def8..05794bc 100644 --- a/c_src/generichash.c +++ b/c_src/generichash.c @@ -157,8 +157,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, // Verify that hash size is valid if ((hash_size <= crypto_generichash_BYTES_MIN) || (hash_size >= crypto_generichash_BYTES_MAX)) { - ret = enacl_error_tuple(env, "invalid_hash_size"); - goto done; + goto bad_arg; } // validate key size @@ -167,8 +166,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, k = NULL; } else if (key.size <= crypto_generichash_KEYBYTES_MIN || key.size >= crypto_generichash_KEYBYTES_MAX) { - ret = enacl_error_tuple(env, "invalid_key_size"); - goto done; + goto bad_arg; } // Create the resource @@ -210,7 +208,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); err: - ret = enacl_error_tuple(env, "internal_error"); + ret = enif_make_atom(env, "notsup"); if (obj != NULL) { if (obj->alive) { sodium_free(obj->ctx); @@ -244,14 +242,12 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, enif_mutex_lock(obj->mtx); if (!obj->alive) { - ret = enacl_error_tuple(env, "finalized"); - goto done; + goto err; } // Update hash state if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) { - ret = enacl_error_tuple(env, "hash_update_error"); - goto done; + goto err; } ret = argv[0]; @@ -259,6 +255,8 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); +err: + ret = enif_make_badarg(env); done: enif_mutex_unlock(obj->mtx); return ret; @@ -278,17 +276,14 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, enif_mutex_lock(obj->mtx); if (!obj->alive) { - ret = enacl_error_tuple(env, "finalized"); - goto done; + goto err; } if (!enif_alloc_binary(obj->outlen, &hash)) { - ret = enacl_error_tuple(env, "alloc_failed"); goto done; } if (0 != crypto_generichash_final(obj->ctx, hash.data, hash.size)) { - ret = enacl_error_tuple(env, "hash_error"); goto release; } @@ -305,6 +300,8 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc, bad_arg: return enif_make_badarg(env); +err: + ret = enif_make_badarg(env); release: enif_release_binary(&hash); done: diff --git a/src/enacl.erl b/src/enacl.erl index 037bafb..4ee0e73 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -351,16 +351,23 @@ generichash(HashSize, Message, Key) -> generichash(HashSize, Message) -> enacl_nif:crypto_generichash(HashSize, Message, <<>>). +%% @doc generichash_init/2 initializes a multi-part hash. +%% @end +-spec generichash_init(generichash_bytes(), binary()) -> reference() | notsup. generichash_init(HashSize, Key) -> enacl_nif:crypto_generichash_init(HashSize, Key). +%% @doc generichash_update/2 updates a multi-part hash with new data. +%% @end +-spec generichash_update(reference(), iodata()) -> reference(). generichash_update(State, Message) -> enacl_nif:crypto_generichash_update(State, Message). +%% @doc generichash_final/1 finalizes a multi-part hash. +-spec generichash_final(reference()) -> binary(). generichash_final(State) -> enacl_nif:crypto_generichash_final(State). - -type pwhash_limit() :: interactive | moderate | sensitive | pos_integer(). %% @doc pwhash/2 hash a password %%