Skip to content
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

CMake: support signing TF-M targets with post binary hooks #14361

Merged
merged 4 commits into from
Mar 8, 2021
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
#!/usr/bin/python
# Copyright (c) 2017-2021 Arm Limited
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
from os.path import abspath, basename, dirname, splitext, isdir
from os.path import join as path_join
import re
import subprocess
import argparse

SCRIPT_DIR = dirname(abspath(__file__))
MBED_OS_ROOT = abspath(path_join(SCRIPT_DIR, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir))

def sign_and_merge_tfm_bin(target_name, target_path, non_secure_bin, secure_bin):

assert os.path.isdir(target_path)
assert os.path.isfile(secure_bin)
assert os.path.isfile(non_secure_bin)

build_dir = dirname(non_secure_bin)
tempdir = path_join(build_dir, 'temp')
if not isdir(tempdir):
os.makedirs(tempdir)
flash_layout = path_join(target_path, 'partition', 'flash_layout.h')
mcuboot_bin = path_join(target_path, 'bl2.bin')
image_macros_s = path_join(target_path, 'partition', 'signing_layout_s.c')
image_macros_ns = path_join(target_path, 'partition', 'signing_layout_ns.c')
s_bin_name, s_bin_ext = splitext(basename(secure_bin))
s_signed_bin = abspath(path_join(tempdir, s_bin_name + '_signed' + s_bin_ext))
ns_bin_name, ns_bin_ext = splitext(basename(non_secure_bin))
ns_signed_bin = abspath(path_join(tempdir, 'tfm_' + ns_bin_name + '_signed' + ns_bin_ext))
concatenated_bin = abspath(path_join(tempdir, s_bin_name + '_' + ns_bin_name + '_concat' + ns_bin_ext))

assert os.path.isfile(image_macros_s)
assert os.path.isfile(image_macros_ns)

#1. Run wrapper to sign the TF-M secure binary
cmd = [
"python3",
path_join(MBED_OS_ROOT, "tools", "psa","tfm", "bin_utils","wrapper.py"),
"-v",
'1.2.0',
"-k",
path_join(target_path, (target_name + '-root-rsa-3072.pem')),
"--layout",
image_macros_s,
"--public-key-format",
'full',
"--align",
'1',
"--pad",
"--pad-header",
"-H",
'0x400',
"--overwrite-only",
"-s",
'auto',
"-d",
'(0,0.0.0+0)',
abspath(secure_bin),
s_signed_bin,
]

retcode = run_cmd(cmd, MBED_OS_ROOT)
if retcode:
raise Exception("Unable to sign " + target_name +
" secure binary, Error code: " + str(retcode))

#2. Run wrapper to sign the non-secure mbed binary
cmd = [
"python3",
path_join(MBED_OS_ROOT, "tools", "psa","tfm", "bin_utils","wrapper.py"),
"-v",
'1.2.0',
"-k",
path_join(target_path, (target_name + '-root-rsa-3072_1.pem')),
"--layout",
image_macros_ns,
"--public-key-format",
'full',
"--align",
'1',
"--pad",
"--pad-header",
"-H",
'0x400',
"--overwrite-only",
"-s",
'auto',
"-d",
'(1,0.0.0+0)',
abspath(non_secure_bin),
ns_signed_bin,
]

retcode = run_cmd(cmd, MBED_OS_ROOT)
if retcode:
raise Exception("Unable to sign " + target_name +
" non-secure binary, Error code: " + str(retcode))

#3. Concatenate signed secure TFM and non-secure mbed binaries
cmd = [
"python3",
path_join(MBED_OS_ROOT, "tools", "psa","tfm", "bin_utils","assemble.py"),
"--layout",
image_macros_s,
"-s",
s_signed_bin,
"-n",
ns_signed_bin,
"-o",
concatenated_bin,
]

retcode = run_cmd(cmd, MBED_OS_ROOT)
if retcode:
raise Exception("Unable to concatenate " + target_name +
" binaries, Error code: " + str(retcode))

#4. Concatenate mcuboot and signed binary and overwrite mbed built binary file
mcuboot_image_size = find_bl2_size(flash_layout)
with open(mcuboot_bin, "rb") as mcuboot_fh, open(concatenated_bin, "rb") as concat_fh:
with open(non_secure_bin, "w+b") as out_fh:
out_fh.write(mcuboot_fh.read())
out_fh.seek(mcuboot_image_size)
out_fh.write(concat_fh.read())


def find_bl2_size(configFile):
bl2_size_re = re.compile(r"^#define\s+FLASH_AREA_BL2_SIZE\s+\({0,1}(0x[0-9a-fA-F]+)\){0,1}")
bl2_size = None
with open(configFile, 'r') as flash_layout_file:
for line in flash_layout_file:
m = bl2_size_re.match(line)
if m is not None:
bl2_size = int(m.group(1), 0)
break
return bl2_size

def run_cmd(cmd, directory):

popen_instance = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=directory,
)

popen_instance.communicate()
return popen_instance.returncode

def parse_args():
parser = argparse.ArgumentParser()

parser.add_argument(
"--tfm-target",
help="Name of the TF-M target",
required=True
)

parser.add_argument(
"--target-path",
help="Path containing the target's bootloader, layouts and signing keys",
required=True
)

parser.add_argument(
"--non-secure-bin",
help="Path to the non-secure binary",
required=True
)

parser.add_argument(
"--secure-bin",
help="Path to the secure binary",
required=True
)

return parser.parse_args()

if __name__ == "__main__":
args = parse_args()
sign_and_merge_tfm_bin(args.tfm_target, args.target_path, args.non_secure_bin, args.secure_bin)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright (c) 2021 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

include(${MBED_PATH}/tools/cmake/mbed_set_post_build.cmake)

#
# Sign TF-M secure and non-secure images and combine them with the bootloader
#
function(mbed_post_build_tfm_sign_image
mbed_target
tfm_target
target_path
secure_bin
)
find_package(Python3)

set(mbed_target_name ${mbed_target})
set(post_build_command
COMMAND ${Python3_EXECUTABLE}
${MBED_PATH}/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_LATEST/scripts/generate_mbed_image.py
--tfm-target ${tfm_target}
--target-path ${target_path}
--secure-bin ${secure_bin}
--non-secure-bin ${CMAKE_BINARY_DIR}/$<TARGET_PROPERTY:mbed-post-build-bin-${mbed_target_name},application>.bin
)

mbed_set_post_build_operation()
endfunction()
9 changes: 9 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_MUSCA_B1/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2020-2021 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

include(${MBED_PATH}/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_LATEST/scripts/mbed_set_post_build_tfm.cmake)

add_library(mbed-arm-musca-b1 INTERFACE)

if(${MBED_TOOLCHAIN} STREQUAL "ARM")
Expand Down Expand Up @@ -52,3 +54,10 @@ target_link_libraries(mbed-arm-musca-b1
${CMAKE_CURRENT_SOURCE_DIR}/s_veneers.o
mbed-arm-ssg
)

mbed_post_build_tfm_sign_image(
ARM_MUSCA_B1
musca_b1
${CMAKE_CURRENT_SOURCE_DIR}
LDong-Arm marked this conversation as resolved.
Show resolved Hide resolved
${CMAKE_CURRENT_SOURCE_DIR}/tfm_s.bin
)
11 changes: 11 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_MUSCA_B1/musca_b1-root-rsa-3072.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Musca-B1 RSA keypair

A default RSA key pair is given to the Musca-B1 target.

Public keys were pre-compiled to `targets/TARGET_ARM_SSG/TARGET_MUSCA_B1/bl2.bin` and private key is in `musca_b1-root-rsa-3072.pem` for Secure image and `musca_b1-root-rsa-3072_1.pem` for Non-Secure image.

DO NOT use them in production code, they are exclusively for testing!

Private key must be stored in a safe place outside of the repository.

`tools/psa/tfm/bin_utils/imgtool.py` can be used to generate new key pairs.
39 changes: 39 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_MUSCA_B1/musca_b1-root-rsa-3072.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
9 changes: 9 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_MUSCA_S1/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2020-2021 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

include(${MBED_PATH}/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_LATEST/scripts/mbed_set_post_build_tfm.cmake)

add_library(mbed-arm-musca-s1 INTERFACE)

if(${MBED_TOOLCHAIN} STREQUAL "ARM")
Expand Down Expand Up @@ -58,3 +60,10 @@ target_link_libraries(mbed-arm-musca-s1
${CMAKE_CURRENT_SOURCE_DIR}/s_veneers.o
mbed-arm-ssg
)

mbed_post_build_tfm_sign_image(
ARM_MUSCA_S1
musca_s1
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/tfm_s.bin
)
11 changes: 11 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_MUSCA_S1/musca_s1-root-rsa-3072.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Musca-S1 RSA keypair

A default RSA key pair is given to the Musca-S1 target.

Public keys were pre-compiled to `targets/TARGET_ARM_SSG/TARGET_MUSCA_S1/bl2.bin` and private key is in `musca_s1-root-rsa-3072.pem` for Secure image and `musca_s1-root-rsa-3072_1.pem` for Non-Secure image.

DO NOT use them in production code, they are exclusively for testing!

Private key must be stored in a safe place outside of the repository.

`tools/psa/tfm/bin_utils/imgtool.py` can be used to generate new key pairs.
Loading