argon2-core.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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. #ifndef argon2_core_H
  14. #define argon2_core_H
  15. #include <string.h>
  16. #include "argon2.h"
  17. /*************************Argon2 internal
  18. * constants**************************************************/
  19. enum argon2_ctx_constants {
  20. /* Version of the algorithm */
  21. ARGON2_VERSION_NUMBER = 0x13,
  22. /* Memory block size in bytes */
  23. ARGON2_BLOCK_SIZE = 1024,
  24. ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
  25. ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
  26. ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32,
  27. ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64,
  28. /* Number of pseudo-random values generated by one call to Blake in Argon2i
  29. to
  30. generate reference block positions */
  31. ARGON2_ADDRESSES_IN_BLOCK = 128,
  32. /* Pre-hashing digest length and its extension*/
  33. ARGON2_PREHASH_DIGEST_LENGTH = 64,
  34. ARGON2_PREHASH_SEED_LENGTH = 72
  35. };
  36. /*************************Argon2 internal data
  37. * types**************************************************/
  38. /*
  39. * Structure for the (1KB) memory block implemented as 128 64-bit words.
  40. * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
  41. * bounds checking).
  42. */
  43. typedef struct block_ {
  44. uint64_t v[ARGON2_QWORDS_IN_BLOCK];
  45. } block;
  46. typedef struct block_region_ {
  47. void * base;
  48. block *memory;
  49. size_t size;
  50. } block_region;
  51. /*****************Functions that work with the block******************/
  52. /* Initialize each byte of the block with @in */
  53. static inline void
  54. init_block_value(block *b, uint8_t in)
  55. {
  56. memset(b->v, in, sizeof(b->v));
  57. }
  58. /* Copy block @src to block @dst */
  59. static inline void
  60. copy_block(block *dst, const block *src)
  61. {
  62. memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
  63. }
  64. /* XOR @src onto @dst bytewise */
  65. static inline void
  66. xor_block(block *dst, const block *src)
  67. {
  68. int i;
  69. for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
  70. dst->v[i] ^= src->v[i];
  71. }
  72. }
  73. /*
  74. * Argon2 instance: memory pointer, number of passes, amount of memory, type,
  75. * and derived values.
  76. * Used to evaluate the number and location of blocks to construct in each
  77. * thread
  78. */
  79. typedef struct Argon2_instance_t {
  80. block_region *region; /* Memory region pointer */
  81. uint64_t *pseudo_rands;
  82. uint32_t passes; /* Number of passes */
  83. uint32_t current_pass;
  84. uint32_t memory_blocks; /* Number of blocks in memory */
  85. uint32_t segment_length;
  86. uint32_t lane_length;
  87. uint32_t lanes;
  88. uint32_t threads;
  89. argon2_type type;
  90. int print_internals; /* whether to print the memory blocks */
  91. } argon2_instance_t;
  92. /*
  93. * Argon2 position: where we construct the block right now. Used to distribute
  94. * work between threads.
  95. */
  96. typedef struct Argon2_position_t {
  97. uint32_t pass;
  98. uint32_t lane;
  99. uint8_t slice;
  100. uint32_t index;
  101. } argon2_position_t;
  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. /*************************Argon2 core
  108. * functions**************************************************/
  109. /*
  110. * Computes absolute position of reference block in the lane following a skewed
  111. * distribution and using a pseudo-random value as input
  112. * @param instance Pointer to the current instance
  113. * @param position Pointer to the current position
  114. * @param pseudo_rand 32-bit pseudo-random value used to determine the position
  115. * @param same_lane Indicates if the block will be taken from the current lane.
  116. * If so we can reference the current segment
  117. * @pre All pointers must be valid
  118. */
  119. static uint32_t index_alpha(const argon2_instance_t *instance,
  120. const argon2_position_t *position, uint32_t pseudo_rand,
  121. int same_lane)
  122. {
  123. /*
  124. * Pass 0:
  125. * This lane : all already finished segments plus already constructed
  126. * blocks in this segment
  127. * Other lanes : all already finished segments
  128. * Pass 1+:
  129. * This lane : (SYNC_POINTS - 1) last segments plus already constructed
  130. * blocks in this segment
  131. * Other lanes : (SYNC_POINTS - 1) last segments
  132. */
  133. uint32_t reference_area_size;
  134. uint64_t relative_position;
  135. uint32_t start_position, absolute_position;
  136. if (position->pass == 0) {
  137. /* First pass */
  138. if (position->slice == 0) {
  139. /* First slice */
  140. reference_area_size =
  141. position->index - 1; /* all but the previous */
  142. } else {
  143. if (same_lane) {
  144. /* The same lane => add current segment */
  145. reference_area_size =
  146. position->slice * instance->segment_length +
  147. position->index - 1;
  148. } else {
  149. reference_area_size =
  150. position->slice * instance->segment_length +
  151. ((position->index == 0) ? (-1) : 0);
  152. }
  153. }
  154. } else {
  155. /* Second pass */
  156. if (same_lane) {
  157. reference_area_size = instance->lane_length -
  158. instance->segment_length + position->index -
  159. 1;
  160. } else {
  161. reference_area_size = instance->lane_length -
  162. instance->segment_length +
  163. ((position->index == 0) ? (-1) : 0);
  164. }
  165. }
  166. /* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
  167. * relative position */
  168. relative_position = pseudo_rand;
  169. relative_position = relative_position * relative_position >> 32;
  170. relative_position = reference_area_size - 1 -
  171. (reference_area_size * relative_position >> 32);
  172. /* 1.2.5 Computing starting position */
  173. start_position = 0;
  174. if (position->pass != 0) {
  175. start_position = (position->slice == ARGON2_SYNC_POINTS - 1)
  176. ? 0
  177. : (position->slice + 1) * instance->segment_length;
  178. }
  179. /* 1.2.6. Computing absolute position */
  180. absolute_position = (start_position + relative_position) %
  181. instance->lane_length; /* absolute position */
  182. return absolute_position;
  183. }
  184. /*
  185. * Function that validates all inputs against predefined restrictions and return
  186. * an error code
  187. * @param context Pointer to current Argon2 context
  188. * @return ARGON2_OK if everything is all right, otherwise one of error codes
  189. * (all defined in <argon2.h>
  190. */
  191. int argon2_validate_inputs(const argon2_context *context);
  192. /*
  193. * Function allocates memory, hashes the inputs with Blake, and creates first
  194. * two blocks. Returns the pointer to the main memory with 2 blocks per lane
  195. * initialized
  196. * @param context Pointer to the Argon2 internal structure containing memory
  197. * pointer, and parameters for time and space requirements.
  198. * @param instance Current Argon2 instance
  199. * @return Zero if successful, -1 if memory failed to allocate. @context->state
  200. * will be modified if successful.
  201. */
  202. int argon2_initialize(argon2_instance_t *instance, argon2_context *context);
  203. /*
  204. * XORing the last block of each lane, hashing it, making the tag. Deallocates
  205. * the memory.
  206. * @param context Pointer to current Argon2 context (use only the out parameters
  207. * from it)
  208. * @param instance Pointer to current instance of Argon2
  209. * @pre instance->state must point to necessary amount of memory
  210. * @pre context->out must point to outlen bytes of memory
  211. * @pre if context->free_cbk is not NULL, it should point to a function that
  212. * deallocates memory
  213. */
  214. void argon2_finalize(const argon2_context *context,
  215. argon2_instance_t *instance);
  216. /*
  217. * Function that fills the segment using previous segments also from other
  218. * threads
  219. * @param instance Pointer to the current instance
  220. * @param position Current position
  221. * @pre all block pointers must be valid
  222. */
  223. typedef void (*fill_segment_fn)(const argon2_instance_t *instance,
  224. argon2_position_t position);
  225. void argon2_fill_segment_avx512f(const argon2_instance_t *instance,
  226. argon2_position_t position);
  227. void argon2_fill_segment_avx2(const argon2_instance_t *instance,
  228. argon2_position_t position);
  229. void argon2_fill_segment_ssse3(const argon2_instance_t *instance,
  230. argon2_position_t position);
  231. void argon2_fill_segment_ref(const argon2_instance_t *instance,
  232. argon2_position_t position);
  233. /*
  234. * Function that fills the entire memory t_cost times based on the first two
  235. * blocks in each lane
  236. * @param instance Pointer to the current instance
  237. * @return Zero if successful, -1 if memory failed to allocate
  238. */
  239. void argon2_fill_memory_blocks(argon2_instance_t *instance, uint32_t pass);
  240. #endif