fwupd/plugins/tpm-eventlog/fu-tpm-eventlog-device.c
Richard Hughes 59d947ac24 tpm-eventlog: Replay the TPM event log to get the PCRx values
In theory, these should always match the reported PCRx values from the TPM.

If the reconstructed event log checksum does not match the TPM value then
something is either implemented wrongly, or something bad has happened.
2020-02-04 11:54:27 +00:00

115 lines
3.3 KiB
C

/*
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include <tss2/tss2_esys.h>
#include "fu-common.h"
#include "fu-tpm-eventlog-device.h"
#include "fu-tpm-eventlog-parser.h"
struct _FuTpmEventlogDevice {
FuDevice parent_instance;
GPtrArray *items;
};
G_DEFINE_TYPE (FuTpmEventlogDevice, fu_tpm_eventlog_device, FU_TYPE_DEVICE)
GPtrArray *
fu_tpm_eventlog_device_get_checksums (FuTpmEventlogDevice *self, guint8 pcr, GError **error)
{
return fu_tpm_eventlog_calc_checksums (self->items, pcr, error);
}
static void
fu_tpm_eventlog_device_to_string (FuDevice *device, guint idt, GString *str)
{
FuTpmEventlogDevice *self = FU_TPM_EVENTLOG_DEVICE (device);
if (self->items->len > 0) {
fu_common_string_append_kv (str, idt, "Items", NULL);
for (guint i = 0; i < self->items->len; i++) {
FuTpmEventlogItem *item = g_ptr_array_index (self->items, i);
fu_tpm_eventlog_item_to_string (item, idt + 1, str);
}
}
}
gchar *
fu_tpm_eventlog_device_report_metadata (FuTpmEventlogDevice *self)
{
GString *str = g_string_new ("");
g_autoptr(GPtrArray) pcrs = NULL;
for (guint i = 0; i < self->items->len; i++) {
FuTpmEventlogItem *item = g_ptr_array_index (self->items, i);
g_autofree gchar *blobstr = fu_tpm_eventlog_blobstr (item->blob);
g_autofree gchar *checksum = fu_tpm_eventlog_strhex (item->checksum_sha1);
g_string_append_printf (str, "0x%08x %s", item->kind, checksum);
if (blobstr != NULL)
g_string_append_printf (str, " [%s]", blobstr);
g_string_append (str, "\n");
}
pcrs = fu_tpm_eventlog_calc_checksums (self->items, 0, NULL);
if (pcrs != NULL) {
for (guint j = 0; j < pcrs->len; j++) {
const gchar *csum = g_ptr_array_index (pcrs, j);
g_string_append_printf (str, "PCR0: %s\n", csum);
}
}
if (str->len > 0)
g_string_truncate (str, str->len - 1);
return g_string_free (str, FALSE);
}
static void
fu_tpm_eventlog_device_init (FuTpmEventlogDevice *self)
{
fu_device_set_name (FU_DEVICE (self), "Event Log");
fu_device_add_flag (FU_DEVICE (self), FWUPD_DEVICE_FLAG_INTERNAL);
fu_device_set_physical_id (FU_DEVICE (self), "DEVNAME=/dev/tpm0");
fu_device_set_logical_id (FU_DEVICE (self), "eventlog");
fu_device_add_parent_guid (FU_DEVICE (self), "system-tpm");
fu_device_add_instance_id (FU_DEVICE (self), "system-tpm-eventlog");
}
static void
fu_tpm_eventlog_device_finalize (GObject *object)
{
FuTpmEventlogDevice *self = FU_TPM_EVENTLOG_DEVICE (object);
g_ptr_array_unref (self->items);
G_OBJECT_CLASS (fu_tpm_eventlog_device_parent_class)->finalize (object);
}
static void
fu_tpm_eventlog_device_class_init (FuTpmEventlogDeviceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
object_class->finalize = fu_tpm_eventlog_device_finalize;
klass_device->to_string = fu_tpm_eventlog_device_to_string;
}
FuTpmEventlogDevice *
fu_tpm_eventlog_device_new (const guint8 *buf, gsize bufsz, GError **error)
{
g_autoptr(FuTpmEventlogDevice) self = NULL;
g_return_val_if_fail (buf != NULL, NULL);
/* create object */
self = g_object_new (FU_TYPE_TPM_EVENTLOG_DEVICE, NULL);
self->items = fu_tpm_eventlog_parser_new (buf, bufsz,
FU_TPM_EVENTLOG_PARSER_FLAG_NONE,
error);
if (self->items == NULL)
return NULL;
return FU_TPM_EVENTLOG_DEVICE (g_steal_pointer (&self));
}