Building the fwTPM¶
This page covers how to build the fwTPM server, the configure options and compile defines that control it, and the compile-time macros that tune size and features. For what the fwTPM is, see the Overview.
Prerequisites¶
wolfSSL must be built with TPM support, keygen, and WC_RSA_NO_PADDING:
cd wolfssl
./configure --enable-wolftpm --enable-pkcallbacks --enable-keygen CFLAGS="-DWC_RSA_NO_PADDING"
make
sudo make install
Build the fwTPM Server¶
Socket transport (SWTPM protocol, default for development):
cd wolftpm
./configure --enable-fwtpm --enable-swtpm
make
This produces src/fwtpm/fwtpm_server and builds the wolfTPM client library with WOLFTPM_SWTPM for socket-based communication.
TIS and shared-memory transport (for fwTPM HAL integration):
./configure --enable-fwtpm --disable-swtpm
make
When --enable-swtpm is omitted, the build uses TIS shared-memory transport (WOLFTPM_FWTPM_HAL, WOLFTPM_ADV_IO) and compiles fwtpm_tis.c into the server.
fwTPM server only (no client library or examples):
./configure --enable-fwtpm-only --enable-swtpm
make
This builds only the fwtpm_server binary and skips libwolftpm, examples, and tests. It is useful for embedded targets that only need the TPM server.
Debug build:
./configure --enable-fwtpm --enable-swtpm --enable-debug
make
Build Output¶
| Artifact | Description |
|---|---|
src/fwtpm/fwtpm_server |
Standalone fwTPM server binary |
src/.libs/libwolftpm.* |
wolfTPM client library |
Key Build Flags¶
| Configure Option | Effect |
|---|---|
--enable-fwtpm |
Build fwtpm_server binary (alongside client library) |
--enable-fwtpm-only |
Build only fwtpm_server (no client library, examples, or tests) |
--enable-swtpm |
Use SWTPM TCP socket transport (ports 2321 and 2322) |
--enable-fwtpm-nv-appendonly |
Append-only NV journal for write-once flash ports (off by default) |
--enable-pqc (the fwTPM build promotes it to --enable-v185) |
TPM 2.0 v1.85 post-quantum support (see Post-Quantum Support) |
--enable-spdm |
SPDM responder (with --enable-tcg or --enable-psk; see SPDM Responder) |
--enable-fuzz |
Fuzzing build |
--enable-debug |
Enable debug logging |
| Compile Define | Set By |
|---|---|
WOLFTPM_FWTPM |
Automatically set for the fwtpm_server target only |
WOLFTPM_SWTPM |
--enable-swtpm |
WOLFTPM_FWTPM_HAL |
--enable-fwtpm --disable-swtpm |
WOLFTPM_FWTPM_TIS |
--enable-fwtpm --disable-swtpm |
WOLFTPM_ADV_IO |
Set with WOLFTPM_FWTPM_HAL |
WOLFTPM_FWTPM_NV_APPEND_ONLY |
--enable-fwtpm-nv-appendonly (CMake WOLFTPM_FWTPM_NV_APPEND_ONLY=yes) |
WOLFTPM_FWTPM_TCG_TEST |
Manually (CFLAGS=-DWOLFTPM_FWTPM_TCG_TEST); off by default |
No vendor commands are registered by default. Define WOLFTPM_FWTPM_TCG_TEST to compile in the optional TPM2_Vendor_TCG_Test (0x20000000) echo command.
Command-Code Enforcement¶
A valid command code carries only the 16-bit index plus, for vendor commands, the V bit (CC_VEND, bit 29). Codes with any other reserved bit set, or codes not in the dispatch table, are rejected with TPM_RC_COMMAND_CODE. TPM2_GetCapability(TPM_CAP_COMMANDS) returns proper TPMA_CC values (index, handle attributes, and V bit, ordered by command code).
Configuration Macros¶
All macros are compile-time overridable (for example -DFWTPM_MAX_OBJECTS=8).
| Macro | Default | Description |
|---|---|---|
FWTPM_MAX_COMMAND_SIZE |
4096 | Maximum command and response buffer size (bytes) |
FWTPM_MAX_RANDOM_BYTES |
48 | Maximum bytes per GetRandom call |
FWTPM_MAX_OBJECTS |
3 | Maximum concurrently loaded transient objects |
FWTPM_MAX_PERSISTENT |
8 | Maximum persistent objects (via EvictControl) |
FWTPM_MAX_PRIVKEY_DER |
1280 (256 with NO_RSA) |
Maximum DER-encoded private key size (bytes) |
FWTPM_MAX_HASH_SEQ |
4 | Maximum concurrent hash and HMAC sequences |
FWTPM_MAX_PRIMARY_CACHE |
4 | Cached primary keys per hierarchy and template |
FWTPM_MAX_SESSIONS |
4 | Maximum concurrent auth sessions |
FWTPM_MAX_NV_INDICES |
16 | Maximum NV RAM index slots; omitted from FWTPM_CTX with FWTPM_NO_NV |
FWTPM_MAX_NV_DATA |
2048 | Maximum data per NV index (bytes) |
FWTPM_DA_DEFAULT_MAX_TRIES |
32 | DA failed-auth count before lockout |
FWTPM_DA_DEFAULT_RECOVERY |
600 | DA self-heal interval (seconds per try) |
FWTPM_DA_DEFAULT_LOCKOUT_RECOVERY |
86400 | lockoutAuth recovery time (seconds) |
FWTPM_DA_MAX_TRIES_LIMIT |
0xFFFF | Upper clamp for a replayed maxTries or failedTries |
FWTPM_MAX_DATA_BUF |
1024 | Internal buffer for HMAC, hash, general data |
FWTPM_MAX_PUB_BUF |
512 | Internal buffer for public area, signatures |
FWTPM_MAX_DER_SIG_BUF |
256 | Internal buffer for DER signatures, ECC points |
FWTPM_MAX_ATTEST_BUF |
1024 | Internal buffer for attestation marshaling |
FWTPM_MAX_CMD_AUTHS |
3 | Maximum authorization sessions per command (TPM spec hard cap) |
FWTPM_MAX_SENSITIVE_SIZE |
FWTPM_MAX_PRIVKEY_DER + 128 |
Maximum marshaled sensitive area (private key, auth, and nonce headroom) |
FWTPM_MAX_SIGN_SEQ |
4 | Maximum concurrent v1.85 PQC sign and verify sequences |
FWTPM_MAX_SYM_KEY_SIZE |
32 | Symmetric key buffer (sized for AES-256) |
FWTPM_MAX_HMAC_KEY_SIZE |
64 | HMAC key buffer (sized for SHA-512 block) |
FWTPM_MAX_HMAC_DIGEST_SIZE |
64 | HMAC output buffer (sized for SHA-512) |
FWTPM_CMD_PORT |
2321 | Default TCP command port |
FWTPM_PLAT_PORT |
2322 | Default TCP platform port |
FWTPM_NV_FILE |
"fwtpm_nv.bin" |
Default NV storage file path |
FWTPM_NV_MAX_WRITE_ALIGN |
64 | Max append-only program granule in bytes (upper bound on a HAL's writeAlign); sizes the pending-granule buffer when WOLFTPM_FWTPM_NV_APPEND_ONLY is set |
FWTPM_PCR_BANKS |
2 | Number of PCR banks (SHA-256 and SHA-384) |
FWTPM_TIS_BURST_COUNT |
64 | TIS FIFO burst count (bytes per transfer) |
FWTPM_TIS_FIFO_SIZE |
4096 | TIS command and response FIFO size |
Stack and Heap Control¶
| Macro | Effect |
|---|---|
WOLFTPM_SMALL_STACK |
Use heap allocation for large stack objects |
WOLFTPM2_NO_HEAP |
Forbid heap allocation (all stack) |
Note
WOLFTPM_SMALL_STACK and WOLFTPM2_NO_HEAP are mutually exclusive. Defining both is a compile error.
v1.85 Embedded RAM Impact¶
Enabling --enable-pqc (or --enable-v185) lifts several internal buffers to accommodate PQC key and signature sizes. The defaults shrink automatically at compile time based on which ML-DSA and ML-KEM parameter sets wolfCrypt was built with (WOLFSSL_NO_ML_DSA_44/65/87, WOLFSSL_NO_KYBER512/768/1024). Boards that only enable the smaller parameter sets get smaller buffers with no per-board override.
Buffer sizes by enabled parameter set:
| Macro | Classical | MLDSA-44 + MLKEM-512 | MLDSA-65 + MLKEM-768 | MLDSA-87 + MLKEM-1024 |
|---|---|---|---|---|
FWTPM_TIS_FIFO_SIZE |
4096 | 4096 | 8192 | 8192 |
FWTPM_MAX_COMMAND_SIZE |
4096 | 4096 | 8192 | 8192 |
FWTPM_MAX_PUB_BUF |
512 | 1440 | 2080 | 2720 |
FWTPM_MAX_DER_SIG_BUF |
256 | 2548 | 3437 | 4755 |
FWTPM_MAX_KEM_CT_BUF |
n/a | 832 | 1152 | 1632 |
Sizing logic lives in wolftpm/fwtpm/fwtpm.h (constants FWTPM_MAX_MLDSA_SIG_SIZE, FWTPM_MAX_MLDSA_PUB_SIZE, FWTPM_MAX_MLKEM_CT_SIZE, FWTPM_MAX_MLKEM_PUB_SIZE) and wolftpm/fwtpm/fwtpm_tis.h (FIFO size). The ML-DSA constants come from wolfCrypt's WC_MLDSA_{44,65,87}_*_SIZE macros. The ML-KEM constants are FIPS 203 spec values, because wolfCrypt's WC_ML_KEM_*_SIZE macros cannot be evaluated by the preprocessor.
The 8192 lifts on the FIFO and command buffers only apply when MLDSA-65 or MLDSA-87 is enabled, because their signatures do not fit a 4096-byte response with TPM headers. MLDSA-44-only and MLKEM-only v1.85 builds stay at 4096.
Per-deployment override: every macro above is still #ifndef-guarded, so a board can override individually on the compile line if the automatic default is wrong for its workload (for example -DFWTPM_TIS_FIFO_SIZE=2048).
Heap versus stack: building with WOLFTPM_SMALL_STACK moves the large per-call buffers off the stack into XMALLOC and XFREE regions. The PQC paths already use FWTPM_DECLARE_BUF and FWTPM_ALLOC_BUF, which respect this flag, so no source changes are required. WOLFTPM2_NO_HEAP is supported but pays the full stack cost, so pair it with the smallest PQC parameter set you can.
Algorithm Feature Macros¶
These macros use wolfCrypt's existing compile-time options to control which cryptographic algorithms are available in fwtpm_server. If an algorithm is disabled, the corresponding TPM commands are excluded from the build.
| Macro | Default | Effect |
|---|---|---|
NO_RSA |
not defined | Excludes RSA keygen, sign, verify, RSA_Encrypt, RSA_Decrypt |
HAVE_ECC |
defined | Enables ECC keygen, sign, verify, ECDH_KeyGen, ECDH_ZGen, ECC_Parameters |
HAVE_ECC384 |
defined | Enables P-384 curve support |
HAVE_ECC521 or HAVE_ALL_CURVES |
build-dependent | Enables P-521 when MAX_ECC_KEY_BITS >= 521 provides 66-byte TPM ECC fields |
ECC_MIN_KEY_SZ |
wolfCrypt-defined | Excludes smaller curves from ECC_Parameters and TPM_CAP_ECC_CURVES |
NO_AES |
not defined | Excludes EncryptDecrypt, EncryptDecrypt2, AES parameter encryption |
WOLFSSL_SHA384 |
defined | Enables SHA-384 PCR bank |
When an algorithm is disabled, commands that exclusively use that algorithm are removed from the dispatch table at compile time. Commands that support multiple algorithms (for example CreatePrimary and Sign) remain available but return TPM_RC_ASYMMETRIC for the disabled algorithm type.
TPM Feature Group Macros¶
These fwTPM-specific macros disable entire groups of TPM 2.0 functionality to reduce code size on constrained targets.
| Macro | Default | Commands Excluded |
|---|---|---|
FWTPM_NO_ATTESTATION |
not defined | Quote, Certify, CertifyCreation, GetTime, NV_Certify |
FWTPM_NO_NV |
not defined | NV_DefineSpace, NV_UndefineSpace, NV_ReadPublic, NV_Write, NV_Read, NV_Extend, NV_Increment, NV_WriteLock, NV_ReadLock, NV_Certify; also removes the in-memory NV index slots from FWTPM_CTX |
FWTPM_NO_POLICY |
not defined | PolicyGetDigest, PolicyRestart, PolicyPCR, PolicyPassword, PolicyAuthValue, PolicyCommandCode, PolicyOR, PolicySecret, PolicyAuthorize, PolicyNV |
FWTPM_NO_CREDENTIAL |
not defined | MakeCredential, ActivateCredential |
FWTPM_NO_DA |
not defined | DictionaryAttackParameters, DictionaryAttackLockReset, and all lockout accounting |
FWTPM_NO_PARAM_ENC |
not defined | Command and response parameter (XOR and AES-CFB) encryption support in sessions |
FWTPM_NO_KEY_MIGRATION |
not defined | Import, Duplicate, Rewrap |
FWTPM_NO_ECDH |
not defined | ECDH_KeyGen, ECDH_ZGen, EC_Ephemeral, ZGen_2Phase, ECC_Parameters (ECDSA sign and verify retained), plus the ecEphemeral* commit state in FWTPM_CTX |
FWTPM_NO_HASH_CMDS |
not defined | Hash, HMAC, HMAC_Start, HashSequenceStart, SequenceUpdate, SequenceComplete, EventSequenceComplete, and the FWTPM_CTX hash-sequence slots |
FWTPM_NO_CONTEXT |
not defined | ContextSave, ContextLoad (FlushContext retained), plus the per-boot context protection key and saved-context replay list in FWTPM_CTX |
FWTPM_NO_SYM_ENCRYPT |
not defined | EncryptDecrypt, EncryptDecrypt2 |
FWTPM_NO_CLOCK |
not defined | ReadClock, ClockSet, ClockRateAdjust |
Removing a command group also removes it from the TPM2_GetCapability(TPM_CAP_COMMANDS) advertisement and the TPM_PT_TOTAL_COMMANDS count, since both are derived from the dispatch table. When WOLFTPM_MLDSA is built, SequenceUpdate alone is retained under FWTPM_NO_HASH_CMDS, because ML-DSA verify sequences stream their message through it. SequenceComplete is not shared (ML-DSA sequences finalize through TPM2_SignSequenceComplete and TPM2_VerifySequenceComplete), so it is gated out with the rest of the hash commands rather than advertised as a command that can never succeed.
The FWTPM_DA_USED_RETRY macro (off by default) does not remove commands. It makes the server return TPM_RC_RETRY on the first DA-protected auth use after startup, emulating a real TPM persisting daUsed. See Dictionary Attack Protection in the Overview.
Minimal build example. There is no umbrella macro. Select the command groups to drop explicitly, so each is a deliberate choice. For example, to build a small ECC-only signing and NV fTPM (this set drops attestation and keeps Sign, VerifySignature, PCR, and NV):
./configure --enable-fwtpm --enable-swtpm \
CFLAGS="-DNO_RSA \
-DFWTPM_NO_POLICY -DFWTPM_NO_ATTESTATION -DFWTPM_NO_CREDENTIAL \
-DFWTPM_NO_DA -DFWTPM_NO_PARAM_ENC -DFWTPM_NO_KEY_MIGRATION \
-DFWTPM_NO_ECDH -DFWTPM_NO_HASH_CMDS -DFWTPM_NO_CONTEXT \
-DFWTPM_NO_SYM_ENCRYPT -DFWTPM_NO_CLOCK"
That set retains a core fTPM: Startup, Shutdown, SelfTest, GetRandom, GetCapability, the PCR_* commands, Create, CreatePrimary, Load, ReadPublic, FlushContext, Sign, VerifySignature, the NV_* commands, and session support (StartAuthSession and Unseal). Add -DFWTPM_NO_NV to also drop NV, or drop any -DFWTPM_NO_* above to keep that group. This ECC-only build is small enough to run as a soft-core fTPM on a constrained FPGA (see the MicroBlaze V example in the wolftpm-examples repository, which fits an ECC-only fTPM into about 192 KB of on-chip memory).
Dependencies:
FWTPM_NO_NValso removesNV_Certify, even ifFWTPM_NO_ATTESTATIONis not set.NO_RSAimplies no RSA attestation signatures. ECC-only attestation still works withHAVE_ECC.