/* * Argon2 source code package * * Written by Daniel Dinu and Dmitry Khovratovich, 2015 * * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. * * You should have received a copy of the CC0 Public Domain Dedication along * with * this software. If not, see * . */ #ifndef argon2_core_H #define argon2_core_H #include #include "argon2.h" /*************************Argon2 internal * constants**************************************************/ enum argon2_ctx_constants { /* Version of the algorithm */ ARGON2_VERSION_NUMBER = 0x13, /* Memory block size in bytes */ ARGON2_BLOCK_SIZE = 1024, ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8, ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16, ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32, ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64, /* Number of pseudo-random values generated by one call to Blake in Argon2i to generate reference block positions */ ARGON2_ADDRESSES_IN_BLOCK = 128, /* Pre-hashing digest length and its extension*/ ARGON2_PREHASH_DIGEST_LENGTH = 64, ARGON2_PREHASH_SEED_LENGTH = 72 }; /*************************Argon2 internal data * types**************************************************/ /* * Structure for the (1KB) memory block implemented as 128 64-bit words. * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no * bounds checking). */ typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block; typedef struct block_region_ { void * base; block *memory; size_t size; } block_region; /*****************Functions that work with the block******************/ /* Initialize each byte of the block with @in */ static inline void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); } /* Copy block @src to block @dst */ static inline void copy_block(block *dst, const block *src) { memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK); } /* XOR @src onto @dst bytewise */ static inline void xor_block(block *dst, const block *src) { int i; for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { dst->v[i] ^= src->v[i]; } } /* * Argon2 instance: memory pointer, number of passes, amount of memory, type, * and derived values. * Used to evaluate the number and location of blocks to construct in each * thread */ 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; uint32_t lane_length; uint32_t lanes; uint32_t threads; argon2_type type; int print_internals; /* whether to print the memory blocks */ } argon2_instance_t; /* * Argon2 position: where we construct the block right now. Used to distribute * work between threads. */ typedef struct Argon2_position_t { uint32_t pass; uint32_t lane; uint8_t slice; uint32_t index; } argon2_position_t; /*Struct that holds the inputs for thread handling FillSegment*/ typedef struct Argon2_thread_data { argon2_instance_t *instance_ptr; argon2_position_t pos; } argon2_thread_data; /*************************Argon2 core * functions**************************************************/ /* * Computes absolute position of reference block in the lane following a skewed * distribution and using a pseudo-random value as input * @param instance Pointer to the current instance * @param position Pointer to the current position * @param pseudo_rand 32-bit pseudo-random value used to determine the position * @param same_lane Indicates if the block will be taken from the current lane. * If so we can reference the current segment * @pre All pointers must be valid */ uint32_t index_alpha(const argon2_instance_t *instance, const argon2_position_t *position, uint32_t pseudo_rand, int same_lane); /* * Function that validates all inputs against predefined restrictions and return * an error code * @param context Pointer to current Argon2 context * @return ARGON2_OK if everything is all right, otherwise one of error codes * (all defined in */ int validate_inputs(const argon2_context *context); /* * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears * password and secret if needed * @param context Pointer to the Argon2 internal structure containing memory * pointer, and parameters for time and space requirements. * @param blockhash Buffer for pre-hashing digest * @param type Argon2 type * @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes * allocated */ void initial_hash(uint8_t *blockhash, argon2_context *context, argon2_type type); /* * Function creates first 2 blocks per lane * @param instance Pointer to the current instance * @param blockhash Pointer to the pre-hashing digest * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values */ void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance); /* * Function allocates memory, hashes the inputs with Blake, and creates first * two blocks. Returns the pointer to the main memory with 2 blocks per lane * initialized * @param context Pointer to the Argon2 internal structure containing memory * pointer, and parameters for time and space requirements. * @param instance Current Argon2 instance * @return Zero if successful, -1 if memory failed to allocate. @context->state * will be modified if successful. */ 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. * @param context Pointer to current Argon2 context (use only the out parameters * from it) * @param instance Pointer to current instance of Argon2 * @pre instance->state must point to necessary amount of memory * @pre context->out must point to outlen bytes of memory * @pre if context->free_cbk is not NULL, it should point to a function that * deallocates memory */ void finalize(const argon2_context *context, argon2_instance_t *instance); /* * Function that fills the segment using previous segments also from other * threads * @param instance Pointer to the current instance * @param position Current position * @pre all block pointers must be valid */ typedef void (*fill_segment_fn)(const argon2_instance_t *instance, argon2_position_t position); int argon2_pick_best_implementation(void); void fill_segment_avx512f(const argon2_instance_t *instance, argon2_position_t position); void fill_segment_avx2(const argon2_instance_t *instance, argon2_position_t position); void fill_segment_ssse3(const argon2_instance_t *instance, argon2_position_t position); void fill_segment_ref(const argon2_instance_t *instance, argon2_position_t position); /* * Function that fills the entire memory t_cost times based on the first two * blocks in each lane * @param instance Pointer to the current instance * @return Zero if successful, -1 if memory failed to allocate */ void fill_memory_blocks(argon2_instance_t *instance); #endif