mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-18 20:47:55 +00:00
6db03b0bdd
When playing with long fbwhiptail/whiptail messages, this commit played around the long string using fold. ''' echo -e "This will replace the encrypted container content and its LUKS Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user under the following 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/modified by the user\n\nThis process requires you to type the current LUKS Disk Recovery Key passphrase and will delete the LUKS TPM Disk Unlock Key slot, if set up, by setting a default boot LUKS key slot (1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to the LUKS device container.\n\nHit Enter to continue." | fold -w 70 -s ''' Which gave the exact output of what will be inside of the fbwhiptail prompt, fixed to 70 chars width: ''' This will replace the encrypted container content and its LUKS Disk Recovery Key. The passphrase associated with this key will be asked from the user under the following conditions: 1-Every boot if no Disk Unlock Key was added to the TPM 2-If the TPM fails (hardware failure) 3-If the firmware has been tampered with/modified by the user This process requires you to type the current LUKS Disk Recovery Key passphrase and will delete the LUKS TPM Disk Unlock Key slot, if set up, by setting a default boot LUKS key slot (1) if present. At the next prompt, you may be asked to select which file corresponds to the LUKS device container. Hit Enter to continue. ''' Therefore, for long prompts in the future, one can just deal with "\n 1-" alignments to be respected in prompts and have fold deal with cutting the length of strings properly. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
171 lines
6.3 KiB
Bash
Executable File
171 lines
6.3 KiB
Bash
Executable File
#!/bin/bash
|
|
# This will generate a disk encryption key and seal / ecncrypt
|
|
# with the current PCRs and then store it in the TPM NVRAM.
|
|
# It will then need to be bundled into initrd that is booted.
|
|
set -e -o pipefail
|
|
. /etc/functions
|
|
|
|
TPM_INDEX=3
|
|
TPM_SIZE=312
|
|
KEY_FILE="/tmp/secret/secret.key"
|
|
TPM_SEALED="/tmp/secret/secret.sealed"
|
|
RECOVERY_KEY="/tmp/secret/recovery.key"
|
|
|
|
. /etc/functions
|
|
. /tmp/config
|
|
|
|
TRACE "Under kexec-seal-key"
|
|
|
|
paramsdir=$1
|
|
if [ -z "$paramsdir" ]; then
|
|
die "Usage $0 /boot"
|
|
fi
|
|
|
|
KEY_DEVICES="$paramsdir/kexec_key_devices.txt"
|
|
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)
|
|
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"
|
|
else
|
|
DEBUG "No LVM volume group defined for activation"
|
|
fi
|
|
|
|
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 LUKS Disk Recovery Key/passphrase: " disk_password
|
|
echo -n "$disk_password" >"$RECOVERY_KEY"
|
|
echo
|
|
|
|
read -s -p "New LUKS TPM Disk Unlock Key passphrase for booting: " key_password
|
|
echo
|
|
read -s -p "Repeat LUKS TPM Disk Unlock Key passphrase for booting: " key_password2
|
|
echo
|
|
|
|
if [ "$key_password" != "$key_password2" ]; then
|
|
die "Key passphrases do not match"
|
|
fi
|
|
|
|
# Generate key file
|
|
echo "++++++ Generating new randomized 128 bytes key file that will be sealed/unsealed by LUKS 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"
|
|
|
|
# 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 LUKS header"
|
|
#check if the device is a LUKS device with luks[1,2]
|
|
# Get the number of key slots used on the LUKS header.
|
|
# LUKS1 Format is :
|
|
# Slot 0: ENABLED
|
|
# Slot 1: ENABLED
|
|
# Slot 2: DISABLED
|
|
# Slot 3: DISABLED
|
|
#...
|
|
# Slot 7: DISABLED
|
|
# Luks2 only reports on enabled slots.
|
|
# luks2 Format is :
|
|
# 0: luks2
|
|
# 1: luks2
|
|
# Meaning that the number of slots used is the number of lines returned by a grep on the LUKS2 above format.
|
|
# We need to count the number of ENABLED slots for both LUKS1 and LUKS2
|
|
# create regex pattern for both LUKS1 and LUKS2
|
|
regex="Slot [0-9]*: ENABLED"
|
|
regex+="\|"
|
|
regex+="[0-9]*: luks2"
|
|
slots_used=$(cryptsetup luksDump "$dev" | grep -c "$regex" || die "Unable to get number of slots used on $dev")
|
|
|
|
DEBUG "Number of slots used on $dev LUKS header: $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 -c "Slot 1: ENABLED")" -eq 1 ] || [ "$(cryptsetup luksDump "$dev" | grep -c "1: luks2")" -eq 1 ]; then
|
|
warn "Slot 1 is the only one existing on $dev LUKS header. Heads cannot use it to store TPM sealed LUKS Disk Unlock Key"
|
|
warn "Slot 1 should not be the only slot existing on $dev LUKS header. Slot 0 should be used to store LUKS Disk Recovery Key/passphrase"
|
|
die "You can safely fix this before continuing through Heads recovery shell: cryptsetup luksAddKey $dev"
|
|
fi
|
|
else
|
|
DEBUG "Slot 1 is not the only existing slot on $dev LUKS header."
|
|
DEBUG "$dev LUKS header's slot 1 will store LUKS Disk Unlock Key that TPM will seal/unseal with LUKS 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 LUKS TPM Disk Unlock Key in LUKS slot 1"
|
|
cryptsetup luksKillSlot \
|
|
--key-file "$RECOVERY_KEY" \
|
|
$dev 1 ||
|
|
warn "$dev: removal of LUKS TPM Disk Unlock Key in LUKS slot 1 failed: might not exist. Continuing"
|
|
|
|
echo "++++++ $dev: Adding LUKS TPM Disk Unlock Key to LUKS slot 1"
|
|
cryptsetup luksAddKey \
|
|
--key-file "$RECOVERY_KEY" \
|
|
--key-slot 1 \
|
|
$dev "$KEY_FILE" ||
|
|
die "$dev: Unable to add LUKS TPM Disk Unlock Key to LUKS 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"
|
|
|
|
pcrf="/tmp/secret/pcrf.bin"
|
|
tpmr pcrread 0 "$pcrf"
|
|
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"
|
|
if [ "$CONFIG_USB_KEYBOARD" = "y" -o -r /lib/modules/libata.ko -o -x /bin/hotp_verification ]; then
|
|
DEBUG "Sealing LUKS 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 LUKS 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 LUKS TPM Disk Unlock Key..."
|
|
tpmr calcfuturepcr 6 "/tmp/luksDump.txt" >>"$pcrf"
|
|
# We take into consideration user files in cbfs
|
|
tpmr pcrread -a 7 "$pcrf"
|
|
|
|
DO_WITH_DEBUG --mask-position 7 \
|
|
tpmr seal "$KEY_FILE" "$TPM_INDEX" 0,1,2,3,4,5,6,7 "$pcrf" \
|
|
"$TPM_SIZE" "$key_password" || die "Unable to write LUKS TPM Disk Unlock Key to NVRAM"
|
|
|
|
# should be okay if this fails
|
|
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"
|
|
|
|
mount -o rw,remount $paramsdir || warn "Failed to remount $paramsdir in RW - continuing"
|
|
cp -f /tmp/luksDump.txt "$paramsdir/kexec_lukshdr_hash.txt" ||
|
|
warn "Failed to copy LUKS header hashes to /boot - continuing"
|
|
mount -o ro,remount $paramsdir || warn "Failed to remount $paramsdir in RO - continuing"
|