heads/initrd/bin/kexec-save-default
Thierry Laurion 150b95a034
TPM disk unlock key setup: Automatically override selected default boot option's initrd's crypttab file(s) to point to LUKS decryption key in injected cpio
- kexec-save-default extracts initrd crypttab files and creates /boot/kexec_initrd_crypttab_overrides.txt entries pointing to /secret.key
- kexec-insert-key applies /boot/kexec_initrd_crypttab_overrides.txt to replace initrd's crypttabs files pointing to inserted /secret.key through cpio
- Both scripts inform the user of applied magic on screen
2023-01-27 13:27:17 -05:00

188 lines
6.0 KiB
Bash
Executable File

#!/bin/sh
# Save these options to be the persistent default
set -e -o pipefail
. /tmp/config
. /etc/functions
while getopts "b:d:p:i:" arg; do
case $arg in
b) bootdir="$OPTARG" ;;
d) paramsdev="$OPTARG" ;;
p) paramsdir="$OPTARG" ;;
i) index="$OPTARG" ;;
esac
done
if [ -z "$bootdir" -o -z "$index" ]; then
die "Usage: $0 -b /boot -i menu_option "
fi
if [ -z "$paramsdev" ]; then
paramsdev="$bootdir"
fi
if [ -z "$paramsdir" ]; then
paramsdir="$bootdir"
fi
bootdir="${bootdir%%/}"
paramsdev="${paramsdev%%/}"
paramsdir="${paramsdir%%/}"
TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt"
ENTRY_FILE="$paramsdir/kexec_default.$index.txt"
HASH_FILE="$paramsdir/kexec_default_hashes.txt"
if [ ! -r "$TMP_MENU_FILE" ]; then
die "No menu options available, please run kexec-select-boot"
fi
entry=`head -n $index $TMP_MENU_FILE | tail -1`
if [ -z "$entry" ]; then
die "Invalid menu index $index"
fi
KEY_DEVICES="$paramsdir/kexec_key_devices.txt"
KEY_LVM="$paramsdir/kexec_key_lvm.txt"
save_key="n"
if [[ "$CONFIG_TPM" = "y" && "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" != "y" ]]; then
if [ ! -r "$KEY_DEVICES" ]; then
read \
-n 1 \
-p "Do you wish to add a disk encryption to the TPM [y/N]: " \
add_key_confirm
echo
if [ "$add_key_confirm" = "y" \
-o "$add_key_confirm" = "Y" ]; then
lvm_suggest="e.g. qubes_dom0 or blank"
devices_suggest="e.g. /dev/sda2 or blank"
save_key="y"
fi
else
read \
-n 1 \
-p "Do you want to reseal a disk key to the TPM [y/N]: " \
change_key_confirm
echo
if [ "$change_key_confirm" = "y" \
-o "$change_key_confirm" = "Y" ]; then
old_lvm_volume_group=""
if [ -r "$KEY_LVM" ]; then
old_lvm_volume_group=`cat $KEY_LVM` || true
old_key_devices=`cat $KEY_DEVICES \
| cut -d\ -f1 \
| grep -v "$old_lvm_volume_group" \
| xargs` || true
else
old_key_devices=`cat $KEY_DEVICES \
| cut -d\ -f1 | xargs` || true
fi
lvm_suggest="was '$old_lvm_volume_group'"
devices_suggest="was '$old_key_devices'"
save_key="y"
fi
fi
if [ "$save_key" = "y" ]; then
echo "+++ LVM volume groups (lvm vgscan): "
lvm vgscan || true
read \
-p "Encrypted LVM group? ($lvm_suggest): " \
lvm_volume_group
echo "+++ Block devices (blkid): "
blkid || true
read \
-p "Encrypted devices? ($devices_suggest): " \
key_devices
save_key_params="-s -p $paramsdev"
if [ -n "$lvm_volume_group" ]; then
save_key_params="$save_key_params -l $lvm_volume_group $key_devices"
else
save_key_params="$save_key_params $key_devices"
fi
echo "Running kexec-save-key with params: $save_key_params"
kexec-save-key $save_key_params \
|| die "Failed to save the disk key"
fi
fi
# try to switch to rw mode
mount -o rw,remount $paramsdev
if [ ! -d $paramsdir ]; then
mkdir -p $paramsdir \
|| die "Failed to create params directory"
fi
rm $paramsdir/kexec_default.*.txt 2>/dev/null || true
echo "$entry" > $ENTRY_FILE
( cd $bootdir && kexec-boot -b "$bootdir" -e "$entry" -f| \
xargs sha256sum > $HASH_FILE \
) || die "Failed to create hashes of boot files"
if [ ! -r $ENTRY_FILE -o ! -r $HASH_FILE ]; then
die "Failed to write default config"
fi
if [ "$save_key" = "y" ]; then
# logic to parse OS initrd to extract crypttab, its filepaths and its OS defined options
mkdir -p /tmp/initrd_extract
cd /tmp/initrd_extract
# Get initrd filename selected to be default initrd that OS could be using to configure LUKS on boot by deploying crypttab files
current_default_initrd=$(cat /boot/kexec_default_hashes.txt | grep initr | awk -F " " {'print $NF'} | sed 's/\.\//\/boot\//g')
# Get crypttab files paths from initrd
echo "Checking current selected default boot's $current_default_initrd for existing crypttab files..."
# First either decompress or use the original if it's not compressed
initrd_decompressed="/tmp/initrd_extract/initrd_decompressed.cpio"
zcat < "$current_default_initrd" > "$initrd_decompressed" 2> /dev/null || initrd_decompressed="$current_default_initrd"
crypttab_files=$(cpio --list --quiet < "$initrd_decompressed" | grep crypttab 2> /dev/null) || true
if [ ! -z "$crypttab_files" ]; then
echo "Extracting current selected default boot's $current_default_initrd for found crypttab files analysis..."
cpio -id --quiet < $initrd_decompressed $crypttab_files 2> /dev/null
rm -f $bootdir/kexec_initrd_crypttab_overrides.txt || true
#Parsing each crypttab file found
echo "$crypttab_files" | while read filepath; do
# Keep only non-commented lines
current_filepath_entries=$(cat "$filepath" | grep -v "^#")
# Modify each retained crypttab line to contain to be injected /secret.key at next default boots
modified_filepath_entries=$(echo "$current_filepath_entries" | sed 's/none/\/secret.key/g')
echo "$modified_filepath_entries" | while read single_modified_filepath_entry; do
# Append each found filepath:entry into additional kexec_ file that will be part of detached signed digest
echo "$filepath:$single_modified_filepath_entry" >> $bootdir/kexec_initrd_crypttab_overrides.txt
done
done
cd - > /dev/null
#insert current default boot's initrd crypttab locations into tracking file to be overwritten into initramfs at kexec-inject-key
echo "The following OS crypttab file:entry were modified from default boot's initrd:"
cat $bootdir/kexec_initrd_crypttab_overrides.txt
echo "Heads added /secret.key in those entries and saved them under $bootdir/kexec_initrd_crypttab_overrides.txt"
echo "Those overrides will be part of detached signed digests and used to prepare cpio injected at kexec of selected default boot entry."
else
echo "No crypttab file found in extracted initrd. Removing $bootdir/kexec_initrd_crypttab_overrides.txt"
rm -f "$bootdir/kexec_initrd_crypttab_overrides.txt" || true
fi
# Cleanup
rm -rf /tmp/initrd_extract || true
fi
# sign and auto-roll config counter
extparam=
if [ "$CONFIG_TPM" = "y" ]; then
extparam=-r
fi
kexec-sign-config -p $paramsdir $extparam \
|| die "Failed to sign default config"
# switch back to ro mode
mount -o ro,remount $paramsdev