1
mirror of https://github.com/jedisct1/libsodium.git synced 2024-12-23 20:15:19 -07:00

pwhash: don't enforce the same limits for argon2i and argon2id

Fixes #606

Also, keep enforcing a minimum number of iterations to create argon2i
hashes, but relax that restriction for verification, as it can be
useful to migrate from hashes made using other libraries.
This commit is contained in:
Frank Denis 2017-10-01 11:02:46 +02:00
parent a8ebd37b7b
commit d49d7e8d4f
6 changed files with 78 additions and 32 deletions

View File

@ -47,7 +47,7 @@
ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS)
/* Minimum and maximum number of passes */
#define ARGON2_MIN_TIME UINT32_C(3)
#define ARGON2_MIN_TIME UINT32_C(1)
#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF)
/* Minimum and maximum password length in bytes */

View File

@ -12,6 +12,7 @@
#include "crypto_pwhash.h"
#include "crypto_pwhash_argon2i.h"
#include "crypto_pwhash_argon2id.h"
#include "private/common.h"
#include "randombytes.h"
#include "utils.h"
@ -26,30 +27,36 @@ crypto_pwhash_argon2i_alg_argon2i13(void)
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;
}
@ -68,24 +75,28 @@ crypto_pwhash_argon2i_strprefix(void)
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;
}
@ -132,20 +143,29 @@ crypto_pwhash_argon2i(unsigned char *const out, unsigned long long outlen,
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) {
@ -167,19 +187,20 @@ crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
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) {
@ -195,12 +216,12 @@ crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES],
{
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;
}

View File

@ -8,6 +8,7 @@
#include "argon2-core.h"
#include "argon2.h"
#include "crypto_pwhash_argon2id.h"
#include "private/common.h"
#include "randombytes.h"
#include "utils.h"
@ -22,30 +23,36 @@ crypto_pwhash_argon2id_alg_argon2id13(void)
size_t
crypto_pwhash_argon2id_bytes_min(void)
{
COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MIN >= ARGON2_MIN_OUTLEN);
return crypto_pwhash_argon2id_BYTES_MIN;
}
size_t
crypto_pwhash_argon2id_bytes_max(void)
{
COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MAX <= ARGON2_MAX_OUTLEN);
return crypto_pwhash_argon2id_BYTES_MAX;
}
size_t
crypto_pwhash_argon2id_passwd_min(void)
{
COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH);
return crypto_pwhash_argon2id_PASSWD_MIN;
}
size_t
crypto_pwhash_argon2id_passwd_max(void)
{
COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH);
return crypto_pwhash_argon2id_PASSWD_MAX;
}
size_t
crypto_pwhash_argon2id_saltbytes(void)
{
COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES >= ARGON2_MIN_SALT_LENGTH);
COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES <= ARGON2_MAX_SALT_LENGTH);
return crypto_pwhash_argon2id_SALTBYTES;
}
@ -64,24 +71,28 @@ crypto_pwhash_argon2id_strprefix(void)
size_t
crypto_pwhash_argon2id_opslimit_min(void)
{
COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MIN >= ARGON2_MIN_TIME);
return crypto_pwhash_argon2id_OPSLIMIT_MIN;
}
size_t
crypto_pwhash_argon2id_opslimit_max(void)
{
COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MAX <= ARGON2_MAX_TIME);
return crypto_pwhash_argon2id_OPSLIMIT_MAX;
}
size_t
crypto_pwhash_argon2id_memlimit_min(void)
{
COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY);
return crypto_pwhash_argon2id_MEMLIMIT_MIN;
}
size_t
crypto_pwhash_argon2id_memlimit_max(void)
{
COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY);
return crypto_pwhash_argon2id_MEMLIMIT_MAX;
}
@ -128,20 +139,29 @@ crypto_pwhash_argon2id(unsigned char *const out, unsigned long long outlen,
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_argon2id_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_argon2id_BYTES_MIN) {
errno = EINVAL;
return -1;
}
if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
errno = EFBIG;
return -1;
}
if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN ||
memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) {
errno = EINVAL;
return -1;
}
switch (alg) {
case crypto_pwhash_argon2id_ALG_ARGON2ID13:
if (argon2id_hash_raw((uint32_t) opslimit, (uint32_t) memlimit,
if (argon2id_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
(uint32_t) 1U, passwd, (size_t) passwdlen, salt,
(size_t) crypto_pwhash_argon2id_SALTBYTES, out,
(size_t) outlen) != ARGON2_OK) {
@ -163,19 +183,20 @@ crypto_pwhash_argon2id_str(char out[crypto_pwhash_argon2id_STRBYTES],
unsigned char salt[crypto_pwhash_argon2id_SALTBYTES];
memset(out, 0, crypto_pwhash_argon2id_STRBYTES);
memlimit /= 1024U;
if (passwdlen > ARGON2_MAX_PWD_LENGTH || opslimit > ARGON2_MAX_TIME ||
memlimit > ARGON2_MAX_MEMORY) {
if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
errno = EFBIG;
return -1;
}
if (passwdlen < ARGON2_MIN_PWD_LENGTH || opslimit < ARGON2_MIN_TIME ||
memlimit < ARGON2_MIN_MEMORY) {
if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN ||
memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) {
errno = EINVAL;
return -1;
}
randombytes_buf(salt, sizeof salt);
if (argon2id_hash_encoded((uint32_t) opslimit, (uint32_t) memlimit,
if (argon2id_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
(uint32_t) 1U, passwd, (size_t) passwdlen, salt,
sizeof salt, STR_HASHBYTES, out,
crypto_pwhash_argon2id_STRBYTES) != ARGON2_OK) {
@ -191,12 +212,12 @@ crypto_pwhash_argon2id_str_verify(const char str[crypto_pwhash_argon2id_STRBYTES
{
int verify_ret;
if (passwdlen > ARGON2_MAX_PWD_LENGTH) {
if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX) {
errno = EFBIG;
return -1;
}
/* LCOV_EXCL_START */
if (passwdlen < ARGON2_MIN_PWD_LENGTH) {
if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN) {
errno = EINVAL;
return -1;
}

View File

@ -8,5 +8,4 @@ c121209f0ba70aed93d49200e5dc82cce013cef25ea31e160bf8db3cf448a59d1a56f6c19259e18e
e942951dfbc2d508294b10f9e97b47d0cd04e668a043cb95679cc1139df7c27cd54367688725be9d069f5704c12223e7e4ca181fbd0bed18bb4634795e545a6c04a7306933a41a794baedbb628d41bc285e0b9084055ae136f6b63624c874f5a1e1d8be7b0b7227a171d2d7ed578d88bfdcf18323198962d0dcad4126fd3f21adeb1e11d66252ea0c58c91696e91031bfdcc2a9dc0e028d17b9705ba2d7bcdcd1e3ba75b4b1fea
9fbbc02a420b00614a49a8e8d89834df368fa54dbef5dce7f9928f4d09f45ce22766598c0c979a707b1df130ab8d63802447923f6e8b89b3c183d71d694161569b1937d8b58f0091fcb8b1f48f2e3f43067bb2498b727fb62cc776ed39219613aa2083619385ec64dfb38f3cda7fddce9cec708a1aa5e9b09d6a5f063cda6c644c5e4a6c1bba9362b27f050984ee3a91bbed69160c95d63c04724f
28645e1a4f5bc2a58786c87f0d88c2c68047b874b122e2c3936fb6adf26d7ca8fbcb872a8aef282ff202526a91b8ca1d0926c4ae0f5429c342bfd4987916b147ccaa1624bbb2d3f197e56601a541939a1a867ee659515d379d252c8b53aa2297b6008f97bc4a246040b0fb4f46754482884ff04bdade7ffc74989c68ec085de660ef2071db22bacc227d43af282a2336049d78fe0b8ff543628dc8
[tv3] pwhash_str failure (maybe intentional): [0]
OK

View File

@ -293,8 +293,13 @@ main(void)
return 1;
}
if (crypto_pwhash_argon2id_str(str_out2, passwd, strlen(passwd), 1, MEMLIMIT) !=
0) {
printf("pwhash_argon2id_str() with a small opslimit should not have failed\n");
return 1;
}
if (crypto_pwhash_argon2id_str(str_out2, passwd, strlen(passwd), 0, MEMLIMIT) !=
-1) {
printf("pwhash_argon2id_str() with a small opslimit should have failed\n");
printf("pwhash_argon2id_str() with a null opslimit should have failed\n");
return 1;
}
if (crypto_pwhash_argon2id_str_verify("$argon2id$m=65536,t=2,p=1c29tZXNhbHQ"

View File

@ -4,7 +4,7 @@
[tv] pwhash failure (maybe intentional): [3]
08d8cd330c57e1b4643241d05bb468ba4ee4e932cd0858816be9ef15360b27bbd06a87130ee92222be267a29b81f5ae8fe8613324cfc4832dc49387fd0602f1c57b4d0f3855db94fb7e12eb05f9a484aed4a4307abf586cd3d55c809bc081541e00b682772fb2066504ff935b8ebc551a2083882f874bc0fae68e56848ae34c91097c3bf0cca8e75c0797eef3efde3f75e005815018db3cf7c109a812264c4de69dcb22322dbbcfa447f5b00ecd1b04a7be1569c8e556adb7bba48adf81d
d6e9d6cabd42fb9ba7162fe9b8e41d59d3c7034756cb460c9affe393308bd0225ce0371f2e6c3ca32aca2002bf2d3909c6b6e7dfc4a00e850ff4f570f8f749d4bb6f0091e554be67a9095ae1eefaa1a933316cbec3c2fd4a14a5b6941bda9b7eabd821d79abde2475a53af1a8571c7ee46460be415882e0b393f48c12f740a6a72cba9773000602e13b40d3dfa6ac1d4ec43a838b7e3e165fecad4b2498389e60a3ff9f0f8f4b9fca1126e64f49501e38690
[tv] pwhash failure (maybe intentional): [6]
7fb72409b0987f8190c3729710e98c3f80c5a8727d425fdcde7f3644d467fe973f5b5fee683bd3fce812cb9ae5e9921a2d06c2f1905e4e839692f2b934b682f11a2fe2b90482ea5dd234863516dba6f52dc0702d324ec77d860c2e181f84472bd7104fedce071ffa93c5309494ad51623d214447a7b2b1462dc7d5d55a1f6fd5b54ce024118d86f0c6489d16545aaa87b6689dad9f2fb47fda9894f8e12b87d978b483ccd4cc5fd9595cdc7a818452f915ce2f7df95ec12b1c72e3788d473441d884f9748eb14703c21b45d82fd667b85f5b2d98c13303b3fe76285531a826b6fc0fe8e3dddecf
4e702bc5f891df884c6ddaa243aa846ce3c087fe930fef0f36b3c2be34164ccc295db509254743f18f947159c813bcd5dd8d94a3aec93bbe57605d1fad1aef1112687c3d4ef1cb329d21f1632f626818d766915d886e8d819e4b0b9c9307f4b6afc081e13b0cf31db382ff1bf05a16aac7af696336d75e99f82163e0f371e1d25c4add808e215697ad3f779a51a462f8bf52610af21fc69dba6b072606f2dabca7d4ae1d91d919
2d232f9dc4de96628b2a4c2b39ceb6a813011fb74a3ba1da096761fabe08f563bd91366aba5c5e35aecd98643cabc16ce560dca261a963230a1fa2af52f2413a57a827c6ee13bcec0c123d195914a55700ccb5756196a86fb9cb4aeacccc0e6dd850f4386b705aaae147ea347543b7fbe24553d9da41f1b335b6e9980cdb966cf7b48520eb42a7269380c885dbefbccf447851fcacbe1753a5b9e1
34b207147fb7ef83e1ca1a97e30aa6e08ea9b6b1048c59c9c13050dff33e76ce3c440d7f018f817e6b8593e78f339ba633b9d7ec3519b5eafbcc4bc2d20b5136bbc7e5b7e92ff37d024bbbecf5738f718ab22c8adcdb82ceffc233b8ad61f91850abdfe8bb119775d9c4243ec1ac761dfbd132489228dfeab5268c7f0ddc29f56b957d1b76c874cdd77e16139e0df9b847248fd782c9a1147b8480