This has been a long thread with a number of questions.
I have some comments for NXP:
For the use-case of using a signed second bootloader, which then executes an encrypted main application: I would think this is common, but seems really unsupported by NXP. The solution given by NXP in AN12604 is good - or should be, except that it is not supported by NXP tools. The image_generate.exe tool attached in AN12604SW is Windows-only and there is no documentation showing what it does - really, this cannot be used. And the image_enc tool, which is cross-platform, does something different, but there is no documentation for this tool, and NXP provide no help for how a second bootloader might call an application image generated from image_enc.
Basically, all the NXP tools assume the user wants to create one boot-able image, to be uploaded using their RAM Flashloader. This is fine if there is no second bootloader and if the serial/USB interface is available. Again, I would think it is quite common that the user wants to create a binary file to be flashed using JTAG. This method seems unsupported by NXP.
For your reference, I have managed to create a signed binary file for a second bootloader image, to be flashed via JTAG, using these steps:
Build the second bootloader image in full in MCUXpresso, Leave XIP_BOOT_HEADER_ENABLE set to 1.
Add a post-build step in MCUXpresso to produce a SREC file output
Use the "SRecord" utility to extract the FCB section (0x0 - 0x1FF) and save it ("fcb.srec")
Use the "SRecord" utllity to remove the FCB, IVT & BD sections from the bootloader image (exclude 0x0 - 0x1FFF)
Use the elftosb tool or Secure Provisioning Tool (SPT) to generate the signed image ("bootloader.bin")
Use the "SRecord" utility to merge the saved FCB section and the output from the tool ("fcb.srec" + "bootloader.bin").
- Flash the resulting SREC image using JTAG (e.g. Segger J-Link)
This works fine.
I also created an encrypted application image, which can be called from this bootloader. The NXP tools are not used here, rather openssl:
- Build the application with XIP_BOOT_HEADER_ENABLE set to 0
- Encrypt the image with openssl
- Flash using JTAG
openssl enc -e -aes-128-ctr -nopad -nosalt -K 11223344556677889900aabbccddeeff -iv 1234567890ABCDEF0102030406002000 -in application.bin -out application_enc.bin
The Initial Vector (iv) used is 1234567890ABCDEF01020304 with (<start-address> >> 4) appended. So in this case, the start address is 0x60020000.
In the bootloader, setup BEE to decrypt over the memory starting at 0x60020000, using the following code:
#include "fsl_bee.h"
#define FLEXSPI_START_ADDR 0x60020000U
#define REG0_START_ADDR_GPR GPR18
#define REG0_END_ADDR_GPR GPR19
#define REG0_DECRYPT_EN_GPR GPR11
#define REG0_DECRYPT_EN IOMUXC_GPR_GPR11_BEE_DE_RX_EN(1)
#define AES_KEY_LEN 16
#define AES_NONCE_LEN 16
#define BEE_REGION_SIZE 0x10000U
static const uint8_t aesKey[] = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x00, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
static const uint8_t aesNonce[] = {0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12};
bee_region_config_t beeConfig;
IOMUXC_GPR_Type *iomuxc = IOMUXC_GPR;
BEE_Init(BEE);
BEE_GetDefaultConfig(&beeConfig);
beeConfig.region0Mode = kBEE_AesCtrMode;
beeConfig.region1Bot = 0U;
beeConfig.region1Top = 0U;
iomuxc->REG0_START_ADDR_GPR = FLEXSPI_START_ADDR;
iomuxc->REG0_END_ADDR_GPR = FLEXSPI_START_ADDR + BEE_REGION_SIZE;
iomuxc->REG0_DECRYPT_EN_GPR = REG0_DECRYPT_EN;
BEE_SetConfig(BEE, &beeConfig);
BEE_SetRegionKey(BEE, kBEE_Region0, aesKey, AES_KEY_LEN);
BEE_SetRegionNonce(BEE, kBEE_Region0, aesNonce, AES_NONCE_LEN);
BEE_Enable(BEE);
BEE_Deinit(BEE);
This works fine.
So please feedback to NXP internally that the tools and methods recommended by NXP are too focused on creating one bootable image, there seems to be too many ways of doing the same thing with different tools, but not enough ways of doing what you want. There is also missing documentation and application notes which provide only part of a solution.