Skip to content

Commit cca8e3a

Browse files
bence-baloghDavid Hu
authored and
David Hu
committed
Platform: AN552: Create unique provisioning bundle
If TFM_DUMMY_PROVISIONING is OFF then calculate the hash of the new private keys' public pair and use that for provisioning. The other keys can also be generated if needed or can be set in the config files. The provisioning bundle build is supported by armclang, gcc and iar as well. Change-Id: I32af4a34720cfa0aeda1220499aa9404a0056cad Signed-off-by: Dávid Házi <[email protected]> Signed-off-by: Bence Balogh <[email protected]>
1 parent ffc32f1 commit cca8e3a

10 files changed

+407
-3
lines changed

docs/platform/arm/mps3/an552/README.rst

+21
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,27 @@ Build instructions with platform name: arm/mps3/an552
2626
provisioning code and provisioning values. The provisioning bundle has to be placed
2727
on the ``0x10022000`` address.
2828

29+
.. note::
30+
31+
If ``-DPLATFORM_DEFAULT_PROVISIONING=OFF`` and ``-DTFM_DUMMY_PROVISIONING=OFF`` are set
32+
then unique values can be used for provisioning. The ${MCUBOOT_KEY_S} and ${MCUBOOT_KEY_NS}
33+
will be used for signing and provisioning so any unique private signing key can be used.
34+
If ``-DMCUBOOT_GENERATE_SIGNING_KEYPAIR=ON`` is set then a new mcuboot signing public and private
35+
keypair is going to be generated and it's going to be used to sign the S and NS binaries.
36+
37+
The hash of the public key is going to be written into the ``provisioning_data.c`` automatically.
38+
The other keys and seeds can be changed by passing the new values to the build command,
39+
otherwise the default values going to be used:
40+
``tf-m/platform/ext/target/arm/mps3/an552/provisioning/provisioning_config.cmake``
41+
Optionally it's possible to pass a new config file with the ``-DPROVISIONING_KEYS_CONFIG``
42+
flag.
43+
44+
The new generated keypair can be found in the ``<build dir>/bin`` folder or in the
45+
``<install directory>/image_signing/keys`` after installation.
46+
The generated provisioning_data.c file can be found at
47+
``<build directory>/platform/target/provisioning/provisioning_data.c``
48+
49+
2950
To run the example code on AN552
3051
--------------------------------
3152
FPGA image is available to download `here <https://developer.arm.com/tools-and-software/development-boards/fpga-prototyping-boards/download-fpga-images>`__

platform/ext/target/arm/mps3/an552/config.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# Make FLIH IRQ test as the default IRQ test on Corstone-310
1111
set(TEST_NS_SLIH_IRQ OFF CACHE BOOL "Whether to build NS regression Second-Level Interrupt Handling tests")
1212
set(PSA_API_TEST_TARGET "cs3x0" CACHE STRING "PSA_API_TARGET name")
13+
set(PROVISIONING_KEYS_CONFIG "${CMAKE_SOURCE_DIR}/platform/ext/target/arm/mps3/an552/provisioning/provisioning_config.cmake" CACHE FILEPATH "The config file which has the keys and seeds for provisioning")
1314

1415
if(BL2)
1516
set(BL2_TRAILER_SIZE 0x800 CACHE STRING "Trailer size")

platform/ext/target/arm/mps3/an552/provisioning/CMakeLists.txt

+46-1
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,24 @@ find_package(Python3)
1010

1111
add_executable(provisioning_bundle)
1212

13+
# The armclang toolchain file does not set the CMAKE_OBJCOPY
14+
# but it's used for the armclang build as well.
15+
unset(CMAKE_OBJCOPY CACHE)
16+
find_program(CMAKE_OBJCOPY NAMES "arm-none-eabi-objcopy")
17+
if(NOT CMAKE_OBJCOPY)
18+
message(FATAL_ERROR "GNU ARM objcopy not found!")
19+
endif()
20+
1321
set_target_properties(provisioning_bundle
1422
PROPERTIES
1523
SUFFIX ".axf"
24+
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
1625
)
1726

1827
target_add_scatter_file(provisioning_bundle
1928
$<$<C_COMPILER_ID:ARMClang>:${CMAKE_CURRENT_SOURCE_DIR}/provisioning_bundle.sct>
2029
$<$<C_COMPILER_ID:GNU>:${CMAKE_CURRENT_SOURCE_DIR}/provisioning_bundle.ld>
30+
$<$<C_COMPILER_ID:IAR>:${CMAKE_CURRENT_SOURCE_DIR}/provisioning_bundle.icf>
2131
)
2232

2333
target_link_options(provisioning_bundle
@@ -35,7 +45,7 @@ target_link_options(provisioning_bundle
3545
target_sources(provisioning_bundle
3646
PRIVATE
3747
./provisioning_code.c
38-
$<$<BOOL:${TFM_DUMMY_PROVISIONING}>:./dummy_provisioning_data.c>
48+
$<IF:$<BOOL:${TFM_DUMMY_PROVISIONING}>,dummy_provisioning_data.c,${CMAKE_CURRENT_BINARY_DIR}/provisioning_data.c>
3949
)
4050

4151
target_include_directories(provisioning_bundle
@@ -101,3 +111,38 @@ target_include_directories(platform_bl2
101111
INTERFACE
102112
.
103113
)
114+
115+
if(NOT TFM_DUMMY_PROVISIONING)
116+
include(${PROVISIONING_KEYS_CONFIG})
117+
add_custom_target(provisioning_data
118+
SOURCES
119+
provisioning_data.c
120+
)
121+
122+
add_custom_command(OUTPUT provisioning_data.c
123+
# FIXME: combining the two generator prepends the current path, so two is used
124+
DEPENDS $<IF:$<BOOL:${MCUBOOT_GENERATE_SIGNING_KEYPAIR}>,generated_private_key,>
125+
$<IF:$<BOOL:${MCUBOOT_GENERATE_SIGNING_KEYPAIR}>,$<TARGET_FILE_DIR:bl2>/generated_private_key_s.pem,${MCUBOOT_KEY_S}>
126+
# FIXME: combining the two generator prepends the current path, so two is used
127+
DEPENDS $<IF:$<BOOL:${MCUBOOT_GENERATE_SIGNING_KEYPAIR}>,generated_private_key,>
128+
$<IF:$<BOOL:${MCUBOOT_GENERATE_SIGNING_KEYPAIR}>,$<TARGET_FILE_DIR:bl2>/generated_private_key_ns.pem,${MCUBOOT_KEY_NS}>
129+
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/provisioning_data_template.jinja2
130+
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/create_provisioning_data.py
131+
WORKING_DIRECTORY ${MCUBOOT_PATH}/scripts
132+
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/create_provisioning_data.py
133+
${CMAKE_CURRENT_BINARY_DIR}/provisioning_data.c
134+
--bl2_rot_priv_key_0 ${MCUBOOT_KEY_S}
135+
--bl2_rot_priv_key_1 ${MCUBOOT_KEY_NS}
136+
--template_path ${CMAKE_CURRENT_SOURCE_DIR}
137+
--secure_debug_pk ${SECURE_DEBUG_PK}
138+
--huk ${HUK}
139+
--iak ${IAK}
140+
--boot_seed ${BOOT_SEED}
141+
--implementation_id ${IMPLEMENTATION_ID}
142+
--certification_reference ${CERTIFICATION_REFERENCE}
143+
--verification_service_url ${VERIFICATION_SERVICE_URL}
144+
--entropy_seed ${ENTROPY_SEED}
145+
146+
)
147+
148+
endif()

platform/ext/target/arm/mps3/an552/provisioning/bl2_provisioning.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ enum tfm_plat_err_t tfm_plat_provisioning_perform(void)
7070

7171
if (lcs == PLAT_OTP_LCS_ASSEMBLY_AND_TEST) {
7272

73-
BOOT_LOG_INF("[INF] Waiting for CM provisioning bundle\r\n");
73+
BOOT_LOG_INF("[INF] Waiting for provisioning bundle\r\n");
7474
while (encrypted_bundle->magic != BUNDLE_MAGIC ||
7575
encrypted_bundle->magic2 != BUNDLE_MAGIC) {
7676
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#! /usr/bin/env python3
2+
#
3+
# -----------------------------------------------------------------------------
4+
# Copyright (c) 2020-2022, Arm Limited. All rights reserved.
5+
#
6+
# SPDX-License-Identifier: BSD-3-Clause
7+
#
8+
# -----------------------------------------------------------------------------
9+
10+
import re
11+
import os
12+
import sys
13+
import click
14+
from jinja2 import Environment, FileSystemLoader
15+
from cryptography.hazmat.primitives.hashes import Hash, SHA256
16+
17+
# Add the cwd to the path so that if there is a version of imgtool in there then
18+
# it gets used over the system imgtool. Used so that imgtool from upstream
19+
# mcuboot is preferred over system imgtool
20+
cwd = os.getcwd()
21+
sys.path = [cwd] + sys.path
22+
import imgtool
23+
import imgtool.main
24+
25+
parser_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../'))
26+
sys.path.append(parser_path)
27+
28+
29+
sign_bin_size_re = re.compile(r"^\s*RE_SIGN_BIN_SIZE\s*=\s*(.*)")
30+
load_addr_re = re.compile(r"^\s*RE_IMAGE_LOAD_ADDRESS\s*=\s*(.*)")
31+
rom_fixed_re = re.compile(r"^\s*RE_IMAGE_ROM_FIXED\s*=\s*(.*)")
32+
33+
#This works around Python 2 and Python 3 handling character encodings
34+
#differently. More information about this issue at
35+
#https://click.palletsprojects.com/en/5.x/python3
36+
os.environ['LC_ALL'] = 'C.UTF-8'
37+
os.environ['LANG'] = 'C.UTF-8'
38+
39+
40+
def get_key_hash_c_array(key_file):
41+
key = imgtool.main.load_key(key_file)
42+
digest = Hash(SHA256())
43+
digest.update(key.get_public_bytes())
44+
return hex_to_c_array(digest.finalize())
45+
46+
47+
@click.argument('outfile')
48+
@click.option('--bl2_rot_priv_key_0', metavar='filename', required=True)
49+
@click.option('--bl2_rot_priv_key_1', metavar='filename', required=False)
50+
@click.option('--bl2_rot_priv_key_2', metavar='filename', required=False)
51+
@click.option('--bl2_rot_priv_key_3', metavar='filename', required=False)
52+
@click.option('--template_path', metavar='filename', required=True)
53+
@click.option('--secure_debug_pk', metavar='key', required=False)
54+
@click.option('--huk', metavar='key', required=False)
55+
@click.option('--iak', metavar='key', required=False)
56+
@click.option('--boot_seed', metavar='seed', required=False)
57+
@click.option('--implementation_id', metavar='id', required=False)
58+
@click.option('--certification_reference', metavar='reference', required=True)
59+
@click.option('--verification_service_url', metavar='url', required=True)
60+
@click.option('--entropy_seed', metavar='seed', required=False)
61+
@click.command(help='''Create a signed or unsigned image\n
62+
INFILE and OUTFILE are parsed as Intel HEX if the params have
63+
.hex extension, otherwise binary format is used''')
64+
def generate_provisioning_data_c(outfile, bl2_rot_priv_key_0,
65+
bl2_rot_priv_key_1,
66+
template_path, bl2_rot_priv_key_2,
67+
bl2_rot_priv_key_3,
68+
secure_debug_pk, huk, iak, boot_seed,
69+
implementation_id,
70+
certification_reference,
71+
verification_service_url,
72+
entropy_seed):
73+
74+
environment = Environment(loader=FileSystemLoader(template_path))
75+
template = environment.get_template("provisioning_data_template.jinja2")
76+
77+
# getpubhash cannot be called directly because of its click decorators
78+
bl2_rot_pub_key_0_hash = ""
79+
if bool(bl2_rot_priv_key_0) is True:
80+
bl2_rot_pub_key_0_hash = get_key_hash_c_array(bl2_rot_priv_key_0)
81+
82+
bl2_rot_pub_key_1_hash = ""
83+
if bool(bl2_rot_priv_key_1) is True:
84+
bl2_rot_pub_key_1_hash = get_key_hash_c_array(bl2_rot_priv_key_1)
85+
86+
bl2_rot_pub_key_2_hash = ""
87+
if bool(bl2_rot_priv_key_2) is True:
88+
bl2_rot_pub_key_2_hash = get_key_hash_c_array(bl2_rot_priv_key_2)
89+
90+
bl2_rot_pub_key_3_hash = ""
91+
if bool(bl2_rot_priv_key_3) is True:
92+
bl2_rot_pub_key_3_hash = get_key_hash_c_array(bl2_rot_priv_key_3)
93+
94+
if bool(huk) is False:
95+
huk = hex_to_c_array(os.urandom(32))
96+
97+
if bool(iak) is False:
98+
iak = hex_to_c_array(os.urandom(32))
99+
100+
if bool(boot_seed) is False:
101+
boot_seed = hex_to_c_array(os.urandom(32))
102+
103+
if bool(implementation_id) is False:
104+
implementation_id = hex_to_c_array(os.urandom(32))
105+
106+
if bool(entropy_seed) is False:
107+
entropy_seed = hex_to_c_array(os.urandom(64))
108+
109+
key_arrays = {
110+
"bl2_rotpk_0": bl2_rot_pub_key_0_hash,
111+
"bl2_rotpk_1": bl2_rot_pub_key_1_hash,
112+
"bl2_rotpk_2": bl2_rot_pub_key_2_hash,
113+
"bl2_rotpk_3": bl2_rot_pub_key_3_hash,
114+
"secure_debug_pk": secure_debug_pk,
115+
"huk": huk,
116+
"iak": iak,
117+
"iak_len": "32",
118+
"boot_seed": boot_seed,
119+
"implementation_id": implementation_id,
120+
"certification_reference": certification_reference,
121+
"verification_service_url": verification_service_url,
122+
"entropy_seed": entropy_seed
123+
}
124+
125+
with open(outfile, "w") as F:
126+
F.write(template.render(key_arrays))
127+
128+
129+
def hex_to_c_array(hex_val):
130+
c_array = ""
131+
for count, b in enumerate(hex_val):
132+
if count % 8 == 0 and count != 0:
133+
c_array = c_array + '\n'
134+
c_array = c_array + "0x{:02x}, ".format(b)
135+
136+
return c_array
137+
138+
139+
if __name__ == '__main__':
140+
generate_provisioning_data_c()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2023 Arm Limited. All rights reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
#include "region_defs.h"
19+
20+
do not initialize { section .noinit };
21+
do not initialize { readwrite };
22+
23+
define block VALUES with fixed order, maximum size = PROVISIONING_BUNDLE_VALUES_SIZE {
24+
ro object *provisioning_data.o
25+
};
26+
"VALUES": place at address PROVISIONING_BUNDLE_VALUES_START { block VALUES };
27+
28+
define ram region DATA = [from PROVISIONING_BUNDLE_DATA_START size PROVISIONING_BUNDLE_DATA_SIZE];
29+
30+
define block RW_DATA {
31+
rw data
32+
};
33+
"RW_DATA": place at start of DATA { block RW_DATA };
34+
35+
define block RO_DATA {
36+
ro data
37+
} except {
38+
ro object *provisioning_data.o
39+
};
40+
"RO_DATA": place in DATA { block RO_DATA };
41+
42+
define block BSS_DATA {
43+
zi section .bss
44+
};
45+
"BSS_DATA": place in DATA { block BSS_DATA };
46+
47+
define block CODE with fixed order, alignment = 4, maximum size = PROVISIONING_BUNDLE_CODE_SIZE {
48+
ro section DO_PROVISION,
49+
ro code,
50+
};
51+
"CODE": place at address PROVISIONING_BUNDLE_CODE_START { block CODE };

platform/ext/target/arm/mps3/an552/provisioning/provisioning_bundle.ld

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ SECTIONS
5959

6060
VALUES :
6161
{
62-
*_provisioning_data.o(.rodata.data)
62+
*provisioning_data.o(.rodata.data)
6363
} > VALUES
6464

6565
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#-------------------------------------------------------------------------------
2+
# Copyright (c) 2023, Arm Limited. All rights reserved.
3+
#
4+
# SPDX-License-Identifier: BSD-3-Clause
5+
#
6+
#-------------------------------------------------------------------------------
7+
8+
set(SECURE_DEBUG_PK "0xf4, 0x0c, 0x8f, 0xbf, 0x12, 0xdb, 0x78, 0x2a, \
9+
0xfd, 0xf4, 0x75, 0x96, 0x6a, 0x06, 0x82, 0x36, \
10+
0xe0, 0x32, 0xab, 0x80, 0xd1, 0xb7, 0xf1, 0xbc, \
11+
0x9f, 0xe7, 0xd8, 0x7a, 0x88, 0xcb, 0x26, 0xd0," CACHE STRING "")
12+
13+
set(HUK "0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
14+
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, \
15+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
16+
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f" CACHE STRING "Hardware unique key")
17+
18+
set(IAK "0xA9, 0xB4, 0x54, 0xB2, 0x6D, 0x6F, 0x90, 0xA4, \
19+
0xEA, 0x31, 0x19, 0x35, 0x64, 0xCB, 0xA9, 0x1F, \
20+
0xEC, 0x6F, 0x9A, 0x00, 0x2A, 0x7D, 0xC0, 0x50, \
21+
0x4B, 0x92, 0xA1, 0x93, 0x71, 0x34, 0x58, 0x5F" CACHE STRING "Initial attestaion key")
22+
23+
set(IAK_LEN "32" CACHE STRING "Initial attestaion key len")
24+
25+
set(BOOT_SEED "0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, \
26+
0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, \
27+
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, \
28+
0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF," CACHE STRING "")
29+
30+
set(IMPLEMENTATION_ID "0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, \
31+
0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, \
32+
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, \
33+
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD," CACHE STRING "")
34+
35+
set(CERTIFICATION_REFERENCE "0604565272829-10010" CACHE STRING "")
36+
37+
set(VERIFICATION_SERVICE_URL "www.trustedfirmware.org" CACHE STRING "")
38+
39+
set(ENTROPY_SEED "0x12, 0x13, 0x23, 0x34, 0x0a, 0x05, 0x89, 0x78, \
40+
0xa3, 0x66, 0x8c, 0x0d, 0x97, 0x55, 0x53, 0xca, \
41+
0xb5, 0x76, 0x18, 0x62, 0x29, 0xc6, 0xb6, 0x79, \
42+
0x75, 0xc8, 0x5a, 0x8d, 0x9e, 0x11, 0x8f, 0x85, \
43+
0xde, 0xc4, 0x5f, 0x66, 0x21, 0x52, 0xf9, 0x39, \
44+
0xd9, 0x77, 0x93, 0x28, 0xb0, 0x5e, 0x02, 0xfa, \
45+
0x58, 0xb4, 0x16, 0xc8, 0x0f, 0x38, 0x91, 0xbb, \
46+
0x28, 0x17, 0xcd, 0x8a, 0xc9, 0x53, 0x72, 0x66" CACHE STRING "")
47+
48+

0 commit comments

Comments
 (0)