xref: /spdk/test/unit/lib/nvmf/auth.c/auth_ut.c (revision bf30e09abe1667ae2769aa367cde39c550bcac00)
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 
602 static void
603 test_auth_failure1(void)
604 {
605 	union nvmf_c2h_msg rsp = {};
606 	struct spdk_nvmf_subsystem subsys = {};
607 	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys };
608 	struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr };
609 	struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp };
610 	struct spdk_nvmf_fabric_auth_recv_cmd cmd = {
611 		.fctype = SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV
612 	};
613 	struct spdk_nvme_cpl *cpl = &rsp.nvme_cpl;
614 	struct spdk_nvmf_qpair_auth *auth;
615 	struct spdk_nvmf_auth_failure *msg;
616 	uint8_t msgbuf[sizeof(*msg)];
617 	int rc;
618 
619 	msg = (void *)msgbuf;
620 	rc = nvmf_qpair_auth_init(&qpair);
621 	SPDK_CU_ASSERT_FATAL(rc == 0);
622 	auth = qpair.auth;
623 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
624 
625 	/* Check failure1 message fields */
626 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
627 	g_req_completed = false;
628 	auth->state = NVMF_QPAIR_AUTH_FAILURE1;
629 	auth->fail_reason = SPDK_NVMF_AUTH_FAILED;
630 	auth->tid = 8;
631 
632 	nvmf_auth_recv_exec(&req);
633 	CU_ASSERT(g_req_completed);
634 	CU_ASSERT_EQUAL(cpl->status.sct, 0);
635 	CU_ASSERT_EQUAL(cpl->status.sc, 0);
636 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_ERROR);
637 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
638 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
639 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
640 	CU_ASSERT_EQUAL(msg->t_id, 8);
641 	CU_ASSERT_EQUAL(msg->rc, SPDK_NVMF_AUTH_FAILURE);
642 	CU_ASSERT_EQUAL(msg->rce, SPDK_NVMF_AUTH_FAILED);
643 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
644 
645 	/* Do a receive while expecting an auth send command */
646 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
647 	g_req_completed = false;
648 	auth->state = NVMF_QPAIR_AUTH_NEGOTIATE;
649 	auth->fail_reason = 0;
650 
651 	nvmf_auth_recv_exec(&req);
652 	CU_ASSERT(g_req_completed);
653 	CU_ASSERT_EQUAL(cpl->status.sct, 0);
654 	CU_ASSERT_EQUAL(cpl->status.sc, 0);
655 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_ERROR);
656 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
657 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
658 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
659 	CU_ASSERT_EQUAL(msg->t_id, 8);
660 	CU_ASSERT_EQUAL(msg->rc, SPDK_NVMF_AUTH_FAILURE);
661 	CU_ASSERT_EQUAL(msg->rce, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
662 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
663 
664 	/* Do a receive but specify a buffer that's too small */
665 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
666 	g_req_completed = false;
667 	auth->state = NVMF_QPAIR_AUTH_FAILURE1;
668 	auth->fail_reason = SPDK_NVMF_AUTH_FAILED;
669 	req.iov[0].iov_len = cmd.al = req.length = sizeof(*msg) - 1;
670 
671 	nvmf_auth_recv_exec(&req);
672 	CU_ASSERT(g_req_completed);
673 	CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC);
674 	CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_INVALID_FIELD);
675 	CU_ASSERT_EQUAL(cpl->status.dnr, 1);
676 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
677 	req.iov[0].iov_len = cmd.al = req.length = sizeof(*msg);
678 
679 	nvmf_qpair_auth_destroy(&qpair);
680 }
681 
682 static void
683 test_auth_challenge(void)
684 {
685 	union nvmf_c2h_msg rsp = {};
686 	struct spdk_nvmf_subsystem subsys = { .mutex = PTHREAD_MUTEX_INITIALIZER };
687 	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys };
688 	struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr };
689 	struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp };
690 	struct spdk_nvmf_fabric_auth_recv_cmd cmd = {
691 		.fctype = SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV
692 	};
693 	struct spdk_nvmf_qpair_auth *auth;
694 	struct spdk_nvmf_dhchap_challenge *msg;
695 	struct spdk_nvmf_auth_failure *fail;
696 	uint8_t msgbuf[4096], cval[4096], dhv[4096];
697 	int rc;
698 
699 	msg = (void *)msgbuf;
700 	fail = (void *)msgbuf;
701 	rc = nvmf_qpair_auth_init(&qpair);
702 	SPDK_CU_ASSERT_FATAL(rc == 0);
703 	auth = qpair.auth;
704 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
705 
706 	/* Successfully receive a challenge message */
707 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
708 	g_req_completed = false;
709 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
710 	auth->dhgroup = SPDK_NVMF_DHCHAP_DHGROUP_NULL;
711 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
712 	g_rand_val = 0xa5;
713 	memset(cval, g_rand_val, sizeof(cval));
714 	auth->digest = SPDK_NVMF_DHCHAP_HASH_SHA384;
715 	auth->tid = 8;
716 
717 	nvmf_auth_recv_exec(&req);
718 	CU_ASSERT(g_req_completed);
719 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_REPLY);
720 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_DHCHAP);
721 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_DHCHAP_CHALLENGE);
722 	CU_ASSERT_EQUAL(msg->t_id, 8);
723 	CU_ASSERT_EQUAL(msg->hl, 48);
724 	CU_ASSERT_EQUAL(msg->hash_id, SPDK_NVMF_DHCHAP_HASH_SHA384);
725 	CU_ASSERT_EQUAL(msg->dhg_id, SPDK_NVMF_DHCHAP_DHGROUP_NULL);
726 	CU_ASSERT_EQUAL(msg->dhvlen, 0);
727 	CU_ASSERT_EQUAL(memcmp(msg->cval, cval, 48), 0);
728 	CU_ASSERT(msg->seqnum != 0);
729 
730 	/* Successfully receive a challenge message w/ a non-NULL dhgroup */
731 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
732 	g_req_completed = false;
733 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
734 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
735 	MOCK_SET(spdk_nvme_dhchap_generate_dhkey, (struct spdk_nvme_dhchap_dhkey *)0xdeadbeef);
736 	g_rand_val = 0xa5;
737 	g_dhv = 0xfe;
738 	g_dhvlen = 256;
739 	memset(cval, g_rand_val, sizeof(cval));
740 	memset(dhv, g_dhv, sizeof(dhv));
741 	auth->digest = SPDK_NVMF_DHCHAP_HASH_SHA384;
742 	auth->dhgroup = SPDK_NVMF_DHCHAP_DHGROUP_2048;
743 	auth->tid = 8;
744 
745 	nvmf_auth_recv_exec(&req);
746 	CU_ASSERT(g_req_completed);
747 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_REPLY);
748 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_DHCHAP);
749 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_DHCHAP_CHALLENGE);
750 	CU_ASSERT_EQUAL(msg->t_id, 8);
751 	CU_ASSERT_EQUAL(msg->hl, 48);
752 	CU_ASSERT_EQUAL(msg->hash_id, SPDK_NVMF_DHCHAP_HASH_SHA384);
753 	CU_ASSERT_EQUAL(msg->dhg_id, SPDK_NVMF_DHCHAP_DHGROUP_2048);
754 	CU_ASSERT_EQUAL(msg->dhvlen, g_dhvlen);
755 	CU_ASSERT_EQUAL(memcmp(msg->cval, cval, 48), 0);
756 	CU_ASSERT_EQUAL(memcmp(&msg->cval[48], dhv, g_dhvlen), 0);
757 	CU_ASSERT(msg->seqnum != 0);
758 
759 	/* Check RAND_bytes failure */
760 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
761 	g_req_completed = false;
762 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
763 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
764 	auth->digest = SPDK_NVMF_DHCHAP_HASH_SHA384;
765 	auth->tid = 8;
766 	MOCK_SET(RAND_bytes, -1);
767 
768 	nvmf_auth_recv_exec(&req);
769 	CU_ASSERT(g_req_completed);
770 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
771 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
772 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
773 	CU_ASSERT_EQUAL(fail->t_id, 8);
774 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
775 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_FAILED);
776 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
777 	MOCK_SET(RAND_bytes, 1);
778 
779 	/* Check spdk_nvme_dhchap_generate_dhkey failure */
780 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
781 	g_req_completed = false;
782 	MOCK_SET(spdk_nvme_dhchap_generate_dhkey, NULL);
783 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
784 	auth->tid = 8;
785 
786 	nvmf_auth_recv_exec(&req);
787 	CU_ASSERT(g_req_completed);
788 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
789 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
790 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
791 	CU_ASSERT_EQUAL(fail->t_id, 8);
792 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
793 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_FAILED);
794 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
795 
796 	/* Check spdk_nvme_dhchap_dhkey_get_pubkey failure */
797 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
798 	g_req_completed = false;
799 	MOCK_SET(spdk_nvme_dhchap_generate_dhkey, (struct spdk_nvme_dhchap_dhkey *)0xdeadbeef);
800 	MOCK_SET(spdk_nvme_dhchap_dhkey_get_pubkey, -EIO);
801 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
802 	auth->tid = 8;
803 
804 	nvmf_auth_recv_exec(&req);
805 	CU_ASSERT(g_req_completed);
806 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
807 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
808 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
809 	CU_ASSERT_EQUAL(fail->t_id, 8);
810 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
811 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_FAILED);
812 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
813 	MOCK_SET(spdk_nvme_dhchap_dhkey_get_pubkey, 0);
814 
815 	/* Check insufficient buffer size */
816 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf));
817 	g_req_completed = false;
818 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
819 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
820 	auth->tid = 8;
821 	cmd.al = req.length = req.iov[0].iov_len = sizeof(msg) + 47;
822 
823 	nvmf_auth_recv_exec(&req);
824 	CU_ASSERT(g_req_completed);
825 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
826 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
827 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
828 	CU_ASSERT_EQUAL(fail->t_id, 8);
829 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
830 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
831 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
832 	MOCK_CLEAR(spdk_nvme_dhchap_get_digest_length);
833 
834 	nvmf_qpair_auth_destroy(&qpair);
835 }
836 
837 static void
838 test_auth_reply(void)
839 {
840 	union nvmf_c2h_msg rsp = {};
841 	struct spdk_nvmf_subsystem subsys = {};
842 	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys };
843 	struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr };
844 	struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp };
845 	struct spdk_nvmf_fabric_auth_send_cmd cmd = {};
846 	struct spdk_nvmf_qpair_auth *auth;
847 	struct spdk_nvmf_dhchap_reply *msg;
848 	uint8_t hl = 48, msgbuf[4096];
849 	int rc;
850 
851 	msg = (void *)msgbuf;
852 	rc = nvmf_qpair_auth_init(&qpair);
853 	SPDK_CU_ASSERT_FATAL(rc == 0);
854 	ut_prep_send_cmd(&req, &cmd, msgbuf, sizeof(*msg) + 2 * hl);
855 	auth = qpair.auth;
856 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
857 	auth->tid = 8;
858 
859 	/* Execute a reply containing a correct response */
860 	g_req_completed = false;
861 	MOCK_SET(nvmf_subsystem_get_dhchap_key, (struct spdk_key *)0xdeadbeef);
862 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, hl);
863 	auth->state = NVMF_QPAIR_AUTH_REPLY;
864 	msg->auth_type = SPDK_NVMF_AUTH_TYPE_DHCHAP;
865 	msg->auth_id = SPDK_NVMF_AUTH_ID_DHCHAP_REPLY;
866 	msg->t_id = auth->tid;
867 	msg->hl = hl;
868 	msg->cvalid = 0;
869 	msg->dhvlen = 0;
870 	msg->seqnum = 0;
871 	memset(msg->rval, 0xa5, hl);
872 	g_rval = 0xa5;
873 
874 	nvmf_auth_send_exec(&req);
875 	CU_ASSERT(g_req_completed);
876 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_SUCCESS1);
877 
878 	/* Execute a reply while not in the REPLY state */
879 	g_req_completed = false;
880 	auth->state = NVMF_QPAIR_AUTH_CHALLENGE;
881 
882 	nvmf_auth_send_exec(&req);
883 	CU_ASSERT(g_req_completed);
884 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
885 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE);
886 
887 	/* Bad message length (smaller than a base reply message) */
888 	g_req_completed = false;
889 	auth->state = NVMF_QPAIR_AUTH_REPLY;
890 	cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) - 1;
891 
892 	nvmf_auth_send_exec(&req);
893 	CU_ASSERT(g_req_completed);
894 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
895 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
896 
897 	/* Hash length mismatch */
898 	g_req_completed = false;
899 	auth->state = NVMF_QPAIR_AUTH_REPLY;
900 	msg->hl = 32;
901 
902 	nvmf_auth_send_exec(&req);
903 	CU_ASSERT(g_req_completed);
904 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
905 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
906 	msg->hl = hl;
907 
908 	/* Bad message length (smaller than size of msg + 2 * hl) */
909 	g_req_completed = false;
910 	auth->state = NVMF_QPAIR_AUTH_REPLY;
911 	cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + 2 * hl - 1;
912 
913 	nvmf_auth_send_exec(&req);
914 	CU_ASSERT(g_req_completed);
915 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
916 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
917 	cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + hl;
918 
919 	/* Bad message length (larger than size of msg + 2 * hl) */
920 	g_req_completed = false;
921 	auth->state = NVMF_QPAIR_AUTH_REPLY;
922 	cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + 2 * hl + 1;
923 
924 	nvmf_auth_send_exec(&req);
925 	CU_ASSERT(g_req_completed);
926 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
927 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
928 	cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + 2 * hl;
929 
930 	/* Transaction ID mismatch */
931 	g_req_completed = false;
932 	auth->state = NVMF_QPAIR_AUTH_REPLY;
933 	msg->t_id = auth->tid + 1;
934 
935 	nvmf_auth_send_exec(&req);
936 	CU_ASSERT(g_req_completed);
937 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
938 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
939 	msg->t_id = auth->tid;
940 
941 	/* Bad cvalid value */
942 	g_req_completed = false;
943 	auth->state = NVMF_QPAIR_AUTH_REPLY;
944 	msg->cvalid = 1;
945 
946 	nvmf_auth_send_exec(&req);
947 	CU_ASSERT(g_req_completed);
948 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
949 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
950 	msg->cvalid = 0;
951 
952 	/* Bad dhvlen (non-zero) */
953 	g_req_completed = false;
954 	auth->state = NVMF_QPAIR_AUTH_REPLY;
955 	msg->dhvlen = 1;
956 
957 	nvmf_auth_send_exec(&req);
958 	CU_ASSERT(g_req_completed);
959 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
960 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
961 	msg->dhvlen = 0;
962 
963 	/* Failure to get the key */
964 	g_req_completed = false;
965 	auth->state = NVMF_QPAIR_AUTH_REPLY;
966 	MOCK_SET(nvmf_subsystem_get_dhchap_key, NULL);
967 
968 	nvmf_auth_send_exec(&req);
969 	CU_ASSERT(g_req_completed);
970 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
971 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
972 	MOCK_SET(nvmf_subsystem_get_dhchap_key, (struct spdk_key *)0xdeadbeef);
973 
974 	/* Calculation failure */
975 	g_req_completed = false;
976 	auth->state = NVMF_QPAIR_AUTH_REPLY;
977 	MOCK_SET(spdk_nvme_dhchap_calculate, -EPERM);
978 
979 	nvmf_auth_send_exec(&req);
980 	CU_ASSERT(g_req_completed);
981 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
982 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
983 	MOCK_SET(spdk_nvme_dhchap_calculate, 0);
984 
985 	/* Response mismatch */
986 	g_req_completed = false;
987 	auth->state = NVMF_QPAIR_AUTH_REPLY;
988 	g_rval = 0x5a;
989 
990 	nvmf_auth_send_exec(&req);
991 	CU_ASSERT(g_req_completed);
992 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
993 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
994 	g_rval = 0xa5;
995 
996 	/* DH secret derivation failure */
997 	g_req_completed = false;
998 	auth->state = NVMF_QPAIR_AUTH_REPLY;
999 	auth->dhgroup = SPDK_NVMF_DHCHAP_DHGROUP_2048;
1000 	MOCK_SET(spdk_nvme_dhchap_dhkey_derive_secret, -EIO);
1001 
1002 	nvmf_auth_send_exec(&req);
1003 	CU_ASSERT(g_req_completed);
1004 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
1005 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
1006 	MOCK_SET(spdk_nvme_dhchap_dhkey_derive_secret, 0);
1007 
1008 	/* Bad cvalid value */
1009 	g_req_completed = false;
1010 	auth->state = NVMF_QPAIR_AUTH_REPLY;
1011 	msg->cvalid = 2;
1012 
1013 	nvmf_auth_send_exec(&req);
1014 	CU_ASSERT(g_req_completed);
1015 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
1016 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
1017 
1018 	/* Bad cvalid/seqnum combination */
1019 	g_req_completed = false;
1020 	auth->state = NVMF_QPAIR_AUTH_REPLY;
1021 	msg->cvalid = 1;
1022 	msg->seqnum = 0;
1023 
1024 	nvmf_auth_send_exec(&req);
1025 	CU_ASSERT(g_req_completed);
1026 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
1027 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
1028 
1029 	/* Missing controller key */
1030 	g_req_completed = false;
1031 	auth->state = NVMF_QPAIR_AUTH_REPLY;
1032 	msg->cvalid = 1;
1033 	msg->seqnum = 1;
1034 	MOCK_ENQUEUE(nvmf_subsystem_get_dhchap_key, (struct spdk_key *)0xdeadbeef);
1035 	MOCK_ENQUEUE(nvmf_subsystem_get_dhchap_key, NULL);
1036 
1037 	nvmf_auth_send_exec(&req);
1038 	CU_ASSERT(g_req_completed);
1039 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
1040 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
1041 
1042 	/* Controller challenge calculation failure */
1043 	g_req_completed = false;
1044 	auth->state = NVMF_QPAIR_AUTH_REPLY;
1045 	msg->cvalid = 1;
1046 	msg->seqnum = 1;
1047 	MOCK_ENQUEUE(spdk_nvme_dhchap_calculate, 0);
1048 	MOCK_ENQUEUE(spdk_nvme_dhchap_calculate, -EIO);
1049 
1050 	nvmf_auth_send_exec(&req);
1051 	CU_ASSERT(g_req_completed);
1052 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1);
1053 	CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED);
1054 
1055 	nvmf_qpair_auth_destroy(&qpair);
1056 }
1057 
1058 static void
1059 test_auth_success1(void)
1060 {
1061 	union nvmf_c2h_msg rsp = {};
1062 	struct spdk_nvmf_subsystem subsys = {};
1063 	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys };
1064 	struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr };
1065 	struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp };
1066 	struct spdk_nvmf_fabric_auth_recv_cmd cmd = {
1067 		.fctype = SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV
1068 	};
1069 	struct spdk_nvmf_qpair_auth *auth;
1070 	struct spdk_nvmf_dhchap_success1 *msg;
1071 	struct spdk_nvmf_auth_failure *fail;
1072 	uint8_t msgbuf[sizeof(*msg) + 48];
1073 	int rc;
1074 
1075 	msg = (void *)msgbuf;
1076 	fail = (void *)msgbuf;
1077 	rc = nvmf_qpair_auth_init(&qpair);
1078 	SPDK_CU_ASSERT_FATAL(rc == 0);
1079 	auth = qpair.auth;
1080 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
1081 	auth->tid = 8;
1082 
1083 	/* Successfully receive a success message */
1084 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
1085 	g_req_completed = false;
1086 	auth->state = NVMF_QPAIR_AUTH_SUCCESS1;
1087 
1088 	nvmf_auth_recv_exec(&req);
1089 	CU_ASSERT(g_req_completed);
1090 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_COMPLETED);
1091 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ENABLED);
1092 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_DHCHAP);
1093 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS1);
1094 	CU_ASSERT_EQUAL(msg->t_id, 8);
1095 	CU_ASSERT_EQUAL(msg->hl, 48);
1096 	CU_ASSERT_EQUAL(msg->rvalid, 0);
1097 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
1098 
1099 	/* Successfully receive a success message w/ bidirectional authentication */
1100 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg) + 48);
1101 	g_req_completed = false;
1102 	auth->state = NVMF_QPAIR_AUTH_SUCCESS1;
1103 	auth->cvalid = true;
1104 	memset(auth->cval, 0xa5, 48);
1105 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
1106 
1107 	nvmf_auth_recv_exec(&req);
1108 	CU_ASSERT(g_req_completed);
1109 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_SUCCESS2);
1110 	CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_DHCHAP);
1111 	CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS1);
1112 	CU_ASSERT_EQUAL(msg->t_id, 8);
1113 	CU_ASSERT_EQUAL(msg->hl, 48);
1114 	CU_ASSERT_EQUAL(msg->rvalid, 1);
1115 	CU_ASSERT_EQUAL(memcmp(msg->rval, auth->cval, 48), 0);
1116 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
1117 	auth->cvalid = false;
1118 
1119 	/* Bad message length (smaller than success1 message) */
1120 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
1121 	g_req_completed = false;
1122 	auth->state = NVMF_QPAIR_AUTH_SUCCESS1;
1123 	cmd.al = req.iov[0].iov_len = req.length = sizeof(*msg) - 1;
1124 
1125 	nvmf_auth_recv_exec(&req);
1126 	CU_ASSERT(g_req_completed);
1127 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_ERROR);
1128 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
1129 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
1130 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
1131 	CU_ASSERT_EQUAL(fail->t_id, 8);
1132 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
1133 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
1134 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
1135 
1136 	/* Bad message length (smaller than msg + hl) */
1137 	ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg));
1138 	g_req_completed = false;
1139 	auth->state = NVMF_QPAIR_AUTH_SUCCESS1;
1140 	auth->cvalid = true;
1141 	MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48);
1142 	cmd.al = req.iov[0].iov_len = req.length = sizeof(*msg) + 47;
1143 
1144 	nvmf_auth_recv_exec(&req);
1145 	CU_ASSERT(g_req_completed);
1146 	CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_ERROR);
1147 	CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR);
1148 	CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE);
1149 	CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1);
1150 	CU_ASSERT_EQUAL(fail->t_id, 8);
1151 	CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE);
1152 	CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD);
1153 	qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING;
1154 	auth->cvalid = false;
1155 	cmd.al = req.iov[0].iov_len = req.length = sizeof(*msg);
1156 
1157 	nvmf_qpair_auth_destroy(&qpair);
1158 }
1159 
1160 int
1161 main(int argc, char **argv)
1162 {
1163 	CU_pSuite suite = NULL;
1164 	unsigned int num_failures;
1165 
1166 	CU_initialize_registry();
1167 	suite = CU_add_suite("nvmf_auth", NULL, NULL);
1168 	CU_ADD_TEST(suite, test_auth_send_recv_error);
1169 	CU_ADD_TEST(suite, test_auth_negotiate);
1170 	CU_ADD_TEST(suite, test_auth_timeout);
1171 	CU_ADD_TEST(suite, test_auth_failure1);
1172 	CU_ADD_TEST(suite, test_auth_challenge);
1173 	CU_ADD_TEST(suite, test_auth_reply);
1174 	CU_ADD_TEST(suite, test_auth_success1);
1175 
1176 	allocate_threads(1);
1177 	set_thread(0);
1178 
1179 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
1180 	CU_cleanup_registry();
1181 
1182 	free_threads();
1183 
1184 	return num_failures;
1185 }
1186