Track liveness stateReject updates to finalized generichash states.

This commit is contained in:
Jesper Louis Andersen 2020-01-17 16:06:15 +01:00
parent f5918c0156
commit df1b134f73
2 changed files with 35 additions and 13 deletions

View File

@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
following the style of the Erlang/OTP `crypto` library. While here, make sure
we clean up correctly and that we don't accidentally mis-ref-count data. The
code is a bit more goto heavy, but this style is surprisingly common in C code.
- The code now rejects updates to generichash states which were already finalized.
### Fixes
- Fix a resource leak in generichash/sign init/update/final.

View File

@ -78,19 +78,23 @@ ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc,
ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ErlNifBinary hash, message, key;
unsigned hashSize;
unsigned hash_size;
ERL_NIF_TERM ret;
// Validate the arguments
if ((argc != 3) || (!enif_get_uint(env, argv[0], &hashSize)) ||
(!enif_inspect_binary(env, argv[1], &message)) ||
(!enif_inspect_binary(env, argv[2], &key)))
if (argc != 3)
goto bad_arg;
if (!enif_get_uint(env, argv[0], &hash_size))
goto bad_arg;
if (!enif_inspect_binary(env, argv[1], &message))
goto bad_arg;
if (!enif_inspect_binary(env, argv[2], &key))
goto bad_arg;
// Verify that hash size is
// crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
if ((hashSize <= crypto_generichash_BYTES_MIN) ||
(hashSize >= crypto_generichash_BYTES_MAX)) {
if ((hash_size <= crypto_generichash_BYTES_MIN) ||
(hash_size >= crypto_generichash_BYTES_MAX)) {
ret = nacl_error_tuple(env, "invalid_hash_size");
goto done;
}
@ -106,7 +110,7 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc,
}
// allocate memory for hash
if (!enif_alloc_binary(hashSize, &hash)) {
if (!enif_alloc_binary(hash_size, &hash)) {
ret = nacl_error_tuple(env, "alloc_failed");
goto done;
}
@ -140,13 +144,14 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc,
ERL_NIF_TERM ret;
// Validate the arguments
if ((argc != 2) || (!enif_get_uint(env, argv[0], &hash_size)) ||
(!enif_inspect_binary(env, argv[1], &key))) {
if (argc != 2)
goto bad_arg;
if (!enif_get_uint(env, argv[0], &hash_size))
goto bad_arg;
if (!enif_inspect_binary(env, argv[1], &key))
goto bad_arg;
}
// Verify that hash size is
// crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
// Verify that hash size is valid
if ((hash_size <= crypto_generichash_BYTES_MIN) ||
(hash_size >= crypto_generichash_BYTES_MAX)) {
ret = nacl_error_tuple(env, "invalid_hash_size");
@ -184,7 +189,7 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc,
// Call the library function
if (0 != crypto_generichash_init(obj->ctx, k, key.size, hash_size)) {
ret = nacl_error_tuple(env, "hash_init_error");
goto done;
goto err;
}
// Create return values
@ -202,6 +207,7 @@ err:
if (obj != NULL) {
if (obj->alive) {
sodium_free(obj->ctx);
obj->alive = 0; // Maintain the invariant consistently
}
}
done:
@ -230,6 +236,11 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc,
if (!enif_inspect_binary(env, argv[2], &data))
goto bad_arg;
if (!obj->alive) {
ret = nacl_error_tuple(env, "finalized");
goto done;
}
// Update hash state
if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) {
ret = nacl_error_tuple(env, "hash_update_error");
@ -264,6 +275,11 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc,
(void **)&obj))
goto bad_arg;
if (!obj->alive) {
ret = nacl_error_tuple(env, "finalized");
goto done;
}
if ((hash_size <= crypto_generichash_BYTES_MIN) ||
(hash_size >= crypto_generichash_BYTES_MAX)) {
ret = nacl_error_tuple(env, "invalid_hash_size");
@ -280,6 +296,11 @@ ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc,
goto release;
}
// Finalize the object such that it cannot be reused by accident
if (obj->ctx)
sodium_free(obj->ctx);
obj->alive = 0;
ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK);
ERL_NIF_TERM h = enif_make_binary(env, &hash);