Skip to content

Add support for west sign for Silabs SoCs #92181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions boards/silabs/radio_boards/siwx917_rb4338a/board.cmake
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 1 addition & 2 deletions boards/silabs/radio_boards/siwx917_rb4342a/board.cmake
Original file line number Diff line number Diff line change
@@ -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
Expand Down
20 changes: 20 additions & 0 deletions doc/develop/west/sign.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 `Simpliciy 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`_.

.. _Simpliciy Commander:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

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
77 changes: 75 additions & 2 deletions scripts/west_commands/sign.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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''')
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.bin: indeed the most overrated name providing the least information ever...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
20 changes: 18 additions & 2 deletions soc/silabs/silabs_siwx91x/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)

Expand All @@ -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()
24 changes: 24 additions & 0 deletions soc/silabs/silabs_siwx91x/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 0 additions & 3 deletions soc/silabs/silabs_siwx91x/siwg917/Kconfig.defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,4 @@ if SOC_SERIES_SIWG917
config NUM_IRQS
default 99

config BUILD_OUTPUT_HEX
default y

endif
Loading