This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Compiler get stuck in side nrf_crypto_hash_update() function

Hi i am using nordic nrf52840 chip. and SDK17.1 i am using.

in that under secure bootloader code i am trying to use the nrf_crypto_hash_update() function to calculate the hash of my application code.

But when compiler reached to this function then it got stuck somewhere. 

Any idea y this happened. is i need to enable something in the code for hash calculation...?

Regards

Rohit Saini

Parents
  • Hello,

    Could you please take a screenshot of the CPU registers and dissambly view when the program is stuck? Also, are you calling this function directly, or via the nrf_crypto_hash_update() function like how we do it in nrf_dfu_validation.c?

    Best regards,

    Vidar

  • Hi,

    find the below screen shots.

    Regards

  • Are you calling it in a critical region? Can you post the code here?

  • And also i doing the same thing in open bootloader code also, but in that i am not facing such an issue.

  • Are you calling it in a critical region? Can you post the code here?

    Where do you place this function in the secure bootloader, and is this the same place where you do it in the open bootloader?

  • Below is the main content 

    int main(void)
    {
    uint32_t ret_val;

    bsp_board_init(BSP_INIT_LEDS);

    for (int i = 0; i < 8; i++)
    {
    nrf_gpio_pin_toggle(LED_2);
    nrf_delay_ms(500);
    }

    if (IsSignatureVerified(APPLICATION) == true)
    {
    // Must happen before flash protection is applied, since it edits a protected page.
    nrf_bootloader_mbr_addrs_populate();

    // Protect MBR and bootloader code from being overwritten.
    ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE);
    APP_ERROR_CHECK(ret_val);
    ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, BOOTLOADER_SIZE);
    APP_ERROR_CHECK(ret_val);

    (void) NRF_LOG_INIT(nrf_bootloader_dfu_timer_counter_get);
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("Inside main");

    ret_val = nrf_bootloader_init(dfu_observer);
    APP_ERROR_CHECK(ret_val);

    NRF_LOG_FLUSH();

    NRF_LOG_ERROR("After main, should never be reached.");
    NRF_LOG_FLUSH();

    APP_ERROR_CHECK_BOOL(false);
    }
    else
    {
    for (int i = 0; i < 8; i++)
    {
    nrf_gpio_pin_toggle(LED_2);
    nrf_delay_ms(2000);
    }
    }
    }

    in side IsSignatureVerified() function i am calling this function. where i am using nrf_crypto_hash_update() function. 

    void capture_flashdata_into_databuffer(uint8_t u8Type)
    {

    uint32_t flashReadAddress = 0;
    uint32_t appEndAddress = 0;
    ret_code_t err_code;

    uint8_t pk_copy[sizeof(pk1)];

    nrf_crypto_hash_context_t hash_context = {0};

    err_code = nrf_crypto_init();
    ASSERT(err_code == NRF_SUCCESS);

    // Convert public key to big-endian format for use in nrf_crypto.
    nrf_crypto_internal_double_swap_endian(pk_copy, pk1, sizeof(pk1) / 2);

    err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info,
    &m_public_key,
    pk_copy,
    sizeof(pk1));
    /* Hash Calculation Code */
    err_code = nrf_crypto_hash_init(&hash_context, &g_nrf_crypto_hash_sha256_info);
    APP_ERROR_CHECK(err_code);
    errorcheck = err_code;


    if(u8Type == BOOT2)
    {
    do
    {

    flashReadAddress = BL2_START_ADDRESS;
    appEndAddress = (BL2_START_ADDRESS + BL2_SIZE_ADDRESS) - 1 ;//0x2AFFF; //
    //flashReadAddress = AP_START_ADDRESS;
    //appEndAddress = (AP_START_ADDRESS + AP_SIZE_ADDRESS) - 1 ;//0x2AFFF; //

    if (flashReadAddress > appEndAddress)
    break;

    while ((appEndAddress - flashReadAddress) >(BLOCK_SIZE-1))
    {
    read_flash_data(flashReadAddress, BLOCK_SIZE);
    flashReadAddress += BLOCK_SIZE;
    err_code = nrf_crypto_hash_update(&hash_context, dataBuffer, BLOCK_SIZE);
    APP_ERROR_CHECK(err_code);
    }

    //uint32_t temp = (appEndAddress - flashReadAddress) + 1;
    dataBufferSize = (appEndAddress - flashReadAddress);
    read_flash_data(flashReadAddress, dataBufferSize);
    dataBuffer_ptr = (uint8_t*) DUMMY_START_ADDRESS;


    err_code = nrf_crypto_hash_update(&hash_context, dataBuffer, dataBufferSize);
    APP_ERROR_CHECK(err_code);
    errorcheck = err_code;

    err_code = nrf_crypto_hash_finalize(&hash_context, m_sig_hash, &hash_len);
    APP_ERROR_CHECK(err_code);
    errorcheck = err_code;

    } while (0);
    }
    else
    {
    do
    {

    flashReadAddress = AP_START_ADDRESS;
    appEndAddress = (AP_START_ADDRESS + AP_SIZE_ADDRESS) - 1 ;//0x2AFFF; //

    if (flashReadAddress > appEndAddress)
    break;

    while ((appEndAddress - flashReadAddress) >(BLOCK_SIZE-1))
    {
    read_flash_data(flashReadAddress, BLOCK_SIZE);
    flashReadAddress += BLOCK_SIZE;
    err_code = nrf_crypto_hash_update(&hash_context, dataBuffer, BLOCK_SIZE);
    APP_ERROR_CHECK(err_code);
    }

    //uint32_t temp = (appEndAddress - flashReadAddress) + 1;
    dataBufferSize = (appEndAddress - flashReadAddress);
    read_flash_data(flashReadAddress, dataBufferSize);
    dataBuffer_ptr = (uint8_t*) DUMMY_START_ADDRESS;


    err_code = nrf_crypto_hash_update(&hash_context, dataBuffer, dataBufferSize);
    APP_ERROR_CHECK(err_code);
    errorcheck = err_code;

    err_code = nrf_crypto_hash_finalize(&hash_context, m_sig_hash, &hash_len);
    APP_ERROR_CHECK(err_code);
    errorcheck = err_code;

    } while (0);
    }

    }

  • IN open bootloader its in main only but in little different way.

    int main(void)
    {
    uint32_t ret_val;

    bsp_board_init(BSP_INIT_LEDS);


    {
    for (int i = 0; i < 6; i++)
    {
    //bsp_board_led_invert(i);
    nrf_gpio_pin_toggle(LED_3);
    nrf_delay_ms(500);
    }
    }

    // Must happen before flash protection is applied, since it edits a protected page.
    nrf_bootloader_mbr_addrs_populate();

    // Protect MBR and bootloader and application code from being overwritten.
    ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE);
    APP_ERROR_CHECK(ret_val);
    ret_val = nrf_bootloader_flash_protect(AP_START_ADDRESS, 0x4000);
    APP_ERROR_CHECK(ret_val);
    ret_val = nrf_bootloader_flash_protect(BL2_START_ADDRESS, (NRF_MBR_PARAMS_PAGE_ADDRESS - 0xF8000)); //ROHIT
    APP_ERROR_CHECK(ret_val);

    NRF_LOG_INFO("Open USB bootloader started");
    //NRF_LOG_FLUSH();

    if (IsSignatureVerified(BOOT2) == true)
    {
    #if 1
    //Jump_To_App();
    Jump_To_Bootloader2();
    #endif
    }

Reply
  • IN open bootloader its in main only but in little different way.

    int main(void)
    {
    uint32_t ret_val;

    bsp_board_init(BSP_INIT_LEDS);


    {
    for (int i = 0; i < 6; i++)
    {
    //bsp_board_led_invert(i);
    nrf_gpio_pin_toggle(LED_3);
    nrf_delay_ms(500);
    }
    }

    // Must happen before flash protection is applied, since it edits a protected page.
    nrf_bootloader_mbr_addrs_populate();

    // Protect MBR and bootloader and application code from being overwritten.
    ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE);
    APP_ERROR_CHECK(ret_val);
    ret_val = nrf_bootloader_flash_protect(AP_START_ADDRESS, 0x4000);
    APP_ERROR_CHECK(ret_val);
    ret_val = nrf_bootloader_flash_protect(BL2_START_ADDRESS, (NRF_MBR_PARAMS_PAGE_ADDRESS - 0xF8000)); //ROHIT
    APP_ERROR_CHECK(ret_val);

    NRF_LOG_INFO("Open USB bootloader started");
    //NRF_LOG_FLUSH();

    if (IsSignatureVerified(BOOT2) == true)
    {
    #if 1
    //Jump_To_App();
    Jump_To_Bootloader2();
    #endif
    }

Children
  • R_S said:
    IN open bootloader its in main only

    Does that mean the secure bootloader is performing the hash computation from other places as well?

    Also, please do not copy-and-paste large code snippets into your post. It makes it hard to read. Instead you can use the formatting tools to insert the code, or upload the c file as an attachment.

  • I am calling this function in the starting only. and before that its not called.

    in later stage for secure boot code its called under "nrf_crypto_hash_calculate()" function only. 

    But that should not effect right...?

  • I did a simple test where I validated the signature of the main application image, but I did not manage to reproduce the problem you saw.

    Here is my test function:

    #include "nrf_crypto.h"
    #include "nrf_crypto_shared.h"
    
    #define APP_START 0x27000
    #define APP_SIZE  99816
    
    /* Application signature copied from pkg_info.txt in \examples\dfu\secure_bootloader\key */
    #define APP_SIGN                                                                                   \
        {                                                                                              \
            0x17, 0x1a, 0x3a, 0x99, 0x45, 0xdd, 0x7b, 0x24, 0xc9, 0x7b, 0x0e, 0x0a, 0xf0, 0x19, 0x3d,  \
                0x97, 0x28, 0xf7, 0xed, 0x72, 0x28, 0xd1, 0x25, 0xd6, 0x84, 0x86, 0xf1, 0x04, 0xd6,    \
                0x22, 0x12, 0xff, 0xf7, 0x39, 0xf1, 0x6e, 0xa0, 0x5a, 0xc0, 0xef, 0xc8, 0xa0, 0x30,    \
                0xb9, 0x50, 0xa9, 0x83, 0x6d, 0x34, 0x0d, 0x91, 0x81, 0xd7, 0x49, 0xfc, 0x27, 0x43,    \
                0x7e, 0x0b, 0x7c, 0xbb, 0x9c, 0x29, 0xe3                                               \
        }
    
    static nrf_crypto_hash_sha256_digest_t              m_sig_hash;
    /** @brief Structure to hold a signature
     */
    static nrf_crypto_ecdsa_secp256r1_signature_t       m_signature;
    
    static nrf_crypto_ecc_public_key_t                  m_public_key;
    
    __ALIGN(4) extern const uint8_t pk[64];
    
    void signature_validate_test(void)
    {
        ret_code_t err_code;
        uint8_t    pk_copy[sizeof(pk)];
        size_t     hash_len = NRF_CRYPTO_HASH_SIZE_SHA256;
        size_t     data_len = APP_SIZE;
        uint8_t    app_signature[] = APP_SIGN;
    
        nrf_crypto_hash_context_t         hash_context   = {0};
        nrf_crypto_ecdsa_verify_context_t verify_context = {0};
       
        NRF_LOG_INFO("Starting signature validation test");
    
        err_code = nrf_crypto_init();
        ASSERT(err_code == NRF_SUCCESS);
        UNUSED_PARAMETER(err_code);
    
        // Convert public key to big-endian format for use in nrf_crypto.
        nrf_crypto_internal_double_swap_endian(pk_copy, pk, sizeof(pk) / 2);
    
        err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info,
                                                      &m_public_key,
                                                      pk_copy,
                                                      sizeof(pk));
        ASSERT(err_code == NRF_SUCCESS);
        UNUSED_PARAMETER(err_code);
    
        NRF_LOG_INFO("Calculating hash (len: %d)", data_len);
        err_code = nrf_crypto_hash_calculate(&hash_context,
                                             &g_nrf_crypto_hash_sha256_info,
                                             (uint8_t *)APP_START,
                                             data_len,
                                             m_sig_hash,
                                             &hash_len);
    
        NRF_LOG_INFO("nrf_crypto_hash_calculate() return value: 0x%x", err_code);
    
        memcpy(m_signature, app_signature, NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE);
    
        // Calculate the signature.
        NRF_LOG_INFO("Verify signature");
    
        // The signature is in little-endian format. Change it to big-endian format for nrf_crypto use.
        nrf_crypto_internal_double_swap_endian_in_place(m_signature, sizeof(m_signature) / 2);
    
        err_code = nrf_crypto_ecdsa_verify(&verify_context,
                                           &m_public_key,
                                           m_sig_hash,
                                           hash_len,
                                           m_signature,
                                           sizeof(m_signature));
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Signature failed (err_code: 0x%x)", err_code);
            NRF_LOG_DEBUG("Signature:");
            NRF_LOG_HEXDUMP_DEBUG(m_signature, sizeof(m_signature));
            NRF_LOG_DEBUG("Hash:");
            NRF_LOG_HEXDUMP_DEBUG(m_sig_hash, hash_len);
            NRF_LOG_DEBUG("Public Key:");
            NRF_LOG_HEXDUMP_DEBUG(pk, sizeof(pk));
            NRF_LOG_FLUSH();
            return;
        }
    
        NRF_LOG_INFO("Image verified");
    
    }
    
    /**@brief Function for application main entry. */
    int main(void)
    {
        uint32_t ret_val;
    
        // Must happen before flash protection is applied, since it edits a protected page.
        nrf_bootloader_mbr_addrs_populate();
    
        // Protect MBR and bootloader code from being overwritten.
        ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE);
        APP_ERROR_CHECK(ret_val);
        ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, BOOTLOADER_SIZE);
        APP_ERROR_CHECK(ret_val);
    
        (void) NRF_LOG_INIT(nrf_bootloader_dfu_timer_counter_get);
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        NRF_LOG_INFO("Inside main");
        signature_validate_test();
        ...

    and full project:

    nRF5_SDK17.1.0_dfu.zip

    Which variant of the cc310 are you including in your project? And have you verified that the Cryptocell interrupt actually gets enabled at the line shown in the screenshot below?

  • Hi Vidar,

    I checked the Cryptocell interrupt is enabled in my case also. Its the same thing what you mentioned in the screen shot.

    So the catch here is in my nrf52840 board right two bootloaders are flashed. First one is the open bootloader and second one is the secure bootloader code.

    and the flow is like ----MBR---->SOFTDEVICE---->OPEN_BOOTLOADER--->SECURE_BOOTLOADER--->APPPLICATION

    Case 1: - if both bootloader is present then hash calculation getting stuck in secure_bootloader code. 

    But

    Case 2:- If only secure bootloader is present then it works fine no issue in hash calculation.

    i tried with your example code also and its working fine in 2nd case. but 1st case same issue even with your example code also. in bootloader 1 i am verifying the hash and signature and then jump to the bootloader 2. so could it be the jumping part that can cause this issue...? 

    This thing only i am not able to figure out. with 2 bootloader only issue comes. i mentioned the address below. 

    MBR+SOFTDEVICE --->0x00000000

    OPEN_BOOTLOADER --->0x27000

    SECURE_BOOTLOADER --->F1000

    APPLICATION --->0x5E000

    Below I attached the jump code used to jump from open bootloader to secure bootloader. please let me know whether i am handling that jumping part properly or not. or i missed something there...?

    void Jump_To_Bootloader2(void)
    {
    /*  uint32_t appStack;
      uint32_t *ptrApp;
      user_code_entry functionPtr;
      appStack = (uint32_t) *((uint32_t*)BL2_START_ADDRESS);
      __disable_interrupt();
      MAP_Interrupt_setVectorTableAddress(BL2_START_ADDRESS & (uint32_t)0x1FFFFF80);
      __set_SP(appStack);
      ptrApp = (uint32_t *)(BL2_START_ADDRESS + 4);
      functionPtr = (user_code_entry)*ptrApp;
      functionPtr();        */
      
        uint32_t start_addr = 0xF1000; // Always boot from end of MBR. If a SoftDevice is present, it will boot the app.
        NRF_LOG_DEBUG("Running nrf_bootloader_app_start with address: 0x%08x", start_addr);
        uint32_t err_code;
    
        // Disable and clear interrupts
        // Notice that this disables only 'external' interrupts (positive IRQn).
        NRF_LOG_DEBUG("Disabling interrupts. NVIC->ICER[0]: 0x%x", NVIC->ICER[0]);
    
        NVIC->ICER[0]=0xFFFFFFFF;
        NVIC->ICPR[0]=0xFFFFFFFF;
    #if defined(__NRF_NVIC_ISER_COUNT) && __NRF_NVIC_ISER_COUNT == 2
        NVIC->ICER[1]=0xFFFFFFFF;
        NVIC->ICPR[1]=0xFFFFFFFF;
    #endif
        
        /*err_code = nrf_dfu_mbr_irq_forward_address_set();
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Failed running nrf_dfu_mbr_irq_forward_address_set()");
        }   
        
        NRF_LOG_FLUSH();*/ 
    
        nrf_bootloader_app_start_final(start_addr);
        
    }

    Regards

    Rohit Saini

  • Hello Rohit,

    The "jump" function looks to be correct.

    Are you calling nrf_crypto_uninit() to uninitialized the cryptocell before you jump to the second  bootloader? Note that the peripherals are not reset when you forward execution to another FW application like this, so it's generally good practice to reset/uninitialize peripherals which have been used before booting the next FW image in your boot chain.

    Regards,

    Vidar

Related