TpmShellApp on QEMU Platforms
Platform-specific guidance for running TpmShellApp on the QEMU Q35 and Arm Virt platforms.
Table of Contents
- FDF Placement
- Protocol Availability
- Running on QEMU Arm Virt
- Running on QEMU Q35
- Hash Algorithm Configuration
- Expected Behavior with MinimumLib
- Event Log and Replay
- Findings
FDF Placement
On Arm Virt, add the INF to FV.FvMain. On Q35, add it to FV.DXEFV:
INF SecurityPkg/Applications/TpmShellApp/TpmShellApp.inf
Protocol Availability
The EFI_TCG2_PROTOCOL is installed by Tcg2Dxe.efi, which only loads when
TPM2_ENABLE=TRUE.
Running on QEMU Arm Virt
On QEMU Arm Virt, the TpmShellApp is placed directly in the firmware volume, which is mapped as an
FSx: device in the UEFI shell. Build with:
stuart_build -c Platforms/QemuArmVirtPkg/PlatformBuild.py --FlashRom BLD_*_TPM2_ENABLE=TRUE
At the UEFI shell, run:
Shell> TpmShellApp.efi help
Shell> TpmShellApp.efi info
Shell> TpmShellApp.efi eventlog
Shell> TpmShellApp.efi replay
Or navigate to the correct FS mapping first:
Shell> map -r
Shell> FS0:
FS0:\> TpmShellApp.efi info
Running on QEMU Q35
On Q35, shell applications are loaded from a virtual drive (FAT filesystem image), not
directly from the firmware volume. The FILE_REGEX build parameter controls which
binaries are copied to the virtual drive:
stuart_build -c Platforms/QemuQ35Pkg/PlatformBuild.py --FlashRom \
BLD_*_TPM2_ENABLE=TRUE \
FILE_REGEX=TpmShellApp.efi
At the UEFI shell, find the virtual drive's FS mapping (typically backed by a PCI device,
not Fv(...)) and run:
Shell> map -r
Shell> FS0:
FS0:\> TpmShellApp.efi info
If the app is not found, verify the virtual drive was created with the binary:
Shell> FS0:
FS0:\> dir
Hash Algorithm Configuration
Both QEMU platforms set PcdTpm2HashMask to 0x02 (SHA256 only). This means the app
will typically only see SHA256 as supported and active, even though swtpm may support all
five algorithms. To see additional algorithms, update PcdTpm2HashMask in the platform
DSC.
Expected Behavior with MinimumLib
Both QEMU platforms use DxeTcg2PhysicalPresenceMinimumLib when TPM is enabled. This
library has specific behaviors that affect TpmShellApp results:
setpcr with Already-Active Banks
When the requested banks match the currently active banks, Tcg2Dxe sends
TCG2_PHYSICAL_PRESENCE_NO_ACTION to the PP library. MinimumLib processes NO_ACTION
successfully, returning EFI_SUCCESS.
Shell> TpmShellApp setpcr 0x2 (SHA256 already active)
Submitting SetActivePcrBanks with parameter 2
Status: Success
Request submitted. Changes will take effect after reboot.
setpcr with Different Banks
When the requested banks differ from active banks, Tcg2Dxe sends
TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS to the PP library. MinimumLib rejects this
operation as it only supports Clear operations.
Shell> TpmShellApp setpcr 0x4 (SHA384, not currently active)
Submitting SetActivePcrBanks with parameter 4
Status: Unsupported
SetActivePcrBanks failed.
This is expected and correct behavior — MinimumLib is designed to block PCR bank changes.
logall Expected Behavior
If the platform only has SHA256 registered (default), logall requests the same bank
that's already active, resulting in a NO_ACTION → EFI_SUCCESS. If additional
algorithms were registered, it would request banks different from the active set,
triggering a SET_PCR_BANKS rejection.
lastresponse Expected Behavior
Reports the result stored in the Tcg2PhysicalPresence NV variable by
ProcessRequest. If no prior SetActivePcrBanks was processed through a reboot cycle,
the response will show no operation present.
Shell> TpmShellApp lastresponse
Operation present: NO
Response code: 0
Event Log and Replay
eventlog on QEMU
The eventlog command dumps the crypto-agile TCG2 event log. On QEMU with the default
SHA256-only configuration, each event contains a single SHA256 digest.
Shell> TpmShellApp.efi eventlog
[TCG2 Event Log]
Spec ID Event: 1 algorithm(s)
SHA256 (alg 0xb, digest 32 bytes)
Event 1: PCR 0 EV_S_CRTM_VERSION (0x8)
SHA256: ab cd ef ...
Event data: 2 bytes
Event 2: PCR 0 EV_EFI_PLATFORM_FIRMWARE_BLOB (0x80000008)
SHA256: 01 23 45 ...
Event data: 16 bytes
...
Total: N event(s)
If PcdTpm2HashMask is updated to enable additional algorithms (e.g., 0x06 for
SHA256 + SHA384), each event will contain multiple digests — one per active algorithm.
replay on QEMU
The replay command replays extend operations from the event log to compute expected
PCR values, then reads the actual PCR values from the TPM via SubmitCommand and
compares them.
Shell> TpmShellApp.efi replay
[Event Log Replay]
Replayed N event(s) across 1 algorithm(s).
PCR 0:
SHA256 Replayed: aa bb cc ...
SHA256 Actual: aa bb cc ...
Result: PASS
PCR 1:
SHA256 Replayed: 11 22 33 ...
SHA256 Actual: 11 22 33 ...
Result: PASS
...
Summary: M PCR bank(s) verified, M PASS, 0 FAIL
On a freshly booted QEMU platform with swtpm, all PCRs should show PASS. A FAIL
indicates that either the event log is incomplete (e.g., truncated) or an extend
operation occurred outside the logged event flow.
Replay with Multiple Algorithms
When multiple hash algorithms are active, the replay verifies each algorithm
independently. Algorithms not supported by BaseCryptLib (e.g., SM3_256) are skipped
with a message:
PCR 0:
SHA256 Replayed: ...
SHA256 Actual: ...
Result: PASS
SM3_256: (replay not supported, skipped)
Truncated Event Log
If the firmware's event log buffer was exhausted, the eventlog and replay commands
print a warning:
Warning: Event log was truncated.
For replay, a truncated log means the replayed PCR values will not include all
extensions, so mismatches are expected.
Findings
April 2026:
Manually updating Tpm2HashMask in the platform .dsc is dangerous. On Q35, PEI picks up
the change and automatically enables/disables any PCR banks that differ from the current
active banks in the TPM (see Tcg2Pei - SyncPcrAllocationsAndPcrMask). If the platform also
disables (i.e. removes) any of the supported hashing algorithms from the platform .dsc,
there are no safeguards to prevent the TPM from enabling/disabling active banks based on
platform support. Because of this, there can be active banks that show up as active when
querying the TPM directly but do not show up as active in the Tcg2Protocol call.
Example:
-
Tpm2HashMaskis updated to0x06(i.e. SHA256 + SHA384 supported). -
SHA384 support is removed from
Tcg2PeiandTcg2Dxe. -
Build/Run the Q35 platform.
-
TPM reports SHA256 as the only active PCR bank.
-
Tcg2Peirecognizes there is a mismatch between platform support (i.e.Tpm2HashMask) and TPM active banks. It activates SHA384 and triggers aResetCold. -
TPM reports SHA256 + SHA384 as active PCR banks.
-
HashLibBaseCryptoRouterPeiandHashLibBaseCryptoRouterDxesetPcdTcg2HashAlgorithmBitmapbased on successfully registered hash algorithms. -
Tcg2Peiregisters SHA256 but is unable to register SHA384. -
Tcg2Dxeregisters SHA256 but is unable to register SHA384. -
Tcg2Dxesets local variables based on what the TPM reports andPcdTcg2HashAlgorithmBitmap.mTcgDxeData.BsCap.HashAlgorithmBitmap = TpmHashAlgorithmBitmap & PcdGet32 (PcdTcg2HashAlgorithmBitmap); mTcgDxeData.BsCap.ActivePcrBanks = ActivePCRBanks & PcdGet32 (PcdTcg2HashAlgorithmBitmap); -
Tcg2Protocolis installed with only SHA256 support reported even though SHA384 is active.