Skip to content

modules/tpm-gpio-reset: TPM GPIO reset audit and assertion tools - #2165

Open
tlaurion wants to merge 4 commits into
linuxboot:masterfrom
tlaurion:doc/tpm-gpio-vuln
Open

modules/tpm-gpio-reset: TPM GPIO reset audit and assertion tools#2165
tlaurion wants to merge 4 commits into
linuxboot:masterfrom
tlaurion:doc/tpm-gpio-vuln

Conversation

@tlaurion

@tlaurion tlaurion commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Adds tpm-gpio-detect (audit) and tpm-gpio-assert (execute) C binaries from the
tlaurion/tpm-gpio-fail fork
(commit 9052dbd, branch minimal-platform-fork), based on
Mate Kukri's original PoC.

modules/tpm-gpio-reset (new, 22 lines)

Builds both C binaries from the fork. Depends on pciutils and tpm2-tools.
Gated behind CONFIG_TPM2_TOOLS=y. Installs into initrd as
bin/tpm-gpio-detect and bin/tpm-gpio-assert.

tpm-gpio-detect (audit -- safe, read-only)

Uses libpci to find the ISA/LPC bridge by device class (no raw MMCFG).
Identifies the PCH platform, reads P2SB SBREG_BAR (hardcoded fallback
when hidden by FSP-S), then checks GPIO pad lock registers via /dev/mem:
PADCFGLOCK and PADCFGLOCKTX per PLTRST# pad (GPP_B13) and ESPI bus pins,
pad mode (NF1/GPIO), per-platform TIER classification. Self-documenting
ASCII table output with register values.

Exit codes: 0=all locked, >0=unlocked count, 2=not vulnerable by design,
126=unknown PCH, 127=hardware error.

tpm-gpio-assert (execute -- TPM may reboot, PCRs cleared, NVRAM preserved)

Calls tpm2 shutdown -c before and tpm2 startup -c after assertion.
Uses libpci to find the PCH, matching kukri's procedure.
Reads PADCFGLOCK/TX status, checks pad mode, performs NF1->GPIO
mode transition to create a PLTRST# reset edge:

  • All PCRs read via tpm2 pcrread before and after assertion
  • DW0 writeback verified (0x80000000), DW1 partial locking noted
  • Mechanism: NF1->GPIO mode transition (confirmed via coreboot GPIO code).
    PADRSTCFG (DW0 bits 31:30) selects pad reset trigger, not attack vector.
  • TPM auto-check via tpm2 pcrread after tpm2 startup -c

Exit codes: 0=DW0 verified, 1=DW0 locked, 2=not vulnerable, 126=unknown
PCH, 127=hardware error. ASCII-only output.

doc/TPM_GPIO_Reset_Approaches.md (new, 442 lines)

Developer reference: 8 approaches attempted on NV4x ADL-P, register
addresses verified against coreboot 26.06, GPIO lock status per
Dasharo/Purism forks, NF1->GPIO mode transition mechanism. TIER ordered:
TIER 1 (confirmed), TIER 2 (unconfirmed), TIER 3 (uncertain), NOT VULNERABLE.

doc/TPM_GPIO_Reset_Vulnerability.md (new, 23 lines)

Points to Heads Wiki Threat Model and Recovery Shell page.

doc/BOARDS_AND_TESTERS.md (+156/-62)

TPM GPIO vulnerability section referencing wiki. Restructured EOL/ESU board table.

initrd/.bash_history (+4 lines)

Recovery shell convenience commands. Removes bash-based PoC script.

doc/faq.md (-120 lines), doc/keys.md, doc/security-model.md

Reduced to wiki cross-references to avoid duplication.

Tested

NV4x ADL-P (0x5182) -- CONFIRMED VULNERABLE (TIER 1)

  • All GPIO pads unlocked (PADCFGLOCK = 0x00000000)
  • DW0 in NF1 mode (0x40000400, mode=1)
  • NF1->GPIO transition verified (DW0 writeback = 0x80000000)
  • tpm2 shutdown/startup session management correct
  • PCRs cleared to zero after assertion -- TPM reset confirmed on hardware

All other 13 platform families are untested
Report with tpm-gpio-detect 2>&1 | tee log. See fork issues.

Cross-references

  • Heads Wiki PR Stable long term kernel is 4.9.38 #224 -- RecoveryShell tools, ADL-P CONFIRMED, flash guides
  • Heads Wiki Threat Model -- per-board TPM GPIO protection table
  • tlaurion/tpm-gpio-fail -- fork with 14 PCH families, C source

Copilot AI review requested due to automatic review settings July 23, 2026 20:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@tlaurion

This comment was marked as duplicate.

@tlaurion

This comment has been minimized.

@tlaurion

This comment has been minimized.

@tlaurion
tlaurion force-pushed the doc/tpm-gpio-vuln branch 15 times, most recently from f6108c4 to 5e5c20a Compare July 31, 2026 02:30
@tlaurion tlaurion changed the title initrd, doc, boards: TPM GPIO reset vulnerability analysis, PoC tool, and board annotations modules/tpm-gpio-reset: TPM GPIO reset audit and assertion tools Jul 31, 2026
@tlaurion

tlaurion commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

Decided to extend @kukrimate Poc in fork and pack for all TPM2 based boards.

@macpijan nv4x_adl confirmed vulnerable.

From the repo's .bash_history at commit d8f1224:

# TPM GPIO Reset Vulnerability test: mount USB stick rw, audit PLTRST# lock status
mount-usb.sh --mode rw && tpm-gpio-detect 2>&1 | tee /media/tpm-gpio-detect.log
# Assert PLTRST# via P2SB PCR write and check TPM PCRs
tpm-gpio-assert 2>&1 | tee /media/tpm-gpio-assert.log

Fork commit: 0291c12 (module modules/tpm-gpio-reset pins CONFIG_TPM2_TOOLS=y). Two commands: tpm-gpio-detect (audit) then tpm-gpio-assert (execute — handles tpm2 shutdown/startup internally).

echo "=== DETECT ===" && cat /media/user/public/tpm-gpio-detect.log && echo && echo "=== ASSERT ===" && cat /media/user/public/tpm-gpio-assert.log
=== DETECT ===
Found platform AlderLake P with PCH ADL-P PCH!
P2SB SBREG_BAR = 0xfd000000 (platform-specific)

--- PLTRST# Pad Lock Status ---
  GPIO       Signal       PADCFGLOCK             PADCFGLOCKTX          
  GPP_B13    PLTRST#      0x00000000 (UNLOCKED)  0x00000000 (UNLOCKED)   <- UNLOCKED

--- Pad Configuration ---
DW0 (0x07d0) = 0x40000400, mode: NF1 (bits 13:10=0x1)
NF1 mode -- mode transition CAN create PLTRST# reset edge

--- eSPI Bus Pin Lock Status ---
  GPIO       Signal       PADCFGLOCK             PADCFGLOCKTX          
  GPP_A1     ESPI_IO0     0x00000000 (UNLOCKED)  0x00000000 (UNLOCKED)   <- UNLOCKED
  GPP_A2     ESPI_IO1     0x00000000 (UNLOCKED)  0x00000000 (UNLOCKED)   <- UNLOCKED
  GPP_A3     ESPI_IO2     0x00000000 (UNLOCKED)  0x00000000 (UNLOCKED)   <- UNLOCKED
  GPP_A4     ESPI_IO3     0x00000000 (UNLOCKED)  0x00000000 (UNLOCKED)   <- UNLOCKED
  GPP_A5     ESPI_CS#     0x00000000 (UNLOCKED)  0x00000000 (UNLOCKED)   <- UNLOCKED
  GPP_A9     ESPI_CLK     0x00000000 (UNLOCKED)  0x00000000 (UNLOCKED)   <- UNLOCKED
  GPP_A14    ESPI_RESET#  0x00000000 (UNLOCKED)  0x00000000 (UNLOCKED)   <- UNLOCKED

--- Vulnerability Classification ---
TIER 1 -- CONFIRMED VULNERABLE: ADL-P mobile: NF1 mode confirmed, PLTRST# verified (TIER 1)
Attack confirmed working by community testing.

=== RESULT: unlocked pins found (unlocked: 8) ===

=== ASSERT ===
SBREG_BAR = 0xfd000000 (MEM)

Found Alder Point P

--- PADCFGLOCK Status (port 0x6e, offset 0x80) ---
PADCFGLOCK   = 0x00000000 (UNLOCKED, bit 13 clear)
PADCFGLOCKTX = 0x00000000 (UNLOCKED, bit 13 clear)

--- PCR State Before Assertion ---
  sha256:
    0 : 0x0000000000000000000000000000000000000000000000000000000000000000
    1 : 0x0000000000000000000000000000000000000000000000000000000000000000
    2 : 0xC45991E14F0B09EBFCD96FF16EAD26D7F3596E3F24677F587ED93FE66F3A9D16
    3 : 0x0000000000000000000000000000000000000000000000000000000000000000
    4 : 0x51737C77C481AA22095B38D38FC9FD494B0FFA4EAE7D3AC238082083D0AFD614
    5 : 0x5DCB5FCAF52F32ED2BDF8F7C5CBA01A54343D8356EB5E2B755B635F217F29EBB
    6 : 0x0000000000000000000000000000000000000000000000000000000000000000
    7 : 0x0000000000000000000000000000000000000000000000000000000000000000
    8 : 0x0000000000000000000000000000000000000000000000000000000000000000
    9 : 0x0000000000000000000000000000000000000000000000000000000000000000
    10: 0x0000000000000000000000000000000000000000000000000000000000000000
    11: 0x0000000000000000000000000000000000000000000000000000000000000000
    12: 0x0000000000000000000000000000000000000000000000000000000000000000
    13: 0x0000000000000000000000000000000000000000000000000000000000000000
    14: 0x0000000000000000000000000000000000000000000000000000000000000000
    15: 0x0000000000000000000000000000000000000000000000000000000000000000
    16: 0x0000000000000000000000000000000000000000000000000000000000000000
    17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    23: 0x0000000000000000000000000000000000000000000000000000000000000000

--- TPM Session Preparation ---
Running tpm2 shutdown -c to cleanly shut down TPM session

*** WARNING: About to assert PLTRST# -- TPM may reboot (PCRs clear, NVRAM preserved) ***
*** This test reboots the TPM (PCRs clear, NVRAM preserved).    ***
PCR port=0x6e offset=0x7d0
DW0 (original) = 0x40000400  DW1 (original) = 0x0003c025

--- Pad Mode Check ---
Current mode: NF1 (DW0 bits 13:10 = 0x1)
Mode transition possible: NF1 -> GPIO -> NF1 (creates PLTRST# reset edge)
PLTRST# assertion CAN attempt mode transition reset
DW0 (asserted) = 0x80000000  DW1 (asserted) = 0x00000025
DW1 partially locked (TX control bits) - does not prevent reset
Registers restored
Running tpm2 startup -c to reinitialize TPM

--- PCR State After Assertion ---
  sha256:
    0 : 0x0000000000000000000000000000000000000000000000000000000000000000
    1 : 0x0000000000000000000000000000000000000000000000000000000000000000
    2 : 0x0000000000000000000000000000000000000000000000000000000000000000
    3 : 0x0000000000000000000000000000000000000000000000000000000000000000
    4 : 0x0000000000000000000000000000000000000000000000000000000000000000
    5 : 0x0000000000000000000000000000000000000000000000000000000000000000
    6 : 0x0000000000000000000000000000000000000000000000000000000000000000
    7 : 0x0000000000000000000000000000000000000000000000000000000000000000
    8 : 0x0000000000000000000000000000000000000000000000000000000000000000
    9 : 0x0000000000000000000000000000000000000000000000000000000000000000
    10: 0x0000000000000000000000000000000000000000000000000000000000000000
    11: 0x0000000000000000000000000000000000000000000000000000000000000000
    12: 0x0000000000000000000000000000000000000000000000000000000000000000
    13: 0x0000000000000000000000000000000000000000000000000000000000000000
    14: 0x0000000000000000000000000000000000000000000000000000000000000000
    15: 0x0000000000000000000000000000000000000000000000000000000000000000
    16: 0x0000000000000000000000000000000000000000000000000000000000000000
    17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    23: 0x0000000000000000000000000000000000000000000000000000000000000000

=== RESULT: PCRs cleared to zero -- TPM reboot confirmed via sha256 PCR read ===

--- Next Steps ---
NF1->GPIO transition executed.
Report results: https://github.com/tlaurion/tpm-gpio-fail/issues
Include this log output.

@tlaurion
tlaurion force-pushed the doc/tpm-gpio-vuln branch 7 times, most recently from 3abc911 to c527dc3 Compare July 31, 2026 04:35
Adds tpm-gpio-detect (audit) and tpm-gpio-assert (execute) from
tlaurion/tpm-gpio-fail, based on Mate Kukri original PoC. Libpci
PCI access. PCR output before/after assertion. ASCII output.

Module depends on pciutils, tpm2-tools. Built when CONFIG_TPM2_TOOLS=y.

TESTED: NV4x ADL-P (0x5182) — PCRs cleared to zero, confirmed.
ALL OTHER PLATFORMS UNTESTED.

Docs: TPM GPIO vulnerability docs point to Heads Wiki threat model.
initrd: .bash_history entries for recovery shell testing.
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion
tlaurion force-pushed the doc/tpm-gpio-vuln branch from c527dc3 to d8f1224 Compare July 31, 2026 04:46
@tlaurion
tlaurion marked this pull request as draft July 31, 2026 04:57
@tlaurion
tlaurion marked this pull request as ready for review July 31, 2026 04:57
@tlaurion

Copy link
Copy Markdown
Collaborator Author

@Thrilleratplay @gaspar-ilom last review before merge please

@tlaurion

Copy link
Copy Markdown
Collaborator Author

Note that Alder Lake work has been made by @Sean-StarLabs

https://review.coreboot.org/q/topic:%22starlabs-lockdown%22

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.

GPIO locking is broken on Kaby Lake and possibly other platforms

3 participants