From 08c2ee1bc9ed96f6f124b428b6027cad9a508937 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 2 Jun 2020 16:09:22 -0700 Subject: chromeos-tpm-recovery: Add support for v1 secdata_kernel The recent format changes to the kernel TPM NVRAM space weren't reflected in the chromeos-tpm-recovery utility yet. This patch fixes that. Since this may require upgrading from the old to the new format (or even the other way around), we also have to fix the longstanding limitation of not recreating TPM spaces for TPM 2.0. We still cannot do that for the firmware TPM space, but at least we can add it for the kernel one. BRANCH=none BUG=chromium:1020578,b:155149943 TEST=Ran on a Trogdor Signed-off-by: Julius Werner Change-Id: Iaf9bc6b29f76cfeaab90ae4f99099735c4f9441b Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2227260 Reviewed-by: Andrey Pronin Reviewed-by: Joel Kitching --- utility/chromeos-tpm-recovery | 89 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 18 deletions(-) diff --git a/utility/chromeos-tpm-recovery b/utility/chromeos-tpm-recovery index e2b0a8de..28a8fa3d 100755 --- a/utility/chromeos-tpm-recovery +++ b/utility/chromeos-tpm-recovery @@ -16,6 +16,8 @@ awk=/usr/bin/awk initctl=/sbin/initctl daemon_was_running= err=0 +secdata_firmware=0x1007 +secdata_kernel=0x1008 tpm2_target() { # This is not an ideal way to tell if we are running on a tpm2 target, but @@ -27,6 +29,32 @@ tpm2_target() { fi } +use_v0_secdata_kernel() { + local fwid=$(crossystem ro_fwid) + local major=$(printf "$fwid" | cut -d. -f2) + local minor=$(printf "$fwid" | cut -d. -f3) + + # TPM1 firmware never supports the v1 kernel space format. + if ! tpm2_target; then + return 0 + fi + + # First some sanity checks: X -eq X checks that X is a number. cut may return + # the whole string if no delimiter found, so major != minor checks that the + # version was at least somewhat correctly formatted. + if [ $major -eq $major ] && [ $minor -eq $minor ] && [ $major -ne $minor ]; then + # Now what we really care about: is this firmware older than CL:2041695? + if [ $major -lt 12953 ]; then + return 0 + else + return 1 + fi + else + log "Cannot parse FWID. Assuming local build that supports v1 kernel space." + return 1 + fi +} + log() { echo "$*" } @@ -63,27 +91,49 @@ tpm_clear_and_reenable () { $tpmc activate } -reset_space () { +write_space () { + # do not quote "$2", as we mean to expand it here + if ! $tpmc write $1 $2; then + log_error "writing to $1 failed" + else + log "$1 written successfully" + fi +} + +reset_ro_space () { local index=$1 - local permissions=$2 - local size=$3 - local bytes="$4" + local bytes="$2" + local size=$(printf "$bytes" | wc -w) + local permissions=0x8001 - if ! tpm2_target; then - # definespace is not yet supported for tpm2 (crosbug.com/p/59361), let's - # just rely on the firmware having created the required spaces for now. + if tpm2_target; then + log "Cannot redefine RO space for TPM2 (b/140958855). Let's just hope it looks good..." + else if ! $tpmc definespace $index $size $permissions; then - log "could not redefine space $index" - return 1 + log_error "could not redefine RO space $index" + # try writing it anyway, just in case it works... fi fi - # do not quote "$bytes", as we mean to expand it here - if ! $tpmc write $index $bytes; then - log "writing to $index failed" - return 1 + write_space $index "$bytes" +} + +reset_rw_space () { + local index=$1 + local bytes="$2" + local size=$(printf "$bytes" | wc -w) + local permissions=0x1 + + if tpm2_target; then + permissions=0x40050001 + fi + + if ! $tpmc definespace $index $size $permissions; then + log_error "could not redefine RW space $index" + # try writing it anyway, just in case it works... fi - log "space $index was recreated successfully" + + write_space $index "$bytes" } restart_daemon_if_needed() { @@ -161,10 +211,13 @@ fi tpm_clear_and_reenable # Reset firmware and kernel spaces to default (rollback version 1/1) -reset_space 0x1007 0x8001 0xa "02 00 01 00 01 00 00 00 00 4f" || \ - log_error "could not fix firmware space" -reset_space 0x1008 0x1 0xd "02 4c 57 52 47 01 00 01 00 00 00 00 55" || \ - log_error "could not fix kernel space" +reset_ro_space $secdata_firmware "02 0 1 0 1 0 0 0 0 4f" + +if use_v0_secdata_kernel; then + reset_rw_space $secdata_kernel "02 4c 57 52 47 1 0 1 0 0 0 0 55" +else + reset_rw_space $secdata_kernel "10 28 0c 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" +fi restart_daemon_if_needed -- cgit v1.2.1