Verified Commit 1f739942 authored by Kyle Rankin's avatar Kyle Rankin Committed by Matt Devillier
Browse files

Use the Librem Key as a TPM work-alike in the absence of a TPM



On machines without a TPM, we'd still like some way for the BIOS to
attest that it has not been modified. With a Librem Key, we can have the
BIOS use its own ROM measurement converted to a SHA256sum and truncated
so it fits within an HOTP secret. Like with a TPM, a malicious BIOS with
access to the correct measurements can send pre-known good measurements
to the Librem Key.

This approach provides one big drawback in that we have to truncate the
SHA256sum to 20 characters so that it fits within the limitations of
HOTP secrets. This means the possibility of collisions is much higher
but again, an attacker could also capture and spoof an existing ROM's
measurements if they have prior access to it, either with this approach
or with a TPM.
Signed-off-by: Kyle Rankin's avatarKyle Rankin <kyle.rankin@puri.sm>
parent 9339394b
......@@ -8,7 +8,7 @@ set -e -o pipefail
case "$CONFIG_FLASHROM_OPTIONS" in
-* )
echo "Board $CONFIG_BOARD detected, continuing..."
[ "$1" != "-s" ] && echo "Board $CONFIG_BOARD detected, continuing..."
;;
* )
die "ERROR: No board has been configured!\n\nEach board requires specific flashrom options and it's unsafe to flash without them.\n\nAborting."
......@@ -30,6 +30,10 @@ flash_rom() {
else
die "$ROM: Read inconsistent"
fi
elif [ "$SHA" -eq 1 ]; then
flashrom $CONFIG_FLASHROM_OPTIONS -r "${ROM}" 1&>2 >/dev/null \
|| die "$ROM: Read failed"
sha256sum ${ROM} | cut -f1 -d ' '
else
cp "$ROM" /tmp/${CONFIG_BOARD}.rom
sha256sum /tmp/${CONFIG_BOARD}.rom
......@@ -60,20 +64,29 @@ flash_rom() {
if [ "$1" == "-c" ]; then
CLEAN=1
READ=0
SHA=0
ROM="$2"
elif [ "$1" == "-r" ]; then
CLEAN=0
READ=1
SHA=0
ROM="$2"
touch $ROM
elif [ "$1" == "-s" ]; then
CLEAN=0
READ=0
SHA=1
ROM="$2"
touch $ROM
else
CLEAN=0
READ=0
SHA=0
ROM="$1"
fi
if [ ! -e "$ROM" ]; then
die "Usage: $0 [-c|-r] <path_to_image.rom>"
die "Usage: $0 [-c|-r|-s] <path_to_image.rom>"
fi
flash_rom $ROM
......
......@@ -24,19 +24,24 @@ else
HOTPKEY_BRANDING="HOTP USB Security Dongle"
fi
tpm nv_readvalue \
-in 4d47 \
-sz 312 \
-of "$HOTP_SEALED" \
|| die "Unable to retrieve sealed file from TPM NV"
tpm unsealfile \
-hk 40000000 \
-if "$HOTP_SEALED" \
-of "$HOTP_SECRET" \
|| die "Unable to unseal HOTP secret"
shred -n 10 -z -u "$HOTP_SEALED" 2> /dev/null
if [ "$CONFIG_TPM" = "y" ]; then
tpm nv_readvalue \
-in 4d47 \
-sz 312 \
-of "$HOTP_SEALED" \
|| die "Unable to retrieve sealed file from TPM NV"
tpm unsealfile \
-hk 40000000 \
-if "$HOTP_SEALED" \
-of "$HOTP_SECRET" \
|| die "Unable to unseal HOTP secret"
shred -n 10 -z -u "$HOTP_SEALED" 2> /dev/null
else
# without a TPM, use the first 20 characters of the ROM SHA256sum
secret_from_rom_hash > $HOTP_SECRET
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
......
......@@ -17,72 +17,76 @@ fi
TOTP_SECRET="/tmp/secret/totp.key"
TOTP_SEALED="/tmp/secret/totp.sealed"
dd \
if=/dev/urandom \
of="$TOTP_SECRET" \
count=1 \
bs=20 \
2>/dev/null \
|| die "Unable to generate 20 random bytes"
secret="`base32 < $TOTP_SECRET`"
# Use the current values of the PCRs, which will be read
# from the TPM as part of the sealing ("X").
# PCR4 == 0 means that we are still in the boot process and
# not a recovery shell.
# should this read the storage root key?
if ! tpm sealfile2 \
-if "$TOTP_SECRET" \
-of "$TOTP_SEALED" \
-hk 40000000 \
-ix 0 X \
-ix 1 X \
-ix 2 X \
-ix 3 X \
-ix 4 0000000000000000000000000000000000000000 \
-ix 7 X \
; then
shred -n 10 -z -u "$TOTP_SECRET" 2> /dev/null
die "Unable to seal secret"
fi
shred -n 10 -z -u "$TOTP_SECRET" 2> /dev/null
# 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"
# Try to write it without the password first, and then create
# the NVRAM space using the owner password if it fails for some reason.
if ! tpm nv_writevalue \
-in $TPM_NVRAM_SPACE \
-if "$TOTP_SEALED" \
; then
warn 'NVRAM space does not exist? Owner password is required'
read -s -p "TPM Owner password: " tpm_password
echo
tpm nv_definespace \
-in $TPM_NVRAM_SPACE \
-sz 312 \
-pwdo "$tpm_password" \
-per 0 \
|| die "Unable to define NVRAM space"
tpm nv_writevalue \
if [ "$CONFIG_TPM" = "y" ]; then
dd \
if=/dev/urandom \
of="$TOTP_SECRET" \
count=1 \
bs=20 \
2>/dev/null \
|| die "Unable to generate 20 random bytes"
secret="`base32 < $TOTP_SECRET`"
# Use the current values of the PCRs, which will be read
# from the TPM as part of the sealing ("X").
# PCR4 == 0 means that we are still in the boot process and
# not a recovery shell.
# should this read the storage root key?
if ! tpm sealfile2 \
-if "$TOTP_SECRET" \
-of "$TOTP_SEALED" \
-hk 40000000 \
-ix 0 X \
-ix 1 X \
-ix 2 X \
-ix 3 X \
-ix 4 0000000000000000000000000000000000000000 \
-ix 7 X \
; then
shred -n 10 -z -u "$TOTP_SECRET" 2> /dev/null
die "Unable to seal secret"
fi
# 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"
# Try to write it without the password first, and then create
# the NVRAM space using the owner password if it fails for some reason.
if ! tpm nv_writevalue \
-in $TPM_NVRAM_SPACE \
-if "$TOTP_SEALED" \
|| die "Unable to write sealed secret to NVRAM"
; then
warn 'NVRAM space does not exist? Owner password is required'
read -s -p "TPM Owner password: " tpm_password
echo
tpm nv_definespace \
-in $TPM_NVRAM_SPACE \
-sz 312 \
-pwdo "$tpm_password" \
-per 0 \
|| die "Unable to define NVRAM space"
tpm nv_writevalue \
-in $TPM_NVRAM_SPACE \
-if "$TOTP_SEALED" \
|| die "Unable to write sealed secret to NVRAM"
fi
shred -n 10 -z -u "$TOTP_SEALED" 2> /dev/null
else
# without a TPM, use the first 20 characters of the ROM SHA256sum
secret_from_rom_hash > $TOTP_SECRET
secret="`base32 < $TOTP_SECRET`"
shred -n 10 -z -u "$TOTP_SECRET" 2> /dev/null
fi
shred -n 10 -z -u "$TOTP_SEALED" 2> /dev/null
url="otpauth://totp/$HOST?secret=$secret"
secret=""
......
......@@ -36,19 +36,24 @@ fi
#counter_value=$(printf "%d" 0x${counter_value})
tpm nv_readvalue \
-in 4d47 \
-sz 312 \
-of "$HOTP_SEALED" \
|| die "Unable to retrieve sealed file from TPM NV"
tpm unsealfile \
-hk 40000000 \
-if "$HOTP_SEALED" \
-of "$HOTP_SECRET" \
|| die "Unable to unseal HOTP secret"
shred -n 10 -z -u "$HOTP_SEALED" 2> /dev/null
if [ "$CONFIG_TPM" = "y" ]; then
tpm nv_readvalue \
-in 4d47 \
-sz 312 \
-of "$HOTP_SEALED" \
|| die "Unable to retrieve sealed file from TPM NV"
tpm unsealfile \
-hk 40000000 \
-if "$HOTP_SEALED" \
-of "$HOTP_SECRET" \
|| die "Unable to unseal HOTP secret"
shred -n 10 -z -u "$HOTP_SEALED" 2> /dev/null
else
# without a TPM, use the first 20 characters of the ROM SHA256sum
secret_from_rom_hash > $HOTP_SECRET
fi
if ! hotp $counter_value < "$HOTP_SECRET"; then
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null
......
......@@ -267,6 +267,19 @@ combine_configs() {
cat /etc/config* > /tmp/config
}
# Generate secret value using first 20 chars of ROM SHA256 hash
secret_from_rom_hash() {
local ROM_IMAGE="/tmp/coreboot-notpm.rom"
echo -e "\nTPM not detected; measuring ROM directly\n" 1>&2
# use a previously-copied image if it exists
if [ -f ${ROM_IMAGE} ]; then
sha256sum ${ROM_IMAGE} | cut -f1 -d ' ' | cut -c 1-20 | tr -d '\n'
else
flash.sh -s ${ROM_IMAGE} | cut -c 1-20 | tr -d '\n'
fi
}
update_checksums()
{
# clear screen
......
......@@ -44,6 +44,11 @@ hwclock -l -s
. /etc/functions
. /etc/config
# Override CONFIG_TPM if needed before init
if [ ! -e /dev/tpm0 ]; then
export CONFIG_TPM='n'
fi
if [ "$CONFIG_COREBOOT" = "y" ]; then
/bin/cbfs-init
fi
......@@ -89,6 +94,11 @@ if [ "$boot_option" = "r" ]; then
exit
fi
# Override CONFIG_TPM if needed and persist via user config
if [ ! -e /dev/tpm0 ]; then
echo "CONFIG_TPM=n" >> /etc/config.user
fi
combine_configs
. /tmp/config
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment