mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-28 22:13:08 +00:00
78144826bb
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. Reviewed-by: Simon Glass <sjg@chromium.org> [vigneshr@ti.com: fixed inconsist cert generation by multiple packing] Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Signed-off-by: Neha Malcom Francis <n-francis@ti.com>
338 lines
11 KiB
Python
338 lines
11 KiB
Python
# SPDX-License-Identifier: GPL-2.0+
|
|
# Copyright 2022 Google LLC
|
|
#
|
|
"""Bintool implementation for openssl
|
|
|
|
openssl provides a number of features useful for signing images
|
|
|
|
Documentation is at https://www.coreboot.org/CBFS
|
|
|
|
Source code is at https://www.openssl.org/
|
|
"""
|
|
|
|
import hashlib
|
|
|
|
from binman import bintool
|
|
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):
|
|
"""openssl tool
|
|
|
|
This bintool supports creating new openssl certificates.
|
|
|
|
It also supports fetching a binary openssl
|
|
|
|
Documentation about openssl is at https://www.openssl.org/
|
|
"""
|
|
def __init__(self, name):
|
|
super().__init__(
|
|
name, 'openssl cryptography toolkit',
|
|
version_regex=r'OpenSSL (.*) \(', version_args='version')
|
|
|
|
def x509_cert(self, cert_fname, input_fname, key_fname, cn, revision,
|
|
config_fname):
|
|
"""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
|
|
cn (str): Common name
|
|
revision (int): Revision number
|
|
config_fname (str): Filename to write fconfig into
|
|
|
|
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 ]
|
|
CN = {cert_fname}
|
|
|
|
[ 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
|
|
|
|
[ swrv ]
|
|
swrv = INTEGER:{revision}
|
|
|
|
[ sysfw_image_integrity ]
|
|
shaType = OID:2.16.840.1.101.3.4.2.3
|
|
shaValue = FORMAT:HEX,OCT:{hashval}
|
|
imageSize = INTEGER:{len(indata)}
|
|
''', 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_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):
|
|
"""Fetch handler for openssl
|
|
|
|
This installs the openssl package using the apt utility.
|
|
|
|
Args:
|
|
method (FETCH_...): Method to use
|
|
|
|
Returns:
|
|
True if the file was fetched and now installed, None if a method
|
|
other than FETCH_BIN was requested
|
|
|
|
Raises:
|
|
Valuerror: Fetching could not be completed
|
|
"""
|
|
if method != bintool.FETCH_BIN:
|
|
return None
|
|
return self.apt_install('openssl')
|