This is Barkhausen Institut's prototype integration of remote attestation with Transport Layer Security.
The background of this project is described in the following research paper:
Carsten Weinhold, Muhammad Usama Sardar, Ionuț Mihalcea, Yogesh Deshpande, Hannes Tschofenig, Yaron Sheffer, Thomas Fossati, Michael Roitzsch, Separate but Together: Integrating Remote Attestation Into TLS, 2025 USENIX Annual Technical Conference (ATC'25), July 7-9, 2025, Boston, MA, USA
The paper describes how remote attestation (RA) can be integrated with the Transport Layer Security (TLS) protocol. The focus is on minimizing protocol overhead by performing the RA exchange and the TLS handshake in parallel. TLS and RA are cryptographically linked in such a way that their respective security properties are additive. The linking mechanism ensures that the TLS channel terminates in the TEE that is being attested. TLS and RA can also fail independently: If the TLS root-of-trust is compromised, the security guarantees of the RA root-of-trust should still remain intact and vice versa (under assumption stated in the threat model in paper).
This project includes the source code of a prototype implementation of the approach. Build scripts for compiling the source code are included. The research prototype described in the paper has been developed by the Composable Operating Systems group at Barkhausen Institut in Dresden, Germany.
Contact authors: Carsten Weinhold carsten.weinhold@barkhauseninstitut.org, Michael Roitzsch michael.roitzsch@barkhauseninstitut.org
To clear a potential confusion: In the paper, the approach for combining RA and TLS is named TLS+RA to express that the RA and TLS protocols are combined in such a way that their security properties are additive. However, in the code, we call it RATLS or ratls, because this is the name we chose when we started the research. We use "RATLS" from here on.
Note: Standard Linux development tools are required. Due to the large
variety of Linux distributions, we cannot provide a comprehensive list. On a
default installation of Ubuntu, it seems sufficient to install the
build-essential and libtool packages for building RATLS and its
dependencies.
The RATLS prototype is built on top of OpenSSL. A copy of OpenSSL (old version 1.1.1m) is included, along with further dependencies. They have to be compiled and installed (in a private install directory) first. To do so, run the following command from the top-level directory:
make bootstrap
Then build RATLS, including a client and server programs:
make
The test client and server programs are dynamically linked against .so files in the install directory. Therefore, the LD_LIBRARY_PATH environment variable has to be set accordingly. Start the server program in its own terminal as follows:
export LD_LIBRARY_PATH=$PWD/install/lib
./build/ratls/ratls-test-server --local-rot cca:none --remote-rot cca:none --local-state none --remote-state cca-dummy
This will start an RATLS-enabled server listening on TCP port 4433. In this example, the server is told to use a dummy plugin for generating and verifying attestations reports. We use a dummy plugin in this example, because it will "work" on any machine by essentially doing nothing; it ships creates and "verifies" dummy data that RATLS will ship around in TLS message extensions. That is, the dummy plugin can be used demonstrate the workflow without having to do any TEE or RoT setup.
Note: We explain below, why cca is a dummy plugin in this release.
The plugins to be used for the local (server) side and expected (dummy)
attestation state are specified using the --local-* command-line switches.
The server expects the client to use the dummy plugin, too (--remote-*
parameters). When the server is running, start the client program in its own
terminal, also with the corresponding plugins selected for local and remote
root-of-trust and expected (dummy) attestation state:
export LD_LIBRARY_PATH=$PWD/install/lib
./build/ratls/ratls-test-client --local-rot cca:none --remote-rot cca:none --local-state none --remote-state cca-dummy --server-address 127.0.0.1
The server will output something like this:
starting server on port 4433
[INFO: 416] Server, App: Waiting for incoming connection
[INFO: 875] Server, ParseExt - ClientHello: Got remote attestation request from client
[INFO: 243] Server, getBinderSecret: SSL_export_handshake_secret_nostd: 1
[INFO: 244] Server, getBinderSecret: binder_secret=22b436b8b602b1651ac19db5bb787df1f96eada1484ac2b6a25d6fc43e21f3fe...
[INFO: 314] Server, AddExt - Certificate: 48 bytes binderSecret=22b436b8b602b1651ac19db5bb787df1f96eada1484ac2b6a25d6fc43e21f3fe...
[INFO: 812] Server, AddExt - Certificate: Attesting to client
[INFO: 956] Server, ParseExt - Certificate: Client responded with quote
[INFO: 314] Server, VerifyCert: 48 bytes binderSecret=22b436b8b602b1651ac19db5bb787df1f96eada1484ac2b6a25d6fc43e21f3fe...
[INFO: 993] Server, VerifyCert: expectedNonce=22b436b8b602b1651ac19db5bb787df1f96eada1484ac2b6a25d6fc43e21f3fe...
[INFO: 1002] Server, VerifyCert: Clients quote checked. OK!
[INFO: 416] Server, App: Waiting for incoming connection
The server will keep running, waiting for the next connection from a client.
The server can also be told to exit after the first connection by adding
--one-shot on its command line.
The client will output something like this:
[INFO: 357] Client, AddExt - ClientHello: Requesting remote attestation from server
[INFO: 562] Client, ParseExt - Certificate: Server responded with quote
[INFO: 243] Client, getBinderSecret: SSL_export_handshake_secret_nostd: 1
[INFO: 244] Client, getBinderSecret: binder_secret=22b436b8b602b1651ac19db5bb787df1f96eada1484ac2b6a25d6fc43e21f3fe...
[INFO: 314] Client, VerifyCert: 48 bytes binderSecret=22b436b8b602b1651ac19db5bb787df1f96eada1484ac2b6a25d6fc43e21f3fe...
[INFO: 632] Client, VerifyCert: Servers quote checked. OK!
[INFO: 314] Client, AddExt - Certificate: 48 bytes binderSecret=22b436b8b602b1651ac19db5bb787df1f96eada1484ac2b6a25d6fc43e21f3fe...
[INFO: 430] Client, AddExt - Certificate: Attesting to server
The client will always terminate after the first connection (except when run in benchmark configuration, covered further down below).
As indicated in the output, the RATLS test client and server perform mutual (dummy) attestation. That is, both the client and the server attest themselves.
The lines relating to "binder secret" refer to the TLS linking hash that is
used to bind the attestation to the negotiated TLS channel. This "binder
secret" / linking hash is extracted from internal OpenSSL state using a new
exporter API we added. The linking hash must be the same for both the client
and the server. If it different, there is a man-in-the-middle attack going on.
See paper for details; and consult src/patches/openssl.diff to see the
differences compared to vanilla OpenSSL that add the new exporter.
The RATLS prototype supports (statically linked) "plugins" that request an attestation report (or "quote") for the system environment in which the host application is running. They require additional setup, which is independent of RATLS and not described here. There is a simple plugin for TPMs and one for AMD's SEV attestation support. None of these are for production, but they do all the operations what must be done during a remote-attestation handshake. This is sufficient for testing RATLS' ability to request, carry, and initiate verification of opaque attestation reports during the TLS handshake and for assessing the performance impact using the corresponding TEE/RoT implementations.
Using the --remote-state command-line option, one can also select an
"expected" state, against which the client and server shall compare the
attestation reports they receive. These expected states are just for development
and testing purposes. See src/ratls/expected.cpp on what is available and
how to add your own.
For the local side of the respective program, one can typically specify
--local-state none, except for the TPM plugin, which requires one of the
tpm-dummy names.
Note: The plugin called cca is a dummy plugin in this release of the
prototype, because hardware for Arm's CCA has not been publicly available at
the time of paper submission and could therefore not be benchmarked. As stated
in the paper, co-authors from Arm developed a proof-of-concept internally to
demonstrate that CCA works in principle, though.
Benchmarks using attestation provider plugins for standard Trusted Platform modules (TPMs) and AMD Secure Encrypted Virtualization (SEV) are presented in the paper.
Specific Trusted Execution Environments (TEEs) and Root-of-Trust (RoT) technologies are required to use the prototype. Setup and configuration of a specific TEE and RoT is necessary, but orthogonal to the problem addressed by the paper (how to combine RA and TLS in a TEE/RoT-agnostic way). Therefore, we do not provide a tutorial for this unrelated part.
However, RATLS can be used with the software TPM emulator swtpm.
Once installed, two instances of swtpm can be started using the
ratls-test-swtpm script. We do not provide complete documentation here and
the script may not work out of the box on all Linux installations; please
consult the commands and comments in the script for guidance.