mirror of https://github.com/ARMmbed/mbed-os.git
Import latest python scripts and MCUBoot image
To help with the integration of Musca B1 into Mbed OS, python signing scripts and MCUBoot image and RSA private key for Musca A has been updated from latest TF-M (https://git.trustedfirmware.org/trusted-firmware-m.git/commit/?id=6c5be4a98e4d7055ee49076ca4e515fb4b172e66). Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com>pull/12231/head
parent
a81f016abc
commit
bc7331b96e
|
@ -10,7 +10,7 @@ These images were compiled by the following command:
|
||||||
### Repository
|
### Repository
|
||||||
https://git.trustedfirmware.org/trusted-firmware-m.git
|
https://git.trustedfirmware.org/trusted-firmware-m.git
|
||||||
### Commit SHA
|
### Commit SHA
|
||||||
8da7f102a6a6a1a99462f7f32edbd1565096c2f3
|
6c5be4a98e4d7055ee49076ca4e515fb4b172e66
|
||||||
```sh
|
```sh
|
||||||
cmake ../ -G"Unix Makefiles" -DTARGET_PLATFORM=MUSCA_A -DCOMPILER=ARMCLANG -DCMAKE_BUILD_TYPE=Debug
|
cmake ../ -G"Unix Makefiles" -DTARGET_PLATFORM=MUSCA_A -DCOMPILER=ARMCLANG -DCMAKE_BUILD_TYPE=Debug
|
||||||
make
|
make
|
||||||
|
|
Binary file not shown.
|
@ -1,7 +1,7 @@
|
||||||
#! /usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2017 Linaro Limited
|
# Copyright 2017 Linaro Limited
|
||||||
# Copyright (c) 2017-2018, Arm Limited.
|
# Copyright (c) 2017-2019, Arm Limited.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
@ -25,6 +25,7 @@ import io
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
from . import macro_parser
|
||||||
|
|
||||||
offset_re = re.compile(r"^#define ([0-9A-Z_]+)_IMAGE_OFFSET\s+((0x)?[0-9a-fA-F]+)")
|
offset_re = re.compile(r"^#define ([0-9A-Z_]+)_IMAGE_OFFSET\s+((0x)?[0-9a-fA-F]+)")
|
||||||
size_re = re.compile(r"^#define ([0-9A-Z_]+)_IMAGE_MAX_SIZE\s+((0x)?[0-9a-fA-F]+)")
|
size_re = re.compile(r"^#define ([0-9A-Z_]+)_IMAGE_MAX_SIZE\s+((0x)?[0-9a-fA-F]+)")
|
||||||
|
@ -44,20 +45,8 @@ class Assembly():
|
||||||
offsets = {}
|
offsets = {}
|
||||||
sizes = {}
|
sizes = {}
|
||||||
|
|
||||||
if os.path.isabs(self.layout_path):
|
offsets = macro_parser.evaluate_macro(self.layout_path, offset_re, 1, 2)
|
||||||
configFile = self.layout_path
|
sizes = macro_parser.evaluate_macro(self.layout_path, size_re, 1, 2)
|
||||||
else:
|
|
||||||
scriptsDir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
configFile = os.path.join(scriptsDir, self.layout_path)
|
|
||||||
|
|
||||||
with open(configFile, 'r') as fd:
|
|
||||||
for line in fd:
|
|
||||||
m = offset_re.match(line)
|
|
||||||
if m is not None:
|
|
||||||
offsets[m.group(1)] = int(m.group(2), 0)
|
|
||||||
m = size_re.match(line)
|
|
||||||
if m is not None:
|
|
||||||
sizes[m.group(1)] = int(m.group(2), 0)
|
|
||||||
|
|
||||||
if 'SECURE' not in offsets:
|
if 'SECURE' not in offsets:
|
||||||
raise Exception("Image config does not have secure partition")
|
raise Exception("Image config does not have secure partition")
|
||||||
|
@ -86,7 +75,7 @@ def main():
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
parser.add_argument('-l', '--layout', required=True,
|
parser.add_argument('-l', '--layout', required=True,
|
||||||
help='Location of the memory layout file')
|
help='Location of the file that contains preprocessed macros')
|
||||||
parser.add_argument('-s', '--secure', required=True,
|
parser.add_argument('-s', '--secure', required=True,
|
||||||
help='Unsigned secure image')
|
help='Unsigned secure image')
|
||||||
parser.add_argument('-n', '--non_secure',
|
parser.add_argument('-n', '--non_secure',
|
||||||
|
@ -97,7 +86,6 @@ def main():
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
output = Assembly(args.layout, args.output)
|
output = Assembly(args.layout, args.output)
|
||||||
|
|
||||||
|
|
||||||
output.add_image(args.secure, "SECURE")
|
output.add_image(args.secure, "SECURE")
|
||||||
output.add_image(args.non_secure, "NON_SECURE")
|
output.add_image(args.non_secure, "NON_SECURE")
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#! /usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2017 Linaro Limited
|
# Copyright 2017 Linaro Limited
|
||||||
# Copyright (c) 2018, Arm Limited.
|
# Copyright (c) 2018-2019, Arm Limited.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
@ -24,6 +24,9 @@ from .imgtool_lib import image
|
||||||
from .imgtool_lib import version
|
from .imgtool_lib import version
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
sign_bin_size_re = re.compile(r"^\s*RE_SIGN_BIN_SIZE\s*=\s*(.*)")
|
||||||
|
image_load_address_re = re.compile(r"^\s*RE_IMAGE_LOAD_ADDRESS\s*=\s*(.*)")
|
||||||
|
|
||||||
def find_load_address(args):
|
def find_load_address(args):
|
||||||
load_address_re = re.compile(r"^#define\sIMAGE_LOAD_ADDRESS\s+(0x[0-9a-fA-F]+)")
|
load_address_re = re.compile(r"^#define\sIMAGE_LOAD_ADDRESS\s+(0x[0-9a-fA-F]+)")
|
||||||
|
|
||||||
|
@ -60,6 +63,7 @@ def get_last_version(path):
|
||||||
|
|
||||||
def next_version_number(args, defaultVersion, path):
|
def next_version_number(args, defaultVersion, path):
|
||||||
newVersion = None
|
newVersion = None
|
||||||
|
versionProvided = False
|
||||||
if (version.compare(args.version, defaultVersion) == 0): # Default version
|
if (version.compare(args.version, defaultVersion) == 0): # Default version
|
||||||
lastVersion = get_last_version(path)
|
lastVersion = get_last_version(path)
|
||||||
if (lastVersion is not None):
|
if (lastVersion is not None):
|
||||||
|
@ -67,6 +71,7 @@ def next_version_number(args, defaultVersion, path):
|
||||||
else:
|
else:
|
||||||
newVersion = version.increment_build_num(defaultVersion)
|
newVersion = version.increment_build_num(defaultVersion)
|
||||||
else: # Version number has been explicitly provided (not using the default)
|
else: # Version number has been explicitly provided (not using the default)
|
||||||
|
versionProvided = True
|
||||||
newVersion = args.version
|
newVersion = args.version
|
||||||
versionString = "{a}.{b}.{c}+{d}".format(
|
versionString = "{a}.{b}.{c}+{d}".format(
|
||||||
a=str(newVersion.major),
|
a=str(newVersion.major),
|
||||||
|
@ -74,16 +79,21 @@ def next_version_number(args, defaultVersion, path):
|
||||||
c=str(newVersion.revision),
|
c=str(newVersion.revision),
|
||||||
d=str(newVersion.build)
|
d=str(newVersion.build)
|
||||||
)
|
)
|
||||||
with open(path, "w") as newFile:
|
if not versionProvided:
|
||||||
newFile.write(versionString)
|
with open(path, "w") as newFile:
|
||||||
|
newFile.write(versionString)
|
||||||
print("**[INFO]** Image version number set to " + versionString)
|
print("**[INFO]** Image version number set to " + versionString)
|
||||||
return newVersion
|
return newVersion
|
||||||
|
|
||||||
def gen_rsa2048(args):
|
def gen_rsa2048(args):
|
||||||
keys.RSA2048.generate().export_private(args.key)
|
keys.RSAutil.generate().export_private(args.key)
|
||||||
|
|
||||||
|
def gen_rsa3072(args):
|
||||||
|
keys.RSAutil.generate(key_size=3072).export_private(args.key)
|
||||||
|
|
||||||
keygens = {
|
keygens = {
|
||||||
'rsa-2048': gen_rsa2048, }
|
'rsa-2048': gen_rsa2048,
|
||||||
|
'rsa-3072': gen_rsa3072, }
|
||||||
|
|
||||||
def do_keygen(args):
|
def do_keygen(args):
|
||||||
if args.type not in keygens:
|
if args.type not in keygens:
|
||||||
|
@ -102,18 +112,38 @@ def do_getpub(args):
|
||||||
def do_sign(args):
|
def do_sign(args):
|
||||||
if args.rsa_pkcs1_15:
|
if args.rsa_pkcs1_15:
|
||||||
keys.sign_rsa_pss = False
|
keys.sign_rsa_pss = False
|
||||||
img = image.Image.load(args.infile,
|
|
||||||
version=next_version_number(args,
|
|
||||||
version.decode_version("0"),
|
|
||||||
"lastVerNum.txt"),
|
|
||||||
header_size=args.header_size,
|
|
||||||
included_header=args.included_header,
|
|
||||||
pad=args.pad)
|
|
||||||
key = keys.load(args.key) if args.key else None
|
|
||||||
img.sign(key, find_load_address(args))
|
|
||||||
|
|
||||||
if args.pad:
|
version_num = next_version_number(args,
|
||||||
img.pad_to(args.pad, args.align)
|
version.decode_version("0"),
|
||||||
|
"lastVerNum.txt")
|
||||||
|
|
||||||
|
if args.security_counter is None:
|
||||||
|
# Security counter has not been explicitly provided,
|
||||||
|
# generate it from the version number
|
||||||
|
args.security_counter = ((version_num.major << 24)
|
||||||
|
+ (version_num.minor << 16)
|
||||||
|
+ version_num.revision)
|
||||||
|
|
||||||
|
if "_s.c" in args.layout:
|
||||||
|
sw_type = "SPE"
|
||||||
|
elif "_ns.c" in args.layout:
|
||||||
|
sw_type = "NSPE"
|
||||||
|
else:
|
||||||
|
sw_type = "NSPE_SPE"
|
||||||
|
|
||||||
|
pad_size = args.pad
|
||||||
|
img = image.Image.load(args.infile,
|
||||||
|
version=version_num,
|
||||||
|
header_size=args.header_size,
|
||||||
|
security_cnt=args.security_counter,
|
||||||
|
included_header=args.included_header,
|
||||||
|
pad=pad_size)
|
||||||
|
key = keys.load(args.key, args.public_key_format) if args.key else None
|
||||||
|
ram_load_address = find_load_address(args)
|
||||||
|
img.sign(sw_type, key, ram_load_address, args.dependencies)
|
||||||
|
|
||||||
|
if pad_size:
|
||||||
|
img.pad_to(pad_size, args.align)
|
||||||
|
|
||||||
img.save(args.outfile)
|
img.save(args.outfile)
|
||||||
|
|
||||||
|
@ -122,6 +152,30 @@ subcmds = {
|
||||||
'getpub': do_getpub,
|
'getpub': do_getpub,
|
||||||
'sign': do_sign, }
|
'sign': do_sign, }
|
||||||
|
|
||||||
|
|
||||||
|
def get_dependencies(text):
|
||||||
|
if text is not None:
|
||||||
|
versions = []
|
||||||
|
images = re.findall(r"\((\d+)", text)
|
||||||
|
if len(images) == 0:
|
||||||
|
msg = "Image dependency format is invalid: {}".format(text)
|
||||||
|
raise argparse.ArgumentTypeError(msg)
|
||||||
|
raw_versions = re.findall(r",\s*([0-9.+]+)\)", text)
|
||||||
|
if len(images) != len(raw_versions):
|
||||||
|
msg = '''There's a mismatch between the number of dependency images
|
||||||
|
and versions in: {}'''.format(text)
|
||||||
|
raise argparse.ArgumentTypeError(msg)
|
||||||
|
for raw_version in raw_versions:
|
||||||
|
try:
|
||||||
|
versions.append(version.decode_version(raw_version))
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
dependencies = dict()
|
||||||
|
dependencies[image.DEP_IMAGES_KEY] = images
|
||||||
|
dependencies[image.DEP_VERSIONS_KEY] = versions
|
||||||
|
return dependencies
|
||||||
|
|
||||||
|
|
||||||
def alignment_value(text):
|
def alignment_value(text):
|
||||||
value = int(text)
|
value = int(text)
|
||||||
if value not in [1, 2, 4, 8]:
|
if value not in [1, 2, 4, 8]:
|
||||||
|
@ -149,17 +203,23 @@ def args():
|
||||||
getpub.add_argument('-l', '--lang', metavar='lang', default='c')
|
getpub.add_argument('-l', '--lang', metavar='lang', default='c')
|
||||||
|
|
||||||
sign = subs.add_parser('sign', help='Sign an image with a private key')
|
sign = subs.add_parser('sign', help='Sign an image with a private key')
|
||||||
sign.add_argument('--layout', required=True,
|
sign.add_argument('-l', '--layout', required=True,
|
||||||
help='Location of the memory layout file')
|
help='Location of the file that contains preprocessed macros')
|
||||||
sign.add_argument('-k', '--key', metavar='filename')
|
sign.add_argument('-k', '--key', metavar='filename')
|
||||||
|
sign.add_argument("-K", "--public-key-format",
|
||||||
|
help='In what format to add the public key to the image manifest: full or hash',
|
||||||
|
metavar='pub_key_format', choices=['full', 'hash'], default='hash')
|
||||||
sign.add_argument("--align", type=alignment_value, required=True)
|
sign.add_argument("--align", type=alignment_value, required=True)
|
||||||
sign.add_argument("-v", "--version", type=version.decode_version,
|
sign.add_argument("-v", "--version", type=version.decode_version,
|
||||||
default="0.0.0+0")
|
default="0.0.0+0")
|
||||||
|
sign.add_argument("-d", "--dependencies", type=get_dependencies,
|
||||||
|
required=False, help='''Add dependence on another image,
|
||||||
|
format: "(<image_ID>,<image_version>), ... "''')
|
||||||
|
sign.add_argument("-s", "--security-counter", type=intparse,
|
||||||
|
help='Specify explicitly the security counter value')
|
||||||
sign.add_argument("-H", "--header-size", type=intparse, required=True)
|
sign.add_argument("-H", "--header-size", type=intparse, required=True)
|
||||||
sign.add_argument("--included-header", default=False, action='store_true',
|
sign.add_argument("--included-header", default=False, action='store_true',
|
||||||
help='Image has gap for header')
|
help='Image has gap for header')
|
||||||
sign.add_argument("--pad", type=intparse,
|
|
||||||
help='Pad image to this many bytes, adding trailer magic')
|
|
||||||
sign.add_argument("--rsa-pkcs1-15",
|
sign.add_argument("--rsa-pkcs1-15",
|
||||||
help='Use old PKCS#1 v1.5 signature algorithm',
|
help='Use old PKCS#1 v1.5 signature algorithm',
|
||||||
default=False, action='store_true')
|
default=False, action='store_true')
|
||||||
|
@ -174,4 +234,4 @@ def args():
|
||||||
subcmds[args.subcmd](args)
|
subcmds[args.subcmd](args)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
args()
|
args()
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
|
||||||
|
# Copyright (c) 2019, 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.
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import cbor
|
||||||
|
|
||||||
|
|
||||||
|
# SW component IDs
|
||||||
|
SW_COMPONENT_RANGE = 0
|
||||||
|
SW_COMPONENT_TYPE = SW_COMPONENT_RANGE + 1
|
||||||
|
MEASUREMENT_VALUE = SW_COMPONENT_RANGE + 2
|
||||||
|
SW_COMPONENT_VERSION = SW_COMPONENT_RANGE + 4
|
||||||
|
SIGNER_ID = SW_COMPONENT_RANGE + 5
|
||||||
|
MEASUREMENT_DESCRIPTION = SW_COMPONENT_RANGE + 6
|
||||||
|
|
||||||
|
|
||||||
|
def create_sw_component_data(sw_type, sw_version, sw_measurement_type,
|
||||||
|
sw_measurement_value, sw_signer_id):
|
||||||
|
|
||||||
|
# List of SW component claims (key ID + value)
|
||||||
|
key_value_list = [
|
||||||
|
SW_COMPONENT_TYPE, sw_type,
|
||||||
|
SW_COMPONENT_VERSION, sw_version,
|
||||||
|
SIGNER_ID, sw_signer_id,
|
||||||
|
MEASUREMENT_DESCRIPTION, sw_measurement_type,
|
||||||
|
MEASUREMENT_VALUE, sw_measurement_value
|
||||||
|
]
|
||||||
|
# The measurement value should be the last item (key + value) in the list
|
||||||
|
# to make it easier to modify its value later in the bootloader.
|
||||||
|
# A dictionary would be the best suited data structure to store these
|
||||||
|
# key-value pairs (claims), however dictionaries are not sorted, but for
|
||||||
|
# example the lists do keep to order of items which we care about now.
|
||||||
|
# An ordered dictionary could be used instead, but it would be converted
|
||||||
|
# to a dict before the encoding and this conversion may not keep the order
|
||||||
|
# of the items.
|
||||||
|
|
||||||
|
if (len(key_value_list) % 2) != 0:
|
||||||
|
print('Error: The length of the sw component claim list must '
|
||||||
|
'be even (key + value).', file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
claim_number = (int)(len(key_value_list) / 2)
|
||||||
|
|
||||||
|
# The output of this function must be a CBOR encoded map (dictionary) of
|
||||||
|
# the SW component claims. The CBOR representation of an array and a map
|
||||||
|
# (dictionary) is quite similar. To convert the encoded list to a map, it
|
||||||
|
# is enough to modify the first byte (CBOR data item header) of the
|
||||||
|
# data. This applies up to 23 items (11 claims in this case) - until the 5
|
||||||
|
# lower bits of the item header are used as an item count specifier.
|
||||||
|
|
||||||
|
if claim_number > 11:
|
||||||
|
print('Error: There are more than 11 claims in the '
|
||||||
|
'list of sw component claims.', file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
record_array = bytearray(cbor.dumps(key_value_list))
|
||||||
|
# Modify the CBOR data item header (from array to map)
|
||||||
|
# 7..5 bits : Major type
|
||||||
|
# Array - 0x80
|
||||||
|
# Map - 0xA0
|
||||||
|
# 4..0 bits : Number of items
|
||||||
|
record_array[0] = 0xA0 + claim_number
|
||||||
|
|
||||||
|
return bytes(record_array)
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright 2017 Linaro Limited
|
# Copyright 2017 Linaro Limited
|
||||||
# Copyright (c) 2018, Arm Limited.
|
# Copyright (c) 2018-2019, Arm Limited.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
@ -18,11 +18,17 @@ Image signing and management.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from . import version as versmod
|
from . import version as versmod
|
||||||
|
from . import boot_record as br
|
||||||
import hashlib
|
import hashlib
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
IMAGE_MAGIC = 0x96f3b83d
|
IMAGE_MAGIC = 0x96f3b83d
|
||||||
IMAGE_HEADER_SIZE = 32
|
IMAGE_HEADER_SIZE = 32
|
||||||
|
TLV_HEADER_SIZE = 4
|
||||||
|
PAYLOAD_DIGEST_SIZE = 32 # SHA256 hash
|
||||||
|
KEYHASH_SIZE = 32
|
||||||
|
DEP_IMAGES_KEY = "images"
|
||||||
|
DEP_VERSIONS_KEY = "versions"
|
||||||
|
|
||||||
# Image header flags.
|
# Image header flags.
|
||||||
IMAGE_F = {
|
IMAGE_F = {
|
||||||
|
@ -31,11 +37,17 @@ IMAGE_F = {
|
||||||
'RAM_LOAD': 0x0000020, }
|
'RAM_LOAD': 0x0000020, }
|
||||||
TLV_VALUES = {
|
TLV_VALUES = {
|
||||||
'KEYHASH': 0x01,
|
'KEYHASH': 0x01,
|
||||||
|
'KEY' : 0x02,
|
||||||
'SHA256' : 0x10,
|
'SHA256' : 0x10,
|
||||||
'RSA2048': 0x20, }
|
'RSA2048': 0x20,
|
||||||
|
'RSA3072': 0x23,
|
||||||
|
'DEPENDENCY': 0x40,
|
||||||
|
'SEC_CNT': 0x50,
|
||||||
|
'BOOT_RECORD': 0x60, }
|
||||||
|
|
||||||
TLV_INFO_SIZE = 4
|
TLV_INFO_SIZE = 4
|
||||||
TLV_INFO_MAGIC = 0x6907
|
TLV_INFO_MAGIC = 0x6907
|
||||||
|
TLV_PROT_INFO_MAGIC = 0x6908
|
||||||
|
|
||||||
# Sizes of the image trailer, depending on flash write size.
|
# Sizes of the image trailer, depending on flash write size.
|
||||||
trailer_sizes = {
|
trailer_sizes = {
|
||||||
|
@ -50,17 +62,25 @@ boot_magic = bytearray([
|
||||||
0x2c, 0xb6, 0x79, 0x80, ])
|
0x2c, 0xb6, 0x79, 0x80, ])
|
||||||
|
|
||||||
class TLV():
|
class TLV():
|
||||||
def __init__(self):
|
def __init__(self, magic=TLV_INFO_MAGIC):
|
||||||
|
self.magic = magic
|
||||||
self.buf = bytearray()
|
self.buf = bytearray()
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return TLV_INFO_SIZE + len(self.buf)
|
||||||
|
|
||||||
def add(self, kind, payload):
|
def add(self, kind, payload):
|
||||||
"""Add a TLV record. Kind should be a string found in TLV_VALUES above."""
|
"""
|
||||||
|
Add a TLV record. Kind should be a string found in TLV_VALUES above.
|
||||||
|
"""
|
||||||
buf = struct.pack('<BBH', TLV_VALUES[kind], 0, len(payload))
|
buf = struct.pack('<BBH', TLV_VALUES[kind], 0, len(payload))
|
||||||
self.buf += buf
|
self.buf += buf
|
||||||
self.buf += payload
|
self.buf += payload
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
header = struct.pack('<HH', TLV_INFO_MAGIC, TLV_INFO_SIZE + len(self.buf))
|
if len(self.buf) == 0:
|
||||||
|
return bytes()
|
||||||
|
header = struct.pack('<HH', self.magic, len(self))
|
||||||
return header + bytes(self.buf)
|
return header + bytes(self.buf)
|
||||||
|
|
||||||
class Image():
|
class Image():
|
||||||
|
@ -79,15 +99,19 @@ class Image():
|
||||||
obj.check()
|
obj.check()
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def __init__(self, version, header_size=IMAGE_HEADER_SIZE, pad=0):
|
def __init__(self, version, header_size=IMAGE_HEADER_SIZE, security_cnt=0,
|
||||||
|
pad=0):
|
||||||
self.version = version
|
self.version = version
|
||||||
self.header_size = header_size or IMAGE_HEADER_SIZE
|
self.header_size = header_size or IMAGE_HEADER_SIZE
|
||||||
|
self.security_cnt = security_cnt
|
||||||
self.pad = pad
|
self.pad = pad
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Image version={}, header_size={}, pad={}, payloadlen=0x{:x}>".format(
|
return "<Image version={}, header_size={}, security_counter={}, \
|
||||||
|
pad={}, payloadlen=0x{:x}>".format(
|
||||||
self.version,
|
self.version,
|
||||||
self.header_size,
|
self.header_size,
|
||||||
|
self.security_cnt,
|
||||||
self.pad,
|
self.pad,
|
||||||
len(self.payload))
|
len(self.payload))
|
||||||
|
|
||||||
|
@ -103,30 +127,94 @@ class Image():
|
||||||
if any(v != 0 and v != b'\000' for v in self.payload[0:self.header_size]):
|
if any(v != 0 and v != b'\000' for v in self.payload[0:self.header_size]):
|
||||||
raise Exception("Padding requested, but image does not start with zeros")
|
raise Exception("Padding requested, but image does not start with zeros")
|
||||||
|
|
||||||
def sign(self, key, ramLoadAddress):
|
def sign(self, sw_type, key, ramLoadAddress, dependencies=None):
|
||||||
self.add_header(key, ramLoadAddress)
|
image_version = (str(self.version.major) + '.'
|
||||||
|
+ str(self.version.minor) + '.'
|
||||||
tlv = TLV()
|
+ str(self.version.revision))
|
||||||
|
|
||||||
sha = hashlib.sha256()
|
|
||||||
sha.update(self.payload)
|
|
||||||
digest = sha.digest()
|
|
||||||
|
|
||||||
tlv.add('SHA256', digest)
|
|
||||||
|
|
||||||
|
# Calculate the hash of the public key
|
||||||
if key is not None:
|
if key is not None:
|
||||||
pub = key.get_public_bytes()
|
pub = key.get_public_bytes()
|
||||||
sha = hashlib.sha256()
|
sha = hashlib.sha256()
|
||||||
sha.update(pub)
|
sha.update(pub)
|
||||||
pubbytes = sha.digest()
|
pubbytes = sha.digest()
|
||||||
tlv.add('KEYHASH', pubbytes)
|
else:
|
||||||
|
pubbytes = bytes(KEYHASH_SIZE)
|
||||||
|
|
||||||
sig = key.sign(self.payload)
|
# The image hash is computed over the image header, the image itself
|
||||||
|
# and the protected TLV area. However, the boot record TLV (which is
|
||||||
|
# part of the protected area) should contain this hash before it is
|
||||||
|
# even calculated. For this reason the script fills this field with
|
||||||
|
# zeros and the bootloader will insert the right value later.
|
||||||
|
image_hash = bytes(PAYLOAD_DIGEST_SIZE)
|
||||||
|
|
||||||
|
# Create CBOR encoded boot record
|
||||||
|
boot_record = br.create_sw_component_data(sw_type, image_version,
|
||||||
|
"SHA256", image_hash,
|
||||||
|
pubbytes)
|
||||||
|
|
||||||
|
# Mandatory protected TLV area: TLV info header
|
||||||
|
# + security counter TLV
|
||||||
|
# + boot record TLV
|
||||||
|
# Size of the security counter TLV: header ('BBH') + payload ('I')
|
||||||
|
# = 8 Bytes
|
||||||
|
protected_tlv_size = TLV_INFO_SIZE + 8 + TLV_HEADER_SIZE \
|
||||||
|
+ len(boot_record)
|
||||||
|
|
||||||
|
if dependencies is None:
|
||||||
|
dependencies_num = 0
|
||||||
|
else:
|
||||||
|
# Size of a dependency TLV:
|
||||||
|
# header ('BBH') + payload('IBBHI') = 16 Bytes
|
||||||
|
dependencies_num = len(dependencies[DEP_IMAGES_KEY])
|
||||||
|
protected_tlv_size += (dependencies_num * 16)
|
||||||
|
|
||||||
|
# At this point the image is already on the payload, this adds
|
||||||
|
# the header to the payload as well
|
||||||
|
self.add_header(key, protected_tlv_size, ramLoadAddress)
|
||||||
|
|
||||||
|
prot_tlv = TLV(TLV_PROT_INFO_MAGIC)
|
||||||
|
|
||||||
|
# Protected TLVs must be added first, because they are also included
|
||||||
|
# in the hash calculation
|
||||||
|
payload = struct.pack('I', self.security_cnt)
|
||||||
|
prot_tlv.add('SEC_CNT', payload)
|
||||||
|
prot_tlv.add('BOOT_RECORD', boot_record)
|
||||||
|
|
||||||
|
if dependencies_num != 0:
|
||||||
|
for i in range(dependencies_num):
|
||||||
|
payload = struct.pack(
|
||||||
|
'<'+'B3x'+'BBHI',
|
||||||
|
int(dependencies[DEP_IMAGES_KEY][i]),
|
||||||
|
dependencies[DEP_VERSIONS_KEY][i].major,
|
||||||
|
dependencies[DEP_VERSIONS_KEY][i].minor,
|
||||||
|
dependencies[DEP_VERSIONS_KEY][i].revision,
|
||||||
|
dependencies[DEP_VERSIONS_KEY][i].build
|
||||||
|
)
|
||||||
|
prot_tlv.add('DEPENDENCY', payload)
|
||||||
|
|
||||||
|
self.payload += prot_tlv.get()
|
||||||
|
|
||||||
|
sha = hashlib.sha256()
|
||||||
|
sha.update(self.payload)
|
||||||
|
image_hash = sha.digest()
|
||||||
|
|
||||||
|
tlv = TLV()
|
||||||
|
|
||||||
|
tlv.add('SHA256', image_hash)
|
||||||
|
|
||||||
|
if key is not None:
|
||||||
|
if key.get_public_key_format() == 'hash':
|
||||||
|
tlv.add('KEYHASH', pubbytes)
|
||||||
|
else:
|
||||||
|
tlv.add('KEY', pub)
|
||||||
|
|
||||||
|
sig = key.sign(bytes(self.payload))
|
||||||
tlv.add(key.sig_tlv(), sig)
|
tlv.add(key.sig_tlv(), sig)
|
||||||
|
|
||||||
self.payload += tlv.get()
|
self.payload += tlv.get()
|
||||||
|
|
||||||
def add_header(self, key, ramLoadAddress):
|
def add_header(self, key, protected_tlv_size, ramLoadAddress):
|
||||||
"""Install the image header.
|
"""Install the image header.
|
||||||
|
|
||||||
The key is needed to know the type of signature, and
|
The key is needed to know the type of signature, and
|
||||||
|
@ -140,28 +228,28 @@ class Image():
|
||||||
|
|
||||||
fmt = ('<' +
|
fmt = ('<' +
|
||||||
# type ImageHdr struct {
|
# type ImageHdr struct {
|
||||||
'I' + # Magic uint32
|
'I' + # Magic uint32
|
||||||
'I' + # LoadAddr uint32
|
'I' + # LoadAddr uint32
|
||||||
'H' + # HdrSz uint16
|
'H' + # HdrSz uint16
|
||||||
'H' + # Pad1 uint16
|
'H' + # PTLVSz uint16
|
||||||
'I' + # ImgSz uint32
|
'I' + # ImgSz uint32
|
||||||
'I' + # Flags uint32
|
'I' + # Flags uint32
|
||||||
'BBHI' + # Vers ImageVersion
|
'BBHI' + # Vers ImageVersion
|
||||||
'I' # Pad2 uint32
|
'I' # Pad1 uint32
|
||||||
) # }
|
) # }
|
||||||
assert struct.calcsize(fmt) == IMAGE_HEADER_SIZE
|
assert struct.calcsize(fmt) == IMAGE_HEADER_SIZE
|
||||||
header = struct.pack(fmt,
|
header = struct.pack(fmt,
|
||||||
IMAGE_MAGIC,
|
IMAGE_MAGIC,
|
||||||
0 if (ramLoadAddress is None) else ramLoadAddress, # LoadAddr
|
0 if (ramLoadAddress is None) else ramLoadAddress, # LoadAddr
|
||||||
self.header_size,
|
self.header_size,
|
||||||
0, # Pad1
|
protected_tlv_size, # TLV info header + Protected TLVs
|
||||||
len(self.payload) - self.header_size, # ImageSz
|
len(self.payload) - self.header_size, # ImageSz
|
||||||
flags, # Flags
|
flags,
|
||||||
self.version.major,
|
self.version.major,
|
||||||
self.version.minor or 0,
|
self.version.minor or 0,
|
||||||
self.version.revision or 0,
|
self.version.revision or 0,
|
||||||
self.version.build or 0,
|
self.version.build or 0,
|
||||||
0) # Pad2
|
0) # Pad1
|
||||||
self.payload = bytearray(self.payload)
|
self.payload = bytearray(self.payload)
|
||||||
self.payload[:len(header)] = header
|
self.payload[:len(header)] = header
|
||||||
|
|
||||||
|
@ -176,4 +264,4 @@ class Image():
|
||||||
pbytes = b'\xff' * padding
|
pbytes = b'\xff' * padding
|
||||||
pbytes += b'\xff' * (tsize - len(boot_magic))
|
pbytes += b'\xff' * (tsize - len(boot_magic))
|
||||||
pbytes += boot_magic
|
pbytes += boot_magic
|
||||||
self.payload += pbytes
|
self.payload += pbytes
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright 2017 Linaro Limited
|
# Copyright (c) 2017,2019 Linaro Limited.
|
||||||
# Copyright (c) 2017-2018, Arm Limited.
|
# Copyright (c) 2017-2019, Arm Limited.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
@ -18,42 +18,64 @@ Cryptographic key management for imgtool.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from Crypto.Hash import SHA256
|
from cryptography.hazmat.backends import default_backend
|
||||||
from Crypto.PublicKey import RSA
|
from cryptography.hazmat.primitives import serialization
|
||||||
from Crypto.Signature import PKCS1_v1_5, PKCS1_PSS
|
from cryptography.hazmat.primitives.hashes import SHA256
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||||
|
from cryptography.hazmat.primitives.asymmetric.padding import PSS, PKCS1v15
|
||||||
|
from cryptography.hazmat.primitives.asymmetric.padding import MGF1
|
||||||
import hashlib
|
import hashlib
|
||||||
from pyasn1.type import namedtype, univ
|
from pyasn1.type import namedtype, univ
|
||||||
from pyasn1.codec.der.encoder import encode
|
from pyasn1.codec.der.encoder import encode
|
||||||
|
|
||||||
|
# Sizes that bootutil will recognize
|
||||||
|
RSA_KEY_SIZES = [2048, 3072]
|
||||||
|
|
||||||
|
# Public exponent
|
||||||
|
PUBLIC_EXPONENT = 65537
|
||||||
|
|
||||||
# By default, we use RSA-PSS (PKCS 2.1). That can be overridden on
|
# By default, we use RSA-PSS (PKCS 2.1). That can be overridden on
|
||||||
# the command line to support the older (less secure) PKCS1.5
|
# the command line to support the older (less secure) PKCS1.5
|
||||||
sign_rsa_pss = True
|
sign_rsa_pss = True
|
||||||
|
|
||||||
AUTOGEN_MESSAGE = "/* Autogenerated by imgtool.py, do not edit. */"
|
AUTOGEN_MESSAGE = "/* Autogenerated by imgtool.py, do not edit. */"
|
||||||
|
|
||||||
class RSAPublicKey(univ.Sequence):
|
class RSAUsageError(Exception):
|
||||||
componentType = namedtype.NamedTypes(
|
pass
|
||||||
namedtype.NamedType('modulus', univ.Integer()),
|
|
||||||
namedtype.NamedType('publicExponent', univ.Integer()))
|
|
||||||
|
|
||||||
class RSA2048():
|
class RSAutil():
|
||||||
def __init__(self, key):
|
def __init__(self, key, public_key_format='hash'):
|
||||||
"""Construct an RSA2048 key with the given key data"""
|
"""Construct an RSA key with the given key data"""
|
||||||
self.key = key
|
self.key = key
|
||||||
|
self.public_key_format = public_key_format
|
||||||
|
|
||||||
|
def key_size(self):
|
||||||
|
return self.key.key_size
|
||||||
|
|
||||||
|
def get_public_key_format(self):
|
||||||
|
return self.public_key_format
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate():
|
def generate(key_size=2048):
|
||||||
return RSA2048(RSA.generate(2048))
|
if key_size not in RSA_KEY_SIZES:
|
||||||
|
raise RSAUsageError("Key size {} is not supported by MCUboot"
|
||||||
|
.format(key_size))
|
||||||
|
return RSAutil(rsa.generate_private_key(
|
||||||
|
public_exponent=PUBLIC_EXPONENT,
|
||||||
|
key_size=key_size,
|
||||||
|
backend=default_backend()))
|
||||||
|
|
||||||
def export_private(self, path):
|
def export_private(self, path):
|
||||||
with open(path, 'wb') as f:
|
with open(path, 'wb') as f:
|
||||||
f.write(self.key.exportKey('PEM'))
|
f.write(self.key.private_bytes(
|
||||||
|
encoding=serialization.Encoding.PEM,
|
||||||
|
format=serialization.PrivateFormat.TraditionalOpenSSL,
|
||||||
|
encryption_algorithm=serialization.NoEncryption()))
|
||||||
|
|
||||||
def get_public_bytes(self):
|
def get_public_bytes(self):
|
||||||
node = RSAPublicKey()
|
return self.key.public_key().public_bytes(
|
||||||
node['modulus'] = self.key.n
|
encoding=serialization.Encoding.DER,
|
||||||
node['publicExponent'] = self.key.e
|
format=serialization.PublicFormat.PKCS1)
|
||||||
return bytearray(encode(node))
|
|
||||||
|
|
||||||
def emit_c(self):
|
def emit_c(self):
|
||||||
print(AUTOGEN_MESSAGE)
|
print(AUTOGEN_MESSAGE)
|
||||||
|
@ -71,34 +93,44 @@ class RSA2048():
|
||||||
def sig_type(self):
|
def sig_type(self):
|
||||||
"""Return the type of this signature (as a string)"""
|
"""Return the type of this signature (as a string)"""
|
||||||
if sign_rsa_pss:
|
if sign_rsa_pss:
|
||||||
return "PKCS1_PSS_RSA2048_SHA256"
|
return "PKCS1_PSS_RSA{}_SHA256".format(self.key_size())
|
||||||
else:
|
else:
|
||||||
return "PKCS15_RSA2048_SHA256"
|
return "PKCS15_RSA{}_SHA256".format(self.key_size())
|
||||||
|
|
||||||
def sig_len(self):
|
def sig_len(self):
|
||||||
return 256
|
return 256 if self.key_size() == 2048 else 384
|
||||||
|
|
||||||
def sig_tlv(self):
|
def sig_tlv(self):
|
||||||
return "RSA2048"
|
return "RSA2048" if self.key_size() == 2048 else "RSA3072"
|
||||||
|
|
||||||
def sign(self, payload):
|
def sign(self, payload):
|
||||||
converted_payload = bytes(payload)
|
|
||||||
sha = SHA256.new(converted_payload)
|
|
||||||
if sign_rsa_pss:
|
if sign_rsa_pss:
|
||||||
signer = PKCS1_PSS.new(self.key)
|
signature = self.key.sign(
|
||||||
|
data=payload,
|
||||||
|
padding=PSS(
|
||||||
|
mgf=MGF1(SHA256()),
|
||||||
|
salt_length=32
|
||||||
|
),
|
||||||
|
algorithm=SHA256()
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
signer = PKCS1_v1_5.new(self.key)
|
signature = self.key.sign(
|
||||||
signature = signer.sign(sha)
|
data=payload,
|
||||||
|
padding=PKCS1v15(),
|
||||||
|
algorithm=SHA256()
|
||||||
|
)
|
||||||
assert len(signature) == self.sig_len()
|
assert len(signature) == self.sig_len()
|
||||||
return signature
|
return signature
|
||||||
|
|
||||||
def load(path):
|
def load(path, public_key_format='hash'):
|
||||||
with open(path, 'rb') as f:
|
with open(path, 'rb') as f:
|
||||||
pem = f.read()
|
pem = f.read()
|
||||||
try:
|
try:
|
||||||
key = RSA.importKey(pem)
|
key = serialization.load_pem_private_key(
|
||||||
if key.n.bit_length() != 2048:
|
pem,
|
||||||
raise Exception("Unsupported RSA bit length, only 2048 supported")
|
password=None,
|
||||||
return RSA2048(key)
|
backend=default_backend()
|
||||||
|
)
|
||||||
|
return RSAutil(key, public_key_format)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise Exception("Unsupported RSA key file")
|
raise Exception("Unsupported RSA key file")
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
#! /usr/bin/env python3
|
||||||
|
#
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
#
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
|
||||||
|
expression_re = re.compile(r"[(]?(([(]?(((0x)[0-9a-fA-F]+)|([0-9]+))[)]?)\s*([\+\-]\s*([(]?(((0x)[0-9a-fA-F]+)|([0-9]+))[)]?)\s*)*)[)]?")
|
||||||
|
|
||||||
|
# Simple parser that takes a string and evaluates an expression from it.
|
||||||
|
# The expression might contain additions and subtractions amongst numbers that
|
||||||
|
# are written in decimal or hexadecimal form.
|
||||||
|
# The parses can process expressions in which the parentheses does not change
|
||||||
|
# the sign of the following number or numbers in an expression.
|
||||||
|
# Thus the parser can process the following expression: (x + y)
|
||||||
|
# However it will not calculate the correct sum for the expression below:
|
||||||
|
# (x - (y + z))
|
||||||
|
def parse_and_sum(text):
|
||||||
|
m = expression_re.match(text)
|
||||||
|
if m is None:
|
||||||
|
msg = "The script was probably invoked manually"
|
||||||
|
msg += " with having certain macros nested in flash_layouts.h.\n"
|
||||||
|
msg += "Please revisit the flash_layout.h file and hardcode values"
|
||||||
|
msg += " for the (NON-)SECURE_IMAGE_OFFSET and"
|
||||||
|
msg += " (NON-)SECURE_IMAGE_MAX_SIZE macros"
|
||||||
|
raise Exception(msg)
|
||||||
|
|
||||||
|
nums = re.findall(r'(0x[A-Fa-f0-9]+)|[\d]+', m.group(0))
|
||||||
|
for i in range(len(nums)):
|
||||||
|
nums[i] = int(nums[i], 0)
|
||||||
|
ops = re.findall(r'\+|\-', m.group(0))
|
||||||
|
sum = nums[0]
|
||||||
|
for i in range(len(ops)):
|
||||||
|
if ops[i] == '+':
|
||||||
|
sum += nums[i+1]
|
||||||
|
else:
|
||||||
|
sum -= nums[i+1]
|
||||||
|
return sum
|
||||||
|
|
||||||
|
|
||||||
|
# Opens a file that contains the macro of interest, then finds the macro with
|
||||||
|
# a regular expression, parses the expression that is defined for the given
|
||||||
|
# macro. Lastly it evaluates the expression with the parse_and_sum function
|
||||||
|
def evaluate_macro(file, regexp, matchGroupKey, matchGroupData):
|
||||||
|
regexp_compiled = re.compile(regexp)
|
||||||
|
|
||||||
|
if os.path.isabs(file):
|
||||||
|
configFile = file
|
||||||
|
else:
|
||||||
|
scriptsDir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
configFile = os.path.join(scriptsDir, file)
|
||||||
|
|
||||||
|
macroValue = {}
|
||||||
|
with open(configFile, 'r') as macros_preprocessed_file:
|
||||||
|
for line in macros_preprocessed_file:
|
||||||
|
m = regexp_compiled.match(line)
|
||||||
|
if m is not None:
|
||||||
|
macroValue[m.group(matchGroupKey)] = \
|
||||||
|
parse_and_sum(m.group(matchGroupData))
|
||||||
|
|
||||||
|
if (matchGroupKey == 0 and not macroValue):
|
||||||
|
macroValue["None"] = None
|
||||||
|
|
||||||
|
return list(macroValue.values())[0] if (matchGroupKey == 0) else macroValue
|
|
@ -54,11 +54,14 @@ def musca_tfm_bin(t_self, non_secure_bin, secure_bin):
|
||||||
#2. Run imgtool to sign the concatenated binary
|
#2. Run imgtool to sign the concatenated binary
|
||||||
sign_args = Namespace(
|
sign_args = Namespace(
|
||||||
layout=flash_layout,
|
layout=flash_layout,
|
||||||
key=path_join(SCRIPT_DIR, 'musca_a1-root-rsa-2048.pem'),
|
key=path_join(SCRIPT_DIR, 'musca_a1-root-rsa-3072.pem'),
|
||||||
|
public_key_format=None,
|
||||||
align=1,
|
align=1,
|
||||||
|
dependencies=None,
|
||||||
version=version.decode_version('1.0'),
|
version=version.decode_version('1.0'),
|
||||||
header_size=0x400,
|
header_size=0x400,
|
||||||
pad=0x100000,
|
pad=0x100000,
|
||||||
|
security_counter=None,
|
||||||
rsa_pkcs1_15=False,
|
rsa_pkcs1_15=False,
|
||||||
included_header=False,
|
included_header=False,
|
||||||
infile=concatenated_bin,
|
infile=concatenated_bin,
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEowIBAAKCAQEA0QYIGhhELBjo+/33DaNPH7vuXvmq0ksY01rpbRiAGfnwnDQb
|
|
||||||
y/O8dNtC54x/EFN+Q14NVyxE0WcIDw27XO7ss5nf4E2EC6p3QWDtFShJpwG0PBDm
|
|
||||||
aYwvX6xBTZ5cFN/y+M89Hm/nW7q0qciIfkc8lMN3Z1RLqo04NcpiYX634RXbd3PU
|
|
||||||
vntyIYlpJPv4ZW5kPsgO14XVXErkUw0v/7f98xM5gz+jrtIPp2qd+f64zvoqvq+4
|
|
||||||
4PqCN1T0PuEr0NMIWBj2XkzIiIExrV+wghfyimknI/Orhz6TGh3+6PgaJGZZ+Byr
|
|
||||||
3M5oG2ZkNez6DRGdr1w6p9FnxkfvsUssYuHRyQIDAQABAoIBAEahFCHFK1v/OtLT
|
|
||||||
eSSZl0Xw2dYr5QXULFpWsOOVUMv2QdB2ZyIehQKziEL3nYPlwpd+82EOa16awwVb
|
|
||||||
LYF0lnUFvLltV/4dJtjnqJTqnSCamc1mJIVrwiJA8XwJ07GWDuL2G//p7jJ3v05T
|
|
||||||
nZOV/KmD9xfqSvshZun+LgolqHqcrAa1f4cmuP9C9oqenZryljyfj7piaIZGI0JR
|
|
||||||
PrJJ5kImYJqRcMgKTyHP4L8nwQ4moMJr6zbfbWxxb5TC7KVZSQ9UKZZ+ZLuy/pkU
|
|
||||||
Qe4G8XSE0r+R9u4JCg87I1vgHhn8WJSxVX027OVUq5HfOzg2skQBTcExph5V9B2b
|
|
||||||
onNxd8UCgYEA/32PW+ZwRcdKXMj+QVkxXUd6xkXy7mTXPEaQuOLWZQgrSqAFH1l4
|
|
||||||
5/6d099KAJrjM6kR8pKXtz72IIyMHTPm332ghymjKvaEl2XP9sF+f6FmYURar4y6
|
|
||||||
8Zh3eivP86+Q/YzOGKwtRSziBMzrAfoIXgtwH8pwIPYLP3zBV4449ZsCgYEA0XC/
|
|
||||||
gu2ub5M6EXBnjq9K2d4LlTyAPsIbAcMSwkhOUH4YJFS22qXLYQUA9zM+DUyLCrl/
|
|
||||||
PKN2G0HQVgMb4DIbeHv8kXB5oGm5zfbWorWqOomXB3AsI7X8YDMtf/PsZV2amBei
|
|
||||||
qVskmPJQV21qFyeOcHlT+dHuRb0O0un3dK8RHmsCgYEApDCH4dJ80osZoflVVJ/C
|
|
||||||
VqTqJOOtFEFgBQ+AUCEPEQyn7aRaxmPUjJsXyKJVx3/ChV+g9hf5Qj1HJXHNVbMW
|
|
||||||
KwhsEpDSmHimizlV5clBxzntNpMcCHdTaJHILo5bbMqmThugE0ELMsp+UgFzAeky
|
|
||||||
WWXWX8fUOYqFff5prh/rQQMCgYBQQ8FhT+113Rp37HgDerJY5HvT6afMZV8sQbJC
|
|
||||||
uqsotepSohShnsBeoihIlF7HgfoXVhepCYwNzh8ll3NrbEiS2BFnO4+hJmOKx3pi
|
|
||||||
SPTAElLLCvYfiXL6+yII01ZZUpIYj5ZLCR7xbovTtZ7e2M4B1L2WFBoYp+eydO/c
|
|
||||||
y+rnmQKBgCh0gfyBT/OKPkfKv+Bbt8HcoxgEj+TyH+vYdeTbP9ZSJ6y5utMbPg7z
|
|
||||||
iLLbJ+9IcSwPCwJSmI+I0Om4xEp4ZblCrzAG7hWvG2NNzxQjmoOOrAANyTvJR/ap
|
|
||||||
N+UkQA4WrMSKEYyBlRS/hR9Unz31vMc2k9Re0ukWhWh/QksQGDfJ
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
A default RSA key pair is given to the Musca-A1 target.
|
A default RSA key pair is given to the Musca-A1 target.
|
||||||
|
|
||||||
Public key was pre-compiled to `targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/mcuboot.bin` and private key is in `musca_a1-root-rsa-2048.pem`.
|
Public key was pre-compiled to `targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/mcuboot.bin` and private key is in `root-rsa-3072.pem`.
|
||||||
|
|
||||||
DO NOT use them in production code, they are exclusively for testing!
|
DO NOT use them in production code, they are exclusively for testing!
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
-----END RSA PRIVATE KEY-----
|
Loading…
Reference in New Issue