Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ build/
examples/wrap/wrap_test
examples/wrap/caps
examples/wrap/hmac
examples/wrap/getrandom
examples/wrap/hash
examples/wrap/encrypt_decrypt
examples/native/native_test
examples/bench/bench
examples/csr/csr
Expand All @@ -56,6 +59,7 @@ examples/pcr/reset
examples/timestamp/clock_set
examples/management/flush
examples/management/tpmclear
examples/management/da_check
pkcs7tpmsigned.p7s
pkcs7tpmsignedex.p7s
examples/tls/tls_server
Expand All @@ -70,6 +74,7 @@ examples/keygen/keyload
examples/keygen/keygen
examples/keygen/keyimport
examples/keygen/external_import
examples/keygen/ecdh
examples/pqc/mldsa_sign
examples/pqc/mlkem_encap
examples/pqc/pqc_mssim_e2e
Expand Down Expand Up @@ -207,6 +212,7 @@ examples/firmware/*.MANIFESTHASH
src/fwtpm/fwtpm_server
fwtpm_nv.bin
fwtpm_test_nv.bin
fwtpm_test_nv.bin.key

# Fuzz artifacts (corpus generated at runtime by gen_corpus.py)
tests/fuzz/corpus/
Expand Down
13 changes: 13 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ The PKCS #7 and TLS examples require generating CSR's and signing them using a t

To enable parameter encryption use `-aes` for AES-CFB mode or `-xor` for XOR mode. Only some TPM commands / responses support parameter encryption. If the TPM2_ API has .flags `CMD_FLAG_ENC2` or `CMD_FLAG_DEC2` set then the command will use parameter encryption / decryption.

On a v1.85 PQC capable TPM the parameter encryption session can also be keyed with a post-quantum primary: pass `-mlkem` to salt the session with an ML-KEM key or `-mldsa` to bind it to an ML-DSA key (`keygen` uses `-paramkey=mlkem|mldsa` since `-mlkem`/`-mldsa` there select the child key). See "Parameter Encryption" below.

There are some vendor specific examples, like the TPM 2.0 extra GPIO examples for ST33 and NPCT75x.

## Native API Test
Expand Down Expand Up @@ -90,6 +92,17 @@ This behavior depends on the `sessionAttributes`:

Either one can be set separately or both can be set in one authorization session. This is up to the user (developer).

### Post-quantum session keys (v1.85)

The parameter encryption session can be keyed with a post-quantum primary instead of an RSA/ECC storage key. ML-KEM is decrypt capable and is used as the session salt key; ML-DSA is sign only and is used as the session bind key. The RSA/ECC storage key (where one is needed, such as the parent of a created child) is unchanged. `wrap_test`, `pcr/quote`, and `nvram/store` and `nvram/counter` accept `-mlkem[=512|768|1024]` and `-mldsa[=44|65|87]`; `keygen` uses `-paramkey=mlkem[=...]` / `-paramkey=mldsa[=...]` because `-mlkem`/`-mldsa` there select the child key. This requires a v1.85 PQC capable TPM.

```sh
./examples/wrap/wrap_test -aes -mlkem=768
./examples/pcr/quote 16 quote.blob -ecc -xor -mldsa=65
./examples/nvram/counter -aes -mldsa=65
./examples/keygen/keygen keyblob.bin -ecc -aes -paramkey=mlkem=768
```

## CSR

Generates a Certificate Signing Request for building a certificate based on a TPM key pair.
Expand Down
12 changes: 9 additions & 3 deletions examples/bench/bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ static int bench_sym_aes(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* storageKey,
return rc;
}

#ifdef WOLFTPM_PQC
#ifdef WOLFTPM_MLDSA
/* Benchmark Pure ML-DSA: key gen, sign and verify (sign/verify sequence). */
static int bench_pqc_mldsa(WOLFTPM2_DEV* dev, double maxDuration,
double maxKeyGenDurSec)
Expand Down Expand Up @@ -291,7 +291,9 @@ static int bench_pqc_mldsa(WOLFTPM2_DEV* dev, double maxDuration,
wolfTPM2_UnloadHandle(dev, &mldsaKey.handle);
return rc;
}
#endif /* WOLFTPM_MLDSA */

#ifdef WOLFTPM_MLKEM
/* Benchmark ML-KEM: key gen, encapsulate and decapsulate. */
static int bench_pqc_mlkem(WOLFTPM2_DEV* dev, double maxDuration,
double maxKeyGenDurSec)
Expand Down Expand Up @@ -353,7 +355,7 @@ static int bench_pqc_mlkem(WOLFTPM2_DEV* dev, double maxDuration,
wolfTPM2_UnloadHandle(dev, &mlkemKey.handle);
return rc;
}
#endif /* WOLFTPM_PQC */
#endif /* WOLFTPM_MLKEM */

static void usage(void)
{
Expand Down Expand Up @@ -677,17 +679,21 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[])
rc = wolfTPM2_UnloadHandle(&dev, &eccKey.handle);
if (rc != 0) goto exit;

#ifdef WOLFTPM_PQC
#if defined(WOLFTPM_MLDSA) || defined(WOLFTPM_MLKEM)
/* Post-quantum (TPM 2.0 v1.85). Skipped under parameter encryption: the
* large PQC public-key responses exceed the parameter-decryption buffer
* (TPM_RC_... BUFFER_E). Free the storage key first so the larger PQC keys
* fit within the TPM's transient object slots. */
if (paramEncAlg == TPM_ALG_NULL) {
wolfTPM2_UnloadHandle(&dev, &storageKey.handle);
#ifdef WOLFTPM_MLDSA
rc = bench_pqc_mldsa(&dev, maxDuration, maxKeyGenDurSec);
if (rc != 0) goto exit;
#endif
#ifdef WOLFTPM_MLKEM
rc = bench_pqc_mlkem(&dev, maxDuration, maxKeyGenDurSec);
if (rc != 0) goto exit;
#endif
}
#endif

Expand Down
60 changes: 60 additions & 0 deletions examples/keygen/create_primary.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ static void usage(void)
printf("Primary Key Type:\n");
printf("\t-rsa: Use RSA for asymmetric key generation (DEFAULT)\n");
printf("\t-ecc: Use ECC for asymmetric key generation \n");
#ifdef WOLFTPM_MLDSA
printf("\t-mldsa[=44|65|87]: Use ML-DSA for primary key generation "
"(v1.85, default 65)\n");
#endif
printf("Hierarchy:\n");
printf("\t-oh: Create keys under the Owner Hierarchy (DEFAULT)\n");
printf("\t-eh: Create keys under the Endorsement Hierarchy\n");
Expand Down Expand Up @@ -77,8 +81,37 @@ static void usage(void)
printf("\t* Create SRK used by wolfTPM:\n");
printf("\t\tcreate_primary -rsa -oh -auth=ThisIsMyStorageKeyAuth "
"-store=0x81000200\n");
#ifdef WOLFTPM_MLDSA
printf("\t* Create an ML-DSA-65 primary key:\n");
printf("\t\tcreate_primary -mldsa -oh\n");
#endif
}

#ifdef WOLFTPM_MLDSA
static int mldsaParamSet(const char* optVal, TPMI_MLDSA_PARAMETER_SET* ps)
Comment thread
dgarske marked this conversation as resolved.
{
int n;
const char* p;

if (optVal[0] == '\0') { /* missing or empty suffix, use default */
*ps = TPM_MLDSA_65;
return TPM_RC_SUCCESS;
}
/* reject non-digit input (e.g. -mldsa=abc) before XATOI */
for (p = optVal; *p != '\0'; p++) {
if (*p < '0' || *p > '9')
return TPM_RC_FAILURE;
}
n = XATOI(optVal);
switch (n) {
case 65: *ps = TPM_MLDSA_65; return TPM_RC_SUCCESS;
case 44: *ps = TPM_MLDSA_44; return TPM_RC_SUCCESS;
case 87: *ps = TPM_MLDSA_87; return TPM_RC_SUCCESS;
default: return TPM_RC_FAILURE;
}
}
#endif /* WOLFTPM_MLDSA */

int TPM2_CreatePrimaryKey_Example(void* userCtx, int argc, char *argv[])
{
int rc;
Expand All @@ -98,6 +131,9 @@ int TPM2_CreatePrimaryKey_Example(void* userCtx, int argc, char *argv[])
#ifdef WOLFTPM_PROVISIONING
int useIAKTemplate = 0, useIDevIDTemplate = 0;
#endif
#ifdef WOLFTPM_MLDSA
TPMI_MLDSA_PARAMETER_SET mldsaPs = TPM_MLDSA_65; /* default param set */
#endif

if (argc >= 2) {
if (XSTRCMP(argv[1], "-?") == 0 ||
Expand All @@ -114,6 +150,19 @@ int TPM2_CreatePrimaryKey_Example(void* userCtx, int argc, char *argv[])
else if (XSTRCMP(argv[argc-1], "-ecc") == 0) {
alg = TPM_ALG_ECC;
}
#ifdef WOLFTPM_MLDSA
else if (XSTRCMP(argv[argc-1], "-mldsa") == 0 ||
XSTRNCMP(argv[argc-1], "-mldsa=",
XSTRLEN("-mldsa=")) == 0) {
const char* optVal = (argv[argc-1][6] == '=') ?
argv[argc-1] + 7 : "";
if (mldsaParamSet(optVal, &mldsaPs) != TPM_RC_SUCCESS) {
usage();
return -1;
}
alg = TPM_ALG_MLDSA;
}
#endif
else if (XSTRCMP(argv[argc-1], "-aes") == 0) {
paramEncAlg = TPM_ALG_CFB;
}
Expand Down Expand Up @@ -221,6 +270,17 @@ int TPM2_CreatePrimaryKey_Example(void* userCtx, int argc, char *argv[])
else
rc = wolfTPM2_GetKeyTemplate_ECC_SRK(&publicTemplate);
}
#ifdef WOLFTPM_MLDSA
else if (alg == TPM_ALG_MLDSA) {
/* ML-DSA is sign-only and has no AIK/IAK/IDevID variant; the
* wrapper enforces TPMA_OBJECT_sign and clears decrypt. */
rc = wolfTPM2_GetKeyTemplate_MLDSA(&publicTemplate,
TPMA_OBJECT_sign | TPMA_OBJECT_fixedTPM |
TPMA_OBJECT_fixedParent | TPMA_OBJECT_sensitiveDataOrigin |
TPMA_OBJECT_userWithAuth | TPMA_OBJECT_noDA,
mldsaPs, 0 /* allowExternalMu: 0 avoids TPM_RC_EXT_MU */);
}
#endif
else {
rc = BAD_FUNC_ARG;
}
Expand Down
Loading
Loading