Issue with FLASH_Write Not Programming CMAC Tag in S32K344 Advanced Secure Boot Example

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

Issue with FLASH_Write Not Programming CMAC Tag in S32K344 Advanced Secure Boot Example

1,436 Views
Luu_Nghia_308
Contributor II

Dear NXP Support Team,

I am currently running the example S32K3_HSE_DemoExamples_1_0_0\S32K3_HSE_DemoExamples\Secure_Boot\S32K344_Advanced_SecureBoot on the S32K344EVB-T172 board.

However, I have observed an issue where the following function call:

FLASH_Write(pCmacTag, Cmac_Tag, sizeof(Cmac_Tag))

does not program the CMAC tag into flash memory at the address defined by CmacTagFlashAddress.

The returned status is 0xC100, which indicates no error, but after dumping the flash memory, I can confirm that the CMAC tag has not been written to the expected flash location.

Luu_Nghia_308_0-1767780900598.png

 

Could you please help me debug this issue?

 

0 Kudos
Reply
12 Replies

1,308 Views
Luu_Nghia_308
Contributor II

I have executed the S32K344_Advanced_SecureBoot application, and the execution completed successfully without any errors. do you have anyway to debug or trace the secure boot process after a system reset?

Luu_Nghia_308_1-1767949217968.png

 

0 Kudos
Reply

1,288 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

One more thing is necessary - once configuration is done, BOOT_SEQ bit in boot configuration word in flash should reprogrammed to '1'. This enables the secure boot. Then SecureBootBlinky application should be executed after reset instead of configuration project. Once BOOT_SEQ is set to '1', normal reset vector (which is pointing to configuration project) is not taken into account. 

I saw that there's a difference between Basic Secure Boot example and Advanced Secure Boot example:

lukaszadrapa_0-1767971770671.png

Basic SB example has BOOT_SEQ already set in the boot header, Advanced SB example does not have BOOT_SEQ set. Either set it here or reprogram the flash manually once the configuration of secure boot is done. I described how it works here:

https://community.nxp.com/t5/S32K/S32K344-Secure-Boot-HSE-VerifyBootImage-issue/m-p/2171055/highligh...

So, as I said above, if secure boot is successful, SecureBootBlinky application will be executed. If secure boot fails, the device will go to recovery mode. That means it will end up in endless loop in RAM at JTAG_RECOVERY_START_ADDRESS which is 0x20400100.

Regards,

Lukas

 

 

0 Kudos
Reply

1,023 Views
Luu_Nghia_308
Contributor II

Hi, @lukaszadrapa 

I am trying to customize S32K344_Advanced_SecureBoot so that it can configure HSE to verify itself.

I have made the following changes:

Linker :

  • Modified the linker file and removed S32K344_SecureBootBlinky.bin

  • Adjusted the PFlash length to 0x50000Luu_Nghia_308_0-1768379017263.png

Main

  • Modified the main() configuration as follows
    #define APPBL_ADDRESS (0x00400000)
    #define APPBL_LENGTH (0x50000)
    #define APP_HEADER_LENGTH 0x0U

Luu_Nghia_308_1-1768379117840.png

 

My expectation is that after a reset, the S32K344_Advanced_SecureBoot application will execute from address 0x00400000.

However, I encounter a crash when attempting to write to the CMAC tag, specifically at the following code:

/* Write TAG in the expected location at the end of the image */
PFLASH_Unlock(PFLASH_BL0, PFLASH_SS5, PFLASH_S0);

status = FLASH_Write(pCmacTag,
Cmac_Tag,
sizeof(Cmac_Tag));

I attached source code file main in below.

Could you please help me identify the root cause of the error and explain how I can successfully execute S32K344_Advanced_SecureBoot after a system reset?

Thank you very much.

 

 

/*
 * main implementation: use this 'C' sample to create your own application
 *
 */
#include "S32K344.h"
#include "hse_host.h"
#include "hse_interface.h"
#include "hse_demo_app_services.h"
#include "hse_host_format_key_catalogs.h"
#include "hse_keys_allocator.h"
#include "hse_host_import_key.h"
#include "hse_host_cipher.h"
#include "hse_host_mac.h"
#include "hse_host_boot.h"
#include <string.h>
#include "pflash.h"
#include "flash.h"

#define AESKEY_BYTE_LENGTH  (16U)

#define APPBL_ADDRESS       (0x00400000)
#define APPBL_LENGTH        (0x50000)
#define APP_HEADER_LENGTH   0x0U

typedef struct{
    uint8_t isNVM;
    uint32_t keyBitLen;
    hseKeyFlags_t keyFlags;
    uint8_t *pKeyValue;
}AesKeyCfg;

const hseKeyGroupCfgEntry_t NVM_Catalog [] =
{
    {HSE_ALL_MU_MASK, HSE_KEY_OWNER_CUST, HSE_KEY_TYPE_AES, 10, 256},
    {HSE_ALL_MU_MASK, HSE_KEY_OWNER_CUST, HSE_KEY_TYPE_AES, 10, 128},
    {0, 0, 0, 0, 0}
};


const hseKeyGroupCfgEntry_t RAM_Catalog [] =
{
    {HSE_ALL_MU_MASK, HSE_KEY_OWNER_ANY, HSE_KEY_TYPE_AES, 10, 256},
    {HSE_ALL_MU_MASK, HSE_KEY_OWNER_ANY, HSE_KEY_TYPE_AES, 10, 256},
    {0, 0, 0, 0, 0}
};

uint8_t LoadedAesKeyValue[AESKEY_BYTE_LENGTH] =
{
    0x42, 0x27, 0x6E, 0xEF, 0x73, 0xFB, 0x1C, 0x8D,
    0x1A, 0x6C, 0xCD, 0xC9, 0x69, 0xB0, 0x1E, 0xE6,
};

AesKeyCfg MacGenAesKey = {
    .isNVM = 1,
    .keyBitLen = 128,
    .keyFlags = HSE_KF_USAGE_SIGN,
    .pKeyValue = &LoadedAesKeyValue[0]
};

AesKeyCfg MacVerAesKey = {
    .isNVM = 1,
    .keyBitLen = 128,
    .keyFlags = HSE_KF_USAGE_VERIFY,
    .pKeyValue = &LoadedAesKeyValue[0]
};

uint8_t Cmac_Tag[16];
uint32_t Cmac_TagLength = 16;
uint32_t CmacTagFlashAddress;
uint8_t * pCmacTag;

hseSmrEntry_t SMR_0 = {
    .pSmrSrc = (uint32_t)APPBL_ADDRESS,
    .smrSize = (uint32_t)APPBL_LENGTH,
    .configFlags = HSE_SMR_CFG_FLAG_INSTALL_AUTH,
    .pSmrDest = 0,
    .checkPeriod = 0,
};

hseCrEntry_t CrEntry = {
    .coreId = 0,
    .preBootSmrMap = (1<<0),                        /* (1 << 0) SMR 0 */
    .pPassReset = APPBL_ADDRESS,                        /* The start address is the address of the Application + size of the application header (0x40) */
    .altPreBootSmrMap = 0,                      /* There will be no alternative verification if the defined preboot verification fails */
    .pAltReset = 0,                             /* There will be no alternative starting address */
    .postBootSmrMap = 0,                            /* No post boot verification required */
    .startOption = HSE_CR_AUTO_START,               /* The core is to be set out of reset automatically after the verification */
    .crSanction = HSE_CR_SANCTION_DIS_INDIV_KEYS        /* Sanction to apply if the verification fails */
};


int main(void) {
    hseSrvResponse_t HseResponse;
    hseKeyHandle_t MacGenKeyHandle;
    hseKeyHandle_t MacVerKeyHandle;
    hseAppCore_t app_core = HSE_APP_CORE0;
    tFLASH_STATUS status;
    hseAttrSmrCoreStatus_t smrCoreStatus;


     /*Check Fw Install Status*/
    WaitForHSEFWInitToFinish();

    /* Stap 1*/
    HseResponse = FormatKeyCatalogs(NVM_Catalog, RAM_Catalog);
    ASSERT(HSE_SRV_RSP_OK == HseResponse);

    HseResponse = HKF_Init(NVM_Catalog, RAM_Catalog);
    ASSERT(HSE_SRV_RSP_OK == HseResponse);

    MacGenKeyHandle = (hseKeyHandle_t)(GET_KEY_HANDLE(HSE_KEY_CATALOG_ID_NVM, 0, 0));
    MacVerKeyHandle = (hseKeyHandle_t)(GET_KEY_HANDLE(HSE_KEY_CATALOG_ID_NVM, 0, 1));

    /* Load key used to generate TAG */
    HseResponse = ImportPlainSymKeyReq(MacGenKeyHandle,
                                       HSE_KEY_TYPE_AES,
                                       MacGenAesKey.keyFlags,
                                       (MacGenAesKey.keyBitLen>>3),
                                       MacGenAesKey.pKeyValue,
                                       0);
    ASSERT(HSE_SRV_RSP_OK == HseResponse);

    /* Load key used to verify the generated TAG */
    HseResponse = ImportPlainSymKeyReq(MacVerKeyHandle,
                                       HSE_KEY_TYPE_AES,
                                       MacVerAesKey.keyFlags,
                                       (MacGenAesKey.keyBitLen>>3),
                                       MacVerAesKey.pKeyValue,
                                       0);
    ASSERT(HSE_SRV_RSP_OK == HseResponse);

    CmacTagFlashAddress = (uint32_t)(APPBL_ADDRESS + APP_HEADER_LENGTH + APPBL_LENGTH);

    /* SMR Configuration */
    SMR_0.authKeyHandle = MacVerKeyHandle;
    SMR_0.authScheme.macScheme.macAlgo = HSE_MAC_ALGO_CMAC;
    SMR_0.authScheme.macScheme.sch.cmac.cipherAlgo = HSE_CIPHER_ALGO_AES;
    SMR_0.pInstAuthTag[0] = CmacTagFlashAddress;
    SMR_0.pInstAuthTag[1] = (uint32_t)NULL;

    /* TAG generation and verification */
    HseResponse = AesCmacGenerate(MacGenKeyHandle,
                                  SMR_0.smrSize,
                                  (const uint8_t *)SMR_0.pSmrSrc,
                                  &Cmac_TagLength,
                                  &Cmac_Tag[0],
                                  0);
    ASSERT(HSE_SRV_RSP_OK == HseResponse);

    HseResponse = AesCmacVerify(MacVerKeyHandle,
                                SMR_0.smrSize,
                                (const uint8_t *)SMR_0.pSmrSrc,
                                &Cmac_TagLength,
                                &Cmac_Tag[0],
                                0);
    ASSERT(HSE_SRV_RSP_OK == HseResponse);

    pCmacTag = (uint8_t *)CmacTagFlashAddress;

    /* Write TAG in the expected location at the end of the image */
    PFLASH_Unlock(PFLASH_BL0, PFLASH_SS5, PFLASH_S0);
   
    status = FLASH_Write (pCmacTag,
                          Cmac_Tag,
                          sizeof(Cmac_Tag));
    (void)status;

    /* Install Secure Memory Region */
    HseResponse = HSE_InstallSmrEntry(0,
                                      &SMR_0,
                                      (const uint8_t *)SMR_0.pSmrSrc,
                                      SMR_0.smrSize,
                                      pCmacTag,
                                      NULL,
                                      Cmac_TagLength,
                                      0);
    ASSERT(HSE_SRV_RSP_OK == HseResponse);

    /* Install CR Entry */
    HseResponse = HSE_InstallCoreResetEntry(app_core, &CrEntry);
    ASSERT(HSE_SRV_RSP_OK == HseResponse);

    /* Get status of the Secure Memory Region and Core Reset Entry installation */
    HseResponse = Get_Attr(
                HSE_SMR_CORE_BOOT_STATUS_ATTR_ID,
                sizeof(hseAttrSmrCoreStatus_t),
                (void *)(&smrCoreStatus));
    ASSERT(HSE_SRV_RSP_OK == HseResponse);

    uint32_t i = 0;

    for (;;) {

        IP_SIUL2->MSCR[31] = SIUL2_MSCR_OBE_MASK;

        for (;;) {
            i = 100000;

            IP_SIUL2->GPDO31 ^= 1;
            while(--i != 0);


        }
    }

    return 0;
}



 

0 Kudos
Reply

1,007 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Here's the reason why you got hardfault:

In the original project, the application (SecureBootBlinky) is forced to flash block 1, so the CMAC was programmed to block 1 by code running from block 0. 

Now you are going to verify application in block 0 and the CMAC is also going to be programmed to block 0 by code running from block 0. 

But read while write is supported only between blocks:

lukaszadrapa_0-1768393708937.png

 

lukaszadrapa_1-1768393715870.png

Solution - the code programming the flash must be executed from another flash block or from RAM. 

Regards,

Lukas

 

 

0 Kudos
Reply

958 Views
Luu_Nghia_308
Contributor II

Hi @lukaszadrapa 

After modifying the Flash configuration to run from RAM, I was able to successfully program the Cmag_Tag at address 0x450000.
In addition, my program was able to execute to completion.

Luu_Nghia_308_0-1768454656828.png

 

However, after performing a reset, I observed that the reset address changed to a different location. I suspect that the HSE may have incorrectly verified the SRM.

Luu_Nghia_308_3-1768454788928.png

 

I do not understand why this issue occurs, as I had previously verified the SRM and successfully initialized the SMR.

 

0 Kudos
Reply

926 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Hi @Luu_Nghia_308 

I did quick test on my board using original project. 

I modified only main.c. I configured it to verify 0x40_0000 - 0x4F_FFFF. The CMAC is programmed to 0x50_0000, so I do not need to care about read-while-write issues. 

The file is attached. Those few changes are marked by:

/*** Modified start ***/

/*** Modified end ***/

After the configuration, you are supposed to re-program BOOT_SEQ in boot configuration word to enable secure boot:

lukaszadrapa_0-1768475014309.png

Or you can go to file:

..\S32K344_Advanced_SecureBoot\src\target\m7\S32DS\Startup_Code\boot_header.c

And set this bit:

lukaszadrapa_1-1768475120636.png

So, BOOT_SEQ will be set right at the beginning.

Then just load the project by debugger (don't do additional reset at this moment), run the configuration project and reset the device. The project will be executed again because the secure boot was successful. 

Then you can try to modify any word in area 0x40_0000 - 0x4F_FFFF. The secure boot will fail and it will end up at JTAG recovery address:

lukaszadrapa_2-1768475282681.png

If you revert back the modification in flash, the project will be executed again after next reset.  

Regards,

Lukas

0 Kudos
Reply

829 Views
Luu_Nghia_308
Contributor II

Hi @lukaszadrapa 

I followed the steps you suggested:

  1. I changed the start address and length of the application.

    #define APPBL_ADDRESS       (0x00400000)
    #define APPBL_LENGTH        (0x00100000)
    #define APP_HEADER_LENGTH   0x0U
    #define CMAC_FLASH_ADDRESS  (0x00500000U)

    Luu_Nghia_308_0-1768561148592.png

     

  2. I updated the addresses:
    .pPassReset = APPBL_ADDRESS;
    CmacTagFlashAddress = (uint32_t)(CMAC_FLASH_ADDRESS);

    Luu_Nghia_308_1-1768561195238.png

     

    Luu_Nghia_308_2-1768561207715.png

     

  3. I added blinky code inside the for loop.

    Luu_Nghia_308_3-1768561242012.png
  4. Secure_boot is enabled (set to 1).

    Luu_Nghia_308_4-1768561315611.png

     

    After resetting the board, my LED does not blink. However, it still does not workCould you please help me check what might be wrong?
0 Kudos
Reply

547 Views
Luu_Nghia_308
Contributor II

Hi @lukaszadrapa 

After the adjustments, it has been working on my side. Thank you for your support

0 Kudos
Reply

496 Views
NghiaLuu
Contributor I

Hi @lukaszadrapa 

I want to place the Interrupt Vector Table (IVT) at the start address 0x400000.
Within this IVT, the start address of the Cortex-M7_0 core code is already defined at offset 0x0C.

NghiaLuu_0-1768819436677.png

 

My question is:
Does the symbol .pPassReset in CrEntry refer to the base address 0x400000 where the IVT is located, or does it refer to the actual start address of the Cortex-M7_0 core code as defined in the IVT?

 

Tags (1)
0 Kudos
Reply

480 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

The HSE FW RM explicitly talks about VTOR address when describing pPassReset parameter:

"A Value of the VTOR of associated application subsystem"

I used this in my example I shared earlier:

.pPassReset = 0x00400000,

This confirms it's address of VTOR, not the entry point directly. 

Regards,

Lukas

0 Kudos
Reply

1,361 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Hi @Luu_Nghia_308 

Is that original project or did you modify it? I was playing with this example several times and it worked on my side. 

I'm not familiar with that debugger, but it looks like it could be caused by the debugger. Take a look at:

https://forum.segger.com/thread/7245-solved-ozone-memory-view-refresh/

https://kb.segger.com/UM08001_J-Link_/_J-Trace_User_Guide#Debugging_applications_that_change_flash_c...

Regards,

Lukas

0 Kudos
Reply

1,314 Views
Luu_Nghia_308
Contributor II

Thank you — it was caused by the debugger.

0 Kudos
Reply