aboutsummaryrefslogtreecommitdiff
path: root/bl2
diff options
context:
space:
mode:
authorDavid Vincze <david.vincze@arm.com>2019-09-27 17:40:29 +0200
committerTamas Ban <tamas.ban@arm.com>2019-10-17 10:29:19 +0000
commit4b84de59de0b883b5e8c3e97b9ed3f7f33618322 (patch)
treebbd4f6484f9a9f3a54b26781d0b4eacbc25964c0 /bl2
parent21f5bf6127bee8ae8f1976ca186dbc7f8dcb5082 (diff)
downloadtrusted-firmware-m-4b84de59de0b883b5e8c3e97b9ed3f7f33618322.tar.gz
Boot: Add measured boot record TLV to image manifest
Generate CBOR encoded boot record structure at build time and add as a new type of TLV to the image manifest for device attestation. This new TLV can represent the image to which it belongs as one item of the SW_COMPONENTS array in an IAT token. Change-Id: I84adf0faa57c40428c3e48cce4398e346d9192b7 Signed-off-by: David Vincze <david.vincze@arm.com>
Diffstat (limited to 'bl2')
-rw-r--r--bl2/ext/mcuboot/scripts/imgtool.py9
-rw-r--r--bl2/ext/mcuboot/scripts/imgtool_lib/boot_record.py77
-rw-r--r--bl2/ext/mcuboot/scripts/imgtool_lib/image.py50
3 files changed, 124 insertions, 12 deletions
diff --git a/bl2/ext/mcuboot/scripts/imgtool.py b/bl2/ext/mcuboot/scripts/imgtool.py
index 1b539c2192..2d1d97bbb9 100644
--- a/bl2/ext/mcuboot/scripts/imgtool.py
+++ b/bl2/ext/mcuboot/scripts/imgtool.py
@@ -103,6 +103,13 @@ def do_sign(args):
+ (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 = macro_parser.evaluate_macro(args.layout, sign_bin_size_re, 0, 1)
img = image.Image.load(args.infile,
version=version_num,
@@ -112,7 +119,7 @@ def do_sign(args):
pad=pad_size)
key = keys.load(args.key, args.public_key_format) if args.key else None
ram_load_address = macro_parser.evaluate_macro(args.layout, image_load_address_re, 0, 1)
- img.sign(key, ram_load_address, args.dependencies)
+ img.sign(sw_type, key, ram_load_address, args.dependencies)
if pad_size:
img.pad_to(pad_size, args.align)
diff --git a/bl2/ext/mcuboot/scripts/imgtool_lib/boot_record.py b/bl2/ext/mcuboot/scripts/imgtool_lib/boot_record.py
new file mode 100644
index 0000000000..41887bb5f0
--- /dev/null
+++ b/bl2/ext/mcuboot/scripts/imgtool_lib/boot_record.py
@@ -0,0 +1,77 @@
+
+# Copyright (c) 2019, Arm Limited.
+#
+# 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
+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)
diff --git a/bl2/ext/mcuboot/scripts/imgtool_lib/image.py b/bl2/ext/mcuboot/scripts/imgtool_lib/image.py
index cb97a350b8..d89ec990f1 100644
--- a/bl2/ext/mcuboot/scripts/imgtool_lib/image.py
+++ b/bl2/ext/mcuboot/scripts/imgtool_lib/image.py
@@ -18,6 +18,7 @@ Image signing and management.
"""
from . import version as versmod
+from . import boot_record as br
import hashlib
import struct
@@ -41,7 +42,8 @@ TLV_VALUES = {
'RSA2048': 0x20,
'RSA3072': 0x23,
'DEPENDENCY': 0x40,
- 'SEC_CNT': 0x50, }
+ 'SEC_CNT': 0x50,
+ 'BOOT_RECORD': 0x60, }
TLV_INFO_SIZE = 4
TLV_INFO_MAGIC = 0x6907
@@ -116,10 +118,39 @@ class Image():
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")
- def sign(self, key, ramLoadAddress, dependencies=None):
- # Size of the security counter TLV:
- # header ('BBH') + payload ('I') = 8 Bytes
- protected_tlv_size = TLV_INFO_SIZE + 8
+ def sign(self, sw_type, key, ramLoadAddress, dependencies=None):
+ image_version = (str(self.version.major) + '.'
+ + str(self.version.minor) + '.'
+ + str(self.version.revision))
+
+ # Calculate the hash of the public key
+ if key is not None:
+ pub = key.get_public_bytes()
+ sha = hashlib.sha256()
+ sha.update(pub)
+ pubbytes = sha.digest()
+ else:
+ pubbytes = bytes(KEYHASH_SIZE)
+
+ # 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
@@ -135,6 +166,7 @@ class Image():
payload = struct.pack('I', self.security_cnt)
tlv.add('SEC_CNT', payload)
+ tlv.add('BOOT_RECORD', boot_record)
if dependencies_num != 0:
for i in range(dependencies_num):
@@ -153,7 +185,6 @@ class Image():
full_size = (TLV_INFO_SIZE + len(tlv.buf) + TLV_HEADER_SIZE
+ PAYLOAD_DIGEST_SIZE)
if key is not None:
- pub = key.get_public_bytes()
if key.get_public_key_format() == 'hash':
tlv_key_data_size = KEYHASH_SIZE
else:
@@ -166,15 +197,12 @@ class Image():
sha = hashlib.sha256()
sha.update(self.payload)
- digest = sha.digest()
+ image_hash = sha.digest()
- tlv.add('SHA256', digest)
+ tlv.add('SHA256', image_hash)
if key is not None:
if key.get_public_key_format() == 'hash':
- sha = hashlib.sha256()
- sha.update(pub)
- pubbytes = sha.digest()
tlv.add('KEYHASH', pubbytes)
else:
tlv.add('KEY', pub)