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