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 };
|
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);
|
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*/
|
/* PBKDF*/
|
||||||
int crypt_pbkdf(const char *kdf, const char *hash,
|
int crypt_pbkdf(const char *kdf, const char *hash,
|
||||||
const char *password, size_t password_length,
|
const char *password, size_t password_length,
|
||||||
|
|||||||
@@ -34,6 +34,33 @@
|
|||||||
#define BENCH_SAMPLES_FAST 3
|
#define BENCH_SAMPLES_FAST 3
|
||||||
#define BENCH_SAMPLES_SLOW 1
|
#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)
|
static long time_ms(struct rusage *start, struct rusage *end)
|
||||||
{
|
{
|
||||||
int count_kernel_time = 0;
|
int count_kernel_time = 0;
|
||||||
@@ -362,8 +389,6 @@ out:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ARGON2_MIN_T_COST 4
|
|
||||||
|
|
||||||
int crypt_pbkdf_perf(const char *kdf, const char *hash,
|
int crypt_pbkdf_perf(const char *kdf, const char *hash,
|
||||||
const char *password, size_t password_size,
|
const char *password, size_t password_size,
|
||||||
const char *salt, size_t salt_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,
|
uint32_t *iterations_out, uint32_t *memory_out,
|
||||||
int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr)
|
int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr)
|
||||||
{
|
{
|
||||||
|
struct crypt_pbkdf_limits pbkdf_limits;
|
||||||
int r = -EINVAL;
|
int r = -EINVAL;
|
||||||
|
|
||||||
if (!kdf || !iterations_out || !memory_out)
|
if (!kdf || !iterations_out || !memory_out)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
r = crypt_pbkdf_get_limits(kdf, &pbkdf_limits);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
*memory_out = 0;
|
*memory_out = 0;
|
||||||
*iterations_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))
|
else if (!strncmp(kdf, "argon2", 6))
|
||||||
r = crypt_argon2_check(kdf, password, password_size,
|
r = crypt_argon2_check(kdf, password, password_size,
|
||||||
salt, salt_size, volume_key_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,
|
parallel_threads, time_ms, iterations_out,
|
||||||
memory_out, progress, usrptr);
|
memory_out, progress, usrptr);
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@@ -51,10 +51,6 @@
|
|||||||
#define DEFAULT_MEM_ALIGNMENT 4096
|
#define DEFAULT_MEM_ALIGNMENT 4096
|
||||||
#define MAX_ERROR_LENGTH 512
|
#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); })
|
#define at_least(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); })
|
||||||
|
|
||||||
struct crypt_device;
|
struct crypt_device;
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ static int PBKDF2_digest_store(struct crypt_device *cd,
|
|||||||
int r;
|
int r;
|
||||||
char *base64_str;
|
char *base64_str;
|
||||||
struct luks2_hdr *hdr;
|
struct luks2_hdr *hdr;
|
||||||
|
struct crypt_pbkdf_limits pbkdf_limits;
|
||||||
struct crypt_pbkdf_type pbkdf = {
|
struct crypt_pbkdf_type pbkdf = {
|
||||||
.type = CRYPT_KDF_PBKDF2,
|
.type = CRYPT_KDF_PBKDF2,
|
||||||
.hash = "sha256",
|
.hash = "sha256",
|
||||||
@@ -110,8 +111,12 @@ static int PBKDF2_digest_store(struct crypt_device *cd,
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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)
|
if (crypt_get_pbkdf(cd)->flags & CRYPT_PBKDF_NO_BENCHMARK)
|
||||||
pbkdf.iterations = MIN_PBKDF2_ITERATIONS;
|
pbkdf.iterations = pbkdf_limits.min_iterations;
|
||||||
else {
|
else {
|
||||||
r = crypt_benchmark_pbkdf_internal(cd, &pbkdf, volume_key_len);
|
r = crypt_benchmark_pbkdf_internal(cd, &pbkdf, volume_key_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|||||||
@@ -289,6 +289,7 @@ int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
|
|||||||
struct crypt_pbkdf_type *pbkdf,
|
struct crypt_pbkdf_type *pbkdf,
|
||||||
size_t volume_key_size)
|
size_t volume_key_size)
|
||||||
{
|
{
|
||||||
|
struct crypt_pbkdf_limits pbkdf_limits;
|
||||||
double PBKDF2_tmp;
|
double PBKDF2_tmp;
|
||||||
uint32_t ms_tmp;
|
uint32_t ms_tmp;
|
||||||
int r = -EINVAL;
|
int r = -EINVAL;
|
||||||
@@ -304,6 +305,10 @@ int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) {
|
if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) {
|
||||||
/*
|
/*
|
||||||
* For PBKDF2 it is enough to run benchmark for only 1 second
|
* 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.);
|
PBKDF2_tmp = ((double)pbkdf->iterations * pbkdf->time_ms / 1000.);
|
||||||
if (PBKDF2_tmp > (double)UINT32_MAX)
|
if (PBKDF2_tmp > (double)UINT32_MAX)
|
||||||
return -EINVAL;
|
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 {
|
} else {
|
||||||
r = crypt_benchmark_pbkdf(cd, pbkdf, "foo", 3,
|
r = crypt_benchmark_pbkdf(cd, pbkdf, "foo", 3,
|
||||||
"0123456789abcdef0123456789abcdef", 32,
|
"0123456789abcdef0123456789abcdef", 32,
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ static uint32_t adjusted_phys_memory(void)
|
|||||||
int verify_pbkdf_params(struct crypt_device *cd,
|
int verify_pbkdf_params(struct crypt_device *cd,
|
||||||
const struct crypt_pbkdf_type *pbkdf)
|
const struct crypt_pbkdf_type *pbkdf)
|
||||||
{
|
{
|
||||||
|
struct crypt_pbkdf_limits pbkdf_limits;
|
||||||
const char *pbkdf_type;
|
const char *pbkdf_type;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
@@ -74,6 +75,10 @@ int verify_pbkdf_params(struct crypt_device *cd,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (crypt_get_type(cd) &&
|
if (crypt_get_type(cd) &&
|
||||||
!strcmp(crypt_get_type(cd), CRYPT_LUKS1) &&
|
!strcmp(crypt_get_type(cd), CRYPT_LUKS1) &&
|
||||||
strcmp(pbkdf_type, CRYPT_KDF_PBKDF2)) {
|
strcmp(pbkdf_type, CRYPT_KDF_PBKDF2)) {
|
||||||
@@ -87,9 +92,9 @@ int verify_pbkdf_params(struct crypt_device *cd,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK &&
|
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"),
|
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 -EINVAL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -97,21 +102,21 @@ int verify_pbkdf_params(struct crypt_device *cd,
|
|||||||
|
|
||||||
/* TODO: properly define minimal iterations and also minimal memory values */
|
/* TODO: properly define minimal iterations and also minimal memory values */
|
||||||
if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK) {
|
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"),
|
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;
|
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"),
|
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;
|
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"),
|
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;
|
r = -EINVAL;
|
||||||
}
|
}
|
||||||
if (!pbkdf->max_memory_kb) {
|
if (!pbkdf->max_memory_kb) {
|
||||||
@@ -135,6 +140,7 @@ int init_pbkdf_type(struct crypt_device *cd,
|
|||||||
const char *dev_type)
|
const char *dev_type)
|
||||||
{
|
{
|
||||||
struct crypt_pbkdf_type *cd_pbkdf = crypt_get_pbkdf(cd);
|
struct crypt_pbkdf_type *cd_pbkdf = crypt_get_pbkdf(cd);
|
||||||
|
struct crypt_pbkdf_limits pbkdf_limits;
|
||||||
const char *hash, *type;
|
const char *hash, *type;
|
||||||
unsigned cpus;
|
unsigned cpus;
|
||||||
uint32_t old_flags, memory_kb;
|
uint32_t old_flags, memory_kb;
|
||||||
@@ -149,6 +155,10 @@ int init_pbkdf_type(struct crypt_device *cd,
|
|||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Crypto backend may be not initialized here,
|
* Crypto backend may be not initialized here,
|
||||||
* cannot check if algorithms are really available.
|
* 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->max_memory_kb = pbkdf->max_memory_kb;
|
||||||
cd_pbkdf->parallel_threads = pbkdf->parallel_threads;
|
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).",
|
log_dbg("Maximum PBKDF threads is %d (requested %d).",
|
||||||
MAX_PBKDF_THREADS, cd_pbkdf->parallel_threads);
|
pbkdf_limits.max_parallel, cd_pbkdf->parallel_threads);
|
||||||
cd_pbkdf->parallel_threads = MAX_PBKDF_THREADS;
|
cd_pbkdf->parallel_threads = pbkdf_limits.max_parallel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cd_pbkdf->parallel_threads) {
|
if (cd_pbkdf->parallel_threads) {
|
||||||
|
|||||||
Reference in New Issue
Block a user