[U-Boot] [PATCH 15/16] efi_loader, pytest: add UEFI secure boot tests (authenticated variables)

AKASHI Takahiro
2019-11-20T02:17:34Z

Heinrich,

On Mon, Nov 18, 2019 at 02:58:26PM +0900, AKASHI Takahiro wrote:
> On Sat, Nov 16, 2019 at 09:28:56PM +0100, Heinrich Schuchardt wrote:
> > On 11/13/19 1:53 AM, AKASHI Takahiro wrote:
> > >Provide a couple of test cases for variable authentication.
> >
> > Please, tell us more in the commit message.
>
> About what?
> I have lots of 'text case' descriptions in *.py files.
>
> > >
> > >Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > >---
> > > .../py/tests/test_efi_secboot/test_authvar.py | 289 ++++++++++++++++++
> > > 1 file changed, 289 insertions(+)
> > > create mode 100644 test/py/tests/test_efi_secboot/test_authvar.py
> > >
> > >diff --git a/test/py/tests/test_efi_secboot/test_authvar.py b/test/py/tests/test_efi_secboot/test_authvar.py
> > >new file mode 100644
> > >index 000000000000..ed18b80084d6
> > >--- /dev/null
> > >+++ b/test/py/tests/test_efi_secboot/test_authvar.py
> > >@@ -0,0 +1,289 @@
> > >+# SPDX-License-Identifier: GPL-2.0+
> > >+# Copyright (c) 2019, Linaro Limited
> > >+# Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > >+#
> > >+# U-Boot UEFI: Variable Authentication Test
> > >+
> > >+"""
> > >+This test verifies variable authentication
> > >+"""
> > >+
> > >+import pytest
> > >+import re
> > >+from defs import *
> > >+
> > >+ at pytest.mark.boardspec('sandbox')
> >
> > Why can't we run this on other architectures?
>
> As you see, we need some data files, most of which contain data for
> signature database variables, to run test cases. Using sandbox
> is the easiest way to minimize hardware requirements.
>
> > The sandbox currently only runs in 64bit mode. This way we might miss
> > errors that only occur on 32bit systems.
>
> Right, but this is not my patch-specific issue.
>
> > >+ at pytest.mark.buildconfigspec('efi_secure_boot')
> > >+ at pytest.mark.buildconfigspec('cmd_fat')
> > >+ at pytest.mark.buildconfigspec('cmd_nvedit_efi')
> > >+ at pytest.mark.slow
> > >+class TestEfiAuthVar(object):
> > >+ def test_efi_var_auth1(self, u_boot_console, efi_boot_env):
> > >+ """
> > >+ Test Case 1 - Install signature database
> > >+ """
> > >+ disk_img = efi_boot_env
> > >+ with u_boot_console.log.section('Test Case 1a'):
> > >+ # Test Case 1a, Initial secure state
> > >+ output = u_boot_console.run_command_list([
> > >+ 'host bind 0 %s' % disk_img,
> > >+ 'printenv -e SecureBoot'])
> > >+ assert(re.search('00000000: 00', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command(
> > >+ 'printenv -e SecureBoot')
> > >+ assert('00000000: 00' in output)
> > >+ output = u_boot_console.run_command(
> > >+ 'printenv -e SetupMode')
> > >+ assert('00000000: 01' in output)
> > >+
> > >+ with u_boot_console.log.section('Test Case 1b'):
> > >+ # Test Case 1b, PK without AUTHENTICATED_WRITE_ACCESS
> > >+ output = u_boot_console.run_command_list([
> > >+ 'host bind 0 %s' % disk_img,
> > >+ 'fatload host 0:1 4000000 PK.auth',
> > >+ 'setenv -e -nv -bs -rt -i 4000000,$filesize PK'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+
> > >+ with u_boot_console.log.section('Test Case 1c'):
> > >+ # Test Case 1c, install PK
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 PK.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
> > >+ 'printenv -e PK'])
> > >+ assert(re.search('PK:', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command(
> > >+ 'printenv -e SecureBoot')
> > >+ assert('00000000: 01' in output)
> > >+ output = u_boot_console.run_command(
> > >+ 'printenv -e SetupMode')
> > >+ assert('00000000: 00' in output)
> > >+
> > >+ with u_boot_console.log.section('Test Case 1d'):
> > >+ # Test Case 1d, db/dbx without KEK
> > >+ 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(re.search('Failed to set EFI variable', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 db.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+
> > >+ with u_boot_console.log.section('Test Case 1e'):
> > >+ # Test Case 1e, install KEK
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 KEK.auth',
> > >+ 'setenv -e -nv -bs -rt -i 4000000,$filesize KEK'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 KEK.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
> > >+ 'printenv -e KEK'])
> > >+ assert(re.search('KEK:', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command(
> > >+ 'printenv -e SecureBoot')
> > >+ assert('00000000: 01' in output)
> > >+
> > >+ with u_boot_console.log.section('Test Case 1f'):
> > >+ # Test Case 1f, install db
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 db.auth',
> > >+ 'setenv -e -nv -bs -rt -i 4000000,$filesize db'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 db.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
> > >+ 'printenv -e -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
> > >+ assert(not re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('db:', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command(
> > >+ 'printenv -e SecureBoot')
> > >+ assert('00000000: 01' in output)
> > >+
> > >+ with u_boot_console.log.section('Test Case 1g'):
> > >+ # Test Case 1g, install dbx
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 db.auth',
> > >+ 'setenv -e -nv -bs -rt -i 4000000,$filesize db'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 db.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
> > >+ 'printenv -e -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
> > >+ assert(not re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('db:', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command(
> > >+ 'printenv -e SecureBoot')
> > >+ assert('00000000: 01' in output)
> > >+
> > >+ def test_efi_var_auth2(self, u_boot_console, efi_boot_env):
> > >+ """
> > >+ Test Case 2 - Update database by overwriting
> > >+ """
> > >+ disk_img = efi_boot_env
> > >+ with u_boot_console.log.section('Test Case 2a'):
> > >+ # Test Case 2a, update without AUTHENTICATED_WRITE_ACCESS
> > >+ output = u_boot_console.run_command_list([
> > >+ 'host bind 0 %s' % disk_img,
> > >+ 'fatload host 0:1 4000000 PK.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
> > >+ 'fatload host 0:1 4000000 KEK.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
> > >+ 'fatload host 0:1 4000000 db.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
> > >+ 'printenv -e -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
> > >+ assert(not re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('db:', ''.join(output)))
> > >+ assert(re.search('DataSize = 0x327', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 db1.auth',
> > >+ 'setenv -e -nv -bs -rt -i 4000000,$filesize db'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+
> > >+ with u_boot_console.log.section('Test Case 2b'):
> > >+ # Test Case 2b, update without correct signature
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 db.esl',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+
> > >+ with u_boot_console.log.section('Test Case 2c'):
> > >+ # Test Case 2c, update with correct signature
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 db1.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
> > >+ 'printenv -e -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
> > >+ assert(not re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('db:', ''.join(output)))
> > >+ assert(re.search('DataSize = 0x329', ''.join(output)))
> > >+
> > >+ def test_efi_var_auth3(self, u_boot_console, efi_boot_env):
> > >+ """
> > >+ Test Case 3 - Append database
> > >+ """
> > >+ disk_img = efi_boot_env
> > >+ with u_boot_console.log.section('Test Case 3a'):
> > >+ # Test Case 3a, update without AUTHENTICATED_WRITE_ACCESS
> > >+ output = u_boot_console.run_command_list([
> > >+ 'host bind 0 %s' % disk_img,
> > >+ 'fatload host 0:1 4000000 PK.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
> > >+ 'fatload host 0:1 4000000 KEK.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
> > >+ 'fatload host 0:1 4000000 db.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
> > >+ 'printenv -e -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
> > >+ assert(not re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('db:', ''.join(output)))
> > >+ assert(re.search('DataSize = 0x327', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 db1.auth',
> > >+ 'setenv -e -nv -bs -rt -a -i 4000000,$filesize db'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+
> > >+ with u_boot_console.log.section('Test Case 3b'):
> > >+ # Test Case 3b, update without correct signature
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 db.esl',
> >
> > Where do find all the files you try to load here?
> >
> > You cannot assume that the sandbox is connected to any special file
> > system while the test is running as there is no buildconfigspec
> > requiring it.
>
> Will add a dependency on 'fs_fat'

CMD_FAT already requires FS_FAT, so I won't make this change.

-Takahiro Akashi

> -Takahiro Akashi
>
> > Best regards
> >
> > Heinrich
> >
> > >+ 'setenv -e -nv -bs -rt -at -a -i 4000000,$filesize db'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+
> > >+ with u_boot_console.log.section('Test Case 3c'):
> > >+ # Test Case 3c, update with correct signature
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 db1.auth',
> > >+ 'setenv -e -nv -bs -rt -at -a -i 4000000,$filesize db',
> > >+ 'printenv -e -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
> > >+ assert(not re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('db:', ''.join(output)))
> > >+ assert(re.search('DataSize = 0x650', ''.join(output)))
> > >+
> > >+ def test_efi_var_auth4(self, u_boot_console, efi_boot_env):
> > >+ """
> > >+ Test Case 4 - Delete database without authentication
> > >+ """
> > >+ disk_img = efi_boot_env
> > >+ with u_boot_console.log.section('Test Case 4a'):
> > >+ # Test Case 4a, update without AUTHENTICATED_WRITE_ACCESS
> > >+ output = u_boot_console.run_command_list([
> > >+ 'host bind 0 %s' % disk_img,
> > >+ 'fatload host 0:1 4000000 PK.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
> > >+ 'fatload host 0:1 4000000 KEK.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
> > >+ 'fatload host 0:1 4000000 db.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
> > >+ 'printenv -e -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
> > >+ assert(not re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('db:', ''.join(output)))
> > >+ assert(re.search('DataSize = 0x327', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command_list([
> > >+ 'setenv -e -nv -bs -rt db',
> > >+ 'printenv -e -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('db:', ''.join(output)))
> > >+ assert(re.search('DataSize = 0x327', ''.join(output)))
> > >+
> > >+ with u_boot_console.log.section('Test Case 4b'):
> > >+ # Test Case 4b, update without correct signature/data
> > >+ output = u_boot_console.run_command_list([
> > >+ 'setenv -e -nv -bs -rt -at db',
> > >+ 'printenv -e -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('db:', ''.join(output)))
> > >+ assert(re.search('DataSize = 0x327', ''.join(output)))
> > >+
> > >+ def test_efi_var_auth5(self, u_boot_console, efi_boot_env):
> > >+ """
> > >+ Test Case 5 - Uninstall(delete) PK
> > >+ """
> > >+ disk_img = efi_boot_env
> > >+ with u_boot_console.log.section('Test Case 4a'):
> > >+ # Test Case 5a, Uninstall PK without correct signature
> > >+ output = u_boot_console.run_command_list([
> > >+ 'host bind 0 %s' % disk_img,
> > >+ 'fatload host 0:1 4000000 PK.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
> > >+ 'fatload host 0:1 4000000 KEK.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
> > >+ 'fatload host 0:1 4000000 db.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
> > >+ 'printenv -e PK'])
> > >+ assert(not re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('PK:', ''.join(output)))
> > >+# assert(re.search('DataSize = 0x31d', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 PK_null.esl',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
> > >+ 'printenv -e PK'])
> > >+ assert(re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('PK:', ''.join(output)))
> > >+
> > >+ with u_boot_console.log.section('Test Case 5b'):
> > >+ # Test Case 5b, Uninstall PK with correct signature
> > >+ output = u_boot_console.run_command_list([
> > >+ 'fatload host 0:1 4000000 PK_null.auth',
> > >+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
> > >+ 'printenv -e PK'])
> > >+ assert(not re.search('Failed to set EFI variable', ''.join(output)))
> > >+ assert(re.search('\"PK\" not defined', ''.join(output)))
> > >+
> > >+ output = u_boot_console.run_command(
> > >+ 'printenv -e SecureBoot')
> > >+ assert('00000000: 00' in output)
> > >+ output = u_boot_console.run_command(
> > >+ 'printenv -e SetupMode')
> > >+ assert('00000000: 01' in output)
> > >
> >