APPROTECT and verify with nrfjprog

Hi

On the nRF52840-QIAA-R there should be implemented the APPROTECT according to this guide:

https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/working-with-the-nrf52-series-improved-approtect

Informational Notice (IN) - Vulnerability of the nRF52 series.

I implemented now the suggested code on top of main:

void AppProtection(void)
{
#ifdef ENABLE_APPROTECT
	if ((NRF_UICR->APPROTECT & UICR_APPROTECT_PALL_Msk) !=
		(UICR_APPROTECT_PALL_Enabled << UICR_APPROTECT_PALL_Pos)) {
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}

        NRF_UICR->APPROTECT = ((NRF_UICR->APPROTECT & ~((uint32_t)UICR_APPROTECT_PALL_Msk)) |
		    (UICR_APPROTECT_PALL_Enabled << UICR_APPROTECT_PALL_Pos));

        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        NVIC_SystemReset();
   	}
#else
	if ((NRF_UICR->APPROTECT & UICR_APPROTECT_PALL_Msk) !=
		(UICR_APPROTECT_PALL_HwDisabled << UICR_APPROTECT_PALL_Pos)) {

        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}

        NRF_UICR->APPROTECT = ((NRF_UICR->APPROTECT & ~((uint32_t)UICR_APPROTECT_PALL_Msk)) |
		    (UICR_APPROTECT_PALL_HwDisabled << UICR_APPROTECT_PALL_Pos));

        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        NVIC_SystemReset();
	}
#endif
}

This is working, but the problem is that the verify in production programming is not working anymore. Is there an option to verify the chip before? Because after a program the chip is getting restarted and read out protection is active which makes verify impossible. Is there a solution to verify with nrfjprog or use nrfjprog to program without starting the code on the nRF52?

nrfjprog --program %HEX_FILE% --verify --log

Parents
  • And in the bootloader the debug_port_disable function will be called aswell when the SDK_config NRF_BL_DEBUG_PORT_DISABLE is enabled:

    void nrf_bootloader_debug_port_disable(void)
    {
        if (NRF_UICR->APPROTECT != 0x0)
        {
            nrf_nvmc_write_word((uint32_t)&NRF_UICR->APPROTECT, 0x0);
            NVIC_SystemReset();
        }
    #if (!defined (NRF52810_XXAA) && !defined (NRF52811_XXAA) && !defined (NRF52832_XXAA) && !defined (NRF52832_XXAB))
        if (NRF_UICR->DEBUGCTRL != 0x0)
        {
            nrf_nvmc_write_word((uint32_t)&NRF_UICR->DEBUGCTRL, 0x0);
            NVIC_SystemReset();
        }
    #endif
    }

    So at the end the device is starting in the bootloader and the function above will enbale the APPROTECT. If a device is running without bootloader (only in development), then the function on top of the main will enable the APPROTECT with the function "AppProtection()"

    Is my understanding and the functions in the bootloader and App correct?

    If yes, the only question is how to flash the nRF52840 with nrfjprog and use the verify, or is there an option to ensure a correct download without verify?

  • Hi Dominik,

    Dominik Eugster said:
    Is my understanding and the functions in the bootloader and App correct?

    Yes that's right. https://docs.nordicsemi.com/bundle/nrf5_SDK_v17.1.1/page/lib_secure_boot.html#secure_boot_debug_prod 

    Dominik Eugster said:
    If yes, the only question is how to flash the nRF52840 with nrfjprog and use the verify, or is there an option to ensure a correct download without verify?

    Could you try the following:

    nrfjprog -f NRF52 --recover
    nrfjprog -f NRF52 --eraseall
    nrfjprog -f NRF52 --program file.hex --verify

    -Priyanka

  • Ok, now I managed to enable ReadProtect only the second time after reset because of the Verify issue.
    To manage this, I use a command line before program / verify and check this value in the App:

    nrfjprog --memwr 0x000F5000 --val 0x12345678

    if I read the address before enabling the ReadBackProtection I read 0xDEADC0DE

    nrfjprog --memrd 0x000F5000 0x000F5000: DEADC0DE 

    my bootloader is starting at 0xF6000 and has 32kB, so in the memory map the part lower than 0xF6000 should be empty, but what this 0xDEADC0DE is meaning?

    Is it safe to use this region below (grey) or should I avoid this? Is there any other way to do the ReadBackProtection in the App only after the second Reset without this Falsh? UICR is not working, I guess the internal falsh is ok only the 0xDEADC0DE is confusing me...

  • I think it's possible to use NRF_UICR->CUSTOMER[x] flag to enable the NRF_UICR->APPROTECT only after the second Reset/Boot, and with nrfjprog --eraseall the flags in uicr will be reset to default before flashing.I will try

  • Hi Dominik,

    That does sound like a good way. And you are also right that --eraseall resets UICR, including protection flags.

    -Priyanka

  • Hi Priyanaka

    With the UIR flags its possible and working like expected.

    The logic is the following: Bootloader has its own UICR (index 1), application has its own UICR (index 0).

    If the index is empty, the bootloader and app is writing the predefined value to this index. Next restart (Reset, Power Reset) the code is checking this value and is writing the AppProtection Flag following by a reset. This logic is needed to ensure that the fisrt time the AppProtect is not activated, second time yes. 

    The if is preventing that this is happening at every reset, it will happen only once:

    void AppProtection(void)
    {
    #ifdef ENABLE_APPROTECT
        if (!is_customer_magic_set())
        {
            NRF_LOG_DEBUG("Customer Magic is not active");
            uicr_write_customer_magic();
        }
        else
        {
            NRF_LOG_DEBUG("Enable AppProtection");
            if ((NRF_UICR->APPROTECT & UICR_APPROTECT_PALL_Msk) !=
        		(UICR_APPROTECT_PALL_Enabled << UICR_APPROTECT_PALL_Pos)) 
            {
                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
                NRF_UICR->APPROTECT = ((NRF_UICR->APPROTECT & ~((uint32_t)UICR_APPROTECT_PALL_Msk)) |
                    (UICR_APPROTECT_PALL_Enabled << UICR_APPROTECT_PALL_Pos));
    
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}
    
                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
                NVIC_SystemReset();
            }
    #else
        	if ((NRF_UICR->APPROTECT & UICR_APPROTECT_PALL_Msk) !=
        		(UICR_APPROTECT_PALL_HwDisabled << UICR_APPROTECT_PALL_Pos))
            {
    
                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
                NRF_UICR->APPROTECT = ((NRF_UICR->APPROTECT & ~((uint32_t)UICR_APPROTECT_PALL_Msk)) |
        		    (UICR_APPROTECT_PALL_HwDisabled << UICR_APPROTECT_PALL_Pos));
    
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}
    
                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
                NVIC_SystemReset();
        	}
    #endif
        }
    }

    Thank you for your help and if there is any issue or problem in the code please let me know

  • Hi,

    This looks like a good approach and the code snippet also looks nice. Slight smile

    Regards,

    Priyanka

Reply Children
No Data
Related