Home | History | Annotate | Line # | Download | only in scryptsalsa208sha256
      1 
      2 #include <errno.h>
      3 #include <limits.h>
      4 #include <stddef.h>
      5 #include <stdint.h>
      6 #include <string.h>
      7 
      8 #include "crypto_pwhash_scryptsalsa208sha256.h"
      9 #include "crypto_scrypt.h"
     10 #include "private/common.h"
     11 #include "randombytes.h"
     12 #include "utils.h"
     13 
     14 #define SETTING_SIZE(saltbytes)                                              \
     15     ((sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + \
     16      BYTES2CHARS(saltbytes))
     17 
     18 static int
     19 pickparams(unsigned long long opslimit, const size_t memlimit,
     20            uint32_t *const N_log2, uint32_t *const p, uint32_t *const r)
     21 {
     22     unsigned long long maxN;
     23     unsigned long long maxrp;
     24 
     25     if (opslimit < 32768) {
     26         opslimit = 32768;
     27     }
     28     *r = 8;
     29     if (opslimit < memlimit / 32) {
     30         *p = 1;
     31         maxN = opslimit / (*r * 4);
     32         for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
     33             if ((uint64_t)(1) << *N_log2 > maxN / 2) {
     34                 break;
     35             }
     36         }
     37     } else {
     38         maxN = memlimit / ((size_t) *r * 128);
     39         for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
     40             if ((uint64_t)(1) << *N_log2 > maxN / 2) {
     41                 break;
     42             }
     43         }
     44         maxrp = (opslimit / 4) / ((uint64_t)(1) << *N_log2);
     45         /* LCOV_EXCL_START */
     46         if (maxrp > 0x3fffffff) {
     47             maxrp = 0x3fffffff;
     48         }
     49         /* LCOV_EXCL_STOP */
     50         *p = (uint32_t)(maxrp) / *r;
     51     }
     52     return 0;
     53 }
     54 
     55 size_t
     56 crypto_pwhash_scryptsalsa208sha256_bytes_min(void)
     57 {
     58     return crypto_pwhash_scryptsalsa208sha256_BYTES_MIN;
     59 }
     60 
     61 size_t
     62 crypto_pwhash_scryptsalsa208sha256_bytes_max(void)
     63 {
     64     return crypto_pwhash_scryptsalsa208sha256_BYTES_MAX;
     65 }
     66 
     67 size_t
     68 crypto_pwhash_scryptsalsa208sha256_passwd_min(void)
     69 {
     70     return crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN;
     71 }
     72 
     73 size_t
     74 crypto_pwhash_scryptsalsa208sha256_passwd_max(void)
     75 {
     76     return crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX;
     77 }
     78 
     79 size_t
     80 crypto_pwhash_scryptsalsa208sha256_saltbytes(void)
     81 {
     82     return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
     83 }
     84 
     85 size_t
     86 crypto_pwhash_scryptsalsa208sha256_strbytes(void)
     87 {
     88     return crypto_pwhash_scryptsalsa208sha256_STRBYTES;
     89 }
     90 
     91 const char *
     92 crypto_pwhash_scryptsalsa208sha256_strprefix(void)
     93 {
     94     return crypto_pwhash_scryptsalsa208sha256_STRPREFIX;
     95 }
     96 
     97 size_t
     98 crypto_pwhash_scryptsalsa208sha256_opslimit_min(void)
     99 {
    100     return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN;
    101 }
    102 
    103 size_t
    104 crypto_pwhash_scryptsalsa208sha256_opslimit_max(void)
    105 {
    106     return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX;
    107 }
    108 
    109 size_t
    110 crypto_pwhash_scryptsalsa208sha256_memlimit_min(void)
    111 {
    112     return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN;
    113 }
    114 
    115 size_t
    116 crypto_pwhash_scryptsalsa208sha256_memlimit_max(void)
    117 {
    118     return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX;
    119 }
    120 
    121 size_t
    122 crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void)
    123 {
    124     return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
    125 }
    126 
    127 size_t
    128 crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void)
    129 {
    130     return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
    131 }
    132 
    133 size_t
    134 crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void)
    135 {
    136     return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE;
    137 }
    138 
    139 size_t
    140 crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void)
    141 {
    142     return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE;
    143 }
    144 
    145 int
    146 crypto_pwhash_scryptsalsa208sha256(unsigned char *const       out,
    147                                    unsigned long long         outlen,
    148                                    const char *const          passwd,
    149                                    unsigned long long         passwdlen,
    150                                    const unsigned char *const salt,
    151                                    unsigned long long opslimit, size_t memlimit)
    152 {
    153     uint32_t N_log2;
    154     uint32_t p;
    155     uint32_t r;
    156 
    157     memset(out, 0, outlen);
    158     if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX ||
    159         outlen > crypto_pwhash_scryptsalsa208sha256_BYTES_MAX) {
    160         errno = EFBIG; /* LCOV_EXCL_LINE */
    161         return -1;     /* LCOV_EXCL_LINE */
    162     }
    163     if (outlen < crypto_pwhash_scryptsalsa208sha256_BYTES_MIN ||
    164         pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
    165         errno = EINVAL; /* LCOV_EXCL_LINE */
    166         return -1;      /* LCOV_EXCL_LINE */
    167     }
    168     return crypto_pwhash_scryptsalsa208sha256_ll(
    169         (const uint8_t *) passwd, (size_t) passwdlen, (const uint8_t *) salt,
    170         crypto_pwhash_scryptsalsa208sha256_SALTBYTES, (uint64_t)(1) << N_log2,
    171         r, p, out, (size_t) outlen);
    172 }
    173 
    174 int
    175 crypto_pwhash_scryptsalsa208sha256_str(
    176     char              out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
    177     const char *const passwd, unsigned long long passwdlen,
    178     unsigned long long opslimit, size_t memlimit)
    179 {
    180     uint8_t salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES];
    181     char    setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U];
    182     escrypt_local_t escrypt_local;
    183     uint32_t        N_log2;
    184     uint32_t        p;
    185     uint32_t        r;
    186 
    187     memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES);
    188     if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX) {
    189         errno = EFBIG; /* LCOV_EXCL_LINE */
    190         return -1;     /* LCOV_EXCL_LINE */
    191     }
    192     if (passwdlen < crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN ||
    193         pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
    194         errno = EINVAL; /* LCOV_EXCL_LINE */
    195         return -1;      /* LCOV_EXCL_LINE */
    196     }
    197     randombytes_buf(salt, sizeof salt);
    198     if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt, (uint8_t *) setting,
    199                           sizeof setting) == NULL) {
    200         errno = EINVAL; /* LCOV_EXCL_LINE */
    201         return -1;      /* LCOV_EXCL_LINE */
    202     }
    203     if (escrypt_init_local(&escrypt_local) != 0) {
    204         return -1; /* LCOV_EXCL_LINE */
    205     }
    206     if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
    207                   (const uint8_t *) setting, (uint8_t *) out,
    208                   crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) {
    209         /* LCOV_EXCL_START */
    210         escrypt_free_local(&escrypt_local);
    211         errno = EINVAL;
    212         return -1;
    213         /* LCOV_EXCL_STOP */
    214     }
    215     escrypt_free_local(&escrypt_local);
    216 
    217     COMPILER_ASSERT(
    218         SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES) ==
    219         crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES);
    220     COMPILER_ASSERT(
    221         crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U +
    222             crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U ==
    223         crypto_pwhash_scryptsalsa208sha256_STRBYTES);
    224 
    225     return 0;
    226 }
    227 
    228 int
    229 crypto_pwhash_scryptsalsa208sha256_str_verify(
    230     const char        str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
    231     const char *const passwd, unsigned long long passwdlen)
    232 {
    233     char            wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES];
    234     escrypt_local_t escrypt_local;
    235     int             ret = -1;
    236 
    237     if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
    238         &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) {
    239         return -1;
    240     }
    241     if (escrypt_init_local(&escrypt_local) != 0) {
    242         return -1; /* LCOV_EXCL_LINE */
    243     }
    244     memset(wanted, 0, sizeof wanted);
    245     if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
    246                   (const uint8_t *) str, (uint8_t *) wanted,
    247                   sizeof wanted) == NULL) {
    248         escrypt_free_local(&escrypt_local);
    249         return -1;
    250     }
    251     escrypt_free_local(&escrypt_local);
    252     ret = sodium_memcmp(wanted, str, sizeof wanted);
    253     sodium_memzero(wanted, sizeof wanted);
    254 
    255     return ret;
    256 }
    257 
    258 int
    259 crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(
    260     const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
    261     unsigned long long opslimit, size_t memlimit)
    262 {
    263     uint32_t N_log2, N_log2_;
    264     uint32_t p, p_;
    265     uint32_t r, r_;
    266 
    267     if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
    268         errno = EINVAL;
    269         return -1;
    270     }
    271     if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
    272         &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) {
    273         errno = EINVAL;
    274         return -1;
    275     }
    276     if (escrypt_parse_setting((const uint8_t *) str,
    277                               &N_log2_, &r_, &p_) == NULL) {
    278         errno = EINVAL;
    279         return -1;
    280     }
    281     if (N_log2 != N_log2_ || r != r_ || p != p_) {
    282         return 1;
    283     }
    284     return 0;
    285 }
    286