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:
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
"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()
};
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;
}
}
+ 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;