mail.coreboot.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
List overview
Download
coreboot-gerrit
January 2015
----- 2024 -----
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
coreboot-gerrit@coreboot.org
1 participants
1236 discussions
Start a n
N
ew thread
New patch to review for coreboot: d9203ab baytrail: use the setting in devicetree.cb to config USBPHY_COMPBG
by Marc Jones
13 Jan '15
13 Jan '15
Marc Jones (marc.jones(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/8216
-gerrit commit d9203ab0a80429f550ea7e8e727322c6cd8609a0 Author: Kane Chen <kane.chen(a)intel.com> Date: Thu Jul 17 09:51:50 2014 -0700 baytrail: use the setting in devicetree.cb to config USBPHY_COMPBG USBPHY_COMPBG needs to be configured by project BUG=chrome-os-partner:30690 BRANCH=none TEST=emerge-rambi coreboot without problem checked the USBPHY_COMPBG is configured properly Original-Change-Id: I05eee384d94cf5deeec14418bd78816df0b26a92 Original-Signed-off-by: Kane Chen <kane.chen(a)intel.com> Original-Reviewed-on:
https://chromium-review.googlesource.com/208557
Original-Reviewed-by: Shawn Nematbakhsh <shawnn(a)chromium.org> (cherry picked from commit 20a9c0ab7ab180596821751110f0c0a35d3ff3a1) Signed-off-by: Marc Jones <marc.jones(a)se-eng.com> Change-Id: I8bed3fa4e74e4bb4c93fa522d9df631bac2d9795 --- src/soc/intel/baytrail/chip.h | 1 + src/soc/intel/baytrail/ehci.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/soc/intel/baytrail/chip.h b/src/soc/intel/baytrail/chip.h index f19055c..97b92ef 100644 --- a/src/soc/intel/baytrail/chip.h +++ b/src/soc/intel/baytrail/chip.h @@ -55,6 +55,7 @@ struct soc_intel_baytrail_config { uint32_t usb2_per_port_rcomp_hs_pullup2; uint32_t usb2_per_port_lane3; uint32_t usb2_per_port_rcomp_hs_pullup3; + uint32_t usb2_comp_bg; /* LPE Audio Clock configuration. */ int lpe_codec_clk_freq; /* 19 or 25 are valid. */ diff --git a/src/soc/intel/baytrail/ehci.c b/src/soc/intel/baytrail/ehci.c index 5d1a4d8..bfdb61a 100644 --- a/src/soc/intel/baytrail/ehci.c +++ b/src/soc/intel/baytrail/ehci.c @@ -96,7 +96,8 @@ static void usb2_phy_init(device_t dev) struct soc_intel_baytrail_config *config = dev->chip_info; struct reg_script usb2_phy_script[] = { /* USB3PHYInit() */ - REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_COMPBG, 0x4700), + REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_COMPBG, + config->usb2_comp_bg), /* Per port phy settings, set in devicetree.cb */ REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE0, config->usb2_per_port_lane0),
1
0
0
0
New patch to review for coreboot: a24cdeb samus: Delay bringing SSD out of reset
by Marc Jones
13 Jan '15
13 Jan '15
Marc Jones (marc.jones(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/8215
-gerrit commit a24cdeb366b9b949ea392a4903161f63767d6f7d Author: Duncan Laurie <dlaurie(a)chromium.org> Date: Tue Jul 15 13:41:18 2014 -0700 samus: Delay bringing SSD out of reset In order to ensure that we meet timing requirements for the SSD power sequencing delay bringing the SSD out of reset until after memory training. BUG=chrome-os-partner:29914 BRANCH=None TEST=build and boot on samus Original-Change-Id: I807e3d3698255287c3fe7219f44e8ec9a0985df1 Original-Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org> Original-Reviewed-on:
https://chromium-review.googlesource.com/208155
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org> (cherry picked from commit 1cf557049c49e1ba11ade1eee7a45fc2b075ff3d) Signed-off-by: Marc Jones <marc.jones(a)se-eng.com> Change-Id: Ib39a14a03e04a167fab45b58b3bc840eb4bcf317 --- src/mainboard/google/samus/gpio.h | 3 ++- src/mainboard/google/samus/romstage.c | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mainboard/google/samus/gpio.h b/src/mainboard/google/samus/gpio.h index c2f5fde..806804c 100644 --- a/src/mainboard/google/samus/gpio.h +++ b/src/mainboard/google/samus/gpio.h @@ -23,6 +23,7 @@ #include <broadwell/gpio.h> #define SAMUS_GPIO_PP3300_AUTOBAHN_EN 23 +#define SAMUS_GPIO_SSD_RESET_L 47 static const struct gpio_config mainboard_gpio_config[] = { PCH_GPIO_UNUSED, /* 0: UNUSED */ @@ -72,7 +73,7 @@ static const struct gpio_config mainboard_gpio_config[] = { PCH_GPIO_UNUSED, /* 44: UNUSED */ PCH_GPIO_PIRQ, /* 45: DSP_INT (PIRQN) */ PCH_GPIO_PIRQ, /* 46: HOTWORD_DET_L (PIRQO) */ - PCH_GPIO_OUT_HIGH, /* 47: SSD_RESET_L */ + PCH_GPIO_OUT_LOW, /* 47: SSD_RESET_L */ PCH_GPIO_UNUSED, /* 48: UNUSED */ PCH_GPIO_UNUSED, /* 49: UNUSED */ PCH_GPIO_UNUSED, /* 50: UNUSED */ diff --git a/src/mainboard/google/samus/romstage.c b/src/mainboard/google/samus/romstage.c index 2e1a71f..5c6e40d 100644 --- a/src/mainboard/google/samus/romstage.c +++ b/src/mainboard/google/samus/romstage.c @@ -67,6 +67,9 @@ void mainboard_romstage_entry(struct romstage_params *rp) /* Initliaze memory */ romstage_common(rp); + /* Bring SSD out of reset */ + set_gpio(SAMUS_GPIO_SSD_RESET_L, GPIO_OUT_HIGH); + /* * Enable PP3300_AUTOBAHN_EN after initial GPIO setup * to prevent possible brownout.
1
0
0
0
New patch to review for coreboot: 67a7492 samus: Disable self refresh and MRC cache on broadwell
by Marc Jones
13 Jan '15
13 Jan '15
Marc Jones (marc.jones(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/8214
-gerrit commit 67a7492729a812fd48b66356fe95b90186da99ad Author: Duncan Laurie <dlaurie(a)chromium.org> Date: Tue Jul 15 13:40:21 2014 -0700 samus: Disable self refresh and MRC cache on broadwell Workarounds for power and/or lpddr3 issues on broadwell SKU. BUG=chrome-os-partner:29787,chrome-os-partner:29117 BRANCH=None TEST=build and boot on samus Original-Change-Id: If99346212c10ad6026250e48bedd916611e2cb8c Original-Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org> Original-Reviewed-on:
https://chromium-review.googlesource.com/208154
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org> (cherry picked from commit c3ee57114315320b542f53645ffb168ad654b756) Signed-off-by: Marc Jones <marc.jones(a)se-eng.com> Change-Id: Ie28f3ad65000a627ba64486e0f16493e8101cef3 --- src/mainboard/google/samus/romstage.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/mainboard/google/samus/romstage.c b/src/mainboard/google/samus/romstage.c index d652859..2e1a71f 100644 --- a/src/mainboard/google/samus/romstage.c +++ b/src/mainboard/google/samus/romstage.c @@ -22,6 +22,7 @@ #include <console/console.h> #include <string.h> #include <ec/google/chromeec/ec.h> +#include <broadwell/cpu.h> #include <broadwell/gpio.h> #include <broadwell/pei_data.h> #include <broadwell/pei_wrapper.h> @@ -54,6 +55,16 @@ void mainboard_romstage_entry(struct romstage_params *rp) mainboard_fill_spd_data(&pei_data); rp->pei_data = &pei_data; + /* + *
http://crosbug.com/p/29117
+ * Disable use of PEI saved data to work around memory issues. + */ + if (cpu_family_model() == BROADWELL_FAMILY_ULT) { + pei_data.disable_self_refresh = 1; + pei_data.disable_saved_data = 1; + } + + /* Initliaze memory */ romstage_common(rp); /*
1
0
0
0
New patch to review for coreboot: 8e0a60d samus: Enable keyboard backlight
by Marc Jones
13 Jan '15
13 Jan '15
Marc Jones (marc.jones(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/8213
-gerrit commit 8e0a60d8dcc20a87dbbfa92a9d94b360c2495e18 Author: Duncan Laurie <dlaurie(a)chromium.org> Date: Tue Jul 15 13:36:52 2014 -0700 samus: Enable keyboard backlight - Turn on keyboard backlight early in boot (not resume) path as a sign of life for the system - Add ACPI device for keyboard backlight so the kernel can find and make use of it BUG=chrome-os-partner:30586 BRANCH=None TEST=build and boot on samus Original-Change-Id: Iecaef0ec5c814774e19d7c4a14cb92dc236cfee3 Original-Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org> Original-Reviewed-on:
https://chromium-review.googlesource.com/208152
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org> (cherry picked from commit e166f76f9bd167468c7637dcce2b9eabf7dce8f0) Signed-off-by: Marc Jones <marc.jones(a)se-eng.com> Change-Id: I47927d97c1586ec09310d014d8fba7d7a3d773c4 --- src/mainboard/google/samus/acpi/mainboard.asl | 18 ++++++++++++++++++ src/mainboard/google/samus/romstage.c | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/mainboard/google/samus/acpi/mainboard.asl b/src/mainboard/google/samus/acpi/mainboard.asl index 624aa38..3aea40c 100644 --- a/src/mainboard/google/samus/acpi/mainboard.asl +++ b/src/mainboard/google/samus/acpi/mainboard.asl @@ -50,6 +50,24 @@ Scope (\_SB) Name (_UID, 2) Name (_PRW, Package() { 14, 0x3 }) // GPIO14 } + + // Keyboard Backlight interface via EC + Device (KBLT) { + Name (_HID, "GOOG0002") + Name (_UID, 1) + + // Read current backlight value + Method (KBQC, 0) + { + Return (\_SB.PCI0.LPCB.EC0.KBLV) + } + + // Write new backlight value + Method (KBCM, 1) + { + Store (Arg0, \_SB.PCI0.LPCB.EC0.KBLV) + } + } } Scope (\_SB.PCI0.I2C0) diff --git a/src/mainboard/google/samus/romstage.c b/src/mainboard/google/samus/romstage.c index c9e13e1..d652859 100644 --- a/src/mainboard/google/samus/romstage.c +++ b/src/mainboard/google/samus/romstage.c @@ -25,6 +25,7 @@ #include <broadwell/gpio.h> #include <broadwell/pei_data.h> #include <broadwell/pei_wrapper.h> +#include <broadwell/pm.h> #include <broadwell/romstage.h> #include <mainboard/google/samus/spd/spd.h> #include <mainboard/google/samus/gpio.h> @@ -33,7 +34,10 @@ void mainboard_romstage_entry(struct romstage_params *rp) { struct pei_data pei_data; - post_code(0x32); + post_code(0x31); + + if (rp->power_state->prev_sleep_state != SLEEP_STATE_S3) + google_chromeec_kbbacklight(100); printk(BIOS_INFO, "MLB: board version %d\n", google_chromeec_get_board_version());
1
0
0
0
New patch to review for coreboot: 2d49eb4 samus: add acpi resource for supporting RT5677 codec
by Marc Jones
13 Jan '15
13 Jan '15
Marc Jones (marc.jones(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/8212
-gerrit commit 2d49eb4b3a389224f05f763a0da933952eea5e77 Author: Kane Chen <kane.chen(a)intel.com> Date: Fri Jul 11 16:24:39 2014 -0700 samus: add acpi resource for supporting RT5677 codec Add codec acpi resource for supporting RT5667 codec. BUG=chrome-os-partner:29649 TEST=emerge-coreboot successfully checked codec device is probed Original-Change-Id: I739c0dbfdbfa221b06f99c3d934825b640096c6b Original-Signed-off-by: Kane Chen <kane.chen(a)intel.com> Original-Reviewed-on:
https://chromium-review.googlesource.com/207707
Original-Reviewed-by: Shawn Nematbakhsh <shawnn(a)chromium.org> Original-Reviewed-by: Duncan Laurie <dlaurie(a)chromium.org> (cherry picked from commit f9698c45a47efe7fd2a1f5432640f3db5e4bd3f0) Signed-off-by: Marc Jones <marc.jones(a)se-eng.com> Change-Id: Ib14b27421613d747e02037ecd2311d9966a5d813 --- src/mainboard/google/samus/acpi/mainboard.asl | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/mainboard/google/samus/acpi/mainboard.asl b/src/mainboard/google/samus/acpi/mainboard.asl index eb66818..624aa38 100644 --- a/src/mainboard/google/samus/acpi/mainboard.asl +++ b/src/mainboard/google/samus/acpi/mainboard.asl @@ -117,6 +117,36 @@ Scope (\_SB.PCI0.I2C0) } } } + + Device (CODC) + { + /* + * TODO(kane): Need official HID. + * + */ + Name (_HID, "RT5677CE") + Name (_DDN, "RT5667 Codec") + Name (_UID, 1) + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x2c, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.PCI0.I2C0", // ResourceSource + ) + Interrupt (ResourceConsumer, Edge, ActiveLow){ 30 } + }) + Method (_STA) + { + If (LEqual (\S1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + } } Scope (\_SB.PCI0.I2C1)
1
0
0
0
New patch to review for coreboot: 69f886c src/arch/arm/Makefile.inc: Remove trailing whitespace
by Paul Menzel
13 Jan '15
13 Jan '15
Paul Menzel (paulepanter(a)users.sourceforge.net) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/8211
-gerrit commit 69f886ca38abcd302a19d4082253f2c19817e4ec Author: Paul Menzel <paulepanter(a)users.sourceforge.net> Date: Tue Jan 13 23:29:05 2015 +0100 src/arch/arm/Makefile.inc: Remove trailing whitespace Remove trailing space introduced in commit 320647ab (vboot2: add verstage). Change-Id: I936eb03457ea161716a1a59890bc3c9c33051265 Signed-off-by: Paul Menzel <paulepanter(a)users.sourceforge.net> --- src/arch/arm/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/arm/Makefile.inc b/src/arch/arm/Makefile.inc index ba7fb60..6f65a71 100644 --- a/src/arch/arm/Makefile.inc +++ b/src/arch/arm/Makefile.inc @@ -61,7 +61,7 @@ bootblock-y += memcpy.S bootblock-y += memmove.S bootblock-y += div0.c -$(objcbfs)/bootblock.debug: $(src)/arch/arm/bootblock.ld $(obj)/ldoptions $$(bootblock-objs) $$(VERSTAGE_LIB) +$(objcbfs)/bootblock.debug: $(src)/arch/arm/bootblock.ld $(obj)/ldoptions $$(bootblock-objs) $$(VERSTAGE_LIB) @printf " LINK $(subst $(obj)/,,$(@))\n" $(LD_bootblock) --gc-sections -static -o $@ -L$(obj) --start-group $(bootblock-objs) --end-group -T $(src)/arch/arm/bootblock.ld
1
0
0
0
Patch set updated for coreboot: 4239d78 vboot2: copy tlcl from vboot_reference as a preparation for vboot2 integration
by Marc Jones
13 Jan '15
13 Jan '15
Marc Jones (marc.jones(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/8164
-gerrit commit 4239d781046f0b88bfbc9e04cb37ca74857d20ee Author: Daisuke Nojiri <dnojiri(a)chromium.org> Date: Wed Jul 2 08:37:23 2014 -0700 vboot2: copy tlcl from vboot_reference as a preparation for vboot2 integration vboot2 abtracts tpm storage as some 'secure' space. Thus, it's firmware's responsibility to handle vboot specific operations with tpm. This CL just copies related files from vboot_reference so that we can see how code was modified in the next CL. Note rollback_index.c/h were renamed to antirollback.c/h. TEST=none BUG=none Branch=none Signed-off-by: Daisuke Nojiri <dnojiri(a)chromium.org> Original-Change-Id: I1792a622058f70a8fcd3c4037547539ad2870420 Original-Reviewed-on:
https://chromium-review.googlesource.com/206462
Original-Commit-Queue: Daisuke Nojiri <dnojiri(a)chromium.org> Original-Tested-by: Daisuke Nojiri <dnojiri(a)chromium.org> Original-Reviewed-by: Randall Spangler <rspangler(a)chromium.org> (cherry picked from commit 2ae188b29242bf09c5e79e31f98b330a30bf7b93) Signed-off-by: Marc Jones <marc.jones(a)se-eng.com> Change-Id: I5fa5a636003e8472127194e961fea4309489b1d9 --- src/include/antirollback.h | 187 +++++++ src/include/tpm_lite/tlcl.h | 209 ++++++++ src/include/tpm_lite/tss_constants.h | 96 ++++ src/lib/tlcl.c | 466 ++++++++++++++++++ src/lib/tlcl_internal.h | 61 +++ src/lib/tlcl_structures.h | 138 ++++++ src/lib/tpm_error_messages.h | 250 ++++++++++ src/vendorcode/google/chromeos/antirollback.c | 676 ++++++++++++++++++++++++++ 8 files changed, 2083 insertions(+) diff --git a/src/include/antirollback.h b/src/include/antirollback.h new file mode 100644 index 0000000..dd0de32 --- /dev/null +++ b/src/include/antirollback.h @@ -0,0 +1,187 @@ +/* Copyright (c) 2013 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. + * + * Functions for querying, manipulating and locking rollback indices + * stored in the TPM NVRAM. + */ + +#ifndef VBOOT_REFERENCE_ROLLBACK_INDEX_H_ +#define VBOOT_REFERENCE_ROLLBACK_INDEX_H_ + +#include "sysincludes.h" +#include "tss_constants.h" + +/* TPM NVRAM location indices. */ +#define FIRMWARE_NV_INDEX 0x1007 +#define KERNEL_NV_INDEX 0x1008 +/* This is just an opaque space for backup purposes */ +#define BACKUP_NV_INDEX 0x1009 +#define BACKUP_NV_SIZE 16 + + +/* Structure definitions for TPM spaces */ + +/* Kernel space - KERNEL_NV_INDEX, locked with physical presence. */ +#define ROLLBACK_SPACE_KERNEL_VERSION 2 +#define ROLLBACK_SPACE_KERNEL_UID 0x4752574C /* 'GRWL' */ + +typedef struct RollbackSpaceKernel { + /* Struct version, for backwards compatibility */ + uint8_t struct_version; + /* Unique ID to detect space redefinition */ + uint32_t uid; + /* Kernel versions */ + uint32_t kernel_versions; + /* Reserved for future expansion */ + uint8_t reserved[3]; + /* Checksum (v2 and later only) */ + uint8_t crc8; +} __attribute__((packed)) RollbackSpaceKernel; + +/* Flags for firmware space */ +/* + * Last boot was developer mode. TPM ownership is cleared when transitioning + * to/from developer mode. + */ +#define FLAG_LAST_BOOT_DEVELOPER 0x01 +/* + * Some systems may not have a dedicated dev-mode switch, but enter and leave + * dev-mode through some recovery-mode magic keypresses. For those systems, the + * dev-mode "switch" state is in this bit (0=normal, 1=dev). To make it work, a + * new flag is passed to VbInit(), indicating that the system lacks a physical + * dev-mode switch. If a physical switch is present, this bit is ignored. + */ +#define FLAG_VIRTUAL_DEV_MODE_ON 0x02 + +/* Firmware space - FIRMWARE_NV_INDEX, locked with global lock. */ +#define ROLLBACK_SPACE_FIRMWARE_VERSION 2 + +typedef struct RollbackSpaceFirmware { + /* Struct version, for backwards compatibility */ + uint8_t struct_version; + /* Flags (see FLAG_* above) */ + uint8_t flags; + /* Firmware versions */ + uint32_t fw_versions; + /* Reserved for future expansion */ + uint8_t reserved[3]; + /* Checksum (v2 and later only) */ + uint8_t crc8; +} __attribute__((packed)) RollbackSpaceFirmware; + + +/* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */ + +/* + * These functions are called from VbInit(). They cannot use global + * variables. + */ + +uint32_t RollbackS3Resume(void); + +/* + * These functions are callable from VbSelectFirmware(). They cannot use + * global variables. + */ + +/** + * This must be called. + */ +uint32_t RollbackFirmwareSetup(int is_hw_dev, + int disable_dev_request, + int clear_tpm_owner_request, + /* two outputs on success */ + int *is_virt_dev, uint32_t *tpm_version); + +/** + * Write may be called if the versions change. + */ +uint32_t RollbackFirmwareWrite(uint32_t version); + +/** + * Lock must be called. + */ +uint32_t RollbackFirmwareLock(void); + +/* + * These functions are callable from VbSelectAndLoadKernel(). They may use + * global variables. + */ + +/** + * Read stored kernel version. + */ +uint32_t RollbackKernelRead(uint32_t *version); + +/** + * Write stored kernel version. + */ +uint32_t RollbackKernelWrite(uint32_t version); + +/** + * Read backup data. + */ +uint32_t RollbackBackupRead(uint8_t *raw); + +/** + * Write backup data. + */ +uint32_t RollbackBackupWrite(uint8_t *raw); + +/** + * Lock must be called. Internally, it's ignored in recovery mode. + */ +uint32_t RollbackKernelLock(int recovery_mode); + +/****************************************************************************/ + +/* + * The following functions are internal apis, listed here for use by unit tests + * only. + */ + +/** + * Issue a TPM_Clear and reenable/reactivate the TPM. + */ +uint32_t TPMClearAndReenable(void); + +/** + * Like TlclWrite(), but checks for write errors due to hitting the 64-write + * limit and clears the TPM when that happens. This can only happen when the + * TPM is unowned, so it is OK to clear it (and we really have no choice). + * This is not expected to happen frequently, but it could happen. + */ +uint32_t SafeWrite(uint32_t index, const void *data, uint32_t length); + +/** + * Similarly to SafeWrite(), this ensures we don't fail a DefineSpace because + * we hit the TPM write limit. This is even less likely to happen than with + * writes because we only define spaces once at initialization, but we'd rather + * be paranoid about this. + */ +uint32_t SafeDefineSpace(uint32_t index, uint32_t perm, uint32_t size); + +/** + * Perform one-time initializations. + * + * Create the NVRAM spaces, and set their initial values as needed. Sets the + * nvLocked bit and ensures the physical presence command is enabled and + * locked. + */ +uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf, + RollbackSpaceKernel *rsk); + +/** + * Start the TPM and establish the root of trust for the anti-rollback + * mechanism. + */ +uint32_t SetupTPM(int developer_mode, int disable_dev_request, + int clear_tpm_owner_request, RollbackSpaceFirmware *rsf); + +/** + * Utility function to turn the virtual dev-mode flag on or off. 0=off, 1=on. + */ +uint32_t SetVirtualDevMode(int val); + +#endif /* VBOOT_REFERENCE_ROLLBACK_INDEX_H_ */ diff --git a/src/include/tpm_lite/tlcl.h b/src/include/tpm_lite/tlcl.h new file mode 100644 index 0000000..5373120 --- /dev/null +++ b/src/include/tpm_lite/tlcl.h @@ -0,0 +1,209 @@ +/* Copyright (c) 2013 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. + */ + +/* + * TPM Lightweight Command Library. + * + * A low-level library for interfacing to TPM hardware or an emulator. + */ + +#ifndef TPM_LITE_TLCL_H_ +#define TPM_LITE_TLCL_H_ +#include <stdint.h> + +#include "tss_constants.h" + +/*****************************************************************************/ +/* Functions implemented in tlcl.c */ + +/** + * Call this first. Returns 0 if success, nonzero if error. + */ +uint32_t TlclLibInit(void); + +/** + * Call this on shutdown. Returns 0 if success, nonzero if error. + */ +uint32_t TlclLibClose(void); + +/* Low-level operations */ + +/** + * Perform a raw TPM request/response transaction. + */ +uint32_t TlclSendReceive(const uint8_t *request, uint8_t *response, + int max_length); + +/** + * Return the size of a TPM request or response packet. + */ +int TlclPacketSize(const uint8_t *packet); + +/* Commands */ + +/** + * Send a TPM_Startup(ST_CLEAR). The TPM error code is returned (0 for + * success). + */ +uint32_t TlclStartup(void); + +/** + * Save the TPM state. Normally done by the kernel before a suspend, included + * here for tests. The TPM error code is returned (0 for success). + */ +uint32_t TlclSaveState(void); + +/** + * Resume by sending a TPM_Startup(ST_STATE). The TPM error code is returned + * (0 for success). + */ +uint32_t TlclResume(void); + +/** + * Run the self test. + * + * Note---this is synchronous. To run this in parallel with other firmware, + * use ContinueSelfTest(). The TPM error code is returned. + */ +uint32_t TlclSelfTestFull(void); + +/** + * Run the self test in the background. + */ +uint32_t TlclContinueSelfTest(void); + +/** + * Define a space with permission [perm]. [index] is the index for the space, + * [size] the usable data size. The TPM error code is returned. + */ +uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size); + +/** + * Write [length] bytes of [data] to space at [index]. The TPM error code is + * returned. + */ +uint32_t TlclWrite(uint32_t index, const void *data, uint32_t length); + +/** + * Read [length] bytes from space at [index] into [data]. The TPM error code + * is returned. + */ +uint32_t TlclRead(uint32_t index, void *data, uint32_t length); + +/** + * Read PCR at [index] into [data]. [length] must be TPM_PCR_DIGEST or + * larger. The TPM error code is returned. + */ +uint32_t TlclPCRRead(uint32_t index, void *data, uint32_t length); + +/** + * Write-lock space at [index]. The TPM error code is returned. + */ +uint32_t TlclWriteLock(uint32_t index); + +/** + * Read-lock space at [index]. The TPM error code is returned. + */ +uint32_t TlclReadLock(uint32_t index); + +/** + * Assert physical presence in software. The TPM error code is returned. + */ +uint32_t TlclAssertPhysicalPresence(void); + +/** + * Enable the physical presence command. The TPM error code is returned. + */ +uint32_t TlclPhysicalPresenceCMDEnable(void); + +/** + * Finalize the physical presence settings: sofware PP is enabled, hardware PP + * is disabled, and the lifetime lock is set. The TPM error code is returned. + */ +uint32_t TlclFinalizePhysicalPresence(void); + +uint32_t TlclAssertPhysicalPresenceResult(void); + +/** + * Turn off physical presence and locks it off until next reboot. The TPM + * error code is returned. + */ +uint32_t TlclLockPhysicalPresence(void); + +/** + * Set the nvLocked bit. The TPM error code is returned. + */ +uint32_t TlclSetNvLocked(void); + +/** + * Return 1 if the TPM is owned, 0 otherwise. + */ +int TlclIsOwned(void); + +/** + * Issue a ForceClear. The TPM error code is returned. + */ +uint32_t TlclForceClear(void); + +/** + * Issue a PhysicalEnable. The TPM error code is returned. + */ +uint32_t TlclSetEnable(void); + +/** + * Issue a PhysicalDisable. The TPM error code is returned. + */ +uint32_t TlclClearEnable(void); + +/** + * Issue a SetDeactivated. Pass 0 to activate. Returns result code. + */ +uint32_t TlclSetDeactivated(uint8_t flag); + +/** + * Get flags of interest. Pointers for flags you aren't interested in may + * be NULL. The TPM error code is returned. + */ +uint32_t TlclGetFlags(uint8_t *disable, uint8_t *deactivated, + uint8_t *nvlocked); + +/** + * Set the bGlobalLock flag, which only a reboot can clear. The TPM error + * code is returned. + */ +uint32_t TlclSetGlobalLock(void); + +/** + * Perform a TPM_Extend. + */ +uint32_t TlclExtend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest); + +/** + * Get the permission bits for the NVRAM space with |index|. + */ +uint32_t TlclGetPermissions(uint32_t index, uint32_t *permissions); + +/** + * Get the entire set of permanent flags. + */ +uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS *pflags); + +/** + * Get the entire set of volatile (ST_CLEAR) flags. + */ +uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS *pflags); + +/** + * Get the ownership flag. The TPM error code is returned. + */ +uint32_t TlclGetOwnership(uint8_t *owned); + +/** + * Request [length] bytes from TPM RNG to be stored in [data]. Actual number of + * bytes read is stored in [size]. The TPM error code is returned. + */ +uint32_t TlclGetRandom(uint8_t *data, uint32_t length, uint32_t *size); + +#endif /* TPM_LITE_TLCL_H_ */ diff --git a/src/include/tpm_lite/tss_constants.h b/src/include/tpm_lite/tss_constants.h new file mode 100644 index 0000000..883a5ad --- /dev/null +++ b/src/include/tpm_lite/tss_constants.h @@ -0,0 +1,96 @@ +/* Copyright (c) 2013 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. + * + * Some TPM constants and type definitions for standalone compilation for use + * in the firmware + */ +#ifndef VBOOT_REFERENCE_TSS_CONSTANTS_H_ +#define VBOOT_REFERENCE_TSS_CONSTANTS_H_ +#include <stdint.h> + +#define TPM_MAX_COMMAND_SIZE 4096 +#define TPM_LARGE_ENOUGH_COMMAND_SIZE 256 /* saves space in the firmware */ +#define TPM_PUBEK_SIZE 256 +#define TPM_PCR_DIGEST 20 + +#define TPM_E_NON_FATAL 0x800 + +#define TPM_SUCCESS ((uint32_t)0x00000000) + +#define TPM_E_AREA_LOCKED ((uint32_t)0x0000003c) +#define TPM_E_BADINDEX ((uint32_t)0x00000002) +#define TPM_E_BAD_PRESENCE ((uint32_t)0x0000002d) +#define TPM_E_IOERROR ((uint32_t)0x0000001f) +#define TPM_E_INVALID_POSTINIT ((uint32_t)0x00000026) +#define TPM_E_MAXNVWRITES ((uint32_t)0x00000048) +#define TPM_E_OWNER_SET ((uint32_t)0x00000014) + +#define TPM_E_NEEDS_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 1)) +#define TPM_E_DOING_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 2)) + +#define TPM_E_ALREADY_INITIALIZED ((uint32_t)0x00005000) /* vboot local */ +#define TPM_E_INTERNAL_INCONSISTENCY ((uint32_t)0x00005001) /* vboot local */ +#define TPM_E_MUST_REBOOT ((uint32_t)0x00005002) /* vboot local */ +#define TPM_E_CORRUPTED_STATE ((uint32_t)0x00005003) /* vboot local */ +#define TPM_E_COMMUNICATION_ERROR ((uint32_t)0x00005004) /* vboot local */ +#define TPM_E_RESPONSE_TOO_LARGE ((uint32_t)0x00005005) /* vboot local */ +#define TPM_E_NO_DEVICE ((uint32_t)0x00005006) /* vboot local */ +#define TPM_E_INPUT_TOO_SMALL ((uint32_t)0x00005007) /* vboot local */ +#define TPM_E_WRITE_FAILURE ((uint32_t)0x00005008) /* vboot local */ +#define TPM_E_READ_EMPTY ((uint32_t)0x00005009) /* vboot local */ +#define TPM_E_READ_FAILURE ((uint32_t)0x0000500a) /* vboot local */ + +#define TPM_NV_INDEX0 ((uint32_t)0x00000000) +#define TPM_NV_INDEX_LOCK ((uint32_t)0xffffffff) +#define TPM_NV_PER_GLOBALLOCK (((uint32_t)1)<<15) +#define TPM_NV_PER_PPWRITE (((uint32_t)1)<<0) +#define TPM_NV_PER_READ_STCLEAR (((uint32_t)1)<<31) +#define TPM_NV_PER_WRITE_STCLEAR (((uint32_t)1)<<14) + +#define TPM_TAG_RQU_COMMAND ((uint16_t) 0xc1) +#define TPM_TAG_RQU_AUTH1_COMMAND ((uint16_t) 0xc2) +#define TPM_TAG_RQU_AUTH2_COMMAND ((uint16_t) 0xc3) + +#define TPM_TAG_RSP_COMMAND ((uint16_t) 0xc4) +#define TPM_TAG_RSP_AUTH1_COMMAND ((uint16_t) 0xc5) +#define TPM_TAG_RSP_AUTH2_COMMAND ((uint16_t) 0xc6) + +typedef uint8_t TSS_BOOL; +typedef uint16_t TPM_STRUCTURE_TAG; + +typedef struct tdTPM_PERMANENT_FLAGS +{ + TPM_STRUCTURE_TAG tag; + TSS_BOOL disable; + TSS_BOOL ownership; + TSS_BOOL deactivated; + TSS_BOOL readPubek; + TSS_BOOL disableOwnerClear; + TSS_BOOL allowMaintenance; + TSS_BOOL physicalPresenceLifetimeLock; + TSS_BOOL physicalPresenceHWEnable; + TSS_BOOL physicalPresenceCMDEnable; + TSS_BOOL CEKPUsed; + TSS_BOOL TPMpost; + TSS_BOOL TPMpostLock; + TSS_BOOL FIPS; + TSS_BOOL Operator; + TSS_BOOL enableRevokeEK; + TSS_BOOL nvLocked; + TSS_BOOL readSRKPub; + TSS_BOOL tpmEstablished; + TSS_BOOL maintenanceDone; + TSS_BOOL disableFullDALogicInfo; +} TPM_PERMANENT_FLAGS; + +typedef struct tdTPM_STCLEAR_FLAGS{ + TPM_STRUCTURE_TAG tag; + TSS_BOOL deactivated; + TSS_BOOL disableForceClear; + TSS_BOOL physicalPresence; + TSS_BOOL physicalPresenceLock; + TSS_BOOL bGlobalLock; +} TPM_STCLEAR_FLAGS; + +#endif /* VBOOT_REFERENCE_TSS_CONSTANTS_H_ */ diff --git a/src/lib/tlcl.c b/src/lib/tlcl.c new file mode 100644 index 0000000..bf2d27f --- /dev/null +++ b/src/lib/tlcl.c @@ -0,0 +1,466 @@ +/* Copyright (c) 2012 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. + */ + +/* A lightweight TPM command library. + * + * The general idea is that TPM commands are array of bytes whose + * fields are mostly compile-time constant. The goal is to build much + * of the commands at compile time (or build time) and change some of + * the fields at run time as needed. The code in + * utility/tlcl_generator.c builds structures containing the commands, + * as well as the offsets of the fields that need to be set at run + * time. + */ + +#include "sysincludes.h" + +#include "tlcl.h" +#include "tlcl_internal.h" +#include "tlcl_structures.h" +#include "utility.h" +#include "vboot_api.h" + +#ifdef FOR_TEST +/* Allow unit testing implementation of TlclSendReceive() */ +#undef CHROMEOS_ENVIRONMENT +#endif + +/* Sets the size field of a TPM command. */ +static inline void SetTpmCommandSize(uint8_t* buffer, uint32_t size) { + ToTpmUint32(buffer + sizeof(uint16_t), size); +} + +/* Gets the size field of a TPM command. */ +__attribute__((unused)) +static inline int TpmCommandSize(const uint8_t* buffer) { + uint32_t size; + FromTpmUint32(buffer + sizeof(uint16_t), &size); + return (int) size; +} + +/* Gets the size field of a TPM request or response. */ +int TlclPacketSize(const uint8_t* packet) { + return TpmCommandSize(packet); +} + +/* Gets the code field of a TPM command. */ +static inline int TpmCommandCode(const uint8_t* buffer) { + uint32_t code; + FromTpmUint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code); + return code; +} + +/* Gets the return code field of a TPM result. */ +static inline int TpmReturnCode(const uint8_t* buffer) { + return TpmCommandCode(buffer); +} + +/* Like TlclSendReceive below, but do not retry if NEEDS_SELFTEST or + * DOING_SELFTEST errors are returned. + */ +static uint32_t TlclSendReceiveNoRetry(const uint8_t* request, + uint8_t* response, int max_length) { + + uint32_t response_length = max_length; + uint32_t result; + +#ifdef EXTRA_LOGGING + VBDEBUG(("TPM: command: %x%x %x%x%x%x %x%x%x%x\n", + request[0], request[1], + request[2], request[3], request[4], request[5], + request[6], request[7], request[8], request[9])); +#endif + + result = VbExTpmSendReceive(request, TpmCommandSize(request), + response, &response_length); + if (0 != result) { + /* Communication with TPM failed, so response is garbage */ + VBDEBUG(("TPM: command 0x%x send/receive failed: 0x%x\n", + TpmCommandCode(request), result)); + return result; + } + /* Otherwise, use the result code from the response */ + result = TpmReturnCode(response); + + /* TODO: add paranoia about returned response_length vs. max_length + * (and possibly expected length from the response header). See + *
crosbug.com/17017
*/ + +#ifdef EXTRA_LOGGING + VBDEBUG(("TPM: response: %x%x %x%x%x%x %x%x%x%x\n", + response[0], response[1], + response[2], response[3], response[4], response[5], + response[6], response[7], response[8], response[9])); +#endif + + VBDEBUG(("TPM: command 0x%x returned 0x%x\n", + TpmCommandCode(request), result)); + + return result; +} + + +/* Sends a TPM command and gets a response. Returns 0 if success or the TPM + * error code if error. In the firmware, waits for the self test to complete + * if needed. In the host, reports the first error without retries. */ +uint32_t TlclSendReceive(const uint8_t* request, uint8_t* response, + int max_length) { + uint32_t result = TlclSendReceiveNoRetry(request, response, max_length); + /* When compiling for the firmware, hide command failures due to the self + * test not having run or completed. */ +#ifndef CHROMEOS_ENVIRONMENT + /* If the command fails because the self test has not completed, try it + * again after attempting to ensure that the self test has completed. */ + if (result == TPM_E_NEEDS_SELFTEST || result == TPM_E_DOING_SELFTEST) { + result = TlclContinueSelfTest(); + if (result != TPM_SUCCESS) { + return result; + } +#if defined(TPM_BLOCKING_CONTINUESELFTEST) || defined(VB_RECOVERY_MODE) + /* Retry only once */ + result = TlclSendReceiveNoRetry(request, response, max_length); +#else + /* This needs serious testing. The TPM specification says: "iii. The + * caller MUST wait for the actions of TPM_ContinueSelfTest to complete + * before reissuing the command C1." But, if ContinueSelfTest is + * non-blocking, how do we know that the actions have completed other than + * trying again? */ + do { + result = TlclSendReceiveNoRetry(request, response, max_length); + } while (result == TPM_E_DOING_SELFTEST); +#endif + } +#endif /* ! defined(CHROMEOS_ENVIRONMENT) */ + return result; +} + +/* Sends a command and returns the error code. */ +static uint32_t Send(const uint8_t* command) { + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + return TlclSendReceive(command, response, sizeof(response)); +} + +/* Exported functions. */ + +uint32_t TlclLibInit(void) { + return VbExTpmInit(); +} + +uint32_t TlclLibClose(void) { + return VbExTpmClose(); +} + +uint32_t TlclStartup(void) { + VBDEBUG(("TPM: Startup\n")); + return Send(tpm_startup_cmd.buffer); +} + +uint32_t TlclSaveState(void) { + VBDEBUG(("TPM: SaveState\n")); + return Send(tpm_savestate_cmd.buffer); +} + +uint32_t TlclResume(void) { + VBDEBUG(("TPM: Resume\n")); + return Send(tpm_resume_cmd.buffer); +} + +uint32_t TlclSelfTestFull(void) { + VBDEBUG(("TPM: Self test full\n")); + return Send(tpm_selftestfull_cmd.buffer); +} + +uint32_t TlclContinueSelfTest(void) { + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + VBDEBUG(("TPM: Continue self test\n")); + /* Call the No Retry version of SendReceive to avoid recursion. */ + return TlclSendReceiveNoRetry(tpm_continueselftest_cmd.buffer, + response, sizeof(response)); +} + +uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) { + struct s_tpm_nv_definespace_cmd cmd; + VBDEBUG(("TPM: TlclDefineSpace(0x%x, 0x%x, %d)\n", index, perm, size)); + Memcpy(&cmd, &tpm_nv_definespace_cmd, sizeof(cmd)); + ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.index, index); + ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.perm, perm); + ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.size, size); + return Send(cmd.buffer); +} + +uint32_t TlclWrite(uint32_t index, const void* data, uint32_t length) { + struct s_tpm_nv_write_cmd cmd; + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + const int total_length = + kTpmRequestHeaderLength + kWriteInfoLength + length; + + VBDEBUG(("TPM: TlclWrite(0x%x, %d)\n", index, length)); + Memcpy(&cmd, &tpm_nv_write_cmd, sizeof(cmd)); + VbAssert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); + SetTpmCommandSize(cmd.buffer, total_length); + + ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.index, index); + ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.length, length); + Memcpy(cmd.buffer + tpm_nv_write_cmd.data, data, length); + + return TlclSendReceive(cmd.buffer, response, sizeof(response)); +} + +uint32_t TlclRead(uint32_t index, void* data, uint32_t length) { + struct s_tpm_nv_read_cmd cmd; + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t result_length; + uint32_t result; + + VBDEBUG(("TPM: TlclRead(0x%x, %d)\n", index, length)); + Memcpy(&cmd, &tpm_nv_read_cmd, sizeof(cmd)); + ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.index, index); + ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.length, length); + + result = TlclSendReceive(cmd.buffer, response, sizeof(response)); + if (result == TPM_SUCCESS && length > 0) { + uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength; + FromTpmUint32(nv_read_cursor, &result_length); + nv_read_cursor += sizeof(uint32_t); + Memcpy(data, nv_read_cursor, result_length); + } + + return result; +} + +uint32_t TlclPCRRead(uint32_t index, void* data, uint32_t length) { + struct s_tpm_pcr_read_cmd cmd; + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t result; + + VBDEBUG(("TPM: TlclPCRRead(0x%x, %d)\n", index, length)); + if (length < kPcrDigestLength) { + return TPM_E_IOERROR; + } + Memcpy(&cmd, &tpm_pcr_read_cmd, sizeof(cmd)); + ToTpmUint32(cmd.buffer + tpm_pcr_read_cmd.pcrNum, index); + + result = TlclSendReceive(cmd.buffer, response, sizeof(response)); + if (result == TPM_SUCCESS) { + uint8_t* pcr_read_cursor = response + kTpmResponseHeaderLength; + Memcpy(data, pcr_read_cursor, kPcrDigestLength); + } + + return result; +} + +uint32_t TlclWriteLock(uint32_t index) { + VBDEBUG(("TPM: Write lock 0x%x\n", index)); + return TlclWrite(index, NULL, 0); +} + +uint32_t TlclReadLock(uint32_t index) { + VBDEBUG(("TPM: Read lock 0x%x\n", index)); + return TlclRead(index, NULL, 0); +} + +uint32_t TlclAssertPhysicalPresence(void) { + VBDEBUG(("TPM: Asserting physical presence\n")); + return Send(tpm_ppassert_cmd.buffer); +} + +uint32_t TlclPhysicalPresenceCMDEnable(void) { + VBDEBUG(("TPM: Enable the physical presence command\n")); + return Send(tpm_ppenable_cmd.buffer); +} + +uint32_t TlclFinalizePhysicalPresence(void) { + VBDEBUG(("TPM: Enable PP cmd, disable HW pp, and set lifetime lock\n")); + return Send(tpm_finalizepp_cmd.buffer); +} + +uint32_t TlclAssertPhysicalPresenceResult(void) { + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + return TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response)); +} + +uint32_t TlclLockPhysicalPresence(void) { + VBDEBUG(("TPM: Lock physical presence\n")); + return Send(tpm_pplock_cmd.buffer); +} + +uint32_t TlclSetNvLocked(void) { + VBDEBUG(("TPM: Set NV locked\n")); + return TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0); +} + +int TlclIsOwned(void) { + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE]; + uint32_t result; + result = TlclSendReceive(tpm_readpubek_cmd.buffer, + response, sizeof(response)); + return (result != TPM_SUCCESS); +} + +uint32_t TlclForceClear(void) { + VBDEBUG(("TPM: Force clear\n")); + return Send(tpm_forceclear_cmd.buffer); +} + +uint32_t TlclSetEnable(void) { + VBDEBUG(("TPM: Enabling TPM\n")); + return Send(tpm_physicalenable_cmd.buffer); +} + +uint32_t TlclClearEnable(void) { + VBDEBUG(("TPM: Disabling TPM\n")); + return Send(tpm_physicaldisable_cmd.buffer); +} + +uint32_t TlclSetDeactivated(uint8_t flag) { + struct s_tpm_physicalsetdeactivated_cmd cmd; + VBDEBUG(("TPM: SetDeactivated(%d)\n", flag)); + Memcpy(&cmd, &tpm_physicalsetdeactivated_cmd, sizeof(cmd)); + *(cmd.buffer + cmd.deactivated) = flag; + return Send(cmd.buffer); +} + +uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS* pflags) { + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t size; + uint32_t result = + TlclSendReceive(tpm_getflags_cmd.buffer, response, sizeof(response)); + if (result != TPM_SUCCESS) + return result; + FromTpmUint32(response + kTpmResponseHeaderLength, &size); + /*
TODO(crbug.com/379255)
: This fails. Find out why. + * VbAssert(size == sizeof(TPM_PERMANENT_FLAGS)); + */ + Memcpy(pflags, + response + kTpmResponseHeaderLength + sizeof(size), + sizeof(TPM_PERMANENT_FLAGS)); + return result; +} + +uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS* vflags) { + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t size; + uint32_t result = + TlclSendReceive(tpm_getstclearflags_cmd.buffer, response, sizeof(response)); + if (result != TPM_SUCCESS) + return result; + FromTpmUint32(response + kTpmResponseHeaderLength, &size); + /* Ugly assertion, but the struct is padded up by one byte. */ + /*
TODO(crbug.com/379255)
: This fails. Find out why. + * VbAssert(size == 7 && sizeof(TPM_STCLEAR_FLAGS) - 1 == 7); + */ + Memcpy(vflags, + response + kTpmResponseHeaderLength + sizeof(size), + sizeof(TPM_STCLEAR_FLAGS)); + return result; +} + +uint32_t TlclGetFlags(uint8_t* disable, + uint8_t* deactivated, + uint8_t *nvlocked) { + TPM_PERMANENT_FLAGS pflags; + uint32_t result = TlclGetPermanentFlags(&pflags); + if (result == TPM_SUCCESS) { + if (disable) + *disable = pflags.disable; + if (deactivated) + *deactivated = pflags.deactivated; + if (nvlocked) + *nvlocked = pflags.nvLocked; + VBDEBUG(("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n", + pflags.disable, pflags.deactivated, pflags.nvLocked)); + } + return result; +} + +uint32_t TlclSetGlobalLock(void) { + uint32_t x; + VBDEBUG(("TPM: Set global lock\n")); + return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0); +} + +uint32_t TlclExtend(int pcr_num, const uint8_t* in_digest, + uint8_t* out_digest) { + struct s_tpm_extend_cmd cmd; + uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; + uint32_t result; + + Memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd)); + ToTpmUint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num); + Memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength); + + result = TlclSendReceive(cmd.buffer, response, sizeof(response)); + if (result != TPM_SUCCESS) + return result; + + Memcpy(out_digest, response + kTpmResponseHeaderLength, kPcrDigestLength); + return result; +} + +uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) { + struct s_tpm_getpermissions_cmd cmd; + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint8_t* nvdata; + uint32_t result; + uint32_t size; + + Memcpy(&cmd, &tpm_getpermissions_cmd, sizeof(cmd)); + ToTpmUint32(cmd.buffer + tpm_getpermissions_cmd.index, index); + result = TlclSendReceive(cmd.buffer, response, sizeof(response)); + if (result != TPM_SUCCESS) + return result; + + nvdata = response + kTpmResponseHeaderLength + sizeof(size); + FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions); + return result; +} + +uint32_t TlclGetOwnership(uint8_t* owned) { + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t size; + uint32_t result = + TlclSendReceive(tpm_getownership_cmd.buffer, response, sizeof(response)); + if (result != TPM_SUCCESS) + return result; + FromTpmUint32(response + kTpmResponseHeaderLength, &size); + /*
TODO(crbug.com/379255)
: This fails. Find out why. + * VbAssert(size == sizeof(*owned)); + */ + Memcpy(owned, + response + kTpmResponseHeaderLength + sizeof(size), + sizeof(*owned)); + return result; +} + +uint32_t TlclGetRandom(uint8_t* data, uint32_t length, uint32_t *size) { + struct s_tpm_get_random_cmd cmd; + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t result; + + VBDEBUG(("TPM: TlclGetRandom(%d)\n", length)); + Memcpy(&cmd, &tpm_get_random_cmd, sizeof(cmd)); + ToTpmUint32(cmd.buffer + tpm_get_random_cmd.bytesRequested, length); + /* There must be room in the response buffer for the bytes. */ + if (length > TPM_LARGE_ENOUGH_COMMAND_SIZE - kTpmResponseHeaderLength + - sizeof(uint32_t)) { + return TPM_E_IOERROR; + } + + result = TlclSendReceive(cmd.buffer, response, sizeof(response)); + if (result == TPM_SUCCESS) { + uint8_t* get_random_cursor; + FromTpmUint32(response + kTpmResponseHeaderLength, size); + + /* There must be room in the target buffer for the bytes. */ + if (*size > length) { + return TPM_E_RESPONSE_TOO_LARGE; + } + get_random_cursor = response + kTpmResponseHeaderLength + + sizeof(uint32_t); + Memcpy(data, get_random_cursor, *size); + } + + return result; +} diff --git a/src/lib/tlcl_internal.h b/src/lib/tlcl_internal.h new file mode 100644 index 0000000..51fe6ef --- /dev/null +++ b/src/lib/tlcl_internal.h @@ -0,0 +1,61 @@ +/* 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. + */ + +#ifndef TPM_LITE_TLCL_INTERNAL_H_ +#define TPM_LITE_TLCL_INTERNAL_H_ + +/* + * These numbers derive from adding the sizes of command fields as shown in the + * TPM commands manual. + */ +#define kTpmRequestHeaderLength 10 +#define kTpmResponseHeaderLength 10 +#define kTpmReadInfoLength 12 +#define kEncAuthLength 20 +#define kPcrDigestLength 20 + + +/* + * Conversion functions. ToTpmTYPE puts a value of type TYPE into a TPM + * command buffer. FromTpmTYPE gets a value of type TYPE from a TPM command + * buffer into a variable. + */ +__attribute__((unused)) +static inline void ToTpmUint32(uint8_t *buffer, uint32_t x) { + buffer[0] = (uint8_t)(x >> 24); + buffer[1] = (uint8_t)((x >> 16) & 0xff); + buffer[2] = (uint8_t)((x >> 8) & 0xff); + buffer[3] = (uint8_t)(x & 0xff); +} + +/* + * See comment for above function. + */ +__attribute__((unused)) +static inline void FromTpmUint32(const uint8_t *buffer, uint32_t *x) { + *x = ((buffer[0] << 24) | + (buffer[1] << 16) | + (buffer[2] << 8) | + buffer[3]); +} + +/* + * See comment for above function. + */ +__attribute__((unused)) +static inline void ToTpmUint16(uint8_t *buffer, uint16_t x) { + buffer[0] = (uint8_t)(x >> 8); + buffer[1] = (uint8_t)(x & 0xff); +} + +/* + * See comment for above function. + */ +__attribute__((unused)) +static inline void FromTpmUint16(const uint8_t *buffer, uint16_t *x) { + *x = (buffer[0] << 8) | buffer[1]; +} + +#endif /* TPM_LITE_TLCL_INTERNAL_H_ */ diff --git a/src/lib/tlcl_structures.h b/src/lib/tlcl_structures.h new file mode 100644 index 0000000..36c1bb9 --- /dev/null +++ b/src/lib/tlcl_structures.h @@ -0,0 +1,138 @@ +/* This file is automatically generated */ + +const struct s_tpm_extend_cmd{ + uint8_t buffer[34]; + uint16_t pcrNum; + uint16_t inDigest; +} tpm_extend_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14, }, +10, 14, }; + +const struct s_tpm_get_random_cmd{ + uint8_t buffer[14]; + uint16_t bytesRequested; +} tpm_get_random_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x46, }, +10, }; + +const struct s_tpm_getownership_cmd{ + uint8_t buffer[22]; +} tpm_getownership_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x11, }, +}; + +const struct s_tpm_getpermissions_cmd{ + uint8_t buffer[22]; + uint16_t index; +} tpm_getpermissions_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x4, }, +18, }; + +const struct s_tpm_getstclearflags_cmd{ + uint8_t buffer[22]; +} tpm_getstclearflags_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x9, }, +}; + +const struct s_tpm_getflags_cmd{ + uint8_t buffer[22]; +} tpm_getflags_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x8, }, +}; + +const struct s_tpm_physicalsetdeactivated_cmd{ + uint8_t buffer[11]; + uint16_t deactivated; +} tpm_physicalsetdeactivated_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72, }, +10, }; + +const struct s_tpm_physicalenable_cmd{ + uint8_t buffer[10]; +} tpm_physicalenable_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f, }, +}; + +const struct s_tpm_physicaldisable_cmd{ + uint8_t buffer[10]; +} tpm_physicaldisable_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70, }, +}; + +const struct s_tpm_forceclear_cmd{ + uint8_t buffer[10]; +} tpm_forceclear_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d, }, +}; + +const struct s_tpm_readpubek_cmd{ + uint8_t buffer[30]; +} tpm_readpubek_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c, }, +}; + +const struct s_tpm_continueselftest_cmd{ + uint8_t buffer[10]; +} tpm_continueselftest_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53, }, +}; + +const struct s_tpm_selftestfull_cmd{ + uint8_t buffer[10]; +} tpm_selftestfull_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, }, +}; + +const struct s_tpm_resume_cmd{ + uint8_t buffer[12]; +} tpm_resume_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x2, }, +}; + +const struct s_tpm_savestate_cmd{ + uint8_t buffer[10]; +} tpm_savestate_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x98, }, +}; + +const struct s_tpm_startup_cmd{ + uint8_t buffer[12]; +} tpm_startup_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1, }, +}; + +const struct s_tpm_finalizepp_cmd{ + uint8_t buffer[12]; +} tpm_finalizepp_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0, }, +}; + +const struct s_tpm_pplock_cmd{ + uint8_t buffer[12]; +} tpm_pplock_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x4, }, +}; + +const struct s_tpm_ppenable_cmd{ + uint8_t buffer[12]; +} tpm_ppenable_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x20, }, +}; + +const struct s_tpm_ppassert_cmd{ + uint8_t buffer[12]; +} tpm_ppassert_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x8, }, +}; + +const struct s_tpm_pcr_read_cmd{ + uint8_t buffer[14]; + uint16_t pcrNum; +} tpm_pcr_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15, }, +10, }; + +const struct s_tpm_nv_read_cmd{ + uint8_t buffer[22]; + uint16_t index; + uint16_t length; +} tpm_nv_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf, }, +10, 18, }; + +const struct s_tpm_nv_write_cmd{ + uint8_t buffer[256]; + uint16_t index; + uint16_t length; + uint16_t data; +} tpm_nv_write_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, }, +10, 18, 22, }; + +const struct s_tpm_nv_definespace_cmd{ + uint8_t buffer[101]; + uint16_t index; + uint16_t perm; + uint16_t size; +} tpm_nv_definespace_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0xcc, 0x0, 0x18, 0, 0, 0, 0, 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x17, }, +12, 70, 77, }; + +const int kWriteInfoLength = 12; +const int kNvDataPublicPermissionsOffset = 60; diff --git a/src/lib/tpm_error_messages.h b/src/lib/tpm_error_messages.h new file mode 100644 index 0000000..14cb86b --- /dev/null +++ b/src/lib/tpm_error_messages.h @@ -0,0 +1,250 @@ +/* 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. + */ + +/* TPM error codes. + * + * Copy-pasted and lightly edited from TCG TPM Main Part 2 TPM Structures + * Version 1.2 Level 2 Revision 103 26 October 2006 Draft. + */ + +#ifndef TPM_ERROR_MESSAGES_H +#define TPM_ERROR_MESSAGES_H + +#define TPM_E_BASE 0x0 +#define TPM_E_NON_FATAL 0x800 + +typedef struct tpm_error_info { + const char* name; + uint32_t code; + const char* description; +} tpm_error_info; + +tpm_error_info tpm_error_table[] = { +{ "TPM_AUTHFAIL", TPM_E_BASE + 1, +"Authentication failed" }, +{ "TPM_BADINDEX", TPM_E_BASE + 2, +"The index to a PCR, DIR or other register is incorrect" }, +{ "TPM_BAD_PARAMETER", TPM_E_BASE + 3, +"One or more parameter is bad" }, +{ "TPM_AUDITFAILURE", TPM_E_BASE + 4, +"An operation completed successfully\n\ +but the auditing of that operation failed" }, +{ "TPM_CLEAR_DISABLED", TPM_E_BASE + 5, +"The clear disable flag is set and all clear operations now require\n\ +physical access" }, +{ "TPM_DEACTIVATED", TPM_E_BASE + 6, +"The TPM is deactivated" }, +{ "TPM_DISABLED", TPM_E_BASE + 7, +"The TPM is disabled" }, +{ "TPM_DISABLED_CMD", TPM_E_BASE + 8, +"The target command has been disabled" }, +{ "TPM_FAIL", TPM_E_BASE + 9, +"The operation failed" }, +{ "TPM_BAD_ORDINAL", TPM_E_BASE + 10, +"The ordinal was unknown or inconsistent" }, +{ "TPM_INSTALL_DISABLED", TPM_E_BASE + 11, +"The ability to install an owner is disabled" }, +{ "TPM_INVALID_KEYHANDLE", TPM_E_BASE + 12, +"The key handle can not be interpreted" }, +{ "TPM_KEYNOTFOUND", TPM_E_BASE + 13, +"The key handle points to an invalid key" }, +{ "TPM_INAPPROPRIATE_ENC", TPM_E_BASE + 14, +"Unacceptable encryption scheme" }, +{ "TPM_MIGRATEFAIL", TPM_E_BASE + 15, +"Migration authorization failed" }, +{ "TPM_INVALID_PCR_INFO", TPM_E_BASE + 16, +"PCR information could not be interpreted" }, +{ "TPM_NOSPACE", TPM_E_BASE + 17, +"No room to load key" }, +{ "TPM_NOSRK", TPM_E_BASE + 18, +"There is no SRK set" }, +{ "TPM_NOTSEALED_BLOB", TPM_E_BASE + 19, +"An encrypted blob is invalid or was not created by this TPM" }, +{ "TPM_OWNER_SET", TPM_E_BASE + 20, +"There is already an Owner" }, +{ "TPM_RESOURCES", TPM_E_BASE + 21, +"The TPM has insufficient internal resources to perform the requested action" }, +{ "TPM_SHORTRANDOM", TPM_E_BASE + 22, +"A random string was too short" }, +{ "TPM_SIZE", TPM_E_BASE + 23, +"The TPM does not have the space to perform the operation" }, +{ "TPM_WRONGPCRVAL", TPM_E_BASE + 24, +"The named PCR value does not match the current PCR value" }, +{ "TPM_BAD_PARAM_SIZE", TPM_E_BASE + 25, +"The paramSize argument to the command has the incorrect value" }, +{ "TPM_SHA_THREAD", TPM_E_BASE + 26, +"There is no existing SHA-1 thread" }, +{ "TPM_SHA_ERROR", TPM_E_BASE + 27, +"The calculation is unable to proceed because the existing SHA-1\n\ +thread has already encountered an error" }, +{ "TPM_FAILEDSELFTEST", TPM_E_BASE + 28, +"Self-test has failed and the TPM has shutdown" }, +{ "TPM_AUTH2FAIL", TPM_E_BASE + 29, +"The authorization for the second key in a 2 key function\n\ +failed authorization" }, +{ "TPM_BADTAG", TPM_E_BASE + 30, +"The tag value sent to for a command is invalid" }, +{ "TPM_IOERROR", TPM_E_BASE + 31, +"An IO error occurred transmitting information to the TPM" }, +{ "TPM_ENCRYPT_ERROR", TPM_E_BASE + 32, +"The encryption process had a problem" }, +{ "TPM_DECRYPT_ERROR", TPM_E_BASE + 33, +"The decryption process did not complete" }, +{ "TPM_INVALID_AUTHHANDLE", TPM_E_BASE + 34, +"An invalid handle was used" }, +{ "TPM_NO_ENDORSEMENT", TPM_E_BASE + 35, +"The TPM does not a EK installed" }, +{ "TPM_INVALID_KEYUSAGE", TPM_E_BASE + 36, +"The usage of a key is not allowed" }, +{ "TPM_WRONG_ENTITYTYPE", TPM_E_BASE + 37, +"The submitted entity type is not allowed" }, +{ "TPM_INVALID_POSTINIT", TPM_E_BASE + 38, +"The command was received in the wrong sequence relative to TPM_Init\n\ +and a subsequent TPM_Startup" }, +{ "TPM_INAPPROPRIATE_SIG", TPM_E_BASE + 39, +"Signed data cannot include additional DER information" }, +{ "TPM_BAD_KEY_PROPERTY", TPM_E_BASE + 40, +"The key properties in TPM_KEY_PARMs are not supported by this TPM" }, +{ "TPM_BAD_MIGRATION", TPM_E_BASE + 41, +"The migration properties of this key are incorrect" }, +{ "TPM_BAD_SCHEME", TPM_E_BASE + 42, +"The signature or encryption scheme for this key is incorrect or not\n\ +permitted in this situation" }, +{ "TPM_BAD_DATASIZE", TPM_E_BASE + 43, +"The size of the data (or blob) parameter is bad or inconsistent\n\ +with the referenced key" }, +{ "TPM_BAD_MODE", TPM_E_BASE + 44, +"A mode parameter is bad, such as capArea or subCapArea for\n\ +TPM_GetCapability, physicalPresence parameter for TPM_PhysicalPresence,\n\ +or migrationType for, TPM_CreateMigrationBlob" }, +{ "TPM_BAD_PRESENCE", TPM_E_BASE + 45, +"Either the physicalPresence or physicalPresenceLock bits\n\ +have the wrong value" }, +{ "TPM_BAD_VERSION", TPM_E_BASE + 46, +"The TPM cannot perform this version of the capability" }, +{ "TPM_NO_WRAP_TRANSPORT", TPM_E_BASE + 47, +"The TPM does not allow for wrapped transport sessions" }, +{ "TPM_AUDITFAIL_UNSUCCESSFUL", TPM_E_BASE + 48, +"TPM audit construction failed and the underlying command\n\ +was returning a failure code also" }, +{ "TPM_AUDITFAIL_SUCCESSFUL", TPM_E_BASE + 49, +"TPM audit construction failed and the underlying command\n\ +was returning success" }, +{ "TPM_NOTRESETABLE", TPM_E_BASE + 50, +"Attempt to reset a PCR register that does not have the resettable attribute" }, +{ "TPM_NOTLOCAL", TPM_E_BASE + 51, +"Attempt to reset a PCR register that requires locality\n\ +and locality modifier not part of command transport" }, +{ "TPM_BAD_TYPE", TPM_E_BASE + 52, +"Make identity blob not properly typed" }, +{ "TPM_INVALID_RESOURCE", TPM_E_BASE + 53, +"When saving context identified resource type does not match actual resource" }, +{ "TPM_NOTFIPS", TPM_E_BASE + 54, +"The TPM is attempting to execute a command only available when in FIPS mode" }, +{ "TPM_INVALID_FAMILY", TPM_E_BASE + 55, +"The command is attempting to use an invalid family ID" }, +{ "TPM_NO_NV_PERMISSION", TPM_E_BASE + 56, +"The permission to manipulate the NV storage is not available" }, +{ "TPM_REQUIRES_SIGN", TPM_E_BASE + 57, +"The operation requires a signed command" }, +{ "TPM_KEY_NOTSUPPORTED", TPM_E_BASE + 58, +"Wrong operation to load an NV key" }, +{ "TPM_AUTH_CONFLICT", TPM_E_BASE + 59, +"NV_LoadKey blob requires both owner and blob authorization" }, +{ "TPM_AREA_LOCKED", TPM_E_BASE + 60, +"The NV area is locked and not writable" }, +{ "TPM_BAD_LOCALITY", TPM_E_BASE + 61, +"The locality is incorrect for the attempted operation" }, +{ "TPM_READ_ONLY", TPM_E_BASE + 62, +"The NV area is read only and canĂ¢t be written to" }, +{ "TPM_PER_NOWRITE", TPM_E_BASE + 63, +"There is no protection on the write to the NV area" }, +{ "TPM_FAMILYCOUNT", TPM_E_BASE + 64, +"The family count value does not match" }, +{ "TPM_WRITE_LOCKED", TPM_E_BASE + 65, +"The NV area has already been written to" }, +{ "TPM_BAD_ATTRIBUTES", TPM_E_BASE + 66, +"The NV area attributes conflict" }, +{ "TPM_INVALID_STRUCTURE", TPM_E_BASE + 67, +"The structure tag and version are invalid or inconsistent" }, +{ "TPM_KEY_OWNER_CONTROL", TPM_E_BASE + 68, +"The key is under control of the TPM Owner and can only be evicted\n\ +by the TPM Owner" }, +{ "TPM_BAD_COUNTER", TPM_E_BASE + 69, +"The counter handle is incorrect" }, +{ "TPM_NOT_FULLWRITE", TPM_E_BASE + 70, +"The write is not a complete write of the area" }, +{ "TPM_CONTEXT_GAP", TPM_E_BASE + 71, +"The gap between saved context counts is too large" }, +{ "TPM_MAXNVWRITES", TPM_E_BASE + 72, +"The maximum number of NV writes without an owner has been exceeded" }, +{ "TPM_NOOPERATOR", TPM_E_BASE + 73, +"No operator AuthData value is set" }, +{ "TPM_RESOURCEMISSING", TPM_E_BASE + 74, +"The resource pointed to by context is not loaded" }, +{ "TPM_DELEGATE_LOCK", TPM_E_BASE + 75, +"The delegate administration is locked" }, +{ "TPM_DELEGATE_FAMILY", TPM_E_BASE + 76, +"Attempt to manage a family other then the delegated family" }, +{ "TPM_DELEGATE_ADMIN", TPM_E_BASE + 77, +"Delegation table management not enabled" }, +{ "TPM_TRANSPORT_NOTEXCLUSIVE", TPM_E_BASE + 78, +"There was a command executed outside of an exclusive transport session" }, +{ "TPM_OWNER_CONTROL", TPM_E_BASE + 79, +"Attempt to context save a owner evict controlled key" }, +{ "TPM_DAA_RESOURCES", TPM_E_BASE + 80, +"The DAA command has no resources available to execute the command" }, +{ "TPM_DAA_INPUT_DATA0", TPM_E_BASE + 81, +"The consistency check on DAA parameter inputData0 has failed" }, +{ "TPM_DAA_INPUT_DATA1", TPM_E_BASE + 82, +"The consistency check on DAA parameter inputData1 has failed" }, +{ "TPM_DAA_ISSUER_SETTINGS", TPM_E_BASE + 83, +"The consistency check on DAA_issuerSettings has failed" }, +{ "TPM_DAA_TPM_SETTINGS", TPM_E_BASE + 84, +"The consistency check on DAA_tpmSpecific has failed" }, +{ "TPM_DAA_STAGE", TPM_E_BASE + 85, +"The atomic process indicated by the submitted DAA command is not\n\ +the expected process" }, +{ "TPM_DAA_ISSUER_VALIDITY", TPM_E_BASE + 86, +"The issuerĂ¢s validity check has detected an inconsistency" }, +{ "TPM_DAA_WRONG_W", TPM_E_BASE + 87, +"The consistency check on w has failed" }, +{ "TPM_BAD_HANDLE", TPM_E_BASE + 88, +"The handle is incorrect" }, +{ "TPM_BAD_DELEGATE", TPM_E_BASE + 89, +"Delegation is not correct" }, +{ "TPM_BADCONTEXT", TPM_E_BASE + 90, +"The context blob is invalid" }, +{ "TPM_TOOMANYCONTEXTS", TPM_E_BASE + 91, +"Too many contexts held by the TPM" }, +{ "TPM_MA_TICKET_SIGNATURE", TPM_E_BASE + 92, +"Migration authority signature validation failure" }, +{ "TPM_MA_DESTINATION", TPM_E_BASE + 93, +"Migration destination not authenticated" }, +{ "TPM_MA_SOURCE", TPM_E_BASE + 94, +"Migration source incorrect" }, +{ "TPM_MA_AUTHORITY", TPM_E_BASE + 95, +"Incorrect migration authority" }, +{ "TPM_PERMANENTEK", TPM_E_BASE + 97, +"Attempt to revoke the EK and the EK is not revocable" }, +{ "TPM_BAD_SIGNATURE", TPM_E_BASE + 98, +"Bad signature of CMK ticket" }, +{ "TPM_NOCONTEXTSPACE", TPM_E_BASE + 99, +"There is no room in the context list for additional contexts" }, +{ "TPM_RETRY", TPM_E_BASE + TPM_E_NON_FATAL, +"The TPM is too busy to respond to the command immediately, but\n\ +the command could be resubmitted at a later time. The TPM MAY\n\ +return TPM_RETRY for any command at any time" }, +{ "TPM_NEEDS_SELFTEST", TPM_E_BASE + TPM_E_NON_FATAL + 1, +"TPM_ContinueSelfTest has not been run" }, +{ "TPM_DOING_SELFTEST", TPM_E_BASE + TPM_E_NON_FATAL + 2, +"The TPM is currently executing the actions of TPM_ContinueSelfTest\n\ +because the ordinal required resources that have not been tested" }, +{ "TPM_DEFEND_LOCK_RUNNING", TPM_E_BASE + TPM_E_NON_FATAL + 3, +"The TPM is defending against dictionary attacks and is in some\n\ +time-out period" }, + }; + +#endif /* TPM_ERROR_MESSAGES_H */ diff --git a/src/vendorcode/google/chromeos/antirollback.c b/src/vendorcode/google/chromeos/antirollback.c new file mode 100644 index 0000000..306e903 --- /dev/null +++ b/src/vendorcode/google/chromeos/antirollback.c @@ -0,0 +1,676 @@ +/* Copyright (c) 2013 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. + * + * Functions for querying, manipulating and locking rollback indices + * stored in the TPM NVRAM. + */ + +#include "sysincludes.h" + +#include "crc8.h" +#include "rollback_index.h" +#include "tlcl.h" +#include "tss_constants.h" +#include "utility.h" +#include "vboot_api.h" + +#ifndef offsetof +#define offsetof(A,B) __builtin_offsetof(A,B) +#endif + +/* + * Provide protoypes for functions not in the header file. These prototypes + * fix -Wmissing-prototypes warnings. + */ +uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf); +uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf); +uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk); +uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk); + +#ifdef FOR_TEST +/* + * Compiling for unit test, so we need the real implementations of + * rollback functions. The unit test mocks the underlying tlcl + * functions, so this is ok to run on the host. + */ +#undef CHROMEOS_ENVIRONMENT +#undef DISABLE_ROLLBACK_TPM +#endif + +#define RETURN_ON_FAILURE(tpm_command) do { \ + uint32_t result_; \ + if ((result_ = (tpm_command)) != TPM_SUCCESS) { \ + VBDEBUG(("Rollback: %08x returned by " #tpm_command \ + "\n", (int)result_)); \ + return result_; \ + } \ + } while (0) + + +uint32_t TPMClearAndReenable(void) +{ + VBDEBUG(("TPM: Clear and re-enable\n")); + RETURN_ON_FAILURE(TlclForceClear()); + RETURN_ON_FAILURE(TlclSetEnable()); + RETURN_ON_FAILURE(TlclSetDeactivated(0)); + + return TPM_SUCCESS; +} + +uint32_t SafeWrite(uint32_t index, const void *data, uint32_t length) +{ + uint32_t result = TlclWrite(index, data, length); + if (result == TPM_E_MAXNVWRITES) { + RETURN_ON_FAILURE(TPMClearAndReenable()); + return TlclWrite(index, data, length); + } else { + return result; + } +} + +uint32_t SafeDefineSpace(uint32_t index, uint32_t perm, uint32_t size) +{ + uint32_t result = TlclDefineSpace(index, perm, size); + if (result == TPM_E_MAXNVWRITES) { + RETURN_ON_FAILURE(TPMClearAndReenable()); + return TlclDefineSpace(index, perm, size); + } else { + return result; + } +} + +/* Functions to read and write firmware and kernel spaces. */ +uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf) +{ + uint32_t r; + int attempts = 3; + + while (attempts--) { + r = TlclRead(FIRMWARE_NV_INDEX, rsf, + sizeof(RollbackSpaceFirmware)); + if (r != TPM_SUCCESS) + return r; + + /* + * No CRC in this version, so we'll create one when we write + * it. Note that we're marking this as version 2, not + * ROLLBACK_SPACE_FIRMWARE_VERSION, because version 2 just + * added the CRC. Later versions will need to set default + * values for any extra fields explicitly (probably here). + */ + if (rsf->struct_version < 2) { + /* Danger Will Robinson! Danger! */ + rsf->struct_version = 2; + return TPM_SUCCESS; + } + + /* + * If the CRC is good, we're done. If it's bad, try a couple + * more times to see if it gets better before we give up. It + * could just be noise. + */ + if (rsf->crc8 == Crc8(rsf, + offsetof(RollbackSpaceFirmware, crc8))) + return TPM_SUCCESS; + + VBDEBUG(("TPM: %s() - bad CRC\n", __func__)); + } + + VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__)); + return TPM_E_CORRUPTED_STATE; +} + +uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf) +{ + RollbackSpaceFirmware rsf2; + uint32_t r; + int attempts = 3; + + /* All writes should use struct_version 2 or greater. */ + if (rsf->struct_version < 2) + rsf->struct_version = 2; + rsf->crc8 = Crc8(rsf, offsetof(RollbackSpaceFirmware, crc8)); + + while (attempts--) { + r = SafeWrite(FIRMWARE_NV_INDEX, rsf, + sizeof(RollbackSpaceFirmware)); + /* Can't write, not gonna try again */ + if (r != TPM_SUCCESS) + return r; + + /* Read it back to be sure it got the right values. */ + r = ReadSpaceFirmware(&rsf2); /* This checks the CRC */ + if (r == TPM_SUCCESS) + return r; + + VBDEBUG(("TPM: %s() - bad CRC\n", __func__)); + /* Try writing it again. Maybe it was garbled on the way out. */ + } + + VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__)); + return TPM_E_CORRUPTED_STATE; +} + +uint32_t SetVirtualDevMode(int val) +{ + RollbackSpaceFirmware rsf; + + VBDEBUG(("TPM: Entering %s()\n", __func__)); + if (TPM_SUCCESS != ReadSpaceFirmware(&rsf)) + return VBERROR_TPM_FIRMWARE_SETUP; + + VBDEBUG(("TPM: flags were 0x%02x\n", rsf.flags)); + if (val) + rsf.flags |= FLAG_VIRTUAL_DEV_MODE_ON; + else + rsf.flags &= ~FLAG_VIRTUAL_DEV_MODE_ON; + /* + * NOTE: This doesn't update the FLAG_LAST_BOOT_DEVELOPER bit. That + * will be done by SetupTPM() on the next boot. + */ + VBDEBUG(("TPM: flags are now 0x%02x\n", rsf.flags)); + + if (TPM_SUCCESS != WriteSpaceFirmware(&rsf)) + return VBERROR_TPM_SET_BOOT_MODE_STATE; + + VBDEBUG(("TPM: Leaving %s()\n", __func__)); + return VBERROR_SUCCESS; +} + +uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk) +{ + uint32_t r; + int attempts = 3; + + while (attempts--) { + r = TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel)); + if (r != TPM_SUCCESS) + return r; + + /* + * No CRC in this version, so we'll create one when we write + * it. Note that we're marking this as version 2, not + * ROLLBACK_SPACE_KERNEL_VERSION, because version 2 just added + * the CRC. Later versions will need to set default values for + * any extra fields explicitly (probably here). + */ + if (rsk->struct_version < 2) { + /* Danger Will Robinson! Danger! */ + rsk->struct_version = 2; + return TPM_SUCCESS; + } + + /* + * If the CRC is good, we're done. If it's bad, try a couple + * more times to see if it gets better before we give up. It + * could just be noise. + */ + if (rsk->crc8 == Crc8(rsk, offsetof(RollbackSpaceKernel, crc8))) + return TPM_SUCCESS; + + VBDEBUG(("TPM: %s() - bad CRC\n", __func__)); + } + + VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__)); + return TPM_E_CORRUPTED_STATE; +} + +uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk) +{ + RollbackSpaceKernel rsk2; + uint32_t r; + int attempts = 3; + + /* All writes should use struct_version 2 or greater. */ + if (rsk->struct_version < 2) + rsk->struct_version = 2; + rsk->crc8 = Crc8(rsk, offsetof(RollbackSpaceKernel, crc8)); + + while (attempts--) { + r = SafeWrite(KERNEL_NV_INDEX, rsk, + sizeof(RollbackSpaceKernel)); + /* Can't write, not gonna try again */ + if (r != TPM_SUCCESS) + return r; + + /* Read it back to be sure it got the right values. */ + r = ReadSpaceKernel(&rsk2); /* This checks the CRC */ + if (r == TPM_SUCCESS) + return r; + + VBDEBUG(("TPM: %s() - bad CRC\n", __func__)); + /* Try writing it again. Maybe it was garbled on the way out. */ + } + + VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__)); + return TPM_E_CORRUPTED_STATE; +} + +uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf, + RollbackSpaceKernel *rsk) +{ + static const RollbackSpaceFirmware rsf_init = { + .struct_version = ROLLBACK_SPACE_FIRMWARE_VERSION, + }; + static const RollbackSpaceKernel rsk_init = { + .struct_version = ROLLBACK_SPACE_KERNEL_VERSION, + .uid = ROLLBACK_SPACE_KERNEL_UID, + }; + TPM_PERMANENT_FLAGS pflags; + uint32_t result; + + VBDEBUG(("TPM: One-time initialization\n")); + + /* + * Do a full test. This only happens the first time the device is + * turned on in the factory, so performance is not an issue. This is + * almost certainly not necessary, but it gives us more confidence + * about some code paths below that are difficult to + * test---specifically the ones that set lifetime flags, and are only + * executed once per physical TPM. + */ + result = TlclSelfTestFull(); + if (result != TPM_SUCCESS) + return result; + + result = TlclGetPermanentFlags(&pflags); + if (result != TPM_SUCCESS) + return result; + + /* + * TPM may come from the factory without physical presence finalized. + * Fix if necessary. + */ + VBDEBUG(("TPM: physicalPresenceLifetimeLock=%d\n", + pflags.physicalPresenceLifetimeLock)); + if (!pflags.physicalPresenceLifetimeLock) { + VBDEBUG(("TPM: Finalizing physical presence\n")); + RETURN_ON_FAILURE(TlclFinalizePhysicalPresence()); + } + + /* + * The TPM will not enforce the NV authorization restrictions until the + * execution of a TPM_NV_DefineSpace with the handle of + * TPM_NV_INDEX_LOCK. Here we create that space if it doesn't already + * exist. */ + VBDEBUG(("TPM: nvLocked=%d\n", pflags.nvLocked)); + if (!pflags.nvLocked) { + VBDEBUG(("TPM: Enabling NV locking\n")); + RETURN_ON_FAILURE(TlclSetNvLocked()); + } + + /* Clear TPM owner, in case the TPM is already owned for some reason. */ + VBDEBUG(("TPM: Clearing owner\n")); + RETURN_ON_FAILURE(TPMClearAndReenable()); + + /* Initializes the firmware and kernel spaces */ + Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware)); + Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel)); + + /* Define the backup space. No need to initialize it, though. */ + RETURN_ON_FAILURE(SafeDefineSpace( + BACKUP_NV_INDEX, TPM_NV_PER_PPWRITE, BACKUP_NV_SIZE)); + + /* Define and initialize the kernel space */ + RETURN_ON_FAILURE(SafeDefineSpace(KERNEL_NV_INDEX, TPM_NV_PER_PPWRITE, + sizeof(RollbackSpaceKernel))); + RETURN_ON_FAILURE(WriteSpaceKernel(rsk)); + + /* Do the firmware space last, so we retry if we don't get this far. */ + RETURN_ON_FAILURE(SafeDefineSpace( + FIRMWARE_NV_INDEX, + TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE, + sizeof(RollbackSpaceFirmware))); + RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); + + return TPM_SUCCESS; +} + + +/* + * SetupTPM starts the TPM and establishes the root of trust for the + * anti-rollback mechanism. SetupTPM can fail for three reasons. 1 A bug. 2 a + * TPM hardware failure. 3 An unexpected TPM state due to some attack. In + * general we cannot easily distinguish the kind of failure, so our strategy is + * to reboot in recovery mode in all cases. The recovery mode calls SetupTPM + * again, which executes (almost) the same sequence of operations. There is a + * good chance that, if recovery mode was entered because of a TPM failure, the + * failure will repeat itself. (In general this is impossible to guarantee + * because we have no way of creating the exact TPM initial state at the + * previous boot.) In recovery mode, we ignore the failure and continue, thus + * giving the recovery kernel a chance to fix things (that's why we don't set + * bGlobalLock). The choice is between a knowingly insecure device and a + * bricked device. + * + * As a side note, observe that we go through considerable hoops to avoid using + * the STCLEAR permissions for the index spaces. We do this to avoid writing + * to the TPM flashram at every reboot or wake-up, because of concerns about + * the durability of the NVRAM. + */ +uint32_t SetupTPM(int developer_mode, int disable_dev_request, + int clear_tpm_owner_request, RollbackSpaceFirmware* rsf) +{ + uint8_t in_flags; + uint8_t disable; + uint8_t deactivated; + uint32_t result; + uint32_t versions; + + RETURN_ON_FAILURE(TlclLibInit()); + +#ifdef TEGRA_SOFT_REBOOT_WORKAROUND + result = TlclStartup(); + if (result == TPM_E_INVALID_POSTINIT) { + /* + * Some prototype hardware doesn't reset the TPM on a CPU + * reset. We do a hard reset to get around this. + */ + VBDEBUG(("TPM: soft reset detected\n", result)); + return TPM_E_MUST_REBOOT; + } else if (result != TPM_SUCCESS) { + VBDEBUG(("TPM: TlclStartup returned %08x\n", result)); + return result; + } +#else + RETURN_ON_FAILURE(TlclStartup()); +#endif + + /* + * Some TPMs start the self test automatically at power on. In that case we + * don't need to call ContinueSelfTest. On some (other) TPMs, + * ContinueSelfTest may block. In that case, we definitely don't want to + * call it here. For TPMs in the intersection of these two sets, we're + * screwed. (In other words: TPMs that require manually starting the + * self-test AND block will have poor performance until we split + * TlclSendReceive() into Send() and Receive(), and have a state machine to + * control setup.) + * + * This comment is likely to become obsolete in the near future, so don't + * trust it. It may have not been updated. + */ +#ifdef TPM_MANUAL_SELFTEST +#ifdef TPM_BLOCKING_CONTINUESELFTEST +#warning "lousy TPM!" +#endif + RETURN_ON_FAILURE(TlclContinueSelfTest()); +#endif + result = TlclAssertPhysicalPresence(); + if (result != TPM_SUCCESS) { + /* + * It is possible that the TPM was delivered with the physical + * presence command disabled. This tries enabling it, then + * tries asserting PP again. + */ + RETURN_ON_FAILURE(TlclPhysicalPresenceCMDEnable()); + RETURN_ON_FAILURE(TlclAssertPhysicalPresence()); + } + + /* Check that the TPM is enabled and activated. */ + RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated, NULL)); + if (disable || deactivated) { + VBDEBUG(("TPM: disabled (%d) or deactivated (%d). Fixing...\n", + disable, deactivated)); + RETURN_ON_FAILURE(TlclSetEnable()); + RETURN_ON_FAILURE(TlclSetDeactivated(0)); + VBDEBUG(("TPM: Must reboot to re-enable\n")); + return TPM_E_MUST_REBOOT; + } + + /* Read the firmware space. */ + result = ReadSpaceFirmware(rsf); + if (TPM_E_BADINDEX == result) { + RollbackSpaceKernel rsk; + + /* + * This is the first time we've run, and the TPM has not been + * initialized. Initialize it. + */ + VBDEBUG(("TPM: Not initialized yet.\n")); + RETURN_ON_FAILURE(OneTimeInitializeTPM(rsf, &rsk)); + } else if (TPM_SUCCESS != result) { + VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n")); + return TPM_E_CORRUPTED_STATE; + } + Memcpy(&versions, &rsf->fw_versions, sizeof(versions)); + VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n", + rsf->struct_version, rsf->flags, versions)); + in_flags = rsf->flags; + + /* If we've been asked to clear the virtual dev-mode flag, do so now */ + if (disable_dev_request) { + rsf->flags &= ~FLAG_VIRTUAL_DEV_MODE_ON; + VBDEBUG(("TPM: Clearing virt dev-switch: f%x\n", rsf->flags)); + } + + /* + * The developer_mode value that's passed in is only set by a hardware + * dev-switch. We should OR it with the virtual switch, whether or not + * the virtual switch is used. If it's not used, it shouldn't change, + * so it doesn't matter. + */ + if (rsf->flags & FLAG_VIRTUAL_DEV_MODE_ON) + developer_mode = 1; + + /* + * Clear ownership if developer flag has toggled, or if an owner-clear + * has been requested. + */ + if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) != + (in_flags & FLAG_LAST_BOOT_DEVELOPER)) { + VBDEBUG(("TPM: Developer flag changed; clearing owner.\n")); + RETURN_ON_FAILURE(TPMClearAndReenable()); + } else if (clear_tpm_owner_request) { + VBDEBUG(("TPM: Clearing owner as specifically requested.\n")); + RETURN_ON_FAILURE(TPMClearAndReenable()); + } + + if (developer_mode) + rsf->flags |= FLAG_LAST_BOOT_DEVELOPER; + else + rsf->flags &= ~FLAG_LAST_BOOT_DEVELOPER; + + + /* If firmware space is dirty, flush it back to the TPM */ + if (rsf->flags != in_flags) { + VBDEBUG(("TPM: Updating firmware space.\n")); + RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); + } + + VBDEBUG(("TPM: SetupTPM() succeeded\n")); + return TPM_SUCCESS; +} + + +#ifdef DISABLE_ROLLBACK_TPM +/* Dummy implementations which don't support TPM rollback protection */ + +uint32_t RollbackS3Resume(void) +{ +#ifndef CHROMEOS_ENVIRONMENT + /* + * Initialize the TPM, but ignore return codes. In ChromeOS + * environment, don't even talk to the TPM. + */ + TlclLibInit(); + TlclResume(); +#endif + return TPM_SUCCESS; +} + +uint32_t RollbackFirmwareSetup(int is_hw_dev, + int disable_dev_request, + int clear_tpm_owner_request, + int *is_virt_dev, uint32_t *version) +{ +#ifndef CHROMEOS_ENVIRONMENT + /* + * Initialize the TPM, but ignores return codes. In ChromeOS + * environment, don't even talk to the TPM. + */ + TlclLibInit(); + TlclStartup(); + TlclContinueSelfTest(); +#endif + *is_virt_dev = 0; + *version = 0; + return TPM_SUCCESS; +} + +uint32_t RollbackFirmwareWrite(uint32_t version) +{ + return TPM_SUCCESS; +} + +uint32_t RollbackFirmwareLock(void) +{ + return TPM_SUCCESS; +} + +uint32_t RollbackKernelRead(uint32_t* version) +{ + *version = 0; + return TPM_SUCCESS; +} + +uint32_t RollbackKernelWrite(uint32_t version) +{ + return TPM_SUCCESS; +} + +uint32_t RollbackBackupRead(uint8_t *raw) +{ + return TPM_SUCCESS; +} + +uint32_t RollbackBackupWrite(uint8_t *raw) +{ + return TPM_SUCCESS; +} + +uint32_t RollbackKernelLock(int recovery_mode) +{ + return TPM_SUCCESS; +} + +#else + +uint32_t RollbackS3Resume(void) +{ + uint32_t result; + RETURN_ON_FAILURE(TlclLibInit()); + result = TlclResume(); + if (result == TPM_E_INVALID_POSTINIT) { + /* + * We're on a platform where the TPM maintains power in S3, so + * it's already initialized. + */ + return TPM_SUCCESS; + } + return result; +} + +uint32_t RollbackFirmwareSetup(int is_hw_dev, + int disable_dev_request, + int clear_tpm_owner_request, + int *is_virt_dev, uint32_t *version) +{ + RollbackSpaceFirmware rsf; + + /* Set version to 0 in case we fail */ + *version = 0; + + RETURN_ON_FAILURE(SetupTPM(is_hw_dev, disable_dev_request, + clear_tpm_owner_request, &rsf)); + Memcpy(version, &rsf.fw_versions, sizeof(*version)); + *is_virt_dev = (rsf.flags & FLAG_VIRTUAL_DEV_MODE_ON) ? 1 : 0; + VBDEBUG(("TPM: RollbackFirmwareSetup %x\n", (int)*version)); + return TPM_SUCCESS; +} + +uint32_t RollbackFirmwareWrite(uint32_t version) +{ + RollbackSpaceFirmware rsf; + uint32_t old_version; + + RETURN_ON_FAILURE(ReadSpaceFirmware(&rsf)); + Memcpy(&old_version, &rsf.fw_versions, sizeof(old_version)); + VBDEBUG(("TPM: RollbackFirmwareWrite %x --> %x\n", (int)old_version, + (int)version)); + Memcpy(&rsf.fw_versions, &version, sizeof(version)); + return WriteSpaceFirmware(&rsf); +} + +uint32_t RollbackFirmwareLock(void) +{ + return TlclSetGlobalLock(); +} + +uint32_t RollbackKernelRead(uint32_t* version) +{ + RollbackSpaceKernel rsk; + uint32_t perms, uid; + + /* + * Read the kernel space and verify its permissions. If the kernel + * space has the wrong permission, or it doesn't contain the right + * identifier, we give up. This will need to be fixed by the + * recovery kernel. We have to worry about this because at any time + * (even with PP turned off) the TPM owner can remove and redefine a + * PP-protected space (but not write to it). + */ + RETURN_ON_FAILURE(ReadSpaceKernel(&rsk)); + RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_NV_INDEX, &perms)); + Memcpy(&uid, &rsk.uid, sizeof(uid)); + if (TPM_NV_PER_PPWRITE != perms || ROLLBACK_SPACE_KERNEL_UID != uid) + return TPM_E_CORRUPTED_STATE; + + Memcpy(version, &rsk.kernel_versions, sizeof(*version)); + VBDEBUG(("TPM: RollbackKernelRead %x\n", (int)*version)); + return TPM_SUCCESS; +} + +uint32_t RollbackKernelWrite(uint32_t version) +{ + RollbackSpaceKernel rsk; + uint32_t old_version; + RETURN_ON_FAILURE(ReadSpaceKernel(&rsk)); + Memcpy(&old_version, &rsk.kernel_versions, sizeof(old_version)); + VBDEBUG(("TPM: RollbackKernelWrite %x --> %x\n", + (int)old_version, (int)version)); + Memcpy(&rsk.kernel_versions, &version, sizeof(version)); + return WriteSpaceKernel(&rsk); +} + +/* + * We don't really care whether the TPM owner has been messing with this or + * not. We lock it along with the Kernel space just to avoid problems, but it's + * only useful in dev-mode and only when the battery has been drained + * completely. There aren't any security issues. It's just in the TPM because + * we don't have any other place to keep it. + */ +uint32_t RollbackBackupRead(uint8_t *raw) +{ + uint32_t r; + r = TlclRead(BACKUP_NV_INDEX, raw, BACKUP_NV_SIZE); + VBDEBUG(("TPM: %s returning 0x%x\n", __func__, r)); + return r; +} + +uint32_t RollbackBackupWrite(uint8_t *raw) +{ + uint32_t r; + r = TlclWrite(BACKUP_NV_INDEX, raw, BACKUP_NV_SIZE); + VBDEBUG(("TPM: %s returning 0x%x\n", __func__, r)); + return r; +} + +uint32_t RollbackKernelLock(int recovery_mode) +{ + if (recovery_mode) + return TPM_SUCCESS; + else + return TlclLockPhysicalPresence(); +} + +#endif /* DISABLE_ROLLBACK_TPM */
1
0
0
0
Patch set updated for coreboot: e258718 vboot_wrapper: handling VBERROR_TPM_REBOOT_REQUIRED from VbInit().
by Marc Jones
13 Jan '15
13 Jan '15
Marc Jones (marc.jones(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/8163
-gerrit commit e2587183e5cd197cada84159935a44f56ddf4176 Author: Kevin Cheng <kevin.cheng(a)intel.com> Date: Mon Jun 30 17:51:48 2014 -0700 vboot_wrapper: handling VBERROR_TPM_REBOOT_REQUIRED from VbInit(). Doing reset while VBERROR_TPM_REBOOT_REQUIRED occured. BUG=chromium:389568 TEST=Manual force VBERROR_TPM_REBOOT_REQUIRED returned from VbInit() and system will reboot. Original-Change-Id: I9d7c4b3a380a931a728f792b4013b3b9bf65dfae Original-Signed-off-by: Kevin Cheng <kevin.cheng(a)intel.com> Original-Reviewed-on:
https://chromium-review.googlesource.com/206337
Original-Reviewed-by: Randall Spangler <rspangler(a)chromium.org> (cherry picked from commit 32728dd9fc43a95d6f763a85f9cc7a660a66b175) Original-Reviewed-on:
https://chromium-review.googlesource.com/206948
Original-Reviewed-by: Shawn Nematbakhsh <shawnn(a)chromium.org> (cherry picked from commit 1ea5e233386d236ce20f3d1695fac3a1bc49d4bd) Signed-off-by: Marc Jones <marc.jones(a)se-eng.com> Change-Id: Ib93fdf7b22918f563d3e29207a75fc831bee186a --- src/vendorcode/google/chromeos/vboot_context.h | 1 + src/vendorcode/google/chromeos/vboot_loader.c | 6 ++++++ src/vendorcode/google/chromeos/vboot_wrapper.c | 7 ++++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/vendorcode/google/chromeos/vboot_context.h b/src/vendorcode/google/chromeos/vboot_context.h index 822fed4..cd82aac 100644 --- a/src/vendorcode/google/chromeos/vboot_context.h +++ b/src/vendorcode/google/chromeos/vboot_context.h @@ -57,6 +57,7 @@ struct vboot_context { void (*log_msg)(const char *fmt, va_list args); void (*fatal_error)(void); void *(*get_region)(uintptr_t offset_addr, size_t size, void *dest); + void (*reset)(void); }; #endif /* VBOOT_CONTEXT_H */ diff --git a/src/vendorcode/google/chromeos/vboot_loader.c b/src/vendorcode/google/chromeos/vboot_loader.c index 80e2aea..daf5260 100644 --- a/src/vendorcode/google/chromeos/vboot_loader.c +++ b/src/vendorcode/google/chromeos/vboot_loader.c @@ -229,6 +229,11 @@ static void vboot_clean_up(struct vboot_context *context) cbmem_entry_remove(context->vblocks); } +static void reset(void) +{ + hard_reset(); +} + static void vboot_invoke_wrapper(struct vboot_handoff *vboot_handoff) { VbCommonParams cparams; @@ -298,6 +303,7 @@ static void vboot_invoke_wrapper(struct vboot_handoff *vboot_handoff) context.log_msg = &log_msg; context.fatal_error = &fatal_error; context.get_region = &vboot_get_region; + context.reset = &reset; vboot_run_stub(&context); diff --git a/src/vendorcode/google/chromeos/vboot_wrapper.c b/src/vendorcode/google/chromeos/vboot_wrapper.c index 5aa0066..dd6065c 100644 --- a/src/vendorcode/google/chromeos/vboot_wrapper.c +++ b/src/vendorcode/google/chromeos/vboot_wrapper.c @@ -43,8 +43,13 @@ static void vboot_wrapper(void *arg) res = VbInit(context->cparams, &context->handoff->init_params); VbExDebug("VbInit() returned 0x%08x\n", res); - if (res != VBERROR_SUCCESS) + if (res != VBERROR_SUCCESS) { + if(res == VBERROR_TPM_REBOOT_REQUIRED) { + VbExDebug("TPM Reboot Required. Proceeding reboot.\n"); + gcontext->reset(); + } return; + } VbExDebug("Calling VbSelectFirmware()\n"); res = VbSelectFirmware(context->cparams, context->fparams);
1
0
0
0
Patch set updated for coreboot: f4b73c2 vboot2: read dev and recovery switch
by Marc Jones
13 Jan '15
13 Jan '15
Marc Jones (marc.jones(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/8162
-gerrit commit f4b73c2b3e22ae57d5ac4f311ff00ddade8022aa Author: Daisuke Nojiri <dnojiri(a)chromium.org> Date: Mon Jun 30 09:56:32 2014 -0700 vboot2: read dev and recovery switch TEST=Built with VBOOT2_VERIFY_FIRMWARE on/off. Booted Nyan Blaze. BUG=none Branch=none Signed-off-by: Daisuke Nojiri <dnojiri(a)chromium.org> Original-Change-Id: Ia5353018a0db3dae2e0432b7e6a34d46f81b0ffa Original-Reviewed-on:
https://chromium-review.googlesource.com/206064
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org> Original-Tested-by: Daisuke Nojiri <dnojiri(a)chromium.org> Original-Commit-Queue: Daisuke Nojiri <dnojiri(a)chromium.org> (cherry picked from commit b420451c71c86bc27784d920f53870ee56ddc0f2) Signed-off-by: Marc Jones <marc.jones(a)se-eng.com> Change-Id: I30c9f0ac44de0a5816b5b8d0ded2dc7d7e77c7a1 --- src/ec/google/chromeec/Makefile.inc | 7 +++++++ src/mainboard/google/nyan_blaze/Makefile.inc | 1 + src/vendorcode/google/chromeos/vboot_main.c | 12 ++++++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/ec/google/chromeec/Makefile.inc b/src/ec/google/chromeec/Makefile.inc index 541bb13..0df6e8b 100644 --- a/src/ec/google/chromeec/Makefile.inc +++ b/src/ec/google/chromeec/Makefile.inc @@ -10,3 +10,10 @@ romstage-y += ec.c crosec_proto.c romstage-$(CONFIG_EC_GOOGLE_CHROMEEC_I2C) += ec_i2c.c romstage-$(CONFIG_EC_GOOGLE_CHROMEEC_LPC) += ec_lpc.c romstage-$(CONFIG_EC_GOOGLE_CHROMEEC_SPI) += ec_spi.c +ifeq ($(CONFIG_VBOOT2_VERIFY_FIRMWARE),y) +verstage-y += ec.c crosec_proto.c +verstage-$(CONFIG_EC_GOOGLE_CHROMEEC_I2C) += ec_i2c.c +verstage-$(CONFIG_EC_GOOGLE_CHROMEEC_LPC) += ec_lpc.c +verstage-$(CONFIG_EC_GOOGLE_CHROMEEC_SPI) += ec_spi.c +endif + diff --git a/src/mainboard/google/nyan_blaze/Makefile.inc b/src/mainboard/google/nyan_blaze/Makefile.inc index 02b3977..dec8f64 100644 --- a/src/mainboard/google/nyan_blaze/Makefile.inc +++ b/src/mainboard/google/nyan_blaze/Makefile.inc @@ -32,6 +32,7 @@ bootblock-y += bootblock.c bootblock-y += pmic.c bootblock-y += reset.c +verstage-$(CONFIG_CHROMEOS) += chromeos.c verstage-y += reset.c romstage-y += reset.c diff --git a/src/vendorcode/google/chromeos/vboot_main.c b/src/vendorcode/google/chromeos/vboot_main.c index 907afd7..8251cfd 100644 --- a/src/vendorcode/google/chromeos/vboot_main.c +++ b/src/vendorcode/google/chromeos/vboot_main.c @@ -264,12 +264,12 @@ void __attribute__((noinline)) select_firmware(void) * invalid secdata and tell us what to do (=reboot). */ //antirollback_read_space_firmware(&ctx); - //if (get_developer_mode_switch()) - // ctx.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE; - //if (get_recovery_mode_switch()) { - // clear_recovery_mode_switch(); - // ctx.flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE; - //} + if (get_developer_mode_switch()) + ctx.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE; + if (get_recovery_mode_switch()) { + clear_recovery_mode_switch(); + ctx.flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE; + } /* Do early init */ VBDEBUG("Phase 1\n");
1
0
0
0
Patch set updated for coreboot: d05f4a6 vboot2: implement vb2ex_read_resource
by Marc Jones
13 Jan '15
13 Jan '15
Marc Jones (marc.jones(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/8161
-gerrit commit d05f4a69b6ab5454997c1e80a1d8206f93287196 Author: Daisuke Nojiri <dnojiri(a)chromium.org> Date: Mon Jun 30 08:28:17 2014 -0700 vboot2: implement vb2ex_read_resource TEST=Built with VBOOT2_VERIFY_FIRMWARE on/off. Booted Nyan Blaze. BUG=None BRANCH=none Signed-off-by: Daisuke Nojiri <dnojiri(a)chromium.org> Original-Change-Id: I633f9dddbf8b2f25797aacc246bcebaafb02bea4 Original-Reviewed-on:
https://chromium-review.googlesource.com/206063
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org> Original-Tested-by: Daisuke Nojiri <dnojiri(a)chromium.org> Original-Commit-Queue: Daisuke Nojiri <dnojiri(a)chromium.org> (cherry picked from commit 1f215672de31847cc647e83d2c04633b7f8dfa33) Signed-off-by: Marc Jones <marc.jones(a)se-eng.com> Change-Id: I57f449b052132b300f7bca4351871c539a7a8694 --- src/vendorcode/google/chromeos/vboot_main.c | 55 +++++++++++++++++++---------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/src/vendorcode/google/chromeos/vboot_main.c b/src/vendorcode/google/chromeos/vboot_main.c index 9779d35..907afd7 100644 --- a/src/vendorcode/google/chromeos/vboot_main.c +++ b/src/vendorcode/google/chromeos/vboot_main.c @@ -31,6 +31,23 @@ struct vboot_region { int32_t size; }; +static void locate_region(const char *name, struct vboot_region *region) +{ + region->size = find_fmap_entry(name, (void **)®ion->offset_addr); + VBDEBUG("Located %s @%x\n", name, region->offset_addr); +} + +static int is_slot_a(struct vb2_context *ctx) +{ + return !(ctx->flags & VB2_CONTEXT_FW_SLOT_B); +} + +static int in_ro(void) +{ + /* TODO: Implement */ + return 1; +} + /* exports */ void vb2ex_printf(const char *func, const char *fmt, ...) @@ -57,27 +74,29 @@ int vb2ex_read_resource(struct vb2_context *ctx, void *buf, uint32_t size) { - VBDEBUG("Reading resource\n"); - return VB2_ERROR_UNKNOWN; -} + struct vboot_region region; + + switch (index) { + case VB2_RES_GBB: + locate_region("GBB", ®ion); + break; + case VB2_RES_FW_VBLOCK: + if (is_slot_a(ctx)) + locate_region("VBLOCK_A", ®ion); + else + locate_region("VBLOCK_B", ®ion); + break; + default: + return VB2_ERROR_EX_READ_RESOURCE_INDEX; + } -/* locals */ + if (offset + size > region.size) + return VB2_ERROR_EX_READ_RESOURCE_SIZE; -static void locate_region(const char *name, struct vboot_region *region) -{ - region->size = find_fmap_entry(name, (void **)®ion->offset_addr); - VBDEBUG("Located %s @%x\n", name, region->offset_addr); -} + if (vboot_get_region(region.offset_addr + offset, size, buf) == NULL) + return VB2_ERROR_UNKNOWN; -static int is_slot_a(struct vb2_context *ctx) -{ - return !(ctx->flags & VB2_CONTEXT_FW_SLOT_B); -} - -static int in_ro(void) -{ - /* TODO: Implement */ - return 1; + return VB2_SUCCESS; } static void reboot(void)
1
0
0
0
← Newer
1
...
56
57
58
59
60
61
62
...
124
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
Results per page:
10
25
50
100
200