Add TPM2_PolicyTransportSPDM support for client and firmware TPM - #594
Add TPM2_PolicyTransportSPDM support for client and firmware TPM#594aidangarske wants to merge 19 commits into
Conversation
…n unsupported TPMs
There was a problem hiding this comment.
🟡 Changes recommended
The new TPM_CAP_SPDM_SESSION_INFO parsing in src/tpm2.c can treat truncated responses as successful empty fields due to missing packet.overflow handling, undermining the intended fail-closed behavior.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR adds TPM 2.0 Library v1.84 SPDM-aware policy and capability support to wolfTPM, including client-side wrappers, firmware TPM (fwTPM) enforcement, and examples/tests under WOLFTPM_SPDM. The main goal is to allow policies to require that authorizing commands arrive over an active SPDM secure session, optionally bound to SPDM key names.
Changes:
- Add
TPM2_PolicyTransportSPDM(CC0x01A1), new return codes (TPM_RC_CHANNEL,TPM_RC_CHANNEL_KEY), andTPM_CAP_SPDM_SESSION_INFOcapability structures/constants. - Implement SPDM session-info capability parsing and wrapper APIs (
wolfTPM2_GetCapability_SPDMSessionInfo,wolfTPM2_PolicyTransportSPDM, offlinewolfTPM2_PolicyTransportSPDMMake). - Extend fwTPM to compute/record the SPDM policy term and enforce it at authorization time; add responder-side session identity tracking and new example/tests.
File summaries
| File | Description |
|---|---|
| wolftpm/tpm2.h | Adds SPDM command/capability constants, return codes, and capability data types for SPDM session info. |
| wolftpm/tpm2_wrap.h | Declares new wrapper APIs for SPDM session-info capability and PolicyTransportSPDM (plus offline digest helper). |
| wolftpm/spdm/spdm_responder.h | Documents new responder-side constraints and adds APIs to query session state/identity key. |
| wolftpm/fwtpm/fwtpm.h | Extends fwTPM session/context state for tracking SPDM secure-channel policy enforcement. |
| src/tpm2.c | Adds TPM_CAP_SPDM_SESSION_INFO parsing and client-side TPM2_PolicyTransportSPDM command marshaling. |
| src/tpm2_wrap.c | Implements wrapper calls for session-info capability, PolicyTransportSPDM, and offline policy digest construction. |
| src/spdm/spdm_responder.c | Tracks whether a connected session is asymmetric vs PSK and prevents finish/exchange mixing and mid-session key rotation. |
| src/fwtpm/include.am | Ensures responder objects are linked into fwtpm_server and sets build flags for availability. |
| src/fwtpm/fwtpm_main.c | Marks TPM commands as arriving over SPDM when dispatched from the SPDM secured-message path. |
| src/fwtpm/fwtpm_command.c | Implements PolicyTransportSPDM, SPDM session-info capability, and enforcement of secure-channel/key-name bindings. |
| tests/unit_tests.c | Adds wrapper/offline helper tests and a live SPDM path test to confirm policy digest behavior. |
| tests/fwtpm_unit_tests.c | Adds fwTPM unit tests for PolicyTransportSPDM digest behavior, enforcement, and SPDM session-info capability behavior. |
| examples/spdm/spdm_test.sh | Extends SPDM test script to cover session-info and PolicyTransportSPDM NV binding scenarios. |
| examples/spdm/spdm_ctrl.c | Adds --session-info and --policy-nv flows demonstrating capability query and NV binding under SPDM. |
| examples/spdm/README.md | Updates documentation and adds nv_bind usage guidance. |
| examples/spdm/nv_bind.c | New focused example showing NV binding to SPDM (PolicyTransportSPDM) and denial off-channel. |
| examples/spdm/include.am | Builds and distributes the new nv_bind example. |
Review details
- Files reviewed: 17/17 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| /* Parse a TPM2B_NAME from a capability response, consuming the full wire | ||
| * length even when the name exceeds the local buffer, so the remaining | ||
| * fields stay aligned. */ | ||
| static int TPM2_ParseSpdmName(TPM2_Packet* packet, TPM2B_NAME* name) | ||
| { | ||
| UINT16 wireSz = 0; | ||
| int avail; | ||
|
|
||
| TPM2_Packet_ParseU16(packet, &wireSz); | ||
| avail = packet->size - packet->pos; | ||
| /* A declared length past the packet or larger than the Name buffer is a | ||
| * malformed capability response; fail rather than return a partial Name. */ | ||
| if (avail < 0 || (int)wireSz > avail || | ||
| (int)wireSz > (int)sizeof(name->name)) { | ||
| return TPM_RC_SIZE; | ||
| } | ||
| name->size = wireSz; | ||
| TPM2_Packet_ParseBytes(packet, name->name, (int)wireSz); | ||
| return TPM_RC_SUCCESS; | ||
| } |
| TPML_SPDM_SESSION_INFO* sessInfo = | ||
| &out->capabilityData.data.spdmSessionInfo; | ||
| TPM2_Packet_ParseU32(&packet, &sessInfo->count); | ||
| if (sessInfo->count > MAX_SPDM_SESS_INFO) | ||
| sessInfo->count = MAX_SPDM_SESS_INFO; |
client command layer and the firmware TPM, per TPM 2.0 Library v1.84.
session, optionally scoped to a requester and/or TPM identity key name folded
into the policy digest.
bound-key mismatch.
authPolicy), and wolfTPM2_GetCapability_SPDMSessionInfo, all under WOLFTPM_SPDM.
secure-channel assertion but report empty names, since no asymmetric key
authenticated them.
active session so a session cannot be relabeled as identity-key authenticated.
computing the policy key-name digest.
tpmKeyName-bound policy that succeeds over its session and is rejected on a
name mismatch.
sweep (no-policy, Nuvoton-only, NO_GETENV, fuzz+spdm), and a non-SPDM build.