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