Software TPM Emulator For QEMU

Jump to: navigation, search

Introduction

Trusted Platform Module (TPM) is a component to provide several security functions, e.g. encryption, random number generation, measurement, etc., and now widely deployed among the new machines due to the requirement of Windows 10 certification. For the developers who want to use TPM to develop the security features, a software TPM emulator is usually a good choice. Before 2.11, QEMU can only do TPM passthrough to access the TPM hardware on the host, and this limits the number of guests to access TPM. Besides, the developers are also limited by the hardware capabilities. It's impossible to develop the TPM 2.0 features with a TPM 1.2 chip. Fortunately, since 2.11, QEMU starts to support the TPM emulator. With TPM emulator, the guest can switch between TPM 1.2 and TPM 2.0 easily, and this makes the developer's life much easier.

Install the Software TPM Emulator

The software TPM emulator swtpm is curently included in openSUSE Tumbleweed. For other products and versions the packages are available in the "security" repo:

https://software.opensuse.org//download.html?project=security&package=swtpm

Just download libtpms0 and swtpm and install them.

Setup a TPM Emulator

swtpm provides 3 types of interface: socket, chardev, and cuse. Here we choose "socket" since it's the only type that doesn't need to create a node in /dev. First, create a directory to store the TPM states right inside the VM directory:

 $ mkdir ${path_to_vm}/mytpm0

And then, start the emulator to create a socket file, swtpm-sock, for QEMU.

 $ swtpm socket --tpmstate dir=${path_to_vm}/mytpm0 \
         --ctrl type=unixio,path=${path_to_vm}/mytpm0/swtpm-sock \
         --log level=20

By default, swtpm starts a TPM 1.2 emulator and stores the states in "tpm-00.permall" in the directory. It's also possible to create a TPM 2.0 instance:

 $ swtpm socket --tpm2 --tpmstate dir=${path_to_vm}/mytpm0 \
         --ctrl type=unixio,path=${path_to_vm}/mytpm0/swtpm-sock \
         --log level=20

The TPM 2.0 states will be stored in "tpm2-00.permall". If you want swtpm to run in the background, just add "-d" to daemonize it.

Start QEMU along with swtpm

Once you start swtpm, add the following QEMU parameters to create the TPM device:

  • For x86_64:
 -chardev socket,id=chrtpm,path=${path_to_vm}/mytpm0/swtpm-sock \
 -tpmdev emulator,id=tpm0,chardev=chrtpm \
 -device tpm-tis,tpmdev=tpm0
  • For aarch64:
 -chardev socket,id=chrtpm,path=${path_to_vm}/mytpm0/swtpm-sock \
 -tpmdev emulator,id=tpm0,chardev=chrtpm \
 -device tpm-tis-device,tpmdev=tpm0

The difference is the device name: tpm-tis vs tpm-tis-device

Then, a TPM device will be available in the guest, and "tpm_version" would show you:

 TPM 1.2 Version Info:
 Chip Version:        1.2.18.158
 Spec Level:          2
 Errata Revision:     3
 TPM Vendor ID:       IBM
 TPM Version:         01010000
 Manufacturer Info:   49424d00

Start swtpm with libvirt

If you use libvirt, add the following TPM emulator device to template:

 <devices>
    <tpm model='tpm-tis'>
      <backend type='emulator' version='2.0'/>
    </tpm>
 </devices>

libvirt will start swtpm as the TPM emulator for the guest VM. You don't need to launch swtpm daemon by yourself.

The tpm-crb TPM model can also be used, but it's only for TPM 2.0.

The corresponding permall file will be created automatically in /var/lib/libvirt/swtpm/[VM_UUID]

e.g.

# ls /var/lib/libvirt/swtpm/00c1ee41-3150-4d24-80b4-ab032732653c/tpm2/
.lock            tpm2-00.permall

The above UUID follows the number in libvirt template.

TPM measurement in OVMF

If you use OVMF firmware for the guest, then the firmware will measure components with TPM.

After booting, kernel exposes the event log by securityfs:

/sys/kernel/security/tpm0/binary_bios_measurements

See also