• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 29295695877

13 Jul 2026 11:19PM UTC coverage: 72.94% (-0.05%) from 72.994%
29295695877

push

github

web-flow
userdb: suppress userdb queries for backends indicating uid/gid/name range info via xattrs on entrypoint sockets (#42961)

Let's optimize userdb queries a bit: by encoding the covered UID/GID
ranges and user/group name patterns on the varlink entrypoint sockets
for userdb backends we can make them wake up less and reduce the work
triggered by queries.

81 of 92 new or added lines in 5 files covered. (88.04%)

5898 existing lines in 76 files now uncovered.

345436 of 473591 relevant lines covered (72.94%)

1320061.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

45.77
/src/cryptsetup/cryptsetup.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <sys/mman.h>
4
#include <sys/stat.h>
5
#include <unistd.h>
6

7
#include "sd-device.h"
8
#include "sd-event.h"
9
#include "sd-json.h"
10
#include "sd-messages.h"
11

12
#include "alloc-util.h"
13
#include "ask-password-api.h"
14
#include "build.h"
15
#include "crypto-util.h"
16
#include "cryptsetup-fido2.h"
17
#include "cryptsetup-keyfile.h"
18
#include "cryptsetup-pkcs11.h"
19
#include "cryptsetup-tpm2.h"
20
#include "cryptsetup-util.h"
21
#include "dlopen-note.h"
22
#include "efi-api.h"
23
#include "efi-loader.h"
24
#include "efivars.h"
25
#include "env-util.h"
26
#include "errno-util.h"
27
#include "escape.h"
28
#include "extract-word.h"
29
#include "fileio.h"
30
#include "format-table.h"
31
#include "fs-util.h"
32
#include "hexdecoct.h"
33
#include "json-util.h"
34
#include "libfido2-util.h"
35
#include "libmount-util.h"
36
#include "log.h"
37
#include "main-func.h"
38
#include "memory-util.h"
39
#include "nulstr-util.h"
40
#include "options.h"
41
#include "parse-util.h"
42
#include "path-util.h"
43
#include "pkcs11-util.h"
44
#include "pretty-print.h"
45
#include "process-util.h"
46
#include "random-util.h"
47
#include "string-table.h"
48
#include "string-util.h"
49
#include "strv.h"
50
#include "time-util.h"
51
#include "tpm2-pcr.h"
52
#include "tpm2-util.h"
53
#include "verbs.h"
54

55
/* internal helper */
56
#define ANY_LUKS "LUKS"
57
/* as in src/cryptsetup.h */
58
#define CRYPT_SECTOR_SIZE 512U
59
#define CRYPT_MAX_SECTOR_SIZE 4096U
60

61
typedef enum PassphraseType {
62
        PASSPHRASE_NONE,
63
        PASSPHRASE_REGULAR = 1 << 0,
64
        PASSPHRASE_RECOVERY_KEY = 1 << 1,
65
        PASSPHRASE_BOTH = PASSPHRASE_REGULAR|PASSPHRASE_RECOVERY_KEY,
66
        _PASSPHRASE_TYPE_MAX,
67
        _PASSPHRASE_TYPE_INVALID = -1,
68
} PassphraseType;
69

70
typedef enum TokenType {
71
        TOKEN_TPM2,
72
        TOKEN_FIDO2,
73
        TOKEN_PKCS11,
74
        _TOKEN_TYPE_MAX,
75
        _TOKEN_TYPE_INVALID = -EINVAL,
76
} TokenType;
77

78
static const char *arg_type = NULL; /* ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2, CRYPT_TCRYPT, CRYPT_BITLK or CRYPT_PLAIN */
79
static char *arg_cipher = NULL;
80
static unsigned arg_key_size = 0;
81
static unsigned arg_sector_size = CRYPT_SECTOR_SIZE;
82
static int arg_key_slot = CRYPT_ANY_SLOT;
83
static unsigned arg_keyfile_size = 0;
84
static uint64_t arg_keyfile_offset = 0;
85
static bool arg_keyfile_erase = false;
86
static bool arg_try_empty_password = false;
87
static char *arg_hash = NULL;
88
static char *arg_header = NULL;
89
static unsigned arg_tries = 3;
90
static bool arg_readonly = false;
91
static bool arg_verify = false;
92
static bool arg_password_cache_set = false; /* Not the actual argument value, just an indicator that some value is set */
93
static AskPasswordFlags arg_ask_password_flags = ASK_PASSWORD_ACCEPT_CACHED | ASK_PASSWORD_PUSH_CACHE;
94
static bool arg_discards = false;
95
static bool arg_same_cpu_crypt = false;
96
static bool arg_submit_from_crypt_cpus = false;
97
static bool arg_no_read_workqueue = false;
98
static bool arg_no_write_workqueue = false;
99
static bool arg_tcrypt_hidden = false;
100
static bool arg_tcrypt_system = false;
101
static bool arg_tcrypt_veracrypt = false;
102
static uint32_t arg_tcrypt_veracrypt_pim = 0;
103
static char **arg_tcrypt_keyfiles = NULL;
104
static uint64_t arg_offset = 0;
105
static uint64_t arg_skip = 0;
106
static usec_t arg_timeout = USEC_INFINITY;
107
static char *arg_pkcs11_uri = NULL;
108
static bool arg_pkcs11_uri_auto = false;
109
static char *arg_fido2_device = NULL;
110
static bool arg_fido2_device_auto = false;
111
static void *arg_fido2_cid = NULL;
112
static size_t arg_fido2_cid_size = 0;
113
static char *arg_fido2_rp_id = NULL;
114
/* For now and for compatibility, if the user explicitly configured FIDO2 support and we do
115
 * not read FIDO2 metadata off the LUKS2 header, default to the systemd 248 logic, where we
116
 * use PIN + UP when needed, and do not configure UV at all. */
117
static Fido2EnrollFlags arg_fido2_manual_flags = FIDO2ENROLL_PIN_IF_NEEDED | FIDO2ENROLL_UP_IF_NEEDED | FIDO2ENROLL_UV_OMIT;
118
static char *arg_tpm2_device = NULL; /* These and the following fields are about locking an encrypted volume to the local TPM */
119
static bool arg_tpm2_device_auto = false;
120
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
121
static char *arg_tpm2_signature = NULL;
122
static bool arg_tpm2_pin = false;
123
static char *arg_tpm2_pcrlock = NULL;
124
static usec_t arg_token_timeout_usec = 30*USEC_PER_SEC;
125
static unsigned arg_tpm2_measure_pcr = UINT_MAX; /* This and the following field is about measuring the unlocked volume key to the local TPM */
126
static char **arg_tpm2_measure_banks = NULL;
127
static char *arg_tpm2_measure_keyslot_nvpcr = NULL;
128
static char *arg_link_keyring = NULL;
129
static char *arg_link_key_type = NULL;
130
static char *arg_link_key_description = NULL;
131
static char *arg_fixate_volume_key = NULL;
132

133
STATIC_DESTRUCTOR_REGISTER(arg_cipher, freep);
151✔
134
STATIC_DESTRUCTOR_REGISTER(arg_hash, freep);
151✔
135
STATIC_DESTRUCTOR_REGISTER(arg_header, freep);
151✔
136
STATIC_DESTRUCTOR_REGISTER(arg_tcrypt_keyfiles, strv_freep);
151✔
137
STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_uri, freep);
151✔
138
STATIC_DESTRUCTOR_REGISTER(arg_fido2_device, freep);
151✔
139
STATIC_DESTRUCTOR_REGISTER(arg_fido2_cid, freep);
151✔
140
STATIC_DESTRUCTOR_REGISTER(arg_fido2_rp_id, freep);
151✔
141
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
151✔
142
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep);
151✔
143
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_measure_banks, strv_freep);
151✔
144
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_measure_keyslot_nvpcr, freep);
151✔
145
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_pcrlock, freep);
151✔
146
STATIC_DESTRUCTOR_REGISTER(arg_link_keyring, freep);
151✔
147
STATIC_DESTRUCTOR_REGISTER(arg_link_key_type, freep);
151✔
148
STATIC_DESTRUCTOR_REGISTER(arg_link_key_description, freep);
151✔
149
STATIC_DESTRUCTOR_REGISTER(arg_fixate_volume_key, freep);
151✔
150

151
static const char* const passphrase_type_table[_PASSPHRASE_TYPE_MAX] = {
152
        [PASSPHRASE_REGULAR]      = "passphrase",
153
        [PASSPHRASE_RECOVERY_KEY] = "recovery key",
154
        [PASSPHRASE_BOTH]         = "passphrase or recovery key",
155
};
156

157
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(passphrase_type, PassphraseType);
×
158

159
static const char* const token_type_table[_TOKEN_TYPE_MAX] = {
160
        [TOKEN_TPM2]   = "tpm2",
161
        [TOKEN_FIDO2]  = "fido2",
162
        [TOKEN_PKCS11] = "pkcs11",
163
};
164

165
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(token_type, TokenType);
46✔
166

167
/* Options Debian's crypttab knows we don't:
168
    check=
169
    checkargs=
170
    noearly
171
    loud
172
    quiet
173
    keyscript=
174
    initramfs
175
*/
176

177
static int parse_one_option(const char *option) {
165✔
178
        const char *val;
165✔
179
        int r;
165✔
180

181
        assert(option);
165✔
182

183
        /* Handled outside of this tool */
184
        if (STR_IN_SET(option, "noauto", "auto", "nofail", "fail", "_netdev", "keyfile-timeout"))
165✔
185
                return 0;
1✔
186

187
        if (startswith(option, "keyfile-timeout="))
164✔
188
                return 0;
189

190
        if ((val = startswith(option, "cipher="))) {
164✔
191
                r = free_and_strdup(&arg_cipher, val);
×
192
                if (r < 0)
×
193
                        return log_oom();
×
194

195
        } else if ((val = startswith(option, "size="))) {
164✔
196

197
                r = safe_atou(val, &arg_key_size);
×
198
                if (r < 0) {
×
199
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
200
                        return 0;
201
                }
202

203
                if (arg_key_size % 8) {
×
204
                        log_warning("size= not a multiple of 8, ignoring.");
×
205
                        return 0;
206
                }
207

208
                arg_key_size /= 8;
×
209

210
        } else if ((val = startswith(option, "sector-size="))) {
164✔
211

212
                r = safe_atou(val, &arg_sector_size);
×
213
                if (r < 0) {
×
214
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
215
                        return 0;
216
                }
217

218
                if (arg_sector_size % 2) {
×
219
                        log_warning("sector-size= not a multiple of 2, ignoring.");
×
220
                        return 0;
221
                }
222

223
                if (arg_sector_size < CRYPT_SECTOR_SIZE || arg_sector_size > CRYPT_MAX_SECTOR_SIZE)
×
224
                        log_warning("sector-size= is outside of %u and %u, ignoring.", CRYPT_SECTOR_SIZE, CRYPT_MAX_SECTOR_SIZE);
×
225

226
        } else if ((val = startswith(option, "key-slot=")) ||
164✔
227
                   (val = startswith(option, "keyslot="))) {
162✔
228

229
                arg_type = ANY_LUKS;
2✔
230
                r = safe_atoi(val, &arg_key_slot);
2✔
231
                if (r < 0)
2✔
232
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
233

234
        } else if ((val = startswith(option, "tcrypt-keyfile="))) {
162✔
235

236
                arg_type = CRYPT_TCRYPT;
×
237
                if (path_is_absolute(val)) {
×
238
                        if (strv_extend(&arg_tcrypt_keyfiles, val) < 0)
×
239
                                return log_oom();
×
240
                } else
241
                        log_warning("Key file path \"%s\" is not absolute, ignoring.", val);
×
242

243
        } else if ((val = startswith(option, "keyfile-size="))) {
162✔
244

245
                r = safe_atou(val, &arg_keyfile_size);
3✔
246
                if (r < 0)
3✔
247
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
248

249
        } else if ((val = startswith(option, "keyfile-offset="))) {
159✔
250

251
                r = safe_atou64(val, &arg_keyfile_offset);
5✔
252
                if (r < 0)
5✔
253
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
254

255
        } else if ((val = startswith(option, "keyfile-erase="))) {
154✔
256

257
                r = parse_boolean(val);
2✔
258
                if (r < 0) {
2✔
259
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
260
                        return 0;
261
                }
262

263
                arg_keyfile_erase = r;
2✔
264

265
        } else if (streq(option, "keyfile-erase"))
152✔
266
                arg_keyfile_erase = true;
×
267

268
        else if ((val = startswith(option, "hash="))) {
152✔
269
                r = free_and_strdup(&arg_hash, val);
×
270
                if (r < 0)
×
271
                        return log_oom();
×
272

273
        } else if ((val = startswith(option, "header="))) {
152✔
274
                if (!arg_type || !STR_IN_SET(arg_type, ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2, CRYPT_TCRYPT))
9✔
275
                        arg_type = ANY_LUKS;
7✔
276

277
                if (!path_is_absolute(val))
9✔
278
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
279
                                               "Header path \"%s\" is not absolute, refusing.", val);
280

281
                if (arg_header)
9✔
282
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
283
                                               "Duplicate header= option, refusing.");
284

285
                arg_header = strdup(val);
9✔
286
                if (!arg_header)
9✔
287
                        return log_oom();
×
288

289
        } else if ((val = startswith(option, "tries="))) {
143✔
290

291
                r = safe_atou(val, &arg_tries);
×
292
                if (r < 0)
×
293
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
165✔
294

295
        } else if (STR_IN_SET(option, "readonly", "read-only"))
143✔
296
                arg_readonly = true;
×
297
        else if (streq(option, "verify"))
143✔
298
                arg_verify = true;
×
299
        else if ((val = startswith(option, "password-echo="))) {
143✔
300
                if (streq(val, "masked"))
×
301
                        arg_ask_password_flags &= ~(ASK_PASSWORD_ECHO|ASK_PASSWORD_SILENT);
×
302
                else {
303
                        r = parse_boolean(val);
×
304
                        if (r < 0) {
×
305
                                log_warning_errno(r, "Invalid password-echo= option \"%s\", ignoring.", val);
×
306
                                return 0;
×
307
                        }
308

309
                        SET_FLAG(arg_ask_password_flags, ASK_PASSWORD_ECHO, r);
×
310
                        SET_FLAG(arg_ask_password_flags, ASK_PASSWORD_SILENT, !r);
×
311
                }
312
        } else if ((val = startswith(option, "password-cache="))) {
143✔
313
                arg_password_cache_set = true;
×
314

315
                if (streq(val, "read-only")) {
×
316
                        arg_ask_password_flags |= ASK_PASSWORD_ACCEPT_CACHED;
×
317
                        arg_ask_password_flags &= ~ASK_PASSWORD_PUSH_CACHE;
×
318
                } else {
319
                        r = parse_boolean(val);
×
320
                        if (r < 0) {
×
321
                                log_warning_errno(r, "Invalid password-cache= option \"%s\", ignoring.", val);
×
322
                                return 0;
323
                        }
324

325
                        SET_FLAG(arg_ask_password_flags, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, r);
×
326
                }
327
        } else if (STR_IN_SET(option, "allow-discards", "discard"))
143✔
328
                arg_discards = true;
×
329
        else if (streq(option, "same-cpu-crypt"))
143✔
330
                arg_same_cpu_crypt = true;
×
331
        else if (streq(option, "submit-from-crypt-cpus"))
143✔
332
                arg_submit_from_crypt_cpus = true;
×
333
        else if (streq(option, "no-read-workqueue"))
143✔
334
                arg_no_read_workqueue = true;
×
335
        else if (streq(option, "no-write-workqueue"))
143✔
336
                arg_no_write_workqueue = true;
×
337
        else if (streq(option, "luks"))
143✔
338
                arg_type = ANY_LUKS;
8✔
339
        else if (streq(option, "bitlk"))
135✔
340
                arg_type = CRYPT_BITLK;
×
341
        else if (streq(option, "tcrypt"))
135✔
342
                arg_type = CRYPT_TCRYPT;
×
343
        else if (STR_IN_SET(option, "tcrypt-hidden", "tcrypthidden")) {
135✔
344
                arg_type = CRYPT_TCRYPT;
×
345
                arg_tcrypt_hidden = true;
×
346
        } else if (streq(option, "tcrypt-system")) {
135✔
347
                arg_type = CRYPT_TCRYPT;
×
348
                arg_tcrypt_system = true;
×
349
        } else if (STR_IN_SET(option, "tcrypt-veracrypt", "veracrypt")) {
135✔
350
                arg_type = CRYPT_TCRYPT;
×
351
                arg_tcrypt_veracrypt = true;
×
352
        } else if ((val = startswith(option, "veracrypt-pim="))) {
135✔
353

354
                r = safe_atou32(val, &arg_tcrypt_veracrypt_pim);
×
355
                if (r < 0) {
×
356
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
357
                        return 0;
×
358
                }
359
        } else if (STR_IN_SET(option, "plain", "swap", "tmp") ||
270✔
360
                   startswith(option, "tmp="))
135✔
361
                arg_type = CRYPT_PLAIN;
×
362
        else if ((val = startswith(option, "timeout="))) {
135✔
363

364
                r = parse_sec_fix_0(val, &arg_timeout);
×
365
                if (r < 0)
×
366
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
367

368
        } else if ((val = startswith(option, "offset="))) {
135✔
369

370
                r = safe_atou64(val, &arg_offset);
×
371
                if (r < 0)
×
372
                        return log_error_errno(r, "Failed to parse %s: %m", option);
×
373

374
        } else if ((val = startswith(option, "skip="))) {
135✔
375

376
                r = safe_atou64(val, &arg_skip);
×
377
                if (r < 0)
×
378
                        return log_error_errno(r, "Failed to parse %s: %m", option);
×
379

380
        } else if ((val = startswith(option, "pkcs11-uri="))) {
135✔
381

382
                if (streq(val, "auto")) {
9✔
383
                        arg_pkcs11_uri = mfree(arg_pkcs11_uri);
9✔
384
                        arg_pkcs11_uri_auto = true;
9✔
385
                } else {
386
                        if (!pkcs11_uri_valid(val))
×
387
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "pkcs11-uri= parameter expects a PKCS#11 URI, refusing.");
×
388

389
                        r = free_and_strdup(&arg_pkcs11_uri, val);
×
390
                        if (r < 0)
×
391
                                return log_oom();
×
392

393
                        arg_pkcs11_uri_auto = false;
×
394
                }
395

396
        } else if ((val = startswith(option, "fido2-device="))) {
126✔
397

398
                if (streq(val, "auto")) {
×
399
                        arg_fido2_device = mfree(arg_fido2_device);
×
400
                        arg_fido2_device_auto = true;
×
401
                } else {
402
                        r = free_and_strdup(&arg_fido2_device, val);
×
403
                        if (r < 0)
×
404
                                return log_oom();
×
405

406
                        arg_fido2_device_auto = false;
×
407
                }
408

409
        } else if ((val = startswith(option, "fido2-cid="))) {
126✔
410

411
                if (streq(val, "auto"))
×
412
                        arg_fido2_cid = mfree(arg_fido2_cid);
×
413
                else {
414
                        _cleanup_free_ void *cid = NULL;
×
415
                        size_t cid_size;
×
416

417
                        r = unbase64mem(val, &cid, &cid_size);
×
418
                        if (r < 0)
×
419
                                return log_error_errno(r, "Failed to decode FIDO2 CID data: %m");
×
420

421
                        free(arg_fido2_cid);
×
422
                        arg_fido2_cid = TAKE_PTR(cid);
×
423
                        arg_fido2_cid_size = cid_size;
×
424
                }
425

426
                /* Turn on FIDO2 as side-effect, if not turned on yet. */
427
                if (!arg_fido2_device && !arg_fido2_device_auto)
×
428
                        arg_fido2_device_auto = true;
×
429

430
        } else if ((val = startswith(option, "fido2-rp="))) {
126✔
431

432
                r = free_and_strdup(&arg_fido2_rp_id, val);
×
433
                if (r < 0)
×
434
                        return log_oom();
×
435

436
        } else if ((val = startswith(option, "fido2-pin="))) {
126✔
437

438
                r = parse_boolean(val);
×
439
                if (r < 0) {
×
440
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
441
                        return 0;
442
                }
443

444
                arg_fido2_manual_flags &= ~FIDO2ENROLL_PIN_IF_NEEDED;
×
445
                SET_FLAG(arg_fido2_manual_flags, FIDO2ENROLL_PIN, r);
×
446

447
        } else if ((val = startswith(option, "fido2-up="))) {
126✔
448

449
                r = parse_boolean(val);
×
450
                if (r < 0) {
×
451
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
452
                        return 0;
453
                }
454

455
                arg_fido2_manual_flags &= ~FIDO2ENROLL_UP_IF_NEEDED;
×
456
                SET_FLAG(arg_fido2_manual_flags, FIDO2ENROLL_UP, r);
×
457

458
        } else if ((val = startswith(option, "fido2-uv="))) {
126✔
459

460
                r = parse_boolean(val);
×
461
                if (r < 0) {
×
462
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
463
                        return 0;
464
                }
465

466
                arg_fido2_manual_flags &= ~FIDO2ENROLL_UV_OMIT;
×
467
                SET_FLAG(arg_fido2_manual_flags, FIDO2ENROLL_UV, r);
×
468

469
        } else if ((val = startswith(option, "tpm2-device="))) {
126✔
470

471
                if (streq(val, "auto")) {
43✔
472
                        arg_tpm2_device = mfree(arg_tpm2_device);
43✔
473
                        arg_tpm2_device_auto = true;
43✔
474
                } else {
475
                        r = free_and_strdup(&arg_tpm2_device, val);
×
476
                        if (r < 0)
×
477
                                return log_oom();
×
478

479
                        arg_tpm2_device_auto = false;
×
480
                }
481

482
        } else if ((val = startswith(option, "tpm2-pcrs="))) {
83✔
483

484
                r = tpm2_parse_pcr_argument_to_mask(val, &arg_tpm2_pcr_mask);
×
485
                if (r < 0)
×
486
                        return r;
487

488
        } else if ((val = startswith(option, "tpm2-signature="))) {
83✔
489

490
                if (!path_is_absolute(val))
3✔
491
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
492
                                               "TPM2 signature path \"%s\" is not absolute, refusing.", val);
493

494
                r = free_and_strdup(&arg_tpm2_signature, val);
3✔
495
                if (r < 0)
3✔
496
                        return log_oom();
×
497

498
        } else if ((val = startswith(option, "tpm2-pin="))) {
80✔
499

500
                r = parse_boolean(val);
×
501
                if (r < 0) {
×
502
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
503
                        return 0;
504
                }
505

506
                arg_tpm2_pin = r;
×
507

508
        } else if ((val = startswith(option, "tpm2-pcrlock="))) {
80✔
509

510
                if (!path_is_absolute(val))
5✔
511
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
512
                                               "TPM2 pcrlock policy path \"%s\" is not absolute, refusing.", val);
513

514
                r = free_and_strdup(&arg_tpm2_pcrlock, val);
5✔
515
                if (r < 0)
5✔
516
                        return log_oom();
×
517

518
        } else if ((val = startswith(option, "tpm2-measure-pcr="))) {
75✔
519
                unsigned pcr;
×
520

521
                r = safe_atou(val, &pcr);
×
522
                if (r < 0) {
×
523
                        r = parse_boolean(val);
×
524
                        if (r < 0) {
×
525
                                log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
526
                                return 0;
×
527
                        }
528

529
                        pcr = r ? TPM2_PCR_SYSTEM_IDENTITY : UINT_MAX;
×
530
                } else if (!TPM2_PCR_INDEX_VALID(pcr)) {
×
531
                        log_warning("Selected TPM index for measurement %u outside of allowed range 0…%u, ignoring.", pcr, TPM2_PCRS_MAX-1);
×
532
                        return 0;
533
                }
534

535
                arg_tpm2_measure_pcr = pcr;
×
536

537
        } else if ((val = startswith(option, "tpm2-measure-bank="))) {
75✔
538

539
#if HAVE_OPENSSL
540
                _cleanup_strv_free_ char **l = NULL;
×
541

542
                r = DLOPEN_LIBCRYPTO(LOG_ERR, recommended);
×
543
                if (r < 0)
×
544
                        return r;
545

546
                l = strv_split(val, ":");
×
547
                if (!l)
×
548
                        return log_oom();
×
549

550
                STRV_FOREACH(i, l) {
×
551
                        const EVP_MD *implementation;
×
552

553
                        implementation = sym_EVP_get_digestbyname(*i);
×
554
                        if (!implementation)
×
555
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown bank '%s', refusing.", val);
×
556

557
                        if (strv_extend(&arg_tpm2_measure_banks, sym_EVP_MD_get0_name(implementation)) < 0)
×
558
                                return log_oom();
×
559
                }
560
#else
561
                log_error("Build lacks OpenSSL support, cannot measure to PCR banks, ignoring: %s", option);
562
#endif
563

564
        } else if ((val = startswith(option, "tpm2-measure-keyslot-nvpcr="))) {
75✔
565

566
                r = isempty(val) ? false : parse_boolean(val);
×
567
                if (r == 0) {
×
568
                        arg_tpm2_measure_keyslot_nvpcr = mfree(arg_tpm2_measure_keyslot_nvpcr);
×
569
                        return 0;
×
570
                }
571
                if (r > 0)
×
572
                        val = "cryptsetup";
573
                else if (!tpm2_nvpcr_name_is_valid(val)) {
×
574
                        log_warning("Invalid NvPCR name, ignoring: %s", option);
×
575
                        return 0;
576
                }
577

578
                if (free_and_strdup(&arg_tpm2_measure_keyslot_nvpcr, val) < 0)
×
579
                        return log_oom();
×
580

581
        } else if ((val = startswith(option, "try-empty-password="))) {
75✔
582

583
                r = parse_boolean(val);
1✔
584
                if (r < 0) {
1✔
585
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
586
                        return 0;
587
                }
588

589
                arg_try_empty_password = r;
1✔
590

591
        } else if (streq(option, "try-empty-password"))
74✔
592
                arg_try_empty_password = true;
1✔
593
        else if ((val = startswith(option, "headless="))) {
73✔
594

595
                r = parse_boolean(val);
62✔
596
                if (r < 0) {
62✔
597
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
×
598
                        return 0;
599
                }
600

601
                SET_FLAG(arg_ask_password_flags, ASK_PASSWORD_HEADLESS, r);
62✔
602
        } else if (streq(option, "headless"))
11✔
603
                arg_ask_password_flags |= ASK_PASSWORD_HEADLESS;
7✔
604

605
        else if ((val = startswith(option, "token-timeout="))) {
4✔
606

607
                r = parse_sec_fix_0(val, &arg_token_timeout_usec);
×
608
                if (r < 0)
×
609
                        log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
135✔
610

611
        } else if ((val = startswith(option, "link-volume-key="))) {
4✔
612
                _cleanup_free_ char *keyring = NULL, *key_type = NULL, *key_description = NULL;
×
613
                const char *sep;
×
614

615
                /* Stick with cryptsetup --link-vk-to-keyring format
616
                 * <keyring_description>::%<key_type>:<key_description>,
617
                 * where %<key_type> is optional and defaults to 'user'.
618
                 */
619
                sep = strstr(val, "::");
×
620
                if (!sep)
×
621
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse link-volume-key= option value: %s", val);
×
622

623
                /* cryptsetup (cli) supports <keyring_description> passed in various formats:
624
                 * - well-known keyrings prefixed with '@' (@u user, @s session, etc)
625
                 * - text descriptions prefixed with "%:" or "%keyring:".
626
                 * - text description with no prefix.
627
                 * - numeric keyring id (ignored in current patch set). */
628
                keyring = strndup(val, sep - val);
×
629
                if (!keyring)
×
630
                        return log_oom();
×
631

632
                /* add type prefix if missing (crypt_set_keyring_to_link() expects it) */
633
                if (!IN_SET(*keyring, '@', '%'))
×
634
                        if (!strprepend(&keyring, "%:"))
×
635
                                return log_oom();
×
636

637
                sep += 2;
×
638

639
                /* %<key_type> is optional (and defaults to 'user') */
640
                if (*sep == '%') {
×
641
                        /* must be separated by colon */
642
                        const char *c = strchr(sep, ':');
×
643
                        if (!c)
×
644
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse link-volume-key= option value: %s", val);
×
645

646
                        key_type = strndup(sep + 1, c - sep - 1);
×
647
                        if (!key_type)
×
648
                                return log_oom();
×
649

650
                        sep = c + 1;
×
651
                }
652

653
                key_description = strdup(sep);
×
654
                if (!key_description)
×
655
                        return log_oom();
×
656

657
                free_and_replace(arg_link_keyring, keyring);
×
658
                free_and_replace(arg_link_key_type, key_type);
×
659
                free_and_replace(arg_link_key_description, key_description);
×
660
        } else if ((val = startswith(option, "fixate-volume-key="))) {
4✔
661
                r = free_and_strdup(&arg_fixate_volume_key, val);
4✔
662
                if (r < 0)
4✔
663
                        return log_oom();
×
664

665
        } else if (!streq(option, "x-initrd.attach"))
×
666
                log_warning("Encountered unknown /etc/crypttab option '%s', ignoring.", option);
×
667

668
        return 0;
669
}
670

671
static int parse_crypt_config(const char *options) {
81✔
672
        assert(options);
81✔
673

674
        for (;;) {
411✔
675
                _cleanup_free_ char *word = NULL;
165✔
676
                int r;
246✔
677

678
                r = extract_first_word(&options, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS | EXTRACT_UNESCAPE_SEPARATORS);
246✔
679
                if (r < 0)
246✔
680
                        return log_error_errno(r, "Failed to parse options: %m");
×
681
                if (r == 0)
246✔
682
                        break;
683

684
                r = parse_one_option(word);
165✔
685
                if (r < 0)
165✔
686
                        return r;
687
        }
688

689
        /* sanity-check options */
690
        if (arg_type && !streq(arg_type, CRYPT_PLAIN)) {
81✔
691
                if (arg_offset != 0)
17✔
692
                      log_warning("offset= ignored with type %s", arg_type);
×
693
                if (arg_skip != 0)
17✔
694
                      log_warning("skip= ignored with type %s", arg_type);
×
695
        }
696

697
        if (arg_pkcs11_uri || arg_pkcs11_uri_auto) {
81✔
698
                /* If password-cache was not configured explicitly, default to no cache for PKCS#11 */
699
                if (!arg_password_cache_set)
9✔
700
                        arg_ask_password_flags &= ~(ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE);
9✔
701

702
                /* This prevents future backward-compatibility issues if we decide to allow caching for PKCS#11 */
703
                if (FLAGS_SET(arg_ask_password_flags, ASK_PASSWORD_ACCEPT_CACHED))
9✔
704
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
705
                                               "Password cache is not supported for PKCS#11 security tokens.");
706
        }
707

708
        return 0;
709
}
710

711
static char* disk_description(const char *path) {
14✔
712
        static const char name_fields[] =
14✔
713
                "DM_NAME\0"
714
                "ID_MODEL_FROM_DATABASE\0"
715
                "ID_MODEL\0";
716

717
        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
14✔
718
        const char *name;
14✔
719
        struct stat st;
14✔
720

721
        assert(path);
14✔
722

723
        if (stat(path, &st) < 0)
14✔
724
                return NULL;
725

726
        if (!S_ISBLK(st.st_mode))
14✔
727
                return NULL;
728

729
        if (sd_device_new_from_stat_rdev(&device, &st) < 0)
×
730
                return NULL;
731

732
        if (sd_device_get_property_value(device, "ID_PART_ENTRY_NAME", &name) >= 0) {
×
733
                _cleanup_free_ char *unescaped = NULL;
×
734
                ssize_t l;
×
735

736
                /* ID_PART_ENTRY_NAME uses \x style escaping, using libblkid's blkid_encode_string(). Let's
737
                 * reverse this here to make the string more human friendly in case people embed spaces or
738
                 * other weird stuff. */
739

740
                l = cunescape(name, UNESCAPE_RELAX, &unescaped);
×
741
                if (l < 0) {
×
742
                        log_debug_errno(l, "Failed to unescape ID_PART_ENTRY_NAME, skipping device: %m");
×
743
                        return NULL;
744
                }
745

746
                if (!isempty(unescaped) && !string_has_cc(unescaped, NULL))
×
747
                        return TAKE_PTR(unescaped);
×
748
        }
749

750
        /* These need no unescaping. */
751
        NULSTR_FOREACH(i, name_fields)
×
752
                if (sd_device_get_property_value(device, i, &name) >= 0 &&
×
753
                    !isempty(name))
×
754
                        return strdup(name);
×
755

756
        return NULL;
757
}
758

759
static char* disk_mount_point(const char *label) {
14✔
760
        _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
14✔
761
        _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
×
762
        _cleanup_free_ char *device = NULL;
14✔
763
        int r;
14✔
764

765
        /* Yeah, we don't support native systemd unit files here for now */
766

767
        assert(label);
14✔
768

769
        device = strjoin("/dev/mapper/", label);
14✔
770
        if (!device)
14✔
771
                return NULL;
772

773
        r = libmount_parse_fstab(&table, &iter);
14✔
774
        if (r < 0)
14✔
775
                return NULL;
776

777
        for (;;) {
×
778
                struct libmnt_fs *fs;
14✔
779

780
                r = sym_mnt_table_next_fs(table, iter, &fs);
14✔
781
                if (r != 0)
14✔
782
                        return NULL;
14✔
783

784
                if (path_equal(sym_mnt_fs_get_source(fs), device)) {
×
785
                        const char *target = sym_mnt_fs_get_target(fs);
×
786
                        if (target)
×
787
                                return strdup(target);
×
788
                }
789
        }
790
}
791

792
static char *friendly_disk_name(const char *src, const char *vol) {
14✔
793
        _cleanup_free_ char *description = NULL, *mount_point = NULL;
14✔
794
        char *name_buffer = NULL;
14✔
795
        int r;
14✔
796

797
        assert(src);
14✔
798
        assert(vol);
14✔
799

800
        description = disk_description(src);
14✔
801
        mount_point = disk_mount_point(vol);
14✔
802

803
        /* If the description string is simply the volume name, then let's not show this twice */
804
        if (description && streq(vol, description))
14✔
805
                description = mfree(description);
×
806

807
        if (mount_point && description)
14✔
808
                r = asprintf(&name_buffer, "%s (%s) on %s", description, vol, mount_point);
×
809
        else if (mount_point)
×
810
                r = asprintf(&name_buffer, "%s on %s", vol, mount_point);
×
811
        else if (description)
14✔
812
                r = asprintf(&name_buffer, "%s (%s)", description, vol);
×
813
        else
814
                return strdup(vol);
14✔
815
        if (r < 0)
×
816
                return NULL;
817

818
        return name_buffer;
×
819
}
820

821
static PassphraseType check_registered_passwords(struct crypt_device *cd) {
15✔
822
        _cleanup_free_ bool *slots = NULL;
15✔
823
        int slot_max;
15✔
824
        PassphraseType passphrase_type = PASSPHRASE_NONE;
15✔
825

826
        assert(cd);
15✔
827

828
        if (!streq_ptr(sym_crypt_get_type(cd), CRYPT_LUKS2)) {
15✔
829
                log_debug("%s: not a LUKS2 device, only passphrases are supported", sym_crypt_get_device_name(cd));
×
830
                return PASSPHRASE_REGULAR;
831
        }
832

833
        /* Search all used slots */
834
        assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
15✔
835
        slots = new(bool, slot_max);
15✔
836
        if (!slots)
15✔
837
                return log_oom();
×
838

839
        for (int slot = 0; slot < slot_max; slot++)
495✔
840
                slots[slot] = IN_SET(sym_crypt_keyslot_status(cd, slot), CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST);
480✔
841

842
        /* Iterate all LUKS2 tokens and keep track of all their slots */
843
        for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
495✔
844
                _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
480✔
845
                const char *type;
480✔
846
                sd_json_variant *w, *z;
480✔
847
                int tk;
480✔
848

849
                tk = cryptsetup_get_token_as_json(cd, token, NULL, &v);
480✔
850
                if (IN_SET(tk, -ENOENT, -EINVAL))
480✔
851
                        continue;
470✔
852
                if (tk < 0) {
10✔
853
                        log_warning_errno(tk, "Failed to read JSON token data, ignoring: %m");
×
854
                        continue;
×
855
                }
856

857
                w = sd_json_variant_by_key(v, "type");
10✔
858
                if (!w || !sd_json_variant_is_string(w)) {
10✔
859
                        log_warning("Token JSON data lacks type field, ignoring.");
×
860
                        continue;
×
861
                }
862

863
                type = sd_json_variant_string(w);
10✔
864
                if (STR_IN_SET(type, "systemd-recovery", "systemd-pkcs11", "systemd-fido2", "systemd-tpm2")) {
10✔
865

866
                        /* At least exists one recovery key */
867
                        if (streq(type, "systemd-recovery"))
10✔
868
                                passphrase_type |= PASSPHRASE_RECOVERY_KEY;
×
869

870
                        w = sd_json_variant_by_key(v, "keyslots");
10✔
871
                        if (!w || !sd_json_variant_is_array(w)) {
10✔
872
                                log_warning("Token JSON data lacks keyslots field, ignoring.");
×
873
                                continue;
×
874
                        }
875

876
                        JSON_VARIANT_ARRAY_FOREACH(z, w) {
20✔
877
                                unsigned u;
10✔
878
                                int at;
10✔
879

880
                                if (!sd_json_variant_is_string(z)) {
10✔
881
                                        log_warning("Token JSON data's keyslot field is not an array of strings, ignoring.");
×
882
                                        continue;
×
883
                                }
884

885
                                at = safe_atou(sd_json_variant_string(z), &u);
10✔
886
                                if (at < 0) {
10✔
887
                                        log_warning_errno(at, "Token JSON data's keyslot field is not an integer formatted as string, ignoring.");
×
888
                                        continue;
×
889
                                }
890

891
                                if (u >= (unsigned) slot_max) {
10✔
892
                                        log_warning_errno(at, "Token JSON data's keyslot field exceeds the maximum value allowed, ignoring.");
×
893
                                        continue;
×
894
                                }
895

896
                                slots[u] = false;
10✔
897
                        }
898
                }
899
        }
900

901
        /* Check if any of the slots is not referenced by systemd tokens */
902
        for (int slot = 0; slot < slot_max; slot++)
15✔
903
                if (slots[slot]) {
15✔
904
                        passphrase_type |= PASSPHRASE_REGULAR;
15✔
905
                        break;
15✔
906
                }
907

908
        /* All the slots are referenced by systemd tokens, so if a recovery key is not enrolled,
909
         * we will not be able to enter a passphrase. */
910
        return passphrase_type;
911
}
912

913
static int get_password(
15✔
914
                const char *vol,
915
                const char *src,
916
                usec_t until,
917
                bool ignore_cached,
918
                PassphraseType passphrase_type,
919
                char ***ret) {
920

921
        _cleanup_free_ char *friendly = NULL, *text = NULL, *disk_path = NULL, *id = NULL;
15✔
922
        _cleanup_strv_free_erase_ char **passwords = NULL;
×
923
        AskPasswordFlags flags = arg_ask_password_flags;
15✔
924
        int r;
15✔
925

926
        assert(vol);
15✔
927
        assert(src);
15✔
928
        assert(ret);
15✔
929

930
        if (FLAGS_SET(arg_ask_password_flags, ASK_PASSWORD_HEADLESS))
15✔
931
                return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "Password querying disabled via 'headless' option.");
15✔
932

933
        friendly = friendly_disk_name(src, vol);
×
934
        if (!friendly)
×
935
                return log_oom();
×
936

937
        if (asprintf(&text, "Please enter %s for disk %s:", passphrase_type_to_string(passphrase_type), friendly) < 0)
×
938
                return log_oom();
×
939

940
        disk_path = cescape(src);
×
941
        if (!disk_path)
×
942
                return log_oom();
×
943

944
        id = strjoin("cryptsetup:", disk_path);
×
945
        if (!id)
×
946
                return log_oom();
×
947

948
        AskPasswordRequest req = {
×
949
                .tty_fd = -EBADF,
950
                .message = text,
951
                .icon = "drive-harddisk",
952
                .id = id,
953
                .keyring = "cryptsetup",
954
                .credential = "cryptsetup.passphrase",
955
                .until = until,
956
                .hup_fd = -EBADF,
957
        };
958

959
        if (ignore_cached)
×
960
                flags &= ~ASK_PASSWORD_ACCEPT_CACHED;
×
961

962
        r = ask_password_auto(&req, flags, &passwords);
×
963
        if (r < 0)
×
964
                return log_error_errno(r, "Failed to query password: %m");
×
965

966
        if (arg_verify) {
×
967
                _cleanup_strv_free_erase_ char **passwords2 = NULL;
×
968

969
                assert(strv_length(passwords) == 1);
×
970

971
                text = mfree(text);
×
972
                if (asprintf(&text, "Please enter %s for disk %s (verification):", passphrase_type_to_string(passphrase_type), friendly) < 0)
×
973
                        return log_oom();
×
974

975
                free(id);
×
976
                id = strjoin("cryptsetup-verification:", disk_path);
×
977
                if (!id)
×
978
                        return log_oom();
×
979

980
                req.message = text;
×
981
                req.id = id;
×
982

983
                r = ask_password_auto(&req, flags, &passwords2);
×
984
                if (r < 0)
×
985
                        return log_error_errno(r, "Failed to query verification password: %m");
×
986

987
                assert(strv_length(passwords2) == 1);
×
988

989
                if (!streq(passwords[0], passwords2[0]))
×
990
                        return log_warning_errno(SYNTHETIC_ERRNO(EAGAIN),
×
991
                                                 "Passwords did not match, retrying.");
992
        }
993

994
        strv_uniq(passwords);
×
995

996
        STRV_FOREACH(p, passwords) {
×
997
                char *c;
×
998

999
                if (strlen(*p)+1 >= arg_key_size)
×
1000
                        continue;
×
1001

1002
                /* Pad password if necessary */
1003
                c = new(char, arg_key_size);
×
1004
                if (!c)
×
1005
                        return log_oom();
15✔
1006

1007
                strncpy(c, *p, arg_key_size);
×
1008
                erase_and_free(*p);
×
1009
                *p = TAKE_PTR(c);
×
1010
        }
1011

1012
        *ret = TAKE_PTR(passwords);
×
1013

1014
        return 0;
×
1015
}
1016

1017
static int measure_volume_key(
×
1018
                struct crypt_device *cd,
1019
                const char *name,
1020
                const void *volume_key,
1021
                size_t volume_key_size) {
1022

1023
        int r;
×
1024

1025
        assert(cd);
×
1026
        assert(name);
×
1027
        assert(volume_key);
×
1028
        assert(volume_key_size > 0);
×
1029

1030
        if (arg_tpm2_measure_pcr == UINT_MAX) {
×
1031
                log_debug("Not measuring volume key, deactivated.");
×
1032
                return 0;
×
1033
        }
1034

1035
        r = efi_measured_os(LOG_WARNING);
×
1036
        if (r < 0)
×
1037
                return r;
1038
        if (r == 0) {
×
1039
                log_debug("OS measurements not explicitly requested and kernel stub did not measure kernel image into the expected PCR, skipping userspace volume key measurement, too.");
×
1040
                return 0;
1041
        }
1042

1043
#if HAVE_TPM2
1044
        _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
×
1045
        r = tpm2_context_new_or_warn(arg_tpm2_device, &c);
×
1046
        if (r < 0)
×
1047
                return r;
1048

1049
        _cleanup_strv_free_ char **l = NULL;
×
1050
        if (strv_isempty(arg_tpm2_measure_banks)) {
×
1051
                r = tpm2_get_good_pcr_banks_strv(c, UINT32_C(1) << arg_tpm2_measure_pcr, &l);
×
1052
                if (r < 0)
×
1053
                        return log_error_errno(r, "Could not verify pcr banks: %m");
×
1054
        }
1055

1056
        _cleanup_free_ char *joined = strv_join(l ?: arg_tpm2_measure_banks, ", ");
×
1057
        if (!joined)
×
1058
                return log_oom();
×
1059

1060
        /* Note: we don't directly measure the volume key, it might be a security problem to send an
1061
         * unprotected direct hash of the secret volume key over the wire to the TPM. Hence let's instead
1062
         * send a HMAC signature instead. */
1063

1064
        _cleanup_free_ char *prefix = NULL;
×
1065

1066
        /* Note: what is extended to the SHA256 bank here must match the expected hash of 'fixate-volume-key='
1067
         * calculated by cryptsetup_get_volume_key_id(). */
1068
        r = cryptsetup_get_volume_key_prefix(cd, name, &prefix);
×
1069
        if (r)
×
1070
                return log_error_errno(r, "Could not verify pcr banks: %m");
×
1071

1072
        r = tpm2_pcr_extend_bytes(
×
1073
                        c,
1074
                        /* banks= */ l ?: arg_tpm2_measure_banks,
×
1075
                        /* pcr_index = */ arg_tpm2_measure_pcr,
1076
                        /* data = */ &IOVEC_MAKE_STRING(prefix),
×
1077
                        /* secret = */ &IOVEC_MAKE(volume_key, volume_key_size),
×
1078
                        /* event_type = */ TPM2_EVENT_VOLUME_KEY,
1079
                        /* description = */ prefix);
1080
        if (r < 0)
×
1081
                return log_error_errno(r, "Could not extend PCR: %m");
×
1082

1083
        log_struct(LOG_INFO,
×
1084
                   LOG_MESSAGE_ID(SD_MESSAGE_TPM_PCR_EXTEND_STR),
1085
                   LOG_MESSAGE("Successfully extended PCR index %u with '%s' and volume key (banks %s).", arg_tpm2_measure_pcr, prefix, joined),
1086
                   LOG_ITEM("MEASURING=%s", prefix),
1087
                   LOG_ITEM("PCR=%u", arg_tpm2_measure_pcr),
1088
                   LOG_ITEM("BANKS=%s", joined));
1089

1090
        return 0;
1091
#else
1092
        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support disabled, not measuring volume key.");
1093
#endif
1094
}
1095

1096
static int measure_keyslot(
25✔
1097
                struct crypt_device *cd,
1098
                const char *name,
1099
                const char *mechanism,
1100
                int keyslot) {
1101

1102
#if HAVE_TPM2
1103
        int r;
25✔
1104
#endif
1105
        assert(cd);
25✔
1106
        assert(name);
25✔
1107

1108
        if (!arg_tpm2_measure_keyslot_nvpcr) {
25✔
1109
                log_debug("Not measuring unlock keyslot, deactivated.");
25✔
1110
                return 0;
25✔
1111
        }
1112

1113
#if HAVE_TPM2
1114
        r = efi_measured_os(LOG_WARNING);
×
1115
        if (r < 0)
×
1116
                return r;
1117
        if (r == 0) {
×
1118
                log_debug("OS measurements not explicitly requested and kernel stub did not measure kernel image into the expected PCR, skipping userspace key slot measurement, too.");
×
1119
                return 0;
1120
        }
1121

1122
        _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
×
1123
        r = tpm2_context_new_or_warn(arg_tpm2_device, &c);
×
1124
        if (r < 0)
×
1125
                return r;
1126

1127
        _cleanup_free_ char *escaped = NULL;
×
1128
        escaped = xescape(name, ":"); /* avoid ambiguity around ":" once we join things below */
×
1129
        if (!escaped)
×
1130
                return log_oom();
×
1131

1132
        _cleanup_free_ char *k = NULL;
×
1133
        if (keyslot >= 0 && asprintf(&k, "%i", keyslot) < 0)
×
1134
                return log_oom();
×
1135

1136
        _cleanup_free_ char *s = NULL;
×
1137
        s = strjoin("cryptsetup-keyslot:", escaped, ":", strempty(sym_crypt_get_uuid(cd)), ":", strempty(mechanism), ":", strempty(k));
×
1138
        if (!s)
×
1139
                return log_oom();
×
1140

1141
        r = tpm2_nvpcr_extend_bytes(c, /* session= */ NULL, arg_tpm2_measure_keyslot_nvpcr, &IOVEC_MAKE_STRING(s), /* secret= */ NULL, TPM2_EVENT_KEYSLOT, s);
×
1142
        if (r == -ENETDOWN) {
×
1143
                /* NvPCR is not initialized yet. Do so now. */
1144
                _cleanup_(iovec_done_erase) struct iovec anchor_secret = {};
×
1145
                r = tpm2_nvpcr_acquire_anchor_secret(&anchor_secret, /* sync_secondary= */ false);
×
1146
                if (r < 0)
×
1147
                        return r;
1148

1149
                r = tpm2_nvpcr_initialize(c, /* session= */ NULL, arg_tpm2_measure_keyslot_nvpcr, &anchor_secret);
×
1150
                if (r < 0)
×
1151
                        return log_error_errno(r, "Failed to extend NvPCR index '%s' with anchor secret: %m", name);
×
1152

1153
                r = tpm2_nvpcr_extend_bytes(c, /* session= */ NULL, arg_tpm2_measure_keyslot_nvpcr, &IOVEC_MAKE_STRING(s), /* secret= */ NULL, TPM2_EVENT_KEYSLOT, s);
×
1154
        }
1155
        if (r < 0)
×
1156
                return log_error_errno(r, "Could not extend NvPCR: %m");
×
1157

1158
        log_struct(LOG_INFO,
×
1159
                   "MESSAGE_ID=" SD_MESSAGE_TPM_NVPCR_EXTEND_STR,
1160
                   LOG_MESSAGE("Successfully extended NvPCR index '%s' with '%s'.", arg_tpm2_measure_keyslot_nvpcr, s),
1161
                   "MEASURING=%s", s,
1162
                   "NVPCR=%s", arg_tpm2_measure_keyslot_nvpcr);
1163

1164
        return 0;
1165
#else
1166
        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support disabled, not measuring keyslot.");
1167
#endif
1168
}
1169

1170
static int log_external_activation(int r, const char *volume) {
×
1171
        assert(volume);
×
1172

1173
        log_notice_errno(r, "Volume '%s' has been activated externally while we have been trying to activate it.", volume);
×
1174
        return 0;
×
1175
}
1176

1177
static int measured_crypt_activate_by_volume_key(
4✔
1178
                struct crypt_device *cd,
1179
                const char *name,
1180
                const char *mechanism,
1181
                int keyslot,
1182
                const void *volume_key,
1183
                size_t volume_key_size,
1184
                uint32_t flags) {
1185

1186
        int r;
4✔
1187

1188
        assert(cd);
4✔
1189
        assert(name);
4✔
1190

1191
        /* A wrapper around crypt_activate_by_volume_key() which also measures to a PCR if that's requested. */
1192

1193
        /* First, check if volume key digest matches the expectation. */
1194
        if (arg_fixate_volume_key) {
4✔
1195
                 _cleanup_free_ char *key_id = NULL;
4✔
1196

1197
                 r = cryptsetup_get_volume_key_id(
4✔
1198
                                 cd,
1199
                                 /* volume_name= */ name,
1200
                                 /* volume_key= */ volume_key,
1201
                                 /* volume_key_size= */ volume_key_size,
1202
                                 /* ret= */ &key_id);
1203
                 if (r < 0)
4✔
1204
                         return log_error_errno(r, "Failed to get volume key id.");
×
1205

1206
                 if (!streq(arg_fixate_volume_key, key_id))
4✔
1207
                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2✔
1208
                                                "Volume key id: '%s' does not match the expectation: '%s'.",
1209
                                                key_id, arg_fixate_volume_key);
1210
        }
1211

1212
        r = sym_crypt_activate_by_volume_key(cd, name, volume_key, volume_key_size, flags);
2✔
1213
        if (r == -EEXIST) /* volume is already active */
2✔
1214
                return log_external_activation(r, name);
×
1215
        if (r < 0)
2✔
1216
                return r;
1217

1218
        if (arg_tpm2_measure_pcr == UINT_MAX) {
2✔
1219
                log_debug("Not measuring volume key, deactivated.");
2✔
1220
                return 0;
1221
        }
1222

1223
        if (volume_key_size > 0)
×
1224
                (void) measure_volume_key(cd, name, volume_key, volume_key_size); /* OK if fails */
×
1225
        else
1226
                log_debug("Not measuring volume key, none specified.");
×
1227

1228
        (void) measure_keyslot(cd, name, mechanism, keyslot); /* ditto */
×
1229
        return r;
×
1230
}
1231

1232
static int measured_crypt_activate_by_passphrase(
33✔
1233
                struct crypt_device *cd,
1234
                const char *name,
1235
                const char *mechanism,
1236
                int keyslot,
1237
                const char *passphrase,
1238
                size_t passphrase_size,
1239
                uint32_t flags) {
1240

1241
        _cleanup_(erase_and_freep) void *vk = NULL;
33✔
1242
        size_t vks;
33✔
1243
        int r;
33✔
1244

1245
        assert(cd);
33✔
1246

1247
        /* A wrapper around crypt_activate_by_passphrase() which also measures to a PCR if that's
1248
         * requested. Note that we may need the volume key for the measurement and/or for the comparison, and
1249
         * crypt_activate_by_passphrase() doesn't give us access to this. Hence, we operate indirectly, and
1250
         * retrieve the volume key first, and then activate through that. */
1251

1252
        if (arg_tpm2_measure_pcr == UINT_MAX && !arg_fixate_volume_key)
33✔
1253
                goto shortcut;
29✔
1254

1255
        r = sym_crypt_get_volume_key_size(cd);
4✔
1256
        if (r < 0)
4✔
1257
                return r;
1258
        if (r == 0) {
4✔
1259
                log_debug("Not measuring volume key, none defined.");
×
1260
                goto shortcut;
×
1261
        }
1262

1263
        vk = malloc(vks = r);
4✔
1264
        if (!vk)
4✔
1265
                return -ENOMEM;
1266

1267
        keyslot = sym_crypt_volume_key_get(cd, keyslot, vk, &vks, passphrase, passphrase_size);
4✔
1268
        if (keyslot < 0)
4✔
1269
                return keyslot;
1270

1271
        return measured_crypt_activate_by_volume_key(cd, name, mechanism, keyslot, vk, vks, flags);
4✔
1272

1273
shortcut:
29✔
1274
        keyslot = sym_crypt_activate_by_passphrase(cd, name, keyslot, passphrase, passphrase_size, flags);
29✔
1275
        if (keyslot == -EEXIST) /* volume is already active */
29✔
1276
                return log_external_activation(keyslot, name);
×
1277
        if (keyslot < 0)
29✔
1278
                return keyslot;
1279

1280
        (void) measure_keyslot(cd, name, mechanism, keyslot);
25✔
1281
        return keyslot;
1282
}
1283

1284
static int attach_tcrypt(
×
1285
                struct crypt_device *cd,
1286
                const char *name,
1287
                TokenType token_type,
1288
                const char *key_file,
1289
                const struct iovec *key_data,
1290
                char **passwords,
1291
                uint32_t flags) {
1292

1293
        int r = 0;
×
1294
        _cleanup_(erase_and_freep) char *passphrase = NULL;
×
1295
        struct crypt_params_tcrypt params = {
×
1296
                .flags = CRYPT_TCRYPT_LEGACY_MODES,
1297
                .keyfiles = (const char **)arg_tcrypt_keyfiles,
1298
                .keyfiles_count = strv_length(arg_tcrypt_keyfiles)
×
1299
        };
1300

1301
        assert(cd);
×
1302
        assert(name);
×
1303
        assert(key_file || key_data || !strv_isempty(passwords));
×
1304

1305
        if (token_type >= 0)
×
1306
                /* Ask for a regular password */
1307
                return log_error_errno(SYNTHETIC_ERRNO(EAGAIN),
×
1308
                                       "Sorry, but tcrypt devices are currently not supported in conjunction with pkcs11/fido2/tpm2 support.");
1309

1310
        if (arg_tcrypt_hidden)
×
1311
                params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
×
1312

1313
        if (arg_tcrypt_system)
×
1314
                params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
×
1315

1316
        if (arg_tcrypt_veracrypt)
×
1317
                params.flags |= CRYPT_TCRYPT_VERA_MODES;
×
1318

1319
        if (arg_tcrypt_veracrypt && arg_tcrypt_veracrypt_pim != 0)
×
1320
                params.veracrypt_pim = arg_tcrypt_veracrypt_pim;
×
1321

1322
        if (key_data) {
×
1323
                params.passphrase = key_data->iov_base;
×
1324
                params.passphrase_size = key_data->iov_len;
×
1325
                r = sym_crypt_load(cd, CRYPT_TCRYPT, &params);
×
1326
        } else if (key_file) {
×
1327
                r = read_one_line_file(key_file, &passphrase);
×
1328
                if (r < 0) {
×
1329
                        log_error_errno(r, "Failed to read password file '%s': %m", key_file);
×
1330
                        return -EAGAIN; /* log with the actual error, but return EAGAIN */
1331
                }
1332
                params.passphrase = passphrase;
×
1333
                params.passphrase_size = strlen(passphrase);
×
1334
                r = sym_crypt_load(cd, CRYPT_TCRYPT, &params);
×
1335
        } else {
1336
                r = -EINVAL;
1337
                STRV_FOREACH(p, passwords){
×
1338
                        params.passphrase = *p;
×
1339
                        params.passphrase_size = strlen(*p);
×
1340
                        r = sym_crypt_load(cd, CRYPT_TCRYPT, &params);
×
1341
                        if (r >= 0)
×
1342
                                break;
1343
                }
1344
        }
1345

1346
        if (r < 0) {
×
1347
                if (r == -EPERM) {
×
1348
                        if (key_data)
×
1349
                                log_error_errno(r, "Failed to activate using discovered key. (Key not correct?)");
×
1350
                        else if (key_file)
×
1351
                                log_error_errno(r, "Failed to activate using password file '%s'. (Key data not correct?)", key_file);
×
1352
                        else
1353
                                log_error_errno(r, "Failed to activate using supplied passwords.");
×
1354

1355
                        return r;
1356
                }
1357

1358
                return log_error_errno(r, "Failed to load tcrypt superblock on device %s: %m", sym_crypt_get_device_name(cd));
×
1359
        }
1360

1361
        r = measured_crypt_activate_by_volume_key(
×
1362
                        cd,
1363
                        name,
1364
                        /* mechanism= */ NULL,
1365
                        /* keyslot= */ -1,
1366
                        /* volume_key= */ NULL,
1367
                        /* volume_key_size= */ 0,
1368
                        flags);
1369
        if (r < 0)
×
1370
                return log_error_errno(r, "Failed to activate tcrypt device %s: %m", sym_crypt_get_device_name(cd));
×
1371

1372
        return 0;
1373
}
1374

1375
static char *make_bindname(const char *volume, TokenType token_type) {
45✔
1376
        const char *token_type_name = token_type_to_string(token_type), *suffix;
45✔
1377
        char *bindname;
45✔
1378
        int r;
45✔
1379

1380
        switch (token_type) {
45✔
1381

1382
        case TOKEN_FIDO2:
1383
                suffix = "-salt";
1384
                break;
1385

1386
        default:
1387
                suffix = NULL;
45✔
1388
        }
1389

1390
        r = asprintf(&bindname,
45✔
1391
                     "@%" PRIx64"/cryptsetup%s%s%s/%s",
1392
                     random_u64(),
1393
                     token_type_name ? "-" : "",
1394
                     strempty(token_type_name),
1395
                     strempty(suffix),
1396
                     volume);
1397
        if (r < 0)
45✔
1398
                return NULL;
45✔
1399

1400
        return bindname;
45✔
1401
}
1402

1403
static int make_security_device_monitor(
×
1404
                sd_event **ret_event,
1405
                sd_device_monitor **ret_monitor) {
1406
        _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
×
1407
        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
×
1408
        int r;
×
1409

1410
        assert(ret_event);
×
1411
        assert(ret_monitor);
×
1412

1413
        /* Waits for a device with "security-device" tag to show up in udev */
1414
        log_debug("Creating device monitor for tag 'security-device' with timeout %s",
×
1415
                  FORMAT_TIMESPAN(arg_token_timeout_usec, 1*USEC_PER_SEC));
1416

1417
        r = sd_event_default(&event);
×
1418
        if (r < 0)
×
1419
                return log_error_errno(r, "Failed to allocate event loop: %m");
×
1420

1421
        r = sd_event_add_time_relative(event, NULL, CLOCK_MONOTONIC, arg_token_timeout_usec, USEC_PER_SEC, NULL, INT_TO_PTR(-ETIMEDOUT));
×
1422
        if (r < 0)
×
1423
                return log_error_errno(r, "Failed to install timeout event source: %m");
×
1424

1425
        r = sd_device_monitor_new(&monitor);
×
1426
        if (r < 0)
×
1427
                return log_error_errno(r, "Failed to allocate device monitor: %m");
×
1428

1429
        (void) sd_device_monitor_set_description(monitor, "security-device");
×
1430

1431
        r = sd_device_monitor_filter_add_match_tag(monitor, "security-device");
×
1432
        if (r < 0)
×
1433
                return log_error_errno(r, "Failed to configure device monitor: %m");
×
1434

1435
        r = sd_device_monitor_attach_event(monitor, event);
×
1436
        if (r < 0)
×
1437
                return log_error_errno(r, "Failed to attach device monitor: %m");
×
1438

1439
        r = sd_device_monitor_start(monitor, NULL, NULL);
×
1440
        if (r < 0)
×
1441
                return log_error_errno(r, "Failed to start device monitor: %m");
×
1442

1443
        *ret_event = TAKE_PTR(event);
×
1444
        *ret_monitor = TAKE_PTR(monitor);
×
1445
        return 0;
×
1446
}
1447

1448
static int run_security_device_monitor(
×
1449
                sd_event *event,
1450
                sd_device_monitor *monitor) {
1451
        bool processed = false;
×
1452
        int r;
×
1453

1454
        assert(event);
×
1455
        assert(monitor);
×
1456

1457
        /* Runs the event loop for the device monitor until either something happens, or the timeout is
1458
         * hit. */
1459

1460
        for (;;) {
×
1461
                int x;
×
1462

1463
                r = sd_event_get_exit_code(event, &x);
×
1464
                if (r < 0) {
×
1465
                        if (r != -ENODATA)
×
1466
                                return log_error_errno(r, "Failed to query exit code from event loop: %m");
×
1467

1468
                        /* On ENODATA we aren't told to exit yet. */
1469
                } else {
1470
                        assert(x == -ETIMEDOUT);
×
1471
                        return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN),
×
1472
                                                "Timed out waiting for security device, aborting security device based authentication attempt.");
1473
                }
1474

1475
                /* Wait for one event, and then eat all subsequent events until there are no further ones */
1476
                r = sd_event_run(event, processed ? 0 : UINT64_MAX);
×
1477
                if (r < 0)
×
1478
                        return log_error_errno(r, "Failed to run event loop: %m");
×
1479
                if (r == 0) /* no events queued anymore */
×
1480
                        return 0;
1481

1482
                processed = true;
×
1483
        }
1484
}
1485

1486
static bool use_token_plugins(void) {
67✔
1487

1488
#if HAVE_TPM2
1489
        /* Currently, there's no way for us to query the volume key when plugins are used. Hence don't use
1490
         * plugins, if measurement has been requested. */
1491
        if (arg_tpm2_measure_pcr != UINT_MAX)
67✔
1492
                return false;
1493
        if (arg_tpm2_measure_keyslot_nvpcr)
67✔
1494
                return false;
1495
        /* Volume key is also needed if the expected key id is set */
1496
        if (arg_fixate_volume_key)
67✔
1497
                return false;
1498
#endif
1499

1500
        /* Disable tokens if we're in FIDO2 mode with manual parameters. */
1501
        if (arg_fido2_cid)
67✔
1502
                return false;
1503

1504
#if HAVE_LIBCRYPTSETUP_PLUGINS
1505
        int r;
67✔
1506

1507
        /* Permit a way to disable libcryptsetup token module support, for debugging purposes. */
1508
        r = getenv_bool("SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE");
67✔
1509
        if (r < 0 && r != -ENXIO)
67✔
1510
                log_debug_errno(r, "Failed to parse $SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE env var: %m");
×
1511
        if (r == 0)
67✔
1512
                return false;
1513

1514
        return sym_crypt_token_external_path();
63✔
1515
#else
1516
        return false;
1517
#endif
1518
}
1519

1520
#if HAVE_LIBCRYPTSETUP_PLUGINS
1521
static int acquire_pins_from_env_variable(char ***ret_pins) {
24✔
1522
        _cleanup_(erase_and_freep) char *envpin = NULL;
24✔
1523
        _cleanup_strv_free_erase_ char **pins = NULL;
24✔
1524
        int r;
24✔
1525

1526
        assert(ret_pins);
24✔
1527

1528
        r = getenv_steal_erase("PIN", &envpin);
24✔
1529
        if (r < 0)
24✔
1530
                return log_error_errno(r, "Failed to acquire PIN from environment: %m");
×
1531
        if (r > 0) {
24✔
1532
                pins = strv_new(envpin);
19✔
1533
                if (!pins)
19✔
1534
                        return log_oom();
×
1535
        }
1536

1537
        *ret_pins = TAKE_PTR(pins);
24✔
1538

1539
        return 0;
24✔
1540
}
1541
#endif
1542

1543
static int crypt_activate_by_token_pin_ask_password(
62✔
1544
                struct crypt_device *cd,
1545
                const char *name,
1546
                const char *type,
1547
                usec_t until,
1548
                void *userdata,
1549
                uint32_t activation_flags,
1550
                const char *message,
1551
                const char *keyring,
1552
                const char *credential) {
1553

1554
#if HAVE_LIBCRYPTSETUP_PLUGINS
1555
        AskPasswordFlags flags = arg_ask_password_flags;
62✔
1556
        _cleanup_strv_free_erase_ char **pins = NULL;
62✔
1557
        int r;
62✔
1558

1559
        r = sym_crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, /* pin= */ NULL, /* pin_size= */ 0, userdata, activation_flags);
62✔
1560
        if (r > 0) /* returns unlocked keyslot id on success */
62✔
1561
                return 0;
1562
        if (r == -EEXIST) /* volume is already active */
38✔
1563
                return log_external_activation(r, name);
×
1564
        if (r != -ENOANO) /* needs pin or pin is wrong */
38✔
1565
                return r;
1566

1567
        r = acquire_pins_from_env_variable(&pins);
24✔
1568
        if (r < 0)
24✔
1569
                return r;
1570

1571
        STRV_FOREACH(p, pins) {
28✔
1572
                r = sym_crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), userdata, activation_flags);
19✔
1573
                if (r > 0) /* returns unlocked keyslot id on success */
19✔
1574
                        return 0;
1575
                if (r == -EEXIST) /* volume is already active */
6✔
1576
                        return log_external_activation(r, name);
×
1577
                if (r != -ENOANO) /* needs pin or pin is wrong */
6✔
1578
                        return r;
1579
        }
1580

1581
        if (FLAGS_SET(arg_ask_password_flags, ASK_PASSWORD_HEADLESS))
9✔
1582
                return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "PIN querying disabled via 'headless' option. Use the '$PIN' environment variable.");
9✔
1583

1584
        for (;;) {
×
1585
                pins = strv_free_erase(pins);
×
1586

1587
                AskPasswordRequest req = {
×
1588
                        .tty_fd = -EBADF,
1589
                        .message = message,
1590
                        .icon = "drive-harddisk",
1591
                        .keyring = keyring,
1592
                        .credential = credential,
1593
                        .until = until,
1594
                        .hup_fd = -EBADF,
1595
                };
1596

1597
                r = ask_password_auto(&req, flags, &pins);
×
1598
                if (r < 0)
×
1599
                        return r;
×
1600

1601
                STRV_FOREACH(p, pins) {
×
1602
                        r = sym_crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), userdata, activation_flags);
×
1603
                        if (r > 0) /* returns unlocked keyslot id on success */
×
1604
                                return 0;
1605
                        if (r == -EEXIST) /* volume is already active */
×
1606
                                return log_external_activation(r, name);
×
1607
                        if (r != -ENOANO) /* needs pin or pin is wrong */
×
1608
                                return r;
1609
                }
1610

1611
                flags &= ~ASK_PASSWORD_ACCEPT_CACHED;
×
1612
        }
1613
        return r;
1614
#else
1615
        return -EOPNOTSUPP;
1616
#endif
1617
}
1618

1619
static int attach_luks2_by_fido2_via_plugin(
×
1620
                struct crypt_device *cd,
1621
                const char *name,
1622
                usec_t until,
1623
                void *userdata,
1624
                uint32_t activation_flags) {
1625

1626
        return crypt_activate_by_token_pin_ask_password(
×
1627
                        cd,
1628
                        name,
1629
                        "systemd-fido2",
1630
                        until,
1631
                        userdata,
1632
                        activation_flags,
1633
                        "Please enter security token PIN:",
1634
                        "fido2-pin",
1635
                        "cryptsetup.fido2-pin");
1636
}
1637

1638
static int attach_luks_or_plain_or_bitlk_by_fido2(
×
1639
                struct crypt_device *cd,
1640
                const char *name,
1641
                const char *key_file,
1642
                const struct iovec *key_data,
1643
                usec_t until,
1644
                uint32_t flags,
1645
                bool pass_volume_key) {
1646

1647
        _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
×
1648
        _cleanup_(erase_and_freep) void *decrypted_key = NULL;
×
1649
        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
×
1650
        size_t decrypted_key_size;
×
1651
        _cleanup_free_ char *friendly = NULL;
×
1652
        int keyslot = arg_key_slot, r;
×
1653
        bool use_libcryptsetup_plugin = use_token_plugins();
×
1654

1655
        assert(cd);
×
1656
        assert(name);
×
1657
        assert(arg_fido2_device || arg_fido2_device_auto);
×
1658

1659
        if (arg_fido2_cid && !key_file && !iovec_is_set(key_data))
×
1660
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1661
                                        "FIDO2 mode with manual parameters selected, but no keyfile specified, refusing.");
1662

1663
        friendly = friendly_disk_name(sym_crypt_get_device_name(cd), name);
×
1664
        if (!friendly)
×
1665
                return log_oom();
×
1666

1667
        for (;;) {
×
1668
                if (use_libcryptsetup_plugin && !arg_fido2_cid) {
×
1669
                        r = attach_luks2_by_fido2_via_plugin(cd, name, until, arg_fido2_device, flags);
×
1670
                        if (IN_SET(r, -ENOTUNIQ, -ENXIO, -ENOENT))
×
1671
                                return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
×
1672
                                                       "Automatic FIDO2 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking.");
1673

1674
                } else {
1675
                        if (arg_fido2_cid)
×
1676
                                r = acquire_fido2_key(
×
1677
                                                name,
1678
                                                friendly,
1679
                                                arg_fido2_device,
1680
                                                arg_fido2_rp_id,
1681
                                                arg_fido2_cid, arg_fido2_cid_size,
1682
                                                key_file, arg_keyfile_size, arg_keyfile_offset,
1683
                                                key_data,
1684
                                                until,
1685
                                                arg_fido2_manual_flags,
1686
                                                "cryptsetup.fido2-pin",
1687
                                                arg_ask_password_flags,
1688
                                                &decrypted_key,
1689
                                                &decrypted_key_size);
1690
                        else
1691
                                r = acquire_fido2_key_auto(
×
1692
                                                cd,
1693
                                                name,
1694
                                                friendly,
1695
                                                arg_fido2_device,
1696
                                                until,
1697
                                                "cryptsetup.fido2-pin",
1698
                                                arg_ask_password_flags,
1699
                                                &decrypted_key,
1700
                                                &decrypted_key_size);
1701
                        if (r >= 0)
×
1702
                                break;
1703
                }
1704

1705
                if (r != -EAGAIN) /* EAGAIN means: token not found */
×
1706
                        return r;
1707

1708
                if (!monitor) {
×
1709
                        /* We didn't find the token. In this case, watch for it via udev. Let's
1710
                         * create an event loop and monitor first. */
1711

1712
                        assert(!event);
×
1713

1714
                        r = make_security_device_monitor(&event, &monitor);
×
1715
                        if (r < 0)
×
1716
                                return r;
1717

1718
                        log_notice("Security token not present for unlocking volume %s, please plug it in.", friendly);
×
1719

1720
                        /* Let's immediately rescan in case the token appeared in the time we needed
1721
                         * to create and configure the monitor */
1722
                        continue;
×
1723
                }
1724

1725
                r = run_security_device_monitor(event, monitor);
×
1726
                if (r < 0)
×
1727
                        return r;
1728

1729
                log_debug("Got one or more potentially relevant udev events, rescanning FIDO2...");
×
1730
        }
1731

1732
        if (pass_volume_key)
×
1733
                r = measured_crypt_activate_by_volume_key(
×
1734
                                cd,
1735
                                name,
1736
                                "fido2",
1737
                                /* keyslot= */ -1,
1738
                                decrypted_key,
1739
                                decrypted_key_size,
1740
                                flags);
1741
        else {
1742
                _cleanup_(erase_and_freep) char *base64_encoded = NULL;
×
1743
                ssize_t base64_encoded_size;
×
1744

1745
                /* Before using this key as passphrase we base64 encode it, for compat with homed */
1746

1747
                base64_encoded_size = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
×
1748
                if (base64_encoded_size < 0)
×
1749
                        return log_oom();
×
1750

1751
                r = measured_crypt_activate_by_passphrase(
×
1752
                                cd,
1753
                                name,
1754
                                "fido2",
1755
                                keyslot,
1756
                                base64_encoded,
1757
                                base64_encoded_size,
1758
                                flags);
1759
        }
1760
        if (r == -EPERM) {
×
1761
                log_error_errno(r, "Failed to activate with FIDO2 decrypted key. (Key incorrect?)");
×
1762
                return -EAGAIN; /* log actual error, but return EAGAIN */
1763
        }
1764
        if (r < 0)
×
1765
                return log_error_errno(r, "Failed to activate with FIDO2 acquired key: %m");
×
1766

1767
        return 0;
1768
}
1769

1770
static int attach_luks2_by_pkcs11_via_plugin(
1✔
1771
                struct crypt_device *cd,
1772
                const char *name,
1773
                const char *friendly_name,
1774
                usec_t until,
1775
                const char *askpw_credential,
1776
                uint32_t flags) {
1777

1778
#if HAVE_LIBCRYPTSETUP_PLUGINS
1779
        int r;
1✔
1780

1781
        if (!streq_ptr(sym_crypt_get_type(cd), CRYPT_LUKS2))
1✔
1782
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Automatic PKCS#11 metadata requires LUKS2 device.");
×
1783

1784
        systemd_pkcs11_plugin_params params = {
1✔
1785
                .friendly_name = friendly_name,
1786
                .until = until,
1787
                .askpw_credential = askpw_credential,
1788
                .askpw_flags = arg_ask_password_flags,
1789
        };
1790

1791
        r = sym_crypt_activate_by_token_pin(cd, name, "systemd-pkcs11", CRYPT_ANY_TOKEN, NULL, 0, &params, flags);
1✔
1792
        if (r > 0) /* returns unlocked keyslot id on success */
1✔
1793
                r = 0;
1794
        if (r == -EEXIST) /* volume is already active */
1✔
1795
                r = log_external_activation(r, name);
×
1796

1797
        return r;
1798
#else
1799
        return -EOPNOTSUPP;
1800
#endif
1801
}
1802

1803
static int attach_luks_or_plain_or_bitlk_by_pkcs11(
1✔
1804
                struct crypt_device *cd,
1805
                const char *name,
1806
                const char *key_file,
1807
                const struct iovec *key_data,
1808
                usec_t until,
1809
                uint32_t flags,
1810
                bool pass_volume_key) {
1811

1812
        _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
1✔
1813
        _cleanup_free_ char *friendly = NULL, *discovered_uri = NULL;
1✔
1814
        size_t decrypted_key_size = 0, discovered_key_size = 0;
1✔
1815
        _cleanup_(erase_and_freep) void *decrypted_key = NULL;
1✔
1816
        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
1✔
1817
        _cleanup_free_ void *discovered_key = NULL;
1✔
1818
        struct iovec discovered_key_data = {};
1✔
1819
        Pkcs11RsaPadding rsa_padding = PKCS11_RSA_PADDING_PKCS1V15;
1✔
1820
        int keyslot = arg_key_slot, r;
1✔
1821
        const char *uri = NULL;
1✔
1822
        bool use_libcryptsetup_plugin = use_token_plugins();
1✔
1823

1824
        assert(cd);
1✔
1825
        assert(name);
1✔
1826
        assert(arg_pkcs11_uri || arg_pkcs11_uri_auto);
1✔
1827

1828
        if (arg_pkcs11_uri_auto) {
1✔
1829
                if (!use_libcryptsetup_plugin) {
1✔
1830
                        r = find_pkcs11_auto_data(cd, &discovered_uri, &discovered_key, &discovered_key_size, &rsa_padding, &keyslot);
×
1831
                        if (IN_SET(r, -ENOTUNIQ, -ENXIO))
×
1832
                                return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
×
1833
                                                       "Automatic PKCS#11 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking.");
1834
                        if (r < 0)
×
1835
                                return r;
1836

1837
                        uri = discovered_uri;
×
1838
                        discovered_key_data = IOVEC_MAKE(discovered_key, discovered_key_size);
×
1839
                        key_data = &discovered_key_data;
×
1840
                }
1841
        } else {
1842
                uri = arg_pkcs11_uri;
×
1843

1844
                if (!key_file && !iovec_is_set(key_data))
×
1845
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PKCS#11 mode selected but no key file specified, refusing.");
×
1846
        }
1847

1848
        friendly = friendly_disk_name(sym_crypt_get_device_name(cd), name);
1✔
1849
        if (!friendly)
1✔
1850
                return log_oom();
×
1851

1852
        for (;;) {
1✔
1853
                if (use_libcryptsetup_plugin && arg_pkcs11_uri_auto)
1✔
1854
                        r = attach_luks2_by_pkcs11_via_plugin(
1✔
1855
                                        cd,
1856
                                        name,
1857
                                        friendly,
1858
                                        until,
1859
                                        "cryptsetup.pkcs11-pin",
1860
                                        flags);
1861
                else {
1862
                        r = decrypt_pkcs11_key(
×
1863
                                        name,
1864
                                        friendly,
1865
                                        uri,
1866
                                        rsa_padding,
1867
                                        key_file, arg_keyfile_size, arg_keyfile_offset,
1868
                                        key_data,
1869
                                        until,
1870
                                        arg_ask_password_flags,
1871
                                        &decrypted_key, &decrypted_key_size);
1872
                        if (r >= 0)
×
1873
                                break;
1874
                }
1875

1876
                if (r != -EAGAIN) /* EAGAIN means: token not found */
1✔
1877
                        return r;
1878

1879
                if (!monitor) {
×
1880
                        /* We didn't find the token. In this case, watch for it via udev. Let's
1881
                         * create an event loop and monitor first. */
1882

1883
                        assert(!event);
×
1884

1885
                        r = make_security_device_monitor(&event, &monitor);
×
1886
                        if (r < 0)
×
1887
                                return r;
1888

1889
                        log_notice("Security token%s%s not present for unlocking volume %s, please plug it in.",
×
1890
                                   uri ? " " : "", strempty(uri), friendly);
1891

1892
                        /* Let's immediately rescan in case the token appeared in the time we needed
1893
                         * to create and configure the monitor */
1894
                        continue;
×
1895
                }
1896

1897
                r = run_security_device_monitor(event, monitor);
×
1898
                if (r < 0)
×
1899
                        return r;
1900

1901
                log_debug("Got one or more potentially relevant udev events, rescanning PKCS#11...");
×
1902
        }
1903
        assert(decrypted_key);
×
1904

1905
        if (pass_volume_key)
×
1906
                r = measured_crypt_activate_by_volume_key(
×
1907
                                cd,
1908
                                name,
1909
                                "pkcs11",
1910
                                /* keyslot= */ -1,
1911
                                decrypted_key,
1912
                                decrypted_key_size,
1913
                                flags);
1914
        else {
1915
                _cleanup_(erase_and_freep) char *base64_encoded = NULL;
×
1916
                ssize_t base64_encoded_size;
×
1917

1918
                /* Before using this key as passphrase we base64 encode it. Why? For compatibility
1919
                 * with homed's PKCS#11 hookup: there we want to use the key we acquired through
1920
                 * PKCS#11 for other authentication/decryption mechanisms too, and some of them do
1921
                 * not take arbitrary binary blobs, but require NUL-terminated strings — most
1922
                 * importantly UNIX password hashes. Hence, for compatibility we want to use a string
1923
                 * without embedded NUL here too, and that's easiest to generate from a binary blob
1924
                 * via base64 encoding. */
1925

1926
                base64_encoded_size = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
×
1927
                if (base64_encoded_size < 0)
×
1928
                        return log_oom();
×
1929

1930
                r = measured_crypt_activate_by_passphrase(
×
1931
                                cd,
1932
                                name,
1933
                                "pkcs11",
1934
                                keyslot,
1935
                                base64_encoded,
1936
                                base64_encoded_size,
1937
                                flags);
1938
        }
1939
        if (r == -EPERM) {
×
1940
                log_error_errno(r, "Failed to activate with PKCS#11 decrypted key. (Key incorrect?)");
1✔
1941
                return -EAGAIN; /* log actual error, but return EAGAIN */
1942
        }
1943
        if (r < 0)
×
1944
                return log_error_errno(r, "Failed to activate with PKCS#11 acquired key: %m");
×
1945

1946
        return 0;
1947
}
1948

1949
static int make_tpm2_device_monitor(
×
1950
                sd_event **ret_event,
1951
                sd_device_monitor **ret_monitor) {
1952

1953
        _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
×
1954
        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
×
1955
        int r;
×
1956

1957
        assert(ret_event);
×
1958
        assert(ret_monitor);
×
1959

1960
        r = sd_event_default(&event);
×
1961
        if (r < 0)
×
1962
                return log_error_errno(r, "Failed to allocate event loop: %m");
×
1963

1964
        r = sd_event_add_time_relative(event, NULL, CLOCK_MONOTONIC, arg_token_timeout_usec, USEC_PER_SEC, NULL, INT_TO_PTR(-ETIMEDOUT));
×
1965
        if (r < 0)
×
1966
                return log_error_errno(r, "Failed to install timeout event source: %m");
×
1967

1968
        r = sd_device_monitor_new(&monitor);
×
1969
        if (r < 0)
×
1970
                return log_error_errno(r, "Failed to allocate device monitor: %m");
×
1971

1972
        (void) sd_device_monitor_set_description(monitor, "tpmrm");
×
1973

1974
        r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, "tpmrm", NULL);
×
1975
        if (r < 0)
×
1976
                return log_error_errno(r, "Failed to configure device monitor: %m");
×
1977

1978
        r = sd_device_monitor_attach_event(monitor, event);
×
1979
        if (r < 0)
×
1980
                return log_error_errno(r, "Failed to attach device monitor: %m");
×
1981

1982
        r = sd_device_monitor_start(monitor, NULL, NULL);
×
1983
        if (r < 0)
×
1984
                return log_error_errno(r, "Failed to start device monitor: %m");
×
1985

1986
        *ret_event = TAKE_PTR(event);
×
1987
        *ret_monitor = TAKE_PTR(monitor);
×
1988
        return 0;
×
1989
}
1990

1991
static int attach_luks2_by_tpm2_via_plugin(
11✔
1992
                struct crypt_device *cd,
1993
                const char *name,
1994
                usec_t until,
1995
                uint32_t flags) {
1996

1997
#if HAVE_LIBCRYPTSETUP_PLUGINS
1998
        systemd_tpm2_plugin_params params = {
11✔
1999
                .search_pcr_mask = arg_tpm2_pcr_mask,
2000
                .device = arg_tpm2_device,
2001
                .signature_path = arg_tpm2_signature,
2002
                .pcrlock_path = arg_tpm2_pcrlock,
2003
        };
2004

2005
        if (!use_token_plugins())
11✔
2006
                return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2✔
2007
                                       "libcryptsetup has external plugins support disabled.");
2008

2009
        return crypt_activate_by_token_pin_ask_password(
9✔
2010
                        cd,
2011
                        name,
2012
                        "systemd-tpm2",
2013
                        until,
2014
                        &params,
2015
                        flags,
2016
                        "Please enter TPM2 PIN:",
2017
                        "tpm2-pin",
2018
                        "cryptsetup.tpm2-pin");
2019
#else
2020
        return -EOPNOTSUPP;
2021
#endif
2022
}
2023

2024
static int attach_luks_or_plain_or_bitlk_by_tpm2(
13✔
2025
                struct crypt_device *cd,
2026
                const char *name,
2027
                const char *key_file,
2028
                const struct iovec *key_data,
2029
                usec_t until,
2030
                uint32_t flags,
2031
                bool pass_volume_key) {
2032

2033
        _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
13✔
2034
        _cleanup_(iovec_done_erase) struct iovec decrypted_key = {};
×
2035
        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
13✔
2036
        _cleanup_free_ char *friendly = NULL;
13✔
2037
        int keyslot = arg_key_slot, r;
13✔
2038

2039
        assert(cd);
13✔
2040
        assert(name);
13✔
2041
        assert(arg_tpm2_device || arg_tpm2_device_auto);
13✔
2042

2043
        friendly = friendly_disk_name(sym_crypt_get_device_name(cd), name);
13✔
2044
        if (!friendly)
13✔
2045
                return log_oom();
×
2046

2047
        for (;;) {
13✔
2048
                if (key_file || iovec_is_set(key_data)) {
13✔
2049
                        /* If key data is specified, use that */
2050

2051
                        r = acquire_tpm2_key(
4✔
2052
                                        name,
2053
                                        arg_tpm2_device,
2054
                                        arg_tpm2_pcr_mask == UINT32_MAX ? TPM2_PCR_MASK_DEFAULT_LEGACY : arg_tpm2_pcr_mask,
2✔
2055
                                        UINT16_MAX,
2056
                                        /* pubkey= */ NULL,
2057
                                        /* pubkey_policy_ref= */ NULL,
2058
                                        /* pubkey_pcr_mask= */ 0,
2059
                                        /* signature_path= */ NULL,
2060
                                        /* pcrlock_path= */ NULL,
2061
                                        /* primary_alg= */ 0,
2062
                                        key_file, arg_keyfile_size, arg_keyfile_offset,
2063
                                        key_data, /* n_blobs= */ iovec_is_set(key_data) ? 1 : 0,
2✔
2064
                                        /* policy_hash= */ NULL, /* we don't know the policy hash */
2065
                                        /* n_policy_hash= */ 0,
2066
                                        /* salt= */ NULL,
2067
                                        /* srk= */ NULL,
2068
                                        /* pcrlock_nv= */ NULL,
2069
                                        arg_tpm2_pin ? TPM2_FLAGS_USE_PIN : 0,
2070
                                        until,
2071
                                        "cryptsetup.tpm2-pin",
2072
                                        arg_ask_password_flags,
2073
                                        /* argon2id_params= */ NULL,
2074
                                        &decrypted_key);
2075
                        if (r >= 0)
2✔
2076
                                break;
2077
                        if (IN_SET(r, -EACCES, -ENOLCK))
2✔
UNCOV
2078
                                return log_error_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed, falling back to traditional unlocking.");
×
2079
                        if (ERRNO_IS_NOT_SUPPORTED(r)) /* TPM2 support not compiled in? */
2✔
UNCOV
2080
                                return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 support not available, falling back to traditional unlocking.");
×
2081
                        /* EAGAIN means: no tpm2 chip found */
2082
                        if (r != -EAGAIN) {
2✔
2083
                                log_notice_errno(r, "TPM2 operation failed, falling back to traditional unlocking: %m");
2✔
2084
                                return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */
2085
                        }
2086
                } else {
2087
                        r = attach_luks2_by_tpm2_via_plugin(cd, name, until, flags);
11✔
2088
                        if (r >= 0)
11✔
2089
                                return 0;
2090
                        /* EAGAIN     means: no tpm2 chip found
2091
                         * EOPNOTSUPP means: no libcryptsetup plugins support */
2092
                        if (r == -ENXIO)
11✔
UNCOV
2093
                                return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN),
×
2094
                                                        "No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking.");
2095
                        if (r == -ENOENT)
11✔
2096
                                return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
4✔
2097
                                                       "No TPM2 metadata enrolled in LUKS2 header or TPM2 support not available, falling back to traditional unlocking.");
2098
                        if (!IN_SET(r, -EOPNOTSUPP, -EAGAIN)) {
7✔
2099
                                log_notice_errno(r, "TPM2 operation failed, falling back to traditional unlocking: %m");
5✔
2100
                                return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */
2101
                        }
2102
                }
2103

2104
                if (r == -EOPNOTSUPP) { /* Plugin not available, let's process TPM2 stuff right here instead */
2✔
2105
                        bool found_some = false;
2✔
2106
                        int token = 0; /* first token to look at */
2✔
2107

2108
                        /* If no key data is specified, look for it in the header. In order to support
2109
                         * software upgrades we'll iterate through all suitable tokens, maybe one of them
2110
                         * works. */
2111

2112
                        for (;;) {
6✔
2113
                                _cleanup_(iovec_done) struct iovec pubkey = {}, salt = {}, srk = {}, pcrlock_nv = {};
2✔
2114
                                _cleanup_free_ char *pubkey_policy_ref = NULL;
4✔
2115
                                struct iovec *blobs = NULL, *policy_hash = NULL;
4✔
2116
                                uint32_t hash_pcr_mask, pubkey_pcr_mask;
4✔
2117
                                size_t n_blobs = 0, n_policy_hash = 0;
4✔
2118
                                uint16_t pcr_bank, primary_alg;
4✔
2119
                                Argon2IdParameters argon2id_params = {};
4✔
2120
                                TPM2Flags tpm2_flags;
4✔
2121

2122
                                CLEANUP_ARRAY(blobs, n_blobs, iovec_array_free);
4✔
UNCOV
2123
                                CLEANUP_ARRAY(policy_hash, n_policy_hash, iovec_array_free);
×
2124

2125
                                r = find_tpm2_auto_data(
4✔
2126
                                                cd,
2127
                                                arg_tpm2_pcr_mask, /* if != UINT32_MAX we'll only look for tokens with this PCR mask */
2128
                                                token, /* search for the token with this index, or any later index than this */
2129
                                                &hash_pcr_mask,
2130
                                                &pcr_bank,
2131
                                                &pubkey,
2132
                                                &pubkey_policy_ref,
2133
                                                &pubkey_pcr_mask,
2134
                                                &primary_alg,
2135
                                                &blobs,
2136
                                                &n_blobs,
2137
                                                &policy_hash,
2138
                                                &n_policy_hash,
2139
                                                &salt,
2140
                                                &srk,
2141
                                                &pcrlock_nv,
2142
                                                &tpm2_flags,
2143
                                                &keyslot,
2144
                                                &token,
2145
                                                &argon2id_params);
2146
                                if (r == -ENXIO)
4✔
2147
                                        /* No further TPM2 tokens found in the LUKS2 header. */
UNCOV
2148
                                        return log_full_errno(found_some ? LOG_NOTICE : LOG_DEBUG,
×
2149
                                                              SYNTHETIC_ERRNO(EAGAIN),
2150
                                                              found_some
2151
                                                              ? "No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking."
2152
                                                              : "No TPM2 metadata enrolled in LUKS2 header, falling back to traditional unlocking.");
2153
                                if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
4✔
2154
                                        /* TPM2 support not compiled in? */
UNCOV
2155
                                        return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
×
2156
                                                               "TPM2 support not available, falling back to traditional unlocking.");
2157
                                if (r < 0)
4✔
2158
                                        return r;
2159

2160
                                found_some = true;
4✔
2161

2162
                                r = acquire_tpm2_key(
4✔
2163
                                                name,
2164
                                                arg_tpm2_device,
2165
                                                hash_pcr_mask,
2166
                                                pcr_bank,
2167
                                                &pubkey,
2168
                                                pubkey_policy_ref,
2169
                                                pubkey_pcr_mask,
2170
                                                arg_tpm2_signature,
2171
                                                arg_tpm2_pcrlock,
2172
                                                primary_alg,
2173
                                                /* key_file= */ NULL, /* key_file_size= */ 0, /* key_file_offset= */ 0, /* no key file */
2174
                                                blobs,
2175
                                                n_blobs,
2176
                                                policy_hash,
2177
                                                n_policy_hash,
2178
                                                &salt,
2179
                                                &srk,
2180
                                                &pcrlock_nv,
2181
                                                tpm2_flags,
2182
                                                until,
2183
                                                "cryptsetup.tpm2-pin",
2184
                                                arg_ask_password_flags,
2185
                                                &argon2id_params,
2186
                                                &decrypted_key);
2187
                                if (IN_SET(r, -EACCES, -ENOLCK))
4✔
UNCOV
2188
                                        return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed, falling back to traditional unlocking.");
×
2189
                                /* Stop unless we should keep iterating to next token because the tried one
2190
                                 * does not match boot state. For now without -EUCLEAN because currently the
2191
                                 * only error it reports won't be solved by moving to another token. */
2192
                                if (!ERRNO_IS_NEG_TPM2_TOKEN_MISMATCH(r))
4✔
2193
                                        break;
2194

2195
                                token++; /* try a different token next time */
2✔
2196
                        }
2197

2198
                        if (r >= 0)
2✔
2199
                                break;
2200
                        /* EAGAIN means: no tpm2 chip found */
UNCOV
2201
                        if (r != -EAGAIN) {
×
UNCOV
2202
                                log_notice_errno(r, "TPM2 operation failed, falling back to traditional unlocking: %m");
×
2203
                                return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */
2204
                        }
2205
                }
2206

2207
                if (!monitor) {
×
2208
                        /* We didn't find the TPM2 device. In this case, watch for it via udev. Let's create
2209
                         * an event loop and monitor first. */
2210

UNCOV
2211
                        assert(!event);
×
2212

2213
                        if (is_efi_boot() && !efi_has_tpm2())
×
2214
                                return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN),
×
2215
                                                        "No TPM2 hardware discovered and EFI firmware does not see it either, falling back to traditional unlocking.");
2216

2217
                        r = make_tpm2_device_monitor(&event, &monitor);
×
UNCOV
2218
                        if (r < 0)
×
2219
                                return r;
2220

2221
                        log_info("TPM2 device not present for unlocking %s, waiting for it to become available.", friendly);
×
2222

2223
                        /* Let's immediately rescan in case the device appeared in the time we needed
2224
                         * to create and configure the monitor */
2225
                        continue;
×
2226
                }
2227

2228
                r = run_security_device_monitor(event, monitor);
×
UNCOV
2229
                if (r < 0)
×
2230
                        return r;
2231

2232
                log_debug("Got one or more potentially relevant udev events, rescanning for TPM2...");
×
2233
        }
2234

2235
        if (pass_volume_key)
2✔
UNCOV
2236
                r = measured_crypt_activate_by_volume_key(
×
2237
                                cd,
2238
                                name,
2239
                                "tpm2",
2240
                                /* keyslot= */ -1,
UNCOV
2241
                                decrypted_key.iov_base,
×
2242
                                decrypted_key.iov_len,
2243
                                flags);
2244
        else {
2245
                _cleanup_(erase_and_freep) char *base64_encoded = NULL;
2✔
2246
                ssize_t base64_encoded_size;
2✔
2247

2248
                /* Before using this key as passphrase we base64 encode it, for compat with homed */
2249

2250
                base64_encoded_size = base64mem(decrypted_key.iov_base, decrypted_key.iov_len, &base64_encoded);
2✔
2251
                if (base64_encoded_size < 0)
2✔
UNCOV
2252
                        return log_oom();
×
2253

2254
                r = measured_crypt_activate_by_passphrase(
2✔
2255
                                cd,
2256
                                name,
2257
                                "tpm2",
2258
                                keyslot,
2259
                                base64_encoded,
2260
                                base64_encoded_size,
2261
                                flags);
2262
        }
2263
        if (r == -EPERM) {
2✔
2264
                log_error_errno(r, "Failed to activate with TPM2 decrypted key. (Key incorrect?)");
13✔
2265
                return -EAGAIN; /* log actual error, but return EAGAIN */
2266
        }
2267
        if (r < 0)
2✔
UNCOV
2268
                return log_error_errno(r, "Failed to activate with TPM2 acquired key: %m");
×
2269

2270
        return 0;
2271
}
2272

2273
static int attach_luks_or_plain_or_bitlk_by_key_data(
3✔
2274
                struct crypt_device *cd,
2275
                const char *name,
2276
                const struct iovec *key_data,
2277
                uint32_t flags,
2278
                bool pass_volume_key) {
2279

2280
        int r;
3✔
2281

2282
        assert(cd);
3✔
2283
        assert(name);
3✔
2284
        assert(key_data);
3✔
2285

2286
        if (pass_volume_key)
3✔
2287
                r = measured_crypt_activate_by_volume_key(cd, name, /* mechanism= */ NULL, /* keyslot= */ -1, key_data->iov_base, key_data->iov_len, flags);
×
2288
        else
2289
                r = measured_crypt_activate_by_passphrase(cd, name, /* mechanism= */ NULL, arg_key_slot, key_data->iov_base, key_data->iov_len, flags);
3✔
2290
        if (r == -EPERM) {
3✔
2291
                log_error_errno(r, "Failed to activate. (Key incorrect?)");
×
2292
                return -EAGAIN; /* Log actual error, but return EAGAIN */
2293
        }
2294
        if (r < 0)
3✔
UNCOV
2295
                return log_error_errno(r, "Failed to activate: %m");
×
2296

2297
        return 0;
2298
}
2299

2300
static int attach_luks_or_plain_or_bitlk_by_key_file(
28✔
2301
                struct crypt_device *cd,
2302
                const char *name,
2303
                const char *key_file,
2304
                uint32_t flags,
2305
                bool pass_volume_key) {
2306

2307
        _cleanup_(erase_and_freep) char *kfdata = NULL;
28✔
2308
        _cleanup_free_ char *bindname = NULL;
28✔
2309
        size_t kfsize;
28✔
2310
        int r;
28✔
2311

2312
        assert(cd);
28✔
2313
        assert(name);
28✔
2314
        assert(key_file);
28✔
2315

2316
        /* If we read the key via AF_UNIX, make this client recognizable */
2317
        bindname = make_bindname(name, /* token_type= */ _TOKEN_TYPE_INVALID);
28✔
2318
        if (!bindname)
28✔
UNCOV
2319
                return log_oom();
×
2320

2321
        r = read_full_file_full(
31✔
2322
                        AT_FDCWD, key_file,
2323
                        arg_keyfile_offset == 0 ? UINT64_MAX : arg_keyfile_offset,
28✔
2324
                        arg_keyfile_size == 0 ? SIZE_MAX : arg_keyfile_size,
28✔
2325
                        READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
2326
                        bindname,
2327
                        &kfdata, &kfsize);
2328
        if (r == -E2BIG) {
28✔
2329
                log_error_errno(r, "Failed to activate, key file '%s' too large.", key_file);
×
2330
                return -EAGAIN;
2331
        }
2332
        if (r == -ENOENT) {
28✔
2333
                log_error_errno(r, "Failed to activate, key file '%s' missing.", key_file);
×
2334
                return -EAGAIN; /* Log actual error, but return EAGAIN */
2335
        }
2336
        if (r < 0)
28✔
UNCOV
2337
                return log_error_errno(r, "Failed to read key file '%s': %m", key_file);
×
2338

2339
        if (pass_volume_key)
28✔
UNCOV
2340
                r = measured_crypt_activate_by_volume_key(cd, name, /* mechanism= */ NULL, /* keyslot= */ -1, kfdata, kfsize, flags);
×
2341
        else
2342
                r = measured_crypt_activate_by_passphrase(cd, name, /* mechanism= */ NULL, arg_key_slot, kfdata, kfsize, flags);
28✔
2343
        if (r == -EPERM) {
28✔
2344
                log_error_errno(r, "Failed to activate with key file '%s'. (Key data incorrect?)", key_file);
28✔
2345
                return -EAGAIN; /* Log actual error, but return EAGAIN */
2346
        }
2347
        if (r < 0)
24✔
2348
                return log_error_errno(r, "Failed to activate with key file '%s': %m", key_file);
2✔
2349

2350
        return 0;
2351
}
2352

UNCOV
2353
static int attach_luks_or_plain_or_bitlk_by_passphrase(
×
2354
                struct crypt_device *cd,
2355
                const char *name,
2356
                char **passwords,
2357
                uint32_t flags,
2358
                bool pass_volume_key) {
2359

UNCOV
2360
        int r;
×
2361

2362
        assert(cd);
×
2363
        assert(name);
×
2364

2365
        r = -EINVAL;
2366
        STRV_FOREACH(p, passwords) {
×
2367
                if (pass_volume_key)
×
UNCOV
2368
                        r = measured_crypt_activate_by_volume_key(cd, name, /* mechanism= */ NULL, /* keyslot= */ -1, *p, arg_key_size, flags);
×
2369
                else
2370
                        r = measured_crypt_activate_by_passphrase(cd, name, /* mechanism= */ NULL, arg_key_slot, *p, strlen(*p), flags);
×
2371
                if (r >= 0)
×
2372
                        break;
2373
        }
2374
        if (r == -EPERM) {
×
2375
                log_error_errno(r, "Failed to activate with specified passphrase. (Passphrase incorrect?)");
×
2376
                return -EAGAIN; /* log actual error, but return EAGAIN */
2377
        }
UNCOV
2378
        if (r < 0)
×
UNCOV
2379
                return log_error_errno(r, "Failed to activate with specified passphrase: %m");
×
2380

2381
        return 0;
2382
}
2383

2384
static int attach_luks_or_plain_or_bitlk(
45✔
2385
                struct crypt_device *cd,
2386
                const char *name,
2387
                TokenType token_type,
2388
                const char *key_file,
2389
                const struct iovec *key_data,
2390
                char **passwords,
2391
                uint32_t flags,
2392
                usec_t until) {
2393

2394
        bool pass_volume_key = false;
45✔
2395
        int r;
45✔
2396

2397
        assert(cd);
45✔
2398
        assert(name);
45✔
2399

2400
        if ((!arg_type && !sym_crypt_get_type(cd)) || streq_ptr(arg_type, CRYPT_PLAIN)) {
45✔
UNCOV
2401
                struct crypt_params_plain params = {
×
2402
                        .offset = arg_offset,
2403
                        .skip = arg_skip,
2404
                        .sector_size = arg_sector_size,
2405
                };
UNCOV
2406
                const char *cipher, *cipher_mode;
×
UNCOV
2407
                _cleanup_free_ char *truncated_cipher = NULL;
×
2408

2409
                if (streq_ptr(arg_hash, "plain"))
×
2410
                        /* plain isn't a real hash type. it just means "use no hash" */
2411
                        params.hash = NULL;
UNCOV
2412
                else if (arg_hash)
×
2413
                        params.hash = arg_hash;
×
UNCOV
2414
                else if (!key_file)
×
2415
                        /* for CRYPT_PLAIN, the behaviour of cryptsetup package is to not hash when a key
2416
                         * file is provided */
UNCOV
2417
                        params.hash = "ripemd160";
×
2418

2419
                if (arg_cipher) {
×
2420
                        size_t l;
×
2421

UNCOV
2422
                        l = strcspn(arg_cipher, "-");
×
2423
                        truncated_cipher = strndup(arg_cipher, l);
×
2424
                        if (!truncated_cipher)
×
UNCOV
2425
                                return log_oom();
×
2426

UNCOV
2427
                        cipher = truncated_cipher;
×
UNCOV
2428
                        cipher_mode = arg_cipher[l] ? arg_cipher+l+1 : "plain";
×
2429
                } else {
2430
                        cipher = "aes";
2431
                        cipher_mode = "cbc-essiv:sha256";
2432
                }
2433

2434
                /* for CRYPT_PLAIN limit reads from keyfile to key length, and ignore keyfile-size */
2435
                arg_keyfile_size = arg_key_size;
×
2436

2437
                /* In contrast to what the name crypt_format() might suggest this doesn't actually format
2438
                 * anything, it just configures encryption parameters when used for plain mode. */
UNCOV
2439
                r = sym_crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, arg_keyfile_size, &params);
×
2440
                if (r < 0)
×
UNCOV
2441
                        return log_error_errno(r, "Loading of cryptographic parameters failed: %m");
×
2442

2443
                /* hash == NULL implies the user passed "plain" */
UNCOV
2444
                pass_volume_key = !params.hash;
×
2445
        }
2446

2447
        log_info("Set cipher %s, mode %s, key size %i bits for device %s.",
45✔
2448
                 sym_crypt_get_cipher(cd),
2449
                 sym_crypt_get_cipher_mode(cd),
2450
                 sym_crypt_get_volume_key_size(cd)*8,
2451
                 sym_crypt_get_device_name(cd));
2452

2453
        if (token_type == TOKEN_TPM2)
45✔
2454
                return attach_luks_or_plain_or_bitlk_by_tpm2(cd, name, key_file, key_data, until, flags, pass_volume_key);
13✔
2455
        if (token_type == TOKEN_FIDO2)
32✔
UNCOV
2456
                return attach_luks_or_plain_or_bitlk_by_fido2(cd, name, key_file, key_data, until, flags, pass_volume_key);
×
2457
        if (token_type == TOKEN_PKCS11)
32✔
2458
                return attach_luks_or_plain_or_bitlk_by_pkcs11(cd, name, key_file, key_data, until, flags, pass_volume_key);
1✔
2459
        if (key_data)
31✔
2460
                return attach_luks_or_plain_or_bitlk_by_key_data(cd, name, key_data, flags, pass_volume_key);
3✔
2461
        if (key_file)
28✔
2462
                return attach_luks_or_plain_or_bitlk_by_key_file(cd, name, key_file, flags, pass_volume_key);
28✔
2463

2464
        return attach_luks_or_plain_or_bitlk_by_passphrase(cd, name, passwords, flags, pass_volume_key);
×
2465
}
2466

UNCOV
2467
static int help(void) {
×
2468
        _cleanup_free_ char *link = NULL;
×
2469
        _cleanup_(table_unrefp) Table *options = NULL, *verbs = NULL;
×
2470
        int r;
×
2471

2472
        r = terminal_urlify_man("systemd-cryptsetup", "8", &link);
×
2473
        if (r < 0)
×
UNCOV
2474
                return log_oom();
×
2475

2476
        r = verbs_get_help_table(&verbs);
×
2477
        if (r < 0)
×
2478
                return r;
2479

2480
        r = option_parser_get_help_table(&options);
×
UNCOV
2481
        if (r < 0)
×
2482
                return r;
2483

UNCOV
2484
        (void) table_sync_column_widths(0, verbs, options);
×
2485

UNCOV
2486
        printf("%s [OPTIONS...] {COMMAND} ...\n\n"
×
2487
               "%sAttach or detach an encrypted block device.%s\n"
2488
               "\n%sCommands:%s\n",
2489
               program_invocation_short_name,
2490
               ansi_highlight(),
2491
               ansi_normal(),
2492
               ansi_underline(),
2493
               ansi_normal());
2494

2495
        r = table_print_or_warn(verbs);
×
UNCOV
2496
        if (r < 0)
×
2497
                return r;
2498

2499
        printf("\n%sOptions:%s\n",
×
2500
               ansi_underline(),
2501
               ansi_normal());
2502

2503
        r = table_print_or_warn(options);
×
UNCOV
2504
        if (r < 0)
×
2505
                return r;
2506

2507
        printf("\nSee the %s for details.\n", link);
×
2508
        return 0;
2509
}
2510

UNCOV
2511
VERB_COMMON_HELP_HIDDEN(help);
×
2512

2513
static int parse_argv(int argc, char *argv[], char ***ret_args) {
151✔
2514
        assert(argc >= 0);
151✔
2515
        assert(argv);
151✔
2516
        assert(ret_args);
151✔
2517

2518
        OptionParser opts = { argc, argv };
151✔
2519

2520
        FOREACH_OPTION_OR_RETURN(c, &opts)
151✔
UNCOV
2521
                switch (c) {
×
2522

2523
                OPTION_COMMON_HELP:
×
UNCOV
2524
                        return help();
×
2525

UNCOV
2526
                OPTION_COMMON_VERSION:
×
UNCOV
2527
                        return version();
×
2528
                }
2529

2530
        *ret_args = option_parser_get_args(&opts);
151✔
2531
        return 1;
151✔
2532
}
2533

2534
static uint32_t determine_flags(void) {
83✔
2535
        uint32_t flags = 0;
83✔
2536

2537
        if (arg_readonly)
83✔
UNCOV
2538
                flags |= CRYPT_ACTIVATE_READONLY;
×
2539

2540
        if (arg_discards)
83✔
UNCOV
2541
                flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
×
2542

2543
        if (arg_same_cpu_crypt)
83✔
UNCOV
2544
                flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;
×
2545

2546
        if (arg_submit_from_crypt_cpus)
83✔
UNCOV
2547
                flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
×
2548

2549
        if (arg_no_read_workqueue)
83✔
UNCOV
2550
                flags |= CRYPT_ACTIVATE_NO_READ_WORKQUEUE;
×
2551

2552
        if (arg_no_write_workqueue)
83✔
UNCOV
2553
                flags |= CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE;
×
2554

2555
        /* Try to decrease the risk of OOM event if memory hard key derivation function is in use */
2556
        /* https://gitlab.com/cryptsetup/cryptsetup/issues/446/ */
2557
        flags |= CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF;
83✔
2558

2559
        return flags;
83✔
2560
}
2561

2562
static void remove_and_erasep(const char **p) {
83✔
2563
        int r;
83✔
2564

2565
        assert(p);
83✔
2566

2567
        if (!*p)
83✔
2568
                return;
2569

2570
        r = unlinkat_deallocate(AT_FDCWD, *p, UNLINK_ERASE);
2✔
2571
        if (r < 0 && r != -ENOENT)
2✔
UNCOV
2572
                log_warning_errno(r, "Unable to erase key file '%s', ignoring: %m", *p);
×
2573
}
2574

2575
static TokenType determine_token_type(void) {
60✔
2576
        if (arg_tpm2_device || arg_tpm2_device_auto)
60✔
2577
                return TOKEN_TPM2;
2578
        if (arg_fido2_device || arg_fido2_device_auto)
47✔
2579
                return TOKEN_FIDO2;
2580
        if (arg_pkcs11_uri || arg_pkcs11_uri_auto)
47✔
2581
                return TOKEN_PKCS11;
1✔
2582

2583
        return _TOKEN_TYPE_INVALID;
2584
}
2585

2586
static int discover_key(const char *key_file, const char *volume, TokenType token_type, struct iovec *ret_key_data) {
17✔
2587
        _cleanup_free_ char *bindname = NULL;
17✔
2588
        const char *token_type_name;
17✔
2589
        int r;
17✔
2590

2591
        assert(key_file);
17✔
2592
        assert(volume);
17✔
2593
        assert(ret_key_data);
17✔
2594

2595
        bindname = make_bindname(volume, token_type);
17✔
2596
        if (!bindname)
17✔
UNCOV
2597
                return log_oom();
×
2598

2599
        /* If a key file is not explicitly specified, search for a key in a well defined search path, and load it. */
2600
        r = find_key_file(key_file, STRV_MAKE("/etc/cryptsetup-keys.d", "/run/cryptsetup-keys.d"), bindname, ret_key_data);
17✔
2601
        if (r <= 0)
17✔
2602
                return r;
2603

2604
        token_type_name = token_type_to_string(token_type);
1✔
2605
        if (token_type_name)
1✔
UNCOV
2606
                log_debug("Automatically discovered encrypted key for volume '%s' (token type: %s).", volume, token_type_name);
×
2607
        else
2608
                log_debug("Automatically discovered key for volume '%s'.", volume);
1✔
2609

2610
        return r;
2611
}
2612

2613
VERB(verb_attach, "attach", "VOLUME SOURCE-DEVICE [KEY-FILE] [CONFIG]", 3, 5, 0,
2614
     "Attach an encrypted block device");
2615
static int verb_attach(int argc, char *argv[], uintptr_t _data, void *userdata) {
83✔
2616
        _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
83✔
2617
        _unused_ _cleanup_(remove_and_erasep) const char *destroy_key_file = NULL;
83✔
2618
        crypt_status_info status;
83✔
2619
        uint32_t flags = 0;
83✔
2620
        unsigned tries;
83✔
2621
        usec_t until;
83✔
2622
        PassphraseType passphrase_type = PASSPHRASE_NONE;
83✔
2623
        int r;
83✔
2624

2625
        /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [KEY-FILE] [CONFIG] */
2626

2627
        assert(argc >= 3 && argc <= 5);
83✔
2628

2629
        const char *volume = ASSERT_PTR(argv[1]),
83✔
2630
                *source = ASSERT_PTR(argv[2]),
83✔
2631
                *key_file = argc >= 4 ? mangle_none(argv[3]) : NULL,
83✔
2632
                *config = argc >= 5 ? mangle_none(argv[4]) : NULL;
83✔
2633

2634
        if (!filename_is_valid(volume))
83✔
UNCOV
2635
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
×
2636

2637
        if (key_file && !path_is_absolute(key_file)) {
83✔
UNCOV
2638
                log_warning("Password file path '%s' is not absolute. Ignoring.", key_file);
×
2639
                key_file = NULL;
2640
        }
2641

2642
        if (config) {
83✔
2643
                r = parse_crypt_config(config);
81✔
2644
                if (r < 0)
81✔
2645
                        return r;
2646
        }
2647

2648
        log_debug("%s %s ← %s type=%s cipher=%s", __func__,
232✔
2649
                  volume, source, strempty(arg_type), strempty(arg_cipher));
2650

2651
        /* A delicious drop of snake oil */
2652
        (void) safe_mlockall(MCL_CURRENT|MCL_FUTURE|MCL_ONFAULT);
83✔
2653

2654
        /* Only erase key files explicitly configured on the command line, never the ones we
2655
         * auto-discover in /etc/cryptsetup-keys.d/ and /run/cryptsetup-keys.d/: those are shared
2656
         * resources not owned by an individual volume. (key_file is NULL when auto-discovery is used.) */
2657
        if (key_file && arg_keyfile_erase)
83✔
2658
                destroy_key_file = key_file; /* let's get this baby erased when we leave */
2✔
2659

2660
        if (arg_header) {
83✔
2661
                if (streq_ptr(arg_type, CRYPT_TCRYPT)){
9✔
UNCOV
2662
                        log_debug("tcrypt header: %s", arg_header);
×
UNCOV
2663
                        r = sym_crypt_init_data_device(&cd, arg_header, source);
×
2664
                } else {
2665
                        log_debug("LUKS header: %s", arg_header);
9✔
2666
                        r = sym_crypt_init(&cd, arg_header);
9✔
2667
                }
2668
        } else
2669
                r = sym_crypt_init(&cd, source);
74✔
2670
        if (r < 0)
83✔
UNCOV
2671
                return log_error_errno(r, "crypt_init() failed: %m");
×
2672

2673
        cryptsetup_enable_logging(cd);
83✔
2674

2675
        status = sym_crypt_status(cd, volume);
83✔
2676
        if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) {
83✔
UNCOV
2677
                log_info("Volume %s already active.", volume);
×
2678
                return 0;
2679
        }
2680

2681
        flags = determine_flags();
83✔
2682

2683
        until = usec_add(now(CLOCK_MONOTONIC), arg_timeout);
83✔
UNCOV
2684
        if (until == USEC_INFINITY)
×
2685
                until = 0;
83✔
2686

2687
        if (arg_key_size == 0)
83✔
2688
                arg_key_size = 256U / 8U;
83✔
2689

2690
        if (key_file) {
83✔
2691
                struct stat st;
28✔
2692

2693
                /* Ideally we'd do this on the open fd, but since this is just a warning it's OK to do this
2694
                 * in two steps. */
2695
                if (stat(key_file, &st) >= 0 && S_ISREG(st.st_mode) && (st.st_mode & 0005))
28✔
2696
                        log_warning("Key file %s is world-readable. This is not a good idea!", key_file);
6✔
2697
        }
2698

2699
        if (!arg_type || STR_IN_SET(arg_type, ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2)) {
83✔
2700
                r = sym_crypt_load(cd, !arg_type || streq(arg_type, ANY_LUKS) ? CRYPT_LUKS : arg_type, NULL);
83✔
2701
                if (r < 0)
83✔
2702
                        return log_error_errno(r, "Failed to load LUKS superblock on device %s: %m", sym_crypt_get_device_name(cd));
38✔
2703

2704
                /* since cryptsetup 2.7.0 (Jan 2024) */
2705
                if (arg_link_key_description) {
83✔
2706
                        r = sym_crypt_set_keyring_to_link(cd, arg_link_key_description, NULL, arg_link_key_type, arg_link_keyring);
×
UNCOV
2707
                        if (r == -ENOSYS)
×
UNCOV
2708
                                log_warning("Loaded libcryptsetup does not support linking volume keys in user specified kernel keyrings upon device activation, ignoring.");
×
UNCOV
2709
                        else if (r < 0)
×
UNCOV
2710
                                log_warning_errno(r, "Failed to set keyring or key description to link volume key in, ignoring: %m");
×
2711
                }
2712

2713
                if (arg_header) {
83✔
2714
                        r = sym_crypt_set_data_device(cd, source);
9✔
2715
                        if (r < 0)
9✔
UNCOV
2716
                                return log_error_errno(r, "Failed to set LUKS data device %s: %m", source);
×
2717
                }
2718

2719
                /* Tokens are available in LUKS2 only, but it is ok to call (and fail) with LUKS1. */
2720
                if (!key_file && use_token_plugins()) {
83✔
2721
                        r = crypt_activate_by_token_pin_ask_password(
53✔
2722
                                        cd,
2723
                                        volume,
2724
                                        /* type= */ NULL,
2725
                                        until,
2726
                                        /* userdata= */ NULL,
2727
                                        flags,
2728
                                        "Please enter LUKS2 token PIN:",
2729
                                        "luks2-pin",
2730
                                        "cryptsetup.luks2-pin");
2731
                        if (r >= 0) {
53✔
2732
                                log_debug("Volume %s activated with a LUKS token.", volume);
38✔
2733
                                return 0;
2734
                        }
2735

2736
                        log_debug_errno(r, "Token activation unsuccessful for device %s: %m", sym_crypt_get_device_name(cd));
15✔
2737
                }
2738
        }
2739

2740
        if (streq_ptr(arg_type, CRYPT_BITLK)) {
45✔
UNCOV
2741
                r = sym_crypt_load(cd, CRYPT_BITLK, NULL);
×
UNCOV
2742
                if (r < 0)
×
UNCOV
2743
                        return log_error_errno(r, "Failed to load Bitlocker superblock on device %s: %m", sym_crypt_get_device_name(cd));
×
2744
        }
2745

2746
        bool use_cached_passphrase = true, try_discover_key = !key_file;
45✔
2747
        const char *discovered_key_fn = strjoina(volume, ".key");
225✔
2748
        _cleanup_strv_free_erase_ char **passwords = NULL;
45✔
2749
        for (tries = 0; arg_tries == 0 || tries < arg_tries; tries++) {
60✔
2750
                _cleanup_(iovec_done_erase) struct iovec discovered_key_data = {};
60✔
2751
                const struct iovec *key_data = NULL;
60✔
2752
                TokenType token_type = determine_token_type();
60✔
2753

2754
                log_debug("Beginning attempt %u to unlock.", tries);
60✔
2755

2756
                /* When we were able to acquire multiple keys, let's always process them in this order:
2757
                 *
2758
                 *    1. A key acquired via PKCS#11 or FIDO2 token, or TPM2 chip
2759
                 *    2. The configured or discovered key, of which both are exclusive and optional
2760
                 *    3. The empty password, in case arg_try_empty_password is set
2761
                 *    4. We enquire the user for a password
2762
                 */
2763

2764
                if (try_discover_key) {
60✔
2765
                        r = discover_key(discovered_key_fn, volume, token_type, &discovered_key_data);
17✔
2766
                        if (r < 0)
17✔
2767
                                return r;
2768
                        if (r > 0)
17✔
2769
                                key_data = &discovered_key_data;
2770
                        else
2771
                                try_discover_key = false;
16✔
2772
                }
2773

2774
                if (token_type < 0 && !key_file && !key_data && !passwords) {
60✔
2775

2776
                        /* If we have nothing to try anymore, then acquire a new password */
2777

2778
                        if (arg_try_empty_password) {
17✔
2779
                                /* Hmm, let's try an empty password now, but only once */
2780
                                arg_try_empty_password = false;
2✔
2781
                                key_data = &iovec_empty;
2✔
2782
                        } else {
2783
                                /* Ask the user for a passphrase or recovery key only as last resort, if we
2784
                                 * have nothing else to check for */
2785
                                if (passphrase_type == PASSPHRASE_NONE) {
15✔
2786
                                        passphrase_type = check_registered_passwords(cd);
15✔
2787
                                        if (passphrase_type == PASSPHRASE_NONE)
15✔
UNCOV
2788
                                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No passphrase or recovery key registered.");
×
2789
                                }
2790

2791
                                r = get_password(
15✔
2792
                                                volume,
2793
                                                source,
2794
                                                until,
2795
                                                /* ignore_cached= */ !use_cached_passphrase || arg_verify,
15✔
2796
                                                passphrase_type,
2797
                                                &passwords);
2798
                                use_cached_passphrase = false;
15✔
2799
                                if (r == -EAGAIN)
15✔
UNCOV
2800
                                        continue;
×
2801
                                if (r < 0)
15✔
2802
                                        return r;
2803
                        }
2804
                }
2805

2806
                if (streq_ptr(arg_type, CRYPT_TCRYPT))
45✔
UNCOV
2807
                        r = attach_tcrypt(cd, volume, token_type, key_file, key_data, passwords, flags);
×
2808
                else
2809
                        r = attach_luks_or_plain_or_bitlk(cd, volume, token_type, key_file, key_data, passwords, flags, until);
45✔
2810
                if (r >= 0)
45✔
2811
                        break;
2812
                if (r != -EAGAIN)
18✔
2813
                        return r;
2814

2815
                /* Key not correct? Let's try again, but let's invalidate one of the passed fields, so that
2816
                 * we fall back to the next best thing. */
2817

2818
                if (token_type == TOKEN_TPM2) {
15✔
2819
                        arg_tpm2_device = mfree(arg_tpm2_device);
11✔
2820
                        arg_tpm2_device_auto = false;
11✔
2821
                        continue;
11✔
2822
                }
2823

2824
                if (token_type == TOKEN_FIDO2) {
4✔
UNCOV
2825
                        arg_fido2_device = mfree(arg_fido2_device);
×
UNCOV
2826
                        arg_fido2_device_auto = false;
×
2827
                        continue;
×
2828
                }
2829

2830
                if (token_type == TOKEN_PKCS11) {
4✔
UNCOV
2831
                        arg_pkcs11_uri = mfree(arg_pkcs11_uri);
×
UNCOV
2832
                        arg_pkcs11_uri_auto = false;
×
2833
                        continue;
×
2834
                }
2835

2836
                if (try_discover_key) {
4✔
UNCOV
2837
                        try_discover_key = false;
×
UNCOV
2838
                        continue;
×
2839
                }
2840

2841
                if (key_file) {
4✔
2842
                        key_file = NULL;
4✔
2843
                        continue;
4✔
2844
                }
2845

UNCOV
2846
                if (passwords) {
×
2847
                        passwords = strv_free_erase(passwords);
×
UNCOV
2848
                        continue;
×
2849
                }
2850

2851
                log_debug("Prepared for next attempt to unlock.");
×
2852
        }
2853

2854
        if (arg_tries != 0 && tries >= arg_tries)
27✔
UNCOV
2855
                return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Too many attempts to activate; giving up.");
×
2856

2857
        return 0;
2858
}
2859

2860
VERB(verb_detach, "detach", "VOLUME", 2, 2, 0,
2861
     "Detach an encrypted block device");
2862
static int verb_detach(int argc, char *argv[], uintptr_t _data, void *userdata) {
68✔
2863
        _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
68✔
2864
        const char *volume = ASSERT_PTR(argv[1]);
68✔
2865
        int r;
68✔
2866

2867
        assert(argc == 2);
68✔
2868

2869
        if (!filename_is_valid(volume))
68✔
UNCOV
2870
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
×
2871

2872
        r = sym_crypt_init_by_name(&cd, volume);
68✔
2873
        if (r == -ENODEV) {
68✔
2874
                log_info("Volume %s already inactive.", volume);
3✔
2875
                return 0;
2876
        }
2877
        if (r < 0)
65✔
UNCOV
2878
                return log_error_errno(r, "crypt_init_by_name() for volume '%s' failed: %m", volume);
×
2879

2880
        cryptsetup_enable_logging(cd);
65✔
2881

2882
        r = sym_crypt_deactivate(cd, volume);
65✔
2883
        if (r < 0)
65✔
UNCOV
2884
                return log_error_errno(r, "Failed to deactivate '%s': %m", volume);
×
2885

2886
        return 0;
2887
}
2888

2889
static int run(int argc, char *argv[]) {
151✔
2890
        int r;
151✔
2891

2892
        LIBBLKID_NOTE(recommended);
151✔
2893
        LIBFIDO2_NOTE(suggested);
151✔
2894
        LIBMOUNT_NOTE(recommended);
151✔
2895
        LIBP11KIT_NOTE(suggested);
151✔
2896
        TPM2_NOTE(suggested);
151✔
2897

2898
        log_setup();
151✔
2899

2900
        umask(0022);
151✔
2901

2902
        char **args = NULL;
151✔
2903
        r = parse_argv(argc, argv, &args);
151✔
2904
        if (r <= 0)
151✔
2905
                return r;
151✔
2906

2907
        r = DLOPEN_CRYPTSETUP(LOG_ERR, required);
151✔
2908
        if (r < 0)
151✔
2909
                return r;
2910

2911
        return dispatch_verb(args, NULL);
151✔
2912
}
2913

2914
DEFINE_MAIN_FUNCTION(run);
151✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc