Adding mcuboot to tfm provisioning sample

I'm working on a project where its desired to use an initial provisioning image with capability to update firmware after the completion of the provisioning step.  For this purpose I am adding secure boot and mcuboot to the cpuapp.  My builds are successful with original project and with CONFIG_SECURE_BOOT=y, but when I add CONFIG_BOOTLOADER_MCUBOOT=y I get an error:

A domain may only have a single child image.Current domain image is:
empty_net_core, `empty_net_core` is a domain parent image, so you may add
`cpunet` as a child inside `empty_net_core`

How do I workaround this error? 

Is the tfm provisioning sample app built without hci in the cpunet? 

If I want to utilize ble during provisioning, how should I modify the configuration?

Also I have noticed this worrisome message at the end of the cmake generation step:

Dropping partition 'hw_unique_key_partition' since its size is 0.

Is this expected or does it indicate something is missing from the configuration? 

Parents
  • Hi,

    How do I workaround this error? 

    Depending on what you want to do, it could be that you should start with another sample. The TF-M provisioning sample is intended to be used for provisioning keys only, so first program this sample in production and do the provisioning (which writes data to the UICR / KMU), and then flash whatever application, bootloader(s) etc that should be subsequently used. For the intended use case for this sample, I do not think a bootloader makes much sense.

    Is the tfm provisioning sample app built without hci in the cpunet? 

    Yes, the provisioning sample is supposes to just do key provisioning. There is no need for a Bluetooth stack for this.

    If I want to utilize ble during provisioning, how should I modify the configuration?

    If that is the case I suspect you want to do something very differently from what the provisioning sample was intended to do. Perhaps you can elaborate on what that is (starting from a high level)?

Reply
  • Hi,

    How do I workaround this error? 

    Depending on what you want to do, it could be that you should start with another sample. The TF-M provisioning sample is intended to be used for provisioning keys only, so first program this sample in production and do the provisioning (which writes data to the UICR / KMU), and then flash whatever application, bootloader(s) etc that should be subsequently used. For the intended use case for this sample, I do not think a bootloader makes much sense.

    Is the tfm provisioning sample app built without hci in the cpunet? 

    Yes, the provisioning sample is supposes to just do key provisioning. There is no need for a Bluetooth stack for this.

    If I want to utilize ble during provisioning, how should I modify the configuration?

    If that is the case I suspect you want to do something very differently from what the provisioning sample was intended to do. Perhaps you can elaborate on what that is (starting from a high level)?

Children
  • This is for a security focused project.   The debug ports must be locked before generating unique identifiers which must never leave the device.    Since the debug ports must be locked to protect these secrets, a bootloader is necessary to allow transition from the provisioning image to the production image.  The production image will utilize TF-M to access the KMU where the data will be  stored.  The unique keys will never leave the secure TF-M zone.

    And yes, I'm aware that the keys can still be accessed in a lab setting by physically attacking the device, however that is unlikely and can also be mitigated with additional physical protections.

    In addition, in order to streamline the manufacturing procedure,  it is desired for this provisioning image to perform manufacturing validation of all functions of the design.  Since Bluetooth is a critical feature, it is necessary for this provisioning image to include the HCI for BLE function in the cpunet.

    From my read of your response, you would recommend starting with a sample that supports bootloader updates and adding the steps to protect the debug ports and provisioning capability.

    What sample would you recommend in this case? 

    What do I find the  steps to add debug port protection to cpuapp/cpunet in nrf5340?

  • Hi,

    I see. What you describe makes sense and is certainly possible, but not supported by our samples. I would start with a sample that includes most of what you need, and if you are making a Bluetooth product, that means starting with a bluetooth sample. If you are prototyping on a DK first, that means you should use nrf5340dk_nrf5340_cpuapp_ns, where the "_ns" part is for "non-secure". Then the app will be non-secure, and TF-M will be included in the build. Moreover, when building a Bluetooth sample for the app core, hci_rpmsg will be automatically included as a child image for the net core.

    Then there are two separate features that needs to be added: DFU support and provisioning support.

    For DFU, you can refer to the Bootloaders and Device Firmware Updates, as well as nRF53 specifics here.

    For provisioning the app core, you can refer to the provisioning sample implementation, but you will need to do things a bit differently. That is because the sample is designed to run in secure mode, and your app needs to run in non-secure (if not, TF-M is irrelevant). So your application cannot do provision directly, but you will need to make a custom secure service in TF-M that can do it for you. That is discussed in this thread. (Alternatively, it should work to have a secure application first and then DFU in a non-secure application and TF-M after provisioning if that fits better). For provisioning the net core you don't have this complication, as there is no secure/non-secure split there.

  • Thanks for confirming this new approach.  I have some additional questions:

    1) Is the code to disable the debug port enabled by:

          a) a kconfig variable

          b) code in sample source

         c) both

    2) The provisioning sample says it used the empty cpunet to disable the debug port.  Do I need to do this for both cores, the cpunet core only or either?

    3) Any thoughts on the dropping hw unique key partition?  Is this dropped because the nrf5340 stores the keys in the KMU which uses the UICR instead of a dedicated flash partition?

    4) its understandable that the samples don't fulfill all end-user requirements, is there any checklist or guidelines for building production ready apps?   Stuff like setting up pre-generated signing keys, disabling debug ports, validating maximum size DFU of all updatable components..

    Thanks for all your help!

    a*

  • Regarding locking the debug port...

    It appears the code to lock the debug port on the cpunet image is in sub-provisioning_image/cpunet_image/src/main.c

    bool is_writable = nrfx_nvmc_word_writable_check((uint32_t)&NRF_UICR->APPROTECT,
    UICR_APPROTECT_PALL_Protected);

    if (!is_writable) {
    printk("Cannot write to the UICR->APPROTECT register, exiting...!\n");
    return;
    }

    nrfx_nvmc_word_write((uint32_t)&NRF_UICR->APPROTECT, UICR_APPROTECT_PALL_Protected);
    printk("The UICR->APPROTECT register is now configured to deny debugging access for the "
    "network core!\n");
    printk("Success!\n")

    Is there any way to add this code into the hci_rpmsg cpunet image.  Maybe something like a module that just runs some code at startup?

    alternatively, is it possible to perform this code from the cpuapp image instead of from the cpunet image?

  • Hi,

    Anthony Ambuehl said:

    1) Is the code to disable the debug port enabled by:

          a) a kconfig variable

          b) code in sample source

         c) both

    2) The provisioning sample says it used the empty cpunet to disable the debug port.  Do I need to do this for both cores, the cpunet core only or either?

    For understanding access port protection, I would recomend taking a look at the CTRL-AP - Control access port section in the product specification. The key points is that the debug port is locked by default, but can be opened in two different ways. One is with an ERASEALL operation, and the other is if a persistent UICR register unlocks it as well as firmware by writing to a volatile register during startup (APPROTECT.DISABLE / SECUREAPPROTECT.DISABLE). Another important point here, is that this is separate for the network core and for the application core, and for secure and non secure on the application core.

    The tools will unlock the access port by default. For instance, with "nrfjprog --recover" the debug port is opened up in the UICR, and a small firwmare image that unlocks it runtime is flashed. The part that unlocks it runtime (implemented by nrf53_handle_approtect() in modules/hal/nordic/nrfx/mdk/system_nrf53_approtect.h) is also included by default in nRF Connect SDK applications. To don't unlock, add CONFIG_NRF_APPROTECT_LOCK /CONFIG_NRF_SECURE_APPROTECT_LOCK). You may also want to write to UICR to remove the magic word that enabled debugger access if that was set by nrfjprog or other tools.

    Anthony Ambuehl said:
    3) Any thoughts on the dropping hw unique key partition?  Is this dropped because the nrf5340 stores the keys in the KMU which uses the UICR instead of a dedicated flash partition?

    Yes, this is only relevant for devices without a KMU.

    Anthony Ambuehl said:
    4) its understandable that the samples don't fulfill all end-user requirements, is there any checklist or guidelines for building production ready apps?   Stuff like setting up pre-generated signing keys, disabling debug ports, validating maximum size DFU of all updatable components..

    We are working on this, but we do not have guidelines at the moment, unfortunately. At the moment, we mostly provide a toolbox an some samples (which you see in the SDK).

    Anthony Ambuehl said:
    Is there any way to add this code into the hci_rpmsg cpunet image.  Maybe something like a module that just runs some code at startup?

    Yes. The hci_rpmsg is automatically included as a child image, but you are free to modify it (this is the sample found under zephyr/samples/bluetooth/hci_rpmsg). You can also modify just the config by putting a child_image/hci_rpmsg.conf file under your application directory, and configure it to disable the access port by adding CONFIG_NRF_APPROTECT_LOCK=y. Then the code I mentioned earlier in this post is run, and access port protection is disabled. You also want to disable i in the UICR during production programming (typically by writing all zeros) to the APPROTECT register in the network core UICR. If you want to write to the UICR programatically instead of direclty from a debugger you will need to add code for that by modifying hci_rpmsg.

Related