Re: [PATCH] tpm: measure DTB in PCR1 instead of PCR0

2024-06-14 Thread Eddie James



On 6/14/24 07:09, Ilias Apalodimas wrote:

The PC client spec [0], doesn't describe measurements for DTBs. It does
describe what do to for ACPI tables though.

There is a description for ACPI in 3.3.4.1 PCR[0] – SRTM, POST BIOS,
and Embedded Drivers and they explicitly mention ACPI in there. There's
no mention of ACPI in 3.3.4.2 PCR[1] – Host Platform Configuration.

However, in Figure 6 --  PCR Mapping of UEFI Components ACPI is shown
in PCR1. The general description also mentions PCR0 is for code and PCR1
is for data such as ACPI and SMBIOS.



Thanks, looks correct.

Reviewed-by: Eddie James 




So let's switch over the DTB measurements to PCR1 which seems a better
fit.

[0] 
https://trustedcomputinggroup.org/resource/pc-client-specific-platform-firmware-profile-specification

Reported-by: Heinrich Schuchardt 
Signed-off-by: Ilias Apalodimas 
---
  boot/bootm.c  | 2 +-
  lib/efi_loader/efi_tcg2.c | 2 +-
  2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/boot/bootm.c b/boot/bootm.c
index 6fa8edab021e..3de87eb185d7 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -963,7 +963,7 @@ int bootm_measure(struct bootm_headers *images)
goto unmap_initrd;

if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) {
-   ret = tcg2_measure_data(dev, &elog, 0, images->ft_len,
+   ret = tcg2_measure_data(dev, &elog, 1, images->ft_len,
(u8 *)images->ft_addr,
EV_TABLE_OF_DEVICES,
strlen("dts") + 1,
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 51264c1b998c..a8a54c9f131d 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -1328,7 +1328,7 @@ efi_status_t efi_tcg2_measure_dtb(void *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 = measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob);
+   ret = measure_event(dev, 1, EV_POST_CODE, event_size, (u8 *)blob);

free(blob);
return ret;
--
2.45.1



Re: tcg2_platform_get_log failing to read address and size of memory-region via ofnode_get_addr_size

2024-03-27 Thread Eddie James



On 3/26/24 11:15, Tim Harvey wrote:

On Tue, Mar 26, 2024 at 2:24 AM Ilias Apalodimas
 wrote:

Hi Tim,

On Tue, 26 Mar 2024 at 03:15, Tim Harvey  wrote:

Greetings,

I'm unable to understand why tcg2_platform_get_log is failing to read
a memory region.

For example the following diffs:

I am not really sure what those nodes are supposed to do in sandbox.
Pehaps Eddie remembers.
What exactly are you trying to achieve here? Read the eventlog from TF-A?



Would you agree with removing the requirement for the event log?



No, the log is required, otherwise it's fairly meaningless work. You 
need the log in your OS to verify the contents of the TPM.


Here is the device tree reserved memory stuff we're using, perhaps it 
will help.


diff --git a/arch/arm/dts/ast2600-p10bmc.dts 
b/arch/arm/dts/ast2600-p10bmc.dts

index 1d0f88bf96..8fbfeaa0d7 100755
--- a/arch/arm/dts/ast2600-p10bmc.dts
+++ b/arch/arm/dts/ast2600-p10bmc.dts
@@ -13,6 +13,17 @@
    reg = <0x8000 0x4000>;
    };

+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log@b3d0 {
+   no-map;
+   reg = <0xb3d0 0x10>;
+   };
+   };
+
    chosen {
    stdout-path = &uart5;
    };
@@ -113,6 +124,7 @@
    tpm@2e {
    compatible = "nuvoton,npct75x";
    reg = <0x2e>;
+   memory-region = <&event_log>;
    };
 };




I have another question that perhaps you may have some feedback on.
The tpm commands such as pcr_extend, pcr_read currently require a
32-byte SHA256 digest and I wish to extend that as my TPM supports
only SHA1. The tpm2_pcr_extend and tpm2_pcr_read functions were
extended to function to allow the digest type and length to be passed
in and I'm wondering what the best way to extend the tpm extend/read
commands would be to support that.

The tcg2_create_digest function creates a digest based on the
capabilities of the tpm and the tcg2_pcr_extend loops over those
calling tpm2_pcr_extend for each digtest supported (and same for
tcg2_pcr_read looping over tpm2_pcr_read) and I'm assuming TPM's can
support multiple algos so I suppose a parameter needs to be added to
the pcr_read and pcr_extend commands. Would you agree with that?

Best Regards,

Tim


Thanks
/Ilias

diff --git a/arch/arm/dts/imx8mm-venice-gw73xx.dtsi
b/arch/arm/dts/imx8mm-venice-gw73xx.dtsi
index 7b2130dbdb21..57b3c227ceaf 100644
--- a/arch/arm/dts/imx8mm-venice-gw73xx.dtsi
+++ b/arch/arm/dts/imx8mm-venice-gw73xx.dtsi
@@ -112,6 +112,7 @@
compatible = "tcg,tpm_tis-spi";
reg = <0x1>;
spi-max-frequency = <3600>;
+ memory-region = <&event_log>;
};
};
diff --git a/arch/arm/dts/imx8mm-venice-gw700x.dtsi
b/arch/arm/dts/imx8mm-venice-gw700x.dtsi
index c305e325d007..697fd1148785 100644
--- a/arch/arm/dts/imx8mm-venice-gw700x.dtsi
+++ b/arch/arm/dts/imx8mm-venice-gw700x.dtsi
@@ -13,6 +13,17 @@
reg = <0x0 0x4000 0 0x8000>;
};

+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ event_log: tcg_event_log {
+ no-map;
+ reg = <0 0x4000 0x2000>;
+ };
+ };
+
gpio-keys {
compatible = "gpio-keys";

And at runtime:
u-boot=> fdt addr $fdtcontroladdr
u-boot=> fdt list 
/soc@0/bus@3080/spba-bus@3080/spi@3083/tpm@1/

tpm@1 {
compatible = "tcg,tpm_tis-spi";
reg = <0x0001>;
spi-max-frequency = <0x02255100>;
memory-region = <0x0025>;
};
u-boot=> fdt list /reserved-memory/
reserved-memory {
#address-cells = <0x0002>;
#size-cells = <0x0002>;
ranges;
tcg_event_log {
};
};
u-boot=> fdt list /reserved-memory/tcg_event_log
tcg_event_log {
no-map;
reg = <0x 0x4000 0x2000>;
phandle = <0x0025>;
};

So why does the following code in tcg2_platform_get_log() return 
-ENOMEM?


if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
0, &args))
return -ENODEV;

a = ofnode_get_addr_size(args.node, "reg", &s);
if (a == FDT_ADDR_T_NONE)
return -ENOMEM;

debugging shows that dev_read_phandle_with_args returns non-zero but
args.args_count is 0.

I feel like the construct of using dev_read_phandle_with_args followed
by the ofnode_get_addr_size is just wrong but I don't understand why
nor do I understand how my dt changes differ from what is in
arch/sandbox/dts/test.dts (other than its using address-size=1 which
doesn't appear to be the issue in my testing). The abstraction of the
ofnode and fdt stuff always trip me up... very confusing.

Can anyone explain the issue here?

Best Regards,

Tim


Re: tcg2_platform_get_log failing to read address and size of memory-region via ofnode_get_addr_size

2024-03-27 Thread Eddie James



On 3/26/24 11:15, Tim Harvey wrote:

On Tue, Mar 26, 2024 at 2:24 AM Ilias Apalodimas
 wrote:

Hi Tim,

On Tue, 26 Mar 2024 at 03:15, Tim Harvey  wrote:

Greetings,

I'm unable to understand why tcg2_platform_get_log is failing to read
a memory region.

For example the following diffs:

I am not really sure what those nodes are supposed to do in sandbox.
Pehaps Eddie remembers.
What exactly are you trying to achieve here? Read the eventlog from TF-A?


Hi Ilias,

I was trying to get measured boot (CONFIG_MEASURED_BOOT=y) working on
a tpm on my board but ran into an issue when I couldn't get the
memory-region I added for testing to be recognized with the current
code in tcg2_platform_get_log().

I wonder if an event log should be required for measured boot - it
sounds like that was something required for EFI, so I was thinking of
submitting the following:
commit b3f336c2f863168219a93cd1c7ac922396e0fad5 (HEAD -> master-venice)
Author: Tim Harvey 
Date:   Tue Mar 26 08:49:07 2024 -0700

 tpm: allow measured boot without an event log

 Currently an event log is required for measured boot. Remove this
 requirement.

 Signed-off-by: Tim Harvey 

diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index 68eaaa639f89..994f8089ba34 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -175,17 +175,19 @@ static int tcg2_log_append_check(struct
tcg2_event_log *elog, u32 pcr_index,
 u32 event_size;
 u8 *log;

-   event_size = size + tcg2_event_get_size(digest_list);
-   if (elog->log_position + event_size > elog->log_size) {
-   printf("%s: log too large: %u + %u > %u\n", __func__,
-  elog->log_position, event_size, elog->log_size);
-   return -ENOBUFS;
-   }
+   if (elog->log_size) {
+   event_size = size + tcg2_event_get_size(digest_list);
+   if (elog->log_position + event_size > elog->log_size) {
+   printf("%s: log too large: %u + %u > %u\n", __func__,
+  elog->log_position, event_size, elog->log_size);
+   return -ENOBUFS;
+   }

-   log = elog->log + elog->log_position;
-   elog->log_position += event_size;
+   log = elog->log + elog->log_position;
+   elog->log_position += event_size;

-   tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
+   tcg2_log_append(pcr_index, event_type, digest_list,
size, event, log);
+   }

 return 0;
  }
@@ -613,10 +615,8 @@ int tcg2_measurement_init(struct udevice **dev,
struct tcg2_event_log *elog,
 return rc;

 rc = tcg2_log_prepare_buffer(*dev, elog, ignore_existing_log);
-   if (rc) {
+   if (rc)
 tcg2_measurement_term(*dev, elog, true);
-   return rc;
-   }

 rc = tcg2_measure_event(*dev, elog, 0, EV_S_CRTM_VERSION,
 strlen(version_string) + 1,

Would you agree with removing the requirement for the event log?



No, the log is required, otherwise it's fairly meaningless work. You 
need the log in your OS to verify the contents of the TPM.


Here is the device tree reserved memory stuff we're using, perhaps it 
will help.


diff --git a/arch/arm/dts/ast2600-p10bmc.dts 
b/arch/arm/dts/ast2600-p10bmc.dts

index 1d0f88bf96..8fbfeaa0d7 100755
--- a/arch/arm/dts/ast2600-p10bmc.dts
+++ b/arch/arm/dts/ast2600-p10bmc.dts
@@ -13,6 +13,17 @@
    reg = <0x8000 0x4000>;
    };

+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log@b3d0 {
+   no-map;
+   reg = <0xb3d0 0x10>;
+   };
+   };
+
    chosen {
    stdout-path = &uart5;
    };
@@ -113,6 +124,7 @@
    tpm@2e {
    compatible = "nuvoton,npct75x";
    reg = <0x2e>;
+   memory-region = <&event_log>;
    };
 };




I have another question that perhaps you may have some feedback on.
The tpm commands such as pcr_extend, pcr_read currently require a
32-byte SHA256 digest and I wish to extend that as my TPM supports
only SHA1. The tpm2_pcr_extend and tpm2_pcr_read functions were
extended to  function to allow the digest type and length to be passed
in and I'm wondering what the best way to extend the tpm extend/read
commands would be to support that.

The tcg2_create_digest function creates a digest based on the
capabilities of the tpm and the tcg2_pcr_extend loops over those
calling tpm2_pcr_extend for each digtest supported (and same for
tcg2_pcr_read looping over tpm2_pcr_read) and I'm assuming TPM's can
support multiple algos so I suppose a parameter needs to be added to
the pcr_read and pcr_extend commands. Would you agree with that?

Best Regards,

Tim


Thanks
/Ilias

diff --git a/arch/arm/dts/imx8mm-venice-g

Re: [PATCH v14 4/8] bootm: Support boot measurement

2023-10-25 Thread Eddie James



On 10/25/23 07:41, Ilias Apalodimas wrote:

On Tue, 24 Oct 2023 at 18:44, 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 a01e6cb8aa..abbc72f4cf 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -685,6 +685,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

I know Simon reviewed this already, but don't we need to add !EFI here?
UEFI already supports measurements via the TCG protocol implementation.
But since EFI is 'default y' nowadays anyone minds if I change the
help & bool messages during merge?
Something along the lines of
bool "Measure boot images and configuration to TPM and event log when
booting without EFI"



Oh right, yes, go ahead, that sounds good, thanks.

Eddie




[...]

Thanks
/Ilias


[PATCH v14 7/8] efi_loader: fix EFI_ENTRY point on get_active_pcr_banks

2023-10-24 Thread Eddie James
From: Ilias Apalodimas 

efi_tcg2_get_active_pcr_banks doesn't immediately call the
EFI_ENTRY() wrapper once it enters the function. Move the call a
few lines above to cover the error cases properly as well.

Signed-off-by: Ilias Apalodimas 
---
 lib/efi_loader/efi_tcg2.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index b87c7900a8..2eaa12b83b 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -717,16 +717,16 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol 
*this,
struct udevice *dev;
efi_status_t ret;
 
+   EFI_ENTRY("%p, %p", this, active_pcr_banks);
+
if (!this || !active_pcr_banks) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
-
ret = tcg2_platform_get_tpm2(&dev);
if (ret != EFI_SUCCESS)
goto out;
 
-   EFI_ENTRY("%p, %p", this, active_pcr_banks);
ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);
 
 out:
-- 
2.39.3



[PATCH v14 1/8] tpm: Fix spelling for tpmu_ha union

2023-10-24 Thread Eddie James
tmpu -> tpmu

Signed-off-by: Eddie James 
Reviewed-by: Ilias Apalodimas 
---
 include/tpm-v2.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 2b6980e441..6684033deb 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -169,7 +169,7 @@ struct tcg_pcr_event {
 /**
  * Definition of TPMU_HA Union
  */
-union tmpu_ha {
+union tpmu_ha {
u8 sha1[TPM2_SHA1_DIGEST_SIZE];
u8 sha256[TPM2_SHA256_DIGEST_SIZE];
u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE];
@@ -185,7 +185,7 @@ union tmpu_ha {
  */
 struct tpmt_ha {
u16 hash_alg;
-   union tmpu_ha digest;
+   union tpmu_ha digest;
 } __packed;
 
 /**
-- 
2.39.3



[PATCH v14 2/8] tpm: sandbox: Update for needed TPM2 capabilities

2023-10-24 Thread Eddie James
The driver needs to support getting the PCRs in the capabilities
command. Fix various other things and support the max number
of PCRs for TPM2.
Remove the !SANDBOX dependency for EFI TCG2 as well.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v8:
 - Use >= for checking the property against TPM2_PROPERTIES_OFFSET

Changes since v5:
 - Remove the !SANDBOX dependency for EFI TCG2

 drivers/tpm/tpm2_tis_sandbox.c | 100 -
 lib/efi_loader/Kconfig |   2 -
 2 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index e4004cfcca..d15a28d9fc 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -22,11 +22,6 @@ enum tpm2_hierarchy {
TPM2_HIERARCHY_NB,
 };
 
-/* Subset of supported capabilities */
-enum tpm2_capability {
-   TPM_CAP_TPM_PROPERTIES = 0x6,
-};
-
 /* Subset of supported properties */
 #define TPM2_PROPERTIES_OFFSET 0x020E
 
@@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
TPM2_PROPERTY_NB,
 };
 
-#define SANDBOX_TPM_PCR_NB 1
+#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
+#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8)
 
 /*
  * Information about our TPM emulation. This is preserved in the sandbox
@@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 
*sendbuf,
int i, j;
 
/* TPM2_GetProperty */
-   u32 capability, property, property_count;
+   u32 capability, property, property_count, val;
 
/* TPM2_PCR_Read/Extend variables */
int pcr_index = 0;
@@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
case TPM2_CC_GET_CAPABILITY:
capability = get_unaligned_be32(sent);
sent += sizeof(capability);
-   if (capability != TPM_CAP_TPM_PROPERTIES) {
-   printf("Sandbox TPM only support TPM_CAPABILITIES\n");
-   return TPM2_RC_HANDLE;
-   }
-
property = get_unaligned_be32(sent);
sent += sizeof(property);
-   property -= TPM2_PROPERTIES_OFFSET;
-
property_count = get_unaligned_be32(sent);
sent += sizeof(property_count);
-   if (!property_count ||
-   property + property_count > TPM2_PROPERTY_NB) {
+
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   break;
+   case TPM2_CAP_TPM_PROPERTIES:
+   if (!property_count) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+
+   if (property >= TPM2_PROPERTIES_OFFSET &&
+   ((property - TPM2_PROPERTIES_OFFSET) +
+property_count > TPM2_PROPERTY_NB)) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+   break;
+   default:
+   printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
+  "TPM2_CAP_TPM_PROPERTIES\n");
rc = TPM2_RC_HANDLE;
return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
}
@@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
put_unaligned_be32(capability, recv);
recv += sizeof(capability);
 
-   /* Give the number of properties that follow */
-   put_unaligned_be32(property_count, recv);
-   recv += sizeof(property_count);
-
-   /* Fill with the properties */
-   for (i = 0; i < property_count; i++) {
-   put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
-  i, recv);
-   recv += sizeof(property);
-   put_unaligned_be32(tpm->properties[property + i],
-  recv);
-   recv += sizeof(property);
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   /* Give the number of algorithms supported - just 
SHA256 */
+   put_unaligned_be32(1, recv);
+   recv += sizeof(u32);
+
+   /* Give SHA256 algorithm */
+   put_unaligned_be16(TPM2_ALG_SHA256, recv);
+   recv += sizeof(u16);
+
+   /* Se

[PATCH v14 0/8] tpm: Support boot measurements

2023-10-24 Thread Eddie James
This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm 
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.

Changes since v13:
 - Rebase without messing up efi_tcg2.c (duplicate functions)

Changes since v12:
 - Rebase on master.
 - Add detail to documentation.

Changes since v11:
 - Rebase on next. Sorry for the delay (been on leave).

Changes since v10:
 - Fix commit message on efi_loader change
 - Drop python test change
 - Squash armv7 fix from Ilias

Changes since v9:
 - Rebase and add Ilias' fixes (thanks!)

Changes since v8:
 - Fix a sandbox driver off-by-one error in checking the property type.
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log and a configuration option
   for systems to select that for the bootm measurement. 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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Re-ordered the patches to put the sandbox TPM driver patch second
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs
 - Remove the !SANDBOX dependency for EFI TCG2
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
 - Change PCR indexes for initrd and dtb
 - Drop u8 casting in measurement test
 - Use bullets in documentation

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v2:
 - Add documentation.
 - Changed reserved memory address to the top of the RAM for sandbox dts.
 - Add measure state to booti and bootz.
 - Skip measurement for EFI images that should be measured

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.
 - Add test case
 - Drop #ifdefs for bootm
 - Add devicetree measurement config option
 - Update sandbox TPM driver

Eddie James (6):
  tpm: Fix spelling for tpmu_ha union
  tpm: sandbox: Update for needed TPM2 capabilities
  tpm: Support boot measurements
  bootm: Support boot measurement
  test: Add sandbox TPM boot measurement
  doc: Add measured boot documentation

Ilias Apalodimas (2):
  efi_loader: fix EFI_ENTRY point on get_active_pcr_banks
  test: use a non system PCR for testing PCR extend

 arch/sandbox/dts/sandbox.dtsi  |   13 +
 arch/sandbox/dts/test.dts  |   13 +
 boot/Kconfig   |   32 +
 boot/bootm.c   |   74 +++
 cmd/booti.c|1 +
 cmd/bootm.c|2 +
 cmd/bootz.c|1 +
 configs/sandbox_defconfig  |1 +
 doc/usage/index.rst|1 +
 doc/usage/measured_boot.rst|   31 +
 drivers/tpm/tpm2_tis_sandbox.c |  100 ++-
 include/bootm.h|   11 +
 include/efi_tcg2.h |   44 --
 include/image.h|1 +
 include/test/suites.h  |1 +
 include/tpm-v2.h   |  263 +++-
 lib/Kconfig|4 +
 lib/efi_loader/Kconfig |2 -
 lib/efi_loader/efi_tcg2.c  | 1055 +++--

[PATCH v14 6/8] doc: Add measured boot documentation

2023-10-24 Thread Eddie James
Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
---
Changes since v12:
 - Add a bit of detail about OS usage and what pieces are measured

 doc/usage/index.rst |  1 +
 doc/usage/measured_boot.rst | 31 +++
 2 files changed, 32 insertions(+)
 create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 98b4719c40..bf53bb6bda 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -14,6 +14,7 @@ Use U-Boot
partitions
cmdline
semihosting
+   measured_boot
 
 Shell commands
 --
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..0aad590859
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,31 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+By default, U-Boot will measure the operating system (linux) image, the
+initrd image, and the "bootargs" environment variable. By enabling
+CONFIG_MEASURE_DEVICETREE, U-Boot will also measure the devicetree image.
+
+The operating system typically would verify that the hashes found in the
+TPM PCRs match the contents of the event log. This can further be checked
+against the hash results of previous boots.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
-- 
2.39.3



[PATCH v14 5/8] test: Add sandbox TPM boot measurement

2023-10-24 Thread Eddie James
Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
 - Only compile in the measurement u-boot command when
   CONFIG_MEASURED_BOOT is enabled.

 arch/sandbox/dts/sandbox.dtsi | 13 +++
 arch/sandbox/dts/test.dts | 13 +++
 configs/sandbox_defconfig |  1 +
 include/test/suites.h |  1 +
 test/boot/Makefile|  1 +
 test/boot/measurement.c   | 66 +++
 test/cmd_ut.c |  4 +++
 7 files changed, 99 insertions(+)
 create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index ff7e5584c5..241f397ba6 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
  * and sandbox64 builds.
  */
 
+#include 
 #include 
 
 #define USB_CLASS_HUB  9
 
 / {
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman {
};
 
@@ -342,6 +354,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index e430347356..67159b3d01 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include 
 #include 
 #include 
 #include 
@@ -68,6 +69,17 @@
osd0 = "/osd";
};
 
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman: binman {
};
 
@@ -1423,6 +1435,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
tpm {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 47417cb039..757dcac4ca 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -349,3 +349,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 1c7dc65966..48ed549c13 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -45,6 +45,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 52947580ae..068522cb9e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 obj-$(CONFIG_CEDIT) += cedit.o
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MEASUREMENT_TEST(_name, _flags)\
+   UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+   struct bootm_headers images;
+   const size_t size = 1024;
+   u8 *kernel;
+   u8 *initrd;
+   size_t i;
+
+   kernel = malloc(size);
+   initrd = malloc(size);
+
+   images.os.image_start = map_to_sysmem(kernel);
+   images.os.image_len = size;
+
+   images.rd_start = map_to_sysmem(initrd);
+   images.rd_end = images.rd_start + size;
+
+   images.ft_addr = malloc(size);
+   images.ft_len = size;
+
+   env_set("bootargs", "measurement testing");
+
+   for (i = 0; i < size; ++i) {
+   kernel[i] =

[PATCH v14 4/8] bootm: Support boot measurement

2023-10-24 Thread Eddie James
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 a01e6cb8aa..abbc72f4cf 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -685,6 +685,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 8f96a80d42..cb61485c22 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #if defined(CONFIG_CMD_USB)
 #include 
 #endif
@@ -673,6 +674,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;
+
+   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 

[PATCH v14 8/8] test: use a non system PCR for testing PCR extend

2023-10-24 Thread Eddie James
From: Ilias Apalodimas 

We currently use PCR 0 for testing the PCR read/extend functionality in
our selftests.  How ever those PCRs are defined by the TCG spec for
platform use.  For example if the tests run *after* the efi subsystem
initialization, which extends PCRs 0 & 7 it will give a false positive.

So let's switch over to a PCR which is more suitable and is defined for
OS use.  It's worth noting that we are using PCR10 here, since PCR9 is
used internally by U-Boot if we choose to measure the loaded DTB

Reviewed-by: Simon Glass 
Signed-off-by: Ilias Apalodimas 
---
 test/py/tests/test_tpm2.py | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py
index c2579fa02c..47392b87a9 100644
--- a/test/py/tests/test_tpm2.py
+++ b/test/py/tests/test_tpm2.py
@@ -239,7 +239,7 @@ def test_tpm2_dam_parameters(u_boot_console):
 def test_tpm2_pcr_read(u_boot_console):
 """Execute a TPM2_PCR_Read command.
 
-Perform a PCR read of the 0th PCR. Must be zero.
+Perform a PCR read of the 10th PCR. Must be zero.
 """
 if is_sandbox(u_boot_console):
 tpm2_sandbox_init(u_boot_console)
@@ -247,7 +247,7 @@ def test_tpm2_pcr_read(u_boot_console):
 force_init(u_boot_console)
 ram = u_boot_utils.find_ram_base(u_boot_console)
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram)
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
@@ -257,7 +257,7 @@ def test_tpm2_pcr_read(u_boot_console):
 updates = int(re.findall(r'\d+', str)[0])
 
 # Check the output value
-assert 'PCR #0 content' in read_pcr
+assert 'PCR #10 content' in read_pcr
 assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr
 
 @pytest.mark.buildconfigspec('cmd_tpm_v2')
@@ -275,19 +275,19 @@ def test_tpm2_pcr_extend(u_boot_console):
 force_init(u_boot_console)
 ram = u_boot_utils.find_ram_base(u_boot_console)
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 str = re.findall(r'\d+ known updates', read_pcr)[0]
 updates = int(re.findall(r'\d+', str)[0])
 
-u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
 # Read the value back into a different place so we can still use 'ram' as
 # our zero bytes
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr
@@ -297,11 +297,11 @@ def test_tpm2_pcr_extend(u_boot_console):
 new_updates = int(re.findall(r'\d+', str)[0])
 assert (updates + 1) == new_updates
 
-u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 assert '7a 05 01 f5 95 7b df 9c b3 a8 ff 49 66 f0 22 65' in read_pcr
-- 
2.39.3



[PATCH v14 3/8] tpm: Support boot measurements

2023-10-24 Thread Eddie James
Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v13:
 - Fix rebase since v11 and prevent duplicate efi_tcg2.c functions

Changes since v10:
 - Fix compile warning for armv7 (thanks Ilias)

Changes since v8:
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log. This should only be used
   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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions

 include/efi_tcg2.h|   44 --
 include/tpm-v2.h  |  259 +
 lib/Kconfig   |4 +
 lib/efi_loader/efi_tcg2.c | 1053 +++--
 lib/tpm-v2.c  |  814 
 5 files changed, 1154 insertions(+), 1020 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..b21c5cb3dd 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
 #define BOOT_SERVICE_CAPABILITY_MIN \
offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id: algorithm defined in enum tpm2_algorithms
- *  @digest_size:  size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-   u16  algorithm_id;
-   u16  digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature: signature, set to Spec ID Event03
- * @platform_class:class defined in TCG ACPI Specification
- * Client  Common Header.
- * @spec_version_minor:minor version
- * @spec_version_major:major version
- * @spec_version_errata:   major version
- * @uintn_size:size of the efi_uintn_t fields used in 
various
- * data structures used in this specification.
- * 0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:  hashing algorithms used in this event log
- * @digest_sizes:  array of number_of_algorithms pairs
- * 1st member defines the algorithm id
- * 2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-   u8 signature[16];
-   u32 platform_class;
-   u8 spec_version_minor;
-   u8 spec_version_major;
-   u8 spec_errata;
-   u8 uintn_size;
-   u32 number_of_algorithms;
-   struct tcg_efi_spec_id_event_algorithm_si

Re: [PATCH v13 0/8] tpm: Support boot measurements

2023-10-24 Thread Eddie James



On 10/19/23 17:49, Ilias Apalodimas wrote:

Hi Eddie,

Does the series compile for you against -master?
For qemu_arm64_defonfig I am getting compilation errors both locally
and on the CI
https://source.denx.de/u-boot/custodians/u-boot-tpm/-/jobs/717362#L39



Yea it was a problem rebasing. I'll send v14 soon.

Thanks,

Eddie




Thanks
/Ilias

On Thu, 19 Oct 2023 at 19:45, Ilias Apalodimas
 wrote:

Thanks Eddie

I've queued this up on public CI.  I also have an internal one, this
one failed to add the TF-A eventlog, but everything else looks fine.
I'll have a look tomorrow, but since this used to work on earlier
versions I suspect it's going to be trivial to fix

Cheers
/Ilias

On Thu, 19 Oct 2023 at 19:21, Eddie James  wrote:

This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.

Changes since v12:
  - Rebase on master.
  - Add detail to documentation.

Changes since v11:
  - Rebase on next. Sorry for the delay (been on leave).

Changes since v10:
  - Fix commit message on efi_loader change
  - Drop python test change
  - Squash armv7 fix from Ilias

Changes since v9:
  - Rebase and add Ilias' fixes (thanks!)

Changes since v8:
  - Fix a sandbox driver off-by-one error in checking the property type.
  - Fix log parsing again - any data corruption seen while replaying the
event log was failing the entire measurement.
  - Added an option to ignore the existing log and a configuration option
for systems to select that for the bootm measurement. 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 v7:
  - Change name of tcg2_init_log and add more documentation
  - Add a check, when parsing the event log header, to ensure that the
previous stage bootloader used all the active PCRs.
  - Change name of tcg2_log_find_end
  - Fix the greater than or equal to check to exit the log parsing
  - Make sure log_position is 0 if there is any error discovering the log
  - Return errors parsing the log if the data is corrupt so that we don't
end up with half a log

Changes since v6:
  - Added comment for bootm_measure
  - Fixed line length in bootm_measure
  - Added Linaro copyright for all the EFI moved code
  - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
copy any discovered event log to the user's log if passed in.

Changes since v5:
  - Re-ordered the patches to put the sandbox TPM driver patch second
  - Remove unused platform_get_eventlog in efi_tcg2.c
  - First look for tpm_event_log_* properties instead of linux,sml-*
  - Fix efi_tcg2.c compilation
  - Select SHA* configs
  - Remove the !SANDBOX dependency for EFI TCG2
  - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
is enabled

Changes since v4:
  - Remove tcg2_measure_event function and check for NULL data in
tcg2_measure_data
  - Use tpm_auto_startup
  - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
  - Change PCR indexes for initrd and dtb
  - Drop u8 casting in measurement test
  - Use bullets in documentation

Changes since v3:
  - Reordered headers
  - Refactored more of EFI code into common code
 Removed digest_info structure and instead used the common alg_to_mask
   and alg_to_len
 Improved event log parsing in common code to get it equivalent to EFI
   Common code now extends PCR if previous bootloader stage couldn't
   No need to allocate memory in the common code, so EFI copies the
   discovered buffer like it did before
 Rename efi measure_event function

Changes since v2:
  - Add documentation.
  - Changed reserved memory address to the top of the RAM for sandbox dts.
  - Add measure state to booti and bootz.
  - Skip measurement for EFI images that should be measured

Changes since v1:
  - Refactor TPM layer functions to allow EFI system to use them, and
remove duplicate EFI functions.
  - Add test case
  - Drop #ifdefs for bootm
  - Add devicetree measurement config option
  - Update sandbox TPM driver

Eddie James (6):
   tpm: Fix spelling for tpmu_ha union
   tpm: sandbox: Update for needed TPM2 capabilities
   tpm: Support boot measurements
   bootm: Support boot measurement
   test: Add sandbox TPM boot measurement
   doc: Add measured boot documentation

Ilias Apalodimas (2):
   efi_loader: fix EFI_ENTRY point on get_active_pcr_banks
   test: use a non system PCR for testing PCR extend

  arch/sandbox/dts/sandbox.dtsi  |  13 +
  arch/san

[PATCH v13 4/8] bootm: Support boot measurement

2023-10-19 Thread Eddie James
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 a01e6cb8aa..abbc72f4cf 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -685,6 +685,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 8f96a80d42..cb61485c22 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #if defined(CONFIG_CMD_USB)
 #include 
 #endif
@@ -673,6 +674,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;
+
+   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 

[PATCH v13 8/8] test: use a non system PCR for testing PCR extend

2023-10-19 Thread Eddie James
From: Ilias Apalodimas 

We currently use PCR 0 for testing the PCR read/extend functionality in
our selftests.  How ever those PCRs are defined by the TCG spec for
platform use.  For example if the tests run *after* the efi subsystem
initialization, which extends PCRs 0 & 7 it will give a false positive.

So let's switch over to a PCR which is more suitable and is defined for
OS use.  It's worth noting that we are using PCR10 here, since PCR9 is
used internally by U-Boot if we choose to measure the loaded DTB

Reviewed-by: Simon Glass 
Signed-off-by: Ilias Apalodimas 
---
 test/py/tests/test_tpm2.py | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py
index c2579fa02c..47392b87a9 100644
--- a/test/py/tests/test_tpm2.py
+++ b/test/py/tests/test_tpm2.py
@@ -239,7 +239,7 @@ def test_tpm2_dam_parameters(u_boot_console):
 def test_tpm2_pcr_read(u_boot_console):
 """Execute a TPM2_PCR_Read command.
 
-Perform a PCR read of the 0th PCR. Must be zero.
+Perform a PCR read of the 10th PCR. Must be zero.
 """
 if is_sandbox(u_boot_console):
 tpm2_sandbox_init(u_boot_console)
@@ -247,7 +247,7 @@ def test_tpm2_pcr_read(u_boot_console):
 force_init(u_boot_console)
 ram = u_boot_utils.find_ram_base(u_boot_console)
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram)
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
@@ -257,7 +257,7 @@ def test_tpm2_pcr_read(u_boot_console):
 updates = int(re.findall(r'\d+', str)[0])
 
 # Check the output value
-assert 'PCR #0 content' in read_pcr
+assert 'PCR #10 content' in read_pcr
 assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr
 
 @pytest.mark.buildconfigspec('cmd_tpm_v2')
@@ -275,19 +275,19 @@ def test_tpm2_pcr_extend(u_boot_console):
 force_init(u_boot_console)
 ram = u_boot_utils.find_ram_base(u_boot_console)
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 str = re.findall(r'\d+ known updates', read_pcr)[0]
 updates = int(re.findall(r'\d+', str)[0])
 
-u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
 # Read the value back into a different place so we can still use 'ram' as
 # our zero bytes
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr
@@ -297,11 +297,11 @@ def test_tpm2_pcr_extend(u_boot_console):
 new_updates = int(re.findall(r'\d+', str)[0])
 assert (updates + 1) == new_updates
 
-u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 assert '7a 05 01 f5 95 7b df 9c b3 a8 ff 49 66 f0 22 65' in read_pcr
-- 
2.39.3



[PATCH v13 3/8] tpm: Support boot measurements

2023-10-19 Thread Eddie James
Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v10:
 - Fix compile warning for armv7 (thanks Ilias)

Changes since v8:
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log. This should only be used
   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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions

 include/efi_tcg2.h|  44 --
 include/tpm-v2.h  | 259 
 lib/Kconfig   |   4 +
 lib/efi_loader/efi_tcg2.c | 821 --
 lib/tpm-v2.c  | 814 +
 5 files changed, 1154 insertions(+), 788 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..b21c5cb3dd 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
 #define BOOT_SERVICE_CAPABILITY_MIN \
offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id: algorithm defined in enum tpm2_algorithms
- *  @digest_size:  size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-   u16  algorithm_id;
-   u16  digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature: signature, set to Spec ID Event03
- * @platform_class:class defined in TCG ACPI Specification
- * Client  Common Header.
- * @spec_version_minor:minor version
- * @spec_version_major:major version
- * @spec_version_errata:   major version
- * @uintn_size:size of the efi_uintn_t fields used in 
various
- * data structures used in this specification.
- * 0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:  hashing algorithms used in this event log
- * @digest_sizes:  array of number_of_algorithms pairs
- * 1st member defines the algorithm id
- * 2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-   u8 signature[16];
-   u32 platform_class;
-   u8 spec_version_minor;
-   u8 spec_version_major;
-   u8 spec_errata;
-   u8 uintn_size;
-   u32 number_of_algorithms;
-   struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
-} __packed;
-
 /**
  * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - l

[PATCH v13 6/8] doc: Add measured boot documentation

2023-10-19 Thread Eddie James
Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
---
Changes since v12:
 - Add a bit of detail about OS usage and what pieces are measured

 doc/usage/index.rst |  1 +
 doc/usage/measured_boot.rst | 31 +++
 2 files changed, 32 insertions(+)
 create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 98b4719c40..bf53bb6bda 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -14,6 +14,7 @@ Use U-Boot
partitions
cmdline
semihosting
+   measured_boot
 
 Shell commands
 --
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..0aad590859
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,31 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+By default, U-Boot will measure the operating system (linux) image, the
+initrd image, and the "bootargs" environment variable. By enabling
+CONFIG_MEASURE_DEVICETREE, U-Boot will also measure the devicetree image.
+
+The operating system typically would verify that the hashes found in the
+TPM PCRs match the contents of the event log. This can further be checked
+against the hash results of previous boots.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
-- 
2.39.3



[PATCH v13 5/8] test: Add sandbox TPM boot measurement

2023-10-19 Thread Eddie James
Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
 - Only compile in the measurement u-boot command when
   CONFIG_MEASURED_BOOT is enabled.

 arch/sandbox/dts/sandbox.dtsi | 13 +++
 arch/sandbox/dts/test.dts | 13 +++
 configs/sandbox_defconfig |  1 +
 include/test/suites.h |  1 +
 test/boot/Makefile|  1 +
 test/boot/measurement.c   | 66 +++
 test/cmd_ut.c |  4 +++
 7 files changed, 99 insertions(+)
 create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index ff7e5584c5..241f397ba6 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
  * and sandbox64 builds.
  */
 
+#include 
 #include 
 
 #define USB_CLASS_HUB  9
 
 / {
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman {
};
 
@@ -342,6 +354,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index e430347356..67159b3d01 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include 
 #include 
 #include 
 #include 
@@ -68,6 +69,17 @@
osd0 = "/osd";
};
 
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman: binman {
};
 
@@ -1423,6 +1435,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
tpm {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 47417cb039..757dcac4ca 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -349,3 +349,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 1c7dc65966..48ed549c13 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -45,6 +45,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 52947580ae..068522cb9e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 obj-$(CONFIG_CEDIT) += cedit.o
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MEASUREMENT_TEST(_name, _flags)\
+   UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+   struct bootm_headers images;
+   const size_t size = 1024;
+   u8 *kernel;
+   u8 *initrd;
+   size_t i;
+
+   kernel = malloc(size);
+   initrd = malloc(size);
+
+   images.os.image_start = map_to_sysmem(kernel);
+   images.os.image_len = size;
+
+   images.rd_start = map_to_sysmem(initrd);
+   images.rd_end = images.rd_start + size;
+
+   images.ft_addr = malloc(size);
+   images.ft_len = size;
+
+   env_set("bootargs", "measurement testing");
+
+   for (i = 0; i < size; ++i) {
+   kernel[i] =

[PATCH v13 7/8] efi_loader: fix EFI_ENTRY point on get_active_pcr_banks

2023-10-19 Thread Eddie James
From: Ilias Apalodimas 

efi_tcg2_get_active_pcr_banks doesn't immediately call the
EFI_ENTRY() wrapper once it enters the function. Move the call a
few lines above to cover the error cases properly as well.

Signed-off-by: Ilias Apalodimas 
---
 lib/efi_loader/efi_tcg2.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 7ada536568..dae1b166c8 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -949,16 +949,16 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol 
*this,
struct udevice *dev;
efi_status_t ret;
 
+   EFI_ENTRY("%p, %p", this, active_pcr_banks);
+
if (!this || !active_pcr_banks) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
-
ret = tcg2_platform_get_tpm2(&dev);
if (ret != EFI_SUCCESS)
goto out;
 
-   EFI_ENTRY("%p, %p", this, active_pcr_banks);
ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);
 
 out:
-- 
2.39.3



[PATCH v13 1/8] tpm: Fix spelling for tpmu_ha union

2023-10-19 Thread Eddie James
tmpu -> tpmu

Signed-off-by: Eddie James 
Reviewed-by: Ilias Apalodimas 
---
 include/tpm-v2.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 2b6980e441..6684033deb 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -169,7 +169,7 @@ struct tcg_pcr_event {
 /**
  * Definition of TPMU_HA Union
  */
-union tmpu_ha {
+union tpmu_ha {
u8 sha1[TPM2_SHA1_DIGEST_SIZE];
u8 sha256[TPM2_SHA256_DIGEST_SIZE];
u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE];
@@ -185,7 +185,7 @@ union tmpu_ha {
  */
 struct tpmt_ha {
u16 hash_alg;
-   union tmpu_ha digest;
+   union tpmu_ha digest;
 } __packed;
 
 /**
-- 
2.39.3



[PATCH v13 2/8] tpm: sandbox: Update for needed TPM2 capabilities

2023-10-19 Thread Eddie James
The driver needs to support getting the PCRs in the capabilities
command. Fix various other things and support the max number
of PCRs for TPM2.
Remove the !SANDBOX dependency for EFI TCG2 as well.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v8:
 - Use >= for checking the property against TPM2_PROPERTIES_OFFSET

Changes since v5:
 - Remove the !SANDBOX dependency for EFI TCG2

 drivers/tpm/tpm2_tis_sandbox.c | 100 -
 lib/efi_loader/Kconfig |   2 -
 2 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index e4004cfcca..d15a28d9fc 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -22,11 +22,6 @@ enum tpm2_hierarchy {
TPM2_HIERARCHY_NB,
 };
 
-/* Subset of supported capabilities */
-enum tpm2_capability {
-   TPM_CAP_TPM_PROPERTIES = 0x6,
-};
-
 /* Subset of supported properties */
 #define TPM2_PROPERTIES_OFFSET 0x020E
 
@@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
TPM2_PROPERTY_NB,
 };
 
-#define SANDBOX_TPM_PCR_NB 1
+#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
+#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8)
 
 /*
  * Information about our TPM emulation. This is preserved in the sandbox
@@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 
*sendbuf,
int i, j;
 
/* TPM2_GetProperty */
-   u32 capability, property, property_count;
+   u32 capability, property, property_count, val;
 
/* TPM2_PCR_Read/Extend variables */
int pcr_index = 0;
@@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
case TPM2_CC_GET_CAPABILITY:
capability = get_unaligned_be32(sent);
sent += sizeof(capability);
-   if (capability != TPM_CAP_TPM_PROPERTIES) {
-   printf("Sandbox TPM only support TPM_CAPABILITIES\n");
-   return TPM2_RC_HANDLE;
-   }
-
property = get_unaligned_be32(sent);
sent += sizeof(property);
-   property -= TPM2_PROPERTIES_OFFSET;
-
property_count = get_unaligned_be32(sent);
sent += sizeof(property_count);
-   if (!property_count ||
-   property + property_count > TPM2_PROPERTY_NB) {
+
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   break;
+   case TPM2_CAP_TPM_PROPERTIES:
+   if (!property_count) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+
+   if (property >= TPM2_PROPERTIES_OFFSET &&
+   ((property - TPM2_PROPERTIES_OFFSET) +
+property_count > TPM2_PROPERTY_NB)) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+   break;
+   default:
+   printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
+  "TPM2_CAP_TPM_PROPERTIES\n");
rc = TPM2_RC_HANDLE;
return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
}
@@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
put_unaligned_be32(capability, recv);
recv += sizeof(capability);
 
-   /* Give the number of properties that follow */
-   put_unaligned_be32(property_count, recv);
-   recv += sizeof(property_count);
-
-   /* Fill with the properties */
-   for (i = 0; i < property_count; i++) {
-   put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
-  i, recv);
-   recv += sizeof(property);
-   put_unaligned_be32(tpm->properties[property + i],
-  recv);
-   recv += sizeof(property);
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   /* Give the number of algorithms supported - just 
SHA256 */
+   put_unaligned_be32(1, recv);
+   recv += sizeof(u32);
+
+   /* Give SHA256 algorithm */
+   put_unaligned_be16(TPM2_ALG_SHA256, recv);
+   recv += sizeof(u16);
+
+   /* Se

[PATCH v13 0/8] tpm: Support boot measurements

2023-10-19 Thread Eddie James
This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm 
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.

Changes since v12:
 - Rebase on master.
 - Add detail to documentation.

Changes since v11:
 - Rebase on next. Sorry for the delay (been on leave).

Changes since v10:
 - Fix commit message on efi_loader change
 - Drop python test change
 - Squash armv7 fix from Ilias

Changes since v9:
 - Rebase and add Ilias' fixes (thanks!)

Changes since v8:
 - Fix a sandbox driver off-by-one error in checking the property type.
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log and a configuration option
   for systems to select that for the bootm measurement. 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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Re-ordered the patches to put the sandbox TPM driver patch second
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs
 - Remove the !SANDBOX dependency for EFI TCG2
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
 - Change PCR indexes for initrd and dtb
 - Drop u8 casting in measurement test
 - Use bullets in documentation

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v2:
 - Add documentation.
 - Changed reserved memory address to the top of the RAM for sandbox dts.
 - Add measure state to booti and bootz.
 - Skip measurement for EFI images that should be measured

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.
 - Add test case
 - Drop #ifdefs for bootm
 - Add devicetree measurement config option
 - Update sandbox TPM driver

Eddie James (6):
  tpm: Fix spelling for tpmu_ha union
  tpm: sandbox: Update for needed TPM2 capabilities
  tpm: Support boot measurements
  bootm: Support boot measurement
  test: Add sandbox TPM boot measurement
  doc: Add measured boot documentation

Ilias Apalodimas (2):
  efi_loader: fix EFI_ENTRY point on get_active_pcr_banks
  test: use a non system PCR for testing PCR extend

 arch/sandbox/dts/sandbox.dtsi  |  13 +
 arch/sandbox/dts/test.dts  |  13 +
 boot/Kconfig   |  32 ++
 boot/bootm.c   |  74 +++
 cmd/booti.c|   1 +
 cmd/bootm.c|   2 +
 cmd/bootz.c|   1 +
 configs/sandbox_defconfig  |   1 +
 doc/usage/index.rst|   1 +
 doc/usage/measured_boot.rst|  23 +
 drivers/tpm/tpm2_tis_sandbox.c | 100 ++--
 include/bootm.h|  11 +
 include/efi_tcg2.h |  44 --
 include/image.h|   1 +
 include/test/suites.h  |   1 +
 include/tpm-v2.h   | 263 ++-
 lib/Kconfig|   4 +
 lib/efi_loader/Kconfig |   2 -
 lib/efi_loader/efi_tcg2.c  | 823 -
 lib/tpm-v2.c   | 814 
 test/boot/M

Re: [PATCH v12 6/8] doc: Add measured boot documentation

2023-10-19 Thread Eddie James



On 10/12/23 10:29, Simon Glass wrote:

Hi Eddie,

On Thu, 12 Oct 2023 at 08:08, Eddie James  wrote:

Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 

This could use a bit more detail. What pieces are measured? What DT
binding is used for the TPM? How is the info checked by the OS or
whatever?



Sure, I'll add a little bit more. The DT binding is described in the 
requirements section.







---
  doc/usage/index.rst |  1 +
  doc/usage/measured_boot.rst | 23 +++
  2 files changed, 24 insertions(+)
  create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index fa702920fa..fb043a8923 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -14,6 +14,7 @@ Use U-Boot
 partitions
 cmdline
 semihosting
+   measured_boot

  Shell commands
  --
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..8357b1f480
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.

Regards,
Simon


Re: [PATCH v12 5/8] test: Add sandbox TPM boot measurement

2023-10-19 Thread Eddie James



On 10/13/23 12:22, Ilias Apalodimas wrote:

Hi Eddie,

This doesn't apply on -master, can you please rebase?



Ugh I thought you wanted -next... I can rebase again.




Thanks
/Ilias

On Thu, 12 Oct 2023 at 16:49, Eddie James  wrote:

Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
  - Only compile in the measurement u-boot command when
CONFIG_MEASURED_BOOT is enabled.

  arch/sandbox/dts/sandbox.dtsi | 13 +++
  arch/sandbox/dts/test.dts | 13 +++
  configs/sandbox_defconfig |  1 +
  include/test/suites.h |  1 +
  test/boot/Makefile|  1 +
  test/boot/measurement.c   | 66 +++
  test/cmd_ut.c |  4 +++
  7 files changed, 99 insertions(+)
  create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index ff7e5584c5..241f397ba6 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
   * and sandbox64 builds.
   */

+#include 
  #include 

  #define USB_CLASS_HUB  9

  / {
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
 binman {
 };

@@ -342,6 +354,7 @@

 tpm2 {
 compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
 };

 triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9a863ea732..bb2ddd9bf2 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@

  /dts-v1/;

+#include 
  #include 
  #include 
  #include 
@@ -68,6 +69,17 @@
 osd0 = "/osd";
 };

+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
 binman: binman {
 };

@@ -1422,6 +1434,7 @@

 tpm2 {
 compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
 };

 tpm {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index d667cb9ae4..12c387a77e 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -349,3 +349,4 @@ CONFIG_UNIT_TEST=y
  CONFIG_UT_TIME=y
  CONFIG_UT_DM=y
  CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 1c7dc65966..48ed549c13 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -45,6 +45,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[]);
  int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
  int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[]);
  int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[]);
  int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
  int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[]);
  int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 52947580ae..068522cb9e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@

  obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
  obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o

  obj-$(CONFIG_EXPO) += expo.o
  obj-$(CONFIG_CEDIT) += cedit.o
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MEASUREMENT_TEST(_name, _flags)\
+   UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+   struct bootm_headers images;
+   const size_t size = 1024;
+   u8 *kernel;
+   u8 *initrd;
+   size_t i;
+
+   kernel = malloc(size);
+   initrd = malloc(size);
+
+   images.os.image_start = map_to_sysmem(kernel);
+   images.os.image_len = size;
+
+   images.rd_start = map_to_sysmem(init

[PATCH v12 4/8] bootm: Support boot measurement

2023-10-12 Thread Eddie James
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 a01e6cb8aa..abbc72f4cf 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -685,6 +685,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 b1c3afe0a3..11b6b3c292 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #if defined(CONFIG_CMD_USB)
 #include 
 #endif
@@ -673,6 +674,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;
+
+   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 

[PATCH v12 2/8] tpm: sandbox: Update for needed TPM2 capabilities

2023-10-12 Thread Eddie James
The driver needs to support getting the PCRs in the capabilities
command. Fix various other things and support the max number
of PCRs for TPM2.
Remove the !SANDBOX dependency for EFI TCG2 as well.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v8:
 - Use >= for checking the property against TPM2_PROPERTIES_OFFSET

Changes since v5:
 - Remove the !SANDBOX dependency for EFI TCG2

 drivers/tpm/tpm2_tis_sandbox.c | 100 -
 lib/efi_loader/Kconfig |   2 -
 2 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index e4004cfcca..d15a28d9fc 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -22,11 +22,6 @@ enum tpm2_hierarchy {
TPM2_HIERARCHY_NB,
 };
 
-/* Subset of supported capabilities */
-enum tpm2_capability {
-   TPM_CAP_TPM_PROPERTIES = 0x6,
-};
-
 /* Subset of supported properties */
 #define TPM2_PROPERTIES_OFFSET 0x020E
 
@@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
TPM2_PROPERTY_NB,
 };
 
-#define SANDBOX_TPM_PCR_NB 1
+#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
+#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8)
 
 /*
  * Information about our TPM emulation. This is preserved in the sandbox
@@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 
*sendbuf,
int i, j;
 
/* TPM2_GetProperty */
-   u32 capability, property, property_count;
+   u32 capability, property, property_count, val;
 
/* TPM2_PCR_Read/Extend variables */
int pcr_index = 0;
@@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
case TPM2_CC_GET_CAPABILITY:
capability = get_unaligned_be32(sent);
sent += sizeof(capability);
-   if (capability != TPM_CAP_TPM_PROPERTIES) {
-   printf("Sandbox TPM only support TPM_CAPABILITIES\n");
-   return TPM2_RC_HANDLE;
-   }
-
property = get_unaligned_be32(sent);
sent += sizeof(property);
-   property -= TPM2_PROPERTIES_OFFSET;
-
property_count = get_unaligned_be32(sent);
sent += sizeof(property_count);
-   if (!property_count ||
-   property + property_count > TPM2_PROPERTY_NB) {
+
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   break;
+   case TPM2_CAP_TPM_PROPERTIES:
+   if (!property_count) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+
+   if (property >= TPM2_PROPERTIES_OFFSET &&
+   ((property - TPM2_PROPERTIES_OFFSET) +
+property_count > TPM2_PROPERTY_NB)) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+   break;
+   default:
+   printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
+  "TPM2_CAP_TPM_PROPERTIES\n");
rc = TPM2_RC_HANDLE;
return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
}
@@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
put_unaligned_be32(capability, recv);
recv += sizeof(capability);
 
-   /* Give the number of properties that follow */
-   put_unaligned_be32(property_count, recv);
-   recv += sizeof(property_count);
-
-   /* Fill with the properties */
-   for (i = 0; i < property_count; i++) {
-   put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
-  i, recv);
-   recv += sizeof(property);
-   put_unaligned_be32(tpm->properties[property + i],
-  recv);
-   recv += sizeof(property);
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   /* Give the number of algorithms supported - just 
SHA256 */
+   put_unaligned_be32(1, recv);
+   recv += sizeof(u32);
+
+   /* Give SHA256 algorithm */
+   put_unaligned_be16(TPM2_ALG_SHA256, recv);
+   recv += sizeof(u16);
+
+   /* Se

[PATCH v12 8/8] test: use a non system PCR for testing PCR extend

2023-10-12 Thread Eddie James
From: Ilias Apalodimas 

We currently use PCR 0 for testing the PCR read/extend functionality in
our selftests.  How ever those PCRs are defined by the TCG spec for
platform use.  For example if the tests run *after* the efi subsystem
initialization, which extends PCRs 0 & 7 it will give a false positive.

So let's switch over to a PCR which is more suitable and is defined for
OS use.  It's worth noting that we are using PCR10 here, since PCR9 is
used internally by U-Boot if we choose to measure the loaded DTB

Reviewed-by: Simon Glass 
Signed-off-by: Ilias Apalodimas 
---
 test/py/tests/test_tpm2.py | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py
index c2579fa02c..47392b87a9 100644
--- a/test/py/tests/test_tpm2.py
+++ b/test/py/tests/test_tpm2.py
@@ -239,7 +239,7 @@ def test_tpm2_dam_parameters(u_boot_console):
 def test_tpm2_pcr_read(u_boot_console):
 """Execute a TPM2_PCR_Read command.
 
-Perform a PCR read of the 0th PCR. Must be zero.
+Perform a PCR read of the 10th PCR. Must be zero.
 """
 if is_sandbox(u_boot_console):
 tpm2_sandbox_init(u_boot_console)
@@ -247,7 +247,7 @@ def test_tpm2_pcr_read(u_boot_console):
 force_init(u_boot_console)
 ram = u_boot_utils.find_ram_base(u_boot_console)
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram)
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
@@ -257,7 +257,7 @@ def test_tpm2_pcr_read(u_boot_console):
 updates = int(re.findall(r'\d+', str)[0])
 
 # Check the output value
-assert 'PCR #0 content' in read_pcr
+assert 'PCR #10 content' in read_pcr
 assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr
 
 @pytest.mark.buildconfigspec('cmd_tpm_v2')
@@ -275,19 +275,19 @@ def test_tpm2_pcr_extend(u_boot_console):
 force_init(u_boot_console)
 ram = u_boot_utils.find_ram_base(u_boot_console)
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 str = re.findall(r'\d+ known updates', read_pcr)[0]
 updates = int(re.findall(r'\d+', str)[0])
 
-u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
 # Read the value back into a different place so we can still use 'ram' as
 # our zero bytes
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr
@@ -297,11 +297,11 @@ def test_tpm2_pcr_extend(u_boot_console):
 new_updates = int(re.findall(r'\d+', str)[0])
 assert (updates + 1) == new_updates
 
-u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 assert '7a 05 01 f5 95 7b df 9c b3 a8 ff 49 66 f0 22 65' in read_pcr
-- 
2.39.3



[PATCH v12 3/8] tpm: Support boot measurements

2023-10-12 Thread Eddie James
Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v10:
 - Fix compile warning for armv7 (thanks Ilias)

Changes since v8:
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log. This should only be used
   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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions

 include/efi_tcg2.h|  44 --
 include/tpm-v2.h  | 259 
 lib/Kconfig   |   4 +
 lib/efi_loader/efi_tcg2.c | 821 --
 lib/tpm-v2.c  | 814 +
 5 files changed, 1154 insertions(+), 788 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..b21c5cb3dd 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
 #define BOOT_SERVICE_CAPABILITY_MIN \
offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id: algorithm defined in enum tpm2_algorithms
- *  @digest_size:  size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-   u16  algorithm_id;
-   u16  digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature: signature, set to Spec ID Event03
- * @platform_class:class defined in TCG ACPI Specification
- * Client  Common Header.
- * @spec_version_minor:minor version
- * @spec_version_major:major version
- * @spec_version_errata:   major version
- * @uintn_size:size of the efi_uintn_t fields used in 
various
- * data structures used in this specification.
- * 0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:  hashing algorithms used in this event log
- * @digest_sizes:  array of number_of_algorithms pairs
- * 1st member defines the algorithm id
- * 2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-   u8 signature[16];
-   u32 platform_class;
-   u8 spec_version_minor;
-   u8 spec_version_major;
-   u8 spec_errata;
-   u8 uintn_size;
-   u32 number_of_algorithms;
-   struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
-} __packed;
-
 /**
  * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - l

[PATCH v12 7/8] efi_loader: fix EFI_ENTRY point on get_active_pcr_banks

2023-10-12 Thread Eddie James
From: Ilias Apalodimas 

efi_tcg2_get_active_pcr_banks doesn't immediately call the
EFI_ENTRY() wrapper once it enters the function. Move the call a
few lines above to cover the error cases properly as well.

Signed-off-by: Ilias Apalodimas 
---
 lib/efi_loader/efi_tcg2.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 7ada536568..dae1b166c8 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -949,16 +949,16 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol 
*this,
struct udevice *dev;
efi_status_t ret;
 
+   EFI_ENTRY("%p, %p", this, active_pcr_banks);
+
if (!this || !active_pcr_banks) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
-
ret = tcg2_platform_get_tpm2(&dev);
if (ret != EFI_SUCCESS)
goto out;
 
-   EFI_ENTRY("%p, %p", this, active_pcr_banks);
ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);
 
 out:
-- 
2.39.3



[PATCH v12 1/8] tpm: Fix spelling for tpmu_ha union

2023-10-12 Thread Eddie James
tmpu -> tpmu

Signed-off-by: Eddie James 
Reviewed-by: Ilias Apalodimas 
---
 include/tpm-v2.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 2b6980e441..6684033deb 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -169,7 +169,7 @@ struct tcg_pcr_event {
 /**
  * Definition of TPMU_HA Union
  */
-union tmpu_ha {
+union tpmu_ha {
u8 sha1[TPM2_SHA1_DIGEST_SIZE];
u8 sha256[TPM2_SHA256_DIGEST_SIZE];
u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE];
@@ -185,7 +185,7 @@ union tmpu_ha {
  */
 struct tpmt_ha {
u16 hash_alg;
-   union tmpu_ha digest;
+   union tpmu_ha digest;
 } __packed;
 
 /**
-- 
2.39.3



[PATCH v12 6/8] doc: Add measured boot documentation

2023-10-12 Thread Eddie James
Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
---
 doc/usage/index.rst |  1 +
 doc/usage/measured_boot.rst | 23 +++
 2 files changed, 24 insertions(+)
 create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index fa702920fa..fb043a8923 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -14,6 +14,7 @@ Use U-Boot
partitions
cmdline
semihosting
+   measured_boot
 
 Shell commands
 --
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..8357b1f480
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
-- 
2.39.3



[PATCH v12 5/8] test: Add sandbox TPM boot measurement

2023-10-12 Thread Eddie James
Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
 - Only compile in the measurement u-boot command when
   CONFIG_MEASURED_BOOT is enabled.

 arch/sandbox/dts/sandbox.dtsi | 13 +++
 arch/sandbox/dts/test.dts | 13 +++
 configs/sandbox_defconfig |  1 +
 include/test/suites.h |  1 +
 test/boot/Makefile|  1 +
 test/boot/measurement.c   | 66 +++
 test/cmd_ut.c |  4 +++
 7 files changed, 99 insertions(+)
 create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index ff7e5584c5..241f397ba6 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
  * and sandbox64 builds.
  */
 
+#include 
 #include 
 
 #define USB_CLASS_HUB  9
 
 / {
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman {
};
 
@@ -342,6 +354,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9a863ea732..bb2ddd9bf2 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include 
 #include 
 #include 
 #include 
@@ -68,6 +69,17 @@
osd0 = "/osd";
};
 
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman: binman {
};
 
@@ -1422,6 +1434,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
tpm {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index d667cb9ae4..12c387a77e 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -349,3 +349,4 @@ CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 1c7dc65966..48ed549c13 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -45,6 +45,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 52947580ae..068522cb9e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 obj-$(CONFIG_CEDIT) += cedit.o
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MEASUREMENT_TEST(_name, _flags)\
+   UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+   struct bootm_headers images;
+   const size_t size = 1024;
+   u8 *kernel;
+   u8 *initrd;
+   size_t i;
+
+   kernel = malloc(size);
+   initrd = malloc(size);
+
+   images.os.image_start = map_to_sysmem(kernel);
+   images.os.image_len = size;
+
+   images.rd_start = map_to_sysmem(initrd);
+   images.rd_end = images.rd_start + size;
+
+   images.ft_addr = malloc(size);
+   images.ft_len = size;
+
+   env_set("bootargs", "measurement testing");
+
+   for (i = 0; i < size; ++i) {
+   kernel[i] =

[PATCH v12 0/8] tpm: Support boot measurements

2023-10-12 Thread Eddie James
This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm 
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.

Changes since v11:
 - Rebase on next. Sorry for the delay (been on leave).

Changes since v10:
 - Fix commit message on efi_loader change
 - Drop python test change
 - Squash armv7 fix from Ilias

Changes since v9:
 - Rebase and add Ilias' fixes (thanks!)

Changes since v8:
 - Fix a sandbox driver off-by-one error in checking the property type.
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log and a configuration option
   for systems to select that for the bootm measurement. 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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Re-ordered the patches to put the sandbox TPM driver patch second
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs
 - Remove the !SANDBOX dependency for EFI TCG2
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
 - Change PCR indexes for initrd and dtb
 - Drop u8 casting in measurement test
 - Use bullets in documentation

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v2:
 - Add documentation.
 - Changed reserved memory address to the top of the RAM for sandbox dts.
 - Add measure state to booti and bootz.
 - Skip measurement for EFI images that should be measured

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.
 - Add test case
 - Drop #ifdefs for bootm
 - Add devicetree measurement config option
 - Update sandbox TPM driver

Eddie James (6):
  tpm: Fix spelling for tpmu_ha union
  tpm: sandbox: Update for needed TPM2 capabilities
  tpm: Support boot measurements
  bootm: Support boot measurement
  test: Add sandbox TPM boot measurement
  doc: Add measured boot documentation

Ilias Apalodimas (2):
  efi_loader: fix EFI_ENTRY point on get_active_pcr_banks
  test: use a non system PCR for testing PCR extend

 arch/sandbox/dts/sandbox.dtsi  |  13 +
 arch/sandbox/dts/test.dts  |  13 +
 boot/Kconfig   |  32 ++
 boot/bootm.c   |  74 +++
 cmd/booti.c|   1 +
 cmd/bootm.c|   2 +
 cmd/bootz.c|   1 +
 configs/sandbox_defconfig  |   1 +
 doc/usage/index.rst|   1 +
 doc/usage/measured_boot.rst|  23 +
 drivers/tpm/tpm2_tis_sandbox.c | 100 ++--
 include/bootm.h|  11 +
 include/efi_tcg2.h |  44 --
 include/image.h|   1 +
 include/test/suites.h  |   1 +
 include/tpm-v2.h   | 263 ++-
 lib/Kconfig|   4 +
 lib/efi_loader/Kconfig |   2 -
 lib/efi_loader/efi_tcg2.c  | 823 -
 lib/tpm-v2.c   | 814 
 test/boot/Makefile |   1 +
 test/boot/measurement.c   

Re: [PATCH v11 3/8] tpm: Support boot measurements

2023-08-10 Thread Eddie James



On 8/10/23 02:44, Ilias Apalodimas wrote:

On Wed, Aug 09, 2023 at 09:01:40AM -0500, Eddie James wrote:

On 8/9/23 05:43, Ilias Apalodimas wrote:

On Wed, 9 Aug 2023 at 13:42, Heinrich Schuchardt  wrote:

On 8/9/23 10:34, Ilias Apalodimas wrote:

Hi Eddie


On Mon, Aug 07, 2023 at 02:25:37PM -0500, Eddie James wrote:

Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v10:
- Fix compile warning for armv7 (thanks Ilias)


This doesn't apply cleanly and I think it's because of commit
d12c3efe53107.  This was merged after my rebase.  Can you rebase on top of
-master and resend?

Tom has started moving new stuff into next as the merge window is closed.

Ah good point, I was going to let this soak on -next anyway.  So
please rebase against -next


I did base this series on next actually, so it should apply there already
(unless there are conflicting changes since Monday). Please let me know if I
do need to rebase it.


I tried using 321d7b4d875a from next and still get an error.
Patch failed at 0003 tpm: Support boot measurements
hint: Use 'git am --show-current-patch=diff' to see the failed patch



OK, I'll rebase.




Thanks
/Ilias

Thanks,

Eddie



Thanks
/Ilias

Best regards

Heinrich


Re: [PATCH v11 3/8] tpm: Support boot measurements

2023-08-09 Thread Eddie James



On 8/9/23 05:43, Ilias Apalodimas wrote:

On Wed, 9 Aug 2023 at 13:42, Heinrich Schuchardt  wrote:

On 8/9/23 10:34, Ilias Apalodimas wrote:

Hi Eddie


On Mon, Aug 07, 2023 at 02:25:37PM -0500, Eddie James wrote:

Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v10:
   - Fix compile warning for armv7 (thanks Ilias)


This doesn't apply cleanly and I think it's because of commit
d12c3efe53107.  This was merged after my rebase.  Can you rebase on top of
-master and resend?

Tom has started moving new stuff into next as the merge window is closed.

Ah good point, I was going to let this soak on -next anyway.  So
please rebase against -next



I did base this series on next actually, so it should apply there 
already (unless there are conflicting changes since Monday). Please let 
me know if I do need to rebase it.



Thanks,

Eddie




Thanks
/Ilias

Best regards

Heinrich


[PATCH v11 3/8] tpm: Support boot measurements

2023-08-07 Thread Eddie James
Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v10:
 - Fix compile warning for armv7 (thanks Ilias)

Changes since v8:
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log. This should only be used
   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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions

 include/efi_tcg2.h|   44 --
 include/tpm-v2.h  |  259 +
 lib/Kconfig   |4 +
 lib/efi_loader/efi_tcg2.c | 1054 +++--
 lib/tpm-v2.c  |  814 
 5 files changed, 1154 insertions(+), 1021 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..b21c5cb3dd 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
 #define BOOT_SERVICE_CAPABILITY_MIN \
offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id: algorithm defined in enum tpm2_algorithms
- *  @digest_size:  size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-   u16  algorithm_id;
-   u16  digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature: signature, set to Spec ID Event03
- * @platform_class:class defined in TCG ACPI Specification
- * Client  Common Header.
- * @spec_version_minor:minor version
- * @spec_version_major:major version
- * @spec_version_errata:   major version
- * @uintn_size:size of the efi_uintn_t fields used in 
various
- * data structures used in this specification.
- * 0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:  hashing algorithms used in this event log
- * @digest_sizes:  array of number_of_algorithms pairs
- * 1st member defines the algorithm id
- * 2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-   u8 signature[16];
-   u32 platform_class;
-   u8 spec_version_minor;
-   u8 spec_version_major;
-   u8 spec_errata;
-   u8 uintn_size;
-   u32 number_of_algorithms;
-   struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
-} __packed;
-
 /**
  * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - l

[PATCH v11 2/8] tpm: sandbox: Update for needed TPM2 capabilities

2023-08-07 Thread Eddie James
The driver needs to support getting the PCRs in the capabilities
command. Fix various other things and support the max number
of PCRs for TPM2.
Remove the !SANDBOX dependency for EFI TCG2 as well.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v8:
 - Use >= for checking the property against TPM2_PROPERTIES_OFFSET

Changes since v5:
 - Remove the !SANDBOX dependency for EFI TCG2

 drivers/tpm/tpm2_tis_sandbox.c | 100 -
 lib/efi_loader/Kconfig |   2 -
 2 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index e4004cfcca..d15a28d9fc 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -22,11 +22,6 @@ enum tpm2_hierarchy {
TPM2_HIERARCHY_NB,
 };
 
-/* Subset of supported capabilities */
-enum tpm2_capability {
-   TPM_CAP_TPM_PROPERTIES = 0x6,
-};
-
 /* Subset of supported properties */
 #define TPM2_PROPERTIES_OFFSET 0x020E
 
@@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
TPM2_PROPERTY_NB,
 };
 
-#define SANDBOX_TPM_PCR_NB 1
+#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
+#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8)
 
 /*
  * Information about our TPM emulation. This is preserved in the sandbox
@@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 
*sendbuf,
int i, j;
 
/* TPM2_GetProperty */
-   u32 capability, property, property_count;
+   u32 capability, property, property_count, val;
 
/* TPM2_PCR_Read/Extend variables */
int pcr_index = 0;
@@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
case TPM2_CC_GET_CAPABILITY:
capability = get_unaligned_be32(sent);
sent += sizeof(capability);
-   if (capability != TPM_CAP_TPM_PROPERTIES) {
-   printf("Sandbox TPM only support TPM_CAPABILITIES\n");
-   return TPM2_RC_HANDLE;
-   }
-
property = get_unaligned_be32(sent);
sent += sizeof(property);
-   property -= TPM2_PROPERTIES_OFFSET;
-
property_count = get_unaligned_be32(sent);
sent += sizeof(property_count);
-   if (!property_count ||
-   property + property_count > TPM2_PROPERTY_NB) {
+
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   break;
+   case TPM2_CAP_TPM_PROPERTIES:
+   if (!property_count) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+
+   if (property >= TPM2_PROPERTIES_OFFSET &&
+   ((property - TPM2_PROPERTIES_OFFSET) +
+property_count > TPM2_PROPERTY_NB)) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+   break;
+   default:
+   printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
+  "TPM2_CAP_TPM_PROPERTIES\n");
rc = TPM2_RC_HANDLE;
return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
}
@@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
put_unaligned_be32(capability, recv);
recv += sizeof(capability);
 
-   /* Give the number of properties that follow */
-   put_unaligned_be32(property_count, recv);
-   recv += sizeof(property_count);
-
-   /* Fill with the properties */
-   for (i = 0; i < property_count; i++) {
-   put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
-  i, recv);
-   recv += sizeof(property);
-   put_unaligned_be32(tpm->properties[property + i],
-  recv);
-   recv += sizeof(property);
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   /* Give the number of algorithms supported - just 
SHA256 */
+   put_unaligned_be32(1, recv);
+   recv += sizeof(u32);
+
+   /* Give SHA256 algorithm */
+   put_unaligned_be16(TPM2_ALG_SHA256, recv);
+   recv += sizeof(u16);
+
+   /* Se

[PATCH v11 8/8] test: use a non system PCR for testing PCR extend

2023-08-07 Thread Eddie James
From: Ilias Apalodimas 

We currently use PCR 0 for testing the PCR read/extend functionality in
our selftests.  How ever those PCRs are defined by the TCG spec for
platform use.  For example if the tests run *after* the efi subsystem
initialization, which extends PCRs 0 & 7 it will give a false positive.

So let's switch over to a PCR which is more suitable and is defined for
OS use.  It's worth noting that we are using PCR10 here, since PCR9 is
used internally by U-Boot if we choose to measure the loaded DTB

Reviewed-by: Simon Glass 
Signed-off-by: Ilias Apalodimas 
---
 test/py/tests/test_tpm2.py | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py
index fce689cd99..8cd3046285 100644
--- a/test/py/tests/test_tpm2.py
+++ b/test/py/tests/test_tpm2.py
@@ -236,7 +236,7 @@ def test_tpm2_dam_parameters(u_boot_console):
 def test_tpm2_pcr_read(u_boot_console):
 """Execute a TPM2_PCR_Read command.
 
-Perform a PCR read of the 0th PCR. Must be zero.
+Perform a PCR read of the 10th PCR. Must be zero.
 """
 if is_sandbox(u_boot_console):
 tpm2_sandbox_init(u_boot_console)
@@ -244,7 +244,7 @@ def test_tpm2_pcr_read(u_boot_console):
 force_init(u_boot_console)
 ram = u_boot_utils.find_ram_base(u_boot_console)
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram)
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
@@ -254,7 +254,7 @@ def test_tpm2_pcr_read(u_boot_console):
 updates = int(re.findall(r'\d+', str)[0])
 
 # Check the output value
-assert 'PCR #0 content' in read_pcr
+assert 'PCR #10 content' in read_pcr
 assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr
 
 @pytest.mark.buildconfigspec('cmd_tpm_v2')
@@ -272,19 +272,19 @@ def test_tpm2_pcr_extend(u_boot_console):
 force_init(u_boot_console)
 ram = u_boot_utils.find_ram_base(u_boot_console)
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 str = re.findall(r'\d+ known updates', read_pcr)[0]
 updates = int(re.findall(r'\d+', str)[0])
 
-u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
 # Read the value back into a different place so we can still use 'ram' as
 # our zero bytes
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr
@@ -294,11 +294,11 @@ def test_tpm2_pcr_extend(u_boot_console):
 new_updates = int(re.findall(r'\d+', str)[0])
 assert (updates + 1) == new_updates
 
-u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 assert '7a 05 01 f5 95 7b df 9c b3 a8 ff 49 66 f0 22 65' in read_pcr
-- 
2.39.3



[PATCH v11 5/8] test: Add sandbox TPM boot measurement

2023-08-07 Thread Eddie James
Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
 - Only compile in the measurement u-boot command when
   CONFIG_MEASURED_BOOT is enabled.

 arch/sandbox/dts/sandbox.dtsi | 13 +++
 arch/sandbox/dts/test.dts | 13 +++
 configs/sandbox_defconfig |  1 +
 include/test/suites.h |  1 +
 test/boot/Makefile|  1 +
 test/boot/measurement.c   | 66 +++
 test/cmd_ut.c |  4 +++
 7 files changed, 99 insertions(+)
 create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 30a305c4d2..ed39d20c6a 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
  * and sandbox64 builds.
  */
 
+#include 
 #include 
 
 #define USB_CLASS_HUB  9
 
 / {
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman {
};
 
@@ -336,6 +348,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index ff9f9222e6..0bac073178 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include 
 #include 
 #include 
 #include 
@@ -66,6 +67,17 @@
osd0 = "/osd";
};
 
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman: binman {
};
 
@@ -1365,6 +1377,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
tpm {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1ec44d5b33..85ef821296 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -344,3 +344,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 1c7dc65966..48ed549c13 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -45,6 +45,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 22ed61c8fa..2dbb032a7e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MEASUREMENT_TEST(_name, _flags)\
+   UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+   struct bootm_headers images;
+   const size_t size = 1024;
+   u8 *kernel;
+   u8 *initrd;
+   size_t i;
+
+   kernel = malloc(size);
+   initrd = malloc(size);
+
+   images.os.image_start = map_to_sysmem(kernel);
+   images.os.image_len = size;
+
+   images.rd_start = map_to_sysmem(initrd);
+   images.rd_end = images.rd_start + size;
+
+   images.ft_addr = malloc(size);
+   images.ft_len = size;
+
+   env_set("bootargs", "measurement testing");
+
+   for (i = 0; i < size; ++i) {
+   kernel[i] = 0xf0 | (i & 0xf);
+   initrd[i] = (i &

[PATCH v11 1/8] tpm: Fix spelling for tpmu_ha union

2023-08-07 Thread Eddie James
tmpu -> tpmu

Signed-off-by: Eddie James 
Reviewed-by: Ilias Apalodimas 
---
 include/tpm-v2.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 2b6980e441..6684033deb 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -169,7 +169,7 @@ struct tcg_pcr_event {
 /**
  * Definition of TPMU_HA Union
  */
-union tmpu_ha {
+union tpmu_ha {
u8 sha1[TPM2_SHA1_DIGEST_SIZE];
u8 sha256[TPM2_SHA256_DIGEST_SIZE];
u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE];
@@ -185,7 +185,7 @@ union tmpu_ha {
  */
 struct tpmt_ha {
u16 hash_alg;
-   union tmpu_ha digest;
+   union tpmu_ha digest;
 } __packed;
 
 /**
-- 
2.39.3



[PATCH v11 7/8] efi_loader: fix EFI_ENTRY point on get_active_pcr_banks

2023-08-07 Thread Eddie James
From: Ilias Apalodimas 

efi_tcg2_get_active_pcr_banks doesn't immediately call the
EFI_ENTRY() wrapper once it enters the function. Move the call a
few lines above to cover the error cases properly as well.

Signed-off-by: Ilias Apalodimas 
---
 lib/efi_loader/efi_tcg2.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 5f0f4b5dd2..829bae7436 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -718,16 +718,16 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol 
*this,
struct udevice *dev;
efi_status_t ret;
 
+   EFI_ENTRY("%p, %p", this, active_pcr_banks);
+
if (!this || !active_pcr_banks) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
-
ret = tcg2_platform_get_tpm2(&dev);
if (ret != EFI_SUCCESS)
goto out;
 
-   EFI_ENTRY("%p, %p", this, active_pcr_banks);
ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);
 
 out:
-- 
2.39.3



[PATCH v11 0/8] tpm: Support boot measurements

2023-08-07 Thread Eddie James
This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm 
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.

Changes since v10:
 - Fix commit message on efi_loader change
 - Drop python test change
 - Squash armv7 fix from Ilias

Changes since v9:
 - Rebase and add Ilias' fixes (thanks!)

Changes since v8:
 - Fix a sandbox driver off-by-one error in checking the property type.
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log and a configuration option
   for systems to select that for the bootm measurement. 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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Re-ordered the patches to put the sandbox TPM driver patch second
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs
 - Remove the !SANDBOX dependency for EFI TCG2
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
 - Change PCR indexes for initrd and dtb
 - Drop u8 casting in measurement test
 - Use bullets in documentation

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v2:
 - Add documentation.
 - Changed reserved memory address to the top of the RAM for sandbox dts.
 - Add measure state to booti and bootz.
 - Skip measurement for EFI images that should be measured

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.
 - Add test case
 - Drop #ifdefs for bootm
 - Add devicetree measurement config option
 - Update sandbox TPM driver

Eddie James (6):
  tpm: Fix spelling for tpmu_ha union
  tpm: sandbox: Update for needed TPM2 capabilities
  tpm: Support boot measurements
  bootm: Support boot measurement
  test: Add sandbox TPM boot measurement
  doc: Add measured boot documentation

Ilias Apalodimas (2):
  efi_loader: fix EFI_ENTRY point on get_active_pcr_banks
  test: use a non system PCR for testing PCR extend

 arch/sandbox/dts/sandbox.dtsi  |   13 +
 arch/sandbox/dts/test.dts  |   13 +
 boot/Kconfig   |   32 +
 boot/bootm.c   |   74 +++
 cmd/booti.c|1 +
 cmd/bootm.c|2 +
 cmd/bootz.c|1 +
 configs/sandbox_defconfig  |1 +
 doc/usage/index.rst|1 +
 doc/usage/measured_boot.rst|   23 +
 drivers/tpm/tpm2_tis_sandbox.c |  100 ++-
 include/bootm.h|   11 +
 include/efi_tcg2.h |   44 --
 include/image.h|1 +
 include/test/suites.h  |1 +
 include/tpm-v2.h   |  263 +++-
 lib/Kconfig|4 +
 lib/efi_loader/Kconfig |2 -
 lib/efi_loader/efi_tcg2.c  | 1056 +++-
 lib/tpm-v2.c   |  814 
 test/boot/Makefile |1 +
 test/boot/measurement.c|   66 ++
 test/cmd_ut.c  |4 +
 test/py/tests/test_tpm2.p

[PATCH v11 6/8] doc: Add measured boot documentation

2023-08-07 Thread Eddie James
Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
---
 doc/usage/index.rst |  1 +
 doc/usage/measured_boot.rst | 23 +++
 2 files changed, 24 insertions(+)
 create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 388e59f173..64eb362aef 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -13,6 +13,7 @@ Use U-Boot
partitions
cmdline
semihosting
+   measured_boot
 
 Shell commands
 --
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..8357b1f480
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
-- 
2.39.3



[PATCH v11 4/8] bootm: Support boot measurement

2023-08-07 Thread Eddie James
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 a643a3d128..b160b20599 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -675,6 +675,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 75f0b4a9af..c20a688749 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #if defined(CONFIG_CMD_USB)
 #include 
 #endif
@@ -673,6 +674,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;
+
+   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 

Re: [PATCH v10 07/10] efi_loader: fix EFI_ENTRY point on get_active_pcr_banks

2023-08-07 Thread Eddie James



On 8/7/23 10:56, Ilias Apalodimas wrote:

Hi Eddie,

On Mon, 7 Aug 2023 at 18:17, Eddie James  wrote:

From: Ilias Apalodimas 

We need a commit message for that.  Something along the lines of
efi_tcg2_get_active_pcr_banks() doesnt immediately call the
EFI_ENTRY() wrappers once it enters the function.  Move the call a few
lines above and cover the error cases properly as well



Oops, yep. I'll fix this too.


Thanks,

Eddie




Thanks
/Ilias

Signed-off-by: Ilias Apalodimas 
---
  lib/efi_loader/efi_tcg2.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 5f0f4b5dd2..829bae7436 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -718,16 +718,16 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol 
*this,
 struct udevice *dev;
 efi_status_t ret;

+   EFI_ENTRY("%p, %p", this, active_pcr_banks);
+
 if (!this || !active_pcr_banks) {
 ret = EFI_INVALID_PARAMETER;
 goto out;
 }
-
 ret = tcg2_platform_get_tpm2(&dev);
 if (ret != EFI_SUCCESS)
 goto out;

-   EFI_ENTRY("%p, %p", this, active_pcr_banks);
 ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);

  out:
--
2.39.3



Re: [PATCH v10 10/10] fix armv7 compilation warning

2023-08-07 Thread Eddie James



On 8/7/23 10:50, Ilias Apalodimas wrote:

Hi Eddie,

On Mon, 7 Aug 2023 at 18:18, Eddie James  wrote:

From: Ilias Apalodimas 

Signed-off-by: Ilias Apalodimas 
---
  lib/tpm-v2.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index d22e21985b..bd0fb078dc 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -671,7 +671,7 @@ __weak int tcg2_platform_get_log(struct udevice *dev, void 
**addr, u32 *size)
 } else {
 struct ofnode_phandle_args args;
 phys_addr_t a;
-   phys_size_t s;
+   fdt_size_t s;

It's been a while since I fixed this, but iirc this had to be squashed
to your changes?



Oh, ok, I can do that.

Thanks,

Eddie




Cheers
/Ilias

 if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
0, &args))
--
2.39.3



[PATCH v10 05/10] test: Add sandbox TPM boot measurement

2023-08-07 Thread Eddie James
Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
 - Only compile in the measurement u-boot command when
   CONFIG_MEASURED_BOOT is enabled.

 arch/sandbox/dts/sandbox.dtsi | 13 +++
 arch/sandbox/dts/test.dts | 13 +++
 configs/sandbox_defconfig |  1 +
 include/test/suites.h |  1 +
 test/boot/Makefile|  1 +
 test/boot/measurement.c   | 66 +++
 test/cmd_ut.c |  4 +++
 7 files changed, 99 insertions(+)
 create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 30a305c4d2..ed39d20c6a 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
  * and sandbox64 builds.
  */
 
+#include 
 #include 
 
 #define USB_CLASS_HUB  9
 
 / {
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman {
};
 
@@ -336,6 +348,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index ff9f9222e6..0bac073178 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include 
 #include 
 #include 
 #include 
@@ -66,6 +67,17 @@
osd0 = "/osd";
};
 
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman: binman {
};
 
@@ -1365,6 +1377,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
tpm {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1ec44d5b33..85ef821296 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -344,3 +344,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 1c7dc65966..48ed549c13 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -45,6 +45,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 22ed61c8fa..2dbb032a7e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MEASUREMENT_TEST(_name, _flags)\
+   UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+   struct bootm_headers images;
+   const size_t size = 1024;
+   u8 *kernel;
+   u8 *initrd;
+   size_t i;
+
+   kernel = malloc(size);
+   initrd = malloc(size);
+
+   images.os.image_start = map_to_sysmem(kernel);
+   images.os.image_len = size;
+
+   images.rd_start = map_to_sysmem(initrd);
+   images.rd_end = images.rd_start + size;
+
+   images.ft_addr = malloc(size);
+   images.ft_len = size;
+
+   env_set("bootargs", "measurement testing");
+
+   for (i = 0; i < size; ++i) {
+   kernel[i] = 0xf0 | (i & 0xf);
+   initrd[i] = (i &

[PATCH v10 10/10] fix armv7 compilation warning

2023-08-07 Thread Eddie James
From: Ilias Apalodimas 

Signed-off-by: Ilias Apalodimas 
---
 lib/tpm-v2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index d22e21985b..bd0fb078dc 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -671,7 +671,7 @@ __weak int tcg2_platform_get_log(struct udevice *dev, void 
**addr, u32 *size)
} else {
struct ofnode_phandle_args args;
phys_addr_t a;
-   phys_size_t s;
+   fdt_size_t s;
 
if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
   0, &args))
-- 
2.39.3



[PATCH v10 08/10] test: use a non system PCR for testing PCR extend

2023-08-07 Thread Eddie James
From: Ilias Apalodimas 

We currently use PCR 0 for testing the PCR read/extend functionality in
our selftests.  How ever those PCRs are defined by the TCG spec for
platform use.  For example if the tests run *after* the efi subsystem
initialization, which extends PCRs 0 & 7 it will give a false positive.

So let's switch over to a PCR which is more suitable and is defined for
OS use.  It's worth noting that we are using PCR10 here, since PCR9 is
used internally by U-Boot if we choose to measure the loaded DTB

Reviewed-by: Simon Glass 
Signed-off-by: Ilias Apalodimas 
---
 test/py/tests/test_tpm2.py | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py
index fce689cd99..8cd3046285 100644
--- a/test/py/tests/test_tpm2.py
+++ b/test/py/tests/test_tpm2.py
@@ -236,7 +236,7 @@ def test_tpm2_dam_parameters(u_boot_console):
 def test_tpm2_pcr_read(u_boot_console):
 """Execute a TPM2_PCR_Read command.
 
-Perform a PCR read of the 0th PCR. Must be zero.
+Perform a PCR read of the 10th PCR. Must be zero.
 """
 if is_sandbox(u_boot_console):
 tpm2_sandbox_init(u_boot_console)
@@ -244,7 +244,7 @@ def test_tpm2_pcr_read(u_boot_console):
 force_init(u_boot_console)
 ram = u_boot_utils.find_ram_base(u_boot_console)
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram)
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
@@ -254,7 +254,7 @@ def test_tpm2_pcr_read(u_boot_console):
 updates = int(re.findall(r'\d+', str)[0])
 
 # Check the output value
-assert 'PCR #0 content' in read_pcr
+assert 'PCR #10 content' in read_pcr
 assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr
 
 @pytest.mark.buildconfigspec('cmd_tpm_v2')
@@ -272,19 +272,19 @@ def test_tpm2_pcr_extend(u_boot_console):
 force_init(u_boot_console)
 ram = u_boot_utils.find_ram_base(u_boot_console)
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 str = re.findall(r'\d+ known updates', read_pcr)[0]
 updates = int(re.findall(r'\d+', str)[0])
 
-u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
 # Read the value back into a different place so we can still use 'ram' as
 # our zero bytes
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr
@@ -294,11 +294,11 @@ def test_tpm2_pcr_extend(u_boot_console):
 new_updates = int(re.findall(r'\d+', str)[0])
 assert (updates + 1) == new_updates
 
-u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
-read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 
0x20))
+read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 
0x20))
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 assert '7a 05 01 f5 95 7b df 9c b3 a8 ff 49 66 f0 22 65' in read_pcr
-- 
2.39.3



[PATCH v10 01/10] tpm: Fix spelling for tpmu_ha union

2023-08-07 Thread Eddie James
tmpu -> tpmu

Signed-off-by: Eddie James 
Reviewed-by: Ilias Apalodimas 
---
 include/tpm-v2.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 2b6980e441..6684033deb 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -169,7 +169,7 @@ struct tcg_pcr_event {
 /**
  * Definition of TPMU_HA Union
  */
-union tmpu_ha {
+union tpmu_ha {
u8 sha1[TPM2_SHA1_DIGEST_SIZE];
u8 sha256[TPM2_SHA256_DIGEST_SIZE];
u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE];
@@ -185,7 +185,7 @@ union tmpu_ha {
  */
 struct tpmt_ha {
u16 hash_alg;
-   union tmpu_ha digest;
+   union tpmu_ha digest;
 } __packed;
 
 /**
-- 
2.39.3



[PATCH v10 03/10] tpm: Support boot measurements

2023-08-07 Thread Eddie James
Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v8:
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log. This should only be used
   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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions

 include/efi_tcg2.h|   44 --
 include/tpm-v2.h  |  259 +
 lib/Kconfig   |4 +
 lib/efi_loader/efi_tcg2.c | 1054 +++--
 lib/tpm-v2.c  |  814 
 5 files changed, 1154 insertions(+), 1021 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..b21c5cb3dd 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
 #define BOOT_SERVICE_CAPABILITY_MIN \
offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id: algorithm defined in enum tpm2_algorithms
- *  @digest_size:  size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-   u16  algorithm_id;
-   u16  digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature: signature, set to Spec ID Event03
- * @platform_class:class defined in TCG ACPI Specification
- * Client  Common Header.
- * @spec_version_minor:minor version
- * @spec_version_major:major version
- * @spec_version_errata:   major version
- * @uintn_size:size of the efi_uintn_t fields used in 
various
- * data structures used in this specification.
- * 0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:  hashing algorithms used in this event log
- * @digest_sizes:  array of number_of_algorithms pairs
- * 1st member defines the algorithm id
- * 2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-   u8 signature[16];
-   u32 platform_class;
-   u8 spec_version_minor;
-   u8 spec_version_major;
-   u8 spec_errata;
-   u8 uintn_size;
-   u32 number_of_algorithms;
-   struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
-} __packed;
-
 /**
  * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log
  * @version:   version number f

[PATCH v10 09/10] test/py: only run 'tpm2 autostart' to init the tpm

2023-08-07 Thread Eddie James
From: Ilias Apalodimas 

commit  ("")
replaced the forced and sandbox tpm2 initialization running 'tpm2
autostart' instead of the startup tpm sequence.  The difference is that
the new function handles the internal tpm_init state internally and
doesn't return an error when trying to initialize the tpm multiple
times.  Replace the remaining instances

Signed-off-by: Ilias Apalodimas 
---
 test/py/tests/test_tpm2.py | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py
index 8cd3046285..5bbb2d2069 100644
--- a/test/py/tests/test_tpm2.py
+++ b/test/py/tests/test_tpm2.py
@@ -61,7 +61,7 @@ def test_tpm2_init(u_boot_console):
 skip_test = u_boot_console.config.env.get('env__tpm_device_test_skip', 
False)
 if skip_test:
 pytest.skip('skip TPM device test')
-u_boot_console.run_command('tpm2 init')
+u_boot_console.run_command('tpm2 autostart')
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
@@ -97,11 +97,7 @@ def test_tpm2_sandbox_self_test_full(u_boot_console):
 """
 if is_sandbox(u_boot_console):
 u_boot_console.restart_uboot()
-u_boot_console.run_command('tpm2 init')
-output = u_boot_console.run_command('echo $?')
-assert output.endswith('0')
-
-u_boot_console.run_command('tpm2 startup TPM2_SU_CLEAR')
+u_boot_console.run_command('tpm2 autostart')
 output = u_boot_console.run_command('echo $?')
 assert output.endswith('0')
 
-- 
2.39.3



[PATCH v10 02/10] tpm: sandbox: Update for needed TPM2 capabilities

2023-08-07 Thread Eddie James
The driver needs to support getting the PCRs in the capabilities
command. Fix various other things and support the max number
of PCRs for TPM2.
Remove the !SANDBOX dependency for EFI TCG2 as well.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v8:
 - Use >= for checking the property against TPM2_PROPERTIES_OFFSET

Changes since v5:
 - Remove the !SANDBOX dependency for EFI TCG2
 
 drivers/tpm/tpm2_tis_sandbox.c | 100 -
 lib/efi_loader/Kconfig |   2 -
 2 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index e4004cfcca..d15a28d9fc 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -22,11 +22,6 @@ enum tpm2_hierarchy {
TPM2_HIERARCHY_NB,
 };
 
-/* Subset of supported capabilities */
-enum tpm2_capability {
-   TPM_CAP_TPM_PROPERTIES = 0x6,
-};
-
 /* Subset of supported properties */
 #define TPM2_PROPERTIES_OFFSET 0x020E
 
@@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
TPM2_PROPERTY_NB,
 };
 
-#define SANDBOX_TPM_PCR_NB 1
+#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
+#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8)
 
 /*
  * Information about our TPM emulation. This is preserved in the sandbox
@@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 
*sendbuf,
int i, j;
 
/* TPM2_GetProperty */
-   u32 capability, property, property_count;
+   u32 capability, property, property_count, val;
 
/* TPM2_PCR_Read/Extend variables */
int pcr_index = 0;
@@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
case TPM2_CC_GET_CAPABILITY:
capability = get_unaligned_be32(sent);
sent += sizeof(capability);
-   if (capability != TPM_CAP_TPM_PROPERTIES) {
-   printf("Sandbox TPM only support TPM_CAPABILITIES\n");
-   return TPM2_RC_HANDLE;
-   }
-
property = get_unaligned_be32(sent);
sent += sizeof(property);
-   property -= TPM2_PROPERTIES_OFFSET;
-
property_count = get_unaligned_be32(sent);
sent += sizeof(property_count);
-   if (!property_count ||
-   property + property_count > TPM2_PROPERTY_NB) {
+
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   break;
+   case TPM2_CAP_TPM_PROPERTIES:
+   if (!property_count) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+
+   if (property >= TPM2_PROPERTIES_OFFSET &&
+   ((property - TPM2_PROPERTIES_OFFSET) +
+property_count > TPM2_PROPERTY_NB)) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+   break;
+   default:
+   printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
+  "TPM2_CAP_TPM_PROPERTIES\n");
rc = TPM2_RC_HANDLE;
return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
}
@@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
put_unaligned_be32(capability, recv);
recv += sizeof(capability);
 
-   /* Give the number of properties that follow */
-   put_unaligned_be32(property_count, recv);
-   recv += sizeof(property_count);
-
-   /* Fill with the properties */
-   for (i = 0; i < property_count; i++) {
-   put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
-  i, recv);
-   recv += sizeof(property);
-   put_unaligned_be32(tpm->properties[property + i],
-  recv);
-   recv += sizeof(property);
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   /* Give the number of algorithms supported - just 
SHA256 */
+   put_unaligned_be32(1, recv);
+   recv += sizeof(u32);
+
+   /* Give SHA256 algorithm */
+   put_unaligned_be16(TPM2_ALG_SHA256, recv);
+   recv += sizeof(u16);
+
+   /* Se

[PATCH v10 00/10] tpm: Support boot measurements

2023-08-07 Thread Eddie James
This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm 
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.

Changes since v9:
 - Rebase and add Ilias' fixes (thanks!)

Changes since v8:
 - Fix a sandbox driver off-by-one error in checking the property type.
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log and a configuration option
   for systems to select that for the bootm measurement. 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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Re-ordered the patches to put the sandbox TPM driver patch second
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs
 - Remove the !SANDBOX dependency for EFI TCG2
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
 - Change PCR indexes for initrd and dtb
 - Drop u8 casting in measurement test
 - Use bullets in documentation

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v2:
 - Add documentation.
 - Changed reserved memory address to the top of the RAM for sandbox dts.
 - Add measure state to booti and bootz.
 - Skip measurement for EFI images that should be measured

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.
 - Add test case
 - Drop #ifdefs for bootm
 - Add devicetree measurement config option
 - Update sandbox TPM driver

Eddie James (6):
  tpm: Fix spelling for tpmu_ha union
  tpm: sandbox: Update for needed TPM2 capabilities
  tpm: Support boot measurements
  bootm: Support boot measurement
  test: Add sandbox TPM boot measurement
  doc: Add measured boot documentation

Ilias Apalodimas (4):
  efi_loader: fix EFI_ENTRY point on get_active_pcr_banks
  test: use a non system PCR for testing PCR extend
  test/py: only run 'tpm2 autostart' to init the tpm
  fix armv7 compilation warning

 arch/sandbox/dts/sandbox.dtsi  |   13 +
 arch/sandbox/dts/test.dts  |   13 +
 boot/Kconfig   |   32 +
 boot/bootm.c   |   74 +++
 cmd/booti.c|1 +
 cmd/bootm.c|2 +
 cmd/bootz.c|1 +
 configs/sandbox_defconfig  |1 +
 doc/usage/index.rst|1 +
 doc/usage/measured_boot.rst|   23 +
 drivers/tpm/tpm2_tis_sandbox.c |  100 ++-
 include/bootm.h|   11 +
 include/efi_tcg2.h |   44 --
 include/image.h|1 +
 include/test/suites.h  |1 +
 include/tpm-v2.h   |  263 +++-
 lib/Kconfig|4 +
 lib/efi_loader/Kconfig |2 -
 lib/efi_loader/efi_tcg2.c  | 1056 +++-
 lib/tpm-v2.c   |  814 
 test/boot/Makefile |1 +
 test/boot/measurement.c|   66 ++
 test/cmd_ut.c  |4 +
 test/py/tests/test_tpm2.py |   24 +-
 24 file

[PATCH v10 07/10] efi_loader: fix EFI_ENTRY point on get_active_pcr_banks

2023-08-07 Thread Eddie James
From: Ilias Apalodimas 

Signed-off-by: Ilias Apalodimas 
---
 lib/efi_loader/efi_tcg2.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 5f0f4b5dd2..829bae7436 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -718,16 +718,16 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol 
*this,
struct udevice *dev;
efi_status_t ret;
 
+   EFI_ENTRY("%p, %p", this, active_pcr_banks);
+
if (!this || !active_pcr_banks) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
-
ret = tcg2_platform_get_tpm2(&dev);
if (ret != EFI_SUCCESS)
goto out;
 
-   EFI_ENTRY("%p, %p", this, active_pcr_banks);
ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);
 
 out:
-- 
2.39.3



[PATCH v10 04/10] bootm: Support boot measurement

2023-08-07 Thread Eddie James
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 a643a3d128..b160b20599 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -675,6 +675,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 75f0b4a9af..c20a688749 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #if defined(CONFIG_CMD_USB)
 #include 
 #endif
@@ -673,6 +674,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;
+
+   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 

[PATCH v10 06/10] doc: Add measured boot documentation

2023-08-07 Thread Eddie James
Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
---
 doc/usage/index.rst |  1 +
 doc/usage/measured_boot.rst | 23 +++
 2 files changed, 24 insertions(+)
 create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 388e59f173..64eb362aef 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -13,6 +13,7 @@ Use U-Boot
partitions
cmdline
semihosting
+   measured_boot
 
 Shell commands
 --
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..8357b1f480
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
-- 
2.39.3



Re: [PATCH v9 4/6] bootm: Support boot measurement

2023-08-07 Thread Eddie James



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

Re: [PATCH v9 4/6] bootm: Support boot measurement

2023-08-07 Thread Eddie James



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.



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_M

Re: [PATCH v9 3/6] tpm: Support boot measurements

2023-04-10 Thread Eddie James



On 4/6/23 04:18, Ilias Apalodimas wrote:

Hi Eddie,

Do you plan on resending this?
If yes, I can spend some time trying to figure out the CI failures and
send you a patch.



Hi,

Yes I do, I have been short on time. I was a bit confused by the CI, it 
didn't seem to run with the updated v9? I believed I had fixed at least 
some of the failures with patch 2 to update the sandbox driver. I also 
haven't figured out how to run the ci suite locally


Thanks,

Eddie



Thanks
/Ilias


On Wed, 8 Mar 2023 at 23:25, Eddie James  wrote:

Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v8:
  - Fix log parsing again - any data corruption seen while replaying the
event log was failing the entire measurement.
  - Added an option to ignore the existing log. This should only be used
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 v7:
  - Change name of tcg2_init_log and add more documentation
  - Add a check, when parsing the event log header, to ensure that the
previous stage bootloader used all the active PCRs.
  - Change name of tcg2_log_find_end
  - Fix the greater than or equal to check to exit the log parsing
  - Make sure log_position is 0 if there is any error discovering the log
  - Return errors parsing the log if the data is corrupt so that we don't
end up with half a log

Changes since v6:
  - Added Linaro copyright for all the EFI moved code
  - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
copy any discovered event log to the user's log if passed in.

Changes since v5:
  - Remove unused platform_get_eventlog in efi_tcg2.c
  - First look for tpm_event_log_* properties instead of linux,sml-*
  - Fix efi_tcg2.c compilation
  - Select SHA* configs

Changes since v4:
  - Remove tcg2_measure_event function and check for NULL data in
tcg2_measure_data
  - Use tpm_auto_startup
  - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
  - Reordered headers
  - Refactored more of EFI code into common code
 Removed digest_info structure and instead used the common alg_to_mask
   and alg_to_len
 Improved event log parsing in common code to get it equivalent to EFI
   Common code now extends PCR if previous bootloader stage couldn't
   No need to allocate memory in the common code, so EFI copies the
   discovered buffer like it did before
 Rename efi measure_event function

Changes since v1:
  - Refactor TPM layer functions to allow EFI system to use them, and
remove duplicate EFI functions

  include/efi_tcg2.h|   44 --
  include/tpm-v2.h  |  259 +
  lib/Kconfig   |4 +
  lib/efi_loader/efi_tcg2.c | 1054 +++--
  lib/tpm-v2.c  |  814 
  5 files changed, 1154 insertions(+), 1021 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..b21c5cb3dd 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
  #define BOOT_SERVICE_CAPABILITY_MIN \
 offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)

-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id: algorithm defined in enum tpm2_algorithms
- *  @digest_size:  size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-   u16  algorithm_id;
-   u16  digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature: signature, set to Spec ID Event03
- * @platform_class:class defined in TCG ACPI Specification
- * Client  Common Header.
- * @spec_version_minor:minor version
- * @spec_version_major:major version
- * @spec_version_errata:   major version
- * @uintn_size:size of the efi_uintn_t fields used in 
various
- * data structures used in this specification.
- * 0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:  hashing algorithms used in this event log
- * @digest_sizes: 

[PATCH v9 3/6] tpm: Support boot measurements

2023-03-08 Thread Eddie James
Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v8:
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log. This should only be used
   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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions

 include/efi_tcg2.h|   44 --
 include/tpm-v2.h  |  259 +
 lib/Kconfig   |4 +
 lib/efi_loader/efi_tcg2.c | 1054 +++--
 lib/tpm-v2.c  |  814 
 5 files changed, 1154 insertions(+), 1021 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..b21c5cb3dd 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
 #define BOOT_SERVICE_CAPABILITY_MIN \
offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id: algorithm defined in enum tpm2_algorithms
- *  @digest_size:  size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-   u16  algorithm_id;
-   u16  digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature: signature, set to Spec ID Event03
- * @platform_class:class defined in TCG ACPI Specification
- * Client  Common Header.
- * @spec_version_minor:minor version
- * @spec_version_major:major version
- * @spec_version_errata:   major version
- * @uintn_size:size of the efi_uintn_t fields used in 
various
- * data structures used in this specification.
- * 0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:  hashing algorithms used in this event log
- * @digest_sizes:  array of number_of_algorithms pairs
- * 1st member defines the algorithm id
- * 2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-   u8 signature[16];
-   u32 platform_class;
-   u8 spec_version_minor;
-   u8 spec_version_major;
-   u8 spec_errata;
-   u8 uintn_size;
-   u32 number_of_algorithms;
-   struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
-} __packed;
-
 /**
  * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log
  * @version:   version number f

[PATCH v9 6/6] doc: Add measured boot documentation

2023-03-08 Thread Eddie James
Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
---
 doc/usage/index.rst |  1 +
 doc/usage/measured_boot.rst | 23 +++
 2 files changed, 24 insertions(+)
 create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 840c20c934..1cb6988d8a 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -12,6 +12,7 @@ Use U-Boot
partitions
cmdline
semihosting
+   measured_boot
 
 Shell commands
 --
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..8357b1f480
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
-- 
2.31.1



[PATCH v9 4/6] bootm: Support boot measurement

2023-03-08 Thread Eddie James
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;
+
+   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 

[PATCH v9 2/6] tpm: sandbox: Update for needed TPM2 capabilities

2023-03-08 Thread Eddie James
The driver needs to support getting the PCRs in the capabilities
command. Fix various other things and support the max number
of PCRs for TPM2.
Remove the !SANDBOX dependency for EFI TCG2 as well.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v8:
 - Use >= for checking the property against TPM2_PROPERTIES_OFFSET

Changes since v5:
 - Remove the !SANDBOX dependency for EFI TCG2

 drivers/tpm/tpm2_tis_sandbox.c | 100 -
 lib/efi_loader/Kconfig |   2 -
 2 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index e4004cfcca..d15a28d9fc 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -22,11 +22,6 @@ enum tpm2_hierarchy {
TPM2_HIERARCHY_NB,
 };
 
-/* Subset of supported capabilities */
-enum tpm2_capability {
-   TPM_CAP_TPM_PROPERTIES = 0x6,
-};
-
 /* Subset of supported properties */
 #define TPM2_PROPERTIES_OFFSET 0x020E
 
@@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
TPM2_PROPERTY_NB,
 };
 
-#define SANDBOX_TPM_PCR_NB 1
+#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
+#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8)
 
 /*
  * Information about our TPM emulation. This is preserved in the sandbox
@@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 
*sendbuf,
int i, j;
 
/* TPM2_GetProperty */
-   u32 capability, property, property_count;
+   u32 capability, property, property_count, val;
 
/* TPM2_PCR_Read/Extend variables */
int pcr_index = 0;
@@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
case TPM2_CC_GET_CAPABILITY:
capability = get_unaligned_be32(sent);
sent += sizeof(capability);
-   if (capability != TPM_CAP_TPM_PROPERTIES) {
-   printf("Sandbox TPM only support TPM_CAPABILITIES\n");
-   return TPM2_RC_HANDLE;
-   }
-
property = get_unaligned_be32(sent);
sent += sizeof(property);
-   property -= TPM2_PROPERTIES_OFFSET;
-
property_count = get_unaligned_be32(sent);
sent += sizeof(property_count);
-   if (!property_count ||
-   property + property_count > TPM2_PROPERTY_NB) {
+
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   break;
+   case TPM2_CAP_TPM_PROPERTIES:
+   if (!property_count) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+
+   if (property >= TPM2_PROPERTIES_OFFSET &&
+   ((property - TPM2_PROPERTIES_OFFSET) +
+property_count > TPM2_PROPERTY_NB)) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+   break;
+   default:
+   printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
+  "TPM2_CAP_TPM_PROPERTIES\n");
rc = TPM2_RC_HANDLE;
return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
}
@@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
put_unaligned_be32(capability, recv);
recv += sizeof(capability);
 
-   /* Give the number of properties that follow */
-   put_unaligned_be32(property_count, recv);
-   recv += sizeof(property_count);
-
-   /* Fill with the properties */
-   for (i = 0; i < property_count; i++) {
-   put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
-  i, recv);
-   recv += sizeof(property);
-   put_unaligned_be32(tpm->properties[property + i],
-  recv);
-   recv += sizeof(property);
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   /* Give the number of algorithms supported - just 
SHA256 */
+   put_unaligned_be32(1, recv);
+   recv += sizeof(u32);
+
+   /* Give SHA256 algorithm */
+   put_unaligned_be16(TPM2_ALG_SHA256, recv);
+   recv += sizeof(u16);
+
+   /* Se

[PATCH v9 5/6] test: Add sandbox TPM boot measurement

2023-03-08 Thread Eddie James
Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
 - Only compile in the measurement u-boot command when
   CONFIG_MEASURED_BOOT is enabled.

 arch/sandbox/dts/sandbox.dtsi | 13 +++
 arch/sandbox/dts/test.dts | 13 +++
 configs/sandbox_defconfig |  1 +
 include/test/suites.h |  1 +
 test/boot/Makefile|  1 +
 test/boot/measurement.c   | 66 +++
 test/cmd_ut.c |  4 +++
 7 files changed, 99 insertions(+)
 create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 7e7fcff6d2..3442be7634 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
  * and sandbox64 builds.
  */
 
+#include 
 #include 
 
 #define USB_CLASS_HUB  9
 
 / {
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman {
};
 
@@ -336,6 +348,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9717103f10..7659effa71 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include 
 #include 
 #include 
 #include 
@@ -66,6 +67,17 @@
osd0 = "/osd";
};
 
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman: binman {
};
 
@@ -1365,6 +1377,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
tpm {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 77ade1f1d8..43b15b8446 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -335,3 +335,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 7c4960c004..b552fea9a9 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -44,6 +44,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 22ed61c8fa..2dbb032a7e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MEASUREMENT_TEST(_name, _flags)\
+   UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+   struct bootm_headers images;
+   const size_t size = 1024;
+   u8 *kernel;
+   u8 *initrd;
+   size_t i;
+
+   kernel = malloc(size);
+   initrd = malloc(size);
+
+   images.os.image_start = map_to_sysmem(kernel);
+   images.os.image_len = size;
+
+   images.rd_start = map_to_sysmem(initrd);
+   images.rd_end = images.rd_start + size;
+
+   images.ft_addr = malloc(size);
+   images.ft_len = size;
+
+   env_set("bootargs", "measurement testing");
+
+   for (i = 0; i < size; ++i) {
+   kernel[i] = 0xf0 | (i & 0xf);
+   initrd[i] = (i &

[PATCH v9 0/6] tpm: Support boot measurements

2023-03-08 Thread Eddie James
This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm 
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.
This series is based on Ilias' auto-startup series and Simon's additions.

Changes since v8:
 - Fix a sandbox driver off-by-one error in checking the property type.
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log and a configuration option
   for systems to select that for the bootm measurement. 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 v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Re-ordered the patches to put the sandbox TPM driver patch second
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs
 - Remove the !SANDBOX dependency for EFI TCG2
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
 - Change PCR indexes for initrd and dtb
 - Drop u8 casting in measurement test
 - Use bullets in documentation

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v2:
 - Add documentation.
 - Changed reserved memory address to the top of the RAM for sandbox dts.
 - Add measure state to booti and bootz.
 - Skip measurement for EFI images that should be measured

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.
 - Add test case
 - Drop #ifdefs for bootm
 - Add devicetree measurement config option
 - Update sandbox TPM driver

Eddie James (6):
  tpm: Fix spelling for tpmu_ha union
  tpm: sandbox: Update for needed TPM2 capabilities
  tpm: Support boot measurements
  bootm: Support boot measurement
  test: Add sandbox TPM boot measurement
  doc: Add measured boot documentation

 arch/sandbox/dts/sandbox.dtsi  |   13 +
 arch/sandbox/dts/test.dts  |   13 +
 boot/Kconfig   |   32 +
 boot/bootm.c   |   74 +++
 cmd/booti.c|1 +
 cmd/bootm.c|2 +
 cmd/bootz.c|1 +
 configs/sandbox_defconfig  |1 +
 doc/usage/index.rst|1 +
 doc/usage/measured_boot.rst|   23 +
 drivers/tpm/tpm2_tis_sandbox.c |  100 ++-
 include/bootm.h|   11 +
 include/efi_tcg2.h |   44 --
 include/image.h|1 +
 include/test/suites.h  |1 +
 include/tpm-v2.h   |  263 +++-
 lib/Kconfig|4 +
 lib/efi_loader/Kconfig |2 -
 lib/efi_loader/efi_tcg2.c  | 1054 +++-
 lib/tpm-v2.c   |  814 
 test/boot/Makefile |1 +
 test/boot/measurement.c|   66 ++
 test/cmd_ut.c  |4 +
 23 files changed, 1473 insertions(+), 1053 deletions(-)
 create mode 100644 doc/usage/measured_boot.rst
 create mode 100644 test/boot/measurement.c

-- 
2.31.1



[PATCH v9 1/6] tpm: Fix spelling for tpmu_ha union

2023-03-08 Thread Eddie James
tmpu -> tpmu

Signed-off-by: Eddie James 
Reviewed-by: Ilias Apalodimas 
---
 include/tpm-v2.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 2b6980e441..6684033deb 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -169,7 +169,7 @@ struct tcg_pcr_event {
 /**
  * Definition of TPMU_HA Union
  */
-union tmpu_ha {
+union tpmu_ha {
u8 sha1[TPM2_SHA1_DIGEST_SIZE];
u8 sha256[TPM2_SHA256_DIGEST_SIZE];
u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE];
@@ -185,7 +185,7 @@ union tmpu_ha {
  */
 struct tpmt_ha {
u16 hash_alg;
-   union tmpu_ha digest;
+   union tpmu_ha digest;
 } __packed;
 
 /**
-- 
2.31.1



Re: [PATCH v8 0/6] tpm: Support boot measurements

2023-03-08 Thread Eddie James



On 3/6/23 00:58, Ilias Apalodimas wrote:

Hi Eddie,

This has a few failures on the CI [0].
Please have a look and let me know if you can't understand the failures



Hi, I think I have fixed the sandbox ones for v9. I'm unsure about the 
EFI selftest one in qemu targets...



Thanks,

Eddie




[0] https://source.denx.de/u-boot/custodians/u-boot-tpm/-/pipelines/15471

Regards
/Ilias
On Fri, Mar 03, 2023 at 01:25:00PM -0600, Eddie James wrote:

This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.
This series is based on Ilias' auto-startup series and Simon's additions.

Changes since v7:
  - Change name of tcg2_init_log and add more documentation
  - Add a check, when parsing the event log header, to ensure that the
previous stage bootloader used all the active PCRs.
  - Change name of tcg2_log_find_end
  - Fix the greater than or equal to check to exit the log parsing
  - Make sure log_position is 0 if there is any error discovering the log
  - Return errors parsing the log if the data is corrupt so that we don't
end up with half a log

Changes since v6:
  - Added comment for bootm_measure
  - Fixed line length in bootm_measure
  - Added Linaro copyright for all the EFI moved code
  - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
copy any discovered event log to the user's log if passed in.

Changes since v5:
  - Re-ordered the patches to put the sandbox TPM driver patch second
  - Remove unused platform_get_eventlog in efi_tcg2.c
  - First look for tpm_event_log_* properties instead of linux,sml-*
  - Fix efi_tcg2.c compilation
  - Select SHA* configs
  - Remove the !SANDBOX dependency for EFI TCG2
  - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
is enabled

Changes since v4:
  - Remove tcg2_measure_event function and check for NULL data in
tcg2_measure_data
  - Use tpm_auto_startup
  - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
  - Change PCR indexes for initrd and dtb
  - Drop u8 casting in measurement test
  - Use bullets in documentation

Changes since v3:
  - Reordered headers
  - Refactored more of EFI code into common code
 Removed digest_info structure and instead used the common alg_to_mask
   and alg_to_len
 Improved event log parsing in common code to get it equivalent to EFI
   Common code now extends PCR if previous bootloader stage couldn't
   No need to allocate memory in the common code, so EFI copies the
   discovered buffer like it did before
 Rename efi measure_event function

Changes since v2:
  - Add documentation.
  - Changed reserved memory address to the top of the RAM for sandbox dts.
  - Add measure state to booti and bootz.
  - Skip measurement for EFI images that should be measured

Changes since v1:
  - Refactor TPM layer functions to allow EFI system to use them, and
remove duplicate EFI functions.
  - Add test case
  - Drop #ifdefs for bootm
  - Add devicetree measurement config option
  - Update sandbox TPM driver

Eddie James (6):
   tpm: Fix spelling for tpmu_ha union
   tpm: sandbox: Update for needed TPM2 capabilities
   tpm: Support boot measurements
   bootm: Support boot measurement
   test: Add sandbox TPM boot measurement
   doc: Add measured boot documentation

  arch/sandbox/dts/sandbox.dtsi  |   13 +
  arch/sandbox/dts/test.dts  |   13 +
  boot/Kconfig   |   23 +
  boot/bootm.c   |   72 +++
  cmd/booti.c|1 +
  cmd/bootm.c|2 +
  cmd/bootz.c|1 +
  configs/sandbox_defconfig  |1 +
  doc/usage/index.rst|1 +
  doc/usage/measured_boot.rst|   23 +
  drivers/tpm/tpm2_tis_sandbox.c |  100 ++-
  include/bootm.h|   11 +
  include/efi_tcg2.h |   44 --
  include/image.h|1 +
  include/test/suites.h  |1 +
  include/tpm-v2.h   |  255 +++-
  lib/Kconfig|4 +
  lib/efi_loader/Kconfig |2 -
  lib/efi_loader/efi_tcg2.c  | 1054 +++-
  lib/tpm-v2.c   |  815 
  test/boot/Makefile |1 +
  test/boot/measurement.c|   66 ++
  test/cmd_ut.c  |4 +
  23 files changed, 1455 insertions(+), 1053 deletions(-)
  create mode 100644 doc/usage/measured_boot.rst
  create mode 100644 test/boot/measurement.c

--
2.31.1



[PATCH v8 5/6] test: Add sandbox TPM boot measurement

2023-03-03 Thread Eddie James
Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

 arch/sandbox/dts/sandbox.dtsi | 13 +++
 arch/sandbox/dts/test.dts | 13 +++
 configs/sandbox_defconfig |  1 +
 include/test/suites.h |  1 +
 test/boot/Makefile|  1 +
 test/boot/measurement.c   | 66 +++
 test/cmd_ut.c |  4 +++
 7 files changed, 99 insertions(+)
 create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 7e7fcff6d2..3442be7634 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
  * and sandbox64 builds.
  */
 
+#include 
 #include 
 
 #define USB_CLASS_HUB  9
 
 / {
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman {
};
 
@@ -336,6 +348,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9717103f10..7659effa71 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include 
 #include 
 #include 
 #include 
@@ -66,6 +67,17 @@
osd0 = "/osd";
};
 
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman: binman {
};
 
@@ -1365,6 +1377,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
tpm {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 77ade1f1d8..43b15b8446 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -335,3 +335,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 7c4960c004..b552fea9a9 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -44,6 +44,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 22ed61c8fa..2dbb032a7e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MEASUREMENT_TEST(_name, _flags)\
+   UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+   struct bootm_headers images;
+   const size_t size = 1024;
+   u8 *kernel;
+   u8 *initrd;
+   size_t i;
+
+   kernel = malloc(size);
+   initrd = malloc(size);
+
+   images.os.image_start = map_to_sysmem(kernel);
+   images.os.image_len = size;
+
+   images.rd_start = map_to_sysmem(initrd);
+   images.rd_end = images.rd_start + size;
+
+   images.ft_addr = malloc(size);
+   images.ft_len = size;
+
+   env_set("bootargs", "measurement testing");
+
+   for (i = 0; i < size; ++i) {
+   kernel[i] = 0xf0 | (i & 0xf);
+   initrd[i] = (i &

[PATCH v8 3/6] tpm: Support boot measurements

2023-03-03 Thread Eddie James
Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.

 include/efi_tcg2.h|   44 --
 include/tpm-v2.h  |  251 +
 lib/Kconfig   |4 +
 lib/efi_loader/efi_tcg2.c | 1054 +++--
 lib/tpm-v2.c  |  815 
 5 files changed, 1147 insertions(+), 1021 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..b21c5cb3dd 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
 #define BOOT_SERVICE_CAPABILITY_MIN \
offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id: algorithm defined in enum tpm2_algorithms
- *  @digest_size:  size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-   u16  algorithm_id;
-   u16  digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature: signature, set to Spec ID Event03
- * @platform_class:class defined in TCG ACPI Specification
- * Client  Common Header.
- * @spec_version_minor:minor version
- * @spec_version_major:major version
- * @spec_version_errata:   major version
- * @uintn_size:size of the efi_uintn_t fields used in 
various
- * data structures used in this specification.
- * 0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:  hashing algorithms used in this event log
- * @digest_sizes:  array of number_of_algorithms pairs
- * 1st member defines the algorithm id
- * 2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-   u8 signature[16];
-   u32 platform_class;
-   u8 spec_version_minor;
-   u8 spec_version_major;
-   u8 spec_errata;
-   u8 uintn_size;
-   u32 number_of_algorithms;
-   struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
-} __packed;
-
 /**
  * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log
  * @version:   version number for this structure
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 6684033deb..ca789d944e 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -216,6 +216,50 @@ struct tcg_pcr_event2 {
u8 event[];
 } __packed;
 
+/**
+ *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
+ *
+ *  @algorithm_id: algorithm defined in enum tpm2_algorithms
+ *  @digest_size:  size of t

[PATCH v8 6/6] doc: Add measured boot documentation

2023-03-03 Thread Eddie James
Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
---
 doc/usage/index.rst |  1 +
 doc/usage/measured_boot.rst | 23 +++
 2 files changed, 24 insertions(+)
 create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 840c20c934..1cb6988d8a 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -12,6 +12,7 @@ Use U-Boot
partitions
cmdline
semihosting
+   measured_boot
 
 Shell commands
 --
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..8357b1f480
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
-- 
2.31.1



[PATCH v8 4/6] bootm: Support boot measurement

2023-03-03 Thread Eddie James
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 v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure

 boot/Kconfig| 23 
 boot/bootm.c| 72 +
 cmd/booti.c |  1 +
 cmd/bootm.c |  2 ++
 cmd/bootz.c |  1 +
 include/bootm.h | 11 
 include/image.h |  1 +
 7 files changed, 111 insertions(+)

diff --git a/boot/Kconfig b/boot/Kconfig
index 5f491625c8..d0d5e5794c 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -629,6 +629,29 @@ 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.
+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..e3ef18166d 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,73 @@ 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;
+
+   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;
+
+   elog.log_size = 0;
+   ret = tcg2_measurement_init(&dev, &elog);
+   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, &e

[PATCH v8 2/6] tpm: sandbox: Update for needed TPM2 capabilities

2023-03-03 Thread Eddie James
The driver needs to support getting the PCRs in the capabilities
command. Fix various other things and support the max number
of PCRs for TPM2.
Remove the !SANDBOX dependency for EFI TCG2 as well.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
 - Remove the !SANDBOX dependency for EFI TCG2

 drivers/tpm/tpm2_tis_sandbox.c | 100 -
 lib/efi_loader/Kconfig |   2 -
 2 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index e4004cfcca..f63c72814f 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -22,11 +22,6 @@ enum tpm2_hierarchy {
TPM2_HIERARCHY_NB,
 };
 
-/* Subset of supported capabilities */
-enum tpm2_capability {
-   TPM_CAP_TPM_PROPERTIES = 0x6,
-};
-
 /* Subset of supported properties */
 #define TPM2_PROPERTIES_OFFSET 0x020E
 
@@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
TPM2_PROPERTY_NB,
 };
 
-#define SANDBOX_TPM_PCR_NB 1
+#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
+#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8)
 
 /*
  * Information about our TPM emulation. This is preserved in the sandbox
@@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 
*sendbuf,
int i, j;
 
/* TPM2_GetProperty */
-   u32 capability, property, property_count;
+   u32 capability, property, property_count, val;
 
/* TPM2_PCR_Read/Extend variables */
int pcr_index = 0;
@@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
case TPM2_CC_GET_CAPABILITY:
capability = get_unaligned_be32(sent);
sent += sizeof(capability);
-   if (capability != TPM_CAP_TPM_PROPERTIES) {
-   printf("Sandbox TPM only support TPM_CAPABILITIES\n");
-   return TPM2_RC_HANDLE;
-   }
-
property = get_unaligned_be32(sent);
sent += sizeof(property);
-   property -= TPM2_PROPERTIES_OFFSET;
-
property_count = get_unaligned_be32(sent);
sent += sizeof(property_count);
-   if (!property_count ||
-   property + property_count > TPM2_PROPERTY_NB) {
+
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   break;
+   case TPM2_CAP_TPM_PROPERTIES:
+   if (!property_count) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+
+   if (property > TPM2_PROPERTIES_OFFSET &&
+   ((property - TPM2_PROPERTIES_OFFSET) +
+property_count > TPM2_PROPERTY_NB)) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+   break;
+   default:
+   printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
+  "TPM2_CAP_TPM_PROPERTIES\n");
rc = TPM2_RC_HANDLE;
return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
}
@@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
put_unaligned_be32(capability, recv);
recv += sizeof(capability);
 
-   /* Give the number of properties that follow */
-   put_unaligned_be32(property_count, recv);
-   recv += sizeof(property_count);
-
-   /* Fill with the properties */
-   for (i = 0; i < property_count; i++) {
-   put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
-  i, recv);
-   recv += sizeof(property);
-   put_unaligned_be32(tpm->properties[property + i],
-  recv);
-   recv += sizeof(property);
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   /* Give the number of algorithms supported - just 
SHA256 */
+   put_unaligned_be32(1, recv);
+   recv += sizeof(u32);
+
+   /* Give SHA256 algorithm */
+   put_unaligned_be16(TPM2_ALG_SHA256, recv);
+   recv += sizeof(u16);
+
+   /* Select the PCRs supported */
+   *recv = SAN

[PATCH v8 0/6] tpm: Support boot measurements

2023-03-03 Thread Eddie James
This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm 
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.
This series is based on Ilias' auto-startup series and Simon's additions.

Changes since v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Re-ordered the patches to put the sandbox TPM driver patch second
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs
 - Remove the !SANDBOX dependency for EFI TCG2
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
 - Change PCR indexes for initrd and dtb
 - Drop u8 casting in measurement test
 - Use bullets in documentation

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v2:
 - Add documentation.
 - Changed reserved memory address to the top of the RAM for sandbox dts.
 - Add measure state to booti and bootz.
 - Skip measurement for EFI images that should be measured

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.
 - Add test case
 - Drop #ifdefs for bootm
 - Add devicetree measurement config option
 - Update sandbox TPM driver

Eddie James (6):
  tpm: Fix spelling for tpmu_ha union
  tpm: sandbox: Update for needed TPM2 capabilities
  tpm: Support boot measurements
  bootm: Support boot measurement
  test: Add sandbox TPM boot measurement
  doc: Add measured boot documentation

 arch/sandbox/dts/sandbox.dtsi  |   13 +
 arch/sandbox/dts/test.dts  |   13 +
 boot/Kconfig   |   23 +
 boot/bootm.c   |   72 +++
 cmd/booti.c|1 +
 cmd/bootm.c|2 +
 cmd/bootz.c|1 +
 configs/sandbox_defconfig  |1 +
 doc/usage/index.rst|1 +
 doc/usage/measured_boot.rst|   23 +
 drivers/tpm/tpm2_tis_sandbox.c |  100 ++-
 include/bootm.h|   11 +
 include/efi_tcg2.h |   44 --
 include/image.h|1 +
 include/test/suites.h  |1 +
 include/tpm-v2.h   |  255 +++-
 lib/Kconfig|4 +
 lib/efi_loader/Kconfig |2 -
 lib/efi_loader/efi_tcg2.c  | 1054 +++-
 lib/tpm-v2.c   |  815 
 test/boot/Makefile |1 +
 test/boot/measurement.c|   66 ++
 test/cmd_ut.c  |4 +
 23 files changed, 1455 insertions(+), 1053 deletions(-)
 create mode 100644 doc/usage/measured_boot.rst
 create mode 100644 test/boot/measurement.c

-- 
2.31.1



[PATCH v8 1/6] tpm: Fix spelling for tpmu_ha union

2023-03-03 Thread Eddie James
tmpu -> tpmu

Signed-off-by: Eddie James 
Reviewed-by: Ilias Apalodimas 
---
 include/tpm-v2.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 2b6980e441..6684033deb 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -169,7 +169,7 @@ struct tcg_pcr_event {
 /**
  * Definition of TPMU_HA Union
  */
-union tmpu_ha {
+union tpmu_ha {
u8 sha1[TPM2_SHA1_DIGEST_SIZE];
u8 sha256[TPM2_SHA256_DIGEST_SIZE];
u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE];
@@ -185,7 +185,7 @@ union tmpu_ha {
  */
 struct tpmt_ha {
u16 hash_alg;
-   union tmpu_ha digest;
+   union tpmu_ha digest;
 } __packed;
 
 /**
-- 
2.31.1



Re: [PATCH v7 3/6] tpm: Support boot measurements

2023-03-03 Thread Eddie James



On 3/2/23 14:22, Ilias Apalodimas wrote:

Hi Eddie,

I found the issue.  I still think we could squeeze things even more in our
abstraction.  Specifically the measure_event() tcg2_agile_log_append()
contain some efi specific bits and I am trying to figure out if we can make
those more generic.  However, that's not a show stopper for me.

[...]


+int tcg2_init_log(struct udevice *dev, struct tcg2_event_log *elog);

We have tcg2_init_log() and tcg2_log_init().  This is a bit confusing when
reading the code.
Since tcg2_log_init() is actually initializing the EventLog can we do
tcg2_init_log -> tcg2_prepare_log_buf or something along those lines?



Sure, sounds good.





+
+/**
+ * Begin measurements.
+ *
+ * @devTPM device

[...]


+static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
+{
+   struct tpml_digest_values digest_list;
+   struct tcg_efi_spec_id_event *event;
+   struct tcg_pcr_event *log;
+   u32 calc_size;
+   u32 active;
+   u32 count;
+   u32 evsz;
+   u32 mask;
+   u16 algo;
+   u16 len;
+   int rc;
+   u32 i;
+   u16 j;
+
+   if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
+   return 0;
+
+   log = (struct tcg_pcr_event *)elog->log;
+   if (get_unaligned_le32(&log->pcr_index) != 0 ||
+   get_unaligned_le32(&log->event_type) != EV_NO_ACTION)
+   return 0;
+
+   for (i = 0; i < sizeof(log->digest); i++) {
+   if (log->digest[i])
+   return 0;
+   }
+
+   evsz = get_unaligned_le32(&log->event_size);
+   if (evsz < offsetof(struct tcg_efi_spec_id_event, digest_sizes) ||
+   evsz + offsetof(struct tcg_pcr_event, event) > elog->log_size)
+   return 0;
+
+   event = (struct tcg_efi_spec_id_event *)log->event;
+   if (memcmp(event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
+  sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03)))
+   return 0;
+
+   if (event->spec_version_minor != 
TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
+   event->spec_version_major != 
TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
+   return 0;
+
+   count = get_unaligned_le32(&event->number_of_algorithms);
+   if (count > ARRAY_SIZE(tpm2_supported_algorithms))
+   return 0;
+
+   calc_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
+   (sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count) +
+   1;
+   if (evsz != calc_size)
+   return 0;
+
+   rc = tcg2_get_active_pcr_banks(dev, &active);
+   if (rc)
+   return rc;

There was a check here in the previous version which I can't find. The
previous stage bootloader is creating an EventLog.  Since it can't control
the TPM the pcr banks that end up in the EventLog are defined at compile
time.  This isn't ideal, but we have 2 options here:
1. Check the hardware active PCR banks and report an error if there's a
mismatch (which is what the older version did)
2. Add the missing function of re-configuring the active banks to
whatever the previous bootloader tells us.

Obviously (2) is a better option, but I am fine if we just report an error
for now.



Yes I found it, and I will add that.




[...]


+   *((u8 *)ev + (event_size - 1)) = 0;
+   elog->log_position = log_size;
+
+   return 0;
+}
+
+static int tcg2_log_find_end(struct tcg2_event_log *elog, struct udevice *dev,

Can we find a better name for this? This basically replays an eventlog we
inherited from a previous stage boot loader into the TPM.
So something like tcg2_replay_eventlog()?



Sure.





+struct tpml_digest_values *digest_list)
+{
+   const u32 offset = offsetof(struct tcg_pcr_event2, digests) +
+   offsetof(struct tpml_digest_values, digests);
+   u32 event_size;
+   u32 count;
+   u16 algo;
+   u32 pcr;
+   u32 pos;
+   u16 len;
+   u8 *log;
+   int rc;
+   u32 i;
+
+   while (elog->log_position + offset < elog->log_size) {
+   log = elog->log + elog->log_position;
+
+   pos = offsetof(struct tcg_pcr_event2, pcr_index);
+   pcr = get_unaligned_le32(log + pos);
+   pos = offsetof(struct tcg_pcr_event2, event_type);
+   if (!get_unaligned_le32(log + pos))
+   return 0;

isn't this an actual error ?



Good point, and all below too. I will return errors there.





+
+   pos = offsetof(struct tcg_pcr_event2, digests) +
+   offsetof(struct tpml_digest_values, count);
+   count = get_unaligned_le32(log + pos);
+   if (count > ARRAY_SIZE(tpm2_supported_algorithms) ||
+   (digest_list->count && digest_list->count != count))
+   return 0;

ditto


+
+   pos = offse

[PATCH v7 3/6] tpm: Support boot measurements

2023-03-01 Thread Eddie James
Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v6:
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.

 include/efi_tcg2.h|   44 --
 include/tpm-v2.h  |  248 +
 lib/Kconfig   |4 +
 lib/efi_loader/efi_tcg2.c | 1054 +++--
 lib/tpm-v2.c  |  804 
 5 files changed, 1133 insertions(+), 1021 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..b21c5cb3dd 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
 #define BOOT_SERVICE_CAPABILITY_MIN \
offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id: algorithm defined in enum tpm2_algorithms
- *  @digest_size:  size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-   u16  algorithm_id;
-   u16  digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature: signature, set to Spec ID Event03
- * @platform_class:class defined in TCG ACPI Specification
- * Client  Common Header.
- * @spec_version_minor:minor version
- * @spec_version_major:major version
- * @spec_version_errata:   major version
- * @uintn_size:size of the efi_uintn_t fields used in 
various
- * data structures used in this specification.
- * 0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:  hashing algorithms used in this event log
- * @digest_sizes:  array of number_of_algorithms pairs
- * 1st member defines the algorithm id
- * 2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-   u8 signature[16];
-   u32 platform_class;
-   u8 spec_version_minor;
-   u8 spec_version_major;
-   u8 spec_errata;
-   u8 uintn_size;
-   u32 number_of_algorithms;
-   struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
-} __packed;
-
 /**
  * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log
  * @version:   version number for this structure
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 6684033deb..c491a58b02 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -216,6 +216,50 @@ struct tcg_pcr_event2 {
u8 event[];
 } __packed;
 
+/**
+ *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
+ *
+ *  @algorithm_id: algorithm defined in enum tpm2_algorithms
+ *  @digest_size:  size of the algorithm
+ */
+struct tcg_efi_spec_id_event_algorithm_size {
+   u16  algorithm_id;
+   u16  digest_size;
+} __packed;
+
+#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
+
+/**
+ * struct TCG_EfiSpecIDEventStruct - content of the event log header
+ *
+ * @signature: sig

[PATCH v7 6/6] doc: Add measured boot documentation

2023-03-01 Thread Eddie James
Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
---
 doc/usage/index.rst |  1 +
 doc/usage/measured_boot.rst | 23 +++
 2 files changed, 24 insertions(+)
 create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index cde7dcb14a..0cf78cb0e7 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -12,6 +12,7 @@ Use U-Boot
partitions
cmdline
semihosting
+   measured_boot
 
 Shell commands
 --
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..8357b1f480
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
-- 
2.31.1



[PATCH v7 5/6] test: Add sandbox TPM boot measurement

2023-03-01 Thread Eddie James
Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

 arch/sandbox/dts/sandbox.dtsi | 13 +++
 arch/sandbox/dts/test.dts | 13 +++
 configs/sandbox_defconfig |  1 +
 include/test/suites.h |  1 +
 test/boot/Makefile|  1 +
 test/boot/measurement.c   | 66 +++
 test/cmd_ut.c |  4 +++
 7 files changed, 99 insertions(+)
 create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 7e7fcff6d2..3442be7634 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
  * and sandbox64 builds.
  */
 
+#include 
 #include 
 
 #define USB_CLASS_HUB  9
 
 / {
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman {
};
 
@@ -336,6 +348,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9717103f10..7659effa71 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include 
 #include 
 #include 
 #include 
@@ -66,6 +67,17 @@
osd0 = "/osd";
};
 
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman: binman {
};
 
@@ -1365,6 +1377,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
tpm {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 77ade1f1d8..43b15b8446 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -335,3 +335,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 7c4960c004..b552fea9a9 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -44,6 +44,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 22ed61c8fa..2dbb032a7e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MEASUREMENT_TEST(_name, _flags)\
+   UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+   struct bootm_headers images;
+   const size_t size = 1024;
+   u8 *kernel;
+   u8 *initrd;
+   size_t i;
+
+   kernel = malloc(size);
+   initrd = malloc(size);
+
+   images.os.image_start = map_to_sysmem(kernel);
+   images.os.image_len = size;
+
+   images.rd_start = map_to_sysmem(initrd);
+   images.rd_end = images.rd_start + size;
+
+   images.ft_addr = malloc(size);
+   images.ft_len = size;
+
+   env_set("bootargs", "measurement testing");
+
+   for (i = 0; i < size; ++i) {
+   kernel[i] = 0xf0 | (i & 0xf);
+   initrd[i] = (i &

[PATCH v7 4/6] bootm: Support boot measurement

2023-03-01 Thread Eddie James
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 v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure

 boot/Kconfig| 23 
 boot/bootm.c| 72 +
 cmd/booti.c |  1 +
 cmd/bootm.c |  2 ++
 cmd/bootz.c |  1 +
 include/bootm.h | 11 
 include/image.h |  1 +
 7 files changed, 111 insertions(+)

diff --git a/boot/Kconfig b/boot/Kconfig
index 5f491625c8..d0d5e5794c 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -629,6 +629,29 @@ 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.
+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..e3ef18166d 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,73 @@ 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;
+
+   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;
+
+   elog.log_size = 0;
+   ret = tcg2_measurement_init(&dev, &elog);
+   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, &e

[PATCH v7 2/6] tpm: sandbox: Update for needed TPM2 capabilities

2023-03-01 Thread Eddie James
The driver needs to support getting the PCRs in the capabilities
command. Fix various other things and support the max number
of PCRs for TPM2.
Remove the !SANDBOX dependency for EFI TCG2 as well.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
 - Remove the !SANDBOX dependency for EFI TCG2

 drivers/tpm/tpm2_tis_sandbox.c | 100 -
 lib/efi_loader/Kconfig |   2 -
 2 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index e4004cfcca..f63c72814f 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -22,11 +22,6 @@ enum tpm2_hierarchy {
TPM2_HIERARCHY_NB,
 };
 
-/* Subset of supported capabilities */
-enum tpm2_capability {
-   TPM_CAP_TPM_PROPERTIES = 0x6,
-};
-
 /* Subset of supported properties */
 #define TPM2_PROPERTIES_OFFSET 0x020E
 
@@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
TPM2_PROPERTY_NB,
 };
 
-#define SANDBOX_TPM_PCR_NB 1
+#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
+#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8)
 
 /*
  * Information about our TPM emulation. This is preserved in the sandbox
@@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 
*sendbuf,
int i, j;
 
/* TPM2_GetProperty */
-   u32 capability, property, property_count;
+   u32 capability, property, property_count, val;
 
/* TPM2_PCR_Read/Extend variables */
int pcr_index = 0;
@@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
case TPM2_CC_GET_CAPABILITY:
capability = get_unaligned_be32(sent);
sent += sizeof(capability);
-   if (capability != TPM_CAP_TPM_PROPERTIES) {
-   printf("Sandbox TPM only support TPM_CAPABILITIES\n");
-   return TPM2_RC_HANDLE;
-   }
-
property = get_unaligned_be32(sent);
sent += sizeof(property);
-   property -= TPM2_PROPERTIES_OFFSET;
-
property_count = get_unaligned_be32(sent);
sent += sizeof(property_count);
-   if (!property_count ||
-   property + property_count > TPM2_PROPERTY_NB) {
+
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   break;
+   case TPM2_CAP_TPM_PROPERTIES:
+   if (!property_count) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+
+   if (property > TPM2_PROPERTIES_OFFSET &&
+   ((property - TPM2_PROPERTIES_OFFSET) +
+property_count > TPM2_PROPERTY_NB)) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+   break;
+   default:
+   printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
+  "TPM2_CAP_TPM_PROPERTIES\n");
rc = TPM2_RC_HANDLE;
return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
}
@@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
put_unaligned_be32(capability, recv);
recv += sizeof(capability);
 
-   /* Give the number of properties that follow */
-   put_unaligned_be32(property_count, recv);
-   recv += sizeof(property_count);
-
-   /* Fill with the properties */
-   for (i = 0; i < property_count; i++) {
-   put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
-  i, recv);
-   recv += sizeof(property);
-   put_unaligned_be32(tpm->properties[property + i],
-  recv);
-   recv += sizeof(property);
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   /* Give the number of algorithms supported - just 
SHA256 */
+   put_unaligned_be32(1, recv);
+   recv += sizeof(u32);
+
+   /* Give SHA256 algorithm */
+   put_unaligned_be16(TPM2_ALG_SHA256, recv);
+   recv += sizeof(u16);
+
+   /* Select the PCRs supported */
+   *recv = SAN

[PATCH v7 1/6] tpm: Fix spelling for tpmu_ha union

2023-03-01 Thread Eddie James
tmpu -> tpmu

Signed-off-by: Eddie James 
Reviewed-by: Ilias Apalodimas 
---
 include/tpm-v2.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 2b6980e441..6684033deb 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -169,7 +169,7 @@ struct tcg_pcr_event {
 /**
  * Definition of TPMU_HA Union
  */
-union tmpu_ha {
+union tpmu_ha {
u8 sha1[TPM2_SHA1_DIGEST_SIZE];
u8 sha256[TPM2_SHA256_DIGEST_SIZE];
u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE];
@@ -185,7 +185,7 @@ union tmpu_ha {
  */
 struct tpmt_ha {
u16 hash_alg;
-   union tmpu_ha digest;
+   union tpmu_ha digest;
 } __packed;
 
 /**
-- 
2.31.1



[PATCH v7 0/6] tpm: Support boot measurements

2023-03-01 Thread Eddie James
This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm 
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.
This series is based on Ilias' auto-startup series and Simon's additions.

Changes since v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Re-ordered the patches to put the sandbox TPM driver patch second
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs
 - Remove the !SANDBOX dependency for EFI TCG2
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
 - Change PCR indexes for initrd and dtb
 - Drop u8 casting in measurement test
 - Use bullets in documentation

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v2:
 - Add documentation.
 - Changed reserved memory address to the top of the RAM for sandbox dts.
 - Add measure state to booti and bootz.
 - Skip measurement for EFI images that should be measured

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.
 - Add test case
 - Drop #ifdefs for bootm
 - Add devicetree measurement config option
 - Update sandbox TPM driver

Eddie James (6):
  tpm: Fix spelling for tpmu_ha union
  tpm: sandbox: Update for needed TPM2 capabilities
  tpm: Support boot measurements
  bootm: Support boot measurement
  test: Add sandbox TPM boot measurement
  doc: Add measured boot documentation

 arch/sandbox/dts/sandbox.dtsi  |   13 +
 arch/sandbox/dts/test.dts  |   13 +
 boot/Kconfig   |   23 +
 boot/bootm.c   |   72 +++
 cmd/booti.c|1 +
 cmd/bootm.c|2 +
 cmd/bootz.c|1 +
 configs/sandbox_defconfig  |1 +
 doc/usage/index.rst|1 +
 doc/usage/measured_boot.rst|   23 +
 drivers/tpm/tpm2_tis_sandbox.c |  100 ++-
 include/bootm.h|   11 +
 include/efi_tcg2.h |   44 --
 include/image.h|1 +
 include/test/suites.h  |1 +
 include/tpm-v2.h   |  252 +++-
 lib/Kconfig|4 +
 lib/efi_loader/Kconfig |2 -
 lib/efi_loader/efi_tcg2.c  | 1054 +++-
 lib/tpm-v2.c   |  804 
 test/boot/Makefile |1 +
 test/boot/measurement.c|   66 ++
 test/cmd_ut.c  |4 +
 23 files changed, 1441 insertions(+), 1053 deletions(-)
 create mode 100644 doc/usage/measured_boot.rst
 create mode 100644 test/boot/measurement.c

-- 
2.31.1



Re: [PATCH v6 6/6] doc: Add measured boot documentation

2023-03-01 Thread Eddie James



On 2/22/23 14:26, Heinrich Schuchardt wrote:


Am 22. Februar 2023 19:02:42 MEZ schrieb Eddie James :

Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
---
doc/usage/index.rst |  1 +
doc/usage/measured_boot.rst | 23 +++
2 files changed, 24 insertions(+)
create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index cde7dcb14a..0cf78cb0e7 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -12,6 +12,7 @@ Use U-Boot
partitions
cmdline
semihosting
+   measured_boot

Shell commands
--
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..8357b1f480
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=

This completely misses o describe measured boot with UEFI.

@Ilias, do you want to add that in a follow up patch?


+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.

Please, provide enough information such that a reader can set this up. This 
should include example code.



Hi Heinrich,


I'm not sure what example code you mean. No additional code is necessary 
for U-Boot to perform the measurements, only the requirements stated. If 
you mean the operating system setup, I don't think here is the right 
place to document that, as it has nothing to do with U-Boot. Either way, 
Linux would not require any code, only a similar devicetree entry and 
TPM driver.



Thanks,

Eddie




Best regards

Heinrich


Re: [PATCH v6 3/6] tpm: Support boot measurements

2023-02-23 Thread Eddie James



On 2/23/23 03:47, Ilias Apalodimas wrote:

On Thu, 23 Feb 2023 at 11:30, Ilias Apalodimas
 wrote:

On Thu, 23 Feb 2023 at 11:02, Ilias Apalodimas
 wrote:

Hi Eddie,

 final_event->number_of_events++;

@@ -350,66 +142,6 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, 
u32 event_type,
   return ret;
  }

-/**
- * platform_get_tpm_device() - retrieve TPM device
- *
- * This function retrieves the udevice implementing a TPM
- *
- * This function may be overridden if special initialization is needed.
- *
- * @dev: udevice
- * Return:   status code
- */
-__weak efi_status_t platform_get_tpm2_device(struct udevice **dev)
-{
- for_each_tpm_device(*dev) {
- /* Only support TPMv2 devices */
- if (tpm_get_version(*dev) == TPM_V2)
- return EFI_SUCCESS;
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- * platform_get_eventlog() - retrieve the eventlog address and size
- *
- * This function retrieves the eventlog address and size if the underlying
- * firmware has done some measurements and passed them.
- *
- * This function may be overridden based on platform specific method of
- * passing the eventlog address and size.
- *
- * @dev: udevice
- * @addr:eventlog address
- * @sz:  eventlog size
- * Return:   status code
- */
-__weak efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr,
-   u32 *sz)
-{
- const u64 *basep;
- const u32 *sizep;
-
- basep = dev_read_prop(dev, "tpm_event_log_addr", NULL);
- if (!basep)
- return EFI_NOT_FOUND;
-
- *addr = be64_to_cpup((__force __be64 *)basep);
-
- sizep = dev_read_prop(dev, "tpm_event_log_size", NULL);
- if (!sizep)
- return EFI_NOT_FOUND;
-
- *sz = be32_to_cpup((__force __be32 *)sizep);
- if (*sz == 0) {
- log_debug("event log empty\n");
- return EFI_NOT_FOUND;
- }
-
- return EFI_SUCCESS;
-}
-
  /**
   * tpm2_get_max_command_size() - get the supported max command size
   *
@@ -485,239 +217,6 @@ static int tpm2_get_manufacturer_id(struct udevice *dev, 
u32 *manufacturer_id)
   return 0;
  }

-/**
- * tpm2_get_num_pcr() - get the number of PCRs
- *
- * @dev: TPM device
- * @manufacturer_id: output buffer for the number
- *
- * Return: 0 on success, -1 on error
- */
-static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
-{
- u8 response[TPM2_RESPONSE_BUFFER_SIZE];
- u32 ret;
-
- memset(response, 0, sizeof(response));
- ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
-   TPM2_PT_PCR_COUNT, response, 1);
- if (ret)
- return -1;
-
- *num_pcr = get_unaligned_be32(response + properties_offset);
- if (*num_pcr > TPM2_MAX_PCRS)
- return -1;
-
- return 0;
-}
-
-/**
- * is_active_pcr() - Check if a supported algorithm is active
- *
- * @dev: TPM device
- * @selection:   struct of PCR information
- *
- * Return: true if PCR is active
- */
-static bool is_active_pcr(struct tpms_pcr_selection *selection)
-{
- int i;
- /*
-  * check the pcr_select. If at least one of the PCRs supports the
-  * algorithm add it on the active ones
-  */
- for (i = 0; i < selection->size_of_select; i++) {
- if (selection->pcr_select[i])
- return true;
- }
-
- return false;
-}
-
-/**
- * tpm2_get_pcr_info() - get the supported, active PCRs and number of banks
- *
- * @dev: TPM device
- * @supported_pcr:   bitmask with the algorithms supported
- * @active_pcr:  bitmask with the active algorithms
- * @pcr_banks:   number of PCR banks
- *
- * Return: 0 on success, -1 on error
- */
-static int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr,
-  u32 *active_pcr, u32 *pcr_banks)
-{
- u8 response[TPM2_RESPONSE_BUFFER_SIZE];
- struct tpml_pcr_selection pcrs;
- u32 ret, num_pcr;
- size_t i;
- int tpm_ret;
-
- *supported_pcr = 0;
- *active_pcr = 0;
- *pcr_banks = 0;
- memset(response, 0, sizeof(response));
- ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
- if (ret)
- goto out;
-
- pcrs.count = get_unaligned_be32(response);
- /*
-  * We only support 5 algorithms for now so check against that
-  * instead of TPM2_NUM_PCR_BANKS
-  */
- if (pcrs.count > MAX_HASH_COUNT || pcrs.count < 1)
- goto out;
-
- tpm_ret = tpm2_get_num_pcr(dev, &num_pcr);
- if (tpm_ret)
- goto out;
-
- for (i = 0; i < pcrs.count; i++) {
- /*
-  * Definition of TPMS_PCR_SELECTION Structure
-  * hash: u16
-  * size_of_select: u8
-  * pcr_select: u8 array
-  *
-  * The offsets depend on the number of the device PCRs
-  * so we ha

[PATCH v6 3/6] tpm: Support boot measurements

2023-02-22 Thread Eddie James
Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v5:
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.

 include/efi_tcg2.h|   44 --
 include/tpm-v2.h  |  242 +
 lib/Kconfig   |4 +
 lib/efi_loader/efi_tcg2.c | 1053 +++--
 lib/tpm-v2.c  |  773 +++
 5 files changed, 1095 insertions(+), 1021 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..b21c5cb3dd 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
 #define BOOT_SERVICE_CAPABILITY_MIN \
offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id: algorithm defined in enum tpm2_algorithms
- *  @digest_size:  size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-   u16  algorithm_id;
-   u16  digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature: signature, set to Spec ID Event03
- * @platform_class:class defined in TCG ACPI Specification
- * Client  Common Header.
- * @spec_version_minor:minor version
- * @spec_version_major:major version
- * @spec_version_errata:   major version
- * @uintn_size:size of the efi_uintn_t fields used in 
various
- * data structures used in this specification.
- * 0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:  hashing algorithms used in this event log
- * @digest_sizes:  array of number_of_algorithms pairs
- * 1st member defines the algorithm id
- * 2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-   u8 signature[16];
-   u32 platform_class;
-   u8 spec_version_minor;
-   u8 spec_version_major;
-   u8 spec_errata;
-   u8 uintn_size;
-   u32 number_of_algorithms;
-   struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
-} __packed;
-
 /**
  * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log
  * @version:   version number for this structure
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 6684033deb..461752aabf 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -216,6 +216,50 @@ struct tcg_pcr_event2 {
u8 event[];
 } __packed;
 
+/**
+ *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
+ *
+ *  @algorithm_id: algorithm defined in enum tpm2_algorithms
+ *  @digest_size:  size of the algorithm
+ */
+struct tcg_efi_spec_id_event_algorithm_size {
+   u16  algorithm_id;
+   u16  digest_size;
+} __packed;
+
+#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
+
+/**
+ * struct TCG_EfiSpecIDEventStruct - content of the event log header
+ *
+ * @signature: signature, set to Spec ID Event03
+ * @platform_class:class defined in TCG ACPI Specification
+ * Client  Common Header.
+ * @spec_version_minor:minor versio

[PATCH v6 5/6] test: Add sandbox TPM boot measurement

2023-02-22 Thread Eddie James
Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
---
Changes since v5:
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

 arch/sandbox/dts/sandbox.dtsi | 13 +++
 arch/sandbox/dts/test.dts | 13 +++
 configs/sandbox_defconfig |  1 +
 include/test/suites.h |  1 +
 test/boot/Makefile|  1 +
 test/boot/measurement.c   | 66 +++
 test/cmd_ut.c |  4 +++
 7 files changed, 99 insertions(+)
 create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 7e7fcff6d2..3442be7634 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
  * and sandbox64 builds.
  */
 
+#include 
 #include 
 
 #define USB_CLASS_HUB  9
 
 / {
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman {
};
 
@@ -336,6 +348,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9717103f10..7659effa71 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include 
 #include 
 #include 
 #include 
@@ -66,6 +67,17 @@
osd0 = "/osd";
};
 
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman: binman {
};
 
@@ -1365,6 +1377,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
tpm {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 77ade1f1d8..43b15b8446 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -335,3 +335,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 7c4960c004..b552fea9a9 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -44,6 +44,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 22ed61c8fa..2dbb032a7e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MEASUREMENT_TEST(_name, _flags)\
+   UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+   struct bootm_headers images;
+   const size_t size = 1024;
+   u8 *kernel;
+   u8 *initrd;
+   size_t i;
+
+   kernel = malloc(size);
+   initrd = malloc(size);
+
+   images.os.image_start = map_to_sysmem(kernel);
+   images.os.image_len = size;
+
+   images.rd_start = map_to_sysmem(initrd);
+   images.rd_end = images.rd_start + size;
+
+   images.ft_addr = malloc(size);
+   images.ft_len = size;
+
+   env_set("bootargs", "measurement testing");
+
+   for (i = 0; i < size; ++i) {
+   kernel[i] = 0xf0 | (i & 0xf);
+   initrd[i] = (i & 0xf0) | 0xf;
+  

[PATCH v6 6/6] doc: Add measured boot documentation

2023-02-22 Thread Eddie James
Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
---
 doc/usage/index.rst |  1 +
 doc/usage/measured_boot.rst | 23 +++
 2 files changed, 24 insertions(+)
 create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index cde7dcb14a..0cf78cb0e7 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -12,6 +12,7 @@ Use U-Boot
partitions
cmdline
semihosting
+   measured_boot
 
 Shell commands
 --
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..8357b1f480
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
-- 
2.31.1



[PATCH v6 4/6] bootm: Support boot measurement

2023-02-22 Thread Eddie James
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 
---
 boot/Kconfig| 23 
 boot/bootm.c| 70 +
 cmd/booti.c |  1 +
 cmd/bootm.c |  2 ++
 cmd/bootz.c |  1 +
 include/bootm.h |  2 ++
 include/image.h |  1 +
 7 files changed, 100 insertions(+)

diff --git a/boot/Kconfig b/boot/Kconfig
index 5f491625c8..d0d5e5794c 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -629,6 +629,29 @@ 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.
+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..10b4848c7e 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,72 @@ 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;
+
+   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;
+
+   ret = tcg2_measurement_init(&dev, &elog);
+   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 +777,9 @@ int do_bootm_state

[PATCH v6 2/6] tpm: sandbox: Update for needed TPM2 capabilities

2023-02-22 Thread Eddie James
The driver needs to support getting the PCRs in the capabilities
command. Fix various other things and support the max number
of PCRs for TPM2.
Remove the !SANDBOX dependency for EFI TCG2 as well.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
Acked-by: Ilias Apalodimas 
---
Changes since v5:
 - Remove the !SANDBOX dependency for EFI TCG2

 drivers/tpm/tpm2_tis_sandbox.c | 100 -
 lib/efi_loader/Kconfig |   2 -
 2 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index e4004cfcca..f63c72814f 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -22,11 +22,6 @@ enum tpm2_hierarchy {
TPM2_HIERARCHY_NB,
 };
 
-/* Subset of supported capabilities */
-enum tpm2_capability {
-   TPM_CAP_TPM_PROPERTIES = 0x6,
-};
-
 /* Subset of supported properties */
 #define TPM2_PROPERTIES_OFFSET 0x020E
 
@@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
TPM2_PROPERTY_NB,
 };
 
-#define SANDBOX_TPM_PCR_NB 1
+#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
+#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8)
 
 /*
  * Information about our TPM emulation. This is preserved in the sandbox
@@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 
*sendbuf,
int i, j;
 
/* TPM2_GetProperty */
-   u32 capability, property, property_count;
+   u32 capability, property, property_count, val;
 
/* TPM2_PCR_Read/Extend variables */
int pcr_index = 0;
@@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
case TPM2_CC_GET_CAPABILITY:
capability = get_unaligned_be32(sent);
sent += sizeof(capability);
-   if (capability != TPM_CAP_TPM_PROPERTIES) {
-   printf("Sandbox TPM only support TPM_CAPABILITIES\n");
-   return TPM2_RC_HANDLE;
-   }
-
property = get_unaligned_be32(sent);
sent += sizeof(property);
-   property -= TPM2_PROPERTIES_OFFSET;
-
property_count = get_unaligned_be32(sent);
sent += sizeof(property_count);
-   if (!property_count ||
-   property + property_count > TPM2_PROPERTY_NB) {
+
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   break;
+   case TPM2_CAP_TPM_PROPERTIES:
+   if (!property_count) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+
+   if (property > TPM2_PROPERTIES_OFFSET &&
+   ((property - TPM2_PROPERTIES_OFFSET) +
+property_count > TPM2_PROPERTY_NB)) {
+   rc = TPM2_RC_HANDLE;
+   return sandbox_tpm2_fill_buf(recv, recv_len,
+tag, rc);
+   }
+   break;
+   default:
+   printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
+  "TPM2_CAP_TPM_PROPERTIES\n");
rc = TPM2_RC_HANDLE;
return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
}
@@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const 
u8 *sendbuf,
put_unaligned_be32(capability, recv);
recv += sizeof(capability);
 
-   /* Give the number of properties that follow */
-   put_unaligned_be32(property_count, recv);
-   recv += sizeof(property_count);
-
-   /* Fill with the properties */
-   for (i = 0; i < property_count; i++) {
-   put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
-  i, recv);
-   recv += sizeof(property);
-   put_unaligned_be32(tpm->properties[property + i],
-  recv);
-   recv += sizeof(property);
+   switch (capability) {
+   case TPM2_CAP_PCRS:
+   /* Give the number of algorithms supported - just 
SHA256 */
+   put_unaligned_be32(1, recv);
+   recv += sizeof(u32);
+
+   /* Give SHA256 algorithm */
+   put_unaligned_be16(TPM2_ALG_SHA256, recv);
+   recv += sizeof(u16);
+
+   /* Select the PCRs supported */
+   *recv = SAN

[PATCH v6 0/6] tpm: Support boot measurements

2023-02-22 Thread Eddie James
This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm 
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.
This series is based on Ilias' auto-startup series and Simon's additions.

Changes since v5:
 - Re-ordered the patches to put the sandbox TPM driver patch second
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs
 - Remove the !SANDBOX dependency for EFI TCG2
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
 - Change PCR indexes for initrd and dtb
 - Drop u8 casting in measurement test
 - Use bullets in documentation

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v2:
 - Add documentation.
 - Changed reserved memory address to the top of the RAM for sandbox dts.
 - Add measure state to booti and bootz.
 - Skip measurement for EFI images that should be measured

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.
 - Add test case
 - Drop #ifdefs for bootm
 - Add devicetree measurement config option
 - Update sandbox TPM driver

Eddie James (6):
  tpm: Fix spelling for tpmu_ha union
  tpm: sandbox: Update for needed TPM2 capabilities
  tpm: Support boot measurements
  bootm: Support boot measurement
  test: Add sandbox TPM boot measurement
  doc: Add measured boot documentation

 arch/sandbox/dts/sandbox.dtsi  |   13 +
 arch/sandbox/dts/test.dts  |   13 +
 boot/Kconfig   |   23 +
 boot/bootm.c   |   70 +++
 cmd/booti.c|1 +
 cmd/bootm.c|2 +
 cmd/bootz.c|1 +
 configs/sandbox_defconfig  |1 +
 doc/usage/index.rst|1 +
 doc/usage/measured_boot.rst|   23 +
 drivers/tpm/tpm2_tis_sandbox.c |  100 ++-
 include/bootm.h|2 +
 include/efi_tcg2.h |   44 --
 include/image.h|1 +
 include/test/suites.h  |1 +
 include/tpm-v2.h   |  246 +++-
 lib/Kconfig|4 +
 lib/efi_loader/Kconfig |2 -
 lib/efi_loader/efi_tcg2.c  | 1053 +++-
 lib/tpm-v2.c   |  773 +++
 test/boot/Makefile |1 +
 test/boot/measurement.c|   66 ++
 test/cmd_ut.c  |4 +
 23 files changed, 1392 insertions(+), 1053 deletions(-)
 create mode 100644 doc/usage/measured_boot.rst
 create mode 100644 test/boot/measurement.c

-- 
2.31.1



[PATCH v6 1/6] tpm: Fix spelling for tpmu_ha union

2023-02-22 Thread Eddie James
tmpu -> tpmu

Signed-off-by: Eddie James 
Reviewed-by: Ilias Apalodimas 
---
 include/tpm-v2.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 2b6980e441..6684033deb 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -169,7 +169,7 @@ struct tcg_pcr_event {
 /**
  * Definition of TPMU_HA Union
  */
-union tmpu_ha {
+union tpmu_ha {
u8 sha1[TPM2_SHA1_DIGEST_SIZE];
u8 sha256[TPM2_SHA256_DIGEST_SIZE];
u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE];
@@ -185,7 +185,7 @@ union tmpu_ha {
  */
 struct tpmt_ha {
u16 hash_alg;
-   union tmpu_ha digest;
+   union tpmu_ha digest;
 } __packed;
 
 /**
-- 
2.31.1



Re: [PATCH v5 0/6] tpm: Support boot measurements

2023-02-22 Thread Eddie James



On 2/21/23 23:36, Joel Stanley wrote:

On Thu, 2 Feb 2023 at 17:08, Eddie James  wrote:

This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.
This series is based on Ilias' auto-startup series:
https://lore.kernel.org/u-boot/20230126081844.591148-1-ilias.apalodi...@linaro.org/

Nice work Eddie. It looks like you're closing in on the issues Ilias
and Simon have.

I did some testing and found some missing dependencies from running
'make check':

sandbox_spl: +make O=/home/joel/dev/u-boot/upstream/build-sandbox_spl
-s sandbox_spl_defconfig
+make O=/home/joel/dev/u-boot/upstream/build-sandbox_spl -s -j8
/usr/bin/ld: warning: test/overlay/test-fdt-overlay-stacked.dtb.o:
missing .note.GNU-stack section implies executable stack
/usr/bin/ld: NOTE: This behaviour is deprecated and will be removed in
a future version of the linker
/usr/bin/ld: /tmp/cc8cNroX.ltrans22.ltrans.o:(.data.rel+0x440):
undefined reference to `do_ut_measurement'
collect2: error: ld returned 1 exit status
make[2]: *** [/home/joel/dev/u-boot/upstream/Makefile:1752: u-boot] Error 1

There's a few variants of the sandbox defconfig. I'm not sure if we
want to exclude the measurement code from those configs, or add it to
the configs.



Thanks Joel. I feel the right thing here would be to only build the 
measurement test when CONFIG_MEASURED_BOOT is enabled, so I'll make that 
change.





When fixing them up to add CONFIG_MEASURED_BOOT=y we still fail to link:

sandbox_spl: +make O=/home/joel/dev/u-boot/upstream/build-sandbox_spl
-s sandbox_spl_defconfig
+make O=/home/joel/dev/u-boot/upstream/build-sandbox_spl -s -j8
/usr/bin/ld: warning: test/overlay/test-fdt-overlay-stacked.dtb.o:
missing .note.GNU-stack section implies executable stack
/usr/bin/ld: NOTE: This behaviour is deprecated and will be removed in
a future version of the linker
/usr/bin/ld: /tmp/ccRuOSFi.ltrans17.ltrans.o: in function `tcg2_create_digest':
/home/joel/dev/u-boot/upstream/build-sandbox_spl/../lib/tpm-v2.c:112:
undefined reference to `sha512_starts'
/usr/bin/ld: 
/home/joel/dev/u-boot/upstream/build-sandbox_spl/../lib/tpm-v2.c:113:
undefined reference to `sha512_update'
/usr/bin/ld: 
/home/joel/dev/u-boot/upstream/build-sandbox_spl/../lib/tpm-v2.c:114:
undefined reference to `sha512_finish'
/usr/bin/ld: 
/home/joel/dev/u-boot/upstream/build-sandbox_spl/../lib/tpm-v2.c:106:
undefined reference to `sha384_starts'
/usr/bin/ld: 
/home/joel/dev/u-boot/upstream/build-sandbox_spl/../lib/tpm-v2.c:107:
undefined reference to `sha384_update'
/usr/bin/ld: 
/home/joel/dev/u-boot/upstream/build-sandbox_spl/../lib/tpm-v2.c:108:
undefined reference to `sha384_finish'
collect2: error: ld returned 1 exit status

This sorted that out for me:

--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -411,6 +411,8 @@ config TPM
 bool "Trusted Platform Module (TPM) Support"
 depends on DM
 imply DM_RNG
+   select SHA512
+   select SHA384

The tree I tested with is here:
https://github.com/shenki/u-boot/commits/measured-boot



Thanks, I'll select those.

Eddie




Cheers,

Joel


Changes since v4:
  - Remove tcg2_measure_event function and check for NULL data in
tcg2_measure_data
  - Use tpm_auto_startup
  - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
  - Change PCR indexes for initrd and dtb
  - Drop u8 casting in measurement test
  - Use bullets in documentation

Changes since v3:
  - Reordered headers
  - Refactored more of EFI code into common code
 Removed digest_info structure and instead used the common alg_to_mask
   and alg_to_len
 Improved event log parsing in common code to get it equivalent to EFI
   Common code now extends PCR if previous bootloader stage couldn't
   No need to allocate memory in the common code, so EFI copies the
   discovered buffer like it did before
 Rename efi measure_event function

Changes since v2:
  - Add documentation.
  - Changed reserved memory address to the top of the RAM for sandbox dts.
  - Add measure state to booti and bootz.
  - Skip measurement for EFI images that should be measured

Changes since v1:
  - Refactor TPM layer functions to allow EFI system to use them, and
remove duplicate EFI functions.
  - Add test case
  - Drop #ifdefs for bootm
  - Add devicetree measurement config option
  - Update sandbox TPM driver

Eddie James (6):
   tpm: Fix spelling for tpmu_ha union
   tpm: Support boot measurements
   bootm: Support boot measurement
   tpm: sandbox: Update for needed TPM2 capabilities
   test: Add sandbox TPM boot measurement
   doc: Add measured boot d

Re: [PATCH v5 0/6] tpm: Support boot measurements

2023-02-22 Thread Eddie James



On 2/22/23 05:33, Ilias Apalodimas wrote:

Hi Eddie,

On Tue, Feb 21, 2023 at 04:38:58PM -0600, Eddie James wrote:

On 2/6/23 06:20, Ilias Apalodimas wrote:

Thanks Eddie,

I quickly tested this but the EFI subsystem fails to initialize the TCG
protocol properly now.  Unfortunately I am on a business trip and I won't
be able to take a look into why till next week


Hi Ilias,


I haven't had the opportunity to test this, have you?


Thanks,

Eddie



Cheers
/Ilias


Still going through the code so bear with me.
It seems that the EFI failure is coming from tcg2_platform_get_log()
specifically if none of linux,sml-base nor tpm_event_log_addr if present in
the dtb.
One thing we should change here is look for tpm_event_log_addr first.  The
reason is that this is a very 'special' case in which TF-A fills in an
eventlog for us, while linux,sml-base is more generic so I'd rather
explicitly prefer TF-A id it prepared an eventlog for us.



OK, thanks, this is helpful, I'll have a look.




On the failure now, if none of the nodes is present we are looking for
'memory-region' within the TPM node?  Looking at the DT specs the tpm
should only support "compatible, label, linux,sml-base/size' am I missing
something?



I just had a commit merged for the reserved memory region: 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/drivers/char/tpm/eventlog/of.c?id=1e2714bb83fc783d58701967391bea242c65eaff


It isn't documented anywhere so far...


Thanks,

Eddie




I also had to apply [0] for this to compile.  You can 'easily' test the EFI
changes by doing a 'printenv -e'.  This will at least initialize the efi
subsystem and install the needed EFI tables (you need CMD_NVEDIT_EFI=y)

[0] 
https://source.denx.de/u-boot/custodians/u-boot-tpm/-/commit/d473596cd6900117485014476c70c49f202bd8da


Hope this helps a bit. Let me know if I can help in any other way.
Don't bother *testing* the eventlog for EFI on a full linux boot. I'll run
that on v6

/Ilias



On Thu, Feb 02, 2023 at 11:05:25AM -0600, Eddie James wrote:

This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.
This series is based on Ilias' auto-startup series:
https://lore.kernel.org/u-boot/20230126081844.591148-1-ilias.apalodi...@linaro.org/

Changes since v4:
   - Remove tcg2_measure_event function and check for NULL data in
 tcg2_measure_data
   - Use tpm_auto_startup
   - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
   - Change PCR indexes for initrd and dtb
   - Drop u8 casting in measurement test
   - Use bullets in documentation

Changes since v3:
   - Reordered headers
   - Refactored more of EFI code into common code
  Removed digest_info structure and instead used the common alg_to_mask
and alg_to_len
  Improved event log parsing in common code to get it equivalent to EFI
Common code now extends PCR if previous bootloader stage couldn't
No need to allocate memory in the common code, so EFI copies the
discovered buffer like it did before
  Rename efi measure_event function

Changes since v2:
   - Add documentation.
   - Changed reserved memory address to the top of the RAM for sandbox dts.
   - Add measure state to booti and bootz.
   - Skip measurement for EFI images that should be measured

Changes since v1:
   - Refactor TPM layer functions to allow EFI system to use them, and
 remove duplicate EFI functions.
   - Add test case
   - Drop #ifdefs for bootm
   - Add devicetree measurement config option
   - Update sandbox TPM driver

Eddie James (6):
tpm: Fix spelling for tpmu_ha union
tpm: Support boot measurements
bootm: Support boot measurement
tpm: sandbox: Update for needed TPM2 capabilities
test: Add sandbox TPM boot measurement
doc: Add measured boot documentation

   arch/sandbox/dts/sandbox.dtsi  |   14 +
   arch/sandbox/dts/test.dts  |   13 +
   boot/Kconfig   |   23 +
   boot/bootm.c   |   70 +++
   cmd/booti.c|1 +
   cmd/bootm.c|2 +
   cmd/bootz.c|1 +
   configs/sandbox_defconfig  |1 +
   doc/usage/index.rst|1 +
   doc/usage/measured_boot.rst|   23 +
   drivers/tpm/tpm2_tis_sandbox.c |  100 +++-
   include/bootm.h|2 +
   include/efi_tcg2.h |   44 --
   include/image.h|1 +
   include/test/suites.h  |1 +
   include/tpm-v2.h   |  246 +++-
   lib/efi_loader/efi_tcg2.c  | 1010 +++--

Re: [PATCH v5 0/6] tpm: Support boot measurements

2023-02-21 Thread Eddie James



On 2/6/23 06:20, Ilias Apalodimas wrote:

Thanks Eddie,

I quickly tested this but the EFI subsystem fails to initialize the TCG
protocol properly now.  Unfortunately I am on a business trip and I won't
be able to take a look into why till next week



Hi Ilias,


I haven't had the opportunity to test this, have you?


Thanks,

Eddie




Cheers
/Ilias

On Thu, Feb 02, 2023 at 11:05:25AM -0600, Eddie James wrote:

This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.
This series is based on Ilias' auto-startup series:
https://lore.kernel.org/u-boot/20230126081844.591148-1-ilias.apalodi...@linaro.org/

Changes since v4:
  - Remove tcg2_measure_event function and check for NULL data in
tcg2_measure_data
  - Use tpm_auto_startup
  - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
  - Change PCR indexes for initrd and dtb
  - Drop u8 casting in measurement test
  - Use bullets in documentation

Changes since v3:
  - Reordered headers
  - Refactored more of EFI code into common code
 Removed digest_info structure and instead used the common alg_to_mask
   and alg_to_len
 Improved event log parsing in common code to get it equivalent to EFI
   Common code now extends PCR if previous bootloader stage couldn't
   No need to allocate memory in the common code, so EFI copies the
   discovered buffer like it did before
 Rename efi measure_event function

Changes since v2:
  - Add documentation.
  - Changed reserved memory address to the top of the RAM for sandbox dts.
  - Add measure state to booti and bootz.
  - Skip measurement for EFI images that should be measured

Changes since v1:
  - Refactor TPM layer functions to allow EFI system to use them, and
remove duplicate EFI functions.
  - Add test case
  - Drop #ifdefs for bootm
  - Add devicetree measurement config option
  - Update sandbox TPM driver

Eddie James (6):
   tpm: Fix spelling for tpmu_ha union
   tpm: Support boot measurements
   bootm: Support boot measurement
   tpm: sandbox: Update for needed TPM2 capabilities
   test: Add sandbox TPM boot measurement
   doc: Add measured boot documentation

  arch/sandbox/dts/sandbox.dtsi  |   14 +
  arch/sandbox/dts/test.dts  |   13 +
  boot/Kconfig   |   23 +
  boot/bootm.c   |   70 +++
  cmd/booti.c|1 +
  cmd/bootm.c|2 +
  cmd/bootz.c|1 +
  configs/sandbox_defconfig  |1 +
  doc/usage/index.rst|1 +
  doc/usage/measured_boot.rst|   23 +
  drivers/tpm/tpm2_tis_sandbox.c |  100 +++-
  include/bootm.h|2 +
  include/efi_tcg2.h |   44 --
  include/image.h|1 +
  include/test/suites.h  |1 +
  include/tpm-v2.h   |  246 +++-
  lib/efi_loader/efi_tcg2.c  | 1010 +++-
  lib/tpm-v2.c   |  771 
  test/boot/Makefile |1 +
  test/boot/measurement.c|   66 +++
  test/cmd_ut.c  |2 +
  21 files changed, 1383 insertions(+), 1010 deletions(-)
  create mode 100644 doc/usage/measured_boot.rst
  create mode 100644 test/boot/measurement.c

--
2.31.1



Re: [PATCH v4 2/6] tpm: Support boot measurements

2023-02-02 Thread Eddie James



On 2/2/23 11:12, Simon Glass wrote:

Hi Eddie / Ilias,

On Thu, 2 Feb 2023 at 09:24, Eddie James  wrote:


On 1/26/23 01:51, Ilias Apalodimas wrote:

Hi Eddie,

Thanks for the cleanup! Unfortunately this doesn't compile with EFI
selected, but in general it looks pretty good.


Thanks, yes I forgot to remove tcg2_pcr_read



On Wed, Jan 25, 2023 at 11:18:06AM -0600, Eddie James wrote:

Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
   include/efi_tcg2.h|  44 --
   include/tpm-v2.h  | 254 ++
   lib/efi_loader/efi_tcg2.c | 975 +++---
   lib/tpm-v2.c  | 799 +++
   4 files changed, 1129 insertions(+), 943 deletions(-)

Can you please point to the spec containing what this implements? I am
still not sure why the identifiers and filenames have EFI in them.



Yes. Primarily implementing this specification: 
https://trustedcomputinggroup.org/wp-content/uploads/TCG_ServerManagDomainFWProfile_r1p00_pub.pdf



See chapter 9, event logging, which mentions the TCG_EfiSpecIdEvent as 
the first event in the event log.



Thanks,

Eddie




Regards,
Simon


[PATCH v5 2/6] tpm: Support boot measurements

2023-02-02 Thread Eddie James
Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James 
---
Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
Removed digest_info structure and instead used the common alg_to_mask
  and alg_to_len
Improved event log parsing in common code to get it equivalent to EFI
  Common code now extends PCR if previous bootloader stage couldn't
  No need to allocate memory in the common code, so EFI copies the
  discovered buffer like it did before
Rename efi measure_event function

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.

 include/efi_tcg2.h|   44 --
 include/tpm-v2.h  |  242 +
 lib/efi_loader/efi_tcg2.c | 1010 +++--
 lib/tpm-v2.c  |  771 
 4 files changed, 1087 insertions(+), 980 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index 874306dc11..23016773f4 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
 #define BOOT_SERVICE_CAPABILITY_MIN \
offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id: algorithm defined in enum tpm2_algorithms
- *  @digest_size:  size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-   u16  algorithm_id;
-   u16  digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature: signature, set to Spec ID Event03
- * @platform_class:class defined in TCG ACPI Specification
- * Client  Common Header.
- * @spec_version_minor:minor version
- * @spec_version_major:major version
- * @spec_version_errata:   major version
- * @uintn_size:size of the efi_uintn_t fields used in 
various
- * data structures used in this specification.
- * 0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:  hashing algorithms used in this event log
- * @digest_sizes:  array of number_of_algorithms pairs
- * 1st member defines the algorithm id
- * 2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-   u8 signature[16];
-   u32 platform_class;
-   u8 spec_version_minor;
-   u8 spec_version_major;
-   u8 spec_errata;
-   u8 uintn_size;
-   u32 number_of_algorithms;
-   struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
-} __packed;
-
 /**
  * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log
  * @version:   version number for this structure
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 84034c1559..3a4227249b 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -214,6 +214,50 @@ struct tcg_pcr_event2 {
u8 event[];
 } __packed;
 
+/**
+ *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
+ *
+ *  @algorithm_id: algorithm defined in enum tpm2_algorithms
+ *  @digest_size:  size of the algorithm
+ */
+struct tcg_efi_spec_id_event_algorithm_size {
+   u16  algorithm_id;
+   u16  digest_size;
+} __packed;
+
+#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
+
+/**
+ * struct TCG_EfiSpecIDEventStruct - content of the event log header
+ *
+ * @signature: signature, set to Spec ID Event03
+ * @platform_class:class defined in TCG ACPI Specification
+ * Client  Common Header.
+ * @spec_version_minor:minor version
+ * @spec_version_major:major version
+ * @spec_version_errata:   major version
+ * @uintn_size:size of the efi_uintn_t fields used in 
various
+ * dat

[PATCH v5 6/6] doc: Add measured boot documentation

2023-02-02 Thread Eddie James
Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James 
---
Changes since v4:
 - Use bullets for the requirements list

 doc/usage/index.rst |  1 +
 doc/usage/measured_boot.rst | 23 +++
 2 files changed, 24 insertions(+)
 create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 3804046835..371ab8179f 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -12,6 +12,7 @@ Use U-Boot
partitions
cmdline
semihosting
+   measured_boot
 
 Shell commands
 --
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 00..8357b1f480
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+Requirements
+-
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
-- 
2.31.1



[PATCH v5 5/6] test: Add sandbox TPM boot measurement

2023-02-02 Thread Eddie James
Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James 
Reviewed-by: Simon Glass 
---
Changes since v4:
 - Drop u8 casting in measurement test

Changes since v2:
 - Changed reserved memory address to the top of the RAM for sandbox dts.

 arch/sandbox/dts/sandbox.dtsi | 14 
 arch/sandbox/dts/test.dts | 13 +++
 configs/sandbox_defconfig |  1 +
 include/test/suites.h |  1 +
 test/boot/Makefile|  1 +
 test/boot/measurement.c   | 66 +++
 test/cmd_ut.c |  2 ++
 7 files changed, 98 insertions(+)
 create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 18bf1cb5b6..3f0e192a83 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,9 +4,22 @@
  * and sandbox64 builds.
  */
 
+#include 
+
 #define USB_CLASS_HUB  9
 
 / {
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman {
};
 
@@ -332,6 +345,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 8c05927670..fa3f42a7b1 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include 
 #include 
 #include 
 #include 
@@ -66,6 +67,17 @@
osd0 = "/osd";
};
 
+   reserved-memory {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   event_log: tcg_event_log {
+   no-map;
+   reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+   };
+   };
+
binman: binman {
};
 
@@ -1345,6 +1357,7 @@
 
tpm2 {
compatible = "sandbox,tpm2";
+   memory-region = <&event_log>;
};
 
uart0: serial {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 34c342b6f5..9c4985adcf 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -337,3 +337,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 9ce49cbb03..4c284bbeaa 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -44,6 +44,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 22ed61c8fa..2dbb032a7e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MEASUREMENT_TEST(_name, _flags)\
+   UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+   struct bootm_headers images;
+   const size_t size = 1024;
+   u8 *kernel;
+   u8 *initrd;
+   size_t i;
+
+   kernel = malloc(size);
+   initrd = malloc(size);
+
+   images.os.image_start = map_to_sysmem(kernel);
+   images.os.image_len = size;
+
+   images.rd_start = map_to_sysmem(initrd);
+   images.rd_end = images.rd_start + size;
+
+   images.ft_addr = malloc(size);
+   images.ft_len = size;
+
+   env_set("bootargs", "measurement testing");
+
+   for (i = 0; i < size; ++i) {
+   kernel[i] = 0xf0 | (i & 0xf);
+   initrd[i

  1   2   >