From c3908f87d63283f5b8f5607c566d19148b782f63 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Fri, 28 Jul 2017 17:58:16 +0200 Subject: [PATCH] Argon2: deallocate memory if fill_memory_blocks() ever fails Also perform a single allocation to store random numbers. --- .../crypto_pwhash/argon2/argon2-core.c | 32 ++++++++++++++----- .../crypto_pwhash/argon2/argon2-core.h | 6 ++++ .../argon2/argon2-fill-block-avx2.c | 8 +---- .../argon2/argon2-fill-block-ref.c | 9 +----- .../argon2/argon2-fill-block-ssse3.c | 8 +---- src/libsodium/crypto_pwhash/argon2/argon2.c | 1 + 6 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/libsodium/crypto_pwhash/argon2/argon2-core.c b/src/libsodium/crypto_pwhash/argon2/argon2-core.c index 85846b78..4140e087 100644 --- a/src/libsodium/crypto_pwhash/argon2/argon2-core.c +++ b/src/libsodium/crypto_pwhash/argon2/argon2-core.c @@ -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; } diff --git a/src/libsodium/crypto_pwhash/argon2/argon2-core.h b/src/libsodium/crypto_pwhash/argon2/argon2-core.h index 69d5925b..454296ea 100644 --- a/src/libsodium/crypto_pwhash/argon2/argon2-core.h +++ b/src/libsodium/crypto_pwhash/argon2/argon2-core.h @@ -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. diff --git a/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-avx2.c b/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-avx2.c index 8597fc44..84dabf5b 100644 --- a/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-avx2.c +++ b/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-avx2.c @@ -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 diff --git a/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-ref.c b/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-ref.c index 98ad50c9..bc1a7795 100644 --- a/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-ref.c +++ b/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-ref.c @@ -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; } diff --git a/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-ssse3.c b/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-ssse3.c index 4056080d..6b3a1a06 100644 --- a/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-ssse3.c +++ b/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-ssse3.c @@ -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 diff --git a/src/libsodium/crypto_pwhash/argon2/argon2.c b/src/libsodium/crypto_pwhash/argon2/argon2.c index f52381db..c9e48e75 100644 --- a/src/libsodium/crypto_pwhash/argon2/argon2.c +++ b/src/libsodium/crypto_pwhash/argon2/argon2.c @@ -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; }