Been working on post-quantum crypto for MAVLink C2 for the past few months.
Wanted to share something I ran into that I haven’t seen discussed anywhere.
The obvious approach to adding PQC to MAVLink is to sign the frame and append
the signature. Tried that. It doesn’t survive a relay.
MAVProxy parses the MAVLink frame, reconstructs it from internal state, and
forwards exactly that — anything appended after the frame boundary is silently
dropped. No error, no warning. The drone receives a valid, unauthenticated frame
with no indication that authentication material ever existed.
Tested it with an actual MAVProxy relay between two UDP sockets. A 4627-byte
ML-DSA-87 signature appended to a COMMAND_LONG arrived at MAVProxy as 4668 bytes,
left as 41.
This matters because almost every real deployment has at least one relay hop.
Point-to-point only isn’t a realistic deployment model.
Numbers on ARM64 (Neoverse-N2, not a flight computer — Cortex-A76 still pending):
Full ML-KEM-1024 session setup: 241µs
ML-DSA-87 sign per command: 509µs
HMAC-SHA3-256 per telemetry packet: 1.1µs
The signing latency is the thing I’m still thinking about. Fine for arm/disarm and
waypoints. Less clear for anything that needs low-latency command response.
Curious if anyone here has looked at this problem, or if PQC is even on the radar
for ArduPilot yet.
Yeah, that would be completely unusable. The design doesn’t do that.
The 4627-byte signature is only for critical commands — arm/disarm, waypoints,
mode changes. Things where non-repudiation actually matters and the latency
budget exists. High-rate telemetry stays on HMAC-SHA3-256: 40 bytes overhead,
1.1µs per packet.
Session key gets established once with ML-KEM-1024 at the start of the flight,
then HMAC runs on every telemetry packet, and ML-DSA-87 only fires on the handful
of commands per flight where you want a cryptographic proof of who sent what.
The part I’m still not sure about is emergency stop — 509µs might be too slow
there. Probably that falls back to the HMAC channel.
I’m probably being a bit too dismissive. At the same time, you seem to be attacking the problem from a per-message standpoint, which seems very cumbersome. Perhaps the entire telemetry session/connection could be protected in a more streamlined way.
To be precise: HMAC-SHA3-256 with the session key authenticates every packet — no command goes unauthenticated regardless of whether ML-DSA is
used. Forging any packet requires breaking the ML-KEM-1024 session.
ML-DSA per-command signing is a separate layer for non-repudiation: proving who issued a command, not whether it’s authentic. Relevant for
audit trails, multi-operator setups, or regulatory accountability — not for routine flight. Most deployments won’t need it.
One thing to note, we do not need secure key exchanges and alike as we can use secure link (USB) to exchange keys beforehand. Transmitted signature should be as short as practical, preferably not much longer than current one. As long as you can’t use QC to guess the key and therefore forge packets we are fine.
Good point, @LupusTheCanine — pre-shared keys provisioned over a trusted physical channel (USB, SD card) are fully supported today. AuthChannel::from_raw_key() accepts any 32-byte key regardless of how it was established, so a PSK
workflow requires no changes to the protocol.
ML-KEM-1024 is an option for scenarios where physical provisioning is impractical: large swarms, remote re-keying after key expiry, or deployments where you cannot physically access the drone before flight. It is not a requirement.
On signature length: ML-DSA-87 at 4627 bytes is the NIST FIPS 204 Level 5 standard — there is no shorter quantum-resistant signature at that security level. For deployments that only need per-packet integrity without non-repudiation,
HMAC-SHA3-256 over the session key gives exactly what you describe: quantum-resistant forgery protection with 40-byte overhead per packet. ML-DSA is reserved for commands where a cryptographic audit trail matters — proof that a specific
operator issued a specific arm or waypoint command, verifiable after the fact.