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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 61A3CC001DB for ; Mon, 7 Aug 2023 14:57:25 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 7C58E833DC; Mon, 7 Aug 2023 16:57:23 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=linux.ibm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=ibm.com header.i=@ibm.com header.b="e5uGVJ8L"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A0E438468A; Mon, 7 Aug 2023 16:57:22 +0200 (CEST) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id EEDDC807B1 for ; Mon, 7 Aug 2023 16:57:19 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=linux.ibm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=eajames@linux.ibm.com Received: from pps.filterd (m0353728.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 377EsdtG003275; Mon, 7 Aug 2023 14:57:09 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=message-id : date : subject : to : cc : references : from : in-reply-to : content-type : content-transfer-encoding : mime-version; s=pp1; bh=ER/MzvZs8ve5P8/f0rIl8sJCp+2aF5h/m9iQO6f+mWY=; b=e5uGVJ8LX0h2oc50VDEJS4h6sdNkH8unNiuWlO0buixiHaxugeKsEMqFjZ7Qt2fhDxSd J1ynDujhYiwGAkL5/tGvHS0n+OzYeLp5zWvthlNVMqKxd9fxzzV1j03nTJS9k5V574A2 +0vYxPDR99N0ekTeYhs1rEY6ZxnlrFRZL2/divqzRvbWYOv8x8tHDP4MJWB3elhHgXIj rPyGxaQbTPj0o9I0oo9xHqeCqg+DN6Z7vfh9tKWuPNhMErR1Ynq5NxPfC4/+kDS9jw4d MvmS33R//lx4hvTKjKCGaqVIay5z4aYySBZVoqh8rZ+BbYwLYqti3Pc0INUKazNcDAbG bA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3sb2su81ce-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 07 Aug 2023 14:57:08 +0000 Received: from m0353728.ppops.net (m0353728.ppops.net [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 377EtFYU004774; Mon, 7 Aug 2023 14:57:08 GMT Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3sb2su81c5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 07 Aug 2023 14:57:08 +0000 Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 377DLTO3000363; Mon, 7 Aug 2023 14:57:06 GMT Received: from smtprelay02.wdc07v.mail.ibm.com ([172.16.1.69]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 3sa28k5u1m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 07 Aug 2023 14:57:06 +0000 Received: from smtpav04.dal12v.mail.ibm.com (smtpav04.dal12v.mail.ibm.com [10.241.53.103]) by smtprelay02.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 377Ev6Cn1442354 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 7 Aug 2023 14:57:06 GMT Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1BD1658056; Mon, 7 Aug 2023 14:57:06 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CF68558052; Mon, 7 Aug 2023 14:57:05 +0000 (GMT) Received: from [9.61.130.18] (unknown [9.61.130.18]) by smtpav04.dal12v.mail.ibm.com (Postfix) with ESMTP; Mon, 7 Aug 2023 14:57:05 +0000 (GMT) Message-ID: Date: Mon, 7 Aug 2023 09:57:05 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.12.0 Subject: Re: [PATCH v9 4/6] bootm: Support boot measurement Content-Language: en-US To: Ilias Apalodimas Cc: Sean Edmond , u-boot@lists.denx.de, sjg@chromium.org, xypron.glpk@gmx.de, joel@jms.id.au References: <20230308212537.1725343-1-eajames@linux.ibm.com> <20230308212537.1725343-5-eajames@linux.ibm.com> <09278063-5160-f33f-9448-65975a2a810e@linux.microsoft.com> <838cf5ad-aa9a-5a08-0c4c-0f37c80b43c1@linux.ibm.com> From: Eddie James In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed X-TM-AS-GCONF: 00 X-Proofpoint-GUID: Ufz-M6AyY82OAcSgVLxjUO2uvenBbfEg X-Proofpoint-ORIG-GUID: 6pOiCZyr_3ZwNvg2zRU848kKbkPKvMkU Content-Transfer-Encoding: 7bit X-Proofpoint-UnRewURL: 0 URL was un-rewritten MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26 definitions=2023-08-07_15,2023-08-03_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 adultscore=0 mlxscore=0 phishscore=0 impostorscore=0 spamscore=0 bulkscore=0 clxscore=1015 priorityscore=1501 mlxlogscore=999 suspectscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2306200000 definitions=main-2308070135 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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.8 at phobos.denx.de X-Virus-Status: Clean On 8/7/23 09:52, Ilias Apalodimas wrote: > Hi, > > On Mon, 7 Aug 2023 at 17:43, Eddie James wrote: >> >> On 8/4/23 13:10, Sean Edmond wrote: >>> On 2023-03-08 1:25 p.m., Eddie James wrote: >>>> Add a configuration option to measure the boot through the bootm >>>> function. Add the measurement state to the booti and bootz paths >>>> as well. >>>> >>>> Signed-off-by: Eddie James >>>> Reviewed-by: Simon Glass >>>> --- >>>> Changes since v8: >>>> - Added a configuration option to select to ignore any existing >>>> event log. This would only be selected for systems that know >>>> that U-Boot is the first stage bootloader. This is necessary >>>> because the reserved memory region may persist through resets >>>> and so U-Boot attempts to append to the previous boot's log. >>>> >>>> Changes since v6: >>>> - Added comment for bootm_measure >>>> - Fixed line length in bootm_measure >>>> >>>> boot/Kconfig | 32 +++++++++++++++++++++ >>>> boot/bootm.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ >>>> cmd/booti.c | 1 + >>>> cmd/bootm.c | 2 ++ >>>> cmd/bootz.c | 1 + >>>> include/bootm.h | 11 ++++++++ >>>> include/image.h | 1 + >>>> 7 files changed, 122 insertions(+) >>>> >>>> diff --git a/boot/Kconfig b/boot/Kconfig >>>> index 5f491625c8..8119519c9f 100644 >>>> --- a/boot/Kconfig >>>> +++ b/boot/Kconfig >>>> @@ -629,6 +629,38 @@ config LEGACY_IMAGE_FORMAT >>>> loaded. If a board needs the legacy image format support in this >>>> case, enable it here. >>>> +config MEASURED_BOOT >>>> + bool "Measure boot images and configuration to TPM and event log" >>>> + depends on HASH && TPM_V2 >>>> + help >>>> + This option enables measurement of the boot process. Measurement >>>> + involves creating cryptographic hashes of the binary images that >>>> + are booting and storing them in the TPM. In addition, a log of >>>> + these hashes is stored in memory for the OS to verify the booted >>>> + images and configuration. Enable this if the OS has configured >>>> + some memory area for the event log and you intend to use some >>>> + attestation tools on your system. >>>> + >>>> +if MEASURED_BOOT >>>> + config MEASURE_DEVICETREE >>>> + bool "Measure the devicetree image" >>>> + default y if MEASURED_BOOT >>>> + help >>>> + On some platforms, the devicetree is not static as it may contain >>>> + random MAC addresses or other such data that changes each boot. >>>> + Therefore, it should not be measured into the TPM. In that case, >>>> + disable the measurement here. >>>> + >>>> + config MEASURE_IGNORE_LOG >>>> + bool "Ignore the existing event log" >>>> + default n >>>> + help >>>> + On platforms that use an event log memory region that persists >>>> + through system resets and are the first stage bootloader, then >>>> + this option should be enabled to ignore any existing data in the >>>> + event log memory region. >>>> +endif # MEASURED_BOOT >>>> + >>>> config SUPPORT_RAW_INITRD >>>> bool "Enable raw initrd images" >>>> help >>>> diff --git a/boot/bootm.c b/boot/bootm.c >>>> index 2eec60ec7b..2685bdbd74 100644 >>>> --- a/boot/bootm.c >>>> +++ b/boot/bootm.c >>>> @@ -22,6 +22,7 @@ >>>> #include >>>> #include >>>> #include >>>> +#include >>>> #if defined(CONFIG_CMD_USB) >>>> #include >>>> #endif >>>> @@ -659,6 +660,75 @@ int bootm_process_cmdline_env(int flags) >>>> return 0; >>>> } >>>> +int bootm_measure(struct bootm_headers *images) >>>> +{ >>>> + int ret = 0; >>>> + >>>> + /* Skip measurement if EFI is going to do it */ >>>> + if (images->os.os == IH_OS_EFI && >>>> + IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) && >>>> + IS_ENABLED(CONFIG_BOOTM_EFI)) >>>> + return ret; >>>> + >>> it looks like your measured boot implementation is hardcoding the >>> following PCR indexes: >>> >>> PCR #8 - kernel image measurement >>> PCR #9 - initrd measurement >>> PCR #0 - kernel DTB measurement >>> PCR #1 - bootargs measurement >> >> Hi, >> >> >> Yes, I followed this document as closely as I could: >> https://trustedcomputinggroup.org/wp-content/uploads/TCG_ServerManagementDomainFirmwareProfile_v1p00_11aug2020.pdf >> >> Which provides what should go in what PCR. I can understand users >> wanting a different setup, but as you say, that's probably out of the >> scope of this series. >> > Completely out of scope* of the series. The purpose is follow the TCG > spec. The minor deviations is our choice of the DTB in PCR1 (but > that's what the spec does for ACPI tables) and the choice for initrd > (which is what we do in the linux kernel). > > We can reuse the functions ofc to measure random blobs, but that would > require some kind of config (maybe in a dts??) of what to measure. > > > Eddie, I've pinged you in the past. I rebased and fixed a few issues > of your tree here [0]. Do you plan to resend it at some point? > > [0]https://source.denx.de/u-boot/custodians/u-boot-tpm/-/commits/eddie2/ Yes, sorry for the delay. I'll resend it now. Thank you for rebasing! Thanks, Eddie > > Cheers > /Ilias >> Thanks, >> >> Eddie >> >> >>> I wasn't able to find any specificaton on this measured boot >>> "profile". Are you able to provide a reference? >>> >>> We've implemented our own version of measured boot, which maps >>> measurements to different PCR indexes. In many cases, the data we're >>> measuring is also different. >>> >>> To make this feature more usable by others it would be nice to see a >>> more generic interface that would allow the user to specify the PCR >>> indexes, and the data to hash into these indexes. This would allow >>> everyone to create their own custom measured boot "profile". This >>> request is probably beyond the scope of your current efforts, but I >>> except this implementation to evolve significantly if/when it's accepted. >>> >>>> + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) { >>>> + struct tcg2_event_log elog; >>>> + struct udevice *dev; >>>> + void *initrd_buf; >>>> + void *image_buf; >>>> + const char *s; >>>> + u32 rd_len; >>>> + bool ign; >>>> + >>>> + elog.log_size = 0; >>>> + ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG); >>>> + ret = tcg2_measurement_init(&dev, &elog, ign); >>>> + if (ret) >>>> + return ret; >>>> + >>>> + image_buf = map_sysmem(images->os.image_start, >>>> + images->os.image_len); >>>> + ret = tcg2_measure_data(dev, &elog, 8, images->os.image_len, >>>> + image_buf, EV_COMPACT_HASH, >>>> + strlen("linux") + 1, (u8 *)"linux"); >>>> + if (ret) >>>> + goto unmap_image; >>>> + >>>> + rd_len = images->rd_end - images->rd_start; >>>> + initrd_buf = map_sysmem(images->rd_start, rd_len); >>>> + ret = tcg2_measure_data(dev, &elog, 9, rd_len, initrd_buf, >>>> + EV_COMPACT_HASH, strlen("initrd") + 1, >>>> + (u8 *)"initrd"); >>>> + if (ret) >>>> + goto unmap_initrd; >>>> + >>>> + if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) { >>>> + ret = tcg2_measure_data(dev, &elog, 0, images->ft_len, >>>> + (u8 *)images->ft_addr, >>>> + EV_TABLE_OF_DEVICES, >>>> + strlen("dts") + 1, >>>> + (u8 *)"dts"); >>>> + if (ret) >>>> + goto unmap_initrd; >>>> + } >>>> + >>>> + s = env_get("bootargs"); >>>> + if (!s) >>>> + s = ""; >>>> + ret = tcg2_measure_data(dev, &elog, 1, strlen(s) + 1, (u8 *)s, >>>> + EV_PLATFORM_CONFIG_FLAGS, >>>> + strlen(s) + 1, (u8 *)s); >>>> + >>>> +unmap_initrd: >>>> + unmap_sysmem(initrd_buf); >>>> + >>>> +unmap_image: >>>> + unmap_sysmem(image_buf); >>>> + tcg2_measurement_term(dev, &elog, ret != 0); >>>> + } >>>> + >>>> + return ret; >>>> +} >>>> + >>>> /** >>>> * Execute selected states of the bootm command. >>>> * >>>> @@ -710,6 +780,10 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int >>>> flag, int argc, >>>> if (!ret && (states & BOOTM_STATE_FINDOTHER)) >>>> ret = bootm_find_other(cmdtp, flag, argc, argv); >>>> + if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !ret && >>>> + (states & BOOTM_STATE_MEASURE)) >>>> + bootm_measure(images); >>>> + >>>> /* Load the OS */ >>>> if (!ret && (states & BOOTM_STATE_LOADOS)) { >>>> iflag = bootm_disable_interrupts(); >>>> diff --git a/cmd/booti.c b/cmd/booti.c >>>> index 6ac39193db..659bb10549 100644 >>>> --- a/cmd/booti.c >>>> +++ b/cmd/booti.c >>>> @@ -127,6 +127,7 @@ int do_booti(struct cmd_tbl *cmdtp, int flag, int >>>> argc, char *const argv[]) >>>> #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH >>>> BOOTM_STATE_RAMDISK | >>>> #endif >>>> + BOOTM_STATE_MEASURE | >>>> BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO | >>>> BOOTM_STATE_OS_GO, >>>> &images, 1); >>>> diff --git a/cmd/bootm.c b/cmd/bootm.c >>>> index 37c2af96e0..0c4a713e02 100644 >>>> --- a/cmd/bootm.c >>>> +++ b/cmd/bootm.c >>>> @@ -161,6 +161,8 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int >>>> argc, char *const argv[]) >>>> BOOTM_STATE_OS_GO; >>>> if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH)) >>>> states |= BOOTM_STATE_RAMDISK; >>>> + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) >>>> + states |= BOOTM_STATE_MEASURE; >>>> if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS)) >>>> states |= BOOTM_STATE_OS_CMDLINE; >>>> ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images, >>>> 1); >>>> diff --git a/cmd/bootz.c b/cmd/bootz.c >>>> index f1423573d2..87922bfc3c 100644 >>>> --- a/cmd/bootz.c >>>> +++ b/cmd/bootz.c >>>> @@ -81,6 +81,7 @@ int do_bootz(struct cmd_tbl *cmdtp, int flag, int >>>> argc, char *const argv[]) >>>> #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH >>>> BOOTM_STATE_RAMDISK | >>>> #endif >>>> + BOOTM_STATE_MEASURE | >>>> BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO | >>>> BOOTM_STATE_OS_GO, >>>> &images, 1); >>>> diff --git a/include/bootm.h b/include/bootm.h >>>> index 044a4797ed..76e8e38c82 100644 >>>> --- a/include/bootm.h >>>> +++ b/include/bootm.h >>>> @@ -55,6 +55,17 @@ ulong bootm_disable_interrupts(void); >>>> int bootm_find_images(int flag, int argc, char *const argv[], ulong >>>> start, >>>> ulong size); >>>> +/* >>>> + * Measure the boot images. Measurement is the process of hashing >>>> some binary >>>> + * data and storing it into secure memory, i.e. TPM PCRs. In >>>> addition, each >>>> + * measurement is logged into the platform event log such that the >>>> operating >>>> + * system can access it and perform attestation of the boot. >>>> + * >>>> + * @images: The structure containing the various images to boot >>>> (linux, >>>> + * initrd, dts, etc.) >>>> + */ >>>> +int bootm_measure(struct bootm_headers *images); >>>> + >>>> int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, >>>> char *const argv[], int states, struct bootm_headers >>>> *images, >>>> int boot_progress); >>>> diff --git a/include/image.h b/include/image.h >>>> index 7717a4c13d..f7414b5338 100644 >>>> --- a/include/image.h >>>> +++ b/include/image.h >>>> @@ -407,6 +407,7 @@ struct bootm_headers { >>>> #define BOOTM_STATE_OS_FAKE_GO 0x00000200 /* 'Almost' run the >>>> OS */ >>>> #define BOOTM_STATE_OS_GO 0x00000400 >>>> #define BOOTM_STATE_PRE_LOAD 0x00000800 >>>> +#define BOOTM_STATE_MEASURE 0x00001000 >>>> int state; >>>> #if defined(CONFIG_LMB) && !defined(USE_HOSTCC) >>>