From patchwork Thu Feb 16 16:29:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Etienne Carriere X-Patchwork-Id: 654043 Delivered-To: patch@linaro.org Received: by 2002:adf:9bcd:0:0:0:0:0 with SMTP id e13csp62184wrc; Thu, 16 Feb 2023 08:30:19 -0800 (PST) X-Google-Smtp-Source: AK7set8aN6gLRTTPRy4kJVLAAJE4XE1Aj9l/JhY5QE987E/0lMCbUbWQuELgNpXjk2AIFmfqGjRL X-Received: by 2002:a05:6870:7392:b0:15e:cd63:b7b6 with SMTP id z18-20020a056870739200b0015ecd63b7b6mr3715027oam.24.1676565019764; Thu, 16 Feb 2023 08:30:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1676565019; cv=none; d=google.com; s=arc-20160816; b=pAxjY8Gl5V73+0gk4vT9DCZrIX61V+muGwuWOPNDYAKMHLH8yO9ms+K45/it9Y+9QT PIbfhFQ9TQuJ51Mnzz220EVE7YYXrxRru2ALhYof5/0WNG3MqMyIZleAiqgGpdCjGP/T fr+vOzkQlRdq8p9CI8zMTgSIkcan91jTL1lnWZbr5AMAg6hIFTWbnkI7qwC+1FCokIBp PVU205NUCAK1kMy1JgYclkIWkTN6NGdAnWMWvea4YAPtbGK+Hnqg+YuSifOFZzFEi9w6 7tkIIsoKrR39IaoWEmkaevZmTFr4CBxhQFpuczmgIIRzrPoE8kwedAGO/VxFj0gx7kYs CYMw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature; bh=xrNFUTZKzT/eLTzejWAyEXbXW92Bs98Tib7LlIEcNL8=; b=cDkXz8NL8FnROjtB1G5Ma5BxXCJjqkCMazBjqtBKLO66mqbijye/B52xl6FxDM1cja O1xoQpMTdUZ6EqMlLTbtQD1wt2mwJCgnbvO9hAOfacK365BNd0xDAh+1SLZi/dA3EZEZ 5G42KMpL4CO6mHVwvp3TUEay6CeRwVnRa+bBUfPxXkp/jUft5oqO2KHTySeYk+xgO6iC p3W6DA6pKUmNGQGAl1Eu0MjEPmE0cEZNANBOkYS+87GeG9p6QSz28nV/t7pG73gDExi3 hirt1amy0vGPZz3puOV7htmF1yT/yMpqAOYy6ZZGQ2V00yIM1+BCfXIFFXx2/PW9thf6 cOVA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dWTgLCH3; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id qf2-20020a05687148c200b0016e2546fe9fsi2071368oab.177.2023.02.16.08.30.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Feb 2023 08:30:19 -0800 (PST) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dWTgLCH3; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 7182E85B6E; Thu, 16 Feb 2023 17:30:13 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org 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=linaro.org header.i=@linaro.org header.b="dWTgLCH3"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A502385B77; Thu, 16 Feb 2023 17:30:10 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-ed1-x52f.google.com (mail-ed1-x52f.google.com [IPv6:2a00:1450:4864:20::52f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 2885985B7D for ; Thu, 16 Feb 2023 17:29:53 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=etienne.carriere@linaro.org Received: by mail-ed1-x52f.google.com with SMTP id v13so4892595eda.11 for ; Thu, 16 Feb 2023 08:29:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=xrNFUTZKzT/eLTzejWAyEXbXW92Bs98Tib7LlIEcNL8=; b=dWTgLCH34CnMEd5iQqDiAivG6Qw8Rl6Lt2bh5Zz2O8FsMmjexezu1STm8A6Dcv8L2e bl0BTVyd5mDeEpzundjCXVzUC113iBxjgR4IfUMl6dN79NU8Z803F1fc99A7vgykFc67 TaAQdWZsa7Bcc/2RlCnGmgnqVHWSLdsOSH5ZJyUNhJFi/lc9axf7D19X4x2pHUJoeMkJ h27o+c0DBTgORwZTyoP5utbhRLpNW2F9330811dBuGaumRtVzykzC5vJ8AuJs8cPSmCN YtIBsENhI/QcFoeFrQCF1nQmnPvJ7PMYqWTMkvb9jR6CxmFXgFl9NVNGvFG1myB+6yGo v1VQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=xrNFUTZKzT/eLTzejWAyEXbXW92Bs98Tib7LlIEcNL8=; b=5KtCSnVGtcc7Ifa2GwS1laE/Yj1NqRou4DjR5b9KelP6rHdLa4NdEKOcwnAI9ZDxh3 rtbBZ3y6Z1Nz0PZdDw798yW5pK1axvwgHeQtlI6vFEBbvuLEXJTCGLq+iAQ9XWCguzhV gfFeeBqEbTSLExACM3H7BFnlEfTCGe6ekDAwNUPmF9yMuBFO54bIzCxLKhGSCTaaOuav Fl+5EhgVsn4sW+JvhUIeJ0XArcQnTnDaJMu9RdzqyL2PC7d7SdCDlzJJvzJCpTYTbD6W f0jLN8Pu5EwHdlMPg2D1h64VM1TvS5wuI9G/nf+rbTc5uBczvl/lXrTpHMYjXE28iyfm 4Acw== X-Gm-Message-State: AO0yUKXF/ITjQlbYBruYPqLiCNrvGmOcFbONOqQKtCRhHP0k4rR38Wru FI1KCHC6lsKDaEXpDGNjm5ppZpNnLaTtE/h2 X-Received: by 2002:a17:906:518d:b0:8b1:78b6:bbd7 with SMTP id y13-20020a170906518d00b008b178b6bbd7mr977415ejk.10.1676564992313; Thu, 16 Feb 2023 08:29:52 -0800 (PST) Received: from lmecxl1178.lme.st.com ([80.215.224.41]) by smtp.gmail.com with ESMTPSA id lf13-20020a170906ae4d00b008b12c318622sm1003211ejb.29.2023.02.16.08.29.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Feb 2023 08:29:51 -0800 (PST) From: Etienne Carriere To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Ilias Apalodimas , Simon Glass , Etienne Carriere Subject: [PATCH v2] efi_loader: Measure the loaded DTB Date: Thu, 16 Feb 2023 17:29:48 +0100 Message-Id: <20230216162948.2343115-1-etienne.carriere@linaro.org> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 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.6 at phobos.denx.de X-Virus-Status: Clean Measures the DTB passed to the EFI application upon new boolean config switch CONFIG_EFI_TCG2_PROTOCOL_MEASURE_DTB. For platforms where the content of the DTB passed to the OS can change across reboots, there is not point measuring it hence the config switch to allow platform to not embed this feature. Co-developed-by: Ilias Apalodimas Signed-off-by: Ilias Apalodimas Signed-off-by: Etienne Carriere Tested-by: Ilias Apalodimas Reviewed-by: Ilias Apalodimas --- Changes since v1 - Moved measurement to after DTB tweaks in efi_install_fdt() and change its measure to hash only populated areas in the DTB (header, structs, strings and reserved memory maps). efi_tcg2_measure_dtb() computes the hash of these concatenated areas and used it as DTB measurement. - Remove useless default value 'n' for EFI_TCG2_PROTOCOL_MEASURE_DTB. - I did not add EFI_TCG2_PROTOCOL_MEASURE_DTB dependencies on !NET_RANDOM_ETHADDR neither on !CMD_KASLRSEED. If ethernet address is random but always the same at each boot as saved in environment, it's measure is meaningful. CMD_KASLRSEED effect in DT if already addressed by efi_try_purge_kaslr_seed() prior measurement. --- cmd/bootefi.c | 8 +++++ include/efi_loader.h | 2 ++ include/efi_tcg2.h | 10 ++++++ include/tpm-v2.h | 2 ++ lib/efi_loader/Kconfig | 11 ++++++ lib/efi_loader/efi_tcg2.c | 73 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 106 insertions(+) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 2a7d42925d..6618335ddf 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -332,6 +332,14 @@ efi_status_t efi_install_fdt(void *fdt) efi_try_purge_kaslr_seed(fdt); + if (CONFIG_IS_ENABLED(EFI_TCG2_PROTOCOL_MEASURE_DTB)) { + ret = efi_tcg2_measure_dtb(fdt); + if (ret == EFI_SECURITY_VIOLATION) { + log_err("ERROR: failed to measure DTB\n"); + return ret; + } + } + /* Install device tree as UEFI table */ ret = efi_install_configuration_table(&efi_guid_fdt, fdt); if (ret != EFI_SUCCESS) { diff --git a/include/efi_loader.h b/include/efi_loader.h index 4560b0d04c..4ecfdf919b 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -531,6 +531,8 @@ efi_status_t efi_tcg2_notify_exit_boot_services_failed(void); efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *handle); /* Measure efi application exit */ efi_status_t efi_tcg2_measure_efi_app_exit(void); +/* Measure DTB */ +efi_status_t efi_tcg2_measure_dtb(void *dtb); /* Called by bootefi to initialize root node */ efi_status_t efi_root_node_register(void); /* Called by bootefi to initialize runtime */ diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index 874306dc11..b1c3abd097 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -233,6 +233,16 @@ struct efi_gpt_data { gpt_entry partitions[]; } __packed; +/** + * struct tdUEFI_PLATFORM_FIRMWARE_BLOB2 + * @blob_description_size: Byte size of @data + * @data: Description data + */ +struct uefi_platform_firmware_blob2 { + u8 blob_description_size; + u8 data[]; +} __packed; + struct efi_tcg2_protocol { efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this, struct efi_tcg2_boot_service_capability *capability); diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 737e57551d..2df3dad553 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -105,6 +105,8 @@ struct udevice; "Exit Boot Services Returned with Failure" #define EFI_EXIT_BOOT_SERVICES_SUCCEEDED \ "Exit Boot Services Returned with Success" +#define EFI_DTB_EVENT_STRING \ + "DTB DATA" /* TPMS_TAGGED_PROPERTY Structure */ struct tpms_tagged_property { diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c56904afc2..c05a54df16 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -346,6 +346,17 @@ config EFI_TCG2_PROTOCOL_EVENTLOG_SIZE this is going to be allocated twice. One for the eventlog it self and one for the configuration table that is required from the spec +config EFI_TCG2_PROTOCOL_MEASURE_DTB + bool "Measure DTB with EFI_TCG2_PROTOCOL" + depends on EFI_TCG2_PROTOCOL + help + When enabled, the DTB image passed to the booted EFI image is + measured using the EFI TCG2 protocol. Do not enable this feature if + the passed DTB contains data that change across platform reboots + and cannot be used has a predictable measurement. Otherwise + this feature allows better measurement of the system boot + sequence. + config EFI_LOAD_FILE2_INITRD bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk" default y diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 918e9a2686..2dcc317157 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -2175,6 +2175,79 @@ out1: return ret; } +/* Return the byte size of reserved map area in DTB or -1 upon error */ +static ssize_t size_of_rsvmap(void *dtb) +{ + struct fdt_reserve_entry e; + ssize_t size_max; + ssize_t size; + u8 *rsvmap_base; + + rsvmap_base = (u8 *)dtb + fdt_off_mem_rsvmap(dtb); + size_max = fdt_totalsize(dtb) - fdt_off_mem_rsvmap(dtb); + size = 0; + + do { + memcpy(&e, rsvmap_base + size, sizeof(e)); + size += sizeof(e); + if (size > size_max) + return -1; + } while (e.size); + + return size; +} + +/** + * efi_tcg2_measure_dtb() - measure DTB passed to the OS + * + * @dtb: pointer to the device tree blob + * + * Return: status code + */ +efi_status_t efi_tcg2_measure_dtb(void *dtb) +{ + struct uefi_platform_firmware_blob2 *blob; + struct fdt_header *header; + sha256_context hash_ctx; + struct udevice *dev; + ssize_t rsvmap_size; + efi_status_t ret; + u32 event_size; + + if (!is_tcg2_protocol_installed()) + return EFI_SUCCESS; + + ret = platform_get_tpm2_device(&dev); + if (ret != EFI_SUCCESS) + return EFI_SECURITY_VIOLATION; + + rsvmap_size = size_of_rsvmap(dtb); + if (rsvmap_size < 0) + return EFI_SECURITY_VIOLATION; + + event_size = sizeof(*blob) + sizeof(EFI_DTB_EVENT_STRING) + SHA256_SUM_LEN; + blob = calloc(1, event_size); + if (!blob) + return EFI_OUT_OF_RESOURCES; + + blob->blob_description_size = sizeof(EFI_DTB_EVENT_STRING); + memcpy(blob->data, EFI_DTB_EVENT_STRING, blob->blob_description_size); + + /* Measure populated areas of the DTB */ + header = dtb; + sha256_starts(&hash_ctx); + sha256_update(&hash_ctx, (u8 *)header, sizeof(struct fdt_header)); + sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_dt_struct(dtb), fdt_size_dt_strings(dtb)); + sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_dt_strings(dtb), fdt_size_dt_struct(dtb)); + sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_mem_rsvmap(dtb), rsvmap_size); + sha256_finish(&hash_ctx, blob->data + blob->blob_description_size); + + ret = tcg2_measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob); + + free(blob); + return ret; +} + /** * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation *