Skip to content

Commit ddf990a

Browse files
committed
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
1 parent 5a2fee0 commit ddf990a

20 files changed

Lines changed: 167 additions & 131 deletions

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ examples/firmware/ifx_fw_update
9292
examples/firmware/st33_fw_update
9393
examples/endorsement/get_ek_certs
9494
examples/endorsement/verify_ek_cert
95-
examples/spdm/spdm_demo
95+
examples/spdm/spdm_ctrl
9696

9797
# Generated Cert Files
9898
certs/ca-*.pem

examples/spdm/README.md

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
# TPM SPDM Examples
1+
# TPM SPDM Setup/Control
22

3-
This directory contains the SPDM demo for Nuvoton NPCT75x TPMs with wolfTPM.
3+
This directory contains the SPDM setup and control tool for Nuvoton NPCT75x
4+
and Nations NS350 TPMs with wolfTPM.
45

56
## Overview
67

7-
The `spdm_demo` establishes an SPDM secure session between the host and a
8-
Nuvoton TPM over SPI, enabling AES-256-GCM encrypted bus communication. Once
9-
active, all TPM commands are automatically encrypted with no application changes.
8+
The `spdm_ctrl` tool establishes SPDM secure sessions between the host and a
9+
TPM over SPI, enabling AES-256-GCM encrypted bus communication. Once active,
10+
all TPM commands are automatically encrypted with no application changes.
11+
12+
Supported hardware:
13+
- **Nuvoton NPCT75x** — Identity key mode (ECDHE P-384)
14+
- **Nations NS350** — Identity key mode + PSK mode
1015

1116
For standard SPDM protocol support (spdm-emu, measurements, challenge, etc.),
1217
see the [wolfSPDM](https://github.com/aidangarske/wolfSPDM) standalone library.
@@ -33,7 +38,16 @@ cd wolfTPM
3338
make
3439
```
3540

36-
## Demo Commands
41+
### wolfTPM with Nations SPDM
42+
43+
```bash
44+
cd wolfTPM
45+
./autogen.sh
46+
./configure --enable-spdm --enable-nations
47+
make
48+
```
49+
50+
## Setup/Control Commands
3751

3852
| Option | Description |
3953
|--------|-------------|
@@ -48,39 +62,60 @@ make
4862
## Usage Examples
4963

5064
```bash
51-
# One-time setup: enable SPDM + GPIO reset
52-
./examples/spdm/spdm_demo --enable
53-
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
65+
# One-time setup: enable SPDM + reset TPM
66+
./examples/spdm/spdm_ctrl --enable
67+
# Reset the TPM (see "TPM Reset Pin Control" below)
5468

5569
# Query SPDM status
56-
./examples/spdm/spdm_demo --status
70+
./examples/spdm/spdm_ctrl --status
5771

5872
# Get TPM identity key
59-
./examples/spdm/spdm_demo --get-pubkey
73+
./examples/spdm/spdm_ctrl --get-pubkey
6074

6175
# Establish SPDM session
62-
./examples/spdm/spdm_demo --connect
76+
./examples/spdm/spdm_ctrl --connect
6377

6478
# Lock SPDM-only mode (connect + lock in one session)
65-
./examples/spdm/spdm_demo --connect --lock
66-
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
79+
./examples/spdm/spdm_ctrl --connect --lock
80+
# Reset the TPM
6781

6882
# All commands now auto-encrypt:
6983
./examples/wrap/caps # auto-SPDM, AES-256-GCM encrypted
7084
./tests/unit.test # full test suite over encrypted bus
7185

7286
# Unlock SPDM-only mode
73-
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
74-
./examples/spdm/spdm_demo --connect --unlock
87+
# Reset the TPM
88+
./examples/spdm/spdm_ctrl --connect --unlock
89+
# Reset the TPM
90+
```
91+
92+
## TPM Reset Pin Control
93+
94+
SPDM enable/disable and SPDM-only mode changes require a TPM reset to take
95+
effect. The reset pin must be connected and controllable by the host.
96+
97+
**Important for custom hardware designs:** Ensure the TPM reset pin is routed
98+
to a host-controllable GPIO. Without reset pin control, SPDM mode changes
99+
cannot be applied and recovery from SPDM-only mode is not possible.
100+
101+
### Raspberry Pi Example (GPIO 4)
102+
103+
```bash
104+
# Assert reset low, wait, release high, wait for TPM startup
75105
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
76106
```
77107

108+
Other platforms will use their own GPIO control mechanism. The key requirement
109+
is toggling the TPM reset line (active low) with sufficient hold time.
110+
78111
## Automated Test Suite
79112

80-
Runs 6 tests: status, connect, lock, unit test over SPDM, unlock, cleartext caps setup lifecycle on hardware.
113+
Runs the full SPDM setup lifecycle on hardware:
81114

82115
```bash
83-
./examples/spdm/spdm_test.sh
116+
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_ctrl nuvoton
117+
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_ctrl nations
118+
./examples/spdm/spdm_test.sh ./examples/spdm/spdm_ctrl nations-psk
84119
```
85120

86121
## Support

examples/spdm/include.am

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33

44
if BUILD_EXAMPLES
55
if BUILD_SPDM
6-
noinst_PROGRAMS += examples/spdm/spdm_demo
6+
noinst_PROGRAMS += examples/spdm/spdm_ctrl
77

8-
examples_spdm_spdm_demo_SOURCES = examples/spdm/spdm_demo.c
9-
examples_spdm_spdm_demo_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
10-
examples_spdm_spdm_demo_DEPENDENCIES = src/libwolftpm.la
11-
examples_spdm_spdm_demo_CFLAGS = $(AM_CFLAGS)
8+
examples_spdm_spdm_ctrl_SOURCES = examples/spdm/spdm_ctrl.c
9+
examples_spdm_spdm_ctrl_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
10+
examples_spdm_spdm_ctrl_DEPENDENCIES = src/libwolftpm.la
11+
examples_spdm_spdm_ctrl_CFLAGS = $(AM_CFLAGS)
1212
endif
1313
endif
1414

1515
example_spdmdir = $(exampledir)/spdm
16-
dist_example_spdm_DATA = examples/spdm/spdm_demo.c
16+
dist_example_spdm_DATA = examples/spdm/spdm_ctrl.c
1717

18-
DISTCLEANFILES+= examples/spdm/.libs/spdm_demo
18+
DISTCLEANFILES+= examples/spdm/.libs/spdm_ctrl
Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* spdm_demo.c
1+
/* spdm_ctrl.c
22
*
33
* Copyright (C) 2006-2025 wolfSSL Inc.
44
*
@@ -40,12 +40,12 @@
4040
#include <wolftpm/tpm2_spdm.h>
4141
#include <wolftpm/spdm/spdm.h>
4242

43-
int TPM2_SPDM_Demo(void* userCtx, int argc, char *argv[]);
43+
int TPM2_SPDM_Ctrl(void* userCtx, int argc, char *argv[]);
4444

4545
static void usage(void)
4646
{
4747
printf("SPDM Demo - TPM secure session\n\n"
48-
"Usage: spdm_demo [options]\n"
48+
"Usage: spdm_ctrl [options]\n"
4949
#ifdef WOLFSPDM_NUVOTON
5050
" --enable Enable SPDM via NTC2_PreConfig\n"
5151
" --disable Disable SPDM via NTC2_PreConfig\n"
@@ -76,7 +76,7 @@ static void usage(void)
7676
}
7777

7878
#ifdef WOLFSPDM_NUVOTON
79-
static int demo_enable(WOLFTPM2_DEV* dev)
79+
static int ctrl_enable(WOLFTPM2_DEV* dev)
8080
{
8181
int rc;
8282
printf("\n=== Enable SPDM ===\n");
@@ -95,7 +95,7 @@ static int demo_enable(WOLFTPM2_DEV* dev)
9595
return rc;
9696
}
9797

98-
static int demo_disable(WOLFTPM2_DEV* dev)
98+
static int ctrl_disable(WOLFTPM2_DEV* dev)
9999
{
100100
int rc;
101101
printf("\n=== Disable SPDM ===\n");
@@ -113,7 +113,7 @@ static int demo_disable(WOLFTPM2_DEV* dev)
113113
return rc;
114114
}
115115

116-
static int demo_status(WOLFTPM2_DEV* dev)
116+
static int ctrl_status(WOLFTPM2_DEV* dev)
117117
{
118118
int rc;
119119
WOLFSPDM_NUVOTON_STATUS status;
@@ -143,7 +143,7 @@ static int demo_status(WOLFTPM2_DEV* dev)
143143
return rc;
144144
}
145145

146-
static int demo_get_pubkey(WOLFTPM2_DEV* dev)
146+
static int ctrl_get_pubkey(WOLFTPM2_DEV* dev)
147147
{
148148
int rc;
149149
byte pubKey[128];
@@ -163,7 +163,7 @@ static int demo_get_pubkey(WOLFTPM2_DEV* dev)
163163
return rc;
164164
}
165165

166-
static int demo_connect(WOLFTPM2_DEV* dev)
166+
static int ctrl_connect(WOLFTPM2_DEV* dev)
167167
{
168168
int rc;
169169

@@ -186,7 +186,7 @@ static int demo_connect(WOLFTPM2_DEV* dev)
186186
return rc;
187187
}
188188

189-
static int demo_lock(WOLFTPM2_DEV* dev, int lock)
189+
static int ctrl_lock(WOLFTPM2_DEV* dev, int lock)
190190
{
191191
int rc;
192192
printf("\n=== SPDM-Only: %s ===\n", lock ? "LOCK" : "UNLOCK");
@@ -220,7 +220,7 @@ static int hex2bin(const char* hex, byte* bin, word32* binSz)
220220
return 0;
221221
}
222222

223-
static int demo_nations_status(WOLFTPM2_DEV* dev)
223+
static int ctrl_nations_status(WOLFTPM2_DEV* dev)
224224
{
225225
int rc;
226226
int isConn;
@@ -277,7 +277,7 @@ static int demo_nations_status(WOLFTPM2_DEV* dev)
277277
return 0; /* status is informational, don't fail */
278278
}
279279

280-
static int demo_nations_psk_connect(WOLFTPM2_DEV* dev, const char* pskHex)
280+
static int ctrl_nations_psk_connect(WOLFTPM2_DEV* dev, const char* pskHex)
281281
{
282282
int rc;
283283
byte psk[128];
@@ -301,7 +301,7 @@ static int demo_nations_psk_connect(WOLFTPM2_DEV* dev, const char* pskHex)
301301
return rc;
302302
}
303303

304-
static int demo_nations_psk_set(WOLFTPM2_DEV* dev,
304+
static int ctrl_nations_psk_set(WOLFTPM2_DEV* dev,
305305
const char* pskHex, const char* clearAuthHex)
306306
{
307307
int rc;
@@ -357,7 +357,7 @@ static int demo_nations_psk_set(WOLFTPM2_DEV* dev,
357357
return rc;
358358
}
359359

360-
static int demo_nations_psk_clear(WOLFTPM2_DEV* dev, const char* authHex)
360+
static int ctrl_nations_psk_clear(WOLFTPM2_DEV* dev, const char* authHex)
361361
{
362362
int rc;
363363
byte clearAuth[256];
@@ -387,7 +387,7 @@ static int demo_nations_psk_clear(WOLFTPM2_DEV* dev, const char* authHex)
387387
return rc;
388388
}
389389

390-
static int demo_nations_identity_key_set(WOLFTPM2_DEV* dev, int set)
390+
static int ctrl_nations_identity_key_set(WOLFTPM2_DEV* dev, int set)
391391
{
392392
int rc;
393393
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)
400400
return rc;
401401
}
402402

403-
static int demo_nations_get_pubkey(WOLFTPM2_DEV* dev)
403+
static int ctrl_nations_get_pubkey(WOLFTPM2_DEV* dev)
404404
{
405405
int rc;
406406
byte pubKey[128];
@@ -428,7 +428,7 @@ static int demo_nations_get_pubkey(WOLFTPM2_DEV* dev)
428428
return rc;
429429
}
430430

431-
static int demo_nations_caps184(WOLFTPM2_DEV* dev)
431+
static int ctrl_nations_caps184(WOLFTPM2_DEV* dev)
432432
{
433433
int rc;
434434
GetCapability_In capIn;
@@ -505,7 +505,7 @@ static int demo_nations_caps184(WOLFTPM2_DEV* dev)
505505
return 0;
506506
}
507507

508-
static int demo_nations_connect(WOLFTPM2_DEV* dev)
508+
static int ctrl_nations_connect(WOLFTPM2_DEV* dev)
509509
{
510510
int rc;
511511

@@ -529,7 +529,7 @@ static int demo_nations_connect(WOLFTPM2_DEV* dev)
529529
}
530530
#endif /* WOLFSPDM_NATIONS */
531531

532-
int TPM2_SPDM_Demo(void* userCtx, int argc, char *argv[])
532+
int TPM2_SPDM_Ctrl(void* userCtx, int argc, char *argv[])
533533
{
534534
int rc, i;
535535
WOLFTPM2_DEV dev;
@@ -568,42 +568,42 @@ int TPM2_SPDM_Demo(void* userCtx, int argc, char *argv[])
568568
for (i = 1; i < argc; i++) {
569569
#ifdef WOLFSPDM_NUVOTON
570570
if (XSTRCMP(argv[i], "--enable") == 0)
571-
rc = demo_enable(&dev);
571+
rc = ctrl_enable(&dev);
572572
else if (XSTRCMP(argv[i], "--disable") == 0)
573-
rc = demo_disable(&dev);
573+
rc = ctrl_disable(&dev);
574574
else if (XSTRCMP(argv[i], "--status") == 0)
575-
rc = demo_status(&dev);
575+
rc = ctrl_status(&dev);
576576
else if (XSTRCMP(argv[i], "--get-pubkey") == 0)
577-
rc = demo_get_pubkey(&dev);
577+
rc = ctrl_get_pubkey(&dev);
578578
else if (XSTRCMP(argv[i], "--connect") == 0)
579-
rc = demo_connect(&dev);
579+
rc = ctrl_connect(&dev);
580580
else if (XSTRCMP(argv[i], "--lock") == 0)
581-
rc = demo_lock(&dev, 1);
581+
rc = ctrl_lock(&dev, 1);
582582
else if (XSTRCMP(argv[i], "--unlock") == 0)
583-
rc = demo_lock(&dev, 0);
583+
rc = ctrl_lock(&dev, 0);
584584
else
585585
#endif
586586
#ifdef WOLFSPDM_NATIONS
587587
if (XSTRCMP(argv[i], "--identity-key-set") == 0)
588-
rc = demo_nations_identity_key_set(&dev, 1);
588+
rc = ctrl_nations_identity_key_set(&dev, 1);
589589
else if (XSTRCMP(argv[i], "--identity-key-unset") == 0)
590-
rc = demo_nations_identity_key_set(&dev, 0);
590+
rc = ctrl_nations_identity_key_set(&dev, 0);
591591
else if (XSTRCMP(argv[i], "--get-pubkey") == 0)
592-
rc = demo_nations_get_pubkey(&dev);
592+
rc = ctrl_nations_get_pubkey(&dev);
593593
else if (XSTRCMP(argv[i], "--connect") == 0)
594-
rc = demo_nations_connect(&dev);
594+
rc = ctrl_nations_connect(&dev);
595595
else if (XSTRCMP(argv[i], "--status") == 0)
596-
rc = demo_nations_status(&dev);
596+
rc = ctrl_nations_status(&dev);
597597
else if (XSTRCMP(argv[i], "--psk") == 0 && i + 1 < argc)
598-
rc = demo_nations_psk_connect(&dev, argv[++i]);
598+
rc = ctrl_nations_psk_connect(&dev, argv[++i]);
599599
else if (XSTRCMP(argv[i], "--psk-set") == 0 && i + 2 < argc)
600600
{
601601
const char* pskArg = argv[++i];
602602
const char* authArg = argv[++i];
603-
rc = demo_nations_psk_set(&dev, pskArg, authArg);
603+
rc = ctrl_nations_psk_set(&dev, pskArg, authArg);
604604
}
605605
else if (XSTRCMP(argv[i], "--psk-clear") == 0 && i + 1 < argc)
606-
rc = demo_nations_psk_clear(&dev, argv[++i]);
606+
rc = ctrl_nations_psk_clear(&dev, argv[++i]);
607607
else if (XSTRCMP(argv[i], "--lock") == 0)
608608
rc = wolfTPM2_SpdmNationsSetOnlyMode(&dev, 1);
609609
else if (XSTRCMP(argv[i], "--unlock") == 0)
@@ -614,7 +614,7 @@ int TPM2_SPDM_Demo(void* userCtx, int argc, char *argv[])
614614
printf(" %s (rc=0x%x)\n", rc == 0 ? "Success" : "FAILED", rc);
615615
}
616616
else if (XSTRCMP(argv[i], "--caps184") == 0)
617-
rc = demo_nations_caps184(&dev);
617+
rc = ctrl_nations_caps184(&dev);
618618
else
619619
#endif
620620
{ printf("Unknown option: %s\n", argv[i]); usage(); rc = BAD_FUNC_ARG; }
@@ -631,7 +631,7 @@ int main(int argc, char *argv[])
631631
{
632632
int rc = -1;
633633
#ifndef WOLFTPM2_NO_WRAPPER
634-
rc = TPM2_SPDM_Demo(NULL, argc, argv);
634+
rc = TPM2_SPDM_Ctrl(NULL, argc, argv);
635635
#else
636636
printf("Wrapper code not compiled in\n");
637637
(void)argc; (void)argv;

examples/spdm/spdm_test.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# along with this program; if not, write to the Free Software
2020
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
2121

22-
SPDM_DEMO="${1:-./examples/spdm/spdm_demo}"
22+
SPDM_DEMO="${1:-./examples/spdm/spdm_ctrl}"
2323
CAPS_DEMO="./examples/wrap/caps"
2424
UNIT_TEST="./tests/unit.test"
2525
GPIO_CHIP="gpiochip0"
@@ -102,7 +102,7 @@ run_test_no_reset() {
102102

103103
if [ ! -x "$SPDM_DEMO" ]; then
104104
echo "Error: $SPDM_DEMO not found."
105-
echo "Usage: $0 [path-to-spdm_demo] [nuvoton|nations|nations-psk]"
105+
echo "Usage: $0 [path-to-spdm_ctrl] [nuvoton|nations|nations-psk]"
106106
exit 1
107107
fi
108108

0 commit comments

Comments
 (0)