summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/USER_RECORD.md7
-rw-r--r--man/homectl.xml1
-rw-r--r--shell-completion/bash/homectl1
-rw-r--r--src/home/homectl.c4
-rw-r--r--src/home/homework-luks.c6
-rw-r--r--src/shared/user-record-show.c2
-rw-r--r--src/shared/user-record.c14
-rw-r--r--src/shared/user-record.h2
8 files changed, 34 insertions, 3 deletions
diff --git a/docs/USER_RECORD.md b/docs/USER_RECORD.md
index f330e8b13a..a00bec2353 100644
--- a/docs/USER_RECORD.md
+++ b/docs/USER_RECORD.md
@@ -490,9 +490,12 @@ the PBKDF operation for the LUKS storage mechanism.
`luksPbkdfType` → A string, indicating the PBKDF type to use for the LUKS storage mechanism.
+`luksPbkdfForceIterations` → An unsigned 64bit integer, indicating the intended
+number of iterations for the PBKDF operation, when LUKS storage is used.
+
`luksPbkdfTimeCostUSec` → An unsigned 64bit integer, indicating the intended
time cost for the PBKDF operation, when the LUKS storage mechanism is used, in
-µs.
+µs. Ignored when `luksPbkdfForceIterations` is set.
`luksPbkdfMemoryCost` → An unsigned 64bit integer, indicating the intended
memory cost for the PBKDF operation, when LUKS storage is used, in bytes.
@@ -737,7 +740,7 @@ that may be used in this section are identical to the equally named ones in the
`gid`, `memberOf`, `fileSystemType`, `partitionUuid`, `luksUuid`,
`fileSystemUuid`, `luksDiscard`, `luksOfflineDiscard`, `luksCipher`,
`luksCipherMode`, `luksVolumeKeySize`, `luksPbkdfHashAlgorithm`,
-`luksPbkdfType`, `luksPbkdfTimeCostUSec`, `luksPbkdfMemoryCost`,
+`luksPbkdfType`, `luksPbkdfForceIterations`, `luksPbkdfTimeCostUSec`, `luksPbkdfMemoryCost`,
`luksPbkdfParallelThreads`, `luksSectorSize`, `autoResizeMode`, `rebalanceWeight`,
`rateLimitIntervalUSec`, `rateLimitBurst`, `enforcePasswordPolicy`,
`autoLogin`, `stopDelayUSec`, `killProcesses`, `passwordChangeMinUSec`,
diff --git a/man/homectl.xml b/man/homectl.xml
index 1064f05650..634b95a081 100644
--- a/man/homectl.xml
+++ b/man/homectl.xml
@@ -689,6 +689,7 @@
<term><option>--luks-volume-key-size=</option><replaceable>BYTES</replaceable></term>
<term><option>--luks-pbkdf-type=</option><replaceable>TYPE</replaceable></term>
<term><option>--luks-pbkdf-hash-algorithm=</option><replaceable>ALGORITHM</replaceable></term>
+ <term><option>--luks-pbkdf-force-iterations=</option><replaceable>ITERATIONS</replaceable></term>
<term><option>--luks-pbkdf-time-cost=</option><replaceable>SECONDS</replaceable></term>
<term><option>--luks-pbkdf-memory-cost=</option><replaceable>BYTES</replaceable></term>
<term><option>--luks-pbkdf-parallel-threads=</option><replaceable>THREADS</replaceable></term>
diff --git a/shell-completion/bash/homectl b/shell-completion/bash/homectl
index 166a50828e..0a7bd0d13c 100644
--- a/shell-completion/bash/homectl
+++ b/shell-completion/bash/homectl
@@ -93,6 +93,7 @@ _homectl() {
--luks-volume-key-size
--luks-pbkdf-type
--luks-pbkdf-hash-algorithm
+ --luks-pbkdf-force-iterations
--luks-pbkdf-time-cost
--luks-pbkdf-memory-cost
--luks-pbkdf-parallel-threads
diff --git a/src/home/homectl.c b/src/home/homectl.c
index 3e846e370a..a6d25c84fc 100644
--- a/src/home/homectl.c
+++ b/src/home/homectl.c
@@ -2392,6 +2392,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_IO_WEIGHT,
ARG_LUKS_PBKDF_TYPE,
ARG_LUKS_PBKDF_HASH_ALGORITHM,
+ ARG_LUKS_PBKDF_FORCE_ITERATIONS,
ARG_LUKS_PBKDF_TIME_COST,
ARG_LUKS_PBKDF_MEMORY_COST,
ARG_LUKS_PBKDF_PARALLEL_THREADS,
@@ -2473,6 +2474,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "luks-volume-key-size", required_argument, NULL, ARG_LUKS_VOLUME_KEY_SIZE },
{ "luks-pbkdf-type", required_argument, NULL, ARG_LUKS_PBKDF_TYPE },
{ "luks-pbkdf-hash-algorithm", required_argument, NULL, ARG_LUKS_PBKDF_HASH_ALGORITHM },
+ { "luks-pbkdf-force-iterations", required_argument, NULL, ARG_LUKS_PBKDF_FORCE_ITERATIONS },
{ "luks-pbkdf-time-cost", required_argument, NULL, ARG_LUKS_PBKDF_TIME_COST },
{ "luks-pbkdf-memory-cost", required_argument, NULL, ARG_LUKS_PBKDF_MEMORY_COST },
{ "luks-pbkdf-parallel-threads", required_argument, NULL, ARG_LUKS_PBKDF_PARALLEL_THREADS },
@@ -3093,10 +3095,12 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_LUKS_VOLUME_KEY_SIZE:
+ case ARG_LUKS_PBKDF_FORCE_ITERATIONS:
case ARG_LUKS_PBKDF_PARALLEL_THREADS:
case ARG_RATE_LIMIT_BURST: {
const char *field =
c == ARG_LUKS_VOLUME_KEY_SIZE ? "luksVolumeKeySize" :
+ c == ARG_LUKS_PBKDF_FORCE_ITERATIONS ? "luksPbkdfForceIterations" :
c == ARG_LUKS_PBKDF_PARALLEL_THREADS ? "luksPbkdfParallelThreads" :
c == ARG_RATE_LIMIT_BURST ? "rateLimitBurst" : NULL;
unsigned n;
diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c
index 39ad56808d..4d04359740 100644
--- a/src/home/homework-luks.c
+++ b/src/home/homework-luks.c
@@ -1670,12 +1670,16 @@ static struct crypt_pbkdf_type* build_good_pbkdf(struct crypt_pbkdf_type *buffer
assert(buffer);
assert(hr);
+ bool benchmark = user_record_luks_pbkdf_force_iterations(hr) == UINT64_MAX;
+
*buffer = (struct crypt_pbkdf_type) {
.hash = user_record_luks_pbkdf_hash_algorithm(hr),
.type = user_record_luks_pbkdf_type(hr),
- .time_ms = user_record_luks_pbkdf_time_cost_usec(hr) / USEC_PER_MSEC,
+ .time_ms = benchmark ? user_record_luks_pbkdf_time_cost_usec(hr) / USEC_PER_MSEC : 0,
+ .iterations = benchmark ? 0 : user_record_luks_pbkdf_force_iterations(hr),
.max_memory_kb = user_record_luks_pbkdf_memory_cost(hr) / 1024,
.parallel_threads = user_record_luks_pbkdf_parallel_threads(hr),
+ .flags = benchmark ? 0 : CRYPT_PBKDF_NO_BENCHMARK,
};
return buffer;
diff --git a/src/shared/user-record-show.c b/src/shared/user-record-show.c
index e89c0de120..da181c6078 100644
--- a/src/shared/user-record-show.c
+++ b/src/shared/user-record-show.c
@@ -314,6 +314,8 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
printf(" PBKDF Type: %s\n", hr->luks_pbkdf_type);
if (hr->luks_pbkdf_hash_algorithm)
printf(" PBKDF Hash: %s\n", hr->luks_pbkdf_hash_algorithm);
+ if (hr->luks_pbkdf_force_iterations != UINT64_MAX)
+ printf(" PBKDF Iters: %" PRIu64 "\n", hr->luks_pbkdf_force_iterations);
if (hr->luks_pbkdf_time_cost_usec != UINT64_MAX)
printf(" PBKDF Time: %s\n", FORMAT_TIMESPAN(hr->luks_pbkdf_time_cost_usec, 0));
if (hr->luks_pbkdf_memory_cost != UINT64_MAX)
diff --git a/src/shared/user-record.c b/src/shared/user-record.c
index 84cbdb1d30..06bc699572 100644
--- a/src/shared/user-record.c
+++ b/src/shared/user-record.c
@@ -55,6 +55,7 @@ UserRecord* user_record_new(void) {
.luks_discard = -1,
.luks_offline_discard = -1,
.luks_volume_key_size = UINT64_MAX,
+ .luks_pbkdf_force_iterations = UINT64_MAX,
.luks_pbkdf_time_cost_usec = UINT64_MAX,
.luks_pbkdf_memory_cost = UINT64_MAX,
.luks_pbkdf_parallel_threads = UINT64_MAX,
@@ -1213,6 +1214,7 @@ static int dispatch_per_machine(const char *name, JsonVariant *variant, JsonDisp
{ "luksVolumeKeySize", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_volume_key_size), 0 },
{ "luksPbkdfHashAlgorithm", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, luks_pbkdf_hash_algorithm), JSON_SAFE },
{ "luksPbkdfType", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, luks_pbkdf_type), JSON_SAFE },
+ { "luksPbkdfForceIterations", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_force_iterations), 0 },
{ "luksPbkdfTimeCostUSec", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_time_cost_usec), 0 },
{ "luksPbkdfMemoryCost", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_memory_cost), 0 },
{ "luksPbkdfParallelThreads", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_parallel_threads), 0 },
@@ -1566,6 +1568,7 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla
{ "luksVolumeKeySize", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_volume_key_size), 0 },
{ "luksPbkdfHashAlgorithm", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, luks_pbkdf_hash_algorithm), JSON_SAFE },
{ "luksPbkdfType", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, luks_pbkdf_type), JSON_SAFE },
+ { "luksPbkdfForceIterations", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_force_iterations), 0 },
{ "luksPbkdfTimeCostUSec", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_time_cost_usec), 0 },
{ "luksPbkdfMemoryCost", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_memory_cost), 0 },
{ "luksPbkdfParallelThreads", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_parallel_threads), 0 },
@@ -1842,6 +1845,17 @@ const char* user_record_luks_pbkdf_type(UserRecord *h) {
return h->luks_pbkdf_type ?: "argon2id";
}
+uint64_t user_record_luks_pbkdf_force_iterations(UserRecord *h) {
+ assert(h);
+
+ /* propagate default "benchmark" mode as itself */
+ if (h->luks_pbkdf_force_iterations == UINT64_MAX)
+ return UINT64_MAX;
+
+ /* clamp everything else to actually accepted number of iterations of libcryptsetup */
+ return CLAMP(h->luks_pbkdf_force_iterations, 1U, UINT32_MAX);
+}
+
uint64_t user_record_luks_pbkdf_time_cost_usec(UserRecord *h) {
assert(h);
diff --git a/src/shared/user-record.h b/src/shared/user-record.h
index 47f4035d45..73fb86cc94 100644
--- a/src/shared/user-record.h
+++ b/src/shared/user-record.h
@@ -309,6 +309,7 @@ typedef struct UserRecord {
uint64_t luks_volume_key_size;
char *luks_pbkdf_hash_algorithm;
char *luks_pbkdf_type;
+ uint64_t luks_pbkdf_force_iterations;
uint64_t luks_pbkdf_time_cost_usec;
uint64_t luks_pbkdf_memory_cost;
uint64_t luks_pbkdf_parallel_threads;
@@ -394,6 +395,7 @@ const char *user_record_luks_cipher(UserRecord *h);
const char *user_record_luks_cipher_mode(UserRecord *h);
uint64_t user_record_luks_volume_key_size(UserRecord *h);
const char* user_record_luks_pbkdf_type(UserRecord *h);
+uint64_t user_record_luks_pbkdf_force_iterations(UserRecord *h);
usec_t user_record_luks_pbkdf_time_cost_usec(UserRecord *h);
uint64_t user_record_luks_pbkdf_memory_cost(UserRecord *h);
uint64_t user_record_luks_pbkdf_parallel_threads(UserRecord *h);