]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/cryptenroll/cryptenroll.c
Merge pull request #29921 from yuwata/sd-dhcp-client-timestamp
[thirdparty/systemd.git] / src / cryptenroll / cryptenroll.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <getopt.h>
4
5 #include "ask-password-api.h"
6 #include "build.h"
7 #include "cryptenroll-fido2.h"
8 #include "cryptenroll-list.h"
9 #include "cryptenroll-password.h"
10 #include "cryptenroll-pkcs11.h"
11 #include "cryptenroll-recovery.h"
12 #include "cryptenroll-tpm2.h"
13 #include "cryptenroll-wipe.h"
14 #include "cryptenroll.h"
15 #include "cryptsetup-util.h"
16 #include "env-util.h"
17 #include "escape.h"
18 #include "fileio.h"
19 #include "libfido2-util.h"
20 #include "main-func.h"
21 #include "memory-util.h"
22 #include "parse-argument.h"
23 #include "parse-util.h"
24 #include "path-util.h"
25 #include "pkcs11-util.h"
26 #include "pretty-print.h"
27 #include "string-table.h"
28 #include "strv.h"
29 #include "terminal-util.h"
30 #include "tpm2-pcr.h"
31
32 static EnrollType arg_enroll_type = _ENROLL_TYPE_INVALID;
33 static char *arg_unlock_keyfile = NULL;
34 static UnlockType arg_unlock_type = UNLOCK_PASSWORD;
35 static char *arg_unlock_fido2_device = NULL;
36 static char *arg_pkcs11_token_uri = NULL;
37 static char *arg_fido2_device = NULL;
38 static char *arg_tpm2_device = NULL;
39 static uint32_t arg_tpm2_seal_key_handle = 0;
40 static char *arg_tpm2_device_key = NULL;
41 static Tpm2PCRValue *arg_tpm2_hash_pcr_values = NULL;
42 static size_t arg_tpm2_n_hash_pcr_values = 0;
43 static bool arg_tpm2_pin = false;
44 static char *arg_tpm2_public_key = NULL;
45 static uint32_t arg_tpm2_public_key_pcr_mask = 0;
46 static char *arg_tpm2_signature = NULL;
47 static char *arg_tpm2_pcrlock = NULL;
48 static char *arg_node = NULL;
49 static int *arg_wipe_slots = NULL;
50 static size_t arg_n_wipe_slots = 0;
51 static WipeScope arg_wipe_slots_scope = WIPE_EXPLICIT;
52 static unsigned arg_wipe_slots_mask = 0; /* Bitmask of (1U << EnrollType), for wiping all slots of specific types */
53 static Fido2EnrollFlags arg_fido2_lock_with = FIDO2ENROLL_PIN | FIDO2ENROLL_UP;
54 #if HAVE_LIBFIDO2
55 static int arg_fido2_cred_alg = COSE_ES256;
56 #else
57 static int arg_fido2_cred_alg = 0;
58 #endif
59
60 assert_cc(sizeof(arg_wipe_slots_mask) * 8 >= _ENROLL_TYPE_MAX);
61
62 STATIC_DESTRUCTOR_REGISTER(arg_unlock_keyfile, freep);
63 STATIC_DESTRUCTOR_REGISTER(arg_unlock_fido2_device, freep);
64 STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_token_uri, freep);
65 STATIC_DESTRUCTOR_REGISTER(arg_fido2_device, freep);
66 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
67 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device_key, freep);
68 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_hash_pcr_values, freep);
69 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
70 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep);
71 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_pcrlock, freep);
72 STATIC_DESTRUCTOR_REGISTER(arg_node, freep);
73 STATIC_DESTRUCTOR_REGISTER(arg_wipe_slots, freep);
74
75 static bool wipe_requested(void) {
76 return arg_n_wipe_slots > 0 ||
77 arg_wipe_slots_scope != WIPE_EXPLICIT ||
78 arg_wipe_slots_mask != 0;
79 }
80
81 static const char* const enroll_type_table[_ENROLL_TYPE_MAX] = {
82 [ENROLL_PASSWORD] = "password",
83 [ENROLL_RECOVERY] = "recovery",
84 [ENROLL_PKCS11] = "pkcs11",
85 [ENROLL_FIDO2] = "fido2",
86 [ENROLL_TPM2] = "tpm2",
87 };
88
89 DEFINE_STRING_TABLE_LOOKUP(enroll_type, EnrollType);
90
91 static const char *const luks2_token_type_table[_ENROLL_TYPE_MAX] = {
92 /* ENROLL_PASSWORD has no entry here, as slots of this type do not have a token in the LUKS2 header */
93 [ENROLL_RECOVERY] = "systemd-recovery",
94 [ENROLL_PKCS11] = "systemd-pkcs11",
95 [ENROLL_FIDO2] = "systemd-fido2",
96 [ENROLL_TPM2] = "systemd-tpm2",
97 };
98
99 DEFINE_STRING_TABLE_LOOKUP(luks2_token_type, EnrollType);
100
101 static int help(void) {
102 _cleanup_free_ char *link = NULL;
103 int r;
104
105 r = terminal_urlify_man("systemd-cryptenroll", "1", &link);
106 if (r < 0)
107 return log_oom();
108
109 printf("%1$s [OPTIONS...] BLOCK-DEVICE\n\n"
110 "%5$sEnroll a security token or authentication credential to a LUKS volume.%6$s\n\n"
111 " -h --help Show this help\n"
112 " --version Show package version\n"
113 " --wipe-slot=SLOT1,SLOT2,…\n"
114 " Wipe specified slots\n"
115 "\n%3$sUnlocking:%4$s\n"
116 " --unlock-key-file=PATH\n"
117 " Use a file to unlock the volume\n"
118 " --unlock-fido2-device=PATH\n"
119 " Use a FIDO2 device to unlock the volume\n"
120 "\n%3$sSimple Enrollment:%4$s\n"
121 " --password Enroll a user-supplied password\n"
122 " --recovery-key Enroll a recovery key\n"
123 "\n%3$sPKCS11 Enrollment:%4$s\n"
124 " --pkcs11-token-uri=URI\n"
125 " Specify PKCS#11 security token URI\n"
126 "\n%3$sFIDO2 Enrollment:%4$s\n"
127 " --fido2-device=PATH\n"
128 " Enroll a FIDO2-HMAC security token\n"
129 " --fido2-credential-algorithm=STRING\n"
130 " Specify COSE algorithm for FIDO2 credential\n"
131 " --fido2-with-client-pin=BOOL\n"
132 " Whether to require entering a PIN to unlock the volume\n"
133 " --fido2-with-user-presence=BOOL\n"
134 " Whether to require user presence to unlock the volume\n"
135 " --fido2-with-user-verification=BOOL\n"
136 " Whether to require user verification to unlock the volume\n"
137 "\n%3$sTPM2 Enrollment:%4$s\n"
138 " --tpm2-device=PATH\n"
139 " Enroll a TPM2 device\n"
140 " --tpm2-seal-key-handle=HANDLE\n"
141 " Specify handle of key to use for sealing\n"
142 " --tpm2-device-key=PATH\n"
143 " Enroll a TPM2 device using its public key\n"
144 " --tpm2-pcrs=PCR1+PCR2+PCR3+…\n"
145 " Specify TPM2 PCRs to seal against\n"
146 " --tpm2-public-key=PATH\n"
147 " Enroll signed TPM2 PCR policy against PEM public key\n"
148 " --tpm2-public-key-pcrs=PCR1+PCR2+PCR3+…\n"
149 " Enroll signed TPM2 PCR policy for specified TPM2 PCRs\n"
150 " --tpm2-signature=PATH\n"
151 " Validate public key enrollment works with JSON signature\n"
152 " file\n"
153 " --tpm2-pcrlock=PATH\n"
154 " Specify pcrlock policy to lock against\n"
155 " --tpm2-with-pin=BOOL\n"
156 " Whether to require entering a PIN to unlock the volume\n"
157 "\nSee the %2$s for details.\n",
158 program_invocation_short_name,
159 link,
160 ansi_underline(),
161 ansi_normal(),
162 ansi_highlight(),
163 ansi_normal());
164
165 return 0;
166 }
167
168 static int parse_argv(int argc, char *argv[]) {
169 enum {
170 ARG_VERSION = 0x100,
171 ARG_PASSWORD,
172 ARG_RECOVERY_KEY,
173 ARG_UNLOCK_KEYFILE,
174 ARG_UNLOCK_FIDO2_DEVICE,
175 ARG_PKCS11_TOKEN_URI,
176 ARG_FIDO2_DEVICE,
177 ARG_TPM2_DEVICE,
178 ARG_TPM2_SEAL_KEY_HANDLE,
179 ARG_TPM2_DEVICE_KEY,
180 ARG_TPM2_PCRS,
181 ARG_TPM2_PUBLIC_KEY,
182 ARG_TPM2_PUBLIC_KEY_PCRS,
183 ARG_TPM2_SIGNATURE,
184 ARG_TPM2_PIN,
185 ARG_TPM2_PCRLOCK,
186 ARG_WIPE_SLOT,
187 ARG_FIDO2_WITH_PIN,
188 ARG_FIDO2_WITH_UP,
189 ARG_FIDO2_WITH_UV,
190 ARG_FIDO2_CRED_ALG,
191 };
192
193 static const struct option options[] = {
194 { "help", no_argument, NULL, 'h' },
195 { "version", no_argument, NULL, ARG_VERSION },
196 { "password", no_argument, NULL, ARG_PASSWORD },
197 { "recovery-key", no_argument, NULL, ARG_RECOVERY_KEY },
198 { "unlock-key-file", required_argument, NULL, ARG_UNLOCK_KEYFILE },
199 { "unlock-fido2-device", required_argument, NULL, ARG_UNLOCK_FIDO2_DEVICE },
200 { "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI },
201 { "fido2-credential-algorithm", required_argument, NULL, ARG_FIDO2_CRED_ALG },
202 { "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE },
203 { "fido2-with-client-pin", required_argument, NULL, ARG_FIDO2_WITH_PIN },
204 { "fido2-with-user-presence", required_argument, NULL, ARG_FIDO2_WITH_UP },
205 { "fido2-with-user-verification", required_argument, NULL, ARG_FIDO2_WITH_UV },
206 { "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
207 { "tpm2-seal-key-handle", required_argument, NULL, ARG_TPM2_SEAL_KEY_HANDLE },
208 { "tpm2-device-key", required_argument, NULL, ARG_TPM2_DEVICE_KEY },
209 { "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
210 { "tpm2-public-key", required_argument, NULL, ARG_TPM2_PUBLIC_KEY },
211 { "tpm2-public-key-pcrs", required_argument, NULL, ARG_TPM2_PUBLIC_KEY_PCRS },
212 { "tpm2-signature", required_argument, NULL, ARG_TPM2_SIGNATURE },
213 { "tpm2-with-pin", required_argument, NULL, ARG_TPM2_PIN },
214 { "tpm2-pcrlock", required_argument, NULL, ARG_TPM2_PCRLOCK },
215 { "wipe-slot", required_argument, NULL, ARG_WIPE_SLOT },
216 {}
217 };
218
219 bool auto_hash_pcr_values = true, auto_public_key_pcr_mask = true, auto_pcrlock = true;
220 int c, r;
221
222 assert(argc >= 0);
223 assert(argv);
224
225 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
226
227 switch (c) {
228
229 case 'h':
230 return help();
231
232 case ARG_VERSION:
233 return version();
234
235 case ARG_FIDO2_WITH_PIN:
236 r = parse_boolean_argument("--fido2-with-client-pin=", optarg, NULL);
237 if (r < 0)
238 return r;
239
240 SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_PIN, r);
241 break;
242
243 case ARG_FIDO2_WITH_UP:
244 r = parse_boolean_argument("--fido2-with-user-presence=", optarg, NULL);
245 if (r < 0)
246 return r;
247
248 SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_UP, r);
249 break;
250
251 case ARG_FIDO2_WITH_UV:
252 r = parse_boolean_argument("--fido2-with-user-verification=", optarg, NULL);
253 if (r < 0)
254 return r;
255
256 SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_UV, r);
257 break;
258
259 case ARG_PASSWORD:
260 if (arg_enroll_type >= 0)
261 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
262 "Multiple operations specified at once, refusing.");
263
264 arg_enroll_type = ENROLL_PASSWORD;
265 break;
266
267 case ARG_RECOVERY_KEY:
268 if (arg_enroll_type >= 0)
269 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
270 "Multiple operations specified at once, refusing.");
271
272 arg_enroll_type = ENROLL_RECOVERY;
273 break;
274
275 case ARG_UNLOCK_KEYFILE:
276 if (arg_unlock_type != UNLOCK_PASSWORD)
277 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
278 "Multiple unlock methods specified at once, refusing.");
279
280 r = parse_path_argument(optarg, /* suppress_root= */ true, &arg_unlock_keyfile);
281 if (r < 0)
282 return r;
283
284 arg_unlock_type = UNLOCK_KEYFILE;
285 break;
286
287 case ARG_UNLOCK_FIDO2_DEVICE: {
288 _cleanup_free_ char *device = NULL;
289
290 if (arg_unlock_type != UNLOCK_PASSWORD)
291 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
292 "Multiple unlock methods specified at once, refusing.");
293
294 assert(!arg_unlock_fido2_device);
295
296 if (!streq(optarg, "auto")) {
297 device = strdup(optarg);
298 if (!device)
299 return log_oom();
300 }
301
302 arg_unlock_type = UNLOCK_FIDO2;
303 arg_unlock_fido2_device = TAKE_PTR(device);
304 break;
305 }
306
307 case ARG_PKCS11_TOKEN_URI: {
308 _cleanup_free_ char *uri = NULL;
309
310 if (streq(optarg, "list"))
311 return pkcs11_list_tokens();
312
313 if (arg_enroll_type >= 0 || arg_pkcs11_token_uri)
314 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
315 "Multiple operations specified at once, refusing.");
316
317 if (streq(optarg, "auto")) {
318 r = pkcs11_find_token_auto(&uri);
319 if (r < 0)
320 return r;
321 } else {
322 if (!pkcs11_uri_valid(optarg))
323 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid PKCS#11 URI: %s", optarg);
324
325 uri = strdup(optarg);
326 if (!uri)
327 return log_oom();
328 }
329
330 arg_enroll_type = ENROLL_PKCS11;
331 arg_pkcs11_token_uri = TAKE_PTR(uri);
332 break;
333 }
334
335 case ARG_FIDO2_CRED_ALG:
336 r = parse_fido2_algorithm(optarg, &arg_fido2_cred_alg);
337 if (r < 0)
338 return log_error_errno(r, "Failed to parse COSE algorithm: %s", optarg);
339 break;
340
341 case ARG_FIDO2_DEVICE: {
342 _cleanup_free_ char *device = NULL;
343
344 if (streq(optarg, "list"))
345 return fido2_list_devices();
346
347 if (arg_enroll_type >= 0 || arg_fido2_device)
348 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
349 "Multiple operations specified at once, refusing.");
350
351 if (!streq(optarg, "auto")) {
352 device = strdup(optarg);
353 if (!device)
354 return log_oom();
355 }
356
357 arg_enroll_type = ENROLL_FIDO2;
358 arg_fido2_device = TAKE_PTR(device);
359 break;
360 }
361
362 case ARG_TPM2_DEVICE: {
363 _cleanup_free_ char *device = NULL;
364
365 if (streq(optarg, "list"))
366 return tpm2_list_devices();
367
368 if (arg_enroll_type >= 0 || arg_tpm2_device)
369 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
370 "Multiple operations specified at once, refusing.");
371
372 if (!streq(optarg, "auto")) {
373 device = strdup(optarg);
374 if (!device)
375 return log_oom();
376 }
377
378 arg_enroll_type = ENROLL_TPM2;
379 arg_tpm2_device = TAKE_PTR(device);
380 break;
381 }
382
383 case ARG_TPM2_SEAL_KEY_HANDLE:
384 r = safe_atou32_full(optarg, 16, &arg_tpm2_seal_key_handle);
385 if (r < 0)
386 return log_error_errno(r, "Could not parse TPM2 seal key handle index '%s': %m", optarg);
387
388 break;
389
390 case ARG_TPM2_DEVICE_KEY:
391 if (arg_enroll_type >= 0 || arg_tpm2_device_key)
392 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
393 "Multiple operations specified at once, refusing.");
394
395
396 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_device_key);
397 if (r < 0)
398 return r;
399
400 arg_enroll_type = ENROLL_TPM2;
401 break;
402
403 case ARG_TPM2_PCRS:
404 auto_hash_pcr_values = false;
405 r = tpm2_parse_pcr_argument_append(optarg, &arg_tpm2_hash_pcr_values, &arg_tpm2_n_hash_pcr_values);
406 if (r < 0)
407 return r;
408
409 break;
410
411 case ARG_TPM2_PIN:
412 r = parse_boolean_argument("--tpm2-with-pin=", optarg, &arg_tpm2_pin);
413 if (r < 0)
414 return r;
415
416 break;
417
418 case ARG_TPM2_PUBLIC_KEY:
419 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_public_key);
420 if (r < 0)
421 return r;
422
423 break;
424
425 case ARG_TPM2_PUBLIC_KEY_PCRS:
426 auto_public_key_pcr_mask = false;
427 r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_public_key_pcr_mask);
428 if (r < 0)
429 return r;
430
431 break;
432
433 case ARG_TPM2_SIGNATURE:
434 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_signature);
435 if (r < 0)
436 return r;
437
438 break;
439
440 case ARG_TPM2_PCRLOCK:
441 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_pcrlock);
442 if (r < 0)
443 return r;
444
445 auto_pcrlock = false;
446 break;
447
448 case ARG_WIPE_SLOT: {
449 const char *p = optarg;
450
451 if (isempty(optarg)) {
452 arg_wipe_slots_mask = 0;
453 arg_wipe_slots_scope = WIPE_EXPLICIT;
454 break;
455 }
456
457 for (;;) {
458 _cleanup_free_ char *slot = NULL;
459 unsigned n;
460
461 r = extract_first_word(&p, &slot, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
462 if (r == 0)
463 break;
464 if (r < 0)
465 return log_error_errno(r, "Failed to parse slot list: %s", optarg);
466
467 if (streq(slot, "all"))
468 arg_wipe_slots_scope = WIPE_ALL;
469 else if (streq(slot, "empty")) {
470 if (arg_wipe_slots_scope != WIPE_ALL) /* if "all" was specified before, that wins */
471 arg_wipe_slots_scope = WIPE_EMPTY_PASSPHRASE;
472 } else if (streq(slot, "password"))
473 arg_wipe_slots_mask |= 1U << ENROLL_PASSWORD;
474 else if (streq(slot, "recovery"))
475 arg_wipe_slots_mask |= 1U << ENROLL_RECOVERY;
476 else if (streq(slot, "pkcs11"))
477 arg_wipe_slots_mask |= 1U << ENROLL_PKCS11;
478 else if (streq(slot, "fido2"))
479 arg_wipe_slots_mask |= 1U << ENROLL_FIDO2;
480 else if (streq(slot, "tpm2"))
481 arg_wipe_slots_mask |= 1U << ENROLL_TPM2;
482 else {
483 int *a;
484
485 r = safe_atou(slot, &n);
486 if (r < 0)
487 return log_error_errno(r, "Failed to parse slot index: %s", slot);
488 if (n > INT_MAX)
489 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Slot index out of range: %u", n);
490
491 a = reallocarray(arg_wipe_slots, sizeof(int), arg_n_wipe_slots + 1);
492 if (!a)
493 return log_oom();
494
495 arg_wipe_slots = a;
496 arg_wipe_slots[arg_n_wipe_slots++] = (int) n;
497 }
498 }
499 break;
500 }
501
502 case '?':
503 return -EINVAL;
504
505 default:
506 assert_not_reached();
507 }
508 }
509
510 if (optind >= argc)
511 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
512 "No block device node specified, refusing.");
513
514 if (argc > optind+1)
515 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
516 "Too many arguments, refusing.");
517
518 r = parse_path_argument(argv[optind], false, &arg_node);
519 if (r < 0)
520 return r;
521
522 if (arg_enroll_type == ENROLL_FIDO2) {
523
524 if (arg_unlock_type == UNLOCK_FIDO2 && !(arg_fido2_device && arg_unlock_fido2_device))
525 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
526 "When both enrolling and unlocking with FIDO2 tokens, automatic discovery is unsupported. "
527 "Please specify device paths for enrolling and unlocking respectively.");
528
529 if (!arg_fido2_device) {
530 r = fido2_find_device_auto(&arg_fido2_device);
531 if (r < 0)
532 return r;
533 }
534 }
535
536 if (auto_pcrlock) {
537 assert(!arg_tpm2_pcrlock);
538
539 r = tpm2_pcrlock_search_file(NULL, NULL, &arg_tpm2_pcrlock);
540 if (r < 0) {
541 if (r != -ENOENT)
542 log_warning_errno(r, "Search for pcrlock.json failed, assuming it does not exist: %m");
543 } else
544 log_info("Automatically using pcrlock policy '%s'.", arg_tpm2_pcrlock);
545 }
546
547 if (auto_public_key_pcr_mask) {
548 assert(arg_tpm2_public_key_pcr_mask == 0);
549 arg_tpm2_public_key_pcr_mask = INDEX_TO_MASK(uint32_t, TPM2_PCR_KERNEL_BOOT);
550 }
551
552 if (auto_hash_pcr_values && !arg_tpm2_pcrlock) { /* Only lock to PCR 7 by default if no pcrlock policy is around (which is a better replacement) */
553 assert(arg_tpm2_n_hash_pcr_values == 0);
554
555 if (!GREEDY_REALLOC_APPEND(
556 arg_tpm2_hash_pcr_values,
557 arg_tpm2_n_hash_pcr_values,
558 &TPM2_PCR_VALUE_MAKE(TPM2_PCR_INDEX_DEFAULT, /* hash= */ 0, /* value= */ {}),
559 1))
560 return log_oom();
561 }
562
563 return 1;
564 }
565
566 static int check_for_homed(struct crypt_device *cd) {
567 int r;
568
569 assert_se(cd);
570
571 /* Politely refuse operating on homed volumes. The enrolled tokens for the user record and the LUKS2
572 * volume should not get out of sync. */
573
574 for (int token = 0; token < crypt_token_max(CRYPT_LUKS2); token ++) {
575 r = cryptsetup_get_token_as_json(cd, token, "systemd-homed", NULL);
576 if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE))
577 continue;
578 if (r < 0)
579 return log_error_errno(r, "Failed to read JSON token data off disk: %m");
580
581 return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN),
582 "LUKS2 volume is managed by systemd-homed, please use homectl to enroll tokens.");
583 }
584
585 return 0;
586 }
587
588 static int load_volume_key_keyfile(
589 struct crypt_device *cd,
590 void *ret_vk,
591 size_t *ret_vks) {
592
593 _cleanup_(erase_and_freep) char *password = NULL;
594 size_t password_len;
595 int r;
596
597 assert_se(cd);
598 assert_se(ret_vk);
599 assert_se(ret_vks);
600
601 r = read_full_file_full(
602 AT_FDCWD,
603 arg_unlock_keyfile,
604 0,
605 SIZE_MAX,
606 READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
607 NULL,
608 &password,
609 &password_len);
610 if (r < 0)
611 return log_error_errno(r, "Reading keyfile %s failed: %m", arg_unlock_keyfile);
612
613 r = crypt_volume_key_get(
614 cd,
615 CRYPT_ANY_SLOT,
616 ret_vk,
617 ret_vks,
618 password,
619 password_len);
620 if (r < 0)
621 return log_error_errno(r, "Unlocking via keyfile failed: %m");
622
623 return r;
624 }
625
626 static int prepare_luks(
627 struct crypt_device **ret_cd,
628 void **ret_volume_key,
629 size_t *ret_volume_key_size) {
630
631 _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
632 _cleanup_(erase_and_freep) void *vk = NULL;
633 size_t vks;
634 int r;
635
636 assert(ret_cd);
637 assert(!ret_volume_key == !ret_volume_key_size);
638
639 r = crypt_init(&cd, arg_node);
640 if (r < 0)
641 return log_error_errno(r, "Failed to allocate libcryptsetup context: %m");
642
643 cryptsetup_enable_logging(cd);
644
645 r = crypt_load(cd, CRYPT_LUKS2, NULL);
646 if (r < 0)
647 return log_error_errno(r, "Failed to load LUKS2 superblock: %m");
648
649 r = check_for_homed(cd);
650 if (r < 0)
651 return r;
652
653 if (!ret_volume_key) {
654 *ret_cd = TAKE_PTR(cd);
655 return 0;
656 }
657
658 r = crypt_get_volume_key_size(cd);
659 if (r <= 0)
660 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine LUKS volume key size");
661 vks = (size_t) r;
662
663 vk = malloc(vks);
664 if (!vk)
665 return log_oom();
666
667 switch (arg_unlock_type) {
668
669 case UNLOCK_KEYFILE:
670 r = load_volume_key_keyfile(cd, vk, &vks);
671 break;
672
673 case UNLOCK_FIDO2:
674 r = load_volume_key_fido2(cd, arg_node, arg_unlock_fido2_device, vk, &vks);
675 break;
676
677 case UNLOCK_PASSWORD:
678 r = load_volume_key_password(cd, arg_node, vk, &vks);
679 break;
680
681 default:
682 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown LUKS unlock method");
683 }
684
685 if (r < 0)
686 return r;
687
688 *ret_cd = TAKE_PTR(cd);
689 *ret_volume_key = TAKE_PTR(vk);
690 *ret_volume_key_size = vks;
691
692 return 0;
693 }
694
695 static int run(int argc, char *argv[]) {
696 _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
697 _cleanup_(erase_and_freep) void *vk = NULL;
698 size_t vks;
699 int slot, r;
700
701 log_show_color(true);
702 log_parse_environment();
703 log_open();
704
705 r = parse_argv(argc, argv);
706 if (r <= 0)
707 return r;
708
709 cryptsetup_enable_logging(NULL);
710
711 if (arg_enroll_type < 0)
712 r = prepare_luks(&cd, NULL, NULL); /* No need to unlock device if we don't need the volume key because we don't need to enroll anything */
713 else
714 r = prepare_luks(&cd, &vk, &vks);
715 if (r < 0)
716 return r;
717
718 switch (arg_enroll_type) {
719
720 case ENROLL_PASSWORD:
721 slot = enroll_password(cd, vk, vks);
722 break;
723
724 case ENROLL_RECOVERY:
725 slot = enroll_recovery(cd, vk, vks);
726 break;
727
728 case ENROLL_PKCS11:
729 slot = enroll_pkcs11(cd, vk, vks, arg_pkcs11_token_uri);
730 break;
731
732 case ENROLL_FIDO2:
733 slot = enroll_fido2(cd, vk, vks, arg_fido2_device, arg_fido2_lock_with, arg_fido2_cred_alg);
734 break;
735
736 case ENROLL_TPM2:
737 slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_seal_key_handle, arg_tpm2_device_key, arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, arg_tpm2_public_key, arg_tpm2_public_key_pcr_mask, arg_tpm2_signature, arg_tpm2_pin, arg_tpm2_pcrlock);
738 break;
739
740 case _ENROLL_TYPE_INVALID:
741 /* List enrolled slots if we are called without anything to enroll or wipe */
742 if (!wipe_requested())
743 return list_enrolled(cd);
744
745 /* Only slot wiping selected */
746 return wipe_slots(cd, arg_wipe_slots, arg_n_wipe_slots, arg_wipe_slots_scope, arg_wipe_slots_mask, -1);
747
748 default:
749 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Operation not implemented yet.");
750 }
751 if (slot < 0)
752 return slot;
753
754 /* After we completed enrolling, remove user selected slots */
755 r = wipe_slots(cd, arg_wipe_slots, arg_n_wipe_slots, arg_wipe_slots_scope, arg_wipe_slots_mask, slot);
756 if (r < 0)
757 return r;
758
759 return 0;
760 }
761
762 DEFINE_MAIN_FUNCTION(run);