fwTPM Overview¶
The wolfTPM fwTPM (also called fTPM) is a firmware TPM 2.0 built on wolfCrypt cryptographic primitives. It is not only an emulator for tests. It is a portable TPM 2.0 command processor that runs as a standalone server process (fwtpm_server) or is linked into an embedded firmware image. A default build with RSA, ECC, AES, and every feature group enabled has 103 of the 112 TPM 2.0 Revision 1.38 command codes in its dispatch table. The eight Version 185 post-quantum commands raise that to 111. See Command Coverage below for the counting convention and the documented limitations, such as the minimal self-test and the missing SU_STATE resume support.
The fwTPM can be used for testing, and it can also be used in production, security-critical, and isolated deployments where a discrete TPM chip is not available or not wanted. In those deployments the security of the TPM depends on the platform that hosts it. A firmware TPM does not provide the physical isolation of a discrete TPM chip on its own, so the integrator must supply the isolation (a separate core, a TrustZone secure world, or similar) and must protect the NV storage. The default file-based NV store keeps hierarchy seeds, authorization values, and private keys in plaintext, and fwtpm_server itself is a development and test tool. The fwTPM also brings post-quantum cryptography and SPDM to platforms without TPM silicon.
Example integration models:
- Embedded and IoT platforms without a discrete TPM chip (bare-metal via an SPI or I2C TIS HAL)
- Isolated deployments, such as a TPM running on a separate core, a TrustZone secure world, or a lock-step real-time core next to a Linux application processor. The isolation comes from the platform, not from the fwTPM.
- Development and testing of TPM-dependent applications (drop-in for swtpm or the Microsoft TPM simulator)
- CI/CD pipelines that need TPM functionality (socket transport compatible with tpm2-tools)
- Prototyping TPM workflows before hardware is available
- Post-quantum and SPDM work without TPM silicon (see Post-Quantum Support and SPDM Responder)
Features¶
- TPM 2.0 command processor covering 103 of the 112 Revision 1.38 command codes in a default build, with the limitations listed in Command Coverage.
- TCP socket transport using the Microsoft TPM simulator protocol, compatible with wolfTPM examples and tpm2-tools. Both the mssim and swtpm TCTI protocols are auto-detected on the command port.
- TIS register-level transport over POSIX shared memory, or over SPI or I2C for bare-metal integration.
- HAL abstractions for I/O and NV storage, so the core logic does not change when porting. See HAL and Porting.
- Post-quantum cryptography with
--enable-pqc: ML-DSA (FIPS 204) signing and ML-KEM (FIPS 203) key encapsulation per TCG TPM 2.0 Library Specification Version 185.--enable-pqcand--enable-v185are distinct project-wide modes, but configure promotes--enable-pqcto the full Version 185 mode when building the fwTPM, so the two behave the same for the fwTPM. Configure auto-detects PQC when--enable-fwtpmis built against a wolfCrypt that has both. See Post-Quantum Support. - SPDM 1.3 responder for testing the SPDM stack without silicon. See SPDM Responder.
- Compile-time feature gates (
FWTPM_NO_*) to shrink the build for constrained targets. See Building.
Architecture¶
+---------------------+ +-------------------------------+
| wolfTPM Client App | | fwtpm_server (or embedded) |
| (examples, tests) | | |
+----------+----------+ | +-------------------------+ |
| | | Transport Layer | |
TCP (SWTPM protocol) | | (socket or TIS) | |
or TIS shared memory | +------------+------------+ |
or SPI/I2C TIS | | |
| | +------------v------------+ |
+--------------->| | FWTPM_ProcessCommand | |
| | (fwtpm_command.c) | |
| +------+-----------+------+ |
| | | |
| +------v-----+ +---v------+ |
| | wolfCrypt | | NV | |
| | (RSA, ECC, | | backend | |
| | SHA, HMAC,| | (fwtpm_ | |
| | RNG, AES) | | nv.c) | |
| +------------+ +----------+ |
+-------------------------------+
Both the socket and TIS transports pass each command to FWTPM_ProcessCommand. The command handlers then use wolfCrypt and the NV backend. The flow is the same for the standalone server and for an embedded integration.
Components:
| File | Role |
|---|---|
fwtpm_command.c |
TPM 2.0 command processor and dispatch table |
fwtpm_io.c |
Transport layer: SWTPM TCP socket protocol (enabled by the swtpm configuration; builds without it use the TIS path) |
fwtpm_nv.c |
NV storage: file-based (default); HAL-abstracted, with a built-in append-only mode for write-once flash |
fwtpm_tis.c |
TIS register state machine (transport-agnostic) |
fwtpm_tis_shm.c |
POSIX shared memory and semaphore TIS transport |
fwtpm_main.c |
Server entry point, CLI argument parsing |
tpm2_util.c |
Shared utilities (hash helpers, ForceZero, PrintBin) |
tpm2_packet.c |
TPM packet marshaling and unmarshaling |
tpm2_param_enc.c |
Parameter encryption (XOR and AES session encryption) |
Supported TPM 2.0 Commands¶
This section lists representative commands and is not exhaustive. It omits supported commands such as PCR_Event, PCR_Allocate, ClockRateAdjust, several policy commands, and some algorithm-dependent commands. The Command Coverage section below has the dispatch-table breakdown. A default build (no FWTPM_NO_* macro set) includes every group below. Setting a gate macro removes that group's commands from the dispatch table, from TPM2_GetCapability(TPM_CAP_COMMANDS), and from the TPM_PT_TOTAL_COMMANDS count. See Building for the gates.
Startup and Self-Test¶
| Command | Description |
|---|---|
TPM2_Startup |
Initialize TPM (SU_CLEAR or SU_STATE) |
TPM2_Shutdown |
Save state and prepare for power-off |
TPM2_SelfTest |
Minimal self-test: a SHA-256 known-answer test and an RNG check. The source calls this nonconformant. |
TPM2_IncrementalSelfTest |
No-op stub that returns an empty to-do list |
TPM2_GetTestResult |
Return self-test result |
Random Number Generation¶
| Command | Description |
|---|---|
TPM2_GetRandom |
Generate random bytes (max 48 per call) |
TPM2_StirRandom |
Add entropy to RNG state |
Capability¶
| Command | Description |
|---|---|
TPM2_GetCapability |
Query TPM properties, algorithms, handles |
Key Management¶
| Command | Description |
|---|---|
TPM2_CreatePrimary |
Create primary key under a hierarchy |
TPM2_Create |
Create child key under a parent |
TPM2_CreateLoaded |
Create and load key in one command |
TPM2_Load |
Load key from private and public parts |
TPM2_LoadExternal |
Load external (software) key |
TPM2_Import |
Import externally wrapped key |
TPM2_Duplicate |
Export key for transfer (inner and outer wrapping) |
TPM2_Rewrap |
Re-wrap a duplicated object from the old parent to a new parent |
TPM2_FlushContext |
Unload a transient object or session |
TPM2_ContextSave |
Save object or session context |
TPM2_ContextLoad |
Restore saved context |
TPM2_ReadPublic |
Read public area of a loaded key |
TPM2_ObjectChangeAuth |
Change authorization of a key |
TPM2_EvictControl |
Make transient key persistent (or remove) |
TPM2_HierarchyControl |
Enable or disable a hierarchy |
TPM2_HierarchyChangeAuth |
Change hierarchy authorization value |
TPM2_Clear |
Regenerate the storage primary seed, reset owner and endorsement authorization and policy state, and schedule eligible objects for removal. Does not regenerate the platform seed or the endorsement seed. |
TPM2_ChangePPS |
Replace platform primary seed |
TPM2_ChangeEPS |
Replace endorsement primary seed |
Cryptographic Operations¶
| Command | Description |
|---|---|
TPM2_Sign |
Sign digest with loaded key |
TPM2_VerifySignature |
Verify signature against loaded key |
TPM2_RSA_Encrypt |
RSA encryption (OAEP, PKCS1) |
TPM2_RSA_Decrypt |
RSA decryption |
TPM2_EncryptDecrypt |
Symmetric encrypt and decrypt |
TPM2_EncryptDecrypt2 |
Symmetric encrypt and decrypt (alternate) |
TPM2_Hash |
Single-shot hash computation |
TPM2_HMAC |
Single-shot HMAC computation |
TPM2_ECDH_KeyGen |
Generate ephemeral ECC key pair |
TPM2_ECDH_ZGen |
Compute ECDH shared secret |
TPM2_ECC_Parameters |
Get ECC curve parameters |
TPM2_TestParms |
Validate algorithm parameter support |
Hash Sequences¶
| Command | Description |
|---|---|
TPM2_HashSequenceStart |
Start a hash sequence |
TPM2_HMAC_Start |
Start an HMAC sequence |
TPM2_SequenceUpdate |
Add data to a hash or HMAC sequence |
TPM2_SequenceComplete |
Finalize hash or HMAC sequence and get result |
TPM2_EventSequenceComplete |
Finalize hash sequence and extend PCR |
Sealing¶
| Command | Description |
|---|---|
TPM2_Unseal |
Unseal data from a sealed object |
PCR (Platform Configuration Registers)¶
| Command | Description |
|---|---|
TPM2_PCR_Read |
Read PCR values |
TPM2_PCR_Extend |
Extend a PCR with a digest |
TPM2_PCR_Reset |
Reset a resettable PCR |
Clock¶
| Command | Description |
|---|---|
TPM2_ReadClock |
Read TPM clock values |
TPM2_ClockSet |
Set TPM clock |
Sessions and Authorization¶
| Command | Description |
|---|---|
TPM2_StartAuthSession |
Create HMAC, policy, or trial session |
Policy¶
| Command | Description |
|---|---|
TPM2_PolicyGetDigest |
Get current policy session digest |
TPM2_PolicyRestart |
Reset policy session digest |
TPM2_PolicyPCR |
Bind policy to PCR values |
TPM2_PolicyPassword |
Include password in policy |
TPM2_PolicyAuthValue |
Include auth value in policy |
TPM2_PolicyCommandCode |
Restrict policy to specific command |
TPM2_PolicyOR |
Logical OR of policy branches |
TPM2_PolicySecret |
Authorization with secret |
TPM2_PolicyAuthorize |
Approve policy with signing key |
TPM2_PolicyNV |
Policy based on NV index comparison |
TPM2_PolicyLocality |
Restrict policy to specific locality |
TPM2_PolicySigned |
Authorize policy with external signing key |
Dictionary Attack (DA) Protection¶
| Command | Description |
|---|---|
TPM2_DictionaryAttackParameters |
Set maxTries, recoveryTime, lockoutRecovery |
TPM2_DictionaryAttackLockReset |
Reset the failed-tries counter (lockoutAuth) |
The fwTPM implements dictionary-attack protection modeled on the TPM 2.0 specification (Part 1, Section 19.8). A failed authorization of a DA-protected entity increments failedTries. Once it reaches maxTries the TPM returns TPM_RC_LOCKOUT. failedTries is persisted in NV on every failure, so a power cycle cannot reset it.
When a clock HAL is registered (FWTPM_Clock_SetHAL), the counter self-heals one try per recoveryTime seconds, and a non-orderly shutdown adds a one-try penalty. On clockless builds neither applies: the persisted failedTries counter does not self-heal, and recovery is only through DictionaryAttackLockReset or Clear, so routine unclean power-off cannot accumulate into lockout.
A failed lockoutAuth locks the lockout hierarchy. On a build with a clock HAL, that lock persists across reboot and clears after lockoutRecovery seconds, except when lockoutRecovery is 0 (reboot-only recovery). On a clockless build, the failed-lockoutAuth lock is cleared on every startup. With a clock HAL, the clock HAL reports milliseconds since boot, so this timer measures continuous post-boot uptime, not wall-clock time across reboots. A device that reboots more often than lockoutRecovery extends its effective recovery window.
There are two separate gates. A failed lockoutAuth blocks later uses of lockoutAuth (DictionaryAttackLockReset, DictionaryAttackParameters, and lockout-authorized Clear). Reaching maxTries blocks authorization of DA-protected objects, NV indices, and bound entities, and the TPM returns TPM_RC_LOCKOUT. The platform hierarchy is always an escape hatch: TPM2_ClearControl(platformAuth, clearDisable=NO) followed by TPM2_Clear(platformAuth) recovers even when disableClear was set. Startup and Shutdown are never DA-gated, so a reboot in lockout can always recover. Entities marked noDA (TPMA_OBJECT_noDA on objects, TPMA_NV_NO_DA on NV indices) never feed the counter and stay usable during lockout.
TPM2_GetCapability(TPM_CAP_TPM_PROPERTIES) reports TPM_PT_MAX_AUTH_FAIL, TPM_PT_LOCKOUT_INTERVAL, TPM_PT_LOCKOUT_RECOVERY, TPM_PT_LOCKOUT_COUNTER, and the inLockout bit of TPM_PT_PERMANENT.
Durable accounting writes the NV FLAGS entry on each DA-protected failure (and on the first DA-protected auth use per boot). The counter stops increasing while it is at maxTries, but clock-based self-healing can lower it, which allows further failed attempts and NV writes in the same boot, so the number of writes per boot is not strictly bounded. On flash-backed targets it still adds wear and makes failed-auth latency NV-bound, so size the NV backend accordingly.
The first use of a DA-protected (non-noDA) authorization after startup can make a TPM persist a daUsed flag to NV and return TPM_RC_RETRY ("resubmit the identical command") while it writes. The TCG architecture describes this as one possible implementation approach, not a requirement for every TPM. Build with FWTPM_DA_USED_RETRY to emulate it so clients exercise their resubmit and retry handling. It is off by default, and DA accounting and persistence are active regardless. Compile out all DA logic with FWTPM_NO_DA.
Coverage: DA, noDA, lockout, self-heal, and persistence unit tests in tests/fwtpm_unit_tests.c, the examples/management/da_check end-to-end example (add -lockout for the destructive lockout and recovery path), and the tests/fwtpm_da_retry.sh harness that exercises the TPM_RC_RETRY path against a FWTPM_DA_USED_RETRY build.
Non-Volatile Storage (NV)¶
| Command | Description |
|---|---|
TPM2_NV_DefineSpace |
Create an NV index |
TPM2_NV_UndefineSpace |
Delete an NV index |
TPM2_NV_ReadPublic |
Read NV index public metadata |
TPM2_NV_Write |
Write data to NV index |
TPM2_NV_Read |
Read data from NV index |
TPM2_NV_Extend |
Extend NV index (hash-extend) |
TPM2_NV_Increment |
Increment NV counter |
TPM2_NV_WriteLock |
Lock NV index for writes |
TPM2_NV_ReadLock |
Lock NV index for reads |
TPM2_NV_SetBits |
OR bits into NV bit field index |
TPM2_NV_ChangeAuth |
Change NV index authorization value |
Attestation and Credentials¶
| Command | Description |
|---|---|
TPM2_Quote |
Generate signed PCR quote |
TPM2_Certify |
Certify a loaded key |
TPM2_CertifyCreation |
Prove key was created by this TPM |
TPM2_GetTime |
Signed attestation of TPM clock |
TPM2_NV_Certify |
Certify NV index contents |
TPM2_MakeCredential |
Create credential blob for a key |
TPM2_ActivateCredential |
Unwrap credential blob |
Command Coverage¶
Implemented (103 Revision 1.38 command codes)¶
This page counts command codes, not command names, and excludes TPM_CC_Vendor_TCG_Test from standard totals. Revision 1.38 defines 112 standard command codes. With RSA, ECC, AES, and all feature groups enabled, the dispatch table holds 103 of them, which is about 92% of the Revision 1.38 set. The Version 185 post-quantum commands add 8. Reaching 113 entries requires WOLFTPM_SPDM (one more command, PolicyTransportSPDM) and the test-only vendor command as well.
Core set, never gated (36 commands): Startup, Shutdown, SelfTest, IncrementalSelfTest, GetTestResult, GetRandom, StirRandom, GetCapability, TestParms, PCR_Read, PCR_Extend, PCR_Reset, PCR_Event, PCR_Allocate, PCR_SetAuthPolicy, PCR_SetAuthValue, CreatePrimary, FlushContext, ReadPublic, Clear, ClearControl, ChangeEPS, ChangePPS, HierarchyControl, HierarchyChangeAuth, SetPrimaryPolicy, EvictControl, Create, ObjectChangeAuth, Load, Sign, VerifySignature, StartAuthSession, Unseal, LoadExternal, CreateLoaded
These are present in every build.
Optional vendor command (off by default, WOLFTPM_FWTPM_TCG_TEST):
Vendor_TCG_Test
Conditional on algorithm (NO_RSA, HAVE_ECC, NO_AES):
RSA_Encrypt, RSA_Decrypt, ECDH_KeyGen, ECDH_ZGen, ECC_Parameters, EC_Ephemeral, ZGen_2Phase, EncryptDecrypt, EncryptDecrypt2
Conditional on feature macros:
FWTPM_NO_POLICY: PolicyGetDigest, PolicyRestart, PolicyPCR, PolicyPassword, PolicyAuthValue, PolicyCommandCode, PolicyOR, PolicySecret, PolicyAuthorize, PolicyLocality, PolicySigned, PolicyNV, PolicyPhysicalPresence, PolicyCpHash, PolicyNameHash, PolicyDuplicationSelect, PolicyNvWritten, PolicyTemplate, PolicyCounterTimer, PolicyTicket, PolicyAuthorizeNV (21 commands). Also gates the conditionalPolicyTransportSPDMcommand.FWTPM_NO_NV: NV_DefineSpace, NV_UndefineSpace, NV_UndefineSpaceSpecial, NV_ReadPublic, NV_Write, NV_Read, NV_Extend, NV_Increment, NV_WriteLock, NV_ReadLock, NV_SetBits, NV_ChangeAuth, NV_GlobalWriteLock (13 commands). Also gates PolicyNV and PolicyAuthorizeNV when policy is enabled and removes the in-memory NV index slots fromFWTPM_CTX. NV_Certify is gated byFWTPM_NO_NVas well asFWTPM_NO_ATTESTATION.FWTPM_NO_ATTESTATION: Quote, Certify, CertifyCreation, GetTime, NV_Certify (NV_Certify is also removed byFWTPM_NO_NV)FWTPM_NO_CREDENTIAL: MakeCredential, ActivateCredentialFWTPM_NO_DA: DictionaryAttackLockReset, DictionaryAttackParameters (2 commands)FWTPM_NO_PARAM_ENC: Disables parameter encryption and decryption for command and response parameters. Sessions still work for HMAC auth, but encrypted transport is disabled. Reduces code size by removing AES-CFB and XOR parameter encryption.FWTPM_NO_KEY_MIGRATION: Import, Duplicate, Rewrap (3 commands). Shared key helpers used by Create and Load are retained.FWTPM_NO_ECDH: ECDH_KeyGen, ECDH_ZGen, EC_Ephemeral, ZGen_2Phase, ECC_Parameters (5 commands). ECDSA sign and verify are retained. Also drops theecEphemeral*commit state fromFWTPM_CTX.FWTPM_NO_HASH_CMDS: Hash, HMAC, HMAC_Start, HashSequenceStart, SequenceUpdate, SequenceComplete, EventSequenceComplete (7 commands). WhenWOLFTPM_MLDSAis built, only SequenceUpdate is retained, because the ML-DSA verify sequences stream their message through it. SequenceComplete is not shared: ML-DSA sequences finalize through SignSequenceComplete and VerifySequenceComplete, so advertising it in a gated build would expose a command that can never succeed. Also drops the per-instance hash-sequence slots (hashSeq[FWTPM_MAX_HASH_SEQ]) fromFWTPM_CTX.FWTPM_NO_CONTEXT: ContextSave, ContextLoad (2 commands). FlushContext is retained. Also drops the per-boot context protection key and the saved-context replay list fromFWTPM_CTX.FWTPM_NO_SYM_ENCRYPT: EncryptDecrypt, EncryptDecrypt2 (2 commands). Nests insideNO_AES. AES itself is retained for session parameter encryption, AES-GCM, and (unlessFWTPM_NO_CONTEXTis also set) context protection.FWTPM_NO_CLOCK: ReadClock, ClockSet, ClockRateAdjust (3 commands). GetTime is underFWTPM_NO_ATTESTATION, not this flag.FWTPM_NO_PP: PolicyPhysicalPresence and physical-presence enforcement. Drops the physical-presence HAL, the platform latch, andFWTPM_PP_SetHAL.
These gates are independent and there is intentionally no umbrella macro: pick exactly the groups your fTPM does not need. Applying every gate leaves the core set of 36 always-present commands, plus whatever the algorithm configuration keeps (keeping NV, or adding FWTPM_NO_NV to drop it). See the MicroBlaze V example in the wolftpm-examples repository (listed in Usage) for a worked selection.
Missing Commands¶
Revision 1.38 baseline (9 missing command codes)¶
Medium (moderate logic, builds on existing infrastructure):
| Command | Spec Section | Difficulty | Notes |
|---|---|---|---|
TPM2_SetCommandCodeAuditStatus |
21.2 | Medium | Manage list of commands that are audited. Needs audit bitmap in context |
TPM2_PP_Commands |
26.2 | Medium | Manage physical presence command list. Needs PP command bitmap |
Hard (complex crypto or new subsystems):
| Command | Spec Section | Difficulty | Notes |
|---|---|---|---|
TPM2_GetSessionAuditDigest |
18.5 | Hard | Sign session audit digest. Requires session audit tracking (running hash of all commands in session). New subsystem |
TPM2_GetCommandAuditDigest |
18.6 | Hard | Sign command audit digest. Requires command audit log with running hash. New subsystem |
TPM2_Commit |
19.2 | Hard | DAA and anonymous attestation ephemeral key. Complex ECC point math (K, L, E generation). Needs DAA support in wolfCrypt |
TPM2_SetAlgorithmSet |
26.3 | Hard | Vendor-specific algorithm configuration. Rarely implemented, can return TPM_RC_COMMAND_CODE |
TPM2_FieldUpgradeStart |
27.2 | Hard | Firmware upgrade initiation. Vendor-specific, requires secure update infrastructure |
TPM2_FieldUpgradeData |
27.3 | Hard | Firmware upgrade data blocks. Vendor-specific |
TPM2_FirmwareRead |
27.4 | Hard | Read firmware for backup. Vendor-specific |
Revision 1.59 additions (5 new command codes)¶
TPM2_MAC shares command code 0x155 with TPM2_HMAC, and TPM2_MAC_Start shares 0x15B with TPM2_HMAC_Start, so they add no new codes. The source shows only the HMAC form (no CMAC handling was found), so the symmetric-key MAC form is not confirmed as supported.
| Command | Spec Section | Difficulty | Notes |
|---|---|---|---|
TPM2_MAC |
15.6 | Medium | Block cipher MAC (CMAC). Like HMAC but uses symmetric key. Needs wolfCrypt CMAC |
TPM2_MAC_Start |
17.3 | Medium | Start MAC sequence. Mirrors HMAC_Start for CMAC |
TPM2_CertifyX509 |
18.8 | Hard | Generate partial X.509 certificate. Complex ASN.1 construction, caller provides tbsCert template. Deprecated in Version 184 |
TPM2_AC_GetCapability |
32.2 | Hard | Deprecated in Version 184. Attached component capability query. Hardware-specific, rarely needed for software TPM |
TPM2_AC_Send |
32.3 | Hard | Deprecated in Version 184. Send data to attached component. Hardware-specific |
TPM2_Policy_AC_SendSelect |
32.4 | Medium | Deprecated in Version 184. Policy for AC_Send. Like other policy commands |
TPM2_ACT_SetTimeout |
33.2 | Medium | Set authenticated countdown timer. Needs ACT state and timer infrastructure |
Version 184 additions (9 command codes, 8 missing)¶
Version 184 marks CreateLoaded, AC_GetCapability, AC_Send, Policy_AC_SendSelect, and CertifyX509 as deprecated. CreateLoaded is still implemented here.
| Command | Spec Section | Difficulty | Notes |
|---|---|---|---|
TPM2_ECC_Encrypt |
14.8 | Medium | ECC-based encryption using the TPM-defined construction from Part 1 Annex C (ephemeral ECDH point, KDF-derived masking, and integrity data). The command does not expose a choice of scheme. |
TPM2_ECC_Decrypt |
14.9 | Medium | ECC-based decryption. Paired with ECC_Encrypt |
TPM2_PolicyCapability |
23.x | Easy | Assert TPM capability value in policy session |
TPM2_PolicyParameters |
23.x | Easy | Assert command parameters in policy session |
TPM2_SetCapability |
30.x | Medium | Modify TPM capability settings. Platform auth required |
TPM2_NV_DefineSpace2 |
31.x | Medium | Extended NV space definition (larger attribute field). Extends existing NV_DefineSpace |
TPM2_NV_ReadPublic2 |
31.x | Easy | Extended NV public read. Extends existing NV_ReadPublic |
TPM2_ReadOnlyControl |
24.x | Easy | Toggle TPM read-only mode. Simple flag |
Conditionally implemented¶
TPM2_PolicyTransportSPDM has a handler and a dispatch-table entry whenever WOLFTPM_SPDM is enabled, and it is removed by FWTPM_NO_POLICY. It is not missing. See SPDM Responder.
Coverage Summary¶
The eight Version 185 PQC commands (TPM2_Encapsulate, TPM2_Decapsulate, TPM2_SignDigest, TPM2_VerifyDigestSignature, TPM2_SignSequenceStart, TPM2_SignSequenceComplete, TPM2_VerifySequenceStart, TPM2_VerifySequenceComplete) are implemented under --enable-pqc. See Post-Quantum Support for the PQC-only restriction on these commands.
| Spec Version | Total Command Codes | Implemented (default build) | Missing | Coverage |
|---|---|---|---|---|
| Revision 1.38 | 112 | 103 | 9 | 92% |
| Revision 1.59 | 117 | 103 | 14 | 88% |
| Version 184 | 126 | 103 | 23 | 82% |
| Version 185 | 134 | 111 | 23 | 83% |
Implemented counts assume RSA, ECC, AES, and all feature groups, with SPDM, PQC (except in the Version 185 row), and the vendor test command disabled. Enabling WOLFTPM_SPDM adds PolicyTransportSPDM (one more implemented code). The Version 185 row includes the eight PQC commands.
Known limitations: TPM2_SelfTest is a minimal smoke test and TPM2_IncrementalSelfTest is a stub, as noted above, SU_STATE resume is not supported (see the lifecycle section), TPM2_PolicySecret rejects nonzero expiration because expiring policy tickets are not supported, and TPM2_DictionaryAttackParameters limits newMaxTries to 65535. The command coverage above should not be read as full conformance with the TCG specification.
Startup and Shutdown Lifecycle¶
- First boot:
FWTPM_NV_Initfinds no NV file, generates random hierarchy seeds, and saves the initial state. TPM2_Startup(SU_CLEAR): Flushes transient objects and sessions and resets PCRs. Required before most other TPM commands.TPM2_GetCapabilityis accepted beforeStartup.- Normal operation: Commands are processed through
FWTPM_ProcessCommand. TPM2_Shutdown: Saves NV state but does not clear the "started" flag. The TPM remains logically powered on.- Server restart (process exit and relaunch) constitutes a power cycle. Only after a power cycle can
TPM2_Startupbe called again.
Calling TPM2_Startup on an already-started TPM returns TPM_RC_INITIALIZE.
Known limitation: Startup(SU_STATE) is accepted without checking that a matching Shutdown(SU_STATE) came before it, and a process restart zeroes FWTPM_CTX and reloads only NV-backed state. Transient objects and sessions are therefore not preserved across a restart, which a conforming TPM Resume requires. This stays a limitation until volatile state serialization and the shutdown and startup sequence checks are implemented.
Primary Key Derivation¶
Primary keys are deterministically derived from the hierarchy seed from the hierarchy seed using KDFa-based formulas that are specific to this implementation. The same seed, the same public template, and the same sensitiveCreate.data always produce the same key. Revision 1.38 discusses primary-object creation in Clause 27.
- RSA: Primes p and q are derived by iterative KDFa with the labels
"RSA p"and"RSA q", then primality testing, then CRT computation. - ECC: The private scalar d is derived with
KDFa(nameAlg, seed, "ECC", hashUnique, counter), and the public point is Q = d*G. - KEYEDHASH and SYMCIPHER: Key bytes are derived with
KDFa(nameAlg, seed, label, hashUnique). For KEYEDHASH, nonemptysensitiveCreate.datais used directly and is not derived. - hashUnique:
H(sensitiveCreate.data || inPublic.unique). BecausesensitiveCreate.datafeedshashUniqueand the cache digest, a different value gives a different key.
A primary key cache (SHA-256 of the template, FWTPM_MAX_PRIMARY_CACHE slots) avoids re-deriving expensive RSA keys on repeated CreatePrimary calls.
Hierarchy seeds are managed by ChangePPS (platform) and ChangeEPS (endorsement). Clear regenerates the owner (storage primary) seed and resets endorsement authorization and policy state, but it leaves the endorsement seed and the platform seed unchanged; use ChangeEPS to replace the endorsement seed. The null seed is re-randomized on every Startup(CLEAR). For post-quantum primary keys, see Post-Quantum Support.