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