RT1064: Signed & Encrypted bootloader & application considerations

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

RT1064: Signed & Encrypted bootloader & application considerations

Jump to solution
4,549 Views
damonb
Contributor III

I have some questions about securing bootloader & application code on a RT1064 using signing and BEE encryption which I hope you can help with.
From a prototype running a second bootloader from FlexSPI Flash and then application code, I need a path to tens of products requiring signed, encrypted images, onto potentially thousands of products. So I'm interested in what descisions need to be made now, regarding choices on which keys and configurations to use, which will allow a smooth scale-up of the project.

Currently, the prototype runs a second bootloader, which runs the application. I have the MCUXpresso Secure Provisioning Tool, which I can use to encrypt an image and generate a key. However, I'm not clear here on the "Boot Type" choice: There are two XIP options given,
"BEE OTPMK Key", and
"(BEE User Keys) Authenicated"
What considerations would affect whether to choose one over the other here? The Keys Management tab allows the generation of (what I assume is) the master key, with a given passphrase and serial number. I assume the passphrase and serial number need to be kept confidential and will be common to all products with images encrypted with this key. What effect does the serial number value have?
If the "(BEE User Keys) Authenicated" option is chosen, another key has to be specified, for which there are several options for configuration, for example "User Key Data". Is there any advantage on choosing this option as I assume this will require this data to be stored confidentially also? I there a scenario where this key is needed later?

I watched the webinar on the NXP website showing some demos of signed & encrypted applications. But it didn't touch on how to have a signed & encrypted second bootloader then run a signed & encrypted application. In this scenario, is the application image generated in the same way using the Secure Provisioning Tool and how does the bootloader code verify and run this? Is there an application note which has examples of this?

Looking further ahead to production units where JTAG is not available, then what mechanisms can be employed to program the key data in the eFuses? Is this something that NXP would do before shipping an order of RT1064s, or would this be done programatically the first time the bootloader is run? Are there examples available for this?

Thanks in advance for any comments.

1 Solution
4,074 Views
damonb
Contributor III

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:

  1. Build the second bootloader image in full in MCUXpresso, Leave XIP_BOOT_HEADER_ENABLE set to 1.

  2. Add a post-build step in MCUXpresso to produce a SREC file output

  3. Use the "SRecord" utility to extract the FCB section (0x0 - 0x1FF) and save it ("fcb.srec")

  4. Use the "SRecord" utllity to remove the FCB, IVT & BD sections from the bootloader image (exclude 0x0 - 0x1FFF)

  5. Use the elftosb tool or Secure Provisioning Tool (SPT) to generate the signed image ("bootloader.bin")

  6. Use the "SRecord" utility to merge the saved FCB section and the output from the tool ("fcb.srec" + "bootloader.bin").

  7. 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:

  1. Build the application with XIP_BOOT_HEADER_ENABLE set to 0
  2. Encrypt the image with openssl
  3. 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.

View solution in original post

23 Replies
3,652 Views
jeremyzhou
NXP Employee
NXP Employee

Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
1) What considerations would affect whether to choose one over the other here?
-- The key difference between the BEE OTPMK Key and (BEE User Keys) Authenicated option is the key selection for BEE, the OTPMK Key is unique for an individual chip, it means each chip could use a unique secret key to encrypt the SW image, so each image can only boot on the chip with the right secret key, “image copy” can be prevented.
Of course, you can set a common key for all chips, then all chips can run a 'common' image.
2) In this scenario, is the application image generated in the same way using the Secure Provisioning Tool and how does the bootloader code verify and run this? Is there an application note which has examples of this?
-- Please refer to the application note.
3) Is this something that NXP would do before shipping an order of RT1064s, or would this be done programmatically the first time the bootloader is run? Are there examples available for this?
-- I think NXP can provide the burn eFuse service for the big customer, customers can use the tool to burn the eFuse.
Have a great day.
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
3,642 Views
damonb
Contributor III

Thank-you for your reply. I tried some experiments: I built the "blinky" demo application from the SDK, but with XIP_BOOT_HEADER_ENABLE set to 0 and used the Secure Provisioning Tool, with Boot Mode set to "Authenticated HAB ", to create some keys and create a signed image of "blinky". I've written this to a RT1064 eval board, including burning the fuses and it runs fine. I left the "Enable Security" check-box unchecked, so I assume this leaves the system "open" rather than "closed".

I wanted to verify whether indeed the HAB authentication was passing or not - I assume the only was to know this is to read the HAB events. I downloaded the 'cst' tool (Linux) and saw that it contained an application called hab_log_parser. I attached the debugger to the running "blinky" application, paused it and exported the memory from 0x20201000 to 0x20201b8. This is the output from the tool:

damonbeales_0-1633968491629.png

So I assume this means it did not work. If it had worked, what would I see - an empty table, or an entry indicating "success" ?

What I want to do next is use this process for a second bootloader, which will then configure BEE on-the-fly decryption and run the main application. But I need to get this working correctly first. Any ideas what I may have done wrong?

I had a quick look at the MCUBootUtility, but this doesn't look like an option for me. Is this an officially supported NXP tool? On the NXP website, the configuration tool specified is the Secure Provisioning Tool, so really this has to be used, which should be fine.

0 Kudos
3,624 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
1) Secure Provisioning Tool provides the log for us to check the manipulation is successful or not, so it can help you to check to enable the authentic boot or not.
2) What I want to do next is use this process for a second bootloader, which will then configure BEE on-the-fly decryption and run the main application. But I need to get this working correctly first. Any ideas what I may have done wrong?
-- Please refer to the application note.
3) Is this an officially supported NXP tool?
-- No, it's managed by an AE coworker, and the Secure Provisioning Tool is released based on the tool actually, the MCUBootUtility is one of the favorite tools for customers during the developing phase.
Have a great day.
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

 

0 Kudos
3,608 Views
damonb
Contributor III

Thank-you.

I repeated the generation of the signed binary and this time it worked ok. I was able to programmatically call the HAB API and confirm that there were no HAB events generated, so this seems to be working.

For the BEE on-the-fly decryption, do you recommend using "XIP Encrypted (BEE User Keys) Unsigned" or "XIP Encrypted (BEE User Keys) Authenticated" for the main application, if the second bootloader has already been signed?

Looking at the "bee" example in the SDK, I see BEE_USE_USER_KEY is not defined by default. So in this case, what is the key that is used for the on-the-fly decryption, I'm not clear on this. It's not clear if the comment in the code refers to the feature being defined or not defined:

damonbeales_1-1634072614234.png

If I define BEE_USE_USER_KEY, then is the decryption done using the key in the SW-GP2 eFuse, which must match the "User Key Data" entered in the Secure Provisioning Tool here:

damonbeales_0-1634070874880.png

Is that right?

I also have a question about key generation in the Secure Provisioning Tool, under the Key Management tab: I notice there are options for "Serial number" and "Duration". Do these settings have any effect?

damonbeales_0-1634059369217.png

Thank-you in advance for your comments.

0 Kudos
3,593 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Sorry for reply late.
1) For the BEE on-the-fly decryption, do you recommend using "XIP Encrypted (BEE User Keys) Unsigned" or "XIP Encrypted (BEE User Keys) Authenticated" for the main application, if the second bootloader has already been signed?
-- You should select XIP Encrypted (BEE User Keys) Authenticated option.
2) Yes, the User Key Data will be burned to SW-GP2 after clicking write image.
3) Do these settings have any effect?
-- In general, you can treat it as the seed for generating the root CA and Private Key.

Have a great day.
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
3,561 Views
damonb
Contributor III

Thank-you.

In my setup, I have a second bootloader and a main application. Both are built separately. I'm using the Secure Provisioning Tool (SPT) to sign the bootloader image and flash it to target. Then separately, I use the SPT to sign & encrypt the main application. But it seems the SPT is assuming the main application is the only application. I can see from the log that even though the main application start address is 0x70020000, it is erasing the flash from 0x70000000 (start of Flash memory) with this command:

blhost -t 50000 -u 0x15A2,0x0073 -j -- flash-erase-region 0x70000000 1089536 9

It is then also writing the FlexSPI NOR config block and another configuration block, which I don't think are required, as the second bootloader has already been flashed:

### Use tag 0xF000000F to notify FlashLoader to program FlexSPI NOR config block to the start of device ###
blhost -t 5000 -u 0x15A2,0x0073 -j -- fill-memory 0x3000 4 0xF000000F word
### Program configuration block ###
blhost -t 5000 -u 0x15A2,0x0073 -j -- configure-memory 9 0x3000

Please confirm the purpose of these two statements.

How can I tell the SPT that this image is going to be called from the second bootloader, so that the image is generated correctly? It is not the boot image, the second bootloader is the boot image. I can't find an option for this.

 

0 Kudos
3,555 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
1) How can I tell the SPT that this image is going to be called from the second bootloader, so that the image is generated correctly? It is not the boot image, the second bootloader is the boot image. I can't find an option for this.
-- Until now, the Secure Provisioning Tool (SPT) hasn't supported the feature, it needs the developers to program the main application image via manipulating the Blhost's command manually.
Hope it helps.
Have a great day.
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
3,532 Views
damonb
Contributor III

Thank-you for your comments.

I need to obtain the following two documents:

Security Reference Manual for the i.MX RT1064 Processor

How to use HAB secure boot in i.MX RT10xx

but the NXP site requires approval. How do I go about this, as I don't know a suitable NXP contact?

Thanks

 

0 Kudos
3,526 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
Unfortunately, I can share these files with you directly, I'd like to suggest you contact NXP's distributors to apply for the files.
Otherwise, you can search them via Google, as some guys may upload them.
Hope it helps.
Have a great day.
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
3,508 Views
damonb
Contributor III

Thank-you, I've requested those documents from NXP.

For the Secure Provisioning Tool, I have a couple of questions on the CLI options in this example CLI command:

securep -w /workspaces/mcuxprovi4 --device MIMXRT1060 --boot-device ISSI_IS25LPxxxA_IS25WPxxxA --boot-type xip_encrypted_bee_user_keys_authenticated build --source-image /images/evkmimxrt1060_iled_blinky_xip.s19 --bee-user-keys-config bee_user_keys_config.json --img-cert crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem

--keys-cfg hab4_key_gen.json

What is the format of the hab4_key_gen.json file?

--bee-user-keys-config bee_user_keys_config.json

What is the format of the bee_user_keys_config.json?

I couldn't find any information on this.

As I mentioned previously, I wish to generate a signed, encrypted application image, which is called from a second bootloader (i.e. it's non-bootable). You mentioned that the SPT doesn't support this configuration. Is the issue with the SPT just with the uploading sequence only (blhost commands)? Is generating the build in SPT ok, or do I need to do it a different way?

 

0 Kudos
3,492 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
1) What is the format of the bee_user_keys_config.json?
-- I don't know actually, I guess the JSON files are deleted after the programming successfully by the SPT tool automatically.
2) Is the issue with the SPT just with the uploading sequence only (blhost commands)? Is generating the build in SPT ok, or do I need to do it a different way?
-- I'm not very clear with this question, you'd better explain or clarify it again.
Have a great day.
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

 

 

 

0 Kudos
3,487 Views
damonb
Contributor III

Sorry for not being clear.

I'm using a second bootloader in my target. This bootloader image will be signed. I need to flash this image to the target using JTAG (using a Segger J-Link). The option of using the Flashloader is not available to me. It seems all the NXP tools assume that the Flashloader can be uploaded and run, but that is not the case for me. I do not have USB or serial available.

So to build the image for my bootloader, I am using the Secure Provisioning Tool to sign the image built by MCUXpresso. But this doesn't seem to produce a complete binary image I can flash using JTAG, it is missing the first 0x1000 bytes, which contains the IVT, etc.

I've read many of NXPs application notes, but they all assume uploading using the NXP tools and the Flashloader.

How can I build a complete binary that is signed. (And then for my application, one that is signed and encrypted?)

 

0 Kudos
3,472 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your clarification.
1) How can I build a complete binary that is signed. (And then for my application, one that is signed and encrypted?)
-- According to your description, it seems like that you want to use the IDE to program signed or encrypted images to MCU via debug tool.
If my understanding is right. I'm afraid that your purpose is impossible to make it, as I know, all IDEs haven't supported the feature now and it needs to use the offline tools to implement the secure boot feature.
Hope this is clear.
Have a great day.
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
3,463 Views
damonb
Contributor III

Sorry, I was not clear.

I compile an application in MCUXpresso, with XIP_BOOT_HEADER_ENABLE = 0.

I have a workspace created in Secure Provisioning Tool with some keys generated. I have "Authenicated (HAB)" boot type selected.

I load the .afx image file from MCUXpresso into Secure Provisioning Tool and click Build Image. This creates two binaries in bootable_images, one called _nopadding.bin.

To write this to my target, I can't use NXP tools like blhost, as I don't have access to USB or serial. I need to use JTAG via Segger J-Link.

How can I create a complete binary image which I can use with J-Link? I don't think _nopadding.bin is suitable, because it doesn't contain the correct header data. Is that correct?

 

 

0 Kudos
3,434 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
1) How can I create a complete binary image which I can use with J-Link? I don't think _nopadding.bin is suitable because it doesn't contain the correct header data. Is that correct?
-- Firstly, the Jlink can program the hex or bin files to an external flash,
Have a great day, next, it's too hard to generate a whole image file (bin or hex) for authentic boot, as I know, there's no such a tool to make it.
In my opinion, I'd like to suggest you modify your custom board to support the Serial Downloader mode.
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
3,422 Views
damonb
Contributor III

Thank-you for your answer, although it is disappointing, I would think it is quite a common scenario to want to flash a complete signed image via JTAG.

I came across NXP AN12604 "Implement second bootloader on i.MXRT10xx series" which is a very useful document. There is a software package with it, AN12604SW, which I downloaded. This contains a Windows command-line tool called "image_generate.exe". AN12604 says how to use this tool to generate an encrypted image, but I don't see any reference to this tool in any other NXP document. Is there a document about this tool? Is it available on Linux? If not, can the same output be generated from another NXP tool, or should openssl be used, for example?

0 Kudos
3,418 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
1) Is there a document about this tool? Is it available on Linux? If not, can the same output be generated from another NXP tool, or should OpenSSL be used, for example?
-- No, there's no such a document now, to be honest, I'm not sure whether the tool is available on Linux, I once used it on Win10.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
3,371 Views
damonb
Contributor III

Thank-you for your answer.

> I'm not sure whether the tool is available on Linux, I once used it on Win10.

Well, the tool came from NXP, so can you find out? I have no way of finding out, I'm not NXP, but you are!

What would be the equivalent openssl command to produce the same output?

 

0 Kudos
3,339 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
1) After checking, it can't run to call the below command in the Linux OS, however, I attached a new tool: image_enc which is equal to the image_generate, it can support the Linux and you can give it a try.

image_generate.exe ifile=iled_blinky.bin ofile=iled_blinky_encrypt.bin base_addr=0x60010000
region_key=00112233445566778899aabbccddeeff region_arg=1,[0x60010000,0xF000,0]


Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
3,306 Views
damonb
Contributor III

Thank-you for the image_enc tool. Unfortunately, it doesn't seem to work correctly and doesn't give the same output as image_generate tool, given the same input parameters.

Looking at the output binary with a hex editor, I can see that image_generate correctly generates the encryption parameters header, with the first 4 bytes as 0xa5 0xa5 0x5c 0xea, which matches the tag field (as described in AN12604). I can then see the encrypted image starting at offset 0x1000.

Using image_enc with the same input parameters, the output binary is unchanged at the start - there is no tag field, it starts with the original image in plain text. There seems to be a block of data inserted at offset 0x0800 and then the rest of the image seems to be encrypted from offset 0x1000.

Here is the start of the binary from image_generate:

damonbeales_0-1635853160373.png

Here is the start of the binary from image_enc:

damonbeales_1-1635853225746.png

My second bootloader image is not encrypted. This configures BEE Region 1 and calls the application.

The application image is built to link at 0x60020000 in Flash. I'm using this command:

image_enc ifile=Application.bin ofile=Application_encrypt.bin base_addr=0x60020000 region1_key=00112233445566778899aabbccddeeff region1_arg=1,[0x60020000,0x100000,0]

Also note that the output from image_generate is exactly 0x1000 bytes larger.

I've tried the Linux and Windows versions of image_enc and the result is the same.

Can you check the tool?

 

0 Kudos