This flow allows creation of authenticated boot images without exposing private keys outside a Hardware Security Module (HSM). The process is split into three stages:
- Stage 0: Produce hash artifacts (no private keys required)
- Stage 1: Offline/HSM signing of produced hashes
- Stage 2: Assemble final boot image using returned signatures
The build host only needs public keys. Private keys (PSK/SSK) remain in the HSM.
Stage 0 Output Format Differs by Device Model
Both files Bootgen writes during Stage 0 -- the SPK file (spk.) and each partition's hashblock file (.N.) -- use the same rule. The format differs depending on the Spartan UltraScale+ device model, and that in turn changes what the HSM has to do during Stage 1:
| Device Models | Contents of spk.<ext> (SPK file) | Contents of <partition>.N.<ext> (hashblock file) | What the HSM must do in Stage 1 |
|---|---|---|---|
| SU10P, SU25P, SU35P | Pre-computed SHA3 hash of the SPK data, with PKCS-style padding (small, fixed-size). | Pre-computed SHA3 hash of the partition's hashblock, with PKCS-style padding (small, fixed-size). | Sign each supplied hash directly. The HSM treats each file as an opaque digest. |
| SU45P, SU60P, SU65P, SU100P, SU150P, SU200P | The full SPK header followed by the raw SPK public key data (larger, variable-size -- NOT pre-hashed). | The raw hashblock for that partition (larger, variable- size -- NOT pre-hashed). | Treat each file as the message to be signed under the LMS scheme. The HSM is responsible for hashing as part of the LMS signature computation. |
On SU10P, SU25P, and SU35P, the signing flow is "hash, then sign", and Bootgen performs the hashing on the build host before writing each Stage 0 file. On SU45P and above, the signing flow uses the LMS signature scheme, which by construction signs the input message itself -- so the HSM must see the raw data and perform the hashing internally. Using the wrong approach for your device model produces a signature that the boot ROM rejects, and boot authentication fails.
Match your HSM signing flow to the target device:
- SU10P / SU25P / SU35P
- Configure the HSM to accept a hash and sign it as-is (no additional digest). Apply this to both the SPK file and every partition hashblock file.
- SU45P / SU60P / SU65P / SU100P / SU150P / SU200P
- Configure the HSM to accept the raw data block and apply the LMS sign-with-internal-hash operation. Apply this to both the SPK file and every partition hashblock file.
Stage 1 – HSM / Offline Signing
Performed entirely inside the secure environment.
Sign:
- SPK hash file → produces spk.<ext>.sig
- Hashblock hash or Hashblock → produces <partition>.N.<ext>.sig (N = partition index)
Example (single authenticated partition, SHAKE256):
Input to HSM:
spk.shake256.sig (hash blob)
plm.0.shake256 (Hashblock hash or Hashblock)
HSM outputs:
spk.shake256.sig (now a signature)
plm.0.shake256.sig (Hashblock hash or Hashblock signature)
Ensure:
- PSK signs SPK hash
- SSK signs hashblock hash/ hashblock hash
- File naming preserved exactly
- Binary (raw) signature format returned
Stage 2 – Final Image Assembly
Recombines original inputs + returned signatures.
Command:
./bootgen -arch spartanup -image test_stage2.bif -w -o boot_new.bin -log trace
Example (corrected for SHAKE256):
new_bif:
{
id_code = 0x04E88093
extended_id_code = 0x01
id = 0x2
boot_config { smap_width = 32 }
ppkfile = ../files/hss_keys/primary.lms.pub
spkfile = ../files/hss_keys/secondary.lms.pub
image {
name = pmc_subsys
id = 0x1c000001
partition {
id = 0x01
type = bootloader
authentication = lms-shake256
presign = plm.0.shake256.sig
spksignature = spk.shake256.sig
file = ../files/plm.elf
}
partition {
id = 0x09
type = pmcdata, load = 0xf2000000
file = ../files/pmc_data.cdo
}
}
}
(If you instead choose lms-sha256, change authentication plus all .shake256 to .sha256 and presign = plm.0.sha256.sig, spksignature = spk.sha256.sig.)
Output: boot_new.bin (fully authenticated boot image)
Bootgen validates:
- Signature lengths/format
- Algorithm consistency
- Presence of required presign + spksignature
Common Issues
- presign file not found:
- Cause: Wrong extension or missing index (.0.)
- spksignature mismatch:
- Cause: SPK public key in Stage 2 differs from Stage 0
- Mixed algorithm/extension:
- lms-shake256 must use .shake256, lms-sha256 must use .sha256
Best Practices
- Keep Stage 0 in build pipeline; isolate Stage 1 (HSM) with audit logging
- Verify returned signatures (size sanity) before Stage 2
- Enforce consistent key sets between Stage 0 and Stage 2
- Automate detection of extension/key mismatches (pre-flight script)
Notes on LMS/HSS
- Single-level LMS (LMS Only) vs hierarchical HSS (multi-level) affects private key handling, not external file naming.
- Hash/signature generation interfaces remain identical for the flow.