blob: c6df64c5316d53735fb147858b24185096254ec2 [file] [log] [blame]
Simon Glassc3fe97f2023-03-02 17:02:45 -07001# SPDX-License-Identifier: GPL-2.0+
2# Copyright 2022 Google LLC
3#
4"""Bintool implementation for openssl
5
6openssl provides a number of features useful for signing images
7
8Documentation is at https://www.coreboot.org/CBFS
9
10Source code is at https://www.openssl.org/
11"""
12
13import hashlib
14
15from binman import bintool
16from u_boot_pylib import tools
17
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +053018
19VALID_SHAS = [256, 384, 512, 224]
20SHA_OIDS = {256:'2.16.840.1.101.3.4.2.1',
21 384:'2.16.840.1.101.3.4.2.2',
22 512:'2.16.840.1.101.3.4.2.3',
23 224:'2.16.840.1.101.3.4.2.4'}
24
Simon Glassc3fe97f2023-03-02 17:02:45 -070025class Bintoolopenssl(bintool.Bintool):
26 """openssl tool
27
28 This bintool supports creating new openssl certificates.
29
30 It also supports fetching a binary openssl
31
32 Documentation about openssl is at https://www.openssl.org/
33 """
34 def __init__(self, name):
35 super().__init__(
36 name, 'openssl cryptography toolkit',
37 version_regex=r'OpenSSL (.*) \(', version_args='version')
38
39 def x509_cert(self, cert_fname, input_fname, key_fname, cn, revision,
40 config_fname):
41 """Create a certificate
42
43 Args:
44 cert_fname (str): Filename of certificate to create
45 input_fname (str): Filename containing data to sign
46 key_fname (str): Filename of .pem file
47 cn (str): Common name
48 revision (int): Revision number
49 config_fname (str): Filename to write fconfig into
50
51 Returns:
52 str: Tool output
53 """
54 indata = tools.read_file(input_fname)
55 hashval = hashlib.sha512(indata).hexdigest()
56 with open(config_fname, 'w', encoding='utf-8') as outf:
57 print(f'''[ req ]
58distinguished_name = req_distinguished_name
59x509_extensions = v3_ca
60prompt = no
61dirstring_type = nobmp
62
63[ req_distinguished_name ]
64CN = {cert_fname}
65
66[ v3_ca ]
67basicConstraints = CA:true
681.3.6.1.4.1.294.1.3 = ASN1:SEQUENCE:swrv
691.3.6.1.4.1.294.1.34 = ASN1:SEQUENCE:sysfw_image_integrity
70
71[ swrv ]
72swrv = INTEGER:{revision}
73
74[ sysfw_image_integrity ]
75shaType = OID:2.16.840.1.101.3.4.2.3
76shaValue = FORMAT:HEX,OCT:{hashval}
77imageSize = INTEGER:{len(indata)}
78''', file=outf)
79 args = ['req', '-new', '-x509', '-key', key_fname, '-nodes',
80 '-outform', 'DER', '-out', cert_fname, '-config', config_fname,
81 '-sha512']
82 return self.run_cmd(*args)
83
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +053084 def x509_cert_sysfw(self, cert_fname, input_fname, key_fname, sw_rev,
Manorit Chawdhry48a00602023-12-29 16:16:26 +053085 config_fname, req_dist_name_dict, firewall_cert_data):
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +053086 """Create a certificate to be booted by system firmware
87
88 Args:
89 cert_fname (str): Filename of certificate to create
90 input_fname (str): Filename containing data to sign
91 key_fname (str): Filename of .pem file
92 sw_rev (int): Software revision
93 config_fname (str): Filename to write fconfig into
94 req_dist_name_dict (dict): Dictionary containing key-value pairs of
95 req_distinguished_name section extensions, must contain extensions for
96 C, ST, L, O, OU, CN and emailAddress
Manorit Chawdhry48a00602023-12-29 16:16:26 +053097 firewall_cert_data (dict):
98 - auth_in_place (int): The Priv ID for copying as the
99 specific host in firewall protected region
100 - num_firewalls (int): The number of firewalls in the
101 extended certificate
102 - certificate (str): Extended firewall certificate with
103 the information for the firewall configurations.
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +0530104
105 Returns:
106 str: Tool output
107 """
108 indata = tools.read_file(input_fname)
109 hashval = hashlib.sha512(indata).hexdigest()
110 with open(config_fname, 'w', encoding='utf-8') as outf:
111 print(f'''[ req ]
112distinguished_name = req_distinguished_name
113x509_extensions = v3_ca
114prompt = no
115dirstring_type = nobmp
116
117[ req_distinguished_name ]
118C = {req_dist_name_dict['C']}
119ST = {req_dist_name_dict['ST']}
120L = {req_dist_name_dict['L']}
121O = {req_dist_name_dict['O']}
122OU = {req_dist_name_dict['OU']}
123CN = {req_dist_name_dict['CN']}
124emailAddress = {req_dist_name_dict['emailAddress']}
125
126[ v3_ca ]
127basicConstraints = CA:true
1281.3.6.1.4.1.294.1.3 = ASN1:SEQUENCE:swrv
1291.3.6.1.4.1.294.1.34 = ASN1:SEQUENCE:sysfw_image_integrity
1301.3.6.1.4.1.294.1.35 = ASN1:SEQUENCE:sysfw_image_load
Manorit Chawdhry48a00602023-12-29 16:16:26 +05301311.3.6.1.4.1.294.1.37 = ASN1:SEQUENCE:firewall
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +0530132
133[ swrv ]
134swrv = INTEGER:{sw_rev}
135
136[ sysfw_image_integrity ]
137shaType = OID:2.16.840.1.101.3.4.2.3
138shaValue = FORMAT:HEX,OCT:{hashval}
139imageSize = INTEGER:{len(indata)}
140
141[ sysfw_image_load ]
142destAddr = FORMAT:HEX,OCT:00000000
Manorit Chawdhry48a00602023-12-29 16:16:26 +0530143authInPlace = INTEGER:{hex(firewall_cert_data['auth_in_place'])}
144
145[ firewall ]
146numFirewallRegions = INTEGER:{firewall_cert_data['num_firewalls']}
147{firewall_cert_data['certificate']}
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +0530148''', file=outf)
149 args = ['req', '-new', '-x509', '-key', key_fname, '-nodes',
150 '-outform', 'DER', '-out', cert_fname, '-config', config_fname,
151 '-sha512']
152 return self.run_cmd(*args)
153
154 def x509_cert_rom(self, cert_fname, input_fname, key_fname, sw_rev,
155 config_fname, req_dist_name_dict, cert_type, bootcore,
156 bootcore_opts, load_addr, sha):
157 """Create a certificate
158
159 Args:
160 cert_fname (str): Filename of certificate to create
161 input_fname (str): Filename containing data to sign
162 key_fname (str): Filename of .pem file
163 sw_rev (int): Software revision
164 config_fname (str): Filename to write fconfig into
165 req_dist_name_dict (dict): Dictionary containing key-value pairs of
166 req_distinguished_name section extensions, must contain extensions for
167 C, ST, L, O, OU, CN and emailAddress
168 cert_type (int): Certification type
169 bootcore (int): Booting core
Neha Malcom Francis14e93422023-10-23 13:31:02 +0530170 bootcore_opts(int): Booting core option, lockstep (0) or split (2) mode
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +0530171 load_addr (int): Load address of image
172 sha (int): Hash function
173
174 Returns:
175 str: Tool output
176 """
177 indata = tools.read_file(input_fname)
178 hashval = hashlib.sha512(indata).hexdigest()
179 with open(config_fname, 'w', encoding='utf-8') as outf:
180 print(f'''
181[ req ]
182 distinguished_name = req_distinguished_name
183 x509_extensions = v3_ca
184 prompt = no
185 dirstring_type = nobmp
186
187 [ req_distinguished_name ]
188C = {req_dist_name_dict['C']}
189ST = {req_dist_name_dict['ST']}
190L = {req_dist_name_dict['L']}
191O = {req_dist_name_dict['O']}
192OU = {req_dist_name_dict['OU']}
193CN = {req_dist_name_dict['CN']}
194emailAddress = {req_dist_name_dict['emailAddress']}
195
196 [ v3_ca ]
197 basicConstraints = CA:true
198 1.3.6.1.4.1.294.1.1 = ASN1:SEQUENCE:boot_seq
199 1.3.6.1.4.1.294.1.2 = ASN1:SEQUENCE:image_integrity
200 1.3.6.1.4.1.294.1.3 = ASN1:SEQUENCE:swrv
201# 1.3.6.1.4.1.294.1.4 = ASN1:SEQUENCE:encryption
202 1.3.6.1.4.1.294.1.8 = ASN1:SEQUENCE:debug
203
204 [ boot_seq ]
205 certType = INTEGER:{cert_type}
206 bootCore = INTEGER:{bootcore}
207 bootCoreOpts = INTEGER:{bootcore_opts}
208 destAddr = FORMAT:HEX,OCT:{load_addr:08x}
209 imageSize = INTEGER:{len(indata)}
210
211 [ image_integrity ]
212 shaType = OID:{SHA_OIDS[sha]}
213 shaValue = FORMAT:HEX,OCT:{hashval}
214
215 [ swrv ]
216 swrv = INTEGER:{sw_rev}
217
218# [ encryption ]
219# initalVector = FORMAT:HEX,OCT:TEST_IMAGE_ENC_IV
220# randomString = FORMAT:HEX,OCT:TEST_IMAGE_ENC_RS
221# iterationCnt = INTEGER:TEST_IMAGE_KEY_DERIVE_INDEX
222# salt = FORMAT:HEX,OCT:TEST_IMAGE_KEY_DERIVE_SALT
223
224 [ debug ]
225 debugUID = FORMAT:HEX,OCT:0000000000000000000000000000000000000000000000000000000000000000
226 debugType = INTEGER:4
227 coreDbgEn = INTEGER:0
228 coreDbgSecEn = INTEGER:0
229''', file=outf)
230 args = ['req', '-new', '-x509', '-key', key_fname, '-nodes',
231 '-outform', 'DER', '-out', cert_fname, '-config', config_fname,
232 '-sha512']
233 return self.run_cmd(*args)
234
235 def x509_cert_rom_combined(self, cert_fname, input_fname, key_fname, sw_rev,
236 config_fname, req_dist_name_dict, load_addr, sha, total_size, num_comps,
237 sysfw_inner_cert_ext_boot_sequence_string, dm_data_ext_boot_sequence_string,
238 imagesize_sbl, hashval_sbl, load_addr_sysfw, imagesize_sysfw,
239 hashval_sysfw, load_addr_sysfw_data, imagesize_sysfw_data,
240 hashval_sysfw_data, sysfw_inner_cert_ext_boot_block,
Neha Malcom Francis14e93422023-10-23 13:31:02 +0530241 dm_data_ext_boot_block, bootcore_opts):
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +0530242 """Create a certificate
243
244 Args:
245 cert_fname (str): Filename of certificate to create
246 input_fname (str): Filename containing data to sign
247 key_fname (str): Filename of .pem file
248 sw_rev (int): Software revision
249 config_fname (str): Filename to write fconfig into
250 req_dist_name_dict (dict): Dictionary containing key-value pairs of
251 req_distinguished_name section extensions, must contain extensions for
252 C, ST, L, O, OU, CN and emailAddress
253 cert_type (int): Certification type
254 bootcore (int): Booting core
255 load_addr (int): Load address of image
256 sha (int): Hash function
Neha Malcom Francis14e93422023-10-23 13:31:02 +0530257 bootcore_opts (int): Booting core option, lockstep (0) or split (2) mode
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +0530258
259 Returns:
260 str: Tool output
261 """
262 indata = tools.read_file(input_fname)
263 hashval = hashlib.sha512(indata).hexdigest()
264 sha_type = SHA_OIDS[sha]
265 with open(config_fname, 'w', encoding='utf-8') as outf:
266 print(f'''
267[ req ]
268distinguished_name = req_distinguished_name
269x509_extensions = v3_ca
270prompt = no
271dirstring_type = nobmp
272
273[ req_distinguished_name ]
274C = {req_dist_name_dict['C']}
275ST = {req_dist_name_dict['ST']}
276L = {req_dist_name_dict['L']}
277O = {req_dist_name_dict['O']}
278OU = {req_dist_name_dict['OU']}
279CN = {req_dist_name_dict['CN']}
280emailAddress = {req_dist_name_dict['emailAddress']}
281
282[ v3_ca ]
283basicConstraints = CA:true
2841.3.6.1.4.1.294.1.3=ASN1:SEQUENCE:swrv
2851.3.6.1.4.1.294.1.9=ASN1:SEQUENCE:ext_boot_info
Manorit Chawdhry8cfcc9b2024-03-26 13:37:06 +05302861.3.6.1.4.1.294.1.8=ASN1:SEQUENCE:debug
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +0530287
288[swrv]
289swrv=INTEGER:{sw_rev}
290
291[ext_boot_info]
292extImgSize=INTEGER:{total_size}
293numComp=INTEGER:{num_comps}
294sbl=SEQUENCE:sbl
295sysfw=SEQUENCE:sysfw
296sysfw_data=SEQUENCE:sysfw_data
297{sysfw_inner_cert_ext_boot_sequence_string}
298{dm_data_ext_boot_sequence_string}
299
300[sbl]
301compType = INTEGER:1
302bootCore = INTEGER:16
Neha Malcom Francis14e93422023-10-23 13:31:02 +0530303compOpts = INTEGER:{bootcore_opts}
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +0530304destAddr = FORMAT:HEX,OCT:{load_addr:08x}
305compSize = INTEGER:{imagesize_sbl}
306shaType = OID:{sha_type}
307shaValue = FORMAT:HEX,OCT:{hashval_sbl}
308
309[sysfw]
310compType = INTEGER:2
311bootCore = INTEGER:0
312compOpts = INTEGER:0
313destAddr = FORMAT:HEX,OCT:{load_addr_sysfw:08x}
314compSize = INTEGER:{imagesize_sysfw}
315shaType = OID:{sha_type}
316shaValue = FORMAT:HEX,OCT:{hashval_sysfw}
317
318[sysfw_data]
319compType = INTEGER:18
320bootCore = INTEGER:0
321compOpts = INTEGER:0
322destAddr = FORMAT:HEX,OCT:{load_addr_sysfw_data:08x}
323compSize = INTEGER:{imagesize_sysfw_data}
324shaType = OID:{sha_type}
325shaValue = FORMAT:HEX,OCT:{hashval_sysfw_data}
326
Manorit Chawdhry8cfcc9b2024-03-26 13:37:06 +0530327[ debug ]
328debugUID = FORMAT:HEX,OCT:0000000000000000000000000000000000000000000000000000000000000000
329debugType = INTEGER:4
330coreDbgEn = INTEGER:0
331coreDbgSecEn = INTEGER:0
332
Neha Malcom Francis5f5f0a62023-07-22 00:14:25 +0530333{sysfw_inner_cert_ext_boot_block}
334
335{dm_data_ext_boot_block}
336 ''', file=outf)
337 args = ['req', '-new', '-x509', '-key', key_fname, '-nodes',
338 '-outform', 'DER', '-out', cert_fname, '-config', config_fname,
339 '-sha512']
340 return self.run_cmd(*args)
341
Simon Glassc3fe97f2023-03-02 17:02:45 -0700342 def fetch(self, method):
343 """Fetch handler for openssl
344
345 This installs the openssl package using the apt utility.
346
347 Args:
348 method (FETCH_...): Method to use
349
350 Returns:
351 True if the file was fetched and now installed, None if a method
352 other than FETCH_BIN was requested
353
354 Raises:
355 Valuerror: Fetching could not be completed
356 """
357 if method != bintool.FETCH_BIN:
358 return None
359 return self.apt_install('openssl')