cryptsetup: manual FIDO2 PIN, UP and UV configuration

When in FIDO2 mode with manual parameters, i.e. when not reading the
parameters off the LUKS2 header, the current behavior in regards to PIN,
UP and UV features is to default to v248 logic, where we use PIN + UP
when needed, and do not configure UV at all. Let's allow users to
configure those features in manual mode too.
This commit is contained in:
Kamil Szczęk 2024-06-07 16:48:41 +02:00 committed by Lennart Poettering
parent 7cddd19236
commit d5fa6e6ca7
2 changed files with 80 additions and 23 deletions

View File

@ -768,6 +768,41 @@
<xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry>
<varlistentry>
<term><option>fido2-pin=</option></term>
<listitem><para>Controls whether to require the user to enter a PIN when unlocking the volume (the
FIDO2 <literal>clientPin</literal> feature). This option only applies when in manual mode, i.e.
when <option>fido2-cid=</option> option is set. Defaults to neither true or false, but rather to
<constant>v248</constant> behavior, that is: try with no PIN first, but if token reports that PIN
is required, try again asking for PIN.</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<varlistentry>
<term><option>fido2-up=</option></term>
<listitem><para>Controls whether to require the user to verify presence (tap the token, the FIDO2
<literal>up</literal> feature) when unlocking the volume. This option only applies when in manual
mode, i.e. when <option>fido2-cid=</option> option is set. Defaults to neither true or false,
but rather to <constant>v248</constant> behavior, that is: try with no UP first, but if token reports
that UP is required, try again with UP enabled.</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<varlistentry>
<term><option>fido2-uv=</option></term>
<listitem><para>Controls whether to require user verification (the FIDO2 <literal>uv</literal> feature)
when unlocking the volume. This option only applies when in manual mode, i.e. when
<option>fido2-cid=</option> option is set. Defaults to neither true or false, but rather to
<constant>v248</constant> behavior, that is: omit configuring UV whatsoever.</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<varlistentry>
<term><option>tpm2-device=</option></term>

View File

@ -97,6 +97,10 @@ static bool arg_fido2_device_auto = false;
static void *arg_fido2_cid = NULL;
static size_t arg_fido2_cid_size = 0;
static char *arg_fido2_rp_id = NULL;
/* For now and for compatibility, if the user explicitly configured FIDO2 support and we do
* not read FIDO2 metadata off the LUKS2 header, default to the systemd 248 logic, where we
* use PIN + UP when needed, and do not configure UV at all. */
static Fido2EnrollFlags arg_fido2_manual_flags = FIDO2ENROLL_PIN_IF_NEEDED | FIDO2ENROLL_UP_IF_NEEDED | FIDO2ENROLL_UV_OMIT;
static char *arg_tpm2_device = NULL; /* These and the following fields are about locking an encrypted volume to the local TPM */
static bool arg_tpm2_device_auto = false;
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
@ -394,6 +398,39 @@ static int parse_one_option(const char *option) {
if (r < 0)
return log_oom();
} else if ((val = startswith(option, "fido2-pin="))) {
r = parse_boolean(val);
if (r < 0) {
log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
return 0;
}
arg_fido2_manual_flags &= ~FIDO2ENROLL_PIN_IF_NEEDED;
SET_FLAG(arg_fido2_manual_flags, FIDO2ENROLL_PIN, r);
} else if ((val = startswith(option, "fido2-up="))) {
r = parse_boolean(val);
if (r < 0) {
log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
return 0;
}
arg_fido2_manual_flags &= ~FIDO2ENROLL_UP_IF_NEEDED;
SET_FLAG(arg_fido2_manual_flags, FIDO2ENROLL_UP, r);
} else if ((val = startswith(option, "fido2-uv="))) {
r = parse_boolean(val);
if (r < 0) {
log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
return 0;
}
arg_fido2_manual_flags &= ~FIDO2ENROLL_UV_OMIT;
SET_FLAG(arg_fido2_manual_flags, FIDO2ENROLL_UV, r);
} else if ((val = startswith(option, "tpm2-device="))) {
if (streq(val, "auto")) {
@ -1361,33 +1398,18 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
_cleanup_(erase_and_freep) void *decrypted_key = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
size_t decrypted_key_size, cid_size = 0;
size_t decrypted_key_size;
_cleanup_free_ char *friendly = NULL;
int keyslot = arg_key_slot, r;
const char *rp_id = NULL;
const void *cid = NULL;
Fido2EnrollFlags required;
bool use_libcryptsetup_plugin = libcryptsetup_plugins_support();
assert(cd);
assert(name);
assert(arg_fido2_device || arg_fido2_device_auto);
if (arg_fido2_cid) {
if (!key_file && !key_data)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"FIDO2 mode with manual parameters selected, but no keyfile specified, refusing.");
rp_id = arg_fido2_rp_id;
cid = arg_fido2_cid;
cid_size = arg_fido2_cid_size;
/* For now and for compatibility, if the user explicitly configured FIDO2 support and we do
* not read FIDO2 metadata off the LUKS2 header, default to the systemd 248 logic, where we
* use PIN + UP when needed, and do not configure UV at all. Eventually, we should make this
* explicitly configurable. */
required = FIDO2ENROLL_PIN_IF_NEEDED | FIDO2ENROLL_UP_IF_NEEDED | FIDO2ENROLL_UV_OMIT;
}
if (arg_fido2_cid && !key_file && !key_data)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"FIDO2 mode with manual parameters selected, but no keyfile specified, refusing.");
friendly = friendly_disk_name(crypt_get_device_name(cd), name);
if (!friendly)
@ -1401,17 +1423,17 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
"Automatic FIDO2 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking.");
} else {
if (cid)
if (arg_fido2_cid)
r = acquire_fido2_key(
name,
friendly,
arg_fido2_device,
rp_id,
cid, cid_size,
arg_fido2_rp_id,
arg_fido2_cid, arg_fido2_cid_size,
key_file, arg_keyfile_size, arg_keyfile_offset,
key_data, key_data_size,
until,
required,
arg_fido2_manual_flags,
"cryptsetup.fido2-pin",
arg_ask_password_flags,
&decrypted_key,