Prepare v2023.10
[platform/kernel/u-boot.git] / test / py / tests / test_efi_secboot / test_signed.py
1 # SPDX-License-Identifier:      GPL-2.0+
2 # Copyright (c) 2019, Linaro Limited
3 # Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
4 #
5 # U-Boot UEFI: Signed Image Authentication Test
6
7 """
8 This test verifies image authentication for signed images.
9 """
10
11 import pytest
12
13
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')
19 @pytest.mark.slow
20 class TestEfiSignedImage(object):
21     def test_efi_signed_image_auth1(self, u_boot_console, efi_boot_env):
22         """
23         Test Case 1 - Secure boot is not in force
24         """
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',
33                 'bootefi bootmgr'])
34             assert 'Hello, world!' in ''.join(output)
35
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',
41                 'bootefi bootmgr'])
42             assert 'Hello, world!' in ''.join(output)
43
44     def test_efi_signed_image_auth2(self, u_boot_console, efi_boot_env):
45         """
46         Test Case 2 - Secure boot is in force,
47                       authenticated by db (TEST_db certificate in db)
48         """
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)
72
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',
86                 'bootefi bootmgr'])
87             assert 'Hello, world!' in ''.join(output)
88
89     def test_efi_signed_image_auth3(self, u_boot_console, efi_boot_env):
90         """
91         Test Case 3 - rejected by dbx (TEST_db certificate in dbx)
92         """
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)
112
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)
124
125     def test_efi_signed_image_auth4(self, u_boot_console, efi_boot_env):
126         """
127         Test Case 4 - revoked by dbx (digest of TEST_db certificate in dbx)
128         """
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)
150
151     def test_efi_signed_image_auth5(self, u_boot_console, efi_boot_env):
152         """
153         Test Case 5 - multiple signatures
154                         one signed with TEST_db, and
155                         one signed with TEST_db1
156         """
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
161             # is verified
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)
176
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)
187
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)
200
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)
212
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)
237
238     def test_efi_signed_image_auth6(self, u_boot_console, efi_boot_env):
239         """
240         Test Case 6 - using digest of signed image in database
241         """
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',
258                 'bootefi bootmgr'])
259             assert 'Hello, world!' in ''.join(output)
260
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)
272
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)
286
287     def test_efi_signed_image_auth7(self, u_boot_console, efi_boot_env):
288         """
289         Test Case 7 - Reject images based on the sha384/512 of their x509 cert
290         """
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)
314
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)
337
338     def test_efi_signed_image_auth8(self, u_boot_console, efi_boot_env):
339         """
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)
343                       Must be rejected.
344         """
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))
355
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))