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