From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 512D8C433F5 for ; Mon, 25 Oct 2021 09:43:49 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5A51360EFF for ; Mon, 25 Oct 2021 09:43:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 5A51360EFF Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmx.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 701A1834A2; Mon, 25 Oct 2021 11:43:45 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=gmx.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; secure) header.d=gmx.net header.i=@gmx.net header.b="Dax1S/3y"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8640283458; Mon, 25 Oct 2021 11:43:42 +0200 (CEST) Received: from mout.gmx.net (mout.gmx.net [212.227.17.21]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 9EDCE8128D for ; Mon, 25 Oct 2021 11:43:34 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmx.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=xypron.glpk@gmx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1635155012; bh=Vm4jTA09Hh0RV70WXeDBIhoG+7H+ukTXI0Nupw7xJQc=; h=X-UI-Sender-Class:Date:Subject:To:Cc:References:From:In-Reply-To; b=Dax1S/3yPGIuIix31mHsJwthG0ixRHtxoiUZjKQ+HMP/ey/LNyv/qqgee42p3xnsO zGmV+MgCszfT1ORXo1uGvur/zwnd3CKs7LBxm+f13Mbl0+xW1cXyUawX5Lqm9gO39J s2jtZW/o1xZg26ZcsWJ1UfScwciSXd8IL9CgEenM= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from [192.168.123.55] ([88.152.144.157]) by mail.gmx.net (mrgmx104 [212.227.17.168]) with ESMTPSA (Nemesis) id 1N7i8Y-1mioQY20fK-014nT8; Mon, 25 Oct 2021 11:43:32 +0200 Message-ID: Date: Mon, 25 Oct 2021 11:43:27 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.1.2 Subject: Re: [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot Content-Language: en-US To: Masahisa Kojima Cc: Ilias Apalodimas , Simon Glass , Alexander Graf , U-Boot Mailing List References: <20211022112426.25009-1-masahisa.kojima@linaro.org> <20211022112426.25009-3-masahisa.kojima@linaro.org> <529ad108-bdea-e901-9e08-1a587b443b1b@gmx.de> From: Heinrich Schuchardt In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:Nc3biLRSfySJeCJahuIcmNT3pZNeLZhi8n3mcrw/NY5KIV8GT3u dHFH/tyVhoncCvF8J1YatJcKUAMQcxVT3NWZfoqIaCGHjTKLSMiZV7HIjjQRbKpIKpEa5Wz w4qam9V8Kljs7oCAldxD3911z3Q4+a0Nn0YLQuu7LF9eNoOp+MkooVu6msj+txU4OLSbNOe SNie0LEdZjBeGJ09SVI0A== X-UI-Out-Filterresults: notjunk:1;V03:K0:JfdB3eKJ3SU=:iJd8TRTZq6bryTRnmHLHZQ GfhvOLgF/kc/FjwgH8cvr4+HU04iiPVl0FsofSAYrEW9VjlJS+ZhzrMofLq1tayxxC1zwT6P5 jYoDrQvojlL0k1cv8vLU0uImSM9jmuqLaiBl8MSQBXf2U6EDW3koLUqntcnR5OCY83Q8Kz0ac OhyolsJycWkKHS4O2Bj/YL9Atk2+ORBMv9dYc3LsF04sxEQTpRCYdDN9Lndl1N10FmVn8dws/ e4p5QXpx3hMJ+U8KGDG/2Bkqf7f6mhRKKTZNYwskKkJAE77A+29iZsDDyUDZNzW1bfvKz9pcV 0SvI1juD2x2Jfj8eJU1cuKy2SwqoohJmCCJrCaDMLCollSWteQ8ekkhqTR66iBnUyOD3tKpre C66yyQEZmsLQ2GAZlb9NdEbdkXh/wTLUbdL7oQRRJFfIwVzm4B5PVnFONbsFk/8vQiuuyjGWG I3aeOAAfBQCqWpgX8XXc0Bu3vzXC8VaM4vqr6F5lXTDIJ3sA+LRQG1RVOEal1eAtKY+8pfGv1 kY5B8mQe7Ay846PSbwG/db1Gz222eI4lb3h0X3q4uzf2aLlBkcDnF9DYpY8ea94JvwUrC1Mhk h4ypWOGF98ji5so6Ef46tQDo60mxq0POyM78GUxSB3VZPSCQd0BDTppp1zugBdR6Y8bYUGyQW n6nJp0vRP0PrnyqcFoaIckYvC588YtcTeSqA0lD1GfoML/Pd7scdwdjQBEX0bFl768VZwk/CG MEzYKVocqRCTyoAhr6+OvJfb6gkY1EzCY+HiRrDG4xCx6dIo/fKN7NpW619n24ZUkQK8RV6Ge S5AMLS2zbV30i0qfVNyGaTC92ArswJwvXr0mVhh/nxCKZTZ3VbXT1D5jLaV1jUJBh60IxfyWG onlFoKxLR+L4I2iCVPaeBju2wrT933G0xSqkfXCgAkjVj6IclOuBRjH1yVyWKsO2gagq5OzrM ovFYMZeTMp8xlYqGikTwItekLHQQOrX+BRuJrP5fIeUJDCQdsElfHcAueu4t7tRqor1QUEFPl LG0jI7+IilfeOAIFNUgTwy+PdjHhW5Qcj5Q8zf/T+ZUHPy+X/PMQcSUGiWDeP6pM6AIwqioNf k2ecnkq7Zo1KfE= X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean On 10/25/21 09:59, Masahisa Kojima wrote: > On Sat, 23 Oct 2021 at 18:42, Heinrich Schuchardt w= rote: >> >> >> >> 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 >>> --- >>> 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_measuredbo= ot.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 :=3D $(CFLAG= S_EFI) -Os -ffreestanding >>> CFLAGS_REMOVE_efi_selftest_miniapp_exception.o :=3D $(CFLAGS_NON_EF= I) >>> CFLAGS_efi_selftest_miniapp_exit.o :=3D $(CFLAGS_EFI) -Os -ffreesta= nding >>> CFLAGS_REMOVE_efi_selftest_miniapp_exit.o :=3D $(CFLAGS_NON_EFI) >>> +CFLAGS_efi_selftest_miniapp_measuredboot.o :=3D $(CFLAGS_EFI) -Os -ff= reestanding >>> +CFLAGS_REMOVE_efi_selftest_miniapp_measuredboot.o :=3D $(CFLAGS_NON_E= FI) >>> CFLAGS_efi_selftest_miniapp_return.o :=3D $(CFLAGS_EFI) -Os -ffrees= tanding >>> CFLAGS_REMOVE_efi_selftest_miniapp_return.o :=3D $(CFLAGS_NON_EFI) >>> CFLAGS_initrddump_exit.o :=3D $(CFLAGS_EFI) -Os -ffreestanding >>> @@ -78,9 +80,11 @@ obj-$(CONFIG_EFI_ESRT) +=3D efi_selftest_esrt.o >>> targets +=3D \ >>> 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_s= elftest_miniapp_exit.efi >>> $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exi= t.efi > \ >>> $(obj)/efi_miniapp_file_image_exit.h >>> >>> +$(obj)/efi_miniapp_file_image_measuredboot.h: $(obj)/efi_selftest_min= iapp_measuredboot.efi >>> + $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_meas= uredboot.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_ret= urn.efi > \ >>> $(obj)/efi_miniapp_file_image_return.h >>> @@ -112,3 +120,5 @@ $(obj)/efi_selftest_loadimage.o: $(obj)/efi_miniap= p_file_image_exit.h >>> $(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_imag= e_exit.h >>> >>> $(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_im= age_return.h >>> + >>> +$(obj)/efi_selftest_tcg2.o: $(obj)/efi_miniapp_file_image_measuredboo= t.h >>> diff --git a/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c b/li= b/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 measur= emt > 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 existin= g 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 =3D=3D 32) #include efi_miniapp_tcg2_riscv32.h #elif defined(__riscv) && (__riscv_xlen =3D=3D 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 >>> +#include >>> + >>> +static efi_guid_t loaded_image_protocol_guid =3D EFI_LOADED_IMAGE_PRO= TOCOL_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 *sys= table) >>> +{ >>> + struct efi_simple_text_output_protocol *cout =3D systable->con_o= ut; >>> + struct efi_boot_services *boottime =3D systable->boottime; >>> + struct efi_loaded_image *loaded_image_protocol; >>> + efi_status_t ret; >>> + >>> + /* >>> + * Open the loaded image protocol. >>> + */ >>> + ret =3D boottime->open_protocol >>> + (image_handle, &loaded_image_protocol_gu= id, >>> + (void **)&loaded_image_protocol, NULL, >>> + NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); >>> + if (ret !=3D EFI_SUCCESS) { >>> + cout->output_string(cout, >>> + L"Could not open loaded image protoc= ol"); >>> + return ret; >>> + } >>> + if ((void *)check_loaded_image_protocol < >>> + loaded_image_protocol->image_base || >>> + (void *)check_loaded_image_protocol >=3D >>> + 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 =3D systable->co= n_out; >>> + efi_status_t ret; >>> + u16 text[] =3D EFI_ST_SUCCESS_STR; >>> + >>> + con_out->output_string(con_out, L"EFI application calling Exit\n= "); >>> + >>> + if (check_loaded_image_protocol(handle, systable) !=3D EFI_SUCCE= SS) { >>> + con_out->output_string(con_out, >>> + L"Loaded image protocol missing\n= "); >>> + ret =3D EFI_NOT_FOUND; >>> + goto out; >>> + } >>> + >>> + /* This return value is expected by the calling test */ >>> + ret =3D 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/e= fi_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 >>> #include >>> +/* 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 >>> +#include >>> +#include >>> +#include >>> >>> static struct efi_boot_services *boottime; >>> static const efi_guid_t guid_tcg2 =3D 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 =3D 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/grubaa6= 4.efi" */ >>> +static const u8 boot_1000[] =3D { >>> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x0= 0, >>> +0x74, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x7= 3, >>> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf= 3, >>> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xa= d, >>> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x0= 4, >>> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0= 0, >>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5= 7, >>> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xf= a, >>> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x4= 5, >>> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6= 2, >>> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x7= 2, >>> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x3= 4, >>> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7= f, >>> +0xff, 0x04, 0x00 }; >>> + >>> +/* "efidebug boot add -b 1001 test1001 virtio 0:1 /EFI/debian/grubaa6= 4.efi" */ >>> +static const u8 boot_1001[] =3D { >>> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x0= 0, >>> +0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x7= 3, >>> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf= 3, >>> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xa= d, >>> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x0= 4, >>> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0= 0, >>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5= 7, >>> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xf= a, >>> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x4= 5, >>> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6= 2, >>> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x7= 2, >>> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x3= 4, >>> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7= f, >>> +0xff, 0x04, 0x00 }; >>> + >>> +/* "efidebug boot add -b 1002 test1002 virtio 0:1 /EFI/debian/grubaa6= 4.efi" */ >>> +static const u8 boot_1002[] =3D { >>> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x0= 0, >>> +0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x7= 3, >>> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf= 3, >>> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xa= d, >>> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x0= 4, >>> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0= 0, >>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5= 7, >>> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xf= a, >>> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x4= 5, >>> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6= 2, >>> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x7= 2, >>> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x3= 4, >>> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7= f, >>> +0xff, 0x04, 0x00}; >>> + >>> +/* "efidebug boot order 1002 1000 1001" */ >>> +static u8 boot_order[] =3D {0x02, 0x10, 0x00, 0x10, 0x01, 0x10}; >>> + >>> +static void *orig_smbios_table; >>> +static u64 dmi_addr =3D U32_MAX; >>> +#define SMBIOS_ENTRY_HEADER_SIZE 0x20 >>> +/* smbios table for the measurement test */ >>> +static u8 smbios_table_test[] =3D { >>> +0x5f, 0x53, 0x4d, 0x5f, 0x2c, 0x1f, 0x03, 0x00, 0x54, 0x00, 0x00, 0x0= 0, >>> +0x00, 0x00, 0x00, 0x00, 0x5f, 0x44, 0x4d, 0x49, 0x5f, 0xe4, 0x5c, 0x0= 1, >>> +0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x0= 0, >>> +0x01, 0x02, 0x00, 0x00, 0x03, 0x00, 0x80, 0x08, 0x01, 0x00, 0x00, 0x0= 0, >>> +0x00, 0x00, 0x00, 0x0c, 0x15, 0x0a, 0xff, 0xff, 0x55, 0x2d, 0x42, 0x6= f, >>> +0x6f, 0x74, 0x00, 0x32, 0x30, 0x32, 0x31, 0x2e, 0x31, 0x30, 0x2d, 0x7= 2, >>> +0x63, 0x34, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x35, 0x2d, 0x67, 0x37, 0x3= 2, >>> +0x37, 0x63, 0x33, 0x66, 0x33, 0x32, 0x35, 0x39, 0x2d, 0x64, 0x69, 0x7= 2, >>> +0x74, 0x79, 0x00, 0x31, 0x30, 0x2f, 0x30, 0x31, 0x2f, 0x32, 0x30, 0x3= 2, >>> +0x31, 0x00, 0x00, 0x01, 0x1b, 0x01, 0x00, 0x01, 0x02, 0x00, 0x03, 0x3= 1, >>> +0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x00, 0x00, 0x00, 0x0= 0, >>> +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x7= 7, >>> +0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x7= 2, >>> +0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x3= 6, >>> +0x37, 0x38, 0x00, 0x00, 0x02, 0x0e, 0x02, 0x00, 0x01, 0x02, 0x00, 0x0= 4, >>> +0x03, 0x01, 0x01, 0x01, 0x00, 0x0a, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x7= 7, >>> +0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x7= 2, >>> +0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3= 3, >>> +0x33, 0x33, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x0= 0, >>> +0x00, 0x03, 0x15, 0x03, 0x00, 0x01, 0x03, 0x00, 0x02, 0x03, 0x03, 0x0= 3, >>> +0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x6= e, >>> +0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x3= 6, >>> +0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x0= 0, >>> +0x00, 0x04, 0x30, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x00, 0x0= 0, >>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0= 0, >>> +0x00, 0x01, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x03, 0x0= 4, >>> +0x04, 0x04, 0x08, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0= 1, >>> +0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x3= 3, >>> +0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3= 3, >>> +0x33, 0x33, 0x00, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x0= 0, >>> +0x00, 0x20, 0x0b, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0= 0, >>> +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_DIGES= T_SIZE] =3D { >>> + {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[] =3D { >>> + {u"BootOrder", NULL, 0, DEFAULT_ATTR, boot_order, sizeo= f(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 =3D boottime->allocate_pool(EFI_LOADER_DATA, img.length, >>> + (void **)&buf); >>> + if (ret !=3D EFI_SUCCESS) { >>> + efi_st_error("Out of memory\n"); >>> + return ret; >>> + } >>> + boottime->set_mem(buf, img.length, 0); >>> + >>> + for (i =3D 0; ; ++i) { >>> + if (!img.lines[i].line) >>> + break; >>> + addr =3D img.lines[i].addr; >>> + len =3D COMPRESSED_DISK_IMAGE_BLOCK_SIZE; >>> + if (addr + len > img.length) >>> + len =3D img.length - addr; >>> + boottime->copy_mem(buf + addr, img.lines[i].line, len); >>> + } >>> + *image =3D buf; >>> + return ret; >>> +} >>> + >>> +/* >>> + * Configure dummy boot variables. >> >> /** >> * efi_status_t setup_boot_variable() - configure dummy boot variable= s >> * >> * 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 =3D 0; i < ARRAY_SIZE(boot_variable_test); i++) { >>> + size =3D 1; >> >> Please, set size to 0. >> >>> + ret =3D 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 =3D 0. >> >>> + if (ret =3D=3D EFI_BUFFER_TOO_SMALL) { >>> + /* Variable exists, save the current vaiable */ >> >> %s/vaiable/value/ >> >>> + boot_variable_test[i].size =3D size; >>> + ret =3D boottime->allocate_pool(EFI_LOADER_DATA, >>> + boot_variable_test= [i].size, >>> + (void **)&boot_var= iable_test[i].buf); >>> + if (ret !=3D EFI_SUCCESS) { >>> + efi_st_error("fail to allocate buffer fo= r boot variable\n"); >> >> In all other tests we use 'Failed to' >> >> %s/fail/Failed/ >> >>> + return ret; >>> + } >>> + ret =3D 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 !=3D EFI_SUCCESS) { >>> + efi_st_error("fail to get current boot v= ariable\n"); >> >> %s/fail/Failed/ >> >> >>> + return ret; >>> + } >>> + } >>> + >>> + /* set boot variable for the measurement test */ >>> + ret =3D runtime->set_variable(boot_variable_test[i].name= , >>> + &efi_global_variable_guid, >>> + boot_variable_test[i].attr, >>> + boot_variable_test[i].test_d= ata_size, >>> + boot_variable_test[i].test_d= ata); >>> + if (ret !=3D 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 =3D 0; i < ARRAY_SIZE(boot_variable_test); i++) { >>> + if (boot_variable_test[i].buf) { >>> + ret =3D 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 !=3D EFI_SUCCESS) { >>> + efi_st_error("### fail to restore boot v= ariable\n"); >>> + return ret; >>> + } >>> + ret =3D boottime->free_pool(boot_variable_test[i= ].buf); >>> + if (ret !=3D EFI_SUCCESS) { >>> + efi_st_error("Failed to free boot variab= le\n"); >>> + return ret; >>> + } >>> + } else { >>> + /* delete the variable used only for testing */ >>> + ret =3D runtime->set_variable(boot_variable_test= [i].name, >>> + &efi_global_variable= _guid, >>> + 0, 0, NULL); >>> + if (ret !=3D EFI_SUCCESS) { >>> + efi_st_error("### fail to delete boot va= riable\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 *systabl= e) >>> +{ >>> + u32 i; >>> + >>> + for (i =3D 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 *systab= le) >>> +{ >>> + 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 =3D find_smbios_table(systable); >>> + >>> + /* Reserve 4kiB page for SMBIOS */ >>> + ret =3D boottime->allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, >>> + EFI_RUNTIME_SERVICES_DATA, 1, &dmi_addr= ); >>> + >>> + if (ret !=3D EFI_SUCCESS) { >>> + /* Could not find space in lowmem, use highmem instead *= / >>> + ret =3D boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES, >>> + EFI_RUNTIME_SERVICES_DATA, 1, >>> + &dmi_addr); >>> + >>> + if (ret !=3D EFI_SUCCESS) >>> + return ret; >>> + } >>> + >>> + dmi =3D (void *)(uintptr_t)dmi_addr; >>> + se =3D dmi; >>> + boottime->copy_mem(se, smbios_table_test, sizeof(smbios_table_te= st)); >>> + >>> + /* update smbios table start address */ >>> + se->struct_table_address =3D (uintptr_t)((u8 *)dmi + SMBIOS_ENTR= Y_HEADER_SIZE); >>> + >>> + /* calculate checksums */ >>> + istart =3D (char *)se + SMBIOS_INTERMEDIATE_OFFSET; >>> + isize =3D sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFS= ET; >>> + se->intermediate_checksum =3D table_compute_checksum(istart, isi= ze); >>> + se->checksum =3D table_compute_checksum(se, sizeof(struct smbios= _entry)); >>> + >>> + /* Install SMBIOS information as configuration table */ >>> + ret =3D boottime->install_configuration_table(&smbios_guid, dmi)= ; >>> + if (ret !=3D 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 =3D EFI_TCG2_PR= OTOCOL_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 =3D img_handle; >>> boottime =3D systable->boottime; >>> + runtime =3D systable->runtime; >>> + >>> + /* Load the application image into memory */ >>> + decompress(&image); >>> + >>> + ret =3D boottime->allocate_pool(EFI_LOADER_DATA, >>> + sizeof(struct efi_tcg2_event) + >>> + sizeof(struct uefi_image_load_even= t), >>> + (void **)&efi_tcg2_event); >>> + if (!efi_tcg2_event) >>> + return EFI_ST_FAILURE; >>> + >>> + efi_tcg2_event->size =3D sizeof(struct efi_tcg2_event) + >>> + sizeof(struct uefi_image_load_event); >>> + efi_tcg2_event->header.header_size =3D sizeof(struct efi_tcg2_ev= ent_header); >>> + efi_tcg2_event->header.header_version =3D 1; >>> + efi_tcg2_event->header.pcr_index =3D 6; >>> + efi_tcg2_event->header.event_type =3D EV_EFI_RUNTIME_SERVICES_DR= IVER; >>> + image_load_event.image_location_in_memory =3D 0x12345678; >>> + image_load_event.image_length_in_memory =3D 0x300000; >>> + image_load_event.image_link_time_address =3D 0x87654321; >>> + image_load_event.length_of_device_path =3D 0; >>> + boottime->copy_mem(efi_tcg2_event->event, &image_load_event, >>> + sizeof(struct uefi_image_load_event)); >>> + >>> + ret =3D setup_boot_variable(); >>> + if (ret !=3D EFI_SUCCESS) >>> + return EFI_ST_FAILURE; >>> + >>> + ret =3D setup_smbios_table(systable); >>> + if (ret !=3D EFI_SUCCESS) >>> + return EFI_ST_FAILURE; >>> + >>> + ret =3D 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_SHA2= 56_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 *tcg= 2, u32 *manufacturer_id) >>> +{ >>> + efi_status_t ret; >>> + u8 cmd[TPM2_CMD_BUF_SIZE] =3D { >>> + 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 =3D tcg2->submit_command(tcg2, 22, cmd, >>> + TPM2_CMD_BUF_SIZE, resp); >>> + if (ret !=3D 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 =3D sizeof(u16) + sizeof(u32) + sizeof(u32) + >>> + sizeof(u8) + sizeof(u32) + sizeof(u32) + sizeof= (u32); >>> + *manufacturer_id =3D 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 =3D 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 =3D 17 + idx_array_sz; >>> + u8 cmd[TPM2_CMD_BUF_SIZE] =3D { >>> + 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 select= ion */ >>> + /* bitmap(idx), Selected PCR bitmap *= / >>> + }; >>> + u8 resp[TPM2_CMD_BUF_SIZE]; >>> + u32 pcr_sel_idx =3D idx / 8; >>> + u8 pcr_sel_bit =3D BIT(idx % 8); >>> + u8 *dst; >>> + >>> + cmd[17 + pcr_sel_idx] =3D pcr_sel_bit; >>> + ret =3D tcg2->submit_command(tcg2, cmd_len, cmd, >>> + TPM2_CMD_BUF_SIZE, resp); >>> + if (ret !=3D EFI_SUCCESS) { >>> + efi_st_error("tcg2->submit_command fail to read PCR\n"); >>> + return ret; >>> + } >>> + >>> + dst =3D 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 =3D (u8 *)expected_pcrs; >>> + u8 *result =3D 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 mea= surement >>> + * it contains the commit hash, so the measurement varies eve= ry build >>> + * with different commit hash. >>> + * - Skip PCR[7] validation. PCR[7] contains UEFI Secure Boot v= ariables >>> + * measurement. These variables can not be updated through ef= i_selftest and >>> + * it varies depending on the platform. >> >> %s/it varies/vary/ >> >>> + */ >>> + for (i =3D 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) { >> >> for (i =3D 1; i < (EFI_TCG2_MAX_PCR_INDEX + 1); ++i) { >> if (i !=3D 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 =3D pcrs + (TPM2_SHA256_DIGEST_SIZE * i); >>> + if (i =3D=3D 0 || i =3D=3D 7) { >>> + expected +=3D TPM2_SHA256_DIGEST_SIZE; >>> + result +=3D 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 +=3D TPM2_SHA256_DIGEST_SIZE; >>> + result +=3D 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 =3D 0; >>> + u16 *exit_data =3D NULL; >>> + u32 i; >>> + u32 manufacturer_id; >>> >>> ret =3D boottime->locate_protocol(&guid_tcg2, NULL, (void **)&t= cg2); >>> if (ret !=3D EFI_SUCCESS) { >>> efi_st_error("TCG2 protocol is not available.\n"); >>> return EFI_ST_FAILURE; >>> } >>> + >>> + /* EFI_TCG2_PROTOCOL.GetCapability test */ >>> capability.size =3D sizeof(struct efi_tcg2_boot_service_capabil= ity) - 1; >>> ret =3D tcg2->get_capability(tcg2, &capability); >>> if (ret !=3D 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 =3D tcg2->get_active_pcr_banks(tcg2, &active_pcr_banks); >>> + if (ret !=3D EFI_SUCCESS) { >>> + efi_st_error("tcg2->get_active_pcr_banks failed\n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + if (active_pcr_banks !=3D capability.active_pcr_banks) { >>> + efi_st_error("tcg2->get_active_pcr_banks return wrong va= lue\n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + >>> + /* EFI_TCG2_PROTOCOL.HashLogExtendEvent test */ >>> + ret =3D tcg2->hash_log_extend_event(tcg2, EFI_TCG2_EXTEND_ONLY, >>> + (uintptr_t)image, >>> + img.length, efi_tcg2_event); >>> + if (ret !=3D EFI_SUCCESS) { >>> + efi_st_error("tcg2->hash_log_extend_event(EXTEND_ONLY) f= ailed\n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + >>> + ret =3D tcg2->hash_log_extend_event(tcg2, PE_COFF_IMAGE, (uintpt= r_t)image, >>> + img.length, efi_tcg2_event); >>> + if (ret !=3D 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 =3D get_manufacturer_id(tcg2, &manufacturer_id); >>> + if (ret !=3D EFI_SUCCESS) { >>> + efi_st_error("get_manufacturer_id failed\n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + if (capability.manufacturer_id !=3D manufacturer_id) { >>> + efi_st_error("tcg2->submit_command test failed\n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + >>> + /* tcg2_measure_pe_image test */ >>> + ret =3D boottime->load_image(false, image_handle, NULL, image, >>> + img.length, &handle); >>> + if (ret !=3D 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 memor= y >> 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 =3D=3D DEVICE_PATH_TYPE_MEDIA_DEVICE > dp->sub_type =3D=3D 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 =3D boottime->start_image(handle, &exit_data_size, &exit_dat= a); >>> + if (ret !=3D EFI_UNSUPPORTED) { >>> + efi_st_error("Wrong return value from application\n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + ret =3D boottime->free_pool(exit_data); >>> + if (ret !=3D EFI_SUCCESS) { >>> + efi_st_error("Failed to free exit data\n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + >>> + /* validate PCR read from the TPM device */ >>> + for (i =3D 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) { >>> + ret =3D read_pcr(tcg2, i); >>> + if (ret !=3D 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 =3D tcg2->get_eventlog(tcg2, TCG2_EVENT_LOG_FORMAT_TCG_2, &e= ventlog, >>> + &eventlog_last_entry, &eventlog_truncat= ed); >>> + if (ret !=3D 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 =3D EFI_ST_SUCCESS; >>> + >>> + if (image) { >>> + r =3D boottime->free_pool(image); >>> + if (r !=3D EFI_SUCCESS) { >>> + efi_st_error("Failed to free image\n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + } >>> + if (efi_tcg2_event) { >>> + r =3D boottime->free_pool(efi_tcg2_event); >>> + if (r !=3D EFI_SUCCESS) { >>> + efi_st_error("Failed to free efi_tcg2_event\n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + } >>> + if (pcrs) { >>> + r =3D boottime->free_pool(pcrs); >>> + if (r !=3D EFI_SUCCESS) { >>> + efi_st_error("Failed to free pcr\n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + } >>> + >>> + r =3D restore_boot_variable(); >>> + if (r !=3D 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_t= able() >>> + * removes dummy SMBIOS table form systab. >>> + */ >>> + r =3D boottime->install_configuration_table(&smbios_guid, orig_s= mbios_table); >>> + if (r !=3D EFI_SUCCESS) { >>> + efi_st_error("Failed to restore SMBOIS table\n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + >>> + if (dmi_addr) { >>> + r =3D boottime->free_pages(dmi_addr, 1); >>> + if (r !=3D EFI_SUCCESS) { >>> + efi_st_error("Failed to free dummy smbios table\= n"); >>> + return EFI_ST_FAILURE; >>> + } >>> + } >>> + >>> + return r; >>> +} >>> + >>> EFI_UNIT_TEST(tcg2) =3D { >>> .name =3D "tcg2", >>> .phase =3D EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, >>> .execute =3D efi_st_tcg2_execute, >>> .setup =3D efi_st_tcg2_setup, >>> + .teardown =3D efi_st_tcg2_teardown, >>> }; >>>