1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2019, Linaro Limited
3 # Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
5 # U-Boot UEFI: Signed Image Authentication Test
8 This test verifies image authentication for signed images.
14 @pytest.mark.boardspec('sandbox')
15 @pytest.mark.buildconfigspec('efi_secure_boot')
16 @pytest.mark.buildconfigspec('cmd_efidebug')
17 @pytest.mark.buildconfigspec('cmd_fat')
18 @pytest.mark.buildconfigspec('cmd_nvedit_efi')
20 class TestEfiSignedImage(object):
21 def test_efi_signed_image_auth1(self, u_boot_console, efi_boot_env):
23 Test Case 1 - Secure boot is not in force
25 u_boot_console.restart_uboot()
26 disk_img = efi_boot_env
27 with u_boot_console.log.section('Test Case 1a'):
28 # Test Case 1a, run signed image if no PK
29 output = u_boot_console.run_command_list([
30 'host bind 0 %s' % disk_img,
31 'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld.efi.signed -s ""',
32 'efidebug boot next 1',
34 assert 'Hello, world!' in ''.join(output)
36 with u_boot_console.log.section('Test Case 1b'):
37 # Test Case 1b, run unsigned image if no PK
38 output = u_boot_console.run_command_list([
39 'efidebug boot add -b 2 HELLO2 host 0:1 /helloworld.efi -s ""',
40 'efidebug boot next 2',
42 assert 'Hello, world!' in ''.join(output)
44 def test_efi_signed_image_auth2(self, u_boot_console, efi_boot_env):
46 Test Case 2 - Secure boot is in force,
47 authenticated by db (TEST_db certificate in db)
49 u_boot_console.restart_uboot()
50 disk_img = efi_boot_env
51 with u_boot_console.log.section('Test Case 2a'):
52 # Test Case 2a, db is not yet installed
53 output = u_boot_console.run_command_list([
54 'host bind 0 %s' % disk_img,
55 'fatload host 0:1 4000000 KEK.auth',
56 'setenv -e -nv -bs -rt -at -i 4000000:$filesize KEK',
57 'fatload host 0:1 4000000 PK.auth',
58 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
59 assert 'Failed to set EFI variable' not in ''.join(output)
60 output = u_boot_console.run_command_list([
61 'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld.efi.signed -s ""',
62 'efidebug boot next 1',
63 'efidebug test bootmgr'])
64 assert('\'HELLO1\' failed' in ''.join(output))
65 assert('efi_start_image() returned: 26' in ''.join(output))
66 output = u_boot_console.run_command_list([
67 'efidebug boot add -b 2 HELLO2 host 0:1 /helloworld.efi -s ""',
68 'efidebug boot next 2',
69 'efidebug test bootmgr'])
70 assert '\'HELLO2\' failed' in ''.join(output)
71 assert 'efi_start_image() returned: 26' in ''.join(output)
73 with u_boot_console.log.section('Test Case 2b'):
74 # Test Case 2b, authenticated by db
75 output = u_boot_console.run_command_list([
76 'fatload host 0:1 4000000 db.auth',
77 'setenv -e -nv -bs -rt -at -i 4000000:$filesize db'])
78 assert 'Failed to set EFI variable' not in ''.join(output)
79 output = u_boot_console.run_command_list([
80 'efidebug boot next 2',
81 'efidebug test bootmgr'])
82 assert '\'HELLO2\' failed' in ''.join(output)
83 assert 'efi_start_image() returned: 26' in ''.join(output)
84 output = u_boot_console.run_command_list([
85 'efidebug boot next 1',
87 assert 'Hello, world!' in ''.join(output)
89 def test_efi_signed_image_auth3(self, u_boot_console, efi_boot_env):
91 Test Case 3 - rejected by dbx (TEST_db certificate in dbx)
93 u_boot_console.restart_uboot()
94 disk_img = efi_boot_env
95 with u_boot_console.log.section('Test Case 3a'):
96 # Test Case 3a, rejected by dbx
97 output = u_boot_console.run_command_list([
98 'host bind 0 %s' % disk_img,
99 'fatload host 0:1 4000000 db.auth',
100 'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx',
101 'fatload host 0:1 4000000 KEK.auth',
102 'setenv -e -nv -bs -rt -at -i 4000000:$filesize KEK',
103 'fatload host 0:1 4000000 PK.auth',
104 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
105 assert 'Failed to set EFI variable' not in ''.join(output)
106 output = u_boot_console.run_command_list([
107 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed -s ""',
108 'efidebug boot next 1',
109 'efidebug test bootmgr'])
110 assert '\'HELLO\' failed' in ''.join(output)
111 assert 'efi_start_image() returned: 26' in ''.join(output)
113 with u_boot_console.log.section('Test Case 3b'):
114 # Test Case 3b, rejected by dbx even if db allows
115 output = u_boot_console.run_command_list([
116 'fatload host 0:1 4000000 db.auth',
117 'setenv -e -nv -bs -rt -at -i 4000000:$filesize db'])
118 assert 'Failed to set EFI variable' not in ''.join(output)
119 output = u_boot_console.run_command_list([
120 'efidebug boot next 1',
121 'efidebug test bootmgr'])
122 assert '\'HELLO\' failed' in ''.join(output)
123 assert 'efi_start_image() returned: 26' in ''.join(output)
125 def test_efi_signed_image_auth4(self, u_boot_console, efi_boot_env):
127 Test Case 4 - revoked by dbx (digest of TEST_db certificate in dbx)
129 u_boot_console.restart_uboot()
130 disk_img = efi_boot_env
131 with u_boot_console.log.section('Test Case 4'):
132 # Test Case 4, rejected by dbx
133 output = u_boot_console.run_command_list([
134 'host bind 0 %s' % disk_img,
135 'fatload host 0:1 4000000 dbx_hash.auth',
136 'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx',
137 'fatload host 0:1 4000000 db.auth',
138 'setenv -e -nv -bs -rt -at -i 4000000:$filesize db',
139 'fatload host 0:1 4000000 KEK.auth',
140 'setenv -e -nv -bs -rt -at -i 4000000:$filesize KEK',
141 'fatload host 0:1 4000000 PK.auth',
142 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
143 assert 'Failed to set EFI variable' not in ''.join(output)
144 output = u_boot_console.run_command_list([
145 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed -s ""',
146 'efidebug boot next 1',
147 'efidebug test bootmgr'])
148 assert '\'HELLO\' failed' in ''.join(output)
149 assert 'efi_start_image() returned: 26' in ''.join(output)
151 def test_efi_signed_image_auth5(self, u_boot_console, efi_boot_env):
153 Test Case 5 - multiple signatures
154 one signed with TEST_db, and
155 one signed with TEST_db1
157 u_boot_console.restart_uboot()
158 disk_img = efi_boot_env
159 with u_boot_console.log.section('Test Case 5a'):
160 # Test Case 5a, authenticated even if only one of signatures
162 output = u_boot_console.run_command_list([
163 'host bind 0 %s' % disk_img,
164 'fatload host 0:1 4000000 db.auth',
165 'setenv -e -nv -bs -rt -at -i 4000000:$filesize db',
166 'fatload host 0:1 4000000 KEK.auth',
167 'setenv -e -nv -bs -rt -at -i 4000000:$filesize KEK',
168 'fatload host 0:1 4000000 PK.auth',
169 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
170 assert 'Failed to set EFI variable' not in ''.join(output)
171 output = u_boot_console.run_command_list([
172 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed_2sigs -s ""',
173 'efidebug boot next 1',
174 'efidebug test bootmgr'])
175 assert 'Hello, world!' in ''.join(output)
177 with u_boot_console.log.section('Test Case 5b'):
178 # Test Case 5b, authenticated if both signatures are verified
179 output = u_boot_console.run_command_list([
180 'fatload host 0:1 4000000 db1.auth',
181 'setenv -e -nv -bs -rt -at -a -i 4000000:$filesize db'])
182 assert 'Failed to set EFI variable' not in ''.join(output)
183 output = u_boot_console.run_command_list([
184 'efidebug boot next 1',
185 'efidebug test bootmgr'])
186 assert 'Hello, world!' in ''.join(output)
188 with u_boot_console.log.section('Test Case 5c'):
189 # Test Case 5c, rejected if one of signatures (digest of
190 # certificate) is revoked
191 output = u_boot_console.run_command_list([
192 'fatload host 0:1 4000000 dbx_hash.auth',
193 'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx'])
194 assert 'Failed to set EFI variable' not in ''.join(output)
195 output = u_boot_console.run_command_list([
196 'efidebug boot next 1',
197 'efidebug test bootmgr'])
198 assert '\'HELLO\' failed' in ''.join(output)
199 assert 'efi_start_image() returned: 26' in ''.join(output)
201 with u_boot_console.log.section('Test Case 5d'):
202 # Test Case 5d, rejected if both of signatures are revoked
203 output = u_boot_console.run_command_list([
204 'fatload host 0:1 4000000 dbx_hash1.auth',
205 'setenv -e -nv -bs -rt -at -a -i 4000000:$filesize dbx'])
206 assert 'Failed to set EFI variable' not in ''.join(output)
207 output = u_boot_console.run_command_list([
208 'efidebug boot next 1',
209 'efidebug test bootmgr'])
210 assert '\'HELLO\' failed' in ''.join(output)
211 assert 'efi_start_image() returned: 26' in ''.join(output)
213 # Try rejection in reverse order.
214 u_boot_console.restart_uboot()
215 with u_boot_console.log.section('Test Case 5e'):
216 # Test Case 5e, authenticated even if only one of signatures
217 # is verified. Same as before but reject dbx_hash1.auth only
218 output = u_boot_console.run_command_list([
219 'host bind 0 %s' % disk_img,
220 'fatload host 0:1 4000000 db.auth',
221 'setenv -e -nv -bs -rt -at -i 4000000:$filesize db',
222 'fatload host 0:1 4000000 KEK.auth',
223 'setenv -e -nv -bs -rt -at -i 4000000:$filesize KEK',
224 'fatload host 0:1 4000000 PK.auth',
225 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK',
226 'fatload host 0:1 4000000 db1.auth',
227 'setenv -e -nv -bs -rt -at -a -i 4000000:$filesize db',
228 'fatload host 0:1 4000000 dbx_hash1.auth',
229 'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx'])
230 assert 'Failed to set EFI variable' not in ''.join(output)
231 output = u_boot_console.run_command_list([
232 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed_2sigs -s ""',
233 'efidebug boot next 1',
234 'efidebug test bootmgr'])
235 assert '\'HELLO\' failed' in ''.join(output)
236 assert 'efi_start_image() returned: 26' in ''.join(output)
238 def test_efi_signed_image_auth6(self, u_boot_console, efi_boot_env):
240 Test Case 6 - using digest of signed image in database
242 u_boot_console.restart_uboot()
243 disk_img = efi_boot_env
244 with u_boot_console.log.section('Test Case 6a'):
245 # Test Case 6a, verified by image's digest in db
246 output = u_boot_console.run_command_list([
247 'host bind 0 %s' % disk_img,
248 'fatload host 0:1 4000000 db_hello_signed.auth',
249 'setenv -e -nv -bs -rt -at -i 4000000:$filesize db',
250 'fatload host 0:1 4000000 KEK.auth',
251 'setenv -e -nv -bs -rt -at -i 4000000:$filesize KEK',
252 'fatload host 0:1 4000000 PK.auth',
253 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
254 assert 'Failed to set EFI variable' not in ''.join(output)
255 output = u_boot_console.run_command_list([
256 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed -s ""',
257 'efidebug boot next 1',
259 assert 'Hello, world!' in ''.join(output)
261 with u_boot_console.log.section('Test Case 6b'):
262 # Test Case 6b, rejected by TEST_db certificate in dbx
263 output = u_boot_console.run_command_list([
264 'fatload host 0:1 4000000 dbx_db.auth',
265 'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx'])
266 assert 'Failed to set EFI variable' not in ''.join(output)
267 output = u_boot_console.run_command_list([
268 'efidebug boot next 1',
269 'efidebug test bootmgr'])
270 assert '\'HELLO\' failed' in ''.join(output)
271 assert 'efi_start_image() returned: 26' in ''.join(output)
273 with u_boot_console.log.section('Test Case 6c'):
274 # Test Case 6c, rejected by image's digest in dbx
275 output = u_boot_console.run_command_list([
276 'fatload host 0:1 4000000 db.auth',
277 'setenv -e -nv -bs -rt -at -i 4000000:$filesize db',
278 'fatload host 0:1 4000000 dbx_hello_signed.auth',
279 'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx'])
280 assert 'Failed to set EFI variable' not in ''.join(output)
281 output = u_boot_console.run_command_list([
282 'efidebug boot next 1',
283 'efidebug test bootmgr'])
284 assert '\'HELLO\' failed' in ''.join(output)
285 assert 'efi_start_image() returned: 26' in ''.join(output)
287 def test_efi_signed_image_auth7(self, u_boot_console, efi_boot_env):
289 Test Case 7 - Reject images based on the sha384/512 of their x509 cert
291 # sha384 of an x509 cert in dbx
292 u_boot_console.restart_uboot()
293 disk_img = efi_boot_env
294 with u_boot_console.log.section('Test Case 7a'):
295 output = u_boot_console.run_command_list([
296 'host bind 0 %s' % disk_img,
297 'fatload host 0:1 4000000 db.auth',
298 'setenv -e -nv -bs -rt -at -i 4000000:$filesize db',
299 'fatload host 0:1 4000000 KEK.auth',
300 'setenv -e -nv -bs -rt -at -i 4000000:$filesize KEK',
301 'fatload host 0:1 4000000 PK.auth',
302 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK',
303 'fatload host 0:1 4000000 db1.auth',
304 'setenv -e -nv -bs -rt -at -a -i 4000000:$filesize db',
305 'fatload host 0:1 4000000 dbx_hash384.auth',
306 'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx'])
307 assert 'Failed to set EFI variable' not in ''.join(output)
308 output = u_boot_console.run_command_list([
309 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed_2sigs -s ""',
310 'efidebug boot next 1',
311 'efidebug test bootmgr'])
312 assert '\'HELLO\' failed' in ''.join(output)
313 assert 'efi_start_image() returned: 26' in ''.join(output)
315 # sha512 of an x509 cert in dbx
316 u_boot_console.restart_uboot()
317 with u_boot_console.log.section('Test Case 7b'):
318 output = u_boot_console.run_command_list([
319 'host bind 0 %s' % disk_img,
320 'fatload host 0:1 4000000 db.auth',
321 'setenv -e -nv -bs -rt -at -i 4000000:$filesize db',
322 'fatload host 0:1 4000000 KEK.auth',
323 'setenv -e -nv -bs -rt -at -i 4000000:$filesize KEK',
324 'fatload host 0:1 4000000 PK.auth',
325 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK',
326 'fatload host 0:1 4000000 db1.auth',
327 'setenv -e -nv -bs -rt -at -a -i 4000000:$filesize db',
328 'fatload host 0:1 4000000 dbx_hash512.auth',
329 'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx'])
330 assert 'Failed to set EFI variable' not in ''.join(output)
331 output = u_boot_console.run_command_list([
332 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed_2sigs -s ""',
333 'efidebug boot next 1',
334 'efidebug test bootmgr'])
335 assert '\'HELLO\' failed' in ''.join(output)
336 assert 'efi_start_image() returned: 26' in ''.join(output)
338 def test_efi_signed_image_auth8(self, u_boot_console, efi_boot_env):
340 Test Case 8 - Secure boot is in force,
341 Same as Test Case 2 but the image binary to be loaded
342 was willfully modified (forged)
345 u_boot_console.restart_uboot()
346 disk_img = efi_boot_env
347 with u_boot_console.log.section('Test Case 8a'):
348 # Test Case 8a, Secure boot is not yet forced
349 output = u_boot_console.run_command_list([
350 'host bind 0 %s' % disk_img,
351 'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld_forged.efi.signed -s ""',
352 'efidebug boot next 1',
353 'efidebug test bootmgr'])
354 assert('hELLO, world!' in ''.join(output))
356 with u_boot_console.log.section('Test Case 8b'):
357 # Test Case 8b, Install signature database and verify the image
358 output = u_boot_console.run_command_list([
359 'fatload host 0:1 4000000 db.auth',
360 'setenv -e -nv -bs -rt -at -i 4000000:$filesize db',
361 'fatload host 0:1 4000000 KEK.auth',
362 'setenv -e -nv -bs -rt -at -i 4000000:$filesize KEK',
363 'fatload host 0:1 4000000 PK.auth',
364 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
365 assert 'Failed to set EFI variable' not in ''.join(output)
366 output = u_boot_console.run_command_list([
367 'efidebug boot next 1',
368 'efidebug test bootmgr'])
369 assert(not 'hELLO, world!' in ''.join(output))
370 assert('\'HELLO1\' failed' in ''.join(output))
371 assert('efi_start_image() returned: 26' in ''.join(output))