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