mirror of
https://github.com/linuxboot/heads.git
synced 2025-02-21 09:31:51 +00:00
Added TPM secret management to generic boot
Also cleaned up error handling and boot parsing edge cases
This commit is contained in:
parent
d67360a24b
commit
22a52ec4b8
@ -18,7 +18,7 @@ CONFIG_DROPBEAR=y
|
|||||||
CONFIG_LINUX_USB=y
|
CONFIG_LINUX_USB=y
|
||||||
CONFIG_LINUX_E1000E=y
|
CONFIG_LINUX_E1000E=y
|
||||||
|
|
||||||
CONFIG_BOOTSCRIPT=/bin/local-init
|
CONFIG_BOOTSCRIPT=/bin/generic-init
|
||||||
|
|
||||||
CONFIG_BOOT_REQ_HASH=n
|
CONFIG_BOOT_REQ_HASH=n
|
||||||
CONFIG_BOOT_REQ_ROLLBACK=n
|
CONFIG_BOOT_REQ_ROLLBACK=n
|
||||||
|
@ -9,9 +9,6 @@ if ! confirm_totp ; then
|
|||||||
recovery 'Failed to unseal TOTP'
|
recovery 'Failed to unseal TOTP'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Extend PCR4 as soon as possible
|
|
||||||
tpm extend -ix 4 -ic local
|
|
||||||
|
|
||||||
if [ ! "$totp_confirm" = "y" ]; then
|
if [ ! "$totp_confirm" = "y" ]; then
|
||||||
recovery "Failed to confirm validity of TOTP"
|
recovery "Failed to confirm validity of TOTP"
|
||||||
fi
|
fi
|
@ -1,17 +1,29 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
# Launches kexec from saved configuration entries
|
||||||
|
set -e -o pipefail
|
||||||
. /etc/functions
|
. /etc/functions
|
||||||
|
|
||||||
dryrun="n"
|
dryrun="n"
|
||||||
while getopts "b:e:r:a:d" arg; do
|
printfiles="n"
|
||||||
|
printinitrd="n"
|
||||||
|
while getopts "b:e:r:a:o:fi" arg; do
|
||||||
case $arg in
|
case $arg in
|
||||||
b) bootdir="$OPTARG" ;;
|
b) bootdir="$OPTARG" ;;
|
||||||
e) entry="$OPTARG" ;;
|
e) entry="$OPTARG" ;;
|
||||||
r) cmdremove="$OPTARG" ;;
|
r) cmdremove="$OPTARG" ;;
|
||||||
a) cmdadd="$OPTARG" ;;
|
a) cmdadd="$OPTARG" ;;
|
||||||
d) dryrun="y" ;;
|
o) override_initrd="$OPTARG" ;;
|
||||||
|
f) dryrun="y"; printfiles="y" ;;
|
||||||
|
i) dryrun="y"; printinitrd="y" ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ -z "$bootdir" -o -z "$entry" ]; then
|
||||||
|
die "Usage: $0 -b /boot/ -e 'kexec params|...|...'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
bootdir=${bootdir%%"/"}
|
||||||
|
|
||||||
kexectype=`echo $entry | cut -d\| -f2`
|
kexectype=`echo $entry | cut -d\| -f2`
|
||||||
kexecparams=`echo $entry | cut -d\| -f3- | tr '|' '\n'`
|
kexecparams=`echo $entry | cut -d\| -f3- | tr '|' '\n'`
|
||||||
kexeccmd="kexec"
|
kexeccmd="kexec"
|
||||||
@ -21,11 +33,15 @@ cmdadd="intel_iommu=on $cmdadd"
|
|||||||
cmdremove="quiet $cmdremove"
|
cmdremove="quiet $cmdremove"
|
||||||
|
|
||||||
fix_file_path() {
|
fix_file_path() {
|
||||||
if [ "$dryrun" = "y" ]; then echo ".$firstval"; fi
|
if [ "$printfiles" = "y" ]; then
|
||||||
|
# output file relative to local boot directory
|
||||||
|
echo ".$firstval"
|
||||||
|
fi
|
||||||
|
|
||||||
|
filepath="$bootdir$firstval"
|
||||||
|
|
||||||
filepath=`find $bootdir -path "*$firstval" | tail -1`
|
|
||||||
if ! [ -r $filepath ]; then
|
if ! [ -r $filepath ]; then
|
||||||
die "failed to find file $firstval"
|
die "Failed to find file $firstval"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +57,7 @@ adjust_cmd_line() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
first_module=y
|
module_number="1"
|
||||||
while read line
|
while read line
|
||||||
do
|
do
|
||||||
key=`echo $line | cut -d\ -f1`
|
key=`echo $line | cut -d\ -f1`
|
||||||
@ -64,14 +80,31 @@ do
|
|||||||
if [ "$key" = "module" ]; then
|
if [ "$key" = "module" ]; then
|
||||||
fix_file_path
|
fix_file_path
|
||||||
cmdline="$restval"
|
cmdline="$restval"
|
||||||
if [ -n "$first_module" ]; then
|
if [ "$kexectype" = "xen" ]; then
|
||||||
adjust_cmd_line
|
if [ "$module_number" -eq 1 ]; then
|
||||||
unset first_module
|
adjust_cmd_line
|
||||||
|
elif [ "$module_number" -eq 2 ]; then
|
||||||
|
if [ "$printinitrd" = "y" ]; then
|
||||||
|
# output the current path to initrd
|
||||||
|
echo $filepath
|
||||||
|
fi
|
||||||
|
if [ -n "$override_initrd" ]; then
|
||||||
|
filepath="$override_initrd"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
module_number=`expr $module_number + 1`
|
||||||
kexeccmd="$kexeccmd --module \"$filepath $cmdline\""
|
kexeccmd="$kexeccmd --module \"$filepath $cmdline\""
|
||||||
fi
|
fi
|
||||||
if [ "$key" = "initrd" ]; then
|
if [ "$key" = "initrd" ]; then
|
||||||
fix_file_path
|
fix_file_path
|
||||||
|
if [ "$printinitrd" = "y" ]; then
|
||||||
|
# output the current path to initrd
|
||||||
|
echo $filepath
|
||||||
|
fi
|
||||||
|
if [ -n "$override_initrd" ]; then
|
||||||
|
filepath="$override_initrd"
|
||||||
|
fi
|
||||||
kexeccmd="$kexeccmd --initrd=$filepath"
|
kexeccmd="$kexeccmd --initrd=$filepath"
|
||||||
fi
|
fi
|
||||||
if [ "$key" = "append" ]; then
|
if [ "$key" = "append" ]; then
|
||||||
|
61
initrd/bin/kexec-insert-key
Executable file
61
initrd/bin/kexec-insert-key
Executable file
@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Unseal a disk key from TPM and add to a new initramfs
|
||||||
|
set -e -o pipefail
|
||||||
|
. /etc/functions
|
||||||
|
|
||||||
|
TMP_KEY_DEVICES="/tmp/kexec/kexec_key_devices.txt"
|
||||||
|
TMP_KEY_LVM="/tmp/kexec/kexec_key_lvm.txt"
|
||||||
|
|
||||||
|
INITRD="$1"
|
||||||
|
|
||||||
|
if [ -z "$INITRD" ]; then
|
||||||
|
die "Usage: $0 /boot/initramfs... "
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -r "$TMP_KEY_DEVICES" ]; then
|
||||||
|
die "No devices defined for disk encryption"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -r "$TMP_KEY_LVM" ]; then
|
||||||
|
# Activate the LVM volume group
|
||||||
|
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"
|
||||||
|
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"
|
||||||
|
|
||||||
|
# Unpack the initrd and fixup the /etc/crypttab
|
||||||
|
# this is a hack to split it into two parts since
|
||||||
|
# we know that the first 0x3400 bytes are the microcode
|
||||||
|
INITRD_DIR=/tmp/secret/initrd
|
||||||
|
SECRET_CPIO=/tmp/secret/initrd.cpio
|
||||||
|
mkdir -p "$INITRD_DIR/etc"
|
||||||
|
|
||||||
|
# Attempt to unseal the disk key from the TPM
|
||||||
|
# should we give this some number of tries?
|
||||||
|
if ! kexec-unseal-key "$INITRD_DIR/secret.key" ; then
|
||||||
|
die 'Unseal disk key failed'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Override PCR 4 so that user can't read the key
|
||||||
|
tpm extend -ix 4 -ic generic \
|
||||||
|
|| die 'Unable to scramble PCR'
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
# overwrite /etc/crypttab to mirror the behavior for in seal-key
|
||||||
|
for uuid in `cat "$TMP_KEY_DEVICES" | cut -d\ -f2`; do
|
||||||
|
echo "luks-$uuid UUID=$uuid /secret.key" >> "$INITRD_DIR/etc/crypttab"
|
||||||
|
done
|
||||||
|
( cd "$INITRD_DIR" ; find . -type f | cpio -H newc -o ) >> "$SECRET_CPIO"
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Boot from signed ISO
|
# Boot from signed ISO
|
||||||
|
set -e -o pipefail
|
||||||
. /etc/functions
|
. /etc/functions
|
||||||
. /etc/config
|
. /etc/config
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
file="$1"
|
set -e -o pipefail
|
||||||
|
bootdir="$1"
|
||||||
|
file="$2"
|
||||||
|
filedir=`dirname $file`
|
||||||
|
|
||||||
reset_entry() {
|
reset_entry() {
|
||||||
name=""
|
name=""
|
||||||
@ -10,20 +13,38 @@ reset_entry() {
|
|||||||
append=""
|
append=""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bootdir=${bootdir%%"/"}
|
||||||
|
bootlen=${#bootdir}
|
||||||
|
appenddir=${filedir:$bootlen}
|
||||||
|
|
||||||
|
fix_path() {
|
||||||
|
path="$@"
|
||||||
|
if [ "${path:0:1}" != "/" ]; then
|
||||||
|
path="$appenddir/$path"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
echo_entry() {
|
echo_entry() {
|
||||||
if [ "$kexectype" = "elf" ]; then
|
if [ "$kexectype" = "elf" ]; then
|
||||||
if [ -z "$kernel" ]; then return; fi
|
if [ -z "$kernel" ]; then return; fi
|
||||||
|
|
||||||
entry="$name|$kexectype|kernel $kernel"
|
fix_path $kernel
|
||||||
if [ -n "$initrd" ]; then entry="$entry|initrd $initrd"; fi
|
entry="$name|$kexectype|kernel $path"
|
||||||
if [ -n "$append" ]; then entry="$entry|append $append"; fi
|
if [ -n "$initrd" ]; then
|
||||||
|
fix_path $initrd
|
||||||
|
entry="$entry|initrd $path"
|
||||||
|
fi
|
||||||
|
if [ -n "$append" ]; then
|
||||||
|
entry="$entry|append $append"
|
||||||
|
fi
|
||||||
|
|
||||||
echo $(eval "echo \"$entry\"")
|
echo $(eval "echo \"$entry\"")
|
||||||
fi
|
fi
|
||||||
if [ "$kexectype" = "multiboot" -o "$kexectype" = "xen" ]; then
|
if [ "$kexectype" = "multiboot" -o "$kexectype" = "xen" ]; then
|
||||||
if [ -z "$kernel" ]; then return; fi
|
if [ -z "$kernel" ]; then return; fi
|
||||||
|
|
||||||
echo $(eval "echo \"$name|$kexectype|kernel $kernel$modules\"")
|
fix_path $kernel
|
||||||
|
echo $(eval "echo \"$name|$kexectype|kernel $path$modules\"")
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +84,8 @@ grub_entry() {
|
|||||||
case $val in
|
case $val in
|
||||||
--nounzip*) val=`echo $val | cut -d\ -f2-` ;;
|
--nounzip*) val=`echo $val | cut -d\ -f2-` ;;
|
||||||
esac
|
esac
|
||||||
modules="$modules|module $val"
|
fix_path $val
|
||||||
|
modules="$modules|module $path"
|
||||||
;;
|
;;
|
||||||
linux*)
|
linux*)
|
||||||
kernel=`echo $trimcmd | cut -d\ -f2`
|
kernel=`echo $trimcmd | cut -d\ -f2`
|
||||||
@ -103,7 +125,8 @@ syslinux_multiboot_append() {
|
|||||||
if [ -z "$kernel" ]; then
|
if [ -z "$kernel" ]; then
|
||||||
kernel="$line"
|
kernel="$line"
|
||||||
else
|
else
|
||||||
modules="$modules|module $line"
|
fix_path $line
|
||||||
|
modules="$modules|module $path"
|
||||||
fi
|
fi
|
||||||
done << EOF
|
done << EOF
|
||||||
$splitval
|
$splitval
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Save these options to be the persistent default
|
# Save these options to be the persistent default
|
||||||
|
set -e -o pipefail
|
||||||
. /etc/functions
|
. /etc/functions
|
||||||
|
|
||||||
while getopts "b:d:p:e:i:" arg; do
|
while getopts "b:d:p:e:i:" arg; do
|
||||||
@ -43,9 +44,11 @@ if [ ! -d $paramsdir ]; then
|
|||||||
mkdir -p $paramsdir \
|
mkdir -p $paramsdir \
|
||||||
|| die "Failed to create params directory"
|
|| die "Failed to create params directory"
|
||||||
fi
|
fi
|
||||||
rm "$paramsdir/kexec_default.*.txt" 2>/dev/null
|
rm "$paramsdir/kexec_default.*.txt" 2>/dev/null || true
|
||||||
echo "$entry" > $ENTRY_FILE
|
echo "$entry" > $ENTRY_FILE
|
||||||
cd $bootdir && kexec-boot -e "$entry" -d | 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
|
if [ ! -r $ENTRY_FILE -o ! -r $HASH_FILE ]; then
|
||||||
die "Failed to write default config"
|
die "Failed to write default config"
|
||||||
fi
|
fi
|
||||||
|
63
initrd/bin/kexec-save-key
Executable file
63
initrd/bin/kexec-save-key
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Generate a TPM key used to unlock LUKS disks
|
||||||
|
set -e -o pipefail
|
||||||
|
. /etc/functions
|
||||||
|
|
||||||
|
lvm_volume_group=""
|
||||||
|
while getopts "p:d:l:" arg; do
|
||||||
|
case $arg in
|
||||||
|
p) paramsdir="$OPTARG" ;;
|
||||||
|
d) paramsdev="$OPTARG" ;;
|
||||||
|
l) lvm_volume_group="$OPTARG" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift `expr $OPTIND - 1`
|
||||||
|
key_devices="$@"
|
||||||
|
|
||||||
|
if [ -z "$paramsdir" ]; then
|
||||||
|
die "Usage: $0 -p /boot/ [-l qubes_dom0] [/dev/sda2 /dev/sda5 ...] "
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$paramsdev" ]; then
|
||||||
|
paramsdev="$paramsdir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$lvm_volume_group" ]; then
|
||||||
|
lvm vgchange -a y $lvm_volume_group \
|
||||||
|
|| die "Failed to activate the LVM group"
|
||||||
|
|
||||||
|
for dev in /dev/$lvm_volume_group/*; do
|
||||||
|
key_devices="$key_devices $dev"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$key_devices" ]; then
|
||||||
|
die "No devices specified for TPM key insertion"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# try to switch to rw mode
|
||||||
|
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 "
|
||||||
|
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"
|
||||||
|
done
|
||||||
|
|
||||||
|
kexec-seal-key $paramsdir \
|
||||||
|
|| die "Failed to save and generate key in TPM"
|
||||||
|
|
||||||
|
# sign and auto-roll config counter
|
||||||
|
kexec-sign-config -p $paramsdir -u \
|
||||||
|
|| die "Failed to sign updated config"
|
||||||
|
|
||||||
|
# switch back to ro mode
|
||||||
|
mount -o ro,remount $paramsdev
|
145
initrd/bin/kexec-seal-key
Executable file
145
initrd/bin/kexec-seal-key
Executable file
@ -0,0 +1,145 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# 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
|
||||||
|
|
||||||
|
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
|
||||||
|
. /etc/config
|
||||||
|
|
||||||
|
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"
|
||||||
|
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
|
||||||
|
|
||||||
|
# Key slot 0 is the manual recovery pass phrase
|
||||||
|
# that they user entered when they installed Qubes,
|
||||||
|
# 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
|
||||||
|
|
||||||
|
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"
|
||||||
|
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"
|
||||||
|
luks_pcr=`tpm calcfuturepcr -ix 16 -if /tmp/luksDump.txt`
|
||||||
|
|
||||||
|
# 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 recovery shell.
|
||||||
|
# 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").
|
||||||
|
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 0000000000000000000000000000000000000000 \
|
||||||
|
-ix 6 $luks_pcr \
|
||||||
|
|| die "Unable to seal secret"
|
||||||
|
|
||||||
|
rm -f "$KEY_FILE" \
|
||||||
|
|| die "Failed to delete key file"
|
||||||
|
|
||||||
|
# try it without the owner password first
|
||||||
|
if ! tpm nv_writevalue \
|
||||||
|
-in $TPM_INDEX \
|
||||||
|
-if "$TPM_SEALED" \
|
||||||
|
; 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
|
||||||
|
|
||||||
|
rm "$TPM_SEALED" \
|
||||||
|
|| warn "Failed to delete the sealed secret - continuing"
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Generic configurable boot script via kexec
|
# Generic configurable boot script via kexec
|
||||||
set -o pipefail
|
set -e -o pipefail
|
||||||
. /etc/config
|
. /etc/config
|
||||||
. /etc/functions
|
. /etc/functions
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ scan_options() {
|
|||||||
option_file="/tmp/kexec_options.txt"
|
option_file="/tmp/kexec_options.txt"
|
||||||
if [ -r $option_file ]; then rm $option_file; fi
|
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
|
||||||
kexec-parse-boot $i >> $option_file
|
kexec-parse-boot "$bootdir" "$i" >> $option_file
|
||||||
done
|
done
|
||||||
if [ ! -r $option_file ]; then
|
if [ ! -r $option_file ]; then
|
||||||
die "Failed to parse any boot options"
|
die "Failed to parse any boot options"
|
||||||
@ -222,18 +222,40 @@ do_boot()
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
kexec-boot -b "$bootdir" -e "$option" -a "$add" -r "$remove"
|
if [ -r "$TMP_KEY_DEVICES" ]; then
|
||||||
die "!!! Failed to boot w/ options: $option"
|
INITRD=`kexec-boot -b "$bootdir" -e "$option" -i` \
|
||||||
|
|| die "!!! Failed to extract the initrd from boot option"
|
||||||
|
if [ -z "$INITRD" ]; then
|
||||||
|
die "!!! No initrd file found in boot option"
|
||||||
|
fi
|
||||||
|
|
||||||
|
kexec-insert-key $INITRD \
|
||||||
|
|| die "!!! Failed to insert disk key into a new initrd"
|
||||||
|
|
||||||
|
kexec-boot -b "$bootdir" -e "$option" \
|
||||||
|
-a "$add" -r "$remove" -o "/tmp/secret/initrd.cpio" \
|
||||||
|
|| die "!!! Failed to boot w/ options: $option"
|
||||||
|
else
|
||||||
|
kexec-boot -b "$bootdir" -e "$option" -a "$add" -r "$remove" \
|
||||||
|
|| die "!!! Failed to boot w/ options: $option"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
check_config $paramsdir
|
check_config $paramsdir
|
||||||
|
TMP_DEFAULT_FILE=`find /tmp/kexec/kexec_default.*.txt 2>/dev/null | head -1` || true
|
||||||
TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt"
|
TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt"
|
||||||
TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt"
|
TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt"
|
||||||
TMP_DEFAULT_FILE=`find /tmp/kexec/kexec_default.*.txt 2>/dev/null | head -1`
|
|
||||||
TMP_DEFAULT_HASH_FILE="/tmp/kexec/kexec_default_hashes.txt"
|
TMP_DEFAULT_HASH_FILE="/tmp/kexec/kexec_default_hashes.txt"
|
||||||
TMP_ROLLBACK_FILE="/tmp/kexec/kexec_rollback.txt"
|
TMP_ROLLBACK_FILE="/tmp/kexec/kexec_rollback.txt"
|
||||||
|
TMP_KEY_DEVICES="/tmp/kexec/kexec_key_devices.txt"
|
||||||
|
TMP_KEY_LVM="/tmp/kexec/kexec_key_lvm.txt"
|
||||||
|
|
||||||
|
if [ ! -r "$TMP_KEY_DEVICES" ]; then
|
||||||
|
# Extend PCR4 as soon as possible
|
||||||
|
tpm extend -ix 4 -ic generic \
|
||||||
|
|| die "Failed to extend PCR 4"
|
||||||
|
fi
|
||||||
|
|
||||||
# if no saved options, scan the boot directory and generate
|
# if no saved options, scan the boot directory and generate
|
||||||
if [ ! -r "$TMP_MENU_FILE" ]; then
|
if [ ! -r "$TMP_MENU_FILE" ]; then
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Sign a valid directory of kexec params
|
# Sign a valid directory of kexec params
|
||||||
|
set -e -o pipefail
|
||||||
. /etc/functions
|
. /etc/functions
|
||||||
|
|
||||||
rollback="n"
|
rollback="n"
|
||||||
|
45
initrd/bin/kexec-unseal-key
Executable file
45
initrd/bin/kexec-unseal-key
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# This will unseal and unecncrypt the drive encryption key from the TPM
|
||||||
|
# The TOTP secret will be shown to the user on each encryption attempt.
|
||||||
|
# It will then need to be bundled into initrd that is booted with Qubes.
|
||||||
|
set -e -o pipefail
|
||||||
|
|
||||||
|
TPM_INDEX=3
|
||||||
|
TPM_SIZE=312
|
||||||
|
|
||||||
|
. /etc/functions
|
||||||
|
mkdir -p /tmp/secret
|
||||||
|
|
||||||
|
sealed_file="/tmp/secret/sealed.key"
|
||||||
|
key_file="$1"
|
||||||
|
|
||||||
|
if [ -z "$key_file" ]; then
|
||||||
|
key_file="/tmp/secret/secret.key"
|
||||||
|
fi
|
||||||
|
|
||||||
|
tpm nv_readvalue \
|
||||||
|
-in "$TPM_INDEX" \
|
||||||
|
-sz "$TPM_SIZE" \
|
||||||
|
-of "$sealed_file" \
|
||||||
|
|| die "Unable to read key from TPM NVRAM"
|
||||||
|
|
||||||
|
for tries in 1 2 3; do
|
||||||
|
read -s -p "Enter unlock password: " tpm_password
|
||||||
|
echo
|
||||||
|
|
||||||
|
if tpm unsealfile \
|
||||||
|
-if "$sealed_file" \
|
||||||
|
-of "$key_file" \
|
||||||
|
-pwdd "$tpm_password" \
|
||||||
|
-hk 40000000 \
|
||||||
|
; then
|
||||||
|
# should be okay if this fails
|
||||||
|
rm -f /tmp/secret/sealed || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
pcrs
|
||||||
|
warn "Unable to unseal disk encryption key"
|
||||||
|
done
|
||||||
|
|
||||||
|
die "Retry count exceeded..."
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Scan for USB installation options
|
# Scan for USB installation options
|
||||||
|
set -e -o pipefail
|
||||||
. /etc/functions
|
. /etc/functions
|
||||||
. /etc/config
|
. /etc/config
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ get_menu_option() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# create ISO menu options
|
# create ISO menu options
|
||||||
ls -1r /media/*.iso 2>/dev/null > /tmp/iso_menu.txt
|
ls -1r /media/*.iso 2>/dev/null > /tmp/iso_menu.txt || true
|
||||||
if [ `cat /tmp/iso_menu.txt | wc -l` -gt 0 ]; then
|
if [ `cat /tmp/iso_menu.txt | wc -l` -gt 0 ]; then
|
||||||
option_confirm=""
|
option_confirm=""
|
||||||
while [ -z "$option" -a "$option_index" != "s" ]
|
while [ -z "$option" -a "$option_index" != "s" ]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user