diff --git a/Makefile b/Makefile deleted file mode 100644 index 672c6b7..0000000 --- a/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -install: reinstall - install -v -b -Dm644 src/ykfde.conf "$(DESTDIR)/etc/ykfde.conf" - -reinstall: - install -Dm644 src/hooks/ykfde "$(DESTDIR)/usr/lib/initcpio/hooks/ykfde" - install -Dm644 src/install/ykfde "$(DESTDIR)/usr/lib/initcpio/install/ykfde" - install -Dm755 src/ykfde-suspend "$(DESTDIR)/usr/lib/ykfde-suspend/ykfde-suspend" - install -Dm755 src/initramfs-suspend "$(DESTDIR)/usr/lib/ykfde-suspend/initramfs-suspend" - install -Dm644 src/ykfde-suspend.service "$(DESTDIR)/usr/lib/systemd/system/ykfde-suspend.service" - install -Dm755 src/ykfde-enroll "$(DESTDIR)/usr/bin/ykfde-enroll" - install -Dm755 src/ykfde-format "$(DESTDIR)/usr/bin/ykfde-format" - install -Dm755 src/ykfde-open "$(DESTDIR)/usr/bin/ykfde-open" - install -Dm644 README.md "$(DESTDIR)/usr/share/doc/ykfde/README.md" -test: - ./testrun.sh - -all: install diff --git a/README.md b/README.md index 54329f5..06aaac4 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ This project leverages a [YubiKey](https://wiki.archlinux.org/index.php/Yubikey) Be aware that this was only tested and intended for: * [Arch Linux](https://www.archlinux.org/) and its derivatives +* [Debian](https://www.debian.org/)/[Ubuntu](https://www.ubuntu.com/) based systems * [YubiKey (version 4 or later)](https://www.yubico.com/products/yubikey-5-overview/) -There is similar project targeting [Debian](https://www.debian.org/)/[Ubuntu](https://www.ubuntu.com/) based systems: [yubikey-luks](https://github.com/cornelinux/yubikey-luks) Table of Contents ================= @@ -80,7 +80,8 @@ Keep in mind that the above doesn't protect you from physical tampering like *ev # Install -## From Arch Linux official repository +## Arch Linux +### From Arch Linux official repository The easiest way is to install package from [official Arch Linux repository](https://www.archlinux.org/packages/community/any/yubikey-full-disk-encryption/). @@ -88,23 +89,33 @@ The easiest way is to install package from [official Arch Linux repository](http sudo pacman -Syu yubikey-full-disk-encryption ``` -## From Github using 'makepkg' +### From Github using 'makepkg' ``` -wget https://raw.githubusercontent.com/agherzan/yubikey-full-disk-encryption/master/PKGBUILD +wget https://raw.githubusercontent.com/agherzan/yubikey-full-disk-encryption/master/packaging/archlinux/PKGBUILD makepkg -srci ``` -## From Github using 'make' +### From Github using 'make' ``` git clone https://github.com/agherzan/yubikey-full-disk-encryption.git -cd yubikey-full-disk-encryption +cd yubikey-full-disk-encryption/packaging/archlinux sudo make install ``` When installing by using `make` you also need to install [yubikey-personalization](https://www.archlinux.org/packages/community/x86_64/yubikey-personalization/) and [expect](https://www.archlinux.org/packages/extra/x86_64/expect/) packages. +## Debian/Ubuntu +### From Github using 'make' +``` +git clone https://github.com/agherzan/yubikey-full-disk-encryption.git +cd yubikey-full-disk-encryption/packaging/debian +make builddeb NO_SIGN=1 +sudo dpkg -i DEBUILD/ykfde_*_all.deb +``` + + # Configure @@ -212,11 +223,11 @@ To kill a ykfde passphrase for existing *LUKS* encrypted volume you can use [ykf ykfde-enroll -d /dev/ -s -k ``` -## Enable ykfde initramfs hook +## Enable ykfde initramfs hook (Arch Linux) **Warning: It's recommended to have already working [encrypted system setup](https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system) with `encrypt` hook and non-ykfde passphrase before starting to use `ykfde` hook with ykfde passphrase to avoid potential misconfigurations.** -Edit `/etc/mkinitcpio.conf` and add the `ykfde` hook before or instead of `encrypt` hook as provided in [example](https://wiki.archlinux.org/index.php/Dm-crypt/System_configuration#Examples). Adding `ykfde` hook before `encrypt` hook will allow for a safe fallback in case of ykfde misconfiguration. You can remove `encrypt` hook later when you confim that everything is working correctly. After making your changes [regenerate initramfs](https://wiki.archlinux.org/index.php/Mkinitcpio#Image_creation_and_activation): +For Arch Linux and its derivatives, edit `/etc/mkinitcpio.conf` and add the `ykfde` hook before or instead of `encrypt` hook as provided in [example](https://wiki.archlinux.org/index.php/Dm-crypt/System_configuration#Examples). Adding `ykfde` hook before `encrypt` hook will allow for a safe fallback in case of ykfde misconfiguration. You can remove `encrypt` hook later when you confim that everything is working correctly. After making your changes [regenerate initramfs](https://wiki.archlinux.org/index.php/Mkinitcpio#Image_creation_and_activation): ``` sudo mkinitcpio -P @@ -224,6 +235,17 @@ sudo mkinitcpio -P Reboot and test your configuration. +## Update crypttab (Debian/Ubuntu) +To unlock LUKS encrypted volumes at boot for Debian/Ubuntu systems, you must append `keyscript=/usr/share/ykfde/ykfde-keyscript` to the `/etc/crypttab` file. For example: +``` +cryptroot /dev/sda none luks,keyscript=/usr/share/ykfde/ykfde-keyscript +``` +After changing this file, update the initial RAM file system: +``` +sudo update-initramfs -u +``` + + ## Enable NFC support in ykfde initramfs hook (experimental) **Warning: Currently NFC support is implemented only in initramfs hook. All ykfde manipulations on booted system have to be done through USB.** diff --git a/packaging/archlinux/Makefile b/packaging/archlinux/Makefile new file mode 100644 index 0000000..084eac0 --- /dev/null +++ b/packaging/archlinux/Makefile @@ -0,0 +1,17 @@ +install: reinstall + install -v -b -Dm644 ../../src/ykfde.conf "$(DESTDIR)/etc/ykfde.conf" + +reinstall: + install -Dm644 ../../src/archlinux/hooks/ykfde "$(DESTDIR)/usr/lib/initcpio/hooks/ykfde" + install -Dm644 ../../src/archlinux/install/ykfde "$(DESTDIR)/usr/lib/initcpio/install/ykfde" + install -Dm755 ../../src/archlinux/ykfde-suspend "$(DESTDIR)/usr/lib/ykfde-suspend/ykfde-suspend" + install -Dm755 ../../src/archlinux/initramfs-suspend "$(DESTDIR)/usr/lib/ykfde-suspend/initramfs-suspend" + install -Dm644 ../../src/archlinux/ykfde-suspend.service "$(DESTDIR)/usr/lib/systemd/system/ykfde-suspend.service" + install -Dm755 ../../src/ykfde-enroll "$(DESTDIR)/usr/bin/ykfde-enroll" + install -Dm755 ../../src/ykfde-format "$(DESTDIR)/usr/bin/ykfde-format" + install -Dm755 ../../src/ykfde-open "$(DESTDIR)/usr/bin/ykfde-open" + install -Dm644 ../../README.md "$(DESTDIR)/usr/share/doc/ykfde/README.md" +test: + ../../src/testrun.sh + +all: install diff --git a/PKGBUILD b/packaging/archlinux/PKGBUILD similarity index 97% rename from PKGBUILD rename to packaging/archlinux/PKGBUILD index d053af0..c863bc6 100644 --- a/PKGBUILD +++ b/packaging/archlinux/PKGBUILD @@ -1,6 +1,6 @@ pkgname=yubikey-full-disk-encryption-git _pkgname=yubikey-full-disk-encryption -pkgver=r136.4d8ba6a +pkgver=r155.dcaac00 pkgrel=1 pkgdesc='Use YubiKey to unlock a LUKS partition' arch=('any') diff --git a/packaging/debian/Makefile b/packaging/debian/Makefile new file mode 100644 index 0000000..1a1abfa --- /dev/null +++ b/packaging/debian/Makefile @@ -0,0 +1,26 @@ +info: + @echo "builddeb [NO_SIGN=1] - build deb package for Ubuntu LTS [NO_SIGN disables signing]" + @echo "clean - clean build directory DEBUILD" + +VERSION=0.1 +SRC_DIR = ykfde-${VERSION} + +debianize: + rm -fr DEBUILD + mkdir -p DEBUILD/${SRC_DIR} + cp -r * DEBUILD/${SRC_DIR} || true + cp -r ../../src/ykfde* DEBUILD/${SRC_DIR} || true + cp -r ../../src/debian/* DEBUILD/${SRC_DIR} || true + cp ../../README.md DEBUILD/${SRC_DIR} || true + (cd DEBUILD; tar -zcf ykfde_${VERSION}.orig.tar.gz --exclude=${SRC_DIR}/debian ${SRC_DIR}) + +builddeb: + make debianize +ifndef NO_SIGN + (cd DEBUILD/${SRC_DIR}; debuild) +else + (cd DEBUILD/${SRC_DIR}; debuild -uc -us) +endif + +clean: + rm -fr DEBUILD diff --git a/packaging/debian/debian/changelog b/packaging/debian/debian/changelog new file mode 100644 index 0000000..82aa37b --- /dev/null +++ b/packaging/debian/debian/changelog @@ -0,0 +1,5 @@ +ykfde (0.1) UNRELEASED; urgency=medium + + * Added Debian/Ubuntu support + + -- crispy-landslide <48504814+crispy-landslide@users.noreply.github.com> Tue, 11 Jan 2022 21:28:25 -0800 diff --git a/packaging/debian/debian/compat b/packaging/debian/debian/compat new file mode 100644 index 0000000..b4de394 --- /dev/null +++ b/packaging/debian/debian/compat @@ -0,0 +1 @@ +11 diff --git a/packaging/debian/debian/control b/packaging/debian/debian/control new file mode 100644 index 0000000..5c17a55 --- /dev/null +++ b/packaging/debian/debian/control @@ -0,0 +1,16 @@ +Source: ykfde +Section: admin +Priority: optional +Maintainer: Andrei Gherzan +Build-Depends: debhelper (>= 11), dh-exec +Standards-Version: 4.1.4 +Homepage: https://github.com/agherzan/yubikey-full-disk-encryption + +Package: ykfde +Architecture: all +Depends: cryptsetup, initramfs-tools, yubikey-personalization (>= 1.5), udisks2, expect, ${misc:Depends} +Description: This project leverages a YubiKey HMAC-SHA1 Challenge-Response + mode for creating strong LUKS encrypted volume passphrases. + It can be used in intramfs stage during boot process as well as on running system. + . + Requires Yubikey 4 or newer. diff --git a/packaging/debian/debian/copyright b/packaging/debian/debian/copyright new file mode 100644 index 0000000..1488d56 --- /dev/null +++ b/packaging/debian/debian/copyright @@ -0,0 +1,7 @@ +Copyright 2017 Andrei Gherzan + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packaging/debian/debian/rules b/packaging/debian/debian/rules new file mode 100644 index 0000000..60f7939 --- /dev/null +++ b/packaging/debian/debian/rules @@ -0,0 +1,17 @@ +#! /usr/bin/make -f + +%: + dh $@ + +override_dh_auto_build: + # nothing to build + +override_dh_install: + dh_install + install -D -o root -g root -m755 hooks/ykfde debian/ykfde/usr/share/initramfs-tools/hooks/ykfde + install -D -o root -g root -m755 key-script debian/ykfde/usr/share/ykfde/ykfde-keyscript + install -D -o root -g root -m755 ykfde-open debian/ykfde/usr/bin/ykfde-open + install -D -o root -g root -m755 ykfde-enroll debian/ykfde/usr/bin/ykfde-enroll + install -D -o root -g root -m755 ykfde-format debian/ykfde/usr/bin/ykfde-format + install -D -o root -g root -m644 README.md debian/ykfde/usr/share/doc/ykfde/README.md + install -D -o root -g root -m644 ykfde.conf debian/ykfde/etc/ykfde.conf diff --git a/packaging/debian/debian/ykfde.postinst b/packaging/debian/debian/ykfde.postinst new file mode 100644 index 0000000..25baaae --- /dev/null +++ b/packaging/debian/debian/ykfde.postinst @@ -0,0 +1,22 @@ +#! /bin/sh + +set -e + +case "$1" in + configure) + if [ -x /usr/sbin/update-initramfs ]; then + echo + update-initramfs -u + fi + ;; + abort-upgrade|abort-remove|abort-deconfigure) + + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# diff --git a/src/hooks/ykfde b/src/archlinux/hooks/ykfde similarity index 100% rename from src/hooks/ykfde rename to src/archlinux/hooks/ykfde diff --git a/src/initramfs-suspend b/src/archlinux/initramfs-suspend similarity index 100% rename from src/initramfs-suspend rename to src/archlinux/initramfs-suspend diff --git a/src/install/ykfde b/src/archlinux/install/ykfde similarity index 100% rename from src/install/ykfde rename to src/archlinux/install/ykfde diff --git a/src/ykfde-suspend b/src/archlinux/ykfde-suspend similarity index 100% rename from src/ykfde-suspend rename to src/archlinux/ykfde-suspend diff --git a/src/ykfde-suspend.service b/src/archlinux/ykfde-suspend.service similarity index 100% rename from src/ykfde-suspend.service rename to src/archlinux/ykfde-suspend.service diff --git a/src/debian/hooks/ykfde b/src/debian/hooks/ykfde new file mode 100755 index 0000000..0413f01 --- /dev/null +++ b/src/debian/hooks/ykfde @@ -0,0 +1,28 @@ +#!/bin/sh + +set -e + +PREREQ="cryptroot" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in + prereqs) + prereqs + exit 0 + ;; +esac + +. /usr/share/initramfs-tools/hook-functions +. /etc/ykfde.conf + +copy_exec /usr/bin/ykchalresp +copy_exec /usr/bin/ykinfo +copy_exec /usr/bin/sha256sum +cp /usr/share/ykfde/ykfde-keyscript "${DESTDIR}/sbin/ykfde-keyscript" +cp /etc/ykfde.conf "${DESTDIR}/etc/ykfde.conf" + +exit 0 diff --git a/src/debian/key-script b/src/debian/key-script new file mode 100755 index 0000000..7198e7a --- /dev/null +++ b/src/debian/key-script @@ -0,0 +1,173 @@ +#!/bin/sh +# shellcheck shell=dash + +# set default values: +DBG="" +YKFDE_CONFIG_FILE="/etc/ykfde.conf" +YKFDE_CHALLENGE_YUBIKEY_INSERT_TIMEOUT="30" +YKFDE_CRYPTSETUP_TRIALS="5" +YKFDE_CHALLENGE_SLOT="2" +YKFDE_CHALLENGE="" +YKFDE_CHALLENGE_PASSWORD_NEEDED="" +YKFDE_USE_PLYMOUTH="" + +message() { + if [ "$YKFDE_USE_PLYMOUTH" ]; then + plymouth display-message --text="$*" + else + echo "$@" >&2 + fi + return 0 +} + +run_hook() { + local _tmp + _tmp="" + + [ -x /bin/plymouth ] && [ "$splash" ] && plymouth --ping && YKFDE_USE_PLYMOUTH=1 + + # shellcheck source=../ykfde.conf + . "$YKFDE_CONFIG_FILE" || { + ykfde_err 001 "Failed to read the YKFDE configuration file '$YKFDE_CONFIG_FILE'" + return 1 + } + + [ "$DBG" ] && message "$0:" + [ "$DBG" ] && message " > Successfully read YKFDE configuration file." + + # sanity checks: + [ "$YKFDE_CRYPTSETUP_TRIALS" -lt 1 ] && YKFDE_CRYPTSETUP_TRIALS="5" + [ "$YKFDE_CHALLENGE_SLOT" -lt 1 ] || [ "$YKFDE_CHALLENGE_SLOT" -gt 2 ] && YKFDE_CHALLENGE_SLOT="2" + + local trial_nr + trial_nr=1 + while [ "$trial_nr" -le "$YKFDE_CRYPTSETUP_TRIALS" ]; do + ykfde_do_it && return 0 + trial_nr=$((trial_nr + 1)) + done + + # if we get here, we did NOT succeed: + ykfde_err 000 "$0 Failed!" + return 1 +} + +ykfde_err() { + local _rc + _rc="$?" + local code + code="$1" + local msg + msg="$2" + [ "$msg" ] && msg="ERROR $code [rc=$_rc]: $msg" || msg="ERROR $code [rc=$_rc]" + message "$msg" #exit 1; +} + +# assemble passphrase and run 'cryptsetup luksOpen' +ykfde_do_it() { + # key used to 'cryptsetup luksOpen' + local _ykfde_passphrase + _ykfde_passphrase="" + local _tmp + _tmp="" + local _rc + _rc="" + + # if we have a challenge + [ "$YKFDE_CHALLENGE" ] || [ "$YKFDE_CHALLENGE_PASSWORD_NEEDED" ] && ykfde_challenge_response + + if [ -z "$_ykfde_passphrase" ]; then + if [ "$YKFDE_CHALLENGE" ] || [ "$YKFDE_CHALLENGE_PASSWORD_NEEDED" ]; then + message " > Challenge-Response failed. Falling back to manual passphrase." + [ "$trial_nr" -le "$YKFDE_CRYPTSETUP_TRIALS" ] && message " Press ENTER to skip and retry Challenge-Response." + fi + + if [ "$YKFDE_USE_PLYMOUTH" ]; then + printf '%s' "$(plymouth ask-for-password --prompt="Enter passphrase" --dont-pause-progress)" + else + # shellcheck disable=SC2169 + printf '%s' "$(/lib/cryptsetup/askpass " Enter passphrase: ")" + fi + exit 0 + fi +} + +ykfde_challenge_response() { + local _yubikey_timeout + _yubikey_timeout="$YKFDE_CHALLENGE_YUBIKEY_INSERT_TIMEOUT" + local _yubikey_timeout_str + _yubikey_timeout_str="" + local _yubikey_detected + _yubikey_detected="" + local _yubikey_nfc_detected + _yubikey_nfc_detected="" + local _ykfde_response + _ykfde_response="" + # to determine if a timeout occurred + local _starttime + _starttime="" + local _endtime + _endtime="" + local _usedtime + _usedtime="" + local _tmp + _tmp="" + local _rc + _rc="" + + [ "$YKFDE_CHALLENGE_YUBIKEY_INSERT_TIMEOUT" -gt 0 ] && _yubikey_timeout_str="$YKFDE_CHALLENGE_YUBIKEY_INSERT_TIMEOUT seconds" + + _starttime="$(date +%s)" + message " > Waiting $_yubikey_timeout_str for YubiKey..." + + while [ -z "$_yubikey_detected" ] && [ -z "$_yubikey_nfc_detected" ]; do + _endtime="$(date +%s)" + _usedtime=$((_endtime - _starttime)) + [ "$DBG" ] && message " (used time:$_usedtime, timeout:$_yubikey_timeout) 'ykinfo -$YKFDE_CHALLENGE_SLOT': " + _tmp="$(ykinfo -"$YKFDE_CHALLENGE_SLOT" 2>&1)" + _rc=$? + [ "$DBG" ] && message "[$_rc] '$_tmp'" + if [ "$_rc" -eq 0 ]; then + _yubikey_detected=1 + fi + if [ "$_yubikey_timeout" -eq -1 ] || [ "$_usedtime" -le "$_yubikey_timeout" ]; then + sleep 0.5 + else + message " Timeout - Challenge-Response aborted." + # timeout + return 1 + fi + done + + [ "$YKFDE_CHALLENGE_PASSWORD_NEEDED" ] && YKFDE_CHALLENGE="" + while [ -z "$YKFDE_CHALLENGE" ]; do + # shellcheck disable=SC2169 + if [ "$YKFDE_USE_PLYMOUTH" ]; then + YKFDE_CHALLENGE="$(plymouth ask-for-password --prompt="Enter challenge" --dont-pause-progress)" + else + YKFDE_CHALLENGE="$(/lib/cryptsetup/askpass " Enter challenge: ")" + fi + done + + if [ "$_yubikey_detected" ]; then + while [ -z "$_ykfde_response" ]; do + [ "$DBG" ] && message " Running: 'ykchalresp -$YKFDE_CHALLENGE_SLOT $YKFDE_CHALLENGE'..." + message " Remember to touch the device if necessary." + YKFDE_CHALLENGE="$(printf %s "$YKFDE_CHALLENGE" | sha256sum | awk '{print $1}')" + _ykfde_response="$(printf %s "$YKFDE_CHALLENGE" | ykchalresp -"$YKFDE_CHALLENGE_SLOT" -i- | tr -d '\n')" + [ "$DBG" ] && message " Received response: '$_ykfde_response'" + done + fi + + if [ "$_ykfde_response" ]; then + if [ "$YKFDE_CHALLENGE_PASSWORD_NEEDED" ]; then + printf '%s' "$YKFDE_CHALLENGE$_ykfde_response" + else + printf '%s' "$_ykfde_response" + fi + exit 0 + fi +} + +run_hook + +exit 0 diff --git a/testrun.sh b/src/testrun.sh similarity index 100% rename from testrun.sh rename to src/testrun.sh