diff --git a/patches/coreboot-fam15h-unreleased/0001-Add-Heads-TPM-measured-boot-support.patch b/patches/coreboot-fam15h-unreleased/0001-Add-Heads-TPM-measured-boot-support.patch new file mode 100644 index 000000000..76ce8f81d --- /dev/null +++ b/patches/coreboot-fam15h-unreleased/0001-Add-Heads-TPM-measured-boot-support.patch @@ -0,0 +1,476 @@ +From 48784d452a85ee282823d1d8c8d3d4eec56de3a2 Mon Sep 17 00:00:00 2001 +From: Martin Kepplinger +Date: Wed, 15 May 2019 11:55:24 +0200 +Subject: [PATCH] Add Heads TPM measured boot support + +Change-Id: I3a64998de2fbb7f2059cb8c68cfbf949b0665665 +Signed-off-by: Martin Kepplinger +--- + src/Kconfig | 15 +++ + src/include/program_loading.h | 2 + + src/lib/cbfs.c | 19 ++- + src/lib/hardwaremain.c | 8 ++ + src/lib/rmodule.c | 3 +- + src/security/tpm/Makefile.inc | 5 + + src/security/tpm/sha1.c | 180 +++++++++++++++++++++++++++++ + src/security/tpm/sha1.h | 47 ++++++++ + src/security/tpm/tspi/tspi.c | 2 +- + src/security/tpm/tss.h | 5 + + src/security/tpm/tss/tcg-1.2/tss.c | 19 +++ + 11 files changed, 299 insertions(+), 6 deletions(-) + create mode 100644 src/security/tpm/sha1.c + create mode 100644 src/security/tpm/sha1.h + +diff --git a/src/Kconfig b/src/Kconfig +index c0315239fc..48e53dc239 100644 +--- a/src/Kconfig ++++ b/src/Kconfig +@@ -332,6 +332,21 @@ config BOOTSPLASH_FILE + config HAVE_RAMPAYLOAD + bool + ++config MEASURED_BOOT ++ bool "Enable TPM measured boot" ++ default n ++ select TPM1 ++ depends on MAINBOARD_HAS_LPC_TPM ++ depends on !VBOOT ++ help ++ Enable this option to measure the bootblock, romstage and ++ CBFS files into TPM PCRs. This does not verify these values ++ (that is the job of something like vboot), but makes it possible ++ for the payload to validate the boot path and allow something ++ like Heads to attest to the user that the system is likely safe. ++ ++ You probably want to say N. ++ + config RAMPAYLOAD + bool "Enable coreboot flow without executing ramstage" + default y if ARCH_X86 +diff --git a/src/include/program_loading.h b/src/include/program_loading.h +index 1b71fadb1b..afd8ba0c54 100644 +--- a/src/include/program_loading.h ++++ b/src/include/program_loading.h +@@ -26,6 +26,8 @@ enum { + /* Last segment of program. Can be used to take different actions for + * cache maintenance of a program load. */ + SEG_FINAL = 1 << 0, ++ /* Indicate that the program segment should not be measured */ ++ SEG_NO_MEASURE = 1 << 1, + }; + + enum prog_type { +diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c +index fbe6e43496..b0a4f8843a 100644 +--- a/src/lib/cbfs.c ++++ b/src/lib/cbfs.c +@@ -97,7 +97,13 @@ void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size) + if (size != NULL) + *size = fsize; + +- return rdev_mmap(&fh.data, 0, fsize); ++ void *buffer = rdev_mmap(&fh.data, 0, fsize); ++ ++#ifndef __SMM__ ++ prog_segment_loaded((uintptr_t)buffer, fsize, 0); ++#endif ++ ++ return buffer; + } + + int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name, +@@ -125,7 +131,8 @@ size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset, + return 0; + if (rdev_readat(rdev, buffer, offset, in_size) != in_size) + return 0; +- return in_size; ++ out_size = in_size; ++ break; + + case CBFS_COMPRESS_LZ4: + if ((ENV_BOOTBLOCK || ENV_VERSTAGE) && +@@ -143,7 +150,7 @@ size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset, + timestamp_add_now(TS_START_ULZ4F); + out_size = ulz4fn(compr_start, in_size, buffer, buffer_size); + timestamp_add_now(TS_END_ULZ4F); +- return out_size; ++ break; + + case CBFS_COMPRESS_LZMA: + /* We assume here romstage and postcar are never compressed. */ +@@ -165,11 +172,15 @@ size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset, + + rdev_munmap(rdev, map); + +- return out_size; ++ break; + + default: + return 0; + } ++ ++ prog_segment_loaded((uintptr_t)buffer, out_size, 0); ++ ++ return out_size; + } + + static inline int tohex4(unsigned int c) +diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c +index 51ff330d84..358d3e40b3 100644 +--- a/src/lib/hardwaremain.c ++++ b/src/lib/hardwaremain.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #if CONFIG(HAVE_ACPI_RESUME) + #include + #endif +@@ -540,3 +541,10 @@ void boot_state_current_unblock(void) + { + boot_state_unblock(current_phase.state_id, current_phase.seq); + } ++ ++// ramstage measurements go into PCR3 if we are doing measured boot ++void platform_segment_loaded(uintptr_t start, size_t size, int flags) ++{ ++ if (CONFIG(MEASURED_BOOT) && !(flags & SEG_NO_MEASURE)) ++ tlcl_measure(2, (const void *) start, size); ++} +diff --git a/src/lib/rmodule.c b/src/lib/rmodule.c +index 56529d2fb2..2702b9d36e 100644 +--- a/src/lib/rmodule.c ++++ b/src/lib/rmodule.c +@@ -197,7 +197,8 @@ int rmodule_load(void *base, struct rmodule *module) + rmodule_clear_bss(module); + + prog_segment_loaded((uintptr_t)module->location, +- rmodule_memory_size(module), SEG_FINAL); ++ rmodule_memory_size(module), ++ SEG_FINAL | SEG_NO_MEASURE); + + return 0; + } +diff --git a/src/security/tpm/Makefile.inc b/src/security/tpm/Makefile.inc +index a2d32cff89..e9a785b797 100644 +--- a/src/security/tpm/Makefile.inc ++++ b/src/security/tpm/Makefile.inc +@@ -18,6 +18,11 @@ romstage-y += tspi/tspi.c + verstage-$(CONFIG_VBOOT) += tspi/tspi.c + postcar-$(CONFIG_VBOOT) += tspi/tspi.c + ++ifeq ($(CONFIG_MEASURED_BOOT),y) ++romstage-y += sha1.c ++ramstage-y += sha1.c ++endif # CONFIG_MEASURED_BOOT ++ + ramstage-$(CONFIG_VBOOT_MEASURED_BOOT) += tspi/log.c + romstage-$(CONFIG_VBOOT_MEASURED_BOOT) += tspi/log.c + verstage-$(CONFIG_VBOOT_MEASURED_BOOT) += tspi/log.c +diff --git a/src/security/tpm/sha1.c b/src/security/tpm/sha1.c +new file mode 100644 +index 0000000000..9879f729b1 +--- /dev/null ++++ b/src/security/tpm/sha1.c +@@ -0,0 +1,180 @@ ++/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. ++ * Use of this source code is governed by a BSD-style license that can be ++ * found in the LICENSE file. ++ * ++ * SHA-1 implementation largely based on libmincrypt in the the Android ++ * Open Source Project (platorm/system/core.git/libmincrypt/sha.c ++ */ ++ ++#include ++#include ++ ++static uint32_t ror27(uint32_t val) ++{ ++ return (val >> 27) | (val << 5); ++} ++static uint32_t ror2(uint32_t val) ++{ ++ return (val >> 2) | (val << 30); ++} ++static uint32_t ror31(uint32_t val) ++{ ++ return (val >> 31) | (val << 1); ++} ++ ++static void sha1_transform(struct sha1_ctx *ctx) ++{ ++ uint32_t W[80]; ++ register uint32_t A, B, C, D, E; ++ int t; ++ ++ A = ctx->state[0]; ++ B = ctx->state[1]; ++ C = ctx->state[2]; ++ D = ctx->state[3]; ++ E = ctx->state[4]; ++ ++#define SHA_F1(A, B, C, D, E, t) do { \ ++ E += ror27(A) + \ ++ (W[t] = __builtin_bswap32(ctx->buf.w[t])) + \ ++ (D^(B&(C^D))) + 0x5A827999; \ ++ B = ror2(B); \ ++ } while (0) ++ ++ for (t = 0; t < 15; t += 5) { ++ SHA_F1(A, B, C, D, E, t + 0); ++ SHA_F1(E, A, B, C, D, t + 1); ++ SHA_F1(D, E, A, B, C, t + 2); ++ SHA_F1(C, D, E, A, B, t + 3); ++ SHA_F1(B, C, D, E, A, t + 4); ++ } ++ SHA_F1(A, B, C, D, E, t + 0); /* 16th one, t == 15 */ ++ ++#undef SHA_F1 ++ ++#define SHA_F1(A, B, C, D, E, t) do { \ ++ E += ror27(A) + \ ++ (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ ++ (D^(B&(C^D))) + 0x5A827999; \ ++ B = ror2(B); \ ++ } while (0) ++ ++ SHA_F1(E, A, B, C, D, t + 1); ++ SHA_F1(D, E, A, B, C, t + 2); ++ SHA_F1(C, D, E, A, B, t + 3); ++ SHA_F1(B, C, D, E, A, t + 4); ++ ++#undef SHA_F1 ++ ++#define SHA_F2(A, B, C, D, E, t) do { \ ++ E += ror27(A) + \ ++ (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ ++ (B^C^D) + 0x6ED9EBA1; \ ++ B = ror2(B); \ ++ } while (0) ++ ++ for (t = 20; t < 40; t += 5) { ++ SHA_F2(A, B, C, D, E, t + 0); ++ SHA_F2(E, A, B, C, D, t + 1); ++ SHA_F2(D, E, A, B, C, t + 2); ++ SHA_F2(C, D, E, A, B, t + 3); ++ SHA_F2(B, C, D, E, A, t + 4); ++ } ++ ++#undef SHA_F2 ++ ++#define SHA_F3(A, B, C, D, E, t) do { \ ++ E += ror27(A) + \ ++ (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ ++ ((B&C)|(D&(B|C))) + 0x8F1BBCDC; \ ++ B = ror2(B); \ ++ } while (0) ++ ++ for (; t < 60; t += 5) { ++ SHA_F3(A, B, C, D, E, t + 0); ++ SHA_F3(E, A, B, C, D, t + 1); ++ SHA_F3(D, E, A, B, C, t + 2); ++ SHA_F3(C, D, E, A, B, t + 3); ++ SHA_F3(B, C, D, E, A, t + 4); ++ } ++ ++#undef SHA_F3 ++ ++#define SHA_F4(A, B, C, D, E, t) do { \ ++ E += ror27(A) + \ ++ (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ ++ (B^C^D) + 0xCA62C1D6; \ ++ B = ror2(B); \ ++ } while (0) ++ ++ for (; t < 80; t += 5) { ++ SHA_F4(A, B, C, D, E, t + 0); ++ SHA_F4(E, A, B, C, D, t + 1); ++ SHA_F4(D, E, A, B, C, t + 2); ++ SHA_F4(C, D, E, A, B, t + 3); ++ SHA_F4(B, C, D, E, A, t + 4); ++ } ++ ++#undef SHA_F4 ++ ++ ctx->state[0] += A; ++ ctx->state[1] += B; ++ ctx->state[2] += C; ++ ctx->state[3] += D; ++ ctx->state[4] += E; ++} ++ ++void sha1_update(struct sha1_ctx *ctx, const uint8_t *data, uint32_t len) ++{ ++ int i = ctx->count % sizeof(ctx->buf); ++ const uint8_t *p = (const uint8_t *)data; ++ ++ ctx->count += len; ++ ++ while (len > sizeof(ctx->buf) - i) { ++ memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i); ++ len -= sizeof(ctx->buf) - i; ++ p += sizeof(ctx->buf) - i; ++ sha1_transform(ctx); ++ i = 0; ++ } ++ ++ while (len--) { ++ ctx->buf.b[i++] = *p++; ++ if (i == sizeof(ctx->buf)) { ++ sha1_transform(ctx); ++ i = 0; ++ } ++ } ++} ++ ++ ++uint8_t *sha1_final(struct sha1_ctx *ctx) ++{ ++ uint32_t cnt = ctx->count * 8; ++ int i; ++ ++ sha1_update(ctx, (uint8_t *)"\x80", 1); ++ while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) ++ sha1_update(ctx, (uint8_t *)"\0", 1); ++ ++ for (i = 0; i < 8; ++i) { ++ uint8_t tmp = cnt >> ((7 - i) * 8); ++ sha1_update(ctx, &tmp, 1); ++ } ++ ++ for (i = 0; i < 5; i++) ++ ctx->buf.w[i] = __builtin_bswap32(ctx->state[i]); ++ ++ return ctx->buf.b; ++} ++ ++void sha1_init(struct sha1_ctx *ctx) ++{ ++ ctx->state[0] = 0x67452301; ++ ctx->state[1] = 0xEFCDAB89; ++ ctx->state[2] = 0x98BADCFE; ++ ctx->state[3] = 0x10325476; ++ ctx->state[4] = 0xC3D2E1F0; ++ ctx->count = 0; ++} +diff --git a/src/security/tpm/sha1.h b/src/security/tpm/sha1.h +new file mode 100644 +index 0000000000..bc3faa58ea +--- /dev/null ++++ b/src/security/tpm/sha1.h +@@ -0,0 +1,47 @@ ++/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. ++ * Use of this source code is governed by a BSD-style license that can be ++ * found in the LICENSE file. ++ */ ++ ++/* SHA-1 functions */ ++ ++#ifndef _sha1_h_ ++#define _sha1_h_ ++ ++#include ++#include ++ ++#define SHA1_DIGEST_SIZE 20 ++#define SHA1_BLOCK_SIZE 64 ++ ++/* ++ * FIXME the DIV_ROUND_UP statement expression blows up here: ++ In file included from src/security/tpm/sha1.h:12, ++ from src/security/tpm/sha1.c:9: ++ src/commonlib/include/commonlib/helpers.h:81:28: error: braced-group ++ within expression allowed only inside a function ++ #define DIV_ROUND_UP(x, y) ({ \ ++ ^ ++ src/security/tpm/sha1.h:23:14: note: in expansion of macro'DIV_ROUND_UP' ++ uint32_t w[DIV_ROUND_UP(SHA1_BLOCK_SIZE, sizeof(uint32_t))]; ++ ^~~~~~~~~~~~ ++ make[1]: *** [Makefile:356: x230/romstage/security/tpm/sha1.o] Error 1 ++ */ ++#undef DIV_ROUND_UP ++#define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) ++ ++/* SHA-1 context */ ++struct sha1_ctx { ++ uint32_t count; ++ uint32_t state[5]; ++ union { ++ uint8_t b[SHA1_BLOCK_SIZE]; ++ uint32_t w[DIV_ROUND_UP(SHA1_BLOCK_SIZE, sizeof(uint32_t))]; ++ } buf; ++}; ++ ++void sha1_init(struct sha1_ctx *ctx); ++void sha1_update(struct sha1_ctx *ctx, const uint8_t *data, uint32_t len); ++uint8_t *sha1_final(struct sha1_ctx *ctx); ++ ++#endif /* _sha1_h_ */ +diff --git a/src/security/tpm/tspi/tspi.c b/src/security/tpm/tspi/tspi.c +index 966b8b7c77..9076ced37a 100644 +--- a/src/security/tpm/tspi/tspi.c ++++ b/src/security/tpm/tspi/tspi.c +@@ -20,8 +20,8 @@ + #include + #include + #include +-#if CONFIG(VBOOT) + #include ++#if CONFIG(VBOOT) + #include + #include + #endif +diff --git a/src/security/tpm/tss.h b/src/security/tpm/tss.h +index 336935d911..90a96621ed 100644 +--- a/src/security/tpm/tss.h ++++ b/src/security/tpm/tss.h +@@ -52,6 +52,11 @@ uint32_t tlcl_get_flags(uint8_t *disable, uint8_t *deactivated, + */ + uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags); + ++/** ++ * Perform a SHA1 hash on a region and extend a PCR with the hash. ++ */ ++uint32_t tlcl_measure(int pcr_num, const void *start, size_t len); ++ + #endif + + #if CONFIG(TPM2) +diff --git a/src/security/tpm/tss/tcg-1.2/tss.c b/src/security/tpm/tss/tcg-1.2/tss.c +index b11d6a3d16..ef4f4d8b86 100644 +--- a/src/security/tpm/tss/tcg-1.2/tss.c ++++ b/src/security/tpm/tss/tcg-1.2/tss.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -361,3 +362,21 @@ uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest, + kPcrDigestLength); + return result; + } ++ ++uint32_t tlcl_measure(int pcr_num, const void *start, size_t len) ++{ ++ VBDEBUG("TPM: pcr %d measure %p @ %zu: ", pcr_num, start, len); ++ ++ struct sha1_ctx sha; ++ sha1_init(&sha); ++ sha1_update(&sha, start, len); ++ ++ const uint8_t *hash = sha1_final(&sha); ++ for (unsigned int i = 0; i < SHA1_DIGEST_SIZE; i++) ++ VBDEBUG("%02x", hash[i]); ++ VBDEBUG("\n"); ++ ++ //hexdump(start, 128); ++ ++ return tlcl_extend(pcr_num, hash, NULL); ++} +-- +2.20.1 + diff --git a/patches/coreboot-fam15h-unreleased/0020-kgpe-d16_measured-boot-support.patch b/patches/coreboot-fam15h-unreleased/0020-kgpe-d16_measured-boot-support.patch new file mode 100644 index 000000000..98324f080 --- /dev/null +++ b/patches/coreboot-fam15h-unreleased/0020-kgpe-d16_measured-boot-support.patch @@ -0,0 +1,67 @@ +diff --git a/src/mainboard/asus/kgpe-d16/romstage.c b/src/mainboard/asus/kgpe-d16/romstage.c +index 637ec42109..8a92f88375 100644 +--- a/src/mainboard/asus/kgpe-d16/romstage.c ++++ b/src/mainboard/asus/kgpe-d16/romstage.c +@@ -46,6 +46,12 @@ + #include + #include + ++#include ++#include ++#include ++#include ++#include ++ + #include "cpu/amd/quadcore/quadcore.c" + + #define SERIAL_0_DEV PNP_DEV(0x2e, W83667HG_A_SP1) +@@ -547,7 +553,6 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) + power_on_reset = 1; + + initialize_mca(1, power_on_reset); +- update_microcode(val); + + post_code(0x33); + +@@ -573,6 +578,13 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) + sr5650_early_setup(); + sb7xx_51xx_early_setup(); + ++ if (CONFIG(MEASURED_BOOT) && CONFIG(LPC_TPM) && boot_cpu()) { ++ tpm_setup(0); ++ tlcl_lib_init(); ++ } ++ ++ update_microcode(val); ++ + if (CONFIG(LOGICAL_CPUS)) { + /* Core0 on each node is configured. Now setup any additional cores. */ + printk(BIOS_DEBUG, "start_other_cores()\n"); +@@ -687,6 +699,17 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) + pci_write_config16(PCI_DEV(0, 0x14, 0), 0x54, 0x0707); + pci_write_config16(PCI_DEV(0, 0x14, 0), 0x56, 0x0bb0); + pci_write_config16(PCI_DEV(0, 0x14, 0), 0x5a, 0x0ff0); ++ ++ if (CONFIG(MEASURED_BOOT) && CONFIG(LPC_TPM)) { ++ size_t bootblock_size = 0; ++ const void *bootblock = cbfs_boot_map_with_leak("bootblock", 1, &bootblock_size); ++ tlcl_measure(2, bootblock, bootblock_size); ++ ++ extern char _romstage, _eromstage; ++ tlcl_measure(2, &_romstage, &_eromstage - &_romstage); ++ } ++ ++ + } + + /** +@@ -718,3 +741,9 @@ BOOL AMD_CB_ManualBUIDSwapList (u8 node, u8 link, const u8 **List) + + return 0; + } ++ ++void platform_segment_loaded(uintptr_t start, size_t size, int flags) ++{ ++ if (CONFIG(MEASURED_BOOT) && !(flags & SEG_NO_MEASURE)) ++ tlcl_measure(2, (const void *) start, size); ++} diff --git a/patches/coreboot-fam15h-unreleased/0021-kgpe-d16_c-environment_bootblock.patch b/patches/coreboot-fam15h-unreleased/0021-kgpe-d16_c-environment_bootblock.patch new file mode 100644 index 000000000..c674c2798 --- /dev/null +++ b/patches/coreboot-fam15h-unreleased/0021-kgpe-d16_c-environment_bootblock.patch @@ -0,0 +1,50 @@ +From 92023c6cfc3db86f9236a01897754a1579afdf64 Mon Sep 17 00:00:00 2001 +From: Arthur Heymans +Date: Sun, 17 Nov 2019 12:20:30 +0100 +Subject: [PATCH] lib/fmap.c: Properly handle cache for + !C_ENVIRONMENT_BOOTBLOCK + +On platforms without C_ENVIRONMENT_BOOTBLOCK the first stage +accessing FMAP is romstage. + +Change-Id: I7d70585b0c076707e73e20c2ed3f11e4c9ffdf37 +Signed-off-by: Arthur Heymans +--- + src/lib/fmap.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/src/lib/fmap.c b/src/lib/fmap.c +index 48aab8f3d5..06e9e202b6 100644 +--- a/src/lib/fmap.c ++++ b/src/lib/fmap.c +@@ -58,6 +58,12 @@ static void report(const struct fmap *fmap) + car_set_var(fmap_print_once, 1); + } + ++#if CONFIG(C_ENVIRONMENT_BOOTBLOCK) ++#define FIRST_C_STAGE ENV_BOOTBLOCK ++#else ++#define FIRST_C_STAGE ENV_ROMSTAGE ++#endif ++ + static void setup_preram_cache(struct mem_region_device *cache_mrdev) + { + if (CONFIG(NO_FMAP_CACHE)) +@@ -81,10 +87,10 @@ static void setup_preram_cache(struct mem_region_device *cache_mrdev) + } + + struct fmap *fmap = (struct fmap *)_fmap_cache; +- if (!ENV_BOOTBLOCK) { +- /* NOTE: This assumes that for all platforms running this code, +- the bootblock is the first stage and the bootblock will make +- at least one FMAP access (usually from finding CBFS). */ ++ /* NOTE: This assumes that for all platforms running this code, ++ the first stage running in a C (!romcc) environment does ++ at least one FMAP access (usually from finding CBFS). */ ++ if (!FIRST_C_STAGE) { + if (!check_signature(fmap)) + goto register_cache; + +-- +2.20.1 +