linuxboot / linuxboot/heads

TPM read fails after interrupted at LUKS-passphrase on T480 - no TOTP/HOTP prompt

Open
#2,205 2 comments 0 reactions 0 assignees View on GitHub

@tlaurion is already working on this.

Since Sep 10, 2026.

  • #2124 by @tlaurion — closed without merging
  • #2206 by @tlaurion — open
Dominant language
Makefile
Stars
1.6k
Forks
211
Avg merge
4d 21h
Merged PRs (30d)
6

Description

### A. Provide Hardware Details

1. What board are you using? (Choose from the list of boards [here](https://github.com/linuxboot/heads/tree/master/boards))

2. Does your computer have a dGPU or is it iGPU-only?
- [ ] dGPU (Distinct GPU other then internal GPU)
- [x] iGPU-only (Internal GPU, normally Intel GPU)

3. Who installed Heads on this computer?
- [ ] Insurgo (Issues to be reported at https://github.com/linuxboot/heads/issues)
- [ ] Nitrokey (Issues to be reported at https://github.com/Nitrokey/heads/issues)
- [ ] Purism (Issues to be reported at https://source.puri.sm/firmware/pureboot/-/issues)
- [ ] Novacustom (Issues to be reported at https://github.com/Dasharo/dasharo-issues)
- [ ] HardnenedVault (Issues to be reported at https://github.com/hardenedvault/vaultboot/issues)
- [ ] Other provider
- [x] Self-installed

4. What PGP key is being used?
- [ ] Librem Key (Nitrokey Pro 2 rebranded)
- [ ] Nitrokey Pro
- [ ] Nitrokey Pro 2
- [x] Nitrokey 3 NFC
- [ ] Nitrokey 3 NFC Mini
- [ ] Nitrokey Storage
- [ ] Nitrokey Storage 2
- [ ] Yubikey
- [ ] Other

5. Are you using the PGP key to provide HOTP verification?
- [x] Yes
- [ ] No
- [ ] I don't know

### B. Identify how the board was flashed

3. Heads initially flashed?
- [x] External flashing
- [ ] Internal-only / 1vyprep+1vyrain / skulls
- [ ] Don't know

4. Was the board flashed with a maximized or non-maximized/legacy rom?
- [x] Maximized
- [ ] Non-maximized / legacy
- [ ] I don't know

5. If Heads was externally flashed, was IFD unlocked?
- [x] Yes
- [ ] No
- [ ] Don't know

### C. Identify the rom related to this bug report

1. Did you download or build the rom at issue in this bug report?
- [x] I downloaded it
- [ ] I built it

2. If you downloaded your rom, where did you get it from?
- [x] Heads CircleCi
- [ ] Purism
- [ ] Nitrokey
- [ ] Dasharo DTS (Novacustom)
- [ ] Somewhere else (please identify)

EOL_t480-hotp-maximized Heads-v0.2.1-3034-gf3004e0

## Please describe the problem
I interrupted two boots at the LUKS passphrase prompt, and in between
I tried booting from USB a couple of times (one attempt found no device
and dropped me into the recovery shell). Since then Heads doesn't get
to the TOTP/HOTP prompt anymore. Instead I get:

"TPM integrity counter cannot be read. Possible cause: TPM was
swapped or reset. This could indicate a TPM swap attack"

I didn't flash anything, no dom0 update, and I never triggered a TPM
reset. /boot still verifies fine: kexec.sig VERIFIED, boot files OK,
Nitrokey matches the ROM-trusted key. The message also survives a full
power off with battery and PSU removed.

**To Reproduce**
1. Boot, get to the LUKS passphrase prompt, interrupt before it unlocks.
2. Repeat once.
3. Somewhere in between, try USB boot; one attempt found no USB device
and dropped to the recovery shell.
4. Boot normally again.
5. No TOTP/HOTP prompt, the preflight error shows up instead.

I don't know whether this reproduces on purpose. It's just what I did.

**Expected behavior**
Normal boot with TOTP/HOTP like before.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Additional context**
I looked at the source at f3004e0 before filing this.

preflight_rollback_counter_before_reseal() reads counter id 1070ab1 out
of /boot/kexec_rollback.txt and then calls tpm2_counter_read
(tpmr.sh:277, nvread 0x$index). That read fails and fail_preflight
fires.

The index itself is still there. tpm2 getcap handles-nv-index lists
0x1070AB1 along with 0x165BA4F, 0x1800001, 0x1800003, 0x1800004,
0x1C00002 and 0x1C0000A. So the NV index hasn't vanished, the read just
doesn't succeed.

As far as I can tell the counter index is only created at TPM
ownership/reset and otherwise only incremented, and kexec_rollback.txt
is only rewritten by update_checksums / kexec-sign-config.sh, which I
never ran here. So a file-vs-TPM desync doesn't look likely to me.

My guess is DA lockout from the interrupted unseal attempts, but I
can't show it from the log, because the read is called as:

if ! tpmr.sh counter_read -ix "$counter_id" >/dev/null 2>&1; then

The 2>&1 throws away the actual tpm2 error, so there's no way to tell
lockout from a missing handle or anything else. That's the part I'd
suggest changing regardless of what my case turns out to be: keeping
that stderr in the debug log would make this kind of report much easier
to act on.

[cbmem.txt](https://github.com/user-attachments/files/31941338/cbmem.txt)
[debug.log](https://github.com/user-attachments/files/31941339/debug.log)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at preflight_rollback_counter_before_reseal() and tpmr.sh:277, where the counter read redirects stderr to /dev/null. Review the linked debug.log and the surrounding preflight flow to determine how diagnostic output is collected. Done means the TPM read failure remains actionable in the debug log, including the underlying tpm2 error, without changing the reported verification behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
linux, shell
Domain
operating-systems, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.