mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-30 09:48:56 +00:00
40c34453df
Exception: scripts sourcing/calls within etc/ash_functions continues to use old TRACE functions until we switch to bash completely getting rid of ash. This would mean getting rid of legacy boards (flash + legacy boards which do not have enough space for bash in flash boards) once and for all. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
171 lines
6.2 KiB
Bash
Executable File
171 lines
6.2 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_FUNC
|
|
|
|
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_USER_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"
|