Data preservation and leakage in secure boot mode

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

Data preservation and leakage in secure boot mode

Data preservation and leakage in secure boot mode

Abstract

Today I'd like to discuss a scenario that I will encounter in practical application.
In the design phase, the Serial Nor flash is usually used as a code storage device for RT series MCUs, such as QSPI, HyperFlash, etc, as these devices all support XIP features. The flash usually is not only occupied by the code but also used to store data, such as device parameters, and log information, and even used as a file system. So we need to evaluate Flash's size.
Is there any constraint to the manipulation of data space in the secure boot mode? And how to keep the data confidential? We'll talk about it below and let's get started.

Secure boot mode

HAB boot

The bootable image is plaintext, and it may be changed after the writing operation of the FlexSPI module. If the digest algorithm obtains the different values will lead to the verification process fails, as the writing operation destroys the integrity of the data, regarding confidentiality, data is stored in plaintext in Serial Nor flash under HAB boot.

 
jeremyzhou_1-1664157588518.png

Fig1 Signature and verification process

Encrypted XIP boot mode

After enabling the Encrypted XIP boot mode, what is the impact on FlexSPI's read and write data operations? The first point is that the read data will be treated as encrypted data and decrypted by the BEE or OTFAD module. However, if a write operation is performed, the BEE or OTFAD module will be bypassed, in another word, the data will be written directly to the Serial Nor flash. in a short, it is not affected by the Encrypted XIP boot mode.

1) Read operation

As shown in Fig 2, the encrypted code and data stored in Serial Nor flash need to be decrypted before they are sent to the CPU for execution. This is also the implementation mechanism of the Encrypted XIP boot mode. To enable the encrypted XIP boot mode, it needs to burn the keys to eFuse, after that, eFuse is impossible to restore, so the test cost seems a bit high, so I recommend you refer to the source code of the 《How to Enable the On-the-fly Decryption》application note to dynamically configure the key of the BEE module and read the encrypted array by DCP from Flash, then compare to plaintext array to verify BEE module participle the decryption flow.

jeremyzhou_2-1664157664830.jpeg

Fig 2

2) Write operation

Modify the source code of the above application note, define s_nor_program_buffer [256], then set the values through the following code, and burn them to the 20th sector, the offset address is 0x14000.

for (i = 0; i < 0xFFU; i++)
     {
         s_nor_program_buffer[i] = i;
     }

 status =
  flexspi_nor_flash_page_program(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE, (void *)s_nor_program_buffer);
 if (status != kStatus_Success)
 {
  PRINTF("Page program failure !\r\n");
  return -1;
 }

    DCACHE_InvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE, FLASH_PAGE_SIZE);

    memcpy(s_nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE),
           sizeof(s_nor_read_buffer));

    for(uint32_t i = 0; i < 256; i++)
    {
     PRINTF("The %d data in the second region is 0x%x\r\n", i, s_nor_read_buffer[i]);
    }

After the programming finishes, connect to Jlink and use J-flash to check whether the burned array is correct. The results prove that the write operation will bypass the BEE or OTFAD module and write the data directly to the Serial Nor flash, which is consistent with Fig 2.

jeremyzhou_3-1664157761870.png

Fig3

Sensitive data preservation

As mentioned at the beginning, in the real project, we may need to use Flash to store data, such as device parameters, log information, or even as a file system, and the saved data is usually a bit sensitive and should prevent being easily obtained by others. For example, in SLN-VIZNAS-IoT, there is a dedicated area for storing facial feature data.

jeremyzhou_4-1664157818453.png

Fig 4

Although the purely facial feature data is only meaningful for specific recognition algorithms, in another word, even if a third-party application obtains the original data, it is useless for hackers.
In the development of real face recognization projects, it is usually to declare other data items associated with facial feature data, such as name, age, preferences, etc, as shown below:

typedef union
{
    struct
    {
        /*put char/unsigned char together to avoid padding*/
        unsigned char magic;
        char name[FEATUREDATA_NAME_MAX_LEN];
        int index;
        // this id identify a feature uniquely,we should use it as a handler for feature add/del/update/rename
        uint16_t id;
        uint16_t pad;
        
        // Add a new component
        uint16_t coffee_taste;     

        /*put feature in the last so, we can take it as dynamic, size limitation:
         * (FEATUREDATA_FLASH_PAGE_SIZE * 2 - 1 - FEATUREDATA_NAME_MAX_LEN - 4 - 4 -2)/4*/
        float feature[0];
    };
    unsigned char raw[FEATUREDATA_FLASH_PAGE_SIZE * 2];
} FeatureItem; // 1kB

After enabling the Encrypted XIP boot mode, the above write operation test has proved that FlexSPI's write operation will program the data into Serial Nor flash directly, but during the reading process, the data will be decrypted by BEE or OTFAD, so we'd better use DCP or other modules to encrypt the data prior to writing, otherwise, the read operation will get the values that the plaintext goes through the decryption calculation.

The risk of leakage

Assume XIP encrypted boot is enabled, and whether it's okay to send the encrypted bootable image sent to the OEM for mass production. Moreover, is it able to allow the customers to access the encrypted bootable image without worrying about application image leakage?
In order to verify the above guesses, I do the following testing on MIMXRT1060-EVK.

  • Select the XIP encrypted mode in the MCUXpresso Secure Provisioning tool to generate and burn the bootable image of the Blink LED;
jeremyzhou_5-1664157965514.png

Fig5

  • Observe the burned image through NXP-MCUBootUtility, you can find that the ciphertext image is very messy when compared to the plaintext image on the right border, so it seems like the NXP-MCUBootUtility can't obtain the plaintext image;
jeremyzhou_6-1664158019026.png

Fig 6

  • Let's observe the ciphertext image in another way, read them through the pyocd command, as shown below;
jeremyzhou_7-1664158077358.png

Fig 7

Open then 9_21_readback.Bin and compare it with the plain text image on the right border, they are the same actually, in other words, the plaintext image was leaked.

jeremyzhou_8-1664158155668.png

Fig 8

Explanation

As the above Fig 2 shows, the encrypted code and data stored in Serial Nor flash need to be decrypted before they are sent to the CPU for execution.
When Jlink connects to the target MCU, it will load the corresponding flash driver algorithm to run in the FlexRAM. If the flash driver algorithm detects the boot type of the MCU just like the following code, then configures the BEE or OTFAD module according to the detecting result, after that, when reading the ciphertext in the Nor Flash, the data will be automatically decrypted.

status = SLN_AUTH_check_context(SLN_CRYPTO_CTX_1);

    configPRINTF(("Context check status %d\r\n", status));
    // DEBUG_LOG_DELAY_MS(1000);  // Optional delay, enable for debugging to ensure log is printed before a crash

    if (SLN_AUTH_NO_CONTEXT == status)
    {
        configPRINTF(("Ensuring context...\r\n"));
        // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a crash

        // Load crypto contexts and make sure they are valid (our own context should be good to get to this point!)
        status = bl_nor_encrypt_ensure_context();

        if (kStatus_Fail == status)
        {
            configPRINTF(("Failed to load crypto context...\r\n"));
            // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a crash

            // Double check if encrypted XIP is enabled
            if (!bl_nor_encrypt_is_enabled())
            {
                configPRINTF(("Not running in encrypted XIP mode, ignore error.\r\n"));
                // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a
                // crash

                // No encrypted XIP enabled, we can ignore the bad status
                status = kStatus_Success;
            }
        }
        else if (kStatus_ReadOnly ==
                 status) // Using this status from standard status to indicate that we need to split PRDB
        {
            volatile uint32_t delay = 1000000;
            // Set up context as needed for this application
            status = bl_nor_encrypt_split_prdb();

            configPRINTF(("Restarting BOOTLOADER...\r\n"));

            while (delay--)
                ;

            // Restart
            DbgConsole_Deinit();
            NVIC_DisableIRQ(LPUART6_IRQn);
            NVIC_SystemReset();
        }
    }
    else if (SLN_AUTH_OK == status)
    {
        configPRINTF(("Ensuring context...\r\n"));
        // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a crash

        // We will check to see if we need to update the backup to the reduced scope PRDB0 for bootloader space
        status = bl_nor_encrypt_ensure_context();

        if (kStatus_Fail == status)
        {
            configPRINTF(("Failed to load crypto context...\r\n"));
            // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a crash

            // Double check if encrypted XIP is enabled
            if (!bl_nor_encrypt_is_enabled())
            {
                configPRINTF(("Not running in encrypted XIP mode, ignore error.\r\n"));

                // No encrypted XIP enabled, we can ignore the bad status
                status = kStatus_Success;
            }
        }
        else if (kStatus_Success == status) // We have good PRDBs so we can update the backup
        {
            bool isMatch    = false;
            bool isOriginal = false;

            configPRINTF(("Checking backup context...\r\n"));
            // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a crash

            // Check if we have identical KIBs and initial CTR
            status = bl_nor_crypto_ctx_compare_backup(&isMatch, &isOriginal, SLN_CRYPTO_CTX_0);

            if (kStatus_Success == status)
            {
                if (isMatch && isOriginal)
                {
                    configPRINTF(("Updating backup context with valid address space...\r\n"));
                    // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before
                    // a crash

                    // Update backup PRDB0
                    status = SLN_AUTH_backup_context(SLN_CRYPTO_CTX_0);
                }
            }
        }
    }

How to handle

Now we already understand the cause of the leak, we must prohibit external tools from loading flashloader or flash driver algorithms into the FlexRAM to run, so in addition to disabling the Debug port, we also need to disable the Serial download method to prevent the hackers take advantage of the Serial Downloader method to make the ROM code load a special flashloader to run in RAM, then configure the BEE or OTFAD module prior to reading the image.

However, compared to simply prohibiting the debug port, I'd highly recommend you select the Secure Debug method, because the debug feature requirement is important to return/filed testing, Secure Debug just is like adding a sturdy lock to the debug port, and only the authorized one can open this lock to enter the debugging mode successfully.

Reference

No ratings
Version history
Last update:
‎09-25-2022 07:15 PM
Updated by: