Repository navigation
Declare the TPM's PCR banks in the event log - #28
Open
iwanicki92 wants to merge 5 commits into
Open
iwanicki92 wants to merge 5 commits into
iwanicki92 wants to merge 5 commits into
Conversation
tis_recv() reads all but the last byte of the response body into the buffer and then reads the last byte into the first byte of that same body. The final byte of every response is therefore whatever the buffer held before, and the first byte is overwritten. Read the last byte into its own place after the bytes already received. Signed-off-by: iwanicki92 <iwanicki92@gmail.com>
tis_recv() waits TIMEOUT_D once after STS_GO, and gives up if no response is there by then. TIMEOUT_D is 30 ms on TPM 2.0 and 750 ms on TPM 1.2. It bounds a register access, not a command, and commands take longer. Linux's TPM driver allows 750 ms for TPM2_GetCapability and TPM2_PCR_Extend (TPM2_DURATION_MEDIUM), and 2 s for slower commands such as TPM2_GetRandom (TPM2_DURATION_LONG). Poll dataAvail every millisecond for up to 2 s instead, which covers both, on both TPM families. This lengthens the TPM 1.2 wait from 750 ms to 2 s. It prepares for a PCR bank query with TPM2_GetCapability, whose response can take longer than 30 ms. The family argument is no longer used and is marked unused, as in crb_recv(). Signed-off-by: iwanicki92 <iwanicki92@gmail.com>
convert_digest_list() steps over an SM3-256 digest by SM3256_SIZE, but adds SHA1_SIZE to the size it returns. A TPM2_PCR_Extend with an SM3-256 digest is therefore built 12 bytes short, and the TPM fails it. Add SM3256_SIZE instead. Nothing extends an SM3-256 bank yet. The PCR bank support that follows extends a placeholder digest into such a bank. Signed-off-by: iwanicki92 <iwanicki92@gmail.com>
.bss starts on the first page boundary after .skinit_reserved. Its page-aligned data comes first: the page tables, the event log and the IOMMU device table, 40 KiB in the 64-bit build. The small .bss variables follow, about 1.2 KiB, and then bootloader_data. GRUB puts a 4 KiB SLRT at bootloader_data and refuses an SKL that leaves less room before the 64 KiB end. In a 64-bit DEBUG build, .skinit_reserved ends 0x380 bytes below 0x4000. Once it crosses 0x4000, .bss starts at 0x5000, and the small variables push bootloader_data past 0xf000. Link the small variables into a section of their own before .bss, in the space that the page alignment of .bss leaves free. The code can then grow until it and the small variables reach 0x5000, about 2.8 KiB more. The cost is room after bootloader_data. A 64-bit DEBUG build puts it at 0xf000, with exactly 4 KiB left instead of 6.8 KiB. An assertion fails the link when less than 4 KiB is left. clang with LTO puts each variable in a section named after it, such as .bss.tis_buff. The page-aligned data moves to .bss..page_data, so the new section can take every .bss.<name> section but that one. The small .bss would share a LOAD segment with the code, and ld 2.39 and later warn about the RWX segment, which --fatal-warnings turns into an error. A maximum page size of 16 bytes puts them in separate segments. skl.bin is a flat binary, so the segments do not change it. Signed-off-by: iwanicki92 <iwanicki92@gmail.com>
The event log declares SHA-1 and SHA-256 whatever banks the TPM has. Linux resets on a log whose banks differ from the TPM's banks, because its extend needs one digest per allocated bank, in the TPM's order. So a TPM with only SHA-256, or with SHA-384 as well, fails every launch. Ask the TPM for its PCR allocation with TPM2_GetCapability, and declare those banks in that order. Each record carries SHA-1 and SHA-256 where the TPM has them. Other banks get a placeholder digest (01 followed by zeros), as Linux and Xen log for such banks. For the records the SKL measures itself, it extends the same placeholder into those banks, so those records replay. The SKINIT record does not replay there, because SKINIT extends PCR 17 with the real digest in every bank. If the query fails, or finds no bank of an algorithm the SKL knows, the log declares SHA-1 and SHA-256, the banks most discrete TPMs have allocated by default. DEBUG builds print the query's return code. The query fails in these cases: - on a CRB TPM, because crb_recv() does not read the reply - in the AMDSL build, which starts the log while the PSP keeps locality 2 locked - on a TPM with more than five banks A bank of an algorithm the SKL does not know is left out of the log. test-event_log.c checks the header and records for two, one and three banks and the fallback. Run it with "make run-test-event_log". It stubs the GetCapability query, so it does not cover the reply parser. Signed-off-by: iwanicki92 <iwanicki92@gmail.com>
This was referenced Oct 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
With a TPM that has only SHA-256 allocated, or SHA-384 as well, every Linux Secure Launch fails. The SKL's event log declares SHA-1 and SHA-256 whatever banks the TPM has. Linux resets on a log whose banks differ from the TPM's, because its extend needs one digest per allocated bank, in the TPM's order.
The last commit asks the TPM for its PCR allocation with
TPM2_GetCapabilityand declares those banks, in that order. Banks the SKL cannot hash get a placeholder digest (01 followed by zeros), as Linux and Xen log for such banks, and the SKL extends the same placeholder there for its own records. If the query fails, the log falls back to SHA-1 and SHA-256.The commits before it are what the query needs:
tis_recv()stored the last byte of every response in the first byte of the body. This commit is taken from patch 0012 in zarhus/meta-trenchboot#58 with its message reworded, because the bank query depends on it.tis_recv()waited oneTIMEOUT_D(30 ms on TPM 2.0) for the response. In CI, a software TPM on a busy runner once answered the bank query later than that. The SKL then fell back to SHA-1 and SHA-256 on a TPM with only SHA-256, and the Linux launch failed. A stalled swtpm reproduces it.tis_recv()now polls for up to 2 s, as long as Linux allows for slow commands.convert_digest_list()counted an SM3-256 digest as 20 bytes, so such an extend was built short.bootloader_dataleaves GRUB less than the 4 KiB it needs for the SLRT, and GRUB then rejects the SKL. The linker script puts the small.bssbefore the page-aligned data, and an assertion fails the link when less than 4 KiB is left.Known limits. None of them is a regression. Before this PR, the log always declared SHA-1 and SHA-256, and in each case below it is no worse than that:
crb_recv()does not read the reply, so the log falls back to the old two banks.The first three commits apply unchanged to
skl-loader-amdsl-noblob. Thelink.ldscommit needs a rebase there, because that branch changes the linker script too.Testing:
make run-test-event_logruns the new hosted test for two, one and three banks and the fallback.skl-loader-amdsl-v11without this PR.