mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Move PBKDF limits to crypto backend (to one place).
This commit is contained in:
@@ -57,6 +57,13 @@ int crypt_hmac_destroy(struct crypt_hmac *ctx);
|
||||
enum { CRYPT_RND_NORMAL = 0, CRYPT_RND_KEY = 1, CRYPT_RND_SALT = 2 };
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips);
|
||||
|
||||
struct crypt_pbkdf_limits {
|
||||
uint32_t min_iterations, max_iterations;
|
||||
uint32_t min_memory, max_memory;
|
||||
uint32_t min_parallel, max_parallel;
|
||||
};
|
||||
int crypt_pbkdf_get_limits(const char *kdf, struct crypt_pbkdf_limits *l);
|
||||
|
||||
/* PBKDF*/
|
||||
int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
|
||||
@@ -34,6 +34,33 @@
|
||||
#define BENCH_SAMPLES_FAST 3
|
||||
#define BENCH_SAMPLES_SLOW 1
|
||||
|
||||
/* These PBKDF2 limits must be never violated */
|
||||
int crypt_pbkdf_get_limits(const char *kdf, struct crypt_pbkdf_limits *limits)
|
||||
{
|
||||
if (!kdf || !limits)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strcmp(kdf, "pbkdf2")) {
|
||||
limits->min_iterations = 1000; /* recommendation in NIST SP 800-132 */
|
||||
limits->max_iterations = UINT32_MAX;
|
||||
limits->min_memory = 0; /* N/A */
|
||||
limits->max_memory = 0; /* N/A */
|
||||
limits->min_parallel = 0; /* N/A */
|
||||
limits->max_parallel = 0; /* N/A */
|
||||
return 0;
|
||||
} else if (!strncmp(kdf, "argon2", 6)) {
|
||||
limits->min_iterations = 4;
|
||||
limits->max_iterations = UINT32_MAX;
|
||||
limits->min_memory = 32;
|
||||
limits->max_memory = 4*1024*1024; /* 4GiB */
|
||||
limits->min_parallel = 1;
|
||||
limits->max_parallel = 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static long time_ms(struct rusage *start, struct rusage *end)
|
||||
{
|
||||
int count_kernel_time = 0;
|
||||
@@ -362,8 +389,6 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
#define ARGON2_MIN_T_COST 4
|
||||
|
||||
int crypt_pbkdf_perf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_size,
|
||||
const char *salt, size_t salt_size,
|
||||
@@ -372,11 +397,16 @@ int crypt_pbkdf_perf(const char *kdf, const char *hash,
|
||||
uint32_t *iterations_out, uint32_t *memory_out,
|
||||
int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr)
|
||||
{
|
||||
struct crypt_pbkdf_limits pbkdf_limits;
|
||||
int r = -EINVAL;
|
||||
|
||||
if (!kdf || !iterations_out || !memory_out)
|
||||
return -EINVAL;
|
||||
|
||||
r = crypt_pbkdf_get_limits(kdf, &pbkdf_limits);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*memory_out = 0;
|
||||
*iterations_out = 0;
|
||||
|
||||
@@ -388,7 +418,7 @@ int crypt_pbkdf_perf(const char *kdf, const char *hash,
|
||||
else if (!strncmp(kdf, "argon2", 6))
|
||||
r = crypt_argon2_check(kdf, password, password_size,
|
||||
salt, salt_size, volume_key_size,
|
||||
ARGON2_MIN_T_COST, max_memory_kb,
|
||||
pbkdf_limits.min_iterations, max_memory_kb,
|
||||
parallel_threads, time_ms, iterations_out,
|
||||
memory_out, progress, usrptr);
|
||||
return r;
|
||||
|
||||
@@ -51,10 +51,6 @@
|
||||
#define DEFAULT_MEM_ALIGNMENT 4096
|
||||
#define MAX_ERROR_LENGTH 512
|
||||
|
||||
#define MAX_PBKDF_THREADS 4
|
||||
#define MAX_PBKDF_MEMORY 4*1024*1024 /* 4GiB */
|
||||
#define MIN_PBKDF2_ITERATIONS 1000 /* recommendation in NIST SP 800-132 */
|
||||
|
||||
#define at_least(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); })
|
||||
|
||||
struct crypt_device;
|
||||
|
||||
@@ -98,6 +98,7 @@ static int PBKDF2_digest_store(struct crypt_device *cd,
|
||||
int r;
|
||||
char *base64_str;
|
||||
struct luks2_hdr *hdr;
|
||||
struct crypt_pbkdf_limits pbkdf_limits;
|
||||
struct crypt_pbkdf_type pbkdf = {
|
||||
.type = CRYPT_KDF_PBKDF2,
|
||||
.hash = "sha256",
|
||||
@@ -110,8 +111,12 @@ static int PBKDF2_digest_store(struct crypt_device *cd,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = crypt_pbkdf_get_limits(CRYPT_KDF_PBKDF2, &pbkdf_limits);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (crypt_get_pbkdf(cd)->flags & CRYPT_PBKDF_NO_BENCHMARK)
|
||||
pbkdf.iterations = MIN_PBKDF2_ITERATIONS;
|
||||
pbkdf.iterations = pbkdf_limits.min_iterations;
|
||||
else {
|
||||
r = crypt_benchmark_pbkdf_internal(cd, &pbkdf, volume_key_len);
|
||||
if (r < 0)
|
||||
|
||||
@@ -289,6 +289,7 @@ int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
|
||||
struct crypt_pbkdf_type *pbkdf,
|
||||
size_t volume_key_size)
|
||||
{
|
||||
struct crypt_pbkdf_limits pbkdf_limits;
|
||||
double PBKDF2_tmp;
|
||||
uint32_t ms_tmp;
|
||||
int r = -EINVAL;
|
||||
@@ -304,6 +305,10 @@ int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) {
|
||||
/*
|
||||
* For PBKDF2 it is enough to run benchmark for only 1 second
|
||||
@@ -326,7 +331,7 @@ int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
|
||||
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);
|
||||
pbkdf->iterations = at_least((uint32_t)PBKDF2_tmp, pbkdf_limits.min_iterations);
|
||||
} else {
|
||||
r = crypt_benchmark_pbkdf(cd, pbkdf, "foo", 3,
|
||||
"0123456789abcdef0123456789abcdef", 32,
|
||||
|
||||
@@ -61,6 +61,7 @@ static uint32_t adjusted_phys_memory(void)
|
||||
int verify_pbkdf_params(struct crypt_device *cd,
|
||||
const struct crypt_pbkdf_type *pbkdf)
|
||||
{
|
||||
struct crypt_pbkdf_limits pbkdf_limits;
|
||||
const char *pbkdf_type;
|
||||
int r = 0;
|
||||
|
||||
@@ -74,6 +75,10 @@ int verify_pbkdf_params(struct crypt_device *cd,
|
||||
return r;
|
||||
}
|
||||
|
||||
r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (crypt_get_type(cd) &&
|
||||
!strcmp(crypt_get_type(cd), CRYPT_LUKS1) &&
|
||||
strcmp(pbkdf_type, CRYPT_KDF_PBKDF2)) {
|
||||
@@ -87,9 +92,9 @@ int verify_pbkdf_params(struct crypt_device *cd,
|
||||
return -EINVAL;
|
||||
}
|
||||
if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK &&
|
||||
pbkdf->iterations < MIN_PBKDF2_ITERATIONS) {
|
||||
pbkdf->iterations < pbkdf_limits.min_iterations) {
|
||||
log_err(cd, _("Forced iteration count is too low for %s (minimum is %u).\n"),
|
||||
pbkdf_type, MIN_PBKDF2_ITERATIONS);
|
||||
pbkdf_type, pbkdf_limits.min_iterations);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
@@ -97,21 +102,21 @@ int verify_pbkdf_params(struct crypt_device *cd,
|
||||
|
||||
/* TODO: properly define minimal iterations and also minimal memory values */
|
||||
if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK) {
|
||||
if (pbkdf->iterations < 4) {
|
||||
if (pbkdf->iterations < pbkdf_limits.min_iterations) {
|
||||
log_err(cd, _("Forced iteration count is too low for %s (minimum is %u).\n"),
|
||||
pbkdf_type, 4);
|
||||
pbkdf_type, pbkdf_limits.min_iterations);
|
||||
r = -EINVAL;
|
||||
}
|
||||
if (pbkdf->max_memory_kb < 32) {
|
||||
if (pbkdf->max_memory_kb < pbkdf_limits.min_memory) {
|
||||
log_err(cd, _("Forced memory cost is too low for %s (minimum is %u kilobytes).\n"),
|
||||
pbkdf_type, 32);
|
||||
pbkdf_type, pbkdf_limits.min_memory);
|
||||
r = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (pbkdf->max_memory_kb > MAX_PBKDF_MEMORY) {
|
||||
if (pbkdf->max_memory_kb > pbkdf_limits.max_memory) {
|
||||
log_err(cd, _("Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes).\n"),
|
||||
MAX_PBKDF_MEMORY);
|
||||
pbkdf_limits.max_memory);
|
||||
r = -EINVAL;
|
||||
}
|
||||
if (!pbkdf->max_memory_kb) {
|
||||
@@ -135,6 +140,7 @@ int init_pbkdf_type(struct crypt_device *cd,
|
||||
const char *dev_type)
|
||||
{
|
||||
struct crypt_pbkdf_type *cd_pbkdf = crypt_get_pbkdf(cd);
|
||||
struct crypt_pbkdf_limits pbkdf_limits;
|
||||
const char *hash, *type;
|
||||
unsigned cpus;
|
||||
uint32_t old_flags, memory_kb;
|
||||
@@ -149,6 +155,10 @@ int init_pbkdf_type(struct crypt_device *cd,
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/*
|
||||
* Crypto backend may be not initialized here,
|
||||
* cannot check if algorithms are really available.
|
||||
@@ -185,10 +195,10 @@ int init_pbkdf_type(struct crypt_device *cd,
|
||||
cd_pbkdf->max_memory_kb = pbkdf->max_memory_kb;
|
||||
cd_pbkdf->parallel_threads = pbkdf->parallel_threads;
|
||||
|
||||
if (cd_pbkdf->parallel_threads > MAX_PBKDF_THREADS) {
|
||||
if (cd_pbkdf->parallel_threads > pbkdf_limits.max_parallel) {
|
||||
log_dbg("Maximum PBKDF threads is %d (requested %d).",
|
||||
MAX_PBKDF_THREADS, cd_pbkdf->parallel_threads);
|
||||
cd_pbkdf->parallel_threads = MAX_PBKDF_THREADS;
|
||||
pbkdf_limits.max_parallel, cd_pbkdf->parallel_threads);
|
||||
cd_pbkdf->parallel_threads = pbkdf_limits.max_parallel;
|
||||
}
|
||||
|
||||
if (cd_pbkdf->parallel_threads) {
|
||||
|
||||
Reference in New Issue
Block a user