diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d269969..61a35cde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ option (OPENDHT_SHARED "Build shared library" ON) option (OPENDHT_LOG "Build with logs" ON) option (OPENDHT_PYTHON "Build Python bindings" OFF) option (OPENDHT_TOOLS "Build DHT tools" ON) +option (OPENDHT_ARGON2 "Use included argon2 sources" OFF) option (OPENDHT_LTO "Build with LTO" OFF) find_package (GnuTLS 3.3 REQUIRED) @@ -26,6 +27,14 @@ find_package (Msgpack 1.2 REQUIRED) if (OPENDHT_TOOLS) find_package (Readline 6 REQUIRED) endif () +if (NOT OPENDHT_ARGON2) + find_package(PkgConfig) + pkg_search_module(argon2 libargon2) + if (NOT argon2_FOUND) + message("Argon2 not found, using included version.") + set(OPENDHT_ARGON2 ON) + endif() +endif () set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -std=c++11 -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -pedantic-errors -fvisibility=hidden") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT") @@ -61,16 +70,21 @@ list (APPEND opendht_SOURCES src/network_engine.cpp src/securedht.cpp src/dhtrunner.cpp - src/argon2/argon2.c - src/argon2/core.c - src/argon2/blake2/blake2b.c - src/argon2/thread.c - src/argon2/encoding.c - src/argon2/ref.c src/indexation/pht.cpp src/log.cpp ) +if (OPENDHT_ARGON2) + list (APPEND opendht_SOURCES + argon2/argon2.c + argon2/core.c + argon2/blake2/blake2b.c + argon2/thread.c + argon2/encoding.c + argon2/ref.c + ) +endif () + list (APPEND opendht_HEADERS include/opendht/def.h include/opendht/utils.h @@ -122,6 +136,12 @@ if (OPENDHT_STATIC) if (OPENDHT_LTO) target_link_libraries(opendht-static -flto -fuse-linker-plugin) endif () + if (OPENDHT_ARGON2) + target_include_directories(opendht-static SYSTEM PRIVATE argon2) + else () + target_link_libraries(opendht-static ${argon2_LIBRARIES}) + target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS}) + endif () target_link_libraries(opendht-static gnutls nettle) install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht) endif () @@ -137,6 +157,12 @@ if (OPENDHT_SHARED) if (OPENDHT_LTO) target_link_libraries(opendht -flto -fuse-linker-plugin) endif () + if (OPENDHT_ARGON2) + target_include_directories(opendht SYSTEM PRIVATE argon2) + else () + target_link_libraries(opendht ${argon2_LIBRARIES}) + target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS}) + endif () target_link_libraries(opendht gnutls nettle) install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht) endif () diff --git a/Makefile.am b/Makefile.am index a8835d8a..1bf729e0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,12 @@ AM_CXXFLAGS = -pthread -SUBDIRS = src +SUBDIRS = + +if WITH_INCLUDED_ARGON2 +SUBDIRS += argon2 +endif + +SUBDIRS += src if ENABLE_TOOLS SUBDIRS += tools diff --git a/src/argon2/LICENSE b/argon2/LICENSE similarity index 100% rename from src/argon2/LICENSE rename to argon2/LICENSE diff --git a/src/argon2/Makefile.am b/argon2/Makefile.am similarity index 100% rename from src/argon2/Makefile.am rename to argon2/Makefile.am diff --git a/src/argon2/argon2.c b/argon2/argon2.c similarity index 86% rename from src/argon2/argon2.c rename to argon2/argon2.c index 52fbae9b..7e2ec8ff 100644 --- a/src/argon2/argon2.c +++ b/argon2/argon2.c @@ -104,6 +104,14 @@ int argon2_hash(const uint32_t t_cost, const uint32_t m_cost, int result; uint8_t *out; + if (pwdlen > ARGON2_MAX_PWD_LENGTH) { + return ARGON2_PWD_TOO_LONG; + } + + if (saltlen > ARGON2_MAX_SALT_LENGTH) { + return ARGON2_SALT_TOO_LONG; + } + if (hashlen > ARGON2_MAX_OUTLEN) { return ARGON2_OUTPUT_TOO_LONG; } @@ -139,7 +147,7 @@ int argon2_hash(const uint32_t t_cost, const uint32_t m_cost, result = argon2_ctx(&context, type); if (result != ARGON2_OK) { - secure_wipe_memory(out, hashlen); + clear_internal_memory(out, hashlen); free(out); return result; } @@ -152,13 +160,13 @@ int argon2_hash(const uint32_t t_cost, const uint32_t m_cost, /* if encoding requested, write it */ if (encoded && encodedlen) { if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) { - secure_wipe_memory(out, hashlen); /* wipe buffers if error */ - secure_wipe_memory(encoded, encodedlen); + clear_internal_memory(out, hashlen); /* wipe buffers if error */ + clear_internal_memory(encoded, encodedlen); free(out); return ARGON2_ENCODING_FAIL; } } - secure_wipe_memory(out, hashlen); + clear_internal_memory(out, hashlen); free(out); return ARGON2_OK; @@ -238,69 +246,64 @@ int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen, argon2_type type) { argon2_context ctx; - uint8_t *out; - int ret; - int decode_result; - uint32_t encoded_len; - size_t encoded_len_tmp; + uint8_t *desired_result = NULL; - if(encoded == NULL) { + int ret = ARGON2_OK; + + size_t encoded_len; + uint32_t max_field_len; + + if (pwdlen > ARGON2_MAX_PWD_LENGTH) { + return ARGON2_PWD_TOO_LONG; + } + + if (encoded == NULL) { return ARGON2_DECODING_FAIL; } - encoded_len_tmp = strlen(encoded); - /* max values, to be updated in decode_string */ - if (UINT32_MAX < encoded_len_tmp) { + encoded_len = strlen(encoded); + if (encoded_len > UINT32_MAX) { return ARGON2_DECODING_FAIL; } - encoded_len = (uint32_t)encoded_len_tmp; - ctx.adlen = encoded_len; - ctx.saltlen = encoded_len; - ctx.outlen = encoded_len; - ctx.allocate_cbk = NULL; - ctx.free_cbk = NULL; - ctx.secret = NULL; - ctx.secretlen = 0; - ctx.pwdlen = 0; - ctx.pwd = NULL; - ctx.ad = malloc(ctx.adlen); + /* No field can be longer than the encoded length */ + max_field_len = (uint32_t)encoded_len; + + ctx.saltlen = max_field_len; + ctx.outlen = max_field_len; + ctx.salt = malloc(ctx.saltlen); ctx.out = malloc(ctx.outlen); - if (!ctx.out || !ctx.salt || !ctx.ad) { - free(ctx.ad); - free(ctx.salt); - free(ctx.out); - return ARGON2_MEMORY_ALLOCATION_ERROR; - } - out = malloc(ctx.outlen); - if (!out) { - free(ctx.ad); - free(ctx.salt); - free(ctx.out); - return ARGON2_MEMORY_ALLOCATION_ERROR; - } - decode_result = decode_string(&ctx, encoded, type); - if (decode_result != ARGON2_OK) { - free(ctx.ad); - free(ctx.salt); - free(ctx.out); - free(out); - return decode_result; + if (!ctx.salt || !ctx.out) { + ret = ARGON2_MEMORY_ALLOCATION_ERROR; + goto fail; } - ret = argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen, - ctx.salt, ctx.saltlen, out, ctx.outlen, NULL, 0, type, - ctx.version); + ctx.pwd = (uint8_t *)pwd; + ctx.pwdlen = (uint32_t)pwdlen; - free(ctx.ad); + ret = decode_string(&ctx, encoded, type); + if (ret != ARGON2_OK) { + goto fail; + } + + /* Set aside the desired result, and get a new buffer. */ + desired_result = ctx.out; + ctx.out = malloc(ctx.outlen); + if (!ctx.out) { + ret = ARGON2_MEMORY_ALLOCATION_ERROR; + goto fail; + } + + ret = argon2_verify_ctx(&ctx, (char *)desired_result, type); + if (ret != ARGON2_OK) { + goto fail; + } + +fail: free(ctx.salt); - - if (ret == ARGON2_OK && argon2_compare(out, ctx.out, ctx.outlen)) { - ret = ARGON2_VERIFY_MISMATCH; - } - free(out); free(ctx.out); + free(desired_result); return ret; } @@ -334,18 +337,16 @@ int argon2id_ctx(argon2_context *context) { int argon2_verify_ctx(argon2_context *context, const char *hash, argon2_type type) { - int result; - if (0 == context->outlen || NULL == hash) { - return ARGON2_OUT_PTR_MISMATCH; + int ret = argon2_ctx(context, type); + if (ret != ARGON2_OK) { + return ret; } - result = argon2_ctx(context, type); - - if (ARGON2_OK != result) { - return result; + if (argon2_compare((uint8_t *)hash, context->out, context->outlen)) { + return ARGON2_VERIFY_MISMATCH; } - return 0 == memcmp(hash, context->out, context->outlen); + return ARGON2_OK; } int argon2d_verify_ctx(argon2_context *context, const char *hash) { diff --git a/src/argon2/argon2.h b/argon2/argon2.h similarity index 100% rename from src/argon2/argon2.h rename to argon2/argon2.h diff --git a/src/argon2/blake2/blake2-impl.h b/argon2/blake2/blake2-impl.h similarity index 98% rename from src/argon2/blake2/blake2-impl.h rename to argon2/blake2/blake2-impl.h index 083bef48..80f97037 100644 --- a/src/argon2/blake2/blake2-impl.h +++ b/argon2/blake2/blake2-impl.h @@ -151,6 +151,6 @@ static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) { return (w >> c) | (w << (64 - c)); } -void secure_wipe_memory(void *v, size_t n); +void clear_internal_memory(void *v, size_t n); #endif diff --git a/src/argon2/blake2/blake2.h b/argon2/blake2/blake2.h similarity index 100% rename from src/argon2/blake2/blake2.h rename to argon2/blake2/blake2.h diff --git a/src/argon2/blake2/blake2b.c b/argon2/blake2/blake2b.c similarity index 96% rename from src/argon2/blake2/blake2b.c rename to argon2/blake2/blake2b.c index 603bc819..156476e7 100644 --- a/src/argon2/blake2/blake2b.c +++ b/argon2/blake2/blake2b.c @@ -61,7 +61,7 @@ static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S, } static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) { - secure_wipe_memory(S, sizeof(*S)); /* wipe */ + clear_internal_memory(S, sizeof(*S)); /* wipe */ blake2b_set_lastblock(S); /* invalidate for further use */ } @@ -157,7 +157,8 @@ int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, memset(block, 0, BLAKE2B_BLOCKBYTES); memcpy(block, key, keylen); blake2b_update(S, block, BLAKE2B_BLOCKBYTES); - secure_wipe_memory(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */ + /* Burn the key from stack */ + clear_internal_memory(block, BLAKE2B_BLOCKBYTES); } return 0; } @@ -284,9 +285,9 @@ int blake2b_final(blake2b_state *S, void *out, size_t outlen) { } memcpy(out, buffer, S->outlen); - secure_wipe_memory(buffer, sizeof(buffer)); - secure_wipe_memory(S->buf, sizeof(S->buf)); - secure_wipe_memory(S->h, sizeof(S->h)); + clear_internal_memory(buffer, sizeof(buffer)); + clear_internal_memory(S->buf, sizeof(S->buf)); + clear_internal_memory(S->h, sizeof(S->h)); return 0; } @@ -324,7 +325,7 @@ int blake2b(void *out, size_t outlen, const void *in, size_t inlen, ret = blake2b_final(&S, out, outlen); fail: - secure_wipe_memory(&S, sizeof(S)); + clear_internal_memory(&S, sizeof(S)); return ret; } @@ -382,7 +383,7 @@ int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) { memcpy(out, out_buffer, toproduce); } fail: - secure_wipe_memory(&blake_state, sizeof(blake_state)); + clear_internal_memory(&blake_state, sizeof(blake_state)); return ret; #undef TRY } diff --git a/src/argon2/blake2/blamka-round-opt.h b/argon2/blake2/blamka-round-opt.h similarity index 100% rename from src/argon2/blake2/blamka-round-opt.h rename to argon2/blake2/blamka-round-opt.h diff --git a/src/argon2/blake2/blamka-round-ref.h b/argon2/blake2/blamka-round-ref.h similarity index 100% rename from src/argon2/blake2/blamka-round-ref.h rename to argon2/blake2/blamka-round-ref.h diff --git a/src/argon2/core.c b/argon2/core.c similarity index 81% rename from src/argon2/core.c rename to argon2/core.c index ed02494a..69b2320c 100644 --- a/src/argon2/core.c +++ b/argon2/core.c @@ -82,25 +82,43 @@ static void store_block(void *output, const block *src) { } } -/***************Memory allocators*****************/ -int allocate_memory(block **memory, uint32_t m_cost) { - if (memory != NULL) { - size_t memory_size = sizeof(block) * m_cost; - if (m_cost != 0 && - memory_size / m_cost != - sizeof(block)) { /*1. Check for multiplication overflow*/ - return ARGON2_MEMORY_ALLOCATION_ERROR; - } +/***************Memory functions*****************/ - *memory = (block *)malloc(memory_size); /*2. Try to allocate*/ - - if (!*memory) { - return ARGON2_MEMORY_ALLOCATION_ERROR; - } - return ARGON2_OK; - } else { +int allocate_memory(const argon2_context *context, uint8_t **memory, + size_t num, size_t size) { + size_t memory_size = num*size; + if (memory == NULL) { return ARGON2_MEMORY_ALLOCATION_ERROR; } + + /* 1. Check for multiplication overflow */ + if (size != 0 && memory_size / size != num) { + return ARGON2_MEMORY_ALLOCATION_ERROR; + } + + /* 2. Try to allocate with appropriate allocator */ + if (context->allocate_cbk) { + (context->allocate_cbk)(memory, memory_size); + } else { + *memory = malloc(memory_size); + } + + if (*memory == NULL) { + return ARGON2_MEMORY_ALLOCATION_ERROR; + } + + return ARGON2_OK; +} + +void free_memory(const argon2_context *context, uint8_t *memory, + size_t num, size_t size) { + size_t memory_size = num*size; + clear_internal_memory(memory, memory_size); + if (context->free_cbk) { + (context->free_cbk)(memory, memory_size); + } else { + free(memory); + } } void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) { @@ -116,17 +134,14 @@ void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) { #endif } -/*********Memory functions*/ - -void clear_memory(argon2_instance_t *instance, int clear) { - if (instance->memory != NULL && clear) { - secure_wipe_memory(instance->memory, - sizeof(block) * instance->memory_blocks); - } +/* Memory clear flag defaults to true. */ +int FLAG_clear_internal_memory = 1; +void clear_internal_memory(void *v, size_t n) { + if (FLAG_clear_internal_memory && v) { + secure_wipe_memory(v, n); + } } -void free_memory(block *memory) { free(memory); } - void finalize(const argon2_context *context, argon2_instance_t *instance) { if (context != NULL && instance != NULL) { block blockhash; @@ -147,26 +162,17 @@ void finalize(const argon2_context *context, argon2_instance_t *instance) { store_block(blockhash_bytes, &blockhash); blake2b_long(context->out, context->outlen, blockhash_bytes, ARGON2_BLOCK_SIZE); - secure_wipe_memory(blockhash.v, - ARGON2_BLOCK_SIZE); /* clear blockhash */ - secure_wipe_memory(blockhash_bytes, - ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */ + /* clear blockhash and blockhash_bytes */ + clear_internal_memory(blockhash.v, ARGON2_BLOCK_SIZE); + clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); } #ifdef GENKAT print_tag(context->out, context->outlen); #endif - /* Clear memory */ - clear_memory(instance, context->flags & ARGON2_FLAG_CLEAR_PASSWORD); - - /* Deallocate the memory */ - if (NULL != context->free_cbk) { - context->free_cbk((uint8_t *)instance->memory, - instance->memory_blocks * sizeof(block)); - } else { - free_memory(instance->memory); - } + free_memory(context, (uint8_t *)instance->memory, + instance->memory_blocks, sizeof(block)); } } @@ -240,29 +246,45 @@ uint32_t index_alpha(const argon2_instance_t *instance, return absolute_position; } +/* Single-threaded version for p=1 case */ +static int fill_memory_blocks_st(argon2_instance_t *instance) { + uint32_t r, s, l; + + for (r = 0; r < instance->passes; ++r) { + for (s = 0; s < ARGON2_SYNC_POINTS; ++s) { + for (l = 0; l < instance->lanes; ++l) { + argon2_position_t position = {r, l, (uint8_t)s, 0}; + fill_segment(instance, position); + } + } +#ifdef GENKAT + internal_kat(instance, r); /* Print all memory blocks */ +#endif + } + return ARGON2_OK; +} + +#if !defined(ARGON2_NO_THREADS) + #ifdef _WIN32 static unsigned __stdcall fill_segment_thr(void *thread_data) #else static void *fill_segment_thr(void *thread_data) #endif { - argon2_thread_data *my_data = (argon2_thread_data *)thread_data; + argon2_thread_data *my_data = thread_data; fill_segment(my_data->instance_ptr, my_data->pos); argon2_thread_exit(); return 0; } -int fill_memory_blocks(argon2_instance_t *instance) { +/* Multi-threaded version for p > 1 case */ +static int fill_memory_blocks_mt(argon2_instance_t *instance) { uint32_t r, s; argon2_thread_handle_t *thread = NULL; argon2_thread_data *thr_data = NULL; int rc = ARGON2_OK; - if (instance == NULL || instance->lanes == 0) { - rc = ARGON2_THREAD_FAIL; - goto fail; - } - /* 1. Allocating space for threads */ thread = calloc(instance->lanes, sizeof(argon2_thread_handle_t)); if (thread == NULL) { @@ -336,6 +358,20 @@ fail: return rc; } +#endif /* ARGON2_NO_THREADS */ + +int fill_memory_blocks(argon2_instance_t *instance) { + if (instance == NULL || instance->lanes == 0) { + return ARGON2_INCORRECT_PARAMETER; + } +#if defined(ARGON2_NO_THREADS) + return fill_memory_blocks_st(instance); +#else + return instance->threads == 1 ? + fill_memory_blocks_st(instance) : fill_memory_blocks_mt(instance); +#endif +} + int validate_inputs(const argon2_context *context) { if (NULL == context) { return ARGON2_INCORRECT_PARAMETER; @@ -354,37 +390,37 @@ int validate_inputs(const argon2_context *context) { return ARGON2_OUTPUT_TOO_LONG; } - /* Validate password length */ + /* Validate password (required param) */ if (NULL == context->pwd) { if (0 != context->pwdlen) { return ARGON2_PWD_PTR_MISMATCH; } - } else { - if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) { - return ARGON2_PWD_TOO_SHORT; - } - - if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) { - return ARGON2_PWD_TOO_LONG; - } } - /* Validate salt length */ + if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) { + return ARGON2_PWD_TOO_SHORT; + } + + if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) { + return ARGON2_PWD_TOO_LONG; + } + + /* Validate salt (required param) */ if (NULL == context->salt) { if (0 != context->saltlen) { return ARGON2_SALT_PTR_MISMATCH; } - } else { - if (ARGON2_MIN_SALT_LENGTH > context->saltlen) { - return ARGON2_SALT_TOO_SHORT; - } - - if (ARGON2_MAX_SALT_LENGTH < context->saltlen) { - return ARGON2_SALT_TOO_LONG; - } } - /* Validate secret length */ + if (ARGON2_MIN_SALT_LENGTH > context->saltlen) { + return ARGON2_SALT_TOO_SHORT; + } + + if (ARGON2_MAX_SALT_LENGTH < context->saltlen) { + return ARGON2_SALT_TOO_LONG; + } + + /* Validate secret (optional param) */ if (NULL == context->secret) { if (0 != context->secretlen) { return ARGON2_SECRET_PTR_MISMATCH; @@ -393,13 +429,12 @@ int validate_inputs(const argon2_context *context) { if (ARGON2_MIN_SECRET > context->secretlen) { return ARGON2_SECRET_TOO_SHORT; } - if (ARGON2_MAX_SECRET < context->secretlen) { return ARGON2_SECRET_TOO_LONG; } } - /* Validate associated data */ + /* Validate associated data (optional param) */ if (NULL == context->ad) { if (0 != context->adlen) { return ARGON2_AD_PTR_MISMATCH; @@ -408,7 +443,6 @@ int validate_inputs(const argon2_context *context) { if (ARGON2_MIN_AD_LENGTH > context->adlen) { return ARGON2_AD_TOO_SHORT; } - if (ARGON2_MAX_AD_LENGTH < context->adlen) { return ARGON2_AD_TOO_LONG; } @@ -467,8 +501,8 @@ int validate_inputs(const argon2_context *context) { void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) { uint32_t l; - /* Make the first and second block in each lane as G(H0||i||0) or - G(H0||i||1) */ + /* Make the first and second block in each lane as G(H0||0||i) or + G(H0||1||i) */ uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; for (l = 0; l < instance->lanes; ++l) { @@ -485,7 +519,7 @@ void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) { load_block(&instance->memory[l * instance->lane_length + 1], blockhash_bytes); } - secure_wipe_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); + clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); } void initial_hash(uint8_t *blockhash, argon2_context *context, @@ -568,22 +602,13 @@ int initialize(argon2_instance_t *instance, argon2_context *context) { if (instance == NULL || context == NULL) return ARGON2_INCORRECT_PARAMETER; + instance->context_ptr = context; /* 1. Memory allocation */ - - if (NULL != context->allocate_cbk) { - uint8_t *p; - result = context->allocate_cbk(&p, instance->memory_blocks * - ARGON2_BLOCK_SIZE); - if (ARGON2_OK != result) { - return result; - } - instance->memory = (block *)p; - } else { - result = allocate_memory(&(instance->memory), instance->memory_blocks); - if (ARGON2_OK != result) { - return result; - } + result = allocate_memory(context, (uint8_t **)&(instance->memory), + instance->memory_blocks, sizeof(block)); + if (result != ARGON2_OK) { + return result; } /* 2. Initial hashing */ @@ -592,9 +617,9 @@ int initialize(argon2_instance_t *instance, argon2_context *context) { /* Hashing all inputs */ initial_hash(blockhash, context, instance->type); /* Zeroing 8 extra bytes */ - secure_wipe_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, - ARGON2_PREHASH_SEED_LENGTH - - ARGON2_PREHASH_DIGEST_LENGTH); + clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, + ARGON2_PREHASH_SEED_LENGTH - + ARGON2_PREHASH_DIGEST_LENGTH); #ifdef GENKAT initial_kat(blockhash, context, instance->type); @@ -604,7 +629,7 @@ int initialize(argon2_instance_t *instance, argon2_context *context) { */ fill_first_blocks(blockhash, instance); /* Clearing the hash */ - secure_wipe_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH); + clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH); return ARGON2_OK; } diff --git a/src/argon2/core.h b/argon2/core.h similarity index 80% rename from src/argon2/core.h rename to argon2/core.h index f5c2d437..a73a01f3 100644 --- a/src/argon2/core.h +++ b/argon2/core.h @@ -30,8 +30,7 @@ #define CONST_CAST(x) (x)(uintptr_t) -/*************************Argon2 internal - * constants**************************************************/ +/**********************Argon2 internal constants*******************************/ enum argon2_core_constants { /* Memory block size in bytes */ @@ -49,8 +48,7 @@ enum argon2_core_constants { ARGON2_PREHASH_SEED_LENGTH = 72 }; -/*************************Argon2 internal data - * types**************************************************/ +/*************************Argon2 internal data types***********************/ /* * Structure for the (1KB) memory block implemented as 128 64-bit words. @@ -87,6 +85,7 @@ typedef struct Argon2_instance_t { uint32_t threads; argon2_type type; int print_internals; /* whether to print the memory blocks */ + argon2_context *context_ptr; /* points back to original context */ } argon2_instance_t; /* @@ -106,32 +105,43 @@ typedef struct Argon2_thread_data { argon2_position_t pos; } argon2_thread_data; -/*************************Argon2 core - * functions**************************************************/ +/*************************Argon2 core functions********************************/ -/* Allocates memory to the given pointer +/* Allocates memory to the given pointer, uses the appropriate allocator as + * specified in the context. Total allocated memory is num*size. + * @param context argon2_context which specifies the allocator * @param memory pointer to the pointer to the memory - * @param m_cost number of blocks to allocate in the memory + * @param size the size in bytes for each element to be allocated + * @param num the number of elements to be allocated * @return ARGON2_OK if @memory is a valid pointer and memory is allocated */ -int allocate_memory(block **memory, uint32_t m_cost); +int allocate_memory(const argon2_context *context, uint8_t **memory, + size_t num, size_t size); -/* Function that securely cleans the memory +/* + * Frees memory at the given pointer, uses the appropriate deallocator as + * specified in the context. Also cleans the memory using clear_internal_memory. + * @param context argon2_context which specifies the deallocator + * @param memory pointer to buffer to be freed + * @param size the size in bytes for each element to be deallocated + * @param num the number of elements to be deallocated + */ +void free_memory(const argon2_context *context, uint8_t *memory, + size_t num, size_t size); + +/* Function that securely cleans the memory. This ignores any flags set + * regarding clearing memory. Usually one just calls clear_internal_memory. * @param mem Pointer to the memory * @param s Memory size in bytes */ void secure_wipe_memory(void *v, size_t n); -/* Clears memory - * @param instance pointer to the current instance - * @param clear_memory indicates if we clear the memory with zeros. +/* Function that securely clears the memory if FLAG_clear_internal_memory is + * set. If the flag isn't set, this function does nothing. + * @param mem Pointer to the memory + * @param s Memory size in bytes */ -void clear_memory(argon2_instance_t *instance, int clear); - -/* Deallocates memory - * @param memory pointer to the blocks - */ -void free_memory(block *memory); +void clear_internal_memory(void *v, size_t n); /* * Computes absolute position of reference block in the lane following a skewed @@ -205,6 +215,7 @@ void finalize(const argon2_context *context, argon2_instance_t *instance); /* * Function that fills the segment using previous segments also from other * threads + * @param context current context * @param instance Pointer to the current instance * @param position Current position * @pre all block pointers must be valid diff --git a/src/argon2/encoding.c b/argon2/encoding.c similarity index 89% rename from src/argon2/encoding.c rename to argon2/encoding.c index 2fc8d547..4fd965b2 100644 --- a/src/argon2/encoding.c +++ b/argon2/encoding.c @@ -39,11 +39,6 @@ * the parameters, salts and outputs. It does not compute the hash * itself. * - * -- The third section is test code, with a main() function. With - * this section, the whole file compiles as a stand-alone program - * that exercises the encoding and decoding functions with some - * test vectors. - * * The code was originally written by Thomas Pornin , * to whom comments and remarks may be sent. It is released under what * should amount to Public Domain or its closest equivalent; the @@ -246,19 +241,18 @@ static const char *decode_decimal(const char *str, unsigned long *v) { * * The code below applies the following format: * - * $argon2[$v=]$m=,t=,p=[,keyid=][,data=][$[$]] + * $argon2[$v=]$m=,t=,p=$$ * - * where is either 'd' or 'i', is a decimal integer (positive, fits in - * an 'unsigned long'), and is Base64-encoded data (no '=' padding + * where is either 'd', 'id', or 'i', is a decimal integer (positive, + * fits in an 'unsigned long'), and is Base64-encoded data (no '=' padding * characters, no newline or whitespace). - * The "keyid" is a binary identifier for a key (up to 8 bytes); - * "data" is associated data (up to 32 bytes). When the 'keyid' - * (resp. the 'data') is empty, then it is ommitted from the output. * * The last two binary chunks (encoded in Base64) are, in that order, - * the salt and the output. Both are optional, but you cannot have an - * output without a salt. The binary salt length is between 8 and 48 bytes. - * The output length is always exactly 32 bytes. + * the salt and the output. Both are required. The binary salt length and the + * output length must be in the allowed ranges defined in argon2.h. + * + * The ctx struct must contain buffers large enough to hold the salt and pwd + * when it is fed into decode_string. */ int decode_string(argon2_context *ctx, const char *str, argon2_type type) { @@ -273,7 +267,7 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) { str += cc_len; \ } while ((void)0, 0) -/* prefix checking with supplied code */ +/* optional prefix checking with supplied code */ #define CC_opt(prefix, code) \ do { \ size_t cc_len = strlen(prefix); \ @@ -283,7 +277,7 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) { } \ } while ((void)0, 0) -/* Decoding prefix into decimal */ +/* Decoding prefix into decimal */ #define DECIMAL(x) \ do { \ unsigned long dec_x; \ @@ -294,6 +288,7 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) { (x) = dec_x; \ } while ((void)0, 0) +/* Decoding base64 into a binary buffer */ #define BIN(buf, max_len, len) \ do { \ size_t bin_len = (max_len); \ @@ -304,26 +299,20 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) { (len) = (uint32_t)bin_len; \ } while ((void)0, 0) - size_t maxadlen = ctx->adlen; size_t maxsaltlen = ctx->saltlen; size_t maxoutlen = ctx->outlen; int validation_result; const char* type_string; - ctx->adlen = 0; - ctx->saltlen = 0; - ctx->outlen = 0; - ctx->pwdlen = 0; - /* We should start with the argon2_type we are using */ - CC("$"); type_string = argon2_type2string(type, 0); - if (type_string) { - CC(type_string); - } else { + if (!type_string) { return ARGON2_INCORRECT_TYPE; } + CC("$"); + CC(type_string); + /* Reading the version number if the default is suppressed */ ctx->version = ARGON2_VERSION_10; CC_opt("$v=", DECIMAL(ctx->version)); @@ -336,21 +325,27 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) { DECIMAL(ctx->lanes); ctx->threads = ctx->lanes; - CC_opt(",data=", BIN(ctx->ad, maxadlen, ctx->adlen)); - if (*str == 0) { - return ARGON2_OK; - } CC("$"); BIN(ctx->salt, maxsaltlen, ctx->saltlen); - if (*str == 0) { - return ARGON2_OK; - } CC("$"); BIN(ctx->out, maxoutlen, ctx->outlen); + + /* The rest of the fields get the default values */ + ctx->secret = NULL; + ctx->secretlen = 0; + ctx->ad = NULL; + ctx->adlen = 0; + ctx->allocate_cbk = NULL; + ctx->free_cbk = NULL; + ctx->flags = ARGON2_DEFAULT_FLAGS; + + /* On return, must have valid context */ validation_result = validate_inputs(ctx); if (validation_result != ARGON2_OK) { return validation_result; } + + /* Can't have any additional characters */ if (*str == 0) { return ARGON2_OK; } else { @@ -393,19 +388,23 @@ int encode_string(char *dst, size_t dst_len, argon2_context *ctx, } while ((void)0, 0) const char* type_string = argon2_type2string(type, 0); - SS("$"); - if (type_string) { - SS(type_string); - } else { - return ARGON2_ENCODING_FAIL; + int validation_result = validate_inputs(ctx); + + if (!type_string) { + return ARGON2_ENCODING_FAIL; } - if (validate_inputs(ctx) != ARGON2_OK) { - return validate_inputs(ctx); + if (validation_result != ARGON2_OK) { + return validation_result; } + + SS("$"); + SS(type_string); + SS("$v="); SX(ctx->version); + SS("$m="); SX(ctx->m_cost); SS(",t="); @@ -413,20 +412,9 @@ int encode_string(char *dst, size_t dst_len, argon2_context *ctx, SS(",p="); SX(ctx->lanes); - if (ctx->adlen > 0) { - SS(",data="); - SB(ctx->ad, ctx->adlen); - } - - if (ctx->saltlen == 0) - return ARGON2_OK; - SS("$"); SB(ctx->salt, ctx->saltlen); - if (ctx->outlen == 0) - return ARGON2_OK; - SS("$"); SB(ctx->out, ctx->outlen); return ARGON2_OK; diff --git a/src/argon2/encoding.h b/argon2/encoding.h similarity index 80% rename from src/argon2/encoding.h rename to argon2/encoding.h index f652dfa0..1c1ec8b9 100644 --- a/src/argon2/encoding.h +++ b/argon2/encoding.h @@ -29,21 +29,21 @@ * is less than the number of required characters (including the * terminating 0), then this function returns ARGON2_ENCODING_ERROR. * -* if ctx->outlen is 0, then the hash string will be a salt string -* (no output). if ctx->saltlen is also 0, then the string will be a -* parameter-only string (no salt and no output). -* * on success, ARGON2_OK is returned. -* -* No other parameters are checked */ int encode_string(char *dst, size_t dst_len, argon2_context *ctx, argon2_type type); /* * Decodes an Argon2 hash string into the provided structure 'ctx'. -* The fields ctx.saltlen, ctx.adlen, ctx.outlen set the maximal salt, ad, out -* length values that are allowed; invalid input string causes an error. +* The only fields that must be set prior to this call are ctx.saltlen and +* ctx.outlen (which must be the maximal salt and out length values that are +* allowed), ctx.salt and ctx.out (which must be buffers of the specified +* length), and ctx.pwd and ctx.pwdlen which must hold a valid password. +* +* Invalid input string causes an error. On success, the ctx is valid and all +* fields have been initialized. +* * Returned value is ARGON2_OK on success, other ARGON2_ codes on error. */ int decode_string(argon2_context *ctx, const char *str, argon2_type type); diff --git a/src/argon2/opt.c b/argon2/opt.c similarity index 54% rename from src/argon2/opt.c rename to argon2/opt.c index ab2cb6a2..2315a087 100644 --- a/src/argon2/opt.c +++ b/argon2/opt.c @@ -20,18 +20,37 @@ #include #include "argon2.h" -#include "opt.h" +#include "core.h" #include "blake2/blake2.h" #include "blake2/blamka-round-opt.h" -void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) { +/* + * Function fills a new memory block and optionally XORs the old block over the new one. + * Memory must be initialized. + * @param state Pointer to the just produced block. Content will be updated(!) + * @param ref_block Pointer to the reference block + * @param next_block Pointer to the block to be XORed over. May coincide with @ref_block + * @param with_xor Whether to XOR into the new block (1) or just overwrite (0) + * @pre all block pointers must be valid + */ +static void fill_block(__m128i *state, const block *ref_block, + block *next_block, int with_xor) { __m128i block_XY[ARGON2_OWORDS_IN_BLOCK]; - uint32_t i; + unsigned int i; - for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { - block_XY[i] = state[i] = _mm_xor_si128( - state[i], _mm_loadu_si128((__m128i const *)(&ref_block[16 * i]))); + if (with_xor) { + for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { + state[i] = _mm_xor_si128( + state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i)); + block_XY[i] = _mm_xor_si128( + state[i], _mm_loadu_si128((const __m128i *)next_block->v + i)); + } + } else { + for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { + block_XY[i] = state[i] = _mm_xor_si128( + state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i)); + } } for (i = 0; i < 8; ++i) { @@ -48,93 +67,38 @@ void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) { for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { state[i] = _mm_xor_si128(state[i], block_XY[i]); - _mm_storeu_si128((__m128i *)(&next_block[16 * i]), state[i]); + _mm_storeu_si128((__m128i *)next_block->v + i, state[i]); } } -void fill_block_with_xor(__m128i *state, const uint8_t *ref_block, - uint8_t *next_block) { - __m128i block_XY[ARGON2_OWORDS_IN_BLOCK]; - uint32_t i; +static void next_addresses(block *address_block, block *input_block) { + /*Temporary zero-initialized blocks*/ + __m128i zero_block[ARGON2_OWORDS_IN_BLOCK]; + __m128i zero2_block[ARGON2_OWORDS_IN_BLOCK]; - for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { - state[i] = _mm_xor_si128( - state[i], _mm_loadu_si128((__m128i const *)(&ref_block[16 * i]))); - block_XY[i] = _mm_xor_si128( - state[i], _mm_loadu_si128((__m128i const *)(&next_block[16 * i]))); - } + memset(zero_block, 0, sizeof(zero_block)); + memset(zero2_block, 0, sizeof(zero2_block)); - for (i = 0; i < 8; ++i) { - BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], - state[8 * i + 3], state[8 * i + 4], state[8 * i + 5], - state[8 * i + 6], state[8 * i + 7]); - } + /*Increasing index counter*/ + input_block->v[6]++; - for (i = 0; i < 8; ++i) { - BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i], - state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i], - state[8 * 6 + i], state[8 * 7 + i]); - } + /*First iteration of G*/ + fill_block(zero_block, input_block, address_block, 0); - for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { - state[i] = _mm_xor_si128(state[i], block_XY[i]); - _mm_storeu_si128((__m128i *)(&next_block[16 * i]), state[i]); - } -} - -void generate_addresses(const argon2_instance_t *instance, - const argon2_position_t *position, - uint64_t *pseudo_rands) { - block address_block, input_block, tmp_block; - uint32_t i; - - init_block_value(&address_block, 0); - init_block_value(&input_block, 0); - - if (instance != NULL && position != NULL) { - input_block.v[0] = position->pass; - input_block.v[1] = position->lane; - input_block.v[2] = position->slice; - input_block.v[3] = instance->memory_blocks; - input_block.v[4] = instance->passes; - input_block.v[5] = instance->type; - - for (i = 0; i < instance->segment_length; ++i) { - if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) { - /*Temporary zero-initialized blocks*/ - __m128i zero_block[ARGON2_OWORDS_IN_BLOCK]; - __m128i zero2_block[ARGON2_OWORDS_IN_BLOCK]; - memset(zero_block, 0, sizeof(zero_block)); - memset(zero2_block, 0, sizeof(zero2_block)); - init_block_value(&address_block, 0); - init_block_value(&tmp_block, 0); - /*Increasing index counter*/ - input_block.v[6]++; - /*First iteration of G*/ - fill_block_with_xor(zero_block, (uint8_t *)&input_block.v, - (uint8_t *)&tmp_block.v); - /*Second iteration of G*/ - fill_block_with_xor(zero2_block, (uint8_t *)&tmp_block.v, - (uint8_t *)&address_block.v); - } - - pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK]; - } - } + /*Second iteration of G*/ + fill_block(zero2_block, address_block, address_block, 0); } void fill_segment(const argon2_instance_t *instance, argon2_position_t position) { block *ref_block = NULL, *curr_block = NULL; + block address_block, input_block; uint64_t pseudo_rand, ref_index, ref_lane; uint32_t prev_offset, curr_offset; uint32_t starting_index, i; __m128i state[64]; int data_independent_addressing; - /* Pseudo-random values that determine the reference block position */ - uint64_t *pseudo_rands = NULL; - if (instance == NULL) { return; } @@ -144,20 +108,26 @@ void fill_segment(const argon2_instance_t *instance, (instance->type == Argon2_id && (position.pass == 0) && (position.slice < ARGON2_SYNC_POINTS / 2)); - pseudo_rands = - (uint64_t *)malloc(sizeof(uint64_t) * instance->segment_length); - if (pseudo_rands == NULL) { - return; - } - if (data_independent_addressing) { - generate_addresses(instance, &position, pseudo_rands); + init_block_value(&input_block, 0); + + input_block.v[0] = position.pass; + input_block.v[1] = position.lane; + input_block.v[2] = position.slice; + input_block.v[3] = instance->memory_blocks; + input_block.v[4] = instance->passes; + input_block.v[5] = instance->type; } starting_index = 0; if ((0 == position.pass) && (0 == position.slice)) { starting_index = 2; /* we have already generated the first two blocks */ + + /* Don't forget to generate the first block of addresses: */ + if (data_independent_addressing) { + next_addresses(&address_block, &input_block); + } } /* Offset of the current block */ @@ -184,7 +154,10 @@ void fill_segment(const argon2_instance_t *instance, /* 1.2 Computing the index of the reference block */ /* 1.2.1 Taking pseudo-random value from the previous block */ if (data_independent_addressing) { - pseudo_rand = pseudo_rands[i]; + if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) { + next_addresses(&address_block, &input_block); + } + pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK]; } else { pseudo_rand = instance->memory[prev_offset].v[0]; } @@ -210,18 +183,13 @@ void fill_segment(const argon2_instance_t *instance, curr_block = instance->memory + curr_offset; if (ARGON2_VERSION_10 == instance->version) { /* version 1.2.1 and earlier: overwrite, not XOR */ - fill_block(state, (uint8_t *)ref_block->v, - (uint8_t *)curr_block->v); + fill_block(state, ref_block, curr_block, 0); } else { if(0 == position.pass) { - fill_block(state, (uint8_t *)ref_block->v, - (uint8_t *)curr_block->v); + fill_block(state, ref_block, curr_block, 0); } else { - fill_block_with_xor(state, (uint8_t *)ref_block->v, - (uint8_t *)curr_block->v); + fill_block(state, ref_block, curr_block, 1); } } } - - free(pseudo_rands); } diff --git a/src/argon2/opt.h b/argon2/opt.h similarity index 100% rename from src/argon2/opt.h rename to argon2/opt.h diff --git a/src/argon2/ref.c b/argon2/ref.c similarity index 60% rename from src/argon2/ref.c rename to argon2/ref.c index 0b086c38..4dbd1e5a 100644 --- a/src/argon2/ref.c +++ b/argon2/ref.c @@ -20,61 +20,38 @@ #include #include "argon2.h" -#include "ref.h" +#include "core.h" #include "blake2/blamka-round-ref.h" #include "blake2/blake2-impl.h" #include "blake2/blake2.h" -void fill_block(const block *prev_block, const block *ref_block, - block *next_block) { +/* + * Function fills a new memory block and optionally XORs the old block over the new one. + * @next_block must be initialized. + * @param prev_block Pointer to the previous block + * @param ref_block Pointer to the reference block + * @param next_block Pointer to the block to be constructed + * @param with_xor Whether to XOR into the new block (1) or just overwrite (0) + * @pre all block pointers must be valid + */ +static void fill_block(const block *prev_block, const block *ref_block, + block *next_block, int with_xor) { block blockR, block_tmp; unsigned i; copy_block(&blockR, ref_block); xor_block(&blockR, prev_block); copy_block(&block_tmp, &blockR); - /*Now blockR = ref_block + prev_block and bloc_tmp = ref_block + prev_block */ - /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then - (16,17,..31)... finally (112,113,...127) */ - for (i = 0; i < 8; ++i) { - BLAKE2_ROUND_NOMSG( - blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2], - blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5], - blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8], - blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11], - blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14], - blockR.v[16 * i + 15]); + /* Now blockR = ref_block + prev_block and block_tmp = ref_block + prev_block */ + if (with_xor) { + /* Saving the next block contents for XOR over: */ + xor_block(&block_tmp, next_block); + /* Now blockR = ref_block + prev_block and + block_tmp = ref_block + prev_block + next_block */ } - /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then - (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */ - for (i = 0; i < 8; i++) { - BLAKE2_ROUND_NOMSG( - blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16], - blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33], - blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64], - blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81], - blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112], - blockR.v[2 * i + 113]); - } - - copy_block(next_block, &block_tmp); - xor_block(next_block, &blockR); -} - - -void fill_block_with_xor(const block *prev_block, const block *ref_block, - block *next_block) { - block blockR, block_tmp; - unsigned i; - - copy_block(&blockR, ref_block); - xor_block(&blockR, prev_block); - copy_block(&block_tmp, &blockR); - xor_block(&block_tmp, next_block); /*Saving the next block contents for XOR over*/ - /*Now blockR = ref_block + prev_block and bloc_tmp = ref_block + prev_block + next_block*/ /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then (16,17,..31)... finally (112,113,...127) */ for (i = 0; i < 8; ++i) { @@ -103,47 +80,22 @@ void fill_block_with_xor(const block *prev_block, const block *ref_block, xor_block(next_block, &blockR); } -void generate_addresses(const argon2_instance_t *instance, - const argon2_position_t *position, - uint64_t *pseudo_rands) { - block zero_block, input_block, address_block,tmp_block; - uint32_t i; - - init_block_value(&zero_block, 0); - init_block_value(&input_block, 0); - - if (instance != NULL && position != NULL) { - input_block.v[0] = position->pass; - input_block.v[1] = position->lane; - input_block.v[2] = position->slice; - input_block.v[3] = instance->memory_blocks; - input_block.v[4] = instance->passes; - input_block.v[5] = instance->type; - - for (i = 0; i < instance->segment_length; ++i) { - if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) { - input_block.v[6]++; - init_block_value(&tmp_block, 0); - init_block_value(&address_block, 0); - fill_block_with_xor(&zero_block, &input_block, &tmp_block); - fill_block_with_xor(&zero_block, &tmp_block, &address_block); - } - - pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK]; - } - } +static void next_addresses(block *address_block, block *input_block, + const block *zero_block) { + input_block->v[6]++; + fill_block(zero_block, input_block, address_block, 0); + fill_block(zero_block, address_block, address_block, 0); } void fill_segment(const argon2_instance_t *instance, argon2_position_t position) { block *ref_block = NULL, *curr_block = NULL; + block address_block, input_block, zero_block; uint64_t pseudo_rand, ref_index, ref_lane; uint32_t prev_offset, curr_offset; uint32_t starting_index; uint32_t i; int data_independent_addressing; - /* Pseudo-random values that determine the reference block position */ - uint64_t *pseudo_rands = NULL; if (instance == NULL) { return; @@ -154,21 +106,27 @@ void fill_segment(const argon2_instance_t *instance, (instance->type == Argon2_id && (position.pass == 0) && (position.slice < ARGON2_SYNC_POINTS / 2)); - pseudo_rands = - (uint64_t *)malloc(sizeof(uint64_t) * (instance->segment_length)); - - if (pseudo_rands == NULL) { - return; - } - if (data_independent_addressing) { - generate_addresses(instance, &position, pseudo_rands); + init_block_value(&zero_block, 0); + init_block_value(&input_block, 0); + + input_block.v[0] = position.pass; + input_block.v[1] = position.lane; + input_block.v[2] = position.slice; + input_block.v[3] = instance->memory_blocks; + input_block.v[4] = instance->passes; + input_block.v[5] = instance->type; } starting_index = 0; if ((0 == position.pass) && (0 == position.slice)) { starting_index = 2; /* we have already generated the first two blocks */ + + /* Don't forget to generate the first block of addresses: */ + if (data_independent_addressing) { + next_addresses(&address_block, &input_block, &zero_block); + } } /* Offset of the current block */ @@ -193,7 +151,10 @@ void fill_segment(const argon2_instance_t *instance, /* 1.2 Computing the index of the reference block */ /* 1.2.1 Taking pseudo-random value from the previous block */ if (data_independent_addressing) { - pseudo_rand = pseudo_rands[i]; + if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) { + next_addresses(&address_block, &input_block, &zero_block); + } + pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK]; } else { pseudo_rand = instance->memory[prev_offset].v[0]; } @@ -219,17 +180,15 @@ void fill_segment(const argon2_instance_t *instance, curr_block = instance->memory + curr_offset; if (ARGON2_VERSION_10 == instance->version) { /* version 1.2.1 and earlier: overwrite, not XOR */ - fill_block(instance->memory + prev_offset, ref_block, curr_block); + fill_block(instance->memory + prev_offset, ref_block, curr_block, 0); } else { if(0 == position.pass) { fill_block(instance->memory + prev_offset, ref_block, - curr_block); + curr_block, 0); } else { - fill_block_with_xor(instance->memory + prev_offset, ref_block, - curr_block); + fill_block(instance->memory + prev_offset, ref_block, + curr_block, 1); } } } - - free(pseudo_rands); } diff --git a/src/argon2/ref.h b/argon2/ref.h similarity index 100% rename from src/argon2/ref.h rename to argon2/ref.h diff --git a/src/argon2/thread.c b/argon2/thread.c similarity index 95% rename from src/argon2/thread.c rename to argon2/thread.c index 5de2c133..13a9b426 100644 --- a/src/argon2/thread.c +++ b/argon2/thread.c @@ -15,6 +15,8 @@ * software. If not, they may be obtained at the above URLs. */ +#if !defined(ARGON2_NO_THREADS) + #include "thread.h" #if defined(_WIN32) #include @@ -51,3 +53,5 @@ void argon2_thread_exit(void) { pthread_exit(NULL); #endif } + +#endif /* ARGON2_NO_THREADS */ diff --git a/src/argon2/thread.h b/argon2/thread.h similarity index 97% rename from src/argon2/thread.h rename to argon2/thread.h index f04bb407..ecbd41dc 100644 --- a/src/argon2/thread.h +++ b/argon2/thread.h @@ -17,6 +17,9 @@ #ifndef ARGON2_THREAD_H #define ARGON2_THREAD_H + +#if !defined(ARGON2_NO_THREADS) + /* Here we implement an abstraction layer for the simpĺe requirements of the Argon2 code. We only require 3 primitives---thread creation, @@ -60,4 +63,5 @@ int argon2_thread_join(argon2_thread_handle_t handle); */ void argon2_thread_exit(void); +#endif /* ARGON2_NO_THREADS */ #endif diff --git a/configure.ac b/configure.ac index ddef5aa6..6f4fb127 100644 --- a/configure.ac +++ b/configure.ac @@ -99,6 +99,24 @@ PKG_CHECK_MODULES([GnuTLS], [gnutls >= 3.3]) PKG_CHECK_MODULES([MsgPack], [msgpack >= 1.2]) CXXFLAGS="${CXXFLAGS} -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT" +dnl Check for Argon2 +AC_ARG_WITH([argon2], AS_HELP_STRING([--without-argon2], [Use included Argon2])) +AS_IF([test "x$with_argon2" != "xno"], + [PKG_CHECK_MODULES([Argon2], [libargon2], [have_argon2=yes], [have_argon2=no])], + [have_argon2=no]) +AS_IF([test "x$have_argon2" = "xyes"], [], [ + AS_IF([test "x$with_argon2" = "xyes"], [ + AC_MSG_ERROR([Argon2 requested but not found]) + ],[ + AC_MSG_NOTICE([Using included Argon2]) + AC_CONFIG_FILES(argon2/Makefile) + AC_SUBST(Argon2_CFLAGS, "-I\${top_srcdir}/argon2") + AC_SUBST(Argon2_LIBS, "\${top_srcdir}/argon2/libargon2.la") + ]) +]) + +AM_CONDITIONAL([WITH_INCLUDED_ARGON2], [test "x$have_argon2" = "xno"]) + AC_ARG_ENABLE([tools], AS_HELP_STRING([--disable-tools],[Disable tools (CLI DHT node)]),,build_tools=yes) AM_CONDITIONAL(ENABLE_TOOLS, test x$build_tools == xyes) AM_COND_IF([ENABLE_TOOLS], [ @@ -120,7 +138,6 @@ AM_COND_IF([USE_CYTHON], [ AC_CONFIG_FILES([Makefile src/Makefile - src/argon2/Makefile tools/Makefile opendht.pc]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index d0d77ed1..29545131 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,11 +1,7 @@ -SUBDIRS = argon2 - lib_LTLIBRARIES = libopendht.la -AM_CPPFLAGS = -I../include/opendht -libopendht_la_CXXFLAGS = @CXXFLAGS@ -libopendht_la_LDFLAGS = @LDFLAGS@ @GnuTLS_LIBS@ @Nettle_LIBS@ -libopendht_la_LIBADD = ./argon2/libargon2.la +libopendht_la_CPPFLAGS = @CPPFLAGS@ -I$(top_srcdir)/include/opendht @Argon2_CFLAGS@ +libopendht_la_LIBADD = @Argon2_LIBS@ @GnuTLS_LIBS@ @Nettle_LIBS@ libopendht_la_SOURCES = \ dht.cpp \ diff --git a/src/crypto.cpp b/src/crypto.cpp index 14337ad3..fee9a394 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -27,7 +27,7 @@ extern "C" { #include #include -#include "argon2/argon2.h" +#include } #include diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index b4f21563..0539e3b0 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -3,9 +3,9 @@ add_executable (dhtnode dhtnode.cpp tools_common.h) add_executable (dhtscanner dhtscanner.cpp tools_common.h) add_executable (dhtchat dhtchat.cpp tools_common.h) -target_link_libraries (dhtnode LINK_PUBLIC gnutls readline) -target_link_libraries (dhtscanner LINK_PUBLIC gnutls readline) -target_link_libraries (dhtchat LINK_PUBLIC gnutls readline) +target_link_libraries (dhtnode LINK_PUBLIC readline) +target_link_libraries (dhtscanner LINK_PUBLIC readline) +target_link_libraries (dhtchat LINK_PUBLIC readline) if (OPENDHT_SHARED) target_link_libraries (dhtnode LINK_PUBLIC opendht)