1 /* 2 * Argon2 reference source code package - reference C implementations 3 * 4 * Copyright 2015 5 * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves 6 * 7 * You may use this work under the terms of a Creative Commons CC0 1.0 8 * License/Waiver or the Apache Public License 2.0, at your option. The terms of 9 * these licenses can be found at: 10 * 11 * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 12 * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * You should have received a copy of both of these licenses along with this 15 * software. If not, they may be obtained at the above URLs. 16 */ 17 18 #ifndef ARGON2_CORE_H 19 #define ARGON2_CORE_H 20 21 #include "argon2.h" 22 23 #if defined(_MSC_VER) 24 #define ALIGN(n) __declspec(align(16)) 25 #elif defined(__GNUC__) || defined(__clang) 26 #define ALIGN(x) __attribute__((__aligned__(x))) 27 #else 28 #define ALIGN(x) 29 #endif 30 31 #define CONST_CAST(x) (x)(uintptr_t) 32 33 /**********************Argon2 internal constants*******************************/ 34 35 enum argon2_core_constants { 36 /* Memory block size in bytes */ 37 ARGON2_BLOCK_SIZE = 1024, 38 ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8, 39 ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16, 40 41 /* Number of pseudo-random values generated by one call to Blake in Argon2i 42 to 43 generate reference block positions */ 44 ARGON2_ADDRESSES_IN_BLOCK = 128, 45 46 /* Pre-hashing digest length and its extension*/ 47 ARGON2_PREHASH_DIGEST_LENGTH = 64, 48 ARGON2_PREHASH_SEED_LENGTH = 72 49 }; 50 51 /*************************Argon2 internal data types***********************/ 52 53 /* 54 * Structure for the (1KB) memory block implemented as 128 64-bit words. 55 * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no 56 * bounds checking). 57 */ 58 typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block; 59 60 /*****************Functions that work with the block******************/ 61 62 /* Initialize each byte of the block with @in */ 63 static void init_block_value(block *b, uint8_t in); 64 65 /* Copy block @src to block @dst */ 66 static void copy_block(block *dst, const block *src); 67 68 /* XOR @src onto @dst bytewise */ 69 static void xor_block(block *dst, const block *src); 70 71 /* 72 * Argon2 instance: memory pointer, number of passes, amount of memory, type, 73 * and derived values. 74 * Used to evaluate the number and location of blocks to construct in each 75 * thread 76 */ 77 typedef struct Argon2_instance_t { 78 block *memory; /* Memory pointer */ 79 uint32_t version; 80 uint32_t passes; /* Number of passes */ 81 uint32_t memory_blocks; /* Number of blocks in memory */ 82 uint32_t segment_length; 83 uint32_t lane_length; 84 uint32_t lanes; 85 uint32_t threads; 86 argon2_type type; 87 int print_internals; /* whether to print the memory blocks */ 88 argon2_context *context_ptr; /* points back to original context */ 89 } argon2_instance_t; 90 91 /* 92 * Argon2 position: where we construct the block right now. Used to distribute 93 * work between threads. 94 */ 95 typedef struct Argon2_position_t { 96 uint32_t pass; 97 uint32_t lane; 98 uint8_t slice; 99 uint32_t index; 100 } argon2_position_t; 101 102 /*Struct that holds the inputs for thread handling FillSegment*/ 103 typedef struct Argon2_thread_data { 104 argon2_instance_t *instance_ptr; 105 argon2_position_t pos; 106 } argon2_thread_data; 107 108 /*************************Argon2 core functions********************************/ 109 110 /* Allocates memory to the given pointer, uses the appropriate allocator as 111 * specified in the context. Total allocated memory is num*size. 112 * @param context argon2_context which specifies the allocator 113 * @param memory pointer to the pointer to the memory 114 * @param size the size in bytes for each element to be allocated 115 * @param num the number of elements to be allocated 116 * @return ARGON2_OK if @memory is a valid pointer and memory is allocated 117 */ 118 static int allocate_memory(const argon2_context *context, uint8_t **memory, 119 size_t num, size_t size); 120 121 /* 122 * Frees memory at the given pointer, uses the appropriate deallocator as 123 * specified in the context. Also cleans the memory using clear_internal_memory. 124 * @param context argon2_context which specifies the deallocator 125 * @param memory pointer to buffer to be freed 126 * @param size the size in bytes for each element to be deallocated 127 * @param num the number of elements to be deallocated 128 */ 129 static void free_memory(const argon2_context *context, uint8_t *memory, 130 size_t num, size_t size); 131 132 /* Function that securely cleans the memory. This ignores any flags set 133 * regarding clearing memory. Usually one just calls clear_internal_memory. 134 * @param mem Pointer to the memory 135 * @param s Memory size in bytes 136 */ 137 static void secure_wipe_memory(void *v, size_t n); 138 139 /* Function that securely clears the memory if FLAG_clear_internal_memory is 140 * set. If the flag isn't set, this function does nothing. 141 * @param mem Pointer to the memory 142 * @param s Memory size in bytes 143 */ 144 static void clear_internal_memory(void *v, size_t n); 145 146 /* 147 * Computes absolute position of reference block in the lane following a skewed 148 * distribution and using a pseudo-random value as input 149 * @param instance Pointer to the current instance 150 * @param position Pointer to the current position 151 * @param pseudo_rand 32-bit pseudo-random value used to determine the position 152 * @param same_lane Indicates if the block will be taken from the current lane. 153 * If so we can reference the current segment 154 * @pre All pointers must be valid 155 */ 156 static uint32_t index_alpha(const argon2_instance_t *instance, 157 const argon2_position_t *position, uint32_t pseudo_rand, 158 int same_lane); 159 160 /* 161 * Function that validates all inputs against predefined restrictions and return 162 * an error code 163 * @param context Pointer to current Argon2 context 164 * @return ARGON2_OK if everything is all right, otherwise one of error codes 165 * (all defined in <argon2.h> 166 */ 167 static int validate_inputs(const argon2_context *context); 168 169 /* 170 * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears 171 * password and secret if needed 172 * @param context Pointer to the Argon2 internal structure containing memory 173 * pointer, and parameters for time and space requirements. 174 * @param blockhash Buffer for pre-hashing digest 175 * @param type Argon2 type 176 * @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes 177 * allocated 178 */ 179 static void initial_hash(uint8_t *blockhash, argon2_context *context, 180 argon2_type type); 181 182 /* 183 * Function creates first 2 blocks per lane 184 * @param instance Pointer to the current instance 185 * @param blockhash Pointer to the pre-hashing digest 186 * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values 187 */ 188 static void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance); 189 190 /* 191 * Function allocates memory, hashes the inputs with Blake, and creates first 192 * two blocks. Returns the pointer to the main memory with 2 blocks per lane 193 * initialized 194 * @param context Pointer to the Argon2 internal structure containing memory 195 * pointer, and parameters for time and space requirements. 196 * @param instance Current Argon2 instance 197 * @return Zero if successful, -1 if memory failed to allocate. @context->state 198 * will be modified if successful. 199 */ 200 static int initialize(argon2_instance_t *instance, argon2_context *context); 201 202 /* 203 * XORing the last block of each lane, hashing it, making the tag. Deallocates 204 * the memory. 205 * @param context Pointer to current Argon2 context (use only the out parameters 206 * from it) 207 * @param instance Pointer to current instance of Argon2 208 * @pre instance->state must point to necessary amount of memory 209 * @pre context->out must point to outlen bytes of memory 210 * @pre if context->free_cbk is not NULL, it should point to a function that 211 * deallocates memory 212 */ 213 static void finalize(const argon2_context *context, argon2_instance_t *instance); 214 215 /* 216 * Function that fills the segment using previous segments also from other 217 * threads 218 * @param context current context 219 * @param instance Pointer to the current instance 220 * @param position Current position 221 * @pre all block pointers must be valid 222 */ 223 static void fill_segment(const argon2_instance_t *instance, 224 argon2_position_t position); 225 226 /* 227 * Function that fills the entire memory t_cost times based on the first two 228 * blocks in each lane 229 * @param instance Pointer to the current instance 230 * @return ARGON2_OK if successful, @context->state 231 */ 232 static int fill_memory_blocks(argon2_instance_t *instance); 233 234 #endif 235