vendor/libsodium/src/libsodium/crypto_pwhash/argon2/pwhash_argon2i.c in rbnacl-libsodium-1.0.13 vs vendor/libsodium/src/libsodium/crypto_pwhash/argon2/pwhash_argon2i.c in rbnacl-libsodium-1.0.15

- old
+ new

@@ -1,15 +1,20 @@ #include <errno.h> #include <limits.h> #include <stddef.h> #include <stdint.h> +#include <stdlib.h> #include <string.h> #include "argon2-core.h" +#include "argon2-encoding.h" #include "argon2.h" +#include "crypto_pwhash.h" #include "crypto_pwhash_argon2i.h" +#include "crypto_pwhash_argon2id.h" +#include "private/common.h" #include "randombytes.h" #include "utils.h" #define STR_HASHBYTES 32U @@ -20,34 +25,40 @@ } size_t crypto_pwhash_argon2i_bytes_min(void) { + COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MIN >= ARGON2_MIN_OUTLEN); return crypto_pwhash_argon2i_BYTES_MIN; } size_t crypto_pwhash_argon2i_bytes_max(void) { + COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MAX <= ARGON2_MAX_OUTLEN); return crypto_pwhash_argon2i_BYTES_MAX; } size_t crypto_pwhash_argon2i_passwd_min(void) { + COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH); return crypto_pwhash_argon2i_PASSWD_MIN; } size_t crypto_pwhash_argon2i_passwd_max(void) { + COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH); return crypto_pwhash_argon2i_PASSWD_MAX; } size_t crypto_pwhash_argon2i_saltbytes(void) { + COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES >= ARGON2_MIN_SALT_LENGTH); + COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES <= ARGON2_MAX_SALT_LENGTH); return crypto_pwhash_argon2i_SALTBYTES; } size_t crypto_pwhash_argon2i_strbytes(void) @@ -62,28 +73,32 @@ } size_t crypto_pwhash_argon2i_opslimit_min(void) { + COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MIN >= ARGON2_MIN_TIME); return crypto_pwhash_argon2i_OPSLIMIT_MIN; } size_t crypto_pwhash_argon2i_opslimit_max(void) { + COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MAX <= ARGON2_MAX_TIME); return crypto_pwhash_argon2i_OPSLIMIT_MAX; } size_t crypto_pwhash_argon2i_memlimit_min(void) { + COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY); return crypto_pwhash_argon2i_MEMLIMIT_MIN; } size_t crypto_pwhash_argon2i_memlimit_max(void) { + COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY); return crypto_pwhash_argon2i_MEMLIMIT_MAX; } size_t crypto_pwhash_argon2i_opslimit_interactive(void) @@ -126,24 +141,33 @@ const char *const passwd, unsigned long long passwdlen, const unsigned char *const salt, unsigned long long opslimit, size_t memlimit, int alg) { memset(out, 0, outlen); - memlimit /= 1024U; - if (outlen > ARGON2_MAX_OUTLEN || passwdlen > ARGON2_MAX_PWD_LENGTH || - opslimit > ARGON2_MAX_TIME || memlimit > ARGON2_MAX_MEMORY) { + if (outlen > crypto_pwhash_argon2i_BYTES_MAX) { errno = EFBIG; return -1; } - if (outlen < ARGON2_MIN_OUTLEN || passwdlen < ARGON2_MIN_PWD_LENGTH || - opslimit < ARGON2_MIN_TIME || memlimit < ARGON2_MIN_MEMORY) { + if (outlen < crypto_pwhash_argon2i_BYTES_MIN) { errno = EINVAL; return -1; } + if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX || + opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX || + memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) { + errno = EFBIG; + return -1; + } + if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN || + opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN || + memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) { + errno = EINVAL; + return -1; + } switch (alg) { case crypto_pwhash_argon2i_ALG_ARGON2I13: - if (argon2i_hash_raw((uint32_t) opslimit, (uint32_t) memlimit, + if (argon2i_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U), (uint32_t) 1U, passwd, (size_t) passwdlen, salt, (size_t) crypto_pwhash_argon2i_SALTBYTES, out, (size_t) outlen) != ARGON2_OK) { return -1; /* LCOV_EXCL_LINE */ } @@ -161,23 +185,24 @@ unsigned long long opslimit, size_t memlimit) { unsigned char salt[crypto_pwhash_argon2i_SALTBYTES]; memset(out, 0, crypto_pwhash_argon2i_STRBYTES); - memlimit /= 1024U; - if (passwdlen > ARGON2_MAX_PWD_LENGTH || opslimit > ARGON2_MAX_TIME || - memlimit > ARGON2_MAX_MEMORY) { + if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX || + opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX || + memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) { errno = EFBIG; return -1; } - if (passwdlen < ARGON2_MIN_PWD_LENGTH || opslimit < ARGON2_MIN_TIME || - memlimit < ARGON2_MIN_MEMORY) { + if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN || + opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN || + memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) { errno = EINVAL; return -1; } randombytes_buf(salt, sizeof salt); - if (argon2i_hash_encoded((uint32_t) opslimit, (uint32_t) memlimit, + if (argon2i_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U), (uint32_t) 1U, passwd, (size_t) passwdlen, salt, sizeof salt, STR_HASHBYTES, out, crypto_pwhash_argon2i_STRBYTES) != ARGON2_OK) { return -1; /* LCOV_EXCL_LINE */ } @@ -189,16 +214,16 @@ const char *const passwd, unsigned long long passwdlen) { int verify_ret; - if (passwdlen > ARGON2_MAX_PWD_LENGTH) { + if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX) { errno = EFBIG; return -1; } /* LCOV_EXCL_START */ - if (passwdlen < ARGON2_MIN_PWD_LENGTH) { + if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN) { errno = EINVAL; return -1; } /* LCOV_EXCL_STOP */ @@ -208,6 +233,58 @@ } if (verify_ret == ARGON2_VERIFY_MISMATCH) { errno = EINVAL; } return -1; +} + +static int +_needs_rehash(const char *str, unsigned long long opslimit, size_t memlimit, + argon2_type type) +{ + unsigned char *fodder; + argon2_context ctx; + size_t fodder_len; + int ret = -1; + + fodder_len = strlen(str); + memlimit /= 1024U; + if (opslimit > UINT32_MAX || memlimit > UINT32_MAX || + fodder_len >= crypto_pwhash_STRBYTES) { + errno = EINVAL; + return -1; + } + memset(&ctx, 0, sizeof ctx); + if ((fodder = (unsigned char *) calloc(fodder_len, 1U)) == NULL) { + return -1; /* LCOV_EXCL_LINE */ + } + ctx.out = ctx.pwd = ctx.salt = fodder; + ctx.outlen = ctx.pwdlen = ctx.saltlen = (uint32_t) fodder_len; + ctx.ad = ctx.secret = NULL; + ctx.adlen = ctx.secretlen = 0U; + if (decode_string(&ctx, str, type) != 0) { + errno = EINVAL; + ret = -1; + } else if (ctx.t_cost != (uint32_t) opslimit || + ctx.m_cost != (uint32_t) memlimit) { + ret = 1; + } else { + ret = 0; + } + free(fodder); + + return ret; +} + +int +crypto_pwhash_argon2i_str_needs_rehash(const char str[crypto_pwhash_argon2i_STRBYTES], + unsigned long long opslimit, size_t memlimit) +{ + return _needs_rehash(str, opslimit, memlimit, Argon2_i); +} + +int +crypto_pwhash_argon2id_str_needs_rehash(const char str[crypto_pwhash_argon2id_STRBYTES], + unsigned long long opslimit, size_t memlimit) +{ + return _needs_rehash(str, opslimit, memlimit, Argon2_id); }