[RFC PATCH 1/2] binman: ti-secure: Add support for firewalling entities

Neha Malcom Francis n-francis at ti.com
Wed Sep 6 05:46:10 CEST 2023


Hi Manorit

On 05/09/23 13:51, Manorit Chawdhry wrote:
> 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 <m-chawdhry at ti.com>
> ---
>   tools/binman/btool/openssl.py   | 16 ++++++++++--
>   tools/binman/etype/ti_secure.py | 54 +++++++++++++++++++++++++++++++++++++++++
>   tools/binman/etype/x509_cert.py |  3 ++-
>   3 files changed, 70 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/binman/btool/openssl.py b/tools/binman/btool/openssl.py
> index aad3b61ae27c..dff439df211f 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 d939dce57139..a980d10f4197 100644
> --- a/tools/binman/etype/ti_secure.py
> +++ b/tools/binman/etype/ti_secure.py
> @@ -7,9 +7,39 @@
>   
>   from binman.entry import EntryArg
>   from binman.etype.x509_cert import Entry_x509_cert
> +from dataclasses import dataclass
>   
>   from dtoc import fdt_util
>   
> +def hex_octet(n):
> +  x = '%x' % (n,)
> +  return ('0' * (len(x) % 2)) + x
> +

If this was the only way to grab the address this way, maybe consider adding 
this as a common fdt_util function?

> + at dataclass
> +class Firewall():
> +    id: int
> +    region: int
> +    control : int
> +    permissions: list[hex]
> +    start_address: str
> +    end_address: str
> +
> +    def get_certificate(self) -> str:
> +        unique_indentifier = f"{self.id}{self.region}"
> +        cert = f"""
> +firewallID{unique_indentifier} = INTEGER:{self.id}
> +region{unique_indentifier} = INTEGER:{self.region}
> +control{unique_indentifier} = INTEGER:{hex(self.control)}
> +nPermissionRegs{unique_indentifier} = INTEGER:{len(self.permissions)}
> +"""

s/indentifier/identifier ?

> +        for index, permission in enumerate(self.permissions):
> +            cert += f"""permissions{unique_indentifier}{index} = INTEGER:{hex(permission)}
> +"""
> +        cert += f"""startAddress{unique_indentifier} = FORMAT:HEX,OCT:{hex_octet(self.start_address)}
> +endAddress{unique_indentifier} = FORMAT:HEX,OCT:{hex_octet(self.end_address)}
> +"""
> +        return cert
> +
>   class Entry_ti_secure(Entry_x509_cert):
>       """Entry containing a TI x509 certificate binary
>   
> @@ -32,11 +62,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 +85,21 @@ class Entry_ti_secure(Entry_x509_cert):
>                   'CN': 'TI Support',
>                   'emailAddress': 'support at ti.com'}
>   
> +    def ReadFirewallNode(self):
> +        self.firewall_cert_data['certificate'] = ""
> +        self.firewall_cert_data['num_firewalls'] = 0
> +        for node in self._node.subnodes:
> +            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 d028cfe38cd9..9e1cf479023b 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,
> 
For v1:
- ti-secure node should contain the documentation of how to use this firewall 
sub-node, basically whatever you've put in x509_cert_sysfw()
- add test(s) for complete test coverage

-- 
Thanking You
Neha Malcom Francis


More information about the U-Boot mailing list