diff --git a/boards/silabs/radio_boards/siwx917_rb4338a/board.cmake b/boards/silabs/radio_boards/siwx917_rb4338a/board.cmake index 7b487f2cec89..c3152294689e 100644 --- a/boards/silabs/radio_boards/siwx917_rb4338a/board.cmake +++ b/boards/silabs/radio_boards/siwx917_rb4338a/board.cmake @@ -1,8 +1,14 @@ # Copyright (c) 2024 Silicon Laboratories Inc. # SPDX-License-Identifier: Apache-2.0 +# Set the flash file based on signing is enabled or not. +if(CONFIG_SIWX91X_SILABS_OTA_SIGN_ENABLE OR CONFIG_SIWX91X_SILABS_OTA_MIC_ENABLE OR CONFIG_SIWX91X_SILABS_OTA_ENCRYPT_ENABLE) + set(FLASH_FILE ${PROJECT_BINARY_DIR}/${KERNEL_NAME}_secure.bin.rps) +else() + set(FLASH_FILE ${PROJECT_BINARY_DIR}/${KERNEL_BIN_NAME}.rps) +endif() board_runner_args(silabs_commander "--device=SiWG917M111GTBA" "--file-type=bin" - "--file=${PROJECT_BINARY_DIR}/${KERNEL_BIN_NAME}.rps") + "--file=${FLASH_FILE}") 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..ebadc6f4955f 100644 --- a/doc/develop/west/sign.rst +++ b/doc/develop/west/sign.rst @@ -58,3 +58,58 @@ both are used, the command-line arguments go last. .. _rimage: https://github.com/thesofproject/rimage + +silabs_commander +*************** + +Signing involves a number of "wrapper" scripts stacked on top of each other: ``west +flash`` invokes ``west build`` which invokes ``cmake`` and ``ninja`` which invokes +``west sign`` which invokes ``imgtool`` or ``rimage`` or `silabs_commander`_. + +The ``silabs_commander`` tool is used to apply sign or MIC or encrypt binaries for Silicon +Labs devices. It is invoked by ``west sign`` or ``west build`` when the ``sign.tool`` +configuration is set to ``silabs_commander``. The tool requires a configuration file +that specifies the signing parameters, such as the key files. The configuration file +can be specified in the ``project config`` file and defined in the ``soc Kconfig`` +file. Here is an example of a ``samples/example/prj.conf`` file for signing with +``silabs_commander``: +.. code-block:: ini + + # Configuration for enabling MIC with silabs_commander + CONFIG_SIWX91X_SILABS_OTA_MIC_ENABLE = n or y + + # Configuration for enabling encryption with silabs_commander + CONFIG_SIWX91X_SILABS_OTA_ENCRYPT_ENABLE = n or y + + # Configuration for enabling signing with silabs_commander + CONFIG_SIWX91X_SILABS_OTA_SIGN_ENABLE = n or y + + # Configuration for OTA encryption key with silabs_commander + CONFIG_SIWX91X_OTA_ENCRYPT_KEY = "ota_encryption_key in hex format" + + # Configuration for OTA signing key with silabs_commander + CONFIG_SIWX91X_OTA_SIGN_KEY = "ota_signing_key file path" + +The ``silabs_commander`` tool will read the configuration file and use the specified +parameters to sign or MIC or encrypt the binary. The secured binary will be saved to the +specified output file. When using ``west sign``, the tool will automatically read the +configuration file and use the specified parameters to sign or MIC or encrypt the binary. +The command can be run as follows: +.. code-block:: console + + west sign --tool silabs_commander or + west build -b example/path --pristine + +This will invoke the ``silabs_commander`` tool with the specified configuration file and +sign or MIC or encrypt the binary according to the parameters defined in the configuration file. +.. note:: + The ``silabs_commander`` tool is specific to Silicon Labs devices and may not be + applicable for other platforms. Ensure that you are using the correct signing tool + for your target device. +.. note:: + The ``silabs_commander`` tool supports various options for security, such as MIC, + encryption, and signing. You can specify these options in the configuration file + to customize the signing process according to your requirements. Refer to the + ``silabs_commander`` documentation for more details on the available options and + how to use them effectively. + "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..d872fbce4c22 100644 --- a/scripts/west_commands/sign.py +++ b/scripts/west_commands/sign.py @@ -13,7 +13,6 @@ import sys from elftools.elf.elffile import ELFFile - from west import manifest from west.commands import Verbosity from west.util import quote_sh_list @@ -79,6 +78,20 @@ [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 + +For this to work, Silabs Commander tool must be installed in your PATH. + +The input binary (zephyr.bin.rps) is signed using the specified OTA key and private key, +producing zephyr_signed.bin.rps by default. If CONFIG_SIWX91X_OTA_ENCRYPT_KEY and CONFIG_SIWX91X_OTA_SIGN_KEY are set +in your build configuration, they will be used unless overridden by command-line arguments. +Additional arguments after '--' are passed to silabs_commander directly. ''' class ToggleAction(argparse.Action): @@ -112,8 +125,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 +208,8 @@ def do_run(self, args, ignored): signer = ImgtoolSigner() elif args.tool == 'rimage': signer = RimageSigner() + elif args.tool == 'silabs_commander': + signer = SilabsRPSSigner() # (Add support for other signers here in elif blocks) else: if args.tool is None: @@ -633,3 +648,83 @@ def sign(self, command, build_dir, build_conf, formats): os.remove(out_bin) os.rename(out_tmp, out_bin) + +class SilabsRPSSigner(Signer): + # Signer class for Silicon Labs Commander tool via west sign -t silabs_commander. + def find_commandertool(self, cmd, args): + if args.tool_path: + commandertool = args.tool_path + if not os.path.isfile(commandertool): + cmd.die(f'--tool-path {commandertool}: no such file') + else: + commandertool = shutil.which('commander') + if not commandertool: + cmd.die(f'SILABS "commander" not found in PATH, try "--tool-path"? Cannot sign {args}') + return commandertool + + def get_security_configs(self, build_conf, args, command): + + # Retrieve configurations, prioritizing command-line args, then build_conf + siwx91x_ota_encrypt_key = getattr(args, 'siwx91x-ota-encrypt-key', build_conf.get('CONFIG_SIWX91X_OTA_ENCRYPT_KEY')) + siwx91x_ota_sign_key = getattr(args, 'siwx91x-ota-sign-key', build_conf.get('CONFIG_SIWX91X_OTA_SIGN_KEY')) + siwx91x_ota_mic_enable = getattr(args, 'siwx91x-mic-enable', build_conf.get('CONFIG_SIWX91X_SILABS_OTA_MIC_ENABLE', False)) + siwx91x_ota_encrypt_enable = getattr(args, 'siwx91x-encrypt-enable', build_conf.get('CONFIG_SIWX91X_SILABS_OTA_ENCRYPT_ENABLE', False)) + siwx91x_ota_sign_enable = getattr(args, 'siwx91x-sign-enable', build_conf.get('CONFIG_SIWX91X_SILABS_OTA_SIGN_ENABLE', False)) + + # Refer find_commandertool() function to identify the Commander tool. + commander_path = self.find_commandertool(command, args) + + # Validate required settings + if siwx91x_ota_encrypt_enable and not siwx91x_ota_encrypt_key: + command.die("SIWX91X_OTA_ENCRYPT_KEY not provided. Use --siwx91x-ota-encrypt-key=your_key or add CONFIG_SIWX91X_OTA_ENCRYPT_KEY in prj.conf.") + if siwx91x_ota_sign_enable and not siwx91x_ota_sign_key: + command.die("SIWX91X_OTA_SIGN_KEY not provided. Use --siwx91x-ota-sign-key=/path/to/key or add CONFIG_SIWX91X_OTA_SIGN_KEY in prj.conf.") + + # Validate private key path + if not os.path.isfile(siwx91x_ota_sign_key): + command.die(f"Private key not found at {siwx91x_ota_sign_key}. Please ensure the path is correct.") + + return commander_path,siwx91x_ota_encrypt_key, siwx91x_ota_sign_key, siwx91x_ota_mic_enable, siwx91x_ota_encrypt_enable, siwx91x_ota_sign_enable + + def sign(self, command, build_dir, build_conf, formats): + """Sign the Zephyr binary using Silicon Labs Commander. + commander_path + :param command: The Sign instance (provides args and utility methods) + :param build_dir: The build directory path + :param build_conf: BuildConfiguration object for the build directory + :param formats: List of formats to generate (e.g., ['bin', 'rps']) + """ + self.command = command + args = command.args + b = pathlib.Path(build_dir) + kernel_name = build_conf.get('CONFIG_KERNEL_BIN_NAME') + # Setting the input and output paths + input_rps = b / 'zephyr' / f'{kernel_name}.bin.rps' + output_rps = args.sbin or (b / 'zephyr' / f'{kernel_name}_secure.bin.rps') + # Check if input binary exists + if not input_rps.is_file(): + command.die(f"No .rps found at {input_rps}. Ensure the build generated kernel_name.bin.rps in {b / 'zephyr'}") + # Load configuration + commander_path,siwx91x_ota_encrypt_key, siwx91x_ota_sign_key, siwx91x_ota_mic_enable, siwx91x_ota_encrypt_enable, siwx91x_ota_sign_enable = self.get_security_configs(build_conf, args, command) + siwx91x_ota_mic_key = siwx91x_ota_encrypt_key + sign_base = [ + commander_path, + "rps", + "convert", + str(output_rps), + "--app", str(input_rps) + ] + + if siwx91x_ota_mic_enable: + sign_base.extend(["--mic", str(siwx91x_ota_mic_key)]) + + if siwx91x_ota_encrypt_enable: + sign_base.extend(["--encrypt", str(siwx91x_ota_encrypt_key)]) + + if siwx91x_ota_sign_enable: + sign_base.extend(["--sign", str(siwx91x_ota_sign_key)]) + + sign_base.extend(args.tool_args) + + command.inf("Running command:", ' '.join(sign_base)) + subprocess.run(sign_base, check=True) diff --git a/soc/silabs/silabs_siwx91x/CMakeLists.txt b/soc/silabs/silabs_siwx91x/CMakeLists.txt index 7e3a8c84a16c..f9c33f5b3987 100644 --- a/soc/silabs/silabs_siwx91x/CMakeLists.txt +++ b/soc/silabs/silabs_siwx91x/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2024 Silicon Laboratories Inc. # SPDX-License-Identifier: Apache-2.0 +include(west) # Add this at the top or before using ${WEST} + add_subdirectory(siwg917) # Necessary to not overwrite NWP Firmware @@ -12,3 +14,12 @@ set_property(GLOBAL APPEND PROPERTY extra_post_build_commands ${KERNEL_BIN_NAME} ${KERNEL_BIN_NAME}.rps ) + +# Custom signing with Silicon Labs Commander +if(CONFIG_SIWX91X_SILABS_OTA_SIGN_ENABLE OR CONFIG_SIWX91X_SILABS_OTA_MIC_ENABLE OR CONFIG_SIWX91X_SILABS_OTA_ENCRYPT_ENABLE) + # Necessary to invoke west sign after build + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${WEST} sign -t silabs_commander --build-dir ${CMAKE_BINARY_DIR} --sbin ${PROJECT_BINARY_DIR}/${KERNEL_NAME}_signed.bin.rps + DEPENDS zephyr_final + ) +endif() diff --git a/soc/silabs/silabs_siwx91x/Kconfig b/soc/silabs/silabs_siwx91x/Kconfig index 458d55dc2c89..dd3b1b2157ed 100644 --- a/soc/silabs/silabs_siwx91x/Kconfig +++ b/soc/silabs/silabs_siwx91x/Kconfig @@ -28,3 +28,39 @@ config SIWX91X_NWP_INIT_PRIORITY Wi-Fi and crypto. endif # SOC_FAMILY_SILABS_SIWX91X + +if SOC_FAMILY_SILABS_SIWX91X +config SIWX91X_SILABS_OTA_SIGN_ENABLE + bool "Silicon Labs Commander Signing Support" + depends on BUILD_OUTPUT_BIN + help + Activates signing of Zephyr binary with Silicon Labs Commander during build process. + For more information refer this + "https://www.silabs.com/documents/public/user-guides/ug574-siwx917-soc-manufacturing-utility-user-guide.pdf" + +config SIWX91X_SILABS_OTA_MIC_ENABLE + bool "Silicon Labs Commander MIC Support" + depends on BUILD_OUTPUT_BIN + help + Activates mic of Zephyr binary with Silicon Labs Commander during build process. + For more information refer this + "https://www.silabs.com/documents/public/user-guides/ug574-siwx917-soc-manufacturing-utility-user-guide.pdf" + +config SIWX91X_SILABS_OTA_ENCRYPT_ENABLE + bool "Silicon Labs Commander Encryption Support" + depends on BUILD_OUTPUT_BIN + help + Activates encryption of Zephyr binary with Silicon Labs Commander during build process. + For more information refer this + "https://www.silabs.com/documents/public/user-guides/ug574-siwx917-soc-manufacturing-utility-user-guide.pdf" + +config SIWX91X_OTA_ENCRYPT_KEY + string "OTA Key for Encryption." + help + Specifies Over the Air key (hex) for encryption with Silicon Labs Commander. + +config SIWX91X_OTA_SIGN_KEY + string "Private Key Path for Signing." + help + Path to private key file for signing with Silicon Labs Commander. +endif