diff --git a/initrd/bin/kexec-insert-key b/initrd/bin/kexec-insert-key index 5b4020ec..8894da12 100755 --- a/initrd/bin/kexec-insert-key +++ b/initrd/bin/kexec-insert-key @@ -30,11 +30,12 @@ fi cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \ || die "LUKS measure failed" -# Unpack the initrd and fixup the /etc/crypttab +# Unpack the initrd and fixup the crypttab # this is a hack to split it into two parts since # we know that the first 0x3400 bytes are the microcode INITRD_DIR=/tmp/secret/initrd SECRET_CPIO=/tmp/secret/initrd.cpio +bootdir=$(dirname "$INITRD") mkdir -p "$INITRD_DIR/etc" # Attempt to unseal the disk key from the TPM @@ -73,9 +74,29 @@ dd if="$INITRD" of="$SECRET_CPIO" bs=512 conv=sync \ || die "Failed to copy initrd to /tmp" if [ "$unseal_failed" = "n" ]; then - # overwrite /etc/crypttab to mirror the behavior for in seal-key - for uuid in `cat "$TMP_KEY_DEVICES" | cut -d\ -f2`; do - echo "luks-$uuid UUID=$uuid /secret.key" >> "$INITRD_DIR/etc/crypttab" - 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 diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index 2e0b3d2a..23ddd46b 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -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