Home | History | Annotate | Line # | Download | only in argon2
      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