Documentation

Complete Guide to Qudo PQC

Everything you need to build, deploy, and integrate post-quantum cryptography into your applications.

Overview

Production-Ready Post-Quantum Cryptography

Qudo PQC implements NIST FIPS 203 (ML-KEM), FIPS 204 (ML-DSA), and FIPS 205 (SLH-DSA) with OpenSSL 3.x provider integration and a native C API.

📚

Four Main Components

  • qudo-mlkem — ML-KEM key encapsulation (FIPS 203)
  • qudo-mldsa — ML-DSA digital signatures (FIPS 204)
  • qudo-slhdsa — SLH-DSA hash-based signatures (FIPS 205)
  • qudo-provider — OpenSSL 3.x provider integration
🔧

Dual API Pattern

All libraries expose two interfaces:

  • Object API — Heap-allocated, user-friendly, automatic resource management
  • Direct API — Zero-allocation, caller-provided buffers, for embedded systems

Runtime CPU Dispatch

Automatic performance optimization:

  • Reference implementation (portable C99)
  • AVX2 optimizations (Intel/AMD)
  • NEON optimizations (ARM)
  • Automatic selection at runtime
Architecture

How Qudo PQC Works

The provider routes OpenSSL EVP API calls to the appropriate Qudo library, enabling seamless integration with any OpenSSL-based application.

Application / OpenSSL EVP API qudo-provider (qudoprovider.so) ├── KEM ops → qudo-mlkem (libqudo-mlkem.so) ├── Sig ops → qudo-mldsa (libqudo-mldsa.so) └── HBS ops → qudo-slhdsa (libqudo-slhdsa.so)
Quick Start

Get Running in 10 Minutes

From zero to quantum-safe TLS in six steps.

1

Check Prerequisites

Required: OpenSSL 3.4+, CMake 3.15+, C99 compiler (GCC 9+, Clang 12+, or MSVC 2019+).

# Verify OpenSSL version openssl version OpenSSL 3.5.0 8 Apr 2025
2

Download or Build

Choose pre-built binaries for your platform or build from source.

Option A — Pre-built Binaries
# Download from the releases page tar -xzf qudo-pqc-linux-x86_64.tar.gz cd qudo-pqc && sudo ./install.sh
Option B — Build from Source
git clone <repository-url> cd qudo-pqc/qudo-provider ./build.sh # builds all libs + provider ./build.sh -i # install to OpenSSL modules
3

Configure OpenSSL

Add the provider configuration block to your openssl.cnf.

# Add to /etc/ssl/openssl.cnf: openssl_conf = openssl_init [openssl_init] providers = provider_sect [provider_sect] default = default_sect qudoprovider = qudoprovider_sect [default_sect] activate = 1 [qudoprovider_sect] activate = 1 module = /usr/lib/ossl-modules/qudoprovider.so
4

Verify Installation

Confirm the provider loads correctly and all algorithms are available.

# Check provider is loaded openssl list -providers -provider qudoprovider qudoprovider name: Qudo PQC Provider version: 1.0.0 status: active # List algorithms openssl list -kem-algorithms -provider qudoprovider openssl list -signature-algorithms -provider qudoprovider # Run the test suite cd qudo-pqc/qudo-provider/build && ctest --output-on-failure 100% tests passed, 0 tests failed out of 5
5

Enable Quantum-Safe TLS

Add PQC hybrid key exchange to your web server configuration — no application code changes.

Nginx
# nginx.conf ssl_ecdh_curve X25519MLKEM768:X25519; sudo systemctl restart nginx
Apache
# ssl.conf SSLOpenSSLConfCmd Groups X25519MLKEM768:X25519 sudo systemctl restart apache2
6

Test Quantum-Safe Connection

Verify your server is negotiating post-quantum key exchange with clients.

# Connect with PQC hybrid key exchange openssl s_client -connect yourserver.com:443 \ -provider qudoprovider -groups X25519MLKEM768 New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384 Server Temp Key: X25519MLKEM768, 1216 bits # Your server is now quantum-safe!
Build Config

CMake Build Configuration

Configure the build system with CMake flags to enable or disable specific features for your target environment.

Common Options
BUILD_SHARED_LIBS=ON
Build shared libraries (.so / .dylib)
MLKEM_DIST_BUILD=ON
Distribution build with all CPU targets
BUILD_TESTS=ON
Build unit and KAT test suites
BUILD_EXAMPLES=ON
Build integration example programs
Provider-Specific Options
QUDO_PROV_BUILD_TESTS=ON
Build provider integration tests
QUDO_PROV_BUILD_EXAMPLES=ON
Build provider example programs
QUDO_PROV_ENABLE_DEBUG=OFF
Enable verbose debug output
Example CMake invocation:
cmake -B build \ -DBUILD_SHARED_LIBS=ON \ -DMLKEM_DIST_BUILD=ON \ -DBUILD_TESTS=ON
Algorithms

Supported PQC Algorithms

NIST-standardized algorithms covering key encapsulation, digital signatures, and hash-based signatures.

Key Encapsulation (ML-KEM / FIPS 203)
Pure KEM
mlkem512mlkem768mlkem1024
Hybrid KEM
X25519MLKEM768SecP256r1MLKEM768SecP384r1MLKEM768SecP521r1MLKEM1024
Digital Signatures (ML-DSA / FIPS 204)
Pure ML-DSA
ML-DSA-44ML-DSA-65ML-DSA-87
Hybrid Signatures
ED25519+ML-DSA-44ED25519+ML-DSA-65ECDSA-P256+ML-DSA-44ECDSA-P384+ML-DSA-65ECDSA-P521+ML-DSA-87
Hash-Based Signatures (SLH-DSA / FIPS 205)
SLH-DSA-SHA2-128fSLH-DSA-SHA2-128sSLH-DSA-SHA2-192fSLH-DSA-SHA2-192sSLH-DSA-SHA2-256fSLH-DSA-SHA2-256sSLH-DSA-SHAKE-128fSLH-DSA-SHAKE-128sSLH-DSA-SHAKE-192fSLH-DSA-SHAKE-192sSLH-DSA-SHAKE-256fSLH-DSA-SHAKE-256s

Stateless hash-based signatures for long-term document integrity (20+ years).

Integration Features
  • DER/PEM serialization for all key types
  • X.509 certificate support
  • PKCS#11 v3.0 compatible interface
  • OpenSSL EVP API drop-in
  • TLS 1.3 hybrid groups
  • Chrome 131+ / Firefox 128+ / Safari 18+
API Reference

API Quick Reference

Key functions across all three libraries. All functions return status codes (0 = success).

QUDO_KEM (ML-KEM)
Object API
QUDO_KEM_new()QUDO_KEM_keypair()QUDO_KEM_encaps()QUDO_KEM_decaps()QUDO_KEM_free()
Direct API
QUDO_KEM_768_keypair()QUDO_KEM_768_encaps()QUDO_KEM_768_decaps()
Header: mlkem_wrapper.h
QUDO_SIG (ML-DSA)
Object API
QUDO_SIG_new()QUDO_SIG_keypair()QUDO_SIG_sign()QUDO_SIG_verify()QUDO_SIG_free()
Serialization
QUDO_SIG_export_pubkey_pem()QUDO_SIG_import_pubkey_pem()QUDO_SIG_export_keypair_der()
Header: mldsa_wrapper.h
QUDO_SLHDSA (SLH-DSA)
Object API
QUDO_SLHDSA_new()QUDO_SLHDSA_keypair()QUDO_SLHDSA_sign()QUDO_SLHDSA_verify()QUDO_SLHDSA_free()
12 Parameter Sets
SHA2 × 128/192/256 × s/fSHAKE × 128/192/256 × s/f
Header: slhdsa_wrapper.h
OpenSSL Provider API (EVP Interface)

When using the provider, all standard OpenSSL EVP functions work transparently with PQC algorithms.

Key Management
EVP_PKEY_keygen()PEM_write_bio_PrivateKey()PEM_read_bio_PrivateKey()
KEM Operations
EVP_PKEY_encapsulate()EVP_PKEY_decapsulate()SSL_CTX_set1_groups_list()
Signature Operations
EVP_DigestSign()EVP_DigestVerify()X509_sign()
Code Examples

Integration Examples

Production-ready code examples for all three libraries and the OpenSSL EVP provider interface.

C API — ML-KEM Key Exchange
#include "mlkem_wrapper.h" int main(void) { // Create KEM context QUDO_KEM *kem = QUDO_KEM_new(QUDO_KEM_768); if (!kem) return -1; // Generate key pair uint8_t pk[MLKEM768_PUBLICKEYBYTES]; uint8_t sk[MLKEM768_SECRETKEYBYTES]; QUDO_KEM_keypair(kem, pk, sk); // Encapsulate (sender side) uint8_t ct[MLKEM768_CIPHERTEXTBYTES]; uint8_t ss_enc[MLKEM768_SSBYTES]; QUDO_KEM_encaps(kem, ct, ss_enc, pk); // Decapsulate (receiver side) uint8_t ss_dec[MLKEM768_SSBYTES]; QUDO_KEM_decaps(kem, ss_dec, ct, sk); QUDO_KEM_free(kem); return 0; }
C API — ML-DSA Signatures
#include "mldsa_wrapper.h" int main(void) { // Create signature context QUDO_SIG *sig = QUDO_SIG_new(QUDO_SIG_ML_DSA_65); if (!sig) return -1; // Generate key pair uint8_t pk[MLDSA65_PUBLICKEYBYTES]; uint8_t sk[MLDSA65_SECRETKEYBYTES]; QUDO_SIG_keypair(sig, pk, sk); // Sign a message const uint8_t msg[] = "Hello, quantum world!"; uint8_t signature[MLDSA65_SIGBYTES]; size_t sig_len; QUDO_SIG_sign(sig, signature, &sig_len, msg, sizeof(msg), sk); // Verify the signature int ok = QUDO_SIG_verify(sig, signature, sig_len, msg, sizeof(msg), pk); QUDO_SIG_free(sig); return ok == 0 ? 0 : -1; }
C API — SLH-DSA Signatures
#include "slhdsa_wrapper.h" int main(void) { // Create SLH-DSA context (SHA2-128f for speed) QUDO_SLHDSA *ctx = QUDO_SLHDSA_new(QUDO_SLHDSA_SHA2_128F); if (!ctx) return -1; // Generate key pair uint8_t pk[SLHDSA_SHA2_128F_PKBYTES]; uint8_t sk[SLHDSA_SHA2_128F_SKBYTES]; QUDO_SLHDSA_keypair(ctx, pk, sk); // Sign a document const uint8_t doc[] = "Long-lived document"; uint8_t sig[SLHDSA_SHA2_128F_SIGBYTES]; size_t sig_len; QUDO_SLHDSA_sign(ctx, sig, &sig_len, doc, sizeof(doc), sk); // Verify int ok = QUDO_SLHDSA_verify(ctx, sig, sig_len, doc, sizeof(doc), pk); QUDO_SLHDSA_free(ctx); return ok == 0 ? 0 : -1; }
OpenSSL EVP API — Provider Integration
#include <openssl/evp.h> #include <openssl/provider.h> int main(void) { // Load the Qudo provider OSSL_PROVIDER *prov = OSSL_PROVIDER_load(NULL, "qudoprovider"); if (!prov) return -1; // Create key generation context for ML-KEM-768 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "mlkem768", NULL); EVP_PKEY_keygen_init(ctx); // Generate key pair EVP_PKEY *pkey = NULL; EVP_PKEY_keygen(ctx, &pkey); // Use pkey with standard EVP API... // EVP_PKEY_encapsulate(), EVP_PKEY_decapsulate() EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); OSSL_PROVIDER_unload(prov); return 0; }
OpenSSL Command Line — TLS with PQC

Use the OpenSSL CLI to generate PQC keys, create certificates, and run a quantum-safe TLS server end-to-end.

# Generate ML-DSA key pair openssl genpkey -algorithm ML-DSA-65 \ -provider qudoprovider -out mldsakey.pem # Create self-signed certificate openssl req -new -x509 -key mldsakey.pem \ -out cert.pem -days 365 -provider qudoprovider # Start TLS server with hybrid KEM openssl s_server -cert cert.pem -key mldsakey.pem \ -groups X25519MLKEM768 -provider qudoprovider # Connect as client openssl s_client -connect localhost:4433 \ -groups X25519MLKEM768 -provider qudoprovider
Testing

Testing Your Integration

A complete test pyramid from unit tests through interoperability and memory safety validation.

1

Unit Tests

Run per-library unit tests and Known Answer Tests (KATs) to verify correctness.

# ML-KEM tests cd qudo-pqc/qudo-mlkem/build ./test_basic && ./test_kat && ./test_kat_nist # ML-DSA tests cd qudo-pqc/qudo-mldsa/build ./test_basic && ./test_kat # SLH-DSA tests cd qudo-pqc/qudo-slhdsa/build ./test_basic && ./test_kat
2

Provider Tests

Run the CTest suite against the OpenSSL provider to confirm all algorithms register correctly.

cd qudo-pqc/qudo-provider/build ctest --output-on-failure -V # Run specific provider tests ./test_provider_kem ./test_provider_sig ./test_provider_tls
3

Interoperability Tests

Verify cross-implementation compatibility with NIST reference vectors.

cd qudo-pqc/tests ./run_all_interop_tests.sh # Per-algorithm interop ./test_interop_mlkem.sh ./test_interop_mldsa.sh ./test_interop_slhdsa.sh
4

Memory Safety & Performance

Run Valgrind for memory safety and OpenSSL speed benchmarks.

# Memory safety check valgrind --leak-check=full ./test_basic valgrind --tool=memcheck ./test_kat # Performance benchmarks openssl speed -provider qudoprovider mlkem768 openssl speed -provider qudoprovider ml-dsa-65 openssl speed -provider qudoprovider slh-dsa-sha2-128f
Performance

Benchmark Results

Measured on Intel Xeon (AVX2) with Qudo PQC v1.0. Median of 10,000 iterations.

ML-KEM Key Exchange (FIPS 203)
KeyGenEncapsDecaps
mlkem512~20µs~28µs~32µs
mlkem768~30µs~40µs~45µs
mlkem1024~48µs~55µs~60µs

2–5x faster than RSA-2048 key exchange. TLS handshakes: 15,000+/sec (X25519MLKEM768 hybrid)

ML-DSA Signatures (FIPS 204)
KeyGenSignVerify
ML-DSA-44~50µs~140µs~60µs
ML-DSA-65~80µs~200µs~90µs
ML-DSA-87~120µs~300µs~140µs

Competitive with ECDSA P-256. Signature sizes: 2,420 / 3,293 / 4,595 bytes

SLH-DSA Hash-Based Signatures (FIPS 205)
KeyGenSignVerifySig Size
SHA2-128f2ms50ms3ms17,088B
SHA2-128s2ms800ms3ms7,856B

Conservative, hash-based security. Best for: long-lived documents, root certificates

Key & Ciphertext Sizes
mlkem768
Public Key1,184 B
Secret Key2,400 B
Ciphertext1,088 B
Shared Secret32 B
ML-DSA-65
Public Key1,952 B
Secret Key4,032 B
Signature3,293 B
Run Your Own Benchmarks

Use the built-in benchmark suite or OpenSSL speed to measure performance on your own hardware.

# Run the built-in benchmark suite cd qudo-pqc/build && ./benchmark_all # OpenSSL speed benchmarks openssl speed -provider qudoprovider mlkem768 openssl speed -provider qudoprovider ml-dsa-65 openssl speed -provider qudoprovider x25519mlkem768 # Compare with classical algorithms openssl speed ecdhp256 rsa2048
Deployment

Deployment Strategies

Three deployment modes to match your migration timeline and risk tolerance.

Plug-In Provider
Zero application code changes

Copy the provider and library files, update openssl.cnf, and restart your services.

  • Copy qudoprovider.so to OpenSSL modules directory
  • Copy libqudo-pqc.so to OpenSSL lib directory
  • Add provider block to openssl.cnf
  • Restart services — PQC algorithms immediately available
Hybrid Mode
Gradual migration path

Run PQC alongside classical algorithms. Existing clients stay connected while new ones get quantum protection.

  • X25519MLKEM768 hybrid key exchange for TLS
  • SecP256r1MLKEM768 for EC-based infrastructure
  • Existing systems stay connected during migration
  • Gradual rollout with zero downtime
Full Quantum-Safe
Long-term security posture

Migrate to pure PQC algorithms for maximum future-proofing.

  • mlkem512/768/1024 for key encapsulation
  • ML-DSA-44/65/87 for digital signatures
  • SLH-DSA variants for long-lived documents
  • Long-term security against quantum adversaries
Security

Security Best Practices

Follow these guidelines to maximize the security of your Qudo PQC integration.

Use Hybrid Mode First
  • X25519MLKEM768 for TLS key exchange
  • Recommended by NIST, NSA, NCSC, and BSI
  • Dual signatures for critical operations
  • Fallback to classical on incompatible clients
Key Management
  • Zero sensitive data with OPENSSL_cleanse()
  • Use Object API for automatic cleanup
  • Store private keys encrypted at rest
  • Rotate keys on a regular schedule
Algorithm Selection Guide
  • TLS/key exchange: mlkem768 or X25519MLKEM768
  • Auth/code signing: ML-DSA-65
  • High-security: mlkem1024 + ML-DSA-87
  • Long-lived documents: SLH-DSA-SHA2-128s
  • Frequent signing (low latency): ML-DSA-44
Migration Checklist
  • Inventory all cryptographic assets
  • Test in staging environment with hybrid mode
  • Verify browser and client compatibility
  • Monitor TLS negotiation logs
  • Run full interoperability test suite
  • Plan certificate reissuance schedule
Troubleshooting

Common Issues & Solutions

Diagnostic commands and solutions for the most frequent integration problems.

?

Provider Not Loading

The provider module cannot be found. Check file paths and permissions.

# Verify OpenSSL module pathopenssl version -mls $(openssl version -m | awk '{print $2}')/qudoprovider.sols $(openssl version -m | awk '{print $2}')/../libqudo-pqc.so# Test provider load directlyopenssl list -providers -provider qudoprovider
?

Build Failures

CMake cannot locate OpenSSL headers or the wrong version is found.

# Set OpenSSL root explicitlyexport OPENSSL_ROOT_DIR=/opt/homebrew/opt/openssl@3cmake -B build -DOPENSSL_ROOT_DIR=$OPENSSL_ROOT_DIR \ -DBUILD_SHARED_LIBS=ON -DMLKEM_DIST_BUILD=ONcmake --build build -j$(nproc)
?

Algorithm Not Found

PQC algorithms are not listed after provider configuration.

# List available algorithmsopenssl list -kem-algorithms -provider qudoprovideropenssl list -signature-algorithms -provider qudoprovider# Verify provider section in configcat /etc/ssl/openssl.cnf | grep -A5 qudoprovider
?

TLS Handshake Failing

Connections fail or fall back to classical key exchange unexpectedly.

# Debug TLS negotiationopenssl s_client -connect yourserver.com:443 \ -provider qudoprovider -groups X25519MLKEM768 -debug# Check server confignginx -T | grep ssl_ecdh_curve
?

OpenSSL Version Mismatch

The provider was built against a different OpenSSL version than installed.

# Check installed versionopenssl version# Install OpenSSL 3.4+apt install libssl-dev openssl # Debian/Ubuntubrew install openssl@3 # macOS
?

Shared Library Not Found

Runtime linker cannot locate libqudo-pqc.so after installation.

# Refresh linker cache (Linux)sudo ldconfig# Or set library path manuallyexport LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATHexport DYLD_LIBRARY_PATH=/usr/local/lib # macOSopenssl version -m
?

Enable Debug Output

Get verbose logging to diagnose provider initialization and algorithm dispatch.

# Build provider with debug symbolscmake -B build -DQUDO_PROV_ENABLE_DEBUG=ON# Enable OpenSSL trace outputOSSL_TRACE=provider openssl list -providers -provider qudoprovider
Resources

Additional Resources

Source code, pre-built binaries, and official NIST standards.

GitHub Repository
  • qudo-mlkem — ML-KEM library
  • qudo-mldsa — ML-DSA library
  • qudo-slhdsa — SLH-DSA library
  • qudo-provider — OpenSSL provider
Pre-Built Downloads
  • Linux x86_64, ARM64, ARM32
  • macOS Apple Silicon & Intel
  • Windows MSVC & MinGW
  • Provider + individual libraries
NIST Standards
  • FIPS 203 — ML-KEM standard
  • FIPS 204 — ML-DSA standard
  • FIPS 205 — SLH-DSA standard
  • NSA CNSA 2.0 guidance
FAQ

Frequently Asked Questions

Answers to the most common questions about deploying Qudo PQC.

No. Qudo PQC is a drop-in OpenSSL 3.x provider. It installs alongside your existing OpenSSL setup without any application code changes. The hybrid key exchange mode (X25519MLKEM768) means existing clients that don't support PQC continue to connect normally — you get zero downtime during migration.
ML-KEM is actually 2–5× faster than RSA-2048 key exchange. The hybrid TLS mode (X25519MLKEM768) supports 15,000+ handshakes per second on modern hardware. ML-DSA signing is competitive with ECDSA P-256. The only algorithm with significant overhead is SLH-DSA, which is recommended only for long-lived documents — not real-time operations.
Yes. NIST published the final FIPS 203, 204, and 205 standards in August 2024 following an 8-year public evaluation. The NSA's CNSA 2.0 mandate requires PQC adoption between 2026 and 2033. Chrome 131+, Firefox 128+, and Safari 18+ already use X25519MLKEM768 by default for TLS. Qudo PQC implements these final NIST standards.
Yes. Hybrid mode is the recommended deployment path. X25519+MLKEM768 combines classical and post-quantum key exchange — an attacker must break both to compromise the session. Hybrid signatures (ECDSA+ML-DSA) provide the same protection for authentication. This approach is explicitly recommended by NIST, NSA, NCSC, and BSI as the transition strategy.
Qudo PQC adds a dual-signature layer to blockchain transactions. The existing ECDSA or EdDSA wallet signature is preserved, and an additional ML-DSA signature is bound to the transaction metadata. This means existing on-chain verification continues to work while adding quantum resistance. The dual-signature approach ensures backward compatibility with deployed smart contracts and wallet infrastructure.
Chrome 131+, Firefox 128+, and Safari 18+ all negotiate X25519MLKEM768 by default when the server supports it. Once you deploy Qudo PQC with the X25519MLKEM768 group configured, these browsers will automatically use quantum-safe key exchange — no user action or configuration required. You can verify the negotiated group with openssl s_client.
Need Help?

Get Support

Our engineering team is here to help you integrate Qudo PQC successfully.