analyze: add "identify-tpm2" command that shows TPM2 chip information

This commit is contained in:
Lennart Poettering
2026-03-04 08:28:29 +01:00
parent 98a9844f3e
commit 205b70e328
5 changed files with 151 additions and 1 deletions
+25
View File
@@ -195,6 +195,11 @@
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="plain">has-tpm2</arg>
</cmdsynopsis>
<cmdsynopsis>
<command>systemd-analyze</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="plain">identify-tpm2</arg>
</cmdsynopsis>
<cmdsynopsis>
<command>systemd-analyze</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
@@ -1028,6 +1033,26 @@ default ignore - -</programlisting>
<xi:include href="version-info.xml" xpointer="v257"/>
</refsect2>
<refsect2>
<title><command>systemd-analyze identify-tpm2</command></title>
<para>Shows vendor information about the TPM 2.0 device discovered.</para>
<example>
<title>Example Output</title>
<programlisting> Family Indicator: 2.0
Level: 0
Revision: 1.59
Specification Date: Mon 2023-01-09
Manufacturer: STM
Vendor String: ST33KTPM2XSPI
Firmware Version: 9.258</programlisting>
</example>
<xi:include href="version-info.xml" xpointer="v260"/>
</refsect2>
<refsect2>
<title><command>systemd-analyze pcrs <optional><replaceable>PCR</replaceable>…</optional></command></title>
+1 -1
View File
@@ -77,7 +77,7 @@ _systemd_analyze() {
)
local -A VERBS=(
[STANDALONE]='time blame unit-files unit-paths exit-status compare-versions timestamp timespan pcrs nvpcrs srk has-tpm2 smbios11 chid image-policy'
[STANDALONE]='time blame unit-files unit-paths exit-status compare-versions timestamp timespan pcrs nvpcrs srk has-tpm2 identify-tpm2 smbios11 chid image-policy'
[CRITICAL_CHAIN]='critical-chain'
[DOT]='dot'
[DUMP]='dump'
+122
View File
@@ -2,8 +2,130 @@
#include "analyze.h"
#include "analyze-has-tpm2.h"
#include "format-table.h"
#include "log.h"
#include "string-util.h"
#include "time-util.h"
#include "tpm2-util.h"
int verb_has_tpm2(int argc, char **argv, void *userdata) {
return verb_has_tpm2_generic(arg_quiet);
}
int verb_identify_tpm2(int argc, char **argv, void *userdata) {
#if HAVE_TPM2
int r;
_cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
r = tpm2_context_new_or_warn(/* device= */ NULL, &c);
if (r < 0)
return r;
Tpm2VendorInfo info;
r = tpm2_get_vendor_info(c, &info);
if (r < 0)
return log_error_errno(r, "Failed to acquire TPM2 vendor information: %m");
_cleanup_(table_unrefp) Table *table = table_new_vertical();
if (!table)
return log_oom();
if (!isempty(info.family_indicator)) {
r = table_add_many(
table,
TABLE_FIELD, "Family Indicator",
TABLE_STRING, info.family_indicator);
if (r < 0)
return table_log_add_error(r);
}
_cleanup_free_ char *rv = NULL;
if (asprintf(&rv, "%" PRIu32 ".%" PRIu32,
info.revision_major,
info.revision_minor) < 0)
return log_oom();
r = table_add_many(
table,
TABLE_FIELD, "Level",
TABLE_UINT32, info.level,
TABLE_FIELD, "Revision",
TABLE_STRING, rv);
if (r < 0)
return table_log_add_error(r);
if (info.year >= 1900) {
struct tm tm = {
.tm_year = info.year - 1900,
.tm_mon = 0, /* january */
.tm_mday = info.day_of_year, /* timegm() will normalize this */
};
usec_t ts;
r = mktime_or_timegm_usec(&tm, /* utc= */ true, &ts);
if (r < 0)
log_debug_errno(r, "Failed to convert the specification date, ignoring.");
else {
r = table_add_many(
table,
TABLE_FIELD, "Specification Date",
TABLE_TIMESTAMP_DATE, ts);
if (r < 0)
return table_log_add_error(r);
}
}
if (!isempty(info.manufacturer)) {
r = table_add_many(
table,
TABLE_FIELD, "Manufacturer",
TABLE_STRING, info.manufacturer);
if (r < 0)
return table_log_add_error(r);
}
if (!isempty(info.vendor_string)) {
r = table_add_many(
table,
TABLE_FIELD, "Vendor String",
TABLE_STRING, info.vendor_string);
if (r < 0)
return table_log_add_error(r);
}
if (info.vendor_tpm_type != 0) {
r = table_add_many(
table,
TABLE_FIELD, "Vendor TPM Type",
TABLE_UINT32_HEX_0x, info.vendor_tpm_type);
if (r < 0)
return table_log_add_error(r);
}
/* Show the first two 16bit words of the firmware version as major/minor */
_cleanup_free_ char *fw = NULL;
if (asprintf(&fw, "%" PRIu16 ".%" PRIu16,
info.firmware_version_major,
info.firmware_version_minor) < 0)
return log_oom();
/* Show the second 32bit as a single value, if non-zero */
if (info.firmware_version2 != 0 && strextendf(&fw, ".%" PRIu32, info.firmware_version2) < 0)
return log_oom();
r = table_add_many(
table,
TABLE_FIELD, "Firmware Version",
TABLE_STRING, fw);
if (r < 0)
return table_log_add_error(r);
r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, /* show_header= */ false);
if (r < 0)
return r;
return EXIT_SUCCESS;
#else
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support not enabled at build time.");
#endif
}
+1
View File
@@ -2,3 +2,4 @@
#pragma once
int verb_has_tpm2(int argc, char *argv[], void *userdata);
int verb_identify_tpm2(int argc, char *argv[], void *userdata);
+2
View File
@@ -258,6 +258,7 @@ static int help(int argc, char *argv[], void *userdata) {
" dlopen-metadata FILE Parse and print ELF dlopen metadata\n"
"\n%3$sTPM Operations:%4$s\n"
" has-tpm2 Report whether TPM2 support is available\n"
" identify-tpm2 Show TPM2 vendor information\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"
@@ -810,6 +811,7 @@ static int run(int argc, char *argv[]) {
{ "fdstore", 2, VERB_ANY, 0, verb_fdstore },
{ "image-policy", 2, 2, 0, verb_image_policy },
{ "has-tpm2", VERB_ANY, 1, 0, verb_has_tpm2 },
{ "identify-tpm2", VERB_ANY, 1, 0, verb_identify_tpm2 },
{ "pcrs", VERB_ANY, VERB_ANY, 0, verb_pcrs },
{ "nvpcrs", VERB_ANY, VERB_ANY, 0, verb_nvpcrs },
{ "srk", VERB_ANY, 1, 0, verb_srk },