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