Skip to content
Maxime Dufour edited this page Oct 9, 2023 · 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.

For user discussions, please subscribe to the swtpm-user 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.

My public GPG Key

Here's my public GPG key you can use for verifying signed tags and releases:

-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBFnVA4YBCAD3fs+WUzvB6OPoj0HhvBlemEV6I8AcDwZHCNvA4UMc03sSVl/Q
tDr4WuZd1v9utvi0xHjsTHbF1ndsgNkNzisvTIBHptcxw+Z3+VskOl3GTsfiKG22
OfZJsdXfhjYW/Oezl2IVy6/QqOV0JeEtV3J10gCHR/5PKhOy+pP/8jlw3EA8GYtY
ojM4znfEXHh6vx//hbf8FVMlVcKwUKHB1zHhM5jF9Kx4ZLU8rYHkMiXXbzdWBkCa
L6E2P2T01hQ1wPpowU9aL/zLt7ISiKMcYLvZJYcgX3quPVSXJRG+y3q3lXv1IOrV
HoGJLdkNu/0bLJoeNBFXiEGs7+tfk4XAjBTTABEBAAG0KlN0ZWZhbiBCZXJnZXIg
PHN0ZWZhbmJAbGludXgudm5ldC5pYm0uY29tPokBPgQTAQIAKAUCWdUDhgIbAwUJ
EswDAAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQda1lgCoLQhENQQf/XmyD
zWL5VSAKbDKcpI5t0PjiC/Brrs1xNtKLht5le4UdhAH6e/y+3H6lhoJCNbHGBE7r
cAM/LVv8MT+4WXhLvRDUkn6Z5cSiMx0ANWDABCHGI3+z2imqI5XjB5fwFq2FIRdu
MUhWRhxSYHDd4E0BN2FvHNUhqm60QlLCrH9zjar8XcJQ1lnDgcSDP9EWENZizYW9
W5DKFiWR4vMXU0lvDpAYyDR1EU4pfnoMDc/19MoI3oR+wP0ELXI52CG0w4Lcs+Y5
8ywb0/El789qRTNQG6bPcZYx6KrRNq8KSrtNY20ID2tyM4boRQ412mD87x/kNWqU
CHklMi79wKcJ7OA73g==
=l1ZJ
-----END PGP PUBLIC KEY BLOCK-----

Compile and install on Linux

# Install dependencies using dnf (RHEL, Fedora)
sudo dnf -y install libtasn1-devel expect socat python3-twisted fuse-devel glib2-devel gnutls-devel gnutls-utils gnutls json-glib-devel
./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 automake libtpms json-glib [...]
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
LC_ALL=C make -j4 check

Compile on Ubuntu (21.04)

sudo apt-get install dh-autoreconf libssl-dev \
     libtasn1-6-dev pkg-config libtpms-dev \
     net-tools iproute2 libjson-glib-dev \
     libgnutls28-dev expect gawk socat \
     libseccomp-dev make -y
./autogen.sh --with-openssl --prefix=/usr
make -j4
make -j4 check
sudo make install

Build Deb package (Ubuntu, Debian)

# At this point libtpms library and development packages MUST be installed.
mk-build-deps -i
# if mk-build-deps creates issues, try this:
sudo apt-get -y install dpkg-dev debhelper libssl-dev libtool net-tools libfuse-dev libglib2.0-dev libgmp-dev expect libtasn1-dev socat python3-twisted gnutls-dev gnutls-bin  libjson-glib-dev python3-setuptools softhsm2 libseccomp-dev gawk libtpms-dev
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

Compile and install on openSUSE (Tumbleweed)

 sudo zypper install -y socat net-tools-deprecated libtasn1-devel gnutls gnutls-devel libseccomp-devel json-glib-devel expect softhsm openssl-devel automake autoconf libtool gcc pkg-config make libtpms-devel
 # we have to created tss group and user
 sudo zypper install system-user-tss
 # tcsd requires that its files be user/group root/tss, so configure swtpm this way
 ./autogen.sh --prefix=/usr --libdir=/usr/lib64 --with-openssl --with-tss-user=root --with-tss-group=tss
 make -j4
 sudo make check -j4
 sudo make install

Compile and install on Alpine

 sudo apk add socat gawk libtasn1-dev gnutls gnutls-utils gnutls-dev expect python3 libseccomp-dev json-glib-dev
 # for simplicity reasons using root/root for tss-user/tss-group
 ./autogen.sh --prefix=/usr --libdir=/usr/lib --with-openssl --with-tss-user=root --with-tss-group=root
 make -j4
 sudo make check -j4
 sudo make install