mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-18 20:47:55 +00:00
TPM Disk Unlock Key sealing/renewal cleanup (Triggered automatically when resealing TOTP)
Changes: - As per master: when TOTP cannot unseal TOTP, user is prompted to either reset or regenerate TOTP - Now, when either is done and a previous TPM Disk Unlock Key was setuped, the user is guided into: - Regenerating checksums and signing them - Regenerating TPM disk Unlock Key and resealing TPM disk Unlock Key with passphrase into TPM - LUKS header being modified, user is asked to resign kexec.sig one last time prior of being able to default boot - When no previous Disk Unlock Key was setuped, the user is guided into: - The above, plus - Detection of LUKS containers,suggesting only relevant partitions - Addition of TRACE and DEBUG statements to troubleshoot actual vs expected behavior while coding - Were missing under TPM Disk Unlock Key setup codepaths - Fixes for #645 : We now check if only one slots exists and we do not use it if its slot1. - Also shows in DEBUG traces now Unrelated staged changes - ash_functions: warn and die now contains proper spacing and eye attaction - all warn and die calls modified if containing warnings and too much punctuation - unify usage of term TPM Disk Unlock Key and Disk Recovery Key
This commit is contained in:
parent
45a4f9d0f3
commit
4910c1188f
2
FAQ.md
2
FAQ.md
@ -110,7 +110,7 @@ to deceive you and steal your login password? Maybe! It wouldn't get
|
||||
your disk password, which is perhaps an improvement.
|
||||
|
||||
|
||||
Disk key in TPM or user passphrase?
|
||||
Disk key in TPM (TPM Disk Unlock Key) or user passphrase?
|
||||
---
|
||||
Depends on your threat model. With the disk key in the TPM an attacker
|
||||
would need to have the entire machine (or a backdoor in the TPM)
|
||||
|
@ -14,5 +14,5 @@ sha256sum /tmp/kgpe-d16-openbmc.rom
|
||||
flashrom --programmer="ast1100:spibus=2,cpu=reset" -c "S25FL128P......0" -w /tmp/kgpe-d16-openbmc.rom \
|
||||
|| die "$ROM: Flash failed"
|
||||
|
||||
warn "Reboot and hopefully it works..."
|
||||
warn "Reboot and hopefully it works"
|
||||
exit 0
|
||||
|
@ -173,7 +173,8 @@ generate_totp_hotp()
|
||||
# clear screen
|
||||
printf "\033c"
|
||||
else
|
||||
warn "Unsealing TOTP/HOTP secret from previous sealed measurements failed. Try "Generate new HOTP/TOTP secret" option if you updated firmware content."
|
||||
warn "Unsealing TOTP/HOTP secret from previous sealed measurements failed"
|
||||
warn "Try "Generate new HOTP/TOTP secret" option if you updated firmware content"
|
||||
fi
|
||||
}
|
||||
|
||||
@ -229,6 +230,7 @@ update_totp()
|
||||
if (whiptail $BG_COLOR_WARNING --title 'Generate new TOTP/HOTP secret' \
|
||||
--yesno "This will erase your old secret and replace it with a new one!\n\nDo you want to proceed?" 0 80) then
|
||||
generate_totp_hotp && update_totp && BG_COLOR_MAIN_MENU=""
|
||||
reseal_tpm_disk_decryption_key
|
||||
fi
|
||||
;;
|
||||
i )
|
||||
@ -237,6 +239,7 @@ update_totp()
|
||||
;;
|
||||
p )
|
||||
reset_tpm && update_totp && BG_COLOR_MAIN_MENU=""
|
||||
reseal_tpm_disk_decryption_key
|
||||
;;
|
||||
x )
|
||||
recovery "User requested recovery shell"
|
||||
@ -298,6 +301,7 @@ update_hotp()
|
||||
if (whiptail $BG_COLOR_WARNING --title 'Generate new TOTP/HOTP secret' \
|
||||
--yesno "This will erase your old secret and replace it with a new one!\n\nDo you want to proceed?" 0 80) then
|
||||
generate_totp_hotp && BG_COLOR_MAIN_MENU=""
|
||||
reseal_tpm_disk_decryption_key
|
||||
fi
|
||||
;;
|
||||
i )
|
||||
@ -523,9 +527,11 @@ show_tpm_totp_hotp_options_menu()
|
||||
case "$option" in
|
||||
g )
|
||||
generate_totp_hotp
|
||||
reseal_tpm_disk_decryption_key
|
||||
;;
|
||||
r )
|
||||
reset_tpm
|
||||
reseal_tpm_disk_decryption_key
|
||||
;;
|
||||
t )
|
||||
prompt_totp_mismatch
|
||||
@ -571,8 +577,10 @@ reset_tpm()
|
||||
# now that the TPM is reset, remove invalid TPM counter files
|
||||
mount_boot
|
||||
mount -o rw,remount /boot
|
||||
warn "Removing rollback and primary handle hash under /boot"
|
||||
rm -f /boot/kexec_rollback.txt
|
||||
rm -f /boot/kexec_primhdl_hash.txt
|
||||
#TODO: When primhdl_hash is gone but not recreated and signed: fail at TPM Disk Unlock Key for TPM2....
|
||||
|
||||
# create Heads TPM counter before any others
|
||||
check_tpm_counter /boot/kexec_rollback.txt "" "$key_password" \
|
||||
|
@ -158,7 +158,9 @@ if [ "$CONFIG_DEBUG_OUTPUT" = "y" ];then
|
||||
#Repeat kexec command that will be executed since in debug
|
||||
DEBUG "kexeccmd= $kexeccmd"
|
||||
|
||||
read -n 1 -p "[DEBUG] Continue booting? [Y/n]: " debug_boot_confirm
|
||||
#Ask user if they want to continue booting without echoing back the input (-s)
|
||||
read -s -n 1 -p "[DEBUG] Continue booting? [Y/n]: " debug_boot_confirm
|
||||
echo
|
||||
if [ "${debug_boot_confirm^^}" = N ]; then
|
||||
# abort
|
||||
die "Boot aborted"
|
||||
|
@ -8,10 +8,10 @@ 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" ;;
|
||||
b) bootdir="$OPTARG" ;;
|
||||
d) paramsdev="$OPTARG" ;;
|
||||
p) paramsdir="$OPTARG" ;;
|
||||
i) index="$OPTARG" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
@ -35,21 +35,53 @@ 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"
|
||||
KEY_DEVICES="$paramsdir/kexec_key_devices.txt"
|
||||
KEY_LVM="$paramsdir/kexec_key_lvm.txt"
|
||||
|
||||
|
||||
lvm_suggest=$(lvm vgscan | awk -F '"' {'print $1'} | tail -n +2)
|
||||
num_lvm=$(echo "$lvm_suggest" | wc -l)
|
||||
if [ "$num_lvm" -eq 1 ] && [ -n "$lvm_suggest" ]; then
|
||||
lvm_volume_group="$lvm_suggest"
|
||||
elif [ -z "$lvm_suggest" ]; then
|
||||
num_lvm=0
|
||||
fi
|
||||
DEBUG "LVM num_lvm: $num_lvm, lvm_suggest: $lvm_suggest"
|
||||
|
||||
# get all LUKS container devices
|
||||
devices_suggest=$(blkid | cut -d ':' -f 1 | while read device; do
|
||||
cryptsetup isLuks "$device"
|
||||
if [ $(echo $?) == 0 ]; then echo "$device"; fi
|
||||
done | sort)
|
||||
num_devices=$(echo "$devices_suggest" | wc -l)
|
||||
|
||||
if [ "$num_devices" -eq 1 ] && [ -s "$devices_suggest" ]; then
|
||||
key_devices=$devices_suggest
|
||||
else
|
||||
devices_suggest=$(echo $devices_suggest)
|
||||
fi
|
||||
DEBUG "LUKS num_devices: $num_devices, devices_suggest: $devices_suggest"
|
||||
|
||||
if [ "$num_lvm" -eq 0 ] && [ "$num_devices" -eq 0 ]; then
|
||||
#No encrypted partition found.
|
||||
no_encrypted_partition=1
|
||||
fi
|
||||
|
||||
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`
|
||||
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" ] && [ "$CONFIG_BASIC" != y ]; then
|
||||
DEBUG "TPM is enabled and TPM_NO_LUKS_DISK_UNLOCK is not set"
|
||||
DEBUG "Checking if a a TPM Disk Unlock Key was previously setuped from $KEY_DEVICES"
|
||||
if [ ! -r "$KEY_DEVICES" ]; then
|
||||
DEBUG "No previous TPM Disk Unlock Key was setuped for LUKS devices, confirming to add a disk encryption to the TPM"
|
||||
read \
|
||||
-n 1 \
|
||||
-p "Do you wish to add a disk encryption to the TPM [y/N]: " \
|
||||
@ -58,11 +90,11 @@ if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" != "y" ] && [
|
||||
|
||||
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"
|
||||
DEBUG "User confirmed to add a disk encryption to the TPM"
|
||||
save_key="y"
|
||||
fi
|
||||
else
|
||||
DEBUG "Previous TPM Disk Unlock Key was setuped for LUKS devices"
|
||||
read \
|
||||
-n 1 \
|
||||
-p "Do you want to reseal a disk key to the TPM [y/N]: " \
|
||||
@ -73,36 +105,85 @@ if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" != "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
|
||||
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
|
||||
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'"
|
||||
lvm_suggest="$old_lvm_volume_group"
|
||||
devices_suggest="$old_key_devices"
|
||||
save_key="y"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$save_key" = "y" ]; then
|
||||
echo "+++ LVM volume groups (lvm vgscan): "
|
||||
lvm vgscan || true
|
||||
if [ -n "$old_key_devices" ] || [ -n "$old_lvm_volume_group" ]; then
|
||||
DEBUG "Previous TPM Disk Unlock Key was setuped for LUKS devices $old_key_devices $old_lvm_volume_group"
|
||||
read \
|
||||
-n 1 \
|
||||
-p "Do you want to reuse configured Encrypted LVM groups/Block devices? (Y/n):" \
|
||||
reuse_past_devices
|
||||
echo
|
||||
if [ "$reuse_past_devices" = "y" ] || [ "$reuse_past_devices" = "Y" ] || [ -z "$reuse_past_devices" ]; then
|
||||
if [ -z "$key_devices" ] && [ -n "$old_key_devices" ]; then
|
||||
key_devices="$old_key_devices"
|
||||
fi
|
||||
if [ -z "$lvm_volume_group" ] && [ -n "$old_lvm_volume_group" ]; then
|
||||
lvm_volume_group="$old_lvm_volume_group"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
DEBUG "No previous TPM Disk Unlock Key was setuped for LUKS devices, setting up new ones"
|
||||
if [ "$num_lvm" -gt 1 ]; then
|
||||
DEBUG "Multiple LVM groups found"
|
||||
//untested
|
||||
selected_lvmdev_not_existing=1
|
||||
while [ $selected_lvmdev_not_existing -ne 0 ]; do
|
||||
{
|
||||
read \
|
||||
-p "Encrypted LVM group? choose between: '$lvm_suggest': " \
|
||||
lvm_volume_group
|
||||
|
||||
read \
|
||||
-p "LVM group containing Encrypted LVs (retype to keep)? ($lvm_suggest): " \
|
||||
lvm_volume_group
|
||||
result=$(echo "$lvm_suggest" | grep -q "$lvm_volume_group") || selected_lvmdev_not_existing=1
|
||||
if [ $? == 0 ]; then
|
||||
selected_lvmdev_not_existing=0
|
||||
fi
|
||||
}
|
||||
done
|
||||
elif [ "$num_lvm" -eq 1 ] && [ -s $lvm_suggest ]; then
|
||||
echo "Single Encrypted LVM group found at $lvm_suggest."
|
||||
lvm_volume_group=$lvm_suggest
|
||||
else
|
||||
echo "No encrypted LVM Group found."
|
||||
fi
|
||||
|
||||
echo "+++ Block devices (blkid): "
|
||||
blkid || true
|
||||
if [ "$num_devices" -gt 1 ]; then
|
||||
DEBUG "Multiple LUKS devices found"
|
||||
selected_luksdev_not_existing=1
|
||||
while [ $selected_luksdev_not_existing -ne 0 ]; do
|
||||
{
|
||||
read \
|
||||
-p "Encrypted devices? (choose between: '$devices_suggest'): " \
|
||||
key_devices
|
||||
|
||||
read \
|
||||
-p "Encrypted devices (retype to keep)? ($devices_suggest): " \
|
||||
key_devices
|
||||
result=$(echo "$devices_suggest" | grep -q "$key_devices") || selected_luksdev_not_existing=1
|
||||
if [ $? == 0 ]; then
|
||||
selected_luksdev_not_existing=0
|
||||
fi
|
||||
}
|
||||
done
|
||||
elif [ "$num_devices" -eq 1 ]; then
|
||||
echo "Single Encrypted Disk found at $devices_suggest."
|
||||
key_devices=$devices_suggest
|
||||
else
|
||||
echo "No encrypted devices found."
|
||||
fi
|
||||
fi
|
||||
|
||||
save_key_params="-s -p $paramsdev"
|
||||
if [ -n "$lvm_volume_group" ]; then
|
||||
@ -110,9 +191,8 @@ if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" != "y" ] && [
|
||||
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"
|
||||
kexec-save-key $save_key_params ||
|
||||
die "Failed to save the disk key"
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -120,19 +200,20 @@ fi
|
||||
mount -o rw,remount $paramsdev
|
||||
|
||||
if [ ! -d $paramsdir ]; then
|
||||
mkdir -p $paramsdir \
|
||||
|| die "Failed to create params directory"
|
||||
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!"
|
||||
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 \
|
||||
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"
|
||||
@ -144,19 +225,19 @@ if [ "$save_key" = "y" ]; then
|
||||
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
|
||||
|
||||
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
|
||||
cpio -id --quiet $crypttab_files <$initrd_decompressed 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
|
||||
@ -165,7 +246,7 @@ if [ "$save_key" = "y" ]; then
|
||||
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
|
||||
echo "$filepath:$single_modified_filepath_entry" >>$bootdir/kexec_initrd_crypttab_overrides.txt
|
||||
done
|
||||
done
|
||||
|
||||
@ -189,14 +270,14 @@ fi
|
||||
|
||||
# sign and auto-roll config counter
|
||||
extparam=
|
||||
if [ "$CONFIG_TPM" = "y" ];then
|
||||
if [ "$CONFIG_TPM" = "y" ]; then
|
||||
if [ "$CONFIG_IGNORE_ROLLBACK" != "y" ]; then
|
||||
extparam=-r
|
||||
fi
|
||||
fi
|
||||
if [ "$CONFIG_BASIC" != "y" ]; then
|
||||
kexec-sign-config -p $paramsdir $extparam \
|
||||
|| die "Failed to sign default config"
|
||||
kexec-sign-config -p $paramsdir $extparam ||
|
||||
die "Failed to sign default config"
|
||||
fi
|
||||
# switch back to ro mode
|
||||
mount -o ro,remount $paramsdev
|
||||
|
@ -1,5 +1,9 @@
|
||||
#!/bin/bash
|
||||
# Generate a TPM key used to unlock LUKS disks
|
||||
|
||||
. /etc/functions
|
||||
|
||||
TRACE "kexec-save-key: start"
|
||||
set -e -o pipefail
|
||||
. /etc/functions
|
||||
|
||||
@ -13,20 +17,28 @@ while getopts "sp:d:l:" arg; do
|
||||
l) lvm_volume_group="$OPTARG" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
DEBUG "kexec-save-key prior of parsing: paramsdir: $paramsdir, paramsdev: $paramsdev, lvm_volume_group: $lvm_volume_group"
|
||||
|
||||
shift `expr $OPTIND - 1`
|
||||
key_devices="$@"
|
||||
|
||||
DEBUG "kexec-save-key: key_devices: $key_devices"
|
||||
|
||||
if [ -z "$paramsdir" ]; then
|
||||
die "Usage: $0 [-s] -p /boot [-l qubes_dom0] [/dev/sda2 /dev/sda5 ...] "
|
||||
fi
|
||||
|
||||
if [ -z "$paramsdev" ]; then
|
||||
paramsdev="$paramsdir"
|
||||
DEBUG "kexec-save-key: paramsdev modified to : $paramsdev"
|
||||
fi
|
||||
|
||||
paramsdev="${paramsdev%%/}"
|
||||
paramsdir="${paramsdir%%/}"
|
||||
|
||||
DEBUG "kexec-save-key prior of last override: paramsdir: $paramsdir, paramsdev: $paramsdev, lvm_volume_group: $lvm_volume_group"
|
||||
|
||||
if [ -n "$lvm_volume_group" ]; then
|
||||
lvm vgchange -a y $lvm_volume_group \
|
||||
|| die "Failed to activate the LVM group"
|
||||
@ -45,14 +57,17 @@ mount -o rw,remount $paramsdev
|
||||
|
||||
rm -f $paramsdir/kexec_key_lvm.txt || true
|
||||
if [ -n "$lvm_volume_group" ]; then
|
||||
DEBUG "kexec-save-key saving under $paramsdir/kexec_key_lvm.txt : lvm_volume_group: $lvm_volume_group"
|
||||
echo "$lvm_volume_group" > $paramsdir/kexec_key_lvm.txt \
|
||||
|| die "Failed to write lvm group to key config "
|
||||
fi
|
||||
|
||||
rm -f $paramsdir/kexec_key_devices.txt || true
|
||||
for dev in $key_devices; do
|
||||
DEBUG "gettinmg uuid for $dev"
|
||||
uuid=`cryptsetup luksUUID "$dev" 2>/dev/null` \
|
||||
|| die "Failed to get UUID for device $dev"
|
||||
DEBUG "saving under $paramsdir/kexec_key_devices.txt : dev: $dev, uuid: $uuid"
|
||||
echo "$dev $uuid" >> $paramsdir/kexec_key_devices.txt \
|
||||
|| die "Failed to add $dev:$uuid to key devices config"
|
||||
done
|
||||
@ -71,4 +86,4 @@ if [ "$skip_sign" != "y" ]; then
|
||||
fi
|
||||
|
||||
# switch back to ro mode
|
||||
mount -o ro,remount $paramsdev
|
||||
mount -o ro,remount $paramsdev
|
@ -26,16 +26,20 @@ KEY_LVM="$paramsdir/kexec_key_lvm.txt"
|
||||
|
||||
if [ ! -r "$KEY_DEVICES" ]; then
|
||||
die "No devices defined for disk encryption"
|
||||
else
|
||||
DEBUG "Devices defined for disk encryption: $(cat "$KEY_DEVICES" | cut -d\ -f1)"
|
||||
fi
|
||||
|
||||
if [ -r "$KEY_LVM" ]; then
|
||||
# Activate the LVM volume group
|
||||
VOLUME_GROUP=`cat $KEY_LVM`
|
||||
VOLUME_GROUP=$(cat $KEY_LVM)
|
||||
if [ -z "$VOLUME_GROUP" ]; then
|
||||
die "No LVM volume group defined for activation"
|
||||
fi
|
||||
lvm vgchange -a y $VOLUME_GROUP \
|
||||
|| die "$VOLUME_GROUP: unable to activate volume group"
|
||||
lvm vgchange -a y $VOLUME_GROUP ||
|
||||
die "$VOLUME_GROUP: unable to activate volume group"
|
||||
else
|
||||
DEBUG "No LVM volume group defined for activation"
|
||||
fi
|
||||
|
||||
DEBUG "$(pcrs)"
|
||||
@ -43,50 +47,69 @@ DEBUG "$(pcrs)"
|
||||
# LUKS Key slot 0 is the manual recovery pass phrase
|
||||
# that they user entered when they installed OS,
|
||||
# key slot 1 is the one that we've generated.
|
||||
read -s -p "Enter disk recovery key: " disk_password
|
||||
echo -n "$disk_password" > "$RECOVERY_KEY"
|
||||
read -s -p "Enter disk recovery key/passphrase: " disk_password
|
||||
echo -n "$disk_password" >"$RECOVERY_KEY"
|
||||
echo
|
||||
|
||||
read -s -p "New disk unlock password for booting: " key_password
|
||||
read -s -p "New TPM Disk Unlock Key passphrase for booting: " key_password
|
||||
echo
|
||||
read -s -p "Repeat unlock code: " key_password2
|
||||
read -s -p "Repeat TPM Disk Unlock key passphrase: " key_password2
|
||||
echo
|
||||
|
||||
if [ "$key_password" != "$key_password2" ]; then
|
||||
die "Key passwords do not match"
|
||||
die "Key passphrases do not match"
|
||||
fi
|
||||
|
||||
# Generate key file
|
||||
echo "++++++ Generating new randomized 128 bytes key file that will be unsealed by TPM Disk Unlock Key passphrase"
|
||||
dd \
|
||||
if=/dev/urandom \
|
||||
of="$KEY_FILE" \
|
||||
bs=1 \
|
||||
count=128 \
|
||||
2>/dev/null \
|
||||
|| die "Unable to generate 128 random bytes"
|
||||
2>/dev/null ||
|
||||
die "Unable to generate 128 random bytes"
|
||||
|
||||
# Count the number of slots used on each device
|
||||
for dev in $(cat "$KEY_DEVICES" | cut -d\ -f1); do
|
||||
DEBUG "Checking number of slots used on $dev"
|
||||
#check if the device is a LUKS device with luks[1,2]
|
||||
slots_used=$(cryptsetup luksDump $dev | grep -c 'luks[0-9]*' || die "Unable to get number of slots used on $dev")
|
||||
DEBUG "Number of slots used on $dev: $slots_used"
|
||||
# If slot1 is the only one used, warn and die with proper messages
|
||||
if [ $slots_used -eq 1 ]; then
|
||||
# Check if slot 1 is the only one existing
|
||||
if cryptsetup luksDump $dev | grep -q "Slot 1: ENABLED"; then
|
||||
warn "Slot 1 is the only one existing on $dev. Heads cannot use it to store TPM sealed LUKS Disk Unlock Key"
|
||||
die "Slot 1 should not be the only one existing on $dev. Fix your custom setup"
|
||||
fi
|
||||
else
|
||||
DEBUG "Slot 1 is not the only one existing on $dev. It is safe to use it to store TPM sealed LUKS Disk Unlock Key"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove all the old keys from slot 1
|
||||
for dev in `cat "$KEY_DEVICES" | cut -d\ -f1`; do
|
||||
echo "++++++ $dev: Removing old key slot"
|
||||
for dev in $(cat "$KEY_DEVICES" | cut -d\ -f1); do
|
||||
echo "++++++ $dev: Removing old key slot 1"
|
||||
cryptsetup luksKillSlot \
|
||||
--key-file "$RECOVERY_KEY" \
|
||||
$dev 1 \
|
||||
|| warn "$dev: ignoring problem"
|
||||
$dev 1 ||
|
||||
warn "$dev: removal of key in slot 1 failed: might not exist. Continuing"
|
||||
|
||||
echo "++++++ $dev: Adding key"
|
||||
echo "++++++ $dev: Adding key to slot 1"
|
||||
cryptsetup luksAddKey \
|
||||
--key-file "$RECOVERY_KEY" \
|
||||
--key-slot 1 \
|
||||
$dev "$KEY_FILE" \
|
||||
|| die "$dev: Unable to add key"
|
||||
$dev "$KEY_FILE" ||
|
||||
die "$dev: Unable to add key to slot 1"
|
||||
done
|
||||
|
||||
# Now that we have setup the new keys, measure the PCRs
|
||||
# We don't care what ends up in PCR 6; we just want
|
||||
# to get the /tmp/luksDump.txt file. We use PCR16
|
||||
# since it should still be zero
|
||||
cat "$KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \
|
||||
|| die "Unable to measure the LUKS headers"
|
||||
cat "$KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks ||
|
||||
die "Unable to measure the LUKS headers"
|
||||
|
||||
pcrf="/tmp/secret/pcrf.bin"
|
||||
tpmr pcrread 0 "$pcrf"
|
||||
@ -94,19 +117,19 @@ tpmr pcrread -a 1 "$pcrf"
|
||||
tpmr pcrread -a 2 "$pcrf"
|
||||
tpmr pcrread -a 3 "$pcrf"
|
||||
# Note that PCR 4 needs to be set with the "normal-boot" path value, read it from event log.
|
||||
tpmr calcfuturepcr 4 >> "$pcrf"
|
||||
tpmr calcfuturepcr 4 >>"$pcrf"
|
||||
if [ "$CONFIG_USB_KEYBOARD" = "y" -o -r /lib/modules/libata.ko -o -x /bin/hotp_verification ]; then
|
||||
DEBUG "Sealing TPM disk unlock key with PCR5 involvement (additional kernel modules are loaded per board config)..."
|
||||
DEBUG "Sealing TPM Disk Unlock key with PCR5 involvement (additional kernel modules are loaded per board config)..."
|
||||
# Here, we take pcr 5 into consideration if modules are expected to be measured+loaded
|
||||
tpmr pcrread -a 5 "$pcrf"
|
||||
else
|
||||
DEBUG "Sealing TPM disk unlock key with PCR5=0 (NO additional kernel modules are loaded per board config)..."
|
||||
DEBUG "Sealing TPM Disk Unlock Key with PCR5=0 (NO additional kernel modules are loaded per board config)..."
|
||||
#no kernel modules are expected to be measured+loaded
|
||||
tpmr calcfuturepcr 5 >> "$pcrf"
|
||||
tpmr calcfuturepcr 5 >>"$pcrf"
|
||||
fi
|
||||
# Precompute the value for pcr 6
|
||||
DEBUG "Precomputing TPM future value for PCR6 sealing/unsealing of TPM disk unlock key..."
|
||||
tpmr calcfuturepcr 6 "/tmp/luksDump.txt" >> "$pcrf"
|
||||
DEBUG "Precomputing TPM future value for PCR6 sealing/unsealing of TPM Disk Unlock Key..."
|
||||
tpmr calcfuturepcr 6 "/tmp/luksDump.txt" >>"$pcrf"
|
||||
# We take into consideration user files in cbfs
|
||||
tpmr pcrread -a 7 "$pcrf"
|
||||
|
||||
@ -115,9 +138,12 @@ DO_WITH_DEBUG --mask-position 7 \
|
||||
"$TPM_SIZE" "$key_password"
|
||||
|
||||
# should be okay if this fails
|
||||
shred -n 10 -z -u "$pcrf".* 2> /dev/null || true
|
||||
shred -n 10 -z -u "$KEY_FILE" 2> /dev/null \
|
||||
|| warn "Failed to delete key file - continuing"
|
||||
shred -n 10 -z -u "$pcrf" 2>/dev/null ||
|
||||
warn "Failed to delete pcrf file - continuing"
|
||||
shred -n 10 -z -u "$KEY_FILE" 2>/dev/null ||
|
||||
warn "Failed to delete key file - continuing"
|
||||
|
||||
cp /tmp/luksDump.txt "$paramsdir/kexec_lukshdr_hash.txt" \
|
||||
|| warn "Failed to have hashes of LUKS header - continuing"
|
||||
mount -o rw,remount $paramsdir || die "Failed to remount $paramsdir in RW - continuing"
|
||||
cp -f /tmp/luksDump.txt "$paramsdir/kexec_lukshdr_hash.txt" ||
|
||||
die "Failed to copy LUKS header hashes to /boot - continuing"
|
||||
mount -o ro,remount $paramsdir || die "Failed to remount $paramsdir in RO - continuing"
|
||||
|
@ -57,7 +57,7 @@ if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
|
||||
|| {
|
||||
echo "FATAL: Hash of TPM2 primary key handle mismatch!";
|
||||
echo "If you have not intentionally regenerated TPM2 primary key,";
|
||||
warn "your system may have been compromised!";
|
||||
warn "your system may have been compromised";
|
||||
}
|
||||
else
|
||||
echo "WARNING: Hash of TPM2 primary key handle does not exist!"
|
||||
@ -252,7 +252,7 @@ default_select() {
|
||||
whiptail $BG_COLOR_ERROR --title 'ERROR: Boot Entry Has Changed' \
|
||||
--msgbox "The list of boot entries has changed\n\nPlease set a new default" 0 80
|
||||
fi
|
||||
warn "!!! Boot entry has changed - please set a new default"
|
||||
warn "Boot entry has changed - please set a new default"
|
||||
return
|
||||
fi
|
||||
parse_option
|
||||
|
@ -26,7 +26,7 @@ DEBUG "Show PCRs"
|
||||
DEBUG "$(pcrs)"
|
||||
|
||||
for tries in 1 2 3; do
|
||||
read -s -p "Enter unlock password (blank to abort): " tpm_password
|
||||
read -s -p "Enter LUKS Disk Unlock Key passphrase (blank to abort): " tpm_password
|
||||
echo
|
||||
if [ -z "$tpm_password" ]; then
|
||||
die "Aborting unseal disk encryption key"
|
||||
|
@ -9,7 +9,7 @@ HOTP_KEY="/boot/kexec_hotp_key"
|
||||
|
||||
mount_boot()
|
||||
{
|
||||
TRACE "Under /bin/seal-htopkey:mount_boot"
|
||||
TRACE "Under /bin/seal-hotpkey:mount_boot"
|
||||
# Mount local disk if it is not already mounted
|
||||
if ! grep -q /boot /proc/mounts ; then
|
||||
mount -o ro /boot \
|
||||
|
@ -495,13 +495,13 @@ tpm1_seal() {
|
||||
# The permissions are 0 since there is nothing special
|
||||
# about the sealed file
|
||||
tpm physicalpresence -s \
|
||||
|| warn "Warning: Unable to assert physical presence"
|
||||
|| warn "Unable to assert physical presence"
|
||||
|
||||
prompt_tpm_password
|
||||
|
||||
tpm nv_definespace -in "$index" -sz "$sealed_size" \
|
||||
-pwdo "$tpm_password" -per 0 \
|
||||
|| warn "Warning: Unable to define NVRAM space; trying anyway"
|
||||
|| warn "Unable to define NVRAM space; trying anyway"
|
||||
|
||||
|
||||
tpm nv_writevalue -in "$index" -if "$sealed_file" \
|
||||
@ -595,7 +595,7 @@ tpm2_reset() {
|
||||
TRACE "Under /bin/tpmr:tpm2_reset"
|
||||
key_password="$1"
|
||||
mkdir -p "$SECRET_DIR"
|
||||
tpm2 clear -c platform || warn "Unable to clear TPM on platform hierarchy!"
|
||||
tpm2 clear -c platform || warn "Unable to clear TPM on platform hierarchy"
|
||||
tpm2 changeauth -c owner "$(tpm2_password_hex "$key_password")"
|
||||
tpm2 changeauth -c endorsement "$(tpm2_password_hex "$key_password")"
|
||||
tpm2 createprimary -C owner -g sha256 -G "${CONFIG_PRIMARY_KEY_TYPE:-rsa}" \
|
||||
@ -673,7 +673,7 @@ tpm2_kexec_finalize() {
|
||||
echo "Locking TPM2 platform hierarchy..."
|
||||
randpass=$(dd if=/dev/urandom bs=4 count=1 status=none | xxd -p)
|
||||
tpm2 changeauth -c platform "$randpass" \
|
||||
|| warn "Failed to lock platform hierarchy of TPM2!"
|
||||
|| warn "Failed to lock platform hierarchy of TPM2"
|
||||
}
|
||||
|
||||
tpm2_shutdown() {
|
||||
|
@ -4,13 +4,13 @@
|
||||
# busybox ash on legacy-flash boards, and with bash on all other boards.
|
||||
|
||||
die() {
|
||||
echo >&2 "$*";
|
||||
echo >&2 " !!! ERROR: $* !!!";
|
||||
sleep 2;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo >&2 "$*";
|
||||
echo >&2 " *** WARNING: $* ***";
|
||||
sleep 1;
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,36 @@ confirm_totp()
|
||||
echo
|
||||
}
|
||||
|
||||
reseal_tpm_disk_decryption_key()
|
||||
{
|
||||
TRACE "Under /etc/functions:reseal_tpm_disk_decryption_key"
|
||||
#Can be called only on resealing, not on tpm reset:
|
||||
#otherise primary handle and rollback would change.
|
||||
if ! grep -q /boot /proc/mounts ; then
|
||||
mount -o ro /boot \
|
||||
|| recovery "Unable to mount /boot"
|
||||
fi
|
||||
|
||||
if [ -s /boot/kexec_key_devices.txt ] || [ -s /boot/kexec_key_lvm.txt ]; then
|
||||
warn "A TPM disk decryption key previoulsy sealed is now invalid since firmware measurements cannot be unsealed"
|
||||
warn "Renewing LUKS Disk Unlock Key to be unsealed by TPM Disk Unlock Key passphrase"
|
||||
while ! kexec-seal-key /boot; do
|
||||
warn "Recovery disk encryption key passphrase invalid. Try again!"
|
||||
done
|
||||
warn "LUKS header hash changed under of /boot/kexec_luks_hdr_hash.txt"
|
||||
warn "Updating checksums and signing all files under /boot/kexec.sig"
|
||||
while ! update_checksums; do
|
||||
warn "Checksums were not signed. Bad GPG PIN provided?"
|
||||
warn "Please update checksums and provide a valid GPG PIN"
|
||||
done
|
||||
warn "Rebooting in 3 seconds to enable booting default boot option"
|
||||
sleep 3
|
||||
reboot
|
||||
else
|
||||
DEBUG "No TPM disk decryption key to reseal"
|
||||
fi
|
||||
}
|
||||
|
||||
# Enable USB storage (if not already enabled), and wait for storage devices to
|
||||
# be detected. If USB storage was already enabled, no wait occurs, this would
|
||||
# have happened already when USB storage was enabled.
|
||||
|
@ -246,7 +246,6 @@ select_luks_container()
|
||||
mount -o remount,ro /boot
|
||||
fi
|
||||
else
|
||||
|
||||
warn "No encrypted device found."
|
||||
return 1
|
||||
fi
|
||||
|
Loading…
Reference in New Issue
Block a user