From 7cc4825231aaa3e960616e5c7a93ec4762f63a1d Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 6 Sep 2017 20:08:20 +0200 Subject: [PATCH] Add crypto_pwhash_str_needs_rehash() --- .../crypto_pwhash/argon2/pwhash_argon2i.c | 55 +++++++++++++++++++ src/libsodium/crypto_pwhash/crypto_pwhash.c | 17 ++++++ src/libsodium/include/sodium/crypto_pwhash.h | 5 ++ .../include/sodium/crypto_pwhash_argon2i.h | 5 ++ .../include/sodium/crypto_pwhash_argon2id.h | 5 ++ 5 files changed, 87 insertions(+) diff --git a/src/libsodium/crypto_pwhash/argon2/pwhash_argon2i.c b/src/libsodium/crypto_pwhash/argon2/pwhash_argon2i.c index 78a67184..50162df9 100644 --- a/src/libsodium/crypto_pwhash/argon2/pwhash_argon2i.c +++ b/src/libsodium/crypto_pwhash/argon2/pwhash_argon2i.c @@ -3,11 +3,14 @@ #include #include #include +#include #include #include "argon2-core.h" +#include "argon2-encoding.h" #include "argon2.h" #include "crypto_pwhash_argon2i.h" +#include "crypto_pwhash_argon2id.h" #include "randombytes.h" #include "utils.h" @@ -211,3 +214,55 @@ crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES], } return -1; } + +static int +crypto_pwhash_argon2_str_needs_rehash(const char *str, + unsigned long long opslimit, + size_t memlimit, int type) +{ + unsigned char *fodder; + argon2_context ctx; + size_t fodder_len; + int ret = -1; + + memlimit /= 1024U; + if (opslimit > UINT32_MAX || memlimit > UINT32_MAX) { + errno = EINVAL; + return -1; + } + memset(&ctx, 0, sizeof ctx); + fodder_len = strlen(str); + if ((fodder = (unsigned char *) calloc(fodder_len, 1U)) == NULL) { + return -1; + } + ctx.salt = ctx.pwd = ctx.salt = ctx.out = fodder; + ctx.saltlen = ctx.pwdlen = ctx.saltlen = ctx.outlen = (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 crypto_pwhash_argon2_str_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 crypto_pwhash_argon2_str_needs_rehash(str, opslimit, memlimit, Argon2_id); +} diff --git a/src/libsodium/crypto_pwhash/crypto_pwhash.c b/src/libsodium/crypto_pwhash/crypto_pwhash.c index bd4b14bf..515393aa 100644 --- a/src/libsodium/crypto_pwhash/crypto_pwhash.c +++ b/src/libsodium/crypto_pwhash/crypto_pwhash.c @@ -186,6 +186,23 @@ crypto_pwhash_str_verify(const char str[crypto_pwhash_STRBYTES], return -1; } +int +crypto_pwhash_str_needs_rehash(const char str[crypto_pwhash_STRBYTES], + unsigned long long opslimit, size_t memlimit) +{ + if (strncmp(str, crypto_pwhash_argon2id_STRPREFIX, + sizeof crypto_pwhash_argon2id_STRPREFIX - 1) == 0) { + return crypto_pwhash_argon2id_str_needs_rehash(str, opslimit, memlimit); + } + if (strncmp(str, crypto_pwhash_argon2i_STRPREFIX, + sizeof crypto_pwhash_argon2i_STRPREFIX - 1) == 0) { + return crypto_pwhash_argon2i_str_needs_rehash(str, opslimit, memlimit); + } + errno = EINVAL; + + return -1; +} + const char * crypto_pwhash_primitive(void) { return crypto_pwhash_PRIMITIVE; diff --git a/src/libsodium/include/sodium/crypto_pwhash.h b/src/libsodium/include/sodium/crypto_pwhash.h index d0b8bba7..d43932b2 100644 --- a/src/libsodium/include/sodium/crypto_pwhash.h +++ b/src/libsodium/include/sodium/crypto_pwhash.h @@ -128,6 +128,11 @@ int crypto_pwhash_str_verify(const char str[crypto_pwhash_STRBYTES], unsigned long long passwdlen) __attribute__ ((warn_unused_result)); +SODIUM_EXPORT +int crypto_pwhash_str_needs_rehash(const char str[crypto_pwhash_STRBYTES], + unsigned long long opslimit, size_t memlimit) + __attribute__ ((warn_unused_result)); + #define crypto_pwhash_PRIMITIVE "argon2i" SODIUM_EXPORT const char *crypto_pwhash_primitive(void) diff --git a/src/libsodium/include/sodium/crypto_pwhash_argon2i.h b/src/libsodium/include/sodium/crypto_pwhash_argon2i.h index 25259915..8e4c1c35 100644 --- a/src/libsodium/include/sodium/crypto_pwhash_argon2i.h +++ b/src/libsodium/include/sodium/crypto_pwhash_argon2i.h @@ -110,6 +110,11 @@ int crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYT unsigned long long passwdlen) __attribute__ ((warn_unused_result)); +SODIUM_EXPORT +int crypto_pwhash_argon2i_str_needs_rehash(const char str[crypto_pwhash_argon2i_STRBYTES], + unsigned long long opslimit, size_t memlimit) + __attribute__ ((warn_unused_result)); + #ifdef __cplusplus } #endif diff --git a/src/libsodium/include/sodium/crypto_pwhash_argon2id.h b/src/libsodium/include/sodium/crypto_pwhash_argon2id.h index 0a35f0cf..51b17aa8 100644 --- a/src/libsodium/include/sodium/crypto_pwhash_argon2id.h +++ b/src/libsodium/include/sodium/crypto_pwhash_argon2id.h @@ -110,6 +110,11 @@ int crypto_pwhash_argon2id_str_verify(const char str[crypto_pwhash_argon2id_STRB unsigned long long passwdlen) __attribute__ ((warn_unused_result)); +SODIUM_EXPORT +int crypto_pwhash_argon2id_str_needs_rehash(const char str[crypto_pwhash_argon2id_STRBYTES], + unsigned long long opslimit, size_t memlimit) + __attribute__ ((warn_unused_result)); + #ifdef __cplusplus } #endif