Add PQC parameter encryption and ML-DSA support to examples

pull/531/head
David Garske 2026-06-25 11:20:37 -07:00
parent 74f428bdfb
commit 0f51da58d0
10 changed files with 556 additions and 34 deletions

View File

@ -215,7 +215,7 @@ exit:
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)
@ -291,7 +291,9 @@ exit:
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)
@ -353,7 +355,7 @@ exit:
wolfTPM2_UnloadHandle(dev, &mlkemKey.handle);
return rc;
}
#endif /* WOLFTPM_PQC */
#endif /* WOLFTPM_MLKEM */
static void usage(void)
{
@ -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

View File

@ -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");
@ -77,8 +81,26 @@ 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)
{
int n = XATOI(optVal);
switch (n) {
case 0: /* missing or empty suffix, use default */
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;
@ -98,6 +120,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 ||
@ -114,6 +139,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 0;
}
alg = TPM_ALG_MLDSA;
}
#endif
else if (XSTRCMP(argv[argc-1], "-aes") == 0) {
paramEncAlg = TPM_ALG_CFB;
}
@ -221,6 +259,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;
}

View File

@ -75,15 +75,27 @@ static void usage(void)
printf("* -sym: Use Symmetric Cipher for key generation\n");
printf("\tDefault Symmetric Cipher is AES CTR with 256 bits\n");
printf("* -keyedhash: Use Keyed Hash for key generation\n");
#ifdef WOLFTPM_PQC
#ifdef WOLFTPM_MLDSA
printf("* -mldsa[=44|65|87]: Use ML-DSA for signing (v1.85, default 65)\n");
#endif
#ifdef WOLFTPM_HASH_MLDSA
printf("* -hash_mldsa[=44|65|87]: Use Hash-ML-DSA for signing "
"(v1.85, default 65 with SHA-256 pre-hash)\n");
#endif
#ifdef WOLFTPM_MLKEM
printf("* -mlkem[=512|768|1024]: Use ML-KEM for key encapsulation "
"(v1.85, default 768)\n");
#endif
printf("* -t: Use default template (otherwise AIK)\n");
printf("* -aes/xor: Use Parameter Encryption\n");
#ifdef WOLFTPM_MLKEM
printf("* -paramkey=mlkem[=512|768|1024]: Use an ML-KEM key as the "
"param-enc session salt (v1.85, default 768)\n");
#endif
#ifdef WOLFTPM_MLDSA
printf("* -paramkey=mldsa[=44|65|87]: Use an ML-DSA key as the "
"param-enc session bind (v1.85, default 65)\n");
#endif
printf("* -unique=[value]\n");
printf("\t* Used for the KDF of the create\n");
printf("* -auth=pass: Use custom password for key authentication\n");
@ -102,17 +114,21 @@ static void usage(void)
printf("\t* Symmetric key, AES, CBC mode, 128 bits, "\
"with XOR parameter encryption\n");
printf("\t\t keygen -sym=aescbc256 -xor\n");
#ifdef WOLFTPM_PQC
#ifdef WOLFTPM_MLDSA
printf("\t* ML-DSA-65 signing key\n");
printf("\t\t keygen -mldsa\n");
#endif
#ifdef WOLFTPM_HASH_MLDSA
printf("\t* Hash-ML-DSA-87 with SHA-256 pre-hash\n");
printf("\t\t keygen -hash_mldsa=87\n");
#endif
#ifdef WOLFTPM_MLKEM
printf("\t* ML-KEM-1024 key encapsulation key\n");
printf("\t\t keygen -mlkem=1024\n");
#endif
}
#ifdef WOLFTPM_PQC
#ifdef WOLFTPM_MLDSA
static int mldsaParamSet(const char* optVal, TPMI_MLDSA_PARAMETER_SET* ps)
{
int n = XATOI(optVal);
@ -124,7 +140,9 @@ static int mldsaParamSet(const char* optVal, TPMI_MLDSA_PARAMETER_SET* ps)
default: return TPM_RC_FAILURE;
}
}
#endif /* WOLFTPM_MLDSA */
#ifdef WOLFTPM_MLKEM
static int mlkemParamSet(const char* optVal, TPMI_MLKEM_PARAMETER_SET* ps)
{
int n = XATOI(optVal);
@ -136,7 +154,7 @@ static int mlkemParamSet(const char* optVal, TPMI_MLKEM_PARAMETER_SET* ps)
default: return TPM_RC_FAILURE;
}
}
#endif /* WOLFTPM_PQC */
#endif /* WOLFTPM_MLKEM */
static int symChoice(const char* symMode, TPM_ALG_ID* algSym, int* keyBits)
{
@ -176,8 +194,15 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
TPMI_ALG_PUBLIC srkAlg = TPM_ALG_RSA; /* default matches seal.c / keyload.c */
TPM_ALG_ID algSym = TPM_ALG_CTR; /* default Symmetric Cipher, see usage */
TPM_ALG_ID paramEncAlg = TPM_ALG_NULL;
#ifdef WOLFTPM_PQC
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
TPM_ALG_ID pqcParamEncAlg = TPM_ALG_NULL;
int pqcParamSet = 0;
WOLFTPM2_KEY pqcKey;
#endif
#ifdef WOLFTPM_MLDSA
TPMI_MLDSA_PARAMETER_SET mldsaPs = TPM_MLDSA_65; /* default */
#endif
#ifdef WOLFTPM_MLKEM
TPMI_MLKEM_PARAMETER_SET mlkemPs = TPM_MLKEM_768; /* default */
#endif
WOLFTPM2_SESSION tpmSession;
@ -228,7 +253,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
alg = TPM_ALG_KEYEDHASH;
bAIK = 0;
}
#ifdef WOLFTPM_PQC
#ifdef WOLFTPM_MLDSA
else if (XSTRCMP(argv[argc-1], "-mldsa") == 0 ||
XSTRNCMP(argv[argc-1], "-mldsa=",
XSTRLEN("-mldsa=")) == 0) {
@ -241,6 +266,8 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
alg = TPM_ALG_MLDSA;
bAIK = 0;
}
#endif /* WOLFTPM_MLDSA */
#ifdef WOLFTPM_HASH_MLDSA
else if (XSTRCMP(argv[argc-1], "-hash_mldsa") == 0 ||
XSTRNCMP(argv[argc-1], "-hash_mldsa=",
XSTRLEN("-hash_mldsa=")) == 0) {
@ -253,6 +280,8 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
alg = TPM_ALG_HASH_MLDSA;
bAIK = 0;
}
#endif /* WOLFTPM_HASH_MLDSA */
#ifdef WOLFTPM_MLKEM
else if (XSTRCMP(argv[argc-1], "-mlkem") == 0 ||
XSTRNCMP(argv[argc-1], "-mlkem=",
XSTRLEN("-mlkem=")) == 0) {
@ -265,7 +294,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
alg = TPM_ALG_MLKEM;
bAIK = 0;
}
#endif /* WOLFTPM_PQC */
#endif /* WOLFTPM_MLKEM */
else if (XSTRCMP(argv[argc-1], "-t") == 0) {
bAIK = 0;
}
@ -281,6 +310,18 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
else if (XSTRCMP(argv[argc-1], "-xor") == 0) {
paramEncAlg = TPM_ALG_XOR;
}
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
else if (XSTRNCMP(argv[argc-1], "-paramkey=",
XSTRLEN("-paramkey=")) == 0) {
/* PQC key for the param-enc session, e.g. "mlkem=768"/"mldsa=65" */
const char* pkVal = argv[argc-1] + XSTRLEN("-paramkey=");
if (parsePqcParamSet(pkVal, &pqcParamEncAlg, &pqcParamSet) != 1) {
printf("Invalid -paramkey value: %s\n", pkVal);
usage();
return 0;
}
}
#endif
else if (XSTRNCMP(argv[argc-1], "-unique=", XSTRLEN("-unique=")) == 0) {
uniqueStr = argv[argc-1] + XSTRLEN("-unique=");
}
@ -310,6 +351,9 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
XMEMSET(&primaryBlob, 0, sizeof(primaryBlob));
XMEMSET(&tpmSession, 0, sizeof(tpmSession));
XMEMSET(&auth, 0, sizeof(auth));
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
XMEMSET(&pqcKey, 0, sizeof(pqcKey));
#endif
/* Only use the ECC SRK for ECC child keys; RSA, SYMCIPHER, KEYEDHASH
* all stay on the RSA SRK so that keyload/seal can round-trip them. */
@ -323,6 +367,16 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
}
}
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
/* A PQC param-enc key only supplies the salt/bind material; a symmetric
* session cipher is still required. Default to AES-CFB if none given. */
if (pqcParamEncAlg != TPM_ALG_NULL && paramEncAlg == TPM_ALG_NULL) {
paramEncAlg = TPM_ALG_CFB;
printf("PQC param-enc key selected; defaulting session cipher to "
"AES-CFB.\n");
}
#endif
printf("TPM2.0 Key generation example\n");
printf("\tKey Blob: %s\n", outputFile);
printf("\tAlgorithm: %s\n", TPM2_GetAlgName(alg));
@ -364,9 +418,20 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
if (srkAlg == TPM_ALG_RSA)
bindKey = NULL; /* cannot bind to key without RSA enabled */
#endif
/* Start an authenticated session (salted / unbound) with parameter encryption */
rc = wolfTPM2_StartSession(&dev, &tpmSession, bindKey, NULL,
TPM_SE_HMAC, paramEncAlg);
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
if (pqcParamEncAlg != TPM_ALG_NULL) {
/* Use a PQC primary as the param-enc session key: ML-KEM salt
* or ML-DSA bind. This replaces the salted-to-SRK session. */
rc = getPrimaryParamEncKey(&dev, &tpmSession, &pqcKey,
pqcParamEncAlg, pqcParamSet, paramEncAlg);
}
else
#endif
{
/* Start an authenticated session (salted / unbound) with parameter encryption */
rc = wolfTPM2_StartSession(&dev, &tpmSession, bindKey, NULL,
TPM_SE_HMAC, paramEncAlg);
}
if (rc != 0) goto exit;
printf("HMAC Session: Handle 0x%x\n",
(word32)tpmSession.handle.hndl);
@ -405,7 +470,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
"not symmetric or keyedhash keys.\n");
rc = BAD_FUNC_ARG;
}
#ifdef WOLFTPM_PQC
#if defined(WOLFTPM_MLDSA) || defined(WOLFTPM_MLKEM)
else if (alg == TPM_ALG_MLDSA || alg == TPM_ALG_HASH_MLDSA ||
alg == TPM_ALG_MLKEM) {
printf("AIK template is RSA or ECC only; PQC keys use their "
@ -454,7 +519,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
TPM_ALG_SHA256, YES, NO);
publicTemplate.objectAttributes |= TPMA_OBJECT_sensitiveDataOrigin;
}
#ifdef WOLFTPM_PQC
#ifdef WOLFTPM_MLDSA
else if (alg == TPM_ALG_MLDSA) {
printf("ML-DSA template (parameter set %u)\n",
(unsigned)mldsaPs);
@ -462,10 +527,12 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
TPMA_OBJECT_sign | TPMA_OBJECT_fixedTPM |
TPMA_OBJECT_fixedParent | TPMA_OBJECT_sensitiveDataOrigin |
TPMA_OBJECT_userWithAuth | TPMA_OBJECT_noDA,
mldsaPs, 0 /* allowExternalMu TPM_RC_EXT_MU at create
mldsaPs, 0 /* allowExternalMu - TPM_RC_EXT_MU at create
* per Part 2 Sec.12.2.3.6 when SET on a TPM
* without μ-direct sign support */);
* without mu-direct sign support */);
}
#endif /* WOLFTPM_MLDSA */
#ifdef WOLFTPM_HASH_MLDSA
else if (alg == TPM_ALG_HASH_MLDSA) {
printf("Hash-ML-DSA template (parameter set %u, pre-hash %s)\n",
(unsigned)mldsaPs, TPM2_GetAlgName(TPM_ALG_SHA256));
@ -475,6 +542,8 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
TPMA_OBJECT_userWithAuth | TPMA_OBJECT_noDA,
mldsaPs, TPM_ALG_SHA256);
}
#endif /* WOLFTPM_HASH_MLDSA */
#ifdef WOLFTPM_MLKEM
else if (alg == TPM_ALG_MLKEM) {
printf("ML-KEM template (parameter set %u)\n",
(unsigned)mlkemPs);
@ -484,7 +553,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
TPMA_OBJECT_userWithAuth | TPMA_OBJECT_noDA,
mlkemPs);
}
#endif /* WOLFTPM_PQC */
#endif /* WOLFTPM_MLKEM */
else {
rc = BAD_FUNC_ARG;
}
@ -613,6 +682,9 @@ exit:
wolfTPM2_UnloadHandle(&dev, &primary->handle);
wolfTPM2_UnloadHandle(&dev, &newKeyBlob.handle);
wolfTPM2_UnloadHandle(&dev, &tpmSession.handle);
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
wolfTPM2_UnloadHandle(&dev, &pqcKey.handle);
#endif
wolfTPM2_Cleanup(&dev);
return rc;

View File

@ -50,6 +50,14 @@ static void usage(void)
printf("./examples/nvram/counter [-nvindex=] [-aes/-xor]\n");
printf("* -nvindex=[handle] (default 0x%x)\n", TPM2_DEMO_NV_COUNTER_INDEX);
printf("* -aes/xor: Use Parameter Encryption\n");
#ifdef WOLFTPM_MLKEM
printf("* -mlkem[=512|768|1024]: Use an ML-KEM key as the param-enc "
"session salt (v1.85, default 768)\n");
#endif
#ifdef WOLFTPM_MLDSA
printf("* -mldsa[=44|65|87]: Use an ML-DSA key as the param-enc "
"session bind (v1.85, default 65)\n");
#endif
}
int TPM2_NVRAM_Counter_Example(void* userCtx, int argc, char *argv[])
@ -63,12 +71,20 @@ int TPM2_NVRAM_Counter_Example(void* userCtx, int argc, char *argv[])
TPMS_NV_PUBLIC nvPublic;
TPMI_RH_NV_AUTH authHandle = TPM_RH_OWNER; /* or TPM_RH_PLATFORM */
int paramEncAlg = TPM_ALG_NULL;
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
TPM_ALG_ID pqcParamEncAlg = TPM_ALG_NULL;
int pqcParamSet = 0;
WOLFTPM2_KEY pqcKey;
#endif
word32 nvIndex = TPM2_DEMO_NV_COUNTER_INDEX;
XMEMSET(&tpmSession, 0, sizeof(tpmSession));
XMEMSET(&parent, 0, sizeof(parent));
XMEMSET(&nv, 0, sizeof(nv));
XMEMSET(&storage, 0, sizeof(storage));
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
XMEMSET(&pqcKey, 0, sizeof(pqcKey));
#endif
if (argc >= 2) {
if (XSTRCMP(argv[1], "-?") == 0 ||
@ -104,6 +120,17 @@ int TPM2_NVRAM_Counter_Example(void* userCtx, int argc, char *argv[])
else if (XSTRCMP(argv[argc-1], "-xor") == 0) {
paramEncAlg = TPM_ALG_XOR;
}
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
else if (parsePqcParamEncArg(argv[argc-1], &pqcParamEncAlg,
&pqcParamSet) != 0) {
/* PQC option; an unsupported parameter set (alg left NULL) is a
* fatal typo, not a silent drop of parameter encryption. */
if (pqcParamEncAlg == TPM_ALG_NULL) {
usage();
return 0;
}
}
#endif
else {
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);
}
@ -111,6 +138,16 @@ int TPM2_NVRAM_Counter_Example(void* userCtx, int argc, char *argv[])
argc--;
}
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
/* A PQC param-enc key only supplies the salt/bind material; a symmetric
* session cipher is still required. Default to AES-CFB if none given. */
if (pqcParamEncAlg != TPM_ALG_NULL && paramEncAlg == TPM_ALG_NULL) {
paramEncAlg = TPM_ALG_CFB;
printf("PQC param-enc key selected; defaulting session cipher to "
"AES-CFB.\n");
}
#endif
printf("NV Counter: NV Index 0x%x\n", nvIndex);
if (paramEncAlg == TPM_ALG_CFB) {
printf("Parameter Encryption: Enabled. (AES CFB)\n\n");
@ -130,9 +167,20 @@ int TPM2_NVRAM_Counter_Example(void* userCtx, int argc, char *argv[])
}
if (paramEncAlg != TPM_ALG_NULL) {
/* Start TPM session for parameter encryption */
rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL,
TPM_SE_HMAC, paramEncAlg);
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
if (pqcParamEncAlg != TPM_ALG_NULL) {
/* Use a PQC primary as the param-enc session key: ML-KEM salt
* or ML-DSA bind. */
rc = getPrimaryParamEncKey(&dev, &tpmSession, &pqcKey,
pqcParamEncAlg, pqcParamSet, paramEncAlg);
}
else
#endif
{
/* Start TPM session for parameter encryption */
rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL,
TPM_SE_HMAC, paramEncAlg);
}
if (rc != 0) goto exit;
printf("TPM2_StartAuthSession: sessionHandle 0x%x\n",
(word32)tpmSession.handle.hndl);
@ -160,8 +208,6 @@ int TPM2_NVRAM_Counter_Example(void* userCtx, int argc, char *argv[])
nvAttributes, 8, (byte*)gNvAuth, sizeof(gNvAuth)-1);
if (rc != 0) goto exit;
wolfTPM2_SetAuthHandle(&dev, 0, &nv.handle);
rc = wolfTPM2_NVReadPublic(&dev, nvIndex, &nvPublic);
}
if (rc != TPM_RC_SUCCESS) {
@ -178,6 +224,11 @@ int TPM2_NVRAM_Counter_Example(void* userCtx, int argc, char *argv[])
goto exit;
}
/* Set the NV index auth in slot 0 (slot 1 holds the param-enc session). A
* salted/PQC param-enc session leaves slot 0 pointing at the salt key, so
* reset it here for both the create and existing-index paths. */
wolfTPM2_SetAuthHandle(&dev, 0, &nv.handle);
rc = wolfTPM2_NVIncrement(&dev, &nv);
if (rc != TPM_RC_SUCCESS) {
printf("NV Increment failed\n");
@ -191,6 +242,9 @@ exit:
}
wolfTPM2_UnloadHandle(&dev, &tpmSession.handle);
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
wolfTPM2_UnloadHandle(&dev, &pqcKey.handle);
#endif
wolfTPM2_Cleanup(&dev);
return rc;

View File

@ -57,6 +57,14 @@ static void usage(void)
printf("* -priv: Store only the private part of the key\n");
printf("* -pub: Store only the public part of the key\n");
printf("* -aes/xor: Use Parameter Encryption\n");
#ifdef WOLFTPM_MLKEM
printf("* -mlkem[=512|768|1024]: Use an ML-KEM key as the param-enc "
"session salt (v1.85, default 768)\n");
#endif
#ifdef WOLFTPM_MLDSA
printf("* -mldsa[=44|65|87]: Use an ML-DSA key as the param-enc "
"session bind (v1.85, default 65)\n");
#endif
}
int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[])
@ -71,6 +79,11 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[])
TPMI_RH_NV_AUTH authHandle = TPM_RH_OWNER; /* or TPM_RH_PLATFORM */
const char* filename = "keyblob.bin";
int paramEncAlg = TPM_ALG_NULL;
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
TPM_ALG_ID pqcParamEncAlg = TPM_ALG_NULL;
int pqcParamSet = 0;
WOLFTPM2_KEY pqcKey;
#endif
int partialStore = 0;
int offset = 0;
/* Needed for TPM2_AppendPublic */
@ -121,6 +134,17 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[])
else if (XSTRCMP(argv[argc-1], "-pub") == 0) {
partialStore = PUBLIC_PART_ONLY;
}
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
else if (parsePqcParamEncArg(argv[argc-1], &pqcParamEncAlg,
&pqcParamSet) != 0) {
/* PQC option; an unsupported parameter set (alg left NULL) is a
* fatal typo, not a silent drop of parameter encryption. */
if (pqcParamEncAlg == TPM_ALG_NULL) {
usage();
return 0;
}
}
#endif
else if (argv[argc-1][0] != '-') {
filename = argv[argc-1];
}
@ -130,6 +154,16 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[])
argc--;
};
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
/* A PQC param-enc key only supplies the salt/bind material; a symmetric
* session cipher is still required. Default to AES-CFB if none given. */
if (pqcParamEncAlg != TPM_ALG_NULL && paramEncAlg == TPM_ALG_NULL) {
paramEncAlg = TPM_ALG_CFB;
printf("PQC param-enc key selected; defaulting session cipher to "
"AES-CFB.\n");
}
#endif
if (paramEncAlg == TPM_ALG_CFB) {
printf("Parameter Encryption: Enabled. (AES CFB)\n\n");
}
@ -144,6 +178,9 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[])
XMEMSET(&keyBlob, 0, sizeof(keyBlob));
XMEMSET(&tpmSession, 0, sizeof(tpmSession));
XMEMSET(&parent, 0, sizeof(parent));
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
XMEMSET(&pqcKey, 0, sizeof(pqcKey));
#endif
rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx);
if (rc != TPM_RC_SUCCESS) {
@ -152,9 +189,20 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[])
}
if (paramEncAlg != TPM_ALG_NULL) {
/* Start TPM session for parameter encryption */
rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL,
TPM_SE_HMAC, paramEncAlg);
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
if (pqcParamEncAlg != TPM_ALG_NULL) {
/* Use a PQC primary as the param-enc session key: ML-KEM salt
* or ML-DSA bind. */
rc = getPrimaryParamEncKey(&dev, &tpmSession, &pqcKey,
pqcParamEncAlg, pqcParamSet, paramEncAlg);
}
else
#endif
{
/* Start TPM session for parameter encryption */
rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL,
TPM_SE_HMAC, paramEncAlg);
}
if (rc != 0) goto exit;
printf("TPM2_StartAuthSession: sessionHandle 0x%x\n",
(word32)tpmSession.handle.hndl);
@ -246,6 +294,9 @@ exit:
}
wolfTPM2_UnloadHandle(&dev, &tpmSession.handle);
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
wolfTPM2_UnloadHandle(&dev, &pqcKey.handle);
#endif
wolfTPM2_Cleanup(&dev);
return rc;

View File

@ -49,6 +49,14 @@ static void usage(void)
printf("* filename: for saving the TPMS_ATTEST structure to a file\n");
printf("* -ecc: Use RSA or ECC for SRK/AIK\n");
printf("* -aes/xor: Use Parameter Encryption\n");
#ifdef WOLFTPM_MLKEM
printf("* -mlkem[=512|768|1024]: Use an ML-KEM key as the param-enc "
"session salt (v1.85, default 768)\n");
#endif
#ifdef WOLFTPM_MLDSA
printf("* -mldsa[=44|65|87]: Use an ML-DSA key as the param-enc "
"session bind (v1.85, default 65)\n");
#endif
printf("Demo usage without parameters, generates quote over PCR%d and\n"
"saves the output TPMS_ATTEST structure to \"quote.blob\" file.\n",
TPM2_TEST_PCR);
@ -80,6 +88,11 @@ int TPM2_PCR_Quote_Test(void* userCtx, int argc, char *argv[])
} cmdOut;
TPM_ALG_ID paramEncAlg = TPM_ALG_NULL;
WOLFTPM2_SESSION tpmSession;
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
TPM_ALG_ID pqcParamEncAlg = TPM_ALG_NULL;
int pqcParamSet = 0;
WOLFTPM2_KEY pqcKey;
#endif
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
XFILE f;
#endif
@ -87,6 +100,9 @@ int TPM2_PCR_Quote_Test(void* userCtx, int argc, char *argv[])
XMEMSET(&storage, 0, sizeof(storage));
XMEMSET(&aik, 0, sizeof(aik));
XMEMSET(&tpmSession, 0, sizeof(tpmSession));
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
XMEMSET(&pqcKey, 0, sizeof(pqcKey));
#endif
if (argc >= 2) {
if (XSTRCMP(argv[1], "-?") == 0 ||
@ -123,9 +139,30 @@ int TPM2_PCR_Quote_Test(void* userCtx, int argc, char *argv[])
else if (XSTRCMP(argv[argc-1], "-xor") == 0) {
paramEncAlg = TPM_ALG_XOR;
}
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
else if (parsePqcParamEncArg(argv[argc-1], &pqcParamEncAlg,
&pqcParamSet) != 0) {
/* PQC option; an unsupported parameter set (alg left NULL) is a
* fatal typo, not a silent drop of parameter encryption. */
if (pqcParamEncAlg == TPM_ALG_NULL) {
usage();
return 0;
}
}
#endif
argc--;
}
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
/* A PQC param-enc key only supplies the salt/bind material; a symmetric
* session cipher is still required. Default to AES-CFB if none given. */
if (pqcParamEncAlg != TPM_ALG_NULL && paramEncAlg == TPM_ALG_NULL) {
paramEncAlg = TPM_ALG_CFB;
printf("PQC param-enc key selected; defaulting session cipher to "
"AES-CFB.\n");
}
#endif
printf("PCR Quote example - Demo of signed PCR measurement\n");
printf("\tOutput file: %s\n", outputFile);
printf("\tPCR Index: %d\n", pcrIndex);
@ -198,9 +235,20 @@ int TPM2_PCR_Quote_Test(void* userCtx, int argc, char *argv[])
if (alg == TPM_ALG_RSA)
bindKey = NULL; /* cannot bind to key without RSA enabled */
#endif
/* Start an authenticated session (salted / unbound) with parameter encryption */
rc = wolfTPM2_StartSession(&dev, &tpmSession, bindKey, NULL,
TPM_SE_HMAC, paramEncAlg);
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
if (pqcParamEncAlg != TPM_ALG_NULL) {
/* Use a PQC primary as the param-enc session key: ML-KEM salt
* or ML-DSA bind. The RSA/ECC SRK stays the AIK parent. */
rc = getPrimaryParamEncKey(&dev, &tpmSession, &pqcKey,
pqcParamEncAlg, pqcParamSet, paramEncAlg);
}
else
#endif
{
/* Start an authenticated session (salted / unbound) with parameter encryption */
rc = wolfTPM2_StartSession(&dev, &tpmSession, bindKey, NULL,
TPM_SE_HMAC, paramEncAlg);
}
if (rc != 0) goto exit;
printf("TPM2_StartAuthSession: sessionHandle 0x%x\n",
(word32)tpmSession.handle.hndl);
@ -334,6 +382,9 @@ exit:
wolfTPM2_UnloadHandle(&dev, &aik.handle);
wolfTPM2_UnloadHandle(&dev, &storage.handle);
wolfTPM2_UnloadHandle(&dev, &tpmSession.handle);
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
wolfTPM2_UnloadHandle(&dev, &pqcKey.handle);
#endif
wolfTPM2_Cleanup(&dev);

View File

@ -430,6 +430,168 @@ int getPrimaryStoragekey(WOLFTPM2_DEV* pDev, WOLFTPM2_KEY* pStorageKey,
return rc;
}
#if defined(WOLFTPM_MLDSA) || defined(WOLFTPM_MLKEM)
int getPrimaryParamEncKey(WOLFTPM2_DEV* pDev, WOLFTPM2_SESSION* session,
WOLFTPM2_KEY* pqcKey, TPM_ALG_ID pqcAlg, int paramSet, int paramEncAlg)
{
int rc;
TPMT_PUBLIC publicTemplate;
#ifdef WOLFTPM_MLDSA
WOLFTPM2_KEY saltKey; /* transient SRK salt for the ML-DSA bound session */
#if !defined(NO_RSA)
TPM_ALG_ID saltAlg = TPM_ALG_RSA;
#else
TPM_ALG_ID saltAlg = TPM_ALG_ECC;
#endif
#endif
const char* pqcAuth = "pqcParamEnc"; /* primary userAuth; the bind auth for
* ML-DSA, immaterial for the ML-KEM
* salt key */
if (pDev == NULL || session == NULL || pqcKey == NULL)
return BAD_FUNC_ARG;
XMEMSET(pqcKey, 0, sizeof(*pqcKey));
XMEMSET(&publicTemplate, 0, sizeof(publicTemplate));
#ifdef WOLFTPM_MLDSA
XMEMSET(&saltKey, 0, sizeof(saltKey));
#endif
if (pqcAlg == TPM_ALG_MLKEM) {
#ifdef WOLFTPM_MLKEM
/* ML-KEM salt key: restricted decryption, which requires a symmetric
* definition (a TPM rejects a restricted key without one). */
rc = wolfTPM2_GetKeyTemplate_MLKEM(&publicTemplate,
TPMA_OBJECT_decrypt | TPMA_OBJECT_restricted |
TPMA_OBJECT_fixedTPM | TPMA_OBJECT_fixedParent |
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_noDA, (TPMI_MLKEM_PARAMETER_SET)paramSet);
if (rc == TPM_RC_SUCCESS) {
publicTemplate.parameters.mlkemDetail.symmetric.algorithm =
TPM_ALG_AES;
publicTemplate.parameters.mlkemDetail.symmetric.keyBits.aes = 128;
publicTemplate.parameters.mlkemDetail.symmetric.mode.aes =
TPM_ALG_CFB;
}
#else
(void)paramSet;
return NOT_COMPILED_IN;
#endif
}
else if (pqcAlg == TPM_ALG_MLDSA) {
#ifdef WOLFTPM_MLDSA
/* ML-DSA is sign-only; it can only be a session bind entity. */
rc = wolfTPM2_GetKeyTemplate_MLDSA(&publicTemplate,
TPMA_OBJECT_sign | TPMA_OBJECT_fixedTPM |
TPMA_OBJECT_fixedParent | TPMA_OBJECT_sensitiveDataOrigin |
TPMA_OBJECT_userWithAuth | TPMA_OBJECT_noDA,
(TPMI_MLDSA_PARAMETER_SET)paramSet, 0);
#else
(void)paramSet;
return NOT_COMPILED_IN;
#endif
}
else {
return BAD_FUNC_ARG;
}
if (rc != TPM_RC_SUCCESS)
return rc;
rc = wolfTPM2_CreatePrimaryKey(pDev, pqcKey, TPM_RH_OWNER, &publicTemplate,
(const byte*)pqcAuth, (int)XSTRLEN(pqcAuth));
if (rc != TPM_RC_SUCCESS)
return rc;
printf("PQC param-enc key: %s primary 0x%x\n", TPM2_GetAlgName(pqcAlg),
(word32)pqcKey->handle.hndl);
/* ML-KEM keys the session salt (tpmKey). ML-DSA is sign-only so it can
* only bind; a transient SRK provides the salt (confidentiality) while the
* ML-DSA key supplies the binding. */
if (pqcAlg == TPM_ALG_MLKEM) {
rc = wolfTPM2_StartSession(pDev, session, pqcKey, NULL,
TPM_SE_HMAC, paramEncAlg);
}
else {
#ifdef WOLFTPM_MLDSA
rc = wolfTPM2_CreateSRK(pDev, &saltKey, saltAlg, NULL, 0);
if (rc == TPM_RC_SUCCESS) {
rc = wolfTPM2_StartSession(pDev, session, &saltKey,
&pqcKey->handle, TPM_SE_HMAC, paramEncAlg);
/* salt is baked into the session key; drop the salt key handle */
wolfTPM2_UnloadHandle(pDev, &saltKey.handle);
}
#endif
}
if (rc != TPM_RC_SUCCESS) {
printf("PQC param-enc StartSession failed 0x%x: %s\n", rc,
TPM2_GetRCString(rc));
wolfTPM2_UnloadHandle(pDev, &pqcKey->handle);
XMEMSET(pqcKey, 0, sizeof(*pqcKey));
}
return rc;
}
/* Returns 1 and sets the alg and paramSet outputs for a valid PQC value, -1 if
* the value names a PQC algorithm but with an unsupported parameter set
* (message printed), or 0 if it is not a PQC option. Outputs are committed
* only on success. An empty suffix ("mlkem=") uses the default like "mlkem". */
int parsePqcParamSet(const char* val, TPM_ALG_ID* alg, int* paramSet)
{
int n;
int localSet;
if (val == NULL || alg == NULL || paramSet == NULL)
return 0;
#ifdef WOLFTPM_MLKEM
if (XSTRCMP(val, "mlkem") == 0 ||
XSTRNCMP(val, "mlkem=", 6) == 0) {
n = (val[5] == '=' && val[6] != '\0') ? XATOI(&val[6]) : 768;
if (n == 512)
localSet = TPM_MLKEM_512;
else if (n == 768)
localSet = TPM_MLKEM_768;
else if (n == 1024)
localSet = TPM_MLKEM_1024;
else {
printf("Invalid ML-KEM parameter set: %d (use 512, 768, or 1024)\n",
n);
return -1;
}
*alg = TPM_ALG_MLKEM;
*paramSet = localSet;
return 1;
}
#endif
#ifdef WOLFTPM_MLDSA
if (XSTRCMP(val, "mldsa") == 0 ||
XSTRNCMP(val, "mldsa=", 6) == 0) {
n = (val[5] == '=' && val[6] != '\0') ? XATOI(&val[6]) : 65;
if (n == 44)
localSet = TPM_MLDSA_44;
else if (n == 65)
localSet = TPM_MLDSA_65;
else if (n == 87)
localSet = TPM_MLDSA_87;
else {
printf("Invalid ML-DSA parameter set: %d (use 44, 65, or 87)\n", n);
return -1;
}
*alg = TPM_ALG_MLDSA;
*paramSet = localSet;
return 1;
}
#endif
return 0;
}
int parsePqcParamEncArg(const char* arg, TPM_ALG_ID* alg, int* paramSet)
{
if (arg == NULL || arg[0] != '-')
return 0;
return parsePqcParamSet(arg + 1, alg, paramSet);
}
#endif /* WOLFTPM_MLDSA || WOLFTPM_MLKEM */
int getRSAkey(WOLFTPM2_DEV* pDev, WOLFTPM2_KEY* pStorageKey, WOLFTPM2_KEY* key,
void* pWolfRsaKey, int tpmDevId, const byte* auth, int authSz,
TPMT_PUBLIC* publicTemplate)

View File

@ -52,6 +52,29 @@ WOLFTPM_LOCAL int getPrimaryStoragekey(WOLFTPM2_DEV* pDev,
WOLFTPM2_KEY* pStorageKey,
TPM_ALG_ID alg);
#if defined(WOLFTPM_MLDSA) || defined(WOLFTPM_MLKEM)
/* Create a transient PQC primary and start an HMAC param-enc session using it:
* ML-KEM as the session salt key, ML-DSA as the bind key (with a transient SRK
* salt, since sign-only ML-DSA cannot supply one). The session is started but
* not assigned a slot; the caller calls wolfTPM2_SetAuthSession() and later
* unloads pqcKey->handle and session->handle. */
WOLFTPM_LOCAL int getPrimaryParamEncKey(WOLFTPM2_DEV* pDev,
WOLFTPM2_SESSION* session,
WOLFTPM2_KEY* pqcKey,
TPM_ALG_ID pqcAlg,
int paramSet,
int paramEncAlg);
/* Parse a PQC parameter-set value ("mlkem[=512|768|1024]" /
* "mldsa[=44|65|87]"). Returns 1 on a valid value (sets the alg and paramSet
* outputs), -1 if a PQC algorithm is named with an unsupported set (printed),
* or 0 if not a PQC value. parsePqcParamEncArg() takes the "-" option form. */
WOLFTPM_LOCAL int parsePqcParamSet(const char* val, TPM_ALG_ID* alg,
int* paramSet);
WOLFTPM_LOCAL int parsePqcParamEncArg(const char* arg, TPM_ALG_ID* alg,
int* paramSet);
#endif
WOLFTPM_LOCAL int getRSAkey(WOLFTPM2_DEV* pDev,
WOLFTPM2_KEY* pStorageKey,
WOLFTPM2_KEY* key,

View File

@ -10,7 +10,8 @@ noinst_PROGRAMS += examples/wrap/wrap_test \
examples/wrap/encrypt_decrypt
noinst_HEADERS += examples/wrap/wrap_test.h
examples_wrap_wrap_test_SOURCES = examples/wrap/wrap_test.c
examples_wrap_wrap_test_SOURCES = examples/wrap/wrap_test.c \
examples/tpm_test_keys.c
examples_wrap_wrap_test_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
examples_wrap_wrap_test_DEPENDENCIES = src/libwolftpm.la

View File

@ -35,6 +35,7 @@
#include <hal/tpm_io.h>
#include <examples/tpm_test.h>
#include <examples/tpm_test_keys.h>
#include <examples/wrap/wrap_test.h>
/* Configuration */
@ -50,9 +51,16 @@
static void usage(void)
{
printf("Expected Usage:\n");
printf("./examples/wrap/wrap_test [-aes/xor]\n");
printf("./examples/wrap/wrap_test [-aes/xor] [-mlkem/-mldsa]\n");
printf("* -aes/xor: Use Parameter Encryption\n");
#ifdef WOLFTPM_MLKEM
printf("* -mlkem[=512|768|1024]: Use an ML-KEM key as the param-enc "
"session salt (v1.85, default 768)\n");
#endif
#ifdef WOLFTPM_MLDSA
printf("* -mldsa[=44|65|87]: Use an ML-DSA key as the param-enc "
"session bind (v1.85, default 65)\n");
#endif
}
int TPM2_Wrapper_Test(void* userCtx)
@ -125,11 +133,21 @@ int TPM2_Wrapper_TestArgs(void* userCtx, int argc, char *argv[])
#endif /* !WOLFTPM2_NO_WOLFCRYPT */
TPM_ALG_ID paramEncAlg = TPM_ALG_NULL;
WOLFTPM2_SESSION tpmSession;
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
/* Optional PQC key used as the parameter-encryption session salt
* (ML-KEM) or bind (ML-DSA) key. */
TPM_ALG_ID pqcParamEncAlg = TPM_ALG_NULL;
int pqcParamSet = 0;
WOLFTPM2_KEY pqcKey;
#endif
XMEMSET(&rsaKey, 0, sizeof(rsaKey));
XMEMSET(&eccKey, 0, sizeof(eccKey));
XMEMSET(&aesKey, 0, sizeof(aesKey));
XMEMSET(&publicKey, 0, sizeof(publicKey));
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
XMEMSET(&pqcKey, 0, sizeof(pqcKey));
#endif
#ifndef WOLFTPM2_NO_WOLFCRYPT
#ifndef NO_RSA
XMEMSET(&wolfRsaPubKey, 0, sizeof(wolfRsaPubKey));
@ -159,12 +177,33 @@ int TPM2_Wrapper_TestArgs(void* userCtx, int argc, char *argv[])
else if (XSTRCMP(argv[argc-1], "-xor") == 0) {
paramEncAlg = TPM_ALG_XOR;
}
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
else if (parsePqcParamEncArg(argv[argc-1], &pqcParamEncAlg,
&pqcParamSet) != 0) {
/* PQC option; an unsupported parameter set (alg left NULL) is a
* fatal typo, not a silent drop of parameter encryption. */
if (pqcParamEncAlg == TPM_ALG_NULL) {
usage();
return 0;
}
}
#endif
else {
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);
}
argc--;
}
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
/* A PQC param-enc key only supplies the salt/bind material; a symmetric
* session cipher is still required. Default to AES-CFB if none given. */
if (pqcParamEncAlg != TPM_ALG_NULL && paramEncAlg == TPM_ALG_NULL) {
paramEncAlg = TPM_ALG_CFB;
printf("PQC param-enc key selected; defaulting session cipher to "
"AES-CFB.\n");
}
#endif
printf("TPM2 Demo for Wrapper API's\n");
@ -265,8 +304,19 @@ int TPM2_Wrapper_TestArgs(void* userCtx, int argc, char *argv[])
#ifdef NO_RSA
bindKey = NULL; /* cannot bind to key without RSA enabled */
#endif
rc = wolfTPM2_StartSession(&dev, &tpmSession, bindKey, NULL,
TPM_SE_HMAC, paramEncAlg);
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
if (pqcParamEncAlg != TPM_ALG_NULL) {
/* Use a PQC primary as the param-enc session key: ML-KEM salt
* or ML-DSA bind. The RSA storageKey stays the child parent. */
rc = getPrimaryParamEncKey(&dev, &tpmSession, &pqcKey,
pqcParamEncAlg, pqcParamSet, paramEncAlg);
}
else
#endif
{
rc = wolfTPM2_StartSession(&dev, &tpmSession, bindKey, NULL,
TPM_SE_HMAC, paramEncAlg);
}
if (rc != 0) goto exit;
printf("TPM2_StartAuthSession: sessionHandle 0x%x\n",
(word32)tpmSession.handle.hndl);
@ -1036,6 +1086,9 @@ exit:
wolfTPM2_UnloadHandle(&dev, &eccKey.handle);
wolfTPM2_UnloadHandle(&dev, &ekKey.handle);
wolfTPM2_UnloadHandle(&dev, &tpmSession.handle);
#if defined(WOLFTPM_MLKEM) || defined(WOLFTPM_MLDSA)
wolfTPM2_UnloadHandle(&dev, &pqcKey.handle);
#endif
/* Only doShutdown=1: Just shutdown the TPM */
wolfTPM2_Reset(&dev, 1, 0);