2023-02-08 21:01:48 +00:00
|
|
|
#!/bin/bash
|
2017-07-12 04:17:45 +00:00
|
|
|
# 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
|
2023-02-18 17:58:43 +00:00
|
|
|
. /etc/functions
|
2017-07-12 04:17:45 +00:00
|
|
|
|
|
|
|
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
|
2018-12-06 23:24:28 +00:00
|
|
|
. /tmp/config
|
2017-07-12 04:17:45 +00:00
|
|
|
|
2023-02-23 22:05:15 +00:00
|
|
|
TRACE "Under kexec-seal-key"
|
|
|
|
|
2017-07-12 04:17:45 +00:00
|
|
|
paramsdir=$1
|
|
|
|
if [ -z "$paramsdir" ]; then
|
2017-07-17 16:43:14 +00:00
|
|
|
die "Usage $0 /boot"
|
2017-07-12 04:17:45 +00:00
|
|
|
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"
|
|
|
|
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"
|
|
|
|
fi
|
|
|
|
|
2023-02-23 22:05:15 +00:00
|
|
|
DEBUG "$(pcrs)"
|
2022-08-25 18:43:31 +00:00
|
|
|
|
|
|
|
# LUKS Key slot 0 is the manual recovery pass phrase
|
|
|
|
# that they user entered when they installed OS,
|
2017-07-12 04:17:45 +00:00
|
|
|
# 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"
|
|
|
|
echo
|
|
|
|
|
2023-02-23 14:15:00 +00:00
|
|
|
read -s -p "New disk unlock password for booting: " key_password
|
|
|
|
echo
|
|
|
|
read -s -p "Repeat unlock code: " key_password2
|
|
|
|
echo
|
|
|
|
|
|
|
|
if [ "$key_password" != "$key_password2" ]; then
|
|
|
|
die "Key passwords do not match"
|
2017-07-12 04:17:45 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
# Generate key file
|
|
|
|
dd \
|
|
|
|
if=/dev/urandom \
|
|
|
|
of="$KEY_FILE" \
|
|
|
|
bs=1 \
|
|
|
|
count=128 \
|
|
|
|
2>/dev/null \
|
|
|
|
|| die "Unable to generate 128 random bytes"
|
|
|
|
|
|
|
|
# Remove all the old keys from slot 1
|
|
|
|
for dev in `cat "$KEY_DEVICES" | cut -d\ -f1`; do
|
|
|
|
echo "++++++ $dev: Removing old key slot"
|
|
|
|
cryptsetup luksKillSlot \
|
|
|
|
--key-file "$RECOVERY_KEY" \
|
|
|
|
$dev 1 \
|
|
|
|
|| warn "$dev: ignoring problem"
|
|
|
|
|
|
|
|
echo "++++++ $dev: Adding key"
|
|
|
|
cryptsetup luksAddKey \
|
|
|
|
--key-file "$RECOVERY_KEY" \
|
|
|
|
--key-slot 1 \
|
|
|
|
$dev "$KEY_FILE" \
|
|
|
|
|| die "$dev: Unable to add key"
|
|
|
|
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"
|
2018-11-07 21:27:52 +00:00
|
|
|
|
tpm2-tools: Change sense of CONFIG_TPM to mean any TPM, not just TPM1.
Most logic throughout Heads doesn't need to know TPM1 versus TPM2 (and
shouldn't, the differences should be localized). Some checks were
incorrect and are fixed by this change. Most checks are now unchanged
relative to master.
There are not that many places outside of tpmr that need to
differentiate TPM1 and TPM2. Some of those are duplicate code that
should be consolidated (seal-hotpkey, unseal-totp, unseal-hotp), and
some more are probably good candidates for abstracting in tpmr so the
business logic doesn't have to know TPM1 vs. TPM2.
Previously, CONFIG_TPM could be variously 'y', 'n', or empty. Now it
is always 'y' or 'n', and 'y' means "any TPM". Board configs are
unchanged, setting CONFIG_TPM2_TOOLS=y implies CONFIG_TPM=y so this
doesn't have to be duplicated and can't be mistakenly mismatched.
There were a few checks for CONFIG_TPM = n that only coincidentally
worked for TPM2 because CONFIG_TPM was empty (not 'n'). This test is
now OK, but the checks were also cleaned up to '!= "y"' for robustness.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-02-22 21:30:07 +00:00
|
|
|
if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_TPM2_TOOLS" != "y" ]; then
|
2022-08-25 18:43:31 +00:00
|
|
|
luks_pcr=`tpm calcfuturepcr -ix 16 -if /tmp/luksDump.txt`
|
|
|
|
# HOTP USB Secrity Dongle loads USB modules which changes PCR5.
|
|
|
|
# In the event HOTP USB Security Dongle is enabled, skip verification of PCR5
|
|
|
|
# If modules should be loaded during normal boot, skip verification of PCR5
|
2017-07-12 04:17:45 +00:00
|
|
|
#
|
2022-08-25 18:43:31 +00:00
|
|
|
#TODO: check condition, no libdata.ko
|
|
|
|
if [ "$CONFIG_USB_KEYBOARD" = "y" -o -r /lib/modules/libata.ko -o -x /bin/hotp_verification ]; then
|
|
|
|
pcr_5="X"
|
|
|
|
else
|
|
|
|
pcr_5="0000000000000000000000000000000000000000"
|
|
|
|
fi
|
2017-07-12 04:17:45 +00:00
|
|
|
|
2022-08-25 18:43:31 +00:00
|
|
|
# Note that PCR 4 needs to be set with the "normal-boot"
|
|
|
|
# path value, which we do not have right now since we are
|
|
|
|
# in a "init" mode
|
|
|
|
# used to be -ix 4 f8fa3b6e32e7c6fe04c366e74636e505b28f3b0d \
|
|
|
|
# now just all zeros in a normal boot
|
|
|
|
# PCR 5 must be all zero since no kernel modules should have
|
|
|
|
# been loaded during a normal boot, but might have been
|
|
|
|
# loaded in the recovery shell.
|
|
|
|
# Otherwise use the current values of the PCRs, which will be read
|
|
|
|
# from the TPM as part of the sealing ("X").
|
2023-02-23 14:15:00 +00:00
|
|
|
tpm sealfile2 \
|
|
|
|
-if "$KEY_FILE" \
|
|
|
|
-of "$TPM_SEALED" \
|
|
|
|
-pwdd "$key_password" \
|
|
|
|
-hk 40000000 \
|
|
|
|
-ix 0 X \
|
|
|
|
-ix 1 X \
|
|
|
|
-ix 2 X \
|
|
|
|
-ix 3 X \
|
|
|
|
-ix 4 0000000000000000000000000000000000000000 \
|
|
|
|
-ix 5 $pcr_5 \
|
|
|
|
-ix 6 $luks_pcr \
|
|
|
|
-ix 7 X
|
2017-07-12 04:17:45 +00:00
|
|
|
|
2022-08-25 18:43:31 +00:00
|
|
|
if [ $? -ne 0 ]; then
|
|
|
|
die "Unable to seal secret"
|
|
|
|
fi
|
2017-07-12 04:17:45 +00:00
|
|
|
|
2022-08-25 18:43:31 +00:00
|
|
|
shred -n 10 -z -u "$KEY_FILE" 2> /dev/null \
|
|
|
|
|| die "Failed to delete key file"
|
2017-07-12 04:17:45 +00:00
|
|
|
|
2022-08-25 18:43:31 +00:00
|
|
|
# try it without the owner password first
|
|
|
|
if ! tpm nv_writevalue \
|
2017-07-12 04:17:45 +00:00
|
|
|
-in $TPM_INDEX \
|
|
|
|
-if "$TPM_SEALED" \
|
2022-08-25 18:43:31 +00:00
|
|
|
; then
|
|
|
|
# to create an nvram space we need the TPM owner password
|
|
|
|
# and the TPM physical presence must be asserted.
|
|
|
|
#
|
|
|
|
# The permissions are 0 since there is nothing special
|
|
|
|
# about the sealed file
|
|
|
|
tpm physicalpresence -s \
|
|
|
|
|| warn "Warning: Unable to assert physical presence"
|
|
|
|
|
|
|
|
read -s -p "TPM Owner password: " tpm_password
|
|
|
|
echo
|
|
|
|
|
|
|
|
tpm nv_definespace \
|
|
|
|
-in $TPM_INDEX \
|
|
|
|
-sz $TPM_SIZE \
|
|
|
|
-pwdo "$tpm_password" \
|
|
|
|
-per 0 \
|
|
|
|
|| warn "Warning: Unable to define NVRAM space; trying anyway"
|
|
|
|
|
|
|
|
|
|
|
|
tpm nv_writevalue \
|
|
|
|
-in $TPM_INDEX \
|
|
|
|
-if "$TPM_SEALED" \
|
|
|
|
|| die "Unable to write sealed secret to NVRAM"
|
|
|
|
fi
|
|
|
|
elif [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
|
|
|
|
pcrf="/tmp/secret/pcrf.bin"
|
|
|
|
#TODO: verify logic below against tpm2
|
|
|
|
tpm2 pcrread -o "$pcrf" sha256:0,1,2,3
|
|
|
|
# pcr 4 is expected to be zero (init mode)
|
|
|
|
dd if=/dev/zero bs=32 count=1 >> "$pcrf"
|
|
|
|
if [ "$CONFIG_USB_KEYBOARD" = "y" -o -r /lib/modules/libata.ko -o -x /bin/hotp_verification ]; then
|
2023-02-23 22:05:15 +00:00
|
|
|
DEBUG "TPM2, with PCR5 involvement (additional kernel modules are loaded per board config)..."
|
2022-08-25 18:43:31 +00:00
|
|
|
# Here, we take pcr 5 into consideration if modules are expected to be measured+loaded
|
|
|
|
#
|
|
|
|
# binary pcr dump can only go via stderr for redirection
|
|
|
|
# sadly this busybox has buggy support for "2>>" and "2|"
|
|
|
|
# so we need workaround...
|
2023-02-23 22:05:15 +00:00
|
|
|
DEBUG "tpm2 pcrread -o /dev/stderr sha256:5 2>&1 >/dev/console | cat >> "$pcrf""
|
2022-08-25 18:43:31 +00:00
|
|
|
tpm2 pcrread -o /dev/stderr sha256:5 2>&1 >/dev/console | cat >> "$pcrf"
|
|
|
|
else
|
2023-02-23 22:05:15 +00:00
|
|
|
DEBUG "TPM2, without PCR5 involvement. Inserting 32 zero bytes under pcrf..."
|
2022-08-25 18:43:31 +00:00
|
|
|
#no kernel modules are expected to be measured+loaded
|
|
|
|
dd if=/dev/zero bs=32 count=1 >> "$pcrf"
|
|
|
|
fi
|
|
|
|
# Use pcr 23 to precompute the value for pcr 6
|
2023-03-07 15:18:56 +00:00
|
|
|
tpm2 pcrreset 23
|
2022-08-25 18:43:31 +00:00
|
|
|
tpmr extend -ix 23 -if /tmp/luksDump.txt
|
|
|
|
tpm2 pcrread -o /dev/stderr sha256:23 2>&1 >/dev/console | cat >> "$pcrf"
|
|
|
|
# goal is to validate that what is in pcr 23 is at pcr 6 at unseal
|
2023-02-23 22:05:15 +00:00
|
|
|
DEBUG "PCR23 content used to simulate PCR6 content at unseal:"
|
|
|
|
DEBUG "$(pcrs)"
|
2022-08-25 18:43:31 +00:00
|
|
|
tpm2 pcrreset 23
|
|
|
|
# We take into consideration user files in cbfs
|
2023-02-23 22:05:15 +00:00
|
|
|
DEBUG "tpm2 pcrread -o /dev/stderr sha256:7 2>&1 >/dev/console | cat >> "$pcrf""
|
2022-08-25 18:43:31 +00:00
|
|
|
tpm2 pcrread -o /dev/stderr sha256:7 2>&1 >/dev/console | cat >> "$pcrf"
|
2023-02-24 21:45:41 +00:00
|
|
|
DEBUG "tpmr seal $KEY_FILE 0x8100000$TPM_INDEX sha256:0,1,2,3,4,5,6,7 $pcrf <password>"
|
2023-02-23 14:15:00 +00:00
|
|
|
tpmr seal "$KEY_FILE" "0x8100000$TPM_INDEX" sha256:0,1,2,3,4,5,6,7 "$pcrf" "$key_password"
|
2022-08-25 18:43:31 +00:00
|
|
|
if [ $? -eq 0 ]; then
|
|
|
|
# should be okay if this fails
|
|
|
|
shred -n 10 -z -u "$pcrf".* 2> /dev/null || true
|
|
|
|
fi
|
2017-07-12 04:17:45 +00:00
|
|
|
fi
|
|
|
|
|
2019-02-22 15:52:35 +00:00
|
|
|
shred -n 10 -z -u "$TPM_SEALED" 2> /dev/null \
|
2017-07-12 04:17:45 +00:00
|
|
|
|| warn "Failed to delete the sealed secret - continuing"
|
2022-08-25 18:43:31 +00:00
|
|
|
|
|
|
|
cp /tmp/luksDump.txt "$paramsdir/kexec_lukshdr_hash.txt" \
|
|
|
|
|| warn "Failed to have hashes of LUKS header - continuing"
|