Bug Summary

File:.build-ci/../plugins/keys/keys-plugin.c
Warning:line 271, column 10
Potential leak of memory pointed to by 'key'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name keys-plugin.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/bin/../lib/clang/22 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I nvme.p -I . -I .. -I src -I ../src -I ccan -I ../ccan -I libnvme/src -I ../libnvme/src -I shared -I ../shared -I /usr/include/json-c -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu99 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-08-08-045408-589-1 -x c ../plugins/keys/keys-plugin.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * This file is part of nvme-cli.
4 * Copyright (c) 2026 SUSE Software Solutions
5 *
6 * Authors: Daniel Wagner <dwagner@suse.de>
7 */
8
9#include <errno(*__errno_location ()).h>
10#include <stdio.h>
11#include <string.h>
12#include <sys/stat.h>
13
14#include <base64.h>
15#include <crc32.h>
16#include <libnvme.h>
17
18#include "fabrics.h"
19#include "logging.h"
20#include "nvme-print.h"
21#include "nvme.h"
22
23#define CREATE_CMD
24#include "keys-plugin.h"
25
26static int read_key_value(const char *inline_value, char **out)
27{
28 char line[512];
29
30 if (inline_value) {
4
Assuming 'inline_value' is non-null
5
Taking true branch
31 *out = strdup(inline_value);
6
Memory is allocated
32 return *out ? 0 : -ENOMEM12;
7
Assuming the condition is true
8
'?' condition is true
33 }
34
35 if (!fgets(line, sizeof(line), stdinstdin))
36 return -EINVAL22;
37 line[strcspn(line, "\n")] = '\0';
38
39 *out = strdup(line);
40 return *out ? 0 : -ENOMEM12;
41}
42
43static int gen_kxchap(int argc, char **argv, struct command *acmd, struct plugin *plugin)
44{
45 const char *desc =
46 "Generate a KX-HMAC-CHAP host key usable for NVMe In-Band Authentication.";
47 const char *secret =
48 "Optional secret (in hexadecimal characters) to be used to initialize the host key.";
49 const char *key_len = "Length of the resulting key (32, 48, or 64 bytes).";
50 const char *hmac =
51 "HMAC function to use for key transformation (0 = none, 1 = SHA-256, 2 = SHA-384, 3 = SHA-512).";
52 const char *nqn = "Host NQN to use for key transformation.";
53
54 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
55 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *raw_secret = NULL((void*)0);
56 __cleanup_free__attribute__((cleanup(shr_freep))) char *hnqn = NULL((void*)0);
57 unsigned char key[68];
58 char encoded_key[128];
59 unsigned long crc = shr_crc32(0L, NULL((void*)0), 0);
60 int err = 0;
61
62 struct config {
63 char *secret;
64 unsigned int key_len;
65 char *nqn;
66 unsigned int hmac;
67 };
68
69 struct config cfg = {
70 .secret = NULL((void*)0),
71 .key_len = 0,
72 .nqn = NULL((void*)0),
73 .hmac = 0,
74 };
75
76 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"secret", 's', "STRING", CFG_STRING, &cfg.secret,
1, secret, 0, }, {"key-length", 'l', "NUM", CFG_POSITIVE, &
cfg.key_len, 1, key_len, 0, }, {"nqn", 'n', "STRING", CFG_STRING
, &cfg.nqn, 1, nqn, 0, }, {"hmac", 'm', "NUM", CFG_POSITIVE
, &cfg.hmac, 1, hmac, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
77 OPT_STR("secret", 's', &cfg.secret, secret),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"secret", 's', "STRING", CFG_STRING, &cfg.secret,
1, secret, 0, }, {"key-length", 'l', "NUM", CFG_POSITIVE, &
cfg.key_len, 1, key_len, 0, }, {"nqn", 'n', "STRING", CFG_STRING
, &cfg.nqn, 1, nqn, 0, }, {"hmac", 'm', "NUM", CFG_POSITIVE
, &cfg.hmac, 1, hmac, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
78 OPT_UINT("key-length", 'l', &cfg.key_len, key_len),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"secret", 's', "STRING", CFG_STRING, &cfg.secret,
1, secret, 0, }, {"key-length", 'l', "NUM", CFG_POSITIVE, &
cfg.key_len, 1, key_len, 0, }, {"nqn", 'n', "STRING", CFG_STRING
, &cfg.nqn, 1, nqn, 0, }, {"hmac", 'm', "NUM", CFG_POSITIVE
, &cfg.hmac, 1, hmac, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
79 OPT_STR("nqn", 'n', &cfg.nqn, nqn),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"secret", 's', "STRING", CFG_STRING, &cfg.secret,
1, secret, 0, }, {"key-length", 'l', "NUM", CFG_POSITIVE, &
cfg.key_len, 1, key_len, 0, }, {"nqn", 'n', "STRING", CFG_STRING
, &cfg.nqn, 1, nqn, 0, }, {"hmac", 'm', "NUM", CFG_POSITIVE
, &cfg.hmac, 1, hmac, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
80 OPT_UINT("hmac", 'm', &cfg.hmac, hmac))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"secret", 's', "STRING", CFG_STRING, &cfg.secret,
1, secret, 0, }, {"key-length", 'l', "NUM", CFG_POSITIVE, &
cfg.key_len, 1, key_len, 0, }, {"nqn", 'n', "STRING", CFG_STRING
, &cfg.nqn, 1, nqn, 0, }, {"hmac", 'm', "NUM", CFG_POSITIVE
, &cfg.hmac, 1, hmac, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
81
82 err = parse_args(argc, argv, desc, opts);
83 if (err)
84 return err;
85
86 err = nvme_create_global_ctx(&ctx);
87 if (err)
88 return err;
89
90 if (cfg.hmac > 3) {
91 nvme_show_error("Invalid HMAC identifier %u", cfg.hmac)nvme_show_message(1, "Invalid HMAC identifier %u", cfg.hmac);
92 return -EINVAL22;
93 }
94 if (cfg.hmac > 0) {
95 switch (cfg.hmac) {
96 case 1:
97 if (!cfg.key_len) {
98 cfg.key_len = 32;
99 } else if (cfg.key_len != 32) {
100 nvme_show_error("Invalid key length %d for SHA(256)", cfg.key_len)nvme_show_message(1, "Invalid key length %d for SHA(256)", cfg
.key_len)
;
101 return -EINVAL22;
102 }
103 break;
104 case 2:
105 if (!cfg.key_len) {
106 cfg.key_len = 48;
107 } else if (cfg.key_len != 48) {
108 nvme_show_error("Invalid key length %d for SHA(384)", cfg.key_len)nvme_show_message(1, "Invalid key length %d for SHA(384)", cfg
.key_len)
;
109 return -EINVAL22;
110 }
111 break;
112 case 3:
113 if (!cfg.key_len) {
114 cfg.key_len = 64;
115 } else if (cfg.key_len != 64) {
116 nvme_show_error("Invalid key length %d for SHA(512)", cfg.key_len)nvme_show_message(1, "Invalid key length %d for SHA(512)", cfg
.key_len)
;
117 return -EINVAL22;
118 }
119 break;
120 default:
121 break;
122 }
123 } else if (!cfg.key_len) {
124 cfg.key_len = 32;
125 }
126
127 err = libnvmf_create_raw_secret(ctx, cfg.secret, cfg.key_len, &raw_secret);
128 if (err)
129 return err;
130
131 if (!cfg.nqn) {
132 err = libnvmf_host_get_ids(ctx, NULL((void*)0), NULL((void*)0), &hnqn, NULL((void*)0));
133 if (err)
134 return err;
135 cfg.nqn = hnqn;
136 }
137
138 err = libnvmf_gen_kxchap_key(ctx, cfg.nqn, cfg.hmac,
139 cfg.key_len, raw_secret, key);
140 if (err)
141 return err;
142
143 crc = shr_crc32(crc, key, cfg.key_len);
144 key[cfg.key_len++] = crc & 0xff;
145 key[cfg.key_len++] = (crc >> 8) & 0xff;
146 key[cfg.key_len++] = (crc >> 16) & 0xff;
147 key[cfg.key_len++] = (crc >> 24) & 0xff;
148
149 memset(encoded_key, 0, sizeof(encoded_key));
150 shr_base64_encode(key, cfg.key_len, encoded_key);
151
152 nvme_show_result("DHHC-1:%02x:%s:", cfg.hmac, encoded_key)nvme_show_message(0, "DHHC-1:%02x:%s:", cfg.hmac, encoded_key
)
;
153 return 0;
154}
155
156static int validate_kxchap_key(const char *key, int *hmac_out,
157 unsigned char *decoded_key, int *decoded_len_out, uint32_t *crc_out)
158{
159 uint32_t crc = shr_crc32(0L, NULL((void*)0), 0);
160 uint32_t key_crc;
161 size_t len = strlen(key);
162 int decoded_len, hmac, err;
163
164 if (sscanf(key, "DHHC-1:%02x:%*s", &hmac) != 1) {
165 nvme_show_error("Invalid key header '%s'", key)nvme_show_message(1, "Invalid key header '%s'", key);
166 return -EINVAL22;
167 }
168 if (hmac > 3) {
169 nvme_show_error("Invalid HMAC identifier %d", hmac)nvme_show_message(1, "Invalid HMAC identifier %d", hmac);
170 return -EINVAL22;
171 }
172
173 /*
174 * The hash identifier selects the function used to transform the
175 * secret into a key; it does not constrain the length of the secret
176 * itself, so apply the same length check whichever one is selected.
177 * A 32, 48 or 64 byte secret plus a 4 byte CRC encodes to 48, 72 or
178 * 92 base64 characters, giving a total of 59, 83 or 103.
179 *
180 * This does not pin the length of the secret - the same number of
181 * base64 characters can carry three different byte counts - so the
182 * decoded length is still checked below. What it does do is bound
183 * the decode before it runs.
184 */
185 if (len != 59 && len != 83 && len != 103) {
186 nvme_show_error("Invalid DHHC-1 string length %zu", len)nvme_show_message(1, "Invalid DHHC-1 string length %zu", len);
187 return -EINVAL22;
188 }
189
190 if (key[len - 1] != ':') {
191 nvme_show_error("Invalid key format (missing trailing ':')")nvme_show_message(1, "Invalid key format (missing trailing ':')"
)
;
192 return -EINVAL22;
193 }
194
195 err = shr_base64_decode(key + 10, len - 11, decoded_key);
196 if (err < 0) {
197 nvme_show_error("Base64 decoding failed, error %d", err)nvme_show_message(1, "Base64 decoding failed, error %d", err);
198 return err;
199 }
200 decoded_len = err;
201 decoded_len -= 4;
202 if (decoded_len != 32 && decoded_len != 48 && decoded_len != 64) {
203 nvme_show_error("Invalid secret length %d", decoded_len)nvme_show_message(1, "Invalid secret length %d", decoded_len);
204 return -EINVAL22;
205 }
206 crc = shr_crc32(crc, decoded_key, decoded_len);
207 key_crc = ((uint32_t)decoded_key[decoded_len]) |
208 ((uint32_t)decoded_key[decoded_len + 1] << 8) |
209 ((uint32_t)decoded_key[decoded_len + 2] << 16) |
210 ((uint32_t)decoded_key[decoded_len + 3] << 24);
211 if (key_crc != crc) {
212 nvme_show_error("CRC mismatch (key %08x, crc %08x)", key_crc, crc)nvme_show_message(1, "CRC mismatch (key %08x, crc %08x)", key_crc
, crc)
;
213 return -EINVAL22;
214 }
215
216 *hmac_out = hmac;
217 *decoded_len_out = decoded_len;
218 *crc_out = crc;
219 return 0;
220}
221
222static int check_kxchap(int argc, char **argv, struct command *acmd, struct plugin *plugin)
223{
224 const char *desc =
225 "Check a KX-HMAC-CHAP host key for usability for NVMe In-Band Authentication,\n"
226 "and, if --identity is given, check whether it is already loaded into a keyring.";
227 const char *keydata = "KX-HMAC-CHAP key (in DHHC-1 interchange format) to be validated. Reads from stdin if not given.";
228 const char *keyring = "Keyring to check for an already loaded key.";
229 const char *keytype = "Key type of the key to look up.";
230 const char *identity = "Identity to look up in the keyring to check if the key is already loaded.";
231
232 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
233 __cleanup_free__attribute__((cleanup(shr_freep))) char *key = NULL((void*)0);
234 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *stored = NULL((void*)0);
235 unsigned char decoded_key[128];
236 long keyring_id = 0, key_id = 0;
237 int decoded_len, hmac, err, stored_len;
238 uint32_t crc;
239 struct config {
240 char *keydata;
241 char *keyring;
242 char *keytype;
243 char *identity;
244 };
245
246 struct config cfg = {
247 .keydata = NULL((void*)0),
248 .keyring = ".nvme",
249 .keytype = "kxchap",
250 .identity = NULL((void*)0),
251 };
252
253 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keydata", 'd', "STRING", CFG_STRING, &cfg.keydata
, 1, keydata, 0, }, {"keyring", 'k', "STRING", CFG_STRING, &
cfg.keyring, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING
, &cfg.keytype, 1, keytype, 0, }, {"identity", 'i', "STRING"
, CFG_STRING, &cfg.identity, 1, identity, 0, }, {"", 0, (
(void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
254 OPT_STR("keydata", 'd', &cfg.keydata, keydata),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keydata", 'd', "STRING", CFG_STRING, &cfg.keydata
, 1, keydata, 0, }, {"keyring", 'k', "STRING", CFG_STRING, &
cfg.keyring, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING
, &cfg.keytype, 1, keytype, 0, }, {"identity", 'i', "STRING"
, CFG_STRING, &cfg.identity, 1, identity, 0, }, {"", 0, (
(void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
255 OPT_STR("keyring", 'k', &cfg.keyring, keyring),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keydata", 'd', "STRING", CFG_STRING, &cfg.keydata
, 1, keydata, 0, }, {"keyring", 'k', "STRING", CFG_STRING, &
cfg.keyring, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING
, &cfg.keytype, 1, keytype, 0, }, {"identity", 'i', "STRING"
, CFG_STRING, &cfg.identity, 1, identity, 0, }, {"", 0, (
(void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
256 OPT_STR("keytype", 't', &cfg.keytype, keytype),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keydata", 'd', "STRING", CFG_STRING, &cfg.keydata
, 1, keydata, 0, }, {"keyring", 'k', "STRING", CFG_STRING, &
cfg.keyring, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING
, &cfg.keytype, 1, keytype, 0, }, {"identity", 'i', "STRING"
, CFG_STRING, &cfg.identity, 1, identity, 0, }, {"", 0, (
(void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
257 OPT_STR("identity", 'i', &cfg.identity, identity))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keydata", 'd', "STRING", CFG_STRING, &cfg.keydata
, 1, keydata, 0, }, {"keyring", 'k', "STRING", CFG_STRING, &
cfg.keyring, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING
, &cfg.keytype, 1, keytype, 0, }, {"identity", 'i', "STRING"
, CFG_STRING, &cfg.identity, 1, identity, 0, }, {"", 0, (
(void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
258
259 err = parse_args(argc, argv, desc, opts);
260 if (err)
1
Assuming 'err' is 0
2
Taking false branch
261 return err;
262
263 err = read_key_value(cfg.keydata, &key);
3
Calling 'read_key_value'
9
Returned allocated memory via 2nd parameter
264 if (err
9.1
'err' is 0
) {
10
Taking false branch
265 nvme_show_error("No key data")nvme_show_message(1, "No key data");
266 return err;
267 }
268
269 err = validate_kxchap_key(key, &hmac, decoded_key, &decoded_len, &crc);
270 if (err
10.1
'err' is -22
)
11
Taking true branch
271 return err;
12
Potential leak of memory pointed to by 'key'
272
273 nvme_show_result("Key is valid (HMAC %d, length %d, CRC %08x)", hmac, decoded_len, crc)nvme_show_message(0, "Key is valid (HMAC %d, length %d, CRC %08x)"
, hmac, decoded_len, crc)
;
274
275 if (!cfg.identity)
276 return 0;
277
278 err = nvme_create_global_ctx(&ctx);
279 if (err) {
280 nvme_show_error("Failed to create global context")nvme_show_message(1, "Failed to create global context");
281 return err;
282 }
283 libnvme_set_logging_level(ctx, log_level, false0, false0);
284
285 err = libnvmf_lookup_keyring(ctx, cfg.keyring, &keyring_id);
286 if (err) {
287 nvme_show_error("Failed to lookup keyring '%s', %s",nvme_show_message(1, "Failed to lookup keyring '%s', %s", cfg
.keyring, libnvme_strerror(-err))
288 cfg.keyring, libnvme_strerror(-err))nvme_show_message(1, "Failed to lookup keyring '%s', %s", cfg
.keyring, libnvme_strerror(-err))
;
289 return err;
290 }
291
292 err = libnvmf_set_keyring(ctx, keyring_id);
293 if (err) {
294 nvme_show_error("Failed to link keyring '%s', %s",nvme_show_message(1, "Failed to link keyring '%s', %s", cfg.keyring
, libnvme_strerror(-err))
295 cfg.keyring, libnvme_strerror(-err))nvme_show_message(1, "Failed to link keyring '%s', %s", cfg.keyring
, libnvme_strerror(-err))
;
296 return err;
297 }
298
299 err = libnvmf_lookup_key(ctx, cfg.keytype, cfg.identity, &key_id);
300 if (err) {
301 nvme_show_result("Key is not loaded for identity '%s'", cfg.identity)nvme_show_message(0, "Key is not loaded for identity '%s'", cfg
.identity)
;
302 return 0;
303 }
304
305 err = libnvmf_read_key(ctx, keyring_id, key_id, &stored_len, &stored);
306 if (err) {
307 nvme_show_error("Failed to read back loaded key, %s",nvme_show_message(1, "Failed to read back loaded key, %s", libnvme_strerror
(-err))
308 libnvme_strerror(-err))nvme_show_message(1, "Failed to read back loaded key, %s", libnvme_strerror
(-err))
;
309 return err;
310 }
311
312 if ((size_t)stored_len == strlen(key) && !memcmp(stored, key, stored_len))
313 nvme_show_result("Key is loaded (serial %08x) and matches", (unsigned int)key_id)nvme_show_message(0, "Key is loaded (serial %08x) and matches"
, (unsigned int)key_id)
;
314 else
315 nvme_show_result("Key is loaded (serial %08x) but differs", (unsigned int)key_id)nvme_show_message(0, "Key is loaded (serial %08x) but differs"
, (unsigned int)key_id)
;
316
317 return 0;
318}
319
320static int append_keyfile(struct libnvme_global_ctx *ctx, const char *keyring,
321 long id, const char *keyfile)
322{
323 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *key_data = NULL((void*)0);
324 __cleanup_free__attribute__((cleanup(shr_freep))) char *exported_key = NULL((void*)0);
325 __cleanup_free__attribute__((cleanup(shr_freep))) char *identity = NULL((void*)0);
326 __cleanup_file__attribute__((cleanup(shr_cleanup_file))) FILE *fd = NULL((void*)0);
327 int err, ver, hmac, key_len;
328 mode_t old_umask;
329 long kr_id;
330 char type;
331
332 err = libnvmf_lookup_keyring(ctx, keyring, &kr_id);
333 if (err) {
334 nvme_show_error("Failed to lookup keyring '%s', %s",nvme_show_message(1, "Failed to lookup keyring '%s', %s", keyring
, libnvme_strerror(-err))
335 keyring, libnvme_strerror(-err))nvme_show_message(1, "Failed to lookup keyring '%s', %s", keyring
, libnvme_strerror(-err))
;
336 return err;
337 }
338
339 identity = libnvmf_describe_key_serial(ctx, id);
340 if (!identity) {
341 nvme_show_error("Failed to get identity info")nvme_show_message(1, "Failed to get identity info");
342 return -EINVAL22;
343 }
344
345 if (sscanf(identity, "NVMe%01d%c%02d %*s", &ver, &type, &hmac) != 3) {
346 nvme_show_error("Failed to parse identity\n")nvme_show_message(1, "Failed to parse identity\n");
347 return -EINVAL22;
348 }
349
350 err = libnvmf_read_key(ctx, kr_id, id, &key_len, &key_data);
351 if (err) {
352 nvme_show_error("Failed to read back derive TLS PSK, %s",nvme_show_message(1, "Failed to read back derive TLS PSK, %s"
, libnvme_strerror(-err))
353 libnvme_strerror(-err))nvme_show_message(1, "Failed to read back derive TLS PSK, %s"
, libnvme_strerror(-err))
;
354 return err;
355 }
356
357 err = libnvmf_export_tls_key_versioned(ctx, ver, hmac, key_data,
358 key_len, &exported_key);
359 if (err) {
360 nvme_show_error("Failed to export key, %s",nvme_show_message(1, "Failed to export key, %s", libnvme_strerror
(-err))
361 libnvme_strerror(-err))nvme_show_message(1, "Failed to export key, %s", libnvme_strerror
(-err))
;
362 return err;
363 }
364
365 old_umask = umask(0);
366
367 fd = fopen(keyfile, "a");
368 if (!fd) {
369 nvme_show_error("Failed to open '%s', %s",nvme_show_message(1, "Failed to open '%s', %s", keyfile, libnvme_strerror
((*__errno_location ())))
370 keyfile, libnvme_strerror(errno))nvme_show_message(1, "Failed to open '%s', %s", keyfile, libnvme_strerror
((*__errno_location ())))
;
371 err = -errno(*__errno_location ());
372 goto out;
373 }
374
375 err = fprintf(fd, "%s %s\n", identity, exported_key);
376 if (err < 0) {
377 nvme_show_error("Failed to append key to '%s', %s",nvme_show_message(1, "Failed to append key to '%s', %s", keyfile
, libnvme_strerror((*__errno_location ())))
378 keyfile, libnvme_strerror(errno))nvme_show_message(1, "Failed to append key to '%s', %s", keyfile
, libnvme_strerror((*__errno_location ())))
;
379 err = -errno(*__errno_location ());
380 } else {
381 err = 0;
382 }
383
384out:
385 chmod(keyfile, 0600);
386 umask(old_umask);
387
388 return err;
389}
390
391static int do_insert_tls_key(struct libnvme_global_ctx *ctx, const char *keyring,
392 const char *keytype, const char *hostnqn, const char *subsysnqn,
393 int identity, int hmac, unsigned char *key_data, int key_len,
394 bool_Bool compat, const char *keyfile, long *tls_key)
395{
396 int err;
397
398 if (compat)
399 err = libnvmf_insert_tls_key_compat(ctx, keyring, keytype, hostnqn,
400 subsysnqn, identity, hmac, key_data, key_len, tls_key);
401 else
402 err = libnvmf_insert_tls_key_versioned(ctx, keyring, keytype, hostnqn,
403 subsysnqn, identity, hmac, key_data, key_len, tls_key);
404 if (err) {
405 nvme_show_error("Failed to insert key, %s", libnvme_strerror(-err))nvme_show_message(1, "Failed to insert key, %s", libnvme_strerror
(-err))
;
406 return err;
407 }
408 nvme_show_result("Inserted TLS key %08x", (unsigned int)*tls_key)nvme_show_message(0, "Inserted TLS key %08x", (unsigned int)*
tls_key)
;
409
410 if (keyfile) {
411 err = append_keyfile(ctx, keyring, *tls_key, keyfile);
412 if (err)
413 return err;
414 }
415
416 return 0;
417}
418
419static int gen_tls(int argc, char **argv, struct command *acmd, struct plugin *plugin)
420{
421 const char *desc = "Generate a TLS key in NVMe PSK Interchange format.";
422 const char *secret =
423 "Optional secret (in hexadecimal characters) to be used for the TLS key.";
424 const char *hmac = "HMAC function to use for the retained key (1 = SHA-256, 2 = SHA-384).";
425 const char *version = "TLS identity version to use (0 = NVMe TCP 1.0c, 1 = NVMe TCP 2.0)";
426 const char *hostnqn = "Host NQN for the retained key.";
427 const char *subsysnqn = "Subsystem NQN for the retained key.";
428 const char *keyring = "Keyring for the retained key.";
429 const char *keytype = "Key type of the retained key.";
430 const char *insert = "Insert retained key into the keyring.";
431 const char *keyfile = "Update key file with the derived TLS PSK.";
432 const char *compat = "Use non-RFC 8446 compliant algorithm for deriving TLS PSK for older implementations.";
433
434 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
435 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *raw_secret = NULL((void*)0);
436 __cleanup_free__attribute__((cleanup(shr_freep))) char *encoded_key = NULL((void*)0);
437 __cleanup_free__attribute__((cleanup(shr_freep))) char *hnqn = NULL((void*)0);
438 int key_len = 32;
439 int err;
440 long tls_key;
441
442 struct config {
443 char *keyring;
444 char *keytype;
445 char *hostnqn;
446 char *subsysnqn;
447 char *secret;
448 char *keyfile;
449 unsigned char hmac;
450 unsigned char version;
451 bool_Bool insert;
452 bool_Bool compat;
453 };
454
455 struct config cfg = {
456 .keyring = ".nvme",
457 .keytype = "psk",
458 .hostnqn = NULL((void*)0),
459 .subsysnqn = NULL((void*)0),
460 .secret = NULL((void*)0),
461 .keyfile = NULL((void*)0),
462 .hmac = 1,
463 .version = 0,
464 .insert = false0,
465 .compat = false0,
466 };
467
468 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"secret"
, 's', "STRING", CFG_STRING, &cfg.secret, 1, secret, 0, }
, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1,
keyfile, 0, }, {"hmac", 'm', "NUM", CFG_BYTE, &cfg.hmac,
1, hmac, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.version
, 1, version, 0, }, {"insert", 'i', ((void*)0), CFG_FLAG, &
cfg.insert, 0, insert, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
469 OPT_STR("keyring", 'k', &cfg.keyring, keyring),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"secret"
, 's', "STRING", CFG_STRING, &cfg.secret, 1, secret, 0, }
, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1,
keyfile, 0, }, {"hmac", 'm', "NUM", CFG_BYTE, &cfg.hmac,
1, hmac, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.version
, 1, version, 0, }, {"insert", 'i', ((void*)0), CFG_FLAG, &
cfg.insert, 0, insert, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
470 OPT_STR("keytype", 't', &cfg.keytype, keytype),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"secret"
, 's', "STRING", CFG_STRING, &cfg.secret, 1, secret, 0, }
, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1,
keyfile, 0, }, {"hmac", 'm', "NUM", CFG_BYTE, &cfg.hmac,
1, hmac, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.version
, 1, version, 0, }, {"insert", 'i', ((void*)0), CFG_FLAG, &
cfg.insert, 0, insert, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
471 OPT_STR("hostnqn", 'n', &cfg.hostnqn, hostnqn),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"secret"
, 's', "STRING", CFG_STRING, &cfg.secret, 1, secret, 0, }
, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1,
keyfile, 0, }, {"hmac", 'm', "NUM", CFG_BYTE, &cfg.hmac,
1, hmac, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.version
, 1, version, 0, }, {"insert", 'i', ((void*)0), CFG_FLAG, &
cfg.insert, 0, insert, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
472 OPT_STR("subsysnqn", 'c', &cfg.subsysnqn, subsysnqn),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"secret"
, 's', "STRING", CFG_STRING, &cfg.secret, 1, secret, 0, }
, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1,
keyfile, 0, }, {"hmac", 'm', "NUM", CFG_BYTE, &cfg.hmac,
1, hmac, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.version
, 1, version, 0, }, {"insert", 'i', ((void*)0), CFG_FLAG, &
cfg.insert, 0, insert, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
473 OPT_STR("secret", 's', &cfg.secret, secret),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"secret"
, 's', "STRING", CFG_STRING, &cfg.secret, 1, secret, 0, }
, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1,
keyfile, 0, }, {"hmac", 'm', "NUM", CFG_BYTE, &cfg.hmac,
1, hmac, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.version
, 1, version, 0, }, {"insert", 'i', ((void*)0), CFG_FLAG, &
cfg.insert, 0, insert, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
474 OPT_STR("keyfile", 'f', &cfg.keyfile, keyfile),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"secret"
, 's', "STRING", CFG_STRING, &cfg.secret, 1, secret, 0, }
, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1,
keyfile, 0, }, {"hmac", 'm', "NUM", CFG_BYTE, &cfg.hmac,
1, hmac, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.version
, 1, version, 0, }, {"insert", 'i', ((void*)0), CFG_FLAG, &
cfg.insert, 0, insert, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
475 OPT_BYTE("hmac", 'm', &cfg.hmac, hmac),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"secret"
, 's', "STRING", CFG_STRING, &cfg.secret, 1, secret, 0, }
, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1,
keyfile, 0, }, {"hmac", 'm', "NUM", CFG_BYTE, &cfg.hmac,
1, hmac, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.version
, 1, version, 0, }, {"insert", 'i', ((void*)0), CFG_FLAG, &
cfg.insert, 0, insert, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
476 OPT_BYTE("identity", 'I', &cfg.version, version),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"secret"
, 's', "STRING", CFG_STRING, &cfg.secret, 1, secret, 0, }
, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1,
keyfile, 0, }, {"hmac", 'm', "NUM", CFG_BYTE, &cfg.hmac,
1, hmac, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.version
, 1, version, 0, }, {"insert", 'i', ((void*)0), CFG_FLAG, &
cfg.insert, 0, insert, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
477 OPT_FLAG("insert", 'i', &cfg.insert, insert),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"secret"
, 's', "STRING", CFG_STRING, &cfg.secret, 1, secret, 0, }
, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1,
keyfile, 0, }, {"hmac", 'm', "NUM", CFG_BYTE, &cfg.hmac,
1, hmac, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.version
, 1, version, 0, }, {"insert", 'i', ((void*)0), CFG_FLAG, &
cfg.insert, 0, insert, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
478 OPT_FLAG("compat", 'C', &cfg.compat, compat))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"secret"
, 's', "STRING", CFG_STRING, &cfg.secret, 1, secret, 0, }
, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1,
keyfile, 0, }, {"hmac", 'm', "NUM", CFG_BYTE, &cfg.hmac,
1, hmac, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.version
, 1, version, 0, }, {"insert", 'i', ((void*)0), CFG_FLAG, &
cfg.insert, 0, insert, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
479
480 err = parse_args(argc, argv, desc, opts);
481 if (err)
482 return err;
483 if (cfg.hmac < 1 || cfg.hmac > 2) {
484 nvme_show_error("Invalid HMAC identifier %u", cfg.hmac)nvme_show_message(1, "Invalid HMAC identifier %u", cfg.hmac);
485 return -EINVAL22;
486 }
487 if (cfg.version > 1) {
488 nvme_show_error("Invalid TLS identity version %u",nvme_show_message(1, "Invalid TLS identity version %u", cfg.version
)
489 cfg.version)nvme_show_message(1, "Invalid TLS identity version %u", cfg.version
)
;
490 return -EINVAL22;
491 }
492 if (cfg.insert) {
493 if (!cfg.subsysnqn) {
494 nvme_show_error("No subsystem NQN specified")nvme_show_message(1, "No subsystem NQN specified");
495 return -EINVAL22;
496 }
497 }
498 if (cfg.hmac == 2)
499 key_len = 48;
500
501 err = nvme_create_global_ctx(&ctx);
502 if (err)
503 return err;
504
505 err = libnvmf_create_raw_secret(ctx, cfg.secret, key_len, &raw_secret);
506 if (err)
507 return err;
508
509 err = libnvmf_export_tls_key(ctx, raw_secret, key_len, &encoded_key);
510 if (err) {
511 nvme_show_error("Failed to export key, %s", libnvme_strerror(-err))nvme_show_message(1, "Failed to export key, %s", libnvme_strerror
(-err))
;
512 return err;
513 }
514 nvme_show_result("%s", encoded_key)nvme_show_message(0, "%s", encoded_key);
515
516 if (cfg.insert) {
517 if (!cfg.hostnqn) {
518 err = libnvmf_host_get_ids(ctx, NULL((void*)0), NULL((void*)0), &hnqn, NULL((void*)0));
519 if (err)
520 return err;
521 cfg.hostnqn = hnqn;
522 }
523
524 err = do_insert_tls_key(ctx, cfg.keyring, cfg.keytype,
525 cfg.hostnqn, cfg.subsysnqn, cfg.version,
526 cfg.hmac, raw_secret, key_len, cfg.compat,
527 cfg.keyfile, &tls_key);
528 if (err)
529 return err;
530 }
531
532 return 0;
533}
534
535static int check_tls(int argc, char **argv, struct command *acmd, struct plugin *plugin)
536{
537 const char *desc =
538 "Check a TLS key for NVMe PSK Interchange format, and, if a subsystem\n"
539 "NQN is given, check whether the corresponding retained key is already\n"
540 "loaded into a keyring.";
541 const char *keydata = "TLS key (in PSK Interchange format) to be validated. Reads from stdin if not given.";
542 const char *identity = "TLS identity version to use (0 = NVMe TCP 1.0c, 1 = NVMe TCP 2.0)";
543 const char *hostnqn = "Host NQN to use when checking whether the key is already loaded.";
544 const char *subsysnqn = "Subsystem NQN to use when checking whether the key is already loaded.";
545 const char *keyring = "Keyring to check for an already loaded key.";
546 const char *keytype = "Key type of the key to look up.";
547 const char *compat = "Use non-RFC 8446 compliant algorithm for checking TLS PSK for older implementations.";
548
549 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
550 __cleanup_free__attribute__((cleanup(shr_freep))) char *key_value = NULL((void*)0);
551 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *decoded_key = NULL((void*)0);
552 __cleanup_free__attribute__((cleanup(shr_freep))) char *hnqn = NULL((void*)0);
553 __cleanup_free__attribute__((cleanup(shr_freep))) char *tls_id = NULL((void*)0);
554 int decoded_len, err = 0;
555 unsigned int hmac;
556 long keyring_id, key_id;
557 struct config {
558 char *keyring;
559 char *keytype;
560 char *hostnqn;
561 char *subsysnqn;
562 char *keydata;
563 unsigned char identity;
564 bool_Bool compat;
565 };
566
567 struct config cfg = {
568 .keyring = ".nvme",
569 .keytype = "psk",
570 .hostnqn = NULL((void*)0),
571 .subsysnqn = NULL((void*)0),
572 .keydata = NULL((void*)0),
573 .identity = 0,
574 .compat = false0,
575 };
576
577 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"identity", 'I', "NUM", CFG_BYTE, &cfg.identity, 1, identity
, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG, &cfg.compat
, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, (
(void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
578 OPT_STR("keyring", 'k', &cfg.keyring, keyring),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"identity", 'I', "NUM", CFG_BYTE, &cfg.identity, 1, identity
, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG, &cfg.compat
, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, (
(void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
579 OPT_STR("keytype", 't', &cfg.keytype, keytype),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"identity", 'I', "NUM", CFG_BYTE, &cfg.identity, 1, identity
, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG, &cfg.compat
, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, (
(void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
580 OPT_STR("hostnqn", 'n', &cfg.hostnqn, hostnqn),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"identity", 'I', "NUM", CFG_BYTE, &cfg.identity, 1, identity
, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG, &cfg.compat
, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, (
(void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
581 OPT_STR("subsysnqn", 'c', &cfg.subsysnqn, subsysnqn),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"identity", 'I', "NUM", CFG_BYTE, &cfg.identity, 1, identity
, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG, &cfg.compat
, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, (
(void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
582 OPT_STR("keydata", 'd', &cfg.keydata, keydata),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"identity", 'I', "NUM", CFG_BYTE, &cfg.identity, 1, identity
, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG, &cfg.compat
, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, (
(void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
583 OPT_BYTE("identity", 'I', &cfg.identity, identity),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"identity", 'I', "NUM", CFG_BYTE, &cfg.identity, 1, identity
, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG, &cfg.compat
, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, (
(void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
584 OPT_FLAG("compat", 'C', &cfg.compat, compat))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"identity", 'I', "NUM", CFG_BYTE, &cfg.identity, 1, identity
, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG, &cfg.compat
, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, (
(void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v'
, "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
585
586 err = parse_args(argc, argv, desc, opts);
587 if (err)
588 return err;
589
590 if (cfg.identity > 1) {
591 nvme_show_error("Invalid TLS identity version %u",nvme_show_message(1, "Invalid TLS identity version %u", cfg.identity
)
592 cfg.identity)nvme_show_message(1, "Invalid TLS identity version %u", cfg.identity
)
;
593 return -EINVAL22;
594 }
595
596 err = read_key_value(cfg.keydata, &key_value);
597 if (err) {
598 nvme_show_error("No key data")nvme_show_message(1, "No key data");
599 return err;
600 }
601
602 err = nvme_create_global_ctx(&ctx);
603 if (err) {
604 nvme_show_error("Failed to create global context")nvme_show_message(1, "Failed to create global context");
605 return err;
606 }
607 libnvme_set_logging_level(ctx, log_level, false0, false0);
608
609 err = libnvmf_import_tls_key(ctx, key_value, &decoded_len,
610 &hmac, &decoded_key);
611 if (err) {
612 nvme_show_error("Key decoding failed, %s", libnvme_strerror(-err))nvme_show_message(1, "Key decoding failed, %s", libnvme_strerror
(-err))
;
613 return err;
614 }
615 nvme_show_result("Key is valid (HMAC %u, length %d)", hmac, decoded_len)nvme_show_message(0, "Key is valid (HMAC %u, length %d)", hmac
, decoded_len)
;
616
617 if (!cfg.subsysnqn)
618 return 0;
619
620 if (!cfg.hostnqn) {
621 err = libnvmf_host_get_ids(ctx, NULL((void*)0), NULL((void*)0), &hnqn, NULL((void*)0));
622 if (err)
623 return err;
624 cfg.hostnqn = hnqn;
625 }
626
627 if (cfg.compat)
628 err = libnvmf_generate_tls_key_identity_compat(ctx,
629 cfg.hostnqn, cfg.subsysnqn, cfg.identity,
630 hmac, decoded_key, decoded_len, &tls_id);
631 else
632 err = libnvmf_generate_tls_key_identity(ctx,
633 cfg.hostnqn, cfg.subsysnqn, cfg.identity,
634 hmac, decoded_key, decoded_len, &tls_id);
635 if (err) {
636 nvme_show_error("Failed to generate identity, %s",nvme_show_message(1, "Failed to generate identity, %s", libnvme_strerror
(-err))
637 libnvme_strerror(-err))nvme_show_message(1, "Failed to generate identity, %s", libnvme_strerror
(-err))
;
638 return err;
639 }
640 nvme_show_result("%s", tls_id)nvme_show_message(0, "%s", tls_id);
641
642 err = libnvmf_lookup_keyring(ctx, cfg.keyring, &keyring_id);
643 if (err) {
644 nvme_show_error("Failed to lookup keyring '%s', %s",nvme_show_message(1, "Failed to lookup keyring '%s', %s", cfg
.keyring, libnvme_strerror(-err))
645 cfg.keyring, libnvme_strerror(-err))nvme_show_message(1, "Failed to lookup keyring '%s', %s", cfg
.keyring, libnvme_strerror(-err))
;
646 return err;
647 }
648
649 err = libnvmf_set_keyring(ctx, keyring_id);
650 if (err) {
651 nvme_show_error("Failed to link keyring '%s', %s",nvme_show_message(1, "Failed to link keyring '%s', %s", cfg.keyring
, libnvme_strerror(-err))
652 cfg.keyring, libnvme_strerror(-err))nvme_show_message(1, "Failed to link keyring '%s', %s", cfg.keyring
, libnvme_strerror(-err))
;
653 return err;
654 }
655
656 err = libnvmf_lookup_key(ctx, cfg.keytype, tls_id, &key_id);
657 if (err) {
658 nvme_show_result("Key is not loaded")nvme_show_message(0, "Key is not loaded");
659 return 0;
660 }
661
662 nvme_show_result("Key is loaded (serial %08x)", (unsigned int)key_id)nvme_show_message(0, "Key is loaded (serial %08x)", (unsigned
int)key_id)
;
663 return 0;
664}
665
666static int insert_tls(int argc, char **argv, struct command *acmd, struct plugin *plugin)
667{
668 const char *desc = "Insert a TLS key (in NVMe PSK Interchange format) into a keyring.\n";
669 const char *keydata = "TLS key (in PSK Interchange format) to be inserted. Reads from stdin if not given.";
670 const char *identity = "TLS identity version to use (0 = NVMe TCP 1.0c, 1 = NVMe TCP 2.0)";
671 const char *hostnqn = "Host NQN for the retained key.";
672 const char *subsysnqn = "Subsystem NQN for the retained key.";
673 const char *keyring = "Keyring for the retained key.";
674 const char *keytype = "Key type of the retained key.";
675 const char *keyfile = "Append the derived TLS PSK to keyfile.";
676 const char *compat = "Use non-RFC 8446 compliant algorithm for older implementations.";
677
678 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
679 __cleanup_free__attribute__((cleanup(shr_freep))) char *key_value = NULL((void*)0);
680 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *decoded_key = NULL((void*)0);
681 __cleanup_free__attribute__((cleanup(shr_freep))) char *hnqn = NULL((void*)0);
682 int decoded_len, err = 0;
683 unsigned int hmac;
684 long tls_key;
685 struct config {
686 char *keyring;
687 char *keytype;
688 char *hostnqn;
689 char *subsysnqn;
690 char *keydata;
691 char *keyfile;
692 unsigned char identity;
693 bool_Bool compat;
694 };
695
696 struct config cfg = {
697 .keyring = ".nvme",
698 .keytype = "psk",
699 .hostnqn = NULL((void*)0),
700 .subsysnqn = NULL((void*)0),
701 .keydata = NULL((void*)0),
702 .keyfile = NULL((void*)0),
703 .identity = 0,
704 .compat = false0,
705 };
706
707 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1
, keyfile, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.
identity, 1, identity, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
708 OPT_STR("keyring", 'k', &cfg.keyring, keyring),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1
, keyfile, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.
identity, 1, identity, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
709 OPT_STR("keytype", 't', &cfg.keytype, keytype),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1
, keyfile, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.
identity, 1, identity, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
710 OPT_STR("hostnqn", 'n', &cfg.hostnqn, hostnqn),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1
, keyfile, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.
identity, 1, identity, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
711 OPT_STR("subsysnqn", 'c', &cfg.subsysnqn, subsysnqn),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1
, keyfile, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.
identity, 1, identity, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
712 OPT_STR("keydata", 'd', &cfg.keydata, keydata),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1
, keyfile, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.
identity, 1, identity, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
713 OPT_STR("keyfile", 'f', &cfg.keyfile, keyfile),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1
, keyfile, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.
identity, 1, identity, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
714 OPT_BYTE("identity", 'I', &cfg.identity, identity),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1
, keyfile, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.
identity, 1, identity, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
715 OPT_FLAG("compat", 'C', &cfg.compat, compat))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"hostnqn", 'n', "STRING", CFG_STRING
, &cfg.hostnqn, 1, hostnqn, 0, }, {"subsysnqn", 'c', "STRING"
, CFG_STRING, &cfg.subsysnqn, 1, subsysnqn, 0, }, {"keydata"
, 'd', "STRING", CFG_STRING, &cfg.keydata, 1, keydata, 0,
}, {"keyfile", 'f', "STRING", CFG_STRING, &cfg.keyfile, 1
, keyfile, 0, }, {"identity", 'I', "NUM", CFG_BYTE, &cfg.
identity, 1, identity, 0, }, {"compat", 'C', ((void*)0), CFG_FLAG
, &cfg.compat, 0, compat, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
716
717 err = parse_args(argc, argv, desc, opts);
718 if (err)
719 return err;
720
721 if (!cfg.subsysnqn) {
722 nvme_show_error("Need to specify a subsystem NQN")nvme_show_message(1, "Need to specify a subsystem NQN");
723 return -EINVAL22;
724 }
725 if (cfg.identity > 1) {
726 nvme_show_error("Invalid TLS identity version %u",nvme_show_message(1, "Invalid TLS identity version %u", cfg.identity
)
727 cfg.identity)nvme_show_message(1, "Invalid TLS identity version %u", cfg.identity
)
;
728 return -EINVAL22;
729 }
730
731 err = read_key_value(cfg.keydata, &key_value);
732 if (err) {
733 nvme_show_error("No key data")nvme_show_message(1, "No key data");
734 return err;
735 }
736
737 err = nvme_create_global_ctx(&ctx);
738 if (err) {
739 nvme_show_error("Failed to create global context")nvme_show_message(1, "Failed to create global context");
740 return err;
741 }
742 libnvme_set_logging_level(ctx, log_level, false0, false0);
743
744 err = libnvmf_import_tls_key(ctx, key_value, &decoded_len,
745 &hmac, &decoded_key);
746 if (err) {
747 nvme_show_error("Key decoding failed, %s", libnvme_strerror(-err))nvme_show_message(1, "Key decoding failed, %s", libnvme_strerror
(-err))
;
748 return err;
749 }
750
751 if (!cfg.hostnqn) {
752 err = libnvmf_host_get_ids(ctx, NULL((void*)0), NULL((void*)0), &hnqn, NULL((void*)0));
753 if (err)
754 return err;
755 cfg.hostnqn = hnqn;
756 }
757
758 return do_insert_tls_key(ctx, cfg.keyring, cfg.keytype, cfg.hostnqn,
759 cfg.subsysnqn, cfg.identity, hmac, decoded_key, decoded_len,
760 cfg.compat, cfg.keyfile, &tls_key);
761}
762
763static void __scan_tls_key(struct libnvme_global_ctx *ctx, long keyring_id,
764 long key_id, char *desc, int desc_len, void *data)
765{
766 FILE *fd = data;
767 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *key_data = NULL((void*)0);
768 __cleanup_free__attribute__((cleanup(shr_freep))) char *encoded_key = NULL((void*)0);
769 int key_len;
770 int ver, hmac;
771 char type;
772 int err;
773
774 err = libnvmf_read_key(ctx, keyring_id, key_id, &key_len, &key_data);
775 if (err)
776 return;
777
778 if (sscanf(desc, "NVMe%01d%c%02d %*s", &ver, &type, &hmac) != 3)
779 return;
780
781 err = libnvmf_export_tls_key_versioned(ctx, ver, hmac, key_data, key_len,
782 &encoded_key);
783 if (err)
784 return;
785 fprintf(fd, "%s %s\n", desc, encoded_key);
786}
787
788static int key_export(int argc, char **argv, struct command *acmd, struct plugin *plugin)
789{
790 const char *desc = "Export NVMeoF TLS PSKs from a keyring.\n";
791 const char *keyring = "Keyring to export the retained keys from.";
792 const char *keyfile = "File to write the exported keys to (default: stdout).";
793
794 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
795 __cleanup_file__attribute__((cleanup(shr_cleanup_file))) FILE *fd = NULL((void*)0);
796 mode_t old_umask = 0;
797 int err = 0;
798
799 struct config {
800 char *keyring;
801 char *keyfile;
802 };
803
804 struct config cfg = {
805 .keyring = ".nvme",
806 .keyfile = NULL((void*)0),
807 };
808
809 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keyfile", 'f', "STRING", CFG_STRING, &
cfg.keyfile, 1, keyfile, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
810 OPT_STR("keyring", 'k', &cfg.keyring, keyring),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keyfile", 'f', "STRING", CFG_STRING, &
cfg.keyfile, 1, keyfile, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
811 OPT_STR("keyfile", 'f', &cfg.keyfile, keyfile))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keyfile", 'f', "STRING", CFG_STRING, &
cfg.keyfile, 1, keyfile, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
812
813 err = parse_args(argc, argv, desc, opts);
814 if (err)
815 return err;
816
817 err = nvme_create_global_ctx(&ctx);
818 if (err) {
819 nvme_show_error("Failed to create global context")nvme_show_message(1, "Failed to create global context");
820 return err;
821 }
822 libnvme_set_logging_level(ctx, log_level, false0, false0);
823
824 if (cfg.keyfile) {
825 old_umask = umask(0);
826
827 fd = fopen(cfg.keyfile, "w");
828 if (!fd) {
829 nvme_show_error("Cannot open keyfile %s, error %d",nvme_show_message(1, "Cannot open keyfile %s, error %d", cfg.
keyfile, (*__errno_location ()))
830 cfg.keyfile, errno)nvme_show_message(1, "Cannot open keyfile %s, error %d", cfg.
keyfile, (*__errno_location ()))
;
831 umask(old_umask);
832 return -errno(*__errno_location ());
833 }
834 } else {
835 fd = freopen(NULL((void*)0), "w", stdoutstdout);
836 }
837
838 err = libnvmf_scan_tls_keys(ctx, cfg.keyring, __scan_tls_key, fd);
839 if (err < 0) {
840 nvme_show_error("Export of TLS keys failed with '%s'",nvme_show_message(1, "Export of TLS keys failed with '%s'", libnvme_strerror
(-err))
841 libnvme_strerror(-err))nvme_show_message(1, "Export of TLS keys failed with '%s'", libnvme_strerror
(-err))
;
842 return err;
843 }
844
845 nvme_show_verbose_info("exporting to %s", cfg.keyfile)nvme_show_verbose_message("exporting to %s", cfg.keyfile);
846
847 if (cfg.keyfile) {
848 umask(old_umask);
849 chmod(cfg.keyfile, 0600);
850 }
851
852 return 0;
853}
854
855static bool_Bool is_kxchap_key(const char *key)
856{
857 return !strncmp(key, "DHHC-1:", 7);
858}
859
860static int import_one_key(struct libnvme_global_ctx *ctx, long keyring_id,
861 const char *identity, const char *key_str)
862{
863 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *psk = NULL((void*)0);
864 unsigned char decoded_key[128];
865 long key_serial;
866 int decoded_len, kxchap_hmac, err;
867 unsigned int tls_hmac;
868 uint32_t crc;
869
870 if (is_kxchap_key(key_str)) {
871 err = validate_kxchap_key(key_str, &kxchap_hmac, decoded_key,
872 &decoded_len, &crc);
873 if (err)
874 return err;
875
876 return libnvmf_update_key(ctx, keyring_id, "kxchap", identity,
877 (unsigned char *)key_str, strlen(key_str),
878 &key_serial);
879 }
880
881 err = libnvmf_import_tls_key(ctx, key_str, &decoded_len, &tls_hmac, &psk);
882 if (err)
883 return err;
884
885 return libnvmf_update_key(ctx, keyring_id, "psk", identity, psk,
886 decoded_len, &key_serial);
887}
888
889static int import_key(struct libnvme_global_ctx *ctx, const char *keyring,
890 FILE *fd)
891{
892 long keyring_id;
893 char line[512];
894 char *key_str;
895 int linenum = 0;
896 int err;
897
898 err = libnvmf_lookup_keyring(ctx, keyring, &keyring_id);
899 if (err) {
900 nvme_show_error("Invalid keyring '%s'", keyring)nvme_show_message(1, "Invalid keyring '%s'", keyring);
901 return err;
902 }
903
904 while (fgets(line, sizeof(line), fd)) {
905 linenum++;
906 key_str = strrchr(line, ' ')_Generic (0 ? (line) : (void *) 1, const void *: (const char *
) (strrchr (line, ' ')), default: strrchr (line, ' '))
;
907 if (!key_str) {
908 nvme_show_error("Parse error in line %d",nvme_show_message(1, "Parse error in line %d", linenum)
909 linenum)nvme_show_message(1, "Parse error in line %d", linenum);
910 continue;
911 }
912 *key_str = '\0';
913 key_str++;
914 key_str[strcspn(key_str, "\n")] = 0;
915
916 err = import_one_key(ctx, keyring_id, line, key_str);
917 if (err)
918 nvme_show_error("Failed to import key in line %d, %s",nvme_show_message(1, "Failed to import key in line %d, %s", linenum
, libnvme_strerror(-err))
919 linenum, libnvme_strerror(-err))nvme_show_message(1, "Failed to import key in line %d, %s", linenum
, libnvme_strerror(-err))
;
920 }
921
922 return 0;
923}
924
925static int key_import(int argc, char **argv, struct command *acmd, struct plugin *plugin)
926{
927 const char *desc = "Import NVMeoF TLS PSKs and KX-HMAC-CHAP keys into a keyring.\n";
928 const char *keyring = "Keyring to import the keys into.";
929 const char *keyfile = "File to read the keys from (default: stdin).";
930 const char *keydata = "Key to insert directly under --identity. Reads from stdin if not given.";
931 const char *identity = "Identity to store a single key under. If given, --keydata (or stdin) is read as a single key instead of a bulk <identity> <key> list.";
932
933 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
934 __cleanup_file__attribute__((cleanup(shr_cleanup_file))) FILE *fd = NULL((void*)0);
935 __cleanup_free__attribute__((cleanup(shr_freep))) char *key = NULL((void*)0);
936 long keyring_id;
937 int err = 0;
938
939 struct config {
940 char *keyring;
941 char *keyfile;
942 char *keydata;
943 char *identity;
944 };
945
946 struct config cfg = {
947 .keyring = ".nvme",
948 .keyfile = NULL((void*)0),
949 .keydata = NULL((void*)0),
950 .identity = NULL((void*)0),
951 };
952
953 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keyfile", 'f', "STRING", CFG_STRING, &
cfg.keyfile, 1, keyfile, 0, }, {"keydata", 'd', "STRING", CFG_STRING
, &cfg.keydata, 1, keydata, 0, }, {"identity", 'i', "STRING"
, CFG_STRING, &cfg.identity, 1, identity, 0, }, {"", 0, (
(void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
954 OPT_STR("keyring", 'k', &cfg.keyring, keyring),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keyfile", 'f', "STRING", CFG_STRING, &
cfg.keyfile, 1, keyfile, 0, }, {"keydata", 'd', "STRING", CFG_STRING
, &cfg.keydata, 1, keydata, 0, }, {"identity", 'i', "STRING"
, CFG_STRING, &cfg.identity, 1, identity, 0, }, {"", 0, (
(void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
955 OPT_STR("keyfile", 'f', &cfg.keyfile, keyfile),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keyfile", 'f', "STRING", CFG_STRING, &
cfg.keyfile, 1, keyfile, 0, }, {"keydata", 'd', "STRING", CFG_STRING
, &cfg.keydata, 1, keydata, 0, }, {"identity", 'i', "STRING"
, CFG_STRING, &cfg.identity, 1, identity, 0, }, {"", 0, (
(void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
956 OPT_STR("keydata", 'd', &cfg.keydata, keydata),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keyfile", 'f', "STRING", CFG_STRING, &
cfg.keyfile, 1, keyfile, 0, }, {"keydata", 'd', "STRING", CFG_STRING
, &cfg.keydata, 1, keydata, 0, }, {"identity", 'i', "STRING"
, CFG_STRING, &cfg.identity, 1, identity, 0, }, {"", 0, (
(void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
957 OPT_STR("identity", 'i', &cfg.identity, identity))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keyfile", 'f', "STRING", CFG_STRING, &
cfg.keyfile, 1, keyfile, 0, }, {"keydata", 'd', "STRING", CFG_STRING
, &cfg.keydata, 1, keydata, 0, }, {"identity", 'i', "STRING"
, CFG_STRING, &cfg.identity, 1, identity, 0, }, {"", 0, (
(void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress output messages, overwrites verbose mode"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
958
959 err = parse_args(argc, argv, desc, opts);
960 if (err)
961 return err;
962
963 err = nvme_create_global_ctx(&ctx);
964 if (err) {
965 nvme_show_error("Failed to create global context")nvme_show_message(1, "Failed to create global context");
966 return err;
967 }
968 libnvme_set_logging_level(ctx, log_level, false0, false0);
969
970 if (!cfg.identity) {
971 if (cfg.keyfile) {
972 fd = fopen(cfg.keyfile, "r");
973 if (!fd) {
974 nvme_show_error("Cannot open keyfile %s, error %d",nvme_show_message(1, "Cannot open keyfile %s, error %d", cfg.
keyfile, (*__errno_location ()))
975 cfg.keyfile, errno)nvme_show_message(1, "Cannot open keyfile %s, error %d", cfg.
keyfile, (*__errno_location ()))
;
976 return -errno(*__errno_location ());
977 }
978 } else {
979 fd = freopen(NULL((void*)0), "r", stdinstdin);
980 }
981
982 err = import_key(ctx, cfg.keyring, fd);
983 if (err) {
984 nvme_show_error("Import of keys failed with '%s'",nvme_show_message(1, "Import of keys failed with '%s'", libnvme_strerror
(err))
985 libnvme_strerror(err))nvme_show_message(1, "Import of keys failed with '%s'", libnvme_strerror
(err))
;
986 return err;
987 }
988
989 nvme_show_verbose_info("importing from %s", cfg.keyfile)nvme_show_verbose_message("importing from %s", cfg.keyfile);
990 return 0;
991 }
992
993 err = read_key_value(cfg.keydata, &key);
994 if (err) {
995 nvme_show_error("No key data")nvme_show_message(1, "No key data");
996 return err;
997 }
998
999 err = libnvmf_lookup_keyring(ctx, cfg.keyring, &keyring_id);
1000 if (err) {
1001 nvme_show_error("Failed to lookup keyring '%s', %s",nvme_show_message(1, "Failed to lookup keyring '%s', %s", cfg
.keyring, libnvme_strerror(-err))
1002 cfg.keyring, libnvme_strerror(-err))nvme_show_message(1, "Failed to lookup keyring '%s', %s", cfg
.keyring, libnvme_strerror(-err))
;
1003 return err;
1004 }
1005
1006 err = import_one_key(ctx, keyring_id, cfg.identity, key);
1007 if (err) {
1008 nvme_show_error("Failed to insert key, %s", libnvme_strerror(-err))nvme_show_message(1, "Failed to insert key, %s", libnvme_strerror
(-err))
;
1009 return err;
1010 }
1011
1012 nvme_show_result("Inserted key for identity '%s'", cfg.identity)nvme_show_message(0, "Inserted key for identity '%s'", cfg.identity
)
;
1013 return 0;
1014}
1015
1016static int key_revoke(int argc, char **argv, struct command *acmd, struct plugin *plugin)
1017{
1018 const char *desc = "Revoke an NVMeoF TLS PSK from a keyring.\n";
1019 const char *keyring = "Keyring to revoke the key from.";
1020 const char *keytype = "Key type of the key to revoke.";
1021 const char *identity = "Identity (description) of the key to revoke.";
1022
1023 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1024 int err = 0;
1025
1026 struct config {
1027 char *keyring;
1028 char *keytype;
1029 char *identity;
1030 };
1031
1032 struct config cfg = {
1033 .keyring = ".nvme",
1034 .keytype = "psk",
1035 .identity = NULL((void*)0),
1036 };
1037
1038 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"identity", 'i', "STRING", CFG_STRING
, &cfg.identity, 1, identity, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1039 OPT_STR("keyring", 'k', &cfg.keyring, keyring),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"identity", 'i', "STRING", CFG_STRING
, &cfg.identity, 1, identity, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1040 OPT_STR("keytype", 't', &cfg.keytype, keytype),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"identity", 'i', "STRING", CFG_STRING
, &cfg.identity, 1, identity, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1041 OPT_STR("identity", 'i', &cfg.identity, identity))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"keyring", 'k', "STRING", CFG_STRING, &cfg.keyring
, 1, keyring, 0, }, {"keytype", 't', "STRING", CFG_STRING, &
cfg.keytype, 1, keytype, 0, }, {"identity", 'i', "STRING", CFG_STRING
, &cfg.identity, 1, identity, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress output messages, overwrites verbose mode", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
1042
1043 err = parse_args(argc, argv, desc, opts);
1044 if (err)
1045 return err;
1046
1047 if (!cfg.identity) {
1048 nvme_show_error("Must specify --identity")nvme_show_message(1, "Must specify --identity");
1049 return -EINVAL22;
1050 }
1051
1052 err = nvme_create_global_ctx(&ctx);
1053 if (err) {
1054 nvme_show_error("Failed to create global context")nvme_show_message(1, "Failed to create global context");
1055 return err;
1056 }
1057 libnvme_set_logging_level(ctx, log_level, false0, false0);
1058
1059 err = libnvmf_revoke_tls_key(ctx, cfg.keyring, cfg.keytype, cfg.identity);
1060 if (err) {
1061 nvme_show_error("Failed to revoke key '%s'",nvme_show_message(1, "Failed to revoke key '%s'", libnvme_strerror
(err))
1062 libnvme_strerror(err))nvme_show_message(1, "Failed to revoke key '%s'", libnvme_strerror
(err))
;
1063 return err;
1064 }
1065
1066 nvme_show_verbose_info("revoking key")nvme_show_verbose_message("revoking key");
1067
1068 return 0;
1069}