Skip to content
Stefan Berger edited this page Jun 5, 2022 · 15 revisions

The following are some more advanced tests of the TPM 2 using the IBM TSS stack from within a VM.

Dictionary Attack : Lockout

> export TPM_INTERFACE_TYPE=dev

# Create an NV RAM index
> tssnvdefinespace -hi o -ha 0x01000000 -pwdn good -sz 16 -at da

# Write some data to it; this command needs to be run twice the first time
> tssnvwrite -ha 0x01000000 -ic test -pwdn good
> tssnvwrite -ha 0x01000000 -ic test -pwdn good

# set the lock-out timeout parameters to 20 seconds
> tssdictionaryattackparameters -lr 20 -nrt 20

# Use a wall clock (stop watch) when starting the following command to trigger the lockout
> tssnvwrite -ha 0x01000000 -ic test -pwdn bad

# You may want to suspend/resume the VM now.
# Only after 20 seconds the following command should pass again without an error

> tssnvwrite -ha 0x01000000 -ic test -pwdn good

Hibernation (ACPI S4)

I tested this with CentOS and SeaBIOS as firmware. It may take quite some time for the display to come back and accept keyboard input. The best is to patiently wait for the screen to reappear and not cause keyboard inputs. In case of problems, please try without attached TPM as well.

Please make sure that the firmware has support for the TPM interface you are using. If using SeaBIOS, the SeaBIOS menu indicates whether there is support for TPM and the TPM interface if the menu entry for TPM is shown.

If you are trying this with libvirt, please make sure that the following is set in the domain XML:

[...]
  <pm>
    <suspend-to-mem enabled='yes'/>
    <suspend-to-disk enabled='yes'/>
  </pm>
[...]
> export TPM_INTERFACE_TYPE=dev
> tsspcrread -ha 1

# Initiate hibernation
systemctl hibernate

# Restart the VM and display the PCR again -- the value of this PCR has to be the same as before (unless you change the firmware)
> tsspcrread -ha 1

Note:

  • With SeaBIOS: Hibernation uses TPM2_Shutdown(SU_STATE) before system shutdown (power-off). When the machine starts the firmware does a TPM2_Startup(SU_CLEAR) and the system goes through a normal boot cycle until it restores the previous screen that was active when the 'systemctl hibernate' was issued. Due to TPM2_Startup() using SU_CLEAR all PCRs are initially in their reset state and then get 'extended' by the firmware.

  • With EDK2: Hibernation uses TPM2_Shutdown(SU_STATE) followed by TPM2_GetRandom() before system shutdown (power-off). When the machine starts the firmware does a TPM2_Startup(SU_CLEAR) and the system goes through a normal boot cycle. It does NOT restore the previous screen that was active when the 'systemctl hibernate' was issued.

Suspend to RAM (ACPI S3)

> export TPM_INTERFACE_TYPE=dev
> tsspcrread -ha 1

# Initiate suspend to RAM
systemctl suspend

# Restart the VM and display the PCR again -- the value of all BIOS PCRs has to be the same
> tsspcrread -ha 1

Note:

  • With SeaBIOS: Suspend To RAM behaves the same as Hibernation.
  • With EDK2: Suspend-to-RAM uses TPM2_Shutdown(SU_STATE) followed by TPM2_GetRandom() before the virtual machine pauses execution. QEMU then resets the hardware interface (TIS or CBR) when waking up as if the machine was reset (indistinguishable). This causes a CMD_INIT to be sent to swtpm to also reset the core TPM 2. There's no TPM2_Startup() being sent to the TPM 2.