[RFC PATCH] binman: bintool: etype: Add support for ti-secure entry

Neha Malcom Francis n-francis at ti.com
Fri Feb 24 13:03:40 CET 2023


core-secdev-k3 is the TI security development package provided for K3
platform devices. This tool helps sign bootloader images with the x509
ceritificate header.

Signed-off-by: Neha Malcom Francis <n-francis at ti.com>
---
This patch depends on https://patchwork.ozlabs.org/project/uboot/patch/20230224115101.563729-1-n-francis@ti.com/
and on ongoing development in https://git.ti.com/cgit/security-development-tools/core-secdev-k3

 tools/binman/btool/tisecuretool.py            |  72 +++++++++++
 tools/binman/etype/ti_secure.py               | 114 ++++++++++++++++++
 tools/binman/ftest.py                         |  36 ++++++
 tools/binman/test/278_ti_secure_rom.dts       |  11 ++
 tools/binman/test/279_ti_secure.dts           |  11 ++
 .../binman/test/280_ti_secure_nofilename.dts  |  10 ++
 tools/binman/test/281_ti_secure_combined.dts  |  12 ++
 7 files changed, 266 insertions(+)
 create mode 100644 tools/binman/btool/tisecuretool.py
 create mode 100644 tools/binman/etype/ti_secure.py
 create mode 100644 tools/binman/test/278_ti_secure_rom.dts
 create mode 100644 tools/binman/test/279_ti_secure.dts
 create mode 100644 tools/binman/test/280_ti_secure_nofilename.dts
 create mode 100644 tools/binman/test/281_ti_secure_combined.dts

diff --git a/tools/binman/btool/tisecuretool.py b/tools/binman/btool/tisecuretool.py
new file mode 100644
index 0000000000..5102bb1f7d
--- /dev/null
+++ b/tools/binman/btool/tisecuretool.py
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2022 Texas Instruments Incorporated - https://www.ti.com/
+# Written by Neha Malcom Francis <n-francis at ti.com>
+#
+"""Bintool implementation for TI security development tools
+
+tisecuretool helps add x509 certification for bootloader images for K3 platform devices
+
+Source code:
+https://git.ti.com/cgit/security-development-tools/core-secdev-k3/"""
+
+import os
+
+from binman import bintool
+from patman import tout
+from patman import tools
+
+class Bintooltisecuretool(bintool.Bintool):
+    """Signing tool for TI bootloaders"""
+    name = 'tisecuretool'
+    def __init__(self, name):
+        super().__init__(name, 'TI secure tool')
+
+    def sign_binary_secure(self, fname, out_fname):
+        """Create a signed binary
+
+        Args:
+            fname (str): Filename to sign
+            out_fname (str): Output filename
+
+        Returns:
+            str: Tool output
+            or None
+        """
+        tool_path = self.get_path()
+        script_path = os.path.join(tool_path, 'scripts/secure-binary-image.sh')
+        args = [
+            'sh',
+            script_path,
+            fname,
+            out_fname
+            ]
+        output = self.run_cmd(*args, add_name=False)
+        return output
+
+    def sign_binary_rom(self, args):
+        """Create a signed binary that is booted by ROM
+
+        Args:
+            fname (str): Filename to sign
+            out_fname (str): Output filename"""
+        tool_path = self.get_path()
+        script_path = os.path.join(tool_path, 'scripts/secure-rom-boot-image.sh')
+        #args.insert(0, script_path)
+        args.insert(0, script_path)
+        output = self.run_cmd(*args, add_name=False)
+        return output
+
+    def fetch(self, method):
+        """Fetch handler for TI secure tool
+
+        This builds the tool from source
+
+        Returns:
+            True if the file was fetched, None if a method other than FETCH_SOURCE
+            was requested
+        """
+        if method != bintool.FETCH_SOURCE:
+            return None
+        result = self.fetch_from_git(
+            'git://git.ti.com/security-development-tools/core-secdev-k3.git', 'tisecuretool')
+        return result
diff --git a/tools/binman/etype/ti_secure.py b/tools/binman/etype/ti_secure.py
new file mode 100644
index 0000000000..26f81ff8e8
--- /dev/null
+++ b/tools/binman/etype/ti_secure.py
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2022 Texas Instruments Incorporated - https://www.ti.com/
+# Written by Neha Malcom Francis <n-francis at ti.com>
+#
+# Entry-type module for signed binaries for TI K3 platform
+#
+
+from binman.etype.blob import Entry_blob
+from binman import bintool
+
+from dtoc import fdt_util
+from patman import terminal
+from patman import tools
+from patman import tout
+
+class Entry_ti_secure(Entry_blob):
+    """An entry which contains a signed x509 binary for signing TI
+    General Purpose as well as High-Security devices.
+
+    Properties / Entry arguments:
+	- filename: filename of binary file to be secured
+
+    Output files:
+        - filename_x509 - output file generated by secure x509 signing script (which
+            used as entry contents)
+    """
+    def __init__(self, section, etype, node):
+        super().__init__(section, etype, node)
+        self.filename = fdt_util.GetString(self._node, 'filename')
+        self.core = fdt_util.GetString(self._node, 'core', 'secure')
+        self.load_addr = fdt_util.GetInt(self._node, 'load', 0x41c00000)
+        self.sw_rev = fdt_util.GetInt(self._node, 'sw-rev', 1)
+        self.sysfw_cert = fdt_util.GetBool(self._node, 'sysfw-cert', False)
+        self.secure = fdt_util.GetBool(self._node, 'secure', False)
+        self.combined = fdt_util.GetBool(self._node, 'combined', False)
+        self.split_dm = fdt_util.GetBool(self._node, 'split-dm', False)
+        self.sysfw_filename = fdt_util.GetString(self._node, 'sysfw-filename')
+        self.sysfw_load_addr = fdt_util.GetInt(self._node, 'sysfw-load', 0x40000)
+        self.sysfw_data_filename = fdt_util.GetString(self._node, 'sysfw-data-filename')
+        self.sysfw_data_load_addr = fdt_util.GetInt(self._node, 'sysfw-data-load', 0x7f000)
+        self.sysfw_inner_cert = fdt_util.GetString(self._node, 'sysfw-inner-cert', "")
+        self.dm_data_filename = fdt_util.GetString(self._node, 'dm-data-filename')
+        self.dm_data_load_addr = fdt_util.GetInt(self._node, 'dm-data-load', 0x41c80000)
+        self.sysfw_inner_cert_filename = fdt_util.GetString(self._node, 'sysfw-inner-cert-filename')
+        self.toolpresent = False
+        if not self.filename:
+            self.Raise("ti_secure must have a 'filename' property")
+
+    def _SignBinarySecure(self):
+        infilename = self.filename
+        outfilename = infilename + '_signed'
+
+        data = self.tisecuretool.sign_binary_secure(infilename, outfilename)
+
+        if data is None:
+            # Bintool is missing, create a zeroed binary
+            self.record_missing_bintool(self.tisecuretool)
+            return tools.get_bytes(0, 1024)
+
+        return tools.read_file(outfilename)
+
+    def _SignBinaryROM(self):
+        input_fname = self.filename
+        output_fname = input_fname + "_x509"
+        if self.combined:
+            args = [
+                '-b', input_fname,
+                '-l', hex(self.load_addr),
+                '-s', self.sysfw_filename,
+                '-m', hex(self.sysfw_load_addr),
+                '-a', self.sysfw_inner_cert,
+                '-d', self.sysfw_data_filename,
+                '-n', hex(self.sysfw_data_load_addr),
+                '-r', str(self.sw_rev),
+                '-o', output_fname,
+            ]
+            if self.split_dm:
+                args.extend(['-t', self.dm_data_filename, '-y', hex(self.dm_data_load_addr)])
+        else:
+            args = [
+                '-a', self.core,
+                '-b', input_fname,
+                '-o', output_fname,
+                '-l', hex(self.load_addr),
+                '-r', str(self.sw_rev),
+
+            ]
+            if self.sysfw_cert == True:
+                args.insert(0, '-u')
+
+        out = self.tisecuretool.sign_binary_rom(args)
+
+        if out is None:
+            # Bintool is missing, create a zeroed binary
+            self.record_missing_bintool(self.tisecuretool)
+            return tools.get_bytes(0, 1024)
+
+        return tools.read_file(output_fname)
+
+    def ProcessContents(self):
+        if self.secure:
+            data = self._SignBinarySecure()
+        else:
+            data = self._SignBinaryROM()
+        return self.ProcessContentsUpdate(data)
+
+    def AddBintools(self, btools):
+        #super().AddBintools(btools)
+        col = terminal.Color()
+        self.tisecuretool = self.AddBintool(btools, 'tisecuretool')
+        out = self.tisecuretool.fetch_tool(bintool.FETCH_SOURCE, col, True)
+        if out == bintool.FAIL:
+            # Bintool is missing, record missing
+            self.record_missing_bintool(self.tisecuretool)
\ No newline at end of file
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index bf902341c5..72cce0ef02 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -97,6 +97,7 @@ PRE_LOAD_MAGIC        = b'UBSH'
 PRE_LOAD_VERSION      = 0x11223344.to_bytes(4, 'big')
 PRE_LOAD_HDR_SIZE     = 0x00001000.to_bytes(4, 'big')
 TI_BOARD_CONFIG_DATA  = b'\x00\x01'
+TIX509DATA            = b'letsgo'
 
 # Subdirectory of the input dir to use to put test FDTs
 TEST_FDT_SUBDIR       = 'fdts'
@@ -206,6 +207,7 @@ class TestFunctional(unittest.TestCase):
         TestFunctional._MakeInputFile('bl2u.bin', ATF_BL2U_DATA)
         TestFunctional._MakeInputFile('fw_dynamic.bin', OPENSBI_DATA)
         TestFunctional._MakeInputFile('scp.bin', SCP_DATA)
+        TestFunctional._MakeInputFile('to_sign.bin', TIX509DATA)
 
         # Add a few .dtb files for testing
         TestFunctional._MakeInputFile('%s/test-fdt1.dtb' % TEST_FDT_SUBDIR,
@@ -6398,5 +6400,39 @@ fdt         fdtmap                Extract the devicetree blob from the fdtmap
         configlen_noheader = TI_BOARD_CONFIG_DATA*4
         self.assertGreater(data, configlen_noheader)
 
+    def testTISecureROMImageMissingTool(self):
+        """Test that a TI secure signed ROM booted image can be generated although tisecuretool is missing"""
+        with test_util.capture_sys_output() as (_, stderr):
+            data = self._DoTestFile('278_ti_secure_rom.dts',
+                force_missing_bintools='tisecuretool')
+        err = stderr.getvalue()
+        self.assertRegex(err,
+                         "Image 'image'.*missing bintools.*: tisecuretool")
+
+    def testTISecureImageMissingTool(self):
+        """Test that a TI secure signed image can be generated although tisecuretool is missing"""
+        with test_util.capture_sys_output() as (_, stderr):
+            data = self._DoTestFile('279_ti_secure.dts',
+                force_missing_bintools='tisecuretool')
+        err = stderr.getvalue()
+        self.assertRegex(err,
+                         "Image 'image'.*missing bintools.*: tisecuretool")
+
+    def testTISecureNoFilename(self):
+        """Test that a missing 'filename' property is detected"""
+        with self.assertRaises(ValueError) as e:
+            self._DoTestFile('280_ti_secure_nofilename.dts')
+        self.assertIn("ti_secure must have a 'filename' property",
+                      str(e.exception))
+
+    def testTISecureImageCombinedMissingTool(self):
+        """Test that a TI secure signed image can be generated although tisecuretool is missing"""
+        with test_util.capture_sys_output() as (_, stderr):
+            data = self._DoTestFile('281_ti_secure_combined.dts',
+                force_missing_bintools='tisecuretool')
+        err = stderr.getvalue()
+        self.assertRegex(err,
+                         "Image 'image'.*missing bintools.*: tisecuretool")
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/278_ti_secure_rom.dts b/tools/binman/test/278_ti_secure_rom.dts
new file mode 100644
index 0000000000..67a6a9de8d
--- /dev/null
+++ b/tools/binman/test/278_ti_secure_rom.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	binman {
+			ti-secure {
+				filename = "to_sign.bin";
+				sysfw-cert;
+			};
+	};
+};
diff --git a/tools/binman/test/279_ti_secure.dts b/tools/binman/test/279_ti_secure.dts
new file mode 100644
index 0000000000..0e60984013
--- /dev/null
+++ b/tools/binman/test/279_ti_secure.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	binman {
+			ti-secure {
+				filename = "to_sign.bin";
+				secure;
+			};
+	};
+};
diff --git a/tools/binman/test/280_ti_secure_nofilename.dts b/tools/binman/test/280_ti_secure_nofilename.dts
new file mode 100644
index 0000000000..928a50a499
--- /dev/null
+++ b/tools/binman/test/280_ti_secure_nofilename.dts
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	binman {
+			ti-secure {
+				secure;
+			};
+	};
+};
diff --git a/tools/binman/test/281_ti_secure_combined.dts b/tools/binman/test/281_ti_secure_combined.dts
new file mode 100644
index 0000000000..aadb5a4306
--- /dev/null
+++ b/tools/binman/test/281_ti_secure_combined.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	binman {
+			ti-secure {
+				filename = "to_sign.bin";
+				combined;
+				split-dm;
+			};
+	};
+};
-- 
2.34.1



More information about the U-Boot mailing list