Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

TpmShellApp on QEMU Platforms

Platform-specific guidance for running TpmShellApp on the QEMU Q35 and Arm Virt platforms.

Table of Contents

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_ACTIONEFI_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 editing Tpm2HashMask can desync the TPM and the protocol

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:

  • Tpm2HashMask is updated to 0x06 (i.e. SHA256 + SHA384 supported).

  • SHA384 support is removed from Tcg2Pei and Tcg2Dxe.

  • Build/Run the Q35 platform.

  • TPM reports SHA256 as the only active PCR bank.

  • Tcg2Pei recognizes there is a mismatch between platform support (i.e. Tpm2HashMask) and TPM active banks. It activates SHA384 and triggers a ResetCold.

  • TPM reports SHA256 + SHA384 as active PCR banks.

  • HashLibBaseCryptoRouterPei and HashLibBaseCryptoRouterDxe set PcdTcg2HashAlgorithmBitmap based on successfully registered hash algorithms.

  • Tcg2Pei registers SHA256 but is unable to register SHA384.

  • Tcg2Dxe registers SHA256 but is unable to register SHA384.

  • Tcg2Dxe sets local variables based on what the TPM reports and PcdTcg2HashAlgorithmBitmap.

    mTcgDxeData.BsCap.HashAlgorithmBitmap = TpmHashAlgorithmBitmap & PcdGet32 (PcdTcg2HashAlgorithmBitmap);
    mTcgDxeData.BsCap.ActivePcrBanks      = ActivePCRBanks & PcdGet32 (PcdTcg2HashAlgorithmBitmap);
    
  • Tcg2Protocol is installed with only SHA256 support reported even though SHA384 is active.