diff options
Diffstat (limited to 'src/libsodium/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c')
-rw-r--r-- | src/libsodium/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c new file mode 100644 index 0000000..b4e64a5 --- /dev/null +++ b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c @@ -0,0 +1,197 @@ + +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +#include "crypto_pwhash_scryptsalsa208sha256.h" +#include "crypto_scrypt.h" +#include "randombytes.h" +#include "utils.h" + +#define SETTING_SIZE(saltbytes) \ + (sizeof "$7$" - 1U) + \ + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + BYTES2CHARS(saltbytes) + +static int +pickparams(unsigned long long opslimit, const size_t memlimit, + uint32_t * const N_log2, uint32_t * const p, uint32_t * const r) +{ + unsigned long long maxN; + unsigned long long maxrp; + + if (opslimit < 32768) { + opslimit = 32768; + } + *r = 8; + if (opslimit < memlimit / 32) { + *p = 1; + maxN = opslimit / (*r * 4); + for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) { + if ((uint64_t)(1) << *N_log2 > maxN / 2) { + break; + } + } + } else { + maxN = memlimit / (*r * 128); + for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) { + if ((uint64_t) (1) << *N_log2 > maxN / 2) { + break; + } + } + maxrp = (opslimit / 4) / ((uint64_t) (1) << *N_log2); + if (maxrp > 0x3fffffff) { + maxrp = 0x3fffffff; + } + *p = (uint32_t) (maxrp) / *r; + } + return 0; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_saltbytes(void) +{ + return crypto_pwhash_scryptsalsa208sha256_SALTBYTES; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_strbytes(void) +{ + return crypto_pwhash_scryptsalsa208sha256_STRBYTES; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void) +{ + return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void) +{ + return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void) +{ + return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void) +{ + return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE; +} + +int +crypto_pwhash_scryptsalsa208sha256(unsigned char * const out, + unsigned long long outlen, + const char * const passwd, + unsigned long long passwdlen, + const unsigned char * const salt, + unsigned long long opslimit, + size_t memlimit) +{ + uint32_t N_log2; + uint32_t p; + uint32_t r; + + memset(out, 0, outlen); + if (passwdlen > SIZE_MAX || outlen > SIZE_MAX) { + errno = EFBIG; + return -1; + } + if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { + errno = EINVAL; + return -1; + } + return crypto_pwhash_scryptsalsa208sha256_ll((const uint8_t *) passwd, + (size_t) passwdlen, + (const uint8_t *) salt, + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, + (uint64_t) (1) << N_log2, r, p, + out, (size_t) outlen); +} + +int +crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES], + const char * const passwd, + unsigned long long passwdlen, + unsigned long long opslimit, + size_t memlimit) +{ + uint8_t salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES]; + char setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U]; + escrypt_local_t escrypt_local; + uint32_t N_log2; + uint32_t p; + uint32_t r; + + memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES); + if (passwdlen > SIZE_MAX) { + errno = EFBIG; + return -1; + } + if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { + errno = EINVAL; + return -1; + } + randombytes_buf(salt, sizeof salt); + if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt, + (uint8_t *) setting, sizeof setting) == NULL) { + errno = EINVAL; + return -1; + } + if (escrypt_init_local(&escrypt_local) != 0) { + return -1; + } + if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, + (const uint8_t *) setting, (uint8_t *) out, + crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) { + escrypt_free_local(&escrypt_local); + errno = EINVAL; + return -1; + } + escrypt_free_local(&escrypt_local); + + (void) sizeof + (int[SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES) + == crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES ? 1 : -1]); + (void) sizeof + (int[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U + + crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U + == crypto_pwhash_scryptsalsa208sha256_STRBYTES ? 1 : -1]); + + return 0; +} + +int +crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], + const char * const passwd, + unsigned long long passwdlen) +{ + char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES]; + escrypt_local_t escrypt_local; + int ret = -1; + + if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) != + &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) { + return -1; + } + if (escrypt_init_local(&escrypt_local) != 0) { + return -1; + } + if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, + (const uint8_t *) str, (uint8_t *) wanted, + sizeof wanted) == NULL) { + escrypt_free_local(&escrypt_local); + return -1; + } + escrypt_free_local(&escrypt_local); + ret = sodium_memcmp(wanted, str, sizeof wanted); + sodium_memzero(wanted, sizeof wanted); + + return ret; +} |