Software TPM for AnyLog


This document summarizes the software TPM implementation used with AnyLog and explains how to deploy it with the AnyLog-TPM offering and connect it to an AnyLog node.

The software TPM flow is useful when you want TPM-backed key operations without depending on a physical TPM chip on every machine. In this model, the TPM logic is provided by swtpm, exposed through a FastAPI service, and consumed by AnyLog through the tpm commands documented below.

What the Software TPM Provides

Software TPM GitHub

The AnyLog-TPM repository packages a TPM2 workflow around:

  • swtpm as the software TPM emulator
  • tpm2-tools for TPM operations
  • a FastAPI-based REST API for TPM actions
  • persistent per-node TPM state directories
  • compatibility adjustments so TPM-generated keys and signatures work with AnyLog

From the TPM repo and compatibility notes, the implementation is tailored so that AnyLog can use TPM-backed node keys with formats it already expects:

  • RSA keys default to 1024 bits
  • signatures are emitted as raw RSA signatures encoded as hex
  • signing uses RSAPSS
  • hashing uses SHA256
  • public keys are returned in PEM format compatible with AnyLog

High-Level Architecture

The deployment has three moving parts:

  1. A software TPM instance managed by swtpm
  2. A REST API from the AnyLog-TPM repo that talks to that TPM instance
  3. An AnyLog node configured with the TPM API connection and the matching TPM shared directory

The shared directory is important because it persists TPM-related data across restarts. In the multi-instance setup, each instance gets its own directory such as:

multiple-instances/shared_dir_node1/
├── tpm_state/
├── key_backups/
└── signing_keys_metadata.json

Depending on usage, the directory also holds TPM context files, encrypted key-store files, and signature artifacts generated by the TPM API.

Deploying the Software TPM

This section uses the repository at:

/Users/roy/Github-Repos/AnyLog-TPM

Option 1: Run One TPM Instance

From the TPM repo root:

./multiple-instances/setup-multiple-instances.sh 1
docker compose -f multiple-instances/docker-compose.instances.yaml up -d

This creates one TPM instance and a corresponding shared directory under multiple-instances/.

By default, the first instance is exposed on:

  • API port 8001
  • SWTPM server port 2321
  • SWTPM control port 2322

Option 2: Run Multiple TPM Instances

If you want one TPM service per AnyLog node, create multiple instances:

./multiple-instances/setup-multiple-instances.sh 5
docker compose -f multiple-instances/docker-compose.instances.yaml up -d

The default port pattern is:

Instance API Port SWTPM Server SWTPM Control
1 8001 2321 2322
2 8002 2323 2324
N 8000 + N 2321 + 2(N-1) 2322 + 2(N-1)

Useful management commands from the TPM repo:

./multiple-instances/manage-instances.sh list
./multiple-instances/manage-instances.sh stop all
./multiple-instances/manage-instances.sh start 1,2
./multiple-instances/manage-instances.sh clear-tpm all
./multiple-instances/manage-instances.sh reset

Verify the TPM API

After the containers are up, verify the API is reachable:

curl http://localhost:8001/health

If you are connecting from another machine, replace localhost with the host IP address of the machine running the TPM service.

Connecting AnyLog to the Software TPM

AnyLog needs two pieces of TPM configuration:

  • conn: the TPM API address in ip:port format
  • tpm_dir: the TPM shared directory for that node

The tpm_dir should match the directory used by the corresponding TPM instance, for example:

/Users/roy/Github-Repos/AnyLog-TPM/multiple-instances/shared_dir_node1

Environment-Based Setup

One practical deployment pattern is to set TPM-related environment values in the AnyLog node configuration:

ENABLE_TPM=true
TPM_IP=192.168.0.140
TPM_PORT=8001
TPM_HOST_PORT=8011
TPM_DIR="/Users/roy/Github-Repos/AnyLog-TPM/multiple-instances/shared_dir_node1"

Then in the AnyLog startup script:

if $TPM_DIR then set tpm_dir = $TPM_DIR
if $TPM_IP then set tpm_ip = $TPM_IP
if $TPM_PORT then set tpm_port = $TPM_PORT

tpm_base_url = !tpm_ip + : + !tpm_port
tpm set where conn = !tpm_base_url and tpm_dir = !tpm_dir

This makes the AnyLog node aware of the TPM endpoint and the TPM-backed storage directory.

Manual CLI Setup

You can also configure TPM directly from the AnyLog CLI:

tpm set where conn = 192.168.86.31:8001 and tpm_dir = /Users/roy/Github-Repos/AnyLog-TPM/multiple-instances/shared_dir_node1
tpm enabled = on
tpm get info

Once enabled, TPM-backed key operations can be used by AnyLog.

Typical AnyLog Workflow

A common sequence is:

  1. Start the TPM API instance
  2. Configure the AnyLog node with tpm set
  3. Enable TPM support with tpm enabled = on
  4. Create node keys with id create keys for node where password = [password]
  5. Optionally store the node key password with tpm set node key password = [password]
  6. Verify the TPM configuration with tpm get info
  7. Enable node authentication with set node authentication on

Example:

tpm set where conn = 192.168.86.31:8001 and tpm_dir = /Users/roy/Github-Repos/AnyLog-TPM/multiple-instances/shared_dir_node1
tpm enabled = on
id create keys for node where password = abc
tpm set node key password = abc
tpm get info
set node authentication on

TPM Commands in AnyLog

The following are the currently supported tpm commands in AnyLog.

tpm set

Registers the TPM service endpoint and the TPM shared directory used by the node.

Usage:

tpm set where conn = [ip:port] and tpm_dir = [tpm_dir]

Example:

tpm set where conn = 192.168.86.31:8001 and tpm_dir = /Users/roy/Github-Repos/AnyLog-TPM/multiple-instances/shared_dir_node1

Notes:

  • conn is required
  • tpm_dir is required by the command definition, although the implementation also attempts to fall back to !tpm_dir
  • the tpm_dir should point to the same instance directory used by the TPM API for that node

tpm enabled

Enables or disables TPM usage on the node.

Usage:

tpm enabled = on/off

Examples:

tpm enabled = on
tpm enabled = off

When TPM is enabled, AnyLog uses the configured TPM integration for supported key operations.

tpm get info

Returns the configured TPM information for the node.

Usage:

tpm get info

Example:

tpm get info

Use this command after tpm set and tpm enabled = on to confirm the node sees the expected TPM configuration.

tpm set node key password

Stores the password used for the TPM-backed node key.

Usage:

tpm set node key password = [password]

Example:

tpm set node key password = 123

Important behavior from the implementation:

  • the TPM configuration must already be set
  • the node key must already exist in TPM
  • if the node key does not exist, AnyLog returns an error instructing you to create it with id create keys for node ...

In practice, run this command after creating the node key.

Using TPM with Multiple AnyLog Nodes

The TPM repo also includes a helper script for running multiple AnyLog nodes against multiple TPM instances:

./multiple-nodes/manage-anylog-nodes.sh setup 1 master 2 operator 1 publisher
./multiple-nodes/manage-anylog-nodes.sh start
./multiple-nodes/manage-anylog-nodes.sh list

In that model:

  • each AnyLog container mounts one TPM shared directory
  • the TPM shared directory is mounted at /app/AnyLog-Network/tpm_dir
  • container names follow the pattern anylog-{type}-tpm{N}

This is the simplest way to keep a one-to-one relationship between an AnyLog node and its TPM state.

Operational Notes

  • Back up the TPM shared directory if you need to preserve TPM state.
  • The tpm_state/ directory is what allows the software TPM to persist across restarts.
  • The key_backups/ and signing_keys_metadata.json files are part of the TPM key recovery and metadata flow.
  • If you reset a TPM instance, previously created TPM-backed keys may need to be recreated.
  • The software TPM approach is intended to emulate TPM-backed operations, but it does not provide the hardware isolation of a physical TPM.

Troubleshooting

If tpm set or tpm get info does not behave as expected, check the following:

  • the TPM API container is running
  • the IP and port in conn are reachable from the AnyLog node
  • the tpm_dir path exists and matches the instance used by the TPM API
  • the node key was created before running tpm set node key password

Useful TPM repo checks:

./multiple-instances/manage-instances.sh list
docker compose -f multiple-instances/docker-compose.instances.yaml ps
curl http://localhost:8001/health