]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
creds-tool: add new "has-tpm2" verb
authorLennart Poettering <lennart@poettering.net>
Tue, 19 Apr 2022 12:47:02 +0000 (14:47 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 20 Apr 2022 14:58:18 +0000 (16:58 +0200)
Sometimes it's useful from shell scripts to check if we have a working
TPM2 chip around. For example, when putting together encrypted
credentials for the initrd (after all: it might be wise to place the
root pw in a credential for the initrd to consume, but do so only if we
can lock it to the TPM2, and not otherwise, so that we risk nothing).

Hence, let's add a new "systemd-creds has-tpm2" verb: it returns zero if we
have a working TPM2 (which means: supported by kernel + firmware + us),
or non-zero otherwise. Also show which parts are available.

Use-case: in future the 'kernel-install' script should use this when
deciding whether to augment kernels with security sensitive credentials.

src/creds/creds.c
src/shared/tpm2-util.h

index 6e3441e5a0b1586d5c6974c5a3db59f6fd692360..1d69aed4c44f164a20c4db827af2667631c1da3b 100644 (file)
@@ -48,6 +48,7 @@ static bool arg_name_any = false;
 static usec_t arg_timestamp = USEC_INFINITY;
 static usec_t arg_not_after = USEC_INFINITY;
 static bool arg_pretty = false;
+static bool arg_quiet = false;
 
 static const char* transcode_mode_table[_TRANSCODE_MAX] = {
         [TRANSCODE_OFF] = "off",
@@ -525,6 +526,34 @@ static int verb_setup(int argc, char **argv, void *userdata) {
         return EXIT_SUCCESS;
 }
 
+static int verb_has_tpm2(int argc, char **argv, void *userdata) {
+        Tpm2Support s;
+
+        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",
+                       plus_minus(s & TPM2_SUPPORT_FIRMWARE),
+                       plus_minus(s & TPM2_SUPPORT_DRIVER),
+                       plus_minus(s & TPM2_SUPPORT_SYSTEM));
+        }
+
+        /* 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 statusses it is customary to return
+         * zero (EXIT_FAILURE) when all is good, instead of all being bad. */
+        return ~s & TPM2_SUPPORT_FULL;
+}
+
 static int verb_help(int argc, char **argv, void *userdata) {
         _cleanup_free_ char *link = NULL;
         int r;
@@ -543,6 +572,7 @@ 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"
@@ -568,6 +598,7 @@ static int verb_help(int argc, char **argv, void *userdata) {
                "                          Pick TPM2 device\n"
                "     --tpm2-pcrs=PCR1+PCR2+PCR3+…\n"
                "                          Specify TPM2 PCRs to seal against\n"
+               "  -q --quiet              Suppress output for 'has-tpm2' verb\n"
                "\nSee the %2$s for details.\n"
                , program_invocation_short_name
                , link
@@ -612,6 +643,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "name",        required_argument, NULL, ARG_NAME        },
                 { "timestamp",   required_argument, NULL, ARG_TIMESTAMP   },
                 { "not-after",   required_argument, NULL, ARG_NOT_AFTER   },
+                { "quiet",       no_argument,       NULL, 'q'             },
                 {}
         };
 
@@ -620,7 +652,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hHTp", options, NULL)) >= 0) {
+        while ((c = getopt_long(argc, argv, "hHTpq", options, NULL)) >= 0) {
 
                 switch (c) {
 
@@ -757,6 +789,10 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case 'q':
+                        arg_quiet = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -774,12 +810,13 @@ static int parse_argv(int argc, char *argv[]) {
 static int creds_main(int argc, char *argv[]) {
 
         static const Verb verbs[] = {
-                { "list",    VERB_ANY, 1,        VERB_DEFAULT, verb_list    },
-                { "cat",     2,        VERB_ANY, 0,            verb_cat     },
-                { "encrypt", 3,        3,        0,            verb_encrypt },
-                { "decrypt", 2,        3,        0,            verb_decrypt },
-                { "setup",   VERB_ANY, 1,        0,            verb_setup   },
-                { "help",    VERB_ANY, 1,        0,            verb_help    },
+                { "list",     VERB_ANY, 1,        VERB_DEFAULT, verb_list     },
+                { "cat",      2,        VERB_ANY, 0,            verb_cat      },
+                { "encrypt",  3,        3,        0,            verb_encrypt  },
+                { "decrypt",  2,        3,        0,            verb_decrypt  },
+                { "setup",    VERB_ANY, 1,        0,            verb_setup    },
+                { "help",     VERB_ANY, 1,        0,            verb_help     },
+                { "has-tpm2", VERB_ANY, 1,        0,            verb_has_tpm2 },
                 {}
         };
 
index 7a0c47e233cea1eb70611f4ac468ca0995e932b9..ef19bed4f6cbb157e12475f89bdadfa2b00ae006 100644 (file)
@@ -91,6 +91,8 @@ typedef struct {
 } systemd_tpm2_plugin_params;
 
 typedef enum Tpm2Support {
+        /* NOTE! The systemd-creds tool returns these flags 1:1 as exit status. Hence these flags are pretty
+         * much ABI! Hence, be extra careful when changing/extending these definitions. */
         TPM2_SUPPORT_NONE     = 0,       /* no support */
         TPM2_SUPPORT_FIRMWARE = 1 << 0,  /* firmware reports TPM2 was used */
         TPM2_SUPPORT_DRIVER   = 1 << 1,  /* the kernel has a driver loaded for it */