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_ctrlr ctrlr = { .subsys = &subsys }; 262 struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr }; 263 struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp }; 264 struct spdk_nvmf_fabric_auth_send_cmd cmd = {}; 265 struct spdk_nvmf_qpair_auth *auth; 266 struct spdk_nvmf_auth_negotiate *msg; 267 struct spdk_nvmf_auth_descriptor *desc; 268 uint8_t msgbuf[4096]; 269 int rc; 270 271 msg = (void *)msgbuf; 272 rc = nvmf_qpair_auth_init(&qpair); 273 SPDK_CU_ASSERT_FATAL(rc == 0); 274 ut_prep_send_cmd(&req, &cmd, msgbuf, sizeof(*msg) + sizeof(*desc)); 275 auth = qpair.auth; 276 277 /* Successful negotiation */ 278 g_req_completed = false; 279 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 280 msg->auth_type = SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE; 281 msg->auth_id = SPDK_NVMF_AUTH_ID_NEGOTIATE; 282 msg->sc_c = SPDK_NVMF_AUTH_SCC_DISABLED; 283 msg->napd = 1; 284 desc = &msg->descriptors[0]; 285 desc->auth_id = SPDK_NVMF_AUTH_TYPE_DHCHAP; 286 desc->halen = 3; 287 desc->hash_id_list[0] = SPDK_NVMF_DHCHAP_HASH_SHA256; 288 desc->hash_id_list[1] = SPDK_NVMF_DHCHAP_HASH_SHA384; 289 desc->hash_id_list[2] = SPDK_NVMF_DHCHAP_HASH_SHA512; 290 desc->dhlen = 6; 291 desc->dhg_id_list[0] = SPDK_NVMF_DHCHAP_DHGROUP_NULL; 292 desc->dhg_id_list[1] = SPDK_NVMF_DHCHAP_DHGROUP_2048; 293 desc->dhg_id_list[2] = SPDK_NVMF_DHCHAP_DHGROUP_3072; 294 desc->dhg_id_list[3] = SPDK_NVMF_DHCHAP_DHGROUP_4096; 295 desc->dhg_id_list[4] = SPDK_NVMF_DHCHAP_DHGROUP_6144; 296 desc->dhg_id_list[5] = SPDK_NVMF_DHCHAP_DHGROUP_8192; 297 298 nvmf_auth_send_exec(&req); 299 CU_ASSERT(g_req_completed); 300 CU_ASSERT_EQUAL(auth->digest, SPDK_NVMF_DHCHAP_HASH_SHA512); 301 CU_ASSERT_EQUAL(auth->dhgroup, SPDK_NVMF_DHCHAP_DHGROUP_8192); 302 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_CHALLENGE); 303 304 /* Invalid auth state */ 305 g_req_completed = false; 306 auth->state = NVMF_QPAIR_AUTH_ERROR; 307 auth->digest = -1; 308 309 nvmf_auth_send_exec(&req); 310 CU_ASSERT(g_req_completed); 311 CU_ASSERT_EQUAL(auth->digest, -1); 312 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 313 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 314 315 /* scc mismatch */ 316 g_req_completed = false; 317 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 318 msg->sc_c = SPDK_NVMF_AUTH_SCC_TLS; 319 320 nvmf_auth_send_exec(&req); 321 CU_ASSERT(g_req_completed); 322 CU_ASSERT_EQUAL(auth->digest, -1); 323 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 324 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_SCC_MISMATCH); 325 msg->sc_c = SPDK_NVMF_AUTH_SCC_DISABLED; 326 327 /* Missing DH-HMAC-CHAP protocol (napd=0) */ 328 g_req_completed = false; 329 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 330 req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg); 331 msg->napd = 0; 332 333 nvmf_auth_send_exec(&req); 334 CU_ASSERT(g_req_completed); 335 CU_ASSERT_EQUAL(auth->digest, -1); 336 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 337 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_PROTOCOL_UNUSABLE); 338 req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg) + sizeof(*desc); 339 msg->napd = 1; 340 341 /* Missing DH-HMAC-CHAP protocol */ 342 g_req_completed = false; 343 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 344 desc->auth_id = SPDK_NVMF_AUTH_TYPE_DHCHAP + 1; 345 346 nvmf_auth_send_exec(&req); 347 CU_ASSERT(g_req_completed); 348 CU_ASSERT_EQUAL(auth->digest, -1); 349 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 350 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_PROTOCOL_UNUSABLE); 351 desc->auth_id = SPDK_NVMF_AUTH_TYPE_DHCHAP; 352 353 /* No valid digests (halen=0) */ 354 g_req_completed = false; 355 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 356 desc->halen = 0; 357 358 nvmf_auth_send_exec(&req); 359 CU_ASSERT(g_req_completed); 360 CU_ASSERT_EQUAL(auth->digest, -1); 361 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 362 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_HASH_UNUSABLE); 363 364 /* No valid digests */ 365 g_req_completed = false; 366 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 367 desc->hash_id_list[0] = SPDK_NVMF_DHCHAP_HASH_SHA512 + 1; 368 desc->hash_id_list[1] = SPDK_NVMF_DHCHAP_HASH_SHA512 + 2; 369 desc->hash_id_list[2] = SPDK_NVMF_DHCHAP_HASH_SHA512 + 3; 370 desc->halen = 3; 371 372 nvmf_auth_send_exec(&req); 373 CU_ASSERT(g_req_completed); 374 CU_ASSERT_EQUAL(auth->digest, -1); 375 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 376 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_HASH_UNUSABLE); 377 desc->hash_id_list[0] = SPDK_NVMF_DHCHAP_HASH_SHA256; 378 desc->hash_id_list[1] = SPDK_NVMF_DHCHAP_HASH_SHA384; 379 desc->hash_id_list[2] = SPDK_NVMF_DHCHAP_HASH_SHA512; 380 381 /* No valid dhgroups (dhlen=0) */ 382 g_req_completed = false; 383 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 384 desc->dhlen = 0; 385 386 nvmf_auth_send_exec(&req); 387 CU_ASSERT(g_req_completed); 388 CU_ASSERT_EQUAL(auth->digest, -1); 389 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 390 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_DHGROUP_UNUSABLE); 391 392 /* No valid dhgroups */ 393 g_req_completed = false; 394 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 395 desc->dhlen = 2; 396 desc->dhg_id_list[0] = SPDK_NVMF_DHCHAP_DHGROUP_8192 + 1; 397 desc->dhg_id_list[1] = SPDK_NVMF_DHCHAP_DHGROUP_8192 + 2; 398 399 nvmf_auth_send_exec(&req); 400 CU_ASSERT(g_req_completed); 401 CU_ASSERT_EQUAL(auth->digest, -1); 402 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 403 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_DHGROUP_UNUSABLE); 404 desc->dhg_id_list[0] = SPDK_NVMF_DHCHAP_DHGROUP_NULL; 405 desc->dhg_id_list[1] = SPDK_NVMF_DHCHAP_DHGROUP_2048; 406 desc->dhlen = 6; 407 408 /* Bad halen value */ 409 g_req_completed = false; 410 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 411 desc->halen = 255; 412 413 nvmf_auth_send_exec(&req); 414 CU_ASSERT(g_req_completed); 415 CU_ASSERT_EQUAL(auth->digest, -1); 416 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 417 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 418 desc->halen = 3; 419 420 /* Bad dhlen value */ 421 g_req_completed = false; 422 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 423 desc->dhlen = 255; 424 425 nvmf_auth_send_exec(&req); 426 CU_ASSERT(g_req_completed); 427 CU_ASSERT_EQUAL(auth->digest, -1); 428 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 429 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 430 desc->dhlen = 6; 431 432 /* Invalid request length (too small) */ 433 g_req_completed = false; 434 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 435 req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg) - 1; 436 437 nvmf_auth_send_exec(&req); 438 CU_ASSERT(g_req_completed); 439 CU_ASSERT_EQUAL(auth->digest, -1); 440 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 441 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 442 443 /* Invalid request length (too small) */ 444 g_req_completed = false; 445 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 446 req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg); 447 448 nvmf_auth_send_exec(&req); 449 CU_ASSERT(g_req_completed); 450 CU_ASSERT_EQUAL(auth->digest, -1); 451 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 452 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 453 454 /* Invalid request length (too small) */ 455 g_req_completed = false; 456 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 457 req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg) + sizeof(*desc) - 1; 458 459 nvmf_auth_send_exec(&req); 460 CU_ASSERT(g_req_completed); 461 CU_ASSERT_EQUAL(auth->digest, -1); 462 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 463 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 464 465 /* Invalid request length (too large) */ 466 g_req_completed = false; 467 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 468 req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg) + sizeof(*desc) + 1; 469 470 nvmf_auth_send_exec(&req); 471 CU_ASSERT(g_req_completed); 472 CU_ASSERT_EQUAL(auth->digest, -1); 473 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 474 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 475 req.length = cmd.tl = req.iov[0].iov_len = sizeof(*msg) + sizeof(*desc); 476 477 nvmf_qpair_auth_destroy(&qpair); 478 } 479 480 static void 481 test_auth_timeout(void) 482 { 483 union nvmf_c2h_msg rsp = {}; 484 struct spdk_nvmf_subsystem subsys = {}; 485 struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys }; 486 struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr }; 487 struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp }; 488 struct spdk_nvmf_fabric_auth_send_cmd cmd = {}; 489 struct spdk_nvmf_qpair_auth *auth; 490 struct spdk_nvmf_auth_negotiate *msg; 491 struct spdk_nvmf_auth_descriptor *desc; 492 uint8_t msgbuf[4096]; 493 int rc; 494 495 msg = (void *)msgbuf; 496 ut_prep_send_cmd(&req, &cmd, msgbuf, sizeof(*msg) + sizeof(*desc)); 497 MOCK_SET(spdk_get_ticks_hz, 1000 * 1000); 498 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 499 500 /* Check that a timeout is correctly detected and qpair is disconnected */ 501 rc = nvmf_qpair_auth_init(&qpair); 502 SPDK_CU_ASSERT_FATAL(rc == 0); 503 MOCK_SET(spdk_get_ticks, NVMF_AUTH_DEFAULT_KATO_US - 1); 504 poll_threads(); 505 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_AUTHENTICATING); 506 MOCK_SET(spdk_get_ticks, NVMF_AUTH_DEFAULT_KATO_US); 507 poll_threads(); 508 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR); 509 nvmf_qpair_auth_destroy(&qpair); 510 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 511 MOCK_SET(spdk_get_ticks, 0); 512 513 /* Check a case where a non-zero kato is set in controller features */ 514 ctrlr.feat.keep_alive_timer.bits.kato = 10 * 1000; 515 rc = nvmf_qpair_auth_init(&qpair); 516 SPDK_CU_ASSERT_FATAL(rc == 0); 517 MOCK_SET(spdk_get_ticks, 10 * 1000 * 1000 - 1); 518 poll_threads(); 519 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_AUTHENTICATING); 520 MOCK_SET(spdk_get_ticks, 10 * 1000 * 1000); 521 poll_threads(); 522 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR); 523 nvmf_qpair_auth_destroy(&qpair); 524 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 525 ctrlr.feat.keep_alive_timer.bits.kato = 0; 526 MOCK_SET(spdk_get_ticks, 0); 527 528 /* Check that reception of a command rearms the timeout poller */ 529 rc = nvmf_qpair_auth_init(&qpair); 530 SPDK_CU_ASSERT_FATAL(rc == 0); 531 auth = qpair.auth; 532 533 MOCK_SET(spdk_get_ticks, NVMF_AUTH_DEFAULT_KATO_US / 2); 534 g_req_completed = false; 535 msg->auth_type = SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE; 536 msg->auth_id = SPDK_NVMF_AUTH_ID_NEGOTIATE; 537 msg->sc_c = SPDK_NVMF_AUTH_SCC_DISABLED; 538 msg->napd = 1; 539 desc = &msg->descriptors[0]; 540 desc->auth_id = SPDK_NVMF_AUTH_TYPE_DHCHAP; 541 desc->halen = 1; 542 desc->hash_id_list[0] = SPDK_NVMF_DHCHAP_HASH_SHA256; 543 desc->dhlen = 1; 544 desc->dhg_id_list[0] = SPDK_NVMF_DHCHAP_DHGROUP_NULL; 545 546 nvmf_auth_send_exec(&req); 547 CU_ASSERT(g_req_completed); 548 CU_ASSERT_EQUAL(auth->digest, SPDK_NVMF_DHCHAP_HASH_SHA256); 549 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_CHALLENGE); 550 551 MOCK_SET(spdk_get_ticks, NVMF_AUTH_DEFAULT_KATO_US); 552 poll_threads(); 553 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_AUTHENTICATING); 554 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_CHALLENGE); 555 556 MOCK_SET(spdk_get_ticks, NVMF_AUTH_DEFAULT_KATO_US + NVMF_AUTH_DEFAULT_KATO_US / 2); 557 poll_threads(); 558 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR); 559 nvmf_qpair_auth_destroy(&qpair); 560 MOCK_SET(spdk_get_ticks, 0); 561 } 562 563 static void 564 test_auth_failure1(void) 565 { 566 union nvmf_c2h_msg rsp = {}; 567 struct spdk_nvmf_subsystem subsys = {}; 568 struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys }; 569 struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr }; 570 struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp }; 571 struct spdk_nvmf_fabric_auth_recv_cmd cmd = { 572 .fctype = SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV 573 }; 574 struct spdk_nvme_cpl *cpl = &rsp.nvme_cpl; 575 struct spdk_nvmf_qpair_auth *auth; 576 struct spdk_nvmf_auth_failure *msg; 577 uint8_t msgbuf[sizeof(*msg)]; 578 int rc; 579 580 msg = (void *)msgbuf; 581 rc = nvmf_qpair_auth_init(&qpair); 582 SPDK_CU_ASSERT_FATAL(rc == 0); 583 auth = qpair.auth; 584 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 585 586 /* Check failure1 message fields */ 587 ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg)); 588 g_req_completed = false; 589 auth->state = NVMF_QPAIR_AUTH_FAILURE1; 590 auth->fail_reason = SPDK_NVMF_AUTH_FAILED; 591 auth->tid = 8; 592 593 nvmf_auth_recv_exec(&req); 594 CU_ASSERT(g_req_completed); 595 CU_ASSERT_EQUAL(cpl->status.sct, 0); 596 CU_ASSERT_EQUAL(cpl->status.sc, 0); 597 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_ERROR); 598 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR); 599 CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE); 600 CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1); 601 CU_ASSERT_EQUAL(msg->t_id, 8); 602 CU_ASSERT_EQUAL(msg->rc, SPDK_NVMF_AUTH_FAILURE); 603 CU_ASSERT_EQUAL(msg->rce, SPDK_NVMF_AUTH_FAILED); 604 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 605 606 /* Do a receive while expecting an auth send command */ 607 ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg)); 608 g_req_completed = false; 609 auth->state = NVMF_QPAIR_AUTH_NEGOTIATE; 610 auth->fail_reason = 0; 611 612 nvmf_auth_recv_exec(&req); 613 CU_ASSERT(g_req_completed); 614 CU_ASSERT_EQUAL(cpl->status.sct, 0); 615 CU_ASSERT_EQUAL(cpl->status.sc, 0); 616 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_ERROR); 617 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR); 618 CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE); 619 CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1); 620 CU_ASSERT_EQUAL(msg->t_id, 8); 621 CU_ASSERT_EQUAL(msg->rc, SPDK_NVMF_AUTH_FAILURE); 622 CU_ASSERT_EQUAL(msg->rce, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 623 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 624 625 /* Do a receive but specify a buffer that's too small */ 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 req.iov[0].iov_len = cmd.al = req.length = sizeof(*msg) - 1; 631 632 nvmf_auth_recv_exec(&req); 633 CU_ASSERT(g_req_completed); 634 CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC); 635 CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_INVALID_FIELD); 636 CU_ASSERT_EQUAL(cpl->status.dnr, 1); 637 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR); 638 req.iov[0].iov_len = cmd.al = req.length = sizeof(*msg); 639 640 nvmf_qpair_auth_destroy(&qpair); 641 } 642 643 static void 644 test_auth_challenge(void) 645 { 646 union nvmf_c2h_msg rsp = {}; 647 struct spdk_nvmf_subsystem subsys = { .mutex = PTHREAD_MUTEX_INITIALIZER }; 648 struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys }; 649 struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr }; 650 struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp }; 651 struct spdk_nvmf_fabric_auth_recv_cmd cmd = { 652 .fctype = SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV 653 }; 654 struct spdk_nvmf_qpair_auth *auth; 655 struct spdk_nvmf_dhchap_challenge *msg; 656 struct spdk_nvmf_auth_failure *fail; 657 uint8_t msgbuf[4096], cval[4096], dhv[4096]; 658 int rc; 659 660 msg = (void *)msgbuf; 661 fail = (void *)msgbuf; 662 rc = nvmf_qpair_auth_init(&qpair); 663 SPDK_CU_ASSERT_FATAL(rc == 0); 664 auth = qpair.auth; 665 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 666 667 /* Successfully receive a challenge message */ 668 ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf)); 669 g_req_completed = false; 670 auth->state = NVMF_QPAIR_AUTH_CHALLENGE; 671 auth->dhgroup = SPDK_NVMF_DHCHAP_DHGROUP_NULL; 672 MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48); 673 g_rand_val = 0xa5; 674 memset(cval, g_rand_val, sizeof(cval)); 675 auth->digest = SPDK_NVMF_DHCHAP_HASH_SHA384; 676 auth->tid = 8; 677 678 nvmf_auth_recv_exec(&req); 679 CU_ASSERT(g_req_completed); 680 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_REPLY); 681 CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_DHCHAP); 682 CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_DHCHAP_CHALLENGE); 683 CU_ASSERT_EQUAL(msg->t_id, 8); 684 CU_ASSERT_EQUAL(msg->hl, 48); 685 CU_ASSERT_EQUAL(msg->hash_id, SPDK_NVMF_DHCHAP_HASH_SHA384); 686 CU_ASSERT_EQUAL(msg->dhg_id, SPDK_NVMF_DHCHAP_DHGROUP_NULL); 687 CU_ASSERT_EQUAL(msg->dhvlen, 0); 688 CU_ASSERT_EQUAL(memcmp(msg->cval, cval, 48), 0); 689 CU_ASSERT(msg->seqnum != 0); 690 691 /* Successfully receive a challenge message w/ a non-NULL dhgroup */ 692 ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf)); 693 g_req_completed = false; 694 auth->state = NVMF_QPAIR_AUTH_CHALLENGE; 695 MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48); 696 MOCK_SET(spdk_nvme_dhchap_generate_dhkey, (struct spdk_nvme_dhchap_dhkey *)0xdeadbeef); 697 g_rand_val = 0xa5; 698 g_dhv = 0xfe; 699 g_dhvlen = 256; 700 memset(cval, g_rand_val, sizeof(cval)); 701 memset(dhv, g_dhv, sizeof(dhv)); 702 auth->digest = SPDK_NVMF_DHCHAP_HASH_SHA384; 703 auth->dhgroup = SPDK_NVMF_DHCHAP_DHGROUP_2048; 704 auth->tid = 8; 705 706 nvmf_auth_recv_exec(&req); 707 CU_ASSERT(g_req_completed); 708 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_REPLY); 709 CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_DHCHAP); 710 CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_DHCHAP_CHALLENGE); 711 CU_ASSERT_EQUAL(msg->t_id, 8); 712 CU_ASSERT_EQUAL(msg->hl, 48); 713 CU_ASSERT_EQUAL(msg->hash_id, SPDK_NVMF_DHCHAP_HASH_SHA384); 714 CU_ASSERT_EQUAL(msg->dhg_id, SPDK_NVMF_DHCHAP_DHGROUP_2048); 715 CU_ASSERT_EQUAL(msg->dhvlen, g_dhvlen); 716 CU_ASSERT_EQUAL(memcmp(msg->cval, cval, 48), 0); 717 CU_ASSERT_EQUAL(memcmp(&msg->cval[48], dhv, g_dhvlen), 0); 718 CU_ASSERT(msg->seqnum != 0); 719 720 /* Check RAND_bytes failure */ 721 ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf)); 722 g_req_completed = false; 723 auth->state = NVMF_QPAIR_AUTH_CHALLENGE; 724 MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48); 725 auth->digest = SPDK_NVMF_DHCHAP_HASH_SHA384; 726 auth->tid = 8; 727 MOCK_SET(RAND_bytes, -1); 728 729 nvmf_auth_recv_exec(&req); 730 CU_ASSERT(g_req_completed); 731 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR); 732 CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE); 733 CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1); 734 CU_ASSERT_EQUAL(fail->t_id, 8); 735 CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE); 736 CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_FAILED); 737 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 738 MOCK_SET(RAND_bytes, 1); 739 740 /* Check spdk_nvme_dhchap_generate_dhkey failure */ 741 ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf)); 742 g_req_completed = false; 743 MOCK_SET(spdk_nvme_dhchap_generate_dhkey, NULL); 744 auth->state = NVMF_QPAIR_AUTH_CHALLENGE; 745 auth->tid = 8; 746 747 nvmf_auth_recv_exec(&req); 748 CU_ASSERT(g_req_completed); 749 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR); 750 CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE); 751 CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1); 752 CU_ASSERT_EQUAL(fail->t_id, 8); 753 CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE); 754 CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_FAILED); 755 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 756 757 /* Check spdk_nvme_dhchap_dhkey_get_pubkey failure */ 758 ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf)); 759 g_req_completed = false; 760 MOCK_SET(spdk_nvme_dhchap_generate_dhkey, (struct spdk_nvme_dhchap_dhkey *)0xdeadbeef); 761 MOCK_SET(spdk_nvme_dhchap_dhkey_get_pubkey, -EIO); 762 auth->state = NVMF_QPAIR_AUTH_CHALLENGE; 763 auth->tid = 8; 764 765 nvmf_auth_recv_exec(&req); 766 CU_ASSERT(g_req_completed); 767 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR); 768 CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE); 769 CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1); 770 CU_ASSERT_EQUAL(fail->t_id, 8); 771 CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE); 772 CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_FAILED); 773 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 774 MOCK_SET(spdk_nvme_dhchap_dhkey_get_pubkey, 0); 775 776 /* Check insufficient buffer size */ 777 ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(msgbuf)); 778 g_req_completed = false; 779 auth->state = NVMF_QPAIR_AUTH_CHALLENGE; 780 MOCK_SET(spdk_nvme_dhchap_get_digest_length, 48); 781 auth->tid = 8; 782 cmd.al = req.length = req.iov[0].iov_len = sizeof(msg) + 47; 783 784 nvmf_auth_recv_exec(&req); 785 CU_ASSERT(g_req_completed); 786 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR); 787 CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE); 788 CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1); 789 CU_ASSERT_EQUAL(fail->t_id, 8); 790 CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE); 791 CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 792 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 793 MOCK_CLEAR(spdk_nvme_dhchap_get_digest_length); 794 795 nvmf_qpair_auth_destroy(&qpair); 796 } 797 798 static void 799 test_auth_reply(void) 800 { 801 union nvmf_c2h_msg rsp = {}; 802 struct spdk_nvmf_subsystem subsys = {}; 803 struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys }; 804 struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr }; 805 struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp }; 806 struct spdk_nvmf_fabric_auth_send_cmd cmd = {}; 807 struct spdk_nvmf_qpair_auth *auth; 808 struct spdk_nvmf_dhchap_reply *msg; 809 uint8_t hl = 48, msgbuf[4096]; 810 int rc; 811 812 msg = (void *)msgbuf; 813 rc = nvmf_qpair_auth_init(&qpair); 814 SPDK_CU_ASSERT_FATAL(rc == 0); 815 ut_prep_send_cmd(&req, &cmd, msgbuf, sizeof(*msg) + 2 * hl); 816 auth = qpair.auth; 817 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 818 auth->tid = 8; 819 820 /* Execute a reply containing a correct response */ 821 g_req_completed = false; 822 MOCK_SET(nvmf_subsystem_get_dhchap_key, (struct spdk_key *)0xdeadbeef); 823 MOCK_SET(spdk_nvme_dhchap_get_digest_length, hl); 824 auth->state = NVMF_QPAIR_AUTH_REPLY; 825 msg->auth_type = SPDK_NVMF_AUTH_TYPE_DHCHAP; 826 msg->auth_id = SPDK_NVMF_AUTH_ID_DHCHAP_REPLY; 827 msg->t_id = auth->tid; 828 msg->hl = hl; 829 msg->cvalid = 0; 830 msg->dhvlen = 0; 831 msg->seqnum = 0; 832 memset(msg->rval, 0xa5, hl); 833 g_rval = 0xa5; 834 835 nvmf_auth_send_exec(&req); 836 CU_ASSERT(g_req_completed); 837 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_SUCCESS1); 838 839 /* Execute a reply while not in the REPLY state */ 840 g_req_completed = false; 841 auth->state = NVMF_QPAIR_AUTH_CHALLENGE; 842 843 nvmf_auth_send_exec(&req); 844 CU_ASSERT(g_req_completed); 845 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 846 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 847 848 /* Bad message length (smaller than a base reply message) */ 849 g_req_completed = false; 850 auth->state = NVMF_QPAIR_AUTH_REPLY; 851 cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) - 1; 852 853 nvmf_auth_send_exec(&req); 854 CU_ASSERT(g_req_completed); 855 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 856 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 857 858 /* Hash length mismatch */ 859 g_req_completed = false; 860 auth->state = NVMF_QPAIR_AUTH_REPLY; 861 msg->hl = 32; 862 863 nvmf_auth_send_exec(&req); 864 CU_ASSERT(g_req_completed); 865 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 866 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 867 msg->hl = hl; 868 869 /* Bad message length (smaller than size of msg + 2 * hl) */ 870 g_req_completed = false; 871 auth->state = NVMF_QPAIR_AUTH_REPLY; 872 cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + 2 * hl - 1; 873 874 nvmf_auth_send_exec(&req); 875 CU_ASSERT(g_req_completed); 876 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 877 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 878 cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + hl; 879 880 /* Bad message length (larger than size of msg + 2 * hl) */ 881 g_req_completed = false; 882 auth->state = NVMF_QPAIR_AUTH_REPLY; 883 cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + 2 * hl + 1; 884 885 nvmf_auth_send_exec(&req); 886 CU_ASSERT(g_req_completed); 887 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 888 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 889 cmd.tl = req.iov[0].iov_len = req.length = sizeof(*msg) + 2 * hl; 890 891 /* Transaction ID mismatch */ 892 g_req_completed = false; 893 auth->state = NVMF_QPAIR_AUTH_REPLY; 894 msg->t_id = auth->tid + 1; 895 896 nvmf_auth_send_exec(&req); 897 CU_ASSERT(g_req_completed); 898 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 899 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 900 msg->t_id = auth->tid; 901 902 /* Bad cvalid value */ 903 g_req_completed = false; 904 auth->state = NVMF_QPAIR_AUTH_REPLY; 905 msg->cvalid = 1; 906 907 nvmf_auth_send_exec(&req); 908 CU_ASSERT(g_req_completed); 909 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 910 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 911 msg->cvalid = 0; 912 913 /* Bad dhvlen (non-zero) */ 914 g_req_completed = false; 915 auth->state = NVMF_QPAIR_AUTH_REPLY; 916 msg->dhvlen = 1; 917 918 nvmf_auth_send_exec(&req); 919 CU_ASSERT(g_req_completed); 920 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 921 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 922 msg->dhvlen = 0; 923 924 /* Failure to get the key */ 925 g_req_completed = false; 926 auth->state = NVMF_QPAIR_AUTH_REPLY; 927 MOCK_SET(nvmf_subsystem_get_dhchap_key, NULL); 928 929 nvmf_auth_send_exec(&req); 930 CU_ASSERT(g_req_completed); 931 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 932 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED); 933 MOCK_SET(nvmf_subsystem_get_dhchap_key, (struct spdk_key *)0xdeadbeef); 934 935 /* Calculation failure */ 936 g_req_completed = false; 937 auth->state = NVMF_QPAIR_AUTH_REPLY; 938 MOCK_SET(spdk_nvme_dhchap_calculate, -EPERM); 939 940 nvmf_auth_send_exec(&req); 941 CU_ASSERT(g_req_completed); 942 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 943 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED); 944 MOCK_SET(spdk_nvme_dhchap_calculate, 0); 945 946 /* Response mismatch */ 947 g_req_completed = false; 948 auth->state = NVMF_QPAIR_AUTH_REPLY; 949 g_rval = 0x5a; 950 951 nvmf_auth_send_exec(&req); 952 CU_ASSERT(g_req_completed); 953 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 954 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED); 955 g_rval = 0xa5; 956 957 /* DH secret derivation failure */ 958 g_req_completed = false; 959 auth->state = NVMF_QPAIR_AUTH_REPLY; 960 auth->dhgroup = SPDK_NVMF_DHCHAP_DHGROUP_2048; 961 MOCK_SET(spdk_nvme_dhchap_dhkey_derive_secret, -EIO); 962 963 nvmf_auth_send_exec(&req); 964 CU_ASSERT(g_req_completed); 965 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_FAILURE1); 966 CU_ASSERT_EQUAL(auth->fail_reason, SPDK_NVMF_AUTH_FAILED); 967 MOCK_SET(spdk_nvme_dhchap_dhkey_derive_secret, 0); 968 969 nvmf_qpair_auth_destroy(&qpair); 970 } 971 972 static void 973 test_auth_success1(void) 974 { 975 union nvmf_c2h_msg rsp = {}; 976 struct spdk_nvmf_subsystem subsys = {}; 977 struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsys }; 978 struct spdk_nvmf_qpair qpair = { .ctrlr = &ctrlr }; 979 struct spdk_nvmf_request req = { .qpair = &qpair, .rsp = &rsp }; 980 struct spdk_nvmf_fabric_auth_recv_cmd cmd = { 981 .fctype = SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV 982 }; 983 struct spdk_nvmf_qpair_auth *auth; 984 struct spdk_nvmf_dhchap_success1 *msg; 985 struct spdk_nvmf_auth_failure *fail; 986 uint8_t msgbuf[sizeof(*msg)]; 987 int rc; 988 989 msg = (void *)msgbuf; 990 fail = (void *)msgbuf; 991 rc = nvmf_qpair_auth_init(&qpair); 992 SPDK_CU_ASSERT_FATAL(rc == 0); 993 auth = qpair.auth; 994 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 995 auth->tid = 8; 996 997 /* Successfully receive a success message */ 998 ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg)); 999 g_req_completed = false; 1000 auth->state = NVMF_QPAIR_AUTH_SUCCESS1; 1001 1002 nvmf_auth_recv_exec(&req); 1003 CU_ASSERT(g_req_completed); 1004 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_COMPLETED); 1005 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ENABLED); 1006 CU_ASSERT_EQUAL(msg->auth_type, SPDK_NVMF_AUTH_TYPE_DHCHAP); 1007 CU_ASSERT_EQUAL(msg->auth_id, SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS1); 1008 CU_ASSERT_EQUAL(msg->t_id, 8); 1009 CU_ASSERT_EQUAL(msg->hl, 48); 1010 CU_ASSERT_EQUAL(msg->rvalid, 0); 1011 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 1012 1013 /* Bad message length (smaller than success1 message) */ 1014 ut_prep_recv_cmd(&req, &cmd, msgbuf, sizeof(*msg)); 1015 g_req_completed = false; 1016 auth->state = NVMF_QPAIR_AUTH_SUCCESS1; 1017 cmd.al = req.iov[0].iov_len = req.length = sizeof(*msg) - 1; 1018 1019 nvmf_auth_recv_exec(&req); 1020 CU_ASSERT(g_req_completed); 1021 CU_ASSERT_EQUAL(auth->state, NVMF_QPAIR_AUTH_ERROR); 1022 CU_ASSERT_EQUAL(qpair.state, SPDK_NVMF_QPAIR_ERROR); 1023 CU_ASSERT_EQUAL(fail->auth_type, SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE); 1024 CU_ASSERT_EQUAL(fail->auth_id, SPDK_NVMF_AUTH_ID_FAILURE1); 1025 CU_ASSERT_EQUAL(fail->t_id, 8); 1026 CU_ASSERT_EQUAL(fail->rc, SPDK_NVMF_AUTH_FAILURE); 1027 CU_ASSERT_EQUAL(fail->rce, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 1028 qpair.state = SPDK_NVMF_QPAIR_AUTHENTICATING; 1029 cmd.al = req.iov[0].iov_len = req.length = sizeof(*msg); 1030 1031 nvmf_qpair_auth_destroy(&qpair); 1032 } 1033 1034 int 1035 main(int argc, char **argv) 1036 { 1037 CU_pSuite suite = NULL; 1038 unsigned int num_failures; 1039 1040 CU_initialize_registry(); 1041 suite = CU_add_suite("nvmf_auth", NULL, NULL); 1042 CU_ADD_TEST(suite, test_auth_send_recv_error); 1043 CU_ADD_TEST(suite, test_auth_negotiate); 1044 CU_ADD_TEST(suite, test_auth_timeout); 1045 CU_ADD_TEST(suite, test_auth_failure1); 1046 CU_ADD_TEST(suite, test_auth_challenge); 1047 CU_ADD_TEST(suite, test_auth_reply); 1048 CU_ADD_TEST(suite, test_auth_success1); 1049 1050 allocate_threads(1); 1051 set_thread(0); 1052 1053 num_failures = spdk_ut_run_tests(argc, argv, NULL); 1054 CU_cleanup_registry(); 1055 1056 free_threads(); 1057 1058 return num_failures; 1059 } 1060