aboutsummaryrefslogtreecommitdiff
path: root/src/tcgbios.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2015-11-22 10:57:52 -0500
committerKevin O'Connor <kevin@koconnor.net>2015-11-22 12:13:08 -0500
commitf51c50a16720feeaa7ddcbfbc798e2da20918239 (patch)
tree0ff41da4538aaffdaa0566ecad6ef5acdf54f4b0 /src/tcgbios.c
parent0818b1dabdf3d61eff0276231c313cb6d64d09eb (diff)
downloadseabios-hppa-f51c50a16720feeaa7ddcbfbc798e2da20918239.zip
seabios-hppa-f51c50a16720feeaa7ddcbfbc798e2da20918239.tar.gz
seabios-hppa-f51c50a16720feeaa7ddcbfbc798e2da20918239.tar.bz2
tpm: Move code around in tcgbios.c
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>
Diffstat (limited to 'src/tcgbios.c')
-rw-r--r--src/tcgbios.c1291
1 files changed, 638 insertions, 653 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,6 +485,242 @@ err_exit:
return TCG_TCG_COMMAND_ERROR;
}
+static u32
+pass_through_to_tpm(u8 locty, const u8 *cmd, u32 cmd_length,
+ u8 *resp, u32 *resp_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 (cmd_length != iovec[0].length)
+ return TCG_INVALID_INPUT_PARA;
+
+ return transmit(locty, iovec, resp, resp_length,
+ TPM_DURATION_TYPE_LONG /* worst case */);
+
+}
+
+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);
+
+ memcpy(tre.digest, hash, sizeof(tre.digest));
+
+ rc = pass_through_to_tpm(0, (u8 *)&tre, sizeof(tre),
+ (u8 *)&rsp, &resp_length);
+
+ 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)
@@ -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,105 +867,289 @@ 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
+ */
+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));
+}
+
+/*
+ * Add a measurement regarding the boot device (CDRom, Floppy, HDD) to
+ * the list of measurements.
*/
static u32
-tpm_extend_acpi_log(struct pcpes *pcpes,
- const char *event, u32 event_length,
- u16 *entry_count)
+tpm_add_bootdevice(u32 bootcd, u32 bootdrv)
{
- u32 size;
+ const char *string;
+
+ 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);
+ switch (bootcd) {
+ case 0:
+ switch (bootdrv) {
+ case 0:
+ string = "Booting BCV device 00h (Floppy)";
+ break;
- if (tpm_state.log_area_next_entry == NULL) {
+ case 0x80:
+ string = "Booting BCV device 80h (HDD)";
+ break;
- tpm_set_failure();
+ default:
+ string = "Booting unknown device";
+ break;
+ }
- return TCG_PC_LOGOVERFLOW;
+ break;
+
+ default:
+ string = "Booting from CD ROM device";
}
- size = offsetof(struct pcpes, event) + event_length;
+ return tpm_add_measurement_to_log(4, EV_ACTION,
+ string, strlen(string),
+ (u8 *)string, strlen(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);
+/*
+ * 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;
- tpm_set_failure();
+ 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;
- return TCG_PC_LOGOVERFLOW;
+ 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);
}
- pcpes->eventdatasize = event_length;
+ return rc;
+}
- 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);
+u32
+tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length)
+{
+ if (!CONFIG_TCGBIOS)
+ return 0;
- tpm_state.log_area_last_entry = tpm_state.log_area_next_entry;
- tpm_state.log_area_next_entry += size;
- tpm_state.entry_count++;
+ if (!has_working_tpm())
+ return TCG_GENERAL_ERROR;
- if (entry_count)
- *entry_count = tpm_state.entry_count;
+ u32 rc = tpm_add_bootdevice(0, bootdrv);
+ if (rc)
+ return rc;
- return 0;
+ 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;
-static u32
-is_preboot_if_shutdown(void)
+ 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)
{
- return tpm_state.if_shutdown;
+ 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();
}
+/****************************************************************
+ * BIOS interface
+ ****************************************************************/
+
+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);
+}
+
static u32
-shutdown_preboot_interface(void)
+hash_log_extend_event_int(const struct hleei_short *hleei_s,
+ struct hleeo *hleeo)
{
u32 rc = 0;
+ struct hleo hleo;
+ struct hleei_long *hleei_l = (struct hleei_long *)hleei_s;
+ const void *logdataptr;
+ u32 logdatalen;
+ struct pcpes *pcpes;
+ u32 pcrindex;
- if (!is_preboot_if_shutdown()) {
- tpm_state.if_shutdown = 1;
- } else {
+ if (is_preboot_if_shutdown() != 0) {
rc = TCG_INTERFACE_SHUTDOWN;
+ goto err_exit;
}
- return rc;
-}
+ /* short or long version? */
+ switch (hleei_s->ipblength) {
+ case sizeof(struct hleei_short):
+ /* short */
+ logdataptr = hleei_s->logdataptr;
+ logdatalen = hleei_s->logdatalen;
+ pcrindex = hleei_s->pcrindex;
+ break;
-static u32
-pass_through_to_tpm(u8 locty, const u8 *cmd, u32 cmd_length,
- u8 *resp, u32 *resp_length)
-{
- struct iovec iovec[2] = {{ 0 }};
- const u32 *tmp;
+ case sizeof(struct hleei_long):
+ /* long */
+ logdataptr = hleei_l->logdataptr;
+ logdatalen = hleei_l->logdatalen;
+ pcrindex = hleei_l->pcrindex;
+ break;
- if (cmd_length < TPM_REQ_HEADER_SIZE)
- return TCG_INVALID_INPUT_PARA;
+ default:
+ /* bad input block */
+ rc = TCG_INVALID_INPUT_PARA;
+ goto err_exit;
+ }
- iovec[0].data = cmd;
- tmp = (const u32 *)&((u8 *)iovec[0].data)[2];
- iovec[0].length = cpu_to_be32(*tmp);
+ pcpes = (struct pcpes *)logdataptr;
- if (cmd_length != iovec[0].length)
- return TCG_INVALID_INPUT_PARA;
+ if (pcpes->pcrindex >= 24 ||
+ pcpes->pcrindex != pcrindex ||
+ logdatalen != offsetof(struct pcpes, event) + pcpes->eventdatasize) {
+ rc = TCG_INVALID_INPUT_PARA;
+ goto err_exit;
+ }
- return transmit(locty, iovec, resp, resp_length,
- TPM_DURATION_TYPE_LONG /* worst case */);
+ rc = hash_log_extend_event(hleei_s->hashdataptr, hleei_s->hashdatalen,
+ pcpes,
+ (char *)&pcpes->event, pcpes->eventdatasize,
+ pcrindex, NULL);
+ if (rc)
+ goto err_exit;
+
+ hleeo->opblength = sizeof(struct hleeo);
+ hleeo->reserved = 0;
+ hleeo->eventnumber = hleo.eventnumber;
+
+err_exit:
+ if (rc != 0) {
+ hleeo->opblength = 4;
+ hleeo->reserved = 0;
+ }
+
+ return rc;
}
@@ -730,65 +1195,18 @@ err_exit:
return rc;
}
-
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);
-
- memcpy(tre.digest, hash, sizeof(tre.digest));
-
- rc = pass_through_to_tpm(0, (u8 *)&tre, sizeof(tre),
- (u8 *)&rsp, &resp_length);
-
- if (rc || resp_length != sizeof(rsp))
- tpm_set_failure();
-
- 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
-hash_log_event(const void *hashdata, u32 hashdata_length,
- struct pcpes *pcpes,
- const char *event, u32 event_length,
- u16 *entry_count)
+shutdown_preboot_interface(void)
{
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;
+ if (!is_preboot_if_shutdown()) {
+ tpm_state.if_shutdown = 1;
+ } else {
+ rc = TCG_INTERFACE_SHUTDOWN;
}
- return tpm_extend_acpi_log(pcpes, event, event_length, entry_count);
+ return rc;
}
static u32
@@ -842,91 +1260,20 @@ err_exit:
}
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);
-}
-
-static u32
-hash_log_extend_event_int(const struct hleei_short *hleei_s,
- struct hleeo *hleeo)
+hash_all_int(const struct hai *hai, u8 *hash)
{
- u32 rc = 0;
- struct hleo hleo;
- struct hleei_long *hleei_l = (struct hleei_long *)hleei_s;
- const void *logdataptr;
- u32 logdatalen;
- struct pcpes *pcpes;
- u32 pcrindex;
-
- if (is_preboot_if_shutdown() != 0) {
- rc = TCG_INTERFACE_SHUTDOWN;
- goto err_exit;
- }
-
- /* short or long version? */
- switch (hleei_s->ipblength) {
- case sizeof(struct hleei_short):
- /* short */
- logdataptr = hleei_s->logdataptr;
- logdatalen = hleei_s->logdatalen;
- pcrindex = hleei_s->pcrindex;
- break;
-
- case sizeof(struct hleei_long):
- /* long */
- logdataptr = hleei_l->logdataptr;
- logdatalen = hleei_l->logdatalen;
- pcrindex = hleei_l->pcrindex;
- break;
-
- default:
- /* bad input block */
- rc = TCG_INVALID_INPUT_PARA;
- goto err_exit;
- }
-
- pcpes = (struct pcpes *)logdataptr;
-
- if (pcpes->pcrindex >= 24 ||
- pcpes->pcrindex != pcrindex ||
- logdatalen != offsetof(struct pcpes, event) + pcpes->eventdatasize) {
- rc = TCG_INVALID_INPUT_PARA;
- goto err_exit;
- }
-
- rc = hash_log_extend_event(hleei_s->hashdataptr, hleei_s->hashdatalen,
- pcpes,
- (char *)&pcpes->event, pcpes->eventdatasize,
- pcrindex, NULL);
- if (rc)
- goto err_exit;
-
- hleeo->opblength = sizeof(struct hleeo);
- hleeo->reserved = 0;
- hleeo->eventnumber = hleo.eventnumber;
-
-err_exit:
- if (rc != 0) {
- hleeo->opblength = 4;
- hleeo->reserved = 0;
- }
+ if (is_preboot_if_shutdown() != 0)
+ return TCG_INTERFACE_SHUTDOWN;
- return rc;
+ 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();
-}