1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2024 Intel Corporation 3 */ 4 5 #include "spdk/nvme.h" 6 #include "spdk/json.h" 7 #include "spdk/log.h" 8 #include "spdk/stdinc.h" 9 #include "spdk/string.h" 10 #include "spdk/thread.h" 11 #include "spdk/util.h" 12 #include "spdk_internal/nvme.h" 13 14 #include <openssl/rand.h> 15 16 #include "nvmf_internal.h" 17 18 #define NVMF_AUTH_DEFAULT_KATO_US (120ull * 1000 * 1000) 19 #define NVMF_AUTH_FAILURE1_DELAY_US (100ull * 1000) 20 #define NVMF_AUTH_DIGEST_MAX_SIZE 64 21 #define NVMF_AUTH_DH_KEY_MAX_SIZE 1024 22 23 #define AUTH_ERRLOG(q, fmt, ...) \ 24 SPDK_ERRLOG("[%s:%s:%u] " fmt, (q)->ctrlr->subsys->subnqn, (q)->ctrlr->hostnqn, \ 25 (q)->qid, ## __VA_ARGS__) 26 #define AUTH_DEBUGLOG(q, fmt, ...) \ 27 SPDK_DEBUGLOG(nvmf_auth, "[%s:%s:%u] " fmt, \ 28 (q)->ctrlr->subsys->subnqn, (q)->ctrlr->hostnqn, (q)->qid, ## __VA_ARGS__) 29 #define AUTH_LOGDUMP(msg, buf, len) \ 30 SPDK_LOGDUMP(nvmf_auth, msg, buf, len) 31 32 enum nvmf_qpair_auth_state { 33 NVMF_QPAIR_AUTH_NEGOTIATE, 34 NVMF_QPAIR_AUTH_CHALLENGE, 35 NVMF_QPAIR_AUTH_REPLY, 36 NVMF_QPAIR_AUTH_SUCCESS1, 37 NVMF_QPAIR_AUTH_SUCCESS2, 38 NVMF_QPAIR_AUTH_FAILURE1, 39 NVMF_QPAIR_AUTH_COMPLETED, 40 NVMF_QPAIR_AUTH_ERROR, 41 }; 42 43 struct spdk_nvmf_qpair_auth { 44 enum nvmf_qpair_auth_state state; 45 struct spdk_poller *poller; 46 int fail_reason; 47 uint16_t tid; 48 int digest; 49 int dhgroup; 50 uint8_t cval[NVMF_AUTH_DIGEST_MAX_SIZE]; 51 uint32_t seqnum; 52 struct spdk_nvme_dhchap_dhkey *dhkey; 53 bool cvalid; 54 }; 55 56 struct nvmf_auth_common_header { 57 uint8_t auth_type; 58 uint8_t auth_id; 59 uint8_t reserved0[2]; 60 uint16_t t_id; 61 }; 62 63 static void 64 nvmf_auth_request_complete(struct spdk_nvmf_request *req, int sct, int sc, int dnr) 65 { 66 struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; 67 68 response->status.sct = sct; 69 response->status.sc = sc; 70 response->status.dnr = dnr; 71 72 spdk_nvmf_request_complete(req); 73 } 74 75 static const char * 76 nvmf_auth_get_state_name(enum nvmf_qpair_auth_state state) 77 { 78 static const char *state_names[] = { 79 [NVMF_QPAIR_AUTH_NEGOTIATE] = "negotiate", 80 [NVMF_QPAIR_AUTH_CHALLENGE] = "challenge", 81 [NVMF_QPAIR_AUTH_REPLY] = "reply", 82 [NVMF_QPAIR_AUTH_SUCCESS1] = "success1", 83 [NVMF_QPAIR_AUTH_SUCCESS2] = "success2", 84 [NVMF_QPAIR_AUTH_FAILURE1] = "failure1", 85 [NVMF_QPAIR_AUTH_COMPLETED] = "completed", 86 [NVMF_QPAIR_AUTH_ERROR] = "error", 87 }; 88 89 return state_names[state]; 90 } 91 92 static void 93 nvmf_auth_set_state(struct spdk_nvmf_qpair *qpair, enum nvmf_qpair_auth_state state) 94 { 95 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 96 97 if (auth->state == state) { 98 return; 99 } 100 101 AUTH_DEBUGLOG(qpair, "auth state: %s\n", nvmf_auth_get_state_name(state)); 102 auth->state = state; 103 } 104 105 static void 106 nvmf_auth_disconnect_qpair(struct spdk_nvmf_qpair *qpair) 107 { 108 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_ERROR); 109 spdk_nvmf_qpair_disconnect(qpair); 110 } 111 112 static void 113 nvmf_auth_request_fail1(struct spdk_nvmf_request *req, int reason) 114 { 115 struct spdk_nvmf_qpair *qpair = req->qpair; 116 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 117 118 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_FAILURE1); 119 auth->fail_reason = reason; 120 121 /* The command itself is completed successfully, but a subsequent AUTHENTICATION_RECV 122 * command will be completed with an AUTH_failure1 message 123 */ 124 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0); 125 } 126 127 static bool 128 nvmf_auth_digest_allowed(struct spdk_nvmf_qpair *qpair, uint8_t digest) 129 { 130 struct spdk_nvmf_tgt *tgt = qpair->group->tgt; 131 132 return tgt->dhchap_digests & SPDK_BIT(digest); 133 } 134 135 static bool 136 nvmf_auth_dhgroup_allowed(struct spdk_nvmf_qpair *qpair, uint8_t dhgroup) 137 { 138 struct spdk_nvmf_tgt *tgt = qpair->group->tgt; 139 140 return tgt->dhchap_dhgroups & SPDK_BIT(dhgroup); 141 } 142 143 static void 144 nvmf_auth_qpair_cleanup(struct spdk_nvmf_qpair_auth *auth) 145 { 146 spdk_poller_unregister(&auth->poller); 147 spdk_nvme_dhchap_dhkey_free(&auth->dhkey); 148 } 149 150 static int 151 nvmf_auth_timeout_poller(void *ctx) 152 { 153 struct spdk_nvmf_qpair *qpair = ctx; 154 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 155 156 AUTH_ERRLOG(qpair, "authentication timed out\n"); 157 spdk_poller_unregister(&auth->poller); 158 159 if (qpair->state == SPDK_NVMF_QPAIR_ENABLED) { 160 /* Reauthentication timeout isn't considered to be a fatal failure */ 161 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_COMPLETED); 162 nvmf_auth_qpair_cleanup(auth); 163 } else { 164 nvmf_auth_disconnect_qpair(qpair); 165 } 166 167 return SPDK_POLLER_BUSY; 168 } 169 170 static int 171 nvmf_auth_rearm_poller(struct spdk_nvmf_qpair *qpair) 172 { 173 struct spdk_nvmf_ctrlr *ctrlr = qpair->ctrlr; 174 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 175 uint64_t timeout; 176 177 timeout = ctrlr->feat.keep_alive_timer.bits.kato > 0 ? 178 ctrlr->feat.keep_alive_timer.bits.kato * 1000 : 179 NVMF_AUTH_DEFAULT_KATO_US; 180 181 spdk_poller_unregister(&auth->poller); 182 auth->poller = SPDK_POLLER_REGISTER(nvmf_auth_timeout_poller, qpair, timeout); 183 if (auth->poller == NULL) { 184 return -ENOMEM; 185 } 186 187 return 0; 188 } 189 190 static int 191 nvmf_auth_check_command(struct spdk_nvmf_request *req, uint8_t secp, 192 uint8_t spsp0, uint8_t spsp1, uint32_t len) 193 { 194 struct spdk_nvmf_qpair *qpair = req->qpair; 195 196 if (secp != SPDK_NVMF_AUTH_SECP_NVME) { 197 AUTH_ERRLOG(qpair, "invalid secp=%u\n", secp); 198 return -EINVAL; 199 } 200 if (spsp0 != 1 || spsp1 != 1) { 201 AUTH_ERRLOG(qpair, "invalid spsp0=%u, spsp1=%u\n", spsp0, spsp1); 202 return -EINVAL; 203 } 204 if (len != req->length) { 205 AUTH_ERRLOG(qpair, "invalid length: %"PRIu32" != %"PRIu32"\n", len, req->length); 206 return -EINVAL; 207 } 208 209 return 0; 210 } 211 212 static void * 213 nvmf_auth_get_message(struct spdk_nvmf_request *req, size_t size) 214 { 215 if (req->length > 0 && req->iovcnt == 1 && req->iov[0].iov_len >= size) { 216 return req->iov[0].iov_base; 217 } 218 219 return NULL; 220 } 221 222 static void 223 nvmf_auth_negotiate_exec(struct spdk_nvmf_request *req, struct spdk_nvmf_auth_negotiate *msg) 224 { 225 struct spdk_nvmf_qpair *qpair = req->qpair; 226 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 227 struct spdk_nvmf_auth_descriptor *desc = NULL; 228 /* These arrays are sorted from the strongest hash/dhgroup to the weakest, so the strongest 229 * hash/dhgroup pair supported by the host is always selected 230 */ 231 enum spdk_nvmf_dhchap_hash digests[] = { 232 SPDK_NVMF_DHCHAP_HASH_SHA512, 233 SPDK_NVMF_DHCHAP_HASH_SHA384, 234 SPDK_NVMF_DHCHAP_HASH_SHA256 235 }; 236 enum spdk_nvmf_dhchap_dhgroup dhgroups[] = { 237 SPDK_NVMF_DHCHAP_DHGROUP_8192, 238 SPDK_NVMF_DHCHAP_DHGROUP_6144, 239 SPDK_NVMF_DHCHAP_DHGROUP_4096, 240 SPDK_NVMF_DHCHAP_DHGROUP_3072, 241 SPDK_NVMF_DHCHAP_DHGROUP_2048, 242 SPDK_NVMF_DHCHAP_DHGROUP_NULL, 243 }; 244 int digest = -1, dhgroup = -1; 245 size_t i, j; 246 247 if (auth->state != NVMF_QPAIR_AUTH_NEGOTIATE) { 248 AUTH_ERRLOG(qpair, "invalid state: %s\n", nvmf_auth_get_state_name(auth->state)); 249 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 250 return; 251 } 252 253 auth->tid = msg->t_id; 254 if (req->length < sizeof(*msg) || req->length != sizeof(*msg) + msg->napd * sizeof(*desc)) { 255 AUTH_ERRLOG(qpair, "invalid message length: %"PRIu32"\n", req->length); 256 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 257 return; 258 } 259 260 if (msg->sc_c != SPDK_NVMF_AUTH_SCC_DISABLED) { 261 AUTH_ERRLOG(qpair, "scc mismatch\n"); 262 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_SCC_MISMATCH); 263 return; 264 } 265 266 for (i = 0; i < msg->napd; ++i) { 267 if (msg->descriptors[i].auth_id == SPDK_NVMF_AUTH_TYPE_DHCHAP) { 268 desc = &msg->descriptors[i]; 269 break; 270 } 271 } 272 if (desc == NULL) { 273 AUTH_ERRLOG(qpair, "no usable protocol found\n"); 274 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_PROTOCOL_UNUSABLE); 275 return; 276 } 277 if (desc->halen > SPDK_COUNTOF(desc->hash_id_list) || 278 desc->dhlen > SPDK_COUNTOF(desc->dhg_id_list)) { 279 AUTH_ERRLOG(qpair, "invalid halen=%u, dhlen=%u\n", desc->halen, desc->dhlen); 280 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 281 return; 282 } 283 284 for (i = 0; i < SPDK_COUNTOF(digests); ++i) { 285 if (!nvmf_auth_digest_allowed(qpair, digests[i])) { 286 continue; 287 } 288 for (j = 0; j < desc->halen; ++j) { 289 if (digests[i] == desc->hash_id_list[j]) { 290 AUTH_DEBUGLOG(qpair, "selected digest: %s\n", 291 spdk_nvme_dhchap_get_digest_name(digests[i])); 292 digest = digests[i]; 293 break; 294 } 295 } 296 if (digest >= 0) { 297 break; 298 } 299 } 300 if (digest < 0) { 301 AUTH_ERRLOG(qpair, "no usable digests found\n"); 302 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_HASH_UNUSABLE); 303 return; 304 } 305 306 for (i = 0; i < SPDK_COUNTOF(dhgroups); ++i) { 307 if (!nvmf_auth_dhgroup_allowed(qpair, dhgroups[i])) { 308 continue; 309 } 310 for (j = 0; j < desc->dhlen; ++j) { 311 if (dhgroups[i] == desc->dhg_id_list[j]) { 312 AUTH_DEBUGLOG(qpair, "selected dhgroup: %s\n", 313 spdk_nvme_dhchap_get_dhgroup_name(dhgroups[i])); 314 dhgroup = dhgroups[i]; 315 break; 316 } 317 } 318 if (dhgroup >= 0) { 319 break; 320 } 321 } 322 if (dhgroup < 0) { 323 AUTH_ERRLOG(qpair, "no usable dhgroups found\n"); 324 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_DHGROUP_UNUSABLE); 325 return; 326 } 327 328 if (nvmf_auth_rearm_poller(qpair)) { 329 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 330 SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 1); 331 nvmf_auth_disconnect_qpair(qpair); 332 return; 333 } 334 335 auth->digest = digest; 336 auth->dhgroup = dhgroup; 337 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_CHALLENGE); 338 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0); 339 } 340 341 static void 342 nvmf_auth_reply_exec(struct spdk_nvmf_request *req, struct spdk_nvmf_dhchap_reply *msg) 343 { 344 struct spdk_nvmf_qpair *qpair = req->qpair; 345 struct spdk_nvmf_ctrlr *ctrlr = qpair->ctrlr; 346 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 347 uint8_t response[NVMF_AUTH_DIGEST_MAX_SIZE]; 348 uint8_t dhsec[NVMF_AUTH_DH_KEY_MAX_SIZE]; 349 struct spdk_key *key = NULL, *ckey = NULL; 350 size_t dhseclen = 0; 351 uint8_t hl; 352 int rc; 353 354 if (auth->state != NVMF_QPAIR_AUTH_REPLY) { 355 AUTH_ERRLOG(qpair, "invalid state=%s\n", nvmf_auth_get_state_name(auth->state)); 356 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 357 goto out; 358 } 359 if (req->length < sizeof(*msg)) { 360 AUTH_ERRLOG(qpair, "invalid message length=%"PRIu32"\n", req->length); 361 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 362 goto out; 363 } 364 365 hl = spdk_nvme_dhchap_get_digest_length(auth->digest); 366 if (hl == 0 || msg->hl != hl) { 367 AUTH_ERRLOG(qpair, "hash length mismatch: %u != %u\n", msg->hl, hl); 368 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 369 goto out; 370 } 371 if ((msg->dhvlen % 4) != 0) { 372 AUTH_ERRLOG(qpair, "dhvlen=%u is not multiple of 4\n", msg->dhvlen); 373 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 374 goto out; 375 } 376 if (req->length != sizeof(*msg) + 2 * hl + msg->dhvlen) { 377 AUTH_ERRLOG(qpair, "invalid message length: %"PRIu32" != %zu\n", 378 req->length, sizeof(*msg) + 2 * hl); 379 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 380 goto out; 381 } 382 if (msg->t_id != auth->tid) { 383 AUTH_ERRLOG(qpair, "transaction id mismatch: %u != %u\n", msg->t_id, auth->tid); 384 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 385 goto out; 386 } 387 if (msg->cvalid != 0 && msg->cvalid != 1) { 388 AUTH_ERRLOG(qpair, "unexpected cvalid=%d\n", msg->cvalid); 389 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 390 goto out; 391 } 392 if (msg->cvalid && msg->seqnum == 0) { 393 AUTH_ERRLOG(qpair, "unexpected seqnum=0 with cvalid=1\n"); 394 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 395 goto out; 396 } 397 398 key = nvmf_subsystem_get_dhchap_key(ctrlr->subsys, ctrlr->hostnqn, NVMF_AUTH_KEY_HOST); 399 if (key == NULL) { 400 AUTH_ERRLOG(qpair, "couldn't get DH-HMAC-CHAP key\n"); 401 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 402 goto out; 403 } 404 405 if (auth->dhgroup != SPDK_NVMF_DHCHAP_DHGROUP_NULL) { 406 AUTH_LOGDUMP("host pubkey:", &msg->rval[2 * hl], msg->dhvlen); 407 dhseclen = sizeof(dhsec); 408 rc = spdk_nvme_dhchap_dhkey_derive_secret(auth->dhkey, &msg->rval[2 * hl], 409 msg->dhvlen, dhsec, &dhseclen); 410 if (rc != 0) { 411 AUTH_ERRLOG(qpair, "couldn't derive DH secret\n"); 412 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 413 goto out; 414 } 415 416 AUTH_LOGDUMP("dh secret:", dhsec, dhseclen); 417 } 418 419 assert(hl <= sizeof(response) && hl <= sizeof(auth->cval)); 420 rc = spdk_nvme_dhchap_calculate(key, (enum spdk_nvmf_dhchap_hash)auth->digest, 421 "HostHost", auth->seqnum, auth->tid, 0, 422 ctrlr->hostnqn, ctrlr->subsys->subnqn, 423 dhseclen > 0 ? dhsec : NULL, dhseclen, 424 auth->cval, response); 425 if (rc != 0) { 426 AUTH_ERRLOG(qpair, "failed to calculate challenge response: %s\n", 427 spdk_strerror(-rc)); 428 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 429 goto out; 430 } 431 432 if (memcmp(msg->rval, response, hl) != 0) { 433 AUTH_ERRLOG(qpair, "challenge response mismatch\n"); 434 AUTH_LOGDUMP("response:", msg->rval, hl); 435 AUTH_LOGDUMP("expected:", response, hl); 436 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 437 goto out; 438 } 439 440 if (msg->cvalid) { 441 ckey = nvmf_subsystem_get_dhchap_key(ctrlr->subsys, ctrlr->hostnqn, 442 NVMF_AUTH_KEY_CTRLR); 443 if (ckey == NULL) { 444 AUTH_ERRLOG(qpair, "missing DH-HMAC-CHAP ctrlr key\n"); 445 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 446 goto out; 447 } 448 rc = spdk_nvme_dhchap_calculate(ckey, (enum spdk_nvmf_dhchap_hash)auth->digest, 449 "Controller", msg->seqnum, auth->tid, 0, 450 ctrlr->subsys->subnqn, ctrlr->hostnqn, 451 dhseclen > 0 ? dhsec : NULL, dhseclen, 452 &msg->rval[hl], auth->cval); 453 if (rc != 0) { 454 AUTH_ERRLOG(qpair, "failed to calculate ctrlr challenge response: %s\n", 455 spdk_strerror(-rc)); 456 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 457 goto out; 458 } 459 auth->cvalid = true; 460 } 461 462 if (nvmf_auth_rearm_poller(qpair)) { 463 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 464 SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 1); 465 nvmf_auth_disconnect_qpair(qpair); 466 goto out; 467 } 468 469 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_SUCCESS1); 470 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0); 471 out: 472 spdk_keyring_put_key(ckey); 473 spdk_keyring_put_key(key); 474 } 475 476 static void 477 nvmf_auth_success2_exec(struct spdk_nvmf_request *req, struct spdk_nvmf_dhchap_success2 *msg) 478 { 479 struct spdk_nvmf_qpair *qpair = req->qpair; 480 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 481 482 if (auth->state != NVMF_QPAIR_AUTH_SUCCESS2) { 483 AUTH_ERRLOG(qpair, "invalid state=%s\n", nvmf_auth_get_state_name(auth->state)); 484 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 485 return; 486 } 487 if (req->length != sizeof(*msg)) { 488 AUTH_ERRLOG(qpair, "invalid message length=%"PRIu32"\n", req->length); 489 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 490 return; 491 } 492 if (msg->t_id != auth->tid) { 493 AUTH_ERRLOG(qpair, "transaction id mismatch: %u != %u\n", msg->t_id, auth->tid); 494 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 495 return; 496 } 497 498 AUTH_DEBUGLOG(qpair, "controller authentication successful\n"); 499 nvmf_qpair_set_state(qpair, SPDK_NVMF_QPAIR_ENABLED); 500 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_COMPLETED); 501 nvmf_auth_qpair_cleanup(auth); 502 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0); 503 } 504 505 static void 506 nvmf_auth_failure2_exec(struct spdk_nvmf_request *req, struct spdk_nvmf_auth_failure *msg) 507 { 508 struct spdk_nvmf_qpair *qpair = req->qpair; 509 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 510 511 /* AUTH_failure2 is only expected when we're waiting for the success2 message */ 512 if (auth->state != NVMF_QPAIR_AUTH_SUCCESS2) { 513 AUTH_ERRLOG(qpair, "invalid state=%s\n", nvmf_auth_get_state_name(auth->state)); 514 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 515 return; 516 } 517 if (req->length != sizeof(*msg)) { 518 AUTH_ERRLOG(qpair, "invalid message length=%"PRIu32"\n", req->length); 519 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 520 return; 521 } 522 if (msg->t_id != auth->tid) { 523 AUTH_ERRLOG(qpair, "transaction id mismatch: %u != %u\n", msg->t_id, auth->tid); 524 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 525 return; 526 } 527 528 AUTH_ERRLOG(qpair, "ctrlr authentication failed: rc=%d, rce=%d\n", msg->rc, msg->rce); 529 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_ERROR); 530 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0); 531 } 532 533 static void 534 nvmf_auth_send_exec(struct spdk_nvmf_request *req) 535 { 536 struct spdk_nvmf_qpair *qpair = req->qpair; 537 struct spdk_nvmf_fabric_auth_send_cmd *cmd = &req->cmd->auth_send_cmd; 538 struct nvmf_auth_common_header *header; 539 int rc; 540 541 rc = nvmf_auth_check_command(req, cmd->secp, cmd->spsp0, cmd->spsp1, cmd->tl); 542 if (rc != 0) { 543 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 544 SPDK_NVME_SC_INVALID_FIELD, 1); 545 return; 546 } 547 548 header = nvmf_auth_get_message(req, sizeof(*header)); 549 if (header == NULL) { 550 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 551 return; 552 } 553 554 switch (header->auth_type) { 555 case SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE: 556 switch (header->auth_id) { 557 case SPDK_NVMF_AUTH_ID_NEGOTIATE: 558 nvmf_auth_negotiate_exec(req, (void *)header); 559 break; 560 case SPDK_NVMF_AUTH_ID_FAILURE2: 561 nvmf_auth_failure2_exec(req, (void *)header); 562 break; 563 default: 564 AUTH_ERRLOG(qpair, "unexpected auth_id=%u\n", header->auth_id); 565 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 566 break; 567 } 568 break; 569 case SPDK_NVMF_AUTH_TYPE_DHCHAP: 570 switch (header->auth_id) { 571 case SPDK_NVMF_AUTH_ID_DHCHAP_REPLY: 572 nvmf_auth_reply_exec(req, (void *)header); 573 break; 574 case SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS2: 575 nvmf_auth_success2_exec(req, (void *)header); 576 break; 577 default: 578 AUTH_ERRLOG(qpair, "unexpected auth_id=%u\n", header->auth_id); 579 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 580 break; 581 } 582 break; 583 default: 584 AUTH_ERRLOG(qpair, "unexpected auth_type=%u\n", header->auth_type); 585 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 586 break; 587 } 588 } 589 590 static void 591 nvmf_auth_recv_complete(struct spdk_nvmf_request *req, uint32_t length) 592 { 593 assert(req->cmd->nvmf_cmd.fctype == SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV); 594 req->length = length; 595 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0); 596 } 597 598 static int 599 nvmf_auth_recv_failure1_done(void *ctx) 600 { 601 struct spdk_nvmf_qpair *qpair = ctx; 602 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 603 604 spdk_poller_unregister(&auth->poller); 605 nvmf_auth_disconnect_qpair(qpair); 606 607 return SPDK_POLLER_BUSY; 608 } 609 610 static void 611 nvmf_auth_recv_failure1(struct spdk_nvmf_request *req, int fail_reason) 612 { 613 struct spdk_nvmf_qpair *qpair = req->qpair; 614 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 615 struct spdk_nvmf_auth_failure *failure; 616 617 failure = nvmf_auth_get_message(req, sizeof(*failure)); 618 if (failure == NULL) { 619 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 620 SPDK_NVME_SC_INVALID_FIELD, 1); 621 nvmf_auth_disconnect_qpair(qpair); 622 return; 623 } 624 625 failure->auth_type = SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE; 626 failure->auth_id = SPDK_NVMF_AUTH_ID_FAILURE1; 627 failure->t_id = auth->tid; 628 failure->rc = SPDK_NVMF_AUTH_FAILURE; 629 failure->rce = fail_reason; 630 631 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_FAILURE1); 632 nvmf_auth_recv_complete(req, sizeof(*failure)); 633 634 spdk_poller_unregister(&auth->poller); 635 auth->poller = SPDK_POLLER_REGISTER(nvmf_auth_recv_failure1_done, qpair, 636 NVMF_AUTH_FAILURE1_DELAY_US); 637 } 638 639 static int 640 nvmf_auth_get_seqnum(struct spdk_nvmf_qpair *qpair) 641 { 642 struct spdk_nvmf_subsystem *subsys = qpair->ctrlr->subsys; 643 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 644 int rc; 645 646 pthread_mutex_lock(&subsys->mutex); 647 if (subsys->auth_seqnum == 0) { 648 rc = RAND_bytes((void *)&subsys->auth_seqnum, sizeof(subsys->auth_seqnum)); 649 if (rc != 1) { 650 pthread_mutex_unlock(&subsys->mutex); 651 return -EIO; 652 } 653 } 654 if (++subsys->auth_seqnum == 0) { 655 subsys->auth_seqnum = 1; 656 657 } 658 auth->seqnum = subsys->auth_seqnum; 659 pthread_mutex_unlock(&subsys->mutex); 660 661 return 0; 662 } 663 664 static int 665 nvmf_auth_recv_challenge(struct spdk_nvmf_request *req) 666 { 667 struct spdk_nvmf_qpair *qpair = req->qpair; 668 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 669 struct spdk_nvmf_dhchap_challenge *challenge; 670 uint8_t hl, dhv[NVMF_AUTH_DH_KEY_MAX_SIZE]; 671 size_t dhvlen = 0; 672 int rc; 673 674 hl = spdk_nvme_dhchap_get_digest_length(auth->digest); 675 assert(hl > 0 && hl <= sizeof(auth->cval)); 676 677 if (auth->dhgroup != SPDK_NVMF_DHCHAP_DHGROUP_NULL) { 678 auth->dhkey = spdk_nvme_dhchap_generate_dhkey(auth->dhgroup); 679 if (auth->dhkey == NULL) { 680 AUTH_ERRLOG(qpair, "failed to generate DH key\n"); 681 return SPDK_NVMF_AUTH_FAILED; 682 } 683 684 dhvlen = sizeof(dhv); 685 rc = spdk_nvme_dhchap_dhkey_get_pubkey(auth->dhkey, dhv, &dhvlen); 686 if (rc != 0) { 687 AUTH_ERRLOG(qpair, "failed to get DH public key\n"); 688 return SPDK_NVMF_AUTH_FAILED; 689 } 690 691 AUTH_LOGDUMP("ctrlr pubkey:", dhv, dhvlen); 692 } 693 694 challenge = nvmf_auth_get_message(req, sizeof(*challenge) + hl + dhvlen); 695 if (challenge == NULL) { 696 AUTH_ERRLOG(qpair, "invalid message length: %"PRIu32"\n", req->length); 697 return SPDK_NVMF_AUTH_INCORRECT_PAYLOAD; 698 } 699 rc = nvmf_auth_get_seqnum(qpair); 700 if (rc != 0) { 701 return SPDK_NVMF_AUTH_FAILED; 702 } 703 rc = RAND_bytes(auth->cval, hl); 704 if (rc != 1) { 705 return SPDK_NVMF_AUTH_FAILED; 706 } 707 if (nvmf_auth_rearm_poller(qpair)) { 708 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 709 SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 1); 710 nvmf_auth_disconnect_qpair(qpair); 711 return 0; 712 } 713 714 memcpy(challenge->cval, auth->cval, hl); 715 memcpy(&challenge->cval[hl], dhv, dhvlen); 716 challenge->auth_type = SPDK_NVMF_AUTH_TYPE_DHCHAP; 717 challenge->auth_id = SPDK_NVMF_AUTH_ID_DHCHAP_CHALLENGE; 718 challenge->t_id = auth->tid; 719 challenge->hl = hl; 720 challenge->hash_id = (uint8_t)auth->digest; 721 challenge->dhg_id = (uint8_t)auth->dhgroup; 722 challenge->dhvlen = dhvlen; 723 challenge->seqnum = auth->seqnum; 724 725 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_REPLY); 726 nvmf_auth_recv_complete(req, sizeof(*challenge) + hl + dhvlen); 727 728 return 0; 729 } 730 731 static int 732 nvmf_auth_recv_success1(struct spdk_nvmf_request *req) 733 { 734 struct spdk_nvmf_qpair *qpair = req->qpair; 735 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 736 struct spdk_nvmf_dhchap_success1 *success; 737 uint8_t hl; 738 739 hl = spdk_nvme_dhchap_get_digest_length(auth->digest); 740 success = nvmf_auth_get_message(req, sizeof(*success) + auth->cvalid * hl); 741 if (success == NULL) { 742 AUTH_ERRLOG(qpair, "invalid message length: %"PRIu32"\n", req->length); 743 return SPDK_NVMF_AUTH_INCORRECT_PAYLOAD; 744 } 745 746 AUTH_DEBUGLOG(qpair, "host authentication successful\n"); 747 success->auth_type = SPDK_NVMF_AUTH_TYPE_DHCHAP; 748 success->auth_id = SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS1; 749 success->t_id = auth->tid; 750 /* Kernel initiator always expects hl to be set, regardless of rvalid */ 751 success->hl = hl; 752 success->rvalid = 0; 753 754 if (!auth->cvalid) { 755 /* Host didn't request to authenticate us, we're done */ 756 nvmf_qpair_set_state(qpair, SPDK_NVMF_QPAIR_ENABLED); 757 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_COMPLETED); 758 nvmf_auth_qpair_cleanup(auth); 759 } else { 760 if (nvmf_auth_rearm_poller(qpair)) { 761 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 762 SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 1); 763 nvmf_auth_disconnect_qpair(qpair); 764 return 0; 765 } 766 AUTH_DEBUGLOG(qpair, "cvalid=1, starting controller authentication\n"); 767 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_SUCCESS2); 768 memcpy(success->rval, auth->cval, hl); 769 success->rvalid = 1; 770 } 771 772 nvmf_auth_recv_complete(req, sizeof(*success) + auth->cvalid * hl); 773 return 0; 774 } 775 776 static void 777 nvmf_auth_recv_exec(struct spdk_nvmf_request *req) 778 { 779 struct spdk_nvmf_qpair *qpair = req->qpair; 780 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 781 struct spdk_nvmf_fabric_auth_recv_cmd *cmd = &req->cmd->auth_recv_cmd; 782 int rc; 783 784 rc = nvmf_auth_check_command(req, cmd->secp, cmd->spsp0, cmd->spsp1, cmd->al); 785 if (rc != 0) { 786 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 787 SPDK_NVME_SC_INVALID_FIELD, 1); 788 return; 789 } 790 791 spdk_iov_memset(req->iov, req->iovcnt, 0); 792 switch (auth->state) { 793 case NVMF_QPAIR_AUTH_CHALLENGE: 794 rc = nvmf_auth_recv_challenge(req); 795 if (rc != 0) { 796 nvmf_auth_recv_failure1(req, rc); 797 } 798 break; 799 case NVMF_QPAIR_AUTH_SUCCESS1: 800 rc = nvmf_auth_recv_success1(req); 801 if (rc != 0) { 802 nvmf_auth_recv_failure1(req, rc); 803 } 804 break; 805 case NVMF_QPAIR_AUTH_FAILURE1: 806 nvmf_auth_recv_failure1(req, auth->fail_reason); 807 break; 808 default: 809 nvmf_auth_recv_failure1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 810 break; 811 } 812 } 813 814 static bool 815 nvmf_auth_check_state(struct spdk_nvmf_qpair *qpair, struct spdk_nvmf_request *req) 816 { 817 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 818 int rc; 819 820 switch (qpair->state) { 821 case SPDK_NVMF_QPAIR_AUTHENTICATING: 822 break; 823 case SPDK_NVMF_QPAIR_ENABLED: 824 if (auth == NULL || auth->state == NVMF_QPAIR_AUTH_COMPLETED) { 825 rc = nvmf_qpair_auth_init(qpair); 826 if (rc != 0) { 827 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 828 SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 0); 829 return false; 830 } 831 } 832 break; 833 default: 834 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 835 SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR, 0); 836 return false; 837 } 838 839 return true; 840 } 841 842 int 843 nvmf_auth_request_exec(struct spdk_nvmf_request *req) 844 { 845 struct spdk_nvmf_qpair *qpair = req->qpair; 846 union nvmf_h2c_msg *cmd = req->cmd; 847 848 if (!nvmf_auth_check_state(qpair, req)) { 849 goto out; 850 } 851 852 assert(cmd->nvmf_cmd.opcode == SPDK_NVME_OPC_FABRIC); 853 switch (cmd->nvmf_cmd.fctype) { 854 case SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND: 855 nvmf_auth_send_exec(req); 856 break; 857 case SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV: 858 nvmf_auth_recv_exec(req); 859 break; 860 default: 861 assert(0 && "invalid fctype"); 862 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 863 SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 0); 864 break; 865 } 866 out: 867 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 868 } 869 870 int 871 nvmf_qpair_auth_init(struct spdk_nvmf_qpair *qpair) 872 { 873 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 874 int rc; 875 876 if (auth == NULL) { 877 auth = calloc(1, sizeof(*qpair->auth)); 878 if (auth == NULL) { 879 return -ENOMEM; 880 } 881 } 882 883 auth->digest = -1; 884 qpair->auth = auth; 885 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_NEGOTIATE); 886 887 rc = nvmf_auth_rearm_poller(qpair); 888 if (rc != 0) { 889 AUTH_ERRLOG(qpair, "failed to arm timeout poller: %s\n", spdk_strerror(-rc)); 890 nvmf_qpair_auth_destroy(qpair); 891 return rc; 892 } 893 894 return 0; 895 } 896 897 void 898 nvmf_qpair_auth_destroy(struct spdk_nvmf_qpair *qpair) 899 { 900 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 901 902 if (auth != NULL) { 903 nvmf_auth_qpair_cleanup(auth); 904 free(qpair->auth); 905 qpair->auth = NULL; 906 } 907 } 908 909 void 910 nvmf_qpair_auth_dump(struct spdk_nvmf_qpair *qpair, struct spdk_json_write_ctx *w) 911 { 912 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 913 const char *digest, *dhgroup; 914 915 if (auth == NULL) { 916 return; 917 } 918 919 spdk_json_write_named_object_begin(w, "auth"); 920 spdk_json_write_named_string(w, "state", nvmf_auth_get_state_name(auth->state)); 921 digest = spdk_nvme_dhchap_get_digest_name(auth->digest); 922 spdk_json_write_named_string(w, "digest", digest ? digest : "unknown"); 923 dhgroup = spdk_nvme_dhchap_get_dhgroup_name(auth->dhgroup); 924 spdk_json_write_named_string(w, "dhgroup", dhgroup ? dhgroup : "unknown"); 925 spdk_json_write_object_end(w); 926 } 927 928 bool 929 nvmf_auth_is_supported(void) 930 { 931 return true; 932 } 933 SPDK_LOG_REGISTER_COMPONENT(nvmf_auth) 934