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 #include <errno.h>
     15 #include <stdint.h>
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 #include <string.h>
     19 
     20 #include <sys/types.h>
     21 #ifdef HAVE_SYS_MMAN_H
     22 # include <sys/mman.h>
     23 #endif
     24 
     25 #include "crypto_generichash_blake2b.h"
     26 #include "private/common.h"
     27 #include "private/implementations.h"
     28 #include "runtime.h"
     29 #include "utils.h"
     30 
     31 #include "argon2-core.h"
     32 #include "blake2b-long.h"
     33 
     34 #if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
     35 # define MAP_ANON MAP_ANONYMOUS
     36 #endif
     37 #ifndef MAP_NOCORE
     38 # define MAP_NOCORE 0
     39 #endif
     40 #ifndef MAP_POPULATE
     41 # define MAP_POPULATE 0
     42 #endif
     43 
     44 static fill_segment_fn fill_segment = fill_segment_ref;
     45 
     46 static void
     47 load_block(block *dst, const void *input)
     48 {
     49     unsigned i;
     50     for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
     51         dst->v[i] = LOAD64_LE((const uint8_t *) input + i * sizeof(dst->v[i]));
     52     }
     53 }
     54 
     55 static void
     56 store_block(void *output, const block *src)
     57 {
     58     unsigned i;
     59     for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
     60         STORE64_LE((uint8_t *) output + i * sizeof(src->v[i]), src->v[i]);
     61     }
     62 }
     63 
     64 /***************Memory allocators*****************/
     65 /* Allocates memory to the given pointer
     66  * @param memory pointer to the pointer to the memory
     67  * @param m_cost number of blocks to allocate in the memory
     68  * @return ARGON2_OK if @memory is a valid pointer and memory is allocated
     69  */
     70 static int allocate_memory(block_region **memory, uint32_t m_cost);
     71 
     72 static int
     73 allocate_memory(block_region **region, uint32_t m_cost)
     74 {
     75     void * base;
     76     block *memory;
     77     size_t memory_size;
     78 
     79     if (region == NULL) {
     80         return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
     81     }
     82     memory_size = sizeof(block) * m_cost;
     83     if (m_cost == 0 ||
     84         memory_size / m_cost !=
     85             sizeof(block)) { /*1. Check for multiplication overflow*/
     86         return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
     87     }
     88     *region = (block_region *) malloc(
     89         sizeof(block_region)); /*2. Try to allocate region*/
     90     if (!*region) {
     91         return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
     92     }
     93     (*region)->base = (*region)->memory = NULL;
     94 
     95 #if defined(MAP_ANON) && defined(HAVE_MMAP)
     96     if ((base = mmap(NULL, memory_size, PROT_READ | PROT_WRITE,
     97                      MAP_ANON | MAP_PRIVATE | MAP_NOCORE | MAP_POPULATE,
     98                      -1, 0)) == MAP_FAILED) {
     99         base = NULL; /* LCOV_EXCL_LINE */
    100     }                /* LCOV_EXCL_LINE */
    101     memcpy(&memory, &base, sizeof memory);
    102 #elif defined(HAVE_POSIX_MEMALIGN)
    103     if ((errno = posix_memalign((void **) &base, 64, memory_size)) != 0) {
    104         base = NULL;
    105     }
    106     memcpy(&memory, &base, sizeof memory);
    107 #else
    108     memory = NULL;
    109     if (memory_size + 63 < memory_size) {
    110         base  = NULL;
    111         errno = ENOMEM;
    112     } else if ((base = malloc(memory_size + 63)) != NULL) {
    113         uint8_t *aligned = ((uint8_t *) base) + 63;
    114         aligned -= (uintptr_t) aligned & 63;
    115         memcpy(&memory, &aligned, sizeof memory);
    116     }
    117 #endif
    118     if (base == NULL) {
    119         return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
    120     }
    121     (*region)->base   = base;
    122     (*region)->memory = memory;
    123     (*region)->size   = memory_size;
    124 
    125     return ARGON2_OK;
    126 }
    127 
    128 /*********Memory functions*/
    129 
    130 /* Clears memory
    131  * @param instance pointer to the current instance
    132  * @param clear_memory indicates if we clear the memory with zeros.
    133  */
    134 static void clear_memory(argon2_instance_t *instance, int clear);
    135 
    136 static void
    137 clear_memory(argon2_instance_t *instance, int clear)
    138 {
    139     /* LCOV_EXCL_START */
    140     if (clear) {
    141         if (instance->region != NULL) {
    142             sodium_memzero(instance->region->memory,
    143                            sizeof(block) * instance->memory_blocks);
    144         }
    145         if (instance->pseudo_rands != NULL) {
    146             sodium_memzero(instance->pseudo_rands,
    147                            sizeof(uint64_t) * instance->segment_length);
    148         }
    149     }
    150     /* LCOV_EXCL_STOP */
    151 }
    152 
    153 /* Deallocates memory
    154  * @param memory pointer to the blocks
    155  */
    156 static void free_memory(block_region *memory);
    157 
    158 static void
    159 free_memory(block_region *region)
    160 {
    161     if (region && region->base) {
    162 #if defined(MAP_ANON) && defined(HAVE_MMAP)
    163         if (munmap(region->base, region->size)) {
    164             return; /* LCOV_EXCL_LINE */
    165         }
    166 #else
    167         free(region->base);
    168 #endif
    169     }
    170     free(region);
    171 }
    172 
    173 void
    174 free_instance(argon2_instance_t *instance, int flags)
    175 {
    176     /* Clear memory */
    177     clear_memory(instance, flags & ARGON2_FLAG_CLEAR_MEMORY);
    178 
    179     /* Deallocate the memory */
    180     free(instance->pseudo_rands);
    181     instance->pseudo_rands = NULL;
    182     free_memory(instance->region);
    183     instance->region = NULL;
    184 }
    185 
    186 void
    187 finalize(const argon2_context *context, argon2_instance_t *instance)
    188 {
    189     if (context != NULL && instance != NULL) {
    190         block    blockhash;
    191         uint32_t l;
    192 
    193         copy_block(&blockhash,
    194                    instance->region->memory + instance->lane_length - 1);
    195 
    196         /* XOR the last blocks */
    197         for (l = 1; l < instance->lanes; ++l) {
    198             uint32_t last_block_in_lane =
    199                 l * instance->lane_length + (instance->lane_length - 1);
    200             xor_block(&blockhash,
    201                       instance->region->memory + last_block_in_lane);
    202         }
    203 
    204         /* Hash the result */
    205         {
    206             uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
    207             store_block(blockhash_bytes, &blockhash);
    208             blake2b_long(context->out, context->outlen, blockhash_bytes,
    209                          ARGON2_BLOCK_SIZE);
    210             sodium_memzero(blockhash.v,
    211                            ARGON2_BLOCK_SIZE); /* clear blockhash */
    212             sodium_memzero(blockhash_bytes,
    213                            ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */
    214         }
    215 
    216         free_instance(instance, context->flags);
    217     }
    218 }
    219 
    220 void
    221 fill_memory_blocks(argon2_instance_t *instance, uint32_t pass)
    222 {
    223     argon2_position_t position;
    224     uint32_t l;
    225     uint32_t s;
    226 
    227     if (instance == NULL || instance->lanes == 0) {
    228         return; /* LCOV_EXCL_LINE */
    229     }
    230 
    231     position.pass = pass;
    232     for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
    233         position.slice = (uint8_t) s;
    234         for (l = 0; l < instance->lanes; ++l) {
    235             position.lane  = l;
    236             position.index = 0;
    237             fill_segment(instance, position);
    238         }
    239     }
    240 }
    241 
    242 int
    243 validate_inputs(const argon2_context *context)
    244 {
    245     /* LCOV_EXCL_START */
    246     if (NULL == context) {
    247         return ARGON2_INCORRECT_PARAMETER;
    248     }
    249 
    250     if (NULL == context->out) {
    251         return ARGON2_OUTPUT_PTR_NULL;
    252     }
    253 
    254     /* Validate output length */
    255     if (ARGON2_MIN_OUTLEN > context->outlen) {
    256         return ARGON2_OUTPUT_TOO_SHORT;
    257     }
    258 
    259     if (ARGON2_MAX_OUTLEN < context->outlen) {
    260         return ARGON2_OUTPUT_TOO_LONG;
    261     }
    262 
    263     /* Validate password (required param) */
    264     if (NULL == context->pwd) {
    265         if (0 != context->pwdlen) {
    266             return ARGON2_PWD_PTR_MISMATCH;
    267         }
    268     }
    269 
    270     if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
    271         return ARGON2_PWD_TOO_SHORT;
    272     }
    273 
    274     if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
    275         return ARGON2_PWD_TOO_LONG;
    276     }
    277 
    278     /* Validate salt (required param) */
    279     if (NULL == context->salt) {
    280         if (0 != context->saltlen) {
    281             return ARGON2_SALT_PTR_MISMATCH;
    282         }
    283     }
    284 
    285     if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
    286         return ARGON2_SALT_TOO_SHORT;
    287     }
    288 
    289     if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
    290         return ARGON2_SALT_TOO_LONG;
    291     }
    292 
    293     /* Validate secret (optional param) */
    294     if (NULL == context->secret) {
    295         if (0 != context->secretlen) {
    296             return ARGON2_SECRET_PTR_MISMATCH;
    297         }
    298     } else {
    299         if (ARGON2_MIN_SECRET > context->secretlen) {
    300             return ARGON2_SECRET_TOO_SHORT;
    301         }
    302 
    303         if (ARGON2_MAX_SECRET < context->secretlen) {
    304             return ARGON2_SECRET_TOO_LONG;
    305         }
    306     }
    307 
    308     /* Validate associated data (optional param) */
    309     if (NULL == context->ad) {
    310         if (0 != context->adlen) {
    311             return ARGON2_AD_PTR_MISMATCH;
    312         }
    313     } else {
    314         if (ARGON2_MIN_AD_LENGTH > context->adlen) {
    315             return ARGON2_AD_TOO_SHORT;
    316         }
    317 
    318         if (ARGON2_MAX_AD_LENGTH < context->adlen) {
    319             return ARGON2_AD_TOO_LONG;
    320         }
    321     }
    322 
    323     /* Validate memory cost */
    324     if (ARGON2_MIN_MEMORY > context->m_cost) {
    325         return ARGON2_MEMORY_TOO_LITTLE;
    326     }
    327 
    328     if (ARGON2_MAX_MEMORY < context->m_cost) {
    329         return ARGON2_MEMORY_TOO_MUCH;
    330     }
    331 
    332     if (context->m_cost < 8 * context->lanes) {
    333         return ARGON2_MEMORY_TOO_LITTLE;
    334     }
    335 
    336     /* Validate time cost */
    337     if (ARGON2_MIN_TIME > context->t_cost) {
    338         return ARGON2_TIME_TOO_SMALL;
    339     }
    340 
    341     if (ARGON2_MAX_TIME < context->t_cost) {
    342         return ARGON2_TIME_TOO_LARGE;
    343     }
    344 
    345     /* Validate lanes */
    346     if (ARGON2_MIN_LANES > context->lanes) {
    347         return ARGON2_LANES_TOO_FEW;
    348     }
    349 
    350     if (ARGON2_MAX_LANES < context->lanes) {
    351         return ARGON2_LANES_TOO_MANY;
    352     }
    353 
    354     /* Validate threads */
    355     if (ARGON2_MIN_THREADS > context->threads) {
    356         return ARGON2_THREADS_TOO_FEW;
    357     }
    358 
    359     if (ARGON2_MAX_THREADS < context->threads) {
    360         return ARGON2_THREADS_TOO_MANY;
    361     }
    362     /* LCOV_EXCL_STOP */
    363 
    364     return ARGON2_OK;
    365 }
    366 
    367 void
    368 fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance)
    369 {
    370     uint32_t l;
    371     /* Make the first and second block in each lane as G(H0||i||0) or
    372        G(H0||i||1) */
    373     uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
    374     for (l = 0; l < instance->lanes; ++l) {
    375         STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
    376         STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
    377         blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
    378                      ARGON2_PREHASH_SEED_LENGTH);
    379         load_block(&instance->region->memory[l * instance->lane_length + 0],
    380                    blockhash_bytes);
    381 
    382         STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
    383         blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
    384                      ARGON2_PREHASH_SEED_LENGTH);
    385         load_block(&instance->region->memory[l * instance->lane_length + 1],
    386                    blockhash_bytes);
    387     }
    388     sodium_memzero(blockhash_bytes, ARGON2_BLOCK_SIZE);
    389 }
    390 
    391 void
    392 initial_hash(uint8_t *blockhash, argon2_context *context, argon2_type type)
    393 {
    394     crypto_generichash_blake2b_state BlakeHash;
    395     uint8_t                          value[4U /* sizeof(uint32_t) */];
    396 
    397     if (NULL == context || NULL == blockhash) {
    398         return; /* LCOV_EXCL_LINE */
    399     }
    400 
    401     crypto_generichash_blake2b_init(&BlakeHash, NULL, 0U,
    402                                     ARGON2_PREHASH_DIGEST_LENGTH);
    403 
    404     STORE32_LE(value, context->lanes);
    405     crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
    406 
    407     STORE32_LE(value, context->outlen);
    408     crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
    409 
    410     STORE32_LE(value, context->m_cost);
    411     crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
    412 
    413     STORE32_LE(value, context->t_cost);
    414     crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
    415 
    416     STORE32_LE(value, ARGON2_VERSION_NUMBER);
    417     crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
    418 
    419     STORE32_LE(value, (uint32_t) type);
    420     crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
    421 
    422     STORE32_LE(value, context->pwdlen);
    423     crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
    424 
    425     if (context->pwd != NULL) {
    426         crypto_generichash_blake2b_update(
    427             &BlakeHash, (const uint8_t *) context->pwd, context->pwdlen);
    428 
    429         /* LCOV_EXCL_START */
    430         if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
    431             sodium_memzero(context->pwd, context->pwdlen);
    432             context->pwdlen = 0;
    433         }
    434         /* LCOV_EXCL_STOP */
    435     }
    436 
    437     STORE32_LE(value, context->saltlen);
    438     crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
    439 
    440     if (context->salt != NULL) {
    441         crypto_generichash_blake2b_update(
    442             &BlakeHash, (const uint8_t *) context->salt, context->saltlen);
    443     }
    444 
    445     STORE32_LE(value, context->secretlen);
    446     crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
    447 
    448     /* LCOV_EXCL_START */
    449     if (context->secret != NULL) {
    450         crypto_generichash_blake2b_update(
    451             &BlakeHash, (const uint8_t *) context->secret, context->secretlen);
    452 
    453         if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
    454             sodium_memzero(context->secret, context->secretlen);
    455             context->secretlen = 0;
    456         }
    457     }
    458     /* LCOV_EXCL_STOP */
    459 
    460     STORE32_LE(value, context->adlen);
    461     crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
    462 
    463     /* LCOV_EXCL_START */
    464     if (context->ad != NULL) {
    465         crypto_generichash_blake2b_update(
    466             &BlakeHash, (const uint8_t *) context->ad, context->adlen);
    467     }
    468     /* LCOV_EXCL_STOP */
    469 
    470     crypto_generichash_blake2b_final(&BlakeHash, blockhash,
    471                                      ARGON2_PREHASH_DIGEST_LENGTH);
    472 }
    473 
    474 int
    475 initialize(argon2_instance_t *instance, argon2_context *context)
    476 {
    477     uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
    478     int     result = ARGON2_OK;
    479 
    480     if (instance == NULL || context == NULL) {
    481         return ARGON2_INCORRECT_PARAMETER;
    482     }
    483 
    484     /* 1. Memory allocation */
    485 
    486     if ((instance->pseudo_rands = (uint64_t *)
    487          malloc(sizeof(uint64_t) * instance->segment_length)) == NULL) {
    488         return ARGON2_MEMORY_ALLOCATION_ERROR;
    489     }
    490 
    491     result = allocate_memory(&(instance->region), instance->memory_blocks);
    492     if (ARGON2_OK != result) {
    493         free_instance(instance, context->flags);
    494         return result;
    495     }
    496 
    497     /* 2. Initial hashing */
    498     /* H_0 + 8 extra bytes to produce the first blocks */
    499     /* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
    500     /* Hashing all inputs */
    501     initial_hash(blockhash, context, instance->type);
    502     /* Zeroing 8 extra bytes */
    503     sodium_memzero(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
    504                    ARGON2_PREHASH_SEED_LENGTH - ARGON2_PREHASH_DIGEST_LENGTH);
    505 
    506     /* 3. Creating first blocks, we always have at least two blocks in a slice
    507      */
    508     fill_first_blocks(blockhash, instance);
    509     /* Clearing the hash */
    510     sodium_memzero(blockhash, ARGON2_PREHASH_SEED_LENGTH);
    511 
    512     return ARGON2_OK;
    513 }
    514 
    515 int
    516 argon2_pick_best_implementation(void)
    517 {
    518 /* LCOV_EXCL_START */
    519 #if defined(HAVE_AVX512FINTRIN_H) && defined(HAVE_AVX2INTRIN_H) && \
    520     defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
    521     if (sodium_runtime_has_avx512f()) {
    522         fill_segment = fill_segment_avx512f;
    523         return 0;
    524     }
    525 #endif
    526 #if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_TMMINTRIN_H) && \
    527     defined(HAVE_SMMINTRIN_H)
    528     if (sodium_runtime_has_avx2()) {
    529         fill_segment = fill_segment_avx2;
    530         return 0;
    531     }
    532 #endif
    533 #if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
    534     if (sodium_runtime_has_ssse3()) {
    535         fill_segment = fill_segment_ssse3;
    536         return 0;
    537     }
    538 #endif
    539     fill_segment = fill_segment_ref;
    540 
    541     return 0;
    542     /* LCOV_EXCL_STOP */
    543 }
    544 
    545 int
    546 _crypto_pwhash_argon2_pick_best_implementation(void)
    547 {
    548     return argon2_pick_best_implementation();
    549 }
    550