From 7254ebed0f5edc1d9fa7f214dbbcaa6c950f4ac1 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 14 Apr 2020 11:51:51 +0900 Subject: [PATCH] efi_loader, pytest: add UEFI secure boot tests (image) Provide test cases for * image authentication for signed images (test_efi_secboot/test_signed.py) * image authentication for unsigned images (test_efi_secboot/test_unsigned.py) Signed-off-by: AKASHI Takahiro --- test/py/tests/test_efi_secboot/test_signed.py | 117 +++++++++++++++++ .../tests/test_efi_secboot/test_unsigned.py | 121 ++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 test/py/tests/test_efi_secboot/test_signed.py create mode 100644 test/py/tests/test_efi_secboot/test_unsigned.py diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py new file mode 100644 index 0000000000..584282b338 --- /dev/null +++ b/test/py/tests/test_efi_secboot/test_signed.py @@ -0,0 +1,117 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2019, Linaro Limited +# Author: AKASHI Takahiro +# +# U-Boot UEFI: Signed Image Authentication Test + +""" +This test verifies image authentication for signed images. +""" + +import pytest +import re +from defs import * + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('efi_secure_boot') +@pytest.mark.buildconfigspec('cmd_efidebug') +@pytest.mark.buildconfigspec('cmd_fat') +@pytest.mark.buildconfigspec('cmd_nvedit_efi') +@pytest.mark.slow +class TestEfiSignedImage(object): + def test_efi_signed_image_auth1(self, u_boot_console, efi_boot_env): + """ + Test Case 1 - authenticated by db + """ + u_boot_console.restart_uboot() + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 1a'): + # Test Case 1a, run signed image if no db/dbx + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""', + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(re.search('Hello, world!', ''.join(output))) + + with u_boot_console.log.section('Test Case 1b'): + # Test Case 1b, run unsigned image if no db/dbx + output = u_boot_console.run_command_list([ + 'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""', + 'efidebug boot next 2', + 'bootefi bootmgr']) + assert(re.search('Hello, world!', ''.join(output))) + + with u_boot_console.log.section('Test Case 1c'): + # Test Case 1c, not authenticated by db + output = u_boot_console.run_command_list([ + 'fatload host 0:1 4000000 db.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db', + 'fatload host 0:1 4000000 KEK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK', + 'fatload host 0:1 4000000 PK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + output = u_boot_console.run_command_list([ + 'efidebug boot next 2', + 'bootefi bootmgr']) + assert(re.search('\'HELLO2\' failed', ''.join(output))) + output = u_boot_console.run_command_list([ + 'efidebug boot next 2', + 'efidebug test bootmgr']) + assert(re.search('efi_start_image[(][)] returned: 26', + ''.join(output))) + assert(not re.search('Hello, world!', ''.join(output))) + + with u_boot_console.log.section('Test Case 1d'): + # Test Case 1d, authenticated by db + output = u_boot_console.run_command_list([ + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(re.search('Hello, world!', ''.join(output))) + + def test_efi_signed_image_auth2(self, u_boot_console, efi_boot_env): + """ + Test Case 2 - rejected by dbx + """ + u_boot_console.restart_uboot() + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 2a'): + # Test Case 2a, rejected by dbx + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatload host 0:1 4000000 db.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx', + 'fatload host 0:1 4000000 KEK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK', + 'fatload host 0:1 4000000 PK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + output = u_boot_console.run_command_list([ + 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""', + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(re.search('\'HELLO\' failed', ''.join(output))) + output = u_boot_console.run_command_list([ + 'efidebug boot next 1', + 'efidebug test bootmgr']) + assert(re.search('efi_start_image[(][)] returned: 26', + ''.join(output))) + assert(not re.search('Hello, world!', ''.join(output))) + + with u_boot_console.log.section('Test Case 2b'): + # Test Case 2b, rejected by dbx even if db allows + output = u_boot_console.run_command_list([ + 'fatload host 0:1 4000000 db.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + output = u_boot_console.run_command_list([ + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(re.search('\'HELLO\' failed', ''.join(output))) + output = u_boot_console.run_command_list([ + 'efidebug boot next 1', + 'efidebug test bootmgr']) + assert(re.search('efi_start_image[(][)] returned: 26', + ''.join(output))) + assert(not re.search('Hello, world!', ''.join(output))) diff --git a/test/py/tests/test_efi_secboot/test_unsigned.py b/test/py/tests/test_efi_secboot/test_unsigned.py new file mode 100644 index 0000000000..22d849afb8 --- /dev/null +++ b/test/py/tests/test_efi_secboot/test_unsigned.py @@ -0,0 +1,121 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2019, Linaro Limited +# Author: AKASHI Takahiro +# +# U-Boot UEFI: Signed Image Authentication Test + +""" +This test verifies image authentication for unsigned images. +""" + +import pytest +import re +from defs import * + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('efi_secure_boot') +@pytest.mark.buildconfigspec('cmd_efidebug') +@pytest.mark.buildconfigspec('cmd_fat') +@pytest.mark.buildconfigspec('cmd_nvedit_efi') +@pytest.mark.slow +class TestEfiUnsignedImage(object): + def test_efi_unsigned_image_auth1(self, u_boot_console, efi_boot_env): + """ + Test Case 1 - rejected when not digest in db or dbx + """ + u_boot_console.restart_uboot() + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 1'): + # Test Case 1 + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatload host 0:1 4000000 KEK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK', + 'fatload host 0:1 4000000 PK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""', + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(re.search('\'HELLO\' failed', ''.join(output))) + output = u_boot_console.run_command_list([ + 'efidebug boot next 1', + 'efidebug test bootmgr']) + assert(re.search('efi_start_image[(][)] returned: 26', + ''.join(output))) + assert(not re.search('Hello, world!', ''.join(output))) + + def test_efi_unsigned_image_auth2(self, u_boot_console, efi_boot_env): + """ + Test Case 2 - authenticated by digest in db + """ + u_boot_console.restart_uboot() + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 2'): + # Test Case 2 + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatload host 0:1 4000000 db_hello.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db', + 'fatload host 0:1 4000000 KEK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK', + 'fatload host 0:1 4000000 PK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""', + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(re.search('Hello, world!', ''.join(output))) + + def test_efi_unsigned_image_auth3(self, u_boot_console, efi_boot_env): + """ + Test Case 3 - rejected by digest in dbx + """ + u_boot_console.restart_uboot() + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 3a'): + # Test Case 3a, rejected by dbx + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatload host 0:1 4000000 db_hello.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx', + 'fatload host 0:1 4000000 KEK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK', + 'fatload host 0:1 4000000 PK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""', + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(re.search('\'HELLO\' failed', ''.join(output))) + output = u_boot_console.run_command_list([ + 'efidebug boot next 1', + 'efidebug test bootmgr']) + assert(re.search('efi_start_image[(][)] returned: 26', + ''.join(output))) + assert(not re.search('Hello, world!', ''.join(output))) + + with u_boot_console.log.section('Test Case 3b'): + # Test Case 3b, rejected by dbx even if db allows + output = u_boot_console.run_command_list([ + 'fatload host 0:1 4000000 db_hello.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""', + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(re.search('\'HELLO\' failed', ''.join(output))) + output = u_boot_console.run_command_list([ + 'efidebug boot next 1', + 'efidebug test bootmgr']) + assert(re.search('efi_start_image[(][)] returned: 26', + ''.join(output))) + assert(not re.search('Hello, world!', ''.join(output))) -- 2.39.5