The tss2-fapi-rs
Rust crate provides an interface to the TCG TSS 2.0 Feature API (FAPI).
Architectural overview:
The current version of the API does not offer any security or code safety guarantees. The implementation that is provided is suitable for exploratory testing and experimentation only. This test implementation does not offer any tangible security benefits and therefore is not suitable for use in production. Documentation pages may be incomplete and are subject to change without notice. Interfaces may change in such a way as to break compatibility with client code.
The following example illustrates how to use the TSS 2.0 FAPI in Rust:
use env_logger::Builder as EnvLogger;
use log::{error, info, warn, LevelFilter};
use std::num::NonZeroUsize;
use tss2_fapi_rs::FapiContext;
fn main() {
// Initialize the logger
EnvLogger::new().filter_level(LevelFilter::Info).init();
// Create a new FAPI context
info!("Creating FAPI context, please wait...");
let mut context = match FapiContext::new() {
Ok(fpai_ctx) => fpai_ctx,
Err(error) => panic!("Failed to create context: {:?}", error),
};
// Perform the provisioning, if it has not been done yet
info!("Provisioning, please wait...");
match context.provision(None, None, None) {
Ok(_) => info!("Success."),
Err(error) => warn!("Provisioning has failed: {:?}", error),
}
// Generate random
info!("Generating random data...");
for _i in 0..8 {
match context.get_random(NonZeroUsize::new(32).unwrap()) {
Ok(random) => info!("Random data: {}", hex::encode(&random[..])),
Err(error) => error!("get_random() failed: {:?}", error),
}
}
}
In this example, it is assumed that a valid FAPI configuration has already been set up on the target system.
Please see the FapiContext
documentation for more details!
Various use-cases of the FAPI require implementing and installing callback functions, for example:
use std::borrow::Cow;
use log::info;
use tss2_fapi_rs::{FapiContext, AuthCallback, AuthCallbackParam};
fn main() {
// Create a new FAPI context
let mut context = FapiContext::new().expect("Failed to create context!");
// Set up "auth" callback function
match context.set_auth_callback(AuthCallback::new(my_auth_func)) {
Ok(_) => info!("Callback installed."),
Err(error) => panic!("Failed to install callback: {:?}", error)
}
}
// Application-defined callback function
fn my_auth_func(param: AuthCallbackParam) -> Option<Cow<'static, str>> {
info!("Auth value for {:?} requested!", param.object_path);
Some(Cow::from("my password"))
}
In order to use the tss2-fapi-rs
library in your Rust project, simply add it to your Cargo.toml
file:
[dependencies]
tss2-fapi-rs = "0.5.3"
Note: Please also consider the prerequisites that are required to use the tss2-fapi-rs
library!
In order to build tss2-fapi-rs
from the sources, run the following command in the project root directory:
$ cargo build --release
Alternatively, the provided Makefile
, in the project root directory, may be invoked for building the library:
$ make build
Note: Please also consider the prerequisites that are required to build the tss2-fapi-rs
library!
Building tss2-fapi-rs
in the fully self-contained Docker environment (see below) has the advantage that the library can be built without the need to install any of the prerequisites – except for Docker and the Compose V2 plug-in – on the “host” system.
With Docker Compose V2 installed, simply run the following make
command in the project root directory:
$ make docker.build
Some examples demonstrating how to use the tss2-fapi-rs
library are provided in the examples
sub-directory.
In order to build and run an example, simply run the following command in the project root directory:
$ cargo run --example <example_name>
Note: Please also consider the prerequisites that are required to use the tss2-fapi-rs
library!
An example FAPI configuration is provided in the examples/data
sub-directory. It can be applied as follows:
Copy the configuration files to the “home” directory:
$ mkdir ~/my-fapi-config
$ cp -r examples/data/* ~/my-fapi-config
Run the example with the desired FAPI configuration:
$ TSS2_FAPICONF=~/my-fapi-config/fapi-config.json cargo run --example [...]
The following prerequisites are required for building or using the tss2-fapi-rs
library:
The native libtss2‑fapi
library, version 3.2.0 or later, and its associated header files must be available:
On Ubuntu 22.04 (Jammy), Debian 12.0 (Bookworm) or later:
libtss2-dev
package.uuid-dev
, libjson-c-dev
, libcrypt-dev
and libcurl4-openssl-dev
On older OS versions or other platforms:
Note: By default, the native FAPI library is detected automatically, using the pkg-config utility. If the required metadata file tss2-fapi.pc
can not be found, please set or update your PKG_CONFIG_PATH
as needed! Alternatively, the location of the native FAPI library and its associated header files can be specified explicitly via the environment variables described below.
A working C compiler (cc
) is required for Rust/Cargo to build some of the required dependencies.
On Ubuntu 22.04 (Jammy), Debian 12.0 (Bookworm) or later, it can be installed via the build-essential
package.
Rust’s bindgen
tool requires that libclang
is available on the system.
On Ubuntu 22.04 (Jammy), Debian 12.0 (Bookworm) or later, it can be installed via the libclang-dev
package.
The following environment variables may specify the location of the native FAPI library during the build process:
TSS2_INCLUDE_PATH
Location of the TSS 2.0 header files. If specified, this path shall contain the tss2_fapi.h
header file.
This variable must be set in conjunction with TSS2_LIBRARY_PATH
to be effective!
TSS2_LIBRARY_PATH
Location of the TSS 2.0 library files. If specified, this path shall contain the libtss2-fapi.so
file.
This variable must be set in conjunction with TSS2_INCLUDE_PATH
to be effective!
TSS2_LIBRARY_VERS
Version of the TSS 2.0 library. If specified, the version string shall have the "major.minor.patch"
format.
The following environment variables can be used to control the runtime behavior:
LD_LIBRARY_PATH
Integration tests for all the supported FAPI functions are provided in the tests
sub-directory.
These tests also serve as additional usage examples for the respective functions.
In order to execute the integration tests, simply run the following command in the project root directory:
$ cargo test --release [<test_name>]
If a test name is not specified, then all available (non-ignored) tests will be executed.
Alternatively, the provided Makefile
, in the project root directory, may be invoked for running the tests:
$ make tests
The integration tests require that a working TPM is available. Using a TPM emulator is recommended for testing!
The Software TPM Emulator (SWTPM) created by Stefan Berger can be used testing purposes:
https://github.com/stefanberger/swtpm
In order to use the SWTPM, the TCTI needs to be configured as follows, specifying the proper IP address and port number:
$ export FAPI_RS_TEST_TCTI="swtpm:host=<ip-address>,port=<port-number>"
A fully self-contained Docker Compose (V2) setup for running the tests, based on SWTPM, is provided at tools/docker
.
The following prerequisites are required for using the Docker environment:
On Ubuntu 22.04 (Jammy) or later:
docker-compose-v2
package.On Debian 12.0 (Bookworm) or later:
docker-ce
, docker-ce-cli
, containerd.io
and docker-compose-plugin
.With Docker Compose V2 installed, you can run the following make
commands in the project root directory:
Runs the test suite completely in the Docker environment:
$ make docker.tests
Starts just the SWTPM container, e.g. if you want to run cargo test
natively:
$ make docker.swtpm
As a more lightweight alternative to SWTPM, the integration tests may also be run using the libtpms library:
https://github.com/stefanberger/libtpms
On Ubuntu 24.04 (Noble), Debian 12.0 (Bookworm) or later, libtpms can be installed via the libtpms-dev
package.
In order to use the libtpms library, the TCTI needs to be configured as follows:
$ export FAPI_RS_TEST_TCTI="libtpms:tpm_state.dat"
Be aware that it is necessary to save the state to the filesystem by specifying a file name when using libtpms for testing!
With the libtpms installed, you can run the following make
commands in the project root directory:
$ make libtpms
The following environment variables can be set as needed:
FAPI_RS_TEST_TCTI
The TCTI connection string to be used for testing. By default, swtpm:host=127.0.0.1,port=2321
is used.
See also: https://github.com/tpm2-software/tpm2-tss/blob/master/doc/tcti.md
FAPI_RS_TEST_PROF
The FAPI profile to be used for testing. By default, RSA2048SHA256
is used. May be set to ECCP256SHA256
.
FAPI_RS_TEST_LOOP
The number of times to repeat each test. Default is 3.
RUST_LOG
Controls the logging level. Set to, for example, debug
in order to enable additional logging outputs.
TSS2_LOG
Controls the logging level of the underlying native TSS2 libraries. This can be set to all+none
in order to silence all outputs from the native TSS2 libraries. It can also be set all+debug
in order to enable some additional debug outputs.
LD_LIBRARY_PATH
On Linux/Unix systems, this can be set to control the location to load the native libtss2-fapi.so
library from. This is useful if you want to test with a “custom” build of tpm2-tss
instead of using the version provided by the operating system.
The integration tests automatically create and use a temporary FAPI configuration. It is generated from the template at:
tests/data/fapi-config.json.template
The FAPI profiles that are intended to be used by the integration tests are stored at:
tests/data/profiles/*.json
Error message:
pkg_config: Required library "tss2-fapi" not found!
The system library `tss2-fapi` required by crate `tss2-fapi-rs` was not found.
Solution:
The native TSS 2.0 FAPI library, or one of its dependencies, can not be found by pkg-config
. Please make sure that the required library and all of its dependencies are installed! If the tss2-fapi.pc
resides at a non-standard location, set PKG_CONFIG_PATH
accordingly. Also, the command pkg-config --libs tss2-fapi
may be useful for debugging.
Error message:
error: linker `cc` not found
note: No such file or directory (os error 2)
Solution:
The C compiler could not be found. Please install a working C compiler (e.g. gcc
or clang
) and then try again.
Error message:
error: failed to run custom build command for `tss2-fapi-rs`
Unable to generate bindings: "fatal error: 'tss2_fapi.h' file not found"
Solution:
The header file for the native TSS 2.0 FAPI library is missing. Make sure that the native TSS 2.0 FAPI library and its header files are installed. If the tss2_fapi.h
is installed at a non-standard location, set TSS2_INCLUDE_PATH
as needed.
Be aware that the “include” directory shall contain a sub-directory named tss2
containing the actual tss2_fapi.h
file.
Error message:
error: failed to run custom build command for `tss2-fapi-rs`
Unable to generate bindings: "fatal error: 'stddef.h' file not found"
Solution:
The C Standard Library header files can not be found. This usually indicates an incomplete/broken installation of the Clang compiler, as used by Rust’s bindgen
tool. Can be fixed, e.g., by (re)installing the clang
or libclang-dev
package.
Error message:
error: linking with `cc` failed: exit status: 1
/usr/bin/ld: cannot find -ltss2-fapi: No such file or directory
Solution:
The native TSS 2.0 FAPI library is missing. Make sure that the native TSS 2.0 FAPI library is actually installed (or has been built from the sources). If the libtss2-fapi.so
resides at a non-standard location, set TSS2_LIBRARY_PATH
as needed.
Error message:
error: failed to run custom build command for `tss2-fapi-rs`
Unable to find libclang: "couldn't find any valid shared libraries matching ..."
Solution:
Indicates that Rust’s bindgen
tool was unable to load the required Clang library. This is usually fixed, e.g., by installing the libclang-dev
package. If the libclang.so
resides at a non-standard location, set LIBCLANG_PATH
as needed.
Error message:
error while loading shared libraries: libtss2-fapi.so.1:
cannot open shared object file: No such file or directory
Solution:
The native TSS 2.0 FAPI library could not be loaded at runtime. Make sure that the native TSS 2.0 FAPI library is actually installed, and that it is located in one of the directories where the dynamic linker/loader is looking for shared libraries. If the libtss2-fapi.so.1
resides at a non-standard location, you may update the LD_LIBRARY_PATH
as needed.
Error message:
ERROR:tcti:src/tss2-tcti/tcti-swtpm.c:617:Tss2_Tcti_Swtpm_Init()
Cannot connect to swtpm TPM socket
Failed to create context: OtherError(IoError)
Failed to connect to the software TPM! Is the software TPM running?
Connection refused
Solution:
If this message appears at runtime, e.g. when trying to run the test cases, it indicates that the connection to the software TPM could not be established. Make sure that the software TPM is actually running and ready for incoming connections! One simple way to get a running software TPM is by using the Docker environment provided in the etc/docker/swtpm
directory.
Error message:
socket_connect() Failed to connect to host 10.0.0.1, port 2321:
errno 99: Cannot assign requested address
Solution:
The native TSS 2.0 FAPI library was unable to connect to the software TPM. This error may occur, after some time, when too many TPM commands are sent to the software TPM at a high rate. There currently is no known solution, but a possible workaround is to simply slow down the sequence of TPM commands, e.g., by adding an artificial delay after each command. Furthermore, adding the disconnect
option to the SWTPM --server
parameter seems to attenuate the problem.
The tss2-fapi-rs
source code can be found at the official GitHub repository:
https://github.com/tpm2-software/rust-tss-fapi/
For bug reports, feature requests, etc., please refer to the issue tracker at:
https://github.com/tpm2-software/rust-tss-fapi/issues/
Security vulnerabilities should be emailed to all members of the MAINTAINERS file.
Copyright 2024, Fraunhofer SIT sponsored by the ELISA research project
All rights reserved.
This work is released under the 3-Clause BSD License (SPDX short identifier: BSD-3-Clause
).
ActnCallback
callback.AuthCallback
callback.BranCallback
callback.FAPI_CONTEXT
and exposes the related FAPI functions.SignCallback
callback.get_esys_blob()
function.FapiContext
struct.create_key()
function.create_nv()
function.sign()
function.quote()
function.create_seal()
function.tss2-fapi-rs
library.