mirror of
https://github.com/linuxboot/heads.git
synced 2025-01-29 15:44:07 +00:00
tpmr: Wrap TPM1 and TPM2 unseal actions so scripts can invoke either
Provide tpmr unseal to unseal a file with TPM1 or TPM2. For TPM1, it wraps tpm nv_readvalue and tpm unsealfile. For TPM2, it wraps tpm2 unseal. kexec-unseal-key, seal-hotpkey, unseal-hotp, and unseal-totp no longer need to differentiate TPM1/TPM2. Fixes spurious shred errors on TPM2 that only apply to TPM1 (temporary sealed secret file and shred are now internal to tpmr). Fixes TPM1 disk unlock key unsealing due to logic errors relating to exit status of tpmr unseal or tpm unsealfile (now always uses status of tpmr unseal). Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
This commit is contained in:
parent
660a5fe71e
commit
0a38717e20
@ -14,22 +14,12 @@ TRACE "Under kexec-unseal-key"
|
||||
|
||||
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
|
||||
|
||||
# TPM1 only - read the sealed value first manually
|
||||
if [ "$CONFIG_TPM2_TOOLS" != "y" ]; then
|
||||
tpm nv_readvalue \
|
||||
-in "$TPM_INDEX" \
|
||||
-sz "$TPM_SIZE" \
|
||||
-of "$sealed_file" \
|
||||
|| die "Unable to read key from TPM NVRAM"
|
||||
fi
|
||||
|
||||
echo "DEBUG: CONFIG_TPM: $CONFIG_TPM"
|
||||
echo "DEBUG: CONFIG_TPM2_TOOLS: $CONFIG_TPM2_TOOLS"
|
||||
echo "DEBUG: Show PCRs"
|
||||
@ -42,22 +32,9 @@ for tries in 1 2 3; do
|
||||
die "Aborting unseal disk encryption key"
|
||||
fi
|
||||
|
||||
unseal_result=1
|
||||
if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
|
||||
DO_WITH_DEBUG tpmr unseal "0x8100000$TPM_INDEX" "sha256:0,1,2,3,4,5,6,7" "$key_file" "$tpm_password"
|
||||
unseal_result="$?"
|
||||
else
|
||||
tpm unsealfile \
|
||||
-if "$sealed_file" \
|
||||
-of "$key_file" \
|
||||
-pwdd "$tpm_password" \
|
||||
-hk 40000000 \
|
||||
|| unseal_result="$?"
|
||||
fi
|
||||
DO_WITH_DEBUG tpmr unseal "$TPM_INDEX" "sha256:0,1,2,3,4,5,6,7" "$TPM_SIZE" "$key_file" "$tpm_password"
|
||||
|
||||
shred -n 10 -z -u "$sealed_file" 2> /dev/null || true
|
||||
|
||||
if [ "$unseal_result" -eq 0 ]; then
|
||||
if [ "$?" -eq 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
. /etc/functions
|
||||
|
||||
HOTP_SEALED="/tmp/secret/hotp.sealed"
|
||||
HOTP_SECRET="/tmp/secret/hotp.key"
|
||||
HOTP_COUNTER="/boot/kexec_hotp_counter"
|
||||
HOTP_KEY="/boot/kexec_hotp_key"
|
||||
@ -27,26 +26,11 @@ else
|
||||
HOTPKEY_BRANDING="HOTP USB Security Dongle"
|
||||
fi
|
||||
|
||||
if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_TPM2_TOOLS" != "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"
|
||||
elif [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
|
||||
tpmr unseal 0x81004d47 sha256:0,1,2,3,4,7 "$HOTP_SECRET" \
|
||||
if [ "$CONFIG_TPM" = "y" ]; then
|
||||
tpmr unseal 4d47 sha256:0,1,2,3,4,7 312 "$HOTP_SECRET" \
|
||||
|| die "Unable to unseal HOTP secret"
|
||||
fi
|
||||
|
||||
|
||||
shred -n 10 -z -u "$HOTP_SEALED" 2> /dev/null
|
||||
|
||||
# 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
|
||||
|
@ -138,13 +138,20 @@ cleanup_session() {
|
||||
fi
|
||||
}
|
||||
|
||||
# tpm2_sealfile: Seal a file against PCR values and, optionally, a password.
|
||||
# Clean up a file by shredding it. No-op if the file wasn't created. Use with
|
||||
# trap EXIT, e.g.:
|
||||
# trap "cleanup_shred '$FILE'" EXIT
|
||||
cleanup_shred() {
|
||||
shred -n 10 -z -u "$1" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# tpm2_seal: Seal a file against PCR values and, optionally, a password.
|
||||
# If a password is given, both the PCRs and password are required to unseal the
|
||||
# file. PCRs are provided as a PCR list and data file. PCR data must be
|
||||
# provided - TPM2 allows the TPM to fall back to current PCR values, but it is
|
||||
# not required to support this.
|
||||
tpm2_sealfile() {
|
||||
TRACE "Under /bin/tpmr:tpm2_sealfile"
|
||||
tpm2_seal() {
|
||||
TRACE "Under /bin/tpmr:tpm2_seal"
|
||||
file="$1" #$KEY_FILE
|
||||
handle="$2" # 0x8100000$TPM_INDEX
|
||||
pcrl="$3" #sha256:0,1,2,3,4,5,6,7
|
||||
@ -153,7 +160,7 @@ tpm2_sealfile() {
|
||||
mkdir -p "$SECRET_DIR"
|
||||
bname="`basename $file`"
|
||||
|
||||
DEBUG "tpm2_sealfile: file=$file handle=$handle pcrl=$pcrl pcrf=$pcrf pass=$([ "$pass" ] && echo "<yes>" || echo "<no>")"
|
||||
DEBUG "tpm2_seal: file=$file handle=$handle pcrl=$pcrl pcrf=$pcrf pass=$([ "$pass" ] && echo "<yes>" || echo "<no>")"
|
||||
|
||||
# Create a policy requiring both PCRs and the object's authentication
|
||||
# value using a trial session.
|
||||
@ -203,17 +210,21 @@ tpm2_sealfile() {
|
||||
DO_WITH_DEBUG tpm2 evictcontrol -Q -C o -P "$key_password" -c "$SECRET_DIR/$bname.seal.ctx" "$handle"
|
||||
}
|
||||
|
||||
# Unseal a file sealed by tpm2_sealfile. The PCR list must be provided, the
|
||||
# Unseal a file sealed by tpm2_seal. The PCR list must be provided, the
|
||||
# password must be provided if one was used to seal (and cannot be provided if
|
||||
# no password was used to seal).
|
||||
tpm2_unsealfile() {
|
||||
TRACE "Under /bin/tpmr:tpm2_unsealfile"
|
||||
handle="$1"
|
||||
tpm2_unseal() {
|
||||
TRACE "Under /bin/tpmr:tpm2_unseal"
|
||||
index="$1"
|
||||
pcrl="$2"
|
||||
file="$3"
|
||||
pass="$4"
|
||||
size="$3"
|
||||
file="$4"
|
||||
pass="$5"
|
||||
|
||||
DEBUG "tpm2_unsealfile: handle=$handle pcrl=$pcrl file=$file pass=$([ "$pass" ] && echo "<yes>" || echo "<no>")"
|
||||
# Pad with up to 6 zeros, i.e. '0x81000001', '0x81001234', etc.
|
||||
handle="$(printf "0x81%6s" "$index" | tr ' ' 0)"
|
||||
|
||||
DEBUG "tpm2_unseal: handle=$handle pcrl=$pcrl size=$size file=$file pass=$([ "$pass" ] && echo "<yes>" || echo "<no>")"
|
||||
|
||||
POLICY_SESSION=/tmp/unsealfile_policy.session
|
||||
rm -f "$POLICY_SESSION"
|
||||
@ -238,6 +249,14 @@ tpm2_unsealfile() {
|
||||
fi
|
||||
|
||||
tpm2 unseal -Q -c "$handle" -p "session:$POLICY_SESSION$UNSEAL_PASS_SUFFIX" > "$file"
|
||||
|
||||
# We don't need to know the size to unseal in TPM2, but TPM1 does.
|
||||
# Ensure the correct size is provided so both will work.
|
||||
# TODO - This isn't actually what -sz means to tpm nv_readvalue
|
||||
#actual_size="$(stat -c "%s" "$file")"
|
||||
#if [ "$actual_size" -ne "$size" ]; then
|
||||
# die "Expected size $size for $file but got $actual_size"
|
||||
#fi
|
||||
}
|
||||
|
||||
tpm2_reset() {
|
||||
@ -271,6 +290,41 @@ tpm2_kexec_finalize() {
|
||||
|| warn "Failed to lock platform hierarchy of TPM2!"
|
||||
}
|
||||
|
||||
tpm1_unseal() {
|
||||
TRACE "Under /bin/tpmr:tpm1_unseal"
|
||||
index="$1"
|
||||
pcrl="$2"
|
||||
size="$3"
|
||||
file="$4"
|
||||
pass="$5"
|
||||
|
||||
# pcrl (the PCR list) is unused in TPM1. The TPM itself knows which
|
||||
# PCRs were used to seal and checks them. We can't verify that it's
|
||||
# correct either, so just ignore it in TPM1.
|
||||
|
||||
sealed_file="$SECRET_DIR/tpm1_unseal_sealed.bin"
|
||||
trap "cleanup_shred '$sealed_file'" EXIT
|
||||
|
||||
rm -f "$sealed_file"
|
||||
|
||||
tpm nv_readvalue \
|
||||
-in "$index" \
|
||||
-sz "$size" \
|
||||
-of "$sealed_file" \
|
||||
|| die "Unable to read sealed file from TPM NVRAM"
|
||||
|
||||
PASS_ARGS=()
|
||||
if [ "$pass" ]; then
|
||||
PASS_ARGS=(-pwdd "$pass")
|
||||
fi
|
||||
|
||||
tpm unsealfile \
|
||||
-if "$sealed_file" \
|
||||
-of "$file" \
|
||||
"${PASS_ARGS[@]}" \
|
||||
-hk 40000000
|
||||
}
|
||||
|
||||
if [ "$CONFIG_TPM" != "y" ]; then
|
||||
echo >&2 "No TPM!"
|
||||
exit 1
|
||||
@ -284,6 +338,8 @@ if [ "$CONFIG_TPM2_TOOLS" != "y" ]; then
|
||||
case "$subcmd" in
|
||||
kexec_finalize)
|
||||
;; # Nothing on TPM1.
|
||||
unseal)
|
||||
shift; tpm1_unseal "$@";;
|
||||
*)
|
||||
exec tpm "$@"
|
||||
;;
|
||||
@ -310,11 +366,11 @@ case "$subcmd" in
|
||||
nv_readvalue)
|
||||
tpm2_nvr "$@";;
|
||||
seal)
|
||||
tpm2_sealfile "$@";;
|
||||
tpm2_seal "$@";;
|
||||
startsession)
|
||||
tpm2_startsession "$@";;
|
||||
unseal)
|
||||
tpm2_unsealfile "$@";;
|
||||
tpm2_unseal "$@";;
|
||||
reset)
|
||||
tpm2_reset "$@";;
|
||||
kexec_finalize)
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
. /etc/functions
|
||||
|
||||
HOTP_SEALED="/tmp/secret/hotp.sealed"
|
||||
HOTP_SECRET="/tmp/secret/hotp.key"
|
||||
HOTP_COUNTER="/boot/kexec_hotp_counter"
|
||||
|
||||
@ -38,22 +37,9 @@ if [ "$counter_value" == "" ]; then
|
||||
fi
|
||||
|
||||
#counter_value=$(printf "%d" 0x${counter_value})
|
||||
if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
|
||||
tpmr unseal 0x81004d47 sha256:0,1,2,3,4,7 "$HOTP_SECRET"
|
||||
elif [ "$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"
|
||||
if [ "$CONFIG_TPM" = "y" ]; then
|
||||
tpmr unseal 4d47 sha256:0,1,2,3,4,7 312 "$HOTP_SECRET"
|
||||
fi
|
||||
shred -n 10 -z -u "$HOTP_SEALED" 2> /dev/null
|
||||
|
||||
if ! hotp $counter_value < "$HOTP_SECRET"; then
|
||||
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null
|
||||
|
@ -3,30 +3,15 @@
|
||||
|
||||
. /etc/functions
|
||||
|
||||
TOTP_SEALED="/tmp/secret/totp.sealed"
|
||||
TOTP_SECRET="/tmp/secret/totp.key"
|
||||
|
||||
TRACE "Under /bin/unseal-totp"
|
||||
|
||||
if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
|
||||
tpmr unseal 0x81004d47 sha256:0,1,2,3,4,7 "$TOTP_SECRET" \
|
||||
|| die "Unable to unseal totp secret"
|
||||
elif [ "$CONFIG_TPM" = "y" ]; then
|
||||
tpm nv_readvalue \
|
||||
-in 4d47 \
|
||||
-sz 312 \
|
||||
-of "$TOTP_SEALED" \
|
||||
|| die "Unable to retrieve sealed file from TPM NV"
|
||||
|
||||
tpm unsealfile \
|
||||
-hk 40000000 \
|
||||
-if "$TOTP_SEALED" \
|
||||
-of "$TOTP_SECRET" \
|
||||
if [ "$CONFIG_TPM" = "y" ]; then
|
||||
tpmr unseal 4d47 sha256:0,1,2,3,4,7 312 "$TOTP_SECRET" \
|
||||
|| die "Unable to unseal totp secret"
|
||||
fi
|
||||
|
||||
shred -n 10 -z -u "$TOTP_SEALED" 2> /dev/null
|
||||
|
||||
if ! totp -q < "$TOTP_SECRET"; then
|
||||
shred -n 10 -z -u "$TOTP_SECRET" 2> /dev/null
|
||||
die 'Unable to compute TOTP hash?'
|
||||
|
Loading…
x
Reference in New Issue
Block a user