A playground for post-quantum cryptography (PQC) on embedded systems and edge devices
This repository serves as a comprehensive research and development platform for post-quantum cryptography implementation on embedded systems and edge devices. It includes working examples, hybrid PQC implementations, and testing frameworks for evaluating quantum-resistant cryptographic algorithms in resource-constrained environments.
Post-quantum cryptography (PQC) has emerged as a critical security technology as organizations prepare for the quantum computing threat. With NIST's finalization of the first PQC standards in August 2024, the field is rapidly transitioning from research to practical implementation, particularly in embedded systems and edge devices where resource constraints present unique challenges.
The rise of quantum computing threatens all current public-key schemes (RSA, ECC, etc.). Shor's algorithm can break these by efficiently solving factorization or discrete-logarithm problems, making "harvest-now, decrypt-later" attacks a real concern for long-lived IoT data once quantum hardware matures. Embedded devices often use weaker crypto already and remain in service for many years, making the upgrade to quantum-resistant algorithms essential.
NIST has selected four primary algorithms for standardization:
- FIPS 203 (ML-KEM): Module-Lattice-Based Key-Encapsulation Mechanism, derived from CRYSTALS-Kyber
- FIPS 204 (ML-DSA): Module-Lattice-Based Digital Signature Algorithm based on CRYSTALS-Dilithium
- FIPS 205 (SLH-DSA): Stateless Hash-Based Digital Signature Algorithm derived from SPHINCS+
- FIPS 206 (FN-DSA): Based on the FALCON algorithm (expected late 2024)
These represent five main mathematical approaches: lattice-based, code-based, hash-based, isogeny-based, and multivariate cryptography. Lattice-based algorithms dominate due to their balance of security, performance, and manageable key sizes.
Resource Constraints: PQC algorithms impose significant resource requirements compared to classical cryptography. While ECC requires only ~32 bytes for keys, ML-KEM-768 needs 1,184 bytes for public keys and up to 2,400 bytes for complete secret keys. Fast implementations of ML-DSA can consume 50 KiB of RAM, problematic for devices with as little as 8-16 KiB available.
Performance Impact: Embedded systems face substantial computational overhead. For example, CRYSTALS-Kyber-512 on a 24 MHz Cortex-M4 requires ≈0.65M CPU cycles for keygen and ≈0.96M for decapsulation, using ~9 KB RAM. Highly optimized assembly can cut this roughly in half and reduce RAM to ~2.5 KB. In contrast, hash-based signatures like SPHINCS+ can take tens of seconds to minutes to generate signatures, making them impractical for many IoT uses.
| Algorithm | Type | Key/Signature Sizes | Performance Notes |
|---|---|---|---|
| CRYSTALS-Kyber-512 | KEM | Pub Key ~800B; Ciphertext ~768B | Fast (~0.5M cycles decaps on Cortex-M4); low RAM (~2-3KB optimized) |
| CRYSTALS-Dilithium-2 | Signature | Pub Key ~1300B; Signature ~2420B | Moderate speed: sign ~6.15M cycles, verify ~1.46M cycles on M4; RAM ~12-14KB |
| Falcon-1024 | Signature | Pub Key ~1.3KB; Signature ~690B | Small signatures but heavy FFT math; slower than Dilithium |
| SPHINCS+-128f | Signature | Pub Key ~32B; Signature ~8-10KB | Very large signatures; extremely slow signing (seconds to minutes) |
Open Quantum Safe (OQS): Provides the most comprehensive toolkit with liboqs library offering a unified C API for quantum-resistant algorithms, supporting all NIST-selected standards plus alternative candidates.
Commercial Solutions: wolfSSL/wolfCrypt leads with strong early PQC support, implementing ML-KEM (Kyber), ML-DSA (Dilithium), SPHINCS+, plus LMS/HSS and XMSS. It's optimized for x86 and ARM with small footprints and integrates into (D)TLS 1.3, MQTT, SSH.
Hardware Vendor Solutions: STMicroelectronics has integrated PQC algorithms into MCUs through X-CUBE-PQC software library. Microchip's MEC175xB MCU family includes immutable hardware engines for ML-DSA, LMS, and ML-KEM.
Hybrid Approaches: Combine traditional and PQC algorithms to hedge against both classical and quantum attacks. For key exchange, this involves combining ML-KEM with ECDH. Digital signatures require dual signing with both classical and PQC schemes.
Cryptographic Agility: Enable systems to easily update cryptographic algorithms without major architectural changes. This requires standardized interfaces, firmware update capabilities, and hardware roots of trust.
Edge Computing Offloading: Leverage edge computing to address IoT device limitations, allowing devices to offload cryptographic tasks to post-quantum edge servers while maintaining local capabilities for critical operations.
- United Kingdom: Discovery phases by 2028, high-priority migrations by 2031, full transitions by 2035
- Canada: Migration plans by April 2026, high-priority systems by end of 2031, remaining systems by 2035
- United States: CNSA 2.0 sets aggressive timelines with exclusive use requirements ranging from 2025 for software/firmware signing to 2033 for legacy equipment
The PQC market is experiencing explosive growth, valued at $297.82 million in 2024 and projected to reach $2.49 billion by 2030 with a 42.5% CAGR. This growth is driven by increasing awareness of quantum threats, government mandates, and the "harvest now, decrypt later" attack vector.
- Begin cryptographic asset discovery immediately, prioritizing systems with long data lifespans or critical security functions
- Focus on cryptographic agility, hybrid implementations, and collaboration with hardware vendors
- Test PQC libraries on target hardware (possibly in hybrid mode)
- Follow evolving standards such as NIST's and industry consortium recommendations
- Plan for hybrid/rollback paths until PQC is fully trusted
The window for proactive migration is narrowing - with quantum computers potentially arriving in the early 2030s, organizations must act decisively to protect their digital infrastructure against future quantum threats.
The repository includes a performance test suite that supports two ML-KEM-768 implementations on ESP32, allowing direct comparison of different library approaches:
| Metric | liboqs-based | ml-kem C++20 | Difference |
|---|---|---|---|
| Init | 209 μs (0.209 ms) | 139 μs (0.139 ms) | ml-kem 33% faster |
| Keypair | 17,606 μs (17.606 ms) | 23,731 μs (23.731 ms) | liboqs 26% faster |
| Encaps | 19,874 μs (19.874 ms) | 27,740 μs (27.740 ms) | liboqs 28% faster |
| Decaps | 22,795 μs (22.795 ms) | 31,098 μs (31.098 ms) | liboqs 27% faster |
| Cleanup | 41 μs (0.041 ms) | 52 μs (0.052 ms) | liboqs 21% faster |
| Total | 85,340 μs (85.340 ms) | 101,638 μs (101.638 ms) | liboqs 16% faster |
| Stack Used | 15,208 bytes | 30,168 bytes | ml-kem uses 2x more |
| Heap Peak | ~4.9 KB | ~9.7 KB | ml-kem uses 2x more |
liboqs-based Implementation:
- ✅ Faster overall: 16% faster total execution time
- ✅ Lower memory footprint: Uses half the stack and heap compared to ml-kem
- ✅ Mature and optimized: Well-tested production library with platform-specific optimizations
- ✅ Better for embedded: Lower resource usage makes it more suitable for constrained devices
ml-kem C++20 Implementation:
- ✅ Faster initialization: 33% faster context setup
- ✅ Header-only: No separate library build required, easier integration
- ✅ Modern C++20: Leverages constexpr and compile-time optimizations
⚠️ Higher memory usage: Requires approximately 2x stack and heap⚠️ Slower operations: 26-28% slower for keypair, encaps, and decaps operations
- Chip: ESP32-D0WD (revision v1.0)
- CPU Frequency: 160 MHz
- ESP-IDF Version: v6.1
- Stack Size: 65,536 bytes (test task)
The performance test supports both implementations via a CMake option:
# Test with liboqs (default)
cd components/liboqs_mlkem/tests/performance
idf.py build flash monitor
# Test with ml-kem C++20 library
cd components/liboqs_mlkem/tests/performance
idf.py -DUSE_ML_KEM_LIBRARY=ON build flash monitorSee components/liboqs_mlkem/tests/performance/README.md for detailed documentation.
A minimal TCP client/server demonstrating ML-KEM-512 + AES-256-GCM lives in examples/host (see its README for details). It uses liboqs for KEM and supports OpenSSL or mbedTLS for HKDF and AEAD (AES-GCM).
Build quickstart:
cd examples/host && mkdir -p build && cd build
cmake -DCRYPTO_BACKEND_DEFAULT=openssl .. && make -j
# or use mbedTLS for HKDF + AES-GCM
cmake -DUSE_OPENSSL_BACKEND=OFF -DUSE_MBEDTLS_BACKEND=ON -DCRYPTO_BACKEND_DEFAULT=mbedtls .. && make -j
Runtime switching is available via crypto_set_operation_backend(...) in the example code.
examples/host/: TCP client/server demo using ML-KEM-512 + AES-256-GCM; CMake project producingbin/server,bin/client,bin/test_backends.impl/: third‑party PQC libraries and embedded implementations:liboqs/(Open Quantum Safe),mbedtls/,kybesp32/(ESP‑IDF project withcomponents/*andmain/).
- Docs and notes:
README.md,impl/README.md,research*.md.
- Host demo (CMake):
cd examples/host && mkdir -p build && cd buildcmake ..(requires CMake ≥3.15, a C compiler, OpenSSL dev headers)make -j(builds server, client, tests)- Run:
./bin/serverand./bin/clientin separate shells. - Options:
cmake -DUSE_MBEDTLS_BACKEND=OFF ..,cmake -DCRYPTO_BACKEND_DEFAULT=mbedtls ...
- ESP32 (optional):
cd impl/kybesp32 && idf.py build flash monitor(requires ESP‑IDF).
- C99 with warnings:
-Wall -Wextra. Prefer 4‑space indentation, K&R braces. - Names: snake_case for functions/files, UPPER_CASE for macros,
typedefsuffixed_t. - Headers expose public APIs; source files keep internals static. Use header guards and minimal includes.
- Build tests with the host demo and run
./bin/test_backendsfromexamples/host/build. - Add focused tests next to sources (e.g.,
test_*.c) and wire them inexamples/host/CMakeLists.txt. - Cover new crypto paths, error handling, and backend selection logic.
- Conventional Commits style:
feat:,fix:,docs:,build:,demo:; include scope when helpful (e.g.,fix(mbedtls): ...). - PRs include: clear summary, rationale, how to test, logs/screenshots if relevant, and affected paths (e.g.,
examples/host/*). - Keep changes minimal and self‑contained; link related issues.
- Never commit secrets or private keys. Zeroize sensitive buffers on error paths.
- OpenSSL is required for the OpenSSL backend;
liboqsandmbedtlsbuild fromimpl/via CMake.
- Do not edit generated files (e.g.,
examples/host/build/*). - Prefer minimal diffs consistent with current structure; update docs when behavior changes.
To run the main MCP server for hybrid PQC testing:
cd hybrid/mcp
python fast_server.pyThis starts the Model Context Protocol (MCP) server that provides tools for running fast hybrid PQC TLS tests between OpenSSL server and mbedTLS client.
To run the C/C++ host demo:
cd examples/host && mkdir -p build && cd build
cmake -DCRYPTO_BACKEND_DEFAULT=openssl .. && make -j
# Run server in one terminal
./bin/server
# Run client in another terminal
./bin/clientTo build and flash the ESP32 target:
cd examples/target
idf.py build flash monitorTo test the MCP server functionality:
cd hybrid/mcp
python test_mcp.pyThis runs a comprehensive test of the hybrid PQC TLS implementation, including:
- OpenSSL server startup
- mbedTLS client build and execution
- Handshake testing
- Output collection and analysis
To run the backend tests:
cd examples/host/build
./bin/test_backendsAdd focused unit tests as test_*.c files next to source files and wire them in examples/host/CMakeLists.txt. Tests should cover:
- New crypto paths
- Error handling
- Backend selection logic
- Performance benchmarks