Merge pull request #1482 from tlaurion/ease_tpm_disk_unlock_key_resealing_after_totp_mismatch-warn_and_die_changes

Ease TPM Disk Unlock Key sealing/resealing after TOTP mismatch (firmware upgrade) + warn and die changes
This commit is contained in:
tlaurion 2023-09-05 11:48:50 -04:00 committed by GitHub
commit 8272d33e7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 565 additions and 319 deletions

2
FAQ.md
View File

@ -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)

View File

@ -13,6 +13,7 @@ CONFIG_LINUX_CONFIG=config/linux-x230-flash.config
#Add bare minimal tools for flashing boards
CONFIG_BASH=n
CONFIG_FLASHROM=y
CONFIG_ZSTD=n
#CONFIG_GPG=y
#CONFIG_FLASHTOOLS=y
CONFIG_PCIUTILS=y

View File

@ -20,8 +20,6 @@ CONFIG_PCIUTILS=y
CONFIG_POPT=y
CONFIG_QRENCODE=y
CONFIG_TPMTOTP=y
# zstd-decompress - for blob jail, needed to extract /init from zstd cpio archive
CONFIG_ZSTD=y
CONFIG_CAIRO=y
CONFIG_FBWHIPTAIL=y

View File

@ -13,6 +13,7 @@ CONFIG_LINUX_CONFIG=config/linux-x230-flash.config
#Add bare minimal tools for flashing boards
CONFIG_BASH=n
CONFIG_FLASHROM=y
CONFIG_ZSTD=n
#CONFIG_GPG=y
#CONFIG_FLASHTOOLS=y
CONFIG_PCIUTILS=y
@ -21,6 +22,7 @@ CONFIG_PCIUTILS=y
#CONFIG_TPMTOTP=y
#CONFIG_DROPBEAR=y
#Additional hardware support
CONFIG_LINUX_USB=y
#CONFIG_LINUX_E1000E=y

View File

@ -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

View File

@ -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,6 +577,7 @@ 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

View File

@ -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"

View File

@ -20,17 +20,17 @@ fi
if [ -r "$TMP_KEY_LVM" ]; then
# Activate the LVM volume group
VOLUME_GROUP=`cat $TMP_KEY_LVM`
VOLUME_GROUP=$(cat $TMP_KEY_LVM)
if [ -z "$TMP_KEY_LVM" ]; 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"
fi
# Measure the LUKS headers before we unseal the disk key
cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \
|| die "LUKS measure failed"
cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks ||
die "LUKS measure failed"
# Unpack the initrd and fixup the crypttab
# this is a hack to split it into two parts since
@ -49,8 +49,8 @@ if ! kexec-unseal-key "$INITRD_DIR/secret.key" ; then
fi
# Override PCR 4 so that user can't read the key
tpmr extend -ix 4 -ic generic \
|| die 'Unable to scramble PCR'
tpmr extend -ix 4 -ic generic ||
die 'Unable to scramble PCR'
# Check to continue
if [ "$unseal_failed" = "y" ]; then
@ -73,8 +73,8 @@ echo '+++ Building initrd'
# pad the initramfs (dracut doesn't pad the last gz blob)
# without this the kernel init/initramfs.c fails to read
# the subsequent uncompressed/compressed cpio
dd if="$INITRD" of="$SECRET_CPIO" bs=512 conv=sync \
|| die "Failed to copy initrd to /tmp"
dd if="$INITRD" of="$SECRET_CPIO" bs=512 conv=sync ||
die "Failed to copy initrd to /tmp"
if [ "$unseal_failed" = "n" ]; then
# kexec-save-default might have created crypttab overrides to be injected in initramfs through additional cpio
@ -92,14 +92,21 @@ if [ "$unseal_failed" = "n" ]; then
done
else
# No crypttab files were found under selected default boot option's initrd file
crypttab_file="etc/crypttab"
# TODO: cpio -t is unfit here :( it just extracts early cpio header and not the whole file. Replace with something else
# Meanwhile, force crypttab to be created from scratch on both possible locations: /etc/crypttab and /cryptroot/crypttab
crypttab_files="etc/crypttab cryptroot/crypttab"
for crypttab_file in $crypttab_files; do
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
echo "+++ The following $crypttab_file overrides will be passed through concatenated secret/initrd.cpio at kexec call:"
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
done
fi
( cd "$INITRD_DIR" ; find . -type f | cpio -H newc -o ) >> "$SECRET_CPIO"
(
cd "$INITRD_DIR"
find . -type f | cpio -H newc -o
) >>"$SECRET_CPIO"
fi

View File

@ -35,34 +35,164 @@ 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
# $lvm_suggest is a multiline string, we need to convert it to a space separated string
lvm_suggest=$(echo $lvm_suggest | tr '\n' ' ')
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
if cryptsetup isLuks "$device"; 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
elif [ -z "$devices_suggest" ]; then
num_devices=0
fi
# $devices_suggest is a multiline string, we need to convert it to a space separated string
devices_suggest=$(echo $devices_suggest | tr '\n' ' ')
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
#Reusable function when user wants to define new TPM DUK for lvms/disks
prompt_for_existing_encrypted_lvms_or_disks() {
TRACE "Under kexec-save-default:prompt_for_existing_encrypted_lvms_or_disks"
DEBUG "num_lvm: $num_lvm, lvm_suggest: $lvm_suggest, num_devices: $num_devices, devices_suggest: $devices_suggest"
# Create an associative array to store the suggested LVMs and their paths
declare -A lvms_array
# Loop through the suggested LVMs and add them to the array
for lvm in $lvm_suggest; do
lvms_array[$lvm]=$lvm
done
# Get the number of suggested LVMs
num_lvms=${#lvms_array[@]}
if [ "$num_lvms" -gt 1 ]; then
DEBUG "Multiple LVMs found: $lvm_suggest"
selected_lvms_not_existing=1
# Create an array to store the selected LVMs
declare -a key_lvms_array
while [ $selected_lvms_not_existing -ne 0 ]; do
{
# Read the user input and store it in a variable
read \
-p "Encrypted LVMs? (choose between/all: $lvm_suggest): " \
key_lvms
# Split the user input by spaces and add each element to the array
IFS=' ' read -r -a key_lvms_array <<<"$key_lvms"
# Loop through the array and check if each element is in the lvms_array
valid=1
for lvm in "${key_lvms_array[@]}"; do
if [[ ! ${lvms_array[$lvm]+_} ]]; then
# If not found, set the flag to indicate invalid input
valid=0
break
fi
done
# If valid, set the flag to indicate valid input
if [[ $valid -eq 1 ]]; then
selected_lvms_not_existing=0
fi
}
done
elif [ "$num_lvms" -eq 1 ]; then
echo "Single Encrypted LVM found at $lvm_suggest."
key_lvms=$lvm_suggest
else
echo "No encrypted LVMs found."
fi
# Create an associative array to store the suggested devices and their paths
declare -A devices_array
# Loop through the suggested devices and add them to the array
for device in $devices_suggest; do
devices_array[$device]=$device
done
# Get the number of suggested devices
num_devices=${#devices_array[@]}
if [ "$num_devices" -gt 1 ]; then
DEBUG "Multiple LUKS devices found: $devices_suggest"
selected_luksdevs_not_existing=1
# Create an array to store the selected devices
declare -a key_devices_array
while [ $selected_luksdevs_not_existing -ne 0 ]; do
{
# Read the user input and store it in a variable
read \
-p "Encrypted devices? (choose between/all: $devices_suggest): " \
key_devices
# Split the user input by spaces and add each element to the array
IFS=' ' read -r -a key_devices_array <<<"$key_devices"
# Loop through the array and check if each element is in the devices_array
valid=1
for device in "${key_devices_array[@]}"; do
if [[ ! ${devices_array[$device]+_} ]]; then
# If not found, set the flag to indicate invalid input
valid=0
break
fi
done
# If valid, set the flag to indicate valid input
if [[ $valid -eq 1 ]]; then
selected_luksdevs_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
DEBUG "Multiple LUKS devices selected: $key_devices"
}
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
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
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 set up from $KEY_DEVICES"
#check if $KEY_DEVICES file exists and is not empty
if [ -r "$KEY_DEVICES" ] && [ -s "$KEY_DEVICES" ]; then
DEBUG "TPM Disk Unlock Key was previously set up from $KEY_DEVICES"
read \
-n 1 \
-p "Do you want to reseal a disk key to the TPM [y/N]: " \
@ -73,36 +203,58 @@ 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
else
DEBUG "No previous TPM Disk Unlock Key was set up for LUKS devices, confirming to add a Disk Encryption Key to the TPM"
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
DEBUG "User confirmed desire to add a Disk Encryption Key to the TPM"
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 set up for LUKS devices $old_key_devices $old_lvm_volume_group"
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
-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
#User doesn't want to reuse past devices, so we need to prompt him from devices_suggest and lvm_suggest
else
prompt_for_existing_encrypted_lvms_or_disks
fi
else
DEBUG "No previous TPM Disk Unlock Key was set up for LUKS devices, setting up new one"
prompt_for_existing_encrypted_lvms_or_disks
fi
save_key_params="-s -p $paramsdev"
if [ -n "$lvm_volume_group" ]; then
@ -110,9 +262,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 TPM Disk Unlock Key"
fi
fi
@ -120,19 +271,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 \
(
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"
@ -140,32 +292,32 @@ 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
initrd_decompressed="/tmp/initrd_extract"
mkdir -p "$initrd_decompressed"
# 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
echo "+++ Extracting current selected default boot's $current_default_initrd to find crypttab files..."
unpack_initramfs.sh "$current_default_initrd" "$initrd_decompressed"
crypttab_files=$(find "$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
DEBUG "Found crypttab files in $current_default_initrd"
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
echo "$crypttab_files" | while read crypttab_file; do
# Change crypttab file path to be relative to initrd for string manipulation
final_initrd_filepath=${crypttab_file#/tmp/initrd_extract}
DEBUG "Final initramfs crypttab path:$final_initrd_filepath"
# Keep only non-commented lines for crypttab entries
current_crypttab_entries=$(cat "$crypttab_file" | grep -v "^#")
DEBUG "Found initrd crypttab entries $final_initrd_filepath:$current_crypttab_entries"
# Modify each retained crypttab line for /secret.key under intramfs to be considered as a keyfile
modified_crypttab_entries=$(echo "$current_crypttab_entries" | sed 's/none/\/secret.key/g')
DEBUG "Modified crypttab entries $final_initrd_filepath:$modified_crypttab_entries"
echo "$modified_crypttab_entries" | while read modified_crypttab_entry; do
echo "$final_initrd_filepath:$modified_crypttab_entry" >>$bootdir/kexec_initrd_crypttab_overrides.txt
done
done
@ -195,8 +347,8 @@ if [ "$CONFIG_TPM" = "y" ];then
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

View File

@ -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,24 +17,32 @@ while getopts "sp:d:l:" arg; do
l) lvm_volume_group="$OPTARG" ;;
esac
done
shift `expr $OPTIND - 1`
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%%/}"
if [ -n "$lvm_volume_group" ]; then
lvm vgchange -a y $lvm_volume_group \
|| die "Failed to activate the LVM group"
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"
#TODO: why reuse key_devices for lvm devices?
for dev in /dev/$lvm_volume_group/*; do
key_devices="$key_devices $dev"
done
@ -45,20 +57,23 @@ mount -o rw,remount $paramsdev
rm -f $paramsdir/kexec_key_lvm.txt || true
if [ -n "$lvm_volume_group" ]; then
echo "$lvm_volume_group" > $paramsdir/kexec_key_lvm.txt \
|| die "Failed to write lvm group to key config "
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
uuid=`cryptsetup luksUUID "$dev" 2>/dev/null` \
|| die "Failed to get UUID for device $dev"
echo "$dev $uuid" >> $paramsdir/kexec_key_devices.txt \
|| die "Failed to add $dev:$uuid to key devices config"
DEBUG "Getting 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
kexec-seal-key $paramsdir \
|| die "Failed to save and generate key in TPM"
kexec-seal-key $paramsdir ||
die "Failed to save and generate TPM Disk Unlock Key"
if [ "$skip_sign" != "y" ]; then
extparam=
@ -66,8 +81,8 @@ if [ "$skip_sign" != "y" ]; then
extparam=-r
fi
# sign and auto-roll config counter
kexec-sign-config -p $paramsdir $extparam \
|| die "Failed to sign updated config"
kexec-sign-config -p $paramsdir $extparam ||
die "Failed to sign updated config"
fi
# switch back to ro mode

View File

@ -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 | tr '\n' ' ')"
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,70 @@ 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
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 for booting: " 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 sealed/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 slot existing on $dev. Fix your custom setup"
fi
else
DEBUG "Slot 1 is not the only existing slot on $dev"
DEBUG "$dev Slot 1 will be used to store LUKS Disk Unlock Key that TPM will seal/unseal with TPM Disk Unlock Key passphrase"
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"
@ -96,16 +120,16 @@ 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"
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"
fi
# Precompute the value for pcr 6
DEBUG "Precomputing TPM future value for PCR6 sealing/unsealing of TPM disk unlock key..."
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 +139,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"

View File

@ -56,12 +56,12 @@ if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
sha256sum -c "$PRIMHASH_FILE" \
|| {
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 "If you have not intentionally regenerated TPM2 primary key,";
warn "your system may have been compromised";
}
else
echo "WARNING: Hash of TPM2 primary key handle does not exist!"
echo "Please rebuild the boot hash tree."
warn "Hash of TPM2 primary key handle does not exist"
warn "Please rebuild the boot hash tree"
default_failed="y"
fi
fi
@ -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

View File

@ -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"

View File

@ -1,21 +1,24 @@
#!/bin/bash
# Measure all of the luks disk encryption headers into
# Measure all of the LUKS Disk Encryption headers into
# a PCR so that we can detect disk swap attacks.
. /etc/functions
TRACE "Under /bin/qubes-measure-luks"
DEBUG "Arguments passed to qubes-measure-luks: $@"
die() { echo >&2 "$@"; exit 1; }
# Measure the luks headers into PCR 6
# Measure the LUKS headers into PCR 6
for dev in "$@"; do
DEBUG "Storing LUKS header for $dev into /tmp/lukshdr-$(echo "$dev" | sed 's/\//_/g')"
cryptsetup luksHeaderBackup $dev \
--header-backup-file /tmp/lukshdr-$(echo "$dev" | sed 's/\//_/g') \
|| die "$dev: Unable to read luks header"
--header-backup-file /tmp/lukshdr-$(echo "$dev" | sed 's/\//_/g') ||
die "$dev: Unable to read LUKS header"
done
DEBUG "Hashing luks headers into /tmp/luksDump.txt"
sha256sum /tmp/lukshdr-* >/tmp/luksDump.txt || die "Unable to hash luks headers"
DEBUG "Removing /tmp/lukshdr-*"
rm /tmp/lukshdr-*
tpmr extend -ix 6 -if /tmp/luksDump.txt \
|| die "Unable to extend PCR"
DEBUG "Extending PCR 6 with /tmp/luksDump.txt"
tpmr extend -ix 6 -if /tmp/luksDump.txt ||
die "Unable to extend PCR"

View File

@ -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 \

View File

@ -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() {

View File

@ -3,6 +3,7 @@ set -e -o pipefail
. /etc/functions
TRACE "Under unpack_initramfs.sh"
# Unpack a Linux initramfs archive.
#
# In general, the initramfs archive is one or more cpio archives, optionally
@ -30,6 +31,7 @@ CPIO_ARGS=("$@")
# Consume zero bytes, the first nonzero byte read (if any) is repeated on stdout
consume_zeros() {
TRACE "Under unpack_initramfs.sh:consume_zeros"
next_byte='00'
while [ "$next_byte" = "00" ]; do
# if we reach EOF, next_byte becomes empty (dd does not fail)
@ -42,11 +44,13 @@ consume_zeros() {
}
unpack_cpio() {
TRACE "Under unpack_initramfs.sh:unpack_cpio"
(cd "$dest_dir"; cpio -i "${CPIO_ARGS[@]}" 2>/dev/null)
}
# unpack the first segment of an archive, then write the rest to another file
unpack_first_segment() {
TRACE "Under unpack_initramfs.sh:unpack_first_segment"
unpack_archive="$1"
dest_dir="$2"
rest_archive="$3"
@ -62,18 +66,21 @@ unpack_first_segment() {
# lib/decompress.c (gzip)
case "$magic" in
00*)
DEBUG "archive segment $magic: uncompressed cpio"
# Skip zero bytes and copy the first nonzero byte
consume_zeros
# Copy the remaining data
cat
;;
303730373031*|303730373032*) # plain cpio
DEBUG "archive segment $magic: plain cpio"
# Unpack the plain cpio, this stops reading after the trailer
unpack_cpio
# Copy the remaining data
cat
;;
1f8b*|1f9e*) # gzip
DEBUG "archive segment $magic: gzip"
# gunzip won't stop when reaching the end of the gzipped member,
# so we can't read another segment after this. We can't
# reasonably determine the member length either, this requires
@ -81,6 +88,7 @@ unpack_first_segment() {
gunzip | unpack_cpio
;;
28b5*) # zstd
DEBUG "archive segment $magic: zstd"
# Like gunzip, this will not stop when reaching the end of the
# frame, and determining the frame length requires walking all
# of its blocks.

View File

@ -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;
}

View File

@ -41,8 +41,7 @@ pcrs() {
fi
}
confirm_totp()
{
confirm_totp() {
TRACE "Under /etc/functions:confirm_totp"
prompt="$1"
last_half=X
@ -51,15 +50,15 @@ confirm_totp()
while true; do
# update the TOTP code every thirty seconds
date=`date "+%Y-%m-%d %H:%M:%S"`
seconds=`date "+%s"`
half=`expr \( $seconds % 60 \) / 30`
date=$(date "+%Y-%m-%d %H:%M:%S")
seconds=$(date "+%s")
half=$(expr \( $seconds % 60 \) / 30)
if [ "$CONFIG_TPM" != "y" ]; then
TOTP="NO TPM"
elif [ "$half" != "$last_half" ]; then
last_half=$half;
TOTP=`unseal-totp` \
|| recovery "TOTP code generation failed"
last_half=$half
TOTP=$(unseal-totp) ||
recovery "TOTP code generation failed"
fi
echo -n "$date $TOTP: "
@ -70,8 +69,8 @@ confirm_totp()
-n 1 \
-s \
-p "$prompt" \
totp_confirm \
&& break
totp_confirm &&
break
# nothing typed, redraw the line
echo -ne '\r'
@ -81,16 +80,50 @@ confirm_totp()
echo
}
reseal_tpm_disk_decryption_key() {
TRACE "Under /etc/functions:reseal_tpm_disk_decryption_key"
#For robustness, exit early if TPM Disk Unlock Key is prohibited in board configs
if [ "$CONFIG_TPM_DISK_UNLOCK_KEY" == "n" ]; then
DEBUG "TPM Disk Unlock Key is prohibited in board configs"
return
else
DEBUG "TPM Disk Unlock Key is allowed in board configs. Continuing"
fi
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 Unlock Key previously sealed is now invalid since firmware measurements could not unseal TOTP"
echo "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 /boot/kexec_luks_hdr_hash.txt"
echo "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.
enable_usb_storage()
{
enable_usb_storage() {
if ! lsmod | grep -q usb_storage; then
timeout=0
echo "Scanning for USB storage devices..."
insmod /lib/modules/usb-storage.ko >/dev/null 2>&1 \
|| die "usb_storage: module load failed"
insmod /lib/modules/usb-storage.ko >/dev/null 2>&1 ||
die "usb_storage: module load failed"
while [[ $(list_usb_storage | wc -l) -eq 0 ]]; do
[[ $timeout -ge 8 ]] && break
sleep 1
@ -99,8 +132,7 @@ enable_usb_storage()
fi
}
list_usb_storage()
{
list_usb_storage() {
TRACE "Under /etc/functions:list_usb_storage"
# List all USB storage devices, including partitions unless we received argument stating we want drives only
# The output is a list of device names, one per line.
@ -157,8 +189,7 @@ list_usb_storage()
done
}
confirm_gpg_card()
{
confirm_gpg_card() {
TRACE "Under /etc/functions:confirm_gpg_card"
read \
-n 1 \
@ -191,8 +222,8 @@ confirm_gpg_card()
set -e
fi
# retry card status
gpg --card-status > /dev/null \
|| die "gpg card read failed"
gpg --card-status >/dev/null ||
die "gpg card read failed"
fi
# restore prev errexit state
if [ "$errexit" = "on" ]; then
@ -205,7 +236,7 @@ confirm_gpg_card()
# line, since some flows need it multiple times and only one prompt is ideal.
prompt_tpm_password() {
if [ -n "$tpm_password" ]; then
return 0;
return 0
fi
read -s -p "TPM Owner password: " tpm_password
@ -233,25 +264,24 @@ prompt_new_owner_password() {
done
}
check_tpm_counter()
{
check_tpm_counter() {
TRACE "Under /etc/functions:check_tpm_counter"
LABEL=${2:-3135106223}
tpm_password="$3"
# if the /boot.hashes file already exists, read the TPM counter ID
# from it.
if [ -r "$1" ]; then
TPM_COUNTER=`grep counter- "$1" | cut -d- -f2`
TPM_COUNTER=$(grep counter- "$1" | cut -d- -f2)
else
warn "$1 does not exist; creating new TPM counter"
prompt_tpm_password
tpmr counter_create \
-pwdo "$tpm_password" \
-pwdc '' \
-la $LABEL \
| tee /tmp/counter \
|| die "Unable to create TPM counter"
TPM_COUNTER=`cut -d: -f1 < /tmp/counter`
-la $LABEL |
tee /tmp/counter ||
die "Unable to create TPM counter"
TPM_COUNTER=$(cut -d: -f1 </tmp/counter)
fi
if [ -z "$TPM_COUNTER" ]; then
@ -259,48 +289,46 @@ check_tpm_counter()
fi
}
read_tpm_counter()
{
read_tpm_counter() {
TRACE "Under /etc/functions:read_tpm_counter"
tpmr counter_read -ix "$1" | tee "/tmp/counter-$1" \
|| die "Counter read failed"
tpmr counter_read -ix "$1" | tee "/tmp/counter-$1" ||
die "Counter read failed"
}
increment_tpm_counter()
{
increment_tpm_counter() {
TRACE "Under /etc/functions:increment_tpm_counter"
tpmr counter_increment -ix "$1" -pwdc '' \
| tee /tmp/counter-$1 \
|| die "Counter increment failed"
tpmr counter_increment -ix "$1" -pwdc '' |
tee /tmp/counter-$1 ||
die "Counter increment failed"
}
check_config() {
TRACE "Under /etc/functions:check_config"
if [ ! -d /tmp/kexec ]; then
mkdir /tmp/kexec \
|| die 'Failed to make kexec tmp dir'
mkdir /tmp/kexec ||
die 'Failed to make kexec tmp dir'
else
rm -rf /tmp/kexec/* \
|| die 'Failed to empty kexec tmp dir'
rm -rf /tmp/kexec/* ||
die 'Failed to empty kexec tmp dir'
fi
if [ ! -r $1/kexec.sig -a "$CONFIG_BASIC" != "y" ]; then
return
fi
if [ `find $1/kexec*.txt | wc -l` -eq 0 ]; then
if [ $(find $1/kexec*.txt | wc -l) -eq 0 ]; then
return
fi
if [ "$2" != "force" ]; then
if ! sha256sum `find $1/kexec*.txt` | gpgv $1/kexec.sig - ; then
if ! sha256sum $(find $1/kexec*.txt) | gpgv $1/kexec.sig -; then
die 'Invalid signature on kexec boot params'
fi
fi
echo "+++ Found verified kexec boot params"
cp $1/kexec*.txt /tmp/kexec \
|| die "Failed to copy kexec boot params to tmp"
cp $1/kexec*.txt /tmp/kexec ||
die "Failed to copy kexec boot params to tmp"
}
# Replace a file in a ROM (add it if the file does not exist)
@ -309,7 +337,7 @@ replace_rom_file() {
ROM_FILE="$2"
NEW_FILE="$3"
if (cbfs.sh -o "$ROM" -l | grep -q "$ROM_FILE") then
if (cbfs.sh -o "$ROM" -l | grep -q "$ROM_FILE"); then
cbfs.sh -o "$ROM" -d "$ROM_FILE"
fi
cbfs.sh -o "$ROM" -a "$ROM_FILE" -f "$NEW_FILE"
@ -359,8 +387,7 @@ set_user_config() {
# Load a config value to a variable, defaulting to empty. Does not fail if the
# config is not set (since it would expand to empty by default).
load_config_value()
{
load_config_value() {
local config_name="$1"
if grep -q "$config_name=" /tmp/config; then
grep "$config_name=" /tmp/config | tail -n1 | cut -f2 -d '=' | tr -d '"'
@ -383,13 +410,12 @@ secret_from_rom_hash() {
sha256sum "${ROM_IMAGE}" | cut -f1 -d ' ' | fromhex_plain
}
update_checksums()
{
update_checksums() {
TRACE "Under /etc/functions:update_checksums"
# ensure /boot mounted
if ! grep -q /boot /proc/mounts; then
mount -o ro /boot \
|| recovery "Unable to mount /boot"
mount -o ro /boot ||
recovery "Unable to mount /boot"
fi
# remount RW
@ -501,8 +527,7 @@ assert_signable() {
rm -f /tmp/signable.*
}
verify_checksums()
{
verify_checksums() {
TRACE "Under /etc/functions:verify_checksums"
local boot_dir="$1"
local gui="${2:-y}"
@ -535,8 +560,7 @@ verify_checksums()
# detect and set /boot device
# mount /boot if successful
detect_boot_device()
{
detect_boot_device() {
TRACE "Under /etc/functions:detect_boot_device"
# unmount /boot to be safe
cd / && umount /boot 2>/dev/null
@ -556,9 +580,9 @@ detect_boot_device()
# filter out extraneous options
>/tmp/boot_device_list
for i in `cat /tmp/disklist`; do
for i in $(cat /tmp/disklist); do
# remove block device from list if numeric partitions exist, since not bootable
DEV_NUM_PARTITIONS=$((`ls -1 $i* | wc -l`-1))
DEV_NUM_PARTITIONS=$(($(ls -1 $i* | wc -l) - 1))
if [ ${DEV_NUM_PARTITIONS} -eq 0 ]; then
echo $i >>/tmp/boot_device_list
else
@ -567,7 +591,7 @@ detect_boot_device()
done
# iterate thru possible options and check for grub dir
for i in `cat /tmp/boot_device_list`; do
for i in $(cat /tmp/boot_device_list); do
umount /boot 2>/dev/null
if mount -o ro $i /boot >/dev/null 2>&1; then
if ls -d /boot/grub* >/dev/null 2>&1; then
@ -583,30 +607,28 @@ detect_boot_device()
return 1
}
scan_boot_options()
{
scan_boot_options() {
local bootdir config option_file
bootdir="$1"
config="$2"
option_file="$3"
if [ -r $option_file ]; then rm $option_file; fi
for i in `find $bootdir -name "$config"`; do
for i in $(find $bootdir -name "$config"); do
DO_WITH_DEBUG kexec-parse-boot "$bootdir" "$i" >>$option_file
done
# FC29/30+ may use BLS format grub config files
# https://fedoraproject.org/wiki/Changes/BootLoaderSpecByDefault
# only parse these if $option_file is still empty
if [ ! -s $option_file ] && [ -d "$bootdir/loader/entries" ]; then
for i in `find $bootdir -name "$config"`; do
for i in $(find $bootdir -name "$config"); do
kexec-parse-bls "$bootdir" "$i" "$bootdir/loader/entries" >>$option_file
done
fi
}
calc()
{
awk "BEGIN { print "$*" }";
calc() {
awk "BEGIN { print "$*" }"
}
# truncate a file to a size only if it is longer (busybox truncate lacks '<' and
@ -635,24 +657,21 @@ fromhex_plain() {
fold -w 60 | xxd -p -r
}
print_battery_health()
{
print_battery_health() {
if [ -d /sys/class/power_supply/BAT* ]; then
battery_health=$(calc $(cat /sys/class/power_supply/BAT*/charge_full)/$(cat /sys/class/power_supply/BAT*/charge_full_design)*100 | awk -F "." {'print $1'})
echo "$battery_health"
fi
}
print_battery_charge()
{
print_battery_charge() {
if [ -d /sys/class/power_supply/BAT* ]; then
battery_charge=$(calc $(cat /sys/class/power_supply/BAT*/charge_now)/$(cat /sys/class/power_supply/BAT*/charge_full)*100 | awk -F "." {'print $1'})
echo "$battery_charge"
fi
}
generate_random_mac_address()
{
generate_random_mac_address() {
#Borrowed from https://stackoverflow.com/questions/42660218/bash-generate-random-mac-address-unicast
hexdump -n 6 -ve '1/1 "%.2x "' /dev/urandom | awk -v a="2,6,a,e" -v r="$RANDOM" 'BEGIN{srand(r);}NR==1{split(a,b,",");r=int(rand()*4+1);printf "%s%s:%s:%s:%s:%s:%s\n",substr($1,0,1),b[r],$2,$3,$4,$5,$6}'
}

View File

@ -246,7 +246,6 @@ select_luks_container()
mount -o remount,ro /boot
fi
else
warn "No encrypted device found."
return 1
fi
@ -302,7 +301,7 @@ while : ; do
if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then
#if no external provisioning provides current Disk Recovery Key passphrase
whiptail --title 'Reencrypt LUKS disk encrypted container ?' \
--msgbox "This will replace the encrypted container content and its Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user in the\nfollowing conditions:\n 1-Every boot if no Disk unlock key was added to the TPM\n 2-If the TPM fails (Hardware failure)\n 3-If the firmware has been tampered with/upgraded/modified by the user\n\nThis process requires you to type the current Disk Recovery Key passphrase\nand will delete TPM Disk unlock key slot if setuped by setting a default boot\n LUKS header (slot 1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to\nthe LUKS device container.\n\nHit Enter to continue." 0 80
--msgbox "This will replace the encrypted container content and its Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user in the\nfollowing conditions:\n 1-Every boot if no Disk unlock key was added to the TPM\n 2-If the TPM fails (Hardware failure)\n 3-If the firmware has been tampered with/upgraded/modified by the user\n\nThis process requires you to type the current Disk Recovery Key passphrase\nand will delete TPM Disk unlock key slot if set up by setting a default boot\n LUKS header (slot 1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to\nthe LUKS device container.\n\nHit Enter to continue." 0 80
echo -e "\nEnter current Disk Recovery Key passphrase (Provisioned at OS installation or by OEM):"
read -r luks_current_Disk_Recovery_Key_passphrase
echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/luks_current_Disk_Recovery_Key_passphrase

View File

@ -4,10 +4,9 @@
# The default PCR to be extended is 5, but can be
# overridden with the MODULE_PCR environment variable
die() {
echo >&2 "$@"
exit 1
}
. /etc/functions
TRACE "Under insmod.sh"
MODULE="$1"; shift
@ -31,18 +30,22 @@ if [ ! -r /sys/class/tpm/tpm0/pcrs -o ! -x /bin/tpm ]; then
fi
if [ -z "$tpm_missing" ]; then
DEBUG "Extending PCR $MODULE_PCR with $MODULE"
tpmr extend -ix "$MODULE_PCR" -if "$MODULE" \
|| die "$MODULE: tpm extend failed"
fi
if [ ! -z "$*" -a -z "$tpm_missing" ]; then
DEBUG "Extending PCR $MODULE_PCR with $*"
TMPFILE=/tmp/insmod.$$
echo "$@" > $TMPFILE
DEBUG "Extending PCR $MODULE_PCR with $TMPFILE"
tpmr extend -ix "$MODULE_PCR" -if $TMPFILE \
|| die "$MODULE: tpm extend on arguments failed"
fi
# Since we have replaced the real insmod, we must invoke
# the busybox insmod via the original executable
DEBUG "Loading $MODULE with busybox insmod"
busybox insmod "$MODULE" "$@" \
|| die "$MODULE: insmod failed"

View File

@ -1,3 +1,6 @@
# ZSTD is always included, unless explicitly turned off
# Needed by initrd/bin/unpack_initramfs.sh under TPM Disk Unlock Key setup
CONFIG_ZSTD ?= y
modules-$(CONFIG_ZSTD) += zstd
zstd_version := 1.5.5