diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml
index e0fb212239b..10518dc791d 100644
--- a/man/systemd-analyze.xml
+++ b/man/systemd-analyze.xml
@@ -177,6 +177,11 @@
image-policyPOLICY
+
+ systemd-analyze
+ OPTIONS
+ has-tpm2
+ systemd-analyzeOPTIONS
@@ -948,6 +953,35 @@ default ignore - -
+
+ systemd-analyze has-tpm2
+
+ 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 yes and exits with exit status zero. If no such device is
+ discovered/supported/used, prints no. Otherwise prints
+ partial. 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.
+
+ Note, this checks for TPM 2.0 devices only, and does not consider TPM 1.2 at all.
+
+ Combine with to suppress the output.
+
+
+ Example Output
+
+ yes
++firmware
++driver
++system
++subsystem
++libraries
+
+
+
+
+
systemd-analyze pcrs PCR…
@@ -1653,6 +1687,12 @@ io.systemd.credential:vmm.notify_socket=vsock-stream:2:254570042
12, 0, 11 is returned if the second
version string is respectively larger, equal, or smaller to the first. In the three-argument form,
0 or 1 if the condition is respectively true or false.
+
+ In case of the has-tpm2 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.
diff --git a/man/systemd-creds.xml b/man/systemd-creds.xml
index c8419d357a1..8f972eeffba 100644
--- a/man/systemd-creds.xml
+++ b/man/systemd-creds.xml
@@ -177,22 +177,6 @@
-
- has-tpm2
-
- 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 yes and exits
- with exit status zero. If no such device is discovered/supported/used, prints
- no. Otherwise prints partial. 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.
-
- Combine with to suppress the output.
-
-
-
-
@@ -445,8 +429,7 @@
- When used with has-tpm2 suppresses the output, and only returns an
- exit status indicating support for TPM2.
+ Suppress additional output.
@@ -461,12 +444,6 @@
Exit statusOn success, 0 is returned.
-
- In case of the has-tpm2 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.
diff --git a/src/analyze/analyze-has-tpm2.c b/src/analyze/analyze-has-tpm2.c
new file mode 100644
index 00000000000..3e13be9f160
--- /dev/null
+++ b/src/analyze/analyze-has-tpm2.c
@@ -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
index 00000000000..c7c639228d8
--- /dev/null
+++ b/src/analyze/analyze-has-tpm2.h
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+int verb_has_tpm2(int argc, char *argv[], void *userdata);
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 1e199e30b70..24188311ff4 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -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 },
diff --git a/src/analyze/meson.build b/src/analyze/meson.build
index a307923c22e..c42db1a6336 100644
--- a/src/analyze/meson.build
+++ b/src/analyze/meson.build
@@ -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',
diff --git a/src/creds/creds.c b/src/creds/creds.c
index 7eec323b9ff..2e28ff3e0ab 100644
--- a/src/creds/creds.c
+++ b/src/creds/creds.c
@@ -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,
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index 10de296124a..38e4da40127 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -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;
diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h
index 6ab6c00af3a..31ce2e89dbc 100644
--- a/src/shared/tpm2-util.h
+++ b/src/shared/tpm2-util.h
@@ -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);
diff --git a/test/units/TEST-65-ANALYZE.sh b/test/units/TEST-65-ANALYZE.sh
index 9fc2de1a21d..db1cc585c75 100755
--- a/test/units/TEST-65-ANALYZE.sh
+++ b/test/units/TEST-65-ANALYZE.sh
@@ -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