Commit 16dc5831 authored by Milan Broz's avatar Milan Broz

Move PBKDF limits to crypto backend (to one place).

parent 169bd9db
......@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment