From: Lennart Poettering Date: Tue, 4 Jun 2024 09:03:39 +0000 (+0200) Subject: analyze: add new verb for determining NvPCR values X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d73d369133dde8b1d29c9e32e6d21cc2fbf3a876;p=thirdparty%2Fsystemd.git analyze: add new verb for determining NvPCR values --- diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index 04b8d8d41f0..fb95a3ec534 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -201,6 +201,12 @@ pcrs PCR + + systemd-analyze + OPTIONS + nvpcrs + NVPCR + systemd-analyze OPTIONS @@ -1059,6 +1065,24 @@ NR NAME SHA256 + + <command>systemd-analyze nvpcrs <optional><replaceable>NVPCR</replaceable>…</optional></command> + + This command shows the known TPM2 NvPCRs (additional PCRs stored in TPM2 NV indexes) along with + their identifying names and current values. + + + Example Output + + $ systemd-analyze nvpcrs +NAME NVINDEX VALUE +cryptsetup 0x1d10201 f400543943cc7215557ce672872ace5382e6d53177cc459078ba9277e41588d9 +hardware 0x1d10200 e155474936d7d74c893e6ece1099a2311d572cf23becea159dabf282db754284 + + + + + <command>systemd-analyze srk <optional>><replaceable>FILE</replaceable></optional></command> diff --git a/shell-completion/bash/systemd-analyze b/shell-completion/bash/systemd-analyze index 832da33021b..0ed8191c0a3 100644 --- a/shell-completion/bash/systemd-analyze +++ b/shell-completion/bash/systemd-analyze @@ -68,7 +68,7 @@ _systemd_analyze() { ) local -A VERBS=( - [STANDALONE]='time blame unit-files unit-paths exit-status compare-versions calendar timestamp timespan pcrs srk has-tpm2 smbios11 chid' + [STANDALONE]='time blame unit-files unit-paths exit-status compare-versions calendar timestamp timespan pcrs nvpcrs srk has-tpm2 smbios11 chid' [CRITICAL_CHAIN]='critical-chain' [DOT]='dot' [DUMP]='dump' diff --git a/src/analyze/analyze-nvpcrs.c b/src/analyze/analyze-nvpcrs.c new file mode 100644 index 00000000000..0fc7b163cf8 --- /dev/null +++ b/src/analyze/analyze-nvpcrs.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "alloc-util.h" +#include "analyze-nvpcrs.h" +#include "analyze.h" +#include "conf-files.h" +#include "constants.h" +#include "format-table.h" +#include "hexdecoct.h" +#include "string-util.h" +#include "strv.h" +#include "tpm2-util.h" + +#if HAVE_TPM2 +static int add_nvpcr_to_table(Tpm2Context **c, Table *t, const char *name) { + int r; + + _cleanup_free_ char *h = NULL; + uint32_t nv_index = 0; + if (c) { + if (!*c) { + r = tpm2_context_new_or_warn(/* device= */ NULL, c); + if (r < 0) + return r; + } + + _cleanup_(iovec_done) struct iovec digest = {}; + r = tpm2_nvpcr_read(*c, /* session= */ NULL, name, &digest, &nv_index); + if (r < 0) + return log_error_errno(r, "Failed to read NvPCR '%s': %m", name); + + h = hexmem(digest.iov_base, digest.iov_len); + if (!h) + return log_oom(); + } else { + r = tpm2_nvpcr_get_index(name, &nv_index); + if (r < 0) + return log_error_errno(r, "Failed to get NV index of NvPCR '%s': %m", name); + } + + r = table_add_many( + t, + TABLE_STRING, name, + TABLE_UINT32_HEX_0x, nv_index, + TABLE_STRING, h); + if (r < 0) + return table_log_add_error(r); + + return 0; +} +#endif + +int verb_nvpcrs(int argc, char *argv[], void *userdata) { +#if HAVE_TPM2 + _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + int r; + + bool have_tpm2 = tpm2_is_fully_supported(); + + if (!have_tpm2) + log_notice("System lacks full TPM2 support, not showing NvPCR state."); + + table = table_new("name", "nvindex", "value"); + if (!table) + return log_oom(); + + (void) table_set_align_percent(table, table_get_cell(table, 0, 1), 100); + (void) table_set_ersatz_string(table, TABLE_ERSATZ_DASH); + (void) table_set_sort(table, (size_t) 0); + + if (!have_tpm2) + (void) table_hide_column_from_display(table, (size_t) 2); + + if (strv_isempty(strv_skip(argv, 1))) { + _cleanup_strv_free_ char **l = NULL; + r = conf_files_list_nulstr( + &l, + ".nvpcr", + /* root= */ NULL, + CONF_FILES_REGULAR|CONF_FILES_BASENAME|CONF_FILES_FILTER_MASKED|CONF_FILES_TRUNCATE_SUFFIX, + CONF_PATHS_NULSTR("nvpcr")); + if (r < 0) + return log_error_errno(r, "Failed to find .nvpcr files: %m"); + + STRV_FOREACH(i, l) { + r = add_nvpcr_to_table(have_tpm2 ? &c : NULL, table, *i); + if (r < 0) + return r; + } + } else + for (int i = 1; i < argc; i++) { + r = add_nvpcr_to_table(have_tpm2 ? &c : NULL, table, argv[i]); + if (r < 0) + return r; + } + + if (table_isempty(table) && FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) + log_notice("No NvPCRs defined."); + else { + r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, /* show_header= */ true); + if (r < 0) + return log_error_errno(r, "Failed to output table: %m"); + } + + return EXIT_SUCCESS; +#else + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support not enabled at build time."); +#endif +} diff --git a/src/analyze/analyze-nvpcrs.h b/src/analyze/analyze-nvpcrs.h new file mode 100644 index 00000000000..258005617ea --- /dev/null +++ b/src/analyze/analyze-nvpcrs.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +int verb_nvpcrs(int argc, char *argv[], void *userdata); diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 9b611daadef..d3040d03e00 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -33,6 +33,7 @@ #include "analyze-inspect-elf.h" #include "analyze-log-control.h" #include "analyze-malloc.h" +#include "analyze-nvpcrs.h" #include "analyze-pcrs.h" #include "analyze-plot.h" #include "analyze-security.h" @@ -258,6 +259,7 @@ static int help(int argc, char *argv[], void *userdata) { "\n%3$sTPM Operations:%4$s\n" " has-tpm2 Report whether TPM2 support is available\n" " pcrs [PCR...] Show TPM2 PCRs and their names\n" + " nvpcrs [NVPCR...] Show additional TPM2 PCRs stored in NV indexes\n" " srk [>FILE] Write TPM2 SRK (to FILE)\n" "\n%3$sOptions:%4$s\n" " --recursive-errors=MODE Control which units are verified\n" @@ -713,6 +715,10 @@ done: return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --offline= requires one or more units to perform a security review."); + if (arg_json_format_flags != SD_JSON_FORMAT_OFF && !STRPTR_IN_SET(argv[optind], "security", "inspect-elf", "dlopen-metadata", "plot", "fdstore", "pcrs", "nvpcrs", "architectures", "capability", "exit-status")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --json= is only supported for security, inspect-elf, dlopen-metadata, plot, fdstore, pcrs, nvpcrs, architectures, capability, exit-status right now."); + if (arg_threshold != 100 && !streq_ptr(argv[optind], "security")) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --threshold= is only supported for security right now."); @@ -806,6 +812,7 @@ static int run(int argc, char *argv[]) { { "image-policy", 2, 2, 0, verb_image_policy }, { "has-tpm2", VERB_ANY, 1, 0, verb_has_tpm2 }, { "pcrs", VERB_ANY, VERB_ANY, 0, verb_pcrs }, + { "nvpcrs", VERB_ANY, VERB_ANY, 0, verb_nvpcrs }, { "srk", VERB_ANY, 1, 0, verb_srk }, { "architectures", VERB_ANY, VERB_ANY, 0, verb_architectures }, { "smbios11", VERB_ANY, 1, 0, verb_smbios11 }, diff --git a/src/analyze/meson.build b/src/analyze/meson.build index e26426fc6c8..03fade3f4bb 100644 --- a/src/analyze/meson.build +++ b/src/analyze/meson.build @@ -21,6 +21,7 @@ systemd_analyze_sources = files( 'analyze-inspect-elf.c', 'analyze-log-control.c', 'analyze-malloc.c', + 'analyze-nvpcrs.c', 'analyze-pcrs.c', 'analyze-plot.c', 'analyze-security.c',