analyze: move "has-tpm2" from systemd-creds to systemd-analyze
authorLennart Poettering <lennart@poettering.net>
Fri, 31 May 2024 10:00:00 +0000 (12:00 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 12 Sep 2024 10:56:03 +0000 (12:56 +0200)
The verb s not really specific to credential management, it was always a
bit misplaced. Hence move it to systemd-analyze, where we already have
some general TPM related verbs such as "srk" and "pcrs"

man/systemd-analyze.xml
man/systemd-creds.xml
src/analyze/analyze-has-tpm2.c [new file with mode: 0644]
src/analyze/analyze-has-tpm2.h [new file with mode: 0644]
src/analyze/analyze.c
src/analyze/meson.build
src/creds/creds.c
src/shared/tpm2-util.c
src/shared/tpm2-util.h
test/units/TEST-65-ANALYZE.sh

index e0fb212239b1ce59997361164c281f2ed5dc0138..10518dc791d5a8bea95f23dc13925be9090c35f4 100644 (file)
       <arg choice="plain">image-policy</arg>
       <arg choice="plain" rep="repeat"><replaceable>POLICY</replaceable></arg>
     </cmdsynopsis>
+    <cmdsynopsis>
+      <command>systemd-analyze</command>
+      <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>
@@ -948,6 +953,35 @@ default         ignore      -         -</programlisting>
       </example>
     </refsect2>
 
+    <refsect2>
+      <title><command>systemd-analyze has-tpm2</command></title>
+
+      <para>Reports whether the system is equipped with a usable TPM2 device. If a TPM2 device has been
+      discovered, is supported, and is being used by firmware, by the OS kernel drivers and by userspace
+      (i.e. systemd) this prints <literal>yes</literal> and exits with exit status zero. If no such device is
+      discovered/supported/used, prints <literal>no</literal>. Otherwise prints
+      <literal>partial</literal>. In either of these two cases exits with non-zero exit status. It also shows
+      five lines indicating separately whether firmware, drivers, the system, the kernel and libraries
+      discovered/support/use TPM2.</para>
+
+      <para>Note, this checks for TPM 2.0 devices only, and does not consider TPM 1.2 at all.</para>
+
+      <para>Combine with <option>--quiet</option> to suppress the output.</para>
+
+      <example>
+        <title>Example Output</title>
+
+        <programlisting>yes
++firmware
++driver
++system
++subsystem
++libraries</programlisting>
+      </example>
+
+      <xi:include href="version-info.xml" xpointer="v257"/>
+    </refsect2>
+
     <refsect2>
       <title><command>systemd-analyze pcrs <optional><replaceable>PCR</replaceable>…</optional></command></title>
 
@@ -1653,6 +1687,12 @@ io.systemd.credential:vmm.notify_socket=vsock-stream:2:254570042
     <constant>12</constant>, <constant>0</constant>, <constant>11</constant> is returned if the second
     version string is respectively larger, equal, or smaller to the first. In the three-argument form,
     <constant>0</constant> or <constant>1</constant> if the condition is respectively true or false.</para>
+
+    <para>In case of the <command>has-tpm2</command> command returns 0 if a TPM2 device is discovered,
+    supported and used by firmware, driver, and userspace (i.e. systemd). Otherwise returns the OR
+    combination of the value 1 (in case firmware support is missing), 2 (in case driver support is missing)
+    and 4 (in case userspace support is missing). If no TPM2 support is available at all, value 7 is hence
+    returned.</para>
   </refsect1>
 
   <xi:include href="common-variables.xml" />
index c8419d357a14bdb74ec2ec21712a49935adb65bf..8f972eeffba1e42ae18eefe9dd0d72381c6ab6aa 100644 (file)
         <xi:include href="version-info.xml" xpointer="v250"/></listitem>
       </varlistentry>
 
-      <varlistentry>
-        <term><command>has-tpm2</command></term>
-
-        <listitem><para>Reports whether the system is equipped with a TPM2 device usable for protecting
-        credentials. If a TPM2 device has been discovered, is supported, and is being used by firmware,
-        by the OS kernel drivers and by userspace (i.e. systemd) this prints <literal>yes</literal> and exits
-        with exit status zero. If no such device is discovered/supported/used, prints
-        <literal>no</literal>. Otherwise prints <literal>partial</literal>. In either of these two cases
-        exits with non-zero exit status. It also shows four lines indicating separately whether firmware,
-        drivers, the system and the kernel discovered/support/use TPM2.</para>
-
-        <para>Combine with <option>--quiet</option> to suppress the output.</para>
-
-        <xi:include href="version-info.xml" xpointer="v251"/></listitem>
-      </varlistentry>
-
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
     </variablelist>
         <term><option>--quiet</option></term>
         <term><option>-q</option></term>
 
-        <listitem><para>When used with <command>has-tpm2</command> suppresses the output, and only returns an
-        exit status indicating support for TPM2.</para>
+        <listitem><para>Suppress additional output.</para>
 
         <xi:include href="version-info.xml" xpointer="v251"/></listitem>
       </varlistentry>
     <title>Exit status</title>
 
     <para>On success, 0 is returned.</para>
-
-    <para>In case of the <command>has-tpm2</command> command returns 0 if a TPM2 device is discovered,
-    supported and used by firmware, driver, and userspace (i.e. systemd). Otherwise returns the OR
-    combination of the value 1 (in case firmware support is missing), 2 (in case driver support is missing)
-    and 4 (in case userspace support is missing). If no TPM2 support is available at all, value 7 is hence
-    returned.</para>
   </refsect1>
 
   <refsect1>
diff --git a/src/analyze/analyze-has-tpm2.c b/src/analyze/analyze-has-tpm2.c
new file mode 100644 (file)
index 0000000..3e13be9
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "analyze.h"
+#include "analyze-has-tpm2.h"
+#include "tpm2-util.h"
+
+int verb_has_tpm2(int argc, char **argv, void *userdata) {
+        return verb_has_tpm2_generic(arg_quiet);
+}
diff --git a/src/analyze/analyze-has-tpm2.h b/src/analyze/analyze-has-tpm2.h
new file mode 100644 (file)
index 0000000..c7c6392
--- /dev/null
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+int verb_has_tpm2(int argc, char *argv[], void *userdata);
index 1e199e30b70c99ded0135754fceee74db64d8fbb..24188311ff49c87ab263d5682a5a26de729f519b 100644 (file)
@@ -26,6 +26,7 @@
 #include "analyze-exit-status.h"
 #include "analyze-fdstore.h"
 #include "analyze-filesystems.h"
+#include "analyze-has-tpm2.h"
 #include "analyze-image-policy.h"
 #include "analyze-inspect-elf.h"
 #include "analyze-log-control.h"
@@ -253,6 +254,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "\n%3$sExecutable Analysis:%4$s\n"
                "  inspect-elf FILE...        Parse and print ELF package metadata\n"
                "\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"
                "  srk [>FILE]                Write TPM2 SRK (to FILE)\n"
                "\n%3$sOptions:%4$s\n"
@@ -700,6 +702,7 @@ static int run(int argc, char *argv[]) {
                 { "malloc",            VERB_ANY, VERB_ANY, 0,            verb_malloc            },
                 { "fdstore",           2,        VERB_ANY, 0,            verb_fdstore           },
                 { "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              },
                 { "srk",               VERB_ANY, 1,        0,            verb_srk               },
                 { "architectures",     VERB_ANY, VERB_ANY, 0,            verb_architectures     },
index a307923c22eab12273d574aac1b3294c61a2f69b..c42db1a63360d4f69cd4457b01bb570d58208c8b 100644 (file)
@@ -14,6 +14,7 @@ systemd_analyze_sources = files(
         'analyze-exit-status.c',
         'analyze-fdstore.c',
         'analyze-filesystems.c',
+        'analyze-has-tpm2.c',
         'analyze-image-policy.c',
         'analyze-inspect-elf.c',
         'analyze-log-control.c',
index 7eec323b9ffd6053c856969c5e93bf021f4d5053..2e28ff3e0ab7f277555664ff2d4bf02490171d62 100644 (file)
@@ -7,6 +7,7 @@
 #include "sd-varlink.h"
 
 #include "build.h"
+#include "build-path.h"
 #include "bus-polkit.h"
 #include "creds-util.h"
 #include "dirent-util.h"
@@ -690,35 +691,10 @@ static int verb_setup(int argc, char **argv, void *userdata) {
 }
 
 static int verb_has_tpm2(int argc, char **argv, void *userdata) {
-        Tpm2Support s;
+        if (!arg_quiet)
+                log_notice("The 'systemd-creds %1$s' command has been replaced by 'systemd-analyze %1$s'. Redirecting invocation.", argv[optind]);
 
-        s = tpm2_support();
-
-        if (!arg_quiet) {
-                if (s == TPM2_SUPPORT_FULL)
-                        puts("yes");
-                else if (s == TPM2_SUPPORT_NONE)
-                        puts("no");
-                else
-                        puts("partial");
-
-                printf("%sfirmware\n"
-                       "%sdriver\n"
-                       "%ssystem\n"
-                       "%ssubsystem\n"
-                       "%slibraries\n",
-                       plus_minus(s & TPM2_SUPPORT_FIRMWARE),
-                       plus_minus(s & TPM2_SUPPORT_DRIVER),
-                       plus_minus(s & TPM2_SUPPORT_SYSTEM),
-                       plus_minus(s & TPM2_SUPPORT_SUBSYSTEM),
-                       plus_minus(s & TPM2_SUPPORT_LIBRARIES));
-        }
-
-        /* Return inverted bit flags. So that TPM2_SUPPORT_FULL becomes EXIT_SUCCESS and the other values
-         * become some reasonable values 1…7. i.e. the flags we return here tell what is missing rather than
-         * what is there, acknowledging the fact that for process exit statuses it is customary to return
-         * zero (EXIT_FAILURE) when all is good, instead of all being bad. */
-        return ~s & TPM2_SUPPORT_FULL;
+        return verb_has_tpm2_generic(arg_quiet);
 }
 
 static int verb_help(int argc, char **argv, void *userdata) {
@@ -739,7 +715,6 @@ static int verb_help(int argc, char **argv, void *userdata) {
                "                          ciphertext credential file\n"
                "  decrypt INPUT [OUTPUT]  Decrypt ciphertext credential file and write to\n"
                "                          plaintext credential file\n"
-               "  has-tpm2                Report whether TPM2 support is available\n"
                "  -h --help               Show this help\n"
                "     --version            Show package version\n"
                "\n%3$sOptions:%4$s\n"
@@ -774,7 +749,6 @@ static int verb_help(int argc, char **argv, void *userdata) {
                "     --user               Select user-scoped credential encryption\n"
                "     --uid=UID            Select user for scoped credentials\n"
                "     --allow-null         Allow decrypting credentials with empty key\n"
-               "  -q --quiet              Suppress output for 'has-tpm2' verb\n"
                "\nSee the %2$s for details.\n",
                program_invocation_short_name,
                link,
index 10de296124adfd327c98500cff16b968345666ac..38e4da40127b23221bf23be2823fce6c8bdfa57c 100644 (file)
@@ -7907,6 +7907,38 @@ Tpm2Support tpm2_support(void) {
         return support;
 }
 
+int verb_has_tpm2_generic(bool quiet) {
+        Tpm2Support s;
+
+        s = tpm2_support();
+
+        if (!quiet) {
+                if (s == TPM2_SUPPORT_FULL)
+                        puts("yes");
+                else if (s == TPM2_SUPPORT_NONE)
+                        puts("no");
+                else
+                        puts("partial");
+
+                printf("%sfirmware\n"
+                       "%sdriver\n"
+                       "%ssystem\n"
+                       "%ssubsystem\n"
+                       "%slibraries\n",
+                       plus_minus(s & TPM2_SUPPORT_FIRMWARE),
+                       plus_minus(s & TPM2_SUPPORT_DRIVER),
+                       plus_minus(s & TPM2_SUPPORT_SYSTEM),
+                       plus_minus(s & TPM2_SUPPORT_SUBSYSTEM),
+                       plus_minus(s & TPM2_SUPPORT_LIBRARIES));
+        }
+
+        /* Return inverted bit flags. So that TPM2_SUPPORT_FULL becomes EXIT_SUCCESS and the other values
+         * become some reasonable values 1…7. i.e. the flags we return here tell what is missing rather than
+         * what is there, acknowledging the fact that for process exit statuses it is customary to return
+         * zero (EXIT_FAILURE) when all is good, instead of all being bad. */
+        return ~s & TPM2_SUPPORT_FULL;
+}
+
 #if HAVE_TPM2
 static void tpm2_pcr_values_apply_default_hash_alg(Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
         TPMI_ALG_HASH default_hash = 0;
index 6ab6c00af3ae53b8307f5b509a0fa96db44839bd..31ce2e89dbc119631e8e67f4fb49a188aa386043 100644 (file)
@@ -463,6 +463,8 @@ typedef enum Tpm2Support {
 
 Tpm2Support tpm2_support(void);
 
+int verb_has_tpm2_generic(bool quiet);
+
 int tpm2_parse_pcr_argument(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values);
 int tpm2_parse_pcr_argument_append(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values);
 int tpm2_parse_pcr_argument_to_mask(const char *arg, uint32_t *mask);
index 9fc2de1a21d6c13dada9ab6d735d6db028ea3811..db1cc585c75e4dfab1aedc4468008139272933e7 100755 (executable)
@@ -965,6 +965,13 @@ systemd-analyze condition --instance=tmp --unit=systemd-growfs@.service
 systemd-analyze verify --instance=tmp --man=no systemd-growfs@.service
 systemd-analyze security --instance=tmp systemd-growfs@.service
 
+systemd-analyze has-tpm2 ||:
+if systemd-analyze has-tpm2 -q ; then
+    echo "have tpm2"
+else
+    echo "have no tpm2"
+fi
+
 systemd-analyze log-level info
 
 touch /testok