Argon2: deallocate memory if fill_memory_blocks() ever fails

Also perform a single allocation to store random numbers.
This commit is contained in:
Frank Denis
2017-07-28 17:58:16 +02:00
parent 8d91a32754
commit c3908f87d6
6 changed files with 34 additions and 30 deletions
@@ -170,7 +170,7 @@ static void free_memory(block_region *memory);
static void
free_memory(block_region *region)
{
if (region->base) {
if (region && region->base) {
#if defined(MAP_ANON) && defined(HAVE_MMAP)
if (munmap(region->base, region->size)) {
return; /* LCOV_EXCL_LINE */
@@ -182,6 +182,19 @@ free_memory(block_region *region)
free(region);
}
void
free_instance(argon2_instance_t *instance, int flags)
{
/* Clear memory */
clear_memory(instance, flags & ARGON2_FLAG_CLEAR_PASSWORD);
/* Deallocate the memory */
free(instance->pseudo_rands);
instance->pseudo_rands = NULL;
free_memory(instance->region);
instance->region = NULL;
}
void
finalize(const argon2_context *context, argon2_instance_t *instance)
{
@@ -212,11 +225,7 @@ finalize(const argon2_context *context, argon2_instance_t *instance)
ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */
}
/* Clear memory */
clear_memory(instance, context->flags & ARGON2_FLAG_CLEAR_PASSWORD);
/* Deallocate the memory */
free_memory(instance->region);
free_instance(instance, context->flags);
}
}
@@ -544,7 +553,7 @@ initial_hash(uint8_t *blockhash, argon2_context *context, argon2_type type)
STORE32_LE(value, context->adlen);
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
/* LCOV_EXCL_START */
/* LCOV_EXCL_START */
if (context->ad != NULL) {
crypto_generichash_blake2b_update(
&BlakeHash, (const uint8_t *) context->ad, context->adlen);
@@ -561,13 +570,20 @@ initialize(argon2_instance_t *instance, argon2_context *context)
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
int result = ARGON2_OK;
if (instance == NULL || context == NULL)
if (instance == NULL || context == NULL) {
return ARGON2_INCORRECT_PARAMETER;
}
/* 1. Memory allocation */
if ((instance->pseudo_rands =
malloc(sizeof(uint64_t) * instance->segment_length)) == NULL) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
result = allocate_memory(&(instance->region), instance->memory_blocks);
if (ARGON2_OK != result) {
free_instance(instance, context->flags);
return result;
}
@@ -76,6 +76,7 @@ void xor_block(block *dst, const block *src);
*/
typedef struct Argon2_instance_t {
block_region *region; /* Memory region pointer */
uint64_t *pseudo_rands;
uint32_t passes; /* Number of passes */
uint32_t memory_blocks; /* Number of blocks in memory */
uint32_t segment_length;
@@ -162,6 +163,11 @@ void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
*/
int initialize(argon2_instance_t *instance, argon2_context *context);
/*
* Deallocates memory. Used on error path.
*/
void free_instance(argon2_instance_t *instance, int flags);
/*
* XORing the last block of each lane, hashing it, making the tag. Deallocates
* the memory.
@@ -163,11 +163,7 @@ fill_segment_avx2(const argon2_instance_t *instance,
data_independent_addressing = 0;
}
pseudo_rands =
(uint64_t *) malloc(sizeof(uint64_t) * instance->segment_length);
if (pseudo_rands == NULL) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
pseudo_rands = instance->pseudo_rands;
if (data_independent_addressing) {
generate_addresses(instance, &position, pseudo_rands);
@@ -240,8 +236,6 @@ fill_segment_avx2(const argon2_instance_t *instance,
}
}
free(pseudo_rands);
return ARGON2_OK;
}
#endif
@@ -161,12 +161,7 @@ fill_segment_ref(const argon2_instance_t *instance, argon2_position_t position)
data_independent_addressing = 0;
}
pseudo_rands =
(uint64_t *) malloc(sizeof(uint64_t) * (instance->segment_length));
if (pseudo_rands == NULL) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
pseudo_rands = instance->pseudo_rands;
if (data_independent_addressing) {
generate_addresses(instance, &position, pseudo_rands);
@@ -236,7 +231,5 @@ fill_segment_ref(const argon2_instance_t *instance, argon2_position_t position)
}
}
free(pseudo_rands);
return ARGON2_OK;
}
@@ -162,11 +162,7 @@ fill_segment_ssse3(const argon2_instance_t *instance,
data_independent_addressing = 0;
}
pseudo_rands =
(uint64_t *) malloc(sizeof(uint64_t) * instance->segment_length);
if (pseudo_rands == NULL) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
pseudo_rands = instance->pseudo_rands;
if (data_independent_addressing) {
generate_addresses(instance, &position, pseudo_rands);
@@ -239,8 +235,6 @@ fill_segment_ssse3(const argon2_instance_t *instance,
}
}
free(pseudo_rands);
return ARGON2_OK;
}
#endif
@@ -73,6 +73,7 @@ argon2_ctx(argon2_context *context, argon2_type type)
result = fill_memory_blocks(&instance);
if (ARGON2_OK != result) {
free_instance(&instance, context->flags);
return result;
}