Skip to content

m900 tower port (rebased on tpm1_fixes)#2118

Open
tlaurion wants to merge 16 commits into
masterfrom
m900_with_tpm1_fixes
Open

m900 tower port (rebased on tpm1_fixes)#2118
tlaurion wants to merge 16 commits into
masterfrom
m900_with_tpm1_fixes

Conversation

@tlaurion
Copy link
Copy Markdown
Collaborator

@tlaurion tlaurion commented May 14, 2026

Summary

Board port for the Lenovo m900 tower (mini PC), rebased on the TPM1 counter auth fix from PR #2117.

Board port:

  • 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

Fixes:

  • Fixed missing execute permission on blobs/m900/m900_download_clean_deguard_me.sh
  • initrd/bin/kexec-seal-key.sh: fix PCR5 mismatch between LUKS DUK seal and unseal. Condition checked CONFIG_USER_USB_KEYBOARD but not CONFIG_USB_KEYBOARD_REQUIRED. Boards with the latter but not the former sealed DUK with PCR5=0 while USB modules extended PCR5 at boot, producing: tpm stdout: Error PCR mismatch from TPM_Unseal

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 Outdated
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.

@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
Copy link
Copy Markdown
Collaborator Author

tlaurion 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?

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?

@notgivenby this has nothing specific to m900, outside of the fact that as opposed to tpm2, we do not configure the dictionary attack config (how many attempt per timeframe nor resolution period).

As said under #2117 , master contains a regression for how we do counter create and how we increment the counter.

Your platform has DA lockout, might be 24h before automatic resolution. i've worked a bit on it today but haven't finished adding code to troubleshot this properly. Maybe tomorrow, most probably monday

@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch 2 times, most recently from 83305bd to 54f250e Compare May 19, 2026 01:25
PR #2068 introduced a regression where `increment_tpm_counter`
was changed from hardcoded `-pwdc ''` (empty counter auth per
TCG spec) to `-pwdc "${tpm_passphrase:-}"` (owner passphrase),
while counters continued to be created with `-pwdc ''`. This
caused every increment to compute SHA1(owner_pass) against a
counter created with SHA1(""), producing persistent TPM_AUTHFAIL.

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.

The repeated auth failures (3 per boot) accumulated the TPM's
dictionary attack (DA) failedTries counter until lockout was
reached (~10 boots = 30 failures). Users reported "hours of
waiting" on affected hardware. On some implementations the DA
state persisted through tpm forceclear.

Fix: restore TCG-compliant empty counter auth:
- tpm1_counter_increment: detect explicit -pwdc '' and call tpm
  directly, bypassing _tpm_auth_retry. Non-empty or absent -pwdc
  falls through to owner-auth retry path for migration of counters
  created by pre-fix code.
- check_tpm_counter: create counters with -pwdc '' instead of
  owner passphrase.
- increment_tpm_counter: increment with -pwdc '' instead of
  owner passphrase; counter_create fallback uses empty auth.
- oem-factory-reset.sh: create counters with -pwdc ''.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch from 54f250e to e8e5aa5 Compare May 20, 2026 15:11
@tlaurion tlaurion changed the title m900 tower port (rebased on tpm1_fixes with DA lockout gating) m900 tower port (rebased on tpm1_fixes) May 20, 2026
@tlaurion
Copy link
Copy Markdown
Collaborator Author

tlaurion commented May 20, 2026

@notgivenby can you test artifacts one last time? tpm reset up to tpm duk setup? changed #2117 to do bare minimal to fix #2068 regression with increment which was using tpm owner passphrase where not needed by spec. Will move all other fixes in pending pr for when I'll have time again; my x230 doesn't have proper 1.2 spec imlementation which makes it impossible to do proper things (da lockout policy cannot be asked for....) while swtpm on qemu is way too permissive and doesn't trigger da defend for long enough to test properly.

If this works for you, we can merge #2117 since its a regression fix and move proper da lockout (tpmr.sh da_state /bad_auth) probing tooling for later, and proceed to even merging this m900 tower board addition when you are satisfied with the results and my changes

@tlaurion tlaurion added the port new board addition from existing coreboot port label May 20, 2026
notgivenby and others added 14 commits May 20, 2026 11:49
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 2 times, most recently from a17c190 to 273f52f Compare May 20, 2026 16:01
@notgivenby
Copy link
Copy Markdown
Contributor

notgivenby commented May 20, 2026

@notgivenby can you test artifacts one last time? tpm reset up to tpm duk setup? changed #2117 to do bare minimal to fix #2068 regression with increment which was using tpm owner passphrase where not needed by spec. Will move all other fixes in pending pr for when I'll have time again; my x230 doesn't have proper 1.2 spec imlementation which makes it impossible to do proper things (da lockout policy cannot be asked for....) while swtpm on qemu is way too permissive and doesn't trigger da defend for long enough to test properly.

If this works for you, we can merge #2117 since its a regression fix and move proper da lockout (tpmr.sh da_state /bad_auth) probing tooling for later, and proceed to even merging this m900 tower board addition when you are satisfied with the results and my changes

@tlaurion I agree :-)
Tested: everything is okay, but the tpm duk set up does not work. erased all settings > added gpg key > reboot > reseted tpm > added default boot > set duk password > reboot > TOTP matches > enter duk password got error (this was probably where I got locked last time) . The duk password was like 1234567890qw. So the probability to mistype it several times is very low. Here are the logs from setting up the duk. duk_set_up_debug.log
duk_set_up_measuring_trace.log

Here are the logs after failed duk entering attempt.
debug.log
measuring_trace.log
new totp generation as suggested does not help.

@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch 2 times, most recently from ad4e5eb to 82d502f Compare May 21, 2026 00:14
…tween 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>
@tlaurion tlaurion force-pushed the m900_with_tpm1_fixes branch from 82d502f to 86eb954 Compare May 21, 2026 00:15
@tlaurion
Copy link
Copy Markdown
Collaborator Author

@notgivenby it must be because board has usb keyboard required which for some reason was not checked when sealing.

Question remains: if the board has ps2 keyboard, usb keyboard should not be enabled by default, but at compile time or through config-gui.sh (with a ps2 keyboard). I leave that to you to decide, but should be documented properly.

Hopefully, last commit should fix your tpm duk unsealing issue, let me know.

@notgivenby
Copy link
Copy Markdown
Contributor

@notgivenby it must be because board has usb keyboard required which for some reason was not checked when sealing.

Question remains: if the board has ps2 keyboard, usb keyboard should not be enabled by default, but at compile time or through config-gui.sh (with a ps2 keyboard). I leave that to you to decide, but should be documented properly.

Hopefully, last commit should fix your tpm duk unsealing issue, let me know.

@tlaurion Thank you!
Tested. Now everything is perfekt! Could you tell me how did you figure out from the logs that the problem was the usb keyboard?

The board has a PS2 header but one would need to buy a ps2 connector (around 10$). The one I got meanwhile arrived. I will able to test in few days. The majority of the boards I saw on used market do not have it. Not sure what would community choose. I suggest to use the ps2 variant with the usb keyboard disabled after I test it. Hopefully it will work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

port new board addition from existing coreboot port

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants