Skip to content

Repository files navigation

mldsa-native-esp32

ESP-IDF component that adapts the PQCA mldsa-native codebase for ML-DSA signatures on ESP32-class targets.

The upstream project describes mldsa-native as a portable C90 implementation of the FIPS 204 ML-DSA post-quantum signature standard, supported by the Post-Quantum Cryptography Alliance. This component keeps upstream sources under mldsa/ and isolates ESP32-specific integration in configuration, wrapper, and CMake files.

Status

  • Target parameter set: ML-DSA-87.
  • Primary tested target in this repository: ESP32-WROOM-32D class hardware.
  • Build system: ESP-IDF component.
  • Backend: portable C path only.
  • Assembly and SIMD backends are not used for Xtensa LX6.

The component is suitable for lab integration and benchmarking in this project. Deployment use still requires system-level review of randomness, key storage, side-channel exposure, firmware update policy, and lifecycle handling.

Local Layout

firmware/components/ml_dsa/
├── include/ml_dsa.h
├── config/mldsa_config_esp32.h
├── mldsa/
├── examples/basic_sign_verify/
└── test_apps/ml_dsa_tests/

Design Choices

  • ML-DSA-87 is selected for a high security margin in long-lived IoT identity experiments. Lower parameter sets would reduce memory and latency.
  • Large temporary buffers are redirected from stack to heap because ESP32 FreeRTOS task stacks are small.
  • Randomness is provided through ESP-IDF esp_fill_random().
  • The component keeps direct header configuration instead of a Kconfig menu.
  • The reduced-RAM upstream mode is not enabled in this component because this project has prioritized the standard path and simpler review.

Randomness Requirement

Key generation and signing require cryptographically strong randomness. On classic ESP32, esp_fill_random() depends on the RF subsystem for hardware randomness. Applications must ensure WiFi or Bluetooth is initialized before generating keys or signatures.

Do not generate long-term keys while RF is disabled.

API Overview

Public constants and functions are exposed through include/ml_dsa.h.

Typical flow:

#include "ml_dsa.h"

uint8_t pk[ML_DSA_PK_BYTES];
uint8_t sk[ML_DSA_SK_BYTES];
uint8_t sig[ML_DSA_SIG_BYTES];
size_t siglen = 0;

ml_dsa_keygen(pk, sk);
ml_dsa_sign(sig, &siglen, message, message_len, context, context_len, sk);
ml_dsa_verify(sig, siglen, message, message_len, context, context_len, pk);

Callers are responsible for allocating buffers of the documented sizes and for protecting secret keys at rest.

Testing

Example project:

cd examples/basic_sign_verify
idf.py build
idf.py flash monitor

Component tests:

cd test_apps/ml_dsa_tests
idf.py build
idf.py flash monitor

Security Notes

  • Store ML-DSA secret keys encrypted at rest.
  • Signing latency varies because ML-DSA uses rejection sampling.
  • This component does not add countermeasures against power analysis, electromagnetic analysis, or fault injection.
  • Upstream formal verification claims apply to upstream code and assumptions. The full consuming firmware still needs its own integration review.

Upstream and License

Upstream project: https://github.com/pq-code-package/mldsa-native

This component keeps upstream licensing for vendored code and uses the license files included in this repository.

About

ML-DSA-87 (FIPS 204) post-quantum digital signatures for ESP32 — mldsa-native port

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages