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