From d43c636437d116c4dbe74c9a1ae8e9373941169f Mon Sep 17 00:00:00 2001 From: Neha Malcom Francis Date: Fri, 6 Oct 2023 15:59:54 +0530 Subject: binman: openssl: x509: ti_secure_rom: Add support for bootcore_opts According to the TRMs of K3 platform of devices, the ROM boot image format specifies a "Core Options Field" that provides the capability to set the boot core in lockstep when set to 0 or to split mode when set to 2. Add support for providing the same from the binman DTS. Also modify existing test case for ensuring future coverage. Signed-off-by: Neha Malcom Francis --- tools/binman/btool/openssl.py | 1 + tools/binman/entries.rst | 1 + tools/binman/etype/ti_secure_rom.py | 16 +++++++++------- tools/binman/test/280_ti_secure_rom.dts | 1 + 4 files changed, 12 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/binman/btool/openssl.py b/tools/binman/btool/openssl.py index aad3b61ae2..e2db8da206 100644 --- a/tools/binman/btool/openssl.py +++ b/tools/binman/btool/openssl.py @@ -155,6 +155,7 @@ authInPlace = INTEGER:2 C, ST, L, O, OU, CN and emailAddress cert_type (int): Certification type bootcore (int): Booting core + bootcore_opts(int): Booting core option (split/lockstep mode) load_addr (int): Load address of image sha (int): Hash function diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index f9900fe6be..fa6d1b6afa 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -1739,6 +1739,7 @@ Properties / Entry arguments: - core: core on which bootloader runs, valid cores are 'secure' and 'public' - content: phandle of SPL in case of legacy bootflow or phandles of component binaries in case of combined bootflow + - core-opts (optional): split-mode (0) or lockstep mode (1) set to 0 by default The following properties are only for generating a combined bootflow binary: - sysfw-inner-cert: boolean if binary contains sysfw inner certificate diff --git a/tools/binman/etype/ti_secure_rom.py b/tools/binman/etype/ti_secure_rom.py index da03c90ef1..ff55d9d1a4 100644 --- a/tools/binman/etype/ti_secure_rom.py +++ b/tools/binman/etype/ti_secure_rom.py @@ -32,6 +32,7 @@ class Entry_ti_secure_rom(Entry_x509_cert): - core: core on which bootloader runs, valid cores are 'secure' and 'public' - content: phandle of SPL in case of legacy bootflow or phandles of component binaries in case of combined bootflow + - core-opts (optional): split-mode (0) or lockstep mode (1) set to 0 by default The following properties are only for generating a combined bootflow binary: - sysfw-inner-cert: boolean if binary contains sysfw inner certificate @@ -70,6 +71,7 @@ class Entry_ti_secure_rom(Entry_x509_cert): self.sw_rev = fdt_util.GetInt(self._node, 'sw-rev', 1) self.sha = fdt_util.GetInt(self._node, 'sha', 512) self.core = fdt_util.GetString(self._node, 'core', 'secure') + self.bootcore_opts = fdt_util.GetInt(self._node, 'core-opts') self.key_fname = self.GetEntryArgsOrProps([ EntryArg('keyfile', str)], required=True)[0] if self.combined: @@ -98,22 +100,19 @@ class Entry_ti_secure_rom(Entry_x509_cert): bytes content of the entry, which is the certificate binary for the provided data """ + if self.bootcore_opts is None: + self.bootcore_opts = 0 + if self.core == 'secure': if self.countersign: self.cert_type = 3 else: self.cert_type = 2 - - if self.fsstub: - self.bootcore_opts = 0 - else: - self.bootcore_opts = 32 - self.bootcore = 0 else: self.cert_type = 1 self.bootcore = 16 - self.bootcore_opts = 0 + return super().GetCertificate(required=required, type='rom') def CombinedGetCertificate(self, required): @@ -132,6 +131,9 @@ class Entry_ti_secure_rom(Entry_x509_cert): self.num_comps = 3 self.sha_type = SHA_OIDS[self.sha] + if self.bootcore_opts is None: + self.bootcore_opts = 0 + # sbl self.content = fdt_util.GetPhandleList(self._node, 'content-sbl') input_data_sbl = self.GetContents(required) diff --git a/tools/binman/test/280_ti_secure_rom.dts b/tools/binman/test/280_ti_secure_rom.dts index d1313769f4..1a3eca9425 100644 --- a/tools/binman/test/280_ti_secure_rom.dts +++ b/tools/binman/test/280_ti_secure_rom.dts @@ -9,6 +9,7 @@ binman { ti-secure-rom { content = <&unsecure_binary>; + core-opts = <2>; }; unsecure_binary: blob-ext { filename = "ti_unsecure.bin"; -- cgit v1.2.3 From 50e538b1c1c630d0508c7cc98ba72f95e44188a9 Mon Sep 17 00:00:00 2001 From: Manorit Chawdhry Date: Wed, 11 Oct 2023 14:09:37 +0530 Subject: binman: ti-secure: Add support for firewalling entities We can now firewall entities while loading them through our secure entity TIFS, the required information should be present in the certificate that is being parsed by TIFS. The following commit adds the support to enable the certificates to be generated if the firewall configurations are present in the binman dtsi nodes. Signed-off-by: Manorit Chawdhry --- tools/binman/btool/openssl.py | 16 +++++++- tools/binman/etype/ti_secure.py | 90 +++++++++++++++++++++++++++++++++++++++++ tools/binman/etype/x509_cert.py | 3 +- 3 files changed, 106 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/binman/btool/openssl.py b/tools/binman/btool/openssl.py index e2db8da206..adf90ed598 100644 --- a/tools/binman/btool/openssl.py +++ b/tools/binman/btool/openssl.py @@ -82,7 +82,7 @@ imageSize = INTEGER:{len(indata)} return self.run_cmd(*args) def x509_cert_sysfw(self, cert_fname, input_fname, key_fname, sw_rev, - config_fname, req_dist_name_dict): + config_fname, req_dist_name_dict, firewall_cert_data): """Create a certificate to be booted by system firmware Args: @@ -94,6 +94,13 @@ imageSize = INTEGER:{len(indata)} req_dist_name_dict (dict): Dictionary containing key-value pairs of req_distinguished_name section extensions, must contain extensions for C, ST, L, O, OU, CN and emailAddress + firewall_cert_data (dict): + - auth_in_place (int): The Priv ID for copying as the + specific host in firewall protected region + - num_firewalls (int): The number of firewalls in the + extended certificate + - certificate (str): Extended firewall certificate with + the information for the firewall configurations. Returns: str: Tool output @@ -121,6 +128,7 @@ basicConstraints = CA:true 1.3.6.1.4.1.294.1.3 = ASN1:SEQUENCE:swrv 1.3.6.1.4.1.294.1.34 = ASN1:SEQUENCE:sysfw_image_integrity 1.3.6.1.4.1.294.1.35 = ASN1:SEQUENCE:sysfw_image_load +1.3.6.1.4.1.294.1.37 = ASN1:SEQUENCE:firewall [ swrv ] swrv = INTEGER:{sw_rev} @@ -132,7 +140,11 @@ imageSize = INTEGER:{len(indata)} [ sysfw_image_load ] destAddr = FORMAT:HEX,OCT:00000000 -authInPlace = INTEGER:2 +authInPlace = INTEGER:{hex(firewall_cert_data['auth_in_place'])} + +[ firewall ] +numFirewallRegions = INTEGER:{firewall_cert_data['num_firewalls']} +{firewall_cert_data['certificate']} ''', file=outf) args = ['req', '-new', '-x509', '-key', key_fname, '-nodes', '-outform', 'DER', '-out', cert_fname, '-config', config_fname, diff --git a/tools/binman/etype/ti_secure.py b/tools/binman/etype/ti_secure.py index b1f5d89198..f80eb542c9 100644 --- a/tools/binman/etype/ti_secure.py +++ b/tools/binman/etype/ti_secure.py @@ -7,9 +7,40 @@ from binman.entry import EntryArg from binman.etype.x509_cert import Entry_x509_cert +from dataclasses import dataclass from dtoc import fdt_util +@dataclass +class Firewall(): + id: int + region: int + control : int + permissions: list[hex] + start_address: str + end_address: str + + def __post_init__(self): + for key, val in self.__dict__.items(): + if val is None: + raise Exception(f"{key} can't be None in firewall node") + + def get_certificate(self) -> str: + unique_identifier = f"{self.id}{self.region}" + cert = f""" +firewallID{unique_identifier} = INTEGER:{self.id} +region{unique_identifier} = INTEGER:{self.region} +control{unique_identifier} = INTEGER:{hex(self.control)} +nPermissionRegs{unique_identifier} = INTEGER:{len(self.permissions)} +""" + for index, permission in enumerate(self.permissions): + cert += f"""permissions{unique_identifier}{index} = INTEGER:{hex(permission)} +""" + cert += f"""startAddress{unique_identifier} = FORMAT:HEX,OCT:{self.start_address:02x} +endAddress{unique_identifier} = FORMAT:HEX,OCT:{self.end_address:02x} +""" + return cert + class Entry_ti_secure(Entry_x509_cert): """Entry containing a TI x509 certificate binary @@ -17,6 +48,11 @@ class Entry_ti_secure(Entry_x509_cert): - content: List of phandles to entries to sign - keyfile: Filename of file containing key to sign binary with - sha: Hash function to be used for signing + - auth-in-place: This is an integer field that contains two pieces + of information + Lower Byte - Remains 0x02 as per our use case + ( 0x02: Move the authenticated binary back to the header ) + Upper Byte - The Host ID of the core owning the firewall Output files: - input. - input file passed to openssl @@ -25,6 +61,35 @@ class Entry_ti_secure(Entry_x509_cert): - cert. - output file generated by openssl (which is used as the entry contents) + Depending on auth-in-place information in the inputs, we read the + firewall nodes that describe the configurations of firewall that TIFS + will be doing after reading the certificate. + + The syntax of the firewall nodes are as such: + + firewall-257-0 { + id = <257>; /* The ID of the firewall being configured */ + region = <0>; /* Region number to configure */ + + control = /* The control register */ + <(FWCTRL_EN | FWCTRL_LOCK | FWCTRL_BG | FWCTRL_CACHE)>; + + permissions = /* The permission registers */ + <((FWPRIVID_ALL << FWPRIVID_SHIFT) | + FWPERM_SECURE_PRIV_RWCD | + FWPERM_SECURE_USER_RWCD | + FWPERM_NON_SECURE_PRIV_RWCD | + FWPERM_NON_SECURE_USER_RWCD)>; + + /* More defines can be found in k3-security.h */ + + start_address = /* The Start Address of the firewall */ + <0x0 0x0>; + end_address = /* The End Address of the firewall */ + <0xff 0xffffffff>; + }; + + openssl signs the provided data, using the TI templated config file and writes the signature in this entry. This allows verification that the data is genuine. @@ -32,11 +97,20 @@ class Entry_ti_secure(Entry_x509_cert): def __init__(self, section, etype, node): super().__init__(section, etype, node) self.openssl = None + self.firewall_cert_data: dict = { + 'auth_in_place': 0x02, + 'num_firewalls': 0, + 'certificate': '', + } def ReadNode(self): super().ReadNode() self.key_fname = self.GetEntryArgsOrProps([ EntryArg('keyfile', str)], required=True)[0] + auth_in_place = fdt_util.GetInt(self._node, 'auth-in-place') + if auth_in_place: + self.firewall_cert_data['auth_in_place'] = auth_in_place + self.ReadFirewallNode() self.sha = fdt_util.GetInt(self._node, 'sha', 512) self.req_dist_name = {'C': 'US', 'ST': 'TX', @@ -46,6 +120,22 @@ class Entry_ti_secure(Entry_x509_cert): 'CN': 'TI Support', 'emailAddress': 'support@ti.com'} + def ReadFirewallNode(self): + self.firewall_cert_data['certificate'] = "" + self.firewall_cert_data['num_firewalls'] = 0 + for node in self._node.subnodes: + if 'firewall' in node.name: + firewall = Firewall( + fdt_util.GetInt(node, 'id'), + fdt_util.GetInt(node, 'region'), + fdt_util.GetInt(node, 'control'), + fdt_util.GetPhandleList(node, 'permissions'), + fdt_util.GetInt64(node, 'start_address'), + fdt_util.GetInt64(node, 'end_address'), + ) + self.firewall_cert_data['num_firewalls'] += 1 + self.firewall_cert_data['certificate'] += firewall.get_certificate() + def GetCertificate(self, required): """Get the contents of this entry diff --git a/tools/binman/etype/x509_cert.py b/tools/binman/etype/x509_cert.py index d028cfe38c..9e1cf47902 100644 --- a/tools/binman/etype/x509_cert.py +++ b/tools/binman/etype/x509_cert.py @@ -98,7 +98,8 @@ class Entry_x509_cert(Entry_collection): key_fname=self.key_fname, config_fname=config_fname, sw_rev=self.sw_rev, - req_dist_name_dict=self.req_dist_name) + req_dist_name_dict=self.req_dist_name, + firewall_cert_data=self.firewall_cert_data) elif type == 'rom': stdout = self.openssl.x509_cert_rom( cert_fname=output_fname, -- cgit v1.2.3 From 30eb98a1eb485a92f57499dcf23442a2cc5ecc52 Mon Sep 17 00:00:00 2001 From: Manorit Chawdhry Date: Wed, 11 Oct 2023 14:09:38 +0530 Subject: binman: ftest: Add test for ti-secure firewall node Add test for TI firewalling node in ti-secure. Signed-off-by: Manorit Chawdhry --- tools/binman/ftest.py | 22 +++++++++++++++++ tools/binman/test/319_ti_secure_firewall.dts | 28 ++++++++++++++++++++++ .../320_ti_secure_firewall_missing_property.dts | 28 ++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 tools/binman/test/319_ti_secure_firewall.dts create mode 100644 tools/binman/test/320_ti_secure_firewall_missing_property.dts (limited to 'tools') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 1555ce9898..5a5da4f53d 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -6463,6 +6463,28 @@ fdt fdtmap Extract the devicetree blob from the fdtmap entry_args=entry_args)[0] self.assertGreater(len(data), len(TI_UNSECURE_DATA)) + def testPackTiSecureFirewall(self): + """Test that an image with a TI secured binary can be created""" + keyfile = self.TestFile('key.key') + entry_args = { + 'keyfile': keyfile, + } + data_no_firewall = self._DoReadFileDtb('296_ti_secure.dts', + entry_args=entry_args)[0] + data_firewall = self._DoReadFileDtb('319_ti_secure_firewall.dts', + entry_args=entry_args)[0] + self.assertGreater(len(data_firewall),len(data_no_firewall)) + + def testPackTiSecureFirewallMissingProperty(self): + """Test that an image with a TI secured binary can be created""" + keyfile = self.TestFile('key.key') + entry_args = { + 'keyfile': keyfile, + } + data_firewall = self._DoReadFileDtb('320_ti_secure_firewall_missing_property.dts', + entry_args=entry_args)[0] + self.assertRegex("can't be None in firewall node", str(e.exception)) + def testPackTiSecureMissingTool(self): """Test that an image with a TI secured binary (non-functional) can be created when openssl is missing""" diff --git a/tools/binman/test/319_ti_secure_firewall.dts b/tools/binman/test/319_ti_secure_firewall.dts new file mode 100644 index 0000000000..7ec407fa67 --- /dev/null +++ b/tools/binman/test/319_ti_secure_firewall.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + ti-secure { + content = <&unsecure_binary>; + auth-in-place = <0xa02>; + + firewall-0-2 { + id = <0>; + region = <2>; + control = <0x31a>; + permissions = <0xc3ffff>; + start_address = <0x0 0x9e800000>; + end_address = <0x0 0x9fffffff>; + }; + + }; + unsecure_binary: blob-ext { + filename = "ti_unsecure.bin"; + }; + }; +}; diff --git a/tools/binman/test/320_ti_secure_firewall_missing_property.dts b/tools/binman/test/320_ti_secure_firewall_missing_property.dts new file mode 100644 index 0000000000..8e995ffa47 --- /dev/null +++ b/tools/binman/test/320_ti_secure_firewall_missing_property.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + ti-secure { + content = <&unsecure_binary>; + auth-in-place = <0xa02>; + + firewall-0-2 { + // id = <0>; + region = <2>; + control = <0x31a>; + permissions = <0xc3ffff>; + start_address = <0x0 0x9e800000>; + end_address = <0x0 0x9fffffff>; + }; + + }; + unsecure_binary: blob-ext { + filename = "ti_unsecure.bin"; + }; + }; +}; -- cgit v1.2.3 From 7252c55a3fceae57ddc32bd10a9b6702c88a7522 Mon Sep 17 00:00:00 2001 From: Neha Malcom Francis Date: Thu, 12 Oct 2023 15:34:20 +0530 Subject: binman: openssl: x509: Support bootcore_opts Support bootcore_opts field in x509 template. The bootcore_opts argument had been defined earlier but not utilised into the final certificate. Fixes: d43c636437d1 ("binman: openssl: x509: ti_secure_rom: Add support for bootcore_opts") Signed-off-by: Neha Malcom Francis --- tools/binman/btool/openssl.py | 5 +++-- tools/binman/etype/x509_cert.py | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/binman/btool/openssl.py b/tools/binman/btool/openssl.py index adf90ed598..ac1eaf5ded 100644 --- a/tools/binman/btool/openssl.py +++ b/tools/binman/btool/openssl.py @@ -238,7 +238,7 @@ emailAddress = {req_dist_name_dict['emailAddress']} imagesize_sbl, hashval_sbl, load_addr_sysfw, imagesize_sysfw, hashval_sysfw, load_addr_sysfw_data, imagesize_sysfw_data, hashval_sysfw_data, sysfw_inner_cert_ext_boot_block, - dm_data_ext_boot_block): + dm_data_ext_boot_block, bootcore_opts): """Create a certificate Args: @@ -254,6 +254,7 @@ emailAddress = {req_dist_name_dict['emailAddress']} bootcore (int): Booting core load_addr (int): Load address of image sha (int): Hash function + bootcore_opts (int): Boot core option (split/lockstep mode) Returns: str: Tool output @@ -298,7 +299,7 @@ sysfw_data=SEQUENCE:sysfw_data [sbl] compType = INTEGER:1 bootCore = INTEGER:16 -compOpts = INTEGER:0 +compOpts = INTEGER:{bootcore_opts} destAddr = FORMAT:HEX,OCT:{load_addr:08x} compSize = INTEGER:{imagesize_sbl} shaType = OID:{sha_type} diff --git a/tools/binman/etype/x509_cert.py b/tools/binman/etype/x509_cert.py index 9e1cf47902..cd240559e5 100644 --- a/tools/binman/etype/x509_cert.py +++ b/tools/binman/etype/x509_cert.py @@ -137,7 +137,8 @@ class Entry_x509_cert(Entry_collection): imagesize_sysfw_data=self.imagesize_sysfw_data, hashval_sysfw_data=self.hashval_sysfw_data, sysfw_inner_cert_ext_boot_block=self.sysfw_inner_cert_ext_boot_block, - dm_data_ext_boot_block=self.dm_data_ext_boot_block + dm_data_ext_boot_block=self.dm_data_ext_boot_block, + bootcore_opts=self.bootcore_opts ) if stdout is not None: data = tools.read_file(output_fname) -- cgit v1.2.3 From ca69452f7ab492e350a8b618845a9b78c4b93adf Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 24 Nov 2023 17:03:24 +0200 Subject: tools/fdtgrep: Include __symbols__ table This is required for overlays to work at SPL. Loading of symbol table depends on DT Overlay support in SPL so make it compile-time dependent. Without this SPL fails to boot some platforms where this feature is not enabled (e.g. dra71-evm.) Without including the file, the symbol CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY will not be visible and we will never include the symbol table. So include Due to some reason it needs to be included after [#include "fdt_host.h"] otherwise it causes a build error. Signed-off-by: Roger Quadros --- tools/fdtgrep.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tools') diff --git a/tools/fdtgrep.c b/tools/fdtgrep.c index 7eabcab439..706b4a35f4 100644 --- a/tools/fdtgrep.c +++ b/tools/fdtgrep.c @@ -22,6 +22,8 @@ #include "fdt_host.h" #include "libfdt_internal.h" +#include + /* Define DEBUG to get some debugging output on stderr */ #ifdef DEBUG #define debug(a, b...) fprintf(stderr, a, ## b) @@ -1234,6 +1236,12 @@ int main(int argc, char *argv[]) disp.fout = stdout; } + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY)) { + /* include symbol table */ + if (value_add(&disp, &disp.value_head, FDT_IS_NODE, 1, "/__symbols__")) + usage("Cannot add __symbols__ value"); + } + /* Run the grep and output the results */ ret = do_fdtgrep(&disp, filename); if (disp.output_fname) -- cgit v1.2.3