mldsa-native is a secure, fast, and portable C90 implementation of the ML-DSA1 post-quantum signature standard. It is a fork of the ML-DSA reference implementation2.
The goal of mldsa-native is paralleling mlkem-native for ML-KEM. All C code in mldsa/src/* and mldsa/src/fips202/* is proved memory-safe (no memory overflow) and type-safe (no integer overflow) using CBMC.
mldsa-native includes native backends for Arm (64-bit, Neon), and Intel/AMD (64-bit, AVX2). See benchmarks for performance data.
mldsa-native is supported by the Post-Quantum Cryptography Alliance as part of the Linux Foundation.
# Install base packages
sudo apt-get update
sudo apt-get install make gcc python3 git
# Clone mldsa-native
git clone https://github.com/pq-code-package/mldsa-native.git
cd mldsa-native
# Build and run tests
make build
make test
# The same using `tests`, a convenience wrapper around `make`
./scripts/tests all
# Show all options
./scripts/tests --helpWe use the C Bounded Model Checker (CBMC) to prove absence of various classes of undefined behaviour in C, including out of bounds memory accesses and integer overflows. The proofs cover all C code in mldsa/src/* and mldsa/src/fips202/* involved in running mldsa-native with its C backend. See proofs/cbmc for details.
HOL-Light functional correctness proofs can be found in proofs/hol_light/x86_64. So far, the following functions have been proven correct:
- x86_64 NTT ntt.S
These proofs are utilizing the verification infrastructure in s2n-bignum.
All assembly in mldsa-native is constant-time in the sense that it is free of secret-dependent control flow, memory access, and instructions that are commonly variable-time, thwarting most timing side channels. C code is hardened against compiler-introduced timing side channels through suitable barriers and constant-time patterns.
Absence of secret-dependent branches, memory-access patterns and variable-latency instructions is also tested using valgrind
with various combinations of compilers and compilation options.
mldsa-native is split into a frontend and two backends for arithmetic and FIPS202 / SHA3. The frontend is fixed, written in C, and covers all routines that are not critical to performance. The backends are flexible, take care of performance-sensitive routines, and can be implemented in C or native code (assembly/intrinsics); see mldsa/src/native/api.h for the arithmetic backend and mldsa/src/fips202/native/api.h for the FIPS-202 backend.
mldsa-native currently offers the following backends:
- Default portable C backend
- 64-bit Arm backend (using Neon)
- 64-bit Intel/AMD backend (using AVX2)
If you'd like contribute new backends, please reach out!
mldsa-native is tested against all official ACVP ML-DSA test vectors3.
You can run ACVP tests using the tests script or the ACVP client directly:
# Using the tests script
./scripts/tests acvp
# Using a specific ACVP release
./scripts/tests acvp --version v1.1.0.40
# Using the ACVP client directly
python3 ./test/acvp_client.py
python3 ./test/acvp_client.py --version v1.1.0.40
# Using specific ACVP test vector files (downloaded from the ACVP-Server)
# python3 ./test/acvp_client.py -p {PROMPT}.json -e {EXPECTED_RESULT}.json
# For example, assuming you have run the above
python3 ./test/acvp_client.py \
-p ./test/.acvp-data/v1.1.0.40/files/ML-DSA-sigVer-FIPS204/prompt.json \
-e ./test/.acvp-data/v1.1.0.40/files/ML-DSA-sigVer-FIPS204/expectedResults.jsonYou can measure performance, memory usage, and binary size using the tests script:
# Speed benchmarks (-c selects cycle counter: NO, PMU, PERF, or MAC)
# Note: PERF/MAC may require the -r flag to run benchmarking binaries using sudo
./scripts/tests bench -c PMU
./scripts/tests bench -c PERF -r
# Stack usage analysis
./scripts/tests stack
# Binary size measurement
./scripts/tests sizeFor CI benchmark results and historical performance data, see the benchmarking page.
Once mldsa-native reaches production readiness, you will be able to import mldsa into your project's source tree and build using your preferred build system. The build system provided in this repository is for development purposes only.
mldsa-native relies on and comes with an implementation of FIPS-2024. If your library has its own FIPS-202 implementation, you can use it instead of the one shipped with mldsa-native. See FIPS202.md, and examples/bring_your_own_fips202 for an example using tiny_sha35.
No. If you want a C-only build, just omit the directories mldsa/src/native and/or mldsa/src/fips202/native from your import
and unset MLD_CONFIG_USE_NATIVE_BACKEND_ARITH and/or MLD_CONFIG_USE_NATIVE_BACKEND_FIPS202 in your config.h.
No. While we recommend that you consider using it, mldsa-native will build + run fine without CBMC -- just make sure to
include cbmc.h and have CBMC undefined. In particular, you do not need to remove all function
contracts and loop invariants from the code; they will be ignored unless CBMC is set.
Yes. mldsa-native supports all three ML-DSA security levels (ML-DSA-44, ML-DSA-65, ML-DSA-87) as defined in FIPS 204. The security level is a compile-time parameter configured by setting MLD_CONFIG_PARAMETER_SET=44/65/87 in config.h.
By default, mldsa-native uses the randomized "hedged" signing variant as specified in FIPS 204 Section 3.4. The hedged variant uses both fresh randomness at signing time and precomputed randomness from the private key. This helps mitigate fault injection attacks and side-channel attacks while protecting against potential flaws in the random number generator.
If you need the deterministic variant of ML-DSA, you can call crypto_sign_signature_internal
directly with an all-zero rnd argument.
However, note that FIPS 204 warns that this should not be used on platforms where fault injection attacks and side-channel attacks are a concern, as the lack of fresh randomness makes fault attacks more difficult to mitigate.
Yes. mldsa-native supports external mu mode, which allows for pre-hashing of messages before signing. This addresses the pre-hashing capability described in the NIST PQC FAQ6 and detailed in NIST's guidance on FIPS 204 Section 67.
External mu mode enables applications to compute the message digest (mu) externally and provide it to the signing implementation, which is particularly useful for large messages or streaming applications where the entire message cannot be held in memory during signing.
Yes. mldsa-native supports HashML-DSA, the pre-hashing variant of ML-DSA defined in FIPS 204 Algorithms 4 and 5.
mldsa-native provides two levels of API:
crypto_sign_signature_pre_hash_internalandcrypto_sign_verify_pre_hash_internal- Low-level functions that accept a pre-hashed message digest. This function supports all 12 allowed hash functions.crypto_sign_signature_pre_hash_shake256andcrypto_sign_verify_pre_hash_shake256- High-level functions that perform SHAKE256 pre-hashing internally for convenience. Currently, only SHAKE256 is supported. If you require another hash function, use the*_pre_hash_internalfunctions or open an issue.
If you think you have found a security bug in mldsa-native, please report the vulnerability through Github's private vulnerability reporting. Please do not create a public GitHub issue.
If you have any other question / non-security related issue / feature request, please open a GitHub issue.
If you want to help us build mldsa-native, please reach out. You can contact the mldsa-native team through the PQCA Discord. See also CONTRIBUTING.md.
Footnotes
-
National Institute of Standards and Technology: FIPS 204 Module-Lattice-Based Digital Signature Standard, https://csrc.nist.gov/pubs/fips/204/final ↩
-
Bai, Ducas, Kiltz, Lepoint, Lyubashevsky, Schwabe, Seiler, Stehlé: CRYSTALS-Dilithium reference implementation, https://github.com/pq-crystals/dilithium/tree/master/ref ↩
-
National Institute of Standards and Technology: Automated Cryptographic Validation Protocol (ACVP) Server, https://github.com/usnistgov/ACVP-Server ↩
-
National Institute of Standards and Technology: FIPS202 SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions, https://csrc.nist.gov/pubs/fips/202/final ↩
-
Markku-Juhani O. Saarinen: tiny_sha3, https://github.com/mjosaarinen/tiny_sha3 ↩
-
National Institute of Standards and Technology: Post-Quantum Cryptography FAQs, https://csrc.nist.gov/Projects/post-quantum-cryptography/faqs#Rdc7 ↩
-
National Institute of Standards and Technology: FIPS 204 Section 6 Guidance, https://csrc.nist.gov/csrc/media/Projects/post-quantum-cryptography/documents/faq/fips204-sec6-03192025.pdf ↩