]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Implement --luks-pbkdf-force-iterations for homed
authorAidan Dang <dang@aidan.gg>
Sat, 3 Dec 2022 15:26:13 +0000 (02:26 +1100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 6 Dec 2022 14:56:11 +0000 (15:56 +0100)
docs/USER_RECORD.md
man/homectl.xml
shell-completion/bash/homectl
src/home/homectl.c
src/home/homework-luks.c
src/shared/user-record-show.c
src/shared/user-record.c
src/shared/user-record.h

index f330e8b13a77d88ec1d7664823b0b9e4a762e4c8..a00bec2353e9ac4e974489cd96fa53744989662b 100644 (file)
@@ -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`,
index 1064f056504c5153764000c34bd3e32c9e437847..634b95a081c95e529d189a2419de71e3a923b182 100644 (file)
         <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>
index 166a50828efc1f93fadc547e1f2afcdd16103b90..0a7bd0d13c88685de0c886de7fad7dbca54eab8f 100644 (file)
@@ -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
index 3e846e370ab588b1c6d94855ae6a748bb3665a83..a6d25c84fc1b5aa53d73e06bdbb57c75c8d0e805 100644 (file)
@@ -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;
index 39ad56808d12217d6a950a14dbafe2b4d398420b..4d043597400d1d2290716ea3ef3f53221234c273 100644 (file)
@@ -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;
index e89c0de1207968b7b24a5d1a94dfde26b6a219de..da181c6078af14559d2436f9ab92c5cb4aaa7834 100644 (file)
@@ -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)
index 84cbdb1d30a998c8de6292db4f5bc4d8194c34c8..06bc699572f28e7ff2dc11a60a6d5476b0939ff8 100644 (file)
@@ -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);
 
index 47f4035d4531e512e5cf587d6e236226cfb6a271..73fb86cc94520e6a8976a49ec743b43d85befbdf 100644 (file)
@@ -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);