mirror of
https://git.proxmox.com/git/fwupd
synced 2025-05-11 09:54:49 +00:00

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.
234 lines
6.7 KiB
C
234 lines
6.7 KiB
C
/*
|
|
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "fu-tpm-eventlog-common.h"
|
|
|
|
const gchar *
|
|
fu_tpm_eventlog_pcr_to_string (gint pcr)
|
|
{
|
|
if (pcr == 0)
|
|
return "BIOS";
|
|
if (pcr == 1)
|
|
return "BIOS Configuration";
|
|
if (pcr == 2)
|
|
return "Option ROMs";
|
|
if (pcr == 3)
|
|
return "Option ROM configuration";
|
|
if (pcr == 4)
|
|
return "Initial program loader code";
|
|
if (pcr == 5)
|
|
return "Initial program loader code configuration";
|
|
if (pcr == 6)
|
|
return "State transitions and wake events";
|
|
if (pcr == 7)
|
|
return "Platform manufacturer specific measurements";
|
|
if (pcr >= 8 && pcr <= 15)
|
|
return "Static operating system";
|
|
if (pcr == 16)
|
|
return "Debug";
|
|
if (pcr == 17)
|
|
return "Dynamic root of trust measurement and launch control policy";
|
|
if (pcr >= 18 && pcr <= 22)
|
|
return "Trusted OS";
|
|
if (pcr == 23)
|
|
return "Application support";
|
|
return "Undefined";
|
|
}
|
|
|
|
const gchar *
|
|
fu_tpm_eventlog_hash_to_string (TPM2_ALG_ID hash_kind)
|
|
{
|
|
if (hash_kind == TPM2_ALG_SHA1)
|
|
return "SHA1";
|
|
if (hash_kind == TPM2_ALG_SHA256)
|
|
return "SHA256";
|
|
if (hash_kind == TPM2_ALG_SHA384)
|
|
return "SHA384";
|
|
if (hash_kind == TPM2_ALG_SHA512)
|
|
return "SHA512";
|
|
return NULL;
|
|
}
|
|
|
|
guint32
|
|
fu_tpm_eventlog_hash_get_size (TPM2_ALG_ID hash_kind)
|
|
{
|
|
if (hash_kind == TPM2_ALG_SHA1)
|
|
return TPM2_SHA1_DIGEST_SIZE;
|
|
if (hash_kind == TPM2_ALG_SHA256)
|
|
return TPM2_SHA256_DIGEST_SIZE;
|
|
if (hash_kind == TPM2_ALG_SHA384)
|
|
return TPM2_SHA384_DIGEST_SIZE;
|
|
if (hash_kind == TPM2_ALG_SHA512)
|
|
return TPM2_SHA512_DIGEST_SIZE;
|
|
return 0;
|
|
}
|
|
|
|
const gchar *
|
|
fu_tpm_eventlog_item_kind_to_string (FuTpmEventlogItemKind event_type)
|
|
{
|
|
if (event_type == EV_PREBOOT_CERT)
|
|
return "EV_PREBOOT_CERT";
|
|
if (event_type == EV_POST_CODE)
|
|
return "EV_POST_CODE";
|
|
if (event_type == EV_NO_ACTION)
|
|
return "EV_NO_ACTION";
|
|
if (event_type == EV_SEPARATOR)
|
|
return "EV_SEPARATOR";
|
|
if (event_type == EV_ACTION)
|
|
return "EV_ACTION";
|
|
if (event_type == EV_EVENT_TAG)
|
|
return "EV_EVENT_TAG";
|
|
if (event_type == EV_S_CRTM_CONTENTS)
|
|
return "EV_S_CRTM_CONTENTS";
|
|
if (event_type == EV_S_CRTM_VERSION)
|
|
return "EV_S_CRTM_VERSION";
|
|
if (event_type == EV_CPU_MICROCODE)
|
|
return "EV_CPU_MICROCODE";
|
|
if (event_type == EV_PLATFORM_CONFIG_FLAGS)
|
|
return "EV_PLATFORM_CONFIG_FLAGS";
|
|
if (event_type == EV_TABLE_OF_DEVICES)
|
|
return "EV_TABLE_OF_DEVICES";
|
|
if (event_type == EV_COMPACT_HASH)
|
|
return "EV_COMPACT_HASH";
|
|
if (event_type == EV_NONHOST_CODE)
|
|
return "EV_NONHOST_CODE";
|
|
if (event_type == EV_NONHOST_CONFIG)
|
|
return "EV_NONHOST_CONFIG";
|
|
if (event_type == EV_NONHOST_INFO)
|
|
return "EV_NONHOST_INFO";
|
|
if (event_type == EV_OMIT_BOOT_DEVICE_EVENTS)
|
|
return "EV_OMIT_BOOT_DEVICE_EVENTS";
|
|
if (event_type == EV_EFI_EVENT_BASE)
|
|
return "EV_EFI_EVENT_BASE";
|
|
if (event_type == EV_EFI_VARIABLE_DRIVER_CONFIG)
|
|
return "EV_EFI_VARIABLE_DRIVER_CONFIG";
|
|
if (event_type == EV_EFI_VARIABLE_BOOT)
|
|
return "EV_EFI_VARIABLE_BOOT";
|
|
if (event_type == EV_EFI_BOOT_SERVICES_APPLICATION)
|
|
return "EV_BOOT_SERVICES_APPLICATION";
|
|
if (event_type == EV_EFI_BOOT_SERVICES_DRIVER)
|
|
return "EV_EFI_BOOT_SERVICES_DRIVER";
|
|
if (event_type == EV_EFI_RUNTIME_SERVICES_DRIVER)
|
|
return "EV_EFI_RUNTIME_SERVICES_DRIVER";
|
|
if (event_type == EV_EFI_GPT_EVENT)
|
|
return "EV_EFI_GPT_EVENT";
|
|
if (event_type == EV_EFI_ACTION)
|
|
return "EV_EFI_ACTION";
|
|
if (event_type == EV_EFI_PLATFORM_FIRMWARE_BLOB)
|
|
return "EV_EFI_PLATFORM_FIRMWARE_BLOB";
|
|
if (event_type == EV_EFI_HANDOFF_TABLES)
|
|
return "EV_EFI_HANDOFF_TABLES";
|
|
if (event_type == EV_EFI_HCRTM_EVENT)
|
|
return "EV_EFI_HCRTM_EVENT";
|
|
if (event_type == EV_EFI_VARIABLE_AUTHORITY)
|
|
return "EV_EFI_EFI_VARIABLE_AUTHORITY";
|
|
return NULL;
|
|
}
|
|
|
|
gchar *
|
|
fu_tpm_eventlog_strhex (GBytes *blob)
|
|
{
|
|
GString *csum = g_string_new (NULL);
|
|
gsize bufsz = 0;
|
|
const guint8 *buf = g_bytes_get_data (blob, &bufsz);
|
|
for (guint i = 0; i < bufsz; i++)
|
|
g_string_append_printf (csum, "%02x", buf[i]);
|
|
return g_string_free (csum, FALSE);
|
|
}
|
|
|
|
gchar *
|
|
fu_tpm_eventlog_blobstr (GBytes *blob)
|
|
{
|
|
gboolean has_printable = FALSE;
|
|
gsize bufsz = 0;
|
|
const guint8 *buf = g_bytes_get_data (blob, &bufsz);
|
|
g_autoptr(GString) str = g_string_new (NULL);
|
|
|
|
for (gsize i = 0; i < bufsz; i++) {
|
|
gchar chr = buf[i];
|
|
if (g_ascii_isprint (chr)) {
|
|
g_string_append_c (str, chr);
|
|
has_printable = TRUE;
|
|
} else {
|
|
g_string_append_c (str, '.');
|
|
}
|
|
}
|
|
if (!has_printable)
|
|
return NULL;
|
|
return g_string_free (g_steal_pointer (&str), FALSE);
|
|
}
|
|
|
|
GPtrArray *
|
|
fu_tpm_eventlog_calc_checksums (GPtrArray *items, guint8 pcr, GError **error)
|
|
{
|
|
guint cnt_sha1 = 0;
|
|
guint cnt_sha256 = 0;
|
|
guint8 digest_sha1[TPM2_SHA1_DIGEST_SIZE] = { 0x0 };
|
|
guint8 digest_sha256[TPM2_SHA256_DIGEST_SIZE] = { 0x0 };
|
|
gsize digest_sha1_len = sizeof(digest_sha1);
|
|
gsize digest_sha256_len = sizeof(digest_sha256);
|
|
g_autoptr(GPtrArray) csums = g_ptr_array_new_with_free_func (g_free);
|
|
|
|
/* sanity check */
|
|
if (items->len == 0) {
|
|
g_set_error_literal (error,
|
|
G_IO_ERROR,
|
|
G_IO_ERROR_INVALID_DATA,
|
|
"no event log data");
|
|
return NULL;
|
|
}
|
|
|
|
/* take existing PCR hash, append new measurement to that,
|
|
* hash that with the same algorithm */
|
|
for (guint i = 0; i < items->len; i++) {
|
|
FuTpmEventlogItem *item = g_ptr_array_index (items, i);
|
|
if (item->pcr != pcr)
|
|
continue;
|
|
if (item->checksum_sha1 != NULL) {
|
|
g_autoptr(GChecksum) csum_sha1 = g_checksum_new (G_CHECKSUM_SHA1);
|
|
g_checksum_update (csum_sha1,
|
|
(const guchar *) digest_sha1,
|
|
digest_sha1_len);
|
|
g_checksum_update (csum_sha1,
|
|
(const guchar *) g_bytes_get_data (item->checksum_sha1, NULL),
|
|
g_bytes_get_size (item->checksum_sha1));
|
|
g_checksum_get_digest (csum_sha1, digest_sha1, &digest_sha1_len);
|
|
cnt_sha1++;
|
|
}
|
|
if (item->checksum_sha256 != NULL) {
|
|
g_autoptr(GChecksum) csum_sha256 = g_checksum_new (G_CHECKSUM_SHA256);
|
|
g_checksum_update (csum_sha256,
|
|
(const guchar *) digest_sha256,
|
|
digest_sha256_len);
|
|
g_checksum_update (csum_sha256,
|
|
(const guchar *) g_bytes_get_data (item->checksum_sha256, NULL),
|
|
g_bytes_get_size (item->checksum_sha256));
|
|
g_checksum_get_digest (csum_sha256, digest_sha256, &digest_sha256_len);
|
|
cnt_sha256++;
|
|
}
|
|
}
|
|
if (cnt_sha1 == 0 && cnt_sha256 == 0) {
|
|
g_set_error_literal (error,
|
|
G_IO_ERROR,
|
|
G_IO_ERROR_INVALID_DATA,
|
|
"no SHA1 or SHA256 data");
|
|
return NULL;
|
|
}
|
|
if (cnt_sha1 > 0) {
|
|
g_autoptr(GBytes) blob_sha1 = NULL;
|
|
blob_sha1 = g_bytes_new_static (digest_sha1, sizeof(digest_sha1));
|
|
g_ptr_array_add (csums, fu_tpm_eventlog_strhex (blob_sha1));
|
|
}
|
|
if (cnt_sha256 > 0) {
|
|
g_autoptr(GBytes) blob_sha256 = NULL;
|
|
blob_sha256 = g_bytes_new_static (digest_sha256, sizeof(digest_sha256));
|
|
g_ptr_array_add (csums, fu_tpm_eventlog_strhex (blob_sha256));
|
|
}
|
|
return g_steal_pointer (&csums);
|
|
}
|