mirror of
https://github.com/stefanberger/swtpm.git
synced 2026-08-07 15:47:41 +00:00
Libtpms-based TPM emulator with socket, character device, and Linux CUSE interface.
Prepend tag-length-value (tlv) headers in front of all data being stored in the byte stream following the header. This lets us uniquely identify plain data (= TPM state), encrypted data (= encrytped TPM state), migration data (which is wrapped plain or encrytped TPM state), and an HMAC block to validate the plain data. We keep support for version 1 for reading the data but convert them to version 2 when writing them out. This way we loose backwards compatibility (downgrading of swtpm is not possible), but it allows us to extend the state in the future by adding addition blocks with tlv headers. Version 1 of the encryption was prepending the hash on the plaintext data then encrypting all of it. This method is not so good. In version 2 we now use Encrypt-then-MAC (EtM) where we encrypt the data and then calculate an HMAC on the encrypted data. Files written by the swtpm didn't have a header before. Now they also get a header. This means that the state written into files and the state retrieved using the API (swtpm_ioctl --save) have the same format, but still differ in so far as the API wraps the data in a tlv header for migration, which the files written out as state would never get. Adapt a couple of test cases show file sizes and hashes have changed now. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> |
||
|---|---|---|
| debian | ||
| dist | ||
| etc | ||
| include | ||
| man | ||
| samples | ||
| src | ||
| tests | ||
| .gitignore | ||
| .travis.yml | ||
| bootstrap.sh | ||
| CHANGES | ||
| configure.ac | ||
| COPYING | ||
| DCO1.1.txt | ||
| INSTALL | ||
| install-sh | ||
| LICENSE | ||
| Makefile.am | ||
| README | ||
| run_tests | ||
| TODO | ||
SWTPM - Software TPM Emulator
David Safford safford@us.ibm.com
Stefan Berger stefanb@us.ibm.com
The SWTPM package provides TPM emulators with different front-end interfaces
to libtpms. TPM emulators provide socket interfaces (TCP/IP) and the Linux
CUSE interface for the creation of multiple native /dev/vtpm* devices.
Those can be the targets of multiple QEMU cuse-tpm instances.
The SWTPM package also provides several tools for using the CUSE TPM,
creating certificates for a TPM, and simulating the manufacturing of
a TPM by creating a TPM's EK and platform certificates etc. Please read
the READMEs in the individual tool's directory under src/.
TPM emulators:
--------------
The primary goal of the CUSE TPM is to support running multiple QEMU guests,
each having its own TPM emulator, without modifying QEMU, the kernel, or
libtpms. The approach is to use the QEMU cuse-tpm driver, pointing it to
/dev/vtpm? which is established as a CUSE frontend to libtpms.
The CUSE frontend supports ioctls on the /dev/vtpm? device file, for
handling hardware specific features, such as hardware reset, hardware
shutdown, setting locality, and getting the tpmEstablished bit and
others. There is a getcapability ioctl to query which of these features
are available on a given vtpm.
This has been tested on Fedora 20, as it has everything needed
(cuse, QEMU with TPM passthrough driver, libtpms...) enabled by default.
It is also known to work on RHEL-6.
Building:
Please read INSTALL for how to build and install the package
Notes: If you are running selinux in enforcing mode (the Fedora 20 default),
then you will get many (6?) rounds of errors, and everytime you have to
use the selinux troubleshooter to add policies to allow the vtpm
server to run. You only have to do this for the first VM.
(If you are running ima-appraisal, you will need to sign the
installed executables and libraries (/usr/bin/swtpm and
/usr/bin/swtpm_cuse and /usr/lib/libswtpm_libtpms.so)
In the Guest:
If you are running a fedora20 guest, then you can start out with:
yum install tpm-tools
systemctl start tcsd.service
tpm_createek
tpm_takeown -u -y -z
tpm_getpubek -u -z
-----------------------------------------------------------------------------
Low level details on the executables:
On Fedora 20, CUSE is a module, so you may need to:
modprobe cuse
For each desired vtpm, as root you simply:
export TPM_PATH=<directory to keep vtpm state files>
./swtpm_cuse -M <major> -m <minor> -n <device name>
The process runs as a background daemon.
Initialize two vTPMs' initial state with an EK each:
# mkdir /tmp/myvtpm0
# chown -R tss:root /tmp/myvtpm0
# swtpm_setup --tpm-state /tmp/myvtpm0 --createek
# mkdir /tmp/myvtpm1
# chown -R tss:root /tmp/myvtpm1
# swtpm_setup --tpm-state /tmp/myvtpm1 --createek
Start the vTPM to use it with QEMU:
# export TPM_PATH=/tmp/myvtpm0
# swtpm_cuse -n vtpm0
# export TPM_PATH=/tmp/myvtpm1
# swtpm_cuse -n vtpm1
Running QEMU with the cuse-tpm:
There are two needed options for the passthrough -tpmdev and -device
as shown in these examples. Note that the "path" parameter points to the
native (/dev/vtpm0...) path, while the id and tpmdev are the guest's view.
$ qemu-system-x86_64 -display sdl -enable-kvm -cdrom cdrom.iso \
-m 1024 -boot d -bios bios.bin -boot menu=on -tpmdev \
cuse-tpm,id=tpm0,path=/dev/vtpm0 \
-device tpm-tis,tpmdev=tpm0 test.img
$ qemu-system-x86_64 -display sdl -enable-kvm -cdrom cdrom.iso \
-m 1024 -boot d -bios bios.bin -boot menu=on -tpmdev \
cuse-tpm,id=tpm1,path=/dev/vtpm1 \
-device tpm-tis,tpmdev=tpm1 test2.img
For this to work, qemu patches that are not included in upstream qemu
are needed. Currently those are maintained in
https://github.com/stefanberger/qemu-tpm
Including them upstream has been discussed, most recently at
https://lists.nongnu.org/archive/html/qemu-devel/2016-06/msg00252.html