diff --git a/src/crypto/wbag-hash.c b/src/crypto/wbag-hash.c index 9ee96e3cf..9a2a2907e 100644 --- a/src/crypto/wbag-hash.c +++ b/src/crypto/wbag-hash.c @@ -28,6 +28,10 @@ extern "C" { #define WBAG_ROUNDS 32768u // number of rounds #endif +#ifndef WBAG_SCRATCHPAD +#define WBAG_SCRATCHPAD (1u * 1024u * 1024u) // 1 MiB per-hash +#endif + #define WBAG_N_ENTRIES ( (WBAG_CACHE_BYTES / WBAG_ENTRY_BYTES) ) #ifndef WBAG_ARGON2_P @@ -65,6 +69,9 @@ _Static_assert(WBAG_ARGON2_P == 2u, "WBAG requires Argon2 p=2"); #if (WBAG_ROUNDS > UINT32_MAX) # error "WBAG_ROUNDS must be <= UINT32_MAX because the rounds counter is u32" #endif +#if (WBAG_SCRATCHPAD % 8u) != 0 +# error "WBAG_SCRATCH_PAD must be a multiple of 8" +#endif #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L _Static_assert(WBAG_ENTRY_BYTES >= 32, "entry must be >= 32"); @@ -218,7 +225,7 @@ int WBAG_hash(const void *bd, size_t bd_len, const uint8_t *cache, uint8_t out32 memcpy(buf + 1, bd, bd_len); blake256_hash(st_bytes, buf, (uint64_t)(bd_len + 1)); - // 2) State lanes + PRNG seed + // 2) State lanes + PRNG seed + scratchpad uint64_t st64[4]; st64[0] = WBAG_load64_le(st_bytes + 0); st64[1] = WBAG_load64_le(st_bytes + 8); @@ -231,6 +238,17 @@ int WBAG_hash(const void *bd, size_t bd_len, const uint8_t *cache, uint8_t out32 s ^= st64[2]; s = WBAG_splitmix64(s); s ^= st64[3]; s = WBAG_splitmix64(s); + uint8_t *scratchpad = (uint8_t*)malloc(WBAG_SCRATCHPAD); + if (!scratchpad) { free(buf); errno = ENOMEM; return -1; } + { + uint64_t q = st64[0] ^ st64[1] ^ st64[2] ^ st64[3] ^ 0x243F6A8885A308D3ULL; + for (size_t i = 0; i < WBAG_SCRATCHPAD/8; i++) { + q = WBAG_splitmix64(q); + WBAG_store64_le(scratchpad + 8*i, q); + } + } + const size_t smask = (WBAG_SCRATCHPAD/8u) - 1u; + // 3) Dependent random rounds const size_t n_mask = (size_t)WBAG_N_ENTRIES - 1; @@ -258,6 +276,11 @@ int WBAG_hash(const void *bd, size_t bd_len, const uint8_t *cache, uint8_t out32 st64[2] = WBAG_rotl64(x2 ^ (x0 + 0x9e3779b97f4a7c15ULL), 17); st64[3] = WBAG_rotl64(x3 ^ (x1 + 0x94d049bb133111ebULL), 29); + size_t sidx = (size_t)((s >> 11) & (uint64_t)smask); + uint64_t v = WBAG_load64_le(scratchpad + (sidx * 8u)); + st64[0] ^= v; + s ^= WBAG_rotl64(v, (unsigned)((s >> 23) & 63u)); + size_t off = (size_t)((s >> 3) & (uint64_t)((size_t)WBAG_ENTRY_BYTES - 8)); uint64_t e = WBAG_load64_le(entry + off); @@ -276,6 +299,7 @@ int WBAG_hash(const void *bd, size_t bd_len, const uint8_t *cache, uint8_t out32 memcpy(buf + (1 + 32), bd, bd_len); groestl(buf, (1 + 32) + bd_len, out32); + free(scratchpad); free(buf); return 0; } @@ -285,6 +309,7 @@ size_t WBAG_cache_bytes(void) { return (size_t)WBAG_CACHE_BYTES; } size_t WBAG_entry_bytes(void) { return (size_t)WBAG_ENTRY_BYTES; } size_t WBAG_cache_entries(void) { return (size_t)WBAG_N_ENTRIES; } size_t WBAG_rounds(void) { return (size_t)WBAG_ROUNDS; } +size_t WBAG_scratchpad(void) { return (size_t)WBAG_SCRATCHPAD; } size_t WBAG_argon_p(void) { return (size_t)WBAG_ARGON2_P; } size_t WBAG_argon_t(void) { return (size_t)WBAG_ARGON2_T; } diff --git a/src/crypto/wbag-hash.h b/src/crypto/wbag-hash.h index f723499d4..9a132d99a 100644 --- a/src/crypto/wbag-hash.h +++ b/src/crypto/wbag-hash.h @@ -20,6 +20,7 @@ size_t WBAG_cache_bytes(void); size_t WBAG_entry_bytes(void); size_t WBAG_cache_entries(void); size_t WBAG_rounds(void); +size_t WBAG_scratchpad(void); size_t WBAG_argon_p(void); size_t WBAG_argon_t(void); diff --git a/tests/hash/wbag_test.cpp b/tests/hash/wbag_test.cpp index afd4e3c78..c91c9787d 100644 --- a/tests/hash/wbag_test.cpp +++ b/tests/hash/wbag_test.cpp @@ -531,11 +531,14 @@ int wbag_test() { const std::vector block(80, 0x42); const size_t cache_bytes = WBAG_cache_bytes(); const double cache_mb = static_cast(cache_bytes) / (1024.0 * 1024.0); + const size_t sp_bytes = WBAG_scratchpad(); + const double sp_mb = static_cast(sp_bytes) / (1024.0 * 1024.0); const int total = static_cast(sizeof(k_wbag_anchor_samples) / sizeof(k_wbag_anchor_samples[0])); std::cerr << "Params:" << " WBAG_CACHE_BYTES=" << cache_mb << ", WBAG_ENTRY_BYTES=" << WBAG_entry_bytes() + << ", WBAG_SCRATCHPAD=" << sp_mb << ", WBAG_ROUNDS=" << WBAG_rounds() << ", WBAG_ARGON2_P=" << WBAG_argon_p() << ", WBAG_ARGON2_T=" << WBAG_argon_t();