Skip to content

Commit 86eb954

Browse files
committed
initrd/bin/kexec-seal-key.sh tpmr.sh doc/tpm.md: fix PCR5 mismatch between LUKS DUK seal and unseal
When CONFIG_USB_KEYBOARD_REQUIRED=y, Heads loads USB kernel modules at boot and extends PCR 5 with their hashes. The LUKS DUK sealing policy includes PCR 5, so the sealed blob stores the PCR 5 value present at seal time. The condition that decides whether PCR 5 has non-zero involvement at seal time checked CONFIG_USER_USB_KEYBOARD (a Makefile variable that defaults the USB keyboard GUI toggle to 'on') but not CONFIG_USB_KEYBOARD_REQUIRED. Boards with the latter but not the former would seal the DUK with PCR 5 = 0 (calcfuturepcr 5 returns zero when no firmware measured into that PCR), while at unseal time on the next boot PCR 5 had been extended by the loaded USB modules. This produced: tpm stdout: Error PCR mismatch from TPM_Unseal TOTP unseal was unaffected because it excludes PCR 5 from its sealing policy. Fix: add CONFIG_USB_KEYBOARD_REQUIRED to the condition so that boards requiring USB keyboards seal PCR 5 with the actual module-extended value, matching what the TPM sees at unseal time. Additionally: - Fix misleading comment in tpm1_unseal(): pcrl is not accepted by unsealfile.c, which has no -ix flag — only sealfile2.c has it. The sealed blob carries the PCR constraints baked in by TPM_Seal() and TPM_Unseal() enforces them automatically. - doc/tpm.md: add Unsealing row to TPM1 vs TPM2 comparison table. - doc/tpm.md: expand PCR 5 description to list the exact condition variables checked by kexec-seal-key.sh. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
1 parent 273f52f commit 86eb954

3 files changed

Lines changed: 16 additions & 9 deletions

File tree

doc/tpm.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,14 @@ to a dedicated LUKS key slot and sealed to TPM NVRAM with the policy below.
185185
| 6 | `calcfuturepcr 6 /tmp/luksDump.txt` | Pre-computed LUKS header measurement |
186186
| 7 | `pcrread` (current value) | User CBFS files |
187187

188-
PCR 5 is conditional: if the board loads extra kernel modules (USB HID,
189-
libata, HOTP token), the actual post-load PCR 5 value is used. If no extra
190-
modules are loaded, `calcfuturepcr 5` computes the zeroed (never-extended)
191-
future value. This means the seal is valid only for the expected module set.
188+
PCR 5 is conditional on whether the board loads extra kernel modules
189+
(USB HID, libata, HOTP token). The condition in `kexec-seal-key.sh`
190+
checks `CONFIG_USER_USB_KEYBOARD`, `CONFIG_USB_KEYBOARD_REQUIRED`, the
191+
presence of `/lib/modules/libata.ko`, and `/bin/hotp_verification`.
192+
If any is true, the actual post-load PCR 5 value is read from hardware
193+
via `tpmr.sh pcrread`. If none are true, `calcfuturepcr 5` computes
194+
the zeroed (never-extended) future value. This means the seal is valid
195+
only for the expected module set.
192196

193197
PCR 6 is pre-computed: `calcfuturepcr 6 /tmp/luksDump.txt` replays the
194198
LUKS header extension to compute the expected post-measurement value. If
@@ -424,7 +428,8 @@ To verify that a new board's coreboot config matches the expected RoT:
424428
| Feature | TPM 1.2 | TPM 2.0 |
425429
| --- | --- | --- |
426430
| PCR hash | SHA-1 (20 bytes) | SHA-256 (32 bytes) |
427-
| Sealing | `tpm sealfile2` | `tpm2 nvdefine` + policy session |
431+
| Sealing | `tpm sealfile2 -ix <pcr> <hash> ...` (specify PCRs and expected values) | `tpm2 nvdefine` + policy session |
432+
| Unsealing | `tpm unsealfile` (no PCR args — TPM enforces from baked blob) | `tpm2 unseal` with policy session |
428433
| Counter | `tpm nv*` | `tpm2 nvincrement` |
429434
| Auth sessions | Not used | Required for policy-based unseal |
430435
| `kexec_finalize` | No-op | Extends PCRs, then `tpm2 shutdown` |

initrd/bin/kexec-seal-key.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ tpmr.sh pcrread -a 2 "$pcrf"
286286
tpmr.sh pcrread -a 3 "$pcrf"
287287
# Note that PCR 4 needs to be set with the "normal-boot" path value, read it from event log.
288288
tpmr.sh calcfuturepcr 4 >>"$pcrf"
289-
if [ "$CONFIG_USER_USB_KEYBOARD" = "y" ] || [ -r /lib/modules/libata.ko ] || [ -x /bin/hotp_verification ]; then
289+
if [ "$CONFIG_USER_USB_KEYBOARD" = "y" ] || [ "$CONFIG_USB_KEYBOARD_REQUIRED" = "y" ] || [ -r /lib/modules/libata.ko ] || [ -x /bin/hotp_verification ]; then
290290
DEBUG "Sealing LUKS TPM Disk Unlock Key with PCR5 involvement (additional kernel modules are loaded per board config)..."
291291
# Here, we take pcr 5 into consideration if modules are expected to be measured+loaded
292292
tpmr.sh pcrread -a 5 "$pcrf"

initrd/bin/tpmr.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -885,9 +885,11 @@ tpm1_unseal() {
885885
file="$4"
886886
pass="$5"
887887

888-
# pcrl (the PCR list) is unused in TPM1. The TPM itself knows which
889-
# PCRs were used to seal and checks them. We can't verify that it's
890-
# correct either, so just ignore it in TPM1.
888+
# pcrl is unused here because tpm unsealfile (unsealfile.c) does not
889+
# accept PCR arguments — only tpm sealfile2 (sealfile2.c -ix ...) does.
890+
# The blob baked at seal time encodes which PCRs were selected and
891+
# their expected values; TPM_Unseal() enforces PCR matching against
892+
# current hardware PCRs automatically from the baked digest.
891893

892894
sealed_file="$SECRET_DIR/tpm1_unseal_sealed.bin"
893895
at_exit cleanup_shred "$sealed_file"

0 commit comments

Comments
 (0)