Request for Guidance and Documentation on ERASEPROTECT/APPROTECT/SECUREAPPROTECT

Hi,

We've created an application for the nRF9160 non secure image with TF-M and are looking to add in ERASEPROTECT/APPROTECT/SECUREAPPROTECT functionality. From reading the Production Programming document I can see that when enabling ERASEPROTECT, APPROTECT, and SECUREAPPROTECT, the only way to recover the device is "if the installed firmware and the debugger both write the same non-zero 32-bit KEY value to ERASPROTECT.DISABLE (0x01C)"

My understanding is that since we already have a application that we want to build for non secure (for example, if it was the Blinky sample built for the nrf9160dk_nrf9160_ns with TF-M), we would need to create a separate secure image in order to write the non-zero 32-bit key value to ERASEPROTECT.DISABLE.

My questions are:

  1. How can we create a separate secure image with our nonsecure application? As I understand, the secure image should run first before handing over control of the execution to the nonsecure application. What would be the best way to add an additional secure image to something like the nonsecure Blinky sample? Would this be a child image?
  2. Is there any examples of how to interact with the ERASEPROTECT, APPROTECT, and SECUREAPPROTECT settings from the application side? I unfortunately don't have much experience working directly with various registers on the nRF9160 and would be happy to get any help possible, especially with regards to what needs to be provisioned to interact with the registers and if there is a getting started guide for tasks like this. I want to create a script that upon boot up of the nRF9160, the program: 
    1. Checks if any of the ERASEPROTECT, APPROTECT, and SECUREAPPROTECT functionalities are not enabled. If any of these are not enabled, the program will enable the protection and perform a reset of the device. On the next boot up, all three of the protections should be enabled.
    2. If ERASEPROTECT, APPROTECT, and SECUREAPPROTECT are all enabled, it will write a 32-bit key to ERASPROTECT.DISABLE. This way, if we need to recover the device, we can use the SWD to write in the 32-bit key to trigger an erase all
    3. Finally, hands over execution to our nonsecure program
  3. Our current application uses MCUBOOT and supports OTA. Would ERASEPROTECT affect the application's ability to download new application updates and boot up with the new updates?

I've found some previous posts which seem to be quite helpful, however I'm still unsure of how I would need to go about integrating it into an existing nonsecure application. 
This post seems fairly helpful in talking about how to create a non-ns script to remove erase protect. However, I'm having a bit of difficulty following/finding the documentation on modifying/reading contents for items like NRF_NVMC and NRF_UICR through the application, and what the particular bits like (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos) being set indicate. 

Thank you in advance!

  • Hi Simon, 

    My apologies in advance if I am incorrect about this, but I want to be able to write (or trigger a write for) a key to the ERASEPROTECT.disable register from my current application.

    To my knowledge, the major constricting requirements are that my application is required to be built for ns (i.e. nrf_modem_lib requires to be run from non-secure firmware), it uses TF-M, and uses MCUboot (for FOTA). I believe the nrf asset tracker v2 has a similar set of requirements, so it could be a good reference for what solution would be needed.

    From Rory's answer above, the best way we know of to set this consistently is through editing the MCUboot Bootloader main.c file to include the following write:


    if (NRF_UICR_S->ERASEPROTECT != UICR_ERASEPROTECT_PALL_Unprotected)
    {
        NRF_CTRL_AP_PERI_S->ERASEPROTECT.DISABLE = (uint32_t)0xDEADF00D;
    }

    I would need a consistent way to be able to set this information either before my application boots or to be triggered to be written, so it can still be recovered when all three of the erase protect, approtect, and secureapprotect functionalities are enabled. The downside of directly editing the MCUboot file is that this change is less portable -- if I were to have a coworker build my application, I would need to have them edit the MCUboot file in-tree. Additionally, the Bootloader isn't upgradable in this case, so the method for generating/setting the key cannot be changed over an OTA update. Furthermore, modifying the MCUBoot Bootloader directly with anything more complex seems risky, as I don't fully understand the MCUBoot Bootloader code. I have some additional logic I want to add for generating the key, but I am not sure if it is safe to add this logic to the Bootloader. 

    I've been able to replicate the ability to write this key in a couple of other ways, each with challenges to integrate into my application:

    - Creating a script built for the nrf9160dk_nrf9160 (not ns) to set the register, however I didn't have much luck integrating this into my current application, as my current application is built for nrf9160dk_nrf9160_ns. I attempted to build a child image with the goal of the secure child image to run and set the key before the main image boots, but was unsuccessful. I can attach a zip of this attempt if helpful.

    - Using the TF-M secure peripheral/partition examples to have the non secure partition send a request to execute some code on the secure environment. This doesn't appear to work in my case since different TF-M build profiles beyond the default don't seem to build with MCUboot. The TF-M secure peripheral/partition seems to require some customization to the TF-M profile settings.

    Thank you in advance for your help!

  • Thanks   for the reply, Understood your comments, 

    since I am not afford to brick another device

    just need a reconfirmation for below steps.

    1. flash this sample code.

    void main(void)
    {
    	const uint32_t key = 0xDEADBEEF;
    
    	NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
    
    	while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
    
    	NRF_CTRL_AP_PERI_S->ERASEPROTECT.DISABLE = key;
    
    	printk("ERASEPROTECT         0x%X\n", NRF_UICR->ERASEPROTECT);
    	printk("ERASEPROTECT.LOCK    0x%X\n", NRF_CTRL_AP_PERI_S->ERASEPROTECT.LOCK);
    	printk("ERASEPROTECT.DISABLE 0x%X\n", NRF_CTRL_AP_PERI_S->ERASEPROTECT.DISABLE);
    }


    2. cmd line values to set protections and reboot the device should enable erase protect with disabling
    key value of 0xDEADBEEF  

     

    # Enable APPROTECT
    nrfjprog --family nRF91 --memwr 0x00FF8000 --val 0
    # Enable SECUREAPPROTECT
    nrfjprog --family nRF91 --memwr 0x00FF802C --val 0
    # Enable ERASEPROTECT
    nrfjprog --family nRF91 --memwr 0x00FF8030 --val 0



    3. JLink script to unlock eraseprotect.

    USB 960093400
    SWDSelect
    SWDWriteDP 1 0x50000000
    SWDWriteDP 2 0x04000010
    SWDWriteAP 3 0xDEADBEEF
    
    sleep 10000
    SWDWriteDP 2 0x04000000
    SWDWriteAP 1 0x00000001
    SWDReadAP 1
    SWDReadAP 1
    sleep 5000
    SWDWriteAP 1 0x00000000
    SWDReadAP 1
    SWDReadAP 1
    sleep 1000
    
    exit

  • Hi Dinesh,

    I just wanted to give you a bit of a recommendation while you do your testing for now. If you can't afford to brick a couple of devices while developing, I recommend doing the ERASEPROTECT development separately from using the APPROTECT and SECUREAPPROTECT for now. This way, if you are unable to get the ERASEPROTECT.disable to work, you can always use use 

    nrfjprog --family nRF91 --recover

    to recover the device and erase all of the firmware. When APPROTECT and SECUREAPPROTECT are enabled, I haven't been able to use the recover command. 

    Once you've finished with developing your solution and can consistently disable ERASEPROTECT by supplying the erase protect key, you could return to also using the APPROTECT and SECUREAPPROTECT functionalities.

    I recommend changing your second step to 

    # Enable ERASEPROTECT
    nrfjprog --family nRF91 --memwr 0x00FF8030 --val 0

    for the meantime until your ERASEPROTECT disable solution works smoothly.

  • Hi,

    I will continue to help in this case.

    blasph said:
    My apologies in advance if I am incorrect about this, but I want to be able to write (or trigger a write for) a key to the ERASEPROTECT.disable register from my current application.

    Yes, that is a good idea.
    I would generally recommend writing your key to this register before enabling eraseprotect.
    This is so that you are sure that you never lock the device before a key is set.

    blasph said:
    that my application is required to be built for ns (i.e. nrf_modem_lib requires to be run from non-secure firmware)

    Correct

    blasph said:
    believe the nrf asset tracker v2 has a similar set of requirements, so it could be a good reference for what solution would be needed.

    Also yes.

    blasph said:

    From Rory's answer above, the best way we know of to set this consistently is through editing the MCUboot Bootloader main.c file to include the following write:

    Doing this in MCUboot is a valid option.

    blasph said:
    The downside of directly editing the MCUboot file is that this change is less portable -- if I were to have a coworker build my application, I would need to have them edit the MCUboot file in-tree.

    We will move from multi-image builds to sysbuild soon, and then I think it will be easier to do something like this.
    But we are not there yet, so for now, I agree, it is less portable.

    blasph said:
    Furthermore, modifying the MCUBoot Bootloader directly with anything more complex seems risky, as I don't fully understand the MCUBoot Bootloader code. I have some additional logic I want to add for generating the key, but I am not sure if it is safe to add this logic to the Bootloader. 

    I agree very much with this. It can be risky to do this inside MCUboot if you want to generate the

    blasph said:
    - Creating a script built for the nrf9160dk_nrf9160 (not ns) to set the register, however I didn't have much luck integrating this into my current application, as my current application is built for nrf9160dk_nrf9160_ns. I attempted to build a child image with the goal of the secure child image to run and set the key before the main image boots, but was unsuccessful. I can attach a zip of this attempt if helpful.

    I do not understand completely what you are trying to do here.
    If you want to write to secure registers when TF-M is enabled, you options are MCUboot or how it is done in the TF-M secure peripheral partition sample, by creating a Application RoT Service. See An Introduction to Trusted Firmware-M (TF-M) for more information on TF-M.

    blasph said:
    - Using the TF-M secure peripheral/partition examples to have the non secure partition send a request to execute some code on the secure environment. This doesn't appear to work in my case since different TF-M build profiles beyond the default don't seem to build with MCUboot. The TF-M secure peripheral/partition seems to require some customization to the TF-M profile settings.

    TF-M will build as part of your application, and does not know about MCUboot.
    Either set ERASEPROTECT.DISABLE from MCUboot or from TF-M.

    See TF-M secure peripheral partition sample.

    EDIT:

    Just want to add some nuance. While it is risky to do stuff in MCUboot, setting ERASEPROTECT.DISABLE later is also risky, as more things can go wrong before you can revert ERASEPROTECT.
    So in the end, I do not see any "perfect" place to do this operation. So you kindof need to decide if you want a more robust MCUboot, so you know you can DFU if anything fails. Or if you want a more robust ERASEPROTECT disable, so you can reprogram if anything fails.

    Regards,
    Sigurd Hellesvik

  • Hi Sigurd,

    Thank you for getting back to me!

    I would generally recommend writing your key to this register before enabling eraseprotect.
    This is so that you are sure that you never lock the device before a key is set.

    My impression was that the ERASEPROTECT.disable key had to be set on each reboot. Does the ERASEPROTECT.disable key persist across reboots, and only need to be set once then?

    We will move from multi-image builds to sysbuild soon, and then I think it will be easier to do something like this.
    But we are not there yet, so for now, I agree, it is less portable.

    Thank you for letting me know about this. I encountered a few examples in the 2.4.0 examples and wasn't sure what it was about.

    If you want to write to secure registers when TF-M is enabled, you options are MCUboot or how it is done in the TF-M secure peripheral partition sample, by creating a Application RoT Service. See An Introduction to Trusted Firmware-M (TF-M) for more information on TF-M.

    I am currently trying on implementing this and have been working on it for the last couple of days without success. I have been able to successfully able to use the example to create and set the Eraseprotect key for my device. However, I am having difficulty integrating it into my main application. 

    In my attempt to integrate it into my main application:

    - I copied over the relevant CMakeLists.txt additions from the tfm_secure_peripheral sample and merged them into my main CMakeLists.txt file

    - Modified the secure_peripheral_partition.c file to no longer use the sample peripherals and only generate and set the key (and removed the init and while loop from the tfm_spp_main, as I only need this code to run once at boot up and not again)

    - copied over my modified secure_peripheral_partition directory

    - copied over the prj.conf symbols CONFIG_TFM_IPC=y and CONFIG_TFM_ISOLATION_LEVEL=1 from the sample. The TFM_PROFILE_NOT_SET=y makes my project not build, but I've also removed this symbol from the sample and the sample still works

    When running my application, I see the key now gets set properly, but my main application fails to run. Would it be possible for me to create a private ticket to see if I could get some help with this final integration step? 

    I will continue doing some further testing and will get back to you as soon as I have new information.

    Thank you for the help!

Related