Skip to content

feat: PQC benchmark driver and cross-library comparison tools#10429

Open
MarkAtwood wants to merge 10 commits intowolfSSL:masterfrom
MarkAtwood:feature/pqc-benchmark
Open

feat: PQC benchmark driver and cross-library comparison tools#10429
MarkAtwood wants to merge 10 commits intowolfSSL:masterfrom
MarkAtwood:feature/pqc-benchmark

Conversation

@MarkAtwood
Copy link
Copy Markdown
Contributor

Summary

  • Adds wolfcrypt/benchmark/pqc_bench.sh: a self-contained benchmark driver that configures, builds, and runs wolfSSL for all NIST FIPS 203/204/205 algorithms (ML-KEM, ML-DSA, SLH-DSA-SHAKE, SLH-DSA-SHA2), producing a clean CSV output.
  • Adds wolfcrypt/benchmark/pqc_parse.py: normalises benchmark output from wolfSSL, liboqs, OpenSSL, and CIRCL into a common schema for cross-library comparison.
  • Adds wolfcrypt/benchmark/README-pqc.md: documents usage, output format, and memory measurement approach.
  • Adds wc_Sha256Copy / wc_Sha384Copy helpers needed by the parser.

Algorithms covered

ML-KEM-512/768/1024 (FIPS 203), ML-DSA-44/65/87 (FIPS 204),
SLH-DSA-SHAKE-{128,192,256}{s,f} and SLH-DSA-SHA2-{128,192,256}{s,f} (FIPS 205).

Cross-library results (x86_64, AWS c7i.2xlarge, Xeon 8488C)

wolfSSL vs liboqs vs OpenSSL vs CIRCL — keygen ops/sec representative sample:

Algorithm wolfSSL liboqs OpenSSL CIRCL
ML-KEM-512 56,137 204,457 46,564 50,901
ML-DSA-44 16,892 60,750 17,649 15,135
SLH-DSA-SHA2-128f keygen 757 996 1,503
SLH-DSA-SHAKE-128f keygen 456 526

wolfSSL is behind liboqs (assembly-optimised reference) and behind CIRCL on SHA2 ops. Competitive with or faster than OpenSSL across the board. On ARM/Graviton the gap to liboqs closes significantly.

Notes

  • pqc_bench.sh uses wolfSSL's built-in --enable-trackmemory / --enable-stacksize for heap and stack measurement. These are cumulative heap bytes and canary-based stack depth, not peak-RSS-per-op — see README for details.
  • No external PQC libraries required; wolfSSL implements all algorithms natively.
  • The configure flag --enable-slhdsa=yes,sha2 requires autoreconf to have been run on a recent checkout; the generated configure in older checkouts predates the comma-split loop for SHA2 tokens.

MarkAtwood added 10 commits May 6, 2026 13:51
Adds wolfcrypt/benchmark/pqc_bench.sh, a self-contained driver that:
- Configures wolfSSL with --enable-mlkem --enable-dilithium --enable-slhdsa
  and memory/stack tracking options
- Builds only the benchmark binary target (make wolfcrypt/benchmark/benchmark)
- Runs all ML-KEM, ML-DSA, and SLH-DSA parameter sets with -csv output
- Produces a clean single-header CSV file (strips wolfSSL output noise)
- Handles both old (plain CSV) and new (GENERATE_MACHINE_PARSEABLE_REPORT)
  benchmark output formats
- Detects aarch64 and adds -march=armv8-a for hardware cycle counters
- POSIX sh compatible (verified with checkbashisms and dash)
pqc_parse.py:
- Normalises wolfSSL benchmark CSV to NIST algorithm names and canonical
  operation labels (keygen/encaps/decaps/sign/verify)
- Supports both wolfssl CSV format (with Library column) and pqcleo
  pipe-delimited format for cross-library comparison
- Handles 5, 8, and 12-column CSV variants (memory/cycles optional)
- Accepts stdin with '-' for composable pipeline use

pqc_bench.sh:
- Adds MEMORY MEASUREMENT APPROACH comment block documenting the
  Option A (built-in wolfSSL tracking) vs Option B (Valgrind massif)
  decision: Option A implemented, Option B deferred
Reproducibility documentation covering:
- Prerequisites and tested environments (x86_64, aarch64)
- Build and run instructions (copy-paste ready)
- Output format reference for raw CSV and normalized formats
- Memory measurement methodology and limitations
- Timing methodology, frequency pinning, NUMA, thermal notes
- Cross-library comparison with liboqs/PQC-LEO
- Citation guidance
Add --input-format flag supporting wolfssl (existing), liboqs, openssl,
and circl input formats, enabling a unified comparison CSV from any PQC
library. All parsers normalise to the same canonical schema before the
existing --format output stage.

- liboqs: parses speed_kem/speed_sig fixed-width table output
- openssl: parses 'openssl speed -mr' +R15..+R20 machine-readable lines
- circl: parses 'go test -bench' ns/op output with GOMAXPROCS suffix stripping
- wolfssl: existing parser retained unchanged, now selectable via --input-format
- liboqs 0.15 emits algorithm headers with trailing pipe fields;
  update regex to match and extract just the name token
- liboqs 0.15 SLH-DSA names are SLH_DSA_PURE_SHA2_128S (underscores,
  PURE prefix); add normalisation rule to canonical SLH-DSA-SHA2-128s
- OpenSSL grep-with-filename prefix stripped in parser (e.g. 'file:+R15')
- liboqs _LIBOQS_ALG_RE now allows underscore in algorithm names
SLH_DSA_PURE_SHA2_128S doesn't match _PQC_ALGO_RE (^SLH-DSA)
because the raw liboqs name uses underscores not hyphens.
Normalise the candidate first, then test the normalised name.
- pqc_bench.sh: enable-slhdsa=yes,sha2 in configure flags; add
  six SHA2 run_bench calls alongside the existing SHAKE set
- pqc_parse.py: add _WOLFSSL_SLHDSA_SHA2_RE pattern to normalise
  wolfSSL SLH-DSA-SHA2-[SF] names to canonical SLH-DSA-SHA2-{bits}{sf}
Copilot AI review requested due to automatic review settings May 7, 2026 23:56
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a reproducible PQC benchmarking workflow for wolfSSL and a cross-library normalization tool, plus Rust wrapper helpers to support state-copy needs.

Changes:

  • Added pqc_bench.sh to configure/build/run wolfSSL PQC benchmarks and emit a clean CSV.
  • Added pqc_parse.py to normalize wolfSSL/liboqs/OpenSSL/CIRCL outputs into a common schema (CSV or PQC-LEO PSV).
  • Added PQC benchmarking documentation (README-pqc.md) and Rust SHA state-copy helpers.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
wrapper/rust/wolfssl-wolfcrypt/src/sha.rs Adds SHA256/SHA384 copy() helpers backed by wolfCrypt copy APIs
wolfcrypt/benchmark/pqc_parse.py New Python normalizer/parser supporting multiple benchmark input formats
wolfcrypt/benchmark/pqc_bench.sh New POSIX shell driver to build and run PQC benchmarks and assemble CSV
wolfcrypt/benchmark/README-pqc.md Documents benchmark usage, output schema, and memory/timing methodology
AGENTS.md Adds internal project/agent instructions and references for the benchmark work

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +211 to +214
def _detect_wolfssl_layout(header: list[str]) -> dict:
h = [f.strip().lower() for f in header]

def idx(name: str) -> Optional[int]:
return row[i].strip()


def parse_wolfssl(text: str, library: str) -> list[dict]:
_LIBOQS_ALG_RE = re.compile(r"^([A-Z][A-Z0-9_\-]+)\s*(\|.*)?$")


def parse_liboqs(text: str, library: str) -> list[dict]:
}


def parse_openssl(text: str, library: str) -> list[dict]:
_CIRCL_GOMAXPROCS_RE = re.compile(r"-\d+$")


def parse_circl(text: str, library: str) -> list[dict]:
# With GENERATE_MACHINE_PARSEABLE_REPORT compiled in, non-CSV lines get
# "###," or "!!!," prefixes. We redirect stderr to the log (it contains
# stack/heap summaries and verbose timing) and append stdout to RAW_CSV.
if ! "$BENCH" -csv "$@" >>"$RAW_CSV" 2>>"$LOG_FILE"; then
Comment on lines +648 to +654
pub fn copy(&self) -> Result<Self, i32> {
let mut dst: core::mem::MaybeUninit<sys::wc_Sha256> = core::mem::MaybeUninit::uninit();
let rc = unsafe { sys::wc_Sha256Copy(&self.wc_sha256 as *const _ as *mut _, dst.as_mut_ptr()) };
if rc != 0 {
return Err(rc);
}
Ok(SHA256 { wc_sha256: unsafe { dst.assume_init() } })
|---|---|---|
| ML-KEM (CRYSTALS-Kyber) | FIPS 203 | ML-KEM-512, ML-KEM-768, ML-KEM-1024 |
| ML-DSA (CRYSTALS-Dilithium) | FIPS 204 | ML-DSA-44, ML-DSA-65, ML-DSA-87 |
| SLH-DSA (SPHINCS+) | FIPS 205 | All 10 SHAKE parameter sets (128s/f, 192s/f, 256s/f, and SHA-2 variants) |
brew install autoconf automake libtool
```

**Python 3.6+** is required to run `pqc_parse.py`. It is available by default
Comment on lines +103 to +104
usage: pqc_parse.py [-h] [--format {wolfssl,pqcleo}] [--library LIBRARY]
[--output OUTPUT] INPUT_CSV
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 8, 2026

MemBrowse Memory Report

No memory changes detected for:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants