xref: /spdk/test/unit/lib/nvmf/auth.c/auth_ut.c (revision 8afdeef3becfe9409cc9e7372bd0bc10e8b7d46d)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2024 Intel Corporation. All rights reserved.
3  */
4 #include "spdk/stdinc.h"
5 
6 #include "spdk_internal/cunit.h"
7 #include "spdk_internal/mock.h"
8 
9 #include "common/lib/ut_multithread.c"
10 #include "unit/lib/json_mock.c"
11 #include "nvmf/auth.c"
12 
13 DEFINE_STUB(spdk_nvme_dhchap_get_digest_name, const char *, (int d), NULL);
14 DEFINE_STUB(spdk_nvme_dhchap_get_dhgroup_name, const char *, (int d), NULL);
15 DEFINE_STUB(spdk_nvme_dhchap_get_digest_length, uint8_t, (int d), 0);
16 DEFINE_STUB_V(spdk_keyring_put_key, (struct spdk_key *k));
17 DEFINE_STUB(nvmf_subsystem_get_dhchap_key, struct spdk_key *,
18 	    (struct spdk_nvmf_subsystem *s, const char *h, enum nvmf_auth_key_type t), NULL);
19 DEFINE_STUB(spdk_nvme_dhchap_generate_dhkey, struct spdk_nvme_dhchap_dhkey *,
20 	    (enum spdk_nvmf_dhchap_dhgroup dhgroup), NULL);
21 DEFINE_STUB_V(spdk_nvme_dhchap_dhkey_free, (struct spdk_nvme_dhchap_dhkey **key));
22 DEFINE_STUB(spdk_nvme_dhchap_dhkey_derive_secret, int,
23 	    (struct spdk_nvme_dhchap_dhkey *key, const void *peer, size_t peerlen, void *secret,
24 	     size_t *seclen), 0);
25 DECLARE_WRAPPER(RAND_bytes, int, (unsigned char *buf, int num));
26 
27 static uint8_t g_rand_val;
28 DEFINE_WRAPPER_MOCK(RAND_bytes, int) = 1;
29 
30 int
31 __wrap_RAND_bytes(unsigned char *buf, int num)
32 {
33 	memset(buf, g_rand_val, num);
34 	return MOCK_GET(RAND_bytes);
35 }
36 
37 void
38 nvmf_qpair_set_state(struct spdk_nvmf_qpair *qpair, enum spdk_nvmf_qpair_state state)
39 {
40 	qpair->state = state;
41 }
42 
43 int
44 spdk_nvmf_qpair_disconnect(struct spdk_nvmf_qpair *qpair)
45 {
46 	nvmf_qpair_set_state(qpair, SPDK_NVMF_QPAIR_ERROR);
47 	return 0;
48 }
49 
50 static bool g_req_completed;
51 
52 int
53 spdk_nvmf_request_complete(struct spdk_nvmf_request *req)
54 {
55 	g_req_completed = true;
56 	return 0;
57 }
58 
59 static uint8_t g_rval;
60 DEFINE_RETURN_MOCK(spdk_nvme_dhchap_calculate, int);
61 
62 int
63 spdk_nvme_dhchap_calculate(struct spdk_key *key, enum spdk_nvmf_dhchap_hash hash,
64 			   const char *type, uint32_t seq, uint16_t tid, uint8_t scc,
65 			   const char *nqn1, const char *nqn2, const void *dhkey, size_t dhlen,
66 			   const void *cval, void *rval)
67 {
68 	memset(rval, g_rval, spdk_nvme_dhchap_get_digest_length(hash));
69 	return MOCK_GET(spdk_nvme_dhchap_calculate);
70 }
71 
72 static uint8_t g_dhv;
73 static size_t g_dhvlen;
74 DEFINE_RETURN_MOCK(spdk_nvme_dhchap_dhkey_get_pubkey, int);
75 
76 int
77 spdk_nvme_dhchap_dhkey_get_pubkey(struct spdk_nvme_dhchap_dhkey *dhkey, void *pub, size_t *len)
78 {
79 	int rc;
80 
81 	rc = MOCK_GET(spdk_nvme_dhchap_dhkey_get_pubkey);
82 	if (rc != 0) {
83 		return rc;
84 	}
85 
86 	SPDK_CU_ASSERT_FATAL(*len >= g_dhvlen);
87 	memset(pub, g_dhv, g_dhvlen);
88 	*len = g_dhvlen;
89 
90 	return rc;
91 }
92 
93 static void
94 ut_clear_resp(struct spdk_nvmf_request *req)
95 {
96 	memset(&req->rsp->nvme_cpl, 0, sizeof(req->rsp->nvme_cpl));
97 }
98 
99 #define ut_prep_cmd(_req, _cmd, _buf, _len, _lfield)		\
100 	do {							\
101 		(_req)->cmd = (void *)_cmd;			\
102 		(_req)->iov[0].iov_base = _buf;			\
103 		(_req)->iov[0].iov_len = _len;			\
104 		(_req)->iovcnt = 1;				\
105 		(_req)->length = _len;				\
106 		(_cmd)->secp = SPDK_NVMF_AUTH_SECP_NVME;	\
107 		(_cmd)->spsp0 = 1;				\
108 		(_cmd)->spsp1 = 1;				\
109 		(_cmd)->_lfield = _len;				\
110 	} while (0)
111 
112 #define ut_prep_send_cmd(req, cmd, buf, len) ut_prep_cmd(req, cmd, buf, len, tl)
113 #define ut_prep_recv_cmd(req, cmd, buf, len) ut_prep_cmd(req, cmd, buf, len, al)
114 
115 static void
116 test_auth_send_recv_error(void)
117 {
118 	union nvmf_c2h_msg rsp = {};
119 	struct spdk_nvmf_subsystem subsys = {};
120 	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys };
121 	struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr };
122 	struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp };
123 	struct spdk_nvme_cpl *cpl = &rsp.nvme_cpl;
124 	struct spdk_nvmf_fabric_auth_send_cmd send_cmd = {};
125 	struct spdk_nvmf_fabric_auth_recv_cmd recv_cmd = {};
126 	struct spdk_nvmf_qpair_auth *auth;
127 	int rc;
128 
129 	rc = nvmf_qpair_auth_init(&qpair);
130 	SPDK_CU_ASSERT_FATAL(rc == 0);
131 	ut_prep_send_cmd(&req, &send_cmd, NULL, 255);
132 	ut_prep_recv_cmd(&req, &recv_cmd, NULL, 255);
133 	auth = qpair.auth;
134 
135 	/* Bad secp (send) */
136 	g_req_completed = false;
137 	req.cmd = (void *)&send_cmd;
138 	ut_clear_resp(&req);
139 	send_cmd.secp = SPDK_NVMF_AUTH_SECP_NVME + 1;
140 
141 	nvmf_auth_send_exec(&req);
142 	CU_ASSERT(g_req_completed);
143 	CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC);
144 	CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_INVALID_FIELD);
145 	CU_ASSERT_EQUAL(cpl->status.dnr, 1);
146 	send_cmd.secp = SPDK_NVMF_AUTH_SECP_NVME;
147 
148 	/* Bad secp (recv) */
149 	g_req_completed = false;
150 	req.cmd = (void *)&recv_cmd;
151 	ut_clear_resp(&req);
152 	recv_cmd.secp = SPDK_NVMF_AUTH_SECP_NVME + 1;
153 
154 	nvmf_auth_recv_exec(&req);
155 	CU_ASSERT(g_req_completed);
156 	CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC);
157 	CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_INVALID_FIELD);
158 	CU_ASSERT_EQUAL(cpl->status.dnr, 1);
159 	recv_cmd.secp = SPDK_NVMF_AUTH_SECP_NVME;
160 
161 	/* Bad spsp0 (send) */
162 	g_req_completed = false;
163 	req.cmd = (void *)&send_cmd;
164 	ut_clear_resp(&req);
165 	send_cmd.spsp0 = 2;
166 
167 	nvmf_auth_send_exec(&req);
168 	CU_ASSERT(g_req_completed);
169 	CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC);
170 	CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_INVALID_FIELD);
171 	CU_ASSERT_EQUAL(cpl->status.dnr, 1);
172 	send_cmd.spsp0 = 1;
173 
174 	/* Bad spsp0 (recv) */
175 	g_req_completed = false;
176 	req.cmd = (void *)&recv_cmd;
177 	ut_clear_resp(&req);
178 	recv_cmd.spsp0 = 2;
179 
180 	nvmf_auth_recv_exec(&req);
181 	CU_ASSERT(g_req_completed);
182 	CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC);
183 	CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_INVALID_FIELD);
184 	CU_ASSERT_EQUAL(cpl->status.dnr, 1);
185 	recv_cmd.spsp0 = 1;
186 
187 	/* Bad spsp1 (send) */
188 	g_req_completed = false;
189 	req.cmd = (void *)&send_cmd;
190 	ut_clear_resp(&req);
191 	send_cmd.spsp1 = 2;
192 
193 	nvmf_auth_send_exec(&req);
194 	CU_ASSERT(g_req_completed);
195 	CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC);
196 	CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_INVALID_FIELD);
197 	CU_ASSERT_EQUAL(cpl->status.dnr, 1);
198 	send_cmd.spsp1 = 1;
199 
200 	/* Bad spsp1 (recv) */
201 	g_req_completed = false;
202 	req.cmd = (void *)&recv_cmd;
203 	ut_clear_resp(&req);
204 	recv_cmd.spsp1 = 2;
205 
206 	nvmf_auth_recv_exec(&req);
207 	CU_ASSERT(g_req_completed);
208 	CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC);
209 	CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_INVALID_FIELD);
210 	CU_ASSERT_EQUAL(cpl->status.dnr, 1);
211 	recv_cmd.spsp1 = 1;
212 
213 	/* Bad length (send) */
214 	g_req_completed = false;
215 	req.cmd = (void *)&send_cmd;
216 	ut_clear_resp(&req);
217 	send_cmd.tl = req.length + 1;
218 
219 	nvmf_auth_recv_exec(&req);
220 	CU_ASSERT(g_req_completed);
221 	CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC);
222 	CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_INVALID_FIELD);
223 	CU_ASSERT_EQUAL(cpl->status.dnr, 1);
224 	send_cmd.tl = req.length;
225 
226 	/* Bad length (recv) */
227 	g_req_completed = false;
228 	req.cmd = (void *)&recv_cmd;
229 	ut_clear_resp(&req);
230 	recv_cmd.al = req.length - 1;
231 
232 	nvmf_auth_recv_exec(&req);
233 	CU_ASSERT(g_req_completed);
234 	CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC);
235 	CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_INVALID_FIELD);
236 	CU_ASSERT_EQUAL(cpl->status.dnr, 1);
237 	recv_cmd.al = req.length;
238 
239 	/* Bad length (smaller than common header) */
240 	g_req_completed = false;
241 	req.cmd = (union nvmf_h2c_msg *)&send_cmd;
242 	ut_clear_resp(&req);
243 	send_cmd.tl = req.length = sizeof(struct nvmf_auth_common_header) - 1;
244 
245 	nvmf_auth_send_exec(&req);
246 	CU_ASSERT(g_req_completed);
247 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
248 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
249 	send_cmd.tl = req.length = 255;
250 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
251 	auth->fail_reason = 0;
252 
253 	nvmf_qpair_auth_destroy(&qpair);
254 }
255 
256 static void
257 test_auth_negotiate(void)
258 {
259 	union nvmf_c2h_msg rsp = {};
260 	struct spdk_nvmf_subsystem subsys = {};
261 	struct spdk_nvmf_tgt tgt = { .dhchap_digests = UINT32_MAX, .dhchap_dhgroups = UINT32_MAX };
262 	struct spdk_nvmf_poll_group group = { .tgt = &tgt };
263 	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys };
264 	struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr, .group = &group };
265 	struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp };
266 	struct spdk_nvmf_fabric_auth_send_cmd cmd = {};
267 	struct spdk_nvmf_qpair_auth *auth;
268 	struct spdk_nvmf_auth_negotiate *msg;
269 	struct spdk_nvmf_auth_descriptor *desc;
270 	uint8_t msgbuf[4096];
271 	int rc;
272 
273 	msg = (void *)msgbuf;
274 	rc = nvmf_qpair_auth_init(&qpair);
275 	SPDK_CU_ASSERT_FATAL(rc == 0);
276 	ut_prep_send_cmd(&req, &cmd, msgbuf, sizeof(*msg) + sizeof(*desc));
277 	auth = qpair.auth;
278 
279 	/* Successful negotiation */
280 	g_req_completed = false;
281 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
282 	msg->auth_type = SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE;
283 	msg->auth_id = SPDK_NVMF_AUTH_ID_NEGOTIATE;
284 	msg->sc_c = SPDK_NVMF_AUTH_SCC_DISABLED;
285 	msg->napd = 1;
286 	desc = &msg->descriptors[0];
287 	desc->auth_id = SPDK_NVMF_AUTH_TYPE_DHCHAP;
288 	desc->halen = 3;
289 	desc->hash_id_list[0] = SPDK_NVMF_DHCHAP_HASH_SHA256;
290 	desc->hash_id_list[1] = SPDK_NVMF_DHCHAP_HASH_SHA384;
291 	desc->hash_id_list[2] = SPDK_NVMF_DHCHAP_HASH_SHA512;
292 	desc->dhlen = 6;
293 	desc->dhg_id_list[0] = SPDK_NVMF_DHCHAP_DHGROUP_NULL;
294 	desc->dhg_id_list[1] = SPDK_NVMF_DHCHAP_DHGROUP_2048;
295 	desc->dhg_id_list[2] = SPDK_NVMF_DHCHAP_DHGROUP_3072;
296 	desc->dhg_id_list[3] = SPDK_NVMF_DHCHAP_DHGROUP_4096;
297 	desc->dhg_id_list[4] = SPDK_NVMF_DHCHAP_DHGROUP_6144;
298 	desc->dhg_id_list[5] = SPDK_NVMF_DHCHAP_DHGROUP_8192;
299 
300 	nvmf_auth_send_exec(&req);
301 	CU_ASSERT(g_req_completed);
302 	CU_ASSERT_EQUAL(auth->digest, SPDK_NVMF_DHCHAP_HASH_SHA512);
303 	CU_ASSERT_EQUAL(auth->dhgroup, SPDK_NVMF_DHCHAP_DHGROUP_8192);
304 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_CHALLENGE);
305 
306 	/* Invalid auth state */
307 	g_req_completed = false;
308 	auth->state = NVMF_QPAIR_AUTH_ERROR;
309 	auth->digest = -1;
310 
311 	nvmf_auth_send_exec(&req);
312 	CU_ASSERT(g_req_completed);
313 	CU_ASSERT_EQUAL(auth->digest, -1);
314 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
315 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
316 
317 	/* scc mismatch */
318 	g_req_completed = false;
319 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
320 	msg->sc_c = SPDK_NVMF_AUTH_SCC_TLS;
321 
322 	nvmf_auth_send_exec(&req);
323 	CU_ASSERT(g_req_completed);
324 	CU_ASSERT_EQUAL(auth->digest, -1);
325 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
326 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_SCC_MISMATCH);
327 	msg->sc_c = SPDK_NVMF_AUTH_SCC_DISABLED;
328 
329 	/* Missing DH-HMAC-CHAP protocol (napd=0) */
330 	g_req_completed = false;
331 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
332 	req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg);
333 	msg->napd = 0;
334 
335 	nvmf_auth_send_exec(&req);
336 	CU_ASSERT(g_req_completed);
337 	CU_ASSERT_EQUAL(auth->digest, -1);
338 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
339 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_PROTOCOL_UNUSABLE);
340 	req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg) + sizeof(*desc);
341 	msg->napd = 1;
342 
343 	/* Missing DH-HMAC-CHAP protocol */
344 	g_req_completed = false;
345 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
346 	desc->auth_id = SPDK_NVMF_AUTH_TYPE_DHCHAP + 1;
347 
348 	nvmf_auth_send_exec(&req);
349 	CU_ASSERT(g_req_completed);
350 	CU_ASSERT_EQUAL(auth->digest, -1);
351 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
352 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_PROTOCOL_UNUSABLE);
353 	desc->auth_id = SPDK_NVMF_AUTH_TYPE_DHCHAP;
354 
355 	/* No valid digests (halen=0) */
356 	g_req_completed = false;
357 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
358 	desc->halen = 0;
359 
360 	nvmf_auth_send_exec(&req);
361 	CU_ASSERT(g_req_completed);
362 	CU_ASSERT_EQUAL(auth->digest, -1);
363 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
364 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_HASH_UNUSABLE);
365 
366 	/* No valid digests */
367 	g_req_completed = false;
368 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
369 	desc->hash_id_list[0] = SPDK_NVMF_DHCHAP_HASH_SHA512 + 1;
370 	desc->hash_id_list[1] = SPDK_NVMF_DHCHAP_HASH_SHA512 + 2;
371 	desc->hash_id_list[2] = SPDK_NVMF_DHCHAP_HASH_SHA512 + 3;
372 	desc->halen = 3;
373 
374 	nvmf_auth_send_exec(&req);
375 	CU_ASSERT(g_req_completed);
376 	CU_ASSERT_EQUAL(auth->digest, -1);
377 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
378 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_HASH_UNUSABLE);
379 	desc->hash_id_list[0] = SPDK_NVMF_DHCHAP_HASH_SHA256;
380 	desc->hash_id_list[1] = SPDK_NVMF_DHCHAP_HASH_SHA384;
381 	desc->hash_id_list[2] = SPDK_NVMF_DHCHAP_HASH_SHA512;
382 
383 	/* No valid dhgroups (dhlen=0) */
384 	g_req_completed = false;
385 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
386 	desc->dhlen = 0;
387 
388 	nvmf_auth_send_exec(&req);
389 	CU_ASSERT(g_req_completed);
390 	CU_ASSERT_EQUAL(auth->digest, -1);
391 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
392 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_DHGROUP_UNUSABLE);
393 
394 	/* No valid dhgroups */
395 	g_req_completed = false;
396 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
397 	desc->dhlen = 2;
398 	desc->dhg_id_list[0] = SPDK_NVMF_DHCHAP_DHGROUP_8192 + 1;
399 	desc->dhg_id_list[1] = SPDK_NVMF_DHCHAP_DHGROUP_8192 + 2;
400 
401 	nvmf_auth_send_exec(&req);
402 	CU_ASSERT(g_req_completed);
403 	CU_ASSERT_EQUAL(auth->digest, -1);
404 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
405 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_DHGROUP_UNUSABLE);
406 	desc->dhg_id_list[0] = SPDK_NVMF_DHCHAP_DHGROUP_NULL;
407 	desc->dhg_id_list[1] = SPDK_NVMF_DHCHAP_DHGROUP_2048;
408 	desc->dhlen = 6;
409 
410 	/* Bad halen value */
411 	g_req_completed = false;
412 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
413 	desc->halen = 255;
414 
415 	nvmf_auth_send_exec(&req);
416 	CU_ASSERT(g_req_completed);
417 	CU_ASSERT_EQUAL(auth->digest, -1);
418 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
419 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
420 	desc->halen = 3;
421 
422 	/* Bad dhlen value */
423 	g_req_completed = false;
424 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
425 	desc->dhlen = 255;
426 
427 	nvmf_auth_send_exec(&req);
428 	CU_ASSERT(g_req_completed);
429 	CU_ASSERT_EQUAL(auth->digest, -1);
430 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
431 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
432 	desc->dhlen = 6;
433 
434 	/* Invalid request length (too small) */
435 	g_req_completed = false;
436 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
437 	req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg) - 1;
438 
439 	nvmf_auth_send_exec(&req);
440 	CU_ASSERT(g_req_completed);
441 	CU_ASSERT_EQUAL(auth->digest, -1);
442 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
443 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
444 
445 	/* Invalid request length (too small) */
446 	g_req_completed = false;
447 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
448 	req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg);
449 
450 	nvmf_auth_send_exec(&req);
451 	CU_ASSERT(g_req_completed);
452 	CU_ASSERT_EQUAL(auth->digest, -1);
453 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
454 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
455 
456 	/* Invalid request length (too small) */
457 	g_req_completed = false;
458 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
459 	req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg) + sizeof(*desc) - 1;
460 
461 	nvmf_auth_send_exec(&req);
462 	CU_ASSERT(g_req_completed);
463 	CU_ASSERT_EQUAL(auth->digest, -1);
464 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
465 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
466 
467 	/* Invalid request length (too large) */
468 	g_req_completed = false;
469 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
470 	req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg) + sizeof(*desc) + 1;
471 
472 	nvmf_auth_send_exec(&req);
473 	CU_ASSERT(g_req_completed);
474 	CU_ASSERT_EQUAL(auth->digest, -1);
475 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
476 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
477 	req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg) + sizeof(*desc);
478 
479 	/* No common digests */
480 	g_req_completed = false;
481 	auth->digest = -1;
482 	auth->dhgroup = -1;
483 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
484 	desc->halen = 1;
485 	tgt.dhchap_digests = SPDK_BIT(SPDK_NVMF_DHCHAP_HASH_SHA384) |
486 			     SPDK_BIT(SPDK_NVMF_DHCHAP_HASH_SHA512);
487 
488 	nvmf_auth_send_exec(&req);
489 	CU_ASSERT(g_req_completed);
490 	CU_ASSERT_EQUAL(auth->digest, -1);
491 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
492 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_HASH_UNUSABLE);
493 	tgt.dhchap_digests = UINT32_MAX;
494 	desc->halen = 3;
495 
496 	/* No common dhgroups */
497 	g_req_completed = false;
498 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
499 	desc->dhlen = 1;
500 	tgt.dhchap_dhgroups = SPDK_BIT(SPDK_NVMF_DHCHAP_DHGROUP_2048) |
501 			      SPDK_BIT(SPDK_NVMF_DHCHAP_DHGROUP_3072) |
502 			      SPDK_BIT(SPDK_NVMF_DHCHAP_DHGROUP_4096) |
503 			      SPDK_BIT(SPDK_NVMF_DHCHAP_DHGROUP_6144) |
504 			      SPDK_BIT(SPDK_NVMF_DHCHAP_DHGROUP_8192);
505 
506 	nvmf_auth_send_exec(&req);
507 	CU_ASSERT(g_req_completed);
508 	CU_ASSERT_EQUAL(auth->dhgroup, -1);
509 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
510 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_DHGROUP_UNUSABLE);
511 	tgt.dhchap_dhgroups = UINT32_MAX;
512 	desc->dhlen = 6;
513 
514 	nvmf_qpair_auth_destroy(&qpair);
515 }
516 
517 static void
518 test_auth_timeout(void)
519 {
520 	union nvmf_c2h_msg rsp = {};
521 	struct spdk_nvmf_subsystem subsys = {};
522 	struct spdk_nvmf_tgt tgt = { .dhchap_digests = UINT32_MAX, .dhchap_dhgroups = UINT32_MAX };
523 	struct spdk_nvmf_poll_group group = { .tgt = &tgt };
524 	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys };
525 	struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr, .group = &group };
526 	struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp };
527 	struct spdk_nvmf_fabric_auth_send_cmd cmd = {};
528 	struct spdk_nvmf_qpair_auth *auth;
529 	struct spdk_nvmf_auth_negotiate *msg;
530 	struct spdk_nvmf_auth_descriptor *desc;
531 	uint8_t msgbuf[4096];
532 	int rc;
533 
534 	msg = (void *)msgbuf;
535 	ut_prep_send_cmd(&req, &cmd, msgbuf, sizeof(*msg) + sizeof(*desc));
536 	MOCK_SET(spdk_get_ticks_hz, 1000 * 1000);
537 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
538 
539 	/* Check that a timeout is correctly detected and qpair is disconnected */
540 	rc = nvmf_qpair_auth_init(&qpair);
541 	SPDK_CU_ASSERT_FATAL(rc == 0);
542 	MOCK_SET(spdk_get_ticks, NVMF_AUTH_DEFAULT_KATO_US - 1);
543 	poll_threads();
544 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_AUTHENTICATING);
545 	MOCK_SET(spdk_get_ticks, NVMF_AUTH_DEFAULT_KATO_US);
546 	poll_threads();
547 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
548 	nvmf_qpair_auth_destroy(&qpair);
549 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
550 	MOCK_SET(spdk_get_ticks, 0);
551 
552 	/* Check a case where a non-zero kato is set in controller features */
553 	ctrlr.feat.keep_alive_timer.bits.kato = 10 * 1000;
554 	rc = nvmf_qpair_auth_init(&qpair);
555 	SPDK_CU_ASSERT_FATAL(rc == 0);
556 	MOCK_SET(spdk_get_ticks, 10 * 1000 * 1000 - 1);
557 	poll_threads();
558 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_AUTHENTICATING);
559 	MOCK_SET(spdk_get_ticks, 10 * 1000 * 1000);
560 	poll_threads();
561 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
562 	nvmf_qpair_auth_destroy(&qpair);
563 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
564 	ctrlr.feat.keep_alive_timer.bits.kato = 0;
565 	MOCK_SET(spdk_get_ticks, 0);
566 
567 	/* Check that reception of a command rearms the timeout poller */
568 	rc = nvmf_qpair_auth_init(&qpair);
569 	SPDK_CU_ASSERT_FATAL(rc == 0);
570 	auth = qpair.auth;
571 
572 	MOCK_SET(spdk_get_ticks, NVMF_AUTH_DEFAULT_KATO_US / 2);
573 	g_req_completed = false;
574 	msg->auth_type = SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE;
575 	msg->auth_id = SPDK_NVMF_AUTH_ID_NEGOTIATE;
576 	msg->sc_c = SPDK_NVMF_AUTH_SCC_DISABLED;
577 	msg->napd = 1;
578 	desc = &msg->descriptors[0];
579 	desc->auth_id = SPDK_NVMF_AUTH_TYPE_DHCHAP;
580 	desc->halen = 1;
581 	desc->hash_id_list[0] = SPDK_NVMF_DHCHAP_HASH_SHA256;
582 	desc->dhlen = 1;
583 	desc->dhg_id_list[0] = SPDK_NVMF_DHCHAP_DHGROUP_NULL;
584 
585 	nvmf_auth_send_exec(&req);
586 	CU_ASSERT(g_req_completed);
587 	CU_ASSERT_EQUAL(auth->digest, SPDK_NVMF_DHCHAP_HASH_SHA256);
588 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_CHALLENGE);
589 
590 	MOCK_SET(spdk_get_ticks, NVMF_AUTH_DEFAULT_KATO_US);
591 	poll_threads();
592 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_AUTHENTICATING);
593 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_CHALLENGE);
594 
595 	MOCK_SET(spdk_get_ticks, NVMF_AUTH_DEFAULT_KATO_US + NVMF_AUTH_DEFAULT_KATO_US / 2);
596 	poll_threads();
597 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
598 	nvmf_qpair_auth_destroy(&qpair);
599 	MOCK_SET(spdk_get_ticks, 0);
600 
601 	/* Check that a timeout during reauthentication doesn't disconnect the qpair, but only
602 	 * resets the state of the authentication */
603 	rc = nvmf_qpair_auth_init(&qpair);
604 	SPDK_CU_ASSERT_FATAL(rc == 0);
605 	auth = qpair.auth;
606 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
607 	qpair.state = SPDK_NVMF_QPAIR_ENABLED;
608 
609 	MOCK_SET(spdk_get_ticks, NVMF_AUTH_DEFAULT_KATO_US);
610 	poll_threads();
611 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ENABLED);
612 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_COMPLETED);
613 	nvmf_qpair_auth_destroy(&qpair);
614 	MOCK_SET(spdk_get_ticks, 0);
615 }
616 
617 static void
618 test_auth_failure1(void)
619 {
620 	union nvmf_c2h_msg rsp = {};
621 	struct spdk_nvmf_subsystem subsys = {};
622 	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys };
623 	struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr };
624 	struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp };
625 	struct spdk_nvmf_fabric_auth_recv_cmd cmd = {
626 		.fctype = SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV
627 	};
628 	struct spdk_nvme_cpl *cpl = &rsp.nvme_cpl;
629 	struct spdk_nvmf_qpair_auth *auth;
630 	struct spdk_nvmf_auth_failure *msg;
631 	uint8_t msgbuf[sizeof(*msg)];
632 	int rc;
633 
634 	msg = (void *)msgbuf;
635 	rc = nvmf_qpair_auth_init(&qpair);
636 	SPDK_CU_ASSERT_FATAL(rc == 0);
637 	auth = qpair.auth;
638 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
639 
640 	/* Check failure1 message fields */
641 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
642 	g_req_completed = false;
643 	auth->state = NVMF_QPAIR_AUTH_FAILURE1;
644 	auth->fail_reason = SPDK_NVMF_AUTH_FAILED;
645 	auth->tid = 8;
646 
647 	nvmf_auth_recv_exec(&req);
648 	CU_ASSERT(g_req_completed);
649 	CU_ASSERT_EQUAL(cpl->status.sct, 0);
650 	CU_ASSERT_EQUAL(cpl->status.sc, 0);
651 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_ERROR);
652 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
653 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
654 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
655 	CU_ASSERT_EQUAL(msg->t_id, 8);
656 	CU_ASSERT_EQUAL(msg->rc, SPDK_NVMF_AUTH_FAILURE);
657 	CU_ASSERT_EQUAL(msg->rce, SPDK_NVMF_AUTH_FAILED);
658 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
659 
660 	/* Do a receive while expecting an auth send command */
661 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
662 	g_req_completed = false;
663 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
664 	auth->fail_reason = 0;
665 
666 	nvmf_auth_recv_exec(&req);
667 	CU_ASSERT(g_req_completed);
668 	CU_ASSERT_EQUAL(cpl->status.sct, 0);
669 	CU_ASSERT_EQUAL(cpl->status.sc, 0);
670 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_ERROR);
671 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
672 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
673 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
674 	CU_ASSERT_EQUAL(msg->t_id, 8);
675 	CU_ASSERT_EQUAL(msg->rc, SPDK_NVMF_AUTH_FAILURE);
676 	CU_ASSERT_EQUAL(msg->rce, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
677 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
678 
679 	/* Do a receive but specify a buffer that's too small */
680 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
681 	g_req_completed = false;
682 	auth->state = NVMF_QPAIR_AUTH_FAILURE1;
683 	auth->fail_reason = SPDK_NVMF_AUTH_FAILED;
684 	req.iov[0].iov_len = cmd.al = req.length = sizeof(*msg) - 1;
685 
686 	nvmf_auth_recv_exec(&req);
687 	CU_ASSERT(g_req_completed);
688 	CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC);
689 	CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_INVALID_FIELD);
690 	CU_ASSERT_EQUAL(cpl->status.dnr, 1);
691 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
692 	req.iov[0].iov_len = cmd.al = req.length = sizeof(*msg);
693 
694 	nvmf_qpair_auth_destroy(&qpair);
695 }
696 
697 static void
698 test_auth_challenge(void)
699 {
700 	union nvmf_c2h_msg rsp = {};
701 	struct spdk_nvmf_subsystem subsys = { .mutex = PTHREAD_MUTEX_INITIALIZER };
702 	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys };
703 	struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr };
704 	struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp };
705 	struct spdk_nvmf_fabric_auth_recv_cmd cmd = {
706 		.fctype = SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV
707 	};
708 	struct spdk_nvmf_qpair_auth *auth;
709 	struct spdk_nvmf_dhchap_challenge *msg;
710 	struct spdk_nvmf_auth_failure *fail;
711 	uint8_t msgbuf[4096], cval[4096], dhv[4096];
712 	int rc;
713 
714 	msg = (void *)msgbuf;
715 	fail = (void *)msgbuf;
716 	rc = nvmf_qpair_auth_init(&qpair);
717 	SPDK_CU_ASSERT_FATAL(rc == 0);
718 	auth = qpair.auth;
719 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
720 
721 	/* Successfully receive a challenge message */
722 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
723 	g_req_completed = false;
724 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
725 	auth->dhgroup = SPDK_NVMF_DHCHAP_DHGROUP_NULL;
726 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
727 	g_rand_val = 0xa5;
728 	memset(cval, g_rand_val, sizeof(cval));
729 	auth->digest = SPDK_NVMF_DHCHAP_HASH_SHA384;
730 	auth->tid = 8;
731 
732 	nvmf_auth_recv_exec(&req);
733 	CU_ASSERT(g_req_completed);
734 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_REPLY);
735 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_DHCHAP);
736 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_DHCHAP_CHALLENGE);
737 	CU_ASSERT_EQUAL(msg->t_id, 8);
738 	CU_ASSERT_EQUAL(msg->hl, 48);
739 	CU_ASSERT_EQUAL(msg->hash_id, SPDK_NVMF_DHCHAP_HASH_SHA384);
740 	CU_ASSERT_EQUAL(msg->dhg_id, SPDK_NVMF_DHCHAP_DHGROUP_NULL);
741 	CU_ASSERT_EQUAL(msg->dhvlen, 0);
742 	CU_ASSERT_EQUAL(memcmp(msg->cval, cval, 48), 0);
743 	CU_ASSERT(msg->seqnum != 0);
744 
745 	/* Successfully receive a challenge message w/ a non-NULL dhgroup */
746 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
747 	g_req_completed = false;
748 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
749 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
750 	MOCK_SET(spdk_nvme_dhchap_generate_dhkey, (struct spdk_nvme_dhchap_dhkey *)0xdeadbeef);
751 	g_rand_val = 0xa5;
752 	g_dhv = 0xfe;
753 	g_dhvlen = 256;
754 	memset(cval, g_rand_val, sizeof(cval));
755 	memset(dhv, g_dhv, sizeof(dhv));
756 	auth->digest = SPDK_NVMF_DHCHAP_HASH_SHA384;
757 	auth->dhgroup = SPDK_NVMF_DHCHAP_DHGROUP_2048;
758 	auth->tid = 8;
759 
760 	nvmf_auth_recv_exec(&req);
761 	CU_ASSERT(g_req_completed);
762 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_REPLY);
763 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_DHCHAP);
764 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_DHCHAP_CHALLENGE);
765 	CU_ASSERT_EQUAL(msg->t_id, 8);
766 	CU_ASSERT_EQUAL(msg->hl, 48);
767 	CU_ASSERT_EQUAL(msg->hash_id, SPDK_NVMF_DHCHAP_HASH_SHA384);
768 	CU_ASSERT_EQUAL(msg->dhg_id, SPDK_NVMF_DHCHAP_DHGROUP_2048);
769 	CU_ASSERT_EQUAL(msg->dhvlen, g_dhvlen);
770 	CU_ASSERT_EQUAL(memcmp(msg->cval, cval, 48), 0);
771 	CU_ASSERT_EQUAL(memcmp(&msg->cval[48], dhv, g_dhvlen), 0);
772 	CU_ASSERT(msg->seqnum != 0);
773 
774 	/* Check RAND_bytes failure */
775 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
776 	g_req_completed = false;
777 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
778 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
779 	auth->digest = SPDK_NVMF_DHCHAP_HASH_SHA384;
780 	auth->tid = 8;
781 	MOCK_SET(RAND_bytes, -1);
782 
783 	nvmf_auth_recv_exec(&req);
784 	CU_ASSERT(g_req_completed);
785 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
786 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
787 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
788 	CU_ASSERT_EQUAL(fail->t_id, 8);
789 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
790 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_FAILED);
791 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
792 	MOCK_SET(RAND_bytes, 1);
793 
794 	/* Check spdk_nvme_dhchap_generate_dhkey failure */
795 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
796 	g_req_completed = false;
797 	MOCK_SET(spdk_nvme_dhchap_generate_dhkey, NULL);
798 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
799 	auth->tid = 8;
800 
801 	nvmf_auth_recv_exec(&req);
802 	CU_ASSERT(g_req_completed);
803 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
804 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
805 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
806 	CU_ASSERT_EQUAL(fail->t_id, 8);
807 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
808 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_FAILED);
809 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
810 
811 	/* Check spdk_nvme_dhchap_dhkey_get_pubkey failure */
812 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
813 	g_req_completed = false;
814 	MOCK_SET(spdk_nvme_dhchap_generate_dhkey, (struct spdk_nvme_dhchap_dhkey *)0xdeadbeef);
815 	MOCK_SET(spdk_nvme_dhchap_dhkey_get_pubkey, -EIO);
816 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
817 	auth->tid = 8;
818 
819 	nvmf_auth_recv_exec(&req);
820 	CU_ASSERT(g_req_completed);
821 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
822 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
823 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
824 	CU_ASSERT_EQUAL(fail->t_id, 8);
825 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
826 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_FAILED);
827 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
828 	MOCK_SET(spdk_nvme_dhchap_dhkey_get_pubkey, 0);
829 
830 	/* Check insufficient buffer size */
831 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
832 	g_req_completed = false;
833 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
834 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
835 	auth->tid = 8;
836 	cmd.al = req.length = req.iov[0].iov_len = sizeof(msg) + 47;
837 
838 	nvmf_auth_recv_exec(&req);
839 	CU_ASSERT(g_req_completed);
840 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
841 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
842 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
843 	CU_ASSERT_EQUAL(fail->t_id, 8);
844 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
845 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
846 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
847 	MOCK_CLEAR(spdk_nvme_dhchap_get_digest_length);
848 
849 	nvmf_qpair_auth_destroy(&qpair);
850 }
851 
852 static void
853 test_auth_reply(void)
854 {
855 	union nvmf_c2h_msg rsp = {};
856 	struct spdk_nvmf_subsystem subsys = {};
857 	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys };
858 	struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr };
859 	struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp };
860 	struct spdk_nvmf_fabric_auth_send_cmd cmd = {};
861 	struct spdk_nvmf_qpair_auth *auth;
862 	struct spdk_nvmf_dhchap_reply *msg;
863 	uint8_t hl = 48, msgbuf[4096];
864 	int rc;
865 
866 	msg = (void *)msgbuf;
867 	rc = nvmf_qpair_auth_init(&qpair);
868 	SPDK_CU_ASSERT_FATAL(rc == 0);
869 	ut_prep_send_cmd(&req, &cmd, msgbuf, sizeof(*msg) + 2 * hl);
870 	auth = qpair.auth;
871 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
872 	auth->tid = 8;
873 
874 	/* Execute a reply containing a correct response */
875 	g_req_completed = false;
876 	MOCK_SET(nvmf_subsystem_get_dhchap_key, (struct spdk_key *)0xdeadbeef);
877 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, hl);
878 	auth->state = NVMF_QPAIR_AUTH_REPLY;
879 	msg->auth_type = SPDK_NVMF_AUTH_TYPE_DHCHAP;
880 	msg->auth_id = SPDK_NVMF_AUTH_ID_DHCHAP_REPLY;
881 	msg->t_id = auth->tid;
882 	msg->hl = hl;
883 	msg->cvalid = 0;
884 	msg->dhvlen = 0;
885 	msg->seqnum = 0;
886 	memset(msg->rval, 0xa5, hl);
887 	g_rval = 0xa5;
888 
889 	nvmf_auth_send_exec(&req);
890 	CU_ASSERT(g_req_completed);
891 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_SUCCESS1);
892 
893 	/* Execute a reply while not in the REPLY state */
894 	g_req_completed = false;
895 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
896 
897 	nvmf_auth_send_exec(&req);
898 	CU_ASSERT(g_req_completed);
899 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
900 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
901 
902 	/* Bad message length (smaller than a base reply message) */
903 	g_req_completed = false;
904 	auth->state = NVMF_QPAIR_AUTH_REPLY;
905 	cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) - 1;
906 
907 	nvmf_auth_send_exec(&req);
908 	CU_ASSERT(g_req_completed);
909 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
910 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
911 
912 	/* Hash length mismatch */
913 	g_req_completed = false;
914 	auth->state = NVMF_QPAIR_AUTH_REPLY;
915 	msg->hl = 32;
916 
917 	nvmf_auth_send_exec(&req);
918 	CU_ASSERT(g_req_completed);
919 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
920 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
921 	msg->hl = hl;
922 
923 	/* Bad message length (smaller than size of msg + 2 * hl) */
924 	g_req_completed = false;
925 	auth->state = NVMF_QPAIR_AUTH_REPLY;
926 	cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + 2 * hl - 1;
927 
928 	nvmf_auth_send_exec(&req);
929 	CU_ASSERT(g_req_completed);
930 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
931 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
932 	cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + hl;
933 
934 	/* Bad message length (larger than size of msg + 2 * hl) */
935 	g_req_completed = false;
936 	auth->state = NVMF_QPAIR_AUTH_REPLY;
937 	cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + 2 * hl + 1;
938 
939 	nvmf_auth_send_exec(&req);
940 	CU_ASSERT(g_req_completed);
941 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
942 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
943 	cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + 2 * hl;
944 
945 	/* Transaction ID mismatch */
946 	g_req_completed = false;
947 	auth->state = NVMF_QPAIR_AUTH_REPLY;
948 	msg->t_id = auth->tid + 1;
949 
950 	nvmf_auth_send_exec(&req);
951 	CU_ASSERT(g_req_completed);
952 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
953 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
954 	msg->t_id = auth->tid;
955 
956 	/* Bad cvalid value */
957 	g_req_completed = false;
958 	auth->state = NVMF_QPAIR_AUTH_REPLY;
959 	msg->cvalid = 1;
960 
961 	nvmf_auth_send_exec(&req);
962 	CU_ASSERT(g_req_completed);
963 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
964 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
965 	msg->cvalid = 0;
966 
967 	/* Bad dhvlen (non-zero) */
968 	g_req_completed = false;
969 	auth->state = NVMF_QPAIR_AUTH_REPLY;
970 	msg->dhvlen = 1;
971 
972 	nvmf_auth_send_exec(&req);
973 	CU_ASSERT(g_req_completed);
974 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
975 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
976 	msg->dhvlen = 0;
977 
978 	/* Failure to get the key */
979 	g_req_completed = false;
980 	auth->state = NVMF_QPAIR_AUTH_REPLY;
981 	MOCK_SET(nvmf_subsystem_get_dhchap_key, NULL);
982 
983 	nvmf_auth_send_exec(&req);
984 	CU_ASSERT(g_req_completed);
985 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
986 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
987 	MOCK_SET(nvmf_subsystem_get_dhchap_key, (struct spdk_key *)0xdeadbeef);
988 
989 	/* Calculation failure */
990 	g_req_completed = false;
991 	auth->state = NVMF_QPAIR_AUTH_REPLY;
992 	MOCK_SET(spdk_nvme_dhchap_calculate, -EPERM);
993 
994 	nvmf_auth_send_exec(&req);
995 	CU_ASSERT(g_req_completed);
996 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
997 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
998 	MOCK_SET(spdk_nvme_dhchap_calculate, 0);
999 
1000 	/* Response mismatch */
1001 	g_req_completed = false;
1002 	auth->state = NVMF_QPAIR_AUTH_REPLY;
1003 	g_rval = 0x5a;
1004 
1005 	nvmf_auth_send_exec(&req);
1006 	CU_ASSERT(g_req_completed);
1007 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
1008 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
1009 	g_rval = 0xa5;
1010 
1011 	/* DH secret derivation failure */
1012 	g_req_completed = false;
1013 	auth->state = NVMF_QPAIR_AUTH_REPLY;
1014 	auth->dhgroup = SPDK_NVMF_DHCHAP_DHGROUP_2048;
1015 	MOCK_SET(spdk_nvme_dhchap_dhkey_derive_secret, -EIO);
1016 
1017 	nvmf_auth_send_exec(&req);
1018 	CU_ASSERT(g_req_completed);
1019 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
1020 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
1021 	MOCK_SET(spdk_nvme_dhchap_dhkey_derive_secret, 0);
1022 
1023 	/* Bad cvalid value */
1024 	g_req_completed = false;
1025 	auth->state = NVMF_QPAIR_AUTH_REPLY;
1026 	msg->cvalid = 2;
1027 
1028 	nvmf_auth_send_exec(&req);
1029 	CU_ASSERT(g_req_completed);
1030 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
1031 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
1032 
1033 	/* Bad cvalid/seqnum combination */
1034 	g_req_completed = false;
1035 	auth->state = NVMF_QPAIR_AUTH_REPLY;
1036 	msg->cvalid = 1;
1037 	msg->seqnum = 0;
1038 
1039 	nvmf_auth_send_exec(&req);
1040 	CU_ASSERT(g_req_completed);
1041 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
1042 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
1043 
1044 	/* Missing controller key */
1045 	g_req_completed = false;
1046 	auth->state = NVMF_QPAIR_AUTH_REPLY;
1047 	msg->cvalid = 1;
1048 	msg->seqnum = 1;
1049 	MOCK_ENQUEUE(nvmf_subsystem_get_dhchap_key, (struct spdk_key *)0xdeadbeef);
1050 	MOCK_ENQUEUE(nvmf_subsystem_get_dhchap_key, NULL);
1051 
1052 	nvmf_auth_send_exec(&req);
1053 	CU_ASSERT(g_req_completed);
1054 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
1055 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
1056 
1057 	/* Controller challenge calculation failure */
1058 	g_req_completed = false;
1059 	auth->state = NVMF_QPAIR_AUTH_REPLY;
1060 	msg->cvalid = 1;
1061 	msg->seqnum = 1;
1062 	MOCK_ENQUEUE(spdk_nvme_dhchap_calculate, 0);
1063 	MOCK_ENQUEUE(spdk_nvme_dhchap_calculate, -EIO);
1064 
1065 	nvmf_auth_send_exec(&req);
1066 	CU_ASSERT(g_req_completed);
1067 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
1068 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
1069 
1070 	nvmf_qpair_auth_destroy(&qpair);
1071 }
1072 
1073 static void
1074 test_auth_success1(void)
1075 {
1076 	union nvmf_c2h_msg rsp = {};
1077 	struct spdk_nvmf_subsystem subsys = {};
1078 	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys };
1079 	struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr };
1080 	struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp };
1081 	struct spdk_nvmf_fabric_auth_recv_cmd cmd = {
1082 		.fctype = SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV
1083 	};
1084 	struct spdk_nvmf_qpair_auth *auth;
1085 	struct spdk_nvmf_dhchap_success1 *msg;
1086 	struct spdk_nvmf_auth_failure *fail;
1087 	uint8_t msgbuf[sizeof(*msg) + 48];
1088 	int rc;
1089 
1090 	msg = (void *)msgbuf;
1091 	fail = (void *)msgbuf;
1092 	rc = nvmf_qpair_auth_init(&qpair);
1093 	SPDK_CU_ASSERT_FATAL(rc == 0);
1094 	auth = qpair.auth;
1095 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
1096 	auth->tid = 8;
1097 
1098 	/* Successfully receive a success message */
1099 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
1100 	g_req_completed = false;
1101 	auth->state = NVMF_QPAIR_AUTH_SUCCESS1;
1102 
1103 	nvmf_auth_recv_exec(&req);
1104 	CU_ASSERT(g_req_completed);
1105 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_COMPLETED);
1106 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ENABLED);
1107 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_DHCHAP);
1108 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS1);
1109 	CU_ASSERT_EQUAL(msg->t_id, 8);
1110 	CU_ASSERT_EQUAL(msg->hl, 48);
1111 	CU_ASSERT_EQUAL(msg->rvalid, 0);
1112 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
1113 
1114 	/* Successfully receive a success message w/ bidirectional authentication */
1115 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg) + 48);
1116 	g_req_completed = false;
1117 	auth->state = NVMF_QPAIR_AUTH_SUCCESS1;
1118 	auth->cvalid = true;
1119 	memset(auth->cval, 0xa5, 48);
1120 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
1121 
1122 	nvmf_auth_recv_exec(&req);
1123 	CU_ASSERT(g_req_completed);
1124 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_SUCCESS2);
1125 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_DHCHAP);
1126 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS1);
1127 	CU_ASSERT_EQUAL(msg->t_id, 8);
1128 	CU_ASSERT_EQUAL(msg->hl, 48);
1129 	CU_ASSERT_EQUAL(msg->rvalid, 1);
1130 	CU_ASSERT_EQUAL(memcmp(msg->rval, auth->cval, 48), 0);
1131 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
1132 	auth->cvalid = false;
1133 
1134 	/* Bad message length (smaller than success1 message) */
1135 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
1136 	g_req_completed = false;
1137 	auth->state = NVMF_QPAIR_AUTH_SUCCESS1;
1138 	cmd.al = req.iov[0].iov_len = req.length = sizeof(*msg) - 1;
1139 
1140 	nvmf_auth_recv_exec(&req);
1141 	CU_ASSERT(g_req_completed);
1142 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_ERROR);
1143 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
1144 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
1145 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
1146 	CU_ASSERT_EQUAL(fail->t_id, 8);
1147 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
1148 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
1149 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
1150 
1151 	/* Bad message length (smaller than msg + hl) */
1152 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
1153 	g_req_completed = false;
1154 	auth->state = NVMF_QPAIR_AUTH_SUCCESS1;
1155 	auth->cvalid = true;
1156 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
1157 	cmd.al = req.iov[0].iov_len = req.length = sizeof(*msg) + 47;
1158 
1159 	nvmf_auth_recv_exec(&req);
1160 	CU_ASSERT(g_req_completed);
1161 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_ERROR);
1162 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
1163 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
1164 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
1165 	CU_ASSERT_EQUAL(fail->t_id, 8);
1166 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
1167 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
1168 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
1169 	auth->cvalid = false;
1170 	cmd.al = req.iov[0].iov_len = req.length = sizeof(*msg);
1171 
1172 	nvmf_qpair_auth_destroy(&qpair);
1173 }
1174 
1175 int
1176 main(int argc, char **argv)
1177 {
1178 	CU_pSuite suite = NULL;
1179 	unsigned int num_failures;
1180 
1181 	CU_initialize_registry();
1182 	suite = CU_add_suite("nvmf_auth", NULL, NULL);
1183 	CU_ADD_TEST(suite, test_auth_send_recv_error);
1184 	CU_ADD_TEST(suite, test_auth_negotiate);
1185 	CU_ADD_TEST(suite, test_auth_timeout);
1186 	CU_ADD_TEST(suite, test_auth_failure1);
1187 	CU_ADD_TEST(suite, test_auth_challenge);
1188 	CU_ADD_TEST(suite, test_auth_reply);
1189 	CU_ADD_TEST(suite, test_auth_success1);
1190 
1191 	allocate_threads(1);
1192 	set_thread(0);
1193 
1194 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
1195 	CU_cleanup_registry();
1196 
1197 	free_threads();
1198 
1199 	return num_failures;
1200 }
1201