Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
319 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,4 +14,5 @@ | |
#include "impl/x25519.h" | ||
|
||
#include "impl/kx.h" | ||
#include "impl/pwhash.h" | ||
#include "impl/sign.h" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
#define hydro_pwhash_ENC_ALGBYTES 1 | ||
#define hydro_pwhash_HASH_ALGBYTES 1 | ||
#define hydro_pwhash_THREADSBYTES 1 | ||
#define hydro_pwhash_OPSLIMITBYTES 8 | ||
#define hydro_pwhash_MEMLIMITBYTES 8 | ||
#define hydro_pwhash_HASHBYTES 32 | ||
#define hydro_pwhash_SALTBYTES 16 | ||
#define hydro_pwhash_PARAMSBYTES \ | ||
(hydro_pwhash_HASH_ALGBYTES + hydro_pwhash_THREADSBYTES + \ | ||
hydro_pwhash_OPSLIMITBYTES + hydro_pwhash_MEMLIMITBYTES + \ | ||
hydro_pwhash_SALTBYTES + hydro_pwhash_HASHBYTES) | ||
#define hydro_pwhash_ENC_ALG 0x01 | ||
#define hydro_pwhash_HASH_ALG 0x01 | ||
#define hydro_pwhash_CONTEXT "hydro_pw" | ||
|
||
static int | ||
_hydro_pwhash_hash(uint8_t out[randombytes_SEEDBYTES], size_t h_len, | ||
const uint8_t salt[hydro_pwhash_SALTBYTES], | ||
const char *passwd, size_t passwd_len, | ||
const char ctx[hydro_pwhash_CONTEXTBYTES], | ||
const uint8_t key[hydro_pwhash_KEYBYTES], uint64_t opslimit, | ||
size_t memlimit, uint8_t threads) | ||
{ | ||
hydro_hash_state h_st; | ||
uint8_t state[gimli_BLOCKBYTES]; | ||
uint8_t tmp64_u8[8]; | ||
uint64_t i; | ||
uint8_t tmp8; | ||
|
||
hydro_hash_init(&h_st, ctx, key, hydro_pwhash_KEYBYTES); | ||
|
||
STORE64_LE(tmp64_u8, (uint64_t) passwd_len); | ||
hydro_hash_update(&h_st, tmp64_u8, sizeof tmp64_u8); | ||
hydro_hash_update(&h_st, passwd, passwd_len); | ||
|
||
hydro_hash_update(&h_st, salt, hydro_pwhash_SALTBYTES); | ||
|
||
tmp8 = hydro_pwhash_HASH_ALG; | ||
hydro_hash_update(&h_st, &tmp8, 1); | ||
|
||
hydro_hash_update(&h_st, &threads, 1); | ||
|
||
STORE64_LE(tmp64_u8, (uint64_t) opslimit); | ||
hydro_hash_update(&h_st, tmp64_u8, sizeof tmp64_u8); | ||
|
||
STORE64_LE(tmp64_u8, (uint64_t) memlimit); | ||
hydro_hash_update(&h_st, tmp64_u8, sizeof tmp64_u8); | ||
|
||
STORE64_LE(tmp64_u8, (uint64_t) h_len); | ||
hydro_hash_update(&h_st, tmp64_u8, sizeof tmp64_u8); | ||
|
||
hydro_hash_final(&h_st, (uint8_t *) (void *) &state, sizeof state); | ||
|
||
gimli_core_u8(state, 0); | ||
for (i = 0; i < opslimit; i++) { | ||
mem_zero(state, gimli_RATE); | ||
gimli_core_u8(state, 1); | ||
} | ||
gimli_core_u8(state, 2); | ||
|
||
COMPILER_ASSERT(randombytes_SEEDBYTES <= gimli_BLOCKBYTES); | ||
mem_cpy(out, state, randombytes_SEEDBYTES); | ||
mem_zero(state, sizeof state); | ||
|
||
return 0; | ||
} | ||
|
||
void | ||
hydro_pwhash_keygen(uint8_t key[hydro_pwhash_KEYBYTES]) | ||
{ | ||
randombytes_buf(key, hydro_pwhash_KEYBYTES); | ||
} | ||
|
||
int | ||
hydro_pwhash_deterministic(uint8_t *h, size_t h_len, const char *passwd, | ||
size_t passwd_len, | ||
const char ctx[hydro_pwhash_CONTEXTBYTES], | ||
const uint8_t key[hydro_pwhash_KEYBYTES], | ||
uint64_t opslimit, size_t memlimit, uint8_t threads) | ||
{ | ||
uint8_t seed[randombytes_SEEDBYTES]; | ||
|
||
COMPILER_ASSERT(sizeof zero >= hydro_pwhash_SALTBYTES); | ||
COMPILER_ASSERT(sizeof zero >= hydro_pwhash_KEYBYTES); | ||
|
||
(void) memlimit; | ||
if (_hydro_pwhash_hash(seed, h_len, zero, passwd, passwd_len, ctx, key, | ||
opslimit, memlimit, threads) != 0) { | ||
return -1; | ||
} | ||
randombytes_buf_deterministic(h, h_len, seed); | ||
mem_zero(seed, sizeof seed); | ||
|
||
return 0; | ||
} | ||
|
||
int | ||
hydro_pwhash_create(uint8_t stored[hydro_pwhash_STOREDBYTES], | ||
const char *passwd, size_t passwd_len, | ||
const uint8_t key[hydro_pwhash_KEYBYTES], uint64_t opslimit, | ||
size_t memlimit, uint8_t threads) | ||
{ | ||
uint8_t *const enc_alg = &stored[0]; | ||
uint8_t *const secretbox = &enc_alg[hydro_pwhash_ENC_ALGBYTES]; | ||
uint8_t *const hash_alg = &secretbox[hydro_secretbox_HEADERBYTES]; | ||
uint8_t *const threads_u8 = &hash_alg[hydro_pwhash_HASH_ALGBYTES]; | ||
uint8_t *const opslimit_u8 = &threads_u8[hydro_pwhash_THREADSBYTES]; | ||
uint8_t *const memlimit_u8 = &opslimit_u8[hydro_pwhash_OPSLIMITBYTES]; | ||
uint8_t *const salt = &memlimit_u8[hydro_pwhash_MEMLIMITBYTES]; | ||
uint8_t *const h = &salt[hydro_pwhash_SALTBYTES]; | ||
|
||
COMPILER_ASSERT(hydro_pwhash_STOREDBYTES >= | ||
hydro_pwhash_ENC_ALGBYTES + hydro_secretbox_HEADERBYTES + | ||
hydro_pwhash_PARAMSBYTES); | ||
(void) memlimit; | ||
mem_zero(stored, hydro_pwhash_STOREDBYTES); | ||
*enc_alg = hydro_pwhash_ENC_ALG; | ||
*hash_alg = hydro_pwhash_HASH_ALG; | ||
*threads_u8 = threads; | ||
STORE64_LE(opslimit_u8, opslimit); | ||
STORE64_LE(memlimit_u8, (uint64_t) memlimit); | ||
randombytes_buf(salt, hydro_pwhash_SALTBYTES); | ||
|
||
if (_hydro_pwhash_hash(h, hydro_pwhash_HASHBYTES, salt, passwd, passwd_len, | ||
hydro_pwhash_CONTEXT, key, opslimit, memlimit, | ||
threads) != 0) { | ||
return -1; | ||
} | ||
COMPILER_ASSERT(hydro_pwhash_KEYBYTES == hydro_secretbox_KEYBYTES); | ||
|
||
return hydro_secretbox_encrypt( | ||
secretbox, hash_alg, hydro_pwhash_PARAMSBYTES, (uint64_t) *enc_alg, | ||
hydro_pwhash_CONTEXT, key); | ||
} | ||
|
||
static int | ||
_hydro_pwhash_verify(uint8_t computed_h[hydro_pwhash_HASHBYTES], | ||
const uint8_t stored[hydro_pwhash_STOREDBYTES], | ||
const char *passwd, size_t passwd_len, | ||
const uint8_t key[hydro_pwhash_KEYBYTES], | ||
uint64_t opslimit_max, size_t memlimit_max, | ||
uint8_t threads_max) | ||
{ | ||
const uint8_t *const enc_alg = &stored[0]; | ||
const uint8_t *const secretbox = &enc_alg[hydro_pwhash_ENC_ALGBYTES]; | ||
uint8_t params[hydro_pwhash_PARAMSBYTES]; | ||
uint8_t *const hash_alg = ¶ms[0]; | ||
uint8_t *const threads_u8 = &hash_alg[hydro_pwhash_HASH_ALGBYTES]; | ||
uint8_t *const opslimit_u8 = &threads_u8[hydro_pwhash_THREADSBYTES]; | ||
uint8_t *const memlimit_u8 = &opslimit_u8[hydro_pwhash_OPSLIMITBYTES]; | ||
uint8_t *const salt = &memlimit_u8[hydro_pwhash_MEMLIMITBYTES]; | ||
uint8_t *const h = &salt[hydro_pwhash_SALTBYTES]; | ||
uint64_t opslimit; | ||
size_t memlimit; | ||
uint8_t threads; | ||
|
||
(void) memlimit; | ||
if (*enc_alg != hydro_pwhash_ENC_ALG) { | ||
return -1; | ||
} | ||
if (hydro_secretbox_decrypt( | ||
params, secretbox, | ||
hydro_secretbox_HEADERBYTES + hydro_pwhash_PARAMSBYTES, | ||
(uint64_t) *enc_alg, hydro_pwhash_CONTEXT, key) != 0) { | ||
return -1; | ||
} | ||
if (*hash_alg != hydro_pwhash_HASH_ALG || | ||
(opslimit = LOAD64_LE(opslimit_u8)) > opslimit_max || | ||
(memlimit = (size_t) LOAD64_LE(memlimit_u8)) > memlimit_max || | ||
(threads = *threads_u8) > threads_max) { | ||
return -1; | ||
} | ||
if (_hydro_pwhash_hash(computed_h, hydro_pwhash_HASHBYTES, salt, passwd, | ||
passwd_len, hydro_pwhash_CONTEXT, key, opslimit, | ||
memlimit, threads) == 0 && | ||
hydro_equal(computed_h, h, hydro_pwhash_HASHBYTES) == 1) { | ||
return 0; | ||
} | ||
return -1; | ||
} | ||
|
||
int | ||
hydro_pwhash_verify(const uint8_t stored[hydro_pwhash_STOREDBYTES], | ||
const char *passwd, size_t passwd_len, | ||
const uint8_t key[hydro_pwhash_KEYBYTES], | ||
uint64_t opslimit_max, size_t memlimit_max, | ||
uint8_t threads_max) | ||
{ | ||
uint8_t computed_h[hydro_pwhash_HASHBYTES]; | ||
int ret; | ||
|
||
ret = _hydro_pwhash_verify(computed_h, stored, passwd, passwd_len, key, | ||
opslimit_max, memlimit_max, threads_max); | ||
hydro_memzero(computed_h, sizeof computed_h); | ||
|
||
return ret; | ||
} | ||
|
||
int | ||
hydro_pwhash_derive_static_key(uint8_t *static_key, size_t static_key_len, | ||
const uint8_t stored[hydro_pwhash_STOREDBYTES], | ||
const char *passwd, size_t passwd_len, | ||
const char ctx[hydro_pwhash_CONTEXTBYTES], | ||
const uint8_t key[hydro_pwhash_KEYBYTES], | ||
uint64_t opslimit_max, size_t memlimit_max, | ||
uint8_t threads_max) | ||
{ | ||
uint8_t computed_h[hydro_pwhash_HASHBYTES]; | ||
|
||
if (_hydro_pwhash_verify(computed_h, stored, passwd, passwd_len, key, | ||
opslimit_max, memlimit_max, threads_max) != 0) { | ||
hydro_memzero(computed_h, sizeof computed_h); | ||
return -1; | ||
} | ||
COMPILER_ASSERT(hydro_kdf_CONTEXTBYTES <= hydro_pwhash_CONTEXTBYTES); | ||
COMPILER_ASSERT(hydro_kdf_KEYBYTES <= hydro_pwhash_HASHBYTES); | ||
hydro_kdf_derive_from_key(static_key, static_key_len, 0, ctx, computed_h); | ||
hydro_memzero(computed_h, sizeof computed_h); | ||
|
||
return 0; | ||
} |
Oops, something went wrong.