diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/Kconfig | 9 | ||||
-rw-r--r-- | test/Makefile | 2 | ||||
-rw-r--r-- | test/cmd_ut.c | 6 | ||||
-rw-r--r-- | test/dm/Makefile | 1 | ||||
-rw-r--r-- | test/dm/fdtdec.c | 59 | ||||
-rw-r--r-- | test/dm/test-fdt.c | 66 | ||||
-rw-r--r-- | test/log/Makefile | 14 | ||||
-rw-r--r-- | test/log/nolog_test.c | 135 | ||||
-rw-r--r-- | test/log/syslog_test.c | 280 | ||||
-rw-r--r-- | test/log/test-main.c | 20 | ||||
-rw-r--r-- | test/py/README.md | 8 | ||||
-rw-r--r-- | test/py/tests/test_efi_secboot/conftest.py | 151 | ||||
-rw-r--r-- | test/py/tests/test_efi_secboot/defs.py | 21 | ||||
-rw-r--r-- | test/py/tests/test_efi_secboot/test_authvar.py | 282 | ||||
-rw-r--r-- | test/py/tests/test_efi_secboot/test_signed.py | 117 | ||||
-rw-r--r-- | test/py/tests/test_efi_secboot/test_unsigned.py | 121 |
16 files changed, 1290 insertions, 2 deletions
diff --git a/test/Kconfig b/test/Kconfig index 0157e0b060..28704a25b6 100644 --- a/test/Kconfig +++ b/test/Kconfig @@ -40,6 +40,15 @@ config UT_LIB_RSA endif +config UT_LOG + bool "Unit tests for logging functions" + depends on UNIT_TEST + default y + help + Enables the 'ut log' command which tests logging functions like + log_err(). + See also CONFIG_LOG_TEST which provides the 'log test' command. + config UT_TIME bool "Unit tests for time functions" depends on UNIT_TEST diff --git a/test/Makefile b/test/Makefile index 2fe41f489c..2971d0d87f 100644 --- a/test/Makefile +++ b/test/Makefile @@ -10,5 +10,5 @@ obj-$(CONFIG_SANDBOX) += compression.o obj-$(CONFIG_SANDBOX) += print_ut.o obj-$(CONFIG_UT_TIME) += time_ut.o obj-$(CONFIG_UT_UNICODE) += unicode_ut.o -obj-$(CONFIG_$(SPL_)LOG) += log/ +obj-y += log/ obj-$(CONFIG_UNIT_TEST) += lib/ diff --git a/test/cmd_ut.c b/test/cmd_ut.c index a3a9d49f7e..7fdcdbb1a6 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -60,6 +60,9 @@ static cmd_tbl_t cmd_ut_sub[] = { #ifdef CONFIG_UT_LIB U_BOOT_CMD_MKENT(lib, CONFIG_SYS_MAXARGS, 1, do_ut_lib, "", ""), #endif +#ifdef CONFIG_UT_LOG + U_BOOT_CMD_MKENT(log, CONFIG_SYS_MAXARGS, 1, do_ut_log, "", ""), +#endif #ifdef CONFIG_UT_TIME U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""), #endif @@ -125,6 +128,9 @@ static char ut_help_text[] = #ifdef CONFIG_UT_LIB "ut lib [test-name] - test library functions\n" #endif +#ifdef CONFIG_UT_LOG + "ut log [test-name] - test logging functions\n" +#endif #ifdef CONFIG_UT_OPTEE "ut optee [test-name]\n" #endif diff --git a/test/dm/Makefile b/test/dm/Makefile index 3daf8a544e..f55874c0f2 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_LED) += led.o obj-$(CONFIG_DM_MAILBOX) += mailbox.o obj-$(CONFIG_DM_MMC) += mmc.o obj-y += ofnode.o +obj-y += fdtdec.o obj-$(CONFIG_OSD) += osd.o obj-$(CONFIG_DM_VIDEO) += panel.o obj-$(CONFIG_DM_PCI) += pci.o diff --git a/test/dm/fdtdec.c b/test/dm/fdtdec.c new file mode 100644 index 0000000000..b2f75b5843 --- /dev/null +++ b/test/dm/fdtdec.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 NXP + */ + +#include <common.h> +#include <dm.h> +#include <dm/of_extra.h> +#include <dm/test.h> +#include <test/ut.h> + +static int dm_test_fdtdec_set_carveout(struct unit_test_state *uts) +{ + struct fdt_memory resv; + void *blob; + const fdt32_t *prop; + int blob_sz, len, offset; + + blob_sz = fdt_totalsize(gd->fdt_blob) + 4096; + blob = malloc(blob_sz); + ut_assertnonnull(blob); + + /* Make a writtable copy of the fdt blob */ + ut_assertok(fdt_open_into(gd->fdt_blob, blob, blob_sz)); + + resv.start = 0x1000; + resv.end = 0x2000; + ut_assertok(fdtdec_set_carveout(blob, "/a-test", + "memory-region", 2, "test_resv1", + &resv)); + + resv.start = 0x10000; + resv.end = 0x20000; + ut_assertok(fdtdec_set_carveout(blob, "/a-test", + "memory-region", 1, "test_resv2", + &resv)); + + resv.start = 0x100000; + resv.end = 0x200000; + ut_assertok(fdtdec_set_carveout(blob, "/a-test", + "memory-region", 0, "test_resv3", + &resv)); + + offset = fdt_path_offset(blob, "/a-test"); + ut_assert(offset > 0); + prop = fdt_getprop(blob, offset, "memory-region", &len); + ut_assertnonnull(prop); + + ut_asserteq(len, 12); + ut_assert(fdt_node_offset_by_phandle(blob, fdt32_to_cpu(prop[0])) > 0); + ut_assert(fdt_node_offset_by_phandle(blob, fdt32_to_cpu(prop[1])) > 0); + ut_assert(fdt_node_offset_by_phandle(blob, fdt32_to_cpu(prop[2])) > 0); + + free(blob); + + return 0; +} +DM_TEST(dm_test_fdtdec_set_carveout, + DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE); diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index 75ae08081c..a56275aef9 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -255,7 +255,7 @@ static int dm_test_fdt(struct unit_test_state *uts) int ret; int i; - ret = dm_scan_fdt(gd->fdt_blob, false); + ret = dm_extended_scan_fdt(gd->fdt_blob, false); ut_assert(!ret); ret = uclass_get(UCLASS_TEST_FDT, &uc); @@ -867,6 +867,7 @@ static int dm_test_read_int(struct unit_test_state *uts) u32 val32; s32 sval; uint val; + u64 val64; ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev)); ut_asserteq_str("a-test", dev->name); @@ -891,10 +892,48 @@ static int dm_test_read_int(struct unit_test_state *uts) ut_assertok(dev_read_u32u(dev, "uint-value", &val)); ut_asserteq(-1234, val); + ut_assertok(dev_read_u64(dev, "int64-value", &val64)); + ut_asserteq_64(0x1111222233334444, val64); + + ut_asserteq_64(-EINVAL, dev_read_u64(dev, "missing", &val64)); + ut_asserteq_64(6, dev_read_u64_default(dev, "missing", 6)); + + ut_asserteq_64(0x1111222233334444, + dev_read_u64_default(dev, "int64-value", 6)); + return 0; } DM_TEST(dm_test_read_int, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); +static int dm_test_read_int_index(struct unit_test_state *uts) +{ + struct udevice *dev; + u32 val32; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_asserteq(-EINVAL, dev_read_u32_index(dev, "missing", 0, &val32)); + ut_asserteq(19, dev_read_u32_index_default(dev, "missing", 0, 19)); + + ut_assertok(dev_read_u32_index(dev, "int-array", 0, &val32)); + ut_asserteq(5678, val32); + ut_assertok(dev_read_u32_index(dev, "int-array", 1, &val32)); + ut_asserteq(9123, val32); + ut_assertok(dev_read_u32_index(dev, "int-array", 2, &val32)); + ut_asserteq(4567, val32); + ut_asserteq(-EOVERFLOW, dev_read_u32_index(dev, "int-array", 3, + &val32)); + + ut_asserteq(5678, dev_read_u32_index_default(dev, "int-array", 0, 2)); + ut_asserteq(9123, dev_read_u32_index_default(dev, "int-array", 1, 2)); + ut_asserteq(4567, dev_read_u32_index_default(dev, "int-array", 2, 2)); + ut_asserteq(2, dev_read_u32_index_default(dev, "int-array", 3, 2)); + + return 0; +} +DM_TEST(dm_test_read_int_index, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + /* Test iteration through devices by drvdata */ static int dm_test_uclass_drvdata(struct unit_test_state *uts) { @@ -953,3 +992,28 @@ static int dm_test_first_child_probe(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_first_child_probe, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test that ofdata is read for parents before children */ +static int dm_test_ofdata_order(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + + ut_assertok(uclass_find_first_device(UCLASS_I2C, &bus)); + ut_assertnonnull(bus); + ut_assert(!(bus->flags & DM_FLAG_PLATDATA_VALID)); + + ut_assertok(device_find_first_child(bus, &dev)); + ut_assertnonnull(dev); + ut_assert(!(dev->flags & DM_FLAG_PLATDATA_VALID)); + + /* read the child's ofdata which should cause the parent's to be read */ + ut_assertok(device_ofdata_to_platdata(dev)); + ut_assert(dev->flags & DM_FLAG_PLATDATA_VALID); + ut_assert(bus->flags & DM_FLAG_PLATDATA_VALID); + + ut_assert(!(dev->flags & DM_FLAG_ACTIVATED)); + ut_assert(!(bus->flags & DM_FLAG_ACTIVATED)); + + return 0; +} +DM_TEST(dm_test_ofdata_order, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); diff --git a/test/log/Makefile b/test/log/Makefile index e0d0a4745f..4c92550f6e 100644 --- a/test/log/Makefile +++ b/test/log/Makefile @@ -3,3 +3,17 @@ # Copyright (c) 2017 Google, Inc obj-$(CONFIG_LOG_TEST) += log_test.o + +ifdef CONFIG_UT_LOG + +obj-y += test-main.o + +ifdef CONFIG_SANDBOX +obj-$(CONFIG_LOG_SYSLOG) += syslog_test.o +endif + +ifndef CONFIG_LOG +obj-$(CONFIG_CONSOLE_RECORD) += nolog_test.o +endif + +endif # CONFIG_UT_LOG diff --git a/test/log/nolog_test.c b/test/log/nolog_test.c new file mode 100644 index 0000000000..84619521c9 --- /dev/null +++ b/test/log/nolog_test.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * Logging function tests for CONFIG_LOG=n. + */ + +/* Needed for testing log_debug() */ +#define DEBUG 1 + +#include <common.h> +#include <console.h> +#include <test/log.h> +#include <test/test.h> +#include <test/suites.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define BUFFSIZE 32 + +static int nolog_test_log_err(struct unit_test_state *uts) +{ + char buf[BUFFSIZE]; + + memset(buf, 0, BUFFSIZE); + console_record_reset_enable(); + log_err("testing %s\n", "log_err"); + gd->flags &= ~GD_FLG_RECORD; + ut_assertok(ut_check_console_line(uts, "testing log_err")); + ut_assertok(ut_check_console_end(uts)); + return 0; +} +LOG_TEST(nolog_test_log_err); + +static int nolog_test_log_warning(struct unit_test_state *uts) +{ + char buf[BUFFSIZE]; + + memset(buf, 0, BUFFSIZE); + console_record_reset_enable(); + log_warning("testing %s\n", "log_warning"); + gd->flags &= ~GD_FLG_RECORD; + ut_assertok(ut_check_console_line(uts, "testing log_warning")); + ut_assertok(ut_check_console_end(uts)); + return 0; +} +LOG_TEST(nolog_test_log_warning); + +static int nolog_test_log_notice(struct unit_test_state *uts) +{ + char buf[BUFFSIZE]; + + memset(buf, 0, BUFFSIZE); + console_record_reset_enable(); + log_notice("testing %s\n", "log_notice"); + gd->flags &= ~GD_FLG_RECORD; + ut_assertok(ut_check_console_line(uts, "testing log_notice")); + ut_assertok(ut_check_console_end(uts)); + return 0; +} +LOG_TEST(nolog_test_log_notice); + +static int nolog_test_log_info(struct unit_test_state *uts) +{ + char buf[BUFFSIZE]; + + memset(buf, 0, BUFFSIZE); + console_record_reset_enable(); + log_err("testing %s\n", "log_info"); + gd->flags &= ~GD_FLG_RECORD; + ut_assertok(ut_check_console_line(uts, "testing log_info")); + ut_assertok(ut_check_console_end(uts)); + return 0; +} +LOG_TEST(nolog_test_log_info); + +#undef _DEBUG +#define _DEBUG 0 +static int nolog_test_nodebug(struct unit_test_state *uts) +{ + char buf[BUFFSIZE]; + + memset(buf, 0, BUFFSIZE); + console_record_reset_enable(); + debug("testing %s\n", "debug"); + gd->flags &= ~GD_FLG_RECORD; + ut_assertok(ut_check_console_end(uts)); + return 0; +} +LOG_TEST(nolog_test_nodebug); + +static int nolog_test_log_nodebug(struct unit_test_state *uts) +{ + char buf[BUFFSIZE]; + + memset(buf, 0, BUFFSIZE); + console_record_reset_enable(); + log_debug("testing %s\n", "log_debug"); + gd->flags &= ~GD_FLG_RECORD; + ut_assert(!strcmp(buf, "")); + ut_assertok(ut_check_console_end(uts)); + return 0; +} +LOG_TEST(nolog_test_log_nodebug); + +#undef _DEBUG +#define _DEBUG 1 +static int nolog_test_debug(struct unit_test_state *uts) +{ + char buf[BUFFSIZE]; + + memset(buf, 0, BUFFSIZE); + console_record_reset_enable(); + debug("testing %s\n", "debug"); + gd->flags &= ~GD_FLG_RECORD; + ut_assertok(ut_check_console_line(uts, "testing debug")); + ut_assertok(ut_check_console_end(uts)); + return 0; +} +LOG_TEST(nolog_test_debug); + +static int nolog_test_log_debug(struct unit_test_state *uts) +{ + char buf[BUFFSIZE]; + + memset(buf, 0, BUFFSIZE); + console_record_reset_enable(); + log_debug("testing %s\n", "log_debug"); + gd->flags &= ~GD_FLG_RECORD; + ut_assertok(ut_check_console_line(uts, "testing log_debug")); + ut_assertok(ut_check_console_end(uts)); + return 0; +} +LOG_TEST(nolog_test_log_debug); diff --git a/test/log/syslog_test.c b/test/log/syslog_test.c new file mode 100644 index 0000000000..6ca5760eac --- /dev/null +++ b/test/log/syslog_test.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * Logging function tests for CONFIG_LOG_SYSLOG=y. + * + * Invoke the test with: ./u-boot -d arch/sandbox/dts/test.dtb + */ + +/* Override CONFIG_LOG_MAX_LEVEL */ +#define LOG_DEBUG + +#include <common.h> +#include <dm/device.h> +#include <hexdump.h> +#include <test/log.h> +#include <test/test.h> +#include <test/suites.h> +#include <test/ut.h> +#include <asm/eth.h> + +DECLARE_GLOBAL_DATA_PTR; + +/** + * struct sb_log_env - private data for sandbox ethernet driver + * + * This structure is used for the private data of the sandbox ethernet + * driver. + * + * @expected: string expected to be written by the syslog driver + * @uts: unit test state + */ +struct sb_log_env { + const char *expected; + struct unit_test_state *uts; +}; + +/** + * sb_log_tx_handler() - transmit callback function + * + * This callback function is invoked when a network package is sent using the + * sandbox Ethernet driver. The private data of the driver holds a sb_log_env + * structure with the unit test state and the expected UDP payload. + * + * The following checks are executed: + * + * * the Ethernet packet indicates a IP broadcast message + * * the IP header is for a local UDP broadcast message to port 514 + * * the UDP payload matches the expected string + * + * After testing the pointer to the expected string is set to NULL to signal + * that the callback function has been called. + * + * @dev: sandbox ethernet device + * @packet: Ethernet packet + * @len: length of Ethernet packet + * Return: 0 = success + */ +static int sb_log_tx_handler(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct sb_log_env *env = priv->priv; + /* uts is updated by the ut_assert* macros */ + struct unit_test_state *uts = env->uts; + char *buf = packet; + struct ethernet_hdr *eth_hdr = packet; + struct ip_udp_hdr *ip_udp_hdr; + + /* Check Ethernet header */ + ut_asserteq_mem(ð_hdr->et_dest, net_bcast_ethaddr, ARP_HLEN); + ut_asserteq(ntohs(eth_hdr->et_protlen), PROT_IP); + + /* Check IP header */ + buf += sizeof(struct ethernet_hdr); + ip_udp_hdr = (struct ip_udp_hdr *)buf; + ut_asserteq(ip_udp_hdr->ip_p, IPPROTO_UDP); + ut_asserteq(ip_udp_hdr->ip_dst.s_addr, 0xffffffff); + ut_asserteq(ntohs(ip_udp_hdr->udp_dst), 514); + ut_asserteq(UDP_HDR_SIZE + strlen(env->expected) + 1, + ntohs(ip_udp_hdr->udp_len)); + + /* Check payload */ + buf += sizeof(struct ip_udp_hdr); + ut_asserteq_mem(env->expected, buf, + ntohs(ip_udp_hdr->udp_len) - UDP_HDR_SIZE); + + /* Signal that the callback function has been executed */ + env->expected = NULL; + + return 0; +} + +/** + * syslog_test_log_err() - test log_err() function + * + * @uts: unit test state + * Return: 0 = success + */ +static int syslog_test_log_err(struct unit_test_state *uts) +{ + int old_log_level = gd->default_log_level; + struct sb_log_env env; + + gd->log_fmt = LOGF_DEFAULT; + gd->default_log_level = LOGL_INFO; + env_set("ethact", "eth@10002000"); + env_set("log_hostname", "sandbox"); + env.expected = "<3>sandbox uboot: syslog_test_log_err() " + "testing log_err\n"; + env.uts = uts; + sandbox_eth_set_tx_handler(0, sb_log_tx_handler); + /* Used by ut_assert macros in the tx_handler */ + sandbox_eth_set_priv(0, &env); + log_err("testing %s\n", "log_err"); + /* Check that the callback function was called */ + sandbox_eth_set_tx_handler(0, NULL); + gd->default_log_level = old_log_level; + + return 0; +} +LOG_TEST(syslog_test_log_err); + +/** + * syslog_test_log_warning() - test log_warning() function + * + * @uts: unit test state + * Return: 0 = success + */ +static int syslog_test_log_warning(struct unit_test_state *uts) +{ + int old_log_level = gd->default_log_level; + struct sb_log_env env; + + gd->log_fmt = LOGF_DEFAULT; + gd->default_log_level = LOGL_INFO; + env_set("ethact", "eth@10002000"); + env_set("log_hostname", "sandbox"); + env.expected = "<4>sandbox uboot: syslog_test_log_warning() " + "testing log_warning\n"; + env.uts = uts; + sandbox_eth_set_tx_handler(0, sb_log_tx_handler); + /* Used by ut_assert macros in the tx_handler */ + sandbox_eth_set_priv(0, &env); + log_warning("testing %s\n", "log_warning"); + sandbox_eth_set_tx_handler(0, NULL); + /* Check that the callback function was called */ + ut_assertnull(env.expected); + gd->default_log_level = old_log_level; + + return 0; +} +LOG_TEST(syslog_test_log_warning); + +/** + * syslog_test_log_notice() - test log_notice() function + * + * @uts: unit test state + * Return: 0 = success + */ +static int syslog_test_log_notice(struct unit_test_state *uts) +{ + int old_log_level = gd->default_log_level; + struct sb_log_env env; + + gd->log_fmt = LOGF_DEFAULT; + gd->default_log_level = LOGL_INFO; + env_set("ethact", "eth@10002000"); + env_set("log_hostname", "sandbox"); + env.expected = "<5>sandbox uboot: syslog_test_log_notice() " + "testing log_notice\n"; + env.uts = uts; + sandbox_eth_set_tx_handler(0, sb_log_tx_handler); + /* Used by ut_assert macros in the tx_handler */ + sandbox_eth_set_priv(0, &env); + log_notice("testing %s\n", "log_notice"); + sandbox_eth_set_tx_handler(0, NULL); + /* Check that the callback function was called */ + ut_assertnull(env.expected); + gd->default_log_level = old_log_level; + + return 0; +} +LOG_TEST(syslog_test_log_notice); + +/** + * syslog_test_log_info() - test log_info() function + * + * @uts: unit test state + * Return: 0 = success + */ +static int syslog_test_log_info(struct unit_test_state *uts) +{ + int old_log_level = gd->default_log_level; + struct sb_log_env env; + + gd->log_fmt = LOGF_DEFAULT; + gd->default_log_level = LOGL_INFO; + env_set("ethact", "eth@10002000"); + env_set("log_hostname", "sandbox"); + env.expected = "<6>sandbox uboot: syslog_test_log_info() " + "testing log_info\n"; + env.uts = uts; + sandbox_eth_set_tx_handler(0, sb_log_tx_handler); + /* Used by ut_assert macros in the tx_handler */ + sandbox_eth_set_priv(0, &env); + log_info("testing %s\n", "log_info"); + sandbox_eth_set_tx_handler(0, NULL); + /* Check that the callback function was called */ + ut_assertnull(env.expected); + gd->default_log_level = old_log_level; + + return 0; +} +LOG_TEST(syslog_test_log_info); + +/** + * syslog_test_log_debug() - test log_debug() function + * + * @uts: unit test state + * Return: 0 = success + */ +static int syslog_test_log_debug(struct unit_test_state *uts) +{ + int old_log_level = gd->default_log_level; + struct sb_log_env env; + + gd->log_fmt = LOGF_DEFAULT; + gd->default_log_level = LOGL_DEBUG; + env_set("ethact", "eth@10002000"); + env_set("log_hostname", "sandbox"); + env.expected = "<7>sandbox uboot: syslog_test_log_debug() " + "testing log_debug\n"; + env.uts = uts; + sandbox_eth_set_tx_handler(0, sb_log_tx_handler); + /* Used by ut_assert macros in the tx_handler */ + sandbox_eth_set_priv(0, &env); + log_debug("testing %s\n", "log_debug"); + sandbox_eth_set_tx_handler(0, NULL); + /* Check that the callback function was called */ + ut_assertnull(env.expected); + gd->default_log_level = old_log_level; + + return 0; +} +LOG_TEST(syslog_test_log_debug); + +/** + * syslog_test_log_nodebug() - test logging level filter + * + * Verify that log_debug() does not lead to a log message if the logging level + * is set to LOGL_INFO. + * + * @uts: unit test state + * Return: 0 = success + */ +static int syslog_test_log_nodebug(struct unit_test_state *uts) +{ + int old_log_level = gd->default_log_level; + struct sb_log_env env; + + gd->log_fmt = LOGF_DEFAULT; + gd->default_log_level = LOGL_INFO; + env_set("ethact", "eth@10002000"); + env_set("log_hostname", "sandbox"); + env.expected = "<7>sandbox uboot: syslog_test_log_nodebug() " + "testing log_debug\n"; + env.uts = uts; + sandbox_eth_set_tx_handler(0, sb_log_tx_handler); + /* Used by ut_assert macros in the tx_handler */ + sandbox_eth_set_priv(0, &env); + log_debug("testing %s\n", "log_debug"); + sandbox_eth_set_tx_handler(0, NULL); + /* Check that the callback function was not called */ + ut_assertnonnull(env.expected); + gd->default_log_level = old_log_level; + + return 0; +} +LOG_TEST(syslog_test_log_nodebug); diff --git a/test/log/test-main.c b/test/log/test-main.c new file mode 100644 index 0000000000..855de47f33 --- /dev/null +++ b/test/log/test-main.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * Logging function tests. + */ + +#include <common.h> +#include <console.h> +#include <test/log.h> +#include <test/suites.h> + +int do_ut_log(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct unit_test *tests = ll_entry_start(struct unit_test, log_test); + const int n_ents = ll_entry_count(struct unit_test, log_test); + + return cmd_ut_category("log", "log_test_", + tests, n_ents, argc, argv); +} diff --git a/test/py/README.md b/test/py/README.md index 2e5025258d..fddc104b26 100644 --- a/test/py/README.md +++ b/test/py/README.md @@ -37,7 +37,15 @@ will be required. The following is an incomplete list: | openssl | | sudo OR guestmount | | e2fsprogs | +| util-linux | +| coreutils | | dosfstools | +| efitools | +| mount | +| mtools | +| sbsigntool | +| udisks2 | + Please use the apporirate commands for your distribution to match these tools up with the package that provides them. diff --git a/test/py/tests/test_efi_secboot/conftest.py b/test/py/tests/test_efi_secboot/conftest.py new file mode 100644 index 0000000000..e542fef6e8 --- /dev/null +++ b/test/py/tests/test_efi_secboot/conftest.py @@ -0,0 +1,151 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2019, Linaro Limited +# Author: AKASHI Takahiro <takahiro.akashi@linaro.org> + +import os +import os.path +import pytest +import re +from subprocess import call, check_call, check_output, CalledProcessError +from defs import * + +# from test/py/conftest.py +def tool_is_in_path(tool): + for path in os.environ["PATH"].split(os.pathsep): + fn = os.path.join(path, tool) + if os.path.isfile(fn) and os.access(fn, os.X_OK): + return True + return False + +# +# Fixture for UEFI secure boot test +# +@pytest.fixture(scope='session') +def efi_boot_env(request, u_boot_config): + """Set up a file system to be used in UEFI secure boot test. + + Args: + request: Pytest request object. + u_boot_config: U-boot configuration. + + Return: + A path to disk image to be used for testing + """ + global HELLO_PATH + + image_path = u_boot_config.persistent_data_dir + image_path = image_path + '/' + EFI_SECBOOT_IMAGE_NAME + image_size = EFI_SECBOOT_IMAGE_SIZE + part_size = EFI_SECBOOT_PART_SIZE + fs_type = EFI_SECBOOT_FS_TYPE + + if HELLO_PATH == '': + HELLO_PATH = u_boot_config.build_dir + '/lib/efi_loader/helloworld.efi' + + try: + non_root = tool_is_in_path('udisksctl') + + # create a disk/partition + check_call('dd if=/dev/zero of=%s bs=1MiB count=%d' + % (image_path, image_size), shell=True) + check_call('sgdisk %s -n 1:0:+%dMiB' + % (image_path, part_size), shell=True) + # create a file system + check_call('dd if=/dev/zero of=%s.tmp bs=1MiB count=%d' + % (image_path, part_size), shell=True) + check_call('mkfs -t %s %s.tmp' % (fs_type, image_path), shell=True) + check_call('dd if=%s.tmp of=%s bs=1MiB seek=1 count=%d conv=notrunc' + % (image_path, image_path, 1), shell=True) + check_call('rm %s.tmp' % image_path, shell=True) + if non_root: + out_data = check_output('udisksctl loop-setup -f %s -o %d' + % (image_path, 1048576), shell=True).decode() + m = re.search('(?<= as )(.*)\.', out_data) + loop_dev = m.group(1) + # print 'loop device is: %s' % loop_dev + out_data = check_output('udisksctl info -b %s' + % loop_dev, shell=True).decode() + m = re.search('MountPoints:[ \t]+(.*)', out_data) + mnt_point = m.group(1) + else: + loop_dev = check_output('sudo losetup -o 1MiB --sizelimit %dMiB --show -f %s | tr -d "\n"' + % (part_size, image_path), shell=True).decode() + mnt_point = '/mnt' + check_output('sudo mount -t %s -o umask=000 %s %s' + % (fs_type, loop_dev, mnt_point), shell=True) + + # print 'mount point is: %s' % mnt_point + + # suffix + # *.key: RSA private key in PEM + # *.crt: X509 certificate (self-signed) in PEM + # *.esl: signature list + # *.hash: message digest of image as signature list + # *.auth: signed signature list in signature database format + # *.efi: UEFI image + # *.efi.signed: signed UEFI image + + # Create signature database + ## PK + check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_PK/ -keyout PK.key -out PK.crt -nodes -days 365' + % mnt_point, shell=True) + check_call('cd %s; %scert-to-efi-sig-list -g %s PK.crt PK.esl; %ssign-efi-sig-list -c PK.crt -k PK.key PK PK.esl PK.auth' + % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH), + shell=True) + ## PK_null for deletion + check_call('cd %s; sleep 2; touch PK_null.esl; %ssign-efi-sig-list -c PK.crt -k PK.key PK PK_null.esl PK_null.auth' + % (mnt_point, EFITOOLS_PATH), shell=True) + ## KEK + check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_KEK/ -keyout KEK.key -out KEK.crt -nodes -days 365' + % mnt_point, shell=True) + check_call('cd %s; %scert-to-efi-sig-list -g %s KEK.crt KEK.esl; %ssign-efi-sig-list -c PK.crt -k PK.key KEK KEK.esl KEK.auth' + % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH), + shell=True) + ## db + check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_db/ -keyout db.key -out db.crt -nodes -days 365' + % mnt_point, shell=True) + check_call('cd %s; %scert-to-efi-sig-list -g %s db.crt db.esl; %ssign-efi-sig-list -c KEK.crt -k KEK.key db db.esl db.auth' + % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH), + shell=True) + ## db1 + check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_db1/ -keyout db1.key -out db1.crt -nodes -days 365' + % mnt_point, shell=True) + check_call('cd %s; %scert-to-efi-sig-list -g %s db1.crt db1.esl; %ssign-efi-sig-list -c KEK.crt -k KEK.key db db1.esl db1.auth' + % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH), + shell=True) + ## db1-update + check_call('cd %s; %ssign-efi-sig-list -a -c KEK.crt -k KEK.key db db1.esl db1-update.auth' + % (mnt_point, EFITOOLS_PATH), shell=True) + ## dbx + check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_dbx/ -keyout dbx.key -out dbx.crt -nodes -days 365' + % mnt_point, shell=True) + check_call('cd %s; %scert-to-efi-sig-list -g %s dbx.crt dbx.esl; %ssign-efi-sig-list -c KEK.crt -k KEK.key dbx dbx.esl dbx.auth' + % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH), + shell=True) + + # Copy image + check_call('cp %s %s' % (HELLO_PATH, mnt_point), shell=True) + + ## Sign image + check_call('cd %s; sbsign --key db.key --cert db.crt helloworld.efi' + % mnt_point, shell=True) + ## Digest image + check_call('cd %s; %shash-to-efi-sig-list helloworld.efi db_hello.hash; %ssign-efi-sig-list -c KEK.crt -k KEK.key db db_hello.hash db_hello.auth' + % (mnt_point, EFITOOLS_PATH, EFITOOLS_PATH), + shell=True) + + if non_root: + check_call('udisksctl unmount -b %s' % loop_dev, shell=True) + # not needed + # check_call('udisksctl loop-delete -b %s' % loop_dev, shell=True) + else: + check_call('sudo umount %s' % loop_dev, shell=True) + check_call('sudo losetup -d %s' % loop_dev, shell=True) + + except CalledProcessError as e: + pytest.skip('Setup failed: %s' % e.cmd) + return + else: + yield image_path + finally: + call('rm -f %s' % image_path, shell=True) diff --git a/test/py/tests/test_efi_secboot/defs.py b/test/py/tests/test_efi_secboot/defs.py new file mode 100644 index 0000000000..d6222809c5 --- /dev/null +++ b/test/py/tests/test_efi_secboot/defs.py @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0+ + +# Disk image name +EFI_SECBOOT_IMAGE_NAME='test_efi_secboot.img' + +# Size in MiB +EFI_SECBOOT_IMAGE_SIZE=16 +EFI_SECBOOT_PART_SIZE=8 + +# Partition file system type +EFI_SECBOOT_FS_TYPE='vfat' + +# Owner guid +GUID='11111111-2222-3333-4444-123456789abc' + +# v1.5.1 or earlier of efitools has a bug in sha256 calculation, and +# you need build a newer version on your own. +EFITOOLS_PATH='' + +# Hello World application for sandbox +HELLO_PATH='' 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 0000000000..55dcaa95f1 --- /dev/null +++ b/test/py/tests/test_efi_secboot/test_authvar.py @@ -0,0 +1,282 @@ +# 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 * + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('efi_secure_boot') +@pytest.mark.buildconfigspec('cmd_fat') +@pytest.mark.buildconfigspec('cmd_nvedit_efi') +@pytest.mark.slow +class TestEfiAuthVar(object): + def test_efi_var_auth1(self, u_boot_console, efi_boot_env): + """ + Test Case 1 - Install signature database + """ + u_boot_console.restart_uboot() + 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('00000000: 00' in ''.join(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([ + '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 -n 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 -n 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 -n -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 -n -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 + """ + u_boot_console.restart_uboot() + 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 -n -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_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 -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('db:', ''.join(output))) + + def test_efi_var_auth3(self, u_boot_console, efi_boot_env): + """ + Test Case 3 - Append database + """ + u_boot_console.restart_uboot() + 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 -n -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_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', + '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 -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('db:', ''.join(output))) + + def test_efi_var_auth4(self, u_boot_console, efi_boot_env): + """ + Test Case 4 - Delete database without authentication + """ + u_boot_console.restart_uboot() + 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 -n -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_list([ + 'setenv -e -nv -bs -rt db', + 'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('db:', ''.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 -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('db:', ''.join(output))) + + def test_efi_var_auth5(self, u_boot_console, efi_boot_env): + """ + Test Case 5 - Uninstall(delete) PK + """ + u_boot_console.restart_uboot() + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 5a'): + # 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 -n PK']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('PK:', ''.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 -n 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 -n 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) 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 <takahiro.akashi@linaro.org> +# +# 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 <takahiro.akashi@linaro.org> +# +# 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))) |