| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- # 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')
|