[--hostnqn=<nqn> | -n <nqn>]
[--subsysnqn=<nqn> | -c <nqn>]
[--keydata=<key> | -d <key>]
- [--output-format=<fmt> | -o <fmt>] [--verbose | -v]
+ [--output-format=<fmt> | -o <fmt>]
+ [--identity=<id-vers> | -I <id-vers>]
+ [--insert | -i ]
+ [--verbose | -v]
DESCRIPTION
-----------
Checks if the key is a valid NVMe TLS PSK in the PSK interchange format
-'NVMeTLSkey-1:01:<base64-encoded data>:', and stores the derived 'retained'
-TLS key in the keyring if the subsystem NQN is specified.
+'NVMeTLSkey-1:01:<base64-encoded data>:'. If '--insert' is specified the
+the derived 'retained' TLS key is stored in the keyring, otherwise the
+TLS identity of the key is printed out.
OPTIONS
-------
--keydata=<key>::
Key to be checked.
+-I <id-vers>::
+--identity=<id-vers>::
+ NVMe TLS key identity version to be used; '0' for the default
+ identity, and '1' for the TLS identity suffixed by the PSK hash
+ as specified in TP8018.
+
+-i:
+--insert:
+ Insert the derived 'retained' key in the keyring.
+
-o <fmt>::
--output-format=<fmt>::
Set the reporting format to 'normal', 'json' or 'binary'. Only one
{
const char *desc = "Check a TLS key for NVMe PSK Interchange format.\n";
const char *keydata = "TLS key (in PSK Interchange format) to be validated.";
+ const char *identity = "TLS identity version to use (0 = NVMe TCP 1.0c, 1 = NVMe TCP 2.0)";
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 retained key into the keyring.";
unsigned char decoded_key[128];
unsigned int decoded_len;
int err = 0, hmac;
long tls_key;
struct config {
- char *keyring;
- char *keytype;
- char *hostnqn;
- char *subsysnqn;
- char *keydata;
+ char *keyring;
+ char *keytype;
+ char *hostnqn;
+ char *subsysnqn;
+ char *keydata;
+ unsigned int identity;
+ bool insert;
};
struct config cfg = {
.hostnqn = NULL,
.subsysnqn = NULL,
.keydata = NULL,
+ .identity = 0,
+ .insert = false,
};
NVME_ARGS(opts, cfg,
OPT_STR("keytype", 't', &cfg.keytype, keytype),
OPT_STR("hostnqn", 'n', &cfg.hostnqn, hostnqn),
OPT_STR("subsysnqn", 'c', &cfg.subsysnqn, subsysnqn),
- OPT_STR("keydata", 'd', &cfg.keydata, keydata));
+ OPT_STR("keydata", 'd', &cfg.keydata, keydata),
+ OPT_UINT("identity", 'I', &cfg.identity, identity),
+ OPT_FLAG("insert", 'i', &cfg.insert, insert));
err = argconfig_parse(argc, argv, desc, opts);
if (err)
nvme_show_error("No key data");
return -EINVAL;
}
+ if (cfg.identity > 1) {
+ nvme_show_error("Invalid TLS identity version %u",
+ cfg.identity);
+ return -EINVAL;
+ }
if (sscanf(cfg.keydata, "NVMeTLSkey-1:%02x:*s", &hmac) != 1) {
nvme_show_error("Invalid key '%s'", cfg.keydata);
return -EINVAL;
}
+ if (cfg.subsysnqn) {
+ if (cfg.insert && !cfg.hostnqn) {
+ cfg.hostnqn = nvmf_hostnqn_from_file();
+ if (!cfg.hostnqn) {
+ nvme_show_error("Failed to read host NQN");
+ return -EINVAL;
+ }
+ }
+ } else if (cfg.insert || cfg.identity == 1) {
+ nvme_show_error("Need to specify a subsystem NQN");
+ return -EINVAL;
+ }
err = base64_decode(cfg.keydata + 16, strlen(cfg.keydata) - 17, decoded_key);
if (err < 0) {
nvme_show_error("Base64 decoding failed (%s, error %d)", cfg.keydata + 16, err);
nvme_show_error("CRC mismatch (key %08x, crc %08x)", key_crc, crc);
return -EINVAL;
}
- if (cfg.subsysnqn) {
- if (!cfg.hostnqn) {
- cfg.hostnqn = nvmf_hostnqn_from_file();
- if (!cfg.hostnqn) {
- nvme_show_error("Failed to read host NQN");
- return -EINVAL;
- }
- }
-
- tls_key = nvme_insert_tls_key(cfg.keyring, cfg.keytype, cfg.hostnqn, cfg.subsysnqn,
- hmac, decoded_key, decoded_len);
+ if (cfg.insert) {
+ tls_key = nvme_insert_tls_key_versioned(cfg.keyring,
+ cfg.keytype, cfg.hostnqn,
+ cfg.subsysnqn, cfg.identity,
+ hmac, decoded_key, decoded_len);
if (tls_key < 0) {
nvme_show_error("Failed to insert key, error %d", errno);
return -errno;
}
} else {
- printf("Key is valid (HMAC %d, length %d, CRC %08x)\n", hmac, decoded_len, crc);
+ char *tls_id;
+
+ tls_id = nvme_generate_tls_key_identity(cfg.hostnqn,
+ cfg.subsysnqn, cfg.identity,
+ hmac, decoded_key, decoded_len);
+ if (!tls_id) {
+ nvme_show_error("Failed to generated identity, error %d",
+ errno);
+ return -errno;
+ }
+ printf("%s\n", tls_id);
+ free(tls_id);
}
return 0;
}