Boot Time Security
Xilinx® supports secure booting on all devices using latest authentication methods to prevent unathorized or modified code from being run on Xilinx devices. Xilinx supports various encryption techniques to make sure only authorized programs access the images. For hardware security features by device, see the following sections.
Secure and Non-Secure Modes in Zynq-7000 SoC Devices
For security reasons, CPU 0 is always the first device out of reset among all master modules within the PS. CPU 1 is held in an WFE state. While the BootROM is running, the JTAG is always disabled, regardless of the reset type, to ensure security. After the BootROM runs, JTAG is enabled if the boot mode is non-secure.
The BootROM code is also responsible for loading the FSBL/User code. When the BootROM releases control to stage 1, the user software assumes full control of the entire system. The only way to execute the BootROM again is by generating one of the system resets. The FSBL/User code size, encrypted and unencrypted, is limited to 192 KB. This limit does not apply with the non-secure execute-in-place option.
The PS boot source is selected using the BOOT_MODE
strapping pins (indicated by a weak pull-up or pull-down
resistor), which are sampled once during power-on reset (POR). The sampled values
are stored in the slcr.BOOT_MODE
register.
The BootROM supports encrypted/authenticated, and unencrypted images referred to as secure boot and non-secure boot, respectively. The BootROM supports execution of the stage 1 image directly from NOR or Quad-SPI when using the execute-in-place (xip_mode) option, but only for non-secure boot images. Execute-in-place is possible only for NOR and Quad-SPI boot modes.
- In secure boot, the CPU, running the BootROM code decrypts and authenticates the user PS image on the boot device, stores it in the OCM, and then branches to it.
- In non-secure boot, the CPU, running the BootROM code disables all secure boot features including the AES unit within the PL before branching to the user image in the OCM memory or the flash device (if execute-in-place (XIP) is used).
Any subsequent boot stages for either the PS or the PL are the responsibility of you, the developer, and are under your control. The BootROM code is not accessible to you. Following a stage 1 secure boot, you can proceed with either secure or non-secure subsequent boot stages. Following a non-secure first stage boot, only non-secure subsequent boot stages are possible.
Zynq UltraScale+ MPSoC Device Security
In a Zynq® UltraScale+™ MPSoC device, the secure boot is accomplished by using the hardware root of trust boot mechanism, which also provides a way to encrypt all of the boot or configuration files. This architecture provides the required confidentiality, integrity, and authentication to host the most secure of applications.
See this link in the Zynq UltraScale+ Device Technical Reference Manual (UG1085) for more information.
Versal ACAP Security
On Versal™ ACAPs, secure boot ensures the confidentiality, integrity, and authentication of the firmware and software loaded onto the device. The root of trust starts with the PMC ROM, which authentications and/or decrypts the PLM software. Now that the PLM software is trusted, the PLM handles loading the rest of the firmware and software in a secure manner. Additionally, if secure boot is not desired then software can at least be validated with a simple checksum.
See Versal ACAP Technical Reference Manual (AM011) for more information.
Using Encryption
Secure booting, which validates the images on devices before they are allowed to execute, has become a mandatory feature for most electronic devices being deployed in the field. For encryption, Xilinx supports an advanced encryption standard (AES) algorithm AES encryption.
AES provides symmetric key cryptography (one key definition for both encryption and decryption). The same steps are performed to complete both encryption and decryption in reverse order.
AES is an iterated symmetric block cipher, which means that it does the following:
- Works by repeating the same defined steps multiple times
- Uses a secret key encryption algorithm
- Operates on a fixed number of bytes
Encryption Process
Bootgen can encrypt the boot image partitions based on the user-provided encryption commands and attributes in the BIF file. AES is a symmetric key encryption technique; it uses the same key for encryption and decryption. The key used to encrypt a boot image should be available on the device for the decryption process while the device is booting with that boot image. Generally, the key is stored either in eFUSE or BBRAM, and the source of the key can be selected during boot image creation through BIF attributes, as shown in the following figure.
Decryption Process
For SoC devices, the BootROM and the FSBL decrypt partitions during the booting cycle. The BootROM reads FSBL from flash, decrypts, loads, and hands off the control. After FSBL start executing, it reads the remaining partitions, decrypts, and loads them. The AES key needed to decrypt the partitions can be retrieved from either eFUSE or BBRAM. The key source field of the boot header table in the boot image is read to know the source of the encryption key. Each encrypted partition is decrypted using a AES hardware engine.
Encrypting Zynq-7000 Device Partitions
Zynq®-7000 SoC devices use the embedded, Progammable Logic (PL), hash-based message authentication code (HMAC) and an advanced encryption standard (AES) module with a cipher block chaining (CBC) mode.
Example BIF File
To create a boot image with encrypted partitions, the AES key file is
specified in the BIF using the aeskeyfile attribute. Specify an encryption=aes
attribute for each image file listed in the BIF file to be encrypted. The example BIF file
(secure.bif) is shown
below:
image:
{
[aeskeyfile] secretkey.nky
[keysrc_encryption] efuse
[bootloader, encryption=aes] fsbl.elf
[encryption=aes] uboot.elf
}
From
the command line, use the following command to generate a boot image with encrypted
fsbl.elf and uboot.elf.
bootgen -arch zynq -image secure.bif -w -o BOOT.bin
Key Generation
Bootgen can generate AES-CBC keys. Bootgen uses the AES key file specified in the BIF for encrypting the partitions. If the key file is empty or non-existent, Bootgen generates the keys in the file specified in the BIF file. If the key file is not specified in the BIF, and encryption is requested for any of the partitions, then Bootgen generates a key file with the name of the BIF file with extension .nky in the same directory as of BIF. The following is a sample key file.
Encrypting Zynq MPSoC Device Partitions
The Zynq® UltraScale+™ MPSoC device uses the AES-GCM core, which has a 32-bit, word-based data interface with support for a 256-bit key. The AES-GCM mode supports encryption and decryption, multiple key sources, and built-in message integrity check.
Operational Key
A good key management practice includes minimizing the use of secret or private keys. This can be accomplished using the operational key option enabled in Bootgen.
Bootgen creates an encrypted, secure header that contains the operational key
(opt_key
), which is user-specified, and the
initialization vector (IV) needed for the first block of the configuration file when
this feature is enabled. The result is that the AES key stored on the device, in either
the BBRAM or eFUSEs, is used for only 384 bits, which significantly limits its exposure
to side channel attacks. The attribute opt_key
is used
to specify operational key usage. See fsbl_config
for more information about the opt_key
value that is an
argument to the fsbl_config
attribute. The following is
an example of using the opt_key
attribute.
image:
{
[fsbl_config] opt_key
[keysrc_encryption] bbram_red_key
[bootloader,
destination_cpu = a53-0,
encryption = aes,
aeskeyfile = aes_p1.nky]fsbl.elf
[destination_cpu = a53-3,
encryption = aes,
aeskeyfile = aes_p2.nky]hello.elf
}
The operation key is given in the AES key (.nky) file with name Key
Opt
as shown in the following example.
Bootgen generates the encryption key file. The operational key opt_key
is then generated in the .nky
file, if opt_key
has been enabled in the BIF file, as
shown in the previous example.
For another example of using the operational key, refer to Using Op Key to Protect the Device Key in a Development Environment.
For more details about this feature, see the Key Management section of the "Security" chapter in the Zynq UltraScale+ Device Technical Reference Manual (UG1085).
Rolling Keys
The AES-GCM also supports the rolling keys feature, where the entire encrypted image is represented in terms of smaller AES encrypted blocks/modules. Each module is encrypted using its own unique key. The initial key is stored at the key source on the device, while keys for each successive module are encrypted (wrapped) in the previous module. The boot images with rolling keys can be generated using Bootgen. The BIF attribute blocks is used to specify the pattern to create multiple smaller blocks for encryption.
image:
{
[keysrc_encryption] bbram_red_key
[
bootloader,
destination_cpu = a53-0,
encryption = aes,
aeskeyfile = aes_p1.nky,
blocks = 1024(2);2048;4096(2);8192(2);4096;2048;1024
] fsbl.elf
[
destination_cpu = a53-3,
encryption = aes,
aeskeyfile = aes_p2.nky,
blocks = 4096(1);1024
] hello.elf
}
- Number of keys in the key file should always be equal to the
number of blocks to be encrypted.
- If the number of keys are less than the number of blocks to be encrypted, Bootgen returns an error.
- If the number of keys are more than the number of blocks to be encrypted, Bootgen ignores (does not read) the extra keys.
- If you want to specify multiple Key/IV Pairs, you should specify
no. of blocks + 1
pairs- The extra Key/IV pair is to encrypt the secure header.
- No Key/IV pair should be repeated in a any of the aes key files given in a single bif except the Key0 and IV0.
Gray/Obfuscated Keys
The user key is encrypted with the family key, which is embedded in the metal layers of the device. This family key is the same for all devices in the Zynq® UltraScale+™ MPSoC. The result is referred to as the obfuscated key. The obfuscated key can reside in either the Authenticated Boot Header or or in eFUSEs.
image:
{
[keysrc_encryption] efuse_gry_key
[bh_key_iv] bhiv.txt
[
bootloader,
destination_cpu = a53-0,
encryption = aes,
aeskeyfile = aes_p1.nky
] fsbl.elf
[
destination_cpu = r5-0,
encryption = aes,
aeskeyfile = aes_p2.nky
] hello.elf
}
Bootgen does the following while creating an image:
- Places the IV from
bhiv.txt
in the field BH IV in Boot Header. - Places the IV 0 from
aes.nky
in the field "Secure Header IV" in Boot Header. - Encrypts the partition, with Key0 and IV0 from aes.nky.
Another example of using the gray/family key is found in Use Cases and Examples.
For more details about this feature, refer to the Zynq UltraScale+ Device Technical Reference Manual (UG1085).
Key Generation
Bootgen has the capability of generating AES-GCM keys. It uses the NIST-approved Counter Mode KDF, with CMAC as the pseudo random function. Bootgen takes seed as input in case the user wants to derive multiple keys from seed due to key rolling. If a seed is specified, the keys are derived using the seed. If seeds are not specified, keys are derived based on Key0. If an empty key file is specified, Bootgen generates a seed with time based randomization (not KDF), which in turn is the input for KDF to generate other the Key/IV pairs.
- If one encryption file is specified and others are generated, Bootgen can make sure to use the same Key0/IV0 pair for the generated keys as in the encryption file for first partition. For example, in the case of a full boot image, the first partition is the bootloader.
- If an encryption file is generated for the first partition and other encryption file with Key0/IV0 is specified for a later partition, then Bootgen exits and returns the error that an incorrect Key0/IV0 pair was used.
Key Generation
A sample key file is shown below.
Obfuscated Key Generation
Bootgen can generate the Obfuscated key by encrypting the red key with the family key and a user-provided IV. The family key is delivered by the Xilinx® Security Group. For more information, see familykey. To generate an obfuscated key, Bootgen takes the following inputs from the BIF file.
obf_key:
{
[aeskeyfile] aes.nky
[familykey] familyKey.cfg
[bh_key_iv] bhiv.txt
}
The command to generate the Obfuscated key is:
bootgen -arch zynqmp -image all.bif -generate_keys obfuscatedkey
Black/PUF Keys
The black key storage solution uses a cryptographically strong key encryption key (KEK), which is generated from a PUF, to encrypt the user key. The resulting black key can then be stored either in the eFUSE or as a part of the authenticated boot header.
image:
{
[puf_file] pufdata.txt
[bh_key_iv] black_iv.txt
[bh_keyfile] black_key.txt
[fsbl_config] puf4kmode, shutter=0x0100005E, pufhd_bh
[keysrc_encryption] bh_blk_key
[
bootloader,
destination_cpu = a53-0,
encryption = aes,
aeskeyfile = aes_p1.nky
] fsbl.elf
[
destination_cpu = r5-0,
encryption = aes,
aeskeyfile = aes_p2.nky
] hello.elf
}
For another example of using the black key, see Use Cases and Examples.
Multiple Encryption Key Files
Earlier versions of Bootgen supported creating the boot image by encrypting multiple partitions with a single encryption key. The same key is used over and over again for every partition. This is a security weakness and not recommended. Each key should be used only once in the flow.
Bootgen supports separate encryption keys for each partition. In case of multiple key files, ensure that each encryption key file uses the same Key0 (device key), IV0, and Operational Key. Bootgen does not allow creating boot images if these are different in each encryption key file. You must specify multiple encryption key files, one for each of partition in the image. The partitions are encrypted using the key that is specified for the partition.
.1
, .2
, .n
, and so on
in the same directory of the key file meant for that partition.The following snippet shows a sample encryption key file:
all:
{
[keysrc_encryption] bbram_red_key
// FSBL (Partition-0)
[
bootloader,
destination_cpu = a53-0,
encryption = aes,
aeskeyfile = key_p0.nky
]fsbla53.elf
// application (Partition-1)
[
destination_cpu = a53-0,
encryption = aes,
aeskeyfile = key_p1.nky
]hello.elf
}
- The partition fsbla53.elf is encrypted using the keys from key_p0.nky file.
- Assuming hello.elf has three partitions because it has three loadable sections, then partition hello.elf.0 is encrypted using keys from the test2.nky file.
- Partition hello.elf.1 is then
encrypted using keys from
test2.1.nky
. - Partition hello.elf.2 is
encrypted using keys from
test2.2.nky
.
Encrypting Versal Device Partitions
The Versal™ device uses the AES-GCM core, which has support for a 256-bit key. When creating a secure image, each partition in a boot image can be optionally encrypted. Key source and aes key file are the prerequisites for encryption.
Key Management
Good key management practice includes minimizing the use of secret or private keys. This can be accomplished this by using different key/IV pairs across different partitions in the boot image. The result is that the AES key stored on the device, in either the BBRAM or eFUSEs, is used for only 384 bits, which significantly limits its exposure to side channel attacks.
all: {
image
{
{type=bootloader, encryption=aes, keysrc=bbram_red_key, aeskeyfile=plm.nky, dpacm_enable, file=plm.elf}
{type=pmcdata, load=0xf2000000, aeskeyfile = pmc_data.nky, file=pmc_data.cdo}
{core=psm, file=psm.elf}
{type=cdo, encryption=aes, keysrc=bbram_red_key, aeskeyfile=ps_data.nky, file=ps_data.cdo}
{type=cdo, file=subsystem.cdo}
{core=a72-0, exception_level = el-3, file=a72-app.elf}
}
}
Rolling Keys
The AES-GCM also supports the rolling keys feature, where the entire encrypted image is represented in terms of smaller AES encrypted blocks/modules. Each module is encrypted using its own unique key. The initial key is stored at the key source on the device, while keys for each successive module are encrypted (wrapped) in the previous module. You can generate the boot images with rolling keys using Bootgen. The BIF attribute blocks is used to specify the pattern to create multiple smaller blocks for encryption.
all:
{
id_code = 0x04ca8093
extended_id_code = 0x01
id = 0x2
metaheader
{
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = efuse_red_metaheader_key.nky,
dpacm_enable
}
image
{
name = pmc_subsys, id = 0x1c000001
partition
{
id = 0x01, type = bootloader,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = bbram_red_key.nky,
dpacm_enable,
blocks = 4096(2);1024;2048(2);4096(*),
file = executable.elf
}
partition
{
id = 0x09, type = pmcdata, load = 0xf2000000,
aeskeyfile = pmcdata.nky,
file = topology_xcvc1902.v1.cdo,
file = pmc_data.cdo
}
}
image
{
name = lpd, id = 0x4210002
partition
{
id = 0x0C, type = cdo,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = key1.nky,
dpacm_enable,
blocks = 8192(20);4096(*),
file = lpd_data.cdo
}
partition
{
id = 0x0B, core = psm,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = key2.nky,
dpacm_enable,
blocks = 4096(2);1024;2048(2);4096(*),
file = psm_fw.elf
}
}
image
{
name = fpd, id = 0x420c003
partition
{
id = 0x08, type = cdo,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = key5.nky,
dpacm_enable,
blocks = 8192(20);4096(*),
file = fpd_data.cdo
}
}
}
- Number of keys in the key file should always be equal to the number of blocks to be encrypted.
- If the number of keys are less than the number of blocks to be encrypted, Bootgen returns an error.
- If the number of keys are more than the number of blocks to be encrypted, Bootgen ignores the extra keys.
Key Generation
Bootgen can generate AES-GCM keys. It uses the NIST-approved Counter Mode KDF, with CMAC as the pseudo random function. Bootgen takes seed as input in case you want to derive multiple keys from seed due to key rolling. If a seed is specified, the keys are derived using the seed. If seeds are not specified, keys are derived based on Key0. If an empty key file is specified, Bootgen generates a seed with time based randomization (not KDF), which in turn is the input for KDF to generate other the Key/IV pairs. The following conditions apply.
- If one encryption file is specified and others are generated, Bootgen can make sure to use the same Key0/IV0 pair for the generated keys as in the encryption file for first partition.
- If an encryption file is generated for the first partition and other encryption file with Key0/IV0 is specified for a later partition, then Bootgen exits and returns the error that an incorrect Key0/IV0 pair was used.
- If no key file is specified and encryption is opted for a partition, bootgen by default generated an aes key file with the name of the partition. By doing this, Bootgen makes sure that a different aeskeyfile is used for each partition.
- Bootgen enables the usage of unique key files for each of the partition created due to multiple loadable sections by reading/generating key file names appended with ".1", ".2"...".n" so on in the same directory of the key file meant for that partition.
Black/PUF Keys
The black key storage solution uses a cryptographically strong key encryption key (KEK), which is generated from a PUF, to encrypt the user key. The resulting black key can then be stored either in the eFUSE or as a part of the authenticated boot header. Example:
test:
{
bh_kek_iv = black_iv.txt
bh_keyfile = black_key.txt
puf_file = pufdata.txt
boot_config {puf4kmode}
image
{
{type=bootloader, encryption = aes, keysrc=bh_blk_key, pufhd_bh, aeskeyfile = red_grey.nky, file=plm.elf}
{type=pmcdata,load=0xf2000000, aeskeyfile = pmcdata.nky, file=pmc_data.cdo}
{core=psm, file=psm.elf}
{type=cdo, file=ps_data.cdo}
{type=cdo, file=subsystem.cdo}
{core=a72-0, exception_level = el-3, file=hello_world.elf}
}
}
Meta Header Encryption
For a Versal ACAP, bootgen encrypts the meta header when encryption is specifically mentioned under the "metaheader" attribute. The aeskeyfile that is to be used can be specified in the bif using the parameters under "metaheader". A snippet of the usage is shown below.
metaheader
{
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = headerkey.nky,
}
The following conditions apply.
- If a specific aeskeyfile is not specified for meta header, Bootgen generates a file named meta_header.nky, and uses it during encryption.
- If a boot loader is present in the bif, it is mandatory to encrypt boot loader to encrypt meta header. For a partial PDI, meta header can be optionally chosen to be encrypted.
Using Authentication
AES encryption is a self-authenticating algorithm with a symmetric key, meaning that the key to encrypt is the same as the one to decrypt. This key must be protected as it is secret (hence storage to internal key space). There is an alternative form of authentication in the form of RSA (Rivest-Shamir-Adleman). RSA is an asymmetric algorithm, meaning that the key to verify is not the same key used to sign. A pair of keys are needed for authentication.
- Signing is done using Secret Key/ Private Key
- Verification is done using a Public Key
This public key does not need to be protected, and does not need special secure storage. This form of authentication can be used with encryption to provide both authenticity and confidentiality. RSA can be used with either encrypted or unencrypted partitions.
RSA not only has the advantage of using a public key, it also has the advantage of authenticating prior to decryption. The hash of the RSA Public key must be stored in the eFUSE. Xilinx® SoC devices support authenticating the partition data before it is sent to the AES decryption engine. This method can be used to help prevent attacks on the decryption engine itself by ensuring that the partition data is authentic before performing any decryption.
In Xilinx SoCs, two pairs of public and secret keys are used - primary and secondary. The function of the primary public/secret key pair is to authenticate the secondary public/secret key pair. The function of the secondary key is to sign/verify partitions.
The first letter of the acronyms used to describe the keys is either P for primary or S for secondary. The second letter of the acronym used to describe the keys is either P for public or S for secret. There are four possible keys:
- PPK = Primary Public Key
- PSK = Primary Secret Key
- SPK = Secondary Public Key
- SSK = Secondary Secret Key
Bootgen can create a authentication certificate in two ways:
- Supply the PSK and SSK. The SPK signature is calculated on-the-fly using these two inputs.
- Supply the PPK and SSK and the SPK signature as inputs. This is used in cases where the PSK is not known.
The primary key is hashed and stored in the eFUSE. This hash is compared against the hash of the primary key stored in the boot image by the FSBL. This hash can be written to the PS eFUSE memory using standalone driver provided along with Vitis.
The following is an example BIF file:
image:
{
[pskfile]primarykey.pem
[sskfile]secondarykey.pem
[bootloader,authentication=rsa] fsbl.elf
[authentication=rsa]uboot.elf
}
For device-specific Authentication information, see the following:
Signing
The following figure shows RSA signing of partitions. From a secure facility, Bootgen signs partitions using the Secret key. The signing process is described in the following steps:
- PPK and SPK are stored in the Authentication Certificate (AC).
- SPK is signed using PSK to get SPK signature; also stored as part of the AC.
- Partition is signed using SSK to get Partition signature, populated in the AC.
- The AC is appended or prepended to each partition that is opted for authentication depending on the device.
- PPK is hashed and stored in eFUSE.
The following table shows the options for Authentication.
Key | Name | Description | Supported File Format |
---|---|---|---|
PPK | Primary Public Key | This key is used to authenticate a partition. It should always be specified when authenticating a partition. |
*.txt *.pem *.pub *.pk1 |
PSK | Primary Secret Key | This key is used to authenticate a partition. It should always be specified when authenticating a partition. |
*.txt *.pem *.pk1 |
SPK | Secondary Public Key | This key, when specified, is used to authenticate a partition. | *.txt *.pem *.pub *.pk1 |
SSK | Secondary Secret Key | This key, when specified, is used to authenticate a partition. | *.txt *.pem *.pk1 |
Verifying
In the device, the BootROM verifies the FSBL, and either the FSBL or U-Boot verifies the subsequent partitions using the Public key.
- Verify PPK: This step establishes the authenticity of primary key, which is
used to authenticate secondary key.
- PPK is read from AC in boot image
- Generate PPK hash
- Hashed PPK is compared with the PPK hash retrieved from eFUSE
- If same, then primary key is trusted, else secure boot fail
- Verify secondary keys: This step establishes the authenticity of secondary
key, which is used to authenticate the partitions.
- SPK is read from AC in boot image
- Generate SPK hashed
- Get the SPK hash, by verifying the SPK signature stored in AC, using PPK
- Compare hashes from step (b) and step (c)
- If same, then secondary key is trusted, else secure boot fail.
- Verify partitions: This step establishes the authenticity of partition which
is being booted.
- Partition is read from the boot image.
- Generate hash of the partition.
- Get the partition hash, by verifying the Partition signature stored in AC, using SPK.
- Compare the hashes from step (b) and step (c)
- If same, then partition is trusted, else secure boot fail
Bootgen can create a authentication certificate in two ways:
- Supply the PSK and SSK. The SPK signature is calculated on-the-fly using these two inputs.
- Supply the PPK and SSK and the SPK signature as inputs. This is used in cases where the PSK is not known.
Zynq UltraScale+ MPSoC Authentication Support
The Zynq® UltraScale+™ MPSoC device uses RSA-4096 authentication, which means the primary and secondary key sizes are 4096-bit.
NIST SHA-3 Support
The generated signature uses the Keccak-SHA3 or NIST-SHA3 based on following table:
Which Authentication Certificate (AC)? | Signature | SHA Algorithm and SPK eFUSE | Secret Key used for Signature Generation |
---|---|---|---|
Partitions header AC (loaded by FSBL/FW) | SPK Signature | If SPKID eFUSEs, then Keccak; If User eFUSE, then NIST | PSK |
BH Signature | Always Keccak | SSKheader | |
Header Signature | Always Nist | SSKheader | |
BootLoader (FSBL) AC (loaded by ROM) | SPK Signature | Always Keccak; Always SPKID eFUSE for SPK | PSK |
BH Signature | Always Keccak | SSKBootloader | |
FSBL Signature | Always Keccak | SSKBootloader | |
Other Partition AC (loaded by FSBL FW) | SPK Signature | If SPKID eFUSEs then Keccak; If User eFUSE then NIST | PSK |
BH Signature | Always Keccak padding | SSKPartition | |
Partition Signature | Always NIST padding | SSKPartition |
Examples
Example 1: BIF file for authenticating the partition with single set of key files:
image:
{
[fsbl_config] bh_auth_enable
[auth_params] ppk_select=0; spk_id=0x00000000
[pskfile] primary_4096.pem
[sskfile] secondary_4096.pem
[pmufw_image] pmufw.elf
[bootloader, authentication=rsa, destination_cpu=a53-0] fsbl.elf
[authenication=rsa, destination_cpu=r5-0] hello.elf
}
Example 2: BIF file for authenticating the partitions with separate secondary key for each partition:
image:
{
[auth_params] ppk_select=1
[pskfile] primary_4096.pem
[sskfile] secondary_4096.pem
// FSBL (Partition-0)
[
bootloader,
destination_cpu = a53-0,
authentication = rsa,
spk_id = 0x01,
sskfile = secondary_p1.pem
] fsbla53.elf
// ATF (Partition-1)
[
destination_cpu = a53-0,
authentication = rsa,
exception_level = el-3,
trustzone = secure,
spk_id = 0x01,
sskfile = secondary_p2.pem
] bl31.elf
// UBOOT (Partition-2)
[
destination_cpu = a53-0,
authentication = rsa,
exception_level = el-2,
spk_id = 0x01,
sskfile = secondary_p3.pem
] u-boot.elf
}
Bitstream Authentication Using External Memory
The authentication of a bitstream is different from other partitions. The FSBL can be wholly contained within the OCM, and therefore authenticated and decrypted inside of the device. For the bitstream, the size of the file is so large that it cannot be wholly contained inside the device and external memory must be used. The use of external memory creates a challenge to maintain security because an adversary may have access to this external memory. When bitstream is requested for authentication, Bootgen divides the whole bitstream into 8MB blocks and has an authentication certificate for each block. If a bitstream is not in multiples of 8MB, the last block contains the remaining bitstream data. When authentication and encryption are both enabled, encryption is first done on the bitstream, then Bootgen divides the encrypted data into blocks and places an authentication certificate for each block.
User eFUSE Support with Enhanced RSA Key Revocation
Enhanced RSA Key Revocation Support
The RSA key provides the ability to revoke the secondary keys of one partition without revoking the secondary keys for all partitions.
This is achieved by using USER_FUSE0
to USER_FUSE7
eFUSEs with the BIF parameter spk_select.
The following BIF file sample shows enhanced user fuse revocation. Image header and FSBL uses different SSKs for authentication (ssk1.pem and ssk2.pem respectively) with the following BIF input.
the_ROM_image:
{
[auth_params]ppk_select = 0
[pskfile]psk.pem
[sskfile]ssk1.pem
[
bootloader,
authentication = rsa,
spk_select = spk-efuse,
spk_id = 0x8,
sskfile = ssk2.pem
] zynqmp_fsbl.elf
[
destination_cpu = a53-0,
authentication = rsa,
spk_select = user-efuse,
spk_id = 0x100,
sskfile = ssk3.pem
] application.elf
[
destination_cpu = a53-0,
authentication = rsa,
spk_select = spk-efuse,
spk_id = 0x8,
sskfile = ssk4.pem
] application2.elf
}
spk_select = spk-efuse
indicates thatspk_id
eFUSE will be used for that partition.spk_select = user-efuse
indicates that user eFUSE will be used for that partition.
Partitions loaded by CSU ROM will always use spk_efuse
.
spk_id
eFUSE specifies which key is valid. Hence, the ROM checks the
entire field of spk_id
eFUSE against the SPK ID to
make sure its a bit for bit match.The user eFUSE specifies which key ID is NOT valid (has been revoked). Therefore, the firmware (non-ROM) checks to see if a given user eFUSE that represents the SPK ID has been programmed.
Key Generation
Bootgen has the capability of generating RSA keys. Alternatively, you can create keys using external tools such as OpenSSL. Bootgen creates the keys in the paths specified in the BIF file.
BIF Example
A sample BIF file, generate_pem.bif:
generate_pem:
{
[pskfile] psk0.pem
[sskfile] ssk0.pem
}
Command
The command to generate keys is, as follows:
bootgen -generate_keys pem -arch zynqmp -image generate_pem.bif
PPK Hash for eFUSE
Bootgen generates the PPK hash for storing in eFUSE for PPK to be trusted. This step is required only for RSA Authentication with eFUSE mode, and can be skipped for RSA Boot Header Authentication for the Zynq® UltraScale+™ MPSoC device. The value from efuseppksha.txt can be programmed to eFUSE for RSA authentication with the eFUSE mode.
For more information about BBRAM and eFUSE programming, see Programming BBRAM and eFUSEs (XAPP1319).
BIF File Example
The following is a sample BIF file, generate_hash_ppk.bif.
generate_hash_ppk:
{
[pskfile] psk0.pem
[sskfile] ssk0.pem
[bootloader, destination_cpu=a53-0, authentication=rsa] fsbl_a53.elf
}
Command
The command to generate PPK hash for eFUSE programming is:
bootgen –image generate_hash_ppk.bif –arch zynqmp –w –o /
test.bin –efuseppkbits efuseppksha.txt
Versal Authentication Support
Bootgen supports RSA-4096 and ECDSA P384 and P521 curves for Versal ACAP authentication. NIST SHA-3 is used to calculate hash on all partitions/headers. The signature calculated on the hash is placed in the PDI.
Meta Header Authentication
For a Versal ACAP, Bootgen authenticates the meta header based on the parameters under the bif attribute "metaheader". A snippet of the usage is shown below.
metaheader
{
authentication = rsa,
pskfile = psk.pem,
sskfile = ssk.pem
}
PPK Hash for eFUSE
Bootgen generates the PPK hash for storing in eFUSE for PPK to be trusted. This step is required only for authentication with eFUSE mode, and can be skipped for Boot Header Authentication. The value from efuseppksha.txt can be programmed to eFUSE for authentication with the eFUSE mode.
BIF File Example
The following is a sample BIF file, generate_hash_ppk.bif.
generate_hash_ppk:
{
pskfile = primary0.pem
sskfile = secondary0.pem
image
{
name = pmc_ss, id = 0x1c000001
{ type=bootloader, authentication=rsa, file=plm.elf}
{ type=pmcdata, load=0xf2000000, file=pmc_cdo.bin}
}
}
Command
The command to generate PPK hash for eFUSE programming is:
bootgen –image generate_hash_ppk.bif –arch versal –w –o test.bin –efuseppkbits efuseppksha.txt
Cumulative Secure Boot Operations for Versal ACAP
Boot Type | Operations | Hardware Crypto Engines | ||
---|---|---|---|---|
Authentication | Decryption | Integrity (Checksum Verification) | ||
Non-secure boot | No | No | No | None |
Asymmetric Hardware Root-of-Trust (A-HWRoT) | Yes (Required) | No | No | RSA/ECDSA along with SHA3 |
Symmetric Hardware Root-of-Trust (S-HWRoT) (Forces decryption of PDI with eFUSE black key) | No | Yes (Required PLM and Meta Header should be encrypted with eFUSE KEK) | No | AES-GCM |
A-HWRoT + S-HWRoT | Yes (Required) | Yes (Required) | No | RSA/ECDSA along with SHA3 and AES-GCM |
Authentication + Decryption of PDI | Yes | Yes (Key source can be either from BBRAM or eFUSE) | No | RSA/ECDSA along with SHA3 and AES-GCM |
Decryption (Uses user-selected key. The key source can be of any type such as BBRAM/BHDR or even eFUSE) | No | Yes | No | AES-GCM |
Checksum Verification | No | No | Yes | SHA3 |
Using HSM Mode
In current cryptography, all the algorithms are public, so it becomes critical to protect the private/secret key. The hardware security module (HSM) is a dedicated crypto-processing device that is specifically designed for the protection of the crypto key lifecycle, and increases key handling security, because only public keys are passed to the Bootgen and not the private/secure keys. A standard mode is also available; this mode does not require passing keys.
In some organizations, an infosec staff is responsible for the production release of a secure embedded product. The infosec staff might use a HSM for digital signatures and a separate secure server for encryption. The HSM and secure server typically reside in a secure area. The HSM is a secure key/signature generation device which generates private keys, signs the partitions using the private key, and provides the public part of the RSA key to Bootgen. The private keys reside in the HSM only.
Bootgen in HSM mode uses only RSA public keys and the signatures that were created by the HSM to generate the boot image. The HSM accepts hash values of partitions generated by Bootgen and returns a signature block, based on the hash and the secret RSA key.
In contrast to the HSM mode, Bootgen in its Standard mode uses AES encryption keys and the RSA Secret keys provided through the BIF file, to encrypt and authenticate the partitions in the image, respectively. The output is a single boot image, which is encrypted and authenticated. For authentication, the user has to provide both sets of public and private/secret keys. The private/secret keys are used by the Bootgen to sign the partitions and create signatures. These signatures along with the public keys are embedded into the final boot image.
For more information about the HSM mode for FPGAs, see the HSM Mode.
Using Advanced Key Management Options
The public keys associated with the private keys are ppk.pub and spk.pub. The HSM accepts hash values of partitions generated by Bootgen and returns a signature block, based on the hash and the secret key.
Creating a Boot Image Using HSM Mode: PSK is not Shared
The following figure shows a Stage 0 to Stage 2 Boot stack that uses the HSM mode. It reduces the number of steps by distributing the SSK.
This figure uses the Zynq® UltraScale+™ MPSoC device to illustrate the stages.
Boot Process
Creating a boot image using HSM mode is similar to creating a boot image using a standard flow with following BIF file.
all:
{
[auth_params] ppk_select=1;spk_id=0x8
[keysrc_encryption]bbram_red_key
[pskfile]primary.pem
[sskfile]secondary.pem
[
bootloader,
encryption=aes,
aeskeyfile=aes.nky,
authentication=rsa
]fsbl.elf
[destination_cpu=a53-0,authentication=rsa]hello_a53_0_64.elf
}
Stage 0: Create a boot image using HSM Mode
A trusted individual creates the SPK signature using the Primary Secret Key. The SPK Signature is on the Authentication Certificate Header, SPK, and SPK ID. To generate a hash for the above, use the following BIF file snippet.
stage 0:
{
[auth_params] ppk_select=1;spk_id=0x3
[spkfile]keys/secondary.pub
}
The following is the Bootgen command:
bootgen -arch zynqmp -image stage0.bif -generate_hashes
The output of this command is: secondary.pub.sha384.
Stage 1: Distribute the SPK Signature
The trusted individual distributes the SPK Signature to the development teams.
openssl rsautl -raw -sign -inkey keys/primary0.pem -in secondary.pub.sha384 > secondary.pub.sha384.sig
The output of this command is: secondary.pub.sha384.sig
Stage 2: Encrypt using AES in FSBL
The development teams use Bootgen to create as many boot images as needed. The development teams use:
- The SPK Signature from the Trusted Individual.
- The Secondary Secret Key (SSK), SPK, and SPKID
Stage2:
{
[keysrc_encryption]bbram_red_key
[auth_params] ppk_select=1;spk_id=0x3
[ppkfile]keys/primary.pub
[sskfile]keys/secondary0.pem
[spksignature]secondary.pub.sha384.sig
[bootloader,destination_cpu=a53-0, encryption=aes, aeskeyfile=aes0.nky, authentication=rsa] fsbl.elf
[destination_cpu=a53-0, authentication=rsa] hello_a53_0_64.elf
}
bootgen -arch zynqmp -image stage2.bif -o final.bin
Creating a Zynq-7000 SoC Device Boot Image using HSM Mode
The following figure provides a diagram of an HSM mode boot image for a Zynq®-7000 SoC device. The steps to create this boot image are immediately after the diagram.
The process to create a boot image using HSM mode for a Zynq®-7000 SoC device is similar to that of a boot image created using a standard flow with the following BIF file. These examples, where needed, use the OpenSSL program to generate hash files.
all:
{
[aeskeyfile]my_efuse.nky
[pskfile]primary.pem
[sskfile]secondary.pem
[bootloader,encryption=aes,authentication=rsa] zynq_fsbl_0.elf
[authentication=rsa]system.bit
}
Stage 0: Generate a hash for SPK
This stage generates the hash of the SPK key.
stage0:
{
[ppkfile] primary.pub
[spkfile] secondary.pub
}
The following is the Bootgen command.
bootgen -image stage0.bif –w -generate_hashes
Stage 1: Sign the SPK Hash
This stage creates the signatures by signing the SPK hash
xil_rsa_sign.exe -gensig -sk primary.pem -data secondary.pub.sha256 -out secondary.pub.sha256.sig
#Swap the bytes in SPK hash
objcopy -I binary -O binary --reverse-bytes=256 secondary.pub.sha256
#Generate SPK signature using OpenSSL
openssl rsautl -raw -sign -inkey primary.pem -in secondary.pub.sha256 > secondary.pub.sha256.sig
#Swap the bytes in SPK signature
objcopy -I binary -O binary --reverse-bytes=256 secondary.pub.sha256.sig
Stage 2: Encrypt using AES
This stage encrypts the partition. The stage2.bif is as follows.
stage2:
{
[aeskeyfile] my_efuse.nky
[bootloader, encryption=aes] zynq_fsbl_0.elf
}
bootgen -image stage2.bif -w -o fsbl_e.bin -encrypt efuse
The
output is the encrypted file fsbl_e.bin.Stage 3: Generate Partition Hashes
This stage generates the hashes of different partitions.
The BIF file is as follows:
stage3a:
{
[ppkfile] primary.pub
[spkfile] secondary.pub
[spksignature] secondary.pub.sha256.sig
[bootimage, authentication=rsa] fsbl_e.bin
}
The
Bootgen command is as
follows.bootgen -image stage3a.bif -w -generate_hashes
The output is the hash file zynq_fsbl_0.elf.0.sha256.
The stage3b BIF file is as follows:
stage3b:
{
[ppkfile] primary.pub
[spkfile] secondary.pub
[spksignature] secondary.pub.sha256.sig
[authentication=rsa] system.bit
}
The
Bootgen command is as
follows.bootgen -image stage3b.bif -w -generate_hashes
The
output is the hash file system.bit.0.sha256.Stage 4: Sign the Hashes
This stage creates signatures from the partition hash files created.
xil_rsa_sign.exe -gensig -sk secondary.pem -data zynq_fsbl_0.elf.0.sha256 -out zynq_fsbl_0.elf.0.sha256.sig
Or
by using the following OpenSSL
program.#Swap the bytes in FSBL hash
objcopy -I binary -O binary --reverse-bytes=256 zynq_fsbl_0.elf.0.sha256
#Generate FSBL signature using OpenSSL
openssl rsautl -raw -sign -inkey secondary.pem -in zynq_fsbl_0.elf.0.sha256 > zynq_fsbl_0.elf.0.sha256.sig
#Swap the bytes in FSBL signature
objcopy -I binary -O binary --reverse-bytes=256 zynq_fsbl_0.elf.0.sha256.sig
The output is the signature file zynq_fsbl_0.elf.0.sha256.sig.
xil_rsa_sign.exe -gensig -sk secondary.pem -data system.bit.0.sha256 -out system.bit.0.sha256.sig
Or
by using the following OpenSSL
program.#Swap the bytes in bitstream hash
objcopy -I binary -O binary --reverse-bytes=256 system.bit.0.sha256
#Generate bitstream signature using OpenSSL
openssl rsautl -raw -sign -inkey secondary.pem -in system.bit.0.sha256 > system.bit.0.sha256.sig
#Swap the bytes in bitstream signature
objcopy -I binary -O binary --reverse-bytes=256 system.bit.0.sha256.sig
The
output is the signature file system.bit.0.sha256.sig.Stage 5: Insert Partition Signatures
Insert partition signatures created above are changed into authentication certificates.
The stage5a.bif is as follows.
stage5a:
{
[ppkfile] primary.pub
[spkfile] secondary.pub
[spksignature] secondary.pub.sha256.sig
[bootimage, authentication=rsa, presign=zynq_fsbl_0.elf.0.sha256.sig] fsbl_e.bin
}
The
Bootgen command is as
follows.bootgen -image stage5a.bif -w -o fsbl_e_ac.bin -efuseppkbits efuseppkbits.txt -nonbooting
The
authenticated output files are fsbl_e_ac.bin and
efuseppkbits.txt.stage5b:
{
[ppkfile] primary.pub
[spkfile] secondary.pub
[spksignature] secondary.pub.sha256.sig
[authentication=rsa, presign=system.bit.0.sha256.sig] system.bit
}
The
Bootgen command is as
follows.bootgen -image stage5b.bif -o system_e_ac.bin –nonbooting
The
authenticated output file is system_e_ac.bin.Stage 6: Generate Header Table Hash
This stage generates the hash for the header tables.
The stage6.bif is as follows.stage6:
{
[bootimage] fsbl_e_ac.bin
[bootimage] system_e_ac.bin
}
The
Bootgen command is as
follows.bootgen -image stage6.bif -generate_hashes
The
output hash file is ImageHeaderTable.sha256.Stage 7: Generate Header Table Signature
This stage generates the header table signature.
xil_rsa_sign.exe -gensig -sk secondary.pem -data ImageHeaderTable.sha256 -out ImageHeaderTable.sha256.sig
Or
by using the following OpenSSL
program:#Swap the bytes in header table hash
objcopy -I binary -O binary --reverse-bytes=256 ImageHeaderTable.sha256
#Generate header table signature using OpenSSL
openssl rsautl -raw -sign -inkey secondary.pem -in ImageHeaderTable.sha256 > ImageHeaderTable.sha256.sig
#Swap the bytes in header table signature
objcopy -I binary -O binary --reverse-bytes=256 ImageHeaderTable.sha256.sig
The
output is the signature file ImageHeaderTable.sha256.sig.Stage 8: Combine Partitions, Insert Header Table Signature
The stage8.bif is as follows:
stage8:
{
[headersignature] ImageHeaderTable.sha256.sig
[bootimage] fsbl_e_ac.bin
[bootimage] system_e_ac.bin
}
The
Bootgen command is as
follows:bootgen -image stage8.bif -w -o final.bin
The
output is the boot image file final.bin.Creating a Zynq UltraScale+ MPSoC Device Boot Image using HSM Mode
The following figure provides a diagram of an HSM mode boot image.
To create a boot image using HSM mode for a Zynq® UltraScale+™ MPSoC device, it would be similar to a boot image created using a standard flow with the following BIF file. These examples, where needed, use the OpenSSL program to generate hash files.
all:
{
[fsbl_config] bh_auth_enable
[keysrc_encryption] bbram_red_key
[pskfile] primary0.pem
[sskfile] secondary0.pem
[
bootloader,
destination_cpu=a53-0,
encryption=aes,
aeskeyfile=aes0.nky,
authentication=rsa
] fsbl.elf
[
destination_device=pl,
encryption=aes,
aeskeyfile=aes1.nky,
authentication=rsa
] system.bit
[
destination_cpu=a53-0,
authentication=rsa,
exception_level=el-3,
trustzone=secure
] bl31.elf
[
destination_cpu=a53-0,
authentication=rsa,
exception_level=el-2
] u-boot.elf
}
Stage 0: Generate a hash for SPK
The following is the snippet from the BIF file.
stage0:
{
[ppkfile]primary.pub
[spkfile]secondary.pub
}
The following is the Bootgen command:
bootgen -arch zynqmp -image stage0.bif -generate_hashes -w on -log error
Stage 1: Sign the SPK Hash (encrypt the partitions)
The following is a code snippet using OpenSSL to generate the SPK hash:
openssl rsautl -raw -sign -inkey primary0.pem -in secondary.pub.sha384 > secondary.pub.sha384.sig
The output of this command is secondary.pub.sha384.sig.
Stage 2a: Encrypt the FSBL
Encrypt the FSBL using the following snippet in the BIF file.
Stage 2a:
{
[keysrc_encryption] bbram_red_key
[
bootloader,destination_cpu=a53-0,
encryption=aes,
aeskeyfile=aes0.nky
] fsbl.elf
}
The Bootgen command is:
bootgen -arch zynqmp -image stage2a.bif -o fsbl_e.bin -w on -log error
Stage 2b: Encrypt Bitstream
Generate the following BIF file entry:
stage2b:
{
[
encryption=aes,
aeskeyfile=aes1.nky,
destination_device=pl,
pid=1
] system.bit
}
The Bootgen command is:
bootgen -arch zynqmp -image stage2b.bif -o system_e.bin -w on -log error
Stage 3: Generate Boot Header Hash
Generate the boot header hash using the following BIF file:
stage3:
{
[fsbl_config] bh_auth_enable
[ppkfile] primary.pub
[spkfile] secondary.pub
[spksignature]secondary.pub.sha384.sig
[bootimage,authentication=rsa]fsbl_e.bin
}
The Bootgen command is:
bootgen -arch zynqmp -image stage3.bif -generate_hashes -w on -log error
Stage 4: Sign Boot Header Hash
Generate the boot header hash with the following OpenSSL command:
openssl rsautl -raw -sign -inkey secondary0.pem -in bootheader.sha384 > bootheader.sha384.sig
Stage 5: Get Partition Hashes
Get partition hashes using the following command in a BIF file:
stage5:
{
[ppkfile]primary.pub
[spkfile]secondary.pub
[spksignature]secondary.pub.sha384.sig
[bhsignature]bootheader.sha384.sig
[bootimage,authentication=rsa]fsbl_e.bin
[bootimage,authentication=rsa]system_e.bin
[
destination_cpu=a53-0,
authentication=rsa,
exception_level=el-3,
trustzone=secure
] bl31.elf
[
destination_cpu=a53-0,
authentication=rsa,
exception_level=el-2
] u-boot.elf
}
The Bootgen command is:
bootgen -arch zynqmp -image stage5.bif -generate_hashes -w on -log error
Multiple hashes will be generated for a bitstream partition. For more details, see Bitstream Authentication Using External Memory.
The Boot Header hash is also generated from in this stage5; which is
different from the one generated in stage3, because the parameter bh_auth_enable
is not used in stage5. This can be
added in stage5 if needed, but does not have a significant impact because the Boot
Header hash generated using stage3 is signed in stage4 and this signature will only
be used in the HSM mode flow.
Stage 6: Sign Partition Hashes
Create the following files using OpenSSL:
openssl rsautl -raw -sign -inkey secondary0.pem -in fsbl.elf.0.sha384 > fsbl.elf.0.sha384.sig
openssl rsautl -raw -sign -inkey secondary0.pem -in system.bit.0.sha384 > system.bit.0.sha384.sig
openssl rsautl -raw -sign -inkey secondary0.pem -in system.bit.1.sha384 > system.bit.1.sha384.sig
openssl rsautl -raw -sign -inkey secondary0.pem -in system.bit.2.sha384 > system.bit.2.sha384.sig
openssl rsautl -raw -sign -inkey secondary0.pem -in system.bit.3.sha384 > system.bit.3.sha384.sig
openssl rsautl -raw -sign -inkey secondary0.pem -in u-boot.elf.0.sha384 > u-boot.elf.0.sha384.sig
openssl rsautl -raw -sign -inkey secondary0.pem -in bl31.elf.0.sha384 > bl31.elf.0.sha384.sig
openssl rsautl -raw -sign -inkey secondary0.pem -in bl31.elf.1.sha384 > bl31.elf.1.sha384.sig
Stage 7: Insert Partition Signatures into Authentication Certificate
Stage 7a: Insert the FSBL signature by adding this code to a BIF file:
Stage7a:
{
[fsbl_config] bh_auth_enable
[ppkfile] primary.pub
[spkfile] secondary.pub
[spksignature]secondary.pub.sha384.sig
[bhsignature]bootheader.sha384.sig
[bootimage,authentication=rsa,presign=fsbl.elf.0.sha384.sig]fsbl_e.bin
}
The
Bootgen command is as
follows:bootgen -arch zynqmp -image stage7a.bif -o fsbl_e_ac.bin -efuseppkbits
efuseppkbits.txt -nonbooting -w on -log error
Stage 7b: Insert the bitstream signature by adding the following to the BIF file:
stage7b:
{
[ppkfile]primary.pub
[spkfile]secondary.pub
[spksignature]secondary.pub.sha384.sig
[bhsignature]bootheader.sha384.sig
[
bootimage,
authentication=rsa,
presign=system.bit.0.sha384.sig
] system_e.bin
}
The Bootgen command is:
bootgen -arch zynqmp -image stage7b.bif -o system_e_ac.bin -nonbooting -w on -log error
Stage 7c: Insert the U-Boot signature by adding the following to the BIF file:
stage7c:
{
[ppkfile] primary.pub
[spkfile] secondary.pub
[spksignature]secondary.pub.sha384.sig
[bhsignature]bootheader.sha384.sig
[
destination_cpu=a53-0,
authentication=rsa,
exception_level=el-2,
presign=u-boot.elf.0.sha384.sig
] u-boot.elf
}
The Bootgen command is:
bootgen -arch zynqmp -image stage7c.bif -o u-boot_ac.bin -nonbooting -w on -log error
Stage 7d: Insert the ATF signature by entering the following into a BIF file:
stage7d:
{
[ppkfile] primary.pub
[spkfile] secondary.pub
[spksignature]secondary.pub.sha384.sig
[bhsignature]bootheader.sha384.sig
[
destination_cpu=a53-0,
authentication=rsa,
exception_level=el-3,
trustzone=secure,
presign=bl31.elf.0.sha384.sig
] bl31.elf
}
The Bootgen command is:
bootgen -arch zynqmp -image stage7d.bif -o bl31_ac.bin -nonbooting -w on -log error
Stage 8: Combine Partitions, Get Header Table Hash
Enter the following in a BIF file:
stage8:
{
[bootimage]fsbl_e_ac.bin
[bootimage]system_e_ac.bin
[bootimage]bl31_ac.bin
[bootimage]u-boot_ac.bin
}
The Bootgen command is:
bootgen -arch zynqmp -image stage8.bif -generate_hashes -o stage8.bin -w on -log error
Stage 9: Sign Header Table Hash
Generate the following files using OpenSSL:
openssl rsautl -raw -sign -inkey secondary0.pem -in ImageHeaderTable.sha384 > ImageHeaderTable.sha384.sig
Stage 10: Combine Partitions, Insert Header Table Signature
Enter the following in a BIF file:
stage10:
{
[headersignature]ImageHeaderTable.sha384.sig
[bootimage]fsbl_e_ac.bin
[bootimage]system_e_ac.bin
[bootimage]bl31_ac.bin
[bootimage]u-boot_ac.bin
}
The Bootgen command is:
bootgen -arch zynqmp -image stage10.bif -o final.bin -w on -log error
Creating a Versal Device Boot Image using HSM
The following figure provides a diagram of an HSM mode boot image for a Versal device.
Generating the PDI
Generate the PDI using the standard BIF.
command : bootgen -arch versal -image all.bif -w on -o final_ref.bin -log error
all:
{
id_code = 0x04ca8093
extended_id_code = 0x01
id = 0x2
boot_config {bh_auth_enable}
metaheader
{
authentication = rsa,
pskfile = rsa-keys/PSK2.pem,
sskfile = rsa-keys/SSK2.pem
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = enc_keys/efuse_red_metaheader_key.nky,
dpacm_enable
}
image
{
name = pmc_subsys, id = 0x1c000001
partition
{
id = 0x01, type = bootloader,
authentication = rsa,
pskfile = rsa-keys/PSK1.pem,
sskfile = rsa-keys/SSK1.pem,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/bbram_red_key.nky,
dpacm_enable,
file = images/gen_files/executable.elf
}
partition
{
id = 0x09, type = pmcdata, load = 0xf2000000,
aeskeyfile = gen_keys/pmcdata.nky,
file = images/gen_files/topology_xcvc1902.v1.cdo,
file = images/gen_files/pmc_data.cdo
}
}
image
{
name = lpd, id = 0x4210002
partition
{
id = 0x0C, type = cdo,
authentication = rsa,
pskfile = rsa-keys/PSK3.pem,
sskfile = rsa-keys/SSK3.pem,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = gen_keys/key1.nky,
dpacm_enable,
file = images/gen_files/lpd_data.cdo
}
partition
{
id = 0x0B, core = psm,
authentication = rsa,
pskfile = rsa-keys/PSK1.pem,
sskfile = rsa-keys/SSK1.pem,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = gen_keys/key2.nky,
dpacm_enable,
blocks = 8192(20);4096(*),
file = images/static_files/psm_fw.elf
}
}
image
{
name = fpd, id = 0x420c003
partition
{
id = 0x08, type = cdo,
authentication = rsa,
pskfile = rsa-keys/PSK3.pem,
sskfile = rsa-keys/SSK3.pem,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = gen_keys/key5.nky,
dpacm_enable,
file = images/gen_files/fpd_data.cdo
}
}
image
{
name = ss, id = 0x1c000033
partition
{
id = 0x0D, type = cdo,
authentication = rsa,
pskfile = rsa-keys/PSK2.pem,
sskfile = rsa-keys/SSK2.pem,
encryption = aes,
keysrc = bbram_red_key,
aeskeyfile = gen_keys/key6.nky,
dpacm_enable,
file = images/gen_files/subsystem.cdo
}
}
}
HSM Mode Steps
Stage 0: Generate SPK Hash
Generate hash for SSK1:command : bootgen -arch versal -image stage0-SSK1.bif -generate_hashes -w on -log error
stage0-SSK1:
{
spkfile = rsa-keys/SSK1.pub
}
Generate
hash for SSK2:
command : bootgen -arch versal -image stage0-SSK2.bif -generate_hashes -w on -log error
stage0-SSK2:
{
spkfile = rsa-keys/SSK2.pub
}
Generate
hash for SSK3:
command : bootgen -arch versal -image stage0-SSK3.bif -generate_hashes -w on -log error
stage0-SSK3:
{
spkfile = rsa-keys/SSK3.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: Encrypt Individual Partitions
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,
encryption=aes,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/bbram_red_key.nky,
dpacm_enable,
file = images/gen_files/executable.elf
}
partition
{
id = 0x09, type = pmcdata,
load = 0xf2000000,
aeskeyfile = encr_keys/pmcdata.nky,
file = images/gen_files/topology_xcvc1902.v1.cdo,
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,
encryption=aes,
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,
encryption = aes,
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,
encryption=aes,
keysrc = bbram_red_key,
aeskeyfile = encr_keys/key5.nky,
dpacm_enable,
file = images/gen_files/fpd_data.cdo
}
}
}
Stage 3: Generate Boot Header Hash
command : bootgen -arch versal -image stage3.bif -generate_hashes -w on -log error
stage3:
{
image_config {bh_auth_enable}
image
{
name = pmc_subsys, id = 0x1c000001
{
type = bootimage,
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,
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,
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,
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,
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,
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
image_config {bh_auth_enable}
image
{
name = pmc_subsys, id = 0x1c000001
{
type = bootimage,
authentication=rsa,
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,
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
{
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.bin -w on -log error
stage7c:
{
image
{
id = 0x1c000000, name = fpd
{ type = bootimage,
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,
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
stage8:
{
id_code = 0x04ca8093
extended_id_code = 0x01
id = 0x2
metaheader
{
authentication = rsa,
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,
revoke_id = 0x00000002
}
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
command : bootgen -arch versal -image stage8b.bif -generate_hashes -w on -log error
stage8b:
{
headersignature = imageheadertable.sha384.sig
id_code = 0x04ca8093
extended_id_code = 0x01
id = 0x2
metaheader
{
authentication = rsa,
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:command : bootgen -arch versal -image stage10.bif -o final.bin -w on -log error
stage10:
{
headersignature = imageheadertable.sha384.sig
id_code = 0x04ca8093
extended_id_code = 0x01
id = 0x2
metaheader
{
authentication = rsa,
ppkfile = rsa-keys/PSK2.pub,
spkfile = rsa-keys/SSK2.pub
spksignature = SSK2.pub.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}
}
}