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 <string.h>
      7 
      8 #include "argon2-core.h"
      9 #include "argon2.h"
     10 #include "crypto_pwhash_argon2id.h"
     11 #include "private/common.h"
     12 #include "randombytes.h"
     13 #include "utils.h"
     14 
     15 #define STR_HASHBYTES 32U
     16 
     17 int
     18 crypto_pwhash_argon2id_alg_argon2id13(void)
     19 {
     20     return crypto_pwhash_argon2id_ALG_ARGON2ID13;
     21 }
     22 
     23 size_t
     24 crypto_pwhash_argon2id_bytes_min(void)
     25 {
     26     COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MIN >= ARGON2_MIN_OUTLEN);
     27     return crypto_pwhash_argon2id_BYTES_MIN;
     28 }
     29 
     30 size_t
     31 crypto_pwhash_argon2id_bytes_max(void)
     32 {
     33     COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MAX <= ARGON2_MAX_OUTLEN);
     34     return crypto_pwhash_argon2id_BYTES_MAX;
     35 }
     36 
     37 size_t
     38 crypto_pwhash_argon2id_passwd_min(void)
     39 {
     40     COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH);
     41     return crypto_pwhash_argon2id_PASSWD_MIN;
     42 }
     43 
     44 size_t
     45 crypto_pwhash_argon2id_passwd_max(void)
     46 {
     47     COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH);
     48     return crypto_pwhash_argon2id_PASSWD_MAX;
     49 }
     50 
     51 size_t
     52 crypto_pwhash_argon2id_saltbytes(void)
     53 {
     54     COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES >= ARGON2_MIN_SALT_LENGTH);
     55     COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES <= ARGON2_MAX_SALT_LENGTH);
     56     return crypto_pwhash_argon2id_SALTBYTES;
     57 }
     58 
     59 size_t
     60 crypto_pwhash_argon2id_strbytes(void)
     61 {
     62     return crypto_pwhash_argon2id_STRBYTES;
     63 }
     64 
     65 const char*
     66 crypto_pwhash_argon2id_strprefix(void)
     67 {
     68     return crypto_pwhash_argon2id_STRPREFIX;
     69 }
     70 
     71 size_t
     72 crypto_pwhash_argon2id_opslimit_min(void)
     73 {
     74     COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MIN >= ARGON2_MIN_TIME);
     75     return crypto_pwhash_argon2id_OPSLIMIT_MIN;
     76 }
     77 
     78 size_t
     79 crypto_pwhash_argon2id_opslimit_max(void)
     80 {
     81     COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MAX <= ARGON2_MAX_TIME);
     82     return crypto_pwhash_argon2id_OPSLIMIT_MAX;
     83 }
     84 
     85 size_t
     86 crypto_pwhash_argon2id_memlimit_min(void)
     87 {
     88     COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY);
     89     return crypto_pwhash_argon2id_MEMLIMIT_MIN;
     90 }
     91 
     92 size_t
     93 crypto_pwhash_argon2id_memlimit_max(void)
     94 {
     95     COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY);
     96     return crypto_pwhash_argon2id_MEMLIMIT_MAX;
     97 }
     98 
     99 size_t
    100 crypto_pwhash_argon2id_opslimit_interactive(void)
    101 {
    102     return crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE;
    103 }
    104 
    105 size_t
    106 crypto_pwhash_argon2id_memlimit_interactive(void)
    107 {
    108     return crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE;
    109 }
    110 
    111 size_t
    112 crypto_pwhash_argon2id_opslimit_moderate(void)
    113 {
    114     return crypto_pwhash_argon2id_OPSLIMIT_MODERATE;
    115 }
    116 
    117 size_t
    118 crypto_pwhash_argon2id_memlimit_moderate(void)
    119 {
    120     return crypto_pwhash_argon2id_MEMLIMIT_MODERATE;
    121 }
    122 
    123 size_t
    124 crypto_pwhash_argon2id_opslimit_sensitive(void)
    125 {
    126     return crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE;
    127 }
    128 
    129 size_t
    130 crypto_pwhash_argon2id_memlimit_sensitive(void)
    131 {
    132     return crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE;
    133 }
    134 
    135 int
    136 crypto_pwhash_argon2id(unsigned char *const out, unsigned long long outlen,
    137                        const char *const passwd, unsigned long long passwdlen,
    138                        const unsigned char *const salt,
    139                        unsigned long long opslimit, size_t memlimit, int alg)
    140 {
    141     memset(out, 0, outlen);
    142     if (outlen > crypto_pwhash_argon2id_BYTES_MAX) {
    143         errno = EFBIG;
    144         return -1;
    145     }
    146     if (outlen < crypto_pwhash_argon2id_BYTES_MIN) {
    147         errno = EINVAL;
    148         return -1;
    149     }
    150     if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
    151         opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
    152         memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
    153         errno = EFBIG;
    154         return -1;
    155     }
    156     if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
    157         opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN ||
    158         memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) {
    159         errno = EINVAL;
    160         return -1;
    161     }
    162     switch (alg) {
    163     case crypto_pwhash_argon2id_ALG_ARGON2ID13:
    164         if (argon2id_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
    165                               (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
    166                               (size_t) crypto_pwhash_argon2id_SALTBYTES, out,
    167                               (size_t) outlen) != ARGON2_OK) {
    168             return -1; /* LCOV_EXCL_LINE */
    169         }
    170         return 0;
    171     default:
    172         errno = EINVAL;
    173         return -1;
    174     }
    175 }
    176 
    177 int
    178 crypto_pwhash_argon2id_str(char out[crypto_pwhash_argon2id_STRBYTES],
    179                            const char *const passwd,
    180                            unsigned long long passwdlen,
    181                            unsigned long long opslimit, size_t memlimit)
    182 {
    183     unsigned char salt[crypto_pwhash_argon2id_SALTBYTES];
    184 
    185     memset(out, 0, crypto_pwhash_argon2id_STRBYTES);
    186     if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
    187         opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
    188         memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
    189         errno = EFBIG;
    190         return -1;
    191     }
    192     if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
    193         opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN ||
    194         memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) {
    195         errno = EINVAL;
    196         return -1;
    197     }
    198     randombytes_buf(salt, sizeof salt);
    199     if (argon2id_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
    200                               (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
    201                               sizeof salt, STR_HASHBYTES, out,
    202                               crypto_pwhash_argon2id_STRBYTES) != ARGON2_OK) {
    203         return -1; /* LCOV_EXCL_LINE */
    204     }
    205     return 0;
    206 }
    207 
    208 int
    209 crypto_pwhash_argon2id_str_verify(const char str[crypto_pwhash_argon2id_STRBYTES],
    210                                   const char *const  passwd,
    211                                   unsigned long long passwdlen)
    212 {
    213     int verify_ret;
    214 
    215     if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX) {
    216         errno = EFBIG;
    217         return -1;
    218     }
    219     /* LCOV_EXCL_START */
    220     if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN) {
    221         errno = EINVAL;
    222         return -1;
    223     }
    224     /* LCOV_EXCL_STOP */
    225 
    226     verify_ret = argon2id_verify(str, passwd, (size_t) passwdlen);
    227     if (verify_ret == ARGON2_OK) {
    228         return 0;
    229     }
    230     if (verify_ret == ARGON2_VERIFY_MISMATCH) {
    231         errno = EINVAL;
    232     }
    233     return -1;
    234 }
    235