Skip to content

(WIP) initrd: fix TPM1/TPM2 add DA lockout handling/gating and test tooling#2124

Draft
tlaurion wants to merge 1 commit into
linuxboot:masterfrom
tlaurion:tpm_da_lockout_rework
Draft

(WIP) initrd: fix TPM1/TPM2 add DA lockout handling/gating and test tooling#2124
tlaurion wants to merge 1 commit into
linuxboot:masterfrom
tlaurion:tpm_da_lockout_rework

Conversation

@tlaurion
Copy link
Copy Markdown
Collaborator

@tlaurion tlaurion commented May 20, 2026

WiP to fix #2123

  • tpm1_counter_increment: empty -pwdc '' bypasses _tpm_auth_retry and calls tpm directly per TCG spec. Non-empty passphrase or no -pwdc falls through to owner-auth retry path (migration for counters created by pre-fix code) (is standalone initrd: fix TPM1 counter auth regression (#2068) #2117)
  • tpm1_bad_auth: emit STATUS when lockout detected or counter ID missing, instead of silent DEBUG-only return. STATUS deduplicated with marker file for loop safety. On lockout, queries da_state and shows remaining duration when available.
  • tpm1_da_state: convert raw hex firmware version (0x0D.0x0C) to human-readable decimal (13.12) in all output and log messages.
  • tpm1_da_state: when state=1 but timer is 0 or empty, print "duration unknown on this TPM" instead of misleading "0s remaining".
  • tpm1_da_state: declare rev_major_dec/rev_minor_dec as local variables and normalize variable names to match tpm2_da_state conventions.
  • tpm2_da_state: declare interval_hex, recovery_hex, interval, recovery as local variables (previously leaked into global scope).
  • da_state output in bad_auth: extract only the => summary line for STATUS on console and the DA: machine line for DEBUG in log. Avoids duplicate re-emission of diagnostic lines already logged internally.
  • tpm1_unseal: detect DA lockout from unseal failure output ("defend lock"), emit WARN, query da_state for remaining time, set marker file so callers show lockout-specific guidance instead of generic reseal.
  • gui-init.sh update_totp: when marker present, show DA-lockout-specific whiptail with TCG exponential backoff guidance instead of generic OEM reset message. Shows exact remaining time when da_state provides it.
  • unseal-totp.sh: check DA lockout marker and show lockout-specific fail_unseal message.
  • recovery shell: show concise DA state summary at STATUS (not INFO) level so it reaches console in Quiet mode.

  - tpm1_counter_increment: empty -pwdc '' bypasses _tpm_auth_retry and
    calls tpm directly per TCG spec. Non-empty passphrase or no -pwdc
    falls through to owner-auth retry path (migration for counters created
    by pre-fix code).
  - tpm1_bad_auth: emit STATUS when lockout detected or counter ID
    missing, instead of silent DEBUG-only return. STATUS deduplicated with
    marker file for loop safety. On lockout, queries da_state and shows
    remaining duration when available.
  - tpm1_da_state: convert raw hex firmware version (0x0D.0x0C) to
    human-readable decimal (13.12) in all output and log messages.
  - tpm1_da_state: when state=1 but timer is 0 or empty, print "duration
    unknown on this TPM" instead of misleading "0s remaining".
  - tpm1_da_state: declare rev_major_dec/rev_minor_dec as local variables
    and normalize variable names to match tpm2_da_state conventions.
  - tpm2_da_state: declare interval_hex, recovery_hex, interval, recovery
    as local variables (previously leaked into global scope).
  - da_state output in bad_auth: extract only the => summary line for
    STATUS on console and the DA: machine line for DEBUG in log. Avoids
    duplicate re-emission of diagnostic lines already logged internally.
  - tpm1_unseal: detect DA lockout from unseal failure output ("defend
    lock"), emit WARN, query da_state for remaining time, set marker file
    so callers show lockout-specific guidance instead of generic reseal.
  - gui-init.sh update_totp: when marker present, show DA-lockout-specific
    whiptail with TCG exponential backoff guidance instead of generic OEM
    reset message. Shows exact remaining time when da_state provides it.
  - unseal-totp.sh: check DA lockout marker and show lockout-specific
    fail_unseal message.
  - recovery shell: show concise DA state summary at STATUS (not INFO)
    level so it reaches console in Quiet mode.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Copilot AI review requested due to automatic review settings May 20, 2026 15:24
@tlaurion tlaurion marked this pull request as draft May 20, 2026 15:24
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Heads initrd TPM handling to fix a TPM1 rollback-counter auth regression and add dictionary-attack (DA) lockout detection/reporting across TPM flows (including UI feedback and recovery-shell visibility).

Changes:

  • Switch TPM1 rollback counter creation/increment to use empty counter auth (-pwdc '') per spec, with a migration fallback for older counters.
  • Add DA lockout state querying (tpmr.sh da_state) and propagate lockout markers/messages into recovery + GUI flows.
  • Expand TPM wrapper docs and add helper commands (da_state, bad_auth) for diagnostics.

Reviewed changes

Copilot reviewed 2 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
initrd/etc/functions.sh Adds recovery DA-state output and preflight DA checks before counter increment; changes TPM1 counter auth behavior.
initrd/bin/tpmr.sh Implements TPM1/TPM2 DA-state queries, TPM1 empty-auth counter increment behavior, DA lockout detection markers, and diagnostic helpers.
initrd/bin/gui-init.sh Adds DA-lockout-specific whiptail flow when TOTP unseal fails and a lockout marker is present.
initrd/bin/unseal-totp.sh Adds explanatory comments about DA lockout marker handling around TPM1 unseal failures.
initrd/bin/oem-factory-reset.sh Creates TPM counter with empty counter auth (-pwdc '').
initrd/bin/tpm-reset.sh Adds guidance/TODO notes clarifying CLI reset scope vs. GUI reprovisioning.
doc/tpm.md Expands TPM wrapper documentation and adds auth-retry / reset / DA-lockout explanations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread initrd/etc/functions.sh
Comment on lines +2095 to +2101
if [ "$CONFIG_TPM" = "y" ]; then
local da_line da_current da_threshold da_timer
da_line="$(tpmr.sh da_state 2>/dev/null | grep '^DA: ')"
da_current=$(echo "$da_line" | sed 's/.*current=\([^ ]*\).*/\1/')
da_threshold=$(echo "$da_line" | sed 's/.*threshold=\([^ ]*\).*/\1/')
# With sed -n /p, da_timer stays empty when timer= field absent (TPM2 clean)
da_timer=$(echo "$da_line" | sed -n 's/.*timer=\([^ ]*\).*/\1/p')
@tlaurion tlaurion changed the title (WIP) initrd: fix TPM1 counter auth regression and add DA lockout handling (WIP) initrd: fix TPM1/TPM2 add DA lockout handling/gating and test tooling May 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TPM1/TPM2 DA policy exposure, tooling to trigger DA defend mode and proper gating on increment and unseal

2 participants