From b04ff66b426c6cffa3b27d0448e633ebf6aba147 Mon Sep 17 00:00:00 2001 From: Aidan Dang Date: Sun, 4 Dec 2022 02:26:13 +1100 Subject: [PATCH] Implement --luks-pbkdf-force-iterations for homed --- docs/USER_RECORD.md | 7 +++++-- man/homectl.xml | 1 + shell-completion/bash/homectl | 1 + src/home/homectl.c | 4 ++++ src/home/homework-luks.c | 6 +++++- src/shared/user-record-show.c | 2 ++ src/shared/user-record.c | 14 ++++++++++++++ src/shared/user-record.h | 2 ++ 8 files changed, 34 insertions(+), 3 deletions(-) diff --git a/docs/USER_RECORD.md b/docs/USER_RECORD.md index f330e8b13a7..a00bec2353e 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 1064f056504..634b95a081c 100644 --- a/man/homectl.xml +++ b/man/homectl.xml @@ -689,6 +689,7 @@ BYTES TYPE ALGORITHM + ITERATIONS SECONDS BYTES THREADS diff --git a/shell-completion/bash/homectl b/shell-completion/bash/homectl index 166a50828ef..0a7bd0d13c8 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 3e846e370ab..a6d25c84fc1 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 39ad56808d1..4d043597400 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 e89c0de1207..da181c6078a 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 84cbdb1d30a..06bc699572f 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 47f4035d453..73fb86cc945 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); -- 2.39.5