This is pretty low-level functionality, hence placed in systemd-analyze.
This is useful for working with systemd-cryptenroll --tpm2-device-key=,
as it acquires the SRK without requiring the full tpm2-tss tool set.
<arg choice="plain">pcrs</arg>
<arg choice="opt" rep="repeat"><replaceable>PCR</replaceable></arg>
</cmdsynopsis>
+ <cmdsynopsis>
+ <command>systemd-analyze</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain">srk</arg> ><arg choice="plain"><replaceable>FILE</replaceable></arg>
+ </cmdsynopsis>
</refsynopsisdiv>
<refsect1>
23 application-support 0000000000000000000000000000000000000000000000000000000000000000</programlisting>
</example>
</refsect2>
+
+ <refsect2>
+ <title><command>systemd-analyze srk > <replaceable>FILE</replaceable></command></title>
+
+ <para>This command reads the Storage Root Key (SRK) from the TPM2 device, and writes it in marshalled
+ TPM2B_PUBLIC format to stdout. Example:</para>
+
+ <programlisting>systemd-analyze srk > srk.tpm2b_public</programlisting>
+ </refsect2>
+
</refsect1>
<refsect1>
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "analyze.h"
+#include "analyze-srk.h"
+#include "tpm2-util.h"
+
+int verb_srk(int argc, char *argv[], void *userdata) {
+#if HAVE_TPM2
+ _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
+ _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
+ int r;
+
+ r = tpm2_context_new(/* device= */ NULL, &c);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create TPM2 context: %m");
+
+ r = tpm2_get_srk(
+ c,
+ /* session= */ NULL,
+ &public,
+ /* ret_name= */ NULL,
+ /* ret_qname= */ NULL,
+ /* ret_handle= */ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get SRK: %m");
+ if (r == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "No SRK stored so far.");
+
+ _cleanup_free_ void *marshalled = NULL;
+ size_t marshalled_size = 0;
+ r = tpm2_marshal_public(public, &marshalled, &marshalled_size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to marshal SRK: %m");
+
+ if (isatty(STDOUT_FILENO))
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Refusing to write binary data to TTY, please redirect output to file.");
+
+ if (fwrite(marshalled, 1, marshalled_size, stdout) != marshalled_size)
+ return log_error_errno(errno, "Failed to write SRK to stdout: %m");
+
+ fflush(stdout);
+
+ return EXIT_SUCCESS;
+#else
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support not available.");
+#endif
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+int verb_srk(int argc, char *argv[], void *userdata);
#include "analyze-plot.h"
#include "analyze-security.h"
#include "analyze-service-watchdogs.h"
+#include "analyze-srk.h"
#include "analyze-syscall-filter.h"
#include "analyze-time.h"
#include "analyze-time-data.h"
" malloc [D-BUS SERVICE...] Dump malloc stats of a D-Bus service\n"
" fdstore SERVICE... Show file descriptor store contents of service\n"
" pcrs [PCR...] Show TPM2 PCRs and their names\n"
+ " srk > FILE Write TPM2 SRK to stdout\n"
"\nOptions:\n"
" --recursive-errors=MODE Control which units are verified\n"
" --offline=BOOL Perform a security review on unit file(s)\n"
{ "fdstore", 2, VERB_ANY, 0, verb_fdstore },
{ "image-policy", 2, 2, 0, verb_image_policy },
{ "pcrs", VERB_ANY, VERB_ANY, 0, verb_pcrs },
+ { "srk", VERB_ANY, 1, 0, verb_srk },
{}
};
'analyze-plot.c',
'analyze-security.c',
'analyze-service-watchdogs.c',
+ 'analyze-srk.c',
'analyze-syscall-filter.c',
'analyze-time.c',
'analyze-time-data.c',