It is recommended for you to remember the following about hash generation:
- Revocation Behavior
-
- If
revoke_idis included in the Authentication Certificate (AC), the corresponding secondary key is revoked which means thatrevoke_idmatches with eFUSEs. - If the Partition Header (PH) includes it, the system revokes the corresponding partition if the partition is encrypted.
- If
- Bootgen Behavior
-
- Bootgen places the
revoke_idin both the Partition Header and the AC’s SPK ID field. - When only authentication is enabled,
revoke_idis included in the AC’s SPK ID field. - When you enable authentication and encryption, both the AC and PH include it.
- When you enable only encryption, the PH includes it.
- Bootgen places the
| Bootgen -verify failure | Cause | Fix |
|---|---|---|
| SPK Signature Verification Failed | revoke_id used in Stage 0 differs from the value used in a later metaheader/partition referencing the same SPK. The Stage 1 signature is bound to the (PSK, SPK, revoke_id) tuple. | Use the same revoke_id everywhere that references a given SPK, or generate a separate Stage 0/1 pair per (SPK, revoke_id) combination. |
| Image Header Table Signature Verification Failed | headersignature = imageheadertable.sha384. sig is missing from the Stage 10 (stage8b.bif) and/or Stage 12 (stage10.bif) metaheader block. | Add the attribute to both BIFs (see Stage 10 and Stage 12). |
| Authentication Error !!! Either Secret Key Pair or BH signature file must be specified in BIF file (during Stage 12 image generation) | headersignature is missing from the Stage 12 metaheader block while no secret key (pskfile / sskfile) is supplied. | Add headersignature = imageheadertable. sha384.sig to the Stage 12 BIF. |
Stage 0: Generate SPK Hash
revoke_id is part
of the SPK hash computation. The Stage 1 SPK signature is therefore bound to the exact (PSK,
SPK, revoke_id) tuple used in Stage 0. The same revoke_id
value must be carried through every later stage that consumes that SPK — Stage 2 partition
encrypts, Stage 7a/7b/7c/7d AC inserts, and the Stage 8a/8b/10 metaheader blocks.If a
later partition or metaheader uses a different revoke_id
with the same SPK signature, image generation succeeds and the device can still boot, but
Bootgen -verify reports that the SPK Signature Verification Failed.
Two valid usage patterns:
- Single revoke_id per SPK
- Use one
revoke_idper SPK and reuse it identically in every stage that references that SPK. The following example already shows this pattern: SPK1 → revoke_id = 0x1, SPK2 → 0x2, SPK3 → 0x3. - Multiple revoke_id values per SPK
- Run Stage 0 / Stage 1 separately for each unique (SPK,
revoke_id) pair, producing one signature file per pair, and reference the matching signature in the corresponding Stage 7/8/10 block.
Generate hash for SPK1:
command : bootgen -arch versal -image stage0-SPK1.bif -generate_hashes -w on -log error
stage0_SPK1:
{
revoke_id = 0x1
spkfile = rsa-keys/SPK1.pub
}
Generate hash for SPK2:
command : bootgen -arch versal -image stage0-SPK2.bif -generate_hashes -w on -log error
stage0_SPK2:
{
revoke_id = 0x2
spkfile = rsa-keys/SPK2.pub
}
Generate hash for SPK3:
command : bootgen -arch versal -image stage0-SPK3.bif -generate_hashes -w on -log error
stage0_SPK3:
{
revoke_id = 0x3
spkfile = rsa-keys/SPK3.pub
}
Stage 1: Sign SPK hash
Sign the generated hashes:
openssl rsautl -raw -sign -inkey rsa-keys/PSK1.pem -in SSK1.pub.sha384 > SSK1.pub.sha384.sig
openssl rsautl -raw -sign -inkey rsa-keys/PSK2.pem -in SSK2.pub.sha384 > SSK2.pub.sha384.sig
openssl rsautl -raw -sign -inkey rsa-keys/PSK3.pem -in SSK3.pub.sha384 > SSK3.pub.sha384.sig
Stage 2: Create Partition Binaries
This stage creates a binary file for the partition. Although this example encrypts the partition, binary file creation requires stage 2 even if the partition is not encrypted.
Encrypt partition 1:
command : bootgen -arch versal -image stage2a.bif -o pmc_subsys_e.bin -w on -log error
stage2a:
{
image
{
name = pmc_subsys, id = 0x1c000001
partition
{
id = 0x01, type = bootloader,
revoke_id = 0x1
encryption=aes,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/bbram_red_key.nky,
dpacm_enable,
file = images/gen_files/plm.elf
}
partition
{
id = 0x09, type = pmcdata,
load = 0xf2000000,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/pmcdata.nky
dpacm_enable
file = images/gen_files/pmc_data.cdo
}
}
}
Encrypt partition 2:
command : bootgen -arch versal -image stage2b-1.bif -o lpd_lpd_data_e.bin -w on -log error
stage2b_1:
{
image
{
name = lpd, id = 0x4210002
partition
{
id = 0x0C, type = cdo,
revoke_id = 0x3,
encryption=aes, delay_auth,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/key1.nky,
dpacm_enable,
file = images/gen_files/lpd_data.cdo
}
}
}
Encrypt partition 3:
command : bootgen -arch versal -image stage2b-2.bif -o lpd_psm_fw_e.bin -w on -log error
stage2b_2:
{
image
{
name = lpd, id = 0x4210002
partition
{
id = 0x0B, core = psm,
revoke_id = 0x1,
encryption = aes, delay_auth,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/key2.nky,
dpacm_enable,
file = images/static_files/psm_fw.elf
}
}
}
Encrypt partition 4:
command : bootgen -arch versal -image stage2c.bif -o fpd_e.bin -w on -log error
stage2c:
{
image
{
name = fpd, id = 0x420c003
partition
{
id = 0x08, type = cdo,
revoke_id = 0x3,
encryption=aes, delay_auth,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/key5.nky,
dpacm_enable,
file = images/gen_files/fpd_data.cdo
}
}
}
Encrypt partition 5:
command : bootgen -arch versal -image stage2d.bif -o subsystem_e.bin -w on -log
error
stage2d:
{
image
{
name = ss, id = 0x1c000033
partition
{
id = 0x0D, type = cdo,
revoke_id = 0x2,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/key6.nky,
dpacm_enable,
file = images/gen_files/subsystem.cdo
}
}
}
Stage 3: Generate Boot Header Hash
command : bootgen -arch versal -image stage3.bif -generate_hashes -w on -log error
stage3:
{
boot_config {bh_auth_enable}
image
{
name = pmc_subsys, id = 0x1c000001
{
type = bootimage,
revoke_id = 0x1,
authentication=rsa,
ppkfile = rsa-keys/PSK1.pub,
spkfile = rsa-keys/SSK1.pub,
spksignature = SSK1.pub.sha384.sig,
file = pmc_subsys_e.bin
}
}
}
Stage 4: Sign Boot Header Hash
Sign the generated hashes:
openssl rsautl -raw -sign -inkey rsa-keys/SSK1.pem -in bootheader.sha384 > bootheader.sha384.sig
Stage 5: Generate Partition Hashes
command : bootgen -arch versal -image stage5.bif -generate_hashes -w on -log error
stage5:
{
bhsignature = bootheader.sha384.sig
image
{
name = pmc_subsys, id = 0x1c000001
{
type = bootimage,
revoke_id = 0x1,
authentication=rsa,
ppkfile = rsa-keys/PSK1.pub,
spkfile = rsa-keys/SSK1.pub,
spksignature = SSK1.pub.sha384.sig,
file = pmc_subsys_e.bin
}
}
image
{
name = lpd, id = 0x4210002
partition
{
type = bootimage,
revoke_id = 0x3,
authentication = rsa,
ppkfile = rsa-keys/PSK3.pub,
spkfile = rsa-keys/SSK3.pub,
spksignature = SSK3.pub.sha384.sig,
file = lpd_lpd_data_e.bin
}
partition
{
type = bootimage,
revoke_id = 0x1,
authentication = rsa,
ppkfile = rsa-keys/PSK1.pub,
spkfile = rsa-keys/SSK1.pub,
spksignature = SSK1.pub.sha384.sig,
file = lpd_psm_fw_e.bin
}
}
image
{
id = 0x1c000000, name = fpd
{
type = bootimage,
revoke_id = 0x3,
authentication=rsa,
ppkfile = rsa-keys/PSK3.pub,
spkfile = rsa-keys/SSK3.pub,
spksignature = SSK3.pub.sha384.sig,
file = fpd_e.bin
}
}
image
{
id = 0x1c000033, name = ss
{
type = bootimage,
revoke_id = 0x2,
authentication = rsa,
ppkfile = rsa-keys/PSK2.pub,
spkfile = rsa-keys/SSK2.pub,
spksignature = SSK2.pub.sha384.sig,
file = subsystem_e.bin
}
}
}
Stage 6: Sign Partition Hashes
openssl rsautl -raw -sign -inkey rsa-keys/SSK1.pem -in pmc_subsys_1.0.sha384 > pmc_subsys.0.sha384.sig
openssl rsautl -raw -sign -inkey rsa-keys/SSK3.pem -in lpd_12.0.sha384 > lpd.0.sha384.sig
openssl rsautl -raw -sign -inkey rsa-keys/SSK1.pem -in lpd_11.0.sha384 > psm.0.sha384.sig
openssl rsautl -raw -sign -inkey rsa-keys/SSK1.pem -in lpd_11.1.sha384 >psm.1.sha384.sig
openssl rsautl -raw -sign -inkey rsa-keys/SSK1.pem -in lpd_11.2.sha384 >psm.2.sha384.sig
openssl rsautl -raw -sign -inkey rsa-keys/SSK1.pem -in lpd_11.3.sha384 >psm.3.sha384.sig
openssl rsautl -raw -sign -inkey rsa-keys/SSK1.pem -in lpd_11.4.sha384 >psm.4.sha384.sig
openssl rsautl -raw -sign -inkey rsa-keys/SSK3.pem -in fpd_8.0.sha384 > fpd_data.cdo.0.sha384.sig
openssl rsautl -raw -sign -inkey rsa-keys/SSK2.pem -in ss_13.0.sha384 > ss.0.sha384.sig
Stage 7: Insert Partition Signatures into Authentication Certificates
Insert partition 1 signature:
command : bootgen -arch versal -image stage7a.bif -o pmc_subsys_e_ac.bin -w on -log error
stage7a:
{
bhsignature = bootheader.sha384.sig
boot_config {bh_auth_enable}
image
{
name = pmc_subsys, id = 0x1c000001
{
type = bootimage,
authentication=rsa,
revoke_id = 0x1
ppkfile = rsa-keys/PSK1.pub,
spkfile = rsa-keys/SSK1.pub,
spksignature = SSK1.pub.sha384.sig,
presign = pmc_subsys.0.sha384.sig,
file = pmc_subsys_e.bin
}
}
}
Insert partition 2 signature:
command : bootgen -arch versal -image stage7b-1.bif -o lpd_lpd_data_e_ac.bin -w on -log error
stage7b_1:
{
image
{
name = lpd, id = 0x4210002
partition
{
type = bootimage,
revoke_id = 0x3,
authentication = rsa,
ppkfile = rsa-keys/PSK3.pub,
spkfile = rsa-keys/SSK3.pub,
spksignature = SSK3.pub.sha384.sig,
presign = lpd.0.sha384.sig,
file = lpd_lpd_data_e.bin
}
}
}
Insert partition 3 signature:
command : bootgen -arch versal -image stage7b-2.bif -o lpd_psm_fw_e_ac.bin -w on -log error
stage7b_2:
{
image
{
name = lpd, id = 0x4210002
partition
{
revoke_id = 0x1,
type = bootimage,
authentication = rsa,
ppkfile = rsa-keys/PSK1.pub,
spkfile = rsa-keys/SSK1.pub,
spksignature = SSK1.pub.sha384.sig,
presign = psm.0.sha384.sig,
file = lpd_psm_fw_e.bin
}
}
}
Insert partition 4 signature:
command : bootgen -arch versal -image stage7c.bif -o fpd_e_ac.bin -w on -log error
stage7c:
{
image
{
id = 0x1c000000, name = fpd
{ type = bootimage,
revoke_id = 0x3,
authentication=rsa,
ppkfile = rsa-keys/PSK3.pub,
spkfile = rsa-keys/SSK3.pub,
spksignature = SSK3.pub.sha384.sig,
presign = fpd_data.cdo.0.sha384.sig,
file = fpd_e.bin
}
}
}
Insert partition 5 signature:
command : bootgen -arch versal -image stage7d.bif -o subsystem_e_ac.bin -w on -log error
stage7d:
{
image
{
id = 0x1c000033, name = ss
{ type = bootimage,
revoke_id = 0x2,
authentication = rsa,
ppkfile = rsa-keys/PSK2.pub,
spkfile = rsa-keys/SSK2.pub,
spksignature = SSK2.pub.sha384.sig,
presign = ss.0.sha384.sig,
file = subsystem_e.bin
}
}
}
Stage 8: Generate Image Header Table Hash
command : bootgen -arch versal -image stage8a.bif -generate_hashes -w on -log error
stage8b:
{
metaheader
{
authentication = rsa,
revoke_id = 0x2,
ppkfile = rsa-keys/PSK2.pub,
spkfile = rsa-keys/SSK2.pub,
spksignature = SSK2.pub.sha384.sig,
headersignature = imageheadertable.sha384.sig,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/efuse_red_metaheader_key.nky,
dpacm_enable
}
image
{
{type = bootimage, file = pmc_subsys_e_ac.bin}
}
image
{
{type = bootimage, file = lpd_lpd_data_e_ac.bin}
{type = bootimage, file = lpd_psm_fw_e_ac.bin}
}
image
{
{type = bootimage, file = fpd_e_ac.bin}
}
image
{
{type = bootimage, file = subsystem_e_ac.bin}
}
}
Stage 9: Sign Image Header Table Hash
Sign the generated hashes:
openssl rsautl -raw -sign -inkey rsa-keys/SSK2.pem -in imageheadertable.sha384 > imageheadertable.sha384.sig
Stage 10: Generate Meta Header Hash
The Image Header Table signature generated in Stage 9 is consumed here through
headersignature so that the meta-header hash produced by -generate_hashes
includes the signed Image Header Table.
command : bootgen -arch versal -image stage8b.bif -generate_hashes -w on -log error
stage8b:
{
metaheader
{
authentication = rsa,
revoke_id = 0x2,
ppkfile = rsa-keys/PSK2.pub,
spkfile = rsa-keys/SSK2.pub,
spksignature = SSK2.pub.sha384.sig,
encryption=aes,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/efuse_red_metaheader_key.nky,
dpacm_enable
}
image
{
{type = bootimage, file = pmc_subsys_e_ac.bin}
}
image
{
{type = bootimage, file = lpd_lpd_data_e_ac.bin}
{type = bootimage, file = lpd_psm_fw_e_ac.bin}
}
image
{
{type = bootimage, file = fpd_e_ac.bin}
}
image
{
{type = bootimage, file = subsystem_e_ac.bin}
}
}
Stage 11: Sign Meta Header Hash
openssl rsautl -raw -sign -inkey rsa-keys/SSK2.pem -in MetaHeader.sha384 > metaheader.sha384.sig
Stage 12: Combine Partitions and Insert Header Signature
Build the complete PDI. The headersignature attribute supplies the Image Header Table signature produced in Stage 9, and presign supplies the meta-header signature produced in Stage 11. Both are required by the final-assembly step. If the headersignature is omitted, Bootgen aborts with:
command : bootgen -arch versal -image stage10.bif -o final.bin -w on -log error
stage10:
{
metaheader
{
authentication = rsa,
revoke_id = 0x2,
ppkfile = rsa-keys/PSK2.pub,
spkfile = rsa-keys/SSK2.pub,
spksignature = SSK2.pub.sha384.sig,
headersignature = imageheadertable.sha384.sig,
presign = metaheader.sha384.sig,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/efuse_red_metaheader_key.nky,
dpacm_enable
}
image
{
{type = bootimage, file = pmc_subsys_e_ac.bin}
}
image
{
{type = bootimage, file = lpd_lpd_data_e_ac.bin}
{type = bootimage, file = lpd_psm_fw_e_ac.bin}
}
image
{
{type = bootimage, file = fpd_e_ac.bin}
}
image
{
{type = bootimage, file = subsystem_e_ac.bin}
}
}
Assuming secondary.pub.sha384 is a Bootgen generated hash for a given SPK,
the following script generates Bootgen usable signature with a PSK primary.pem.
#! /bin/bash
ecdsa-p384-sign() {
cp $2 $2.hash
truncate -s 48 $2.hash
openssl pkeyutl -sign -inkey $1 -pkeyopt digest:sha3-384 -out $2.der -in $2.hash
r=$(openssl asn1parse -in $2.der -inform DER | sed -n 2p | sed -n 's/.*INTEGER.*:\(.*\)/0000000000000000\1/p' | sed -n 's/.*\(.\{96\}\).*/\1/p')
s=$(openssl asn1parse -in $2.der -inform DER | sed -n 3p | sed -n 's/.*INTEGER.*:\(.*\)/0000000000000000\1/p' | sed -n 's/.*\(.\{96\}\).*/\1/p')
padding=$(head -c 832 /dev/zero | LC_ALL=C tr "\000" "00")
echo -n $r$s$padding > $3
}
ecdsa-p384-sign primary.pem secondary.pub.sha384 secondary.pub.sha384.sig