SLH-DSA vs ML-DSA vs FN-DSA: Post-Quantum Firmware Signing and Secure Boot for IoT (2026)

SLH-DSA vs ML-DSA vs FN-DSA: Post-Quantum Firmware Signing and Secure Boot for IoT (2026)

Post-Quantum Firmware Signing for IoT: SLH-DSA vs ML-DSA vs FN-DSA vs LMS

A device you ship in 2026 may still be in a pump station, a substation or a car in 2041, and its boot ROM will trust exactly the public key you burned into it. If that key is RSA or ECDSA, a cryptographically relevant quantum computer could one day let an attacker forge a “valid” firmware image for every unit in the field, and you cannot patch a ROM. That is why post-quantum firmware signing is the one part of the PQC migration where the deadline is set by silicon lead times and device lifetimes, not by when the quantum computer arrives.

The good news is that signature verification, unlike key exchange, is cheap to host on a small device and the signing side lives in your build infrastructure. The bad news is that every candidate scheme trades something painful: signature size, flash, verify time, state management, or standardization maturity.

What this covers: the four realistic schemes (ML-DSA, SLH-DSA, FN-DSA and the stateful LMS/XMSS family), their published sizes, what verification costs on a Cortex-M class part, how boot ROM and image formats (MCUboot, SUIT) have to change, hybrid signing, rollback protection, HSM key management, and the CNSA 2.0 timeline. It ends with a decision matrix and a checklist.

Context and Background

Secure boot rests on one asymmetric operation. At build time a signing service produces a signature over an image hash. At boot, an immutable first-stage verifier (ROM or locked flash) checks that signature against a public key, or a hash of one, held in one-time-programmable (OTP) fuses. Everything after that is a chain of trust: the verified stage verifies the next. The same primitive protects over-the-air (OTA) updates, which is why firmware signing is a long-lived use of public-key cryptography. For background on the chain itself, see our deep dive on TPM 2.0, secure boot, measured boot and remote attestation for IoT fleets.

Signatures are the more urgent PQC target than encryption for a specific reason. Harvest-now-decrypt-later attacks threaten the confidentiality of recorded traffic, but a forged firmware signature only matters if the forger has a quantum computer at the moment of attack. That sounds like relief, but device lifetimes invert it: an ECDSA public key fused into a chip today must still be unbroken when the last unit retires. Policy bodies therefore treat code signing as an early migration item. The US National Security Agency’s CNSA 2.0 guidance lists software and firmware signing as the first category to move, with the instruction to support and prefer the new algorithms by 2025 where available and to use them exclusively by 2030 (see the NSA CNSA 2.0 FAQ and the summary in the Entrust write-up of the 2024 update). NIST’s deprecation plan for classical public-key algorithms is covered in our post on post-quantum cryptography for OT and IIoT, CNSA 2.0 and NIST IR 8547.

NIST has now standardized or is standardizing four signature families relevant here:

  • ML-DSA (FIPS 204, from CRYSTALS-Dilithium), a lattice scheme, final since August 2024.
  • SLH-DSA (FIPS 205, from SPHINCS+), a stateless hash-based scheme, final since August 2024.
  • FN-DSA (FIPS 206, from Falcon), a lattice scheme over NTRU lattices. As of this writing it is not a final standard; NIST’s own roadmap material and secondary sources describe FIPS 206 as still in draft with finalization expected around late 2026 to early 2027. Treat any claim that it is final as wrong until you see it on csrc.nist.gov.
  • LMS and XMSS (NIST SP 800-208, RFC 8554 and RFC 8391), stateful hash-based schemes, approved since 2020 and the only PQ signatures NSA already allows for firmware today.

Our companion post on ML-KEM and ML-DSA memory and performance on constrained microcontrollers covers the raw arithmetic cost. This post focuses on the system decisions: which scheme goes into which boot stage, how images and manifests carry the bigger signatures, and how you survive the transition without bricking a fleet.

One framing point governs the rest. For firmware, the verifier is the constrained party and the signer is not. Anything that makes signing slow, large-state or awkward (SLH-DSA’s cost, LMS’s state) is paid once per release in a datacentre HSM. Anything that makes verification slow or large is paid on every boot of every device. Good PQ firmware design pushes cost to the signer wherever possible, and that bias explains most of the choices below.

The Four Candidate Schemes and What They Cost

Direct answer: For most IoT fleets, ML-DSA-44 or ML-DSA-65 is the pragmatic default for updatable stages, LMS (single tree, SHA-256/192 or SHA-256) is the conservative choice for the immutable root where CNSA 2.0 compliance matters today, SLH-DSA is a robust but heavy fallback, and FN-DSA is attractive for size but not yet final and harder to implement safely on small MCUs.

Post-quantum firmware signing pipeline from HSM to device bootloader verification

Figure 1: End-to-end post-quantum firmware signing pipeline. The HSM signs the image digest, the signature rides in an MCUboot TLV or SUIT envelope, and the on-device bootloader verifies and then enforces rollback policy.

Figure 1 is the pipeline every scheme plugs into. The scheme choice changes the box labelled “HSM signing” and the size of the signature in the manifest. It does not change the shape of the system, except for stateful schemes, which add a state commit step we will draw later.

Published sizes

The sizes below come straight from the standards. Public key and signature bytes are what you must store, transmit and parse.

Scheme Security category Public key (bytes) Signature (bytes) Source
ML-DSA-44 2 1,312 2,420 FIPS 204
ML-DSA-65 3 1,952 3,309 FIPS 204
ML-DSA-87 5 2,592 4,627 FIPS 204
SLH-DSA-SHA2-128s 1 32 7,856 FIPS 205
SLH-DSA-SHA2-128f 1 32 17,088 FIPS 205
SLH-DSA-SHA2-192s 3 48 16,224 FIPS 205
SLH-DSA-SHA2-256s 5 64 29,792 FIPS 205
SLH-DSA-SHA2-256f 5 64 49,856 FIPS 205
FN-DSA-512 (Falcon-512) 1 897 about 666 Falcon spec, FIPS 206 draft
FN-DSA-1024 (Falcon-1024) 5 1,793 about 1,280 Falcon spec, FIPS 206 draft
ECDSA P-256 (reference) classical 64 64 FIPS 186-5
Ed25519 (reference) classical 32 64 RFC 8032

The ML-DSA and SLH-DSA rows are the parameter tables in FIPS 204 and FIPS 205. The Falcon rows come from the Falcon submission; because FIPS 206 is a draft, confirm the final encoding sizes (Falcon signatures are variable-length in the original spec, and a padded fixed-length format was introduced for use cases that need it) before you size a flash partition. LMS and XMSS sizes depend on parameters, so they are discussed separately.

The first thing the table shows is the cost ladder against ECDSA. Moving from a 64-byte signature to ML-DSA-44’s 2,420 bytes is roughly a 38-fold increase; to a 49,856-byte SLH-DSA-256f signature it is nearly 800-fold. Public keys behave differently: SLH-DSA keys are smaller than ML-DSA’s by a factor of 40 or more, which matters when a key (or its hash) must fit in scarce OTP fuses.

ML-DSA: the balanced default

ML-DSA is a Fiat-Shamir-with-aborts lattice signature. Its verification is deterministic and fast because it is dominated by number-theoretic transforms (NTTs) over a 23-bit prime modulus (q = 8,380,417), matrix-vector expansion from a seed using SHAKE, and a hash of the message. There is no rejection sampling on the verifier side; that cost sits in signing. For a firmware use case that asymmetry is ideal: the signer is a server, the verifier does one bounded pass.

The practical costs on a small device are RAM and flash for the expanded public matrix and polynomial vectors. Implementations such as the pqm4 project benchmark Dilithium/ML-DSA on Cortex-M4 and report verification costs and stack usage (on the order of tens of kilobytes, depending on how aggressively the matrix is regenerated on the fly). I am deliberately not quoting a single cycle count here because results vary by compiler, SHAKE implementation and parameter set; read the current pqm4 tables and, better, measure on your part. Our constrained-MCU PQC benchmark post discusses typical orders of magnitude.

Two ML-DSA properties matter for secure boot specifically. First, FIPS 204 defines both a “pure” and a pre-hash (HashML-DSA) mode. Firmware signers usually want the pre-hash or external-mu style so the HSM never needs the whole image; but the verifier and signer must agree on the exact mode and context string or every signature fails. Second, FIPS 204 requires verification to be strict about encoding, so a bootloader must reject malformed signatures rather than fuzzily accept them.

SLH-DSA: conservative assumptions, heavy output

SLH-DSA is built from hash functions only (a hypertree of few-time and one-time signatures), so its security rests on the weakest, best-understood assumption in the field. That is its whole selling point: if lattice cryptanalysis ever surprises us, SLH-DSA is unaffected. It is also stateless, so there is no index to lose.

The price is size and signing time. The “s” (small) variants minimize signature size at the cost of very slow signing; the “f” (fast) variants sign faster but emit signatures roughly twice as large. Verification is much cheaper than signing, since it recomputes only a path of hashes, but it is still thousands of hash calls, so a Cortex-M without SHA-256 acceleration feels it. An 8 KB signature (128s) can be tolerable inside an OTA package; a 30 to 50 KB signature (256s/256f) starts competing with the firmware itself on small parts, and it will not fit in a typical MCUboot TLV area without redesign.

SLH-DSA also has a usage-limit property that surprises people: the standard parameter sets are specified for up to 2^64 signatures per key. That is effectively unlimited for firmware release volumes, which is a real advantage over LMS.

FN-DSA (Falcon): smallest lattice output, trickiest implementation

Falcon’s draw is size. FN-DSA-512 has a 897-byte public key and a signature near 666 bytes, which makes it the only PQ option whose signature fits comfortably in the sort of manifest space a classical ECDSA design budgeted. Verification is also fast: it needs only an NTT-based polynomial multiplication and a norm check, and it avoids ML-DSA’s matrix expansion.

The problems are on the signing side and in maturity. Falcon signing uses discrete Gaussian sampling and floating-point arithmetic (FFT over complex numbers) in the reference implementation, which is hard to make constant-time and is the reason NIST has taken longer to finalize it. For firmware that is acceptable, because signing runs in a controlled build service, but an HSM vendor must have implemented it correctly, and as of today few have FIPS-validated modules for a standard that is still a draft. Verification on the device does not need floating point, which is the good news for the IoT side.

My view: FN-DSA is worth designing for (leave room in your manifest for a small signature type and algorithm identifier), but I would not tape out a ROM that mandates it before FIPS 206 is final and CMVP-validated HSMs exist.

LMS and XMSS: stateful and approved today

LMS (RFC 8554) and XMSS (RFC 8391) are Merkle-tree hash-based schemes standardized for use in NIST SP 800-208. Each private key holds a fixed number of one-time signing keys. Signing the n-th message consumes leaf n, and reusing a leaf breaks security completely. The signer therefore must persist and atomically advance a counter, which turns key custody into a state management problem we cover in the key-management section.

What you get in return is the smallest, simplest, best-understood verifier: a chain of hashes and a Merkle path. The LMS public key is tiny (the SHA-256/192 variant gives a 48-byte key: a four-byte LMS type, four-byte OTS type, 16-byte identifier and 24-byte root). Signature size depends on tree height h and Winternitz parameter w. With a single tree of height 10 and w = 8 using SHA-256/192, a signature is on the order of 1.2 KB; heights of 15 to 20 grow it modestly while giving 32,768 to about a million signatures. Treat these figures as approximate and compute exact lengths from RFC 8554 for your parameters.

LMS verification costs on the order of a few hundred to a couple of thousand hash invocations depending on w. That is cheap on any MCU with a SHA-256 accelerator and tolerable without one. This is why LMS is already shipping in boot ROMs, and why CNSA 2.0 names it as the approved algorithm for firmware signing today: NSA’s guidance accepts LMS and XMSS parameters generally and suggests the SHA-256/192 LMS variant, while excluding the multi-tree variants HSS and XMSS^MT in the summary I verified; check the current CNSA 2.0 text for the exact wording, since I could only verify that through a secondary summary.

Boot chain showing where post-quantum signatures are verified from ROM to application

Figure 2: A staged secure boot chain. The ROM verifies stage 1 against a key hash held in OTP fuses; later stages can use larger, updatable algorithms because their verifier code is itself replaceable.

Where Each Scheme Belongs in the Boot Chain

The staged chain in Figure 2 is the most important design lens in this post. The right algorithm depends on which stage you are protecting, because the stages have opposite constraints.

The immutable root: ROM and fuses

The first verifier is burned into mask ROM or locked flash and cannot be changed after tape-out. Whatever algorithm it implements is the algorithm that must secure the product for its whole life. The key (or its hash) lives in OTP fuses, which are scarce: a typical secure MCU might expose a few hundred bits of key-hash storage per slot.

That produces four constraints:

  1. Fuse budget. A SHA-256 or SHA-384 hash of the public key fits regardless of the algorithm, so you never store the ML-DSA key (1,952 bytes) in fuses. You store its hash and ship the full key in the signed header of stage 1. LMS’s 48-byte key can also be stored directly in many designs.
  2. Code size and verifier simplicity. ROM area is expensive and ROM bugs are unfixable. An LMS verifier is a few hundred lines of C over SHA-256. An ML-DSA verifier needs SHAKE-256 (Keccak), NTT, rounding and hint handling, and an FN-DSA verifier needs a different NTT and compressed-signature decoding. Smaller means easier to review and formally verify.
  3. Stack. ROM often runs with a small fixed stack before DRAM is initialized, running out of internal SRAM. LMS needs only a handful of 32-byte buffers. ML-DSA needs polynomial vectors; with an on-the-fly matrix it can fit in tens of kilobytes, which some small parts cannot spare.
  4. Algorithm agility. Because the ROM cannot be patched, it should recognize an algorithm identifier and ideally support two, so a later key or algorithm revocation does not require new silicon.

For the immutable root, my recommendation follows directly: LMS or XMSS as the primary root-of-trust signature where compliance or conservatism demands it today, with ML-DSA support if the ROM budget allows. If you are designing a new SoC and ROM budget is tight, LMS alone is defensible because the state problem is solvable at the signing service.

The updatable middle and the application

Once stage 1 is running and verified, the later stages are ordinary flash code. The bootloader (for example MCUboot) can be updated by a signed update to itself, and its verifier is just code. Here ML-DSA is natural: it has a stateless signer, large parameter headroom, a FIPS standard in force, and wide library support in liboqs, mbedTLS-adjacent ports and vendor SDKs. Larger signature sizes are mostly a flash and bandwidth issue, not a security one.

This split matters operationally. The stage-1 key signs very rarely (perhaps only when you replace the bootloader), so even a small LMS tree of a few thousand leaves lasts the life of the product. The application signing key signs every release and is the one that benefits from stateless ML-DSA. This is the two-tier design: a hash-based root of trust for rarely-signed, high-assurance material, and a lattice signature for frequent releases.

Image format and manifest overhead

A larger signature is not just more bytes; it changes the image format. MCUboot stores its signature and public key hash in a trailing TLV (type-length-value) area appended to the image, and its layout has fixed maximum sizes configured at build time. Its historic design assumes signatures from RSA-2048/3072 or ECDSA/Ed25519, i.e. 64 to 384 bytes. A 2,420 to 4,627-byte ML-DSA signature, or the key itself, needs an enlarged TLV area (the IMAGE_TLV size limits in the config) and a bigger header-and-trailer reserve. Whether your MCUboot fork already carries PQ support depends on the version; check the MCUboot project release notes rather than assuming, because I could not verify a mainline PQ release for this post.

For the IETF side, the SUIT (Software Updates for Internet of Things) family is the standards-based alternative: the architecture is RFC 9019, the information model is RFC 9124, and the CBOR manifest format is in the SUIT manifest specification (draft-ietf-suit-manifest, which was progressing through the RFC process; verify the current RFC number before citing it). SUIT signs manifests using COSE (RFC 9052/9053), so adding a PQ algorithm is a matter of assigning COSE algorithm identifiers. IETF work on registering ML-DSA, SLH-DSA, Falcon and HSS-LMS for COSE is under way in drafts; the HSS-LMS COSE registration is specified in RFC 8778 for the stateful case. Practically, SUIT already has an “algorithm identifier plus opaque signature bytes” model, which is why it absorbs PQ signatures with fewer layout changes than a fixed-width TLV scheme. The cost is that a SUIT manifest is parsed in the bootloader, so you must size its CBOR parser buffers for multi-kilobyte signature fields.

Verify Cost on a Cortex-M: What You Can and Cannot Claim

Every PQC post is tempted to print a table of cycle counts. I will not, for a simple reason: verification time on a Cortex-M depends on the core (M0+ has no hardware multiplier worth the name for 32×32 to 64-bit products, M4 and M7 have DSP instructions, M33 adds some), on whether a SHA-256 or Keccak accelerator exists, on compiler flags, and on whether the implementation trades RAM for speed. Published benchmarks exist (the pqm4 project for M4, and several papers for M0+ and M33), and you should read the current tables for your target. What I can give you is the structure of the cost, which is stable across silicon.

Where the time goes

  • ML-DSA verify: expand the public matrix A from a 32-byte seed with SHAKE-128 (this dominates), run a handful of NTTs and inverse NTTs, compute w' from the signature and public key, hash the result with SHAKE-256, and compare. The Keccak permutation is the hot loop, so a Keccak accelerator or an M4/M7 assembly Keccak matters more than the NTT.
  • SLH-DSA verify: recompute a FORS tree root and then a chain of WOTS+ and Merkle authentication paths across d layers. Cost is the number of hash compressions, and it scales with the parameter set; the “f” and “s” sets differ in the balance of layers versus tree height.
  • FN-DSA verify: decode a compressed signature, NTT, pointwise multiply by the public key, inverse NTT and a norm bound check. It is the cheapest of the lattice schemes and needs no matrix expansion.
  • LMS verify: hash a message with randomizer, run up to 2^w - 1 chain steps per Winternitz digit across the digits, hash the chain tops into a leaf, and walk the Merkle path. Hash count is a few hundred at w = 4 up to roughly a couple of thousand at w = 8, depending on tree height and chain steps.

Back-of-envelope RAM and ROM

I will mark this next table as illustrative: these are order-of-magnitude planning estimates drawn from the algorithm structure, not measurements, and you should replace them with numbers from your own build.

Scheme Peak RAM (illustrative) Code (illustrative) Dominant primitive
LMS SHA-256 under 1 KB a few KB SHA-256
FN-DSA-512 verify a few KB tens of KB NTT
ML-DSA-44 verify roughly 10-40 KB tens of KB SHAKE-128/256
SLH-DSA-128s verify a few KB a few KB hash code SHA-256 or SHAKE

One engineering detail makes a large difference: stream the image hash, not the image. Verification needs a digest of the image, so the bootloader hashes flash in chunks (4 KB at a time is common) and feeds the digest to the verifier. The signature itself is a few kilobytes, so with ML-DSA you must hold the signature (2.4 KB), the public key (1.3 KB) and workspace in RAM simultaneously, or process the signature in a streaming decoder. The code for streaming ML-DSA verification exists in the research literature but not every library supports it.

The comparative takeaway is robust even without a number table. On a part with a SHA-256 accelerator, LMS verifies faster and in less RAM than any lattice option. On a part with a Keccak accelerator, ML-DSA closes most of that gap. Without any accelerator, ML-DSA verification on a Cortex-M4-class device is still feasible within a boot-time budget measured in tens of milliseconds to low hundreds, which is acceptable for devices that boot once a day but not for a sensor that must resume within a millisecond budget after deep sleep. In that case verify at update time and store a MAC-protected “already verified” marker keyed from a device secret, rather than re-verifying a PQ signature on every wake.

The wake-from-sleep trap

Many battery IoT devices wake thousands of times a day and do not run the full boot chain each time. They run a warm-start path. If your security argument needs signature verification at every cold boot only, that is fine, but make sure the warm path cannot be induced to load an unverified image. Pair the PQ signature check with an authenticated local record (a hash of the verified image stored in tamper-protected memory) so subsequent boots compare hashes rather than re-verifying.

Hybrid classical and post-quantum dual signature verification flow for firmware

Figure 3: Hybrid firmware signing. The manifest carries both a classical and a post-quantum signature over the same digest, and the verifier boots only if both pass.

Hybrid Signing: Belt and Braces, With a Price

Hybrid signing attaches two independent signatures, typically ECDSA P-384 and a PQ scheme, so the image is trusted only if both verify. The argument for hybrid is hedging: ML-DSA is new, and lattice cryptanalysis has had surprises in the NIST process (the SIKE break and the Rainbow break were both against other families, not lattices, but they show that late breaks happen). A hybrid signature remains secure unless both schemes fail, so you hold on to ECDSA’s decades of analysis while the PQ side matures.

The argument against is cost and complexity. The device must carry two verifiers, the manifest carries two signatures, and bootloader code paths double. In a ROM-constrained system it can be unaffordable to add a second algorithm. CNSA 2.0 itself leans toward PQ-only for its approved set (it requires the NSA-approved algorithms rather than hybrid constructions), whereas European agencies such as Germany’s BSI and France’s ANSSI have published guidance favoring hybrid during the transition. If you sell to both markets, expect conflicting requirements. Check each agency’s current document, because these positions have moved.

How to structure a hybrid signature safely

Do not invent a combiner. Use one of two patterns.

  1. Parallel independent signatures over the same message. The verifier requires all signatures valid, and the signed content includes the algorithm identifiers of both so an attacker cannot strip one and downgrade. In a SUIT envelope this is naturally expressed with a COSE_Sign structure (multiple signers). In an MCUboot TLV list it means two signature TLVs plus a policy flag.
  2. Composite signature. A single algorithm identifier names the pair, and the standard defines the combined encoding. The IETF LAMPS working group is developing composite ML-DSA specifications for certificates; for firmware you can reuse the idea but the composite drafts target X.509 and TLS, so verify applicability.

In both cases, the downgrade rule is the critical bit: the bootloader’s policy must say “both required,” and that policy must itself be anchored in something the attacker cannot change (a fused policy bit or a signed bootloader). An unsigned “accept classical only” fallback defeats the entire design.

Time-bounded hybrid and the sunset

Hybrid is a transition tool, not a destination. Plan a field upgrade path: ship with both signatures, then, once the bootloader has been updated everywhere to support ML-DSA verification, drop classical verification from the policy in a later signed update. Because the policy bit is only ever tightened, you can add a fuse or a monotonic counter to make “PQ required” irreversible once set.

Rollback Protection and Anti-Downgrade

A valid old signature is still a valid signature. If an attacker can reflash version 1.0, which was properly signed but has a known vulnerability, the signature check passes. Quantum resistance does nothing for this. Rollback protection is orthogonal to the signature algorithm, but PQ migration creates new rollback hazards, so treat them together.

Mechanism. Each image carries a monotonically increasing security version (not the marketing version). The device keeps a counter in tamper-resistant storage, either OTP fuses burned one bit at a time or a secure monotonic counter in a secure element or RPMB (replay protected memory block). The bootloader refuses any image whose security version is below the counter and increments the counter after a successful boot into the new image (MCUboot offers a hardware-backed security counter, and SUIT manifests carry a monotonic sequence number; consult each spec for exact semantics).

New hazards in the PQ transition

  • Algorithm downgrade. An attacker replays an old classical-only image to a device that now supports hybrid. Fix: bump the security counter when you move to PQ so all classical-only images fall below the floor.
  • Key revocation. If a classical key is compromised, you must revoke it, and revocation requires the device to reject images by a key rather than only by version. Include a key epoch in the signed header and a fused key-epoch counter.
  • Stateful scheme coupling. If you use LMS, you can bind the counter to the tree: each leaf index is unique and increasing, so some designs treat the leaf index as an implicit monotonic version. Do not do that. A signer that restores from backup can reuse indices (a security failure), and a hotfix signed with a lower index would break monotonicity. Keep an explicit version.

Fuse-count economics

Fuse-based counters have a hard ceiling. If your design burns one fuse per version, 32 fuses means 32 security-version increments over the device’s life. Reserve security-version bumps for genuine security fixes, not every release, and document the budget. For PQ migration, plan on spending at least two increments (one for introducing PQ, one for retiring classical).

Key Management, HSMs and the Statefulness Problem

On the signer side, the algorithm choice determines what your HSM and release process must guarantee. This is where hash-based signatures bite.

Stateful LMS signing sequence with atomic index reservation in an HSM

Figure 4: Stateful signing for LMS or XMSS. The index is reserved and durably committed before the signature leaves the HSM, so a crash or restore can never reuse a one-time key.

The stateful rule

SP 800-208 is explicit that stateful hash-based signature keys must be generated and used inside a hardware cryptographic module, and that the state must never be exported or restored in a way that could repeat an index. In practice this means: no backup and restore of the private key through ordinary HSM key-wrapping; no cloning of an HSM for disaster recovery; no virtualised signer that can be snapshotted. NIST and NSA both treat these as hard requirements, and the standard permits the one-time-key subdivision technique only in tightly controlled ways.

Figure 4 shows the safe order of operations: reserve the index, commit it to non-volatile storage, only then compute and release the signature. If the HSM crashes after commit but before release, you burn one leaf, which is harmless. If it releases before commit, you can reuse a leaf, which is catastrophic.

To make disaster recovery workable, the common practice is to partition the tree across multiple HSMs: with LMS, each HSM gets its own sub-range of leaf indices (or, better, its own independent LMS keypair and its own public key) so no two modules can ever sign with the same leaf. You then fuse or embed multiple public keys in the device. With HSS (multi-level LMS), a root tree signs child trees, which lets one signing server pre-generate and hand out lower-level trees, but note the CNSA 2.0 caveat above about multi-tree variants.

Capacity planning

Tree height determines the signature budget: h = 10 gives 1,024 signatures, h = 15 gives 32,768, h = 20 gives 1,048,576. A conservative planner counts every signature operation, including test builds and failed pipeline runs, because every call to the HSM consumes a leaf. The classic mistake is wiring CI to sign every commit with the production LMS key. Use one key per environment, and sign only release candidates with the production key.

A sizing example, illustrative rather than measured: a vendor releasing four firmware lines, each with a monthly release and three hotfix signatures per quarter, consumes about 4 x (12 + 12) = 96 signatures per year. A 1,024-leaf tree lasts a decade at that rate, but a 10,000-device fleet signed per device (per-unit personalization signatures) would exhaust it on day one. Per-unit signing needs a different structure, such as signing a Merkle root over per-device attestations, or a stateless scheme.

Stateless schemes simplify operations

The operational case for ML-DSA and SLH-DSA is simply that none of this applies. You can back up the key under ordinary HSM wrapping, run active-active HSMs, and sign from CI at will. That is why my default for the frequently-signing application key is ML-DSA rather than LMS, even though LMS is better understood. HSM support matters: check that your HSM vendor offers FIPS 204 mechanisms (PKCS#11 v3.2 defined ML-DSA and SLH-DSA mechanisms; verify your vendor’s firmware level) and, for LMS, that the HSM implements the NIST-compliant state handling, not just the math.

Key hierarchy

A sensible hierarchy for a PQ-ready product:

  1. Root key, offline: LMS (or XMSS) key in an air-gapped HSM, used only to sign intermediate certificates or the stage-1 bootloader. Its hash is fused.
  2. Release key, online HSM: ML-DSA-65 (or -44 on very tight devices) signing production firmware, with the public key delivered inside a root-signed header so it can rotate.
  3. Development keys: separate, short-lived, different algorithm identifiers, never accepted by production-fused devices.

Rotation is the capability that makes PQ transitions survivable. If the release key is in a root-signed header with an epoch number, you can move from ML-DSA-44 to ML-DSA-65, or to FN-DSA when it is final, with a normal OTA update.

Trade-offs, Gotchas, and What Goes Wrong

Flash and bandwidth overhead. A 4.6 KB ML-DSA-87 signature on a 100 KB image is 4.6 percent overhead, and on a delta update measured in a few hundred bytes it is a 10x increase in payload. For NB-IoT or LoRaWAN-class links with slow or metered uplinks, signature size can dominate. FN-DSA and LMS are far kinder here. Delta updates are the pattern where the choice of scheme most visibly changes cost per device.

Dual-slot flash budgets. MCUboot’s swap and direct-XIP modes reserve space for a trailer. A bigger TLV area means bigger headers in both slots. On a part with 512 KB flash and a 200 KB firmware, the PQ headers are noise; on a 64 KB part they are a design problem.

Side channels and fault injection. The verifier is attacked by glitching more often than by cryptanalysis. A faulted comparison that skips the final signature check bypasses secure boot regardless of the algorithm. Use redundant checks, randomized delays and constant-flow comparisons. Larger PQ verifiers have a larger attack surface to harden than a 64-byte ECDSA check. Signing-side side channels (Falcon’s Gaussian sampler, ML-DSA’s rejection loop) matter at the HSM, not the device.

Implementation maturity. ML-DSA ASM for Cortex-M exists in research code, while production libraries vary. Prefer the formally verified or heavily reviewed implementations (such as those in mlkem-native-style projects, PQ Code Package, and liboqs) and run the NIST ACVP test vectors in CI.

Standards-shifting risk. FIPS 206 is a draft, and CNSA 2.0 and NIST IR 8547 may update. Early adopters of FN-DSA may need to re-spin if the final encoding differs. Mitigate with algorithm identifiers and a signed bootloader that can learn new algorithms.

Anti-patterns

  • Fusing a PQ public key directly because “it fits” without a hash indirection, leaving no room for rotation.
  • One production LMS key shared across CI runners.
  • Verifying the PQ signature but trusting an unsigned manifest field for the version or the target hardware ID.
  • Shipping hybrid with a “classical-only is acceptable” fallback.
  • Choosing SLH-DSA-256f for an MCU because “hash-based is safest,” then discovering the signature does not fit the OTA payload.

CNSA 2.0 and Compliance Timelines

NSA’s CNSA 2.0 sets algorithm requirements for National Security Systems and, by extension, for vendors who sell into them. For software and firmware signing, it names LMS and XMSS (as specified in NIST SP 800-208) as the approved algorithms, with the instruction to start the transition immediately, to “support and prefer” CNSA 2.0 signatures by 2025 where available, and to use them exclusively by 2030. Later NSA material also approves ML-DSA-87 (the Category 5 parameter set) for general signature use, and the FAQ lineage is worth rereading every few months. Because I verified the firmware dates through a secondary summary of the NSA FAQ rather than the primary PDF text in this session, cross-check those dates against the NSA document before quoting them in a contract.

NIST’s parallel timeline, in IR 8547 (initial public draft), proposes deprecating 112-bit-security classical public-key algorithms after 2030 and disallowing all classical public-key signature algorithms after 2035. Together these mean that a product introduced in 2026 with a ten-to-fifteen-year support commitment will outlive both deadlines. That is the practical forcing function: you need PQ verification capability in silicon or in a replaceable bootloader at design time, even if you keep signing classically for another cycle.

The key point for buyers in other sectors (automotive, medical, industrial) is that CNSA is not law for them, but regulators and large customers use it as a benchmark, and the EU Cyber Resilience Act’s secure-update and vulnerability-handling expectations push toward cryptography that remains valid across the support period. See our post on post-quantum cryptography for OT and IIoT for the regulatory view.

A Decision Matrix

Criterion LMS / XMSS ML-DSA SLH-DSA FN-DSA
Standard status SP 800-208, RFC 8554 / 8391, approved FIPS 204 final FIPS 205 final FIPS 206 draft
Signature size about 1-2 KB (param dependent) 2.4-4.6 KB 7.9-49.9 KB about 0.7-1.3 KB
Public key 48-64 bytes 1.3-2.6 KB 32-64 bytes 0.9-1.8 KB
Verify cost on MCU Low Moderate Moderate to high Low to moderate
Signer state Stateful, critical Stateless Stateless Stateless
HSM maturity Good but special-purpose Growing Growing Immature
Security assumption Hash only Lattice Hash only NTRU lattice
Best fit ROM root of trust, offline root Updatable stages, app signing Hedge, long-life root where size is tolerable Bandwidth-bound delta updates once final

Practical Recommendations

Start from the constraints, not from the algorithms. If the device has a ROM you cannot change and a long field life, make the root verifier LMS (or XMSS), keep the signing key offline in a purpose-built HSM with partitioned leaf ranges, and fuse a hash of the public key rather than the key. If your silicon budget allows, add an ML-DSA verifier in the ROM too, so the root can later pivot to a stateless scheme by changing which key hash you trust.

For everything that can be updated, use ML-DSA, usually parameter set 65 for general products and 44 only if flash is very tight and your risk assessment permits Category 2. Put the release public key in a root-signed header with an epoch, so you can rotate. Use hybrid during the transition if your customers or regulators demand it, and write the “both required” policy into a protected bit, not a configuration file.

Treat SLH-DSA as an insurance policy you can deploy where size is cheap: a rarely-updated, extremely long-lived firmware root with generous partition space, or a second independent signature in a defence-in-depth design. Treat FN-DSA as a design target: reserve an algorithm identifier and a small-signature slot in your manifest, and revisit once FIPS 206 is final and your HSM vendor ships a validated implementation.

Checklist

  • [ ] Decide PQ algorithm per boot stage (ROM, bootloader, application) and document why.
  • [ ] Fuse a hash of the public key; ship the key in a signed header; include a key epoch.
  • [ ] Size MCUboot TLV or SUIT buffers for the largest signature you may adopt, not the one you use today.
  • [ ] Add a security-version counter and budget fuse increments; bump it when introducing PQ.
  • [ ] For LMS/XMSS, use hardware state with atomic index commit; forbid key backup/restore and CI use of production keys.
  • [ ] Run NIST ACVP vectors and negative tests (malformed, truncated, wrong-context signatures) in CI.
  • [ ] Measure verify time and peak RAM on the real target, including worst-case flash read latency.
  • [ ] Make downgrade (hybrid to classical-only) impossible once PQ is enforced.
  • [ ] Plan the OTA path for the bootloader itself, so the root can learn new algorithms.
  • [ ] Cross-check CNSA 2.0, IR 8547 and FIPS 206 status against primary sources each quarter.

Frequently Asked Questions

Which post-quantum signature is best for IoT firmware signing?

There is no single winner. LMS or XMSS is the best fit for an immutable boot ROM and is the only family NSA currently approves for firmware, but its statefulness demands careful HSM handling. ML-DSA is the best general choice for updatable bootloader and application signing because it is stateless, standardized in FIPS 204 and fast to verify. SLH-DSA and FN-DSA are niche: one for conservatism, the other for compact signatures once standardized.

Is FN-DSA (Falcon) a final standard yet?

No. FIPS 206 was still a draft when I checked, with finalization described by secondary sources as expected in late 2026 or early 2027. The Falcon algorithm itself is well studied and was selected by NIST in 2022, but encodings and details can change between draft and final. For firmware, design your manifest to carry an algorithm identifier and a small signature, and wait for the final text and validated HSMs before fusing anything.

How big are post-quantum signatures compared with ECDSA?

Much bigger. ECDSA P-256 signatures are 64 bytes. ML-DSA-44 signatures are 2,420 bytes, ML-DSA-65 are 3,309 and ML-DSA-87 are 4,627. SLH-DSA ranges from 7,856 bytes for the 128s set to 49,856 bytes for 256f. FN-DSA-512 is about 666 bytes. LMS depends on parameters but is typically around one to two kilobytes. Public keys range from 32 bytes for SLH-DSA to roughly 2.6 KB for ML-DSA-87.

Why is LMS called stateful, and why does it matter for HSMs?

An LMS private key is a set of one-time keys arranged in a Merkle tree. Each signature consumes one leaf, and signing twice with the same leaf lets an attacker forge signatures. The signer must therefore advance and durably store an index before releasing every signature. That forbids ordinary key backup, cloning and snapshotting, and it is why SP 800-208 requires hardware modules with controlled state.

Do I need hybrid classical plus post-quantum signing?

It depends on who you sell to and how long devices live. Hybrid hedges against an undiscovered weakness in a young PQ scheme and is favoured by several European agencies, whereas CNSA 2.0 points toward PQ-only approved algorithms. If you do go hybrid, require both signatures, include algorithm identifiers in the signed data, anchor the policy in protected storage, and plan to retire the classical half through a signed update.

Does PQ signing change MCUboot or SUIT updates?

Yes, mostly in sizing. MCUboot’s trailing TLV area and image header assume signatures of a few hundred bytes, so ML-DSA needs larger reserves and possibly a patched or newer build with PQ support. SUIT (RFC 9019 architecture, RFC 9124 information model) signs manifests with COSE, so new algorithm identifiers fit naturally, but manifest parsers and buffers must handle multi-kilobyte signature fields. Verify current upstream support before committing.

Further Reading

By Riju — about

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *