mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Move PBKDF internal benchmark to one place.
Also cache its value in active context, so we run benchmark only once. The patch also changes calculated value for LUKS1 key digest to 125 miliseconds (it means that for full 8 used slots the additional slow-down is circa 1 second). Note that there is no need to have too high iteration count for key digest; if it is too computationally expensive, attacker will better decrypt of one sector with candidate key anyway. (Check for a known signature.) The reason to have some delay for key digest check was to complicate brute-force search for volume key with LUKS header only (and if RNG used to generate volumekey was flawed allowing such a search i reasonable time).
This commit is contained in:
@@ -255,11 +255,77 @@ int crypt_benchmark_pbkdf(struct crypt_device *cd,
|
||||
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,
|
||||
&pbkdf->time_ms, &pbkdf->max_memory_kb, progress, usrptr);
|
||||
&pbkdf->iterations, &pbkdf->max_memory_kb, progress, usrptr);
|
||||
|
||||
if (!r)
|
||||
log_dbg("Benchmark returns %s(%s) %u iterations, %u memory, %u threads (for %zu-bits key).",
|
||||
pbkdf->type, kdf_opt, pbkdf->time_ms, pbkdf->max_memory_kb,
|
||||
pbkdf->type, kdf_opt, pbkdf->iterations, pbkdf->max_memory_kb,
|
||||
pbkdf->parallel_threads, volume_key_size * 8);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int benchmark_callback(long time_ms, void *usrptr)
|
||||
{
|
||||
struct crypt_pbkdf_type *pbkdf = usrptr;
|
||||
|
||||
log_dbg("PBKDF benchmark: memory cost = %u, iterations = %u, "
|
||||
"threads = %u (took %ld ms)", pbkdf->max_memory_kb,
|
||||
pbkdf->iterations, pbkdf->parallel_threads, time_ms);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Used in internal places to benchmark crypt_device context PBKDF.
|
||||
* Once requested parameters are benchmarked, iterations attribute is set,
|
||||
* and the benchamarked values can be reused.
|
||||
* Note that memory cost can be changed after benchark (if used).
|
||||
* NOTE: You need to check that you are benchmarking for the same key size.
|
||||
*/
|
||||
int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
|
||||
struct crypt_pbkdf_type *pbkdf,
|
||||
size_t volume_key_size)
|
||||
{
|
||||
double PBKDF2_tmp;
|
||||
uint32_t ms_tmp;
|
||||
int r = -EINVAL;
|
||||
|
||||
/* Already benchmarked */
|
||||
if (pbkdf->iterations) {
|
||||
log_dbg("Reusing PBKDF benchmark values.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) {
|
||||
/*
|
||||
* For PBKDF2 it is enouch to run benchmark for only 1 second
|
||||
* and interpolate final iterarions value from it.
|
||||
*/
|
||||
ms_tmp = pbkdf->time_ms;
|
||||
pbkdf->time_ms = 1000;
|
||||
pbkdf->parallel_threads = 0; /* N/A in PBKDF2 */
|
||||
pbkdf->max_memory_kb = 0; /* N/A in PBKDF2 */
|
||||
|
||||
r = crypt_benchmark_pbkdf(cd, pbkdf, "foo", 3, "bar", 3,
|
||||
volume_key_size, &benchmark_callback, pbkdf);
|
||||
pbkdf->time_ms = ms_tmp;
|
||||
if (r < 0) {
|
||||
log_err(cd, _("Not compatible PBKDF2 options (using hash algorithm %s).\n"),
|
||||
pbkdf->hash);
|
||||
return r;
|
||||
}
|
||||
|
||||
PBKDF2_tmp = ((double)pbkdf->iterations * pbkdf->time_ms / 1000.);
|
||||
if (PBKDF2_tmp > (double)UINT32_MAX)
|
||||
return -EINVAL;
|
||||
pbkdf->iterations = at_least((uint32_t)PBKDF2_tmp, MIN_PBKDF2_ITERATIONS);
|
||||
} else {
|
||||
r = crypt_benchmark_pbkdf(cd, pbkdf, "foo", 3,
|
||||
"0123456789abcdef0123456789abcdef", 32,
|
||||
volume_key_size, &benchmark_callback, pbkdf);
|
||||
if (r < 0)
|
||||
log_err(cd, _("Not compatible PBKDF options.\n"));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user