]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme-gen-tls-key: add options to derive a TLS key
authorHannes Reinecke <hare@suse.de>
Wed, 22 Mar 2023 14:58:27 +0000 (15:58 +0100)
committerDaniel Wagner <wagi@monom.org>
Mon, 27 Mar 2023 15:56:52 +0000 (17:56 +0200)
Add options to derive a TLS key and store it into the given keyring.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Documentation/nvme-gen-tls-key.txt
nvme.c

index cfa861470865f9dc31e4b9ad60f7ac3f186cab9d..9a03e3ab31104997a6a430f4efff736c1597cd46 100644 (file)
@@ -8,18 +8,52 @@ nvme-gen-tls-key - Generate a NVMe TLS PSK
 SYNOPSIS
 --------
 [verse]
-'nvme gen-tls-key' [--hmac=<hmac-id> | -h <hmac-id>]
+'nvme gen-tls-key' [--keyring=<name> | -k <name>]
+                      [--keytype=<type> | -t <type> ]
+                     [--hostnqn=<nqn> | -n <nqn>]
+                     [--subsysnqn=<nqn> | -c <nqn>]
+                     [--hmac=<hmac-id> | -h <hmac-id>]
                      [--secret=<secret> | -s <secret> ]
+                     [--insert | -i ]
 
 DESCRIPTION
 -----------
-Generate a base64-encoded NVMe TLS pre-shared key (PSK) in
-the PSK interchange format
-NVMeTLSkey-1:01:VRLbtnN9AQb2WXW3c9+wEf/DRLz0QuLdbYvEhwtdWwNf9LrZ:
-and prints it to stdout.
+Generate a base64-encoded NVMe TLS pre-shared key (PSK).
+The resulting key is either printed in the PSK interchange format
+'NVMeTLSkey-1:01:<base64 encoded data>:',
+inserted as a 'retained' key into the specified keyring, or both.
+When the PSK should be inserted into the keyring a 'retained' key
+is derived from the secret key material, and the resulting 'retained'
+key is stored with the identity
+'NVMe0R0<hmac> <host NQN> <subsystem NQN>'
+in the keyring.
+The 'retained' key is derived from the secret key material,
+the specified subsystem NQN, and the host NQN.
+Once the 'retained' key is stored in the keyring the original
+secret key material cannot be retrieved.
 
 OPTIONS
 -------
+-k <name>::
+--keyring=<name>::
+       Name of the keyring into which the 'retained' TLS key should be
+       stored. Default is '.nvme'.
+
+-t <type>::
+--keytype=<type>::
+       Type of the key for resulting TLS key.
+       Default is 'psk'.
+
+-n <nqn>::
+--hostnqn=<nqn>::
+       Host NVMe Qualified Name (NQN) to be used to derive the
+       'retained' TLS key
+
+-c <nqn>::
+--subsysnqn=<nqn>::
+       Subsystem NVMe Qualified Name (NQN) to be used to derive the
+       'retained' TLS key
+
 -h <hmac-id>::
 --hmac=<hmac-id>::
        Select a HMAC algorithm to use. Possible values are:
@@ -31,6 +65,11 @@ OPTIONS
        Secret value (in hexadecimal) to be used for the key. If none are
        provided a random value is used.
 
+-i::
+--insert::
+       Insert the resulting TLS key into the keyring without printing out
+       the key in PSK interchange format.
+
 EXAMPLES
 --------
 No Examples
diff --git a/nvme.c b/nvme.c
index a40a58c8a94584f8514f379d2e1ca25fac3149b0..4c0d44ff7f0cafc7993a4398b398788f2918eb2e 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -8827,26 +8827,47 @@ static int gen_tls_key(int argc, char **argv, struct command *command, struct pl
                "to be used for the TLS key.";
        const char *hmac = "HMAC function to use for the retained key "\
                "(1 = SHA-256, 2 = SHA-384).";
+       const char *hostnqn = "Host NQN for the retained key.";
+       const char *subsysnqn = "Subsystem NQN for the retained key.";
+       const char *keyring = "Keyring for the retained key.";
+       const char *keytype = "Key type of the retained key.";
+       const char *insert = "Insert only, do not print the retained key.";
 
        unsigned char *raw_secret;
        char encoded_key[128];
        int key_len = 32;
        unsigned long crc = crc32(0L, NULL, 0);
-       int err = 0;
+       int err;
+       long tls_key;
 
        struct config {
+               char            *keyring;
+               char            *keytype;
+               char            *hostnqn;
+               char            *subsysnqn;
                char            *secret;
                unsigned int    hmac;
+               bool            insert;
        };
 
        struct config cfg = {
+               .keyring        = ".nvme",
+               .keytype        = "psk",
+               .hostnqn        = NULL,
+               .subsysnqn      = NULL,
                .secret         = NULL,
                .hmac           = 1,
+               .insert         = false,
        };
 
        OPT_ARGS(opts) = {
+               OPT_STR("keyring",      'k', &cfg.keyring,      keyring),
+               OPT_STR("keytype",      't', &cfg.keytype,      keytype),
+               OPT_STR("hostnqn",      'n', &cfg.hostnqn,      hostnqn),
+               OPT_STR("subsysnqn",    'c', &cfg.subsysnqn,    subsysnqn),
                OPT_STR("secret",       's', &cfg.secret,       secret),
                OPT_UINT("hmac",        'm', &cfg.hmac,         hmac),
+               OPT_FLAG("insert",      'i', &cfg.insert,       insert),
                OPT_END()
        };
 
@@ -8857,7 +8878,10 @@ static int gen_tls_key(int argc, char **argv, struct command *command, struct pl
                fprintf(stderr, "Invalid HMAC identifier %u\n", cfg.hmac);
                return -EINVAL;
        }
-
+       if (cfg.insert && !cfg.subsysnqn) {
+               fprintf(stderr, "No subsystem NQN specified\n");
+               return -EINVAL;
+       }
        if (cfg.hmac == 2)
                key_len = 48;
 
@@ -8891,6 +8915,36 @@ static int gen_tls_key(int argc, char **argv, struct command *command, struct pl
                }
        }
 
+       if (cfg.hostnqn && !cfg.subsysnqn) {
+               fprintf(stderr,
+                       "Need to specify subsystem NQN to insert a TLS key\n");
+               return -EINVAL;
+       }
+       if (cfg.subsysnqn) {
+               if (!cfg.hostnqn) {
+                       cfg.hostnqn = nvmf_hostnqn_from_file();
+                       if (!cfg.hostnqn) {
+                               fprintf(stderr,
+                                       "Failed to read host NQN\n");
+                               return -EINVAL;
+                       }
+               }
+
+               tls_key = nvme_insert_tls_key(cfg.keyring, cfg.keytype,
+                                     cfg.hostnqn, cfg.subsysnqn, cfg.hmac,
+                                     raw_secret, key_len);
+               if (tls_key < 0) {
+                       fprintf(stderr,
+                               "Failed to insert key, error %d\n", errno);
+                       return -errno;
+               }
+
+               if (cfg.insert) {
+                       printf("Inserted TLS key %08x\n",
+                              (unsigned int)tls_key);
+                       return 0;
+               }
+       }
        crc = crc32(crc, raw_secret, key_len);
        raw_secret[key_len++] = crc & 0xff;
        raw_secret[key_len++] = (crc >> 8) & 0xff;