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 Edward

    Raoul is currently out of office so I've been asked to take over this case in his absence.

    Please check out this case by Hung, and the one he links to, where there is a thorough discussion on how to use the ERASEPROTECT.DISABLE register. Let me know if something there is unclear, but I think most aspects are covered.

    Best regards,

    Simon

  • Hi Simon,

    Thank you for sharing this case. I was wondering, does Nordic publish some sort of guide/sample of how to add the write the ERASEPROTECT.DISABLE key to an existing application? If so, that would be very helpful. 

    Thank you!

  • Hi blasph,

    We were in a similar situation, and figured out how to enable/disable all three protections: APPROTECT, SECUREAPPROTECT, and ERASEPROTECT.

    First off, we found that CONFIG_NRF_APPROTECT_LOCK and CONFIG_NRF_SECURE_APPROTECT_LOCK are only supported on the nRF52 and nRF53 series SoCs, and cannot be used with the nRF91 series. See documentation here.

    Setting these protections on the nRF9160 seems to only be possible by writing to the UICR with a JLink during production.

    Mechanism to set ERASEPROTECT.DISABLE in MCUBoot

    This is very important to implement first, as it is needed if you ever want to disable ERASEPROTECT. Without this mechanism, you will never be able to erase the chip again once ERASEPROTECT is enabled, and it could become a brick.

    We decided to trigger setting NRF_CTRL_AP_PERI_S->ERASEPROTECT.DISABLE to our special 32-bit unlock key in MCUBoot only when serial recovery is forced via GPIO button press. Just before boot_serial_enter() is called in MCUBoot, we check if NRF_UICR_S->ERASEPROTECT is enabled, and if it is, set NRF_CTRL_AP_PERI_S->ERASEPROTECT.DISABLE = (uint32_t)0xDEADF00D.

    bootloader/mcuboot/boot/zephyr/main.c

    #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO
        if (detect_pin() &&
                !boot_skip_serial_recovery()) {
    
            if (NRF_UICR_S->ERASEPROTECT != UICR_ERASEPROTECT_PALL_Unprotected)
            {
                // Disable ERASEPROTECT in serial recovery
                NRF_CTRL_AP_PERI_S->ERASEPROTECT.DISABLE = (uint32_t)0xDEADF00D;
            }
            boot_serial_enter();
        }
    #endif

    If serial recovery is not activated at boot, you can optionally prevent ERASEPROTECT.DISABLE from being written to until next reboot by setting NRF_CTRL_AP_PERI_S->ERASEPROTECT.LOCK = (uint32_t)0x00000001

        ...
        if (NRF_UICR_S->ERASEPROTECT != UICR_ERASEPROTECT_PALL_Unprotected)
        {
            // Lock ERASEPROTECT before booting image
            NRF_CTRL_AP_PERI_S->ERASEPROTECT.LOCK = (uint32_t)0x00000001;
        }
        FIH_CALL(boot_go, fih_rc, &rsp);
        ...

    Enabling APPROTECT, SECUREAPPROTECT, and ERASEPROTECT in Production

    We learned that you can use a sequence of nrfjprog commands, or a JLink Commander script to program our factory_image.hex file, and then write to the UICR to set all three protections, followed by a pin reset.

    nrfjprog commands:

    nrfjprog.exe --family NRF91 --program factory_image.hex --chiperase --verify factory_image.hex
    nrfjprog.exe --family NRF91 --memwr 0x00FF8000 --val 0
    nrfjprog.exe --family NRF91 --memwr 0x00FF802C --val 0
    nrfjprog.exe --family NRF91 --memwr 0x00FF8030 --val 0
    nrfjprog.exe --family NRF91 --pinreset

    JLink Commander script:

    device NRF9160_XXAA
    selectinterface SWD
    speed 4000
    connect
    halt
    erase
    loadfile factory_image.hex
    write4 0x00FF8000 0
    write4 0x00FF802C 0
    write4 0x00FF8030 0
    RSetType 2
    reset
    exit

    At this point, the nRF9160 should have all three protections set. The JLink debugger will no longer work at all if you try to even connect and detect the Chip ID. The nRF9160 is completely protected from any and all access over the SWD interface, including flash read, write, and erase, and is considered "sealed". The only access that can be done over CTRL-AP is to set ERASEPROTECT.DISABLE to hopefully disable ERASEPROTECT and allow an ERASEALL.


    Disabling ERASEPROTECT and Performing ERASEALL

    If you do need to erase a device that has been sealed, you must first boot the nRF9160 and trigger the mechanism to set ERASEPROTECT.DISABLE to the known 32-bit key value.

    For this example, serial recovery must be forced via button press so that ERASEPROTECT.DISABLE is set to our key 0xDEADF00D.

    Then, the following JLink Commander script can be used to set the Ctrl-AP ERASEPROTECT.DISABLE to the matching key, and then trigger an ERASEALL and RESET.

    JLink Commander script:

    // Setup SWD
    SWDSelect               // Activate SWD
    SWDWriteDP 1 0x50000000 // Enable debug power
    
    // Set ERASEPROTECT.DISABLE
    SWDWriteDP 2 0x04000010 // Select the 0x04XXXXXX Access Port and 0xXXXXX01X Register bank in the access port
    SWDWriteAP 3 0xDEADF00D // CTRL-AP Bank 1, register offset 3 (ERASEPROTECT.DISABLE 0x01C)
    
    // Perform ERASEALL
    SWDWriteDP 2 0x04000000 // Select the 0x04XXXXXX Access Port and 0xXXXXX00X Register bank in the access port
    SWDWriteAP 1 0x00000001 // CTRL-AP Bank 0, register offset 1 (ERASEALL 0x004)
    SWDReadAP 2             // CTRL-AP Bank 0, register offset 2 (ERASEALLSTATUS 0x008)
    SWDReadAP 2             // Second read returns the value: 0 = Ready, 1 = Busy
    sleep 2000
    SWDReadAP 2             // CTRL-AP Bank 0, register offset 2 (ERASEALLSTATUS 0x008)
    SWDReadAP 2             // Second read returns the value: 0 = Ready, 1 = Busy
    
    // Perform RESET
    SWDWriteAP 0 0x00000001 // CTRL-AP Bank 0, register offset 0 (RESET 0x000)
    SWDWriteAP 0 0x00000000 // CTRL-AP Bank 0, register offset 0 (RESET 0x000)
    SWDReadAP 0             // CTRL-AP Bank 0, register offset 0 (RESET 0x000)
    SWDReadAP 0             // Second read returns the value: 0 = NoReset, 1 = Reset
    exit

    Hope this helps!

  • Hi Rory,

    Thank you very much for replying and for the in depth write up! 

    Thank you for clarifying that those KCONFIGs don't work for the nRF9160. 

    The information you provided about setting the protections via the JLink Commander scripts and modifying the mcuboot main.c is extremely helpful, thank you for sharing that! I'll try implementing this over the next couple of days and will circle back with my findings. 

  • Hi

    We have a GitHub script that should work for disabling eraseprotect that Sigurd links to in this ticket. Here he also links to the device protection Application note that can be usefult for additional information. Other than that we don't have a specific sample that does this I'm afraid.

    Best regards,

    Simon

Related