This is a quick set of instructions to build, install and run the tpm2-abrmd.
To build and install the tpm2-abrmd software the following dependencies are required:
- GNU Autoconf
- GNU Autoconf archive
- GNU Automake
- GNU Libtool
- C compiler
- C Library Development Libraries and Header Files (for pthreads headers)
- pkg-config
- glib and gio 2.0 libraries and development files
- libtss2-sys, libtss2-mu and TCTI libraries from https://github.com/tpm2-software/tpm2-tss
- dbus
NOTE: Different GNU/Linux distros package glib-2.0 differently and so additional packages may be required. The tabrmd requires the GObject and GIO D-Bus support from glib-2.0 so please be sure you have whatever packages your distro provides are installed for these features.
The following dependencies are required only if the test suite is being built and executed.
- cmocka unit test framework
- swtpm or tpm_server TPM2 simulator
- Alternately, run the test suite on a real TPM hardware, with a safety attention described below.
tpm2-abrmd
must run as user tss
or root
.
As is common security practice we encourage everyone to run the tpm2-abrmd
as an unprivileged user. This requires creating a user account and group to
use for this purpose. Our current configuration assumes that the name for this
user and group is tss
per the norm established by the trousers
TPM 1.2
software stack.
This account and the associated group must be created before running the
daemon. The following command should be sufficient to create the tss
account:
$ sudo useradd --system --user-group tss
You may wish to further restrict this user account based on your needs. This topic however is beyond the scope of this document.
To run tpm2-abrmd as root, which is not recommended, use the --allow-root
option.
As is always the case, you should check for packages available through your Linux distro before you attempt to download and build the tpm2-abrmd from source code directly. If you need a newer version than provided by your Distro of choice then you should download our latest stable release here: https://github.com/01org/tpm2-abrmd/releases/latest.
The latest unstable development work can be obtained from the Git VCS here: https://github.com/01org/tpm2-abrmd.git. This method should be used only by developers and should be assumed to be unstable.
The remainder of this document assumes that you have:
- obtained the tpm2-abmrd source code using a method described above
- extracted the source code if necessary
- set your current working directory to be the root of the tpm2-abrmd source tree
If you're looking to contribute to the project then you will need to build from the project's git repository. Building from git requires some additional work to "bootstrap" the autotools machinery. This is accomplished by executing the `bootstrap script:
$ ./bootstrap
If you're building from a release source tarball you should skip this step.
The source code for must be configured before the tpm2-abrmd can be built. In the most simple case you may run the `configure script without any options:
$ ./configure
If your system is capable of compiling the source code then the configure
script will exit with a status code of 0
. Otherwise an error code will be
returned.
In many cases you'll need to provide the ./configure
script with additional
information about your environment. Typically you'll either be telling the
script about some location to install a component, or you'll be instructing
the script to enable some additional feature or function. We'll cover each
in turn.
Invoking the configure script with the --help
option will display
all supported options.
The default values for GNU installation directories are documented here: https://www.gnu.org/prep/standards/html_node/Directory-Variables.html
The tpm2-abrmd
claims a name on the D-Bus system bus. This requires policy
to allow the tss
user account to claim this name. By default the build
installs this configuration file to ${sysconfdir}/dbus-1/system.d
. We allow
this to be overridden using the --with-dbuspolicydir
option.
Using Debian (and it's various derivatives) as an example we can instruct the build to install the dbus policy configuration in the right location with the following configure option:
--with-dbuspolicydir=/etc/dbus-1/system.d
In most configurations the tpm2-abrmd
daemon should be started as part of
the boot process. To enable this we provide a systemd unit as well as a
systemd preset file.
By default the build installs this file to `${libdir}/systemd/system. Just like D-Bus the location of unit files is distro specific and so you may need to configure the build to install this file in the appropriate location.
Again using Debian as an example we can instruct the build to install the systemd unit in the right location with the following configure option:
--with-systemdsystemunitdir=/lib/systemd/system
By default the build installs the systemd preset file for the tabrmd to
${libdir}/systemd/system-preset
. If you need to install this file to a
different directory pass the desired path to the configure
script using this
option. For example:
--with-systemdpresetdir=/lib/systemd/system-preset
The systemd preset file will enable the tabrmd by default, causing it to be
started by systemd on boot. If you wish for the daemon to be disabled by
default some reason you may use this option to the configure
script to do
so.
To override the system data directory, used for
${datadir}/dbus-1/system-services/com.intel.tss2.Tabrmd.service,
use the --datarootdir
option.
Using Debian as an example we can instruct the build to install the
DBUS service files in the right location with the following configure option:
--datarootdir=/usr/share
When provided to the ./configure
script this option will attempt to detect
whether or not the cmocka unit testing library is installed. If not then the
configure step will fail. If it is available then the unit tests will be
enabled in the build and they will be built and executed as part of the test
harness:
$ ./configure --enable-unit
If the ./configure
script finds the cmocka framework then executing make check
will cause the unit tests to be built and executed.
In addition to unit tests we provide a collection of integration tests.
Integration tests differ from unit tests in that they require a running
instance of the tpm2-abrmd
daemon. Integration tests exercise a specific
behavior of the tpm2-abrmd
and ensure that the daemon behaves as expected.
In order for the tpm2-abrmd
daemon to run it must have a TPM2 device to
talk to. This can be done in two ways:
- Using an implementation of the TPM2 in software the TPM2 device can be
simulated. This is the most flexible, fast and safest way to test the
tpm2-abrmd
. - Using the TPM2 device on your computer (if it has one). This method is NOT recommended and may cause damage / wear-out of the TPM and its resources. This option is provided for developers and integrators who know what they're doing and who understand the associated risks: You have been warned.
The next two subsections describe these two configurations:
If the configure script is passed the --enable-integration
option then the
test harness will execute the integration tests against the software TPM2
simulator. The configure script will check for the existance of one of the
software TPM2 simulator executables swtpm
or tpm_server
on the PATH. An
instance of the simulator will be created for each test executable to allow the
parallel execution of test cases.
This is the recommended integration test configuration. It requires that you
first download and compile the TPM2 software simulator as documented by the
simulators' maintainers. Once you have swtpm
or tpm_server
built, you must
ensure that it is discoverable via the PATH environment variable when the
./configure
script is run.
It's possible to run the integration tests against "real" TPM2 hardware, not just against the simulator. This does however come with some restrictions. Firstly your TPM2 hardware must be properly initialized by your platform and the kernel properly configured to load the appropriate driver. How to do all of this is beyond the scope of this document and so we assume the reader has already done this.
Once your TPM2 hardware is all set up you may configure tpm2-abrmd build to
run the integration tests against the TPM2 device by passing the
./configure
script the --enable-test-hwtpm
option:
$ ./configure --enable-test-hwtpm
Providing this option will enable the integration tests much like the
--enable-integration
but the configure script will not check for the
simulator executable.
The test harness can then be run with the typical make check
though there
are some limitations due to the use of the hardware TPM:
- The test harness does not support parallel execution of tests in this configuration. When each test is executed a fresh instance of the daemon is started and since there's only one instance of the TPM2 device.
- The tests must be executed as a privileged user. This is required as the
daemon will interact with the TPM2 device through the
/dev/tpm0
device node and access to it typically requires elevated privileges. The easiest approach, which is also the most risky, is to run tests in this configuration as theroot
user. - To simplify the test harness in this configuration the tpm2-abrmd is run on the DBus system bus (it's run on the session bus when tests are executed against the simulator) and the default DBus name for the daemon (com.intel.tss2.Tabrmd) is used. This implies that any existing instance of the daemon that may have been started when your system boots must be stopped before the test harness can run tests against your TPM hardware.
Finally executing tests against real TPM2 hardware is exponentially slower than running them against the software simulator. People often refer to the TPM2 as a "crypto decelerator" for a reason :) As such we recommend that tests be executed individually until you're confident your configuration works as expected. An example follows:
sudo make check TESTS=test/integration/auth-session-start-flush.int
This example runs only the auth-session-start-flush.int
test which isn't
particularly compute-intensive since it doesn't create any keys or carry out
any signing or encryption operations other than those done by the TPM2
device as part of its session management operations.
WARNING: If this test suite is executed against a TPM2 it may result in the TPM2 device being damaged or destroyed. You have been warned ... again.
Compiling the code requires running make
. You may provide make
whatever
parameters required for your environment (e.g. to enable parallel builds) but
the defaults should be sufficient:
$ make
Once successfully built the tpm2-abrmd
daemon it should be installed using
the command:
$ sudo make install
This will install the executable to locations determined at configure time.
See the output of ./configure --help
for the available options. Typically
you won't need to do much more than provide an alternative --prefix
option
at configure time, and maybe DESTDIR
at install time if you're packaging
for a distro.
NOTE: It may be necessary to run ldconfig (as root) to update the run-time bindings before executing a program that links against the tabrmd library:
$ sudo ldconfig
After installing the compiled software and configuration all components with new configuration (Systemd and D-Bus) must be prompted to reload their configs. This can be accomplished by restarting your system but this isn't strictly necessary and is generally considered bad form.
Instead each component can be instructed to reload its config manually. The following sections describe this process for each.
The dbus-daemon will also need to be instructed to read this configuration
file (assuming it's installed in a location consulted by dbus-daemon) before
the policy will be in effect. This is typically accomplished by sending the
dbus-daemon
the HUP
signal like so:
$ sudo pkill -HUP dbus-daemon
If this doesn't work on your distro please consult your distro's documentation for DBUS-DAEMON(1).
Assuming that the tpm2-abrmd
unit was installed in the correct location for
your distro Systemd must be instructed to reload it's configuration. This is
accomplished with the following command:
$ systemctl daemon-reload
Once systemd has loaded the unit file you should be able to use systemctl
to perform the start / stop / status operations as expected. Systemd should
also now start the daemon when the system boots.
On systems using SELinux (for example, check with the getenforce
utility) the
default service policy is too restrictive. The repository contains an SELinux
policy module which, when applied as below, allows the daemon to operate on
systems with SELinux in enforcing mode.
First, ensure SELinux policy development files are installed (i.e on Fedora they
can be installed with dnf install selinux-policy-devel
).
Then build and install the policy module:
$ pushd selinux
$ make -f /usr/share/selinux/devel/Makefile tabrmd.pp
$ sudo semodule -i tabrmd.pp
$ sudo restorecon /path/to/installed/tpm2-abrmd
Once the module is installed you can ensure the daemon is correctly labelled by checking with:
$ ls -Z /path/to/installed/tpm2-abrmd
system_u:object_r:tabrmd_exec_t:s0 /usr/local/sbin/tpm2-abrmd
Once the tpm2-abrmd
installed and running it's possible to query the
dbus-daemon to see evidence of its presence. The following command will list
all names on the system bus. We filter for the expected name to keep the
output manageable:
dbus-send --system --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames
that should return output like:
method return time=1524690245.245721 sender=org.freedesktop.DBus -> destination=:1.190 serial=3 reply_serial=2
array [
...
string "com.intel.tss2.Tabrmd"
...
]
This lets us know that the daemon has claimed the expected name on the system bus, but for many this isn't enough. How do we know that the daemon isn't hung / unresponsive? The most simple way to do this is to use the 'introspection' interface to query the daemon for the functions / methods that it supports. Every dbus daemon supports this interface:
dbus-send --system --dest=com.intel.tss2.Tabrmd --type=method_call --print-reply /com/intel/tss2/Tabrmd/Tcti org.freedesktop.DBus.Introspectable.Introspect
that should return output like:
method return time=1524690897.749245 sender=:1.192 -> destination=:1.193 serial=7 reply_serial=2
string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!-- GDBus 2.50.3 -->
<node>
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg type="s" name="interface_name" direction="in"/>
<arg type="s" name="property_name" direction="in"/>
<arg type="v" name="value" direction="out"/>
</method>
<method name="GetAll">
<arg type="s" name="interface_name" direction="in"/>
<arg type="a{sv}" name="properties" direction="out"/>
</method>
<method name="Set">
<arg type="s" name="interface_name" direction="in"/>
<arg type="s" name="property_name" direction="in"/>
<arg type="v" name="value" direction="in"/>
</method>
<signal name="PropertiesChanged">
<arg type="s" name="interface_name"/>
<arg type="a{sv}" name="changed_properties"/>
<arg type="as" name="invalidated_properties"/>
</signal>
</interface>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg type="s" name="xml_data" direction="out"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Peer">
<method name="Ping"/>
<method name="GetMachineId">
<arg type="s" name="machine_uuid" direction="out"/>
</method>
</interface>
<interface name="com.intel.tss2.TctiTabrmd">
<method name="CreateConnection">
<arg type="ah" name="fds" direction="out"/>
<arg type="t" name="id" direction="out"/>
</method>
<method name="Cancel">
<arg type="t" name="id" direction="in"/>
<arg type="u" name="return_code" direction="out"/>
</method>
<method name="SetLocality">
<arg type="t" name="id" direction="in"/>
<arg type="y" name="locality" direction="in"/>
<arg type="u" name="return_code" direction="out"/>
</method>
</interface>
</node>
"