Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add support for TPM2 in all shell scripts #1031

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions initrd/bin/cbfs-init
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ for cbfsname in `echo $cbfsfiles`; do
|| die "$filename: mkdir failed"
cbfs -t 50 -r $cbfsname > "$filename" \
|| die "$filename: cbfs file read failed"
if [ "$CONFIG_TPM" = "y" ]; then
TMPFILE=/tmp/cbfs.$$
echo "$filename" > $TMPFILE
cat $filename >> $TMPFILE
tpm extend -ix "$CONFIG_PCR" -if $TMPFILE \
|| die "$filename: tpm extend failed"
fi

TMPFILE=/tmp/cbfs.$$
echo "$filename" > $TMPFILE
cat $filename >> $TMPFILE
tpmx extend "$TMPFILE" "$CONFIG_PCR" \
|| die "$filename: tpm extend failed"
fi
done

Expand Down
3 changes: 1 addition & 2 deletions initrd/bin/kexec-insert-key
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ if ! kexec-unseal-key "$INITRD_DIR/secret.key" ; then
fi

# Override PCR 4 so that user can't read the key
tpm extend -ix 4 -ic generic \
|| die 'Unable to scramble PCR'
tpmx extend generic || die 'Unable to scramble PCR'

# Check to continue
if [ "$unseal_failed" = "y" ]; then
Expand Down
8 changes: 2 additions & 6 deletions initrd/bin/kexec-select-boot
Original file line number Diff line number Diff line change
Expand Up @@ -338,12 +338,8 @@ while true; do
user_select
fi

if [ "$CONFIG_TPM" = "y" \
-a ! -r "$TMP_KEY_DEVICES" ]; then
# Extend PCR4 as soon as possible
tpm extend -ix 4 -ic generic \
|| die "Failed to extend PCR 4"
fi
# Extend PCR4 as soon as possible
tpmx extend generic || die "Failed to extend PCR 4"

# if no saved options, scan the boot directory and generate
if [ ! -r "$TMP_MENU_FILE" ]; then
Expand Down
3 changes: 1 addition & 2 deletions initrd/bin/qubes-measure-luks
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ for dev in "$@"; do
|| die "$dev: Unable to measure"
done > /tmp/luksDump.txt

tpm extend -ix 6 -if /tmp/luksDump.txt \
|| die "Unable to extend PCR"
tpmx extend /tmp/luksDump.txt 6 || die "Unable to extend PCR6"
30 changes: 30 additions & 0 deletions initrd/bin/recovery
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/sh

. /etc/functions

echo >&2 "!!!!! $*"

# Remove any temporary secret files that might be hanging around
# but recreate the directory so that new tools can use it.
shred -n 10 -z -u /tmp/secret/* 2> /dev/null
rm -rf /tmp/secret
mkdir -p /tmp/secret

# ensure /tmp/config exists for recovery scripts that depend on it
touch /tmp/config

tpmx extend recovery

while [ true ]
do
echo >&2 "!!!!! Starting recovery shell"
sleep 1

if [ -x /bin/setsid ]; then
/bin/setsid -c /bin/ash
else
/bin/ash
fi
# clear screen
printf "\033c"
done
17 changes: 1 addition & 16 deletions initrd/bin/seal-hotpkey
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mount_boot()
fi
}

# TODO: This really should be queried from USB device information
# Use stored HOTP key branding (this might be useful after OEM reset)
if [ -r /boot/kexec_hotp_key ]; then
HOTPKEY_BRANDING="$(cat /boot/kexec_hotp_key)"
Expand All @@ -43,17 +44,6 @@ shred -n 10 -z -u "$HOTP_SEALED" 2> /dev/null
# get current value of HOTP counter in TPM, create if absent
mount_boot

#check_tpm_counter $HOTP_COUNTER hotp \
#|| die "Unable to find/create TPM counter"
#counter="$TPM_COUNTER"
#
#counter_value=$(read_tpm_counter $counter | cut -f2 -d ' ' | awk 'gsub("^000e","")')
#if [ "$counter_value" == "" ]; then
# die "Unable to read HOTP counter"
#fi

#counter_value=$(printf "%d" 0x${counter_value})

counter_value=1

enable_usb
Expand Down Expand Up @@ -96,11 +86,6 @@ fi
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null

# Make sure our counter is incremented ahead of the next check
#increment_tpm_counter $counter > /dev/null \
#|| die "Unable to increment tpm counter"
#increment_tpm_counter $counter > /dev/null \
#|| die "Unable to increment tpm counter"

mount -o remount,rw /boot

counter_value=`expr $counter_value + 1`
Expand Down
34 changes: 1 addition & 33 deletions initrd/bin/tpm-reset
Original file line number Diff line number Diff line change
@@ -1,34 +1,2 @@
#!/bin/sh
. /etc/functions

echo '*****'
echo '***** WARNING: This will erase all keys and secrets from the TPM'
echo '*****'

read -s -p "New TPM owner password: " key_password
echo

if [ -z "$key_password" ]; then
die "Empty owner password is not allowed"
fi

read -s -p "Repeat owner password: " key_password2
echo


if [ "$key_password" != "$key_password2" ]; then
die "Key passwords do not match"
fi

# Make sure the TPM is ready to be reset
tpm physicalpresence -s
tpm physicalenable
tpm physicalsetdeactivated -c
tpm forceclear
tpm physicalenable
tpm takeown -pwdo "$key_password"

# And now turn it all back on
tpm physicalpresence -s
tpm physicalenable
tpm physicalsetdeactivated -c
tpmx reset
113 changes: 113 additions & 0 deletions initrd/bin/tpmx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#!/bin/sh

# Abstraction layer over tpm commands to ensure the programmer does not have to
# care about TPM 1.2 vs TPM2

set -e pipefail

. /etc/functions

SECRET_DIR="/tmp/secret"
DEFAULT_HANDLE="0x81000000"
ENC_SESSION_FILE="enc.ctx"
DEC_SESSION_FILE="dec.ctx"

# @param: code to be extended
# @param (optional): PCR index to extend, default 4
extend()
{
local ARGUMENT=$1
local PCR=${2:-4}

if [ "$CONFIG_TPM" = "y" ]; then
tpm extend -ix $PCR -ic $ARGUMENT
elif ["$CONFIG_TPM2" = "y" ]; then
tpm2 pcrevent $PCR $ARGUMENT $1>/dev/null
fi
}

# Clears all keys from the TPM and takes ownership
reset()
{
echo '*****'
echo '***** WARNING: This will erase all keys and secrets from the TPM'
echo '*****'

read -s -p "New TPM owner password: " key_password
echo

if [ -z "$key_password" ]; then
die "Empty owner password is not allowed"
fi

read -s -p "Repeat owner password: " key_password2
echo

if [ "$key_password" != "$key_password2" ]; then
die "Key passwords do not match"
fi

if [ "$CONFIG_TPM" = "y" ]; then
# Make sure the TPM is ready to be reset
tpm physicalpresence -s
tpm physicalenable
tpm physicalsetdeactivated -c
tpm forceclear
tpm physicalenable
tpm takeown -pwdo "$key_password"

# And now turn it all back on
tpm physicalpresence -s
tpm physicalenable
tpm physicalsetdeactivated -c

elif [ "$CONFIG_TPM2" = "y" ]; then
mkdir -p "$SECRET_DIR"
tpm2 clear -c platform
tpm2 changeauth -c owner "$key_password"
tpm2 createprimary -C owner -g sha256 -G \
"${CONFIG_PRIMARY_KEY_TYPE:-rsa}" \
-c "$SECRET_DIR/primary.ctx" -P "$key_password"
tpm2 evictcontrol -C owner -c "$SECRET_DIR/primary.ctx" \
"$DEFAULT_HANDLE" -P "$key_password"
startsession
fi
}

# TPM2 Only, start an auth session with the TPM. Should be done very early on
# to prevent TPM sniffing attacks
tpm2_startsession()
{
if [ "$CONFIG_TPM2" = "y" ]; then
mkdir -p "$SECRET_DIR"
tpm2 startauthsession -c "$DEFAULT_HANDLE" --hmac-session \
-S "/tmp/$ENC_SESSION_FILE"
tpm2 startauthsession -c "$DEFAULT_HANDLE" --hmac-session \
-S "/tmp/$DEC_SESSION_FILE"
tpm2 sessionconfig --disable-encrypt "/tmp/$DEC_SESSION_FILE"
fi
}

usage()
{
echo "Usage: tpmx [COMMAND] [ARGS] "
echo "Commands: "
echo " extend [ARGUMENT] [PCR] extends argument into pcr (default pcr is 4) "
echo " reset clears all keys from tpm and take ownership "
echo "TPM2 only commands: "
echo " startsession establish a secure channel with the tpm "
}

cmd="$1"
shift 1
case "$cmd" in
extend)
extend "$@";;
reset)
reset "$@";;
startsession)
tpm2_startsession "@";;
*)
usage
exit 1
esac
6 changes: 2 additions & 4 deletions initrd/bin/uefi-init
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ if [ -n "GUID" ]; then
uefi -r $GUID | gunzip -c > $TMPFILE \
|| die "Failed to read config GUID from ROM"

if [ "$CONFIG_TPM" = "y" ]; then
tpm extend -ix "$CONFIG_PCR" -if $TMPFILE \
|| die "$filename: tpm extend failed"
fi
tpmx extend "$TMPFILE" "$CONFIG_PCR" \
|| die "$filename: tpm extend failed"

( cd / ; cpio -iud < $TMPFILE 2>/dev/null ) \
|| die "Failed to extract config GUID"
Expand Down
36 changes: 9 additions & 27 deletions initrd/bin/unseal-hotp
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,26 @@

. /etc/functions

HOTP_SEALED="/tmp/secret/hotp.sealed"
HOTP_SECRET="/tmp/secret/hotp.key"
HOTP_COUNTER="/boot/kexec_hotp_counter"

mount_boot_or_die()
{
# Mount local disk if it is not already mounted
if ! grep -q /boot /proc/mounts ; then
mount -o ro /boot \
|| die "Unable to mount /boot"
fi
}

# Store counter in file instead of TPM for now, as it conflicts with Heads
# config TPM counter as TPM 1.2 can only increment one counter between reboots
# get current value of HOTP counter in TPM, create if absent
mount_boot_or_die

#check_tpm_counter $HOTP_COUNTER hotp \
#|| die "Unable to find/create TPM counter"
#counter="$TPM_COUNTER"
#
#counter_value=$(read_tpm_counter $counter | cut -f2 -d ' ' | awk 'gsub("^000e","")')
#
HOTP_SEALED="/tmp/secret/hotp.sealed"
HOTP_SECRET="/tmp/secret/hotp.key"
HOTP_COUNTER="/boot/kexec_hotp_counter"

# Mount local disk if it is not already mounted
if ! grep -q /boot /proc/mounts ; then
mount -o ro /boot \
|| die "Unable to mount /boot"
fi

counter_value=$(cat $HOTP_COUNTER)

if [ "$counter_value" == "" ]; then
die "Unable to read HOTP counter"
fi

#counter_value=$(printf "%d" 0x${counter_value})

tpm nv_readvalue \
-in 4d47 \
-sz 312 \
Expand All @@ -57,17 +44,12 @@ fi

shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null

#increment_tpm_counter $counter > /dev/null \
#|| die "Unable to increment tpm counter"

mount -o remount,rw /boot

counter_value=`expr $counter_value + 1`
echo $counter_value > $HOTP_COUNTER \
|| die "Unable to create hotp counter file"

#sha256sum /tmp/counter-$counter > $HOTP_COUNTER \
#|| die "Unable to create hotp counter file"
mount -o remount,ro /boot

exit 0
3 changes: 1 addition & 2 deletions initrd/bin/usb-init
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#!/bin/sh
# Boot a USB installation

. /etc/functions
. /tmp/config

if [ "$CONFIG_TPM" = "y" ]; then
# Extend PCR4 as soon as possible
tpm extend -ix 4 -ic usb
tpmx extend usb
fi

usb-scan
Expand Down
2 changes: 1 addition & 1 deletion initrd/bin/wget-measure.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ fi
wget "$URL" || die "$URL: failed"

FILE="`basename "$URL"`"
tpm extend -ix "$INDEX" -if "$FILE" || die "$FILE: tpm extend failed"
tpmx extend "$FILE" "$INDEX" || die "$FILE: tpm extend failed"


Loading