-
Notifications
You must be signed in to change notification settings - Fork 34
Add ML-KEM and ML-DSA support #399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
aad005d
d203979
be25627
3df1a6f
f78fdb8
c1b7c10
60f2cd6
dae5cd6
0aec54f
618ad0a
39e677c
ef9ac48
ed58142
0b04e5a
371c4e6
f69c064
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| name: wolfSSL Versions (PQC) | ||
|
|
||
| # Backward-compatibility matrix for ML-KEM and ML-DSA. Mirrors wolfTPM's | ||
| # wolfssl-versions-pqc.yml pattern: a discover-versions job dynamically | ||
| # resolves the latest -stable wolfSSL tag and decides if it is past the PQC | ||
| # floor, then the build job runs three rows -- pre-PQC floor, dynamically | ||
| # resolved latest -stable, and master. | ||
| # | ||
| # PQC_FLOOR is v5.9.1-stable: the wc_MlDsaKey_* / wc_dilithium_sign_ctx_msg | ||
| # API that wolfProvider's PQC code depends on lands post-v5.9.1-stable | ||
| # (wolfSSL PR #10436), so v5.9.2-stable+ is the first PQC-eligible release. | ||
| # Older wolfSSL versions skip the PQC code paths via settings.h gating and | ||
| # only verify the no-symbol path still builds. | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ 'master', 'main', 'release/**' ] | ||
| pull_request: | ||
| branches: [ '*' ] | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| discover-versions: | ||
| name: Resolve wolfSSL version matrix | ||
| runs-on: ubuntu-22.04 | ||
| outputs: | ||
| matrix: ${{ steps.set-matrix.outputs.matrix }} | ||
| latest-stable: ${{ steps.set-matrix.outputs.latest-stable }} | ||
| steps: | ||
| - name: Resolve latest -stable wolfSSL tag | ||
| id: set-matrix | ||
| run: | | ||
| set -euo pipefail | ||
| LATEST=$(git ls-remote --tags --refs \ | ||
| https://github.com/wolfSSL/wolfssl.git 'v*-stable' \ | ||
| | awk -F/ '{print $NF}' | sort -V | tail -n 1) | ||
| if [ -z "${LATEST:-}" ]; then | ||
| echo "::error::Could not resolve latest wolfSSL -stable tag" | ||
| exit 1 | ||
| fi | ||
| echo "Latest stable wolfSSL: $LATEST" | ||
| echo "latest-stable=$LATEST" >> "$GITHUB_OUTPUT" | ||
| # Enable PQC when $LATEST is strictly newer than v5.9.1-stable | ||
| # (i.e. v5.9.2-stable, v5.10+, v6+, ...). Anything at or before | ||
| # the floor lacks the wc_MlDsaKey_* / wc_dilithium_sign_ctx_msg | ||
| # API and stays on the no-symbol path. | ||
| PQC_FLOOR="v5.9.1-stable" | ||
| if [ "$(printf '%s\n%s\n' "$PQC_FLOOR" "$LATEST" \ | ||
| | sort -V | tail -n1)" != "$PQC_FLOOR" ]; then | ||
| LATEST_PQC_ELIGIBLE=true | ||
| else | ||
| LATEST_PQC_ELIGIBLE=false | ||
| fi | ||
| echo "latest-stable PQC eligible: $LATEST_PQC_ELIGIBLE" | ||
| MATRIX=$(jq -nc \ | ||
| --arg latest "$LATEST" \ | ||
| --argjson latest_pqc "$LATEST_PQC_ELIGIBLE" '{ | ||
| include: [ | ||
| {"name":"pre-PQC (v5.8.0-stable, PQC disabled)", | ||
| "wolfssl-ref":"v5.8.0-stable","pqc":false}, | ||
| {"name":("latest stable (" + $latest + ", PQC " + | ||
| (if $latest_pqc then "enabled" else "disabled" end) + ")"), | ||
| "wolfssl-ref":$latest,"pqc":$latest_pqc}, | ||
| {"name":"master (PQC enabled)", | ||
| "wolfssl-ref":"master","pqc":true} | ||
| ] | ||
| }') | ||
| echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT" | ||
|
|
||
| pqc-build-test: | ||
| name: ${{ matrix.name }} | ||
| needs: discover-versions | ||
| runs-on: ubuntu-22.04 | ||
| timeout-minutes: 30 | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: ${{ fromJson(needs.discover-versions.outputs.matrix) }} | ||
| steps: | ||
| - name: Checkout wolfProvider | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 1 | ||
|
|
||
| # OpenSSL is pinned to 3.5.4 on every row so the cross-provider interop | ||
| # test can verify against the default provider's native ML-KEM/ML-DSA. | ||
| # OpenSSL 3.5 is the first release with native PQC support; older 3.x | ||
| # versions can build wolfProvider but the interop step would have | ||
| # nothing to compare against on the default-provider side. | ||
| - name: Build wolfProvider (PQC=${{ matrix.pqc }}) | ||
| run: | | ||
| if [ "${{ matrix.pqc }}" = "true" ]; then | ||
| OPENSSL_TAG=openssl-3.5.4 \ | ||
| WOLFSSL_TAG=${{ matrix.wolfssl-ref }} \ | ||
| ./scripts/build-wolfprovider.sh --enable-pqc | ||
| else | ||
| OPENSSL_TAG=openssl-3.5.4 \ | ||
| WOLFSSL_TAG=${{ matrix.wolfssl-ref }} \ | ||
| ./scripts/build-wolfprovider.sh | ||
| fi | ||
|
|
||
| # On PQC-enabled rows the PQC tests must be present. We do NOT assert | ||
| # absence on the no-PQC rows because v5.9.x's --enable-all-crypto now | ||
| # auto-enables MLKEM/DILITHIUM, so the "latest stable" row will pick up | ||
| # PQC at the wolfSSL level even without --enable-pqc. wolfProvider | ||
| # auto-detects and compiles in the PQC code in that case, which is fine. | ||
| - name: Confirm PQC tests present on PQC-enabled rows | ||
| if: matrix.pqc == true | ||
| run: | | ||
| ./test/unit.test --list | grep -q 'test_mlkem_keygen' \ | ||
| || { echo 'ERROR: PQC tests missing in PQC-enabled build'; \ | ||
| exit 1; } | ||
| ./test/unit.test --list | grep -q 'test_mldsa_sign_verify' \ | ||
| || { echo 'ERROR: ML-DSA tests missing in PQC-enabled build'; \ | ||
| exit 1; } | ||
|
|
||
| # Three-way interop: wolfProvider <-> OpenSSL default <-> wolfSSL direct. | ||
| # Only runs on PQC-enabled rows; OpenSSL 3.5+ has native ML-KEM/ML-DSA | ||
| # in the default provider, so this proves wolfProvider's bytes are | ||
| # FIPS 203/204 standards-compliant against two reference implementations. | ||
| # Linux x86_64 OpenSSL installs to lib64 by default; LD_LIBRARY_PATH | ||
| # must include both lib and lib64 or the dynamic linker falls through | ||
| # to the system libcrypto/libssl (Ubuntu 22.04 ships 3.0.2, which has | ||
| # no ML-KEM/ML-DSA in the default provider). | ||
| - name: Three-way PQC interop validation | ||
| if: matrix.pqc == true | ||
| run: | | ||
| LD_LIBRARY_PATH="$(pwd)/wolfssl-install/lib:$(pwd)/openssl-install/lib:$(pwd)/openssl-install/lib64" \ | ||
| ./test/pqc_interop.test | ||
|
|
||
| - name: Print errors on failure | ||
| if: ${{ failure() }} | ||
| run: | | ||
| if [ -f test-suite.log ]; then | ||
| cat test-suite.log | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,7 @@ This retrieves dependencies (OpenSSL and wolfSSL) and compiles them as necessary | |
| | `--openssl-dir=/path` | Use existing OpenSSL installation | | ||
| | `--replace-default` | Make wolfProvider the default provider | | ||
| | `--enable-replace-default-testing` | Enable unit testing with replace-default | | ||
| | `--enable-pqc` | Enable ML-KEM and ML-DSA post-quantum algorithms (adds `--enable-mlkem --enable-dilithium --enable-experimental` to wolfSSL). Requires wolfSSL post-v5.9.1-stable. | | ||
|
|
||
| **Examples:** | ||
|
|
||
|
|
@@ -82,6 +83,7 @@ sudo make install | |
| | `--enable-pwdbased` | PKCS#12 support | | ||
| | `--enable-hmac-copy` | Faster repeated HMAC with same key (wolfSSL 5.7.8+) | | ||
| | `--enable-sp=yes,asm --enable-sp-math-all` | SP Integer maths | | ||
| | `--enable-mlkem --enable-dilithium --enable-experimental` | ML-KEM and ML-DSA post-quantum algorithms (wolfSSL post-v5.9.1-stable). The `build-wolfprovider.sh --enable-pqc` flag sets these automatically. | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above |
||
|
|
||
| **Optional CPPFLAGS:** | ||
|
|
||
|
|
@@ -151,6 +153,58 @@ This makes replace default mode useful for testing scenarios where you want to e | |
|
|
||
| --- | ||
|
|
||
| ## Post-Quantum Cryptography (ML-KEM and ML-DSA) | ||
|
|
||
| wolfProvider supports NIST's post-quantum algorithms via the wolfSSL backend: | ||
|
|
||
| | Algorithm | Standard | Parameter Sets | | ||
| |-----------|----------|----------------| | ||
| | ML-KEM (key encapsulation) | FIPS 203 | ML-KEM-512, ML-KEM-768, ML-KEM-1024 | | ||
| | ML-DSA (digital signature) | FIPS 204 | ML-DSA-44, ML-DSA-65, ML-DSA-87 | | ||
|
|
||
| ML-DSA uses pure mode with an empty context string (FIPS 204 sec 5.2, Algorithm 22) — interoperable with OpenSSL 3.5+'s native ML-DSA. | ||
|
|
||
| ### Requirements | ||
|
|
||
| - **wolfSSL**: post-v5.9.1-stable (i.e. v5.9.2-stable or master). Older releases lack the `wc_MlDsaKey_*` and `wc_dilithium_sign_ctx_msg` API surface that wolfProvider's PQC code uses. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| - **OpenSSL**: any 3.x. OpenSSL 3.5+ is required only for cross-provider interop against its native ML-KEM/ML-DSA implementations. | ||
|
|
||
| ### Building with PQC | ||
|
|
||
| ```bash | ||
| ./scripts/build-wolfprovider.sh --enable-pqc | ||
| ``` | ||
|
|
||
| This adds `--enable-mlkem --enable-dilithium --enable-experimental` to the wolfSSL configure step. wolfProvider auto-detects the resulting `WOLFSSL_HAVE_MLKEM` / `HAVE_DILITHIUM` macros via `include/wolfprovider/settings.h` (gated on `__has_include` of the corresponding wolfSSL headers) and registers the six PQC algorithms. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| ### Usage Example | ||
|
|
||
| ```bash | ||
| # Generate an ML-DSA-65 key with wolfProvider | ||
| OPENSSL_CONF=provider.conf openssl genpkey -algorithm ML-DSA-65 -out key.pem | ||
|
|
||
| # Sign and verify with ML-DSA-65 | ||
| OPENSSL_CONF=provider.conf openssl pkeyutl -sign -inkey key.pem -in msg.bin -out sig.bin | ||
| OPENSSL_CONF=provider.conf openssl pkeyutl -verify -pubin -inkey pub.pem -sigfile sig.bin -in msg.bin | ||
| ``` | ||
|
|
||
| The OpenSSL CLI can also enumerate available algorithms: | ||
|
|
||
| ```bash | ||
| OPENSSL_CONF=provider.conf openssl list -kem-algorithms -provider libwolfprov | ||
| OPENSSL_CONF=provider.conf openssl list -signature-algorithms -provider libwolfprov | ||
| ``` | ||
|
|
||
| ### Validation | ||
|
|
||
| A standalone three-way interop validator (`test/pqc_interop.test`) cross-checks every ML-KEM / ML-DSA combination against: | ||
| - OpenSSL 3.5+'s native default provider | ||
| - wolfSSL's `wc_*` APIs directly (no provider abstraction) | ||
|
|
||
| This proves wolfProvider's raw-key, ciphertext, and signature bytes are FIPS 203 / 204 standards-compliant. The CI workflow `.github/workflows/wolfssl-versions-pqc.yml` runs this validator on every PR, plus a backward-compatibility build against pre-PQC wolfSSL to verify the no-symbol path still builds cleanly. | ||
|
|
||
| --- | ||
|
|
||
| ## Testing | ||
|
|
||
| ### Unit Tests | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -169,6 +169,42 @@ | |
| #ifdef HAVE_ED448 | ||
| #define WP_HAVE_ED448 | ||
| #endif | ||
| /* PQC: gate on both wolfSSL feature macro AND header availability. On wolfSSL | ||
| * master with --enable-all-crypto (no --enable-experimental), the feature | ||
| * macros can be defined in options.h while the mlkem.h / dilithium.h headers | ||
| * are not installed, so probe the headers too. */ | ||
| #ifdef WOLFSSL_HAVE_MLKEM | ||
| #if defined(__has_include) | ||
| /* wc_mlkem.h is present in both v5.9.1-stable (alongside mlkem.h) | ||
| * and on master (where mlkem.h was removed). Probe wc_mlkem.h only. */ | ||
| #if __has_include(<wolfssl/wolfcrypt/wc_mlkem.h>) | ||
| #define WP_HAVE_MLKEM | ||
| #define WP_HAVE_ML_KEM_512 | ||
| #define WP_HAVE_ML_KEM_768 | ||
| #define WP_HAVE_ML_KEM_1024 | ||
| #endif | ||
| #else | ||
| #define WP_HAVE_MLKEM | ||
| #define WP_HAVE_ML_KEM_512 | ||
| #define WP_HAVE_ML_KEM_768 | ||
| #define WP_HAVE_ML_KEM_1024 | ||
| #endif | ||
| #endif | ||
| #ifdef HAVE_DILITHIUM | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| #if defined(__has_include) | ||
| #if __has_include(<wolfssl/wolfcrypt/dilithium.h>) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check for the new |
||
| #define WP_HAVE_MLDSA | ||
| #define WP_HAVE_ML_DSA_44 | ||
| #define WP_HAVE_ML_DSA_65 | ||
| #define WP_HAVE_ML_DSA_87 | ||
| #endif | ||
| #else | ||
| #define WP_HAVE_MLDSA | ||
| #define WP_HAVE_ML_DSA_44 | ||
| #define WP_HAVE_ML_DSA_65 | ||
| #define WP_HAVE_ML_DSA_87 | ||
| #endif | ||
| #endif | ||
| #if !defined(NO_AES_CBC) && (defined(WP_HAVE_HMAC) || defined(WP_HAVE_CMAC)) | ||
| #define WP_HAVE_KBKDF | ||
| #endif | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,8 @@ show_help() { | |
| echo " --debug-silent Debug logging compiled in but silent by default. Use WOLFPROV_LOG_LEVEL and WOLFPROV_LOG_COMPONENTS env vars to enable at runtime. Requires --debug." | ||
| echo " --enable-seed-src Enable SEED-SRC entropy source with /dev/urandom caching for fork-safe entropy." | ||
| echo " Note: This also enables WC_RNG_SEED_CB in wolfSSL." | ||
| echo " --enable-pqc Build wolfSSL with ML-KEM and ML-DSA post-quantum algorithms enabled." | ||
| echo " Adds --enable-mlkem --enable-dilithium --enable-experimental to wolfSSL configure." | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. update flags to new ones (see above) |
||
| echo "" | ||
| echo "Environment Variables:" | ||
| echo " OPENSSL_TAG OpenSSL tag to use (e.g., openssl-3.5.0)" | ||
|
|
@@ -51,6 +53,7 @@ show_help() { | |
| echo " WOLFPROV_FIPS_BASELINE If set to 1, applies FIPS baseline patch to OpenSSL (mutually exclusive with WOLFPROV_REPLACE_DEFAULT)" | ||
| echo " WOLFPROV_LEAVE_SILENT If set to 1, suppress logging of return 0 in functions where return 0 is expected behavior sometimes." | ||
| echo " WOLFPROV_SEED_SRC If set to 1, enables SEED-SRC with /dev/urandom caching (also enables WC_RNG_SEED_CB in wolfSSL)" | ||
| echo " WOLFPROV_PQC If set to 1, enables ML-KEM and ML-DSA post-quantum algorithms in wolfSSL" | ||
| echo "" | ||
| } | ||
|
|
||
|
|
@@ -146,6 +149,9 @@ for arg in "$@"; do | |
| --enable-seed-src) | ||
| WOLFPROV_SEED_SRC=1 | ||
| ;; | ||
| --enable-pqc) | ||
| WOLFPROV_PQC=1 | ||
| ;; | ||
| *) | ||
| args_wrong+="$arg, " | ||
| ;; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,6 +38,11 @@ if [ "$WOLFPROV_SEED_SRC" = "1" ]; then | |
| WOLFSSL_FIPS_CONFIG_CFLAGS="${WOLFSSL_FIPS_CONFIG_CFLAGS} -DWC_RNG_SEED_CB" | ||
| fi | ||
|
|
||
| # Enable ML-KEM and ML-DSA in wolfSSL when --enable-pqc is requested | ||
| if [ "$WOLFPROV_PQC" = "1" ]; then | ||
| WOLFSSL_CONFIG_OPTS="${WOLFSSL_CONFIG_OPTS} --enable-mlkem --enable-dilithium --enable-experimental" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fix enable flags |
||
| fi | ||
|
|
||
| WOLFSSL_DEBUG_ASN_TEMPLATE=${DWOLFSSL_DEBUG_ASN_TEMPLATE:-0} | ||
| WOLFPROV_DISABLE_ERR_TRACE=${WOLFPROV_DISABLE_ERR_TRACE:-0} | ||
| WOLFPROV_DEBUG=${WOLFPROV_DEBUG:-0} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use
--enable-mldsainstead of--enable-dilithiumgoing forward. Furthermore, both ML-KEM and ML-DSA don't require--enable-experimentalanymore.