Skip to content

m900 tower port (rebased on tpm1_fixes with DA lockout gating)#2118

Open
tlaurion wants to merge 40 commits into
masterfrom
m900_with_tpm1_fixes
Open

m900 tower port (rebased on tpm1_fixes with DA lockout gating)#2118
tlaurion wants to merge 40 commits into
masterfrom
m900_with_tpm1_fixes

Conversation

@tlaurion
Copy link
Copy Markdown
Collaborator

@tlaurion tlaurion commented May 14, 2026

Supersedes #2111, rebased on #2117 (tpm1_fixes with DA lockout gating).

Board port (notgivenby's commits):

  • Board configs for m900 tower (maximized and hotp-maximized variants)
  • Coreboot config, linux config, ME blob handling
  • Review comments addressed: typos, blob names, board name includes 'tower'
  • CircleCI integration for both variants (requires seed:coreboot-25.09)
  • CircleCI x86_blobs step added for m900 ME download/deguard
  • Blob download script refactored to use shared blobs/lib.sh

Inherited from tpm1_fixes (PR #2117):

  • TPM1 counter auth regression fix: empty counter auth restored per TCG spec
  • tpm1_reset: physical presence cycle to clear defend lock
  • DA lockout gating: preflight guard, da_state diagnostics, bad_auth testing
  • doc/tpm.md: DA diagnosis, escalation, testing, physical presence

@notgivenby so you can test artifacts.

Copilot AI review requested due to automatic review settings May 14, 2026 19:52
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 ports the Lenovo M900 Tower (Skylake/Kaby Lake LGA1151 mini-tower) to Heads with two board variants (maximized, hotp-maximized), plus targeted TPM1 reliability fixes in tpmr.sh so that auth-failure detection and tpm1_reset() recover from the TPM_DEFEND_LOCK_RUNNING state after multiple bad passphrases. Documentation in doc/tpm.md is expanded with TPM1 vs TPM2 error-stream conventions, auth grep patterns, and the defend-lock recovery flow.

Changes:

  • New EOL_m900_tower-{maximized,hotp-maximized} boards with shared coreboot/linux configs and an ME blob preparation pipeline (download → me_cleaner → deguard).
  • TPM1 auth grep patterns extended to include defend/0x98e/0x149; tpm1_reset() cycles physical presence on defend lock running after forceclear.
  • CircleCI: two new build jobs (depend on the existing EOL_t480-hotp-maximized 25.09 seed).

Reviewed changes

Copilot reviewed 10 out of 14 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
boards/EOL_m900_tower-maximized/EOL_m900_tower-maximized.config New maximized board config (no HOTP).
boards/EOL_m900_tower-hotp-maximized/EOL_m900_tower-hotp-maximized.config New hotp-maximized variant.
config/coreboot-m900-maximized.config Coreboot 25.09 config for Lenovo M900.
config/linux-m900.config Linux 6.1.8 kernel config for the board.
targets/m900_me_blobs.mk Make rules tying the ME blob script into the board build.
blobs/m900/m900_download_clean_deguard_me.sh Downloads ASRock BIOS, neuters/deguards ME 11.6.0.1126.
blobs/m900/README.md Blob layout, sources and integrity notes.
blobs/m900/hashes.txt SHA256 of ME/IFD/GBE blobs.
blobs/m900/.gitignore Ignores generated me.bin/m900_me.bin.
initrd/bin/tpmr.sh Adds defend-lock detection in auth-retry grep and tpm1_reset() recovery sequence.
doc/tpm.md New sections on TPM1/TPM2 auth error patterns and defend-lock recovery.
.circleci/config.yml Adds the two M900 board build jobs (depending on the 25.09 seed).

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

Comment thread blobs/m900/m900_download_clean_deguard_me.sh Outdated
Comment thread doc/tpm.md Outdated
Comment thread doc/tpm.md
Comment thread blobs/m900/README.md Outdated
Comment thread blobs/m900/README.md Outdated
@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch 2 times, most recently from 78366db to a9cd1fc Compare May 14, 2026 20:13
@tlaurion tlaurion requested a review from Copilot May 14, 2026 20:18
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

Copilot reviewed 10 out of 14 changed files in this pull request and generated 5 comments.

Comment thread blobs/m900/m900_download_clean_deguard_me.sh Outdated
Comment thread blobs/m900/m900_download_clean_deguard_me.sh
Comment thread blobs/m900/README.md Outdated
Comment thread blobs/m900/hashes.txt
Comment thread blobs/m900/.gitignore Outdated
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

Copilot reviewed 10 out of 14 changed files in this pull request and generated no new comments.

@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch 3 times, most recently from 863c9b7 to 6919d44 Compare May 14, 2026 20:52
@tlaurion tlaurion requested a review from Copilot May 14, 2026 20:53
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

Copilot reviewed 10 out of 14 changed files in this pull request and generated no new comments.

@notgivenby
Copy link
Copy Markdown
Contributor

debug.log
measuring_trace.log

the fix did not help.

PR #2068 (tpm_reseal_ux-integrity_report-detect_disk_and_tpm_swap,
merged at d3d8053) changed increment_tpm_counter from hardcoded
-pwdc '' (empty counter auth) to -pwdc "${tpm_passphrase:-}" (owner
passphrase from cache/prompt), but left check_tpm_counter using empty
-pwdc when called from kexec-sign-config.sh without a $3 passphrase
argument.  This caused every counter increment to compute
SHA1(owner_pass) while the counter was created with SHA1("") -
persistent TPM_AUTH_FAIL.

Per TCG TPM Main Spec Part 3, TPM_CreateCounter uses owner auth
(-pwdo) but TPM_IncrementCounter uses the counter's own authData,
not the owner password.  The correct design for Heads' rollback
counter is empty auth: rollback security comes from the signed
/boot/kexec_rollback.txt and TPM sealing, not counter access control.

The repeated auth failures (3 per boot x ~5 boots via the
_tpm_auth_retry loop) triggered TPM 1.2 dictionary-attack lockout
(TPM_DEFEND_LOCK_RUNNING), which persisted through forceclear on
some implementations, causing tpm takeown to fail and TPM reset to
abort - a cascade failure from the counter auth mismatch.

Changes:
- initrd/bin/tpmr.sh (_tpm_auth_retry, tpm2_counter_inc, tpm2_seal,
  tpm1_seal): add 'defend' and '0x98e|0x149' to auth detection grep
  patterns so defend lock and TPM2 RC codes are treated as retryable
  auth failures rather than fatal errors
- initrd/bin/tpmr.sh (tpm1_reset): detect defend lock after takeown
  failure and cycle physical presence to clear the lock state before
  retrying; full AC power cycle remains the fallback if software
  presence is insufficient
- initrd/bin/tpmr.sh (tpm1_counter_increment): detect -pwdc '' and
  call tpm directly, bypassing _tpm_auth_retry which injected the
  owner passphrase.  Use || return to survive set -e on expected
  auth failure.
- initrd/etc/functions.sh (check_tpm_counter): pass -pwdc '' instead
  of -pwdc "${tpm_passphrase:-}" so counters use SHA1("") per TCG
  spec.  Document that $3 is intentionally ignored.
- initrd/etc/functions.sh (increment_tpm_counter): try -pwdc '' first
  for TPM1.  If that fails on a readable counter (created by PR #2068
  era code), prompt for owner passphrase and retry as migration
  fallback with clear WARN explaining the one-time migration and
  TPM reset option.
- initrd/etc/functions.sh (increment_tpm_counter): remove the
  TPM1-specific owner-passphrase prompt block added by PR #2068
- initrd/etc/functions.sh (increment_tpm_counter): DIE-path fallback
  counter_create: -pwdc '' for consistency
- initrd/bin/oem-factory-reset.sh: counter_create -pwdc '' for
  consistency with the empty-auth design
- doc/tpm.md: document TPM1 boot chain, tpmtotp tool selection,
  auth retry patterns, defend lock recovery, and physical presence

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch from 6919d44 to 9d1e115 Compare May 16, 2026 01:39
@tlaurion tlaurion changed the title m900 tower port + TPM1 auth/defend lock fixes m900 tower port + TPM1 counter auth and defend lock fixes May 16, 2026
@tlaurion
Copy link
Copy Markdown
Collaborator Author

debug.log measuring_trace.log

the fix did not help.

went down the rabbit hole and found the regression and created fix pushed onto #2117 and rebased on top of it.

@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch 3 times, most recently from 3e31d39 to 22ca620 Compare May 16, 2026 02:00
@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch from 8838b18 to 3ef9c50 Compare May 16, 2026 02:13
@tlaurion
Copy link
Copy Markdown
Collaborator Author

tlaurion commented May 16, 2026

@notgivenby hopefully this works. Added m900 blobs download in circleci so it downloads it once and reuses cache if already there and checksums match, reworked the script to reuse lib added, and fixups for tpm1.

Keep me posted. Hopefully #2117 (we are based on it here) fixes your issue.

@notgivenby
Copy link
Copy Markdown
Contributor

notgivenby commented May 16, 2026

debug.log
measuring_trace.log

You invested really a lot of time into debugging...I do not want to misuse you and your time here. Please let me known if @tlaurion you think we need to stop the attempts to port let us say not most popular board for only few people. The issue still maybe releveant for other ports who knows. For future attemps, perhaps I need to select a desktop board from other vendor perhaps with tpm2?

@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch from 55137bd to 06c398b Compare May 19, 2026 00:24
…, skip migration fallback

When da_state is unavailable (pre-rev 103 TPM1) and the counter
increment itself fails, check the output for defend lock patterns
before attempting the owner-passphrase migration fallback.  On
defend lock, DIE immediately with TPM reset guidance instead of
confusing the user with an owner passphrase prompt.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch from 06c398b to d7741e7 Compare May 19, 2026 00:35
…d path

The preflight guard must run for both TPM1 and TPM2.  TPM1 degrades
gracefully (no DA: line → skip), TPM2 always works.  Keep comments
clear about the pre-rev 103 TPM1 limitation.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch from d7741e7 to 03bba64 Compare May 19, 2026 00:42
tlaurion added 3 commits May 18, 2026 20:47
When tpm1_da_state returns unavailable (pre-rev 103 TPM1), bad_auth
now explains that the DA counter can't be read and the test proceeds
by attempting the increment.  User is told to repeat bad_auth until
the increment itself fails to confirm lockout.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
…n bad_auth guidance

User-facing messages now say 'TPM 1.2 spec rev' instead of 'TPM spec rev'
to avoid confusion with TPM 2.0.  bad_auth guidance text rewritten to
describe the limitation clearly without raw parenthetical formatting.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
…03 TPM1

Per UX best practices: one line per state, no raw codes, explicit
'expected' for intentional failures.  da_state shows one-line status
with vendor/rev on second line.  bad_auth shows action + outcome
without redundant DA state dumps.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch from 03bba64 to 86fca59 Compare May 19, 2026 01:07
tlaurion added 4 commits May 18, 2026 21:09
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
…er TPM1

Replace technical output ('TPM DA state: unavailable (TPM 1.2 pre-rev 103)')
with plain language: 'TPM 1.2 too old to report DA lockout state.'
bad_auth now reads: 'testing lockout by attempting increment...'
'Repeat until the increment fails with lockout.'
Vendor/rev info moved to DEBUG log only.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
…nd pre-rev 103 fallback

Document the TPM1 version-first probe (skip CAP_DA_LOGIC if rev < 103),
the preflight guard defend lock fallback for pre-rev 103 TPMs, and the
firmware version logging in tpm2_da_state.  Update tpmr.sh function
comments to reflect current behavior and non-developer UX patterns.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
- Only skip DA_LOGIC when revMajor is a valid hex value strictly < 103
- If revMajor is unparseable (format mismatch), try DA_LOGIC anyway
- Use BusyBox-compatible basic regex (no \+ ERE operator)
- If DA_LOGIC fails despite rev >= 103, show version in error message
- Clearer DEBUG logging at each decision point

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch from 86fca59 to 83305bd Compare May 19, 2026 01:19
tlaurion and others added 15 commits May 18, 2026 21:25
- Add da_state and bad_auth to the subcommand reference table
- Fix misleading NVRAM index claim (0x3135106223 is not fixed for TPM2)
- Fix bad_auth debug.log claim: increment output goes to console
- Fix _tpm_auth_retry comment: 'owner auth' -> 'authorization' (handles counter auth too)

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: notgivenby <notgivenby@gmail.com>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: notgivenby <notgivenby@gmail.com>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: notgivenby <notgivenby@gmail.com>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: notgivenby <notgivenby@gmail.com>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: notgivenby <notgivenby@gmail.com>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: notgivenby <notgivenby@gmail.com>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: notgivenby <notgivenby@gmail.com>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: notgivenby <notgivenby@gmail.com>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
…900_tower board

Signed-off-by: notgivenby <notgivenby@gmail.com>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: notgivenby <notgivenby@gmail.com>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
m900 ME blob download/deguard script was not wired into the
x86_blobs CI job.  Add it after the xx80 steps, following the
same pattern as other board families.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Signed-off-by: notgivenby <notgivenby@gmail.com>
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Fix the blobs/m900 download script to source shared blobs/lib.sh and
use its chk_sha256sum from the shared library (review comment).
Update board config descriptions and fix typos in README and
m900_me_blobs.mk target paths.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch from 83305bd to 54f250e Compare May 19, 2026 01:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants