CONFIG_BOOT_SIGNATURE_KEY_FILE doesn't correctly get propagated to MCUBoot build

I'm setting CONFIG_BOOT_SIGNATURE_KEY_FILE while building an application with the nRF SDK 1.3.0 from the command line using west:

west build -t flash -p auto -b playerdata_edge_v2_0_3 edge -DCONFIG_BOOT_SIGNATURE_KEY_FILE=\"edge-v2-production.pem\"

I see from the application ninja logs that this is correctly signing the image with the specified key (albeit, it assumes that the key is located in `bootloader/mcuboot`, but I can live with that).

However, the public key baked into the MCUBoot build is incorrectly being extracted from the default MCUBoot key, as we can see from the MCUBoot ninja logs:

build zephyr/autogen-pubkey.c: CUSTOM_COMMAND /Users/hayden/development/PlayerData/edge-v2/bootloader/mcuboot/root-rsa-2048.pem || zephyr/driver_validation_h_target zephyr/kobj_types_h_target zephyr/offsets zephyr/offsets_h zephyr/parse_syscalls_target zephyr/syscall_list_h_target zephyr/zephyr_generated_headers
  COMMAND = cd /Users/hayden/development/PlayerData/edge-v2/build/mcuboot && /Users/hayden/development/PlayerData/edge-v2/env/bin/python3.8 /Users/hayden/development/PlayerData/edge-v2/bootloader/mcuboot/scripts/imgtool.py getpub -k /Users/hayden/development/PlayerData/edge-v2/bootloader/mcuboot/root-rsa-2048.pem > /Users/hayden/development/PlayerData/edge-v2/build/mcuboot/zephyr/autogen-pubkey.c
  DESC = Generating zephyr/autogen-pubkey.c
  restat = 1

It looks like the config variable isn't being correctly passed through to the MCUBoot build.

I've tried adding it to the `SHARED_MULTI_IMAGE_VARIABLES` list from my application CMakeLists.txt:

list(APPEND SHARED_MULTI_IMAGE_VARIABLES CONFIG_BOOT_SIGNATURE_KEY_FILE)

The variable is now being set in `extra_kconfig_options.conf`, however it is missing quotes so the toolchain is refusing to accept it:

/Users/hayden/development/PlayerData/edge-v2/build/mcuboot/zephyr/misc/generated/extra_kconfig_options.conf:2: warning: malformed string literal in assignment to BOOT_SIGNATURE_KEY_FILE (defined at /Users/hayden/development/PlayerData/edge-v2/bootloader/mcuboot/zephyr/Kconfig:38). Assignment ignored.

CONFIG_BOOT_SIGNATURE_KEY_FILE=edge-v2-production.pem

Is this a bug, or am I not setting the right config options here?

Parents
  • Hi!

    Looking at the CMakeLists.txt for the mcuboot project here:
    https://github.com/NordicPlayground/fw-nrfconnect-mcuboot/blob/v1.4.99-ncs2/boot/zephyr/CMakeLists.txt#L192


    We can see here that you can either provide an absolute path to the key-file, or place the key-file in MCUBOOT_DIR -> ncs\bootloader\mcuboot


    Note that the script that does automatic signing using imgtool.py, seems to expect the key to be located in ncs\bootloader\mcuboot. Ref: https://github.com/NordicPlayground/fw-nrfconnect-mcuboot/blob/v1.4.99-ncs2/zephyr/CMakeLists.txt#L103 


    If you are using absolute paths, change line 103 here to --key ${CONFIG_BOOT_SIGNATURE_KEY_FILE}

    When it comes to actually setting CONFIG_BOOT_SIGNATURE_KEY_FILE, I believe you also need to configure it in a dedicated .conf file for MCUBoot.

    In the CMakeLists.txt for your application, add something like this:


    set(mcuboot_CONF_FILE
    prj.conf
    ${CMAKE_CURRENT_LIST_DIR}/mcuboot.conf
    )

    This is similar to how we have a dedicated .conf for SPM.

    set(spm_CONF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/spm.conf)

    For the absolute path, mcuboot.conf would look something like this:

    CONFIG_BOOT_SIGNATURE_KEY_FILE="C:/ncs/nrf/applications/asset_tracker/my_root-rsa-2048.pem"

    For keys placed in MCUBOOT_DIR -> ncs\bootloader\mcuboot

    CONFIG_BOOT_SIGNATURE_KEY_FILE="my_root-rsa-2048.pem"
    Best regards,
    Heidi

Reply
  • Hi!

    Looking at the CMakeLists.txt for the mcuboot project here:
    https://github.com/NordicPlayground/fw-nrfconnect-mcuboot/blob/v1.4.99-ncs2/boot/zephyr/CMakeLists.txt#L192


    We can see here that you can either provide an absolute path to the key-file, or place the key-file in MCUBOOT_DIR -> ncs\bootloader\mcuboot


    Note that the script that does automatic signing using imgtool.py, seems to expect the key to be located in ncs\bootloader\mcuboot. Ref: https://github.com/NordicPlayground/fw-nrfconnect-mcuboot/blob/v1.4.99-ncs2/zephyr/CMakeLists.txt#L103 


    If you are using absolute paths, change line 103 here to --key ${CONFIG_BOOT_SIGNATURE_KEY_FILE}

    When it comes to actually setting CONFIG_BOOT_SIGNATURE_KEY_FILE, I believe you also need to configure it in a dedicated .conf file for MCUBoot.

    In the CMakeLists.txt for your application, add something like this:


    set(mcuboot_CONF_FILE
    prj.conf
    ${CMAKE_CURRENT_LIST_DIR}/mcuboot.conf
    )

    This is similar to how we have a dedicated .conf for SPM.

    set(spm_CONF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/spm.conf)

    For the absolute path, mcuboot.conf would look something like this:

    CONFIG_BOOT_SIGNATURE_KEY_FILE="C:/ncs/nrf/applications/asset_tracker/my_root-rsa-2048.pem"

    For keys placed in MCUBOOT_DIR -> ncs\bootloader\mcuboot

    CONFIG_BOOT_SIGNATURE_KEY_FILE="my_root-rsa-2048.pem"
    Best regards,
    Heidi

Children
  • I have tried the above steps but unfortunately it dint worked

    I am on ncs master branch and using the serial lte modem application (~\master\nrf\applications\serial_lte_modem)

    build logs

    C:\Data\GIT\ncs\master\nrf\applications\serial_lte_modem>west build -b nrf9160_pca10090ns -d build
    -- west build: generating a build system
    Including boilerplate (Zephyr base): C:/Data/GIT/ncs/master/zephyr/cmake/app/boilerplate.cmake
    -- Application: C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem
    -- Using NCS Toolchain 1.3.0 for building. (C:/Data/GIT/ncs/master/toolchain/cmake)
    -- Zephyr version: 2.4.0 (C:/Data/GIT/ncs/master/zephyr)
    -- Found Python3: C:/Data/GIT/ncs/master/toolchain/opt/bin/python.exe (found suitable exact version "3.8.2") found components:  Interpreter
    -- Found west (found suitable version "0.7.3", minimum required is "0.7.1")
    -- Board: nrf9160_pca10090ns
    CMake Warning at C:/Data/GIT/ncs/master/zephyr/cmake/app/boilerplate.cmake:241 (message):
      Deprecated BOARD=nrf9160_pca10090ns name specified, board automatically
      changed to: nrf9160dk_nrf9160ns.
    Call Stack (most recent call first):
      C:/Data/GIT/ncs/master/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:24 (include)
      C:/Data/GIT/ncs/master/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:35 (include_boilerplate)
      CMakeLists.txt:25 (find_package)
    
    
    -- Cache files will be written to: C:/Data/GIT/ncs/master/zephyr/.cache
    -- Found dtc: C:/Data/GIT/ncs/master/toolchain/opt/bin/dtc.exe (found suitable version "1.4.7", minimum required is "1.4.6")
    -- Found toolchain: gnuarmemb (C:/Data/GIT/ncs/master/toolchain/opt)
    -- Found BOARD.dts: C:/Data/GIT/ncs/master/zephyr/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160ns.dts
    -- Found devicetree overlay: C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/nrf9160dk_nrf9160ns.overlay
    -- Generated zephyr.dts: C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/zephyr/zephyr.dts
    -- Generated devicetree_unfixed.h: C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/zephyr/include/generated/devicetree_unfixed.h
    Parsing C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/Kconfig
    Loaded configuration 'C:/Data/GIT/ncs/master/zephyr/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160ns_defconfig'
    Merged configuration 'C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/prj.conf'
    Configuration saved to 'C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/zephyr/.config'
    Kconfig header saved to 'C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/zephyr/include/generated/autoconf.h'
    -- The C compiler identification is GNU 9.2.1
    -- The CXX compiler identification is GNU 9.2.1
    -- The ASM compiler identification is GNU
    -- Found assembler: C:/Data/GIT/ncs/master/toolchain/opt/bin/arm-none-eabi-gcc.exe
    Changed board to secure nrf9160dk_nrf9160 (NOT NS)
    
    === child image spm -  begin ===
    Including boilerplate (Zephyr base): C:/Data/GIT/ncs/master/zephyr/cmake/app/boilerplate.cmake
    -- Application: C:/Data/GIT/ncs/master/nrf/samples/spm
    -- Using NCS Toolchain 1.3.0 for building. (C:/Data/GIT/ncs/master/toolchain/cmake)
    -- Zephyr version: 2.4.0 (C:/Data/GIT/ncs/master/zephyr)
    -- Found Python3: C:/Data/GIT/ncs/master/toolchain/opt/bin/python.exe (found suitable exact version "3.8.2") found components:  Interpreter
    -- Found west (found suitable version "0.7.3", minimum required is "0.7.1")
    -- Board: nrf9160dk_nrf9160
    -- Cache files will be written to: C:/Data/GIT/ncs/master/zephyr/.cache
    -- Found dtc: C:/Data/GIT/ncs/master/toolchain/opt/bin/dtc.exe (found suitable version "1.4.7", minimum required is "1.4.6")
    -- Found toolchain: gnuarmemb (C:/Data/GIT/ncs/master/toolchain/opt)
    -- Found BOARD.dts: C:/Data/GIT/ncs/master/zephyr/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160.dts
    -- Found devicetree overlay: C:/Data/GIT/ncs/master/nrf/samples/spm/nrf9160dk_nrf9160.overlay
    -- Generated zephyr.dts: C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/spm/zephyr/zephyr.dts
    -- Generated devicetree_unfixed.h: C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/spm/zephyr/include/generated/devicetree_unfixed.h
    Parsing C:/Data/GIT/ncs/master/zephyr/Kconfig
    Loaded configuration 'C:/Data/GIT/ncs/master/zephyr/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_defconfig'
    Merged configuration 'prj.conf'
    Merged configuration 'C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/child_secure_partition_manager.conf'
    Configuration saved to 'C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/spm/zephyr/.config'
    Kconfig header saved to 'C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/spm/zephyr/include/generated/autoconf.h'
    -- The C compiler identification is GNU 9.2.1
    -- The CXX compiler identification is GNU 9.2.1
    -- The ASM compiler identification is GNU
    -- Found assembler: C:/Data/GIT/ncs/master/toolchain/opt/bin/arm-none-eabi-gcc.exe
    -- Configuring done
    -- Generating done
    -- Build files have been written to: C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/spm
    === child image spm -  end ===
    
    Changed board to secure nrf9160dk_nrf9160 (NOT NS)
    
    === child image mcuboot -  begin ===
    Including boilerplate (Zephyr base): C:/Data/GIT/ncs/master/zephyr/cmake/app/boilerplate.cmake
    -- Application: C:/Data/GIT/ncs/master/bootloader/mcuboot/boot/zephyr
    -- Using NCS Toolchain 1.3.0 for building. (C:/Data/GIT/ncs/master/toolchain/cmake)
    -- Zephyr version: 2.4.0 (C:/Data/GIT/ncs/master/zephyr)
    -- Found Python3: C:/Data/GIT/ncs/master/toolchain/opt/bin/python.exe (found suitable exact version "3.8.2") found components:  Interpreter
    -- Found west (found suitable version "0.7.3", minimum required is "0.7.1")
    -- Board: nrf9160dk_nrf9160
    -- Cache files will be written to: C:/Data/GIT/ncs/master/zephyr/.cache
    -- Found dtc: C:/Data/GIT/ncs/master/toolchain/opt/bin/dtc.exe (found suitable version "1.4.7", minimum required is "1.4.6")
    -- Found toolchain: gnuarmemb (C:/Data/GIT/ncs/master/toolchain/opt)
    -- Found BOARD.dts: C:/Data/GIT/ncs/master/zephyr/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160.dts
    -- Found devicetree overlay: C:/Data/GIT/ncs/master/bootloader/mcuboot/boot/zephyr/dts.overlay
    -- Generated zephyr.dts: C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/mcuboot/zephyr/zephyr.dts
    -- Generated devicetree_unfixed.h: C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/mcuboot/zephyr/include/generated/devicetree_unfixed.h
    CMake Error at C:/Data/GIT/ncs/master/zephyr/cmake/kconfig.cmake:181 (message):
      File not found:
      C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/mcuboot.conf
    Call Stack (most recent call first):
      C:/Data/GIT/ncs/master/zephyr/cmake/app/boilerplate.cmake:591 (include)
      C:/Data/GIT/ncs/master/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:24 (include)
      C:/Data/GIT/ncs/master/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:35 (include_boilerplate)
      CMakeLists.txt:44 (find_package)
    
    -- Configuring incomplete, errors occurred!
    
    CMake Error at C:/Data/GIT/ncs/master/nrf/cmake/multi_image.cmake:195 (message):
      CMake generation for mcuboot failed, aborting.  Command: 1
    Call Stack (most recent call first):
      C:/Data/GIT/ncs/master/nrf/cmake/multi_image.cmake:56 (add_child_image_from_source)
      C:/Data/GIT/ncs/master/nrf/cmake/mcuboot.cmake:90 (add_child_image)
      C:/Data/GIT/ncs/master/bootloader/mcuboot/zephyr/CMakeLists.txt:1 (include)
    
    
    -- Configuring incomplete, errors occurred!
    See also "C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/CMakeFiles/CMakeOutput.log".
    See also "C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/build/CMakeFiles/CMakeError.log".
    FATAL ERROR: command exited with status 1: 'C:\Data\GIT\ncs\master\toolchain\opt\bin\cmake.EXE' '-DWEST_PYTHON=c:\data\git\ncs\master\toolchain\opt\bin\python.exe' '-BC:\Data\GIT\ncs\master\nrf\applications\serial_lte_modem\build' '-SC:\Data\GIT\ncs\master\nrf\applications\serial_lte_modem' -GNinja -DBOARD=nrf9160_pca10090ns
    
    C:\Data\GIT\ncs\master\nrf\applications\serial_lte_modem>

    mcuboot child config file.

    3404.CMakeLists.txt
    #
    # Copyright (c) 2019 Nordic Semiconductor
    #
    # SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
    #
    
    cmake_minimum_required(VERSION 3.13.1)
    
    # This sample runs as a non-secure application on nRF91. Therefore, it
    # requires the secure_partition_manager that prepares the required
    # peripherals to be available for the application.
    #
    # Configure the SPM image to enable the peripherals that this sample
    # needs.
    set(spm_CONF_FILE
      prj.conf
      ${CMAKE_CURRENT_LIST_DIR}/child_secure_partition_manager.conf
      )
    
    set(mcuboot_CONF_FILE
      prj.conf
      ${CMAKE_CURRENT_LIST_DIR}/mcuboot.conf
    )
    
    find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
    project(serial_lte_modem)
    
    target_sources(app PRIVATE src/main.c)
    target_sources(app PRIVATE src/slm_util.c)
    target_sources(app PRIVATE src/slm_at_host.c)
    target_sources(app PRIVATE src/slm_at_tcpip.c)
    target_sources(app PRIVATE src/slm_at_icmp.c)
    target_sources(app PRIVATE src/slm_at_gps.c)
    target_sources(app PRIVATE src/slm_at_mqtt.c)
    target_sources(app PRIVATE src/slm_at_ftp.c)
    
    add_subdirectory(src/tcpip_proxy)
    
    zephyr_include_directories(src)
    
    mcuboot.conf.txt
    #
    # Copyright (c) 2019 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
    #
    
    #CONFIG_BOOT_SIGNATURE_KEY_FILE=my-root-rsa-2048.pem
    CONFIG_BOOT_SIGNATURE_KEY_FILE="C:/Data/GIT/ncs/master/nrf/applications/serial_lte_modem/my-root-rsa-2048.pem"

    regards

    KK

  • Apologies - I should have reported back.

    We also didn't have success with any statically defined method.

    What we ended up doing was passing declaration flags to cmake - a bit like this (copied and modified from our build scripts, so may need a bit of customisation for your environment):

    # We found that the key file has to be placed in the bootloader/mcuboot 
    # directory.
    # It _should_ accept an absolute path, but appears to behave inconsistenly
    # between the MCUBoot CMake config and the main project CMake config.
    
    cp $KEYFILE /workdir/zephyr/../bootloader/mcuboot/production-key.pem
    
    # Build and sign using our key. The first flag sets the signature key file 
    # used by nRF SDK during the main project build.
    # The second flag sets the signature key file that will be used by MCUBoot
    # to verify the image. Obviously, they need to be the same.
    
    west build -p auto -b ${board} ${project} -- \
      -DCONFIG_BOOT_SIGNATURE_KEY_FILE="production-key.pem" \
      -Dmcuboot_CONFIG_BOOT_SIGNATURE_KEY_FILE="production-key.pem"
    
    # We can now use `imgtool.py` to verify that the image was indeed signed
    # using our key.
    
    bootloader/mcuboot/scripts/imgtool.py verify \
      --key $KEYFILE build/zephyr/app_update.bin
    
     

    I hope that helps!

  • Thanks for the information, i think it should work me as well.

    Unfortunately most of the samples by nrf works as is, but if you start tailoring slightly to needs they fails and costs lot of time in debugging and understanding the entire flow...its really frustrating.

    Btw since you are using mcuboot are you able to do DFU over serial?

    regards

    KK

  • We're doing OTA updates via bluetooth, so I haven't tried serial.

    Unfortunately most of the samples by nrf works as is, but if you start tailoring slightly to needs they fails and costs lot of time in debugging and understanding the entire flow...its really frustrating.

    I feel your pain - I've had very much the same experience with the nRF Connect SDK.

    It's a shame because so much of it is nearly right. It's just a bit broken.

  • I have figured out the right way of defining your private key for MCUBoot, here are the steps

    1. generate the key as described here https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/mcuboot/imgtool.html
    2. copy the generated key to your application project directory
    3. just update/add the config option CONFIG_BOOT_SIGNATURE_KEY_FILE="my-private.pem" to your mcuboot configuration file, similar to whats done here https://github.com/nrfconnect/sdk-nrf/blob/250d239e979fd3cbc3afa5a986ec8f1172c307d6/applications/serial_lte_modem/slm_mcuboot.conf#L28
    4. no need to copy your generated private key to mcuboot source folder.

    credits:

    https://devzone.nordicsemi.com/f/nordic-q-a/66296/fota-change-signature-key

    regards

    KK

Related