Skip to content
Stefan Berger edited this page Jul 22, 2020 · 64 revisions

Welcome to the swtpm wiki!

Build Status Coverage Status Coverity Build Status CII Best Practices

Goal

The goal of the swtpm project is to provide a TPM emulator (TPM 1.2 & TPM 2) that can be integrated into virtualized environments, such as virtual machines and containers. So far it has been integrated into QEMU and as a prototype into RunC (PR).

Swtpm builds on top of libtpms that provides the TPM 1.2 and TPM 2 emulation.

Mailing Lists

For announcements of swtpm releases and security issues, please subscribe to the swtpm-announce mailing list here.

Security/Trust Model of the Software TPM

Since the swtpm is fully implemented in software its security is not as strong as that of a hardware TPM. When the swtpm process is running, process ownership governs who can peek into the process and find secrets there, by hooking gdb to it for example. The persistent state the swtpm keeps is written into files and those are protected by file ownership and file access permission flags. Whoever can access those files can extract its secrets. To protect the state, a user can use a secret to encrypt the state, which will make it more difficult for an administrator to extract secrets from the swtpm's state files but does not prevent the administrator from peeking into the running swtpm process. Running the swtpm in a shielded environment using a technology like Intel's SGX, or AMD's SME, can likely help address this issue.

Security/Trust Model of the Software TPM and Confidential Computing (in the cloud)

When it comes to confidential computing we would begin by assuming that swtpm is running inside a protected environment and is shielded from attacks by the host administrator (root). Also, in such an environment we would probably want to assume that we will only be able to trust the hardware and firmware of the system.

With this model a challenge now arises when wanting to migrate a software TPM (or as a matter of fact a VM) from one system to another. It seems that in such a case we would have to request a (public-key encrypted) AES key from the remote system's firmware along with a signature (issued by the remote system's trusted firmware key). On the local system we would pass the packet with the encrypted AES key and signature to the firmware, decrypt the key with the firmware's private key and verify the signature to ensure that it comes from a trusted target (firmware better keep signing keys at a kernel-inaccessible place) and we would do swtpm migration by sending TPM data (encrypted?) to the firmware and then pass the firmware-encrypted data to QEMU for migration. On the receiving end we would then decrypt the TPM's state via the firmware again.

Further, a cloud user for example would have to be sure that migration is actually occurring in the way as described and would also have to be sure that an encryption key for swtpm's state is used so that the state of the TPM remains hidden from the host administrator. Attestation of each cloud host's full software stack and knowing all its components' hashes may be a solution. However, where does swtpm's AES key come from so that the host administrator can never decrypt the state file?

Releases

Swtpm releases occur in irregular intervals whenever a set of features warrants a new release. For every release there will be a stable branch, such as for example the v0.2.0 release (git tag) has a stable-0.2.0 git branch to which bug fixes are applied related to bugs found in v0.2.0. If you find a problem in a release version, first try to checkout the code from the stable branch and see whether the problem has already been fixed. Otherwise, file an issue on github along with a description of what the problem is and if you have a patch already, you may send a PR.

Compile and install on Linux

# Install dependencies using dnf (RHEL, Fedora)
sudo dnf -y install libtasn1-devel tpm-tools expect socat python3-twisted fuse-devel glib2-devel gnutls-devel gnutls-utils gnutls
./autogen.sh --with-openssl --prefix=/usr
make -j4
# Depending on how many CPUs you have, choose the -j parameter 
# carefully for the next command. The tests work on Raspberry PI 2
# for example but only if run with '-j1', otherwise timeouts may
# occur.
make -j4 check
sudo make install

Build a 32 bit version on x86_64 (for testing)

This requires that libtpms has also been compiled for 32bit.

PKG_CONFIG_PATH=/usr/lib/pkgconfig/ CFLAGS="-m32" ./autogen.sh --with-openssl --prefix=/usr --libdir=/lib
make clean
make -j4
make -j4 check
sudo make install

Compile and install on Cygwin

./autogen.sh --with-openssl --prefix=/usr --with-tss-user=<your username> --with-tss-group=None
make -j4
make -j4 check
make install

Compile and install on OpenBSD

./autogen.sh --with-openssl --prefix=/usr --without-cuse --with-tss-user=root --with-tss-group=wheel
gmake -j 4
# the following solves lazy linking problem...
sudo gmake install
gmake check
sudo gmake install

Compile on OS X

# Not familiar with this platform...; libtpms was installed into /User/adminuser/lib
brew install socat gawk gnutls [...]
brew tap discoteq/discoteq
brew install flock
LDFLAGS="-L/usr/local/opt/openssl/lib -L/Users/adminuser/lib" CFLAGS="-I/usr/local/opt/openssl/include -I/Users/adminuser/include -O2" CC=gcc PKG_CONFIG_PATH=/Users/adminuser/lib/pkgconfig/ ./autogen.sh --prefix=/Users/adminuser/ --with-openssl --with-tss-user=adminuser --with-tss-group=adminuser
make -j4
make -j4 check

Build Deb package (Ubuntu, Debian)

# At this point libtpms library and development packages should be installed.
# There should be no libtpms installed in /lib or /lib64 since this may create problems
# when dh_shlibdeps tries to determine package dependencies
sudo apt-get -y install  libfuse-dev libglib2.0-dev libgmp-dev expect libtasn1-dev socat tpm-tools python3-twisted gnutls-dev gnutls-bin
dpkg-buildpackage -us -uc -j$(nproc)

Build on RHEL 6

RHEL 6 doesn't have a recent version of gnutls and therefore won't be able to build swtpm_cert and the EK and platform certificates cannot be created. Install python3 and then configure it as follows:

 scl enable rh-python35 bash
 # libtpms was configured with --libdir=/lib64
 CFLAGS="-O1" PKG_CONFIG_PATH=/lib64/pkgconfig/ ./autogen.sh --prefix=/usr --libdir=/lib64 --without-selinux