Add Argon2 benchmark code.

Code based on patch by Ondrej Mosnacek

The new benchmark works as follows:

Phase 1:
It searches for smallest parameters, such that the duration is 250 ms
(this part is quite fast).
Then it uses that data point to estimate the paramters that will have
the desired duration (and fulfill the basic constraints).

Phase 2:
The candidate parameters are then measured and if their duration falls
within +-5% of the target duration, they are accepted.
Otherwise, new candidate parameters are estimated based on the last
measurement and phase 2 is repeated.

When measuring the duration for given parameters, the measurement
is repeated 3 or 4 times and a minimum of the measured durations
is used as the final duration (to reduce variance in measurements).
A minimum is taken instead of mean, because the measurements definitely
have a certain lower bound, but no upper bound (therefore mean value
would tend to be higher than the value with highest probability density).
The actual "most likely" duration is going to be somewhere just above
the minimum measurable value, so minimum over the observations is
a better estimate than mean.

Signed-off-by: Milan Broz <gmazyland@gmail.com>
This commit is contained in:
Milan Broz
2017-08-05 21:51:55 +02:00
parent 0abf57be5d
commit 8a859391be
4 changed files with 264 additions and 21 deletions

View File

@@ -241,26 +241,26 @@ int crypt_benchmark_pbkdf(struct crypt_device *cd,
uint32_t *iterations,
uint32_t *memory)
{
uint32_t iterations_sec;
int r;
r = init_crypto(cd);
if (r < 0)
return r;
if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) {
if (!iterations || memory)
return -EINVAL;
/* Hack to not print hash for argon, it is used also for AF later.*/
if (pbkdf->hash && !memory)
log_dbg("Running %s-%s benchmark.", pbkdf->type, pbkdf->hash);
else
log_dbg("Running %s benchmark.", pbkdf->type);
r = crypt_pbkdf_check(pbkdf->type, pbkdf->hash, password, password_size,
salt, salt_size, volume_key_size, &iterations_sec);
*iterations = (uint32_t)((uint64_t)iterations_sec * (uint64_t)pbkdf->time_ms / 1000);
if (!r)
log_dbg("PBKDF2 benchmark, hash %s: %u iterations per second (%zu-bits key).",
pbkdf->hash, iterations_sec, volume_key_size * 8);
} else
r = -EINVAL;
r = crypt_pbkdf_perf(pbkdf->type, pbkdf->hash, password, password_size,
salt, salt_size, volume_key_size, pbkdf->time_ms,
pbkdf->max_memory_kb, pbkdf->parallel_threads,
iterations, memory);
if (!r)
log_dbg(" %u iterations, %u memory (for %zu-bits key).",
iterations ? *iterations : 0, memory ? *memory : 0,
volume_key_size * 8);
return r;
}