From cdcc04a5fa93782166e6cd88b29f8d0031252f3a Mon Sep 17 00:00:00 2001 From: shimunn Date: Tue, 17 Sep 2019 16:14:12 +0200 Subject: [PATCH] dracut --- dracut/Makefile | 22 +++++++ dracut/README.md | 112 ++++++++++++++++++++++++++++++++++++ dracut/module-setup.sh | 66 +++++++++++++++++++++ dracut/ykluks.sh | 128 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 328 insertions(+) create mode 100644 dracut/Makefile create mode 100644 dracut/README.md create mode 100755 dracut/module-setup.sh create mode 100755 dracut/ykluks.sh diff --git a/dracut/Makefile b/dracut/Makefile new file mode 100644 index 0000000..e9cec4b --- /dev/null +++ b/dracut/Makefile @@ -0,0 +1,22 @@ +.PHONY: install + +DRACUT_MODULE_D=/usr/lib/dracut/modules.d/95fido2luks +DRACUT_CONF_D=/etc/dracut.conf.d + +build: + cargo install --root . --path ../ --force + rm -f .crates.toml +install: build + mkdir -p ${DRACUT_MODULE_D} + cp bin/* /usr/local/bin/ + cp module-setup.sh ykluks.sh bin/* ${DRACUT_MODULE_D}/ + chown -R root: ${DRACUT_MODULE_D}/ +setup: install + bin/fido2luks setup + cp fido2luks.json /etc/fido2luks.json +clean: + cargo clean + rm -rf bin fido2luks.json +uninstall: + rm -rf /etc/fido2luks.json ${DRACUT_CONF_D}/fido2luks.conf ${DRACUT_MODULES_D}/95fido2luks + diff --git a/dracut/README.md b/dracut/README.md new file mode 100644 index 0000000..9f1dd6f --- /dev/null +++ b/dracut/README.md @@ -0,0 +1,112 @@ +# ykluks +Dracut module to use yubikey in challenge/response mode to unlock LUKS partition. + +This module is written to work with Qubes OS 3.2. It may work with other dracut +based distributions but there are other more complete tools you may want to try +(e.g. https://github.com/bpereto/ykfde). + +For ubuntu based distributions you may want to try this one: https://github.com/cornelinux/yubikey-luks + + +WARNING +------- + +Please note that the current version is tested with a LVM-on-LUKS setup only. The default Qubes OS installation +is a LUKS-on-LVM setup which will not work yet. Patches for LUKS-on-LVM are welcome as well as experienced testers +because a dont have a LUKS-on-LVM installation to test with. + + +Initialize Yubikey +------------------ + +Install yubikey tools. + + qubes-dom0-update ykpers + +Initialize the Yubikey for challenge/response in slot 2. + + ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible + + +Add luks slot +------------- + +You need to manually add a new luks slot with the response you get when sending your +password to the yubikey. + +Get response from yubikey. + + ykchalresp -2 mypassword + +You may want to check which LUKS key slots are currently used. Make sure you use the correct device file. +This may help if you want to replace your current password with a more secure backup password later. + + sudo cryptsetup LuksDump /dev/sdXX + +Use the output from the previous command as new passphrase. + + sudo cryptsetup luksAddKey --key-slot a_free_key_slot /dev/sdXX + + +Install ykluks +-------------- + +To get the ykluks archive to dom0 you can run the following command where downloadvm is the VM you want to use for downloading ykluks. + + qvm-run --pass-io downloadvm "wget -O - https://github.com/the2nd/ykluks/archive/master.zip" > ykluks.zip + +Unzip it. + + unzip ykluks.zip + rm ykluks.zip + + +Run the installer script. This will copy all files to the right place. + + cd ykluks-master + sudo ./install.sh + + +Prepare system for ykluks enabled initramfs +------------------------------------------- + +Now we need to do some modifications for ykluks to work. + +You may want to make a backup of your current initramfs. You can use the old initramfs in case something went wrong (see "something went wrong" below). + + sudo cp -av /boot/initramfs-4.8.12-12.pvops.qubes.x86_64.img /boot/initramfs-4.8.12-12.pvops.qubes.x86_64.img.org + +1. Comment out all lines in crypttab. +2. Change the line with "rd.luks.uuid=..." in /etc/default/grub to "rd.ykluks.uuid=..." +3. Change the line with "rd.qubes.hide_all_usb" in /etc/default/grub to "rd.ykluks.hide_all_usb" + + +Now we have to recreate the grub config and the initramfs. + + sudo grub2-mkconfig > /boot/grub2/grub.cfg + sudo dracut -f + +That's it. After a reboot you should be able to unlock your LUKS partition with your password and your yubikey. + + +Remove normal password and add secure backup password +----------------------------------------------------- +If everyting works as expected you may want to replace your (probably) insecure LUKS password with a secure backup password. + +Add the new backup password. + + sudo cryptsetup luksAddKey --key-slot a_free_key_slot /dev/sdXX + sudo cryptsetup luksKillslot --key-slot your_old_key_slot /dev/sdXX + + +Something went wrong :( +----------------------- + +In case you run into any trouble after ykluks installation you can use the backup initramfs you (hopefully) created before generating a new one. + +1. Select the Qubes OS boot entry in the grub boot menu. +2. Press "e" to get into edit mode. +3. First we need to change the "rd.ykluks.uuid=..." parameter back to "rd.luks.uuid=...". This is normally in the line that starts with "module /vmlinuz-...". +4. Then we need to get the line that loads the initramfs. This line normally starts with "module --nounzip /initramfs-..". Just append .org to this line. +5. Press "CTRL+X" to boot this configuration. + diff --git a/dracut/module-setup.sh b/dracut/module-setup.sh new file mode 100755 index 0000000..2ef49dc --- /dev/null +++ b/dracut/module-setup.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +check() { + return 0 +} + +depends() { + echo rootfs-block + return 0 +} + +install() { + #inst_hook pre-trigger 91 "$moddir/ykluks.sh" + inst_hook initqueue 01 "$moddir/ykluks.sh" + #inst_hook pre-mount 1 "$moddir/fix_crypttab.sh" + #inst_hook pre-trigger 10 "$moddir/ykluks.sh" + #inst_hook cmdline 5 "$moddir/ykluks.sh" + + #inst_simple "/bin/bash" "/bin/bash" + inst tr + inst cut + inst true + inst find + inst blkid + inst lsusb + inst cryptsetup + inst fido2luks + # Stolen from qubes-pciback module. + inst lspci + inst grep + inst awk + #inst_simple "/usr/bin/tr" "/bin/tr" + #inst_simple "/usr/bin/cut" "/bin/cut" + #inst_simple "/usr/bin/true" "/bin/true" + #inst_simple "/usr/sbin/blkid" "/bin/blkid" + #inst_simple "/usr/bin/ykchalresp" "/bin/ykchalresp" + inst_simple "/etc/fido2luks.json" "/etc/fido2luks.json" + + #inst_rules "$moddir/20-ykfde.rules" + inst_rules "/usr/lib/udev/rules.d/60-u2f-hidraw.rules" + #inst_simple "$moddir/ykluks.sh" "/bin/ykluks.sh" + #inst_hook cmdline 30 "$moddir/parse-mod.sh" + #inst_simple "$moddir/ykfde.sh" /sbin/ykfde.sh + #inst_simple /usr/lib/udev/ykfde + #inst_simple /etc/ykfde.conf + #inst_dir /etc/ykfde.d/* + + inst_multiple -o \ + $systemdsystemunitdir/systemd-ask-password-console.path \ + $systemdsystemunitdir/systemd-ask-password-console.service \ + systemd-ask-password systemd-tty-ask-password-agent + + dracut_need_initqueue +} + +installkernel() { + # Stolen from qubes-pciback module. + local mod= + for mod in pciback xen-pciback; do + if modinfo -k "${kernel}" "${mod}" >/dev/null 2>&1; then + hostonly='' instmods "${mod}" + fi + done +} diff --git a/dracut/ykluks.sh b/dracut/ykluks.sh new file mode 100755 index 0000000..683e68f --- /dev/null +++ b/dracut/ykluks.sh @@ -0,0 +1,128 @@ +#!/bin/sh + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +# Set defaults. +YK_SLOT="2" +DEVICE_MAX_WAIT="60" +MESSAGE_TIMEOUT="10" +SHOW_YK_INSERT_MSG="false" +LUKS_PROMPT="Passphrase" +FIDO2LUKS_PROMPT="Password" +LUKS_PASSPHRASE_FALLBACK="false" + +# Load config file. +FIDO2LUKS_CONFIG="/etc/fido2luks.json" +if [ -f "$FIDO2LUKS_CONFIG" ] ; then + export FIDO2LUKS_CONFIG="$FIDO2LUKS_CONFIG" +fi + +LUKS_UUIDS="$(getargs rd.fido2luks.uuid | tr ' ' '\n'| cut -d '-' -f 2-)" + +display_msg_timeout () { + local MSG="$1" + (plymouth display-message --text="$MSG";sleep $MESSAGE_TIMEOUT;plymouth hide-message --text="$MSG") & +} + +display_msg () { + local MSG="$1" + plymouth display-message --text="$MSG" & +} + +hide_msg () { + local MSG="$1" + plymouth hide-message --text="$MSG" & +} + +hide_devices () { + # Find all networking devices currenly installed... + HIDE_PCI="`lspci -mm -n | grep '^[^ ]* "02'|awk '{print $1}'`" + + # ... and optionally all USB controllers... + if getargbool 0 rd.fido2luks.hide_all_usb; then + HIDE_PCI="$HIDE_PCI `lspci -mm -n | grep '^[^ ]* "0c03'|awk '{print $1}'`" + fi + + HIDE_PCI="$HIDE_PCI `getarg rd.fido2luks.hide_pci | tr ',' ' '`" + + modprobe xen-pciback 2>/dev/null || : + + # ... and hide them so that Dom0 doesn't load drivers for them + for dev in $HIDE_PCI; do + BDF=0000:$dev + if [ -e /sys/bus/pci/devices/$BDF/driver ]; then + echo -n $BDF > /sys/bus/pci/devices/$BDF/driver/unbind + fi + echo -n $BDF > /sys/bus/pci/drivers/pciback/new_slot + echo -n $BDF > /sys/bus/pci/drivers/pciback/bind + done +} + +handle_authenticator () { + WAIT_COUNTER="0" + YUBIKEY_TEST="" + YUBIKEY_MSG="Please insert your authenticator..." + while ! fido2luks connected 2> /dev/null ; do + YUBIKEY_TEST="1" + if [ "$SHOW_YK_INSERT_MSG" != "true" ] ; then + break + fi + + if [ "$YUBIKEY_MSG" != "" ] ; then + display_msg "$YUBIKEY_MSG" + HIDE_MSG="$YUBIKEY_MSG" + YUBIKEY_MSG="" + fi + + if [ "$WAIT_COUNTER" -ge "$DEVICE_MAX_WAIT" ] ; then + break + fi + + WAIT_COUNTER="$[$WAIT_COUNTER+1]" + sleep 1 + done + + if [ "$HIDE_MSG" != "" ] ; then + hide_msg "$HIDE_MSG" + fi + + while true ; do + if [ "$YUBIKEY_TEST" == "" ] ; then + if [ "$LUKS_PASSPHRASE_FALLBACK" != "true" ] ; then + break + fi + LUKS_PASSPHRASE="$(/usr/bin/systemd-ask-password --no-tty "$LUKS_PROMPT")" + for UUID in $LUKS_UUIDS ; do + DEV="$(blkid -U "$UUID")" + if echo "$LUKS_PASSPHRASE" | cryptsetup luksOpen "$DEV" luks-$UUID ; then + LUKS_MSG="Luks device opened successful: $DEV" + display_msg_timeout "$LUKS_MSG" + else + LUKS_MSG="Failed to open luks device: $DEV (Wrong password?)" + display_msg_timeout "$LUKS_MSG" + LUKS_OPEN_FAILURE="true" + fi + done + else + fido2luks open + YUBIKEY_MSG="Received response from yubikey." + display_msg_timeout "$YUBIKEY_MSG" + LUKS_OPEN_FAILURE="false" + fi + + + if ! $LUKS_OPEN_FAILURE ; then + break + fi + done +} + +if [ "$LUKS_UUIDS" != "" ] ; then + handle_authenticator +fi + +rm /etc/udev/rules.d/60-u2f-hidraw.rules +systemctl daemon-reload + +# Make sure we hide devices from dom0 after yubikey/luks setup. +hide_devices