Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using in 1FA mode with multiple drives #79

Open
Brando753 opened this issue Feb 18, 2022 · 2 comments
Open

Using in 1FA mode with multiple drives #79

Brando753 opened this issue Feb 18, 2022 · 2 comments

Comments

@Brando753
Copy link

Brando753 commented Feb 18, 2022

I may just be doing something wrong in my setup but I am trying to use the 1FA mode with 8 SSD's at boot. I am running a freshly installed Debian stable (bullseye) installation

Using the following ykluks.cfg file:

# If you change this file, you need to run 
#   update-initramfs -u
WELCOME_TEXT="Please insert HSM to boot device..."
# Set to "1" if you want both your password and Yubikey response be bundled together and writtent to key slot.
CONCATENATE=0
# Set to "1" if you want to hash your password with sha256.
HASH=0
# Generated with pwgen -s 128 (this code is different than what I use on the system but the same length)
YUBIKEY_CHALLENGE="YH3hzaphiGX0noE6XuCOhtkqeh2zbemKezASnqMiKoflsFJQr8x1wblOhWO18dBWl4sIw5HYhGiV5QwnXZfLzoBRJaG0lCEosz5Rvg8PgcZOsAiczj1gnG4FPX9rtRh2"

I have tried three crypttab configurations, one where only one drive decrypts on boot which works as expected, one where I am using the yubikey-luks keyscript with all drives at boot, and then another that attempts to use ykluks with decrypt_keyctl to cache the result for the other drives.

First configuration:

sda3_crypt UUID=56e8721e-dfa2-4b8e-9ff7-c6f1ae921cd6 none luks,discard,keyscript=/usr/share/yubikey-luks/ykluks-keyscript

This works as you would expect, on boot, the system automatically queries the yubikey and then decrypts the main drive. I however want to decrypt all drives at boot if possible so I modified the crypttab to look like the following:

sda3_crypt UUID=56e8721e-dfa2-4b8e-9ff7-c6f1ae921cd6 none luks,discard,keyscript=/usr/share/yubikey-luks/ykluks-keyscript
zfs_drive_1 UUID=7238e9b5-00b7-4df4-a879-dcd315c6bc83 none luks,discard,keyscript=/usr/share/yubikey-luks/ykluks-keyscript
zfs_drive_2 UUID=1ad2085d-b501-489b-bc8d-56830e13fd16 none luks,discard,keyscript=/usr/share/yubikey-luks/ykluks-keyscript
zfs_drive_3 UUID=c7dc8717-b671-46cd-b08d-2d303dd43feb none luks,discard,keyscript=/usr/share/yubikey-luks/ykluks-keyscript
zfs_drive_4 UUID=857426a7-b72b-4dc8-8919-e1c25af119ee none luks,discard,keyscript=/usr/share/yubikey-luks/ykluks-keyscript
zfs_drive_5 UUID=c3d90f0f-d6e7-4069-8165-dce62e727e45 none luks,discard,keyscript=/usr/share/yubikey-luks/ykluks-keyscript
zfs_drive_6 UUID=634cb46b-0a97-4e55-8bd4-48c08547bbc7 none luks,discard,keyscript=/usr/share/yubikey-luks/ykluks-keyscript
zfs_drive_7 UUID=4fcc39ab-6046-4485-b499-53c9de279df4 none luks,discard,keyscript=/usr/share/yubikey-luks/ykluks-keyscript

This I would think would be the default configuration however the behavior when running on this mode is that the password for one of the drives is asked (usually zfs_drive_1 or zfs_drive_2) and if I enter the manual password it would then decrypt all the rest of the drives and boot without any further prompts. The expected behavior is that the system just boots without user interaction, this will be important as this system will be a headless server.

Finally, I thought that perhaps it's running into an issue querying the yubikey so frequently so perhaps we could cache the result using the decrypt_keyctl keyscript however the system will no longer boot with the following crypttab:

sda3_crypt UUID=56e8721e-dfa2-4b8e-9ff7-c6f1ae921cd6 zfs_pool: luks,discard,keyscript=decrypt_keyctl,keyscript=/usr/share/yubikey-luks/ykluks-keyscript
zfs_drive_1 UUID=7238e9b5-00b7-4df4-a879-dcd315c6bc83 zfs_pool luks,discard,keyscript=decrypt_keyctl
zfs_drive_2 UUID=1ad2085d-b501-489b-bc8d-56830e13fd16 zfs_pool luks,discard,keyscript=decrypt_keyctl
zfs_drive_3 UUID=c7dc8717-b671-46cd-b08d-2d303dd43feb zfs_pool luks,discard,keyscript=decrypt_keyctl
zfs_drive_4 UUID=857426a7-b72b-4dc8-8919-e1c25af119ee zfs_pool luks,discard,keyscript=decrypt_keyctl
zfs_drive_5 UUID=c3d90f0f-d6e7-4069-8165-dce62e727e45 zfs_pool luks,discard,keyscript=decrypt_keyctl
zfs_drive_6 UUID=634cb46b-0a97-4e55-8bd4-48c08547bbc7 zfs_pool luks,discard,keyscript=decrypt_keyctl
zfs_drive_7 UUID=4fcc39ab-6046-4485-b499-53c9de279df4 zfs_pool luks,discard,keyscript=decrypt_keyctl

This will result in the error cryptesetup: ERROR: sda3_crypt: invalid value for keyscript options, skipping I am not sure if it's possible to chain multiple keyscripts or how you would properly do it.

For added clarity, I would do an sudo update-initramfs -u between each change of crypttab. I built yubikey-luks against the current master branch so its not the stale version in the stable repos.

If anyone has this working on multiple drives has any ideas about what I should be doing please let me know!

@SE-1523
Copy link

SE-1523 commented Mar 26, 2022

Hey,

I got a similar problem. In my case the os is stored on one drive, data is stored on another, both holding the LUKS encryption layers and on top LVM volumes. After the installation of Debian 11 I followed the instructions to enroll the YubiKey and set up the the /etc/crypttab file. As a result the root partition (and since this is part of the "System" volume group the whole first drive) is decrypted by initramfs hook cryptroot during boot. The other drive is not decrypted using YubiKey, but later in boot time asking for the during the Debian installation set LUKS passphrase.

As mentioned in /usr/share/initramfs-tools/hooks/cryptroot:

crypttab_print_initramfs_entry()
Print a crypttab(5) entry - unless is was already processed - if it
has the 'initramfs' option set.

and

generate_initrd_crypttab()
Generate the crypttab(5) snippet that is relevant at initramfs
stage. (Devices that aren't required at the initramfs stage are
ignored.)

So, in my case the solution was to add the 'initramfs' option to each line in my crypttab. This will make cryptroot processing all marked LUKS partiontions in initramfs stage. In my case it means I'm asked twice for a password used for challenge response with the YubiKey, since I'd like to use 2FA. In case of 1FA I only guess that this will work to.

It would be great to see a hint in README since it took me a long time to figure it out, and I found some more people asking the same questions but having no answers.

My crypttab looks like:

nvme0n1p3 UUID=<myUUID> none initramfs,luks,keyscript=/usr/share/yubikey-luks/ykluks-keyscript
nvme1n1p1 UUID=<myUUID> none initramfs,luks,keyscript=/usr/share/yubikey-luks/ykluks-keyscript

@ghost
Copy link

ghost commented Mar 23, 2024

Hi!

I've got a working solution that integrates ykluks-keyscript with decrypt_keyctl so that the challenge only has to be entered once and will then be re-used for all partitions with the same (arbitrary) id passed to ykluks-keyscript/decrypt_keyctl (column 3 in /etc/crypttab).

To make this work, the passkey derived from the challenge needs to be cached by ykluks-keyscript in the kernel keyring under the correct key id such that decrypt_keyctl can find and retrieve it.

Plus - as pointed out by @SE-1523 - you'll have to add the initramfs option to all disks (except cryptroot) that share the same passkey, see the description of the keyscript option in crypttab(5).

The final solution looks like this:

/etc/crypttab:

cryptroot /dev/disk/by-partuuid/<UUID1> arbitrary-identifier   luks,keyscript=/usr/share/yubikey-luks/ykluks-keyscript
cryptdata /dev/disk/by-partuuid/<UUID2> arbitrary-identifier   luks,initramfs,keyscript=decrypt_keyctl

This requires a patch of ykluks-keyscript along the lines of:

if [ "$check_yubikey_present" = "1" ]; then
    message "Accessing yubikey..."
    if [ "$HASH" = "1" ]; then
        PW=$(printf %s "$PW" | sha256sum | awk '{print $1}')
    fi
    R="$(printf %s "$PW" | ykchalresp -2 -i- 2>/dev/null || true)"
    message "Retrieved the response from the Yubikey"
    if [ "$CONCATENATE" = "1" ]; then
        PW=$(printf '%s' "$PW$R")
    else
        PW=$(printf '%s' "$R")
    fi
fi

# Integration with /lib/cryptsetup/scripts/decrypt_keyctl - see there for details.
if [ -z "${CRYPTTAB_KEY:-}" ] || [ "$CRYPTTAB_KEY" = "none" ]; then
    ID_="cryptsetup"
else
    ID_="cryptsetup:$CRYPTTAB_KEY"
fi
KID_="$(printf "%s" "$PW" | keyctl padd user "$ID_" @u)"
TIMEOUT_='60'
keyctl timeout "$KID_" "$TIMEOUT_"

printf '%s' "$PW"

(Error checking removed for clarity.)

and a patch of /usr/share/initramfs-tools/hooks/yubikey-luks with something like:

# Integration with decrypt_keyctl
if [ -x /usr/bin/keyctl ]; then
        copy_exec /usr/bin/keyctl
fi

And finally the keyutils package containing the required keyctl tool should be added as dependency or recommended package to the control file.

If @Vincent43 or @cornelinux think that this change would be worthwhile, I could provide a PR. But as this requires quite some extra work on my part please comment first whether such an approach adds value and would be secure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants