NCS 3.0.2 MCUboot link error: undefined reference to rsa_pub_key / rsa_pub_key_len (works on NCS 2.4.2)

Environment

  • NCS: v3.0.2 (Zephyr 4.0.99)

  • Toolchain: Zephyr SDK 0.17.0 (arm-zephyr-eabi gcc 12.2)

  • West: 1.2.0

  • Building via nRF Connect / sysbuild

  • Board: custom nRF52840 (project also builds fine on NCS 2.4.2)

Issue Summary:
I’m facing an issue with mcuboot in NCS 3.0.2. Initially, I started getting undefined reference to rsa_pub_key and rsa_pub_key_len during the build. To resolve this, I checked mcuboot_config.h and saw that only 2048 and 3072 bit RSA keys are supported. I then tried adding CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN=2048 in sysbuild.conf, but got this warning instead:

warning: attempt to assign the value '2048' to the undefined symbol BOOT_SIGNATURE_TYPE_RSA_LEN

sysbuild.conf:

SB_CONFIG_BOOTLOADER_MCUBOOT=y
SB_CONFIG_PARTITION_MANAGER=y
# SB_CONFIG_BOOT_SIGNATURE_TYPE_ED25519=y
# SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y
SB_CONFIG_BOOT_SIGNATURE_TYPE_RSA=y
# SB_CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN=2048
SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="D://Development//Repo//BLE_firmware_nRF//signature//infinity.pem"


prj.conf:

# Incresed stack due to settings API usage
# CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=8192

CONFIG_BT=y
# CONFIG_BT_LL_SOFTDEVICE=n

# Enable Bluetooth Controller
CONFIG_BT_CTLR=y
CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y

CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y

CONFIG_BT_CTLR_TX_PWR_PLUS_8=y

# Enable SMP Server
CONFIG_MCUMGR=y
CONFIG_MCUMGR_GRP_IMG=y

# CONFIG_MCUMGR_GRP_IMG dependencies
CONFIG_IMG_MANAGER=y

# CONFIG_IMG_MANAGER dependencies
CONFIG_STREAM_FLASH=y

# CONFIG_MCUMGR dependencies
CONFIG_NET_BUF=y
CONFIG_ZCBOR=y

# Ensure an MCUboot-compatible binary is generated.
CONFIG_BOOTLOADER_MCUBOOT=y

CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_UUID_CNT=1
CONFIG_BT_GATT_DM=y
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_GATT_DYNAMIC_DB=y

CONFIG_BT_DEVICE_NAME="SB PINPAD"
CONFIG_BT_DEVICE_APPEARANCE=833
CONFIG_BT_DEVICE_NAME_DYNAMIC=n

# check if we need this
CONFIG_BT_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y

# for LittleFS
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=y

#  Enable loging 
# IMPORTANT -> THIS MUST BE COMMENTED OUT DURING PRODUCTION
# CONFIG_LOG=y
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
# CONFIG_LOG_DEFAULT_LEVEL=3
# CONFIG_LOG_MODE_IMMEDIATE=y

CONFIG_BT_CREATE_CONN_TIMEOUT=10
CONFIG_BT_CONN_PARAM_UPDATE_TIMEOUT=10000
CONFIG_BT_CONN_PARAM_RETRY_COUNT=6
CONFIG_BT_CONN_PARAM_RETRY_TIMEOUT=10000
CONFIG_BASE64=y

CONFIG_BT_L2CAP_TX_MTU=251
CONFIG_BT_BUF_ACL_RX_SIZE=256
CONFIG_BT_BUF_ACL_TX_SIZE=256
CONFIG_BT_PHY_UPDATE=n

CONFIG_BT_BUF_ACL_RX_COUNT=4
CONFIG_BT_BUF_ACL_TX_COUNT=4
CONFIG_BT_MAX_CONN=4

# Enable ADC for temp & Battery status
CONFIG_ADC=y

# Power Management
CONFIG_PM=y
CONFIG_PM_DEVICE=y


CONFIG_REBOOT=y
CONFIG_BT_DIS=y
# CONFIG_BT_DIS_MANUF="SwipBox International A/S"
# CONFIG_BT_DIS_MODEL="Infinity PINpad"
CONFIG_BT_DIS_PNP=n

CONFIG_BT_DIS_FW_REV=y
CONFIG_BT_DIS_FW_REV_STR="1.0.3"         

CONFIG_BT_DIS_HW_REV=y
CONFIG_BT_DIS_HW_REV_STR="1"

CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=n

CONFIG_MBEDTLS_PSA_CRYPTO_C=y

CONFIG_CRYPTO=y
CONFIG_MBEDTLS=y

# Enable nordic security backend and PSA APIs
CONFIG_NRF_SECURITY=y
CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE=y
CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE=y
CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT=y
CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT=y
CONFIG_PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY=y
CONFIG_PSA_WANT_ALG_RSA_PKCS1V15_SIGN=y
CONFIG_PSA_WANT_ALG_RSA_PKCS1V15_CRYPT=y

CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y

# Algorithms
CONFIG_PSA_WANT_ALG_SHA_256=y

# Define key size
CONFIG_PSA_WANT_RSA_KEY_SIZE_1024=y

# Mbedtls configuration
CONFIG_MBEDTLS_ENABLE_HEAP=y

CONFIG_MCUMGR_TRANSPORT_BT=y
CONFIG_MCUMGR_TRANSPORT_BT_PERM_RW=n
CONFIG_MCUMGR_TRANSPORT_BT_CONN_PARAM_CONTROL=y
# CONFIG_MCUMGR_TRANSPORT_UART=y
CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y

# Enable the mcumgr Packet Reassembly feature over Bluetooth and its configuration dependencies.
# MCUmgr buffer size is optimized to fit one SMP packet divided into five Bluetooth Write Commands,
# transmitted with the maximum possible MTU value: 498 bytes.
CONFIG_MCUMGR_TRANSPORT_BT_REASSEMBLY=y
CONFIG_MCUMGR_GRP_OS_MCUMGR_PARAMS=y

CONFIG_THREAD_NAME=y

#32KB
CONFIG_MAIN_STACK_SIZE=27648

#18KB
CONFIG_HEAP_MEM_POOL_SIZE=18432 

#8KB
CONFIG_MBEDTLS_HEAP_SIZE=7168

#5KB
CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=5120

#8KB
CONFIG_BT_RX_STACK_SIZE=9216

#4KB
CONFIG_BT_HCI_TX_STACK_SIZE=5120

CONFIG_DISABLE_FLASH_PATCH=y

# CONFIG_MCUMGR_SMP_BT=y
# CONFIG_BT_DFU_SMP=y

# SMP GATT service registration
CONFIG_MCUMGR_TRANSPORT_BT_DYNAMIC_SVC_REGISTRATION=y

For context, I was using this same RSA signature setup in NCS 2.4.2 without any issue. Can someone clarify what’s changed in NCS 3.0.2, and also confirm if it’s possible to still use a 1024-bit RSA key with mcuboot in this version?

Thanks.

Parents
  • There's an update, I used the imgtool to get public key from the private key that my bootloader uses. I figured out that it's an ECDSA_P256 key, not RSA. Now the problem is that the OTA between firmwares based on different NCS versions, the OTA fails. Here are different cases:

    1. When I perform OTA for NCS 3.0.2 based firmware to the same NCS based firmware, it's a success. The image is confirmed and it stays on the updated firmware even after hard reset.
    2. When I OTA NCS 2.4.2 based firmware to NCS 3.0.2 based firmware, it's also a success but upon hard reset, it reverts back to the older firmware, that's based on NCS 2.4.2 (probably image not confirmed).
    3. When I OTA NCS 3.0.2 based firmware to the one based on NCS 2.4.2, it doesn't even upgrade, and prints out the older version. The device manager app says "hash not found (8)".

    Note: I'm using Device Manager from Nordic for OTA's.

  • Hi,

    I see you made some progress. Regarding 2 it seems the image is not confirmed as you write, as it is reverted on the next boot. Do you try to confirm it in this case? Do you have logging to indicate why it does not happen? Note that the image can be confirmed both via SMP, or by the image itself by calling boot_write_img_confirmed().

    There may also be a problem that is hinted to by your case 3, which makes me wonder if you are using static partitioning or if the partition layout has changed between your 2.4.2 based firmware and your 3.0.2? If so, that will cause problems. You need to use static partitioning when doing DFU between versions, as changes in partitions will cause problems. See Static and dynamic configuration.

  • I confirm the image from Nordic Device Manager app, it says Upload Complete. But the next boot, which takes around 40 seconds to boot, it reverts back to the older version.

    I tried calling boot_write_img_confirmed() in main from the updated firmware, it returned 0 (success), But the firmware reverted back on the next boot.

    As for the partitions, I have verified that I'm using pm_static.yml for both projects (NCS 2.4.2 & NCS 3.0.2 based).

    pm_static.yml

    external_flash:
      address: 0x0
      end_address: 0x400000
      region: external_flash
      size: 0x400000
    littlefs_storage:
      address: 0x000F8000
      end_address: 0x0008000
      region: flash_primary
      size: 0x0008000
    
    

    I have verified through the build logs that the pm_static.yml is being used in both builds and the dts that defined mcuboot, slot-0 and slot-1 also has same addresses for all of them. However, the partitions.yml file generated in the build directory is different for both projects on some points, sharing it here:

    partitions.yml (NCS 3.0.2)

    app:
      address: 0xc200
      end_address: 0x7f000
      region: flash_primary
      size: 0x72e00
    external_flash:
      address: 0x0
      end_address: 0x400000
      region: external_flash
      size: 0x400000
    littlefs_storage:
      address: 0xf8000
      end_address: 0x100000
      region: flash_primary
      size: 0x8000
    mcuboot:
      address: 0x0
      end_address: 0xc000
      placement:
        align:
          end: 0x1000
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0xc000
    mcuboot_pad:
      address: 0xc000
      end_address: 0xc200
      placement:
        align:
          start: 0x1000
        before:
        - mcuboot_primary_app
      region: flash_primary
      size: 0x200
    mcuboot_primary:
      address: 0xc000
      end_address: 0x7f000
      orig_span: &id001
      - mcuboot_pad
      - app
      region: flash_primary
      sharers: 0x1
      size: 0x73000
      span: *id001
    mcuboot_primary_app:
      address: 0xc200
      end_address: 0x7f000
      orig_span: &id002
      - app
      region: flash_primary
      size: 0x72e00
      span: *id002
    mcuboot_secondary:
      address: 0x7f000
      end_address: 0xf2000
      placement:
        after:
        - mcuboot_primary
        align:
          start: 0x1000
      region: flash_primary
      share_size:
      - mcuboot_primary
      size: 0x73000
    nvs_storage:
      address: 0xf2000
      end_address: 0xf8000
      placement:
        align:
          start: 0x1000
        before:
        - end
      region: flash_primary
      size: 0x6000
    sram_primary:
      address: 0x20000000
      end_address: 0x20040000
      region: sram_primary
      size: 0x40000
    

    partitions.yml (NCS 2.4.2)

    app:
      address: 0xc200
      end_address: 0x82000
      region: flash_primary
      size: 0x75e00
    external_flash:
      address: 0x0
      end_address: 0x400000
      region: external_flash
      size: 0x400000
    littlefs_storage:
      address: 0xf8000
      end_address: 0x100000
      region: flash_primary
      size: 0x8000
    mcuboot:
      address: 0x0
      end_address: 0xc000
      placement:
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0xc000
    mcuboot_pad:
      address: 0xc000
      end_address: 0xc200
      placement:
        align:
          start: 0x1000
        before:
        - mcuboot_primary_app
      region: flash_primary
      size: 0x200
    mcuboot_primary:
      address: 0xc000
      end_address: 0x82000
      orig_span: &id001
      - mcuboot_pad
      - app
      region: flash_primary
      sharers: 0x1
      size: 0x76000
      span: *id001
    mcuboot_primary_app:
      address: 0xc200
      end_address: 0x82000
      orig_span: &id002
      - app
      region: flash_primary
      size: 0x75e00
      span: *id002
    mcuboot_secondary:
      address: 0x82000
      end_address: 0xf8000
      placement:
        after:
        - mcuboot_primary
        align:
          start: 0x1000
        align_next: 0x1000
      region: flash_primary
      share_size:
      - mcuboot_primary
      size: 0x76000
    sram_primary:
      address: 0x20000000
      end_address: 0x20040000
      region: sram_primary
      size: 0x40000
    

    I'm not sure why the addresses are different at some points.

  • Hi,

    The partitions.yml show that the slots have moved, so it is expected that DFU failes in this case.  You need make all the partitioning static (meaning add all the partitions you need static to the pm_static.yml). See Static partition requirement for DFU. I suggest you subseqwuently verify that you actually get the same partitions in both builds, as there is no point attempting DFU with differing partition layout - particularily with different start address, that will fail.

  • Hmm, maybe the dynamic partitioning is messing up the addresses, I'll try statically defining the app and boot partitions inside pm_static.yml

Reply Children
No Data
Related