Address review feedback

- Renamed spdm_demo to spdm_ctrl: file, binary, internal demo_* functions to ctrl_*, all references in
  include.am, spdm_test.sh, .gitignore, CLAUDE.md, both READMEs
  - README mentions Nations: title updated to Nuvoton NPCT75x and Nations NS350 TPMs, added Nations build section
  - README section header renamed from Demo Commands to Setup/Control Commands
  - README added reset pin control section: documents GPIO reset requirement, Pi-specific example, custom hardware
  design guidance
  - Moved spdm_tcg.c to common build section, no longer conditional on Nuvoton/Nations in src/spdm/include.am
  - Removed redundant wolfSSL options include from spdm_internal.h since tpm2_types.h handles this
  - Added WOLFTPM_SPDM_TCG generic guard as auto-define in spdm_types.h, replaced ~30 occurrences of #if        defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS) across all files
pull/458/head
Aidan Garske 2026-03-25 18:59:32 +00:00
parent 5a2fee018a
commit ddf990a4c9
20 changed files with 167 additions and 131 deletions

2
.gitignore vendored
View File

@ -92,7 +92,7 @@ examples/firmware/ifx_fw_update
examples/firmware/st33_fw_update
examples/endorsement/get_ek_certs
examples/endorsement/verify_ek_cert
examples/spdm/spdm_demo
examples/spdm/spdm_ctrl
# Generated Cert Files
certs/ca-*.pem

View File

@ -1,12 +1,17 @@
# TPM SPDM Examples
# TPM SPDM Setup/Control
This directory contains the SPDM demo for Nuvoton NPCT75x TPMs with wolfTPM.
This directory contains the SPDM setup and control tool for Nuvoton NPCT75x
and Nations NS350 TPMs with wolfTPM.
## Overview
The `spdm_demo` establishes an SPDM secure session between the host and a
Nuvoton TPM over SPI, enabling AES-256-GCM encrypted bus communication. Once
active, all TPM commands are automatically encrypted with no application changes.
The `spdm_ctrl` tool establishes SPDM secure sessions between the host and a
TPM over SPI, enabling AES-256-GCM encrypted bus communication. Once active,
all TPM commands are automatically encrypted with no application changes.
Supported hardware:
- **Nuvoton NPCT75x** — Identity key mode (ECDHE P-384)
- **Nations NS350** — Identity key mode + PSK mode
For standard SPDM protocol support (spdm-emu, measurements, challenge, etc.),
see the [wolfSPDM](https://github.com/aidangarske/wolfSPDM) standalone library.
@ -33,7 +38,16 @@ cd wolfTPM
make
```
## Demo Commands
### wolfTPM with Nations SPDM
```bash
cd wolfTPM
./autogen.sh
./configure --enable-spdm --enable-nations
make
```
## Setup/Control Commands
| Option | Description |
|--------|-------------|
@ -48,39 +62,60 @@ make
## Usage Examples
```bash
# One-time setup: enable SPDM + GPIO reset
./examples/spdm/spdm_demo --enable
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
# One-time setup: enable SPDM + reset TPM
./examples/spdm/spdm_ctrl --enable
# Reset the TPM (see "TPM Reset Pin Control" below)
# Query SPDM status
./examples/spdm/spdm_demo --status
./examples/spdm/spdm_ctrl --status
# Get TPM identity key
./examples/spdm/spdm_demo --get-pubkey
./examples/spdm/spdm_ctrl --get-pubkey
# Establish SPDM session
./examples/spdm/spdm_demo --connect
./examples/spdm/spdm_ctrl --connect
# Lock SPDM-only mode (connect + lock in one session)
./examples/spdm/spdm_demo --connect --lock
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
./examples/spdm/spdm_ctrl --connect --lock
# Reset the TPM
# All commands now auto-encrypt:
./examples/wrap/caps # auto-SPDM, AES-256-GCM encrypted
./tests/unit.test # full test suite over encrypted bus
# Unlock SPDM-only mode
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
./examples/spdm/spdm_demo --connect --unlock
# Reset the TPM
./examples/spdm/spdm_ctrl --connect --unlock
# Reset the TPM
```
## TPM Reset Pin Control
SPDM enable/disable and SPDM-only mode changes require a TPM reset to take
effect. The reset pin must be connected and controllable by the host.
**Important for custom hardware designs:** Ensure the TPM reset pin is routed
to a host-controllable GPIO. Without reset pin control, SPDM mode changes
cannot be applied and recovery from SPDM-only mode is not possible.
### Raspberry Pi Example (GPIO 4)
```bash
# Assert reset low, wait, release high, wait for TPM startup
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
```
Other platforms will use their own GPIO control mechanism. The key requirement
is toggling the TPM reset line (active low) with sufficient hold time.
## Automated Test Suite
Runs 6 tests: status, connect, lock, unit test over SPDM, unlock, cleartext caps setup lifecycle on hardware.
Runs the full SPDM setup lifecycle on hardware:
```bash
./examples/spdm/spdm_test.sh
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_ctrl nuvoton
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_ctrl nations
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_ctrl nations-psk
```
## Support

View File

@ -3,16 +3,16 @@
if BUILD_EXAMPLES
if BUILD_SPDM
noinst_PROGRAMS += examples/spdm/spdm_demo
noinst_PROGRAMS += examples/spdm/spdm_ctrl
examples_spdm_spdm_demo_SOURCES = examples/spdm/spdm_demo.c
examples_spdm_spdm_demo_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
examples_spdm_spdm_demo_DEPENDENCIES = src/libwolftpm.la
examples_spdm_spdm_demo_CFLAGS = $(AM_CFLAGS)
examples_spdm_spdm_ctrl_SOURCES = examples/spdm/spdm_ctrl.c
examples_spdm_spdm_ctrl_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
examples_spdm_spdm_ctrl_DEPENDENCIES = src/libwolftpm.la
examples_spdm_spdm_ctrl_CFLAGS = $(AM_CFLAGS)
endif
endif
example_spdmdir = $(exampledir)/spdm
dist_example_spdm_DATA = examples/spdm/spdm_demo.c
dist_example_spdm_DATA = examples/spdm/spdm_ctrl.c
DISTCLEANFILES+= examples/spdm/.libs/spdm_demo
DISTCLEANFILES+= examples/spdm/.libs/spdm_ctrl

View File

@ -1,4 +1,4 @@
/* spdm_demo.c
/* spdm_ctrl.c
*
* Copyright (C) 2006-2025 wolfSSL Inc.
*
@ -40,12 +40,12 @@
#include <wolftpm/tpm2_spdm.h>
#include <wolftpm/spdm/spdm.h>
int TPM2_SPDM_Demo(void* userCtx, int argc, char *argv[]);
int TPM2_SPDM_Ctrl(void* userCtx, int argc, char *argv[]);
static void usage(void)
{
printf("SPDM Demo - TPM secure session\n\n"
"Usage: spdm_demo [options]\n"
"Usage: spdm_ctrl [options]\n"
#ifdef WOLFSPDM_NUVOTON
" --enable Enable SPDM via NTC2_PreConfig\n"
" --disable Disable SPDM via NTC2_PreConfig\n"
@ -76,7 +76,7 @@ static void usage(void)
}
#ifdef WOLFSPDM_NUVOTON
static int demo_enable(WOLFTPM2_DEV* dev)
static int ctrl_enable(WOLFTPM2_DEV* dev)
{
int rc;
printf("\n=== Enable SPDM ===\n");
@ -95,7 +95,7 @@ static int demo_enable(WOLFTPM2_DEV* dev)
return rc;
}
static int demo_disable(WOLFTPM2_DEV* dev)
static int ctrl_disable(WOLFTPM2_DEV* dev)
{
int rc;
printf("\n=== Disable SPDM ===\n");
@ -113,7 +113,7 @@ static int demo_disable(WOLFTPM2_DEV* dev)
return rc;
}
static int demo_status(WOLFTPM2_DEV* dev)
static int ctrl_status(WOLFTPM2_DEV* dev)
{
int rc;
WOLFSPDM_NUVOTON_STATUS status;
@ -143,7 +143,7 @@ static int demo_status(WOLFTPM2_DEV* dev)
return rc;
}
static int demo_get_pubkey(WOLFTPM2_DEV* dev)
static int ctrl_get_pubkey(WOLFTPM2_DEV* dev)
{
int rc;
byte pubKey[128];
@ -163,7 +163,7 @@ static int demo_get_pubkey(WOLFTPM2_DEV* dev)
return rc;
}
static int demo_connect(WOLFTPM2_DEV* dev)
static int ctrl_connect(WOLFTPM2_DEV* dev)
{
int rc;
@ -186,7 +186,7 @@ static int demo_connect(WOLFTPM2_DEV* dev)
return rc;
}
static int demo_lock(WOLFTPM2_DEV* dev, int lock)
static int ctrl_lock(WOLFTPM2_DEV* dev, int lock)
{
int rc;
printf("\n=== SPDM-Only: %s ===\n", lock ? "LOCK" : "UNLOCK");
@ -220,7 +220,7 @@ static int hex2bin(const char* hex, byte* bin, word32* binSz)
return 0;
}
static int demo_nations_status(WOLFTPM2_DEV* dev)
static int ctrl_nations_status(WOLFTPM2_DEV* dev)
{
int rc;
int isConn;
@ -277,7 +277,7 @@ static int demo_nations_status(WOLFTPM2_DEV* dev)
return 0; /* status is informational, don't fail */
}
static int demo_nations_psk_connect(WOLFTPM2_DEV* dev, const char* pskHex)
static int ctrl_nations_psk_connect(WOLFTPM2_DEV* dev, const char* pskHex)
{
int rc;
byte psk[128];
@ -301,7 +301,7 @@ static int demo_nations_psk_connect(WOLFTPM2_DEV* dev, const char* pskHex)
return rc;
}
static int demo_nations_psk_set(WOLFTPM2_DEV* dev,
static int ctrl_nations_psk_set(WOLFTPM2_DEV* dev,
const char* pskHex, const char* clearAuthHex)
{
int rc;
@ -357,7 +357,7 @@ static int demo_nations_psk_set(WOLFTPM2_DEV* dev,
return rc;
}
static int demo_nations_psk_clear(WOLFTPM2_DEV* dev, const char* authHex)
static int ctrl_nations_psk_clear(WOLFTPM2_DEV* dev, const char* authHex)
{
int rc;
byte clearAuth[256];
@ -387,7 +387,7 @@ static int demo_nations_psk_clear(WOLFTPM2_DEV* dev, const char* authHex)
return rc;
}
static int demo_nations_identity_key_set(WOLFTPM2_DEV* dev, int set)
static int ctrl_nations_identity_key_set(WOLFTPM2_DEV* dev, int set)
{
int rc;
printf("\n=== Nations Identity Key %s ===\n", set ? "Set" : "Unset");
@ -400,7 +400,7 @@ static int demo_nations_identity_key_set(WOLFTPM2_DEV* dev, int set)
return rc;
}
static int demo_nations_get_pubkey(WOLFTPM2_DEV* dev)
static int ctrl_nations_get_pubkey(WOLFTPM2_DEV* dev)
{
int rc;
byte pubKey[128];
@ -428,7 +428,7 @@ static int demo_nations_get_pubkey(WOLFTPM2_DEV* dev)
return rc;
}
static int demo_nations_caps184(WOLFTPM2_DEV* dev)
static int ctrl_nations_caps184(WOLFTPM2_DEV* dev)
{
int rc;
GetCapability_In capIn;
@ -505,7 +505,7 @@ static int demo_nations_caps184(WOLFTPM2_DEV* dev)
return 0;
}
static int demo_nations_connect(WOLFTPM2_DEV* dev)
static int ctrl_nations_connect(WOLFTPM2_DEV* dev)
{
int rc;
@ -529,7 +529,7 @@ static int demo_nations_connect(WOLFTPM2_DEV* dev)
}
#endif /* WOLFSPDM_NATIONS */
int TPM2_SPDM_Demo(void* userCtx, int argc, char *argv[])
int TPM2_SPDM_Ctrl(void* userCtx, int argc, char *argv[])
{
int rc, i;
WOLFTPM2_DEV dev;
@ -568,42 +568,42 @@ int TPM2_SPDM_Demo(void* userCtx, int argc, char *argv[])
for (i = 1; i < argc; i++) {
#ifdef WOLFSPDM_NUVOTON
if (XSTRCMP(argv[i], "--enable") == 0)
rc = demo_enable(&dev);
rc = ctrl_enable(&dev);
else if (XSTRCMP(argv[i], "--disable") == 0)
rc = demo_disable(&dev);
rc = ctrl_disable(&dev);
else if (XSTRCMP(argv[i], "--status") == 0)
rc = demo_status(&dev);
rc = ctrl_status(&dev);
else if (XSTRCMP(argv[i], "--get-pubkey") == 0)
rc = demo_get_pubkey(&dev);
rc = ctrl_get_pubkey(&dev);
else if (XSTRCMP(argv[i], "--connect") == 0)
rc = demo_connect(&dev);
rc = ctrl_connect(&dev);
else if (XSTRCMP(argv[i], "--lock") == 0)
rc = demo_lock(&dev, 1);
rc = ctrl_lock(&dev, 1);
else if (XSTRCMP(argv[i], "--unlock") == 0)
rc = demo_lock(&dev, 0);
rc = ctrl_lock(&dev, 0);
else
#endif
#ifdef WOLFSPDM_NATIONS
if (XSTRCMP(argv[i], "--identity-key-set") == 0)
rc = demo_nations_identity_key_set(&dev, 1);
rc = ctrl_nations_identity_key_set(&dev, 1);
else if (XSTRCMP(argv[i], "--identity-key-unset") == 0)
rc = demo_nations_identity_key_set(&dev, 0);
rc = ctrl_nations_identity_key_set(&dev, 0);
else if (XSTRCMP(argv[i], "--get-pubkey") == 0)
rc = demo_nations_get_pubkey(&dev);
rc = ctrl_nations_get_pubkey(&dev);
else if (XSTRCMP(argv[i], "--connect") == 0)
rc = demo_nations_connect(&dev);
rc = ctrl_nations_connect(&dev);
else if (XSTRCMP(argv[i], "--status") == 0)
rc = demo_nations_status(&dev);
rc = ctrl_nations_status(&dev);
else if (XSTRCMP(argv[i], "--psk") == 0 && i + 1 < argc)
rc = demo_nations_psk_connect(&dev, argv[++i]);
rc = ctrl_nations_psk_connect(&dev, argv[++i]);
else if (XSTRCMP(argv[i], "--psk-set") == 0 && i + 2 < argc)
{
const char* pskArg = argv[++i];
const char* authArg = argv[++i];
rc = demo_nations_psk_set(&dev, pskArg, authArg);
rc = ctrl_nations_psk_set(&dev, pskArg, authArg);
}
else if (XSTRCMP(argv[i], "--psk-clear") == 0 && i + 1 < argc)
rc = demo_nations_psk_clear(&dev, argv[++i]);
rc = ctrl_nations_psk_clear(&dev, argv[++i]);
else if (XSTRCMP(argv[i], "--lock") == 0)
rc = wolfTPM2_SpdmNationsSetOnlyMode(&dev, 1);
else if (XSTRCMP(argv[i], "--unlock") == 0)
@ -614,7 +614,7 @@ int TPM2_SPDM_Demo(void* userCtx, int argc, char *argv[])
printf(" %s (rc=0x%x)\n", rc == 0 ? "Success" : "FAILED", rc);
}
else if (XSTRCMP(argv[i], "--caps184") == 0)
rc = demo_nations_caps184(&dev);
rc = ctrl_nations_caps184(&dev);
else
#endif
{ printf("Unknown option: %s\n", argv[i]); usage(); rc = BAD_FUNC_ARG; }
@ -631,7 +631,7 @@ int main(int argc, char *argv[])
{
int rc = -1;
#ifndef WOLFTPM2_NO_WRAPPER
rc = TPM2_SPDM_Demo(NULL, argc, argv);
rc = TPM2_SPDM_Ctrl(NULL, argc, argv);
#else
printf("Wrapper code not compiled in\n");
(void)argc; (void)argv;

View File

@ -19,7 +19,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
SPDM_DEMO="${1:-./examples/spdm/spdm_demo}"
SPDM_DEMO="${1:-./examples/spdm/spdm_ctrl}"
CAPS_DEMO="./examples/wrap/caps"
UNIT_TEST="./tests/unit.test"
GPIO_CHIP="gpiochip0"
@ -102,7 +102,7 @@ run_test_no_reset() {
if [ ! -x "$SPDM_DEMO" ]; then
echo "Error: $SPDM_DEMO not found."
echo "Usage: $0 [path-to-spdm_demo] [nuvoton|nations|nations-psk]"
echo "Usage: $0 [path-to-spdm_ctrl] [nuvoton|nations|nations-psk]"
exit 1
fi

View File

@ -24,9 +24,9 @@ make && sudo make install && sudo ldconfig && popd
./autogen.sh && ./configure --enable-spdm --enable-nuvoton && make
# Enable SPDM (one-time), reset, connect
./examples/spdm/spdm_demo --enable
./examples/spdm/spdm_ctrl --enable
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
./examples/spdm/spdm_demo --connect
./examples/spdm/spdm_ctrl --connect
```
See [Building](#building) and [Nuvoton NPCT75x Details](#nuvoton-npct75x) for
@ -44,7 +44,7 @@ make && sudo make install && sudo ldconfig && popd
./autogen.sh && ./configure --enable-spdm --enable-nations && make
# Connect (identity key is factory default)
./examples/spdm/spdm_demo --connect
./examples/spdm/spdm_ctrl --connect
```
See [Building](#building) and [Nations NS350 Details](#nations-ns350) for full
@ -194,13 +194,13 @@ make
```bash
# Enable SPDM on the TPM (persists across resets)
./examples/spdm/spdm_demo --enable
./examples/spdm/spdm_ctrl --enable
# GPIO reset
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
# Verify SPDM is enabled
./examples/spdm/spdm_demo --status
./examples/spdm/spdm_ctrl --status
```
#### Nations
@ -209,7 +209,7 @@ Identity key mode is the factory default — no setup required. If previously
unset, restore with:
```bash
./examples/spdm/spdm_demo --identity-key-set
./examples/spdm/spdm_ctrl --identity-key-set
```
### Establishing a Session
@ -218,10 +218,10 @@ unset, restore with:
```bash
# Establish SPDM session (VERSION → GET_PUBK → KEY_EXCHANGE → GIVE_PUB → FINISH)
./examples/spdm/spdm_demo --connect
./examples/spdm/spdm_ctrl --connect
# Query SPDM status
./examples/spdm/spdm_demo --status
./examples/spdm/spdm_ctrl --status
```
**Note:** `--get-pubkey` retrieves the TPM's identity key as part of the full
@ -234,7 +234,7 @@ Requires PSK to be provisioned first. See
```bash
# Establish PSK session (VERSION → CAPS → ALGO → PSK_EXCHANGE → PSK_FINISH)
./examples/spdm/spdm_demo --psk <psk_hex_128chars>
./examples/spdm/spdm_ctrl --psk <psk_hex_128chars>
```
### Lock/Unlock SPDM-Only Mode
@ -245,7 +245,7 @@ enforcement to take effect.
**Nuvoton (identity key):**
```bash
./examples/spdm/spdm_demo --connect --lock
./examples/spdm/spdm_ctrl --connect --lock
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
# TPM now requires SPDM — all commands auto-encrypted:
@ -253,27 +253,27 @@ gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
./tests/unit.test # full test suite over encrypted bus
# Unlock
./examples/spdm/spdm_demo --connect --unlock
./examples/spdm/spdm_ctrl --connect --unlock
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
```
**Nations (identity key):**
```bash
./examples/spdm/spdm_demo --connect --lock
./examples/spdm/spdm_ctrl --connect --lock
# Power cycle required (unplug and re-plug Raspberry Pi)
./examples/spdm/spdm_demo --connect --unlock
./examples/spdm/spdm_ctrl --connect --unlock
# Power cycle again
```
**Nations (PSK mode):**
```bash
./examples/spdm/spdm_demo --psk <hex> --lock
./examples/spdm/spdm_ctrl --psk <hex> --lock
# Power cycle required
./examples/spdm/spdm_demo --psk <hex> --unlock
./examples/spdm/spdm_ctrl --psk <hex> --unlock
# Power cycle again
```
@ -284,20 +284,20 @@ is provisioned by default; it must be unset before PSK can be used.
```bash
# 1. Unset identity key (enables PSK mode)
./examples/spdm/spdm_demo --identity-key-unset
./examples/spdm/spdm_ctrl --identity-key-unset
# 2. Provision PSK (64-byte PSK + 32-byte ClearAuth)
# The demo computes SHA-384(ClearAuth) and sends PSK(64)+Digest(48) = 112 bytes
./examples/spdm/spdm_demo --psk-set <psk_hex_128chars> <clearauth_hex_64chars>
./examples/spdm/spdm_ctrl --psk-set <psk_hex_128chars> <clearauth_hex_64chars>
# 3. Establish PSK session
./examples/spdm/spdm_demo --psk <psk_hex_128chars>
./examples/spdm/spdm_ctrl --psk <psk_hex_128chars>
# 4. Clear PSK (sends raw 32-byte ClearAuth; TPM verifies SHA-384 internally)
./examples/spdm/spdm_demo --psk-clear <clearauth_hex_64chars>
./examples/spdm/spdm_ctrl --psk-clear <clearauth_hex_64chars>
# 5. Restore identity key (factory default)
./examples/spdm/spdm_demo --identity-key-set
./examples/spdm/spdm_ctrl --identity-key-set
```
**Important:** The ClearAuth must be exactly 32 bytes. PSK_SET stores its SHA-384
@ -308,13 +308,13 @@ to verify. Using the wrong size makes PSK_CLEAR impossible.
```bash
# Nuvoton (identity key — includes GPIO resets between tests)
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_demo nuvoton
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_ctrl nuvoton
# Nations (identity key — no GPIO resets)
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_demo nations
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_ctrl nations
# Nations (PSK — full lifecycle: provision → connect → clear → restore)
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_demo nations-psk
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_ctrl nations-psk
```
## TCG SPDM Vendor Commands
@ -335,7 +335,7 @@ SPDM `VENDOR_DEFINED_REQUEST` messages with `StandardID=0x0001` (TCG).
## Command Reference
All `spdm_demo` options in one table:
All `spdm_ctrl` options in one table:
| Option | Vendor | Description |
|-------------------------------|---------|-------------|

View File

@ -11,17 +11,15 @@ src_libwolftpm_la_SOURCES += \
src/spdm/spdm_msg.c \
src/spdm/spdm_secured.c \
src/spdm/spdm_session.c \
src/spdm/spdm_tcg.c \
src/spdm/spdm_transcript.c
# spdm_tcg.c: shared TCG SPDM code (Nuvoton + Nations)
# Vendor-specific SPDM code
if BUILD_NUVOTON
src_libwolftpm_la_SOURCES += src/spdm/spdm_tcg.c src/spdm/spdm_nuvoton.c
src_libwolftpm_la_SOURCES += src/spdm/spdm_nuvoton.c
endif
if BUILD_NATIONS
if !BUILD_NUVOTON
src_libwolftpm_la_SOURCES += src/spdm/spdm_tcg.c
endif
src_libwolftpm_la_SOURCES += src/spdm/spdm_nations.c
src_libwolftpm_la_SOURCES += src/spdm/spdm_psk.c
endif

View File

@ -183,7 +183,7 @@ int wolfSPDM_SetRequesterKeyPair(WOLFSPDM_CTX* ctx,
return WOLFSPDM_SUCCESS;
}
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
int wolfSPDM_SetRequesterKeyTPMT(WOLFSPDM_CTX* ctx,
const byte* tpmtPub, word32 tpmtPubSz)
{
@ -197,7 +197,7 @@ int wolfSPDM_SetRequesterKeyTPMT(WOLFSPDM_CTX* ctx,
ctx->reqPubKeyTPMTLen = tpmtPubSz;
return WOLFSPDM_SUCCESS;
}
#endif /* WOLFSPDM_NUVOTON || WOLFSPDM_NATIONS */
#endif /* WOLFTPM_SPDM_TCG */
/* wolfSPDM_SetPSK moved to spdm_psk.c */
@ -275,7 +275,7 @@ byte wolfSPDM_GetNegotiatedVersion(WOLFSPDM_CTX* ctx)
return ctx->spdmVersion;
}
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
word32 wolfSPDM_GetConnectionHandle(WOLFSPDM_CTX* ctx)
{
if (ctx == NULL) {
@ -309,7 +309,7 @@ int wolfSPDM_Connect(WOLFSPDM_CTX* ctx)
return WOLFSPDM_E_IO_FAIL;
}
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
if (ctx->mode == WOLFSPDM_MODE_NUVOTON ||
ctx->mode == WOLFSPDM_MODE_NATIONS) {
return wolfSPDM_ConnectTCG(ctx);
@ -389,7 +389,7 @@ int wolfSPDM_SendReceive(WOLFSPDM_CTX* ctx,
return WOLFSPDM_E_IO_FAIL;
}
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
if (ctx->mode == WOLFSPDM_MODE_NUVOTON ||
ctx->mode == WOLFSPDM_MODE_NATIONS ||
ctx->mode == WOLFSPDM_MODE_NATIONS_PSK) {
@ -480,7 +480,7 @@ int wolfSPDM_SendReceive(WOLFSPDM_CTX* ctx,
return WOLFSPDM_SUCCESS;
}
#endif /* WOLFSPDM_NUVOTON || WOLFSPDM_NATIONS */
#endif /* WOLFTPM_SPDM_TCG */
rc = ctx->ioCb(ctx, txBuf, txSz, rxBuf, rxSz, ctx->ioUserCtx);
if (rc != 0) {

View File

@ -27,12 +27,7 @@
#include <config.h>
#endif
/* wolfSSL options MUST be included first */
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
/* spdm_types.h pulls in wolfSSL options via tpm2_types.h */
#include <wolftpm/spdm/spdm.h>
#include <wolftpm/spdm/spdm_types.h>
#include <wolftpm/spdm/spdm_error.h>
@ -79,7 +74,7 @@ struct WOLFSPDM_CTX {
WOLFSPDM_IO_CB ioCb;
void* ioUserCtx;
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
/* TCG binding fields (shared by Nuvoton + Nations) */
word32 connectionHandle; /* Connection handle (usually 0) */
word16 fipsIndicator; /* FIPS service indicator */
@ -213,7 +208,7 @@ static WC_INLINE word64 SPDM_Get64LE(const byte* buf) {
/* ----- Write TCG SPDM Binding header ----- */
/* tag(2/BE) + size(4/BE) +
* connHandle(4/BE) + fips(2/BE) + reserved(4) */
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
static WC_INLINE void wolfSPDM_WriteTcgHeader(byte* buf, word16 tag,
word32 totalSz, word32 connHandle, word16 fips)
{

View File

@ -78,7 +78,7 @@ int wolfSPDM_BuildKeyExchange(WOLFSPDM_CTX* ctx, byte* buf, word32* bufSz)
buf[offset++] = ctx->spdmVersion;
buf[offset++] = SPDM_KEY_EXCHANGE;
buf[offset++] = 0x00; /* MeasurementSummaryHashType = None */
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
buf[offset++] = 0xFF; /* SlotID = 0xFF (no cert, use provisioned public key) */
#else
buf[offset++] = 0x00; /* SlotID = 0 (certificate slot 0) */
@ -254,7 +254,7 @@ int wolfSPDM_BuildFinish(WOLFSPDM_CTX* ctx, byte* buf, word32* bufSz)
* and FINISH header. For PUB_KEY_ID mode, Cm = SHA-384(TPMT_PUBLIC)
* of the requester's public key (matching how Ct is computed for
* responder per TCG SPDM binding). */
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
if (rc == WOLFSPDM_SUCCESS && mutualAuth && ctx->reqPubKeyTPMTLen > 0) {
byte cmHash[WOLFSPDM_HASH_SIZE];
rc = wolfSPDM_Sha384Hash(cmHash, ctx->reqPubKeyTPMT,

View File

@ -65,7 +65,7 @@ int wolfSPDM_EncryptInternal(WOLFSPDM_CTX* ctx,
return WOLFSPDM_E_BUFFER_SMALL;
}
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
if (ctx->mode == WOLFSPDM_MODE_NUVOTON ||
ctx->mode == WOLFSPDM_MODE_NATIONS ||
ctx->mode == WOLFSPDM_MODE_NATIONS_PSK) {
@ -194,7 +194,7 @@ int wolfSPDM_DecryptInternal(WOLFSPDM_CTX* ctx,
/* ----- Transport-specific header parsing ----- */
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
if (ctx->mode == WOLFSPDM_MODE_NUVOTON ||
ctx->mode == WOLFSPDM_MODE_NATIONS ||
ctx->mode == WOLFSPDM_MODE_NATIONS_PSK) {
@ -296,7 +296,7 @@ int wolfSPDM_DecryptInternal(WOLFSPDM_CTX* ctx,
if (rc == 0) {
appDataLen = SPDM_Get16LE(decrypted);
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
if (ctx->mode == WOLFSPDM_MODE_NUVOTON ||
ctx->mode == WOLFSPDM_MODE_NATIONS ||
ctx->mode == WOLFSPDM_MODE_NATIONS_PSK) {

View File

@ -29,7 +29,7 @@
#include "spdm_internal.h"
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
#include <wolftpm/spdm/spdm_tcg.h>
@ -575,6 +575,6 @@ int wolfSPDM_ConnectTCG(WOLFSPDM_CTX* ctx)
return WOLFSPDM_SUCCESS;
}
#endif /* WOLFSPDM_NUVOTON || WOLFSPDM_NATIONS */
#endif /* WOLFTPM_SPDM_TCG */
#endif /* WOLFTPM_SPDM */

View File

@ -574,7 +574,7 @@ static int test_invalid_curve_point(void)
TEST_PASS();
}
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
/* I/O callback that returns a TCG response with msgSize < TCG_HEADER_SIZE */
static int tcg_underflow_io_cb(WOLFSPDM_CTX* ctx, const byte* txBuf, word32 txSz,
byte* rxBuf, word32* rxSz, void* userCtx)
@ -618,7 +618,7 @@ static int test_tcg_underflow(void)
TEST_CTX_FREE();
TEST_PASS();
}
#endif /* WOLFSPDM_NUVOTON || WOLFSPDM_NATIONS */
#endif /* WOLFTPM_SPDM_TCG */
#ifdef WOLFSPDM_NATIONS
static int test_nations_mode(void)
@ -975,7 +975,7 @@ int main(void)
/* Security tests */
test_mitm_signature_rejected();
test_invalid_curve_point();
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
test_tcg_underflow();
#endif
#ifdef WOLFSPDM_NATIONS

View File

@ -42,7 +42,7 @@
#include <wolftpm/tpm2_wrap.h>
/* TIS functions for SPI/I2C TPM transport */
#if (defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)) && \
#if defined(WOLFTPM_SPDM_TCG) && \
!defined(WOLFTPM_LINUX_DEV) && !defined(WOLFTPM_SWTPM) && \
!defined(WOLFTPM_WINAPI)
#include <wolftpm/tpm2_tis.h>
@ -205,7 +205,7 @@ int wolfTPM2_SPDM_SecuredExchange(
return BAD_FUNC_ARG;
}
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
/* In SPDM-only mode, TPM commands must be wrapped in SPDM VENDOR_DEFINED
* messages with the TPM2_CMD vendor code. The TPM's SPDM layer only
* accepts SPDM messages (starting with version byte 0x13), not raw TPM
@ -247,7 +247,7 @@ int wolfTPM2_SPDM_SecuredExchange(
return TPM_RC_SUCCESS;
}
#endif /* WOLFSPDM_NUVOTON || WOLFSPDM_NATIONS */
#endif /* WOLFTPM_SPDM_TCG */
/* Standard SPDM mode: send TPM command as raw app data */
return wolfSPDM_SecuredExchange(ctx->spdmCtx,
@ -258,7 +258,7 @@ int wolfTPM2_SPDM_SecuredExchange(
/* Nuvoton-Specific Functions */
/* -------------------------------------------------------------------------- */
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
/* Set built-in TIS I/O callback for routing SPDM through TPM SPI/I2C.
* Must be called after wolfTPM2_SPDM_InitCtx() and SetTPMCtx(). */
@ -381,6 +381,6 @@ int wolfTPM2_SPDM_Disable(WOLFTPM2_SPDM_CTX* ctx)
#endif /* WOLFSPDM_NUVOTON */
#endif /* WOLFSPDM_NUVOTON || WOLFSPDM_NATIONS */
#endif /* WOLFTPM_SPDM_TCG */
#endif /* WOLFTPM_SPDM */

View File

@ -1116,7 +1116,7 @@ int wolfTPM2_SpdmCleanup(WOLFTPM2_DEV* dev)
return TPM_RC_SUCCESS;
}
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
/* Shared TCG SPDM functions */
int wolfTPM2_SpdmGetPubKey(WOLFTPM2_DEV* dev, byte* pubKey, word32* pubKeySz)
@ -1124,7 +1124,7 @@ int wolfTPM2_SpdmGetPubKey(WOLFTPM2_DEV* dev, byte* pubKey, word32* pubKeySz)
WOLFTPM2_SPDM_CHECK_CTX(dev);
return wolfSPDM_Nuvoton_GetPubKey(dev->spdmCtx->spdmCtx, pubKey, pubKeySz);
}
#endif /* WOLFSPDM_NUVOTON || WOLFSPDM_NATIONS */
#endif /* WOLFTPM_SPDM_TCG */
#ifdef WOLFSPDM_NUVOTON
/* Nuvoton-specific SPDM functions */

View File

@ -67,7 +67,7 @@ typedef enum {
struct WOLFSPDM_CTX;
typedef struct WOLFSPDM_CTX WOLFSPDM_CTX;
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
#include <wolftpm/spdm/spdm_tcg.h>
#endif
#ifdef WOLFSPDM_NUVOTON
@ -130,7 +130,7 @@ WOLFTPM_API int wolfSPDM_SecuredExchange(WOLFSPDM_CTX* ctx,
/* Session info */
WOLFTPM_API word32 wolfSPDM_GetSessionId(WOLFSPDM_CTX* ctx);
WOLFTPM_API byte wolfSPDM_GetNegotiatedVersion(WOLFSPDM_CTX* ctx);
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
WOLFTPM_API word32 wolfSPDM_GetConnectionHandle(WOLFSPDM_CTX* ctx);
WOLFTPM_API word16 wolfSPDM_GetFipsIndicator(WOLFSPDM_CTX* ctx);
#endif

View File

@ -35,7 +35,7 @@
#include <wolftpm/spdm/spdm_types.h>
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
#ifdef __cplusplus
extern "C" {
@ -159,6 +159,6 @@ WOLFTPM_API int wolfSPDM_ConnectTCG(WOLFSPDM_CTX* ctx);
}
#endif
#endif /* WOLFSPDM_NUVOTON || WOLFSPDM_NATIONS */
#endif /* WOLFTPM_SPDM_TCG */
#endif /* WOLFSPDM_TCG_H */

View File

@ -137,6 +137,14 @@ extern "C" {
#define WOLFSPDM_PUBKEY_BUF_SZ 256 /* Public key buffer */
#endif
/* ----- TCG Build Option ----- */
/* Nuvoton or Nations enables TCG SPDM binding; future chips can set directly */
#if (defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)) && \
!defined(WOLFTPM_SPDM_TCG)
#define WOLFTPM_SPDM_TCG
#endif
/* ----- PSK Build Option ----- */
/* Nations build enables PSK by default; can also be set independently */

View File

@ -176,7 +176,7 @@ WOLFTPM_API void wolfTPM2_SPDM_FreeCtx(
/* Nuvoton-Specific Functions (requires wolfSPDM with --enable-nuvoton)
* -------------------------------------------------------------------------- */
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
/**
* Set the built-in TIS I/O callback for routing SPDM through TPM SPI/I2C.
@ -193,7 +193,7 @@ WOLFTPM_API int wolfTPM2_SPDM_SetTisIO(
WOLFTPM2_SPDM_CTX* ctx
);
#endif /* WOLFSPDM_NUVOTON || WOLFSPDM_NATIONS */
#endif /* WOLFTPM_SPDM_TCG */
#ifdef __cplusplus
} /* extern "C" */

View File

@ -498,7 +498,7 @@ WOLFTPM_API int wolfTPM2_SpdmDisconnect(WOLFTPM2_DEV* dev);
*/
WOLFTPM_API int wolfTPM2_SpdmCleanup(WOLFTPM2_DEV* dev);
#if defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS)
#ifdef WOLFTPM_SPDM_TCG
/*!
\ingroup wolfTPM2_Wrappers
\brief Get the TPM's SPDM-Identity public key (shared TCG function).
@ -512,7 +512,7 @@ WOLFTPM_API int wolfTPM2_SpdmCleanup(WOLFTPM2_DEV* dev);
*/
WOLFTPM_API int wolfTPM2_SpdmGetPubKey(WOLFTPM2_DEV* dev,
byte* pubKey, word32* pubKeySz);
#endif /* WOLFSPDM_NUVOTON || WOLFSPDM_NATIONS */
#endif /* WOLFTPM_SPDM_TCG */
#ifdef WOLFSPDM_NUVOTON
/* Nuvoton-specific SPDM functions (requires wolfSPDM with --enable-nuvoton) */