heads/initrd/bin/seal-totp

105 lines
2.7 KiB
Plaintext
Raw Normal View History

#!/bin/bash
# Generate a random secret, seal it with the PCRs
# and write it to the TPM NVRAM.
#
# Pass in a hostname if you want to change it from the default string
#
. /etc/functions
TRACE "Under /bin/seal-totp"
TPM_NVRAM_SPACE=4d47
HOST="$1"
if [ -z "$HOST" ]; then
HOST="TPMTOTP"
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`"
Addition of qemu-(fb)whiptail-tpm2(-hotp) boards -coreboot support of TPM v2.0 (shared config for TPM2 support across all 4 previous variations) -swtpm set to be launched under TPM v2.0 mode under board config -Documentation file under each board.md softlinks to qemu-coreboot-fbwhiptail-tpm1.md (which has been generalized) This is skeleton for TPM v2 integration under Heads ------------- WiP TODO: - libcurl cannot be built as a tpm2-tools dependency as of now not sure why. curl currently needs to be added in board config to be built - Note: tpm-reset (master and here) needs some review, no handle of no tpm use case. Caller is responsible to not call it otherwise does nothing - init tries to bind fd and fails currently - Note: Check if whiptail is different of fbwhiptail in clearing screen. As of now every clear seems to be removed, still whiptail clears previous console output - When no OS' /boot can be mounted, do not try to TPM reset (will fail) - seal-hotpkey is not working properly - setting disk unlock key asks for TPM ownership passphrase (sealing in NV requires ownership, but text is misleading user as if reowning TPM) - We should cache input, feed tpm behind the scene and wipe passphrase and state clearly that this is TPM disk unlock kye passphrase. - primary key from TPM2 is invalid most of the time from kexec-select-boot and verifying global hashes but is setuped correctly at disk unlock key setup - would be nice to take advantage of bash function tracing to understand where we are for debugging purposes, code takes ash in consideration only - tpmr says it implements nv calls but actually doesn't. Removing those falsely wrapped functions would help. - Implementing them would be better - REVIEW TODOS IN CODE - READD CIRCLECI CONFIG Current state: - TPM unseal works without disk unlock key and generates TOTP properly (was missing die condition at unseal to not produce always good TOTP even if invalid) - TPM disk encryption key fails. Hypothesis is that sealing with USB drivers loaded and measures in inconsistent with sealed with/without. - TPM disk unsealing happens without USB modules being loaded in non-HOTP setup. This fails. - Current tests are with fbwhiptail (no clear called so having traces on command line of what happens) - Testing with HOTP implementation for sealing/unsealing since that forces USB module loads on each boot to remove this from failing possibilities
2022-08-25 18:43:31 +00:00
if [ "$CONFIG_TPM" = "y" ];then
# 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
Addition of qemu-(fb)whiptail-tpm2(-hotp) boards -coreboot support of TPM v2.0 (shared config for TPM2 support across all 4 previous variations) -swtpm set to be launched under TPM v2.0 mode under board config -Documentation file under each board.md softlinks to qemu-coreboot-fbwhiptail-tpm1.md (which has been generalized) This is skeleton for TPM v2 integration under Heads ------------- WiP TODO: - libcurl cannot be built as a tpm2-tools dependency as of now not sure why. curl currently needs to be added in board config to be built - Note: tpm-reset (master and here) needs some review, no handle of no tpm use case. Caller is responsible to not call it otherwise does nothing - init tries to bind fd and fails currently - Note: Check if whiptail is different of fbwhiptail in clearing screen. As of now every clear seems to be removed, still whiptail clears previous console output - When no OS' /boot can be mounted, do not try to TPM reset (will fail) - seal-hotpkey is not working properly - setting disk unlock key asks for TPM ownership passphrase (sealing in NV requires ownership, but text is misleading user as if reowning TPM) - We should cache input, feed tpm behind the scene and wipe passphrase and state clearly that this is TPM disk unlock kye passphrase. - primary key from TPM2 is invalid most of the time from kexec-select-boot and verifying global hashes but is setuped correctly at disk unlock key setup - would be nice to take advantage of bash function tracing to understand where we are for debugging purposes, code takes ash in consideration only - tpmr says it implements nv calls but actually doesn't. Removing those falsely wrapped functions would help. - Implementing them would be better - REVIEW TODOS IN CODE - READD CIRCLECI CONFIG Current state: - TPM unseal works without disk unlock key and generates TOTP properly (was missing die condition at unseal to not produce always good TOTP even if invalid) - TPM disk encryption key fails. Hypothesis is that sealing with USB drivers loaded and measures in inconsistent with sealed with/without. - TPM disk unsealing happens without USB modules being loaded in non-HOTP setup. This fails. - Current tests are with fbwhiptail (no clear called so having traces on command line of what happens) - Testing with HOTP implementation for sealing/unsealing since that forces USB module loads on each boot to remove this from failing possibilities
2022-08-25 18:43:31 +00:00
# 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 \
-in $TPM_NVRAM_SPACE \
-if "$TOTP_SEALED" \
|| die "Unable to write sealed secret to NVRAM"
fi
elif [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
pcrf="/tmp/secret/pcrf.bin"
tpm2 pcrread -o "$pcrf" sha256:0,1,2,3
# pcr 4 is expected to be zero (boot mode: init)
dd if=/dev/zero bs=32 count=1 >> "$pcrf"
# pcr 5 (kernel modules loaded) is not measured at sealing/unsealing of totp
# pcr 6 (drive luks header) is not measured at sealing/unsealing of totp
# pcr 7 is containing measurements of user injected stuff in cbfs
tpm2 pcrread -o /dev/stderr sha256:7 2>&1 >/dev/console | cat >> "$pcrf"
tpmr seal "$TOTP_SECRET" "0x8100$TPM_NVRAM_SPACE" sha256:0,1,2,3,4,7 "$pcrf" \
|| die "Unable to write sealed secret to NVRAM"
fi
shred -n 10 -z -u "$TOTP_SEALED" 2> /dev/null
url="otpauth://totp/$HOST?secret=$secret"
secret=""
qrenc "$url"
echo "$url"