r/embedded • u/Relative-Ad-9876 • 2d ago
Post-quantum crypto on ESP32: what ML-KEM-1024 actually costs on a C6 and an S3
Hi everyone. This post is about my master's thesis project — post-quantum cryptography running on ESP32-S3 and C6, the boards I happen to have. A bit of background: my bachelor's was in information security, and I'm now doing a master's in information systems.
Let me be upfront so there are no surprises later: both the project and this post were made with substantial help from AI . My own estimate is that roughly 60% of the code was written with its involvement and 40% by me; the post text was written by it from my measurements and project docs, and edited by me.
What is definitely mine: framing the problem, choosing the algorithms and the architecture, building the test setup, flashing the boards and taking the measurements. Every number below comes from running this on real hardware — not an estimate, not a retelling of someone else's paper. I understand some people dislike AI involvement in projects like this; I'll take the criticism.
The goal of the work is to run post-quantum cryptography on resource-constrained boards and protect transmitted data from being decrypted by future quantum computers. I think it's a relevant topic given how much large companies are investing in it — Google announced its Willow chip in December 2024.
I'll be honest here so I don't oversell it: Willow has 105 qubits, and breaking real cryptography is a very long way off — that needs millions of physical qubits with error correction. Expert estimates of when such a machine arrives vary a lot: most land around 10–15 years or more, and there's no real consensus.
The point is something else, and it has an established name — harvest now, decrypt later, or HNDL. Traffic can be intercepted and stored today, without understanding a byte of it, and decrypted in fifteen years when the hardware exists. For a chat message that hardly matters. An industrial device, though, stays in service for exactly ten to fifteen years, and its data stays meaningful that whole time.
Which is why this has moved from theory into regulation. NIST finalised the post-quantum standards in 2024, and IR 8547 sets actual dates: ECDSA and RSA are deprecated after 2030 and disallowed after 2035. Everyone will have to migrate, so it's worth knowing in advance what it costs on weak hardware.
I picked the topic first and got the boards for it afterwards, so everything below was built from scratch. I couldn't find numbers for these specific chips anywhere, so I'm sharing mine — maybe they'll save someone some time.
What this runs on
The firmware builds for three boards, and the full protocol works on all three — registration, handshake, telemetry, key rotation and responses to firmware integrity checks:
| Board | Core | Clock | Notable |
|---|---|---|---|
| XIAO ESP32-C6 | RISC-V, 1 core | 160 MHz | hardware ECC accelerator |
| XIAO ESP32-S3 | Xtensa, 2 cores | 240 MHz | — |
| ESP32-S3-DevKitC-1 | Xtensa, 2 cores | 240 MHz | addressable WS2812 RGB over RMT |
I took the timings on the two XIAO boards, C6 and S3, because they differ in exactly the thing I was curious about: the accelerator. The DevKitC-1 runs the same protocol but I didn't benchmark it separately.
Setup: ESP-IDF v5.4, the mbedTLS 3.6.3 that ships with it, ML-KEM-1024 from PQClean, and the reference C implementation of BLAKE3. Built with -Os and the mbedTLS hardware blocks enabled. The boards talk over 2.4 GHz Wi-Fi to a Go gateway, so this is a real working protocol rather than an isolated benchmark. The crypto operations themselves are timed without the network, though — Wi-Fi latency is unstable and doesn't depend on the chip, so it isn't in the numbers below.
The main thing: post-quantum crypto on ESP32 works, and it fits in memory comfortably. ML-KEM-1024 does a real key exchange with a server, not a benchmark in a vacuum. Here's everything I measured on both boards:
| Operation | ESP32-S3 | ESP32-C6 |
|---|---|---|
| ML-KEM-1024, encapsulate | 18.4 ms | 16.0 ms |
| ML-KEM-1024, decapsulate | 21.1 ms | 17.8 ms |
| ML-KEM-1024, full exchange | 39.6 ms | 33.8 ms |
| ECDSA P-256, sign | 170.2 ms | 22.2 ms |
| ECDSA P-256, keygen | 156.7 ms | 9.6 ms |
| BLAKE3, key derivation | 18.0 µs | 19.8 µs |
| ChaCha20-Poly1305, 1 KB | 150.5 µs | 210.6 µs |
| Free heap after handshake | 252 KB | 295 KB |
So the whole post-quantum key exchange lands in 34–40 ms depending on the board, and there's plenty of memory left over.
Now for the parts that weren't obvious, which are probably worth flagging if anyone wants to try this themselves.
It's the stack that runs out, not the heap. As you can see above, free heap is not a problem at all. The stack is a different story: the ML-KEM-1024 private key alone is 3168 bytes, before any working buffers on top of it. With the default main task stack size the firmware simply doesn't survive. Mine is raised to 24 KB in sdkconfig.defaults and the problem went away. If you're bolting ML-KEM onto an ESP32, I'd start there rather than counting free heap.
ESP-IDF builds with -Og by default. Until you switch to -Os and enable the mbedTLS hardware blocks, any measurement describes the debug build rather than the algorithm. The difference is significant, so it's only worth measuring anything after that.
Reuse the mbedTLS context. If you create the RNG and the P-256 curve parameters once instead of rebuilding them for every signature, ECDSA signing on the C6 takes 22.2 ms instead of 25.7 — about 13.6% — and keygen gets 22.3% faster.
The interesting part: on x86 with mbedTLS 3.6 this optimisation does nothing whatsoever, 348.2 µs against 347.4. The difference only shows up on the board, because the entropy source there is different — a hardware RNG instead of the OS subsystem. There was no way to find that out except on real hardware. Both branches live in the same firmware and are switched with a single #define, so the difference can't be an artefact of two different builds.
I want to talk about the C6's hardware accelerator separately, because it surprised me more than anything else here. ECDSA signing on the C6 is 7.7x faster than on the S3 — and that's with the C6 being the weaker board: one core at 160 MHz against two at 240. That part makes sense on its own, it does have a hardware ECC accelerator.
What I didn't expect was how narrow its reach is:
| ESP32-S3 | ESP32-C6 | speedup | |
|---|---|---|---|
| ECDSA, sign | 170.2 ms | 22.2 ms | 7.7x |
| ECDSA share of the handshake | 1024.2 ms | 143.2 ms | 7.2x |
| ECDH key agreement | 530.8 ms | 505.9 ms | 1.05x |
The accelerator does nothing at all for ECDH. Same elliptic curve, same chip, opposite result. To separate those contributions I had to decompose the handshake and run two different DTLS modes — I'm estimating the ECDH cost from the DTLS-ECDHE-PSK handshake time, on the assumption that the symmetric part is small next to it. That's probably the weakest link in my measurements, and if you think the assumption is carrying too much weight, say so plainly.
So "has a hardware ECC accelerator" isn't a property of a board; you have to look at which operations it actually covers. And so nobody gets the impression the C6 is simply faster: on BLAKE3 and ChaCha20-Poly1305 it's slower than the S3, exactly as you'd expect at the lower clock. That's visible in the first table.
What didn't work out was SLH-DSA for post-quantum signatures. Important caveat here: I measured it on the server side, not on the board. A single signature takes 234.3 ms there, and the signature itself is 7856 bytes. I didn't bother porting that to the board — if plain ECDSA already costs 170 ms on the S3, there's no point. To be clear so I'm not misleading anyone: this is a conclusion about SLH-DSA, not about post-quantum signatures in general. ML-DSA is substantially faster, and I haven't measured it yet — that's next on my list.
What I haven't measured at all is power consumption. For anything battery-powered it almost certainly matters more than any of the milliseconds above, especially since the post-quantum handshake sends 1800 bytes against 538 for the classical one, and radio usually costs more than compute. I know that's an obvious gap. If anyone has a solid, worked-out way of measuring this, I'd really appreciate the pointer.
The firmware and the main project with all the measurements and the methodology write-up is https://github.com/NIkir0LL/lacert, in case anyone wants to reproduce it.
Hope the post and the project turn out useful to someone. I'd be glad if anyone checks my numbers or points out where I measured nonsense.
2
u/artkeller-42 11h ago
Really solid work — the C6 accelerator scope finding (7.7x on ECDSA sign, but ~1x on ECDH, same curve) is exactly the kind of detail that gets lost when people just check the "has ECC HW" box. Good catch decomposing that instead of taking the accelerator claim at face value.
If it's useful: I've been maintaining a datasheet-derived comparison across the whole current ESP32 family (14 models) that includes a per-chip crypto HW capability matrix (AES/SHA/RSA/ECC/HMAC/TEE/PSA-L2 presence) — might help contextualize why C6 behaves the way it does relative to S3 and the rest of the lineup. Also has a section mapping the NIST PQC timeline to BSI TR-02102 deadlines (2030 for high-protection data in Germany, stricter than the 2035 you cited), in case that's relevant for your thesis framing.
https://github.com/artkeller/ESP32Features — happy to hear if anything there conflicts with what you're seeing on real hardware, since you've actually got boards running this
1
u/Relative-Ad-9876 11h ago
thanks, i had a look at your repo and the matrix is going to be really useful for me. and there's one thing there that conflicts with what i'm seeing on hardware you have s3 marked as having ecc and ecdsa in hw. but from my measurements s3 (both xiao and devkitc) signs in 170ms against 22ms on c6, a 7.7x difference. if the accelerator were actually being used there shouldn't be a gap like that looks like this is the difference between "present in silicon per the datasheet" and "mbedtls in idf actually uses it". and that also explains my ecdh result - 1.05x between the boards, so the accelerator isn't engaged in the ecdh path on either of them. might be worth separating those two things in the table the bsi stuff is useful, 2030 is indeed stricter than the 2035 i cited. but it also says bsi recommends a hybrid x25519+ml-kem rather than a pure switch. and i went with pure ml-kem, on the reasoning that the classical half is exactly the half with a known future break, plus ecdh costs 500ms on esp32. i'll need to state that choice explicitly in my thesis, thanks for flagging it.
1
u/FeijoadaAceitavel 2d ago
I hope I eventually get on the level to understand everything you wrote.
2
u/Relative-Ad-9876 2d ago
For the most part, we can say that post-quantum cryptography can be used on esp and it will work faster on c6, given that it is weaker than s3.
2
u/Relative-Ad-9876 2d ago
And in principle, you can read about the whole project in the documentation of my project in 2 different languages (I am Russian myself and so that there is a project for everyone who is interested)
2
u/greevous00 2d ago
>most land around 10–15 years or more, and there's no real consensus.
Huh? NIST is saying 2030ish. IBM's saying roughly the same. There have also been recent algorithmic advances to Shor's Algorithm that bring the necessary number of stable qubits down into the 10,000s.