Skip to content

Commit

Permalink
refactor: Rewrite luks tpm2 script. (#302)
Browse files Browse the repository at this point in the history
* refactor: Rewrite luks tpm2 script.

The previous version of the tpm2 script did not fail out when
encountering unsupported configurations. This script is narrowly focused
at enabling tpm2 decryption for root devices. By default we expect this
to be configured via the installer.

This script will now fail out if it cannot find the disk. The disk is
determined via the kernel commandline instead of /etc/crypttab. It still
only supports a single disk. It now also provides hints on why the
script has failed and the commands to run to disable and/or enable.

* refactor: Provide more information with script

* refactor: Include more safety checks

* fix: remove unnecessary luks check

---------

Co-authored-by: Benjamin Sherman <[email protected]>
  • Loading branch information
m2Giles and bsherman authored Jul 7, 2024
1 parent 8ff52f4 commit 6ff6bef
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 44 deletions.
60 changes: 48 additions & 12 deletions build/ublue-os-luks/luks-disable-tpm2-autounlock
Original file line number Diff line number Diff line change
@@ -1,45 +1,81 @@
#!/bin/bash
## disable auto-unlock LUKS2 encrypted root on Fedora/Silverblue/maybe others
set -u
set -euo pipefail

[ "$UID" -eq 0 ] || { echo "This script must be run as root."; exit 1;}

read -p "This will modify your system and disable TPM2 auto-unlock of your LUKS partition! Are you sure you've read the script and are good with this? " -n 1 -r
echo "This script utilizes systemd-cryptenroll for removing tpm2 auto-unlock."
echo "You can review systemd-cryptenroll's manpage for more information."
read -p "This will modify your system and disable TPM2 auto-unlock of your LUKS partition! Are you sure you are good with this? " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
[[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell
[[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell
fi

DISK_UUID=$(sudo awk '{ print $2 }' /etc/crypttab | cut -d= -f2)
## Inspect Kernel Cmdline for rd.luks.uuid
RD_LUKS_UUID="$(xargs -n1 -a /proc/cmdline | grep rd.luks.uuid | cut -d = -f 2)"

# Check to make sure cmdline rd.luks.uuid exists
if [[ -z ${RD_LUKS_UUID:-} ]]; then
printf "LUKS device not defined on Kernel Commandline.\n"
printf "This is not supported by this script.\n"
printf "Exiting...\n"
exit 1
fi

# Check to make sure that the specified cmdline uuid exists.
if ! grep -q "${RD_LUKS_UUID}" <<< "$(lsblk)" ; then
printf "LUKS device not listed in block devices.\n"
printf "Exiting...\n"
exit 1
fi

# Cut off the luks-
LUKS_PREFIX="luks-"
if grep -q ^${LUKS_PREFIX} <<< "${RD_LUKS_UUID}"; then
DISK_UUID=${RD_LUKS_UUID#"$LUKS_PREFIX"}
else
echo "LUKS UUID format mismatch."
echo "Exiting..."
exit 1
fi

# Specify Crypt Disk by-uuid
CRYPT_DISK="/dev/disk/by-uuid/$DISK_UUID"

# Check to make sure crypt disk exists
if [[ ! -L "$CRYPT_DISK" ]]; then
printf "LUKS device not listed in block devices.\n"
printf "Exiting...\n"
exit 1
fi

## Restore the crypttab
cp -a /etc/crypttab /etc/crypttab.working-before-disable-tpm2
if [ -f /etc/crypttab.known-good ]; then
echo "Restoring /etc/crypttab.known-good to original /etc/crypttab"
mv /etc/crypttab.known-good /etc/crypttab
else
echo "No /etc/crypttab.known-good found to restore"
fi

## Wipe luks slot
cryptsetup luksDump $CRYPT_DISK | grep systemd-tpm2 > /dev/null
if [ 0 -eq $? ]; then
if cryptsetup luksDump "$CRYPT_DISK" | grep systemd-tpm2 > /dev/null; then
echo "Wiping systemd-tpm2 from LUKS on $CRYPT_DISK"
systemd-cryptenroll --wipe-slot=tpm2 $CRYPT_DISK
systemd-cryptenroll --wipe-slot=tpm2 "$CRYPT_DISK"
else
echo "No systemd-tpm2 found in LUKS to wipe"
fi

## Disable initramfs
rpm-ostree initramfs | grep tpm2 > /dev/null
if [ 0 -eq $? ]; then
if rpm-ostree initramfs | grep tpm2 > /dev/null; then
echo "WARNING: if you configured initramfs for anything other than TPM2, this wipes that too..."
echo "here's a printout:"
rpm-ostree initramfs
echo
echo "Disabling rpm-ostree initramfs..."
rpm-ostree initramfs --disable
else
echo "TPM2 was not found in 'rpm-ostree initramfs'..."
echo "TPM2 is not configured in 'rpm-ostree initramfs'..."
fi

echo "TPM2 auto-unlock disabled..."
echo "To reenroll TPM2 auto unlock please run ujust setup-luks-tpm-unlock..."
81 changes: 50 additions & 31 deletions build/ublue-os-luks/luks-enable-tpm2-autounlock
Original file line number Diff line number Diff line change
@@ -1,57 +1,76 @@
#!/bin/bash
## setup auto-unlock LUKS2 encrypted root on Fedora/Silverblue/maybe others
set -u
set -eou pipefail

[ "$UID" -eq 0 ] || { echo "This script must be run as root."; exit 1;}

read -p "This will modify your system and enable TPM2 auto-unlock of your LUKS partition! Are you sure you've read the script and are good with this? " -n 1 -r
echo "This script uses systemd-cryptenroll to enable TPM2 auto-unlock."
echo "You can review systemd-cryptenroll's manpage for more information."
echo "This script will modify your system."
echo "It will enable TPM2 auto-unlock of your LUKS partition for your root device!"
echo "It will bind to PCR 7 only which is tied to your secureboot state."
read -p "Are you sure are good with this and want to enable TPM2 auto-unlock? " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
[[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell
[[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell
fi

## Inspect crypttab to find disk info, should look like this
#sudo cat /etc/crypttab
#luks-912462a2-39ce-abcd-1234-89c6c0304cb4 UUID=912462a2-39ce-abcd-1234-89c6c0304cb4 none discard
DISK_UUID=$(sudo awk '{ print $2 }' /etc/crypttab | cut -d= -f2)
CRYPT_DISK="/dev/disk/by-uuid/$DISK_UUID"
## Inspect Kernel Cmdline for rd.luks.uuid
RD_LUKS_UUID="$(xargs -n1 -a /proc/cmdline | grep rd.luks.uuid | cut -d = -f 2)"

## Backup the crypttab
if [ -f /etc/crypttab.known-good ]; then
echo "Our backup already exists at /etc/crypttab.known-good\nExiting..."
[[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1
# Check to make sure cmdline rd.luks.uuid exists
if [[ -z ${RD_LUKS_UUID:-} ]]; then
printf "LUKS device not defined on Kernel Commandline.\n"
printf "This is not supported by this script.\n"
printf "Exiting...\n"
exit 1
fi
cp -a /etc/crypttab /etc/crypttab.known-good

## modify the crypttab
grep tpm2-device /etc/crypttab > /dev/null
if [ 0 -eq $? ]; then
echo "TPM2 already present in /etc/crypttab. Exiting..."
[[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1
# Check to make sure that the specified cmdline uuid exists.
if ! grep -q "${RD_LUKS_UUID}" <<< "$(lsblk)" ; then
printf "LUKS device not listed in block devices.\n"
printf "Exiting...\n"
exit 1
fi
sed -i "s/discard/discard,tpm2-device=auto/" /etc/crypttab

cryptsetup luksDump $CRYPT_DISK | grep systemd-tpm2 > /dev/null
if [ 0 -eq $? ]; then
KEYSLOT=$(cryptsetup luksDump $CRYPT_DISK|grep -A23 systemd-tpm2|grep Keyslot|awk '{print $2}')
echo "TPM2 already present in LUKS Keyslot $KEYSLOT of $CRYPT_DISK. Exiting..."
[[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1
# Cut off the luks-
LUKS_PREFIX="luks-"
if grep -q ^${LUKS_PREFIX} <<< "${RD_LUKS_UUID}"; then
DISK_UUID=${RD_LUKS_UUID#"$LUKS_PREFIX"}
else
echo "LUKS UUID format mismatch."
echo "Exiting..."
exit 1
fi

# Specify Crypt Disk by-uuid
CRYPT_DISK="/dev/disk/by-uuid/$DISK_UUID"

# Check to make sure crypt disk exists
if [[ ! -L "$CRYPT_DISK" ]]; then
printf "LUKS device not listed in block devices.\n"
printf "Exiting...\n"
exit 1
fi

if cryptsetup luksDump "$CRYPT_DISK" | grep systemd-tpm2 > /dev/null; then
KEYSLOT=$(cryptsetup luksDump "$CRYPT_DISK"|grep -A29 systemd-tpm2|grep Keyslot|awk '{print $2}')
echo "TPM2 already present in LUKS Keyslot $KEYSLOT of $CRYPT_DISK."
echo "Remove the existing TPM2 enrollment with ujust remove-luks-tpm2-autounlock"
echo "Exiting..."
[[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
fi

## Run crypt enroll
echo "Enrolling TPM2 unlock requires your existing LUKS2 unlock password"
echo
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 $CRYPT_DISK
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 "$CRYPT_DISK"


lsinitrd 2>&1 | grep -q tpm2-tss > /dev/null
if [ 1 -eq $? ]; then
if lsinitrd 2>&1 | grep -q tpm2-tss > /dev/null; then
## add tpm2-tss to initramfs
rpm-ostree initramfs | grep tpm2 > /dev/null
if [ 0 -eq $? ]; then
if rpm-ostree initramfs | grep tpm2 > /dev/null; then
echo "TPM2 already present in rpm-ostree initramfs config."
rpm-ostree initramfs
echo
echo "Re-running initramfs to pickup changes above."
fi
rpm-ostree initramfs --enable --arg=--force-add --arg=tpm2-tss
Expand Down
6 changes: 5 additions & 1 deletion build/ublue-os-luks/ublue-os-luks.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Name: ublue-os-luks
Packager: ublue-os
Vendor: ublue-os
Version: 0.2
Version: 0.3
Release: 1%{?dist}
Summary: ublue-os scripts for simplified LUKS usage
License: MIT
Expand Down Expand Up @@ -31,6 +31,10 @@ install -Dm644 %{SOURCE2} %{buildroot}/%{_exec_prefix}/lib/dracut/dracut.conf.d
%attr(0644,root,root) %{_exec_prefix}/lib/dracut/dracut.conf.d/90-ublue-luks.conf

%changelog
* Thu Jul 04 2024 m2Giles <[email protected]> - 0.3
- Rewrite enable script to fail out if disk is not found
- LUKs disk is determined from kernel commandline instead of /etc/crypttab

* Sat Jun 29 2024 Benjamin Sherman <[email protected]> - 0.2
- Add tpm, fido2, pkcs11 to dracut config enabling initramfs LUKS unlock options

Expand Down

0 comments on commit 6ff6bef

Please sign in to comment.