From d5fa6e6ca785140b50cb30361e9ddc4e538c3f40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Szcz=C4=99k?= Date: Fri, 7 Jun 2024 16:48:41 +0200 Subject: [PATCH] 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. --- man/crypttab.xml | 35 +++++++++++++++++++ src/cryptsetup/cryptsetup.c | 68 ++++++++++++++++++++++++------------- 2 files changed, 80 insertions(+), 23 deletions(-) diff --git a/man/crypttab.xml b/man/crypttab.xml index 955111fe94..3aa809e667 100644 --- a/man/crypttab.xml +++ b/man/crypttab.xml @@ -768,6 +768,41 @@ + + + + Controls whether to require the user to enter a PIN when unlocking the volume (the + FIDO2 clientPin feature). This option only applies when in manual mode, i.e. + when option is set. Defaults to neither true or false, but rather to + v248 behavior, that is: try with no PIN first, but if token reports that PIN + is required, try again asking for PIN. + + + + + + + + Controls whether to require the user to verify presence (tap the token, the FIDO2 + up feature) when unlocking the volume. This option only applies when in manual + mode, i.e. when option is set. Defaults to neither true or false, + but rather to v248 behavior, that is: try with no UP first, but if token reports + that UP is required, try again with UP enabled. + + + + + + + + Controls whether to require user verification (the FIDO2 uv feature) + when unlocking the volume. This option only applies when in manual mode, i.e. when + option is set. Defaults to neither true or false, but rather to + v248 behavior, that is: omit configuring UV whatsoever. + + + + diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 42586a0aee..ac46793e05 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -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,