Hi Stefan,
As part of trying to better understand the TPM code, I found some changes to tcgbios.c were helpful. It's mostly code movement. I've only compile tested these changes, but I think they are safe.
I don't want to conflict with any changes you may have pending. So, let me know if this is a problem.
The series is on top of your latest patches. (FYI, I made a minor change to a comment in your patch 2.) I've also put this series (and your series) up at:
https://github.com/KevinOConnor/seabios/tree/testing
-Kevin
Kevin O'Connor (7): tpm: Add "static" declaration to functions not used outside tcgbios.c tpm: Move code around in tcgbios.c tpm: Move error recovery from tpm_extend_acpi_log() to only caller tpm: Open code tpm_ipl() into callers tpm: Change tpm_add_measurement() to tpm_add_action() tpm: Move tpm_add_bootdevice() into callers tpm: Move tpm_start_option_rom_scan() and tpm_calling_int19h() into callers
src/tcgbios.c | 1258 +++++++++++++++++++++++++-------------------------------- 1 file changed, 556 insertions(+), 702 deletions(-)
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/tcgbios.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index 5229b4e..341ab9d 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -1136,7 +1136,7 @@ tpm_calling_int19h(void) /* * Add event separators for PCRs 0 to 7; specs on 'Measuring Boot Events' */ -u32 +static u32 tpm_add_event_separators(void) { u32 rc; @@ -1205,7 +1205,7 @@ tpm_add_bootdevice(u32 bootcd, u32 bootdrv) /* * Add measurement to the log about option rom scan */ -u32 +static u32 tpm_start_option_rom_scan(void) { if (!CONFIG_TCGBIOS) @@ -1248,7 +1248,7 @@ tpm_option_rom(const void *addr, u32 len) }
-u32 +static u32 tpm_smbios_measure(void) { if (!CONFIG_TCGBIOS)
Move like functions near each other. Reduce forward function declarations. This is only code movement - no code changes.
This groups the code into six sections: TPM state tracking, TPM hardware interface, ACPI TCPA table interface, Helper functions, Setup and Measurements, BIOS interface.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/tcgbios.c | 1377 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 681 insertions(+), 696 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index 341ab9d..7877840 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -58,31 +58,9 @@ static const u8 GetCapability_Durations[] = { static u8 evt_separator[] = {0xff,0xff,0xff,0xff};
-#define RSDP_CAST(ptr) ((struct rsdp_descriptor *)ptr) - -/* local function prototypes */ - -static u32 build_and_send_cmd(u8 locty, u32 ordinal, - const u8 *append, u32 append_size, - u8 *resbuffer, u32 return_size, u32 *returnCode, - enum tpmDurationType to_t); -static u32 tpm_calling_int19h(void); -static u32 tpm_add_event_separators(void); -static u32 tpm_start_option_rom_scan(void); -static u32 tpm_smbios_measure(void); - -/* helper functions */ - -static inline void *input_buf32(struct bregs *regs) -{ - return MAKE_FLATPTR(regs->es, regs->di); -} - -static inline void *output_buf32(struct bregs *regs) -{ - return MAKE_FLATPTR(regs->ds, regs->si); -} - +/**************************************************************** + * TPM state tracking + ****************************************************************/
typedef struct { u8 tpm_probed:1; @@ -108,16 +86,20 @@ typedef struct { u8 * log_area_last_entry; } tpm_state_t;
- tpm_state_t tpm_state VARLOW = { .tpm_driver_to_use = TPM_INVALID_DRIVER, };
+static u32 +is_preboot_if_shutdown(void) +{ + return tpm_state.if_shutdown; +}
-/******************************************************** - Extensions for TCG-enabled BIOS - *******************************************************/
+/**************************************************************** + * TPM hardware interface + ****************************************************************/
static u32 is_tpm_present(void) @@ -156,31 +138,57 @@ has_working_tpm(void) return tpm_state.tpm_working; }
-static void -tpm_set_failure(void) +static u32 +transmit(u8 locty, const struct iovec iovec[], + u8 *respbuffer, u32 *respbufferlen, + enum tpmDurationType to_t) { - u32 returnCode; + u32 rc = 0; + u32 irc; + struct tpm_driver *td; + unsigned int i;
- /* we will try to deactivate the TPM now - ignoring all errors */ - build_and_send_cmd(0, TPM_ORD_PhysicalPresence, - PhysicalPresence_CMD_ENABLE, - sizeof(PhysicalPresence_CMD_ENABLE), - NULL, 0, &returnCode, - TPM_DURATION_TYPE_SHORT); + if (tpm_state.tpm_driver_to_use == TPM_INVALID_DRIVER) + return TCG_FATAL_COM_ERROR;
- build_and_send_cmd(0, TPM_ORD_PhysicalPresence, - PhysicalPresence_PRESENT, - sizeof(PhysicalPresence_PRESENT), - NULL, 0, &returnCode, - TPM_DURATION_TYPE_SHORT); + td = &tpm_drivers[tpm_state.tpm_driver_to_use];
- build_and_send_cmd(0, TPM_ORD_SetTempDeactivated, - NULL, 0, NULL, 0, &returnCode, - TPM_DURATION_TYPE_SHORT); + irc = td->activate(locty); + if (irc != 0) { + /* tpm could not be activated */ + return TCG_FATAL_COM_ERROR; + }
- tpm_state.tpm_working = 0; + for (i = 0; iovec[i].length; i++) { + irc = td->senddata(iovec[i].data, + iovec[i].length); + if (irc != 0) + return TCG_FATAL_COM_ERROR; + } + + irc = td->waitdatavalid(); + if (irc != 0) + return TCG_FATAL_COM_ERROR; + + irc = td->waitrespready(to_t); + if (irc != 0) + return TCG_FATAL_COM_ERROR; + + irc = td->readresp(respbuffer, + respbufferlen); + if (irc != 0) + return TCG_FATAL_COM_ERROR; + + td->ready(); + + return rc; }
+ +/**************************************************************** + * ACPI TCPA table interface + ****************************************************************/ + static struct tcpa_descriptor_rev2 * find_tcpa_by_rsdp(struct rsdp_descriptor *rsdp) { @@ -218,7 +226,6 @@ find_tcpa_by_rsdp(struct rsdp_descriptor *rsdp) return tcpa; }
- static struct tcpa_descriptor_rev2 * find_tcpa_table(void) { @@ -242,7 +249,6 @@ find_tcpa_table(void) return tcpa; }
- static u8 * get_lasa_base_ptr(u32 *log_area_minimum_length) { @@ -258,7 +264,6 @@ get_lasa_base_ptr(u32 *log_area_minimum_length) return log_area_start_address; }
- /* clear the ACPI log */ static void reset_acpi_log(void) @@ -275,75 +280,72 @@ reset_acpi_log(void) tpm_state.entry_count = 0; }
+static void tpm_set_failure(void);
/* - initialize the TCPA ACPI subsystem; find the ACPI tables and determine - where the TCPA table is. + * Extend the ACPI log with the given entry by copying the + * entry data into the log. + * Input + * pcpes : Pointer to the event 'header' to be copied into the log + * event : Pointer to the event 'body' to be copied into the log + * event_length: Length of the event array + * entry_count : optional pointer to get the current entry count + * + * Output: + * Returns an error code in case of faiure, 0 in case of success */ -static void -tpm_acpi_init(void) +static u32 +tpm_extend_acpi_log(struct pcpes *pcpes, + const char *event, u32 event_length, + u16 *entry_count) { - tpm_state.if_shutdown = 0; - tpm_state.tpm_probed = 0; - tpm_state.tpm_found = 0; - tpm_state.tpm_working = 0; + u32 size;
- if (!has_working_tpm()) { - tpm_state.if_shutdown = 1; - return; - } + if (!has_working_tpm()) + return TCG_GENERAL_ERROR;
- reset_acpi_log(); -} + dprintf(DEBUG_tcg, "TCGBIOS: LASA = %p, next entry = %p\n", + tpm_state.log_area_start_address, tpm_state.log_area_next_entry);
+ if (tpm_state.log_area_next_entry == NULL) {
-static u32 -transmit(u8 locty, const struct iovec iovec[], - u8 *respbuffer, u32 *respbufferlen, - enum tpmDurationType to_t) -{ - u32 rc = 0; - u32 irc; - struct tpm_driver *td; - unsigned int i; + tpm_set_failure();
- if (tpm_state.tpm_driver_to_use == TPM_INVALID_DRIVER) - return TCG_FATAL_COM_ERROR; + return TCG_PC_LOGOVERFLOW; + }
- td = &tpm_drivers[tpm_state.tpm_driver_to_use]; + size = offsetof(struct pcpes, event) + event_length;
- irc = td->activate(locty); - if (irc != 0) { - /* tpm could not be activated */ - return TCG_FATAL_COM_ERROR; - } + if ((tpm_state.log_area_next_entry + size - tpm_state.log_area_start_address) > + tpm_state.log_area_minimum_length) { + dprintf(DEBUG_tcg, "TCGBIOS: LOG OVERFLOW: size = %d\n", size);
- for (i = 0; iovec[i].length; i++) { - irc = td->senddata(iovec[i].data, - iovec[i].length); - if (irc != 0) - return TCG_FATAL_COM_ERROR; + tpm_set_failure(); + + return TCG_PC_LOGOVERFLOW; }
- irc = td->waitdatavalid(); - if (irc != 0) - return TCG_FATAL_COM_ERROR; + pcpes->eventdatasize = event_length;
- irc = td->waitrespready(to_t); - if (irc != 0) - return TCG_FATAL_COM_ERROR; + memcpy(tpm_state.log_area_next_entry, pcpes, offsetof(struct pcpes, event)); + memcpy(tpm_state.log_area_next_entry + offsetof(struct pcpes, event), + event, event_length);
- irc = td->readresp(respbuffer, - respbufferlen); - if (irc != 0) - return TCG_FATAL_COM_ERROR; + tpm_state.log_area_last_entry = tpm_state.log_area_next_entry; + tpm_state.log_area_next_entry += size; + tpm_state.entry_count++;
- td->ready(); + if (entry_count) + *entry_count = tpm_state.entry_count;
- return rc; + return 0; }
+/**************************************************************** + * Helper functions + ****************************************************************/ + /* * Send a TPM command with the given ordinal. Append the given buffer * containing all data in network byte order to the command (this is @@ -393,6 +395,31 @@ build_and_send_cmd(u8 locty, u32 ordinal, const u8 *append, u32 append_size, return 0; }
+static void +tpm_set_failure(void) +{ + u32 returnCode; + + /* we will try to deactivate the TPM now - ignoring all errors */ + build_and_send_cmd(0, TPM_ORD_PhysicalPresence, + PhysicalPresence_CMD_ENABLE, + sizeof(PhysicalPresence_CMD_ENABLE), + NULL, 0, &returnCode, + TPM_DURATION_TYPE_SHORT); + + build_and_send_cmd(0, TPM_ORD_PhysicalPresence, + PhysicalPresence_PRESENT, + sizeof(PhysicalPresence_PRESENT), + NULL, 0, &returnCode, + TPM_DURATION_TYPE_SHORT); + + build_and_send_cmd(0, TPM_ORD_SetTempDeactivated, + NULL, 0, NULL, 0, &returnCode, + TPM_DURATION_TYPE_SHORT); + + tpm_state.tpm_working = 0; +} + static u32 determine_timeouts(void) { @@ -458,47 +485,283 @@ err_exit: return TCG_TCG_COMMAND_ERROR; }
- static u32 -tpm_startup(void) +pass_through_to_tpm(u8 locty, const u8 *cmd, u32 cmd_length, + u8 *resp, u32 *resp_length) { - u32 rc; - u32 returnCode; + struct iovec iovec[2] = {{ 0 }}; + const u32 *tmp;
- if (!has_working_tpm()) - return TCG_GENERAL_ERROR; + if (cmd_length < TPM_REQ_HEADER_SIZE) + return TCG_INVALID_INPUT_PARA;
- dprintf(DEBUG_tcg, "TCGBIOS: Starting with TPM_Startup(ST_CLEAR)\n"); - rc = build_and_send_cmd(0, TPM_ORD_Startup, - Startup_ST_CLEAR, sizeof(Startup_ST_CLEAR), - NULL, 0, &returnCode, TPM_DURATION_TYPE_SHORT); + iovec[0].data = cmd; + tmp = (const u32 *)&((u8 *)iovec[0].data)[2]; + iovec[0].length = cpu_to_be32(*tmp);
- dprintf(DEBUG_tcg, "Return code from TPM_Startup = 0x%08x\n", - returnCode); + if (cmd_length != iovec[0].length) + return TCG_INVALID_INPUT_PARA;
- if (CONFIG_COREBOOT) { - /* with other firmware on the system the TPM may already have been - * initialized - */ - if (returnCode == TPM_INVALID_POSTINIT) - returnCode = 0; - } + return transmit(locty, iovec, resp, resp_length, + TPM_DURATION_TYPE_LONG /* worst case */);
- if (rc || returnCode) - goto err_exit; +}
- rc = determine_timeouts(); - if (rc) - goto err_exit; +static u32 +tpm_extend(u8 *hash, u32 pcrindex) +{ + u32 rc; + struct tpm_req_extend tre = { + .tag = cpu_to_be16(TPM_TAG_RQU_CMD), + .totlen = cpu_to_be32(sizeof(tre)), + .ordinal = cpu_to_be32(TPM_ORD_Extend), + .pcrindex = cpu_to_be32(pcrindex), + }; + struct tpm_rsp_extend rsp; + u32 resp_length = sizeof(rsp);
- rc = build_and_send_cmd(0, TPM_ORD_SelfTestFull, NULL, 0, - NULL, 0, &returnCode, TPM_DURATION_TYPE_LONG); + memcpy(tre.digest, hash, sizeof(tre.digest));
- dprintf(DEBUG_tcg, "Return code from TPM_SelfTestFull = 0x%08x\n", - returnCode); + rc = pass_through_to_tpm(0, (u8 *)&tre, sizeof(tre), + (u8 *)&rsp, &resp_length);
- if (rc || returnCode) - goto err_exit; + if (rc || resp_length != sizeof(rsp)) + tpm_set_failure(); + + return rc; +} + +static u32 +hash_log_event(const void *hashdata, u32 hashdata_length, + struct pcpes *pcpes, + const char *event, u32 event_length, + u16 *entry_count) +{ + u32 rc = 0; + + if (pcpes->pcrindex >= 24) + return TCG_INVALID_INPUT_PARA; + + if (hashdata) { + rc = sha1(hashdata, hashdata_length, pcpes->digest); + if (rc) + return rc; + } + + return tpm_extend_acpi_log(pcpes, event, event_length, entry_count); +} + +static u32 +hash_log_extend_event(const void *hashdata, u32 hashdata_length, + struct pcpes *pcpes, + const char *event, u32 event_length, + u32 pcrindex, u16 *entry_count) +{ + u32 rc; + + rc = hash_log_event(hashdata, hashdata_length, pcpes, + event, event_length, entry_count); + if (rc) + return rc; + + return tpm_extend(pcpes->digest, pcrindex); +} + +/* + * Add a measurement to the log; the data at data_seg:data/length are + * appended to the TCG_PCClientPCREventStruct + * + * Input parameters: + * pcrindex : which PCR to extend + * event_type : type of event; specs section on 'Event Types' + * event : pointer to info (e.g., string) to be added to log as-is + * event_length: length of the event + * hashdata : pointer to the data to be hashed + * hashdata_length: length of the data to be hashed + */ +static u32 +tpm_add_measurement_to_log(u32 pcrindex, u32 event_type, + const char *event, u32 event_length, + const u8 *hashdata, u32 hashdata_length) +{ + struct pcpes pcpes = { + .pcrindex = pcrindex, + .eventtype = event_type, + }; + u16 entry_count; + + return hash_log_extend_event(hashdata, hashdata_length, &pcpes, + event, event_length, pcrindex, + &entry_count); +} + + +/**************************************************************** + * Setup and Measurements + ****************************************************************/ + +/* + * Add a measurement to the list of measurements + * pcrIndex : PCR to be extended + * event_type : type of event; specs section on 'Event Types' + * data : additional parameter; used as parameter for + * 'action index' + */ +static u32 +tpm_add_measurement(u32 pcrIndex, + u16 event_type, + const char *string) +{ + u32 rc; + u32 len; + + switch (event_type) { + case EV_SEPARATOR: + len = sizeof(evt_separator); + rc = tpm_add_measurement_to_log(pcrIndex, event_type, + (char *)NULL, 0, + (u8 *)evt_separator, len); + break; + + case EV_ACTION: + rc = tpm_add_measurement_to_log(pcrIndex, event_type, + string, strlen(string), + (u8 *)string, strlen(string)); + break; + + default: + rc = TCG_INVALID_INPUT_PARA; + } + + return rc; +} + +static u32 +tpm_calling_int19h(void) +{ + if (!CONFIG_TCGBIOS) + return 0; + + if (!has_working_tpm()) + return TCG_GENERAL_ERROR; + + return tpm_add_measurement(4, EV_ACTION, + "Calling INT 19h"); +} + +/* + * Add event separators for PCRs 0 to 7; specs on 'Measuring Boot Events' + */ +static u32 +tpm_add_event_separators(void) +{ + u32 rc; + u32 pcrIndex = 0; + + if (!CONFIG_TCGBIOS) + return 0; + + if (!has_working_tpm()) + return TCG_GENERAL_ERROR; + + while (pcrIndex <= 7) { + rc = tpm_add_measurement(pcrIndex, EV_SEPARATOR, NULL); + if (rc) + break; + pcrIndex ++; + } + + return rc; +} + +/* + * Add measurement to the log about option rom scan + */ +static u32 +tpm_start_option_rom_scan(void) +{ + if (!CONFIG_TCGBIOS) + return 0; + + if (!has_working_tpm()) + return TCG_GENERAL_ERROR; + + return tpm_add_measurement(2, EV_ACTION, + "Start Option ROM Scan"); +} + +static u32 +tpm_smbios_measure(void) +{ + if (!CONFIG_TCGBIOS) + return 0; + + if (!has_working_tpm()) + return TCG_GENERAL_ERROR; + + u32 rc; + struct pcctes pcctes = { + .eventid = 1, + .eventdatasize = SHA1_BUFSIZE, + }; + struct smbios_entry_point *sep = SMBiosAddr; + + dprintf(DEBUG_tcg, "TCGBIOS: SMBIOS at %p\n", sep); + + if (!sep) + return 0; + + rc = sha1((const u8 *)sep->structure_table_address, + sep->structure_table_length, pcctes.digest); + if (rc) + return rc; + + return tpm_add_measurement_to_log(1, + EV_EVENT_TAG, + (const char *)&pcctes, sizeof(pcctes), + (u8 *)&pcctes, sizeof(pcctes)); +} + +static u32 +tpm_startup(void) +{ + u32 rc; + u32 returnCode; + + if (!has_working_tpm()) + return TCG_GENERAL_ERROR; + + dprintf(DEBUG_tcg, "TCGBIOS: Starting with TPM_Startup(ST_CLEAR)\n"); + rc = build_and_send_cmd(0, TPM_ORD_Startup, + Startup_ST_CLEAR, sizeof(Startup_ST_CLEAR), + NULL, 0, &returnCode, TPM_DURATION_TYPE_SHORT); + + dprintf(DEBUG_tcg, "Return code from TPM_Startup = 0x%08x\n", + returnCode); + + if (CONFIG_COREBOOT) { + /* with other firmware on the system the TPM may already have been + * initialized + */ + if (returnCode == TPM_INVALID_POSTINIT) + returnCode = 0; + } + + if (rc || returnCode) + goto err_exit; + + rc = determine_timeouts(); + if (rc) + goto err_exit; + + rc = build_and_send_cmd(0, TPM_ORD_SelfTestFull, NULL, 0, + NULL, 0, &returnCode, TPM_DURATION_TYPE_LONG); + + dprintf(DEBUG_tcg, "Return code from TPM_SelfTestFull = 0x%08x\n", + returnCode); + + if (rc || returnCode) + goto err_exit;
rc = build_and_send_cmd(3, TSC_ORD_ResetEstablishmentBit, NULL, 0, NULL, 0, &returnCode, TPM_DURATION_TYPE_SHORT); @@ -528,6 +791,25 @@ err_exit: return TCG_TCG_COMMAND_ERROR; }
+/* + initialize the TCPA ACPI subsystem; find the ACPI tables and determine + where the TCPA table is. + */ +static void +tpm_acpi_init(void) +{ + tpm_state.if_shutdown = 0; + tpm_state.tpm_probed = 0; + tpm_state.tpm_found = 0; + tpm_state.tpm_working = 0; + + if (!has_working_tpm()) { + tpm_state.if_shutdown = 1; + return; + } + + reset_acpi_log(); +}
void tpm_setup(void) @@ -542,7 +824,6 @@ tpm_setup(void) tpm_startup(); }
- void tpm_prepboot(void) { @@ -586,275 +867,221 @@ err_exit: }
/* - * Extend the ACPI log with the given entry by copying the - * entry data into the log. - * Input - * pcpes : Pointer to the event 'header' to be copied into the log - * event : Pointer to the event 'body' to be copied into the log - * event_length: Length of the event array - * entry_count : optional pointer to get the current entry count - * - * Output: - * Returns an error code in case of faiure, 0 in case of success + * Add measurement to the log about an option rom */ -static u32 -tpm_extend_acpi_log(struct pcpes *pcpes, - const char *event, u32 event_length, - u16 *entry_count) +u32 +tpm_option_rom(const void *addr, u32 len) { - u32 size; + if (!CONFIG_TCGBIOS) + return 0;
if (!has_working_tpm()) return TCG_GENERAL_ERROR;
- dprintf(DEBUG_tcg, "TCGBIOS: LASA = %p, next entry = %p\n", - tpm_state.log_area_start_address, tpm_state.log_area_next_entry); - - if (tpm_state.log_area_next_entry == NULL) { + u32 rc; + struct pcctes_romex pcctes = { + .eventid = 7, + .eventdatasize = sizeof(u16) + sizeof(u16) + SHA1_BUFSIZE, + };
- tpm_set_failure(); + rc = sha1((const u8 *)addr, len, pcctes.digest); + if (rc) + return rc;
- return TCG_PC_LOGOVERFLOW; - } + return tpm_add_measurement_to_log(2, + EV_EVENT_TAG, + (const char *)&pcctes, sizeof(pcctes), + (u8 *)&pcctes, sizeof(pcctes)); +}
- size = offsetof(struct pcpes, event) + event_length; +/* + * Add a measurement regarding the boot device (CDRom, Floppy, HDD) to + * the list of measurements. + */ +static u32 +tpm_add_bootdevice(u32 bootcd, u32 bootdrv) +{ + const char *string;
- if ((tpm_state.log_area_next_entry + size - tpm_state.log_area_start_address) > - tpm_state.log_area_minimum_length) { - dprintf(DEBUG_tcg, "TCGBIOS: LOG OVERFLOW: size = %d\n", size); + if (!CONFIG_TCGBIOS) + return 0;
- tpm_set_failure(); + if (!has_working_tpm()) + return TCG_GENERAL_ERROR;
- return TCG_PC_LOGOVERFLOW; - } + switch (bootcd) { + case 0: + switch (bootdrv) { + case 0: + string = "Booting BCV device 00h (Floppy)"; + break;
- pcpes->eventdatasize = event_length; + case 0x80: + string = "Booting BCV device 80h (HDD)"; + break;
- memcpy(tpm_state.log_area_next_entry, pcpes, offsetof(struct pcpes, event)); - memcpy(tpm_state.log_area_next_entry + offsetof(struct pcpes, event), - event, event_length); + default: + string = "Booting unknown device"; + break; + }
- tpm_state.log_area_last_entry = tpm_state.log_area_next_entry; - tpm_state.log_area_next_entry += size; - tpm_state.entry_count++; + break;
- if (entry_count) - *entry_count = tpm_state.entry_count; + default: + string = "Booting from CD ROM device"; + }
- return 0; + return tpm_add_measurement_to_log(4, EV_ACTION, + string, strlen(string), + (u8 *)string, strlen(string)); }
- +/* + * Add a measurement related to Initial Program Loader to the log. + * Creates two log entries. + * + * Input parameter: + * bootcd : 0: MBR of hdd, 1: boot image, 2: boot catalog of El Torito + * addr : address where the IP data are located + * length : IP data length in bytes + */ static u32 -is_preboot_if_shutdown(void) +tpm_ipl(enum ipltype bootcd, const u8 *addr, u32 length) { - return tpm_state.if_shutdown; -} + u32 rc; + const char *string;
+ switch (bootcd) { + case IPL_EL_TORITO_1: + /* specs: see section 'El Torito' */ + string = "EL TORITO IPL"; + rc = tpm_add_measurement_to_log(4, EV_IPL, + string, strlen(string), + addr, length); + break;
-static u32 -shutdown_preboot_interface(void) -{ - u32 rc = 0; + case IPL_EL_TORITO_2: + /* specs: see section 'El Torito' */ + string = "BOOT CATALOG"; + rc = tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA, + string, strlen(string), + addr, length); + break;
- if (!is_preboot_if_shutdown()) { - tpm_state.if_shutdown = 1; - } else { - rc = TCG_INTERFACE_SHUTDOWN; + default: + /* specs: see section 'Hard Disk Device or Hard Disk-Like Devices' */ + /* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */ + string = "MBR"; + rc = tpm_add_measurement_to_log(4, EV_IPL, + string, strlen(string), + addr, 0x1b8); + + if (rc) + break; + + /* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */ + string = "MBR PARTITION_TABLE"; + rc = tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA, + string, strlen(string), + addr + 0x1b8, 0x48); }
return rc; }
-static u32 -pass_through_to_tpm(u8 locty, const u8 *cmd, u32 cmd_length, - u8 *resp, u32 *resp_length) +u32 +tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length) { - struct iovec iovec[2] = {{ 0 }}; - const u32 *tmp; - - if (cmd_length < TPM_REQ_HEADER_SIZE) - return TCG_INVALID_INPUT_PARA; - - iovec[0].data = cmd; - tmp = (const u32 *)&((u8 *)iovec[0].data)[2]; - iovec[0].length = cpu_to_be32(*tmp); + if (!CONFIG_TCGBIOS) + return 0;
- if (cmd_length != iovec[0].length) - return TCG_INVALID_INPUT_PARA; + if (!has_working_tpm()) + return TCG_GENERAL_ERROR;
- return transmit(locty, iovec, resp, resp_length, - TPM_DURATION_TYPE_LONG /* worst case */); + u32 rc = tpm_add_bootdevice(0, bootdrv); + if (rc) + return rc;
+ return tpm_ipl(IPL_BCV, addr, length); }
-static u32 -pass_through_to_tpm_int(struct pttti *pttti, struct pttto *pttto) +u32 +tpm_add_cdrom(u32 bootdrv, const u8 *addr, u32 length) { - u32 rc = 0; - u32 resbuflen = 0; - struct tpm_req_header *trh; + if (!CONFIG_TCGBIOS) + return 0;
- if (is_preboot_if_shutdown()) { - rc = TCG_INTERFACE_SHUTDOWN; - goto err_exit; - } + if (!has_working_tpm()) + return TCG_GENERAL_ERROR;
- trh = (struct tpm_req_header *)pttti->tpmopin; + u32 rc = tpm_add_bootdevice(1, bootdrv); + if (rc) + return rc;
- if (pttti->ipblength < sizeof(struct pttti) + TPM_REQ_HEADER_SIZE || - pttti->opblength < sizeof(struct pttto) || - be32_to_cpu(trh->totlen) + sizeof(struct pttti) > pttti->ipblength ) { - rc = TCG_INVALID_INPUT_PARA; - goto err_exit; - } + return tpm_ipl(IPL_EL_TORITO_1, addr, length); +}
- resbuflen = pttti->opblength - offsetof(struct pttto, tpmopout); +u32 +tpm_add_cdrom_catalog(const u8 *addr, u32 length) +{ + if (!CONFIG_TCGBIOS) + return 0;
- rc = pass_through_to_tpm(0, pttti->tpmopin, - pttti->ipblength - offsetof(struct pttti, tpmopin), - pttto->tpmopout, &resbuflen); + if (!has_working_tpm()) + return TCG_GENERAL_ERROR;
+ u32 rc = tpm_add_bootdevice(1, 0); if (rc) - goto err_exit; - - pttto->opblength = offsetof(struct pttto, tpmopout) + resbuflen; - pttto->reserved = 0; - -err_exit: - if (rc != 0) { - pttto->opblength = 4; - pttto->reserved = 0; - } + return rc;
- return rc; + return tpm_ipl(IPL_EL_TORITO_2, addr, length); }
- -static u32 -tpm_extend(u8 *hash, u32 pcrindex) +void +tpm_s3_resume(void) { u32 rc; - struct tpm_req_extend tre = { - .tag = cpu_to_be16(TPM_TAG_RQU_CMD), - .totlen = cpu_to_be32(sizeof(tre)), - .ordinal = cpu_to_be32(TPM_ORD_Extend), - .pcrindex = cpu_to_be32(pcrindex), - }; - struct tpm_rsp_extend rsp; - u32 resp_length = sizeof(rsp); + u32 returnCode;
- memcpy(tre.digest, hash, sizeof(tre.digest)); + if (!CONFIG_TCGBIOS) + return;
- rc = pass_through_to_tpm(0, (u8 *)&tre, sizeof(tre), - (u8 *)&rsp, &resp_length); + if (!has_working_tpm()) + return;
- if (rc || resp_length != sizeof(rsp)) - tpm_set_failure(); + dprintf(DEBUG_tcg, "TCGBIOS: Resuming with TPM_Startup(ST_STATE)\n");
- return rc; -} + rc = build_and_send_cmd(0, TPM_ORD_Startup, + Startup_ST_STATE, sizeof(Startup_ST_STATE), + NULL, 0, &returnCode, TPM_DURATION_TYPE_SHORT);
+ dprintf(DEBUG_tcg, "TCGBIOS: ReturnCode from TPM_Startup = 0x%08x\n", + returnCode);
-static u32 -hash_all_int(const struct hai *hai, u8 *hash) -{ - if (is_preboot_if_shutdown() != 0) - return TCG_INTERFACE_SHUTDOWN; - - if (hai->ipblength != sizeof(struct hai) || - hai->hashdataptr == 0 || - hai->hashdatalen == 0 || - hai->algorithmid != TPM_ALG_SHA) - return TCG_INVALID_INPUT_PARA; - - return sha1((const u8 *)hai->hashdataptr, hai->hashdatalen, hash); -} - -static u32 -hash_log_event(const void *hashdata, u32 hashdata_length, - struct pcpes *pcpes, - const char *event, u32 event_length, - u16 *entry_count) -{ - u32 rc = 0; - - if (pcpes->pcrindex >= 24) - return TCG_INVALID_INPUT_PARA; - - if (hashdata) { - rc = sha1(hashdata, hashdata_length, pcpes->digest); - if (rc) - return rc; - } - - return tpm_extend_acpi_log(pcpes, event, event_length, entry_count); -} - -static u32 -hash_log_event_int(const struct hlei *hlei, struct hleo *hleo) -{ - u32 rc = 0; - u16 size; - struct pcpes *pcpes; - u16 entry_count; - - if (is_preboot_if_shutdown() != 0) { - rc = TCG_INTERFACE_SHUTDOWN; - goto err_exit; - } - - size = hlei->ipblength; - if (size != sizeof(*hlei)) { - rc = TCG_INVALID_INPUT_PARA; + if (rc || returnCode) goto err_exit; - }
- pcpes = (struct pcpes *)hlei->logdataptr; + return;
- if (pcpes->pcrindex >= 24 || - pcpes->pcrindex != hlei->pcrindex || - pcpes->eventtype != hlei->logeventtype || - hlei->logdatalen != - offsetof(struct pcpes, event) + pcpes->eventdatasize) { - rc = TCG_INVALID_INPUT_PARA; - goto err_exit; - } +err_exit: + dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
- rc = hash_log_event(hlei->hashdataptr, hlei->hashdatalen, - pcpes, (char *)&pcpes->event, pcpes->eventdatasize, - &entry_count); - if (rc) - goto err_exit; + tpm_set_failure(); +}
- /* updating the log was fine */ - hleo->opblength = sizeof(struct hleo); - hleo->reserved = 0; - hleo->eventnumber = entry_count;
-err_exit: - if (rc != 0) { - hleo->opblength = 2; - hleo->reserved = 0; - } +/**************************************************************** + * BIOS interface + ****************************************************************/
- return rc; +static inline void *input_buf32(struct bregs *regs) +{ + return MAKE_FLATPTR(regs->es, regs->di); }
-static u32 -hash_log_extend_event(const void *hashdata, u32 hashdata_length, - struct pcpes *pcpes, - const char *event, u32 event_length, - u32 pcrindex, u16 *entry_count) +static inline void *output_buf32(struct bregs *regs) { - u32 rc; - - rc = hash_log_event(hashdata, hashdata_length, pcpes, - event, event_length, entry_count); - if (rc) - return rc; - - return tpm_extend(pcpes->digest, pcrindex); + return MAKE_FLATPTR(regs->ds, regs->si); }
static u32 @@ -926,6 +1153,126 @@ err_exit:
}
+static u32 +pass_through_to_tpm_int(struct pttti *pttti, struct pttto *pttto) +{ + u32 rc = 0; + u32 resbuflen = 0; + struct tpm_req_header *trh; + + if (is_preboot_if_shutdown()) { + rc = TCG_INTERFACE_SHUTDOWN; + goto err_exit; + } + + trh = (struct tpm_req_header *)pttti->tpmopin; + + if (pttti->ipblength < sizeof(struct pttti) + TPM_REQ_HEADER_SIZE || + pttti->opblength < sizeof(struct pttto) || + be32_to_cpu(trh->totlen) + sizeof(struct pttti) > pttti->ipblength ) { + rc = TCG_INVALID_INPUT_PARA; + goto err_exit; + } + + resbuflen = pttti->opblength - offsetof(struct pttto, tpmopout); + + rc = pass_through_to_tpm(0, pttti->tpmopin, + pttti->ipblength - offsetof(struct pttti, tpmopin), + pttto->tpmopout, &resbuflen); + + if (rc) + goto err_exit; + + pttto->opblength = offsetof(struct pttto, tpmopout) + resbuflen; + pttto->reserved = 0; + +err_exit: + if (rc != 0) { + pttto->opblength = 4; + pttto->reserved = 0; + } + + return rc; +} + +static u32 +shutdown_preboot_interface(void) +{ + u32 rc = 0; + + if (!is_preboot_if_shutdown()) { + tpm_state.if_shutdown = 1; + } else { + rc = TCG_INTERFACE_SHUTDOWN; + } + + return rc; +} + +static u32 +hash_log_event_int(const struct hlei *hlei, struct hleo *hleo) +{ + u32 rc = 0; + u16 size; + struct pcpes *pcpes; + u16 entry_count; + + if (is_preboot_if_shutdown() != 0) { + rc = TCG_INTERFACE_SHUTDOWN; + goto err_exit; + } + + size = hlei->ipblength; + if (size != sizeof(*hlei)) { + rc = TCG_INVALID_INPUT_PARA; + goto err_exit; + } + + pcpes = (struct pcpes *)hlei->logdataptr; + + if (pcpes->pcrindex >= 24 || + pcpes->pcrindex != hlei->pcrindex || + pcpes->eventtype != hlei->logeventtype || + hlei->logdatalen != + offsetof(struct pcpes, event) + pcpes->eventdatasize) { + rc = TCG_INVALID_INPUT_PARA; + goto err_exit; + } + + rc = hash_log_event(hlei->hashdataptr, hlei->hashdatalen, + pcpes, (char *)&pcpes->event, pcpes->eventdatasize, + &entry_count); + if (rc) + goto err_exit; + + /* updating the log was fine */ + hleo->opblength = sizeof(struct hleo); + hleo->reserved = 0; + hleo->eventnumber = entry_count; + +err_exit: + if (rc != 0) { + hleo->opblength = 2; + hleo->reserved = 0; + } + + return rc; +} + +static u32 +hash_all_int(const struct hai *hai, u8 *hash) +{ + if (is_preboot_if_shutdown() != 0) + return TCG_INTERFACE_SHUTDOWN; + + if (hai->ipblength != sizeof(struct hai) || + hai->hashdataptr == 0 || + hai->hashdatalen == 0 || + hai->algorithmid != TPM_ALG_SHA) + return TCG_INVALID_INPUT_PARA; + + return sha1((const u8 *)hai->hashdataptr, hai->hashdatalen, hash); +}
static u32 tss_int(struct ti *ti, struct to *to) @@ -944,7 +1291,6 @@ tss_int(struct ti *ti, struct to *to) return rc; }
- static u32 compact_hash_log_extend_event_int(u8 *buffer, u32 info, @@ -975,7 +1321,6 @@ compact_hash_log_extend_event_int(u8 *buffer, return rc; }
- void VISIBLE32FLAT tpm_interrupt_handler32(struct bregs *regs) { @@ -1053,363 +1398,3 @@ tpm_interrupt_handler32(struct bregs *regs)
return; } - -/* - * Add a measurement to the log; the data at data_seg:data/length are - * appended to the TCG_PCClientPCREventStruct - * - * Input parameters: - * pcrindex : which PCR to extend - * event_type : type of event; specs section on 'Event Types' - * event : pointer to info (e.g., string) to be added to log as-is - * event_length: length of the event - * hashdata : pointer to the data to be hashed - * hashdata_length: length of the data to be hashed - */ -static u32 -tpm_add_measurement_to_log(u32 pcrindex, u32 event_type, - const char *event, u32 event_length, - const u8 *hashdata, u32 hashdata_length) -{ - struct pcpes pcpes = { - .pcrindex = pcrindex, - .eventtype = event_type, - }; - u16 entry_count; - - return hash_log_extend_event(hashdata, hashdata_length, &pcpes, - event, event_length, pcrindex, - &entry_count); -} - - -/* - * Add a measurement to the list of measurements - * pcrIndex : PCR to be extended - * event_type : type of event; specs section on 'Event Types' - * data : additional parameter; used as parameter for - * 'action index' - */ -static u32 -tpm_add_measurement(u32 pcrIndex, - u16 event_type, - const char *string) -{ - u32 rc; - u32 len; - - switch (event_type) { - case EV_SEPARATOR: - len = sizeof(evt_separator); - rc = tpm_add_measurement_to_log(pcrIndex, event_type, - (char *)NULL, 0, - (u8 *)evt_separator, len); - break; - - case EV_ACTION: - rc = tpm_add_measurement_to_log(pcrIndex, event_type, - string, strlen(string), - (u8 *)string, strlen(string)); - break; - - default: - rc = TCG_INVALID_INPUT_PARA; - } - - return rc; -} - - -static u32 -tpm_calling_int19h(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - return tpm_add_measurement(4, EV_ACTION, - "Calling INT 19h"); -} - -/* - * Add event separators for PCRs 0 to 7; specs on 'Measuring Boot Events' - */ -static u32 -tpm_add_event_separators(void) -{ - u32 rc; - u32 pcrIndex = 0; - - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - while (pcrIndex <= 7) { - rc = tpm_add_measurement(pcrIndex, EV_SEPARATOR, NULL); - if (rc) - break; - pcrIndex ++; - } - - return rc; -} - - -/* - * Add a measurement regarding the boot device (CDRom, Floppy, HDD) to - * the list of measurements. - */ -static u32 -tpm_add_bootdevice(u32 bootcd, u32 bootdrv) -{ - const char *string; - - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - switch (bootcd) { - case 0: - switch (bootdrv) { - case 0: - string = "Booting BCV device 00h (Floppy)"; - break; - - case 0x80: - string = "Booting BCV device 80h (HDD)"; - break; - - default: - string = "Booting unknown device"; - break; - } - - break; - - default: - string = "Booting from CD ROM device"; - } - - return tpm_add_measurement_to_log(4, EV_ACTION, - string, strlen(string), - (u8 *)string, strlen(string)); -} - - -/* - * Add measurement to the log about option rom scan - */ -static u32 -tpm_start_option_rom_scan(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - return tpm_add_measurement(2, EV_ACTION, - "Start Option ROM Scan"); -} - - -/* - * Add measurement to the log about an option rom - */ -u32 -tpm_option_rom(const void *addr, u32 len) -{ - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - u32 rc; - struct pcctes_romex pcctes = { - .eventid = 7, - .eventdatasize = sizeof(u16) + sizeof(u16) + SHA1_BUFSIZE, - }; - - rc = sha1((const u8 *)addr, len, pcctes.digest); - if (rc) - return rc; - - return tpm_add_measurement_to_log(2, - EV_EVENT_TAG, - (const char *)&pcctes, sizeof(pcctes), - (u8 *)&pcctes, sizeof(pcctes)); -} - - -static u32 -tpm_smbios_measure(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - u32 rc; - struct pcctes pcctes = { - .eventid = 1, - .eventdatasize = SHA1_BUFSIZE, - }; - struct smbios_entry_point *sep = SMBiosAddr; - - dprintf(DEBUG_tcg, "TCGBIOS: SMBIOS at %p\n", sep); - - if (!sep) - return 0; - - rc = sha1((const u8 *)sep->structure_table_address, - sep->structure_table_length, pcctes.digest); - if (rc) - return rc; - - return tpm_add_measurement_to_log(1, - EV_EVENT_TAG, - (const char *)&pcctes, sizeof(pcctes), - (u8 *)&pcctes, sizeof(pcctes)); -} - - -/* - * Add a measurement related to Initial Program Loader to the log. - * Creates two log entries. - * - * Input parameter: - * bootcd : 0: MBR of hdd, 1: boot image, 2: boot catalog of El Torito - * addr : address where the IP data are located - * length : IP data length in bytes - */ -static u32 -tpm_ipl(enum ipltype bootcd, const u8 *addr, u32 length) -{ - u32 rc; - const char *string; - - switch (bootcd) { - case IPL_EL_TORITO_1: - /* specs: see section 'El Torito' */ - string = "EL TORITO IPL"; - rc = tpm_add_measurement_to_log(4, EV_IPL, - string, strlen(string), - addr, length); - break; - - case IPL_EL_TORITO_2: - /* specs: see section 'El Torito' */ - string = "BOOT CATALOG"; - rc = tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA, - string, strlen(string), - addr, length); - break; - - default: - /* specs: see section 'Hard Disk Device or Hard Disk-Like Devices' */ - /* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */ - string = "MBR"; - rc = tpm_add_measurement_to_log(4, EV_IPL, - string, strlen(string), - addr, 0x1b8); - - if (rc) - break; - - /* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */ - string = "MBR PARTITION_TABLE"; - rc = tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA, - string, strlen(string), - addr + 0x1b8, 0x48); - } - - return rc; -} - -u32 -tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length) -{ - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - u32 rc = tpm_add_bootdevice(0, bootdrv); - if (rc) - return rc; - - return tpm_ipl(IPL_BCV, addr, length); -} - -u32 -tpm_add_cdrom(u32 bootdrv, const u8 *addr, u32 length) -{ - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - u32 rc = tpm_add_bootdevice(1, bootdrv); - if (rc) - return rc; - - return tpm_ipl(IPL_EL_TORITO_1, addr, length); -} - -u32 -tpm_add_cdrom_catalog(const u8 *addr, u32 length) -{ - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - u32 rc = tpm_add_bootdevice(1, 0); - if (rc) - return rc; - - return tpm_ipl(IPL_EL_TORITO_2, addr, length); -} - -void -tpm_s3_resume(void) -{ - u32 rc; - u32 returnCode; - - if (!CONFIG_TCGBIOS) - return; - - if (!has_working_tpm()) - return; - - dprintf(DEBUG_tcg, "TCGBIOS: Resuming with TPM_Startup(ST_STATE)\n"); - - rc = build_and_send_cmd(0, TPM_ORD_Startup, - Startup_ST_STATE, sizeof(Startup_ST_STATE), - NULL, 0, &returnCode, TPM_DURATION_TYPE_SHORT); - - dprintf(DEBUG_tcg, "TCGBIOS: ReturnCode from TPM_Startup = 0x%08x\n", - returnCode); - - if (rc || returnCode) - goto err_exit; - - return; - -err_exit: - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - - tpm_set_failure(); -}
Move tpm state checking and error handling from tpm_extend_acpi_log() to its only caller hash_log_event(). This makes tpm_extend_acpi_log() specific to just ACPI table handling.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/tcgbios.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index 7877840..88652fe 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -280,8 +280,6 @@ reset_acpi_log(void) tpm_state.entry_count = 0; }
-static void tpm_set_failure(void); - /* * Extend the ACPI log with the given entry by copying the * entry data into the log. @@ -301,27 +299,17 @@ tpm_extend_acpi_log(struct pcpes *pcpes, { u32 size;
- if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - dprintf(DEBUG_tcg, "TCGBIOS: LASA = %p, next entry = %p\n", tpm_state.log_area_start_address, tpm_state.log_area_next_entry);
- if (tpm_state.log_area_next_entry == NULL) { - - tpm_set_failure(); - + if (tpm_state.log_area_next_entry == NULL) return TCG_PC_LOGOVERFLOW; - }
size = offsetof(struct pcpes, event) + event_length;
if ((tpm_state.log_area_next_entry + size - tpm_state.log_area_start_address) > tpm_state.log_area_minimum_length) { dprintf(DEBUG_tcg, "TCGBIOS: LOG OVERFLOW: size = %d\n", size); - - tpm_set_failure(); - return TCG_PC_LOGOVERFLOW; }
@@ -548,7 +536,13 @@ hash_log_event(const void *hashdata, u32 hashdata_length, return rc; }
- return tpm_extend_acpi_log(pcpes, event, event_length, entry_count); + if (!has_working_tpm()) + return TCG_GENERAL_ERROR; + + rc = tpm_extend_acpi_log(pcpes, event, event_length, entry_count); + if (rc) + tpm_set_failure(); + return rc; }
static u32
The only three three callers of tpm_ipl() exactly correlate with the three switch branches in tpm_ipl(), so just move the appropriate code into the callers.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/tcgbios.c | 80 ++++++++++++++++++----------------------------------------- 1 file changed, 24 insertions(+), 56 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index 88652fe..1f73593 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -930,59 +930,6 @@ tpm_add_bootdevice(u32 bootcd, u32 bootdrv) (u8 *)string, strlen(string)); }
-/* - * Add a measurement related to Initial Program Loader to the log. - * Creates two log entries. - * - * Input parameter: - * bootcd : 0: MBR of hdd, 1: boot image, 2: boot catalog of El Torito - * addr : address where the IP data are located - * length : IP data length in bytes - */ -static u32 -tpm_ipl(enum ipltype bootcd, const u8 *addr, u32 length) -{ - u32 rc; - const char *string; - - switch (bootcd) { - case IPL_EL_TORITO_1: - /* specs: see section 'El Torito' */ - string = "EL TORITO IPL"; - rc = tpm_add_measurement_to_log(4, EV_IPL, - string, strlen(string), - addr, length); - break; - - case IPL_EL_TORITO_2: - /* specs: see section 'El Torito' */ - string = "BOOT CATALOG"; - rc = tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA, - string, strlen(string), - addr, length); - break; - - default: - /* specs: see section 'Hard Disk Device or Hard Disk-Like Devices' */ - /* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */ - string = "MBR"; - rc = tpm_add_measurement_to_log(4, EV_IPL, - string, strlen(string), - addr, 0x1b8); - - if (rc) - break; - - /* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */ - string = "MBR PARTITION_TABLE"; - rc = tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA, - string, strlen(string), - addr + 0x1b8, 0x48); - } - - return rc; -} - u32 tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length) { @@ -996,7 +943,20 @@ tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length) if (rc) return rc;
- return tpm_ipl(IPL_BCV, addr, length); + /* specs: see section 'Hard Disk Device or Hard Disk-Like Devices' */ + /* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */ + const char *string = "MBR"; + rc = tpm_add_measurement_to_log(4, EV_IPL, + string, strlen(string), + addr, 0x1b8); + if (rc) + return rc; + + /* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */ + string = "MBR PARTITION_TABLE"; + return tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA, + string, strlen(string), + addr + 0x1b8, 0x48); }
u32 @@ -1012,7 +972,11 @@ tpm_add_cdrom(u32 bootdrv, const u8 *addr, u32 length) if (rc) return rc;
- return tpm_ipl(IPL_EL_TORITO_1, addr, length); + /* specs: see section 'El Torito' */ + const char *string = "EL TORITO IPL"; + return tpm_add_measurement_to_log(4, EV_IPL, + string, strlen(string), + addr, length); }
u32 @@ -1028,7 +992,11 @@ tpm_add_cdrom_catalog(const u8 *addr, u32 length) if (rc) return rc;
- return tpm_ipl(IPL_EL_TORITO_2, addr, length); + /* specs: see section 'El Torito' */ + const char *string = "BOOT CATALOG"; + return tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA, + string, strlen(string), + addr, length); }
void
Make the only caller of tpm_add_measurement() with EV_SEPARATOR directly call tpm_add_measurement_to_log(). Rename to tpm_add_action() and change all callers with EV_ACTION to use this function.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/tcgbios.c | 55 +++++++++++++------------------------------------------ 1 file changed, 13 insertions(+), 42 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index 1f73593..01fddcc 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -55,8 +55,6 @@ static const u8 GetCapability_Durations[] = { 0x00, 0x00, 0x01, 0x20 };
-static u8 evt_separator[] = {0xff,0xff,0xff,0xff}; -
/**************************************************************** * TPM state tracking @@ -594,40 +592,13 @@ tpm_add_measurement_to_log(u32 pcrindex, u32 event_type, * Setup and Measurements ****************************************************************/
-/* - * Add a measurement to the list of measurements - * pcrIndex : PCR to be extended - * event_type : type of event; specs section on 'Event Types' - * data : additional parameter; used as parameter for - * 'action index' - */ +// Add an EV_ACTION measurement to the list of measurements static u32 -tpm_add_measurement(u32 pcrIndex, - u16 event_type, - const char *string) +tpm_add_action(u32 pcrIndex, const char *string) { - u32 rc; - u32 len; - - switch (event_type) { - case EV_SEPARATOR: - len = sizeof(evt_separator); - rc = tpm_add_measurement_to_log(pcrIndex, event_type, - (char *)NULL, 0, - (u8 *)evt_separator, len); - break; - - case EV_ACTION: - rc = tpm_add_measurement_to_log(pcrIndex, event_type, - string, strlen(string), - (u8 *)string, strlen(string)); - break; - - default: - rc = TCG_INVALID_INPUT_PARA; - } - - return rc; + u32 len = strlen(string); + return tpm_add_measurement_to_log(pcrIndex, EV_ACTION, + string, len, (u8 *)string, len); }
static u32 @@ -639,8 +610,7 @@ tpm_calling_int19h(void) if (!has_working_tpm()) return TCG_GENERAL_ERROR;
- return tpm_add_measurement(4, EV_ACTION, - "Calling INT 19h"); + return tpm_add_action(4, "Calling INT 19h"); }
/* @@ -658,8 +628,12 @@ tpm_add_event_separators(void) if (!has_working_tpm()) return TCG_GENERAL_ERROR;
+ static const u8 evt_separator[] = {0xff,0xff,0xff,0xff}; while (pcrIndex <= 7) { - rc = tpm_add_measurement(pcrIndex, EV_SEPARATOR, NULL); + rc = tpm_add_measurement_to_log(pcrIndex, EV_SEPARATOR, + NULL, 0, + (u8 *)evt_separator, + sizeof(evt_separator)); if (rc) break; pcrIndex ++; @@ -680,8 +654,7 @@ tpm_start_option_rom_scan(void) if (!has_working_tpm()) return TCG_GENERAL_ERROR;
- return tpm_add_measurement(2, EV_ACTION, - "Start Option ROM Scan"); + return tpm_add_action(2, "Start Option ROM Scan"); }
static u32 @@ -925,9 +898,7 @@ tpm_add_bootdevice(u32 bootcd, u32 bootdrv) string = "Booting from CD ROM device"; }
- return tpm_add_measurement_to_log(4, EV_ACTION, - string, strlen(string), - (u8 *)string, strlen(string)); + return tpm_add_action(4, string); }
u32
The switch statement in tpm_add_bootdevice() corresponds with its call sites - just perform the appropriate action in each caller.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/tcgbios.c | 51 +++++++-------------------------------------------- 1 file changed, 7 insertions(+), 44 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index 01fddcc..d415714 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -861,46 +861,6 @@ tpm_option_rom(const void *addr, u32 len) (u8 *)&pcctes, sizeof(pcctes)); }
-/* - * Add a measurement regarding the boot device (CDRom, Floppy, HDD) to - * the list of measurements. - */ -static u32 -tpm_add_bootdevice(u32 bootcd, u32 bootdrv) -{ - const char *string; - - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - switch (bootcd) { - case 0: - switch (bootdrv) { - case 0: - string = "Booting BCV device 00h (Floppy)"; - break; - - case 0x80: - string = "Booting BCV device 80h (HDD)"; - break; - - default: - string = "Booting unknown device"; - break; - } - - break; - - default: - string = "Booting from CD ROM device"; - } - - return tpm_add_action(4, string); -} - u32 tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length) { @@ -910,13 +870,16 @@ tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length) if (!has_working_tpm()) return TCG_GENERAL_ERROR;
- u32 rc = tpm_add_bootdevice(0, bootdrv); + const char *string = "Booting BCV device 00h (Floppy)"; + if (bootdrv == 0x80) + string = "Booting BCV device 80h (HDD)"; + u32 rc = tpm_add_action(4, string); if (rc) return rc;
/* specs: see section 'Hard Disk Device or Hard Disk-Like Devices' */ /* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */ - const char *string = "MBR"; + string = "MBR"; rc = tpm_add_measurement_to_log(4, EV_IPL, string, strlen(string), addr, 0x1b8); @@ -939,7 +902,7 @@ tpm_add_cdrom(u32 bootdrv, const u8 *addr, u32 length) if (!has_working_tpm()) return TCG_GENERAL_ERROR;
- u32 rc = tpm_add_bootdevice(1, bootdrv); + u32 rc = tpm_add_action(4, "Booting from CD ROM device"); if (rc) return rc;
@@ -959,7 +922,7 @@ tpm_add_cdrom_catalog(const u8 *addr, u32 length) if (!has_working_tpm()) return TCG_GENERAL_ERROR;
- u32 rc = tpm_add_bootdevice(1, 0); + u32 rc = tpm_add_action(4, "Booting from CD ROM device"); if (rc) return rc;
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/tcgbios.c | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index d415714..c6782ee 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -601,18 +601,6 @@ tpm_add_action(u32 pcrIndex, const char *string) string, len, (u8 *)string, len); }
-static u32 -tpm_calling_int19h(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - return tpm_add_action(4, "Calling INT 19h"); -} - /* * Add event separators for PCRs 0 to 7; specs on 'Measuring Boot Events' */ @@ -642,21 +630,6 @@ tpm_add_event_separators(void) return rc; }
-/* - * Add measurement to the log about option rom scan - */ -static u32 -tpm_start_option_rom_scan(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - if (!has_working_tpm()) - return TCG_GENERAL_ERROR; - - return tpm_add_action(2, "Start Option ROM Scan"); -} - static u32 tpm_smbios_measure(void) { @@ -743,7 +716,7 @@ tpm_startup(void) if (rc) goto err_exit;
- rc = tpm_start_option_rom_scan(); + rc = tpm_add_action(2, "Start Option ROM Scan"); if (rc) goto err_exit;
@@ -817,7 +790,7 @@ tpm_prepboot(void) if (rc || returnCode) goto err_exit;
- rc = tpm_calling_int19h(); + rc = tpm_add_action(4, "Calling INT 19h"); if (rc) goto err_exit;
On 11/22/2015 12:20 PM, Kevin O'Connor wrote:
Hi Stefan,
As part of trying to better understand the TPM code, I found some changes to tcgbios.c were helpful. It's mostly code movement. I've only compile tested these changes, but I think they are safe.
I don't want to conflict with any changes you may have pending. So, let me know if this is a problem.
I do have other changes and extensions pending, but go ahead and apply it.
The series is on top of your latest patches. (FYI, I made a minor change to a comment in your patch 2.) I've also put this series (and your series) up at:
I applied them locally. From what i can see from tests I have done, results are still like before.
ACK to series.
Stefan
-Kevin
Kevin O'Connor (7): tpm: Add "static" declaration to functions not used outside tcgbios.c tpm: Move code around in tcgbios.c tpm: Move error recovery from tpm_extend_acpi_log() to only caller tpm: Open code tpm_ipl() into callers tpm: Change tpm_add_measurement() to tpm_add_action() tpm: Move tpm_add_bootdevice() into callers tpm: Move tpm_start_option_rom_scan() and tpm_calling_int19h() into callers
src/tcgbios.c | 1258 +++++++++++++++++++++++++-------------------------------- 1 file changed, 556 insertions(+), 702 deletions(-)
On Sun, Nov 22, 2015 at 06:54:47PM -0500, Stefan Berger wrote:
On 11/22/2015 12:20 PM, Kevin O'Connor wrote:
Hi Stefan,
As part of trying to better understand the TPM code, I found some changes to tcgbios.c were helpful. It's mostly code movement. I've only compile tested these changes, but I think they are safe.
I don't want to conflict with any changes you may have pending. So, let me know if this is a problem.
I do have other changes and extensions pending, but go ahead and apply it.
The series is on top of your latest patches. (FYI, I made a minor change to a comment in your patch 2.) I've also put this series (and your series) up at:
I applied them locally. From what i can see from tests I have done, results are still like before.
ACK to series.
Thanks. I ran across a few other things - I sent an email series and put the changes up on github.
There were a few other things I noticed, but that I have not tried changing:
- It's odd that "Booting from CD ROM device" is added twice for cdrom boots. Is that intentional?
- It's odd that is_tpm_present() is called from tpm_interrupt_handler32() , as that probes the hardware. I would think that if the has_working_tpm() check in tpm_interrupt_handler32() passes then is_tpm_present() would always pass.
- It seems the "TPM hardware interface" group of functions could be moved to tpm_drivers.c . Doing that seems like it could simpify the software/hardware interface as only a handful of functions would need to be exported (instead of the function table that tpm_drivers.c currently exports). Could tpm_drivers.c just export something like: tpmhw_probe(), tpmhw_set_timeouts(), tpmhw_transmit() ?
I will hold off on further changes until you can merge any features you have pending.
-Kevin
On 11/22/2015 08:26 PM, Kevin O'Connor wrote:
On Sun, Nov 22, 2015 at 06:54:47PM -0500, Stefan Berger wrote:
On 11/22/2015 12:20 PM, Kevin O'Connor wrote:
Hi Stefan,
As part of trying to better understand the TPM code, I found some changes to tcgbios.c were helpful. It's mostly code movement. I've only compile tested these changes, but I think they are safe.
I don't want to conflict with any changes you may have pending. So, let me know if this is a problem.
I do have other changes and extensions pending, but go ahead and apply it.
The series is on top of your latest patches. (FYI, I made a minor change to a comment in your patch 2.) I've also put this series (and your series) up at:
I applied them locally. From what i can see from tests I have done, results are still like before.
ACK to series.
Thanks. I ran across a few other things - I sent an email series and put the changes up on github.
There were a few other things I noticed, but that I have not tried changing:
- It's odd that "Booting from CD ROM device" is added twice for cdrom boots. Is that intentional?
That is not necessary. We can remove one of these log messages.
- It's odd that is_tpm_present() is called from tpm_interrupt_handler32() , as that probes the hardware. I would think that if the has_working_tpm() check in tpm_interrupt_handler32() passes then is_tpm_present() would always pass.
correct.
- It seems the "TPM hardware interface" group of functions could be moved to tpm_drivers.c . Doing that seems like it could simpify the software/hardware interface as only a handful of functions would need to be exported (instead of the function table that tpm_drivers.c currently exports). Could tpm_drivers.c just export something like: tpmhw_probe(), tpmhw_set_timeouts(), tpmhw_transmit() ?
Yes.
I will hold off on further changes until you can merge any features you have pending.
It's mostly the menu that I would want to have merged next. All patches after that are not that important and I'll only resurrect them once the changes here settle.
I looked over and tried your 2nd series of 8 patches and the tests I did all had the same results as without these patches applied. So from my point of view, they can be applied. I leave it up to you regarding 4/8 and the fixed-size buffer on the stack. If we ever have a bigger message to pass then we can adjust the buffer following the warning the code is emitting, otherwise if we pass the event and its size around we won't have to do that. If stack usage is not an issue I think your changes in probably the right direction.
All the arrays at the beginning of the file are basically the bodies of TPM requests. We could extend those arrays by prefixing them with their headers and won't have to build the header in the transmit function anymore. Some messages will still need to be built, like TPM_Extend, but those can be hard-coded. Is that a change we would want?
I am also trying to add similar code to SLOF, which is under BSD. I hope that you agree that I can make similar transformations that you did to the pending SLOF patches as well.
Thanks and regards, Stefan
On Sun, Nov 22, 2015 at 11:11:36PM -0500, Stefan Berger wrote:
On 11/22/2015 08:26 PM, Kevin O'Connor wrote:
I will hold off on further changes until you can merge any features you have pending.
It's mostly the menu that I would want to have merged next. All patches after that are not that important and I'll only resurrect them once the changes here settle.
Okay. I forget why the menu code didn't get added - can you resend it?
I looked over and tried your 2nd series of 8 patches and the tests I did all had the same results as without these patches applied. So from my point of view, they can be applied. I leave it up to you regarding 4/8 and the fixed-size buffer on the stack. If we ever have a bigger message to pass then we can adjust the buffer following the warning the code is emitting, otherwise if we pass the event and its size around we won't have to do that. If stack usage is not an issue I think your changes in probably the right direction.
SeaBIOS (by default) uses its own 2K stack for "runtime" usage (the 16bit bios calls), and it has either a 4K or 16K stack during the POST phase.
If performance was a concern, tpm_extend_acpi_log() could be split into two parts (eg, tpm_log_get_space() and tpm_log_reserve_space() ) and the calling code could directly memcpy everything to its final location in the acpi log. However, it seems like just undoing my patch 4 makes the most sense. I'll pull that patch out and repost tonight.
All the arrays at the beginning of the file are basically the bodies of TPM requests. We could extend those arrays by prefixing them with their headers and won't have to build the header in the transmit function anymore. Some messages will still need to be built, like TPM_Extend, but those can be hard-coded. Is that a change we would want?
It's possible to do that for build_and_send_cmd(). The biggest command (in the current code) is 12 bytes though, so it seems like it is just simpler to copy it.
I am also trying to add similar code to SLOF, which is under BSD. I hope that you agree that I can make similar transformations that you did to the pending SLOF patches as well.
Yes, that's fine.
-Kevin
On Mon, Nov 23, 2015 at 11:17:35AM -0500, Kevin O'Connor wrote:
However, it seems like just undoing my patch 4 makes the most sense. I'll pull that patch out and repost tonight.
FYI, I modified the series (mostly reverted patch 4) and pushed to github:
https://github.com/KevinOConnor/seabios/tree/testing
-Kevin
On 11/23/2015 11:40 PM, Kevin O'Connor wrote:
On Mon, Nov 23, 2015 at 11:17:35AM -0500, Kevin O'Connor wrote:
However, it seems like just undoing my patch 4 makes the most sense. I'll pull that patch out and repost tonight.
FYI, I modified the series (mostly reverted patch 4) and pushed to github:
Tested it. Works as before.
Stefan
On Tue, Nov 24, 2015 at 12:40:32PM -0500, Stefan Berger wrote:
On 11/23/2015 11:40 PM, Kevin O'Connor wrote:
On Mon, Nov 23, 2015 at 11:17:35AM -0500, Kevin O'Connor wrote:
However, it seems like just undoing my patch 4 makes the most sense. I'll pull that patch out and repost tonight.
FYI, I modified the series (mostly reverted patch 4) and pushed to github:
Tested it. Works as before.
Thanks - I pushed that code.
Separately, is the call to PhysicalPresence_CMD_ENABLE in tpm_set_failure() correct, or should that be PhysicalPresence_CMD_DISABLE?
-Kevin
On 11/28/2015 07:44 AM, Kevin O'Connor wrote:
On Tue, Nov 24, 2015 at 12:40:32PM -0500, Stefan Berger wrote:
On 11/23/2015 11:40 PM, Kevin O'Connor wrote:
On Mon, Nov 23, 2015 at 11:17:35AM -0500, Kevin O'Connor wrote:
However, it seems like just undoing my patch 4 makes the most sense. I'll pull that patch out and repost tonight.
FYI, I modified the series (mostly reverted patch 4) and pushed to github:
Tested it. Works as before.
Thanks - I pushed that code.
Separately, is the call to PhysicalPresence_CMD_ENABLE in tpm_set_failure() correct, or should that be PhysicalPresence_CMD_DISABLE?
It's correct. Per spec on TPM_SetTempDeactivated:
"This command allows the operator of the platform to deactivate the TPM until the next boot of the platform. This command requires operator authentication. The operator can provide the authentication by either the assertion of physical presence or presenting the operator AuthData value"
Stefan