mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-30 09:48:56 +00:00
b500505312
Most logic throughout Heads doesn't need to know TPM1 versus TPM2 (and shouldn't, the differences should be localized). Some checks were incorrect and are fixed by this change. Most checks are now unchanged relative to master. There are not that many places outside of tpmr that need to differentiate TPM1 and TPM2. Some of those are duplicate code that should be consolidated (seal-hotpkey, unseal-totp, unseal-hotp), and some more are probably good candidates for abstracting in tpmr so the business logic doesn't have to know TPM1 vs. TPM2. Previously, CONFIG_TPM could be variously 'y', 'n', or empty. Now it is always 'y' or 'n', and 'y' means "any TPM". Board configs are unchanged, setting CONFIG_TPM2_TOOLS=y implies CONFIG_TPM=y so this doesn't have to be duplicated and can't be mistakenly mismatched. There were a few checks for CONFIG_TPM = n that only coincidentally worked for TPM2 because CONFIG_TPM was empty (not 'n'). This test is now OK, but the checks were also cleaned up to '!= "y"' for robustness. Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
199 lines
6.3 KiB
Bash
Executable File
199 lines
6.3 KiB
Bash
Executable File
#!/bin/bash
|
|
# Save these options to be the persistent default
|
|
set -e -o pipefail
|
|
. /tmp/config
|
|
. /etc/functions
|
|
|
|
TRACE "Under /bin/kexec-save-default"
|
|
|
|
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"
|
|
PRIMHASH_FILE="$paramsdir/kexec_primhdl_hash.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 "LVM group containing Encrypted LVs (retype to keep)? ($lvm_suggest): " \
|
|
lvm_volume_group
|
|
|
|
echo "+++ Block devices (blkid): "
|
|
blkid || true
|
|
|
|
read \
|
|
-p "Encrypted devices (retype to keep)? ($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
|
|
|
|
if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
|
|
sha256sum /tmp/primary.handle > "$PRIMHASH_FILE" \
|
|
|| die "ERROR: Failed to Hash TPM2 primary key handle!"
|
|
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
|
|
if [ "$CONFIG_IGNORE_ROLLBACK" != "y" ]; then
|
|
extparam=-r
|
|
fi
|
|
fi
|
|
kexec-sign-config -p $paramsdir $extparam \
|
|
|| die "Failed to sign default config"
|
|
|
|
# switch back to ro mode
|
|
mount -o ro,remount $paramsdev
|