#include "cryptsetup-tpm2.h"
#include "cryptsetup-util.h"
#include "device-util.h"
-#include "efi-loader.h"
+#include "efi-api.h"
#include "env-util.h"
#include "escape.h"
#include "fileio.h"
#include "path-util.h"
#include "pkcs11-util.h"
#include "pretty-print.h"
+#include "process-util.h"
#include "random-util.h"
-#include "string-util.h"
+#include "string-table.h"
#include "strv.h"
#include "tpm2-util.h"
/* internal helper */
#define ANY_LUKS "LUKS"
/* as in src/cryptsetup.h */
-#define CRYPT_SECTOR_SIZE 512
-#define CRYPT_MAX_SECTOR_SIZE 4096
+#define CRYPT_SECTOR_SIZE 512U
+#define CRYPT_MAX_SECTOR_SIZE 4096U
+
+typedef enum PassphraseType {
+ PASSPHRASE_NONE,
+ PASSPHRASE_REGULAR = 1 << 0,
+ PASSPHRASE_RECOVERY_KEY = 1 << 1,
+ PASSPHRASE_BOTH = PASSPHRASE_REGULAR|PASSPHRASE_RECOVERY_KEY,
+ _PASSPHRASE_TYPE_MAX,
+ _PASSPHRASE_TYPE_INVALID = -1,
+} PassphraseType;
static const char *arg_type = NULL; /* ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2, CRYPT_TCRYPT, CRYPT_BITLK or CRYPT_PLAIN */
static char *arg_cipher = NULL;
static char *arg_tpm2_device = NULL;
static bool arg_tpm2_device_auto = false;
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
+static char *arg_tpm2_signature = NULL;
+static bool arg_tpm2_pin = false;
static bool arg_headless = false;
static usec_t arg_token_timeout_usec = 30*USEC_PER_SEC;
STATIC_DESTRUCTOR_REGISTER(arg_fido2_cid, freep);
STATIC_DESTRUCTOR_REGISTER(arg_fido2_rp_id, freep);
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep);
+
+static const char* const passphrase_type_table[_PASSPHRASE_TYPE_MAX] = {
+ [PASSPHRASE_REGULAR] = "passphrase",
+ [PASSPHRASE_RECOVERY_KEY] = "recovery key",
+ [PASSPHRASE_BOTH] = "passphrase or recovery key",
+};
+
+const char* passphrase_type_to_string(PassphraseType t);
+PassphraseType passphrase_type_from_string(const char *s);
+
+DEFINE_STRING_TABLE_LOOKUP(passphrase_type, PassphraseType);
/* Options Debian's crypttab knows we don't:
} else if ((val = startswith(option, "tpm2-pcrs="))) {
- if (isempty(val))
- arg_tpm2_pcr_mask = 0;
- else {
- uint32_t mask;
+ r = tpm2_parse_pcr_argument(val, &arg_tpm2_pcr_mask);
+ if (r < 0)
+ return r;
- r = tpm2_parse_pcrs(val, &mask);
- if (r < 0)
- return r;
+ } else if ((val = startswith(option, "tpm2-signature="))) {
- if (arg_tpm2_pcr_mask == UINT32_MAX)
- arg_tpm2_pcr_mask = mask;
- else
- arg_tpm2_pcr_mask |= mask;
+ if (!path_is_absolute(val))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "TPM2 signature path \"%s\" is not absolute, refusing.", val);
+
+ r = free_and_strdup(&arg_tpm2_signature, val);
+ if (r < 0)
+ return log_oom();
+
+ } else if ((val = startswith(option, "tpm2-pin="))) {
+
+ r = parse_boolean(val);
+ if (r < 0) {
+ log_error_errno(r, "Failed to parse %s, ignoring: %m", option);
+ return 0;
}
+ arg_tpm2_pin = r;
+
} else if ((val = startswith(option, "try-empty-password="))) {
r = parse_boolean(val);
"ID_MODEL\0";
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
- const char *i, *name;
+ const char *name;
struct stat st;
assert(path);
return name_buffer;
}
+static PassphraseType check_registered_passwords(struct crypt_device *cd) {
+ _cleanup_free_ bool *slots = NULL;
+ int slot_max;
+ PassphraseType passphrase_type = PASSPHRASE_NONE;
+
+ assert(cd);
+
+ if (!streq_ptr(crypt_get_type(cd), CRYPT_LUKS2)) {
+ log_debug("%s: not a LUKS2 device, only passphrases are supported", crypt_get_device_name(cd));
+ return PASSPHRASE_REGULAR;
+ }
+
+ /* Search all used slots */
+ assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
+ slots = new(bool, slot_max);
+ if (!slots)
+ return log_oom();
+
+ for (int slot = 0; slot < slot_max; slot++)
+ slots[slot] = IN_SET(crypt_keyslot_status(cd, slot), CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST);
+
+ /* Iterate all LUKS2 tokens and keep track of all their slots */
+ for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
+ _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+ const char *type;
+ JsonVariant *w, *z;
+ int tk;
+
+ tk = cryptsetup_get_token_as_json(cd, token, NULL, &v);
+ if (IN_SET(tk, -ENOENT, -EINVAL))
+ continue;
+ if (tk < 0) {
+ log_warning_errno(tk, "Failed to read JSON token data, ignoring: %m");
+ continue;
+ }
+
+ w = json_variant_by_key(v, "type");
+ if (!w || !json_variant_is_string(w)) {
+ log_warning("Token JSON data lacks type field, ignoring.");
+ continue;
+ }
+
+ type = json_variant_string(w);
+ if (STR_IN_SET(type, "systemd-recovery", "systemd-pkcs11", "systemd-fido2", "systemd-tpm2")) {
+
+ /* At least exists one recovery key */
+ if (streq(type, "systemd-recovery"))
+ passphrase_type |= PASSPHRASE_RECOVERY_KEY;
+
+ w = json_variant_by_key(v, "keyslots");
+ if (!w || !json_variant_is_array(w)) {
+ log_warning("Token JSON data lacks keyslots field, ignoring.");
+ continue;
+ }
+
+ JSON_VARIANT_ARRAY_FOREACH(z, w) {
+ unsigned u;
+ int at;
+
+ if (!json_variant_is_string(z)) {
+ log_warning("Token JSON data's keyslot field is not an array of strings, ignoring.");
+ continue;
+ }
+
+ at = safe_atou(json_variant_string(z), &u);
+ if (at < 0) {
+ log_warning_errno(at, "Token JSON data's keyslot field is not an integer formatted as string, ignoring.");
+ continue;
+ }
+
+ if (u >= (unsigned) slot_max) {
+ log_warning_errno(at, "Token JSON data's keyslot field exceeds the maximum value allowed, ignoring.");
+ continue;
+ }
+
+ slots[u] = false;
+ }
+ }
+ }
+
+ /* Check if any of the slots is not referenced by systemd tokens */
+ for (int slot = 0; slot < slot_max; slot++)
+ if (slots[slot]) {
+ passphrase_type |= PASSPHRASE_REGULAR;
+ break;
+ }
+
+ /* All the slots are referenced by systemd tokens, so if a recovery key is not enrolled,
+ * we will not be able to enter a passphrase. */
+ return passphrase_type;
+}
+
static int get_password(
const char *vol,
const char *src,
usec_t until,
bool accept_cached,
+ PassphraseType passphrase_type,
char ***ret) {
_cleanup_free_ char *friendly = NULL, *text = NULL, *disk_path = NULL;
_cleanup_strv_free_erase_ char **passwords = NULL;
- char **p, *id;
+ char *id;
int r = 0;
AskPasswordFlags flags = arg_ask_password_flags | ASK_PASSWORD_PUSH_CACHE;
if (!friendly)
return log_oom();
- if (asprintf(&text, "Please enter passphrase for disk %s:", friendly) < 0)
+ if (asprintf(&text, "Please enter %s for disk %s:", passphrase_type_to_string(passphrase_type), friendly) < 0)
return log_oom();
disk_path = cescape(src);
assert(strv_length(passwords) == 1);
- if (asprintf(&text, "Please enter passphrase for disk %s (verification):", friendly) < 0)
+ if (asprintf(&text, "Please enter %s for disk %s (verification):", passphrase_type_to_string(passphrase_type), friendly) < 0)
return log_oom();
id = strjoina("cryptsetup-verification:", disk_path);
if (r < 0)
return log_error_errno(r, "Failed to allocate device monitor: %m");
+ (void) sd_device_monitor_set_description(monitor, "security-device");
+
r = sd_device_monitor_filter_add_match_tag(monitor, "security-device");
if (r < 0)
return log_error_errno(r, "Failed to configure device monitor: %m");
#if HAVE_LIBCRYPTSETUP_PLUGINS
static int acquire_pins_from_env_variable(char ***ret_pins) {
- char *e;
+ _cleanup_(erase_and_freep) char *envpin = NULL;
_cleanup_strv_free_erase_ char **pins = NULL;
+ int r;
assert(ret_pins);
- e = getenv("PIN");
- if (e) {
- pins = strv_new(e);
+ r = getenv_steal_erase("PIN", &envpin);
+ if (r < 0)
+ return log_error_errno(r, "Failed to acquire PIN from environment: %m");
+ if (r > 0) {
+ pins = strv_new(envpin);
if (!pins)
return log_oom();
-
- string_erase(e);
- if (unsetenv("PIN") < 0)
- return log_error_errno(errno, "Failed to unset $PIN: %m");
}
*ret_pins = TAKE_PTR(pins);
}
#endif
-static int attach_luks2_by_fido2(
+static int crypt_activate_by_token_pin_ask_password(
struct crypt_device *cd,
const char *name,
+ const char *type,
usec_t until,
bool headless,
void *usrptr,
- uint32_t activation_flags) {
+ uint32_t activation_flags,
+ const char *message,
+ const char *key_name,
+ const char *credential_name) {
#if HAVE_LIBCRYPTSETUP_PLUGINS
AskPasswordFlags flags = ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_ACCEPT_CACHED;
_cleanup_strv_free_erase_ char **pins = NULL;
- char **p;
int r;
- r = crypt_activate_by_token_pin(cd, name, "systemd-fido2", CRYPT_ANY_TOKEN, NULL, 0, usrptr, activation_flags);
+ r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, NULL, 0, usrptr, activation_flags);
if (r > 0) /* returns unlocked keyslot id on success */
r = 0;
if (r != -ENOANO) /* needs pin or pin is wrong */
return r;
STRV_FOREACH(p, pins) {
- r = crypt_activate_by_token_pin(cd, name, "systemd-fido2", CRYPT_ANY_TOKEN, *p, strlen(*p), usrptr, activation_flags);
+ r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), usrptr, activation_flags);
if (r > 0) /* returns unlocked keyslot id on success */
r = 0;
if (r != -ENOANO) /* needs pin or pin is wrong */
for (;;) {
pins = strv_free_erase(pins);
- r = ask_password_auto("Please enter security token PIN:", "drive-harddisk", NULL, "fido2-pin", "cryptsetup.fido2-pin", until, flags, &pins);
+ r = ask_password_auto(message, "drive-harddisk", NULL, key_name, credential_name, until, flags, &pins);
if (r < 0)
return r;
STRV_FOREACH(p, pins) {
- r = crypt_activate_by_token_pin(cd, name, "systemd-fido2", CRYPT_ANY_TOKEN, *p, strlen(*p), usrptr, activation_flags);
+ r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), usrptr, activation_flags);
if (r > 0) /* returns unlocked keyslot id on success */
r = 0;
if (r != -ENOANO) /* needs pin or pin is wrong */
#endif
}
+static int attach_luks2_by_fido2_via_plugin(
+ struct crypt_device *cd,
+ const char *name,
+ usec_t until,
+ bool headless,
+ void *usrptr,
+ uint32_t activation_flags) {
+
+ return crypt_activate_by_token_pin_ask_password(
+ cd,
+ name,
+ "systemd-fido2",
+ until,
+ headless,
+ usrptr,
+ activation_flags,
+ "Please enter security token PIN:",
+ "fido2-pin",
+ "cryptsetup.fido2-pin");
+}
+
static int attach_luks_or_plain_or_bitlk_by_fido2(
struct crypt_device *cd,
const char *name,
for (;;) {
if (use_libcryptsetup_plugin && !arg_fido2_cid) {
- r = attach_luks2_by_fido2(cd, name, until, arg_headless, arg_fido2_device, flags);
+ r = attach_luks2_by_fido2_via_plugin(cd, name, until, arg_headless, arg_fido2_device, flags);
if (IN_SET(r, -ENOTUNIQ, -ENXIO, -ENOENT))
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
"Automatic FIDO2 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking.");
return 0;
}
-static int attach_luks2_by_pkcs11(
+static int attach_luks2_by_pkcs11_via_plugin(
struct crypt_device *cd,
const char *name,
const char *friendly_name,
for (;;) {
if (use_libcryptsetup_plugin && arg_pkcs11_uri_auto)
- r = attach_luks2_by_pkcs11(cd, name, friendly, until, arg_headless, flags);
+ r = attach_luks2_by_pkcs11_via_plugin(cd, name, friendly, until, arg_headless, flags);
else {
r = decrypt_pkcs11_key(
name,
/* Before using this key as passphrase we base64 encode it. Why? For compatibility
* with homed's PKCS#11 hookup: there we want to use the key we acquired through
* PKCS#11 for other authentication/decryption mechanisms too, and some of them do
- * not not take arbitrary binary blobs, but require NUL-terminated strings — most
+ * not take arbitrary binary blobs, but require NUL-terminated strings — most
* importantly UNIX password hashes. Hence, for compatibility we want to use a string
* without embedded NUL here too, and that's easiest to generate from a binary blob
* via base64 encoding. */
if (r < 0)
return log_error_errno(r, "Failed to allocate device monitor: %m");
+ (void) sd_device_monitor_set_description(monitor, "tpmrm");
+
r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, "tpmrm", NULL);
if (r < 0)
return log_error_errno(r, "Failed to configure device monitor: %m");
return 0;
}
-static int attach_luks2_by_tpm2(
+static int attach_luks2_by_tpm2_via_plugin(
struct crypt_device *cd,
const char *name,
+ usec_t until,
+ bool headless,
uint32_t flags) {
#if HAVE_LIBCRYPTSETUP_PLUGINS
- int r;
-
systemd_tpm2_plugin_params params = {
.search_pcr_mask = arg_tpm2_pcr_mask,
- .device = arg_tpm2_device
+ .device = arg_tpm2_device,
+ .signature_path = arg_tpm2_signature,
};
- if (!crypt_token_external_path())
+ if (!libcryptsetup_plugins_support())
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Libcryptsetup has external plugins support disabled.");
- r = crypt_activate_by_token_pin(cd, name, "systemd-tpm2", CRYPT_ANY_TOKEN, NULL, 0, ¶ms, flags);
- if (r > 0) /* returns unlocked keyslot id on success */
- r = 0;
-
- return r;
+ return crypt_activate_by_token_pin_ask_password(
+ cd,
+ name,
+ "systemd-tpm2",
+ until,
+ headless,
+ ¶ms,
+ flags,
+ "Please enter TPM2 PIN:",
+ "tpm2-pin",
+ "cryptsetup.tpm2-pin");
#else
return -EOPNOTSUPP;
#endif
arg_tpm2_device,
arg_tpm2_pcr_mask == UINT32_MAX ? TPM2_PCR_MASK_DEFAULT : arg_tpm2_pcr_mask,
UINT16_MAX,
- 0,
+ /* pubkey= */ NULL, /* pubkey_size= */ 0,
+ /* pubkey_pcr_mask= */ 0,
+ /* signature_path= */ NULL,
+ /* primary_alg= */ 0,
key_file, arg_keyfile_size, arg_keyfile_offset,
key_data, key_data_size,
- NULL, 0, /* we don't know the policy hash */
+ /* policy_hash= */ NULL, /* policy_hash_size= */ 0, /* we don't know the policy hash */
+ arg_tpm2_pin ? TPM2_FLAGS_USE_PIN : 0,
+ until,
+ arg_headless,
+ arg_ask_password_flags,
&decrypted_key, &decrypted_key_size);
if (r >= 0)
break;
+ if (IN_SET(r, -EACCES, -ENOLCK))
+ return log_error_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed, falling back to traditional unlocking.");
if (ERRNO_IS_NOT_SUPPORTED(r)) /* TPM2 support not compiled in? */
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 support not available, falling back to traditional unlocking.");
- if (r != -EAGAIN) /* EAGAIN means: no tpm2 chip found */
- return r;
+ /* EAGAIN means: no tpm2 chip found */
+ if (r != -EAGAIN) {
+ log_notice_errno(r, "TPM2 operation failed, falling back to traditional unlocking: %m");
+ return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */
+ }
} else {
- r = attach_luks2_by_tpm2(cd, name, flags);
+ r = attach_luks2_by_tpm2_via_plugin(cd, name, until, arg_headless, flags);
+ if (r >= 0)
+ return 0;
/* EAGAIN means: no tpm2 chip found
* EOPNOTSUPP means: no libcryptsetup plugins support */
if (r == -ENXIO)
- return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
- "No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking.");
+ return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking.");
if (r == -ENOENT)
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
"No TPM2 metadata enrolled in LUKS2 header or TPM2 support not available, falling back to traditional unlocking.");
- if (!IN_SET(r, -EOPNOTSUPP, -EAGAIN))
- return r;
+ if (!IN_SET(r, -EOPNOTSUPP, -EAGAIN)) {
+ log_notice_errno(r, "TPM2 operation failed, falling back to traditional unlocking: %m");
+ return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */
+ }
}
- if (r == -EOPNOTSUPP) {
+ if (r == -EOPNOTSUPP) { /* Plugin not available, let's process TPM2 stuff right here instead */
_cleanup_free_ void *blob = NULL, *policy_hash = NULL;
size_t blob_size, policy_hash_size;
bool found_some = false;
* works. */
for (;;) {
- uint32_t pcr_mask;
+ _cleanup_free_ void *pubkey = NULL;
+ size_t pubkey_size = 0;
+ uint32_t hash_pcr_mask, pubkey_pcr_mask;
uint16_t pcr_bank, primary_alg;
+ TPM2Flags tpm2_flags;
r = find_tpm2_auto_data(
cd,
arg_tpm2_pcr_mask, /* if != UINT32_MAX we'll only look for tokens with this PCR mask */
token, /* search for the token with this index, or any later index than this */
- &pcr_mask,
+ &hash_pcr_mask,
&pcr_bank,
+ &pubkey, &pubkey_size,
+ &pubkey_pcr_mask,
&primary_alg,
&blob, &blob_size,
&policy_hash, &policy_hash_size,
+ &tpm2_flags,
&keyslot,
&token);
if (r == -ENXIO)
/* No further TPM2 tokens found in the LUKS2 header. */
- return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
- found_some
- ? "No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking."
- : "No TPM2 metadata enrolled in LUKS2 header, falling back to traditional unlocking.");
+ return log_full_errno(found_some ? LOG_NOTICE : LOG_DEBUG,
+ SYNTHETIC_ERRNO(EAGAIN),
+ found_some
+ ? "No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking."
+ : "No TPM2 metadata enrolled in LUKS2 header, falling back to traditional unlocking.");
if (ERRNO_IS_NOT_SUPPORTED(r)) /* TPM2 support not compiled in? */
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 support not available, falling back to traditional unlocking.");
if (r < 0)
r = acquire_tpm2_key(
name,
arg_tpm2_device,
- pcr_mask,
+ hash_pcr_mask,
pcr_bank,
+ pubkey, pubkey_size,
+ pubkey_pcr_mask,
+ arg_tpm2_signature,
primary_alg,
- NULL, 0, 0, /* no key file */
+ /* key_file= */ NULL, /* key_file_size= */ 0, /* key_file_offset= */ 0, /* no key file */
blob, blob_size,
policy_hash, policy_hash_size,
+ tpm2_flags,
+ until,
+ arg_headless,
+ arg_ask_password_flags,
&decrypted_key, &decrypted_key_size);
+ if (IN_SET(r, -EACCES, -ENOLCK))
+ return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed, falling back to traditional unlocking.");
if (r != -EPERM)
break;
if (r >= 0)
break;
- if (r != -EAGAIN) /* EAGAIN means: no tpm2 chip found */
- return r;
+ /* EAGAIN means: no tpm2 chip found */
+ if (r != -EAGAIN) {
+ log_notice_errno(r, "TPM2 operation failed, falling back to traditional unlocking: %m");
+ return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */
+ }
}
if (!monitor) {
if (is_efi_boot() && !efi_has_tpm2())
return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN),
- "No TPM2 hardware discovered and EFI bios indicates no support for it either, assuming TPM2-less system, falling back to traditional unocking.");
+ "No TPM2 hardware discovered and EFI firmware does not see it either, falling back to traditional unlocking.");
r = make_tpm2_device_monitor(&event, &monitor);
if (r < 0)
uint32_t flags,
bool pass_volume_key) {
- char **p;
int r;
assert(cd);
if (r < 0)
return log_oom();
- printf("%s attach VOLUME SOURCEDEVICE [PASSWORD] [OPTIONS]\n"
+ printf("%s attach VOLUME SOURCEDEVICE [KEY-FILE] [OPTIONS]\n"
"%s detach VOLUME\n\n"
"Attaches or detaches an encrypted block device.\n"
"\nSee the %s for details.\n",
const char *verb;
int r;
- if (argc <= 1)
+ if (argv_looks_like_help(argc, argv))
return help();
if (argc < 3)
uint32_t flags = 0;
unsigned tries;
usec_t until;
+ PassphraseType passphrase_type = PASSPHRASE_NONE;
- /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */
+ /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [KEY-FILE] [OPTIONS] */
if (argc < 4)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach requires at least two arguments.");
volume = argv[2];
source = argv[3];
- key_file = argc >= 5 && !STR_IN_SET(argv[4], "", "-", "none") ? argv[4] : NULL;
- options = argc >= 6 && !STR_IN_SET(argv[5], "", "-", "none") ? argv[5] : NULL;
+ key_file = mangle_none(argc >= 5 ? argv[4] : NULL);
+ options = mangle_none(argc >= 6 ? argv[5] : NULL);
if (!filename_is_valid(volume))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
if (until == USEC_INFINITY)
until = 0;
- arg_key_size = (arg_key_size > 0 ? arg_key_size : (256 / 8));
+ if (arg_key_size == 0)
+ arg_key_size = 256U / 8U;
if (key_file) {
struct stat st;
}
/* Tokens are available in LUKS2 only, but it is ok to call (and fail) with LUKS1. */
- if (!key_file && !key_data) {
- r = crypt_activate_by_token(cd, volume, CRYPT_ANY_TOKEN, NULL, flags);
+ if (!key_file && !key_data && getenv_bool("SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE") != 0) {
+ r = crypt_activate_by_token_pin_ask_password(
+ cd,
+ volume,
+ NULL,
+ until,
+ arg_headless,
+ NULL,
+ flags,
+ "Please enter LUKS2 token PIN:",
+ "luks2-pin",
+ "cryptsetup.luks2-pin");
if (r >= 0) {
log_debug("Volume %s activated with LUKS token id %i.", volume, r);
return 0;
key_data_size = 0;
} else {
- /* Ask the user for a passphrase only as last resort, if we have
+ /* Ask the user for a passphrase or recovery key only as last resort, if we have
* nothing else to check for */
+ if (passphrase_type == PASSPHRASE_NONE) {
+ passphrase_type = check_registered_passwords(cd);
+ if (passphrase_type == PASSPHRASE_NONE)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No passphrase or recovery key registered.");
+ }
- r = get_password(volume, source, until, tries == 0 && !arg_verify, &passwords);
+ r = get_password(volume, source, until, tries == 0 && !arg_verify, passphrase_type, &passwords);
if (r == -EAGAIN)
continue;
if (r < 0)