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