binman: ti-secure: Add support for TI signing
The ti-secure entry contains certificate for binaries that will be loaded or booted by system firmware whereas the ti-secure-rom entry contains certificate for binaries that will be booted by ROM. Support for both these types of certificates is necessary for booting of K3 devices. Signed-off-by: Neha Malcom Francis <n-francis@ti.com> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
		
							parent
							
								
									96ff5709e4
								
							
						
					
					
						commit
						dd467d4f53
					
				|  | @ -0,0 +1,51 @@ | ||||||
|  | -----BEGIN RSA PRIVATE KEY----- | ||||||
|  | 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 | ||||||
|  | -----END RSA PRIVATE KEY----- | ||||||
|  | @ -0,0 +1,10 @@ | ||||||
|  | -----BEGIN RSA PRIVATE KEY----- | ||||||
|  | MIIBWwIBAAKBgQDRfrnXQaP0k6vRK/gZ+bDflSU6y1JagGeQ/b+QYuiDz14japog | ||||||
|  | 8fRSu5WBsAxaSaySAUwS3L9Ppw+hGMecmyIJ494aMfZTtk1g49gU58joduiRnu7e | ||||||
|  | QSZHMnehhuNlfD7A2tAAKnxIYuabs8zHYM/SS9Ne7t3kIQMbKfUSzNy6qQIBAQIB | ||||||
|  | AQJBAOelUA376o6w3HkShXfN+shaOZYqFuTJ9exLMwsLp7DZKXB5F9I4JJ+Vkvho | ||||||
|  | k6QWs7vkhleLSYUZknXHYm26ZE0CQQDnhTtd4PTBoZPjPXOeYMJFtEdMNy0XP6ey | ||||||
|  | bcce389ugoY7BEkvASrd8PHgJQHziepgWOG4DGp33c64Hfq4zI3NAgEBAgEBAkA0 | ||||||
|  | RbK4uqoLciQluesTPU6lBy7Se3Dw0F9xBqlF5SR4KI6q+zQrHpBKyFOofMHZgizR | ||||||
|  | iCrL55cxEM146zMw3AnF | ||||||
|  | -----END RSA PRIVATE KEY----- | ||||||
|  | @ -15,6 +15,13 @@ import hashlib | ||||||
| from binman import bintool | from binman import bintool | ||||||
| from u_boot_pylib import tools | from u_boot_pylib import tools | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | VALID_SHAS = [256, 384, 512, 224] | ||||||
|  | SHA_OIDS = {256:'2.16.840.1.101.3.4.2.1', | ||||||
|  |             384:'2.16.840.1.101.3.4.2.2', | ||||||
|  |             512:'2.16.840.1.101.3.4.2.3', | ||||||
|  |             224:'2.16.840.1.101.3.4.2.4'} | ||||||
|  | 
 | ||||||
| class Bintoolopenssl(bintool.Bintool): | class Bintoolopenssl(bintool.Bintool): | ||||||
|     """openssl tool |     """openssl tool | ||||||
| 
 | 
 | ||||||
|  | @ -74,6 +81,243 @@ imageSize              = INTEGER:{len(indata)} | ||||||
|                 '-sha512'] |                 '-sha512'] | ||||||
|         return self.run_cmd(*args) |         return self.run_cmd(*args) | ||||||
| 
 | 
 | ||||||
|  |     def x509_cert_sysfw(self, cert_fname, input_fname, key_fname, sw_rev, | ||||||
|  |                   config_fname, req_dist_name_dict): | ||||||
|  |         """Create a certificate to be booted by system firmware | ||||||
|  | 
 | ||||||
|  |         Args: | ||||||
|  |             cert_fname (str): Filename of certificate to create | ||||||
|  |             input_fname (str): Filename containing data to sign | ||||||
|  |             key_fname (str): Filename of .pem file | ||||||
|  |             sw_rev (int): Software revision | ||||||
|  |             config_fname (str): Filename to write fconfig into | ||||||
|  |             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 | ||||||
|  | 
 | ||||||
|  |         Returns: | ||||||
|  |             str: Tool output | ||||||
|  |         """ | ||||||
|  |         indata = tools.read_file(input_fname) | ||||||
|  |         hashval = hashlib.sha512(indata).hexdigest() | ||||||
|  |         with open(config_fname, 'w', encoding='utf-8') as outf: | ||||||
|  |             print(f'''[ req ] | ||||||
|  | distinguished_name     = req_distinguished_name | ||||||
|  | x509_extensions        = v3_ca | ||||||
|  | prompt                 = no | ||||||
|  | dirstring_type         = nobmp | ||||||
|  | 
 | ||||||
|  | [ req_distinguished_name ] | ||||||
|  | C                      = {req_dist_name_dict['C']} | ||||||
|  | ST                     = {req_dist_name_dict['ST']} | ||||||
|  | L                      = {req_dist_name_dict['L']} | ||||||
|  | O                      = {req_dist_name_dict['O']} | ||||||
|  | OU                     = {req_dist_name_dict['OU']} | ||||||
|  | CN                     = {req_dist_name_dict['CN']} | ||||||
|  | emailAddress           = {req_dist_name_dict['emailAddress']} | ||||||
|  | 
 | ||||||
|  | [ v3_ca ] | ||||||
|  | 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 | ||||||
|  | 
 | ||||||
|  | [ swrv ] | ||||||
|  | swrv = INTEGER:{sw_rev} | ||||||
|  | 
 | ||||||
|  | [ sysfw_image_integrity ] | ||||||
|  | shaType                = OID:2.16.840.1.101.3.4.2.3 | ||||||
|  | shaValue               = FORMAT:HEX,OCT:{hashval} | ||||||
|  | imageSize              = INTEGER:{len(indata)} | ||||||
|  | 
 | ||||||
|  | [ sysfw_image_load ] | ||||||
|  | destAddr = FORMAT:HEX,OCT:00000000 | ||||||
|  | authInPlace = INTEGER:2 | ||||||
|  | ''', file=outf) | ||||||
|  |         args = ['req', '-new', '-x509', '-key', key_fname, '-nodes', | ||||||
|  |                 '-outform', 'DER', '-out', cert_fname, '-config', config_fname, | ||||||
|  |                 '-sha512'] | ||||||
|  |         return self.run_cmd(*args) | ||||||
|  | 
 | ||||||
|  |     def x509_cert_rom(self, cert_fname, input_fname, key_fname, sw_rev, | ||||||
|  |                   config_fname, req_dist_name_dict, cert_type, bootcore, | ||||||
|  |                   bootcore_opts, load_addr, sha): | ||||||
|  |         """Create a certificate | ||||||
|  | 
 | ||||||
|  |         Args: | ||||||
|  |             cert_fname (str): Filename of certificate to create | ||||||
|  |             input_fname (str): Filename containing data to sign | ||||||
|  |             key_fname (str): Filename of .pem file | ||||||
|  |             sw_rev (int): Software revision | ||||||
|  |             config_fname (str): Filename to write fconfig into | ||||||
|  |             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 | ||||||
|  |             cert_type (int): Certification type | ||||||
|  |             bootcore (int): Booting core | ||||||
|  |             load_addr (int): Load address of image | ||||||
|  |             sha (int): Hash function | ||||||
|  | 
 | ||||||
|  |         Returns: | ||||||
|  |             str: Tool output | ||||||
|  |         """ | ||||||
|  |         indata = tools.read_file(input_fname) | ||||||
|  |         hashval = hashlib.sha512(indata).hexdigest() | ||||||
|  |         with open(config_fname, 'w', encoding='utf-8') as outf: | ||||||
|  |             print(f''' | ||||||
|  | [ req ] | ||||||
|  |  distinguished_name     = req_distinguished_name | ||||||
|  |  x509_extensions        = v3_ca | ||||||
|  |  prompt                 = no | ||||||
|  |  dirstring_type         = nobmp | ||||||
|  | 
 | ||||||
|  |  [ req_distinguished_name ] | ||||||
|  | C                      = {req_dist_name_dict['C']} | ||||||
|  | ST                     = {req_dist_name_dict['ST']} | ||||||
|  | L                      = {req_dist_name_dict['L']} | ||||||
|  | O                      = {req_dist_name_dict['O']} | ||||||
|  | OU                     = {req_dist_name_dict['OU']} | ||||||
|  | CN                     = {req_dist_name_dict['CN']} | ||||||
|  | emailAddress           = {req_dist_name_dict['emailAddress']} | ||||||
|  | 
 | ||||||
|  |  [ v3_ca ] | ||||||
|  |  basicConstraints = CA:true | ||||||
|  |  1.3.6.1.4.1.294.1.1 = ASN1:SEQUENCE:boot_seq | ||||||
|  |  1.3.6.1.4.1.294.1.2 = ASN1:SEQUENCE:image_integrity | ||||||
|  |  1.3.6.1.4.1.294.1.3 = ASN1:SEQUENCE:swrv | ||||||
|  | # 1.3.6.1.4.1.294.1.4 = ASN1:SEQUENCE:encryption | ||||||
|  |  1.3.6.1.4.1.294.1.8 = ASN1:SEQUENCE:debug | ||||||
|  | 
 | ||||||
|  |  [ boot_seq ] | ||||||
|  |  certType = INTEGER:{cert_type} | ||||||
|  |  bootCore = INTEGER:{bootcore} | ||||||
|  |  bootCoreOpts = INTEGER:{bootcore_opts} | ||||||
|  |  destAddr = FORMAT:HEX,OCT:{load_addr:08x} | ||||||
|  |  imageSize = INTEGER:{len(indata)} | ||||||
|  | 
 | ||||||
|  |  [ image_integrity ] | ||||||
|  |  shaType = OID:{SHA_OIDS[sha]} | ||||||
|  |  shaValue = FORMAT:HEX,OCT:{hashval} | ||||||
|  | 
 | ||||||
|  |  [ swrv ] | ||||||
|  |  swrv = INTEGER:{sw_rev} | ||||||
|  | 
 | ||||||
|  | # [ encryption ] | ||||||
|  | # initalVector = FORMAT:HEX,OCT:TEST_IMAGE_ENC_IV | ||||||
|  | # randomString = FORMAT:HEX,OCT:TEST_IMAGE_ENC_RS | ||||||
|  | # iterationCnt = INTEGER:TEST_IMAGE_KEY_DERIVE_INDEX | ||||||
|  | # salt = FORMAT:HEX,OCT:TEST_IMAGE_KEY_DERIVE_SALT | ||||||
|  | 
 | ||||||
|  |  [ debug ] | ||||||
|  |  debugUID = FORMAT:HEX,OCT:0000000000000000000000000000000000000000000000000000000000000000 | ||||||
|  |  debugType = INTEGER:4 | ||||||
|  |  coreDbgEn = INTEGER:0 | ||||||
|  |  coreDbgSecEn = INTEGER:0 | ||||||
|  | ''', file=outf) | ||||||
|  |         args = ['req', '-new', '-x509', '-key', key_fname, '-nodes', | ||||||
|  |                 '-outform', 'DER', '-out', cert_fname, '-config', config_fname, | ||||||
|  |                 '-sha512'] | ||||||
|  |         return self.run_cmd(*args) | ||||||
|  | 
 | ||||||
|  |     def x509_cert_rom_combined(self, cert_fname, input_fname, key_fname, sw_rev, | ||||||
|  |                   config_fname, req_dist_name_dict, load_addr, sha, total_size, num_comps, | ||||||
|  |                   sysfw_inner_cert_ext_boot_sequence_string, dm_data_ext_boot_sequence_string, | ||||||
|  |                   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): | ||||||
|  |         """Create a certificate | ||||||
|  | 
 | ||||||
|  |         Args: | ||||||
|  |             cert_fname (str): Filename of certificate to create | ||||||
|  |             input_fname (str): Filename containing data to sign | ||||||
|  |             key_fname (str): Filename of .pem file | ||||||
|  |             sw_rev (int): Software revision | ||||||
|  |             config_fname (str): Filename to write fconfig into | ||||||
|  |             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 | ||||||
|  |             cert_type (int): Certification type | ||||||
|  |             bootcore (int): Booting core | ||||||
|  |             load_addr (int): Load address of image | ||||||
|  |             sha (int): Hash function | ||||||
|  | 
 | ||||||
|  |         Returns: | ||||||
|  |             str: Tool output | ||||||
|  |         """ | ||||||
|  |         indata = tools.read_file(input_fname) | ||||||
|  |         hashval = hashlib.sha512(indata).hexdigest() | ||||||
|  |         sha_type = SHA_OIDS[sha] | ||||||
|  |         with open(config_fname, 'w', encoding='utf-8') as outf: | ||||||
|  |             print(f''' | ||||||
|  | [ req ] | ||||||
|  | distinguished_name     = req_distinguished_name | ||||||
|  | x509_extensions        = v3_ca | ||||||
|  | prompt                 = no | ||||||
|  | dirstring_type         = nobmp | ||||||
|  | 
 | ||||||
|  | [ req_distinguished_name ] | ||||||
|  | C                      = {req_dist_name_dict['C']} | ||||||
|  | ST                     = {req_dist_name_dict['ST']} | ||||||
|  | L                      = {req_dist_name_dict['L']} | ||||||
|  | O                      = {req_dist_name_dict['O']} | ||||||
|  | OU                     = {req_dist_name_dict['OU']} | ||||||
|  | CN                     = {req_dist_name_dict['CN']} | ||||||
|  | emailAddress           = {req_dist_name_dict['emailAddress']} | ||||||
|  | 
 | ||||||
|  | [ v3_ca ] | ||||||
|  | basicConstraints = CA:true | ||||||
|  | 1.3.6.1.4.1.294.1.3=ASN1:SEQUENCE:swrv | ||||||
|  | 1.3.6.1.4.1.294.1.9=ASN1:SEQUENCE:ext_boot_info | ||||||
|  | 
 | ||||||
|  | [swrv] | ||||||
|  | swrv=INTEGER:{sw_rev} | ||||||
|  | 
 | ||||||
|  | [ext_boot_info] | ||||||
|  | extImgSize=INTEGER:{total_size} | ||||||
|  | numComp=INTEGER:{num_comps} | ||||||
|  | sbl=SEQUENCE:sbl | ||||||
|  | sysfw=SEQUENCE:sysfw | ||||||
|  | sysfw_data=SEQUENCE:sysfw_data | ||||||
|  | {sysfw_inner_cert_ext_boot_sequence_string} | ||||||
|  | {dm_data_ext_boot_sequence_string} | ||||||
|  | 
 | ||||||
|  | [sbl] | ||||||
|  | compType = INTEGER:1 | ||||||
|  | bootCore = INTEGER:16 | ||||||
|  | compOpts = INTEGER:0 | ||||||
|  | destAddr = FORMAT:HEX,OCT:{load_addr:08x} | ||||||
|  | compSize = INTEGER:{imagesize_sbl} | ||||||
|  | shaType  = OID:{sha_type} | ||||||
|  | shaValue = FORMAT:HEX,OCT:{hashval_sbl} | ||||||
|  | 
 | ||||||
|  | [sysfw] | ||||||
|  | compType = INTEGER:2 | ||||||
|  | bootCore = INTEGER:0 | ||||||
|  | compOpts = INTEGER:0 | ||||||
|  | destAddr = FORMAT:HEX,OCT:{load_addr_sysfw:08x} | ||||||
|  | compSize = INTEGER:{imagesize_sysfw} | ||||||
|  | shaType  = OID:{sha_type} | ||||||
|  | shaValue = FORMAT:HEX,OCT:{hashval_sysfw} | ||||||
|  | 
 | ||||||
|  | [sysfw_data] | ||||||
|  | compType = INTEGER:18 | ||||||
|  | bootCore = INTEGER:0 | ||||||
|  | compOpts = INTEGER:0 | ||||||
|  | destAddr = FORMAT:HEX,OCT:{load_addr_sysfw_data:08x} | ||||||
|  | compSize = INTEGER:{imagesize_sysfw_data} | ||||||
|  | shaType  = OID:{sha_type} | ||||||
|  | shaValue = FORMAT:HEX,OCT:{hashval_sysfw_data} | ||||||
|  | 
 | ||||||
|  | {sysfw_inner_cert_ext_boot_block} | ||||||
|  | 
 | ||||||
|  | {dm_data_ext_boot_block} | ||||||
|  |         ''', file=outf) | ||||||
|  |         args = ['req', '-new', '-x509', '-key', key_fname, '-nodes', | ||||||
|  |                 '-outform', 'DER', '-out', cert_fname, '-config', config_fname, | ||||||
|  |                 '-sha512'] | ||||||
|  |         return self.run_cmd(*args) | ||||||
|  | 
 | ||||||
|     def fetch(self, method): |     def fetch(self, method): | ||||||
|         """Fetch handler for openssl |         """Fetch handler for openssl | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1701,6 +1701,71 @@ the included board config binaries. Example:: | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | .. _etype_ti_secure: | ||||||
|  | 
 | ||||||
|  | Entry: ti-secure: Entry containing a TI x509 certificate binary | ||||||
|  | --------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  | Properties / Entry arguments: | ||||||
|  |     - 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 | ||||||
|  | 
 | ||||||
|  | Output files: | ||||||
|  |     - input.<unique_name> - input file passed to openssl | ||||||
|  |     - config.<unique_name> - input file generated for openssl (which is | ||||||
|  |       used as the config file) | ||||||
|  |     - cert.<unique_name> - output file generated by openssl (which is | ||||||
|  |       used as the entry contents) | ||||||
|  | 
 | ||||||
|  | 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. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | .. _etype_ti_secure_rom: | ||||||
|  | 
 | ||||||
|  | Entry: ti-secure-rom: Entry containing a TI x509 certificate binary for images booted by ROM | ||||||
|  | -------------------------------------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  | Properties / Entry arguments: | ||||||
|  |     - keyfile: Filename of file containing key to sign binary with | ||||||
|  |     - combined: boolean if device follows combined boot flow | ||||||
|  |     - countersign: boolean if device contains countersigned system firmware | ||||||
|  |     - load: load address of SPL | ||||||
|  |     - sw-rev: software revision | ||||||
|  |     - sha: Hash function to be used for signing | ||||||
|  |     - 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 | ||||||
|  | 
 | ||||||
|  | The following properties are only for generating a combined bootflow binary: | ||||||
|  |     - sysfw-inner-cert: boolean if binary contains sysfw inner certificate | ||||||
|  |     - dm-data: boolean if binary contains dm-data binary | ||||||
|  |     - content-sbl: phandle of SPL binary | ||||||
|  |     - content-sysfw: phandle of sysfw binary | ||||||
|  |     - content-sysfw-data: phandle of sysfw-data or tifs-data binary | ||||||
|  |     - content-sysfw-inner-cert (optional): phandle of sysfw inner certificate binary | ||||||
|  |     - content-dm-data (optional): phandle of dm-data binary | ||||||
|  |     - load-sysfw: load address of sysfw binary | ||||||
|  |     - load-sysfw-data: load address of sysfw-data or tifs-data binary | ||||||
|  |     - load-sysfw-inner-cert (optional): load address of sysfw inner certificate binary | ||||||
|  |     - load-dm-data (optional): load address of dm-data binary | ||||||
|  | 
 | ||||||
|  | Output files: | ||||||
|  |     - input.<unique_name> - input file passed to openssl | ||||||
|  |     - config.<unique_name> - input file generated for openssl (which is | ||||||
|  |       used as the config file) | ||||||
|  |     - cert.<unique_name> - output file generated by openssl (which is | ||||||
|  |       used as the entry contents) | ||||||
|  | 
 | ||||||
|  | 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. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| .. _etype_u_boot: | .. _etype_u_boot: | ||||||
| 
 | 
 | ||||||
| Entry: u-boot: U-Boot flat binary | Entry: u-boot: U-Boot flat binary | ||||||
|  |  | ||||||
|  | @ -0,0 +1,76 @@ | ||||||
|  | # SPDX-License-Identifier: GPL-2.0+ | ||||||
|  | # Copyright (c) 2022 Texas Instruments Incorporated - https://www.ti.com/ | ||||||
|  | # Written by Neha Malcom Francis <n-francis@ti.com> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | # Support for generation of TI secured binary blobs | ||||||
|  | 
 | ||||||
|  | from binman.entry import EntryArg | ||||||
|  | from binman.etype.x509_cert import Entry_x509_cert | ||||||
|  | 
 | ||||||
|  | from dtoc import fdt_util | ||||||
|  | 
 | ||||||
|  | class Entry_ti_secure(Entry_x509_cert): | ||||||
|  |     """Entry containing a TI x509 certificate binary | ||||||
|  | 
 | ||||||
|  |     Properties / Entry arguments: | ||||||
|  |         - 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 | ||||||
|  | 
 | ||||||
|  |     Output files: | ||||||
|  |         - input.<unique_name> - input file passed to openssl | ||||||
|  |         - config.<unique_name> - input file generated for openssl (which is | ||||||
|  |           used as the config file) | ||||||
|  |         - cert.<unique_name> - output file generated by openssl (which is | ||||||
|  |           used as the entry contents) | ||||||
|  | 
 | ||||||
|  |     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. | ||||||
|  |     """ | ||||||
|  |     def __init__(self, section, etype, node): | ||||||
|  |         super().__init__(section, etype, node) | ||||||
|  |         self.openssl = None | ||||||
|  | 
 | ||||||
|  |     def ReadNode(self): | ||||||
|  |         super().ReadNode() | ||||||
|  |         self.key_fname = self.GetEntryArgsOrProps([ | ||||||
|  |             EntryArg('keyfile', str)], required=True)[0] | ||||||
|  |         self.sha = fdt_util.GetInt(self._node, 'sha', 512) | ||||||
|  |         self.req_dist_name = {'C': 'US', | ||||||
|  |                 'ST': 'TX', | ||||||
|  |                 'L': 'Dallas', | ||||||
|  |                 'O': 'Texas Instruments Incorporated', | ||||||
|  |                 'OU': 'Processors', | ||||||
|  |                 'CN': 'TI Support', | ||||||
|  |                 'emailAddress': 'support@ti.com'} | ||||||
|  | 
 | ||||||
|  |     def GetCertificate(self, required): | ||||||
|  |         """Get the contents of this entry | ||||||
|  | 
 | ||||||
|  |         Args: | ||||||
|  |             required: True if the data must be present, False if it is OK to | ||||||
|  |                 return None | ||||||
|  | 
 | ||||||
|  |         Returns: | ||||||
|  |             bytes content of the entry, which is the certificate binary for the | ||||||
|  |                 provided data | ||||||
|  |         """ | ||||||
|  |         return super().GetCertificate(required=required, type='sysfw') | ||||||
|  | 
 | ||||||
|  |     def ObtainContents(self): | ||||||
|  |         data = self.GetCertificate(False) | ||||||
|  |         if data is None: | ||||||
|  |             return False | ||||||
|  |         self.SetContents(data) | ||||||
|  |         return True | ||||||
|  | 
 | ||||||
|  |     def ProcessContents(self): | ||||||
|  |         # The blob may have changed due to WriteSymbols() | ||||||
|  |         data = self.GetCertificate(True) | ||||||
|  |         return self.ProcessContentsUpdate(data) | ||||||
|  | 
 | ||||||
|  |     def AddBintools(self, btools): | ||||||
|  |         super().AddBintools(btools) | ||||||
|  |         self.openssl = self.AddBintool(btools, 'openssl') | ||||||
|  | @ -0,0 +1,247 @@ | ||||||
|  | # SPDX-License-Identifier: GPL-2.0+ | ||||||
|  | # Copyright (c) 2022 Texas Instruments Incorporated - https://www.ti.com/ | ||||||
|  | # Written by Neha Malcom Francis <n-francis@ti.com> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | # Support for generation of TI secured bootloaders booted by ROM | ||||||
|  | 
 | ||||||
|  | from binman.entry import EntryArg | ||||||
|  | from binman.etype.x509_cert import Entry_x509_cert | ||||||
|  | 
 | ||||||
|  | import hashlib | ||||||
|  | 
 | ||||||
|  | from dtoc import fdt_util | ||||||
|  | from u_boot_pylib  import tools | ||||||
|  | 
 | ||||||
|  | VALID_SHAS = [256, 384, 512, 224] | ||||||
|  | SHA_OIDS = {256:'2.16.840.1.101.3.4.2.1', | ||||||
|  |             384:'2.16.840.1.101.3.4.2.2', | ||||||
|  |             512:'2.16.840.1.101.3.4.2.3', | ||||||
|  |             224:'2.16.840.1.101.3.4.2.4'} | ||||||
|  | 
 | ||||||
|  | class Entry_ti_secure_rom(Entry_x509_cert): | ||||||
|  |     """Entry containing a TI x509 certificate binary for images booted by ROM | ||||||
|  | 
 | ||||||
|  |     Properties / Entry arguments: | ||||||
|  |         - keyfile: Filename of file containing key to sign binary with | ||||||
|  |         - combined: boolean if device follows combined boot flow | ||||||
|  |         - countersign: boolean if device contains countersigned system firmware | ||||||
|  |         - load: load address of SPL | ||||||
|  |         - sw-rev: software revision | ||||||
|  |         - sha: Hash function to be used for signing | ||||||
|  |         - 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 | ||||||
|  | 
 | ||||||
|  |     The following properties are only for generating a combined bootflow binary: | ||||||
|  |         - sysfw-inner-cert: boolean if binary contains sysfw inner certificate | ||||||
|  |         - dm-data: boolean if binary contains dm-data binary | ||||||
|  |         - content-sbl: phandle of SPL binary | ||||||
|  |         - content-sysfw: phandle of sysfw binary | ||||||
|  |         - content-sysfw-data: phandle of sysfw-data or tifs-data binary | ||||||
|  |         - content-sysfw-inner-cert (optional): phandle of sysfw inner certificate binary | ||||||
|  |         - content-dm-data (optional): phandle of dm-data binary | ||||||
|  |         - load-sysfw: load address of sysfw binary | ||||||
|  |         - load-sysfw-data: load address of sysfw-data or tifs-data binary | ||||||
|  |         - load-sysfw-inner-cert (optional): load address of sysfw inner certificate binary | ||||||
|  |         - load-dm-data (optional): load address of dm-data binary | ||||||
|  | 
 | ||||||
|  |     Output files: | ||||||
|  |         - input.<unique_name> - input file passed to openssl | ||||||
|  |         - config.<unique_name> - input file generated for openssl (which is | ||||||
|  |           used as the config file) | ||||||
|  |         - cert.<unique_name> - output file generated by openssl (which is | ||||||
|  |           used as the entry contents) | ||||||
|  | 
 | ||||||
|  |     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. | ||||||
|  |     """ | ||||||
|  |     def __init__(self, section, etype, node): | ||||||
|  |         super().__init__(section, etype, node) | ||||||
|  |         self.openssl = None | ||||||
|  | 
 | ||||||
|  |     def ReadNode(self): | ||||||
|  |         super().ReadNode() | ||||||
|  |         self.combined = fdt_util.GetBool(self._node, 'combined', False) | ||||||
|  |         self.countersign = fdt_util.GetBool(self._node, 'countersign', False) | ||||||
|  |         self.load_addr = fdt_util.GetInt(self._node, 'load', 0x00000000) | ||||||
|  |         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.key_fname = self.GetEntryArgsOrProps([ | ||||||
|  |             EntryArg('keyfile', str)], required=True)[0] | ||||||
|  |         if self.combined: | ||||||
|  |             self.sysfw_inner_cert = fdt_util.GetBool(self._node, 'sysfw-inner-cert', False) | ||||||
|  |             self.load_addr_sysfw = fdt_util.GetInt(self._node, 'load-sysfw', 0x00000000) | ||||||
|  |             self.load_addr_sysfw_data = fdt_util.GetInt(self._node, 'load-sysfw-data', 0x00000000) | ||||||
|  |             self.dm_data = fdt_util.GetBool(self._node, 'dm-data', False) | ||||||
|  |             if self.dm_data: | ||||||
|  |                 self.load_addr_dm_data = fdt_util.GetInt(self._node, 'load-dm-data', 0x00000000) | ||||||
|  |         self.req_dist_name = {'C': 'US', | ||||||
|  |                     'ST': 'TX', | ||||||
|  |                     'L': 'Dallas', | ||||||
|  |                     'O': 'Texas Instruments Incorporated', | ||||||
|  |                     'OU': 'Processors', | ||||||
|  |                     'CN': 'TI Support', | ||||||
|  |                     'emailAddress': 'support@ti.com'} | ||||||
|  | 
 | ||||||
|  |     def NonCombinedGetCertificate(self, required): | ||||||
|  |         """Generate certificate for legacy boot flow | ||||||
|  | 
 | ||||||
|  |         Args: | ||||||
|  |             required: True if the data must be present, False if it is OK to | ||||||
|  |                 return None | ||||||
|  | 
 | ||||||
|  |         Returns: | ||||||
|  |             bytes content of the entry, which is the certificate binary for the | ||||||
|  |                 provided data | ||||||
|  |         """ | ||||||
|  |         if self.core == 'secure': | ||||||
|  |             if self.countersign: | ||||||
|  |                 self.cert_type = 3 | ||||||
|  |             else: | ||||||
|  |                 self.cert_type = 2 | ||||||
|  |             self.bootcore = 0 | ||||||
|  |             self.bootcore_opts = 32 | ||||||
|  |         else: | ||||||
|  |             self.cert_type = 1 | ||||||
|  |             self.bootcore = 16 | ||||||
|  |             self.bootcore_opts = 0 | ||||||
|  |         return super().GetCertificate(required=required, type='rom') | ||||||
|  | 
 | ||||||
|  |     def CombinedGetCertificate(self, required): | ||||||
|  |         """Generate certificate for combined boot flow | ||||||
|  | 
 | ||||||
|  |         Args: | ||||||
|  |             required: True if the data must be present, False if it is OK to | ||||||
|  |                 return None | ||||||
|  | 
 | ||||||
|  |         Returns: | ||||||
|  |             bytes content of the entry, which is the certificate binary for the | ||||||
|  |                 provided data | ||||||
|  |         """ | ||||||
|  |         uniq = self.GetUniqueName() | ||||||
|  | 
 | ||||||
|  |         self.num_comps = 3 | ||||||
|  |         self.sha_type = SHA_OIDS[self.sha] | ||||||
|  | 
 | ||||||
|  |         # sbl | ||||||
|  |         self.content = fdt_util.GetPhandleList(self._node, 'content-sbl') | ||||||
|  |         input_data_sbl = self.GetContents(required) | ||||||
|  |         if input_data_sbl is None: | ||||||
|  |             return None | ||||||
|  | 
 | ||||||
|  |         input_fname_sbl = tools.get_output_filename('input.%s' % uniq) | ||||||
|  |         tools.write_file(input_fname_sbl, input_data_sbl) | ||||||
|  | 
 | ||||||
|  |         indata_sbl = tools.read_file(input_fname_sbl) | ||||||
|  |         self.hashval_sbl = hashlib.sha512(indata_sbl).hexdigest() | ||||||
|  |         self.imagesize_sbl = len(indata_sbl) | ||||||
|  | 
 | ||||||
|  |         # sysfw | ||||||
|  |         self.content = fdt_util.GetPhandleList(self._node, 'content-sysfw') | ||||||
|  |         input_data_sysfw = self.GetContents(required) | ||||||
|  | 
 | ||||||
|  |         input_fname_sysfw = tools.get_output_filename('input.%s' % uniq) | ||||||
|  |         tools.write_file(input_fname_sysfw, input_data_sysfw) | ||||||
|  | 
 | ||||||
|  |         indata_sysfw = tools.read_file(input_fname_sysfw) | ||||||
|  |         self.hashval_sysfw = hashlib.sha512(indata_sysfw).hexdigest() | ||||||
|  |         self.imagesize_sysfw = len(indata_sysfw) | ||||||
|  | 
 | ||||||
|  |         # sysfw data | ||||||
|  |         self.content = fdt_util.GetPhandleList(self._node, 'content-sysfw-data') | ||||||
|  |         input_data_sysfw_data = self.GetContents(required) | ||||||
|  | 
 | ||||||
|  |         input_fname_sysfw_data = tools.get_output_filename('input.%s' % uniq) | ||||||
|  |         tools.write_file(input_fname_sysfw_data, input_data_sysfw_data) | ||||||
|  | 
 | ||||||
|  |         indata_sysfw_data = tools.read_file(input_fname_sysfw_data) | ||||||
|  |         self.hashval_sysfw_data = hashlib.sha512(indata_sysfw_data).hexdigest() | ||||||
|  |         self.imagesize_sysfw_data = len(indata_sysfw_data) | ||||||
|  | 
 | ||||||
|  |         # sysfw inner cert | ||||||
|  |         self.sysfw_inner_cert_ext_boot_block = "" | ||||||
|  |         self.sysfw_inner_cert_ext_boot_sequence_string = "" | ||||||
|  |         imagesize_sysfw_inner_cert = 0 | ||||||
|  |         if self.sysfw_inner_cert: | ||||||
|  |             self.content = fdt_util.GetPhandleList(self._node, 'content-sysfw-inner-cert') | ||||||
|  |             input_data_sysfw_inner_cert = self.GetContents(required) | ||||||
|  | 
 | ||||||
|  |             input_fname_sysfw_inner_cert = tools.get_output_filename('input.%s' % uniq) | ||||||
|  |             tools.write_file(input_fname_sysfw_inner_cert, input_data_sysfw_inner_cert) | ||||||
|  | 
 | ||||||
|  |             indata_sysfw_inner_cert = tools.read_file(input_fname_sysfw_inner_cert) | ||||||
|  |             hashval_sysfw_inner_cert = hashlib.sha512(indata_sysfw_inner_cert).hexdigest() | ||||||
|  |             imagesize_sysfw_inner_cert = len(indata_sysfw_inner_cert) | ||||||
|  |             self.num_comps += 1 | ||||||
|  |             self.sysfw_inner_cert_ext_boot_sequence_string = "sysfw_inner_cert=SEQUENCE:sysfw_inner_cert" | ||||||
|  |             self.sysfw_inner_cert_ext_boot_block = f"""[sysfw_inner_cert] | ||||||
|  | compType = INTEGER:3 | ||||||
|  | bootCore = INTEGER:0 | ||||||
|  | compOpts = INTEGER:0 | ||||||
|  | destAddr = FORMAT:HEX,OCT:00000000 | ||||||
|  | compSize = INTEGER:{imagesize_sysfw_inner_cert} | ||||||
|  | shaType  = OID:{self.sha_type} | ||||||
|  | shaValue = FORMAT:HEX,OCT:{hashval_sysfw_inner_cert}""" | ||||||
|  | 
 | ||||||
|  |         # dm data | ||||||
|  |         self.dm_data_ext_boot_sequence_string = "" | ||||||
|  |         self.dm_data_ext_boot_block = "" | ||||||
|  |         imagesize_dm_data = 0 | ||||||
|  |         if self.dm_data: | ||||||
|  |             self.content = fdt_util.GetPhandleList(self._node, 'content-dm-data') | ||||||
|  |             input_data_dm_data = self.GetContents(required) | ||||||
|  | 
 | ||||||
|  |             input_fname_dm_data = tools.get_output_filename('input.%s' % uniq) | ||||||
|  |             tools.write_file(input_fname_dm_data, input_data_dm_data) | ||||||
|  | 
 | ||||||
|  |             indata_dm_data = tools.read_file(input_fname_dm_data) | ||||||
|  |             hashval_dm_data = hashlib.sha512(indata_dm_data).hexdigest() | ||||||
|  |             imagesize_dm_data = len(indata_dm_data) | ||||||
|  |             self.num_comps += 1 | ||||||
|  |             self.dm_data_ext_boot_sequence_string = "dm_data=SEQUENCE:dm_data" | ||||||
|  |             self.dm_data_ext_boot_block = f"""[dm_data] | ||||||
|  | compType = INTEGER:17 | ||||||
|  | bootCore = INTEGER:16 | ||||||
|  | compOpts = INTEGER:0 | ||||||
|  | destAddr = FORMAT:HEX,OCT:{self.load_addr_dm_data:08x} | ||||||
|  | compSize = INTEGER:{imagesize_dm_data} | ||||||
|  | shaType  = OID:{self.sha_type} | ||||||
|  | shaValue = FORMAT:HEX,OCT:{hashval_dm_data}""" | ||||||
|  | 
 | ||||||
|  |         self.total_size = self.imagesize_sbl +  self.imagesize_sysfw + self.imagesize_sysfw_data + imagesize_sysfw_inner_cert + imagesize_dm_data | ||||||
|  |         return super().GetCertificate(required=required, type='rom-combined') | ||||||
|  | 
 | ||||||
|  |     def GetCertificate(self, required): | ||||||
|  |         """Get the contents of this entry | ||||||
|  | 
 | ||||||
|  |         Args: | ||||||
|  |             required: True if the data must be present, False if it is OK to | ||||||
|  |                 return None | ||||||
|  | 
 | ||||||
|  |         Returns: | ||||||
|  |             bytes content of the entry, which is the certificate binary for the | ||||||
|  |                 provided data | ||||||
|  |         """ | ||||||
|  |         if self.combined: | ||||||
|  |             return self.CombinedGetCertificate(required) | ||||||
|  |         else: | ||||||
|  |             return self.NonCombinedGetCertificate(required) | ||||||
|  | 
 | ||||||
|  |     def ObtainContents(self): | ||||||
|  |         data = self.GetCertificate(False) | ||||||
|  |         if data is None: | ||||||
|  |             return False | ||||||
|  |         self.SetContents(data) | ||||||
|  |         return True | ||||||
|  | 
 | ||||||
|  |     def ProcessContents(self): | ||||||
|  |         # The blob may have changed due to WriteSymbols() | ||||||
|  |         data = self.GetCertificate(True) | ||||||
|  |         return self.ProcessContentsUpdate(data) | ||||||
|  | 
 | ||||||
|  |     def AddBintools(self, btools): | ||||||
|  |         super().AddBintools(btools) | ||||||
|  |         self.openssl = self.AddBintool(btools, 'openssl') | ||||||
|  | @ -31,6 +31,26 @@ class Entry_x509_cert(Entry_collection): | ||||||
|     def __init__(self, section, etype, node): |     def __init__(self, section, etype, node): | ||||||
|         super().__init__(section, etype, node) |         super().__init__(section, etype, node) | ||||||
|         self.openssl = None |         self.openssl = None | ||||||
|  |         self.req_dist_name =  None | ||||||
|  |         self.cert_type = None | ||||||
|  |         self.bootcore = None | ||||||
|  |         self.bootcore_opts = None | ||||||
|  |         self.load_addr = None | ||||||
|  |         self.sha = None | ||||||
|  |         self.total_size = None | ||||||
|  |         self.num_comps = None | ||||||
|  |         self.sysfw_inner_cert_ext_boot_sequence_string = None | ||||||
|  |         self.dm_data_ext_boot_sequence_string = None | ||||||
|  |         self.imagesize_sbl = None | ||||||
|  |         self.hashval_sbl = None | ||||||
|  |         self.load_addr_sysfw = None | ||||||
|  |         self.imagesize_sysfw = None | ||||||
|  |         self.hashval_sysfw = None | ||||||
|  |         self.load_addr_sysfw_data = None | ||||||
|  |         self.imagesize_sysfw_data = None | ||||||
|  |         self.hashval_sysfw_data = None | ||||||
|  |         self.sysfw_inner_cert_ext_boot_block = None | ||||||
|  |         self.dm_data_ext_boot_block = None | ||||||
| 
 | 
 | ||||||
|     def ReadNode(self): |     def ReadNode(self): | ||||||
|         super().ReadNode() |         super().ReadNode() | ||||||
|  | @ -38,13 +58,16 @@ class Entry_x509_cert(Entry_collection): | ||||||
|         self._cert_rev = fdt_util.GetInt(self._node, 'cert-revision-int', 0) |         self._cert_rev = fdt_util.GetInt(self._node, 'cert-revision-int', 0) | ||||||
|         self.key_fname = self.GetEntryArgsOrProps([ |         self.key_fname = self.GetEntryArgsOrProps([ | ||||||
|             EntryArg('keyfile', str)], required=True)[0] |             EntryArg('keyfile', str)], required=True)[0] | ||||||
|  |         self.sw_rev = fdt_util.GetInt(self._node, 'sw-rev', 1) | ||||||
| 
 | 
 | ||||||
|     def GetCertificate(self, required): |     def GetCertificate(self, required, type='generic'): | ||||||
|         """Get the contents of this entry |         """Get the contents of this entry | ||||||
| 
 | 
 | ||||||
|         Args: |         Args: | ||||||
|             required: True if the data must be present, False if it is OK to |             required: True if the data must be present, False if it is OK to | ||||||
|                 return None |                 return None | ||||||
|  |             type: Type of x509 certificate to generate, current supported ones are | ||||||
|  |             'generic', 'sysfw', 'rom' | ||||||
| 
 | 
 | ||||||
|         Returns: |         Returns: | ||||||
|             bytes content of the entry, which is the signed vblock for the |             bytes content of the entry, which is the signed vblock for the | ||||||
|  | @ -60,6 +83,7 @@ class Entry_x509_cert(Entry_collection): | ||||||
|         input_fname = tools.get_output_filename('input.%s' % uniq) |         input_fname = tools.get_output_filename('input.%s' % uniq) | ||||||
|         config_fname = tools.get_output_filename('config.%s' % uniq) |         config_fname = tools.get_output_filename('config.%s' % uniq) | ||||||
|         tools.write_file(input_fname, input_data) |         tools.write_file(input_fname, input_data) | ||||||
|  |         if type == 'generic': | ||||||
|             stdout = self.openssl.x509_cert( |             stdout = self.openssl.x509_cert( | ||||||
|                 cert_fname=output_fname, |                 cert_fname=output_fname, | ||||||
|                 input_fname=input_fname, |                 input_fname=input_fname, | ||||||
|  | @ -67,6 +91,53 @@ class Entry_x509_cert(Entry_collection): | ||||||
|                 cn=self._cert_ca, |                 cn=self._cert_ca, | ||||||
|                 revision=self._cert_rev, |                 revision=self._cert_rev, | ||||||
|                 config_fname=config_fname) |                 config_fname=config_fname) | ||||||
|  |         elif type == 'sysfw': | ||||||
|  |             stdout = self.openssl.x509_cert_sysfw( | ||||||
|  |                 cert_fname=output_fname, | ||||||
|  |                 input_fname=input_fname, | ||||||
|  |                 key_fname=self.key_fname, | ||||||
|  |                 config_fname=config_fname, | ||||||
|  |                 sw_rev=self.sw_rev, | ||||||
|  |                 req_dist_name_dict=self.req_dist_name) | ||||||
|  |         elif type == 'rom': | ||||||
|  |             stdout = self.openssl.x509_cert_rom( | ||||||
|  |                 cert_fname=output_fname, | ||||||
|  |                 input_fname=input_fname, | ||||||
|  |                 key_fname=self.key_fname, | ||||||
|  |                 config_fname=config_fname, | ||||||
|  |                 sw_rev=self.sw_rev, | ||||||
|  |                 req_dist_name_dict=self.req_dist_name, | ||||||
|  |                 cert_type=self.cert_type, | ||||||
|  |                 bootcore=self.bootcore, | ||||||
|  |                 bootcore_opts=self.bootcore_opts, | ||||||
|  |                 load_addr=self.load_addr, | ||||||
|  |                 sha=self.sha | ||||||
|  |             ) | ||||||
|  |         elif type == 'rom-combined': | ||||||
|  |             stdout = self.openssl.x509_cert_rom_combined( | ||||||
|  |                 cert_fname=output_fname, | ||||||
|  |                 input_fname=input_fname, | ||||||
|  |                 key_fname=self.key_fname, | ||||||
|  |                 config_fname=config_fname, | ||||||
|  |                 sw_rev=self.sw_rev, | ||||||
|  |                 req_dist_name_dict=self.req_dist_name, | ||||||
|  |                 load_addr=self.load_addr, | ||||||
|  |                 sha=self.sha, | ||||||
|  |                 total_size=self.total_size, | ||||||
|  |                 num_comps=self.num_comps, | ||||||
|  |                 sysfw_inner_cert_ext_boot_sequence_string=self.sysfw_inner_cert_ext_boot_sequence_string, | ||||||
|  |                 dm_data_ext_boot_sequence_string=self.dm_data_ext_boot_sequence_string, | ||||||
|  |                 imagesize_sbl=self.imagesize_sbl, | ||||||
|  |                 hashval_sbl=self.hashval_sbl, | ||||||
|  |                 load_addr_sysfw=self.load_addr_sysfw, | ||||||
|  |                 imagesize_sysfw=self.imagesize_sysfw, | ||||||
|  |                 hashval_sysfw=self.hashval_sysfw, | ||||||
|  |                 load_addr_sysfw_data=self.load_addr_sysfw_data, | ||||||
|  |                 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 | ||||||
|  |             ) | ||||||
|         if stdout is not None: |         if stdout is not None: | ||||||
|             data = tools.read_file(output_fname) |             data = tools.read_file(output_fname) | ||||||
|         else: |         else: | ||||||
|  |  | ||||||
|  | @ -98,6 +98,7 @@ PRE_LOAD_MAGIC        = b'UBSH' | ||||||
| PRE_LOAD_VERSION      = 0x11223344.to_bytes(4, 'big') | PRE_LOAD_VERSION      = 0x11223344.to_bytes(4, 'big') | ||||||
| PRE_LOAD_HDR_SIZE     = 0x00001000.to_bytes(4, 'big') | PRE_LOAD_HDR_SIZE     = 0x00001000.to_bytes(4, 'big') | ||||||
| TI_BOARD_CONFIG_DATA  = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | TI_BOARD_CONFIG_DATA  = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | ||||||
|  | TI_UNSECURE_DATA      = b'unsecuredata' | ||||||
| 
 | 
 | ||||||
| # Subdirectory of the input dir to use to put test FDTs | # Subdirectory of the input dir to use to put test FDTs | ||||||
| TEST_FDT_SUBDIR       = 'fdts' | TEST_FDT_SUBDIR       = 'fdts' | ||||||
|  | @ -211,6 +212,7 @@ class TestFunctional(unittest.TestCase): | ||||||
|         TestFunctional._MakeInputFile('fw_dynamic.bin', OPENSBI_DATA) |         TestFunctional._MakeInputFile('fw_dynamic.bin', OPENSBI_DATA) | ||||||
|         TestFunctional._MakeInputFile('scp.bin', SCP_DATA) |         TestFunctional._MakeInputFile('scp.bin', SCP_DATA) | ||||||
|         TestFunctional._MakeInputFile('rockchip-tpl.bin', ROCKCHIP_TPL_DATA) |         TestFunctional._MakeInputFile('rockchip-tpl.bin', ROCKCHIP_TPL_DATA) | ||||||
|  |         TestFunctional._MakeInputFile('ti_unsecure.bin', TI_UNSECURE_DATA) | ||||||
| 
 | 
 | ||||||
|         # Add a few .dtb files for testing |         # Add a few .dtb files for testing | ||||||
|         TestFunctional._MakeInputFile('%s/test-fdt1.dtb' % TEST_FDT_SUBDIR, |         TestFunctional._MakeInputFile('%s/test-fdt1.dtb' % TEST_FDT_SUBDIR, | ||||||
|  | @ -6451,5 +6453,55 @@ fdt         fdtmap                Extract the devicetree blob from the fdtmap | ||||||
|             data = self._DoReadFile('279_ti_board_cfg_no_type.dts') |             data = self._DoReadFile('279_ti_board_cfg_no_type.dts') | ||||||
|         self.assertIn("Schema validation error", str(e.exception)) |         self.assertIn("Schema validation error", str(e.exception)) | ||||||
| 
 | 
 | ||||||
|  |     def testPackTiSecure(self): | ||||||
|  |         """Test that an image with a TI secured binary can be created""" | ||||||
|  |         keyfile = self.TestFile('key.key') | ||||||
|  |         entry_args = { | ||||||
|  |             'keyfile': keyfile, | ||||||
|  |         } | ||||||
|  |         data = self._DoReadFileDtb('279_ti_secure.dts', | ||||||
|  |                                    entry_args=entry_args)[0] | ||||||
|  |         self.assertGreater(len(data), len(TI_UNSECURE_DATA)) | ||||||
|  | 
 | ||||||
|  |     def testPackTiSecureMissingTool(self): | ||||||
|  |         """Test that an image with a TI secured binary (non-functional) can be created | ||||||
|  |         when openssl is missing""" | ||||||
|  |         keyfile = self.TestFile('key.key') | ||||||
|  |         entry_args = { | ||||||
|  |             'keyfile': keyfile, | ||||||
|  |         } | ||||||
|  |         with test_util.capture_sys_output() as (_, stderr): | ||||||
|  |             self._DoTestFile('279_ti_secure.dts', | ||||||
|  |                              force_missing_bintools='openssl', | ||||||
|  |                              entry_args=entry_args) | ||||||
|  |         err = stderr.getvalue() | ||||||
|  |         self.assertRegex(err, "Image 'image'.*missing bintools.*: openssl") | ||||||
|  | 
 | ||||||
|  |     def testPackTiSecureROM(self): | ||||||
|  |         """Test that a ROM image with a TI secured binary can be created""" | ||||||
|  |         keyfile = self.TestFile('key.key') | ||||||
|  |         entry_args = { | ||||||
|  |             'keyfile': keyfile, | ||||||
|  |         } | ||||||
|  |         data = self._DoReadFileDtb('280_ti_secure_rom.dts', | ||||||
|  |                                 entry_args=entry_args)[0] | ||||||
|  |         data_a = self._DoReadFileDtb('288_ti_secure_rom_a.dts', | ||||||
|  |                                 entry_args=entry_args)[0] | ||||||
|  |         data_b = self._DoReadFileDtb('289_ti_secure_rom_b.dts', | ||||||
|  |                                 entry_args=entry_args)[0] | ||||||
|  |         self.assertGreater(len(data), len(TI_UNSECURE_DATA)) | ||||||
|  |         self.assertGreater(len(data_a), len(TI_UNSECURE_DATA)) | ||||||
|  |         self.assertGreater(len(data_b), len(TI_UNSECURE_DATA)) | ||||||
|  | 
 | ||||||
|  |     def testPackTiSecureROMCombined(self): | ||||||
|  |         """Test that a ROM image with a TI secured binary can be created""" | ||||||
|  |         keyfile = self.TestFile('key.key') | ||||||
|  |         entry_args = { | ||||||
|  |             'keyfile': keyfile, | ||||||
|  |         } | ||||||
|  |         data = self._DoReadFileDtb('281_ti_secure_rom_combined.dts', | ||||||
|  |                                 entry_args=entry_args)[0] | ||||||
|  |         self.assertGreater(len(data), len(TI_UNSECURE_DATA)) | ||||||
|  | 
 | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|     unittest.main() |     unittest.main() | ||||||
|  |  | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0+ | ||||||
|  | 
 | ||||||
|  | /dts-v1/; | ||||||
|  | 
 | ||||||
|  | / { | ||||||
|  | 	#address-cells = <1>; | ||||||
|  | 	#size-cells = <1>; | ||||||
|  | 
 | ||||||
|  | 	binman { | ||||||
|  | 		ti-secure { | ||||||
|  | 			content = <&unsecure_binary>; | ||||||
|  | 		}; | ||||||
|  | 		unsecure_binary: blob-ext { | ||||||
|  | 			filename = "ti_unsecure.bin"; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0+ | ||||||
|  | 
 | ||||||
|  | /dts-v1/; | ||||||
|  | 
 | ||||||
|  | / { | ||||||
|  | 	#address-cells = <1>; | ||||||
|  | 	#size-cells = <1>; | ||||||
|  | 
 | ||||||
|  | 	binman { | ||||||
|  | 		ti-secure-rom { | ||||||
|  | 			content = <&unsecure_binary>; | ||||||
|  | 		}; | ||||||
|  | 		unsecure_binary: blob-ext { | ||||||
|  | 			filename = "ti_unsecure.bin"; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  | @ -0,0 +1,25 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0+ | ||||||
|  | 
 | ||||||
|  | /dts-v1/; | ||||||
|  | 
 | ||||||
|  | / { | ||||||
|  | 	#address-cells = <1>; | ||||||
|  | 	#size-cells = <1>; | ||||||
|  | 
 | ||||||
|  | 	binman { | ||||||
|  | 		ti-secure-rom { | ||||||
|  | 			content = <&unsecure_binary>; | ||||||
|  | 			content-sbl = <&unsecure_binary>; | ||||||
|  | 			content-sysfw = <&unsecure_binary>; | ||||||
|  | 			content-sysfw-data = <&unsecure_binary>; | ||||||
|  | 			content-sysfw-inner-cert = <&unsecure_binary>; | ||||||
|  | 			content-dm-data = <&unsecure_binary>; | ||||||
|  | 			combined; | ||||||
|  | 			sysfw-inner-cert; | ||||||
|  | 			dm-data; | ||||||
|  | 		}; | ||||||
|  | 		unsecure_binary: blob-ext { | ||||||
|  | 			filename = "ti_unsecure.bin"; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0+ | ||||||
|  | 
 | ||||||
|  | /dts-v1/; | ||||||
|  | 
 | ||||||
|  | / { | ||||||
|  | 	#address-cells = <1>; | ||||||
|  | 	#size-cells = <1>; | ||||||
|  | 
 | ||||||
|  | 	binman { | ||||||
|  | 		ti-secure-rom { | ||||||
|  | 			content = <&unsecure_binary>; | ||||||
|  | 			core = "secure"; | ||||||
|  | 			countersign; | ||||||
|  | 		}; | ||||||
|  | 		unsecure_binary: blob-ext { | ||||||
|  | 			filename = "ti_unsecure.bin"; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0+ | ||||||
|  | 
 | ||||||
|  | /dts-v1/; | ||||||
|  | 
 | ||||||
|  | / { | ||||||
|  | 	#address-cells = <1>; | ||||||
|  | 	#size-cells = <1>; | ||||||
|  | 
 | ||||||
|  | 	binman { | ||||||
|  | 		ti-secure-rom { | ||||||
|  | 			content = <&unsecure_binary>; | ||||||
|  | 			core = "public"; | ||||||
|  | 		}; | ||||||
|  | 		unsecure_binary: blob-ext { | ||||||
|  | 			filename = "ti_unsecure.bin"; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
		Loading…
	
		Reference in New Issue