Merge pull request #36 from aeternity/generichash_segfault

Generic hash state needs to be 64-byte aligned
This commit is contained in:
Jesper Louis Andersen 2018-11-08 11:36:38 +01:00 committed by GitHub
commit 885662c069
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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); 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 static
ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ERL_NIF_TERM enif_crypto_generichash_init(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
ErlNifBinary key; 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"); return nacl_error_tuple(env, "invalid_key_size");
} }
// Create a resource for hash state // Create a resource for hash state (+ 60 to make room for 64-byte alignment)
crypto_generichash_state *state = (crypto_generichash_state *)enif_alloc_resource(generichash_state_type, crypto_generichash_statebytes()); void *state = enif_alloc_resource(generichash_state_type, crypto_generichash_statebytes() + 60);
if( !state ) { if( !state ) {
return nacl_error_tuple(env, "alloc_failed"); return nacl_error_tuple(env, "alloc_failed");
} }
// Call the library function // 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"); 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; unsigned hashSize;
crypto_generichash_state *state; void *state;
// Validate the arguments // Validate the arguments
if( (argc != 3) || if( (argc != 3) ||
@ -1586,11 +1593,10 @@ ERL_NIF_TERM enif_crypto_generichash_update(ErlNifEnv *env, int argc, ERL_NIF_TE
} }
// Update hash state // 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"); return nacl_error_tuple(env, "hash_update_error");
} }
// Generate return value // Generate return value
ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate"); ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate");
ERL_NIF_TERM e2 = argv[0]; 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; unsigned hashSize;
crypto_generichash_state *state; void *state;
// Validate the arguments // Validate the arguments
if( (argc != 2) || 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"); return nacl_error_tuple(env, "alloc_failed");
} }
// calculate hash // calculate hash
if( 0 != crypto_generichash_final(state, hash.data, hash.size) ) { if( 0 != crypto_generichash_final(align64(state), hash.data, hash.size) ) {
enif_release_binary(&hash); enif_release_binary(&hash);
return nacl_error_tuple(env, "hash_error"); return nacl_error_tuple(env, "hash_error");
} }