Track liveness stateReject updates to finalized generichash states.
This commit is contained in:
parent
f5918c0156
commit
df1b134f73
@ -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
|
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
|
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.
|
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
|
### Fixes
|
||||||
- Fix a resource leak in generichash/sign init/update/final.
|
- Fix a resource leak in generichash/sign init/update/final.
|
||||||
|
@ -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 enacl_crypto_generichash(ErlNifEnv *env, int argc,
|
||||||
ERL_NIF_TERM const argv[]) {
|
ERL_NIF_TERM const argv[]) {
|
||||||
ErlNifBinary hash, message, key;
|
ErlNifBinary hash, message, key;
|
||||||
unsigned hashSize;
|
unsigned hash_size;
|
||||||
ERL_NIF_TERM ret;
|
ERL_NIF_TERM ret;
|
||||||
|
|
||||||
// Validate the arguments
|
// Validate the arguments
|
||||||
if ((argc != 3) || (!enif_get_uint(env, argv[0], &hashSize)) ||
|
if (argc != 3)
|
||||||
(!enif_inspect_binary(env, argv[1], &message)) ||
|
goto bad_arg;
|
||||||
(!enif_inspect_binary(env, argv[2], &key)))
|
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;
|
goto bad_arg;
|
||||||
|
|
||||||
// Verify that hash size is
|
// Verify that hash size is
|
||||||
// crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
|
// crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
|
||||||
if ((hashSize <= crypto_generichash_BYTES_MIN) ||
|
if ((hash_size <= crypto_generichash_BYTES_MIN) ||
|
||||||
(hashSize >= crypto_generichash_BYTES_MAX)) {
|
(hash_size >= crypto_generichash_BYTES_MAX)) {
|
||||||
ret = nacl_error_tuple(env, "invalid_hash_size");
|
ret = nacl_error_tuple(env, "invalid_hash_size");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -106,7 +110,7 @@ ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allocate memory for hash
|
// allocate memory for hash
|
||||||
if (!enif_alloc_binary(hashSize, &hash)) {
|
if (!enif_alloc_binary(hash_size, &hash)) {
|
||||||
ret = nacl_error_tuple(env, "alloc_failed");
|
ret = nacl_error_tuple(env, "alloc_failed");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -140,13 +144,14 @@ ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc,
|
|||||||
ERL_NIF_TERM ret;
|
ERL_NIF_TERM ret;
|
||||||
|
|
||||||
// Validate the arguments
|
// Validate the arguments
|
||||||
if ((argc != 2) || (!enif_get_uint(env, argv[0], &hash_size)) ||
|
if (argc != 2)
|
||||||
(!enif_inspect_binary(env, argv[1], &key))) {
|
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;
|
goto bad_arg;
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that hash size is
|
// Verify that hash size is valid
|
||||||
// crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
|
|
||||||
if ((hash_size <= crypto_generichash_BYTES_MIN) ||
|
if ((hash_size <= crypto_generichash_BYTES_MIN) ||
|
||||||
(hash_size >= crypto_generichash_BYTES_MAX)) {
|
(hash_size >= crypto_generichash_BYTES_MAX)) {
|
||||||
ret = nacl_error_tuple(env, "invalid_hash_size");
|
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
|
// Call the library function
|
||||||
if (0 != crypto_generichash_init(obj->ctx, k, key.size, hash_size)) {
|
if (0 != crypto_generichash_init(obj->ctx, k, key.size, hash_size)) {
|
||||||
ret = nacl_error_tuple(env, "hash_init_error");
|
ret = nacl_error_tuple(env, "hash_init_error");
|
||||||
goto done;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create return values
|
// Create return values
|
||||||
@ -202,6 +207,7 @@ err:
|
|||||||
if (obj != NULL) {
|
if (obj != NULL) {
|
||||||
if (obj->alive) {
|
if (obj->alive) {
|
||||||
sodium_free(obj->ctx);
|
sodium_free(obj->ctx);
|
||||||
|
obj->alive = 0; // Maintain the invariant consistently
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
@ -230,6 +236,11 @@ ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc,
|
|||||||
if (!enif_inspect_binary(env, argv[2], &data))
|
if (!enif_inspect_binary(env, argv[2], &data))
|
||||||
goto bad_arg;
|
goto bad_arg;
|
||||||
|
|
||||||
|
if (!obj->alive) {
|
||||||
|
ret = nacl_error_tuple(env, "finalized");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
// Update hash state
|
// Update hash state
|
||||||
if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) {
|
if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) {
|
||||||
ret = nacl_error_tuple(env, "hash_update_error");
|
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))
|
(void **)&obj))
|
||||||
goto bad_arg;
|
goto bad_arg;
|
||||||
|
|
||||||
|
if (!obj->alive) {
|
||||||
|
ret = nacl_error_tuple(env, "finalized");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if ((hash_size <= crypto_generichash_BYTES_MIN) ||
|
if ((hash_size <= crypto_generichash_BYTES_MIN) ||
|
||||||
(hash_size >= crypto_generichash_BYTES_MAX)) {
|
(hash_size >= crypto_generichash_BYTES_MAX)) {
|
||||||
ret = nacl_error_tuple(env, "invalid_hash_size");
|
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;
|
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 ok = enif_make_atom(env, ATOM_OK);
|
||||||
ERL_NIF_TERM h = enif_make_binary(env, &hash);
|
ERL_NIF_TERM h = enif_make_binary(env, &hash);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user