security/tpm: Retrieve factory configuration for device w/ Google TPM
This patch enables retrieval of factory configuration data from Google TPM devices (both Cr50 and Ti50). This patch utilizes vendor-specific command TPM2_CR50_SUB_CMD_GET_FACTORY_CONFIG (68). The factory config space is a 64-bit, one-time programmable. For the unprovisioned one, the read will be 0x0. BUG=b:317880956 TEST=Able to retrieve the factory config from google/screebo. Change-Id: Ifd0e850770152a03aa46d7f8bbb76f7520a59081 Signed-off-by: Subrata Banik <subratabanik@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/79736 Reviewed-by: Kapil Porwal <kapilporwal@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
		| @@ -348,6 +348,9 @@ static int marshal_cr50_vendor_command(struct obuf *ob, const void *command_body | |||||||
| 	case TPM2_CR50_SUB_CMD_RESET_EC: | 	case TPM2_CR50_SUB_CMD_RESET_EC: | ||||||
| 		rc |= obuf_write_be16(ob, *sub_command); | 		rc |= obuf_write_be16(ob, *sub_command); | ||||||
| 		break; | 		break; | ||||||
|  | 	case TPM2_CR50_SUB_CMD_GET_FACTORY_CONFIG: | ||||||
|  | 		rc |= obuf_write_be16(ob, *sub_command); | ||||||
|  | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		/* Unsupported subcommand. */ | 		/* Unsupported subcommand. */ | ||||||
| 		printk(BIOS_WARNING, "Unsupported cr50 subcommand: 0x%04x\n", | 		printk(BIOS_WARNING, "Unsupported cr50 subcommand: 0x%04x\n", | ||||||
| @@ -581,6 +584,8 @@ static int unmarshal_vendor_command(struct ibuf *ib, | |||||||
| 		return ibuf_read_be8(ib, &vcr->boot_mode); | 		return ibuf_read_be8(ib, &vcr->boot_mode); | ||||||
| 	case TPM2_CR50_SUB_CMD_RESET_EC: | 	case TPM2_CR50_SUB_CMD_RESET_EC: | ||||||
| 		break; | 		break; | ||||||
|  | 	case TPM2_CR50_SUB_CMD_GET_FACTORY_CONFIG: | ||||||
|  | 		return ibuf_read_be64(ib, &vcr->factory_config); | ||||||
| 	default: | 	default: | ||||||
| 		printk(BIOS_ERR, | 		printk(BIOS_ERR, | ||||||
| 		       "%s:%d - unsupported vendor command %#04x!\n", | 		       "%s:%d - unsupported vendor command %#04x!\n", | ||||||
|   | |||||||
| @@ -352,6 +352,11 @@ struct vendor_command_response { | |||||||
| 		uint8_t recovery_button_state; | 		uint8_t recovery_button_state; | ||||||
| 		uint8_t tpm_mode; | 		uint8_t tpm_mode; | ||||||
| 		uint8_t boot_mode; | 		uint8_t boot_mode; | ||||||
|  | 		/* | ||||||
|  | 		 * bits 63..8 : reserved | ||||||
|  | 		 * bits 7..0 : factory config | ||||||
|  | 		 */ | ||||||
|  | 		uint64_t factory_config; | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								src/security/tpm/tss/vendor/cr50/cr50.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								src/security/tpm/tss/vendor/cr50/cr50.c
									
									
									
									
										vendored
									
									
								
							| @@ -176,3 +176,31 @@ tpm_result_t tlcl_cr50_reset_ec(void) | |||||||
|  |  | ||||||
| 	return TPM_SUCCESS; | 	return TPM_SUCCESS; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | tpm_result_t tlcl_cr50_get_factory_config(uint64_t *factory_config) | ||||||
|  | { | ||||||
|  | 	struct tpm2_response *response; | ||||||
|  | 	uint16_t factory_config_command = TPM2_CR50_SUB_CMD_GET_FACTORY_CONFIG; | ||||||
|  | 	*factory_config = 0; | ||||||
|  |  | ||||||
|  | 	response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &factory_config_command); | ||||||
|  |  | ||||||
|  | 	if (!response) | ||||||
|  | 		return TPM_IOERROR; | ||||||
|  |  | ||||||
|  | 	/* Explicitly inform caller when command is not supported */ | ||||||
|  | 	if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND || | ||||||
|  | 	    response->hdr.tpm_code == VENDOR_RC_NO_SUCH_SUBCOMMAND) | ||||||
|  | 		return TPM_CB_NO_SUCH_COMMAND; | ||||||
|  |  | ||||||
|  | 	/* Unexpected return code from TPM */ | ||||||
|  | 	if (response->hdr.tpm_code) | ||||||
|  | 		return TPM_IOERROR; | ||||||
|  |  | ||||||
|  | 	/* TPM command completed without error */ | ||||||
|  | 	*factory_config = response->vcr.factory_config; | ||||||
|  |  | ||||||
|  | 	printk(BIOS_INFO, "Reading factory config = %016" PRIX64 "\n", *factory_config); | ||||||
|  |  | ||||||
|  | 	return TPM_SUCCESS; | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								src/security/tpm/tss/vendor/cr50/cr50.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								src/security/tpm/tss/vendor/cr50/cr50.h
									
									
									
									
										vendored
									
									
								
							| @@ -17,6 +17,7 @@ | |||||||
| #define TPM2_CR50_SUB_CMD_TPM_MODE (40) | #define TPM2_CR50_SUB_CMD_TPM_MODE (40) | ||||||
| #define TPM2_CR50_SUB_CMD_GET_BOOT_MODE (52) | #define TPM2_CR50_SUB_CMD_GET_BOOT_MODE (52) | ||||||
| #define TPM2_CR50_SUB_CMD_RESET_EC (53) | #define TPM2_CR50_SUB_CMD_RESET_EC (53) | ||||||
|  | #define TPM2_CR50_SUB_CMD_GET_FACTORY_CONFIG (68) | ||||||
|  |  | ||||||
| /* Cr50 vendor-specific error codes. */ | /* Cr50 vendor-specific error codes. */ | ||||||
| #define VENDOR_RC_ERR              0x00000500 | #define VENDOR_RC_ERR              0x00000500 | ||||||
| @@ -105,4 +106,12 @@ tpm_result_t tlcl_cr50_immediate_reset(uint16_t timeout_ms); | |||||||
|  */ |  */ | ||||||
| tpm_result_t tlcl_cr50_reset_ec(void); | tpm_result_t tlcl_cr50_reset_ec(void); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * TPM command to get the factory config. | ||||||
|  |  * | ||||||
|  |  * Returns TPM_* for errors. | ||||||
|  |  * On Success, TPM_SUCCESS if factory config is successfully retrieved. | ||||||
|  |  */ | ||||||
|  | tpm_result_t tlcl_cr50_get_factory_config(uint64_t *factory_config); | ||||||
|  |  | ||||||
| #endif /* CR50_TSS_STRUCTURES_H_ */ | #endif /* CR50_TSS_STRUCTURES_H_ */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user