nRF9160: Enable APPROTECT from non-secure code

Is it possible to write to the UICR to set APPROTECT from non-secure code?

The description in section 4.4.8.10 of the nRF9160_PS_v2.1 claims to "Allow non-secure code to set APPROTECT" and defines a key value that must be set along with the Set bit.

Section 4.4.4 of the nRF9160 PS v2.1 defines a procedure for setting APPROTECT by writing to WRITEUICRNS after first setting SECUREAPPROTECT. I'm not sure how to execute this procedure, and not example is given.

I've tried writing to WRITEUICRNS with the code below, and APPROTECT never actually gets enabled.

    // Write UICR from non-secure code
    NRF_NVMC->WRITEUICRNS = (uint32_t)((NVMC_WRITEUICRNS_KEY_Keyvalid << NVMC_WRITEUICRNS_KEY_Pos) |
                                       (NVMC_WRITEUICRNS_SET_Set << NVMC_WRITEUICRNS_SET_Pos));

Parents
  • Hi Rory,

    Just letting you know that I've seen your case. I had some other cases to take care of and now I'll just need some time to research this APPROTECT behavior. I'll get back to you soon.

    Best regards,

    Raoul

  • Hi again,

    Thanks for waiting. I'll try to give an overview, which hopefuly is useful to others as well:

    To disable APPROTECT, a write must be performed to UICR (see Enabling access port protection mechanism docs).

    The nRF9160 has a "system protection unit" (SPU), that determines which resources (like memory and peripherals) can be accessed from where.

    The SPU -> UICR subsection states the following:

    The user information configuration registers (UICR) and factory information configuration registers (FICR) are always considered as secure.

    So, since UICR is always secure, APPROTECT can't be enabled or disabled from what ARM calls the "Non-Secure Processing Environment" (NSPE).

    The suggested way to do this, is creating a custom Application Root-of-Trust (RoT) Service to do whatever you need to do with the UICR.

    Then you can call the Application RoT Service from the NSPE. Please see TF-M secure peripheral partition for a sample on how to write code for the SPE (Secure Processing Environment)

    For an intro to TF-M concepts such as Application RoT Service and SPE/NSPE, see Blog: An Introduction to Trusted Firmware-M (TF-M)

    However as my colleague suggests, this might be an XY Problem. Why are you trying to do this? If all you are trying to do is make use of the APPROTECT mechanism, know that NCS has kconfig options for this: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/app_dev/ap_protect/index.html#configuration-overview-in-the-ncs

    The idea is that you create a build configuration for development that leaves the AP open, and then you have a "release" build configuration where the Kconfig option is set to lock the AP (preventing anyone from reading out your firmware without erasing all of flash first).

    You should only need to define your own RoT service if you have the need for some custom mechanism that let's you arbitrarily lock the AP from within your code.

    Does that clarify things?

    Best regards,

    Raoul

  • This clears a few things up for me.

    I originally thought I could just define CONFIG_NRF_APPROTECT_LOCK=y, but this is only supported on nRF52 and nRF53 series SoCs, per the documentation. This config option does nothing on the nRF9160.

    What we are trying to do is enable APPROTECT from our non-secure application to enforce readback protection over the SWD port. We have devices deployed that are based on NCS 2.3.0 and are compiled with the default TF-M profile. These device never had APPROTECT set in production, so we are trying to enable it now with a FOTA update.

    Can you please explain more about the use cases around using NRF_NVMC->WRITEUICRNS to "Allow non-secure code to set APPROTECT" as the nRF9160 product specification suggest? Is there any example code you can provide on how you use this register?

    I see how we could create a RoT service just to enable APPROTECT in the UICR if it is not already enabled, but I was hoping WRITEUICRNS was designed to do that for us, as it is described.

    Thanks for your help!

  • Hi Rory, 

    Sorry for the late response. Raoul is OoO and asked me to look into this thread.

    Rory said:
    Can you please explain more about the use cases around using NRF_NVMC->WRITEUICRNS to "Allow non-secure code to set APPROTECT" as the nRF9160 product specification suggest? Is there any example code you can provide on how you use this register?

    Unfortunately there seems to be no samples to demonstrate the use of this register. UICR register only has read access from non-secure code. You need to define own secure functions in SPM that can be called from the non-secure domain.There is some old guideline given which might help you to get an idea of how to write such functions.

  • I am using TF-M, not SPM. Is there a example of how to use TF-M to write to the UICR? All I need is a few lines of code to run on every bootup that will check if APPROTECT is disabled (set to 0xFFFFFFFF), and if it is disabled, enable is by writing 0x00000000 to APPROTECT. I understand this requires enabling flash write operations in the NVMC, writing to the UICR, and then waiting for the write to complete before disabling flash write mode. Any examples you can point me towards would be greatly appreciated. Thanks!

  • It is mostly like below code snippet

    /* Enable write mode in NVMC */
    NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Wen;
    while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
    
    /* Write new value to UICR->XXXX */
    NRF_UICR_S->XXXXX = uicr_new_value;
    while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
    
    
    /* Enable read mode in NVMC */
    NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Ren;
    while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);

Reply
  • It is mostly like below code snippet

    /* Enable write mode in NVMC */
    NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Wen;
    while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
    
    /* Write new value to UICR->XXXX */
    NRF_UICR_S->XXXXX = uicr_new_value;
    while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
    
    
    /* Enable read mode in NVMC */
    NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Ren;
    while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);

Children
No Data
Related