From 1121321573fdbfc52ea3d2ebba8d01c7f6353c33 Mon Sep 17 00:00:00 2001 From: Hans Svensson Date: Thu, 8 Nov 2018 10:43:51 +0100 Subject: [PATCH] Generic hash state needs to be 64-byte aligned At least according to: https://libsodium.gitbook.io/doc/hashing/generic_hashing We noticed crashes when it was not 16-byte aligned - probably is architecture dependent. This makes the safe choice and always 64-byte align it. --- c_src/enacl_nif.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index 364a47d..1497215 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -1511,6 +1511,13 @@ ERL_NIF_TERM enif_crypto_generichash(ErlNifEnv *env, int argc, ERL_NIF_TERM cons return enif_make_tuple2(env, ok, ret); } +static +crypto_generichash_state *align64(void *ptr){ + if((unsigned long)ptr % 64 == 0) + return ptr; + return ptr + (64 - ((unsigned long)ptr % 64)); +} + static ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary key; @@ -1538,14 +1545,14 @@ ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, ERL_NIF_TERM return nacl_error_tuple(env, "invalid_key_size"); } - // Create a resource for hash state - crypto_generichash_state *state = (crypto_generichash_state *)enif_alloc_resource(generichash_state_type, crypto_generichash_statebytes()); + // Create a resource for hash state (+ 60 to make room for 64-byte alignment) + void *state = enif_alloc_resource(generichash_state_type, crypto_generichash_statebytes() + 60); if( !state ) { return nacl_error_tuple(env, "alloc_failed"); } // Call the library function - if( 0 != crypto_generichash_init(state, k, key.size, hashSize) ) { + if( 0 != crypto_generichash_init(align64(state), k, key.size, hashSize) ) { return nacl_error_tuple(env, "hash_init_error"); } @@ -1569,7 +1576,7 @@ ERL_NIF_TERM enif_crypto_generichash_update(ErlNifEnv *env, int argc, ERL_NIF_TE unsigned hashSize; - crypto_generichash_state *state; + void *state; // Validate the arguments if( (argc != 3) || @@ -1586,11 +1593,10 @@ ERL_NIF_TERM enif_crypto_generichash_update(ErlNifEnv *env, int argc, ERL_NIF_TE } // Update hash state - if( 0 != crypto_generichash_update(state, message.data, message.size) ) { + if( 0 != crypto_generichash_update(align64(state), message.data, message.size) ) { return nacl_error_tuple(env, "hash_update_error"); } - // Generate return value ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate"); ERL_NIF_TERM e2 = argv[0]; @@ -1606,7 +1612,7 @@ ERL_NIF_TERM enif_crypto_generichash_final(ErlNifEnv *env, int argc, ERL_NIF_TER unsigned hashSize; - crypto_generichash_state *state; + void *state; // Validate the arguments if( (argc != 2) || @@ -1626,8 +1632,8 @@ ERL_NIF_TERM enif_crypto_generichash_final(ErlNifEnv *env, int argc, ERL_NIF_TER return nacl_error_tuple(env, "alloc_failed"); } - // calculate hash - if( 0 != crypto_generichash_final(state, hash.data, hash.size) ) { + // calculate hash + if( 0 != crypto_generichash_final(align64(state), hash.data, hash.size) ) { enif_release_binary(&hash); return nacl_error_tuple(env, "hash_error"); }