security/tpm: replace CONFIG(TPMx) checks with runtime check
This prepares the code for enabling both CONFIG_TPM1 and CONFIG_TPM2 during compilation, in which case actual TPM family in use can be determined at runtime. In some places both compile-time and runtime checks are necessary. Yet in places like probe functions runtime state checks don't make sense as runtime state is defined by results of probing. Change-Id: Id9cc25aad8d1d7bfad12b7a92059b1b3641bbfa9 Ticket: https://ticket.coreboot.org/issues/433 Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/69161 Reviewed-by: Jérémy Compostella <jeremy.compostella@intel.com> Reviewed-by: Julius Werner <jwerner@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
		
				
					committed by
					
						
						Martin L Roth
					
				
			
			
				
	
			
			
			
						parent
						
							094a051732
						
					
				
				
					commit
					47e9e8cde1
				
			@@ -25,7 +25,9 @@
 | 
				
			|||||||
#include <device/device.h>
 | 
					#include <device/device.h>
 | 
				
			||||||
#include <device/mmio.h>
 | 
					#include <device/mmio.h>
 | 
				
			||||||
#include <device/pci.h>
 | 
					#include <device/pci.h>
 | 
				
			||||||
 | 
					#include <drivers/crb/tpm.h>
 | 
				
			||||||
#include <drivers/uart/pl011.h>
 | 
					#include <drivers/uart/pl011.h>
 | 
				
			||||||
 | 
					#include <security/tpm/tss.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <types.h>
 | 
					#include <types.h>
 | 
				
			||||||
#include <version.h>
 | 
					#include <version.h>
 | 
				
			||||||
@@ -205,7 +207,7 @@ static void *get_tcpa_log(u32 *size)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void acpi_create_tcpa(acpi_header_t *header, void *unused)
 | 
					static void acpi_create_tcpa(acpi_header_t *header, void *unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!CONFIG(TPM1))
 | 
						if (tlcl_get_family() != TPM_1)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	acpi_tcpa_t *tcpa = (acpi_tcpa_t *)header;
 | 
						acpi_tcpa_t *tcpa = (acpi_tcpa_t *)header;
 | 
				
			||||||
@@ -251,7 +253,7 @@ static void *get_tpm2_log(u32 *size)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void acpi_create_tpm2(acpi_header_t *header, void *unused)
 | 
					static void acpi_create_tpm2(acpi_header_t *header, void *unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!CONFIG(TPM2))
 | 
						if (tlcl_get_family() != TPM_2)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	acpi_tpm2_t *tpm2 = (acpi_tpm2_t *)header;
 | 
						acpi_tpm2_t *tpm2 = (acpi_tpm2_t *)header;
 | 
				
			||||||
@@ -271,7 +273,7 @@ static void acpi_create_tpm2(acpi_header_t *header, void *unused)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* Hard to detect for coreboot. Just set it to 0 */
 | 
						/* Hard to detect for coreboot. Just set it to 0 */
 | 
				
			||||||
	tpm2->platform_class = 0;
 | 
						tpm2->platform_class = 0;
 | 
				
			||||||
	if (CONFIG(CRB_TPM)) {
 | 
						if (CONFIG(CRB_TPM) && tpm2_has_crb_active()) {
 | 
				
			||||||
		/* Must be set to 7 for CRB Support */
 | 
							/* Must be set to 7 for CRB Support */
 | 
				
			||||||
		tpm2->control_area = CONFIG_CRB_TPM_BASE_ADDRESS + 0x40;
 | 
							tpm2->control_area = CONFIG_CRB_TPM_BASE_ADDRESS + 0x40;
 | 
				
			||||||
		tpm2->start_method = 7;
 | 
							tpm2->start_method = 7;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -142,6 +142,9 @@ static int smbios_write_type43_tpm(struct device *dev, int *handle, unsigned lon
 | 
				
			|||||||
	uint32_t fw_ver1, fw_ver2;
 | 
						uint32_t fw_ver1, fw_ver2;
 | 
				
			||||||
	uint8_t major_spec_ver, minor_spec_ver;
 | 
						uint8_t major_spec_ver, minor_spec_ver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tlcl_get_family() == TPM_1)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tpm2_get_info(&info);
 | 
						tpm2_get_info(&info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If any of these have invalid values, assume TPM not present or disabled */
 | 
						/* If any of these have invalid values, assume TPM not present or disabled */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -320,3 +320,29 @@ void tpm2_get_info(struct tpm2_info *tpm2_info)
 | 
				
			|||||||
	tpm2_info->device_id = (interfaceReg >> 32) & 0xFFFF;
 | 
						tpm2_info->device_id = (interfaceReg >> 32) & 0xFFFF;
 | 
				
			||||||
	tpm2_info->revision = (interfaceReg >> 24) & 0xFF;
 | 
						tpm2_info->revision = (interfaceReg >> 24) & 0xFF;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * tpm2_has_crb_active
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Checks that CRB interface is available and active.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The body was derived from crb_probe() which unlike this function can also
 | 
				
			||||||
 | 
					 * write to registers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool tpm2_has_crb_active(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint64_t tpmStatus = read64(CRB_REG(0, CRB_REG_INTF_ID));
 | 
				
			||||||
 | 
						printk(BIOS_SPEW, "Interface ID Reg. %llx\n", tpmStatus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((tpmStatus & CRB_INTF_REG_CAP_CRB) == 0) {
 | 
				
			||||||
 | 
							printk(BIOS_DEBUG, "TPM: CRB Interface is not supported.\n");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((tpmStatus & (0xf)) != 1) {
 | 
				
			||||||
 | 
							printk(BIOS_DEBUG, "TPM: CRB Interface is not active.\n");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,3 +64,4 @@ tpm_result_t tpm2_init(void);
 | 
				
			|||||||
void tpm2_get_info(struct tpm2_info *tpm2_info);
 | 
					void tpm2_get_info(struct tpm2_info *tpm2_info);
 | 
				
			||||||
size_t tpm2_process_command(const void *tpm2_command, size_t command_size,
 | 
					size_t tpm2_process_command(const void *tpm2_command, size_t command_size,
 | 
				
			||||||
			    void *tpm2_response, size_t max_response);
 | 
								    void *tpm2_response, size_t max_response);
 | 
				
			||||||
 | 
					bool tpm2_has_crb_active(void);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -809,7 +809,7 @@ static void lpc_tpm_fill_ssdt(const struct device *dev)
 | 
				
			|||||||
	acpigen_write_scope(path);
 | 
						acpigen_write_scope(path);
 | 
				
			||||||
	acpigen_write_device(acpi_device_name(dev));
 | 
						acpigen_write_device(acpi_device_name(dev));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (CONFIG(TPM2)) {
 | 
						if (tlcl_get_family() == TPM_2) {
 | 
				
			||||||
		acpigen_write_name_string("_HID", "MSFT0101");
 | 
							acpigen_write_name_string("_HID", "MSFT0101");
 | 
				
			||||||
		acpigen_write_name_string("_CID", "MSFT0101");
 | 
							acpigen_write_name_string("_CID", "MSFT0101");
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@
 | 
				
			|||||||
#include <acpi/acpi_device.h>
 | 
					#include <acpi/acpi_device.h>
 | 
				
			||||||
#include <cbmem.h>
 | 
					#include <cbmem.h>
 | 
				
			||||||
#include <console/console.h>
 | 
					#include <console/console.h>
 | 
				
			||||||
 | 
					#include <security/tpm/tss.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "tpm_ppi.h"
 | 
					#include "tpm_ppi.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -35,6 +36,8 @@ static void set_package_element_name(const char *package_name, unsigned int elem
 | 
				
			|||||||
/* PPI function is passed in src_op. Converted to Local2. Clobbers Local1 and Local2 */
 | 
					/* PPI function is passed in src_op. Converted to Local2. Clobbers Local1 and Local2 */
 | 
				
			||||||
static void verify_supported_ppi(uint8_t src_op)
 | 
					static void verify_supported_ppi(uint8_t src_op)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						enum tpm_family family = tlcl_get_family();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Old OSes incorrectly pass a Buffer instead of a Package.
 | 
						 * Old OSes incorrectly pass a Buffer instead of a Package.
 | 
				
			||||||
	 * See TCG Physical Presence Interface Specification Chapter 8.1.2 for details.
 | 
						 * See TCG Physical Presence Interface Specification Chapter 8.1.2 for details.
 | 
				
			||||||
@@ -62,7 +65,7 @@ static void verify_supported_ppi(uint8_t src_op)
 | 
				
			|||||||
	acpigen_write_store();
 | 
						acpigen_write_store();
 | 
				
			||||||
	acpigen_emit_namestring("^FSUP");
 | 
						acpigen_emit_namestring("^FSUP");
 | 
				
			||||||
	acpigen_emit_byte(LOCAL2_OP);
 | 
						acpigen_emit_byte(LOCAL2_OP);
 | 
				
			||||||
	acpigen_emit_byte(CONFIG(TPM1) ? ONE_OP : ZERO_OP);
 | 
						acpigen_emit_byte(family == TPM_1 ? ONE_OP : ZERO_OP);
 | 
				
			||||||
	acpigen_emit_byte(LOCAL1_OP);
 | 
						acpigen_emit_byte(LOCAL1_OP);
 | 
				
			||||||
	acpigen_write_if_lequal_op_int(LOCAL1_OP, 0);
 | 
						acpigen_write_if_lequal_op_int(LOCAL1_OP, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,7 +87,7 @@ static void verify_supported_ppi(uint8_t src_op)
 | 
				
			|||||||
	acpigen_write_store();
 | 
						acpigen_write_store();
 | 
				
			||||||
	acpigen_emit_namestring("^FSUP");
 | 
						acpigen_emit_namestring("^FSUP");
 | 
				
			||||||
	acpigen_emit_byte(LOCAL2_OP);
 | 
						acpigen_emit_byte(LOCAL2_OP);
 | 
				
			||||||
	acpigen_emit_byte(CONFIG(TPM1) ? ZERO_OP : ONE_OP);
 | 
						acpigen_emit_byte(family == TPM_1 ? ZERO_OP : ONE_OP);
 | 
				
			||||||
	acpigen_emit_byte(LOCAL1_OP);
 | 
						acpigen_emit_byte(LOCAL1_OP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	acpigen_write_if_lequal_op_int(LOCAL1_OP, 1);
 | 
						acpigen_write_if_lequal_op_int(LOCAL1_OP, 1);
 | 
				
			||||||
@@ -114,7 +117,7 @@ static void tpm_ppi_func0_cb(void *arg)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static void tpm_ppi_func1_cb(void *arg)
 | 
					static void tpm_ppi_func1_cb(void *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (CONFIG(TPM2))
 | 
						if (tlcl_get_family() == TPM_2)
 | 
				
			||||||
		/* Interface version: 1.3 */
 | 
							/* Interface version: 1.3 */
 | 
				
			||||||
		acpigen_write_return_string("1.3");
 | 
							acpigen_write_return_string("1.3");
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
@@ -400,6 +403,8 @@ static void tpm_ppi_func7_cb(void *arg)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static void tpm_ppi_func8_cb(void *arg)
 | 
					static void tpm_ppi_func8_cb(void *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						enum tpm_family family = tlcl_get_family();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	acpigen_write_to_integer(ARG1_OP, LOCAL0_OP);
 | 
						acpigen_write_to_integer(ARG1_OP, LOCAL0_OP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Revision 1 */
 | 
						/* Revision 1 */
 | 
				
			||||||
@@ -410,7 +415,7 @@ static void tpm_ppi_func8_cb(void *arg)
 | 
				
			|||||||
	acpigen_write_store();
 | 
						acpigen_write_store();
 | 
				
			||||||
	acpigen_emit_namestring("^FSUP");
 | 
						acpigen_emit_namestring("^FSUP");
 | 
				
			||||||
	acpigen_emit_byte(LOCAL2_OP);
 | 
						acpigen_emit_byte(LOCAL2_OP);
 | 
				
			||||||
	acpigen_emit_byte(CONFIG(TPM1) ? ONE_OP : ZERO_OP);
 | 
						acpigen_emit_byte(family == TPM_1 ? ONE_OP : ZERO_OP);
 | 
				
			||||||
	acpigen_emit_byte(LOCAL1_OP);
 | 
						acpigen_emit_byte(LOCAL1_OP);
 | 
				
			||||||
	acpigen_write_if_lequal_op_int(LOCAL1_OP, 0);
 | 
						acpigen_write_if_lequal_op_int(LOCAL1_OP, 0);
 | 
				
			||||||
	acpigen_write_return_byte(0);	/* Not implemented */
 | 
						acpigen_write_return_byte(0);	/* Not implemented */
 | 
				
			||||||
@@ -418,7 +423,7 @@ static void tpm_ppi_func8_cb(void *arg)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// FIXME: Only advertise supported functions
 | 
						// FIXME: Only advertise supported functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (CONFIG(TPM1)) {
 | 
						if (family == TPM_1) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Some functions do not require PP depending on configuration.
 | 
							 * Some functions do not require PP depending on configuration.
 | 
				
			||||||
		 * Those aren't listed here, so the 'required PP' is always set for those.
 | 
							 * Those aren't listed here, so the 'required PP' is always set for those.
 | 
				
			||||||
@@ -434,7 +439,7 @@ static void tpm_ppi_func8_cb(void *arg)
 | 
				
			|||||||
			acpigen_write_return_integer(PPI8_RET_ALLOWED);
 | 
								acpigen_write_return_integer(PPI8_RET_ALLOWED);
 | 
				
			||||||
			acpigen_pop_len();	/* Pop : If */
 | 
								acpigen_pop_len();	/* Pop : If */
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (CONFIG(TPM2)) {
 | 
						} else if (family == TPM_2) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Some functions do not require PP depending on configuration.
 | 
							 * Some functions do not require PP depending on configuration.
 | 
				
			||||||
		 * Those aren't listed here, so the 'required PP' is always set for those.
 | 
							 * Those aren't listed here, so the 'required PP' is always set for those.
 | 
				
			||||||
@@ -564,6 +569,12 @@ void tpm_ppi_acpi_fill_ssdt(const struct device *dev)
 | 
				
			|||||||
	printk(BIOS_DEBUG, "PPI: Pending OS request: 0x%x (0x%x)\n", ppib->pprq, ppib->pprm);
 | 
						printk(BIOS_DEBUG, "PPI: Pending OS request: 0x%x (0x%x)\n", ppib->pprq, ppib->pprm);
 | 
				
			||||||
	printk(BIOS_DEBUG, "PPI: OS response: CMD 0x%x = 0x%x\n", ppib->lppr, ppib->pprp);
 | 
						printk(BIOS_DEBUG, "PPI: OS response: CMD 0x%x = 0x%x\n", ppib->lppr, ppib->pprp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum tpm_family family = tlcl_get_family();
 | 
				
			||||||
 | 
						if (family == TPM_UNKNOWN) {
 | 
				
			||||||
 | 
							printk(BIOS_WARN, "PPI: %s: aborting, because no TPM detected\n", __func__);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Clear unsupported fields */
 | 
						/* Clear unsupported fields */
 | 
				
			||||||
	ppib->next_step = 0;
 | 
						ppib->next_step = 0;
 | 
				
			||||||
	ppib->ppin = 1; // Not used by ACPI. Read by EDK-2, must be 1.
 | 
						ppib->ppin = 1; // Not used by ACPI. Read by EDK-2, must be 1.
 | 
				
			||||||
@@ -574,7 +585,7 @@ void tpm_ppi_acpi_fill_ssdt(const struct device *dev)
 | 
				
			|||||||
	bool found = false;
 | 
						bool found = false;
 | 
				
			||||||
	/* Fill in defaults, the TPM command executor may overwrite this list */
 | 
						/* Fill in defaults, the TPM command executor may overwrite this list */
 | 
				
			||||||
	memset(ppib->func, 0, sizeof(ppib->func));
 | 
						memset(ppib->func, 0, sizeof(ppib->func));
 | 
				
			||||||
	if (CONFIG(TPM1)) {
 | 
						if (family == TPM_1) {
 | 
				
			||||||
		for (size_t i = 0; i < ARRAY_SIZE(tpm1_funcs); i++) {
 | 
							for (size_t i = 0; i < ARRAY_SIZE(tpm1_funcs); i++) {
 | 
				
			||||||
			ppib->func[tpm1_funcs[i]] = 1;
 | 
								ppib->func[tpm1_funcs[i]] = 1;
 | 
				
			||||||
			if (ppib->pprq == tpm1_funcs[i])
 | 
								if (ppib->pprq == tpm1_funcs[i])
 | 
				
			||||||
@@ -706,17 +717,24 @@ void tpm_ppi_acpi_fill_ssdt(const struct device *dev)
 | 
				
			|||||||
void lb_tpm_ppi(struct lb_header *header)
 | 
					void lb_tpm_ppi(struct lb_header *header)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct lb_tpm_physical_presence *tpm_ppi;
 | 
						struct lb_tpm_physical_presence *tpm_ppi;
 | 
				
			||||||
 | 
						enum tpm_family family;
 | 
				
			||||||
	void *ppib;
 | 
						void *ppib;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ppib = cbmem_find(CBMEM_ID_TPM_PPI);
 | 
						ppib = cbmem_find(CBMEM_ID_TPM_PPI);
 | 
				
			||||||
	if (!ppib)
 | 
						if (!ppib)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						family = tlcl_get_family();
 | 
				
			||||||
 | 
						if (family == TPM_UNKNOWN) {
 | 
				
			||||||
 | 
							printk(BIOS_WARN, "PPI: %s: aborting, because no TPM detected\n", __func__);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tpm_ppi = (struct lb_tpm_physical_presence *)lb_new_record(header);
 | 
						tpm_ppi = (struct lb_tpm_physical_presence *)lb_new_record(header);
 | 
				
			||||||
	tpm_ppi->tag = LB_TAG_TPM_PPI_HANDOFF;
 | 
						tpm_ppi->tag = LB_TAG_TPM_PPI_HANDOFF;
 | 
				
			||||||
	tpm_ppi->size = sizeof(*tpm_ppi);
 | 
						tpm_ppi->size = sizeof(*tpm_ppi);
 | 
				
			||||||
	tpm_ppi->ppi_address = (uintptr_t)ppib;
 | 
						tpm_ppi->ppi_address = (uintptr_t)ppib;
 | 
				
			||||||
	tpm_ppi->tpm_version = CONFIG(TPM1) ? LB_TPM_VERSION_TPM_VERSION_1_2 :
 | 
						tpm_ppi->tpm_version = family == TPM_1 ? LB_TPM_VERSION_TPM_VERSION_1_2 :
 | 
				
			||||||
		LB_TPM_VERSION_TPM_VERSION_2;
 | 
							LB_TPM_VERSION_TPM_VERSION_2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tpm_ppi->ppi_version = BCD(1, 3);
 | 
						tpm_ppi->ppi_version = BCD(1, 3);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,10 +9,8 @@
 | 
				
			|||||||
#include <types.h>
 | 
					#include <types.h>
 | 
				
			||||||
#include <vb2_sha.h>
 | 
					#include <vb2_sha.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if CONFIG(TPM_LOG_CB) && CONFIG(TPM1)
 | 
					#if CONFIG(TPM_LOG_CB)
 | 
				
			||||||
#  define TPM_MEASURE_ALGO VB2_HASH_SHA1
 | 
					#  define TPM_MEASURE_ALGO (tlcl_get_family() == TPM_1 ? VB2_HASH_SHA1 : VB2_HASH_SHA256)
 | 
				
			||||||
#elif CONFIG(TPM_LOG_CB) && CONFIG(TPM2)
 | 
					 | 
				
			||||||
#  define TPM_MEASURE_ALGO VB2_HASH_SHA256
 | 
					 | 
				
			||||||
#elif CONFIG(TPM_LOG_TPM1)
 | 
					#elif CONFIG(TPM_LOG_TPM1)
 | 
				
			||||||
#  define TPM_MEASURE_ALGO VB2_HASH_SHA1
 | 
					#  define TPM_MEASURE_ALGO VB2_HASH_SHA1
 | 
				
			||||||
#elif CONFIG(TPM_LOG_TPM2)
 | 
					#elif CONFIG(TPM_LOG_TPM2)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,9 @@ static tpm_result_t tpm1_invoke_state_machine(void)
 | 
				
			|||||||
	uint8_t deactivated;
 | 
						uint8_t deactivated;
 | 
				
			||||||
	tpm_result_t rc = TPM_SUCCESS;
 | 
						tpm_result_t rc = TPM_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tlcl_get_family() != TPM_1)
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check that the TPM is enabled and activated. */
 | 
						/* Check that the TPM is enabled and activated. */
 | 
				
			||||||
	rc = tlcl1_get_flags(&disabled, &deactivated, NULL);
 | 
						rc = tlcl1_get_flags(&disabled, &deactivated, NULL);
 | 
				
			||||||
	if (rc != TPM_SUCCESS) {
 | 
						if (rc != TPM_SUCCESS) {
 | 
				
			||||||
@@ -199,7 +202,7 @@ tpm_result_t tpm_clear_and_reenable(void)
 | 
				
			|||||||
		return rc;
 | 
							return rc;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if CONFIG(TPM1)
 | 
						if (tlcl_get_family() == TPM_1) {
 | 
				
			||||||
		rc = tlcl1_set_enable();
 | 
							rc = tlcl1_set_enable();
 | 
				
			||||||
		if (rc != TPM_SUCCESS) {
 | 
							if (rc != TPM_SUCCESS) {
 | 
				
			||||||
			printk(BIOS_ERR, "TPM Error (%#x): Can't set enabled state.\n", rc);
 | 
								printk(BIOS_ERR, "TPM Error (%#x): Can't set enabled state.\n", rc);
 | 
				
			||||||
@@ -211,7 +214,7 @@ tpm_result_t tpm_clear_and_reenable(void)
 | 
				
			|||||||
			printk(BIOS_ERR, "TPM Error (%#x): Can't set deactivated state.\n", rc);
 | 
								printk(BIOS_ERR, "TPM Error (%#x): Can't set deactivated state.\n", rc);
 | 
				
			||||||
			return rc;
 | 
								return rc;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
#endif
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return TPM_SUCCESS;
 | 
						return TPM_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,14 +33,29 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
tpm_result_t tlcl_lib_init(void);
 | 
					tpm_result_t tlcl_lib_init(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Commands */
 | 
					/**
 | 
				
			||||||
 | 
					 * Query active TPM family.  Returns TPM_UNKNOWN if uninitialized and TPM_1 or TPM_2 otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline enum tpm_family tlcl_get_family(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* Defined in tss/tss.c */
 | 
				
			||||||
	extern enum tpm_family tlcl_tpm_family;
 | 
						extern enum tpm_family tlcl_tpm_family;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (CONFIG(TPM1) && CONFIG(TPM2))
 | 
				
			||||||
 | 
							return tlcl_tpm_family;
 | 
				
			||||||
 | 
						if (CONFIG(TPM1))
 | 
				
			||||||
 | 
							return TPM_1;
 | 
				
			||||||
 | 
						if (CONFIG(TPM2))
 | 
				
			||||||
 | 
							return TPM_2;
 | 
				
			||||||
 | 
						return TPM_UNKNOWN;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Commands */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TLCL_CALL(name, ...) do {                         \
 | 
					#define TLCL_CALL(name, ...) do {                         \
 | 
				
			||||||
		if (CONFIG(TPM1) && (!CONFIG(TPM2) || tlcl_tpm_family == TPM_1)) \
 | 
							if (tlcl_get_family() == TPM_1)           \
 | 
				
			||||||
			return tlcl1_##name(__VA_ARGS__); \
 | 
								return tlcl1_##name(__VA_ARGS__); \
 | 
				
			||||||
		if (CONFIG(TPM2) && (!CONFIG(TPM1) || tlcl_tpm_family == TPM_2)) \
 | 
							if (tlcl_get_family() == TPM_2)           \
 | 
				
			||||||
			return tlcl2_##name(__VA_ARGS__); \
 | 
								return tlcl2_##name(__VA_ARGS__); \
 | 
				
			||||||
		return TPM_CB_INTERNAL_INCONSISTENCY;     \
 | 
							return TPM_CB_INTERNAL_INCONSISTENCY;     \
 | 
				
			||||||
	} while (0)
 | 
						} while (0)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ static tpm_result_t safe_write(uint32_t index, const void *data, uint32_t length
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
tpm_result_t antirollback_read_space_kernel(struct vb2_context *ctx)
 | 
					tpm_result_t antirollback_read_space_kernel(struct vb2_context *ctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!CONFIG(TPM2)) {
 | 
						if (tlcl_get_family() == TPM_1) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Before reading the kernel space, verify its permissions. If
 | 
							 * Before reading the kernel space, verify its permissions. If
 | 
				
			||||||
		 * the kernel space has the wrong permission, we give up. This
 | 
							 * the kernel space has the wrong permission, we give up. This
 | 
				
			||||||
@@ -224,12 +224,6 @@ static uint32_t define_space(const char *name, uint32_t index, uint32_t length,
 | 
				
			|||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Nothing special in the TPM2 path yet. */
 | 
					 | 
				
			||||||
static tpm_result_t safe_write(uint32_t index, const void *data, uint32_t length)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return tlcl_write(index, data, length);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static tpm_result_t setup_space(const char *name, uint32_t index, const void *data,
 | 
					static tpm_result_t setup_space(const char *name, uint32_t index, const void *data,
 | 
				
			||||||
				uint32_t length, const TPMA_NV nv_attributes,
 | 
									uint32_t length, const TPMA_NV nv_attributes,
 | 
				
			||||||
				const uint8_t *nv_policy, size_t nv_policy_size)
 | 
									const uint8_t *nv_policy, size_t nv_policy_size)
 | 
				
			||||||
@@ -376,7 +370,7 @@ static tpm_result_t setup_widevine_counter_spaces(void)
 | 
				
			|||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static tpm_result_t _factory_initialize_tpm(struct vb2_context *ctx)
 | 
					static tpm_result_t _factory_initialize_tpm2(struct vb2_context *ctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	RETURN_ON_FAILURE(tlcl_force_clear());
 | 
						RETURN_ON_FAILURE(tlcl_force_clear());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -426,11 +420,6 @@ static tpm_result_t _factory_initialize_tpm(struct vb2_context *ctx)
 | 
				
			|||||||
	return TPM_SUCCESS;
 | 
						return TPM_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tpm_result_t antirollback_lock_space_firmware(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return tlcl2_lock_nv_write(FIRMWARE_NV_INDEX);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
tpm_result_t antirollback_read_space_mrc_hash(uint32_t index, uint8_t *data, uint32_t size)
 | 
					tpm_result_t antirollback_read_space_mrc_hash(uint32_t index, uint8_t *data, uint32_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (size != HASH_NV_SIZE) {
 | 
						if (size != HASH_NV_SIZE) {
 | 
				
			||||||
@@ -521,25 +510,9 @@ tpm_result_t antirollback_write_space_vbios_hash(const uint8_t *data, uint32_t s
 | 
				
			|||||||
	return safe_write(VBIOS_CACHE_NV_INDEX, data, size);
 | 
						return safe_write(VBIOS_CACHE_NV_INDEX, data, size);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#endif /* CONFIG(TPM2) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					#if CONFIG(TPM1)
 | 
				
			||||||
 * 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
 | 
					 | 
				
			||||||
 * 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.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static tpm_result_t safe_write(uint32_t index, const void *data, uint32_t length)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	tpm_result_t rc = tlcl_write(index, data, length);
 | 
					 | 
				
			||||||
	if (rc == TPM_MAXNVWRITES) {
 | 
					 | 
				
			||||||
		RETURN_ON_FAILURE(tpm_clear_and_reenable());
 | 
					 | 
				
			||||||
		return tlcl_write(index, data, length);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return rc;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Similarly to safe_write(), this ensures we don't fail a DefineSpace because
 | 
					 * Similarly to safe_write(), this ensures we don't fail a DefineSpace because
 | 
				
			||||||
@@ -558,7 +531,7 @@ static tpm_result_t safe_define_space(uint32_t index, uint32_t perm, uint32_t si
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static tpm_result_t _factory_initialize_tpm(struct vb2_context *ctx)
 | 
					static tpm_result_t _factory_initialize_tpm1(struct vb2_context *ctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	TPM_PERMANENT_FLAGS pflags;
 | 
						TPM_PERMANENT_FLAGS pflags;
 | 
				
			||||||
	tpm_result_t rc;
 | 
						tpm_result_t rc;
 | 
				
			||||||
@@ -616,12 +589,45 @@ static tpm_result_t _factory_initialize_tpm(struct vb2_context *ctx)
 | 
				
			|||||||
	return TPM_SUCCESS;
 | 
						return TPM_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tpm_result_t antirollback_lock_space_firmware(void)
 | 
					#endif /* CONFIG(TPM1) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static tpm_result_t safe_write(uint32_t index, const void *data, uint32_t length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return tlcl1_set_global_lock();
 | 
						tpm_result_t rc = tlcl_write(index, data, length);
 | 
				
			||||||
 | 
						if (tlcl_get_family() == TPM_1 && rc == TPM_MAXNVWRITES) {
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * Clear the TPM on write error due to hitting the 64-write
 | 
				
			||||||
 | 
							 * limit.  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.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							RETURN_ON_FAILURE(tpm_clear_and_reenable());
 | 
				
			||||||
 | 
							rc = tlcl_write(index, data, length);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if CONFIG(TPM1)
 | 
				
			||||||
 | 
						if (tlcl_get_family() == TPM_1)
 | 
				
			||||||
 | 
							return _factory_initialize_tpm1(ctx);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#if CONFIG(TPM2)
 | 
				
			||||||
 | 
						if (tlcl_get_family() == TPM_2)
 | 
				
			||||||
 | 
							return _factory_initialize_tpm2(ctx);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						return TPM_CB_CORRUPTED_STATE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t antirollback_lock_space_firmware(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (tlcl_get_family() == TPM_1)
 | 
				
			||||||
 | 
							return tlcl1_set_global_lock();
 | 
				
			||||||
 | 
						if (tlcl_get_family() == TPM_2)
 | 
				
			||||||
 | 
							return tlcl2_lock_nv_write(FIRMWARE_NV_INDEX);
 | 
				
			||||||
 | 
						return TPM_CB_CORRUPTED_STATE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Perform one-time initializations.
 | 
					 * Perform one-time initializations.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
					/* SPDX-License-Identifier: GPL-2.0-only */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <security/tpm/tspi.h>
 | 
					#include <security/tpm/tspi.h>
 | 
				
			||||||
 | 
					#include <security/tpm/tss.h>
 | 
				
			||||||
#include <security/vboot/tpm_common.h>
 | 
					#include <security/vboot/tpm_common.h>
 | 
				
			||||||
#include <security/tpm/tss_errors.h>
 | 
					#include <security/tpm/tss_errors.h>
 | 
				
			||||||
#include <vb2_api.h>
 | 
					#include <vb2_api.h>
 | 
				
			||||||
@@ -43,7 +44,8 @@ tpm_result_t vboot_extend_pcr(struct vb2_context *ctx, int pcr,
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	_Static_assert(sizeof(buffer) >= VB2_SHA256_DIGEST_SIZE,
 | 
						_Static_assert(sizeof(buffer) >= VB2_SHA256_DIGEST_SIZE,
 | 
				
			||||||
		       "Buffer needs to be able to fit at least a SHA256");
 | 
							       "Buffer needs to be able to fit at least a SHA256");
 | 
				
			||||||
	enum vb2_hash_algorithm algo = CONFIG(TPM1) ? VB2_HASH_SHA1 : VB2_HASH_SHA256;
 | 
						enum vb2_hash_algorithm algo = tlcl_get_family() == TPM_1 ?
 | 
				
			||||||
 | 
							VB2_HASH_SHA1 : VB2_HASH_SHA256;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (which_digest) {
 | 
						switch (which_digest) {
 | 
				
			||||||
	/* SHA1 of (devmode|recmode|keyblock) bits */
 | 
						/* SHA1 of (devmode|recmode|keyblock) bits */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,11 @@ void cse_board_reset(void)
 | 
				
			|||||||
	if (CONFIG(CSE_RESET_CLEAR_EC_AP_IDLE_FLAG))
 | 
						if (CONFIG(CSE_RESET_CLEAR_EC_AP_IDLE_FLAG))
 | 
				
			||||||
		google_chromeec_clear_ec_ap_idle();
 | 
							google_chromeec_clear_ec_ap_idle();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Assuming that if particular TPM implementation is enabled at compile
 | 
				
			||||||
 | 
						 * time, it's the one being used.  This isn't generic code, so can
 | 
				
			||||||
 | 
						 * probably get away with it.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
	if (CONFIG(TPM2) && CONFIG(TPM_GOOGLE_CR50)) {
 | 
						if (CONFIG(TPM2) && CONFIG(TPM_GOOGLE_CR50)) {
 | 
				
			||||||
		/* Initialize TPM and get the cr50 firmware version. */
 | 
							/* Initialize TPM and get the cr50 firmware version. */
 | 
				
			||||||
		rc = tlcl_lib_init();
 | 
							rc = tlcl_lib_init();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,10 @@ static void disable_platform_hierarchy(void *unused)
 | 
				
			|||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* In case both families are enabled, but TPM1 is in use. */
 | 
				
			||||||
 | 
						if (tlcl_get_family() != TPM_2)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = tlcl2_disable_platform_hierarchy();
 | 
						rc = tlcl2_disable_platform_hierarchy();
 | 
				
			||||||
	if (rc != TPM_SUCCESS)
 | 
						if (rc != TPM_SUCCESS)
 | 
				
			||||||
		printk(BIOS_ERR, "Platform hierarchy disablement failed: %#x\n",
 | 
							printk(BIOS_ERR, "Platform hierarchy disablement failed: %#x\n",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user