1 /* 2 * Argon2 source code package 3 * 4 * Written by Daniel Dinu and Dmitry Khovratovich, 2015 5 * 6 * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. 7 * 8 * You should have received a copy of the CC0 Public Domain Dedication along 9 * with 10 * this software. If not, see 11 * <http://creativecommons.org/publicdomain/zero/1.0/>. 12 */ 13 14 #ifndef argon2_core_H 15 #define argon2_core_H 16 17 #include <string.h> 18 19 #include "argon2.h" 20 21 /*************************Argon2 internal 22 * constants**************************************************/ 23 24 enum argon2_ctx_constants { 25 /* Version of the algorithm */ 26 ARGON2_VERSION_NUMBER = 0x13, 27 28 /* Memory block size in bytes */ 29 ARGON2_BLOCK_SIZE = 1024, 30 ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8, 31 ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16, 32 ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32, 33 ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64, 34 35 /* Number of pseudo-random values generated by one call to Blake in Argon2i 36 to 37 generate reference block positions */ 38 ARGON2_ADDRESSES_IN_BLOCK = 128, 39 40 /* Pre-hashing digest length and its extension*/ 41 ARGON2_PREHASH_DIGEST_LENGTH = 64, 42 ARGON2_PREHASH_SEED_LENGTH = 72 43 }; 44 45 /*************************Argon2 internal data 46 * types**************************************************/ 47 48 /* 49 * Structure for the (1KB) memory block implemented as 128 64-bit words. 50 * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no 51 * bounds checking). 52 */ 53 typedef struct block_ { 54 uint64_t v[ARGON2_QWORDS_IN_BLOCK]; 55 } block; 56 57 typedef struct block_region_ { 58 void * base; 59 block *memory; 60 size_t size; 61 } block_region; 62 63 /*****************Functions that work with the block******************/ 64 65 /* Initialize each byte of the block with @in */ 66 static inline void 67 init_block_value(block *b, uint8_t in) 68 { 69 memset(b->v, in, sizeof(b->v)); 70 } 71 72 /* Copy block @src to block @dst */ 73 static inline void 74 copy_block(block *dst, const block *src) 75 { 76 memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK); 77 } 78 79 /* XOR @src onto @dst bytewise */ 80 static inline void 81 xor_block(block *dst, const block *src) 82 { 83 int i; 84 for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { 85 dst->v[i] ^= src->v[i]; 86 } 87 } 88 89 /* 90 * Argon2 instance: memory pointer, number of passes, amount of memory, type, 91 * and derived values. 92 * Used to evaluate the number and location of blocks to construct in each 93 * thread 94 */ 95 typedef struct Argon2_instance_t { 96 block_region *region; /* Memory region pointer */ 97 uint64_t *pseudo_rands; 98 uint32_t passes; /* Number of passes */ 99 uint32_t current_pass; 100 uint32_t memory_blocks; /* Number of blocks in memory */ 101 uint32_t segment_length; 102 uint32_t lane_length; 103 uint32_t lanes; 104 uint32_t threads; 105 argon2_type type; 106 int print_internals; /* whether to print the memory blocks */ 107 } argon2_instance_t; 108 109 /* 110 * Argon2 position: where we construct the block right now. Used to distribute 111 * work between threads. 112 */ 113 typedef struct Argon2_position_t { 114 uint32_t pass; 115 uint32_t lane; 116 uint8_t slice; 117 uint32_t index; 118 } argon2_position_t; 119 120 /*Struct that holds the inputs for thread handling FillSegment*/ 121 typedef struct Argon2_thread_data { 122 argon2_instance_t *instance_ptr; 123 argon2_position_t pos; 124 } argon2_thread_data; 125 126 /*************************Argon2 core 127 * functions**************************************************/ 128 129 /* 130 * Computes absolute position of reference block in the lane following a skewed 131 * distribution and using a pseudo-random value as input 132 * @param instance Pointer to the current instance 133 * @param position Pointer to the current position 134 * @param pseudo_rand 32-bit pseudo-random value used to determine the position 135 * @param same_lane Indicates if the block will be taken from the current lane. 136 * If so we can reference the current segment 137 * @pre All pointers must be valid 138 */ 139 static uint32_t index_alpha(const argon2_instance_t *instance, 140 const argon2_position_t *position, uint32_t pseudo_rand, 141 int same_lane) 142 { 143 /* 144 * Pass 0: 145 * This lane : all already finished segments plus already constructed 146 * blocks in this segment 147 * Other lanes : all already finished segments 148 * Pass 1+: 149 * This lane : (SYNC_POINTS - 1) last segments plus already constructed 150 * blocks in this segment 151 * Other lanes : (SYNC_POINTS - 1) last segments 152 */ 153 uint32_t reference_area_size; 154 uint64_t relative_position; 155 uint32_t start_position, absolute_position; 156 157 if (position->pass == 0) { 158 /* First pass */ 159 if (position->slice == 0) { 160 /* First slice */ 161 reference_area_size = 162 position->index - 1; /* all but the previous */ 163 } else { 164 if (same_lane) { 165 /* The same lane => add current segment */ 166 reference_area_size = 167 position->slice * instance->segment_length + 168 position->index - 1; 169 } else { 170 reference_area_size = 171 position->slice * instance->segment_length + 172 ((position->index == 0) ? (-1) : 0); 173 } 174 } 175 } else { 176 /* Second pass */ 177 if (same_lane) { 178 reference_area_size = instance->lane_length - 179 instance->segment_length + position->index - 180 1; 181 } else { 182 reference_area_size = instance->lane_length - 183 instance->segment_length + 184 ((position->index == 0) ? (-1) : 0); 185 } 186 } 187 188 /* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce 189 * relative position */ 190 relative_position = pseudo_rand; 191 relative_position = relative_position * relative_position >> 32; 192 relative_position = reference_area_size - 1 - 193 (reference_area_size * relative_position >> 32); 194 195 /* 1.2.5 Computing starting position */ 196 start_position = 0; 197 198 if (position->pass != 0) { 199 start_position = (position->slice == ARGON2_SYNC_POINTS - 1) 200 ? 0 201 : (position->slice + 1) * instance->segment_length; 202 } 203 204 /* 1.2.6. Computing absolute position */ 205 absolute_position = (start_position + relative_position) % 206 instance->lane_length; /* absolute position */ 207 return absolute_position; 208 } 209 210 /* 211 * Function that validates all inputs against predefined restrictions and return 212 * an error code 213 * @param context Pointer to current Argon2 context 214 * @return ARGON2_OK if everything is all right, otherwise one of error codes 215 * (all defined in <argon2.h> 216 */ 217 int validate_inputs(const argon2_context *context); 218 219 /* 220 * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears 221 * password and secret if needed 222 * @param context Pointer to the Argon2 internal structure containing memory 223 * pointer, and parameters for time and space requirements. 224 * @param blockhash Buffer for pre-hashing digest 225 * @param type Argon2 type 226 * @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes 227 * allocated 228 */ 229 void initial_hash(uint8_t *blockhash, argon2_context *context, 230 argon2_type type); 231 232 /* 233 * Function creates first 2 blocks per lane 234 * @param instance Pointer to the current instance 235 * @param blockhash Pointer to the pre-hashing digest 236 * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values 237 */ 238 void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance); 239 240 /* 241 * Function allocates memory, hashes the inputs with Blake, and creates first 242 * two blocks. Returns the pointer to the main memory with 2 blocks per lane 243 * initialized 244 * @param context Pointer to the Argon2 internal structure containing memory 245 * pointer, and parameters for time and space requirements. 246 * @param instance Current Argon2 instance 247 * @return Zero if successful, -1 if memory failed to allocate. @context->state 248 * will be modified if successful. 249 */ 250 int initialize(argon2_instance_t *instance, argon2_context *context); 251 252 /* 253 * Deallocates memory. Used on error path. 254 */ 255 void free_instance(argon2_instance_t *instance, int flags); 256 257 /* 258 * XORing the last block of each lane, hashing it, making the tag. Deallocates 259 * the memory. 260 * @param context Pointer to current Argon2 context (use only the out parameters 261 * from it) 262 * @param instance Pointer to current instance of Argon2 263 * @pre instance->state must point to necessary amount of memory 264 * @pre context->out must point to outlen bytes of memory 265 * @pre if context->free_cbk is not NULL, it should point to a function that 266 * deallocates memory 267 */ 268 void finalize(const argon2_context *context, argon2_instance_t *instance); 269 270 /* 271 * Function that fills the segment using previous segments also from other 272 * threads 273 * @param instance Pointer to the current instance 274 * @param position Current position 275 * @pre all block pointers must be valid 276 */ 277 typedef void (*fill_segment_fn)(const argon2_instance_t *instance, 278 argon2_position_t position); 279 int argon2_pick_best_implementation(void); 280 void fill_segment_avx512f(const argon2_instance_t *instance, 281 argon2_position_t position); 282 void fill_segment_avx2(const argon2_instance_t *instance, 283 argon2_position_t position); 284 void fill_segment_ssse3(const argon2_instance_t *instance, 285 argon2_position_t position); 286 void fill_segment_ref(const argon2_instance_t *instance, 287 argon2_position_t position); 288 289 /* 290 * Function that fills the entire memory t_cost times based on the first two 291 * blocks in each lane 292 * @param instance Pointer to the current instance 293 * @return Zero if successful, -1 if memory failed to allocate 294 */ 295 void fill_memory_blocks(argon2_instance_t *instance, uint32_t pass); 296 297 #endif 298