mirror of
https://github.com/linuxboot/heads.git
synced 2025-04-07 19:34:26 +00:00
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
This commit is contained in:
parent
8a60930c6b
commit
150b95a034
@ -35,19 +35,8 @@ cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \
|
||||
# we know that the first 0x3400 bytes are the microcode
|
||||
INITRD_DIR=/tmp/secret/initrd
|
||||
SECRET_CPIO=/tmp/secret/initrd.cpio
|
||||
|
||||
# Not all distro put crypttab under /etc/ within initramfs, but finding it at
|
||||
# runtime needs unpacking, which may be hard to do, so it is made overridable
|
||||
# with a file at /boot/kexec_initrd_crypttab_path.txt, whose content could be
|
||||
# obtained with $ cpio -t < ${uncompressed_initrd} | grep crypttab .
|
||||
|
||||
bootdir=$(dirname "$INITRD")
|
||||
if [ -r $bootdir/kexec_initrd_crypttab_path.txt ]; then
|
||||
crypttab_path=$(cat $bootdir/kexec_initrd_crypttab_path.txt)
|
||||
else
|
||||
crypttab_path=etc/crypttab
|
||||
fi
|
||||
mkdir -p "$INITRD_DIR/$(dirname $crypttab_path)"
|
||||
mkdir -p "$INITRD_DIR/etc"
|
||||
|
||||
# Attempt to unseal the disk key from the TPM
|
||||
# should we give this some number of tries?
|
||||
@ -84,18 +73,30 @@ echo '+++ Building initrd'
|
||||
dd if="$INITRD" of="$SECRET_CPIO" bs=512 conv=sync \
|
||||
|| die "Failed to copy initrd to /tmp"
|
||||
|
||||
# The "target" field of the record within the crypttab stored in the root
|
||||
# file system for the luks container which is going to be unlocked via
|
||||
# kexec-insert-key should be modified into the same "luks-$uuid" format,
|
||||
# otherwise the boot sequence will get stuck when OS is trying to unlock them
|
||||
# again, in order to map them according to "target" fields written in the
|
||||
# crypttab stored in the root fs.
|
||||
|
||||
if [ "$unseal_failed" = "n" ]; then
|
||||
# overwrite crypttab to mirror the behavior for in seal-key
|
||||
for uuid in `cat "$TMP_KEY_DEVICES" | cut -d\ -f2`; do
|
||||
# In Debian, the "luks" option at last should not be omitted
|
||||
echo "luks-$uuid UUID=$uuid /secret.key luks" >> "$INITRD_DIR/$crypttab_path"
|
||||
done
|
||||
# kexec-save-default might have created crypttab overrides to be injected in initramfs through additional cpio
|
||||
if [ -r "$bootdir/kexec_initrd_crypttab_overrides.txt" ]; then
|
||||
echo "$bootdir/kexec_initrd_crypttab_overrides.txt found..."
|
||||
echo "Preparing initramfs crypttab overrides as defined under $bootdir/kexec_initrd_crypttab_overrides.txt to be injected through cpio at next kexec call..."
|
||||
# kexec-save-default has found crypttab files under initrd and saved them
|
||||
cat "$bootdir/kexec_initrd_crypttab_overrides.txt" | while read line; do
|
||||
crypttab_file=$(echo "$line" | awk -F ':' {'print $1'})
|
||||
crypttab_entry=$(echo "$line" | awk -F ':' {'print $NF'})
|
||||
# Replace each initrd crypttab file with modified entry containing /secret.key path
|
||||
mkdir -p "$INITRD_DIR/$(dirname $crypttab_file)"
|
||||
echo "$crypttab_entry" | tee -a "$INITRD_DIR/$crypttab_file" > /dev/null
|
||||
echo "initramfs's $crypttab_file will be overriden with $crypttab_entry"
|
||||
done
|
||||
else
|
||||
# No crypttab files were found under selected default boot option's initrd file
|
||||
crypttab_file="etc/crypttab"
|
||||
mkdir -p "$INITRD_DIR/$(dirname $crypttab_file)"
|
||||
# overwrite crypttab to mirror behavior of seal-key
|
||||
echo "The following /etc/crypttab lines will be passed through cpio into kexec call for default boot option:"
|
||||
for uuid in `cat "$TMP_KEY_DEVICES" | cut -d\ -f2`; do
|
||||
# NOTE: discard operation (TRIM) is activated by default if no crypptab found in initrd
|
||||
echo "luks-$uuid UUID=$uuid /secret.key luks,discard" | tee -a "$INITRD_DIR/$crypttab_file"
|
||||
done
|
||||
fi
|
||||
( cd "$INITRD_DIR" ; find . -type f | cpio -H newc -o ) >> "$SECRET_CPIO"
|
||||
fi
|
||||
|
@ -129,6 +129,52 @@ 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user