security/tpm: Unify the coreboot TPM software stack

* Remove 2nd software stack in pc80 drivers directory.
* Create TSPI interface for common usage.
* Refactor TSS / TIS code base.
* Add vendor tss (Cr50) directory.
* Change kconfig options for TPM to TPM1.
* Add user / board configuration with:
  * MAINBOARD_HAS_*_TPM # * BUS driver
  * MAINBOARD_HAS_TPM1 or MAINBOARD_HAS_TPM2
  * Add kconfig TPM user selection (e.g. pluggable TPMs)
* Fix existing headers and function calls.
* Fix vboot for interface usage and antirollback mode.

Change-Id: I7ec277e82a3c20c62a0548a1a2b013e6ce8f5b3f
Signed-off-by: Philipp Deppenwiese <zaolin@das-labor.org>
Reviewed-on: https://review.coreboot.org/24903
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Philipp Deppenwiese
2018-02-27 19:40:52 +01:00
committed by Martin Roth
parent 961d31bdb3
commit c07f8fbe6f
112 changed files with 1126 additions and 1396 deletions

View File

@@ -1,6 +1,7 @@
## This file is part of the coreboot project.
##
## Copyright (C) 2017 Philipp Deppenwiese, Facebook, Inc.
## Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
## Copyright (C) 2018 Facebook Inc.
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
@@ -12,58 +13,84 @@
## GNU General Public License for more details.
##
source "src/security/tpm/tss/vendor/cr50/Kconfig"
menu "Trusted Platform Module"
config TPM
config TPM1
bool
default n
select LPC_TPM if MAINBOARD_HAS_LPC_TPM
select I2C_TPM if !MAINBOARD_HAS_LPC_TPM && !SPI_TPM
help
Enable this option to enable TPM support in coreboot.
If unsure, say N.
default y if MAINBOARD_HAS_TPM1 || USER_TPM1
depends on MAINBOARD_HAS_LPC_TPM || MAINBOARD_HAS_I2C_TPM_GENERIC \
|| MAINBOARD_HAS_I2C_TPM_ATMEL
config TPM2
bool
select LPC_TPM if MAINBOARD_HAS_LPC_TPM
select I2C_TPM if !MAINBOARD_HAS_LPC_TPM && !SPI_TPM
help
Enable this option to enable TPM2 support in coreboot.
default y if MAINBOARD_HAS_TPM2 || USER_TPM2
depends on MAINBOARD_HAS_I2C_TPM_GENERIC || MAINBOARD_HAS_LPC_TPM \
|| MAINBOARD_HAS_I2C_TPM_ATMEL || MAINBOARD_HAS_I2C_TPM_CR50 \
|| MAINBOARD_HAS_SPI_TPM_CR50
If unsure, say N.
config MAINBOARD_HAS_TPM1
bool
config MAINBOARD_HAS_TPM2
bool
if !MAINBOARD_HAS_TPM1 && !MAINBOARD_HAS_TPM2
choice
prompt "Trusted Platform Module"
default USER_NO_TPM
config USER_NO_TPM
bool "disabled"
config USER_TPM1
bool "1.2"
depends on MAINBOARD_HAS_LPC_TPM || MAINBOARD_HAS_I2C_TPM_GENERIC \
|| MAINBOARD_HAS_I2C_TPM_ATMEL
help
Enable this option to enable TPM 1.0 - 1.2 support in coreboot.
If unsure, say N.
config USER_TPM2
bool "2.0"
depends on MAINBOARD_HAS_I2C_TPM_GENERIC || MAINBOARD_HAS_LPC_TPM \
|| MAINBOARD_HAS_I2C_TPM_ATMEL || MAINBOARD_HAS_I2C_TPM_CR50 \
|| MAINBOARD_HAS_SPI_TPM_CR50
help
Enable this option to enable TPM 2.0 support in coreboot.
If unsure, say N.
endchoice
endif
config TPM_DEACTIVATE
bool "Deactivate TPM"
default n
depends on !VBOOT
depends on TPM1
help
Deactivate TPM by issuing deactivate command.
config DEBUG_TPM
bool "Output verbose TPM debug messages"
default n
depends on TPM || TPM2
select DRIVER_TPM_DISPLAY_TIS_BYTES if I2C_TPM
depends on TPM1 || TPM2
help
This option enables additional TPM related debug messages.
config MAINBOARD_HAS_TPM_CR50
bool
default y if MAINBOARD_HAS_SPI_TPM_CR50 || MAINBOARD_HAS_I2C_TPM_CR50
config TPM_RDRESP_NEED_DELAY
bool "Enable Delay Workaround for TPM"
default n
select MAINBOARD_HAS_TPM2
select POWER_OFF_ON_CR50_UPDATE if ARCH_X86
config POWER_OFF_ON_CR50_UPDATE
bool
depends on LPC_TPM
help
Power off machine while waiting for CR50 update to take effect.
config MAINBOARD_HAS_LPC_TPM
bool
default n
help
Board has TPM support
config MAINBOARD_HAS_TPM2
bool
default n
help
There is a TPM device installed on the mainboard, and it is
compliant with version 2 TCG TPM specification. Could be connected
over LPC, SPI or I2C.
Certain TPMs seem to need some delay when reading response
to work around a race-condition-related issue, possibly
caused by ill-programmed TPM firmware.
endmenu # Trusted Platform Module (tpm)

View File

@@ -1,14 +1,45 @@
subdirs-$(CONFIG_TPM_CR50) += tss/vendor/cr50
## TSS
verstage-$(CONFIG_TPM) += tss/tcg-1.2/tss.c
verstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss_marshaling.c
verstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss.c
ifeq ($(CONFIG_TPM1),y)
ifeq ($(CONFIG_VBOOT_SEPARATE_VERSTAGE),y)
romstage-$(CONFIG_TPM) += tss/tcg-1.2/tss.c
romstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss_marshaling.c
romstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss.c
endif # CONFIG_VBOOT_SEPARATE_VERSTAGE
ramstage-y += tss/tcg-1.2/tss.c
romstage-y += tss/tcg-1.2/tss.c
ramstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss_marshaling.c
ramstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss.c
verstage-$(CONFIG_VBOOT) += tss/tcg-1.2/tss.c
postcar-$(CONFIG_VBOOT) += tss/tcg-1.2/tss.c
## TSPI
ramstage-y += tspi/tspi.c
romstage-y += tspi/tspi.c
verstage-$(CONFIG_VBOOT) += tspi/tspi.c
postcar-$(CONFIG_VBOOT) += tspi/tspi.c
endif # CONFIG_TPM1
ifeq ($(CONFIG_TPM2),y)
ramstage-y += tss/tcg-2.0/tss_marshaling.c
ramstage-y += tss/tcg-2.0/tss.c
romstage-y += tss/tcg-2.0/tss_marshaling.c
romstage-y += tss/tcg-2.0/tss.c
verstage-$(CONFIG_VBOOT) += tss/tcg-2.0/tss_marshaling.c
verstage-$(CONFIG_VBOOT) += tss/tcg-2.0/tss.c
postcar-$(CONFIG_VBOOT) += tss/tcg-2.0/tss_marshaling.c
postcar-$(CONFIG_VBOOT) += tss/tcg-2.0/tss.c
## TSPI
ramstage-y += tspi/tspi.c
romstage-y += tspi/tspi.c
verstage-$(CONFIG_VBOOT) += tspi/tspi.c
postcar-$(CONFIG_VBOOT) += tspi/tspi.c
endif # CONFIG_TPM2

View File

@@ -88,8 +88,6 @@ int tis_close(void);
int tis_sendrecv(const u8 *sendbuf, size_t send_size, u8 *recvbuf,
size_t *recv_len);
void init_tpm(int s3resume);
/*
* tis_plat_irq_status()
*

44
src/security/tpm/tspi.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* This file is part of the coreboot project.
*
* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Copyright 2018 Facebook Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef TSPI_H_
#define TSPI_H_
#include <security/tpm/tss.h>
/**
* Ask vboot for a digest and extend a TPM PCR with it.
* @param pcr sets the pcr index
* @param digest sets the hash to extend into the tpm
* @param out_digest get extended hash
* @return TPM_SUCCESS on success. If not a tpm error is returned
*/
uint32_t tpm_extend_pcr(int pcr, uint8_t *digest, uint8_t *out_digest);
/**
* Issue a TPM_Clear and reenable/reactivate the TPM.
* @return TPM_SUCCESS on success. If not a tpm error is returned
*/
uint32_t tpm_clear_and_reenable(void);
/**
* Start the TPM and establish the root of trust.
* @param s3flag tells the tpm setup if we wake up from a s3 state on x86
* @return TPM_SUCCESS on success. If not a tpm error is returned
*/
uint32_t tpm_setup(int s3flag);
#endif /* TSPI_H_ */

View File

@@ -0,0 +1,190 @@
/*
* This file is part of the coreboot project.
*
* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Copyright 2017 Facebook Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <console/cbmem_console.h>
#include <console/console.h>
#include <reset.h>
#include <security/tpm/tspi.h>
#include <security/tpm/tss.h>
#include <stdlib.h>
#include <string.h>
#if IS_ENABLED(CONFIG_TPM1)
static uint32_t tpm1_invoke_state_machine(void)
{
uint8_t disable;
uint8_t deactivated;
uint32_t result = TPM_SUCCESS;
/* Check that the TPM is enabled and activated. */
result = tlcl_get_flags(&disable, &deactivated, NULL);
if (result != TPM_SUCCESS) {
printk(BIOS_ERR, "TPM: Can't read capabilities.\n");
return result;
}
if (!!deactivated != IS_ENABLED(CONFIG_TPM_DEACTIVATE)) {
printk(BIOS_INFO,
"TPM: Unexpected TPM deactivated state. Toggling...\n");
result = tlcl_set_deactivated(!deactivated);
if (result != TPM_SUCCESS) {
printk(BIOS_ERR,
"TPM: Can't toggle deactivated state.\n");
return result;
}
deactivated = !deactivated;
result = TPM_E_MUST_REBOOT;
}
if (disable && !deactivated) {
printk(BIOS_INFO, "TPM: disabled (%d). Enabling...\n", disable);
result = tlcl_set_enable();
if (result != TPM_SUCCESS) {
printk(BIOS_ERR, "TPM: Can't set enabled state.\n");
return result;
}
printk(BIOS_INFO, "TPM: Must reboot to re-enable\n");
result = TPM_E_MUST_REBOOT;
}
return result;
}
#endif
/*
* tpm_setup 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 tpm_setup(int s3flag)
{
uint32_t result;
result = tlcl_lib_init();
if (result != TPM_SUCCESS) {
printk(BIOS_ERR, "TPM: Can't initialize.\n");
goto out;
}
/* Handle special init for S3 resume path */
if (s3flag) {
result = tlcl_resume();
if (result == TPM_E_INVALID_POSTINIT)
printk(BIOS_INFO, "TPM: Already initialized.\n");
return TPM_SUCCESS;
}
result = tlcl_startup();
if (result != TPM_SUCCESS) {
printk(BIOS_ERR, "TPM: Can't run startup command.\n");
goto out;
}
result = tlcl_assert_physical_presence();
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.
*/
result = tlcl_physical_presence_cmd_enable();
if (result != TPM_SUCCESS) {
printk(
BIOS_ERR,
"TPM: Can't enable physical presence command.\n");
goto out;
}
result = tlcl_assert_physical_presence();
if (result != TPM_SUCCESS) {
printk(BIOS_ERR,
"TPM: Can't assert physical presence.\n");
goto out;
}
}
#if IS_ENABLED(CONFIG_TPM1)
result = tpm1_invoke_state_machine();
if (result != TPM_SUCCESS)
return result;
#endif
out:
if (result != TPM_SUCCESS)
post_code(POST_TPM_FAILURE);
else
printk(BIOS_INFO, "TPM: setup succeeded\n");
return result;
}
uint32_t tpm_clear_and_reenable(void)
{
uint32_t result;
printk(BIOS_INFO, "TPM: Clear and re-enable\n");
result = tlcl_force_clear();
if (result != TPM_SUCCESS) {
printk(BIOS_ERR, "TPM: Can't initiate a force clear.\n");
return result;
}
#if IS_ENABLED(CONFIG_TPM1)
result = tlcl_set_enable();
if (result != TPM_SUCCESS) {
printk(BIOS_ERR, "TPM: Can't set enabled state.\n");
return result;
}
result = tlcl_set_deactivated(0);
if (result != TPM_SUCCESS) {
printk(BIOS_ERR, "TPM: Can't set deactivated state.\n");
return result;
}
#endif
return TPM_SUCCESS;
}
uint32_t tpm_extend_pcr(int pcr, uint8_t *digest, uint8_t *out_digest)
{
if (!digest)
return TPM_E_IOERROR;
if (out_digest)
return tlcl_extend(pcr, digest, out_digest);
return tlcl_extend(pcr, digest, NULL);
}

View File

@@ -11,13 +11,70 @@
#ifndef TSS_H_
#define TSS_H_
#include <stdint.h>
#include <types.h>
#include "tss_constants.h"
#include <security/tpm/tss/common/tss_common.h>
#include <security/tpm/tss_errors.h>
#include <security/tpm/tss/vendor/cr50/cr50.h>
#if IS_ENABLED(CONFIG_TPM1)
#include <security/tpm/tss/tcg-1.2/tss_structures.h>
/**
* 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 tlcl_define_space(uint32_t index, uint32_t perm, uint32_t size);
/**
* Issue a PhysicalEnable. The TPM error code is returned.
*/
uint32_t tlcl_set_enable(void);
/**
* Issue a SetDeactivated. Pass 0 to activate. Returns result code.
*/
uint32_t tlcl_set_deactivated(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 tlcl_get_flags(uint8_t *disable, uint8_t *deactivated,
uint8_t *nvlocked);
/**
* Get the entire set of permanent flags.
*/
uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags);
#endif
#if IS_ENABLED(CONFIG_TPM2)
#include <security/tpm/tss/tcg-2.0/tss_structures.h>
/*
* Define a TPM2 space. The define space command TPM command used by the tlcl
* layer offers the ability to use custom nv attributes and policies.
*/
uint32_t tlcl_define_space(uint32_t space_index, size_t space_size,
const TPMA_NV nv_attributes,
const uint8_t *nv_policy, size_t nv_policy_size);
/*
* Makes tpm_process_command available for on top implementations of
* custom tpm standards like cr50
*/
void *tpm_process_command(TPM_CC command, void *command_body);
#endif
/*****************************************************************************/
/* Functions implemented in tlcl.c */
/* Generic Functions implemented in tlcl.c */
/**
* Call this first. Returns 0 if success, nonzero if error.
@@ -57,23 +114,6 @@ uint32_t tlcl_self_test_full(void);
*/
uint32_t tlcl_continue_self_test(void);
#if IS_ENABLED(CONFIG_TPM)
/**
* 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 tlcl_define_space(uint32_t index, uint32_t perm, uint32_t size);
#elif IS_ENABLED(CONFIG_TPM2)
/*
* Define a TPM space. The define space command TPM command used by the tlcl
* layer is enforcing the policy which would not allow to delete the created
* space after any PCR0 change from its initial value.
*/
uint32_t tlcl_define_space(uint32_t space_index, size_t space_size);
#endif
/**
* Write [length] bytes of [data] to space at [index]. The TPM error code is
* returned.
@@ -112,23 +152,6 @@ uint32_t tlcl_set_nv_locked(void);
*/
uint32_t tlcl_force_clear(void);
/**
* Issue a PhysicalEnable. The TPM error code is returned.
*/
uint32_t tlcl_set_enable(void);
/**
* Issue a SetDeactivated. Pass 0 to activate. Returns result code.
*/
uint32_t tlcl_set_deactivated(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 tlcl_get_flags(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.
@@ -146,32 +169,9 @@ uint32_t tlcl_lock_nv_write(uint32_t index);
uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest,
uint8_t *out_digest);
/**
* Get the entire set of permanent flags.
*/
uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags);
/**
* Disable platform hierarchy. Specific to TPM2. The TPM error code is returned.
*/
uint32_t tlcl_disable_platform_hierarchy(void);
/**
* CR50 specific tpm command to enable nvmem commits before internal timeout
* expires.
*/
uint32_t tlcl_cr50_enable_nvcommits(void);
/**
* CR50 specific tpm command to restore header(s) of the dormant RO/RW
* image(s) and in case there indeed was a dormant image, trigger reboot after
* the timeout milliseconds. Note that timeout of zero means "NO REBOOT", not
* "IMMEDIATE REBOOT".
*
* Return value indicates success or failure of accessing the TPM; in case of
* success the number of restored headers is saved in num_restored_headers.
*/
uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms,
uint8_t *num_restored_headers);
#endif /* TSS_H_ */
#endif /* TSS_H_ */

View File

@@ -0,0 +1,23 @@
/*
* This file is part of the coreboot project.
*
* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Copyright 2018 Facebook Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef TCG_TSS_COMMON_H_
#define TCG_TSS_COMMON_H_
#define TPM_PCR_MINIMUM_DIGEST_SIZE 20
#define TPM_SUCCESS ((uint32_t)0x00000000)
#endif /* TCG_TSS_COMMON_H_ */

View File

@@ -20,8 +20,9 @@
#include <security/tpm/tis.h>
#include <vb2_api.h>
#include <security/tpm/tss.h>
#include "tss_internal.h"
#include "tss_structures.h"
#include "tss_commands.h"
#ifdef FOR_TEST
#include <stdio.h>

View File

@@ -0,0 +1,178 @@
/*
* This file is part of the coreboot project.
*
* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Copyright 2018 Facebook Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
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;

View File

@@ -1,164 +1,69 @@
/* This file is automatically generated */
/* 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 TCG1_TSS_STRUCTURES_H_
#define TCG1_TSS_STRUCTURES_H_
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, };
#include <stdint.h>
#include "../common/tss_common.h"
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, };
#define TPM_MAX_COMMAND_SIZE 4096
#define TPM_LARGE_ENOUGH_COMMAND_SIZE 256 /* saves space in the firmware */
#define TPM_PUBEK_SIZE 256
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, },
};
#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)
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, };
#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)
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, },
};
#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)
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, },
};
typedef uint8_t TSS_BOOL;
typedef uint16_t TPM_STRUCTURE_TAG;
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, };
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;
const struct s_tpm_physicalenable_cmd{
uint8_t buffer[10];
} tpm_physicalenable_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f, },
};
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;
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;
#endif /* TCG1_TSS_STRUCTURES_H_ */

View File

@@ -10,7 +10,7 @@
#include <string.h>
#include <vb2_api.h>
#include <security/tpm/tis.h>
#include <security/tpm/antirollback.h>
#include <security/tpm/tss.h>
#include "tss_structures.h"
#include "tss_marshaling.h"
@@ -21,7 +21,7 @@
* TPM2 specification.
*/
static void *tpm_process_command(TPM_CC command, void *command_body)
void *tpm_process_command(TPM_CC command, void *command_body)
{
struct obuf ob;
struct ibuf ib;
@@ -53,13 +53,6 @@ static void *tpm_process_command(TPM_CC command, void *command_body)
return tpm_unmarshal_response(command, &ib);
}
uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags)
{
printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
return TPM_SUCCESS;
}
static uint32_t tlcl_send_startup(TPM_SU type)
{
struct tpm2_startup startup;
@@ -139,30 +132,6 @@ uint32_t tlcl_force_clear(void)
return TPM_SUCCESS;
}
uint32_t tlcl_get_flags(uint8_t *disable, uint8_t *deactivated,
uint8_t *nvlocked)
{
/*
* TPM2 does not map directly into these flags TPM1.2 based firmware
* expects to be able to retrieve.
*
* In any case, if any of these conditions are present, the following
* firmware flow would be interrupted and will have a chance to report
* an error. Let's just hardcode an "All OK" response for now.
*/
if (disable)
*disable = 0;
if (nvlocked)
*nvlocked = 1;
if (deactivated)
*deactivated = 0;
return TPM_SUCCESS;
}
static uint8_t tlcl_init_done CAR_GLOBAL;
/* This function is called directly by vboot, uses vboot return types. */
@@ -247,18 +216,6 @@ uint32_t tlcl_self_test_full(void)
return TPM_SUCCESS;
}
uint32_t tlcl_set_deactivated(uint8_t flag)
{
printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
return TPM_SUCCESS;
}
uint32_t tlcl_set_enable(void)
{
printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
return TPM_SUCCESS;
}
uint32_t tlcl_lock_nv_write(uint32_t index)
{
struct tpm2_response *response;
@@ -306,29 +263,12 @@ uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length)
return TPM_SUCCESS;
}
uint32_t tlcl_define_space(uint32_t space_index, size_t space_size)
uint32_t tlcl_define_space(uint32_t space_index, size_t space_size,
const TPMA_NV nv_attributes,
const uint8_t *nv_policy, size_t nv_policy_size)
{
struct tpm2_nv_define_space_cmd nvds_cmd;
struct tpm2_response *response;
/*
* Different sets of NVRAM space attributes apply to the "ro" spaces,
* i.e. those which should not be possible to delete or modify once
* the RO exits, and the rest of the NVRAM spaces.
*/
const TPMA_NV ro_space_attributes = {
.TPMA_NV_PPWRITE = 1,
.TPMA_NV_AUTHREAD = 1,
.TPMA_NV_PPREAD = 1,
.TPMA_NV_PLATFORMCREATE = 1,
.TPMA_NV_WRITE_STCLEAR = 1,
.TPMA_NV_POLICY_DELETE = 1,
};
const TPMA_NV default_space_attributes = {
.TPMA_NV_PPWRITE = 1,
.TPMA_NV_AUTHREAD = 1,
.TPMA_NV_PPREAD = 1,
.TPMA_NV_PLATFORMCREATE = 1,
};
/* Prepare the define space command structure. */
memset(&nvds_cmd, 0, sizeof(nvds_cmd));
@@ -336,37 +276,21 @@ uint32_t tlcl_define_space(uint32_t space_index, size_t space_size)
nvds_cmd.publicInfo.dataSize = space_size;
nvds_cmd.publicInfo.nvIndex = HR_NV_INDEX + space_index;
nvds_cmd.publicInfo.nameAlg = TPM_ALG_SHA256;
nvds_cmd.publicInfo.attributes = nv_attributes;
/* RO only NV spaces should be impossible to destroy. */
if ((space_index == FIRMWARE_NV_INDEX) ||
(space_index == REC_HASH_NV_INDEX)) {
/*
* This policy digest was obtained using TPM2_PolicyPCR
* selecting only PCR_0 with a value of all zeros.
*/
const uint8_t pcr0_unchanged_policy[] = {
0x09, 0x93, 0x3C, 0xCE, 0xEB, 0xB4, 0x41, 0x11,
0x18, 0x81, 0x1D, 0xD4, 0x47, 0x78, 0x80, 0x08,
0x88, 0x86, 0x62, 0x2D, 0xD7, 0x79, 0x94, 0x46,
0x62, 0x26, 0x68, 0x8E, 0xEE, 0xE6, 0x6A, 0xA1
};
nvds_cmd.publicInfo.attributes = ro_space_attributes;
/*
* Use policy digest based on default pcr0 value. This makes
* sure that the space can not be deleted as soon as PCR0
* value has been extended from default.
*/
nvds_cmd.publicInfo.authPolicy.t.buffer = pcr0_unchanged_policy;
nvds_cmd.publicInfo.authPolicy.t.size =
sizeof(pcr0_unchanged_policy);
} else {
nvds_cmd.publicInfo.attributes = default_space_attributes;
/*
* Use policy digest based on default pcr0 value. This makes
* sure that the space can not be deleted as soon as PCR0
* value has been extended from default.
*/
if (nv_policy && nv_policy_size) {
nvds_cmd.publicInfo.authPolicy.t.buffer = nv_policy;
nvds_cmd.publicInfo.authPolicy.t.size = nv_policy_size;
}
response = tpm_process_command(TPM2_NV_DefineSpace, &nvds_cmd);
printk(BIOS_INFO, "%s: response is %x\n",
__func__, response ? response->hdr.tpm_code : -1);
printk(BIOS_INFO, "%s: response is %x\n", __func__,
response ? response->hdr.tpm_code : -1);
if (!response)
return TPM_E_NO_DEVICE;
@@ -397,42 +321,3 @@ uint32_t tlcl_disable_platform_hierarchy(void)
return TPM_SUCCESS;
}
uint32_t tlcl_cr50_enable_nvcommits(void)
{
uint16_t sub_command = TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS;
struct tpm2_response *response;
printk(BIOS_INFO, "Enabling cr50 nvmem commmits\n");
response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &sub_command);
if (response == NULL || (response && response->hdr.tpm_code)) {
if (response)
printk(BIOS_INFO, "%s: failed %x\n", __func__,
response->hdr.tpm_code);
else
printk(BIOS_INFO, "%s: failed\n", __func__);
return TPM_E_IOERROR;
}
return TPM_SUCCESS;
}
uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms,
uint8_t *num_restored_headers)
{
struct tpm2_response *response;
uint16_t command_body[] = {
TPM2_CR50_SUB_CMD_TURN_UPDATE_ON, timeout_ms
};
printk(BIOS_INFO, "Checking cr50 for pending updates\n");
response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, command_body);
if (!response || response->hdr.tpm_code)
return TPM_E_INTERNAL_INCONSISTENCY;
*num_restored_headers = response->vcr.num_restored_headers;
return TPM_SUCCESS;
}

View File

@@ -11,6 +11,7 @@
#include <string.h>
#include "tss_marshaling.h"
#include <security/tpm/tss/vendor/cr50/cr50.h>
static uint16_t tpm_tag CAR_GLOBAL; /* Depends on the command type. */

View File

@@ -14,16 +14,18 @@
#include <stdint.h>
#include <compiler.h>
#include <types.h>
#include <security/tpm/tss.h>
#include "../common/tss_common.h"
/* This should be plenty for what firmware needs. */
#define TPM_BUFFER_SIZE 256
/* Some TPM2 return codes used in this library. */
#define TPM2_RC_SUCCESS 0
#define TPM2_RC_NV_DEFINED 0x14c
/* Basic TPM2 types. */
typedef uint16_t TPM_SU;
typedef uint16_t TPM_ALG_ID;
typedef uint32_t TPM_CC;
typedef uint32_t TPM_HANDLE;
typedef uint32_t TPM_RC;
typedef uint8_t TPMI_YES_NO;
@@ -47,6 +49,8 @@ typedef TPM_HANDLE TPM_RH;
#define TPM_RS_PW 0x40000009
#define TPM_RH_PLATFORM 0x4000000C
typedef uint32_t TPM_CC;
typedef struct {
uint16_t size;
uint8_t *buffer;
@@ -74,13 +78,6 @@ struct tpm_header {
/* TPM2 specifies vendor commands need to have this bit set. Vendor command
space is defined by the lower 16 bits. */
#define TPM_CC_VENDOR_BIT_MASK 0x20000000
/* FIXME: below is not enough to differentiate between vendors commands
of numerous devices. However, the current tpm2 APIs aren't very amenable
to extending generically because the marshaling code is assuming all
knowledge of all commands. */
#define TPM2_CR50_VENDOR_COMMAND ((TPM_CC)(TPM_CC_VENDOR_BIT_MASK | 0))
#define TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS (21)
#define TPM2_CR50_SUB_CMD_TURN_UPDATE_ON (24)
/* Startup values. */
#define TPM_SU_CLEAR 0

View File

@@ -0,0 +1,28 @@
## This file is part of the coreboot project.
##
## Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
## Copyright (C) 2018 Facebook, Inc.
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; version 2 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
config TPM_CR50
bool
default y if MAINBOARD_HAS_I2C_TPM_CR50 || MAINBOARD_HAS_SPI_TPM_CR50
select POWER_OFF_ON_CR50_UPDATE if ARCH_X86
if TPM_CR50
config POWER_OFF_ON_CR50_UPDATE
bool
help
Power off machine while waiting for CR50 update to take effect.
endif

View File

@@ -0,0 +1,5 @@
ramstage-y += cr50.c
romstage-y += cr50.c
postcar-y += cr50.c
verstage-$(CONFIG_VBOOT) += cr50.c

54
src/security/tpm/tss/vendor/cr50/cr50.c vendored Normal file
View File

@@ -0,0 +1,54 @@
/*
* Copyright 2016 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.
*/
#include <arch/early_variables.h>
#include <console/console.h>
#include <endian.h>
#include <string.h>
#include <vb2_api.h>
#include <security/tpm/tis.h>
#include <security/tpm/tss.h>
#include "../../tcg-2.0/tss_marshaling.h"
uint32_t tlcl_cr50_enable_nvcommits(void)
{
uint16_t sub_command = TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS;
struct tpm2_response *response;
printk(BIOS_INFO, "Enabling cr50 nvmem commmits\n");
response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &sub_command);
if (response == NULL || (response && response->hdr.tpm_code)) {
if (response)
printk(BIOS_INFO, "%s: failed %x\n", __func__,
response->hdr.tpm_code);
else
printk(BIOS_INFO, "%s: failed\n", __func__);
return TPM_E_IOERROR;
}
return TPM_SUCCESS;
}
uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms,
uint8_t *num_restored_headers)
{
struct tpm2_response *response;
uint16_t command_body[] = {
TPM2_CR50_SUB_CMD_TURN_UPDATE_ON, timeout_ms
};
printk(BIOS_INFO, "Checking cr50 for pending updates\n");
response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, command_body);
if (!response || response->hdr.tpm_code)
return TPM_E_INTERNAL_INCONSISTENCY;
*num_restored_headers = response->vcr.num_restored_headers;
return TPM_SUCCESS;
}

47
src/security/tpm/tss/vendor/cr50/cr50.h vendored Normal file
View File

@@ -0,0 +1,47 @@
/*
* This file is part of the coreboot project.
*
* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Copyright 2018 Facebook Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef CR50_TSS_STRUCTURES_H_
#define CR50_TSS_STRUCTURES_H_
#include <stdint.h>
/* FIXME: below is not enough to differentiate between vendors commands
of numerous devices. However, the current tpm2 APIs aren't very amenable
to extending generically because the marshaling code is assuming all
knowledge of all commands. */
#define TPM2_CR50_VENDOR_COMMAND ((TPM_CC)(TPM_CC_VENDOR_BIT_MASK | 0))
#define TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS (21)
#define TPM2_CR50_SUB_CMD_TURN_UPDATE_ON (24)
/**
* CR50 specific tpm command to enable nvmem commits before internal timeout
* expires.
*/
uint32_t tlcl_cr50_enable_nvcommits(void);
/**
* CR50 specific tpm command to restore header(s) of the dormant RO/RW
* image(s) and in case there indeed was a dormant image, trigger reboot after
* the timeout milliseconds. Note that timeout of zero means "NO REBOOT", not
* "IMMEDIATE REBOOT".
*
* Return value indicates success or failure of accessing the TPM; in case of
* success the number of restored headers is saved in num_restored_headers.
*/
uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms,
uint8_t *num_restored_headers);
#endif /* CR50_TSS_STRUCTURES_H_ */

View File

@@ -1,100 +0,0 @@
/* 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_E_NV_DEFINED ((uint32_t)0x0000500b) /* 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)
/* Some TPM2 return codes used in this library. */
#define TPM2_RC_SUCCESS 0
#define TPM2_RC_NV_DEFINED 0x14c
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_ */

View File

@@ -1,255 +0,0 @@
/* 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 TSS_ERROR_MESSAGES_H_
#define TSS_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 /* TSS_ERROR_MESSAGES_H_ */

View File

@@ -0,0 +1,42 @@
/* 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 TSS_ERRORS_H_
#define TSS_ERRORS_H_
#define TPM_E_BASE 0x0
#define TPM_E_NON_FATAL 0x800
#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_E_NV_DEFINED ((uint32_t)0x0000500b) /* vboot local */
#endif /* TSS_ERRORS_H_ */

View File

@@ -17,10 +17,7 @@ menu "Verified Boot (vboot)"
config VBOOT
bool "Verify firmware with vboot."
default n
select TPM if !MAINBOARD_HAS_TPM2 && !VBOOT_MOCK_SECDATA
select TPM2 if MAINBOARD_HAS_TPM2 && !VBOOT_MOCK_SECDATA
select TPM_INIT_FAILURE_IS_FATAL if PC80_SYSTEM && LPC_TPM
select SKIP_TPM_STARTUP_ON_NORMAL_BOOT if PC80_SYSTEM && LPC_TPM
select VBOOT_MOCK_SECDATA if !TPM1 && !TPM2
depends on HAVE_HARD_RESET
help
Enabling VBOOT will use vboot to verify the components of the firmware

View File

@@ -9,7 +9,8 @@
#ifndef ANTIROLLBACK_H_
#define ANTIROLLBACK_H_
#include "tss_constants.h"
#include <types.h>
#include <security/tpm/tspi.h>
struct vb2_context;
enum vb2_pcr_digest;
@@ -55,27 +56,11 @@ uint32_t antirollback_write_space_rec_hash(const uint8_t *data, uint32_t size);
/* Lock down recovery hash space in TPM. */
uint32_t antirollback_lock_space_rec_hash(void);
/****************************************************************************/
/* Start of the root of trust */
uint32_t vboot_setup_tpm(struct vb2_context *ctx);
/*
* The following functions are internal apis, listed here for use by unit tests
* only.
*/
/**
* Ask vboot for a digest and extend a TPM PCR with it.
*/
uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr,
/* vboot_extend_pcr function for vb2 context */
uint32_t vboot_extend_pcr(struct vb2_context *ctx, int pcr,
enum vb2_pcr_digest which_digest);
/**
* Issue a TPM_Clear and reenable/reactivate the TPM.
*/
uint32_t tpm_clear_and_reenable(void);
/**
* Start the TPM and establish the root of trust for the antirollback mechanism.
*/
uint32_t setup_tpm(struct vb2_context *ctx);
#endif /* ANTIROLLBACK_H_ */

View File

@@ -32,54 +32,50 @@
* stored in the TPM NVRAM.
*/
#include <security/tpm/antirollback.h>
#include <stdlib.h>
#include <security/tpm/tss.h>
#include <security/tpm/tspi.h>
#include <vb2_api.h>
uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr,
enum vb2_pcr_digest which_digest)
#include "antirollback.h"
int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
{
return TPM_SUCCESS;
return VB2_SUCCESS;
}
uint32_t tpm_clear_and_reenable(void)
uint32_t vboot_extend_pcr(struct vb2_context *ctx, int pcr,
enum vb2_pcr_digest which_digest)
{
return TPM_SUCCESS;
return VB2_SUCCESS;
}
uint32_t antirollback_read_space_firmware(struct vb2_context *ctx)
{
vb2api_secdata_create(ctx);
return TPM_SUCCESS;
return VB2_SUCCESS;
}
uint32_t antirollback_write_space_firmware(struct vb2_context *ctx)
{
return TPM_SUCCESS;
return VB2_SUCCESS;
}
uint32_t antirollback_lock_space_firmware()
{
return TPM_SUCCESS;
return VB2_SUCCESS;
}
uint32_t antirollback_lock_space_rec_hash(void)
{
return TPM_SUCCESS;
return VB2_SUCCESS;
}
uint32_t antirollback_read_space_rec_hash(uint8_t *data, uint32_t size)
{
return TPM_SUCCESS;
return VB2_SUCCESS;
}
uint32_t antirollback_write_space_rec_hash(const uint8_t *data, uint32_t size)
{
return TPM_SUCCESS;
}
uint32_t tlcl_lib_init(void)
{
return VB2_SUCCESS;
}

View File

@@ -32,10 +32,10 @@
* stored in the TPM NVRAM.
*/
#include <security/tpm/antirollback.h>
#include <security/vboot/antirollback.h>
#include <stdlib.h>
#include <string.h>
#include <security/tpm/tss.h>
#include <security/tpm/tspi.h>
#include <vb2_api.h>
#include <console/console.h>
@@ -64,7 +64,7 @@
static uint32_t safe_write(uint32_t index, const void *data, uint32_t length);
uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr,
uint32_t vboot_extend_pcr(struct vb2_context *ctx, int pcr,
enum vb2_pcr_digest which_digest)
{
uint8_t buffer[VB2_PCR_DIGEST_RECOMMENDED_SIZE];
@@ -74,10 +74,10 @@ uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr,
rv = vb2api_get_pcr_digest(ctx, which_digest, buffer, &size);
if (rv != VB2_SUCCESS)
return rv;
if (size < TPM_PCR_DIGEST)
if (size < TPM_PCR_MINIMUM_DIGEST_SIZE)
return VB2_ERROR_UNKNOWN;
return tlcl_extend(pcr, buffer, NULL);
return tpm_extend_pcr(pcr, buffer, NULL);
}
static uint32_t read_space_firmware(struct vb2_context *ctx)
@@ -158,6 +158,35 @@ static const uint8_t secdata_kernel[] = {
static const uint8_t rec_hash_data[REC_HASH_NV_SIZE] = { };
#if IS_ENABLED(CONFIG_TPM2)
/*
* Different sets of NVRAM space attributes apply to the "ro" spaces,
* i.e. those which should not be possible to delete or modify once
* the RO exits, and the rest of the NVRAM spaces.
*/
const static TPMA_NV ro_space_attributes = {
.TPMA_NV_PPWRITE = 1,
.TPMA_NV_AUTHREAD = 1,
.TPMA_NV_PPREAD = 1,
.TPMA_NV_PLATFORMCREATE = 1,
.TPMA_NV_WRITE_STCLEAR = 1,
.TPMA_NV_POLICY_DELETE = 1,
};
const static TPMA_NV rw_space_attributes = {
.TPMA_NV_PPWRITE = 1,
.TPMA_NV_AUTHREAD = 1,
.TPMA_NV_PPREAD = 1,
.TPMA_NV_PLATFORMCREATE = 1,
};
/*
* This policy digest was obtained using TPM2_PolicyPCR
* selecting only PCR_0 with a value of all zeros.
*/
const static uint8_t pcr0_unchanged_policy[] = {
0x09, 0x93, 0x3C, 0xCE, 0xEB, 0xB4, 0x41, 0x11, 0x18, 0x81, 0x1D,
0xD4, 0x47, 0x78, 0x80, 0x08, 0x88, 0x86, 0x62, 0x2D, 0xD7, 0x79,
0x94, 0x46, 0x62, 0x26, 0x68, 0x8E, 0xEE, 0xE6, 0x6A, 0xA1};
/* Nothing special in the TPM2 path yet. */
static uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
@@ -166,11 +195,13 @@ static uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
}
static uint32_t set_space(const char *name, uint32_t index, const void *data,
uint32_t length)
uint32_t length, const TPMA_NV nv_attributes,
const uint8_t *nv_policy, size_t nv_policy_size)
{
uint32_t rv;
rv = tlcl_define_space(index, length);
rv = tlcl_define_space(index, length, nv_attributes, nv_policy,
nv_policy_size);
if (rv == TPM_E_NV_DEFINED) {
/*
* Continue with writing: it may be defined, but not written
@@ -193,19 +224,22 @@ static uint32_t set_space(const char *name, uint32_t index, const void *data,
static uint32_t set_firmware_space(const void *firmware_blob)
{
return set_space("firmware", FIRMWARE_NV_INDEX, firmware_blob,
VB2_SECDATA_SIZE);
VB2_SECDATA_SIZE, ro_space_attributes,
pcr0_unchanged_policy, sizeof(pcr0_unchanged_policy));
}
static uint32_t set_kernel_space(const void *kernel_blob)
{
return set_space("kernel", KERNEL_NV_INDEX, kernel_blob,
sizeof(secdata_kernel));
sizeof(secdata_kernel), rw_space_attributes, NULL, 0);
}
static uint32_t set_rec_hash_space(const uint8_t *data)
{
return set_space("MRC Hash", REC_HASH_NV_INDEX, data,
REC_HASH_NV_SIZE);
REC_HASH_NV_SIZE,
ro_space_attributes, pcr0_unchanged_policy,
sizeof(pcr0_unchanged_policy));
}
static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
@@ -228,13 +262,6 @@ static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
return TPM_SUCCESS;
}
uint32_t tpm_clear_and_reenable(void)
{
VBDEBUG("TPM: Clear and re-enable\n");
RETURN_ON_FAILURE(tlcl_force_clear());
return TPM_SUCCESS;
}
uint32_t antirollback_lock_space_firmware(void)
{
return tlcl_lock_nv_write(FIRMWARE_NV_INDEX);
@@ -247,16 +274,6 @@ uint32_t antirollback_lock_space_rec_hash(void)
#else
uint32_t tpm_clear_and_reenable(void)
{
VBDEBUG("TPM: Clear and re-enable\n");
RETURN_ON_FAILURE(tlcl_force_clear());
RETURN_ON_FAILURE(tlcl_set_enable());
RETURN_ON_FAILURE(tlcl_set_deactivated(0));
return TPM_SUCCESS;
}
/**
* Like tlcl_write(), 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
@@ -416,110 +433,22 @@ static uint32_t factory_initialize_tpm(struct vb2_context *ctx)
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 setup_tpm(struct vb2_context *ctx)
uint32_t vboot_setup_tpm(struct vb2_context *ctx)
{
uint8_t disable;
uint8_t deactivated;
uint32_t result;
RETURN_ON_FAILURE(tlcl_lib_init());
/* Handle special init for S3 resume path */
if (ctx->flags & VB2_CONTEXT_S3_RESUME) {
result = tlcl_resume();
if (result == TPM_E_INVALID_POSTINIT)
printk(BIOS_DEBUG, "TPM: Already initialized.\n");
return TPM_SUCCESS;
}
if (IS_ENABLED(CONFIG_VBOOT_SOFT_REBOOT_WORKAROUND)) {
result = tlcl_startup();
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");
ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT;
return TPM_E_MUST_REBOOT;
} else if (result != TPM_SUCCESS) {
VBDEBUG("TPM: tlcl_startup returned %08x\n", result);
return result;
}
} else
RETURN_ON_FAILURE(tlcl_startup());
/*
* Some TPMs start the self test automatically at power on. In that case
* we don't need to call ContinueSelfTest. On some (other) TPMs,
* continue_self_test may block. In that case, we definitely don't want
* to call it here. For TPMs in the intersection of these two sets, we
* are screwed. (In other words: TPMs that require manually starting the
* self-test AND block will have poor performance until we split
* tlcl_send_receive() 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(tlcl_continue_self_test());
#endif
result = tlcl_assert_physical_presence();
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(tlcl_physical_presence_cmd_enable());
RETURN_ON_FAILURE(tlcl_assert_physical_presence());
}
/* Check that the TPM is enabled and activated. */
RETURN_ON_FAILURE(tlcl_get_flags(&disable, &deactivated, NULL));
if (disable || deactivated) {
VBDEBUG("TPM: disabled (%d) or deactivated (%d). Fixing...\n",
disable, deactivated);
RETURN_ON_FAILURE(tlcl_set_enable());
RETURN_ON_FAILURE(tlcl_set_deactivated(0));
VBDEBUG("TPM: Must reboot to re-enable\n");
result = tpm_setup(ctx->flags & VB2_CONTEXT_S3_RESUME);
if (result == TPM_E_MUST_REBOOT)
ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT;
return TPM_E_MUST_REBOOT;
}
VBDEBUG("TPM: SetupTPM() succeeded\n");
return TPM_SUCCESS;
return result;
}
uint32_t antirollback_read_space_firmware(struct vb2_context *ctx)
{
uint32_t rv;
rv = setup_tpm(ctx);
rv = vboot_setup_tpm(ctx);
if (rv)
return rv;
@@ -585,3 +514,13 @@ uint32_t antirollback_write_space_rec_hash(const uint8_t *data, uint32_t size)
return write_secdata(REC_HASH_NV_INDEX, data, size);
}
int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
{
uint32_t rv;
printk(BIOS_INFO, "Clearing TPM owner\n");
rv = tpm_clear_and_reenable();
if (rv)
return VB2_ERROR_EX_TPM_CLEAR_OWNER;
return VB2_SUCCESS;
}

View File

@@ -13,7 +13,6 @@
* GNU General Public License for more details.
*/
#include <security/tpm/antirollback.h>
#include <arch/exception.h>
#include <assert.h>
#include <bootmode.h>
@@ -27,6 +26,8 @@
#include <security/vboot/misc.h>
#include <security/vboot/vbnv.h>
#include "antirollback.h"
/* The max hash size to expect is for SHA512. */
#define VBOOT_MAX_HASH_SIZE VB2_SHA512_DIGEST_SIZE
@@ -53,16 +54,6 @@ void vb2ex_printf(const char *func, const char *fmt, ...)
return;
}
int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
{
uint32_t rv;
printk(BIOS_INFO, "Clearing TPM owner\n");
rv = tpm_clear_and_reenable();
if (rv)
return VB2_ERROR_EX_TPM_CLEAR_OWNER;
return VB2_SUCCESS;
}
int vb2ex_read_resource(struct vb2_context *ctx,
enum vb2_resource_index index,
uint32_t offset,
@@ -290,8 +281,8 @@ static void save_if_needed(struct vb2_context *ctx)
static uint32_t extend_pcrs(struct vb2_context *ctx)
{
return tpm_extend_pcr(ctx, 0, BOOT_MODE_PCR) ||
tpm_extend_pcr(ctx, 1, HWID_DIGEST_PCR);
return vboot_extend_pcr(ctx, 0, BOOT_MODE_PCR) ||
vboot_extend_pcr(ctx, 1, HWID_DIGEST_PCR);
}
/**