Skip to content

Xilinx Signing

Looking for the full Zynq UltraScale+ design?

This page documents the SignBootgenImage request and archive formats. For the complete secure boot design — the product with its PSK and SSK key operations, the PPK eFUSE values and which slot each one belongs to, and verification before shipping — see Building CRA-ready Zynq UltraScale+ MPSoC gateways.

In order to do Xilinx boot.bin signing for Zynq UltraScale+ MPSoC devices following actions/configurations are required

  • Product is created with a configuration which supports Xilinx boot image signing.
    • Product operation SignBootgenImage has been configured

Product configuration

  1. Create product with needed signing operations.
    1. Check product for product configuration details.

Input data for Xilinx signing

The input is a tar.gz archive containing a request.json descriptor and the binary component files referenced by it. The tar.gz payload must be base64-encoded before uploading to the platform.

Archive contents

The tar.gz archive must contain:

  • request.json: describes the boot image structure (generated from the Xilinx BIF file)
  • Binary component files (ELF and flat binary) referenced by request.json

request.json format

The request.json describes the Zynq UltraScale+ boot image layout. It corresponds to the Xilinx Bootgen BIF (Boot Image Format) file, with authentication-related fields removed (the platform handles key management and RSA authentication).

Example request.json:

{
  "arch": "zynqmp",
  "ppk_select": 0,
  "spk_id": 0,
  "images": [{
    "output": "boot.bin",
    "fsbl_config": ["a53_x64"],
    "items": [
      {"filename": "pmufw.elf", "attributes": "pmufw_image"},
      {"filename": "fsbl.elf", "attributes": "bootloader, destination_cpu=a53-0"},
      {"filename": "mini.bit", "attributes": "destination_device=pl"},
      {"filename": "bl31.elf", "attributes": "destination_cpu=a53-0, exception_level=el-3, trustzone"},
      {"filename": "tee-pager_v2.bin", "attributes": "destination_cpu=a53-0, exception_level=el-1, trustzone, load=0x7e800000, startup=0x7e800000"},
      {"filename": "u-boot.elf", "attributes": "destination_cpu=a53-0, exception_level=el-2"}
    ]
  }]
}

Note

The attributes field corresponds to Xilinx Bootgen BIF attributes. Do not include pskfile, sskfile, or authentication attributes. The platform adds RSA authentication using its own PSK/SSK keys managed in the HSM.

Note

The platform supports different hash algorithms and key sizes. The values and component list shown above are examples. Configure them according to your product's requirements.

Key selection: ppk_select and spk_id

The PSK names carry AMD's PPK slot numbers:

arch ppk_select Key operation eFUSE value (product secrets)
zynqmp 0 BootgenPSK0 EFusePPK0Bits (PPK0 eFUSEs)
zynqmp 1 BootgenPSK1 EFusePPK1Bits (PPK1 eFUSEs)
zynq 0 BootgenPSK EFusePPKBits

spk_id is the value the boot ROM compares with the 32-bit SPK_ID eFUSE, so it is written into every authentication certificate. eFUSE bits can only be set, so each SPK revocation burns one more bit, and each step uses its own SSK:

spk_id 0 1 3 7 15 31 63 127
SSK BootgenSSK BootgenSSK2 BootgenSSK3 BootgenSSK4 BootgenSSK5 BootgenSSK6 BootgenSSK7 BootgenSSK8

Any other spk_id is refused. spk_id belongs at the top level of request.json; an spk_id inside an item's attributes is refused. zynq images use ppk_select 0 and spk_id 0. Only SignBootgenImage (signing) is supported.

Typical boot image components

A Zynq UltraScale+ boot image typically contains the following components:

File Description Format
pmufw.elf Platform Management Unit firmware ELF
fsbl.elf First Stage Boot Loader ELF
*.bit FPGA bitstream Xilinx bitstream
bl31.elf ARM Trusted Firmware (EL3) ELF
tee-pager*.bin OP-TEE secure OS (flat binary) Raw binary
u-boot.elf U-Boot bootloader ELF

Output

The platform returns a tar.gz archive (raw binary, not base64) containing boot.bin (filename is configured by 'output' field in request.json), the fully assembled and RSA-authenticated Zynq UltraScale+ boot image, as produced by Bootgen.

The archive also holds primary.pub (the PPK) and secondary.pub (the SPK). bootgen -efuseppkbits over primary.pub must give the eFUSE value from the product secrets for the ppk_select used.

The returned boot.bin:

  • Is a valid ZynqMP boot image (boot ROM header at offset 0)
  • Has RSA authentication on each component (equivalent to [authentication=rsa] in the BIF)
  • Uses the product's PSK/SSK key pair for signing

Developer example: preparing a Xilinx boot image for signing

1. Start from the Bootgen BIF file

A typical Xilinx Bootgen BIF file (boot.bif) for a Zynq UltraScale+ design looks like:

the_ROM_image:
{
  [fsbl_config] a53_x64
  [pmufw_image] pmufw.elf
  [bootloader, destination_cpu=a53-0,
   authentication=rsa, pskfile=psk.pem, sskfile=ssk.pem] fsbl.elf
  [destination_device=pl,
   authentication=rsa, pskfile=psk.pem, sskfile=ssk.pem] mini.bit
  [destination_cpu=a53-0, exception_level=el-3, trustzone,
   authentication=rsa, pskfile=psk.pem, sskfile=ssk.pem] bl31.elf
  [destination_cpu=a53-0, exception_level=el-1, trustzone,
   load=0x7e800000, startup=0x7e800000,
   authentication=rsa, pskfile=psk.pem, sskfile=ssk.pem] tee-pager_v2.bin
  [destination_cpu=a53-0, exception_level=el-2,
   authentication=rsa, pskfile=psk.pem, sskfile=ssk.pem] u-boot.elf
}

Warning

When building the request.json for the LAAVAT Platform, strip the authentication, pskfile, and sskfile attributes from each item. The platform handles key management and adds RSA authentication using its own keys stored in the HSM.

2. Generate request.json from the BIF

Convert the BIF to request.json by extracting the architecture, image items, and their attributes (without the authentication/key fields):

{
  "arch": "zynqmp",
  "ppk_select": 0,
  "spk_id": 0,
  "images": [{
    "output": "boot.bin",
    "fsbl_config": ["a53_x64"],
    "items": [
      {"filename": "pmufw.elf", "attributes": "pmufw_image"},
      {"filename": "fsbl.elf", "attributes": "bootloader, destination_cpu=a53-0"},
      {"filename": "mini.bit", "attributes": "destination_device=pl"},
      {"filename": "bl31.elf", "attributes": "destination_cpu=a53-0, exception_level=el-3, trustzone"},
      {"filename": "tee-pager_v2.bin", "attributes": "destination_cpu=a53-0, exception_level=el-1, trustzone, load=0x7e800000, startup=0x7e800000"},
      {"filename": "u-boot.elf", "attributes": "destination_cpu=a53-0, exception_level=el-2"}
    ]
  }]
}

3. Package the archive

Create a tar.gz archive containing request.json and all referenced binary files:

tar czf xilinx-payload.tar.gz request.json pmufw.elf fsbl.elf mini.bit bl31.elf tee-pager_v2.bin u-boot.elf

4. Submit to the LAAVAT Platform

The tar.gz is base64-encoded and uploaded via the standard image signing flow. See the usage example below.

PPK hash for eFuse programming

The boot ROM on the ZynqMP verifies boot.bin against the PPK hash burned into the PPK0 or PPK1 eFUSEs, chosen by ppk_select. The values are delivered with the product secrets as EFusePPK0Bits and EFusePPK1Bits (Zynq-7000: EFusePPKBits), see the table above.

For production:

  • The PPK hash (SHA3-384 in AMD's Keccak form) must be programmed into the device eFuses during manufacturing
  • The PPK hash is a one-time-programmable value. Once set, only boot images signed with the matching PPK can boot

For R&D/unfused devices, the bh_auth_enable BIF flag enables authentication without eFuses (for testing).

Example usage with reference client package: Xilinx signing

The examples below use two config files created with config-init: test.ini for the regular user and approver.ini for a user in the approvers group. Each config holds a token_file reference rather than a literal token, so no token appears on the command line. See Reference Client › Usage for how to create these configs and for the secure token-input forms (-t @file, -t @-).

(venv) $ signing-tool -n test.ini imagesigning add SignBootgenImage \
    -N test -D test2 -P adcb30d8-f009-438e-b1b2-96f507b306cb --operid 4add90e9-ffb3-4708-9554-ed2e82e8fd71 -F xilinx-payload.tar.gz

# Approve the signing request
(venv) $ signing-tool -n approver.ini imagesigning approve \
    -I a83081a6-1d3b-4117-a81b-0ebcfcf0669c

# Get the signed payload (a raw tar.gz: boot.bin, primary.pub, secondary.pub; --skipBase64 because it is not base64)
(venv) $ signing-tool -n test.ini imagesigning get \
    -I a83081a6-1d3b-4117-a81b-0ebcfcf0669c -O /tmp/signed-boot.tar.gz --wait --skipBase64