From 89f0eead16ed51d12fe77f79bc5109db634ec061 Mon Sep 17 00:00:00 2001 From: Krystian Hebel Date: Tue, 12 Dec 2023 15:29:29 +0100 Subject: [PATCH] txt-tpm1-evt-log-parser.awk: add parser for Intel TXT TPM 1.2 event log Contrary to TPM 2.0 format, this one is specific to Intel TXT and cannot be used for parsing firmware entries, hence the seemingly inconsistent file name. Similarly to TPM 2.0 parser, this one also must operate on regular file. Signed-off-by: Krystian Hebel --- anti-evil-maid.spec.in | 1 + sbin/anti-evil-maid-dump-evt-log | 3 +- sbin/txt-tpm1-evt-log-parser.awk | 96 ++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100755 sbin/txt-tpm1-evt-log-parser.awk diff --git a/anti-evil-maid.spec.in b/anti-evil-maid.spec.in index 9c3ef46..2c38b93 100644 --- a/anti-evil-maid.spec.in +++ b/anti-evil-maid.spec.in @@ -50,6 +50,7 @@ cp -r systemd $RPM_BUILD_ROOT/usr/lib /usr/sbin/anti-evil-maid-seal /usr/sbin/anti-evil-maid-tpm-setup /usr/sbin/tpm2-evt-log-parser.awk +/usr/sbin/txt-tpm1-evt-log-parser.awk /usr/share/doc/anti-evil-maid/README /usr/lib/systemd/system/anti-evil-maid-seal.service /usr/lib/systemd/system/tcsd.service.d/anti-evil-maid-seal.conf diff --git a/sbin/anti-evil-maid-dump-evt-log b/sbin/anti-evil-maid-dump-evt-log index f723735..d2a3aaf 100755 --- a/sbin/anti-evil-maid-dump-evt-log +++ b/sbin/anti-evil-maid-dump-evt-log @@ -16,7 +16,8 @@ dd if=/dev/mem bs=1 skip=$base count=$size of=/tmp/log.bin if [ "$_tpm_version" -eq 2 ]; then /usr/sbin/tpm2-evt-log-parser.awk /tmp/log.bin else - echo "TPM 1.2 event log format not supported yet" + # Intel only, unless AMD implementation will choose to use TXT format + /usr/sbin/txt-tpm1-evt-log-parser.awk /tmp/log.bin fi rm /tmp/log.bin diff --git a/sbin/txt-tpm1-evt-log-parser.awk b/sbin/txt-tpm1-evt-log-parser.awk new file mode 100755 index 0000000..0e6549c --- /dev/null +++ b/sbin/txt-tpm1-evt-log-parser.awk @@ -0,0 +1,96 @@ +#!/usr/bin/gawk -bf +@load "readfile" + +function assert(condition, string) +{ + if (!condition) { + print string + exit 1 + } +} + +function ord_init() +{ + for (_i = 0; _i < 256; _i++) { + ord[sprintf("%c", _i)] = _i + } +} + +function x2n(hex, width) +{ + mult = 1 + num = 0 + for (_i = 0; _i < width; _i++) { + num += ord[substr(hex, _i+1, 1)] * mult + mult *= 256 + } + return num +} + +function hexdump(hex, len) +{ + for (_i = 0; _i < len; _i++) { + printf("%02x", ord[substr(hex, _i+1, 1)]) + } +} + +function string_or_hex(str, len) +{ + _len = len + if (_len > 128) + _len = 128 + # String must start with a series of printable characters ... + if (match(str, "[[:graph:][:blank:]]*", a) != 1) { + hexdump(str, _len) + # ... long until the end, with "optional" (i.e. bad implementation) \0. + } else if (len != a[0, "length"] && + (len != a[0, "length"] + 1 || index(str, "\0") != len)) { + hexdump(str, _len) + } else + printf("%.*s", _len, a[0]) + if (_len != len) + printf("... (event truncated to %d first bytes, was %d)", _len, len) +} + +BEGIN { + PROCINFO["readfile"] + FIELDWIDTHS = "20 12 1 1 1 1 4 4 4 *" + ord_init() +} +{ + # Header sanity checks + assert($1 == "TXT Event Container\0", "Bad TXT Event Container signature") + assert(match($2, "\0{12}"), "Reserved field is not all 0") + assert($3 == "\1", "Bad container major version") + # Minor version is bumped if there are compatible changes like new + # fields added to the end of structure. Header stores offset to PCR + # events so those new fields can be skipped. + #assert($4 == "\0", "Bad container minor version") + assert($5 == "\1", "Bad event structure major version") + # There is no field that would specify size of whole event structure, + # any new fields added to it would break this parser. + assert($6 == "\0", "Bad event structure minor version") + assert(x2n($7, 4) == length(), "Bad container size") + assert(x2n($8, 4) >= (20+12+1+1+1+1+4+4+4), "PCR Event offset too small") + assert(x2n($9, 4) > x2n($8, 4), "Next Event offset too small") + FIELDWIDTHS="4 4 20 4 *" + $0 = substr($0, x2n($8, 4) + 1) +} +{ + entry = 0 + printf("\n") + while (NF > 0) { + if ($2 == "\0\0\0\0") break + printf("Entry %d:\n", ++entry) + printf(" PCR: %d\n", x2n($1, 4)) + printf(" Event Type: %#x\n", x2n($2, 4)) + printf(" Digests:\n") + printf(" SHA1: ") + hexdump($3, 20) + printf("\n") + printf(" Event: ") + string_or_hex($5, x2n($4, 4)) + printf("\n\n") + $0 = substr($5, x2n($4, 4) + 1) + } +}