fwupd/plugins/tpm-eventlog/fu-tpm-eventlog.c
Mario Limonciello 825c04df73 trivial: tpm-eventlog: Modify -p argument behavior
If using this argument, only display the final calculated value.
2020-04-29 13:18:53 -05:00

146 lines
4.1 KiB
C

/*
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#define G_LOG_DOMAIN "FuTpmEventlog"
#include "config.h"
#include <fwupd.h>
#include <glib/gi18n.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "fu-tpm-eventlog-parser.h"
static gint
fu_tmp_eventlog_sort_cb (gconstpointer a, gconstpointer b)
{
FuTpmEventlogItem *item_a = *((FuTpmEventlogItem **) a);
FuTpmEventlogItem *item_b = *((FuTpmEventlogItem **) b);
if (item_a->pcr > item_b->pcr)
return 1;
if (item_a->pcr < item_b->pcr)
return -1;
return 0;
}
static gboolean
fu_tmp_eventlog_process (const gchar *fn, gint pcr, GError **error)
{
gsize bufsz = 0;
g_autofree guint8 *buf = NULL;
g_autoptr(GPtrArray) items = NULL;
g_autoptr(GString) str = g_string_new (NULL);
gint max_pcr = 0;
/* parse this */
if (!g_file_get_contents (fn, (gchar **) &buf, &bufsz, error))
return FALSE;
items = fu_tpm_eventlog_parser_new (buf, bufsz,
FU_TPM_EVENTLOG_PARSER_FLAG_ALL_ALGS |
FU_TPM_EVENTLOG_PARSER_FLAG_ALL_PCRS,
error);
if (items == NULL)
return FALSE;
g_ptr_array_sort (items, fu_tmp_eventlog_sort_cb);
for (guint i = 0; i < items->len; i++) {
FuTpmEventlogItem *item = g_ptr_array_index (items, i);
if (item->pcr > max_pcr)
max_pcr = item->pcr;
if (pcr >= 0 && item->pcr != pcr)
continue;
fu_tpm_eventlog_item_to_string (item, 0, str);
g_string_append (str, "\n");
}
if (pcr > max_pcr) {
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
"invalid PCR specified: %d", pcr);
return FALSE;
}
fu_common_string_append_kv (str, 0, "Reconstructed PCRs", NULL);
for (guint8 i = 0; i <= max_pcr; i++) {
g_autoptr(GPtrArray) pcrs = fu_tpm_eventlog_calc_checksums (items, i, NULL);
if (pcrs == NULL)
continue;
for (guint j = 0; j < pcrs->len; j++) {
const gchar *csum = g_ptr_array_index (pcrs, j);
g_autofree gchar *title = NULL;
if (pcr >= 0 && i != (guint) pcr)
continue;
title = g_strdup_printf ("%x", i);
fu_common_string_append_kv (str, 1, title, csum);
}
}
/* success */
g_print ("%s", str->str);
return TRUE;
}
int
main (int argc, char *argv[])
{
const gchar *fn;
gboolean verbose = FALSE;
gboolean interactive = isatty (fileno (stdout)) != 0;
gint pcr = -1;
g_autoptr(GError) error = NULL;
g_autoptr(GOptionContext) context = g_option_context_new (NULL);
const GOptionEntry options[] = {
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
/* TRANSLATORS: command line option */
_("Show extra debugging information"), NULL },
{ "pcr", 'p', 0, G_OPTION_ARG_INT, &pcr,
/* TRANSLATORS: command line option */
_("Only show single PCR value"), NULL },
{ NULL}
};
#ifdef HAVE_GETUID
/* ensure root user */
if (argc < 2 && interactive && (getuid () != 0 || geteuid () != 0))
/* TRANSLATORS: we're poking around as a power user */
g_printerr ("%s\n", _("This program may only work correctly as root"));
#endif
setlocale (LC_ALL, "");
bindtextdomain (GETTEXT_PACKAGE, FWUPD_LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
/* TRANSLATORS: program name */
g_set_application_name (_("fwupd TPM event log utility"));
g_option_context_add_main_entries (context, options, NULL);
g_option_context_set_description (context,
"This tool will read and parse the TPM event log "
"from the system firwmare.");
if (!g_option_context_parse (context, &argc, &argv, &error)) {
/* TRANSLATORS: the user didn't read the man page */
g_print ("%s: %s\n", _("Failed to parse arguments"),
error->message);
return EXIT_FAILURE;
}
/* set verbose? */
if (verbose) {
g_setenv ("G_MESSAGES_DEBUG", "all", FALSE);
g_setenv ("FWUPD_TPM_EVENTLOG_VERBOSE", "1", FALSE);
}
/* allow user to chose a local file */
fn = argc <= 1 ? "/sys/kernel/security/tpm0/binary_bios_measurements" : argv[1];
if (!fu_tmp_eventlog_process (fn, pcr, &error)) {
/* TRANSLATORS: failed to read measurements file */
g_printerr ("%s: %s\n", _("Failed to parse file"),
error->message);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}