diff --git a/boards/silabs/radio_boards/siwx917_rb4338a/board.cmake b/boards/silabs/radio_boards/siwx917_rb4338a/board.cmake index 7b487f2cec89..05a945dd6c81 100644 --- a/boards/silabs/radio_boards/siwx917_rb4338a/board.cmake +++ b/boards/silabs/radio_boards/siwx917_rb4338a/board.cmake @@ -1,8 +1,7 @@ # Copyright (c) 2024 Silicon Laboratories Inc. # SPDX-License-Identifier: Apache-2.0 -board_runner_args(silabs_commander "--device=SiWG917M111GTBA" "--file-type=bin" - "--file=${PROJECT_BINARY_DIR}/${KERNEL_BIN_NAME}.rps") +board_runner_args(silabs_commander "--device=SiWG917M111GTBA") include(${ZEPHYR_BASE}/boards/common/silabs_commander.board.cmake) # It is not possible to load/flash a firmware using JLink, but it is possible to diff --git a/boards/silabs/radio_boards/siwx917_rb4342a/board.cmake b/boards/silabs/radio_boards/siwx917_rb4342a/board.cmake index f901065afa1f..d32b7aa45e14 100644 --- a/boards/silabs/radio_boards/siwx917_rb4342a/board.cmake +++ b/boards/silabs/radio_boards/siwx917_rb4342a/board.cmake @@ -1,8 +1,7 @@ # Copyright (c) 2025 Silicon Laboratories Inc. # SPDX-License-Identifier: Apache-2.0 -board_runner_args(silabs_commander "--device=SiWG917M111GTBA" "--file-type=bin" - "--file=${PROJECT_BINARY_DIR}/${KERNEL_BIN_NAME}.rps") +board_runner_args(silabs_commander "--device=SiWG917M111GTBA") include(${ZEPHYR_BASE}/boards/common/silabs_commander.board.cmake) # It is not possible to load/flash a firmware using JLink, but it is possible to diff --git a/doc/develop/west/sign.rst b/doc/develop/west/sign.rst index 21eeac87e530..b2d853672803 100644 --- a/doc/develop/west/sign.rst +++ b/doc/develop/west/sign.rst @@ -58,3 +58,23 @@ both are used, the command-line arguments go last. .. _rimage: https://github.com/thesofproject/rimage + + +silabs_commander +**************** + +The ``silabs_commander`` tool is used to apply sign or MIC or encrypt binaries for Silicon Labs +devices. It can be invoked either by ``west sign`` when the ``sign.tool`` configuration is set to +``silabs_commander`` or by ``west build`` if ``CONFIG_SIWX91X_SIGN_KEY`` or +``CONFIG_SIWX91X_MIC_KEY`` is set. + +If one of ``CONFIG_SIWX91X_SIGN_KEY`` or ``CONFIG_SIWX91X_MIC_KEY`` is set, ``west flash`` will +automatically flash the signed version of the binary. + +``silabs_commander`` require `Simplicity Commander`_ to be install on the host. The provisionning of the +key on the device is described in `UG574 SiWx917 SoC Manufacturing Utility User Guide`_. + +.. _Simplicity Commander: + https://www.silabs.com/developer-tools/simplicity-studio/simplicity-commander?tab=downloads +.. _UG574 SiWx917 SoC Manufacturing Utility User Guide: + https://www.silabs.com/documents/public/user-guides/ug574-siwx917-soc-manufacturing-utility-user-guide.pdf diff --git a/scripts/west_commands/sign.py b/scripts/west_commands/sign.py index 411563068b0c..c6fa273138e5 100644 --- a/scripts/west_commands/sign.py +++ b/scripts/west_commands/sign.py @@ -79,6 +79,26 @@ [rimage] sections in your west config file(s); this is especially useful when invoking west sign _indirectly_ through CMake/ninja. See how at https://docs.zephyrproject.org/latest/develop/west/sign.html + +silabs_commander +---------------- + +To create a signed binary with the silabs_commander tool, run this from your +build directory: + + west sign -t silabs_commander -- [--sign PRIVATE.pem] [--encrypt KEY] [--mic KEY] + +For this to work, either "commander" must be installed or you must pass +the path to "commander" using the -p option. + +If an argument is not specified, the value provided by Kconfig +(CONFIG_SIWX91X_SIGN_KEY, CONFIG_SIWX91X_MIC_KEY and CONFIG_SIWX91X_ENCRYPT) +is used. + +The exact behavior of these option are described in Silabs UG574[1] or in the +output of "commander rps converter --help" + +[1]: https://www.silabs.com/documents/public/user-guides/ug574-siwx917-soc-manufacturing-utility-user-guide.pdf ''' class ToggleAction(argparse.Action): @@ -112,8 +132,8 @@ def do_add_parser(self, parser_adder): # general options group = parser.add_argument_group('tool control options') - group.add_argument('-t', '--tool', choices=['imgtool', 'rimage'], - help='''image signing tool name; imgtool and rimage + group.add_argument('-t', '--tool', choices=['imgtool', 'rimage', 'silabs_commander'], + help='''image signing tool name; imgtool, rimage and silabs_commander are currently supported (imgtool is deprecated)''') group.add_argument('-p', '--tool-path', default=None, help='''path to the tool itself, if needed''') @@ -195,6 +215,8 @@ def do_run(self, args, ignored): signer = ImgtoolSigner() elif args.tool == 'rimage': signer = RimageSigner() + elif args.tool == 'silabs_commander': + signer = CommanderSigner() # (Add support for other signers here in elif blocks) else: if args.tool is None: @@ -633,3 +655,54 @@ def sign(self, command, build_dir, build_conf, formats): os.remove(out_bin) os.rename(out_tmp, out_bin) + +class CommanderSigner(Signer): + @staticmethod + def get_tool(command): + if command.args.tool_path: + tool = command.args.tool_path + if not os.path.isfile(tool): + command.die(f'--tool-path {tool}: no such file') + else: + tool = shutil.which('commander') + if not tool: + command.die('"commander" not found; either install it or provide --tool-path') + return tool + + @staticmethod + def get_keys(command, build_conf): + sign_key = getattr(command.args, 'sign', + build_conf.get('CONFIG_SIWX91X_SIGN_KEY', None)) + mic_key = getattr(command.args, 'mic', + build_conf.get('CONFIG_SIWX91X_MIC_KEY', None)) + encrypt_key = None + if build_conf.get('CONFIG_SIWX91X_ENCRYPT', False): + encrypt_key = mic_key + encrypt_key = getattr(command.args, 'encrypt', encrypt_key) + return (sign_key, mic_key, encrypt_key) + + @staticmethod + def get_input_output(command, build_dir, build_conf): + kernel_prefix = (pathlib.Path(build_dir) / 'zephyr' / + build_conf.get('CONFIG_KERNEL_BIN_NAME', "zephyr")) + in_file = f'{kernel_prefix}.rps' + out_file = command.args.sbin or f'{kernel_prefix}.signed.rps' + return (in_file, out_file) + + def sign(self, command, build_dir, build_conf, formats): + tool = self.get_tool(command) + in_file, out_file = self.get_input_output(command, build_dir, build_conf) + sign_key, mic_key, encrypt_key = self.get_keys(command, build_conf) + + commandline = [ tool, "rps", "convert", out_file, "--app", in_file ] + if mic_key: + commandline.extend(["--mic", mic_key]) + if encrypt_key: + commandline.extend(["--encrypt", encrypt_key]) + if sign_key: + commandline.extend(["--sign", sign_key]) + commandline.extend(command.args.tool_args) + + if not command.args.quiet: + command.inf("Signing with:", ' '.join(commandline)) + subprocess.run(commandline, check=True) diff --git a/soc/silabs/silabs_siwx91x/CMakeLists.txt b/soc/silabs/silabs_siwx91x/CMakeLists.txt index 7e3a8c84a16c..f1e6e5e6255f 100644 --- a/soc/silabs/silabs_siwx91x/CMakeLists.txt +++ b/soc/silabs/silabs_siwx91x/CMakeLists.txt @@ -1,5 +1,6 @@ -# Copyright (c) 2024 Silicon Laboratories Inc. +# Copyright (c) 2024-2025 Silicon Laboratories Inc. # SPDX-License-Identifier: Apache-2.0 +include(west) add_subdirectory(siwg917) @@ -10,5 +11,20 @@ set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/siwx91x_isp_prepare.py --load-addr ${FLASH_LOAD_ADDRESS} ${KERNEL_BIN_NAME} - ${KERNEL_BIN_NAME}.rps + ${KERNEL_NAME}.rps ) + +# runners_yaml_props_target controls the file used by "west flash" +if(CONFIG_SIWX91X_SIGN_KEY OR CONFIG_SIWX91X_MIC_KEY) + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${CMAKE_COMMAND} -E env ZEPHYR_BASE=${ZEPHYR_BASE} + ${WEST} sign -t silabs_commander --build-dir ${CMAKE_BINARY_DIR} + ) + set_target_properties(runners_yaml_props_target + PROPERTIES bin_file ${PROJECT_BINARY_DIR}/${KERNEL_NAME}.signed.rps + ) +else() + set_target_properties(runners_yaml_props_target + PROPERTIES bin_file ${PROJECT_BINARY_DIR}/${KERNEL_NAME}.rps + ) +endif() diff --git a/soc/silabs/silabs_siwx91x/Kconfig b/soc/silabs/silabs_siwx91x/Kconfig index 9f508223585f..4fba0363d013 100644 --- a/soc/silabs/silabs_siwx91x/Kconfig +++ b/soc/silabs/silabs_siwx91x/Kconfig @@ -38,4 +38,28 @@ config SIWX91X_NWP_INIT_PRIORITY have a higher priority than services that depend on it, such as Bluetooth, Wi-Fi and crypto. +config SIWX91X_SIGN_KEY + string "Signing key" + help + Sign the firmware using this private key. This value is passed as-is + to the command "commander rps convert". The value is usually a path to + PEM formatted file. + +config SIWX91X_MIC_KEY + string "Integrity Code (MIC) key" + help + Check integrity of the firmware using MIC (AES CBC-MAC) based + integrity check instead of CRC based check. + This value is passed as-is to the command "commander rps convert". The + value is usually a string of 32 hexadecimal number representing the + AES-256 key. + +config SIWX91X_ENCRYPT + bool "Also encrypt the firmware" + depends on SIWX91X_MIC_KEY != "" + help + Encrypt the application image using AES ECB encryption. + The key used is the value of CONFIG_SIWX91X_MIC_KEY. This value is + passed as-is to the command "commander rps convert". + endif # SOC_FAMILY_SILABS_SIWX91X diff --git a/soc/silabs/silabs_siwx91x/siwg917/Kconfig.defconfig b/soc/silabs/silabs_siwx91x/siwg917/Kconfig.defconfig index 9fa79429bcd1..9a26bf77381c 100644 --- a/soc/silabs/silabs_siwx91x/siwg917/Kconfig.defconfig +++ b/soc/silabs/silabs_siwx91x/siwg917/Kconfig.defconfig @@ -6,7 +6,4 @@ if SOC_SERIES_SIWG917 config NUM_IRQS default 99 -config BUILD_OUTPUT_HEX - default y - endif