From 2582b3cc92c35343a23acc4a568ddc49dc7d8656 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 30 Oct 2026 12:17:04 -0700 Subject: [PATCH 1/2] bench: cover every ML-DSA and ML-KEM parameter set --- examples/bench/bench.c | 57 +++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/examples/bench/bench.c b/examples/bench/bench.c index b0c38efc..dd28427c 100644 --- a/examples/bench/bench.c +++ b/examples/bench/bench.c @@ -269,9 +269,10 @@ static int bench_sym_aes(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* storageKey, #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) + double maxKeyGenDurSec, int level) { int rc, count; + int strength; double start; WOLFTPM2_KEY mldsaKey; TPMT_PUBLIC publicTemplate; @@ -287,10 +288,14 @@ static int bench_pqc_mldsa(WOLFTPM2_DEV* dev, double maxDuration, XMEMSET(message, 0x11, sizeof(message)); XMEMSET(sig, 0, sizeof(sig)); + /* The reported strength is the parameter set name, not the enum value. */ + strength = (level == TPM_MLDSA_44) ? 44 : + (level == TPM_MLDSA_65) ? 65 : 87; + rc = wolfTPM2_GetKeyTemplate_MLDSA(&publicTemplate, TPMA_OBJECT_sign | TPMA_OBJECT_fixedTPM | TPMA_OBJECT_fixedParent | TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | - TPMA_OBJECT_noDA, TPM_MLDSA_65, 0); + TPMA_OBJECT_noDA, level, 0); if (rc != 0) return rc; bench_stats_start(&count, &start); @@ -301,7 +306,7 @@ static int bench_pqc_mldsa(WOLFTPM2_DEV* dev, double maxDuration, &publicTemplate, NULL, 0); if (rc != 0) break; } while (bench_stats_check(start, &count, maxKeyGenDurSec)); - rc = bench_asym_done("ML-DSA", 65, "key gen", count, start, rc); + rc = bench_asym_done("ML-DSA", strength, "key gen", count, start, rc); if (rc != 0) return rc; if (count == 0) @@ -325,7 +330,7 @@ static int bench_pqc_mldsa(WOLFTPM2_DEV* dev, double maxDuration, } if (rc != 0) break; } while (bench_stats_check(start, &count, maxDuration)); - rc = bench_asym_done("ML-DSA", 65, "sign", count, start, rc); + rc = bench_asym_done("ML-DSA", strength, "sign", count, start, rc); if (rc != 0) goto exit; if (count == 0) goto exit; /* no signature produced; nothing to verify */ @@ -338,7 +343,7 @@ static int bench_pqc_mldsa(WOLFTPM2_DEV* dev, double maxDuration, message, (int)sizeof(message), sig, sigSz, &validation); if (rc != 0) break; } while (bench_stats_check(start, &count, maxDuration)); - rc = bench_asym_done("ML-DSA", 65, "verify", count, start, rc); + rc = bench_asym_done("ML-DSA", strength, "verify", count, start, rc); if (rc != 0) goto exit; exit: @@ -350,9 +355,10 @@ static int bench_pqc_mldsa(WOLFTPM2_DEV* dev, double maxDuration, #ifdef WOLFTPM_MLKEM /* Benchmark ML-KEM: key gen, encapsulate and decapsulate. */ static int bench_pqc_mlkem(WOLFTPM2_DEV* dev, double maxDuration, - double maxKeyGenDurSec) + double maxKeyGenDurSec, int level) { int rc, count; + int strength; double start; WOLFTPM2_KEY mlkemKey; TPMT_PUBLIC publicTemplate; @@ -364,10 +370,14 @@ static int bench_pqc_mlkem(WOLFTPM2_DEV* dev, double maxDuration, XMEMSET(&mlkemKey, 0, sizeof(mlkemKey)); XMEMSET(&publicTemplate, 0, sizeof(publicTemplate)); + /* The reported strength is the parameter set name, not the enum value. */ + strength = (level == TPM_MLKEM_512) ? 512 : + (level == TPM_MLKEM_768) ? 768 : 1024; + rc = wolfTPM2_GetKeyTemplate_MLKEM(&publicTemplate, TPMA_OBJECT_decrypt | TPMA_OBJECT_fixedTPM | TPMA_OBJECT_fixedParent | TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | - TPMA_OBJECT_noDA, TPM_MLKEM_768); + TPMA_OBJECT_noDA, level); if (rc != 0) return rc; bench_stats_start(&count, &start); @@ -378,7 +388,7 @@ static int bench_pqc_mlkem(WOLFTPM2_DEV* dev, double maxDuration, &publicTemplate, NULL, 0); if (rc != 0) break; } while (bench_stats_check(start, &count, maxKeyGenDurSec)); - rc = bench_asym_done("ML-KEM", 768, "key gen", count, start, rc); + rc = bench_asym_done("ML-KEM", strength, "key gen", count, start, rc); if (rc != 0) return rc; if (count == 0) @@ -392,7 +402,7 @@ static int bench_pqc_mlkem(WOLFTPM2_DEV* dev, double maxDuration, secret, &secretSz); if (rc != 0) break; } while (bench_stats_check(start, &count, maxDuration)); - rc = bench_asym_done("ML-KEM", 768, "encap", count, start, rc); + rc = bench_asym_done("ML-KEM", strength, "encap", count, start, rc); if (rc != 0) goto exit; bench_stats_start(&count, &start); @@ -402,7 +412,7 @@ static int bench_pqc_mlkem(WOLFTPM2_DEV* dev, double maxDuration, secret, &secretSz); if (rc != 0) break; } while (bench_stats_check(start, &count, maxDuration)); - rc = bench_asym_done("ML-KEM", 768, "decap", count, start, rc); + rc = bench_asym_done("ML-KEM", strength, "decap", count, start, rc); if (rc != 0) goto exit; exit: @@ -453,6 +463,17 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) WOLFTPM2_SESSION tpmSession; double maxDuration = TPM2_BENCH_DURATION_SEC; double maxKeyGenDurSec = TPM2_BENCH_DURATION_KEYGEN_SEC; +#if defined(WOLFTPM_MLDSA) || defined(WOLFTPM_MLKEM) + int i; +#endif +#ifdef WOLFTPM_MLDSA + static const int mldsaLevels[] = { + TPM_MLDSA_44, TPM_MLDSA_65, TPM_MLDSA_87 }; +#endif +#ifdef WOLFTPM_MLKEM + static const int mlkemLevels[] = { + TPM_MLKEM_512, TPM_MLKEM_768, TPM_MLKEM_1024 }; +#endif /* Static, so a previous call with -iter must not leak into this one */ gBenchIter = 0; @@ -770,12 +791,20 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) 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; + for (i = 0; i < (int)(sizeof(mldsaLevels)/sizeof(mldsaLevels[0])); + i++) { + rc = bench_pqc_mldsa(&dev, maxDuration, maxKeyGenDurSec, + mldsaLevels[i]); + if (rc != 0) goto exit; + } #endif #ifdef WOLFTPM_MLKEM - rc = bench_pqc_mlkem(&dev, maxDuration, maxKeyGenDurSec); - if (rc != 0) goto exit; + for (i = 0; i < (int)(sizeof(mlkemLevels)/sizeof(mlkemLevels[0])); + i++) { + rc = bench_pqc_mlkem(&dev, maxDuration, maxKeyGenDurSec, + mlkemLevels[i]); + if (rc != 0) goto exit; + } #endif } #endif From c5c1c2a8a35f3b1a4d57bbea004e22149df397c4 Mon Sep 17 00:00:00 2001 From: David Garske Date: Sat, 31 Oct 2026 10:39:02 -0700 Subject: [PATCH 2/2] bench: walk the ECC curves and the RSA key sizes the build supports --- examples/bench/bench.c | 65 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/examples/bench/bench.c b/examples/bench/bench.c index dd28427c..ce7fead3 100644 --- a/examples/bench/bench.c +++ b/examples/bench/bench.c @@ -458,11 +458,31 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) int count; int sha1Supported; int rsaBits = WOLFTPM2_WRAP_RSA_KEY_BITS; + int skipDec = 0; /* skip a decrypt op whose paired encrypt was unsupported */ TPM_ALG_ID paramEncAlg = TPM_ALG_NULL; WOLFTPM2_SESSION tpmSession; double maxDuration = TPM2_BENCH_DURATION_SEC; double maxKeyGenDurSec = TPM2_BENCH_DURATION_KEYGEN_SEC; + int j; + int k; + int eccBits; + static const int rsaSizes[] = { + 2048, +#if MAX_RSA_KEY_BITS >= 3072 + 3072, +#endif +#if MAX_RSA_KEY_BITS >= 4096 + 4096, +#endif + }; + TPM_ECC_CURVE eccCurve; + static const TPM_ECC_CURVE eccCurves[] = { + TPM_ECC_NIST_P256, +#if defined(HAVE_ECC384) && ECC_MIN_KEY_SZ <= 384 + TPM_ECC_NIST_P384, +#endif + }; #if defined(WOLFTPM_MLDSA) || defined(WOLFTPM_MLKEM) int i; #endif @@ -628,11 +648,18 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) if (rc != 0 && (rc & RC_MAX_FMT1) != TPM_RC_HASH) goto exit; + for (k = 0; k < (int)(sizeof(rsaSizes)/sizeof(rsaSizes[0])); k++) { + rsaBits = rsaSizes[k]; + /* Create RSA key for encrypt/decrypt */ rc = wolfTPM2_GetKeyTemplate_RSA(&publicTemplate, TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | TPMA_OBJECT_decrypt | TPMA_OBJECT_sign | TPMA_OBJECT_noDA); if (rc != 0) goto exit; + /* The template helper takes no size, so it comes from + * WOLFTPM2_WRAP_RSA_KEY_BITS. Override it to walk the sizes the TPM + * structures can carry. */ + publicTemplate.parameters.rsaDetail.keyBits = (TPMI_RSA_KEY_BITS)rsaBits; bench_stats_start(&count, &start); do { if (count > 0) { @@ -641,9 +668,16 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) } rc = wolfTPM2_CreateAndLoadKey(&dev, &rsaKey, &storageKey.handle, &publicTemplate, (byte*)gKeyAuth, sizeof(gKeyAuth)-1); - if (rc != 0) goto exit; + /* A part that does not implement this modulus reports itself here + * rather than ending the benchmark. */ + if (rc != 0) break; } while (bench_stats_check(start, &count, maxKeyGenDurSec)); - bench_stats_asym_finish("RSA", rsaBits, "key gen", count, start); + rc = bench_asym_done("RSA", rsaBits, "key gen", count, start, rc); + if (rc != 0) goto exit; + if (count == 0) { + XMEMSET(&rsaKey, 0, sizeof(rsaKey)); + continue; /* size unsupported; the rest needs the key */ + } /* Perform RSA encrypt / decrypt (no pad) */ /* No padding means the message is exactly the modulus width, which the @@ -712,13 +746,18 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) rc = wolfTPM2_UnloadHandle(&dev, &rsaKey.handle); if (rc != 0) goto exit; + } /* RSA sizes */ + for (j = 0; j < (int)(sizeof(eccCurves)/sizeof(eccCurves[0])); j++) { + eccCurve = eccCurves[j]; + eccBits = (eccCurve == TPM_ECC_NIST_P256) ? 256 : 384; + /* Create an ECC key for ECDSA */ rc = wolfTPM2_GetKeyTemplate_ECC(&publicTemplate, TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | TPMA_OBJECT_sign | TPMA_OBJECT_noDA, - TPM_ECC_NIST_P256, TPM_ALG_ECDSA); + eccCurve, TPM_ALG_ECDSA); if (rc != 0) goto exit; bench_stats_start(&count, &start); do { @@ -728,9 +767,16 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) } rc = wolfTPM2_CreateAndLoadKey(&dev, &eccKey, &storageKey.handle, &publicTemplate, (byte*)gKeyAuth, sizeof(gKeyAuth)-1); - if (rc != 0) goto exit; + /* A part that does not implement this curve reports itself here + * rather than ending the benchmark. */ + if (rc != 0) break; } while (bench_stats_check(start, &count, maxDuration)); - bench_stats_asym_finish("ECC", 256, "key gen", count, start); + rc = bench_asym_done("ECC", eccBits, "key gen", count, start, rc); + if (rc != 0) goto exit; + if (count == 0) { + XMEMSET(&eccKey, 0, sizeof(eccKey)); + continue; /* curve unsupported; the rest needs the key */ + } /* Perform sign / verify */ message.size = TPM_SHA256_DIGEST_SIZE; /* test message 0x11,0x11,etc */ @@ -743,7 +789,7 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) cipher.buffer, &cipher.size); if (rc != 0) break; } while (bench_stats_check(start, &count, maxDuration)); - rc = bench_asym_done("ECDSA", 256, "sign", count, start, rc); + rc = bench_asym_done("ECDSA", eccBits, "sign", count, start, rc); if (rc != 0) goto exit; bench_stats_start(&count, &start); @@ -752,7 +798,7 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) message.buffer, message.size); if (rc != 0) break; } while (bench_stats_check(start, &count, maxDuration)); - rc = bench_asym_done("ECDSA", 256, "verify", count, start, rc); + rc = bench_asym_done("ECDSA", eccBits, "verify", count, start, rc); if (rc != 0) goto exit; rc = wolfTPM2_UnloadHandle(&dev, &eccKey.handle); @@ -763,7 +809,7 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) rc = wolfTPM2_GetKeyTemplate_ECC(&publicTemplate, TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | TPMA_OBJECT_decrypt | TPMA_OBJECT_noDA, - TPM_ECC_NIST_P256, TPM_ALG_ECDH); + eccCurve, TPM_ALG_ECDH); if (rc != 0) goto exit; rc = wolfTPM2_CreateAndLoadKey(&dev, &eccKey, &storageKey.handle, &publicTemplate, (byte*)gKeyAuth, sizeof(gKeyAuth)-1); @@ -777,11 +823,12 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) cipher.buffer, &cipher.size); if (rc != 0) break; } while (bench_stats_check(start, &count, maxDuration)); - rc = bench_asym_done("ECDHE", 256, "agree", count, start, rc); + rc = bench_asym_done("ECDHE", eccBits, "agree", count, start, rc); if (rc != 0) goto exit; rc = wolfTPM2_UnloadHandle(&dev, &eccKey.handle); if (rc != 0) goto exit; + } /* ECC curves */ #if defined(WOLFTPM_MLDSA) || defined(WOLFTPM_MLKEM) /* Post-quantum (TPM 2.0 v1.85). Skipped under parameter encryption: the