Home | History | Annotate | Line # | Download | only in argon2
      1 
      2 #include <errno.h>
      3 #include <limits.h>
      4 #include <stddef.h>
      5 #include <stdint.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 
      9 #include "argon2-core.h"
     10 #include "argon2-encoding.h"
     11 #include "argon2.h"
     12 #include "crypto_pwhash.h"
     13 #include "crypto_pwhash_argon2i.h"
     14 #include "crypto_pwhash_argon2id.h"
     15 #include "private/common.h"
     16 #include "randombytes.h"
     17 #include "utils.h"
     18 
     19 #define STR_HASHBYTES 32U
     20 
     21 int
     22 crypto_pwhash_argon2i_alg_argon2i13(void)
     23 {
     24     return crypto_pwhash_argon2i_ALG_ARGON2I13;
     25 }
     26 
     27 size_t
     28 crypto_pwhash_argon2i_bytes_min(void)
     29 {
     30     COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MIN >= ARGON2_MIN_OUTLEN);
     31     return crypto_pwhash_argon2i_BYTES_MIN;
     32 }
     33 
     34 size_t
     35 crypto_pwhash_argon2i_bytes_max(void)
     36 {
     37     COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MAX <= ARGON2_MAX_OUTLEN);
     38     return crypto_pwhash_argon2i_BYTES_MAX;
     39 }
     40 
     41 size_t
     42 crypto_pwhash_argon2i_passwd_min(void)
     43 {
     44     COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH);
     45     return crypto_pwhash_argon2i_PASSWD_MIN;
     46 }
     47 
     48 size_t
     49 crypto_pwhash_argon2i_passwd_max(void)
     50 {
     51     COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH);
     52     return crypto_pwhash_argon2i_PASSWD_MAX;
     53 }
     54 
     55 size_t
     56 crypto_pwhash_argon2i_saltbytes(void)
     57 {
     58     COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES >= ARGON2_MIN_SALT_LENGTH);
     59     COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES <= ARGON2_MAX_SALT_LENGTH);
     60     return crypto_pwhash_argon2i_SALTBYTES;
     61 }
     62 
     63 size_t
     64 crypto_pwhash_argon2i_strbytes(void)
     65 {
     66     return crypto_pwhash_argon2i_STRBYTES;
     67 }
     68 
     69 const char*
     70 crypto_pwhash_argon2i_strprefix(void)
     71 {
     72     return crypto_pwhash_argon2i_STRPREFIX;
     73 }
     74 
     75 size_t
     76 crypto_pwhash_argon2i_opslimit_min(void)
     77 {
     78     COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MIN >= ARGON2_MIN_TIME);
     79     return crypto_pwhash_argon2i_OPSLIMIT_MIN;
     80 }
     81 
     82 size_t
     83 crypto_pwhash_argon2i_opslimit_max(void)
     84 {
     85     COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MAX <= ARGON2_MAX_TIME);
     86     return crypto_pwhash_argon2i_OPSLIMIT_MAX;
     87 }
     88 
     89 size_t
     90 crypto_pwhash_argon2i_memlimit_min(void)
     91 {
     92     COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY);
     93     return crypto_pwhash_argon2i_MEMLIMIT_MIN;
     94 }
     95 
     96 size_t
     97 crypto_pwhash_argon2i_memlimit_max(void)
     98 {
     99     COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY);
    100     return crypto_pwhash_argon2i_MEMLIMIT_MAX;
    101 }
    102 
    103 size_t
    104 crypto_pwhash_argon2i_opslimit_interactive(void)
    105 {
    106     return crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE;
    107 }
    108 
    109 size_t
    110 crypto_pwhash_argon2i_memlimit_interactive(void)
    111 {
    112     return crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE;
    113 }
    114 
    115 size_t
    116 crypto_pwhash_argon2i_opslimit_moderate(void)
    117 {
    118     return crypto_pwhash_argon2i_OPSLIMIT_MODERATE;
    119 }
    120 
    121 size_t
    122 crypto_pwhash_argon2i_memlimit_moderate(void)
    123 {
    124     return crypto_pwhash_argon2i_MEMLIMIT_MODERATE;
    125 }
    126 
    127 size_t
    128 crypto_pwhash_argon2i_opslimit_sensitive(void)
    129 {
    130     return crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE;
    131 }
    132 
    133 size_t
    134 crypto_pwhash_argon2i_memlimit_sensitive(void)
    135 {
    136     return crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE;
    137 }
    138 
    139 int
    140 crypto_pwhash_argon2i(unsigned char *const out, unsigned long long outlen,
    141                       const char *const passwd, unsigned long long passwdlen,
    142                       const unsigned char *const salt,
    143                       unsigned long long opslimit, size_t memlimit, int alg)
    144 {
    145     memset(out, 0, outlen);
    146     if (outlen > crypto_pwhash_argon2i_BYTES_MAX) {
    147         errno = EFBIG;
    148         return -1;
    149     }
    150     if (outlen < crypto_pwhash_argon2i_BYTES_MIN) {
    151         errno = EINVAL;
    152         return -1;
    153     }
    154     if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX ||
    155         opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX ||
    156         memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) {
    157         errno = EFBIG;
    158         return -1;
    159     }
    160     if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN ||
    161         opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN ||
    162         memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) {
    163         errno = EINVAL;
    164         return -1;
    165     }
    166     switch (alg) {
    167     case crypto_pwhash_argon2i_ALG_ARGON2I13:
    168         if (argon2i_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
    169                              (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
    170                              (size_t) crypto_pwhash_argon2i_SALTBYTES, out,
    171                              (size_t) outlen) != ARGON2_OK) {
    172             return -1; /* LCOV_EXCL_LINE */
    173         }
    174         return 0;
    175     default:
    176         errno = EINVAL;
    177         return -1;
    178     }
    179 }
    180 
    181 int
    182 crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
    183                           const char *const passwd,
    184                           unsigned long long passwdlen,
    185                           unsigned long long opslimit, size_t memlimit)
    186 {
    187     unsigned char salt[crypto_pwhash_argon2i_SALTBYTES];
    188 
    189     memset(out, 0, crypto_pwhash_argon2i_STRBYTES);
    190     if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX ||
    191         opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX ||
    192         memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) {
    193         errno = EFBIG;
    194         return -1;
    195     }
    196     if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN ||
    197         opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN ||
    198         memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) {
    199         errno = EINVAL;
    200         return -1;
    201     }
    202     randombytes_buf(salt, sizeof salt);
    203     if (argon2i_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
    204                              (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
    205                              sizeof salt, STR_HASHBYTES, out,
    206                              crypto_pwhash_argon2i_STRBYTES) != ARGON2_OK) {
    207         return -1; /* LCOV_EXCL_LINE */
    208     }
    209     return 0;
    210 }
    211 
    212 int
    213 crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES],
    214                                  const char *const  passwd,
    215                                  unsigned long long passwdlen)
    216 {
    217     int verify_ret;
    218 
    219     if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX) {
    220         errno = EFBIG;
    221         return -1;
    222     }
    223     /* LCOV_EXCL_START */
    224     if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN) {
    225         errno = EINVAL;
    226         return -1;
    227     }
    228     /* LCOV_EXCL_STOP */
    229 
    230     verify_ret = argon2i_verify(str, passwd, (size_t) passwdlen);
    231     if (verify_ret == ARGON2_OK) {
    232         return 0;
    233     }
    234     if (verify_ret == ARGON2_VERIFY_MISMATCH) {
    235         errno = EINVAL;
    236     }
    237     return -1;
    238 }
    239 
    240 static int
    241 _needs_rehash(const char *str, unsigned long long opslimit, size_t memlimit,
    242               argon2_type type)
    243 {
    244     unsigned char  *fodder;
    245     argon2_context  ctx;
    246     size_t          fodder_len;
    247     int             ret = -1;
    248 
    249     fodder_len = strlen(str);
    250     memlimit /= 1024U;
    251     if (opslimit > UINT32_MAX || memlimit > UINT32_MAX ||
    252         fodder_len >= crypto_pwhash_STRBYTES) {
    253         errno = EINVAL;
    254         return -1;
    255     }
    256     memset(&ctx, 0, sizeof ctx);
    257     if ((fodder = (unsigned char *) calloc(fodder_len, 1U)) == NULL) {
    258         return -1; /* LCOV_EXCL_LINE */
    259     }
    260     ctx.out    = ctx.pwd       = ctx.salt    = fodder;
    261     ctx.outlen = ctx.pwdlen    = ctx.saltlen = (uint32_t) fodder_len;
    262     ctx.ad     = ctx.secret    = NULL;
    263     ctx.adlen  = ctx.secretlen = 0U;
    264     if (decode_string(&ctx, str, type) != 0) {
    265         errno = EINVAL;
    266         ret = -1;
    267     } else if (ctx.t_cost != (uint32_t) opslimit ||
    268                ctx.m_cost != (uint32_t) memlimit) {
    269         ret = 1;
    270     } else {
    271         ret = 0;
    272     }
    273     free(fodder);
    274 
    275     return ret;
    276 }
    277 
    278 int
    279 crypto_pwhash_argon2i_str_needs_rehash(const char str[crypto_pwhash_argon2i_STRBYTES],
    280                                        unsigned long long opslimit, size_t memlimit)
    281 {
    282     return _needs_rehash(str, opslimit, memlimit, Argon2_i);
    283 }
    284 
    285 int
    286 crypto_pwhash_argon2id_str_needs_rehash(const char str[crypto_pwhash_argon2id_STRBYTES],
    287                                         unsigned long long opslimit, size_t memlimit)
    288 {
    289     return _needs_rehash(str, opslimit, memlimit, Argon2_id);
    290 }
    291