Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2024 Intel Corporation
3 : : */
4 : :
5 : : #include "spdk/nvme.h"
6 : : #include "spdk/json.h"
7 : : #include "spdk/log.h"
8 : : #include "spdk/stdinc.h"
9 : : #include "spdk/string.h"
10 : : #include "spdk/thread.h"
11 : : #include "spdk/util.h"
12 : : #include "spdk_internal/nvme.h"
13 : :
14 : : #include <openssl/rand.h>
15 : :
16 : : #include "nvmf_internal.h"
17 : :
18 : : #define NVMF_AUTH_DEFAULT_KATO_US (120ull * 1000 * 1000)
19 : : #define NVMF_AUTH_DIGEST_MAX_SIZE 64
20 : : #define NVMF_AUTH_DH_KEY_MAX_SIZE 1024
21 : :
22 : : #define AUTH_ERRLOG(q, fmt, ...) \
23 : : SPDK_ERRLOG("[%s:%s:%u] " fmt, (q)->ctrlr->subsys->subnqn, (q)->ctrlr->hostnqn, \
24 : : (q)->qid, ## __VA_ARGS__)
25 : : #define AUTH_DEBUGLOG(q, fmt, ...) \
26 : : SPDK_DEBUGLOG(nvmf_auth, "[%s:%s:%u] " fmt, \
27 : : (q)->ctrlr->subsys->subnqn, (q)->ctrlr->hostnqn, (q)->qid, ## __VA_ARGS__)
28 : : #define AUTH_LOGDUMP(msg, buf, len) \
29 : : SPDK_LOGDUMP(nvmf_auth, msg, buf, len)
30 : :
31 : : enum nvmf_qpair_auth_state {
32 : : NVMF_QPAIR_AUTH_NEGOTIATE,
33 : : NVMF_QPAIR_AUTH_CHALLENGE,
34 : : NVMF_QPAIR_AUTH_REPLY,
35 : : NVMF_QPAIR_AUTH_SUCCESS1,
36 : : NVMF_QPAIR_AUTH_SUCCESS2,
37 : : NVMF_QPAIR_AUTH_FAILURE1,
38 : : NVMF_QPAIR_AUTH_COMPLETED,
39 : : NVMF_QPAIR_AUTH_ERROR,
40 : : };
41 : :
42 : : struct spdk_nvmf_qpair_auth {
43 : : enum nvmf_qpair_auth_state state;
44 : : struct spdk_poller *poller;
45 : : int fail_reason;
46 : : uint16_t tid;
47 : : int digest;
48 : : int dhgroup;
49 : : uint8_t cval[NVMF_AUTH_DIGEST_MAX_SIZE];
50 : : uint32_t seqnum;
51 : : struct spdk_nvme_dhchap_dhkey *dhkey;
52 : : bool cvalid;
53 : : };
54 : :
55 : : struct nvmf_auth_common_header {
56 : : uint8_t auth_type;
57 : : uint8_t auth_id;
58 : : uint8_t reserved0[2];
59 : : uint16_t t_id;
60 : : };
61 : :
62 : : static void
63 : 4284 : nvmf_auth_request_complete(struct spdk_nvmf_request *req, int sct, int sc, int dnr)
64 : : {
65 : 4284 : struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
66 : :
67 : 4284 : response->status.sct = sct;
68 : 4284 : response->status.sc = sc;
69 : 4284 : response->status.dnr = dnr;
70 : :
71 : 4284 : spdk_nvmf_request_complete(req);
72 : 4284 : }
73 : :
74 : : static const char *
75 : 4576 : nvmf_auth_get_state_name(enum nvmf_qpair_auth_state state)
76 : : {
77 : : static const char *state_names[] = {
78 : : [NVMF_QPAIR_AUTH_NEGOTIATE] = "negotiate",
79 : : [NVMF_QPAIR_AUTH_CHALLENGE] = "challenge",
80 : : [NVMF_QPAIR_AUTH_REPLY] = "reply",
81 : : [NVMF_QPAIR_AUTH_SUCCESS1] = "success1",
82 : : [NVMF_QPAIR_AUTH_SUCCESS2] = "success2",
83 : : [NVMF_QPAIR_AUTH_FAILURE1] = "failure1",
84 : : [NVMF_QPAIR_AUTH_COMPLETED] = "completed",
85 : : [NVMF_QPAIR_AUTH_ERROR] = "error",
86 : : };
87 : :
88 : 4576 : return state_names[state];
89 : : }
90 : :
91 : : static void
92 : 5204 : nvmf_auth_set_state(struct spdk_nvmf_qpair *qpair, enum nvmf_qpair_auth_state state)
93 : : {
94 : 5204 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
95 : :
96 [ + + ]: 5204 : if (auth->state == state) {
97 : 924 : return;
98 : : }
99 : :
100 [ - + + - ]: 4280 : AUTH_DEBUGLOG(qpair, "auth state: %s\n", nvmf_auth_get_state_name(state));
101 : 4280 : auth->state = state;
102 : : }
103 : :
104 : : static void
105 : 16 : nvmf_auth_disconnect_qpair(struct spdk_nvmf_qpair *qpair)
106 : : {
107 : 16 : nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_ERROR);
108 : 16 : spdk_nvmf_qpair_disconnect(qpair);
109 : 16 : }
110 : :
111 : : static void
112 : 16 : nvmf_auth_request_fail1(struct spdk_nvmf_request *req, int reason)
113 : : {
114 : 16 : struct spdk_nvmf_qpair *qpair = req->qpair;
115 : 16 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
116 : :
117 : 16 : nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_FAILURE1);
118 : 16 : auth->fail_reason = reason;
119 : :
120 : : /* The command itself is completed successfully, but a subsequent AUTHENTICATION_RECV
121 : : * command will be completed with an AUTH_failure1 message
122 : : */
123 : 16 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0);
124 : 16 : }
125 : :
126 : : static bool
127 : 1204 : nvmf_auth_digest_allowed(struct spdk_nvmf_qpair *qpair, uint8_t digest)
128 : : {
129 : 1204 : struct spdk_nvmf_tgt *tgt = qpair->group->tgt;
130 : :
131 [ - + ]: 1204 : return tgt->dhchap_digests & SPDK_BIT(digest);
132 : : }
133 : :
134 : : static bool
135 : 1644 : nvmf_auth_dhgroup_allowed(struct spdk_nvmf_qpair *qpair, uint8_t dhgroup)
136 : : {
137 : 1644 : struct spdk_nvmf_tgt *tgt = qpair->group->tgt;
138 : :
139 [ - + ]: 1644 : return tgt->dhchap_dhgroups & SPDK_BIT(dhgroup);
140 : : }
141 : :
142 : : static int
143 : 0 : nvmf_auth_timeout_poller(void *ctx)
144 : : {
145 : 0 : struct spdk_nvmf_qpair *qpair = ctx;
146 : 0 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
147 : :
148 : 0 : AUTH_ERRLOG(qpair, "authentication timed out\n");
149 : :
150 : 0 : spdk_poller_unregister(&auth->poller);
151 : 0 : nvmf_auth_disconnect_qpair(qpair);
152 : :
153 : 0 : return SPDK_POLLER_BUSY;
154 : : }
155 : :
156 : : static int
157 : 4264 : nvmf_auth_rearm_poller(struct spdk_nvmf_qpair *qpair)
158 : : {
159 : 4264 : struct spdk_nvmf_ctrlr *ctrlr = qpair->ctrlr;
160 : 4264 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
161 : : uint64_t timeout;
162 : :
163 : 4264 : timeout = ctrlr->feat.keep_alive_timer.bits.kato > 0 ?
164 [ + - ]: 4264 : ctrlr->feat.keep_alive_timer.bits.kato * 1000 :
165 : : NVMF_AUTH_DEFAULT_KATO_US;
166 : :
167 : 4264 : spdk_poller_unregister(&auth->poller);
168 : 4264 : auth->poller = SPDK_POLLER_REGISTER(nvmf_auth_timeout_poller, qpair, timeout);
169 [ - + ]: 4264 : if (auth->poller == NULL) {
170 : 0 : return -ENOMEM;
171 : : }
172 : :
173 : 4264 : return 0;
174 : : }
175 : :
176 : : static void
177 : 1796 : nvmf_auth_qpair_cleanup(struct spdk_nvmf_qpair_auth *auth)
178 : : {
179 : 1796 : spdk_poller_unregister(&auth->poller);
180 : 1796 : spdk_nvme_dhchap_dhkey_free(&auth->dhkey);
181 : 1796 : }
182 : :
183 : : static int
184 : 4280 : nvmf_auth_check_command(struct spdk_nvmf_request *req, uint8_t secp,
185 : : uint8_t spsp0, uint8_t spsp1, uint32_t len)
186 : : {
187 : 4280 : struct spdk_nvmf_qpair *qpair = req->qpair;
188 : :
189 [ - + ]: 4280 : if (secp != SPDK_NVMF_AUTH_SECP_NVME) {
190 : 0 : AUTH_ERRLOG(qpair, "invalid secp=%u\n", secp);
191 : 0 : return -EINVAL;
192 : : }
193 [ + - - + ]: 4280 : if (spsp0 != 1 || spsp1 != 1) {
194 : 0 : AUTH_ERRLOG(qpair, "invalid spsp0=%u, spsp1=%u\n", spsp0, spsp1);
195 : 0 : return -EINVAL;
196 : : }
197 [ - + ]: 4280 : if (len != req->length) {
198 : 0 : AUTH_ERRLOG(qpair, "invalid length: %"PRIu32" != %"PRIu32"\n", len, req->length);
199 : 0 : return -EINVAL;
200 : : }
201 : :
202 : 4280 : return 0;
203 : : }
204 : :
205 : : static void *
206 : 4280 : nvmf_auth_get_message(struct spdk_nvmf_request *req, size_t size)
207 : : {
208 [ + - + - : 4280 : if (req->length > 0 && req->iovcnt == 1 && req->iov[0].iov_len >= size) {
+ - ]
209 : 4280 : return req->iov[0].iov_base;
210 : : }
211 : :
212 : 0 : return NULL;
213 : : }
214 : :
215 : : static void
216 : 908 : nvmf_auth_negotiate_exec(struct spdk_nvmf_request *req, struct spdk_nvmf_auth_negotiate *msg)
217 : : {
218 : 908 : struct spdk_nvmf_qpair *qpair = req->qpair;
219 : 908 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
220 : 908 : struct spdk_nvmf_auth_descriptor *desc = NULL;
221 : : /* These arrays are sorted from the strongest hash/dhgroup to the weakest, so the strongest
222 : : * hash/dhgroup pair supported by the host is always selected
223 : : */
224 : 908 : enum spdk_nvmf_dhchap_hash digests[] = {
225 : : SPDK_NVMF_DHCHAP_HASH_SHA512,
226 : : SPDK_NVMF_DHCHAP_HASH_SHA384,
227 : : SPDK_NVMF_DHCHAP_HASH_SHA256
228 : : };
229 : 908 : enum spdk_nvmf_dhchap_dhgroup dhgroups[] = {
230 : : SPDK_NVMF_DHCHAP_DHGROUP_8192,
231 : : SPDK_NVMF_DHCHAP_DHGROUP_6144,
232 : : SPDK_NVMF_DHCHAP_DHGROUP_4096,
233 : : SPDK_NVMF_DHCHAP_DHGROUP_3072,
234 : : SPDK_NVMF_DHCHAP_DHGROUP_2048,
235 : : SPDK_NVMF_DHCHAP_DHGROUP_NULL,
236 : : };
237 : 908 : int digest = -1, dhgroup = -1;
238 : : size_t i, j;
239 : :
240 [ - + ]: 908 : if (auth->state != NVMF_QPAIR_AUTH_NEGOTIATE) {
241 : 0 : AUTH_ERRLOG(qpair, "invalid state: %s\n", nvmf_auth_get_state_name(auth->state));
242 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
243 : 8 : return;
244 : : }
245 : :
246 : 908 : auth->tid = msg->t_id;
247 [ + - - + ]: 908 : if (req->length < sizeof(*msg) || req->length != sizeof(*msg) + msg->napd * sizeof(*desc)) {
248 : 0 : AUTH_ERRLOG(qpair, "invalid message length: %"PRIu32"\n", req->length);
249 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
250 : 0 : return;
251 : : }
252 : :
253 [ - + ]: 908 : if (msg->sc_c != SPDK_NVMF_AUTH_SCC_DISABLED) {
254 : 0 : AUTH_ERRLOG(qpair, "scc mismatch\n");
255 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_SCC_MISMATCH);
256 : 0 : return;
257 : : }
258 : :
259 [ + - ]: 908 : for (i = 0; i < msg->napd; ++i) {
260 [ + - ]: 908 : if (msg->descriptors[i].auth_id == SPDK_NVMF_AUTH_TYPE_DHCHAP) {
261 : 908 : desc = &msg->descriptors[i];
262 : 908 : break;
263 : : }
264 : : }
265 [ - + ]: 908 : if (desc == NULL) {
266 : 0 : AUTH_ERRLOG(qpair, "no usable protocol found\n");
267 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_PROTOCOL_UNUSABLE);
268 : 0 : return;
269 : : }
270 [ + - ]: 908 : if (desc->halen > SPDK_COUNTOF(desc->hash_id_list) ||
271 [ - + ]: 908 : desc->dhlen > SPDK_COUNTOF(desc->dhg_id_list)) {
272 : 0 : AUTH_ERRLOG(qpair, "invalid halen=%u, dhlen=%u\n", desc->halen, desc->dhlen);
273 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
274 : 0 : return;
275 : : }
276 : :
277 [ + + ]: 1208 : for (i = 0; i < SPDK_COUNTOF(digests); ++i) {
278 [ + + ]: 1204 : if (!nvmf_auth_digest_allowed(qpair, digests[i])) {
279 : 4 : continue;
280 : : }
281 [ + + ]: 2728 : for (j = 0; j < desc->halen; ++j) {
282 [ + + ]: 2432 : if (digests[i] == desc->hash_id_list[j]) {
283 [ - + + - ]: 904 : AUTH_DEBUGLOG(qpair, "selected digest: %s\n",
284 : : spdk_nvme_dhchap_get_digest_name(digests[i]));
285 : 904 : digest = digests[i];
286 : 904 : break;
287 : : }
288 : : }
289 [ + + ]: 1200 : if (digest >= 0) {
290 : 904 : break;
291 : : }
292 : : }
293 [ + + ]: 908 : if (digest < 0) {
294 : 4 : AUTH_ERRLOG(qpair, "no usable digests found\n");
295 : 4 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_HASH_UNUSABLE);
296 : 4 : return;
297 : : }
298 : :
299 [ + + ]: 1648 : for (i = 0; i < SPDK_COUNTOF(dhgroups); ++i) {
300 [ + + ]: 1644 : if (!nvmf_auth_dhgroup_allowed(qpair, dhgroups[i])) {
301 : 16 : continue;
302 : : }
303 [ + + ]: 5416 : for (j = 0; j < desc->dhlen; ++j) {
304 [ + + ]: 4688 : if (dhgroups[i] == desc->dhg_id_list[j]) {
305 [ - + + - ]: 900 : AUTH_DEBUGLOG(qpair, "selected dhgroup: %s\n",
306 : : spdk_nvme_dhchap_get_dhgroup_name(dhgroups[i]));
307 : 900 : dhgroup = dhgroups[i];
308 : 900 : break;
309 : : }
310 : : }
311 [ + + ]: 1628 : if (dhgroup >= 0) {
312 : 900 : break;
313 : : }
314 : : }
315 [ + + ]: 904 : if (dhgroup < 0) {
316 : 4 : AUTH_ERRLOG(qpair, "no usable dhgroups found\n");
317 : 4 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_DHGROUP_UNUSABLE);
318 : 4 : return;
319 : : }
320 : :
321 [ - + ]: 900 : if (nvmf_auth_rearm_poller(qpair)) {
322 : 0 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC,
323 : : SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 1);
324 : 0 : nvmf_auth_disconnect_qpair(qpair);
325 : 0 : return;
326 : : }
327 : :
328 : 900 : auth->digest = digest;
329 : 900 : auth->dhgroup = dhgroup;
330 : 900 : nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_CHALLENGE);
331 : 900 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0);
332 : : }
333 : :
334 : : static void
335 : 900 : nvmf_auth_reply_exec(struct spdk_nvmf_request *req, struct spdk_nvmf_dhchap_reply *msg)
336 : : {
337 : 900 : struct spdk_nvmf_qpair *qpair = req->qpair;
338 : 900 : struct spdk_nvmf_ctrlr *ctrlr = qpair->ctrlr;
339 : 900 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
340 : 0 : uint8_t response[NVMF_AUTH_DIGEST_MAX_SIZE];
341 : 0 : uint8_t dhsec[NVMF_AUTH_DH_KEY_MAX_SIZE];
342 : 900 : struct spdk_key *key = NULL, *ckey = NULL;
343 : 900 : size_t dhseclen = 0;
344 : : uint8_t hl;
345 : : int rc;
346 : :
347 [ - + ]: 900 : if (auth->state != NVMF_QPAIR_AUTH_REPLY) {
348 : 0 : AUTH_ERRLOG(qpair, "invalid state=%s\n", nvmf_auth_get_state_name(auth->state));
349 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
350 : 0 : goto out;
351 : : }
352 [ - + ]: 900 : if (req->length < sizeof(*msg)) {
353 : 0 : AUTH_ERRLOG(qpair, "invalid message length=%"PRIu32"\n", req->length);
354 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
355 : 0 : goto out;
356 : : }
357 : :
358 : 900 : hl = spdk_nvme_dhchap_get_digest_length(auth->digest);
359 [ + - - + ]: 900 : if (hl == 0 || msg->hl != hl) {
360 : 0 : AUTH_ERRLOG(qpair, "hash length mismatch: %u != %u\n", msg->hl, hl);
361 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
362 : 0 : goto out;
363 : : }
364 [ - + ]: 900 : if ((msg->dhvlen % 4) != 0) {
365 : 0 : AUTH_ERRLOG(qpair, "dhvlen=%u is not multiple of 4\n", msg->dhvlen);
366 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
367 : 0 : goto out;
368 : : }
369 [ - + ]: 900 : if (req->length != sizeof(*msg) + 2 * hl + msg->dhvlen) {
370 : 0 : AUTH_ERRLOG(qpair, "invalid message length: %"PRIu32" != %zu\n",
371 : : req->length, sizeof(*msg) + 2 * hl);
372 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
373 : 0 : goto out;
374 : : }
375 [ - + ]: 900 : if (msg->t_id != auth->tid) {
376 : 0 : AUTH_ERRLOG(qpair, "transaction id mismatch: %u != %u\n", msg->t_id, auth->tid);
377 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
378 : 0 : goto out;
379 : : }
380 [ + + - + ]: 900 : if (msg->cvalid != 0 && msg->cvalid != 1) {
381 : 0 : AUTH_ERRLOG(qpair, "unexpected cvalid=%d\n", msg->cvalid);
382 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
383 : 0 : goto out;
384 : : }
385 [ + + - + ]: 900 : if (msg->cvalid && msg->seqnum == 0) {
386 : 0 : AUTH_ERRLOG(qpair, "unexpected seqnum=0 with cvalid=1\n");
387 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
388 : 0 : goto out;
389 : : }
390 : :
391 : 900 : key = nvmf_subsystem_get_dhchap_key(ctrlr->subsys, ctrlr->hostnqn, NVMF_AUTH_KEY_HOST);
392 [ - + ]: 900 : if (key == NULL) {
393 : 0 : AUTH_ERRLOG(qpair, "couldn't get DH-HMAC-CHAP key\n");
394 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED);
395 : 0 : goto out;
396 : : }
397 : :
398 [ + + ]: 900 : if (auth->dhgroup != SPDK_NVMF_DHCHAP_DHGROUP_NULL) {
399 [ - + + - ]: 852 : AUTH_LOGDUMP("host pubkey:", &msg->rval[2 * hl], msg->dhvlen);
400 : 852 : dhseclen = sizeof(dhsec);
401 : 852 : rc = spdk_nvme_dhchap_dhkey_derive_secret(auth->dhkey, &msg->rval[2 * hl],
402 : 852 : msg->dhvlen, dhsec, &dhseclen);
403 [ - + ]: 852 : if (rc != 0) {
404 : 0 : AUTH_ERRLOG(qpair, "couldn't derive DH secret\n");
405 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED);
406 : 0 : goto out;
407 : : }
408 : :
409 [ - + + - ]: 852 : AUTH_LOGDUMP("dh secret:", dhsec, dhseclen);
410 : : }
411 : :
412 [ + - + - ]: 900 : assert(hl <= sizeof(response) && hl <= sizeof(auth->cval));
413 : 1800 : rc = spdk_nvme_dhchap_calculate(key, (enum spdk_nvmf_dhchap_hash)auth->digest,
414 : 900 : "HostHost", auth->seqnum, auth->tid, 0,
415 : 900 : ctrlr->hostnqn, ctrlr->subsys->subnqn,
416 : 900 : dhseclen > 0 ? dhsec : NULL, dhseclen,
417 [ + + ]: 900 : auth->cval, response);
418 [ - + ]: 900 : if (rc != 0) {
419 : 0 : AUTH_ERRLOG(qpair, "failed to calculate challenge response: %s\n",
420 : : spdk_strerror(-rc));
421 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED);
422 : 0 : goto out;
423 : : }
424 : :
425 [ - + + + ]: 900 : if (memcmp(msg->rval, response, hl) != 0) {
426 : 4 : AUTH_ERRLOG(qpair, "challenge response mismatch\n");
427 [ - + + - ]: 4 : AUTH_LOGDUMP("response:", msg->rval, hl);
428 [ - + + - ]: 4 : AUTH_LOGDUMP("expected:", response, hl);
429 : 4 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED);
430 : 4 : goto out;
431 : : }
432 : :
433 [ + + ]: 896 : if (msg->cvalid) {
434 : 668 : ckey = nvmf_subsystem_get_dhchap_key(ctrlr->subsys, ctrlr->hostnqn,
435 : : NVMF_AUTH_KEY_CTRLR);
436 [ + + ]: 668 : if (ckey == NULL) {
437 : 4 : AUTH_ERRLOG(qpair, "missing DH-HMAC-CHAP ctrlr key\n");
438 : 4 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED);
439 : 4 : goto out;
440 : : }
441 : 1328 : rc = spdk_nvme_dhchap_calculate(ckey, (enum spdk_nvmf_dhchap_hash)auth->digest,
442 : 664 : "Controller", msg->seqnum, auth->tid, 0,
443 : 664 : ctrlr->subsys->subnqn, ctrlr->hostnqn,
444 : 664 : dhseclen > 0 ? dhsec : NULL, dhseclen,
445 [ + + ]: 664 : &msg->rval[hl], auth->cval);
446 [ - + ]: 664 : if (rc != 0) {
447 : 0 : AUTH_ERRLOG(qpair, "failed to calculate ctrlr challenge response: %s\n",
448 : : spdk_strerror(-rc));
449 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED);
450 : 0 : goto out;
451 : : }
452 : 664 : auth->cvalid = true;
453 : : }
454 : :
455 [ - + ]: 892 : if (nvmf_auth_rearm_poller(qpair)) {
456 : 0 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC,
457 : : SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 1);
458 : 0 : nvmf_auth_disconnect_qpair(qpair);
459 : 0 : goto out;
460 : : }
461 : :
462 : 892 : nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_SUCCESS1);
463 : 892 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0);
464 : 900 : out:
465 : 900 : spdk_keyring_put_key(ckey);
466 : 900 : spdk_keyring_put_key(key);
467 : 900 : }
468 : :
469 : : static void
470 : 660 : nvmf_auth_success2_exec(struct spdk_nvmf_request *req, struct spdk_nvmf_dhchap_success2 *msg)
471 : : {
472 : 660 : struct spdk_nvmf_qpair *qpair = req->qpair;
473 : 660 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
474 : :
475 [ - + ]: 660 : if (auth->state != NVMF_QPAIR_AUTH_SUCCESS2) {
476 : 0 : AUTH_ERRLOG(qpair, "invalid state=%s\n", nvmf_auth_get_state_name(auth->state));
477 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
478 : 0 : return;
479 : : }
480 [ - + ]: 660 : if (req->length != sizeof(*msg)) {
481 : 0 : AUTH_ERRLOG(qpair, "invalid message length=%"PRIu32"\n", req->length);
482 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
483 : 0 : return;
484 : : }
485 [ - + ]: 660 : if (msg->t_id != auth->tid) {
486 : 0 : AUTH_ERRLOG(qpair, "transaction id mismatch: %u != %u\n", msg->t_id, auth->tid);
487 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
488 : 0 : return;
489 : : }
490 : :
491 [ - + + - ]: 660 : AUTH_DEBUGLOG(qpair, "controller authentication successful\n");
492 : 660 : nvmf_qpair_set_state(qpair, SPDK_NVMF_QPAIR_ENABLED);
493 : 660 : nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_COMPLETED);
494 : 660 : nvmf_auth_qpair_cleanup(auth);
495 : 660 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0);
496 : : }
497 : :
498 : : static void
499 : 4 : nvmf_auth_failure2_exec(struct spdk_nvmf_request *req, struct spdk_nvmf_auth_failure *msg)
500 : : {
501 : 4 : struct spdk_nvmf_qpair *qpair = req->qpair;
502 : 4 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
503 : :
504 : : /* AUTH_failure2 is only expected when we're waiting for the success2 message */
505 [ - + ]: 4 : if (auth->state != NVMF_QPAIR_AUTH_SUCCESS2) {
506 : 0 : AUTH_ERRLOG(qpair, "invalid state=%s\n", nvmf_auth_get_state_name(auth->state));
507 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
508 : 0 : return;
509 : : }
510 [ - + ]: 4 : if (req->length != sizeof(*msg)) {
511 : 0 : AUTH_ERRLOG(qpair, "invalid message length=%"PRIu32"\n", req->length);
512 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
513 : 0 : return;
514 : : }
515 [ - + ]: 4 : if (msg->t_id != auth->tid) {
516 : 0 : AUTH_ERRLOG(qpair, "transaction id mismatch: %u != %u\n", msg->t_id, auth->tid);
517 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
518 : 0 : return;
519 : : }
520 : :
521 : 4 : AUTH_ERRLOG(qpair, "ctrlr authentication failed: rc=%d, rce=%d\n", msg->rc, msg->rce);
522 : 4 : nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_ERROR);
523 : 4 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0);
524 : : }
525 : :
526 : : static void
527 : 2472 : nvmf_auth_send_exec(struct spdk_nvmf_request *req)
528 : : {
529 : 2472 : struct spdk_nvmf_qpair *qpair = req->qpair;
530 : 2472 : struct spdk_nvmf_fabric_auth_send_cmd *cmd = &req->cmd->auth_send_cmd;
531 : : struct nvmf_auth_common_header *header;
532 : : int rc;
533 : :
534 : 2472 : rc = nvmf_auth_check_command(req, cmd->secp, cmd->spsp0, cmd->spsp1, cmd->tl);
535 [ - + ]: 2472 : if (rc != 0) {
536 : 0 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC,
537 : : SPDK_NVME_SC_INVALID_FIELD, 1);
538 : 0 : return;
539 : : }
540 : :
541 : 2472 : header = nvmf_auth_get_message(req, sizeof(*header));
542 [ - + ]: 2472 : if (header == NULL) {
543 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
544 : 0 : return;
545 : : }
546 : :
547 [ + + - ]: 2472 : switch (header->auth_type) {
548 : 912 : case SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE:
549 [ + + - ]: 912 : switch (header->auth_id) {
550 : 908 : case SPDK_NVMF_AUTH_ID_NEGOTIATE:
551 : 908 : nvmf_auth_negotiate_exec(req, (void *)header);
552 : 908 : break;
553 : 4 : case SPDK_NVMF_AUTH_ID_FAILURE2:
554 : 4 : nvmf_auth_failure2_exec(req, (void *)header);
555 : 4 : break;
556 : 0 : default:
557 : 0 : AUTH_ERRLOG(qpair, "unexpected auth_id=%u\n", header->auth_id);
558 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
559 : 0 : break;
560 : : }
561 : 912 : break;
562 : 1560 : case SPDK_NVMF_AUTH_TYPE_DHCHAP:
563 [ + + - ]: 1560 : switch (header->auth_id) {
564 : 900 : case SPDK_NVMF_AUTH_ID_DHCHAP_REPLY:
565 : 900 : nvmf_auth_reply_exec(req, (void *)header);
566 : 900 : break;
567 : 660 : case SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS2:
568 : 660 : nvmf_auth_success2_exec(req, (void *)header);
569 : 660 : break;
570 : 0 : default:
571 : 0 : AUTH_ERRLOG(qpair, "unexpected auth_id=%u\n", header->auth_id);
572 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
573 : 0 : break;
574 : : }
575 : 1560 : break;
576 : 0 : default:
577 : 0 : AUTH_ERRLOG(qpair, "unexpected auth_type=%u\n", header->auth_type);
578 : 0 : nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
579 : 0 : break;
580 : : }
581 : : }
582 : :
583 : : static void
584 : 1808 : nvmf_auth_recv_complete(struct spdk_nvmf_request *req, uint32_t length)
585 : : {
586 [ - + ]: 1808 : assert(req->cmd->nvmf_cmd.fctype == SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV);
587 : 1808 : req->length = length;
588 : 1808 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0);
589 : 1808 : }
590 : :
591 : : static void
592 : 16 : nvmf_auth_recv_failure1(struct spdk_nvmf_request *req, int fail_reason)
593 : : {
594 : 16 : struct spdk_nvmf_qpair *qpair = req->qpair;
595 : 16 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
596 : : struct spdk_nvmf_auth_failure *failure;
597 : :
598 : 16 : failure = nvmf_auth_get_message(req, sizeof(*failure));
599 [ - + ]: 16 : if (failure == NULL) {
600 : 0 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC,
601 : : SPDK_NVME_SC_INVALID_FIELD, 1);
602 : 0 : nvmf_auth_disconnect_qpair(qpair);
603 : 0 : return;
604 : : }
605 : :
606 : 16 : failure->auth_type = SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE;
607 : 16 : failure->auth_id = SPDK_NVMF_AUTH_ID_FAILURE1;
608 : 16 : failure->t_id = auth->tid;
609 : 16 : failure->rc = SPDK_NVMF_AUTH_FAILURE;
610 : 16 : failure->rce = fail_reason;
611 : :
612 : 16 : nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_FAILURE1);
613 : 16 : nvmf_auth_recv_complete(req, sizeof(*failure));
614 : 16 : nvmf_auth_disconnect_qpair(qpair);
615 : : }
616 : :
617 : : static int
618 : 900 : nvmf_auth_get_seqnum(struct spdk_nvmf_qpair *qpair)
619 : : {
620 : 900 : struct spdk_nvmf_subsystem *subsys = qpair->ctrlr->subsys;
621 : 900 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
622 : : int rc;
623 : :
624 [ - + ]: 900 : pthread_mutex_lock(&subsys->mutex);
625 [ + + ]: 900 : if (subsys->auth_seqnum == 0) {
626 : 8 : rc = RAND_bytes((void *)&subsys->auth_seqnum, sizeof(subsys->auth_seqnum));
627 [ - + ]: 8 : if (rc != 1) {
628 [ # # ]: 0 : pthread_mutex_unlock(&subsys->mutex);
629 : 0 : return -EIO;
630 : : }
631 : : }
632 [ - + ]: 900 : if (++subsys->auth_seqnum == 0) {
633 : 0 : subsys->auth_seqnum = 1;
634 : :
635 : : }
636 : 900 : auth->seqnum = subsys->auth_seqnum;
637 [ - + ]: 900 : pthread_mutex_unlock(&subsys->mutex);
638 : :
639 : 900 : return 0;
640 : : }
641 : :
642 : : static int
643 : 900 : nvmf_auth_recv_challenge(struct spdk_nvmf_request *req)
644 : : {
645 : 900 : struct spdk_nvmf_qpair *qpair = req->qpair;
646 : 900 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
647 : : struct spdk_nvmf_dhchap_challenge *challenge;
648 : 0 : uint8_t hl, dhv[NVMF_AUTH_DH_KEY_MAX_SIZE];
649 : 900 : size_t dhvlen = 0;
650 : : int rc;
651 : :
652 : 900 : hl = spdk_nvme_dhchap_get_digest_length(auth->digest);
653 [ + - + - ]: 900 : assert(hl > 0 && hl <= sizeof(auth->cval));
654 : :
655 [ + + ]: 900 : if (auth->dhgroup != SPDK_NVMF_DHCHAP_DHGROUP_NULL) {
656 : 852 : auth->dhkey = spdk_nvme_dhchap_generate_dhkey(auth->dhgroup);
657 [ - + ]: 852 : if (auth->dhkey == NULL) {
658 : 0 : AUTH_ERRLOG(qpair, "failed to generate DH key\n");
659 : 0 : return SPDK_NVMF_AUTH_FAILED;
660 : : }
661 : :
662 : 852 : dhvlen = sizeof(dhv);
663 : 852 : rc = spdk_nvme_dhchap_dhkey_get_pubkey(auth->dhkey, dhv, &dhvlen);
664 [ - + ]: 852 : if (rc != 0) {
665 : 0 : AUTH_ERRLOG(qpair, "failed to get DH public key\n");
666 : 0 : return SPDK_NVMF_AUTH_FAILED;
667 : : }
668 : :
669 [ - + + - ]: 852 : AUTH_LOGDUMP("ctrlr pubkey:", dhv, dhvlen);
670 : : }
671 : :
672 : 900 : challenge = nvmf_auth_get_message(req, sizeof(*challenge) + hl + dhvlen);
673 [ - + ]: 900 : if (challenge == NULL) {
674 : 0 : AUTH_ERRLOG(qpair, "invalid message length: %"PRIu32"\n", req->length);
675 : 0 : return SPDK_NVMF_AUTH_INCORRECT_PAYLOAD;
676 : : }
677 : 900 : rc = nvmf_auth_get_seqnum(qpair);
678 [ - + ]: 900 : if (rc != 0) {
679 : 0 : return SPDK_NVMF_AUTH_FAILED;
680 : : }
681 : 900 : rc = RAND_bytes(auth->cval, hl);
682 [ - + ]: 900 : if (rc != 1) {
683 : 0 : return SPDK_NVMF_AUTH_FAILED;
684 : : }
685 [ - + ]: 900 : if (nvmf_auth_rearm_poller(qpair)) {
686 : 0 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC,
687 : : SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 1);
688 : 0 : nvmf_auth_disconnect_qpair(qpair);
689 : 0 : return 0;
690 : : }
691 : :
692 [ - + - + ]: 900 : memcpy(challenge->cval, auth->cval, hl);
693 [ - + - + ]: 900 : memcpy(&challenge->cval[hl], dhv, dhvlen);
694 : 900 : challenge->auth_type = SPDK_NVMF_AUTH_TYPE_DHCHAP;
695 : 900 : challenge->auth_id = SPDK_NVMF_AUTH_ID_DHCHAP_CHALLENGE;
696 : 900 : challenge->t_id = auth->tid;
697 : 900 : challenge->hl = hl;
698 : 900 : challenge->hash_id = (uint8_t)auth->digest;
699 : 900 : challenge->dhg_id = (uint8_t)auth->dhgroup;
700 : 900 : challenge->dhvlen = dhvlen;
701 : 900 : challenge->seqnum = auth->seqnum;
702 : :
703 : 900 : nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_REPLY);
704 : 900 : nvmf_auth_recv_complete(req, sizeof(*challenge) + hl + dhvlen);
705 : :
706 : 900 : return 0;
707 : : }
708 : :
709 : : static int
710 : 892 : nvmf_auth_recv_success1(struct spdk_nvmf_request *req)
711 : : {
712 : 892 : struct spdk_nvmf_qpair *qpair = req->qpair;
713 : 892 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
714 : : struct spdk_nvmf_dhchap_success1 *success;
715 : : uint8_t hl;
716 : :
717 : 892 : hl = spdk_nvme_dhchap_get_digest_length(auth->digest);
718 [ - + ]: 892 : success = nvmf_auth_get_message(req, sizeof(*success) + auth->cvalid * hl);
719 [ - + ]: 892 : if (success == NULL) {
720 : 0 : AUTH_ERRLOG(qpair, "invalid message length: %"PRIu32"\n", req->length);
721 : 0 : return SPDK_NVMF_AUTH_INCORRECT_PAYLOAD;
722 : : }
723 : :
724 [ - + + - ]: 892 : AUTH_DEBUGLOG(qpair, "host authentication successful\n");
725 : 892 : success->auth_type = SPDK_NVMF_AUTH_TYPE_DHCHAP;
726 : 892 : success->auth_id = SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS1;
727 : 892 : success->t_id = auth->tid;
728 : : /* Kernel initiator always expects hl to be set, regardless of rvalid */
729 : 892 : success->hl = hl;
730 : 892 : success->rvalid = 0;
731 : :
732 [ - + + + ]: 892 : if (!auth->cvalid) {
733 : : /* Host didn't request to authenticate us, we're done */
734 : 228 : nvmf_qpair_set_state(qpair, SPDK_NVMF_QPAIR_ENABLED);
735 : 228 : nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_COMPLETED);
736 : 228 : nvmf_auth_qpair_cleanup(auth);
737 : : } else {
738 [ - + ]: 664 : if (nvmf_auth_rearm_poller(qpair)) {
739 : 0 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC,
740 : : SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 1);
741 : 0 : nvmf_auth_disconnect_qpair(qpair);
742 : 0 : return 0;
743 : : }
744 [ - + + - ]: 664 : AUTH_DEBUGLOG(qpair, "cvalid=1, starting controller authentication\n");
745 : 664 : nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_SUCCESS2);
746 [ - + - + ]: 664 : memcpy(success->rval, auth->cval, hl);
747 : 664 : success->rvalid = 1;
748 : : }
749 : :
750 [ - + ]: 892 : nvmf_auth_recv_complete(req, sizeof(*success) + auth->cvalid * hl);
751 : 892 : return 0;
752 : : }
753 : :
754 : : static void
755 : 1808 : nvmf_auth_recv_exec(struct spdk_nvmf_request *req)
756 : : {
757 : 1808 : struct spdk_nvmf_qpair *qpair = req->qpair;
758 : 1808 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
759 : 1808 : struct spdk_nvmf_fabric_auth_recv_cmd *cmd = &req->cmd->auth_recv_cmd;
760 : : int rc;
761 : :
762 : 1808 : rc = nvmf_auth_check_command(req, cmd->secp, cmd->spsp0, cmd->spsp1, cmd->al);
763 [ - + ]: 1808 : if (rc != 0) {
764 : 0 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC,
765 : : SPDK_NVME_SC_INVALID_FIELD, 1);
766 : 0 : return;
767 : : }
768 : :
769 : 1808 : spdk_iov_memset(req->iov, req->iovcnt, 0);
770 [ + + + - ]: 1808 : switch (auth->state) {
771 : 900 : case NVMF_QPAIR_AUTH_CHALLENGE:
772 : 900 : rc = nvmf_auth_recv_challenge(req);
773 [ - + ]: 900 : if (rc != 0) {
774 : 0 : nvmf_auth_recv_failure1(req, rc);
775 : : }
776 : 900 : break;
777 : 892 : case NVMF_QPAIR_AUTH_SUCCESS1:
778 : 892 : rc = nvmf_auth_recv_success1(req);
779 [ - + ]: 892 : if (rc != 0) {
780 : 0 : nvmf_auth_recv_failure1(req, rc);
781 : : }
782 : 892 : break;
783 : 16 : case NVMF_QPAIR_AUTH_FAILURE1:
784 : 16 : nvmf_auth_recv_failure1(req, auth->fail_reason);
785 : 16 : break;
786 : 0 : default:
787 : 0 : nvmf_auth_recv_failure1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
788 : 0 : break;
789 : : }
790 : : }
791 : :
792 : : int
793 : 4284 : nvmf_auth_request_exec(struct spdk_nvmf_request *req)
794 : : {
795 : 4284 : struct spdk_nvmf_qpair *qpair = req->qpair;
796 : 4284 : union nvmf_h2c_msg *cmd = req->cmd;
797 : :
798 : : /* We don't support reauthentication */
799 [ + + ]: 4284 : if (qpair->state != SPDK_NVMF_QPAIR_AUTHENTICATING) {
800 : 4 : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC,
801 : : SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR, 0);
802 : 4 : return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS;
803 : : }
804 : :
805 [ - + ]: 4280 : assert(cmd->nvmf_cmd.opcode == SPDK_NVME_OPC_FABRIC);
806 [ + + - ]: 4280 : switch (cmd->nvmf_cmd.fctype) {
807 : 2472 : case SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND:
808 : 2472 : nvmf_auth_send_exec(req);
809 : 2472 : break;
810 : 1808 : case SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV:
811 : 1808 : nvmf_auth_recv_exec(req);
812 : 1808 : break;
813 : 0 : default:
814 : 0 : assert(0 && "invalid fctype");
815 : : nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC,
816 : : SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 0);
817 : : break;
818 : : }
819 : :
820 : 4280 : return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS;
821 : : }
822 : :
823 : : int
824 : 908 : nvmf_qpair_auth_init(struct spdk_nvmf_qpair *qpair)
825 : : {
826 : : struct spdk_nvmf_qpair_auth *auth;
827 : : int rc;
828 : :
829 [ - + ]: 908 : assert(qpair->auth == NULL);
830 : 908 : auth = calloc(1, sizeof(*qpair->auth));
831 [ - + ]: 908 : if (auth == NULL) {
832 : 0 : return -ENOMEM;
833 : : }
834 : :
835 : 908 : auth->digest = -1;
836 : 908 : qpair->auth = auth;
837 : 908 : nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_NEGOTIATE);
838 : :
839 : 908 : rc = nvmf_auth_rearm_poller(qpair);
840 [ - + ]: 908 : if (rc != 0) {
841 : 0 : AUTH_ERRLOG(qpair, "failed to arm timeout poller: %s\n", spdk_strerror(-rc));
842 : 0 : nvmf_qpair_auth_destroy(qpair);
843 : 0 : return rc;
844 : : }
845 : :
846 : 908 : return 0;
847 : : }
848 : :
849 : : void
850 : 10487 : nvmf_qpair_auth_destroy(struct spdk_nvmf_qpair *qpair)
851 : : {
852 : 10487 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
853 : :
854 [ + + ]: 10487 : if (auth != NULL) {
855 : 908 : nvmf_auth_qpair_cleanup(auth);
856 : 908 : free(qpair->auth);
857 : 908 : qpair->auth = NULL;
858 : : }
859 : 10487 : }
860 : :
861 : : void
862 : 298 : nvmf_qpair_auth_dump(struct spdk_nvmf_qpair *qpair, struct spdk_json_write_ctx *w)
863 : : {
864 : 298 : struct spdk_nvmf_qpair_auth *auth = qpair->auth;
865 : : const char *digest, *dhgroup;
866 : :
867 [ + + ]: 298 : if (auth == NULL) {
868 : 2 : return;
869 : : }
870 : :
871 : 296 : spdk_json_write_named_object_begin(w, "auth");
872 : 296 : spdk_json_write_named_string(w, "state", nvmf_auth_get_state_name(auth->state));
873 : 296 : digest = spdk_nvme_dhchap_get_digest_name(auth->digest);
874 [ + - ]: 296 : spdk_json_write_named_string(w, "digest", digest ? digest : "unknown");
875 : 296 : dhgroup = spdk_nvme_dhchap_get_dhgroup_name(auth->dhgroup);
876 [ + - ]: 296 : spdk_json_write_named_string(w, "dhgroup", dhgroup ? dhgroup : "unknown");
877 : 296 : spdk_json_write_object_end(w);
878 : : }
879 : :
880 : : bool
881 : 312 : nvmf_auth_is_supported(void)
882 : : {
883 : 312 : return true;
884 : : }
885 : 882 : SPDK_LOG_REGISTER_COMPONENT(nvmf_auth)
|