[PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
Heinrich Schuchardt
xypron.glpk at gmx.de
Mon Oct 25 11:43:27 CEST 2021
On 10/25/21 09:59, Masahisa Kojima wrote:
> On Sat, 23 Oct 2021 at 18:42, Heinrich Schuchardt <xypron.glpk at gmx.de> wrote:
>>
>>
>>
>> On 10/22/21 13:24, Masahisa Kojima wrote:
>>> This commit adds the missing EFI_TCG2_PROTOCOL selftest
>>> and Measured Boot selftest in lib/efi_selftest.
>>>
>>> Signed-off-by: Masahisa Kojima <masahisa.kojima at linaro.org>
>>> ---
>>> lib/efi_selftest/Makefile | 10 +
>>> .../efi_selftest_miniapp_measuredboot.c | 93 ++
>>> lib/efi_selftest/efi_selftest_tcg2.c | 804 +++++++++++++++++-
>>> 3 files changed, 906 insertions(+), 1 deletion(-)
>>> create mode 100644 lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
>>>
>>> diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
>>> index 9ff6e1760c..09950ee028 100644
>>> --- a/lib/efi_selftest/Makefile
>>> +++ b/lib/efi_selftest/Makefile
>>> @@ -14,6 +14,8 @@ CFLAGS_efi_selftest_miniapp_exception.o := $(CFLAGS_EFI) -Os -ffreestanding
>>> CFLAGS_REMOVE_efi_selftest_miniapp_exception.o := $(CFLAGS_NON_EFI)
>>> CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
>>> CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI)
>>> +CFLAGS_efi_selftest_miniapp_measuredboot.o := $(CFLAGS_EFI) -Os -ffreestanding
>>> +CFLAGS_REMOVE_efi_selftest_miniapp_measuredboot.o := $(CFLAGS_NON_EFI)
>>> CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding
>>> CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI)
>>> CFLAGS_initrddump_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
>>> @@ -78,9 +80,11 @@ obj-$(CONFIG_EFI_ESRT) += efi_selftest_esrt.o
>>> targets += \
>>> efi_miniapp_file_image_exception.h \
>>> efi_miniapp_file_image_exit.h \
>>> +efi_miniapp_file_image_measuredboot.h \
>>> efi_miniapp_file_image_return.h \
>>> efi_selftest_miniapp_exception.efi \
>>> efi_selftest_miniapp_exit.efi \
>>> +efi_selftest_miniapp_measuredboot.efi \
>>> efi_selftest_miniapp_return.efi
>>>
>>> ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
>>> @@ -99,6 +103,10 @@ $(obj)/efi_miniapp_file_image_exit.h: $(obj)/efi_selftest_miniapp_exit.efi
>>> $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exit.efi > \
>>> $(obj)/efi_miniapp_file_image_exit.h
>>>
>>> +$(obj)/efi_miniapp_file_image_measuredboot.h: $(obj)/efi_selftest_miniapp_measuredboot.efi
>>> + $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_measuredboot.efi > \
>>> + $(obj)/efi_miniapp_file_image_measuredboot.h
>>> +
>>> $(obj)/efi_miniapp_file_image_return.h: $(obj)/efi_selftest_miniapp_return.efi
>>> $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_return.efi > \
>>> $(obj)/efi_miniapp_file_image_return.h
>>> @@ -112,3 +120,5 @@ $(obj)/efi_selftest_loadimage.o: $(obj)/efi_miniapp_file_image_exit.h
>>> $(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h
>>>
>>> $(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h
>>> +
>>> +$(obj)/efi_selftest_tcg2.o: $(obj)/efi_miniapp_file_image_measuredboot.h
>>> diff --git a/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
>>
>> Thank you for going the extra mile and adding the test.
>>
>> Which image is actually loaded seems to be irrelevant for the test. Can
>> we reuse an existing one, e.g. efi_miniapp_file_image_return.h?
>>
>> I guess the PCR related to the loaded image is not checked as it will
>> depend on the build tools and date.
>
> Sorry, I'm doing wrong.
> Actually this selftest verifies the PE/COFF image measurement, so measuremt
> will be different depending on the build tools and date.
> # In my build environment, timestamp is set to all zero.
>
> To test the PE/COFF image measurement, I must prepare the
> static PE/COFF image. I plan to add efi_miniapp_file_image_measuredboot.h
> as a pre-compiled small static PE/COFF image for the measurement test,
> instead of adding efi_selftest_miniapp_measuredboot.c or reusing existing one.
You will need one image per UEFI architecture (ia32, x64, arm, aa64,
riscv32, riscv64). You could present the image via the
EFI_LOAD_FILE2_PROTOCOL, see lib/efi_selftest/efi_selftest_load_file.c.
Here is how to detect the target architecture:
#if defined(__arm__)
#include efi_miniapp_tcg2_arm.h
#elif defined(__aarch64__)
#include efi_miniapp_tcg2_aarch64.h
#elif defined(__i386__)
#include efi_miniapp_tcg2_ia32.h
#elif defined(__x86_64__)
#include efi_miniapp_tcg2_x64.h
#elif defined(__riscv) && (__riscv_xlen == 32)
#include efi_miniapp_tcg2_riscv32.h
#elif defined(__riscv) && (__riscv_xlen == 64)
#include efi_miniapp_tcg2_riscv64.h
#endif
Best regards
Heinrich
>
>>
>>> new file mode 100644
>>> index 0000000000..926713c1c2
>>> --- /dev/null
>>> +++ b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
>>> @@ -0,0 +1,93 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * efi_selftest_miniapp_measuredboot
>>> + *
>>> + * Copyright (c) 2018 Heinrich Schuchardt
>>> + * Copyright (c) 2021 Masahisa Kojima
>>> + *
>>> + * This EFI application is run by the StartImage selftest.
>>
>> This is incorrect due to copy and paste.
>>
>>> + * It uses the Exit boot service to return and used for
>>> + * Measured Boot selftest.
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <efi_selftest.h>
>>> +
>>> +static efi_guid_t loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
>>> +
>>> +/**
>>> + * check_loaded_image_protocol() - check image_base/image_size
>>> + *
>>> + * Try to open the loaded image protocol. Check that this function is located
>>> + * between image_base and image_base + image_size.
>>> + *
>>> + * @image_handle: handle of the loaded image
>>> + * @systable: system table
>>> + * @return: status code
>>> + */
>>> +static efi_status_t EFIAPI check_loaded_image_protocol
>>> + (efi_handle_t image_handle, struct efi_system_table *systable)
>>> +{
>>> + struct efi_simple_text_output_protocol *cout = systable->con_out;
>>> + struct efi_boot_services *boottime = systable->boottime;
>>> + struct efi_loaded_image *loaded_image_protocol;
>>> + efi_status_t ret;
>>> +
>>> + /*
>>> + * Open the loaded image protocol.
>>> + */
>>> + ret = boottime->open_protocol
>>> + (image_handle, &loaded_image_protocol_guid,
>>> + (void **)&loaded_image_protocol, NULL,
>>> + NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
>>> + if (ret != EFI_SUCCESS) {
>>> + cout->output_string(cout,
>>> + L"Could not open loaded image protocol");
>>> + return ret;
>>> + }
>>> + if ((void *)check_loaded_image_protocol <
>>> + loaded_image_protocol->image_base ||
>>> + (void *)check_loaded_image_protocol >=
>>> + loaded_image_protocol->image_base +
>>> + loaded_image_protocol->image_size) {
>>> + cout->output_string(cout,
>>> + L"Incorrect image_base or image_size\n");
>>> + return EFI_NOT_FOUND;
>>> + }
>>> + return EFI_SUCCESS;
>>> +}
>>> +
>>> +/**
>>> + * Entry point of the EFI application.
>>> + *
>>> + * @handle: handle of the loaded image
>>> + * @systable: system table
>>> + * @return: status code
>>> + */
>>> +efi_status_t EFIAPI efi_main(efi_handle_t handle,
>>> + struct efi_system_table *systable)
>>> +{
>>> + struct efi_simple_text_output_protocol *con_out = systable->con_out;
>>> + efi_status_t ret;
>>> + u16 text[] = EFI_ST_SUCCESS_STR;
>>> +
>>> + con_out->output_string(con_out, L"EFI application calling Exit\n");
>>> +
>>> + if (check_loaded_image_protocol(handle, systable) != EFI_SUCCESS) {
>>> + con_out->output_string(con_out,
>>> + L"Loaded image protocol missing\n");
>>> + ret = EFI_NOT_FOUND;
>>> + goto out;
>>> + }
>>> +
>>> + /* This return value is expected by the calling test */
>>> + ret = EFI_UNSUPPORTED;
>>> +out:
>>> + systable->boottime->exit(handle, ret, sizeof(text), text);
>>> +
>>> + /*
>>> + * This statement should not be reached.
>>> + * To enable testing use a different return value.
>>> + */
>>> + return EFI_SUCCESS;
>>> +}
>>> diff --git a/lib/efi_selftest/efi_selftest_tcg2.c b/lib/efi_selftest/efi_selftest_tcg2.c
>>> index 1399309cec..50de735f5e 100644
>>> --- a/lib/efi_selftest/efi_selftest_tcg2.c
>>> +++ b/lib/efi_selftest/efi_selftest_tcg2.c
>>> @@ -9,10 +9,495 @@
>>>
>>> #include <efi_selftest.h>
>>> #include <efi_tcg2.h>
>>> +/* Include containing the miniapp.efi application */
>>> +#include "efi_miniapp_file_image_measuredboot.h"
>>
>> efi_miniapp_file_image_return.h
>
> As I said above, I will prepare static PE/COFF image only for the
> measurement purpose.
>
>>
>>> +
>>> +#include <linux/unaligned/access_ok.h>
>>> +#include <mapmem.h>
>>> +#include <smbios.h>
>>> +#include <tables_csum.h>
>>>
>>> static struct efi_boot_services *boottime;
>>> static const efi_guid_t guid_tcg2 = EFI_TCG2_PROTOCOL_GUID;
>>>
>>> +/* Block size of compressed disk image */
>>> +#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
>>> +
>>> +static efi_handle_t image_handle;
>>> +/* Decompressed file image */
>>> +static u8 *image;
>>> +
>>> +/* One 8 byte block of the compressed disk image */
>>> +struct line {
>>> + size_t addr;
>>> + char *line;
>>> +};
>>> +
>>> +/* Compressed file image */
>>> +struct compressed_file_image {
>>> + size_t length;
>>> + struct line lines[];
>>> +};
>>> +
>>> +static struct compressed_file_image img = EFI_ST_DISK_IMG;
>>> +
>>> +static struct efi_tcg2_event *efi_tcg2_event;
>>> +
>>> +static struct efi_runtime_services *runtime;
>>> +#define BOOT_NAME_1000 u"Boot1000"
>>> +#define BOOT_NAME_1001 u"Boot1001"
>>> +#define BOOT_NAME_1002 u"Boot1002"
>>> +
>>> +#define DEFAULT_ATTR (EFI_VARIABLE_NON_VOLATILE | \
>>> + EFI_VARIABLE_BOOTSERVICE_ACCESS | \
>>> + EFI_VARIABLE_RUNTIME_ACCESS)
>>> +
>>> +/* "efidebug boot add -b 1000 test1000 virtio 0:1 /EFI/debian/grubaa64.efi" */
>>> +static const u8 boot_1000[] = {
>>> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
>>> +0x74, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
>>> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
>>> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
>>> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
>>> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
>>> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
>>> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
>>> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
>>> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
>>> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
>>> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
>>> +0xff, 0x04, 0x00 };
>>> +
>>> +/* "efidebug boot add -b 1001 test1001 virtio 0:1 /EFI/debian/grubaa64.efi" */
>>> +static const u8 boot_1001[] = {
>>> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
>>> +0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
>>> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
>>> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
>>> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
>>> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
>>> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
>>> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
>>> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
>>> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
>>> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
>>> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
>>> +0xff, 0x04, 0x00 };
>>> +
>>> +/* "efidebug boot add -b 1002 test1002 virtio 0:1 /EFI/debian/grubaa64.efi" */
>>> +static const u8 boot_1002[] = {
>>> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
>>> +0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
>>> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
>>> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
>>> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
>>> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
>>> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
>>> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
>>> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
>>> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
>>> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
>>> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
>>> +0xff, 0x04, 0x00};
>>> +
>>> +/* "efidebug boot order 1002 1000 1001" */
>>> +static u8 boot_order[] = {0x02, 0x10, 0x00, 0x10, 0x01, 0x10};
>>> +
>>> +static void *orig_smbios_table;
>>> +static u64 dmi_addr = U32_MAX;
>>> +#define SMBIOS_ENTRY_HEADER_SIZE 0x20
>>> +/* smbios table for the measurement test */
>>> +static u8 smbios_table_test[] = {
>>> +0x5f, 0x53, 0x4d, 0x5f, 0x2c, 0x1f, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x00, 0x5f, 0x44, 0x4d, 0x49, 0x5f, 0xe4, 0x5c, 0x01,
>>> +0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
>>> +0x01, 0x02, 0x00, 0x00, 0x03, 0x00, 0x80, 0x08, 0x01, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x0c, 0x15, 0x0a, 0xff, 0xff, 0x55, 0x2d, 0x42, 0x6f,
>>> +0x6f, 0x74, 0x00, 0x32, 0x30, 0x32, 0x31, 0x2e, 0x31, 0x30, 0x2d, 0x72,
>>> +0x63, 0x34, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x35, 0x2d, 0x67, 0x37, 0x32,
>>> +0x37, 0x63, 0x33, 0x66, 0x33, 0x32, 0x35, 0x39, 0x2d, 0x64, 0x69, 0x72,
>>> +0x74, 0x79, 0x00, 0x31, 0x30, 0x2f, 0x30, 0x31, 0x2f, 0x32, 0x30, 0x32,
>>> +0x31, 0x00, 0x00, 0x01, 0x1b, 0x01, 0x00, 0x01, 0x02, 0x00, 0x03, 0x31,
>>> +0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77,
>>> +0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x72,
>>> +0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
>>> +0x37, 0x38, 0x00, 0x00, 0x02, 0x0e, 0x02, 0x00, 0x01, 0x02, 0x00, 0x04,
>>> +0x03, 0x01, 0x01, 0x01, 0x00, 0x0a, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77,
>>> +0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x72,
>>> +0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
>>> +0x33, 0x33, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00,
>>> +0x00, 0x03, 0x15, 0x03, 0x00, 0x01, 0x03, 0x00, 0x02, 0x03, 0x03, 0x03,
>>> +0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x6e,
>>> +0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
>>> +0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00,
>>> +0x00, 0x04, 0x30, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +0x00, 0x01, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x03, 0x04,
>>> +0x04, 0x04, 0x08, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01,
>>> +0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x33,
>>> +0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
>>> +0x33, 0x33, 0x00, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x00,
>>> +0x00, 0x20, 0x0b, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x7f, 0x04, 0x06, 0x00, 0x00, 0x00
>>> +};
>>> +
>>> +#define TPM2_CMD_BUF_SIZE 64
>>> +/* TPM command is big endian */
>>> +#define __MSB(x) ((x) >> 8)
>>> +#define __LSB(x) ((x) & 0xFF)
>>> +#define tpm_u16(x) __MSB(x), __LSB(x)
>>> +#define tpm_u32(x) tpm_u16((x) >> 16), tpm_u16((x) & 0xFFFF)
>>> +#define TPM2_PCR_READ_HEADER_SIZE 30
>>> +
>>> +static u8 *pcrs;
>>> +static u8 expected_pcrs[EFI_TCG2_MAX_PCR_INDEX + 1][TPM2_SHA256_DIGEST_SIZE] = {
>>> + {0x91, 0x21, 0x37, 0xc7, 0x1a, 0x49, 0x19, 0xc8,
>>> + 0xf1, 0xfb, 0xa9, 0x84, 0x5c, 0x65, 0xa9, 0xdd,
>>> + 0x7b, 0xb9, 0xfe, 0xa1, 0xcd, 0x64, 0x49, 0xdd,
>>> + 0xed, 0xe2, 0x65, 0x82, 0xc5, 0x3e, 0xf4, 0xc4},
>>> +
>>> + {0xf5, 0x79, 0xf3, 0x20, 0x62, 0x6e, 0x8b, 0x58,
>>> + 0x62, 0xa3, 0x4e, 0x2f, 0xb7, 0x10, 0xac, 0x34,
>>> + 0x4e, 0x68, 0x94, 0x37, 0x87, 0x29, 0xc4, 0xbe,
>>> + 0xa3, 0xc4, 0xd9, 0x14, 0x2b, 0x66, 0x79, 0x9b},
>>> +
>>> + {0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
>>> + 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
>>> + 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
>>> + 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
>>> +
>>> + {0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
>>> + 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
>>> + 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
>>> + 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
>>> +
>>> + {0xbe, 0xea, 0xdc, 0xe0, 0x44, 0x5b, 0x5f, 0x14,
>>> + 0xef, 0x24, 0x5d, 0x13, 0x15, 0xfe, 0x41, 0x86,
>>> + 0xc2, 0xd5, 0xdc, 0x0d, 0x04, 0x2f, 0xd4, 0x04,
>>> + 0x0d, 0x02, 0x62, 0xc0, 0x34, 0x80, 0xee, 0xd5},
>>> +
>>> + {0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
>>> + 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
>>> + 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
>>> + 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
>>> +
>>> + {0x8d, 0x28, 0xde, 0x72, 0x22, 0x3e, 0x88, 0x1a,
>>> + 0x37, 0xfa, 0x47, 0x12, 0x68, 0x45, 0xdf, 0x71,
>>> + 0x50, 0x8f, 0xab, 0x59, 0x50, 0x7b, 0x52, 0x32,
>>> + 0xa6, 0xaa, 0x03, 0x3d, 0x4e, 0x22, 0x89, 0xd7},
>>> +
>>> + {0x96, 0x74, 0xae, 0xcd, 0x3f, 0x40, 0xb4, 0xa9,
>>> + 0x36, 0xae, 0x19, 0xc8, 0x84, 0x8a, 0xb9, 0x5a,
>>> + 0x87, 0x99, 0xd8, 0x89, 0x7f, 0xfc, 0x40, 0x48,
>>> + 0x05, 0x99, 0x65, 0x2e, 0x55, 0xd4, 0x93, 0x32},
>>> +
>>> + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +};
>>> +
>>> +struct boot_variable {
>>> + u16 name[16];
>>> + u8 *buf;
>>> + efi_uintn_t size;
>>> + u32 attr;
>>> + const u8 *test_data;
>>> + efi_uintn_t test_data_size;
>>> +};
>>> +
>>> +static struct boot_variable boot_variable_test[] = {
>>> + {u"BootOrder", NULL, 0, DEFAULT_ATTR, boot_order, sizeof(boot_order)},
>>> + {BOOT_NAME_1000, NULL, 0, DEFAULT_ATTR, boot_1000, sizeof(boot_1000)},
>>> + {BOOT_NAME_1001, NULL, 0, DEFAULT_ATTR, boot_1001, sizeof(boot_1001)},
>>> + {BOOT_NAME_1002, NULL, 0, DEFAULT_ATTR, boot_1002, sizeof(boot_1002)},
>>> +};
>>> +
>>> +/*
>>> + * Decompress the disk image.
>>> + *
>>> + * @image decompressed disk image
>>> + * @return status code
>>> + */
>>> +static efi_status_t decompress(u8 **image)
>>> +{
>>> + u8 *buf;
>>> + size_t i;
>>> + size_t addr;
>>> + size_t len;
>>> + efi_status_t ret;
>>> +
>>> + ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
>>> + (void **)&buf);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("Out of memory\n");
>>> + return ret;
>>> + }
>>> + boottime->set_mem(buf, img.length, 0);
>>> +
>>> + for (i = 0; ; ++i) {
>>> + if (!img.lines[i].line)
>>> + break;
>>> + addr = img.lines[i].addr;
>>> + len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
>>> + if (addr + len > img.length)
>>> + len = img.length - addr;
>>> + boottime->copy_mem(buf + addr, img.lines[i].line, len);
>>> + }
>>> + *image = buf;
>>> + return ret;
>>> +}
>>> +
>>> +/*
>>> + * Configure dummy boot variables.
>>
>> /**
>> * efi_status_t setup_boot_variable() - configure dummy boot variables
>> *
>> * Preexisting variable values are saved and will be restored by
>> * calling restore_boot_variable().
>> *
>>
>>> + *
>>> + * @return status code
>>> + */
>>> +static efi_status_t setup_boot_variable(void)
>>> +{
>>> + efi_status_t ret;
>>> + u32 i;
>>> + efi_uintn_t size;
>>> + u8 dummy;
>>
>> This variable is superfluous.
>>
>>> +
>>> + for (i = 0; i < ARRAY_SIZE(boot_variable_test); i++) {
>>> + size = 1;
>>
>> Please, set size to 0.
>>
>>> + ret = runtime->get_variable(boot_variable_test[i].name,
>>> + &efi_global_variable_guid,
>>> + &boot_variable_test[i].attr,
>>> + &size,
>>> + &dummy);
>>
>> Instead of dummy you can use NULL if size = 0.
>>
>>> + if (ret == EFI_BUFFER_TOO_SMALL) {
>>> + /* Variable exists, save the current vaiable */
>>
>> %s/vaiable/value/
>>
>>> + boot_variable_test[i].size = size;
>>> + ret = boottime->allocate_pool(EFI_LOADER_DATA,
>>> + boot_variable_test[i].size,
>>> + (void **)&boot_variable_test[i].buf);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("fail to allocate buffer for boot variable\n");
>>
>> In all other tests we use 'Failed to'
>>
>> %s/fail/Failed/
>>
>>> + return ret;
>>> + }
>>> + ret = runtime->get_variable(boot_variable_test[i].name,
>>> + &efi_global_variable_guid,
>>> + &boot_variable_test[i].attr,
>>> + &boot_variable_test[i].size,
>>> + boot_variable_test[i].buf);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("fail to get current boot variable\n");
>>
>> %s/fail/Failed/
>>
>>
>>> + return ret;
>>> + }
>>> + }
>>> +
>>> + /* set boot variable for the measurement test */
>>> + ret = runtime->set_variable(boot_variable_test[i].name,
>>> + &efi_global_variable_guid,
>>> + boot_variable_test[i].attr,
>>> + boot_variable_test[i].test_data_size,
>>> + boot_variable_test[i].test_data);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("### fail to set test boot variable(%d)n", i);
>>
>> %s/### fail/Failed/
>>
>>> + return ret;
>>> + }
>>> + }
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/*
>>
>> /**
>> * efi_status_t restore_boot_variable() - restore original values
>> *
>> * Restore the variable values saved in setup_boot_variable().
>> *
>>
>>> + * Restore original boot variables.
>>> + *
>>> + * @return status code
>>> + */
>>> +efi_status_t restore_boot_variable(void)
>>> +{
>>> + int i;
>>> + efi_status_t ret;
>>> +
>>> + for (i = 0; i < ARRAY_SIZE(boot_variable_test); i++) {
>>> + if (boot_variable_test[i].buf) {
>>> + ret = runtime->set_variable(boot_variable_test[i].name,
>>> + &efi_global_variable_guid,
>>> + boot_variable_test[i].attr,
>>> + boot_variable_test[i].size,
>>> + boot_variable_test[i].buf);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("### fail to restore boot variable\n");
>>> + return ret;
>>> + }
>>> + ret = boottime->free_pool(boot_variable_test[i].buf);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("Failed to free boot variable\n");
>>> + return ret;
>>> + }
>>> + } else {
>>> + /* delete the variable used only for testing */
>>> + ret = runtime->set_variable(boot_variable_test[i].name,
>>> + &efi_global_variable_guid,
>>> + 0, 0, NULL);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("### fail to delete boot variable\n");
>>
>> %s/### fail/Failed/
>>
>>> + return ret;
>>> + }
>>> + }
>>> + }
>>> +
>>> + return EFI_SUCCESS;
>>> +}
>>> +
>>> +/**
>>> + * Find smbios table
>>> + *
>>> + * @systable system table
>>> + * @return status code
>>> + */
>>> +static void *find_smbios_table(const struct efi_system_table *systable)
>>> +{
>>> + u32 i;
>>> +
>>> + for (i = 0; i < systable->nr_tables; i++) {
>>> + if (!guidcmp(&smbios_guid, &systable->tables[i].guid))
>>> + return systable->tables[i].table;
>>> + }
>>> +
>>> + return NULL;
>>> +}
>>> +
>>> +/**
>>> + * Prepare the dummy SMBIOS table
>>> + *
>>> + * @systable system table
>>> + * @return status code
>>> + */
>>> +efi_status_t setup_smbios_table(const struct efi_system_table *systable)
>>> +{
>>> + struct smbios_entry *se;
>>> + efi_status_t ret;
>>> + /* Map within the low 32 bits, to allow for 32bit SMBIOS tables */
>>> + void *dmi;
>>> + char *istart;
>>> + int isize;
>>> +
>>> + if (sizeof(smbios_table_test) > EFI_PAGE_SIZE)
>>> + return EFI_OUT_OF_RESOURCES;
>>> +
>>> + orig_smbios_table = find_smbios_table(systable);
>>> +
>>> + /* Reserve 4kiB page for SMBIOS */
>>> + ret = boottime->allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
>>> + EFI_RUNTIME_SERVICES_DATA, 1, &dmi_addr);
>>> +
>>> + if (ret != EFI_SUCCESS) {
>>> + /* Could not find space in lowmem, use highmem instead */
>>> + ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
>>> + EFI_RUNTIME_SERVICES_DATA, 1,
>>> + &dmi_addr);
>>> +
>>> + if (ret != EFI_SUCCESS)
>>> + return ret;
>>> + }
>>> +
>>> + dmi = (void *)(uintptr_t)dmi_addr;
>>> + se = dmi;
>>> + boottime->copy_mem(se, smbios_table_test, sizeof(smbios_table_test));
>>> +
>>> + /* update smbios table start address */
>>> + se->struct_table_address = (uintptr_t)((u8 *)dmi + SMBIOS_ENTRY_HEADER_SIZE);
>>> +
>>> + /* calculate checksums */
>>> + istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
>>> + isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
>>> + se->intermediate_checksum = table_compute_checksum(istart, isize);
>>> + se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
>>> +
>>> + /* Install SMBIOS information as configuration table */
>>> + ret = boottime->install_configuration_table(&smbios_guid, dmi);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("Cannot install SMBIOS table\n");
>>> + boottime->free_pages(dmi_addr, 1);
>>> + }
>>> +
>>> + return ret;
>>> +}
>>> +
>>> /**
>>> * efi_st_tcg2_setup() - setup test
>>> *
>>> @@ -23,7 +508,171 @@ static const efi_guid_t guid_tcg2 = EFI_TCG2_PROTOCOL_GUID;
>>> static int efi_st_tcg2_setup(const efi_handle_t img_handle,
>>> const struct efi_system_table *systable)
>>> {
>>> + efi_status_t ret;
>>> + struct uefi_image_load_event image_load_event;
>>> +
>>> + image_handle = img_handle;
>>> boottime = systable->boottime;
>>> + runtime = systable->runtime;
>>> +
>>> + /* Load the application image into memory */
>>> + decompress(&image);
>>> +
>>> + ret = boottime->allocate_pool(EFI_LOADER_DATA,
>>> + sizeof(struct efi_tcg2_event) +
>>> + sizeof(struct uefi_image_load_event),
>>> + (void **)&efi_tcg2_event);
>>> + if (!efi_tcg2_event)
>>> + return EFI_ST_FAILURE;
>>> +
>>> + efi_tcg2_event->size = sizeof(struct efi_tcg2_event) +
>>> + sizeof(struct uefi_image_load_event);
>>> + efi_tcg2_event->header.header_size = sizeof(struct efi_tcg2_event_header);
>>> + efi_tcg2_event->header.header_version = 1;
>>> + efi_tcg2_event->header.pcr_index = 6;
>>> + efi_tcg2_event->header.event_type = EV_EFI_RUNTIME_SERVICES_DRIVER;
>>> + image_load_event.image_location_in_memory = 0x12345678;
>>> + image_load_event.image_length_in_memory = 0x300000;
>>> + image_load_event.image_link_time_address = 0x87654321;
>>> + image_load_event.length_of_device_path = 0;
>>> + boottime->copy_mem(efi_tcg2_event->event, &image_load_event,
>>> + sizeof(struct uefi_image_load_event));
>>> +
>>> + ret = setup_boot_variable();
>>> + if (ret != EFI_SUCCESS)
>>> + return EFI_ST_FAILURE;
>>> +
>>> + ret = setup_smbios_table(systable);
>>> + if (ret != EFI_SUCCESS)
>>> + return EFI_ST_FAILURE;
>>> +
>>> + ret = boottime->allocate_pool(EFI_LOADER_DATA,
>>> + (EFI_TCG2_MAX_PCR_INDEX + 1) *
>>> + TPM2_SHA256_DIGEST_SIZE,
>>> + (void **)&pcrs);
>>> + if (!pcrs)
>>> + return EFI_ST_FAILURE;
>>> +
>>> + boottime->set_mem(pcrs, (EFI_TCG2_MAX_PCR_INDEX + 1) * TPM2_SHA256_DIGEST_SIZE, 0);
>>> +
>>> + return EFI_ST_SUCCESS;
>>> +}
>>> +
>>> +/**
>>> + * Get manufacturer_id through submit_command API
>>> + *
>>> + * @tcg2 tcg2 protocol
>>> + * @manufacturer_id pointer to the manufacturer_id
>>> + * @return status code
>>> + */
>>> +static efi_status_t get_manufacturer_id(struct efi_tcg2_protocol *tcg2, u32 *manufacturer_id)
>>> +{
>>> + efi_status_t ret;
>>> + u8 cmd[TPM2_CMD_BUF_SIZE] = {
>>> + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
>>> + tpm_u32(22), /* Length */
>>> + tpm_u32(TPM2_CC_GET_CAPABILITY), /* Command code */
>>> +
>>> + tpm_u32(TPM2_CAP_TPM_PROPERTIES), /* Capability */
>>> + tpm_u32(TPM2_PT_MANUFACTURER), /* Property */
>>> + tpm_u32(1), /* Property count */
>>> + };
>>> + u8 resp[TPM2_CMD_BUF_SIZE];
>>> + unsigned int value_off;
>>> +
>>> + ret = tcg2->submit_command(tcg2, 22, cmd,
>>> + TPM2_CMD_BUF_SIZE, resp);
>>> + if (ret != EFI_SUCCESS)
>>> + return ret;
>>> +
>>> + /*
>>> + * In the response buffer, the properties are located after the:
>>> + * tag (u16), response size (u32), response code (u32),
>>> + * YES/NO flag (u8), TPM_CAP (u32).
>>> + * The value is located after count (u32), property (u32).
>>> + */
>>> + value_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
>>> + sizeof(u8) + sizeof(u32) + sizeof(u32) + sizeof(u32);
>>> + *manufacturer_id = get_unaligned_be32(&resp[value_off]);
>>> +
>>> + return ret;
>>> +}
>>> +
>>> +/**
>>> + * Read the PCR from the TPM device
>>> + *
>>> + * @tcg2 tcg2 protocol
>>> + * @idx pcr index to read
>>> + * @return status code
>>> + */
>>> +static efi_status_t read_pcr(struct efi_tcg2_protocol *tcg2, u32 idx)
>>> +{
>>> + efi_status_t ret;
>>> + u8 idx_array_sz = 3; /* support 24 PCRs */
>>
>> This is a constant.
>>
>> #define IDX_ARRAY_SZ 3
>>
>> You can move it close to the TPM2_CMD_BUF_SIZE definition.
>>
>>> + u32 cmd_len = 17 + idx_array_sz;
>>> + u8 cmd[TPM2_CMD_BUF_SIZE] = {
>>> + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
>>> + tpm_u32(cmd_len), /* Length */
>>> + tpm_u32(TPM2_CC_PCR_READ), /* Command code */
>>> + /* TPML_PCR_SELECTION */
>>> + tpm_u32(1), /* Number of selections */
>>> + tpm_u16(TPM2_ALG_SHA256), /* Algorithm of the hash */
>>> + idx_array_sz, /* Array size for selection */
>>> + /* bitmap(idx), Selected PCR bitmap */
>>> + };
>>> + u8 resp[TPM2_CMD_BUF_SIZE];
>>> + u32 pcr_sel_idx = idx / 8;
>>> + u8 pcr_sel_bit = BIT(idx % 8);
>>> + u8 *dst;
>>> +
>>> + cmd[17 + pcr_sel_idx] = pcr_sel_bit;
>>> + ret = tcg2->submit_command(tcg2, cmd_len, cmd,
>>> + TPM2_CMD_BUF_SIZE, resp);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("tcg2->submit_command fail to read PCR\n");
>>> + return ret;
>>> + }
>>> +
>>> + dst = pcrs + (idx * TPM2_SHA256_DIGEST_SIZE);
>>> + boottime->copy_mem(dst, &resp[TPM2_PCR_READ_HEADER_SIZE],
>>> + TPM2_SHA256_DIGEST_SIZE);
>>> +
>>> + return ret;
>>> +}
>>> +
>>> +/**
>>> + * Compare the expected and actual pcrs
>>> + *
>>> + * @return status code
>>> + */
>>> +static int validate_pcrs(void)
>>> +{
>>> + u32 i;
>>> + u8 *expected = (u8 *)expected_pcrs;
>>> + u8 *result = pcrs;
>>
>> Making expected_pcrs and pcrs arrays with elements of size
>> TPM2_SHA256_DIGEST_SIZE can replace these pointers.
>>
>>> +
>>> + /*
>>> + * - Skip PCR[0] validation. PCR[0] contains U-Boot version measurement
>>> + * it contains the commit hash, so the measurement varies every build
>>> + * with different commit hash.
>>> + * - Skip PCR[7] validation. PCR[7] contains UEFI Secure Boot variables
>>> + * measurement. These variables can not be updated through efi_selftest and
>>> + * it varies depending on the platform.
>>
>> %s/it varies/vary/
>>
>>> + */
>>> + for (i = 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) {
>>
>> for (i = 1; i < (EFI_TCG2_MAX_PCR_INDEX + 1); ++i) {
>> if (i != 7)
>> continue;
>> if (memcmp(pcr[i], expected_pcr[i], PM2_SHA256_DIGEST_SIZE)) {
>> if (memcmp(expected, result, TPM2_SHA256_DIGEST_SIZE)) {
>> efi_st_printf("PCR[%d] is not the expected value\n", i);
>> return EFI_ST_FAILURE;
>> }
>> }
>> }
>>
>>> + result = pcrs + (TPM2_SHA256_DIGEST_SIZE * i);
>>> + if (i == 0 || i == 7) {
>>> + expected += TPM2_SHA256_DIGEST_SIZE;
>>> + result += TPM2_SHA256_DIGEST_SIZE;
>>> + continue; /* skip validation */
>>> + }
>>> + if (memcmp(expected, result, TPM2_SHA256_DIGEST_SIZE)) {
>>> + efi_st_printf("PCR[%d] is not the expected value\n", i);
>>> + return EFI_ST_FAILURE;
>>> + }
>>> + expected += TPM2_SHA256_DIGEST_SIZE;
>>> + result += TPM2_SHA256_DIGEST_SIZE;
>>> + }
>>>
>>> return EFI_ST_SUCCESS;
>>> }
>>> @@ -31,7 +680,8 @@ static int efi_st_tcg2_setup(const efi_handle_t img_handle,
>>> /**
>>> * efi_st_tcg2_execute() - execute test
>>> *
>>> - * Call the GetCapability service of the EFI_TCG2_PROTOCOL.
>>> + * Call EFI_TCG2_PROTOCOL services and check the
>>> + * Measured Boot behavior.
>>> *
>>> * Return: status code
>>> */
>>> @@ -40,12 +690,22 @@ static int efi_st_tcg2_execute(void)
>>> struct efi_tcg2_protocol *tcg2;
>>> struct efi_tcg2_boot_service_capability capability;
>>> efi_status_t ret;
>>> + u32 active_pcr_banks;
>>> + u64 eventlog, eventlog_last_entry;
>>> + bool eventlog_truncated;
>>> + efi_handle_t handle;
>>> + efi_uintn_t exit_data_size = 0;
>>> + u16 *exit_data = NULL;
>>> + u32 i;
>>> + u32 manufacturer_id;
>>>
>>> ret = boottime->locate_protocol(&guid_tcg2, NULL, (void **)&tcg2);
>>> if (ret != EFI_SUCCESS) {
>>> efi_st_error("TCG2 protocol is not available.\n");
>>> return EFI_ST_FAILURE;
>>> }
>>> +
>>> + /* EFI_TCG2_PROTOCOL.GetCapability test */
>>> capability.size = sizeof(struct efi_tcg2_boot_service_capability) - 1;
>>> ret = tcg2->get_capability(tcg2, &capability);
>>> if (ret != EFI_BUFFER_TOO_SMALL) {
>>> @@ -64,12 +724,154 @@ static int efi_st_tcg2_execute(void)
>>> }
>>> efi_st_printf("TPM supports 0x%.8x event logs\n",
>>> capability.supported_event_logs);
>>> +
>>> + /* EFI_TCG2_PROTOCOL.GetActivePcrBanks test */
>>> + ret = tcg2->get_active_pcr_banks(tcg2, &active_pcr_banks);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("tcg2->get_active_pcr_banks failed\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> + if (active_pcr_banks != capability.active_pcr_banks) {
>>> + efi_st_error("tcg2->get_active_pcr_banks return wrong value\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> +
>>> + /* EFI_TCG2_PROTOCOL.HashLogExtendEvent test */
>>> + ret = tcg2->hash_log_extend_event(tcg2, EFI_TCG2_EXTEND_ONLY,
>>> + (uintptr_t)image,
>>> + img.length, efi_tcg2_event);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("tcg2->hash_log_extend_event(EXTEND_ONLY) failed\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> +
>>> + ret = tcg2->hash_log_extend_event(tcg2, PE_COFF_IMAGE, (uintptr_t)image,
>>> + img.length, efi_tcg2_event);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("tcg2->hash_log_extend_event(PE_COFF_IMAGE) failed\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> +
>>> + /* EFI_TCG2_PROTOCOL.SubmitCommand test */
>>> + ret = get_manufacturer_id(tcg2, &manufacturer_id);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("get_manufacturer_id failed\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> + if (capability.manufacturer_id != manufacturer_id) {
>>> + efi_st_error("tcg2->submit_command test failed\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> +
>>> + /* tcg2_measure_pe_image test */
>>> + ret = boottime->load_image(false, image_handle, NULL, image,
>>> + img.length, &handle);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("Failed to load image\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> +
>>> + /* measure ready_to_boot event(boot variables, smbios table, etc.) */
>>> + /* TODO: add GPT measurement test */
>>
>> lib/efi_selftest/efi_selftest_block_device.c shows how to setup a memory
>> based block device.
>
> Thank you for the information.
> I tried to copy efi_selftest_block_device but I encountered error.
>
> To test GPT measurement, I need to add the device path node having
> following type.
> dp->type == DEVICE_PATH_TYPE_MEDIA_DEVICE
> dp->sub_type == DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH
> If I added this node in the device path,
> boottime->connect_controller() returns EFI_NOT_FOUND
> and I'm investigating how to use connect_controller.
>
> For other comments, I will include fixes in the next version.
>
> Thanks,
> Masahisa Kojima
>
>>
>>> + ret = boottime->start_image(handle, &exit_data_size, &exit_data);
>>> + if (ret != EFI_UNSUPPORTED) {
>>> + efi_st_error("Wrong return value from application\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> + ret = boottime->free_pool(exit_data);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("Failed to free exit data\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> +
>>> + /* validate PCR read from the TPM device */
>>> + for (i = 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) {
>>> + ret = read_pcr(tcg2, i);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("read pcr error\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> + }
>>> + if (validate_pcrs()) {
>>> + efi_st_error("PCR validation failed\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> +
>>> + /* EFI_TCG2_PROTOCOL.GetEventLog test */
>>> + ret = tcg2->get_eventlog(tcg2, TCG2_EVENT_LOG_FORMAT_TCG_2, &eventlog,
>>> + &eventlog_last_entry, &eventlog_truncated);
>>> + if (ret != EFI_SUCCESS) {
>>> + efi_st_error("tcg2->get_eventlog failed\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> + /* TODO: eventlog format check */
>>> +
>>> return EFI_ST_SUCCESS;
>>> }
>>>
>>> +/*
>>> + * Tear down unit test.
>>
>> /**
>> * efi_st_tcg2_teardown() - tear down unit test
>> *
>>
>> Overall the design looks good to me.
>>
>> Best regards
>>
>> Heinrich
>>
>>> + *
>>> + * @return: EFI_ST_SUCCESS for success
>>> + */
>>> +static int efi_st_tcg2_teardown(void)
>>> +{
>>> + efi_status_t r = EFI_ST_SUCCESS;
>>> +
>>> + if (image) {
>>> + r = boottime->free_pool(image);
>>> + if (r != EFI_SUCCESS) {
>>> + efi_st_error("Failed to free image\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> + }
>>> + if (efi_tcg2_event) {
>>> + r = boottime->free_pool(efi_tcg2_event);
>>> + if (r != EFI_SUCCESS) {
>>> + efi_st_error("Failed to free efi_tcg2_event\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> + }
>>> + if (pcrs) {
>>> + r = boottime->free_pool(pcrs);
>>> + if (r != EFI_SUCCESS) {
>>> + efi_st_error("Failed to free pcr\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> + }
>>> +
>>> + r = restore_boot_variable();
>>> + if (r != EFI_SUCCESS) {
>>> + efi_st_error("Failed to restore boot variables\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> +
>>> + /*
>>> + * Restore SMBIOS table
>>> + * If orig_smbios_table is NULL, calling install_configuration_table()
>>> + * removes dummy SMBIOS table form systab.
>>> + */
>>> + r = boottime->install_configuration_table(&smbios_guid, orig_smbios_table);
>>> + if (r != EFI_SUCCESS) {
>>> + efi_st_error("Failed to restore SMBOIS table\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> +
>>> + if (dmi_addr) {
>>> + r = boottime->free_pages(dmi_addr, 1);
>>> + if (r != EFI_SUCCESS) {
>>> + efi_st_error("Failed to free dummy smbios table\n");
>>> + return EFI_ST_FAILURE;
>>> + }
>>> + }
>>> +
>>> + return r;
>>> +}
>>> +
>>> EFI_UNIT_TEST(tcg2) = {
>>> .name = "tcg2",
>>> .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
>>> .execute = efi_st_tcg2_execute,
>>> .setup = efi_st_tcg2_setup,
>>> + .teardown = efi_st_tcg2_teardown,
>>> };
>>>
More information about the U-Boot
mailing list