[RFC PATCH 1/2] binman: ti-secure: Add support for firewalling entities
Manorit Chawdhry
m-chawdhry at ti.com
Wed Sep 6 06:44:50 CEST 2023
Hi Neha,
On 09:16-20230906, Neha Malcom Francis wrote:
> 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?
>
Ah yes, I believe it can come helpful to other people using openssl too
as openssl gets the input in this hex_octet form. Will be moving there
as you mentioned. Thanks for the suggestion!
> > + 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 ?
>
Ah yes, a typo.
> > + 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
Sure, would keep these in mind. Thanks for reviewing!
Regards,
Manorit
>
> --
> Thanking You
> Neha Malcom Francis
More information about the U-Boot
mailing list