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 (req->length != sizeof(*msg) + 2 * hl + msg->dhvlen) { 365 AUTH_ERRLOG(qpair, "invalid message length: %"PRIu32" != %zu\n", 366 req->length, sizeof(*msg) + 2 * hl); 367 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 368 goto out; 369 } 370 if (msg->t_id != auth->tid) { 371 AUTH_ERRLOG(qpair, "transaction id mismatch: %u != %u\n", msg->t_id, auth->tid); 372 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 373 goto out; 374 } 375 if (msg->cvalid != 0 && msg->cvalid != 1) { 376 AUTH_ERRLOG(qpair, "unexpected cvalid=%d\n", msg->cvalid); 377 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 378 goto out; 379 } 380 if (msg->cvalid && msg->seqnum == 0) { 381 AUTH_ERRLOG(qpair, "unexpected seqnum=0 with cvalid=1\n"); 382 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 383 goto out; 384 } 385 386 key = nvmf_subsystem_get_dhchap_key(ctrlr->subsys, ctrlr->hostnqn, NVMF_AUTH_KEY_HOST); 387 if (key == NULL) { 388 AUTH_ERRLOG(qpair, "couldn't get DH-HMAC-CHAP key\n"); 389 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 390 goto out; 391 } 392 393 if (auth->dhgroup != SPDK_NVMF_DHCHAP_DHGROUP_NULL) { 394 AUTH_LOGDUMP("host pubkey:", &msg->rval[2 * hl], msg->dhvlen); 395 dhseclen = sizeof(dhsec); 396 rc = spdk_nvme_dhchap_dhkey_derive_secret(auth->dhkey, &msg->rval[2 * hl], 397 msg->dhvlen, dhsec, &dhseclen); 398 if (rc != 0) { 399 AUTH_ERRLOG(qpair, "couldn't derive DH secret\n"); 400 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 401 goto out; 402 } 403 404 AUTH_LOGDUMP("dh secret:", dhsec, dhseclen); 405 } 406 407 assert(hl <= sizeof(response) && hl <= sizeof(auth->cval)); 408 rc = spdk_nvme_dhchap_calculate(key, (enum spdk_nvmf_dhchap_hash)auth->digest, 409 "HostHost", auth->seqnum, auth->tid, 0, 410 ctrlr->hostnqn, ctrlr->subsys->subnqn, 411 dhseclen > 0 ? dhsec : NULL, dhseclen, 412 auth->cval, response); 413 if (rc != 0) { 414 AUTH_ERRLOG(qpair, "failed to calculate challenge response: %s\n", 415 spdk_strerror(-rc)); 416 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 417 goto out; 418 } 419 420 if (memcmp(msg->rval, response, hl) != 0) { 421 AUTH_ERRLOG(qpair, "challenge response mismatch\n"); 422 AUTH_LOGDUMP("response:", msg->rval, hl); 423 AUTH_LOGDUMP("expected:", response, hl); 424 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 425 goto out; 426 } 427 428 if (msg->cvalid) { 429 ckey = nvmf_subsystem_get_dhchap_key(ctrlr->subsys, ctrlr->hostnqn, 430 NVMF_AUTH_KEY_CTRLR); 431 if (ckey == NULL) { 432 AUTH_ERRLOG(qpair, "missing DH-HMAC-CHAP ctrlr key\n"); 433 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 434 goto out; 435 } 436 rc = spdk_nvme_dhchap_calculate(ckey, (enum spdk_nvmf_dhchap_hash)auth->digest, 437 "Controller", msg->seqnum, auth->tid, 0, 438 ctrlr->subsys->subnqn, ctrlr->hostnqn, 439 dhseclen > 0 ? dhsec : NULL, dhseclen, 440 &msg->rval[hl], auth->cval); 441 if (rc != 0) { 442 AUTH_ERRLOG(qpair, "failed to calculate ctrlr challenge response: %s\n", 443 spdk_strerror(-rc)); 444 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_FAILED); 445 goto out; 446 } 447 auth->cvalid = true; 448 } 449 450 if (nvmf_auth_rearm_poller(qpair)) { 451 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 452 SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 1); 453 nvmf_auth_disconnect_qpair(qpair); 454 goto out; 455 } 456 457 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_SUCCESS1); 458 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0); 459 out: 460 spdk_keyring_put_key(ckey); 461 spdk_keyring_put_key(key); 462 } 463 464 static void 465 nvmf_auth_success2_exec(struct spdk_nvmf_request *req, struct spdk_nvmf_dhchap_success2 *msg) 466 { 467 struct spdk_nvmf_qpair *qpair = req->qpair; 468 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 469 470 if (auth->state != NVMF_QPAIR_AUTH_SUCCESS2) { 471 AUTH_ERRLOG(qpair, "invalid state=%s\n", nvmf_auth_get_state_name(auth->state)); 472 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 473 return; 474 } 475 if (req->length != sizeof(*msg)) { 476 AUTH_ERRLOG(qpair, "invalid message length=%"PRIu32"\n", req->length); 477 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 478 return; 479 } 480 if (msg->t_id != auth->tid) { 481 AUTH_ERRLOG(qpair, "transaction id mismatch: %u != %u\n", msg->t_id, auth->tid); 482 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 483 return; 484 } 485 486 AUTH_DEBUGLOG(qpair, "controller authentication successful\n"); 487 nvmf_qpair_set_state(qpair, SPDK_NVMF_QPAIR_ENABLED); 488 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_COMPLETED); 489 nvmf_auth_qpair_cleanup(auth); 490 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0); 491 } 492 493 static void 494 nvmf_auth_failure2_exec(struct spdk_nvmf_request *req, struct spdk_nvmf_auth_failure *msg) 495 { 496 struct spdk_nvmf_qpair *qpair = req->qpair; 497 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 498 499 /* AUTH_failure2 is only expected when we're waiting for the success2 message */ 500 if (auth->state != NVMF_QPAIR_AUTH_SUCCESS2) { 501 AUTH_ERRLOG(qpair, "invalid state=%s\n", nvmf_auth_get_state_name(auth->state)); 502 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 503 return; 504 } 505 if (req->length != sizeof(*msg)) { 506 AUTH_ERRLOG(qpair, "invalid message length=%"PRIu32"\n", req->length); 507 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 508 return; 509 } 510 if (msg->t_id != auth->tid) { 511 AUTH_ERRLOG(qpair, "transaction id mismatch: %u != %u\n", msg->t_id, auth->tid); 512 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 513 return; 514 } 515 516 AUTH_ERRLOG(qpair, "ctrlr authentication failed: rc=%d, rce=%d\n", msg->rc, msg->rce); 517 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_ERROR); 518 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0); 519 } 520 521 static void 522 nvmf_auth_send_exec(struct spdk_nvmf_request *req) 523 { 524 struct spdk_nvmf_qpair *qpair = req->qpair; 525 struct spdk_nvmf_fabric_auth_send_cmd *cmd = &req->cmd->auth_send_cmd; 526 struct nvmf_auth_common_header *header; 527 int rc; 528 529 rc = nvmf_auth_check_command(req, cmd->secp, cmd->spsp0, cmd->spsp1, cmd->tl); 530 if (rc != 0) { 531 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 532 SPDK_NVME_SC_INVALID_FIELD, 1); 533 return; 534 } 535 536 header = nvmf_auth_get_message(req, sizeof(*header)); 537 if (header == NULL) { 538 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD); 539 return; 540 } 541 542 switch (header->auth_type) { 543 case SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE: 544 switch (header->auth_id) { 545 case SPDK_NVMF_AUTH_ID_NEGOTIATE: 546 nvmf_auth_negotiate_exec(req, (void *)header); 547 break; 548 case SPDK_NVMF_AUTH_ID_FAILURE2: 549 nvmf_auth_failure2_exec(req, (void *)header); 550 break; 551 default: 552 AUTH_ERRLOG(qpair, "unexpected auth_id=%u\n", header->auth_id); 553 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 554 break; 555 } 556 break; 557 case SPDK_NVMF_AUTH_TYPE_DHCHAP: 558 switch (header->auth_id) { 559 case SPDK_NVMF_AUTH_ID_DHCHAP_REPLY: 560 nvmf_auth_reply_exec(req, (void *)header); 561 break; 562 case SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS2: 563 nvmf_auth_success2_exec(req, (void *)header); 564 break; 565 default: 566 AUTH_ERRLOG(qpair, "unexpected auth_id=%u\n", header->auth_id); 567 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 568 break; 569 } 570 break; 571 default: 572 AUTH_ERRLOG(qpair, "unexpected auth_type=%u\n", header->auth_type); 573 nvmf_auth_request_fail1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 574 break; 575 } 576 } 577 578 static void 579 nvmf_auth_recv_complete(struct spdk_nvmf_request *req, uint32_t length) 580 { 581 assert(req->cmd->nvmf_cmd.fctype == SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV); 582 req->length = length; 583 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, SPDK_NVME_SC_SUCCESS, 0); 584 } 585 586 static void 587 nvmf_auth_recv_failure1(struct spdk_nvmf_request *req, int fail_reason) 588 { 589 struct spdk_nvmf_qpair *qpair = req->qpair; 590 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 591 struct spdk_nvmf_auth_failure *failure; 592 593 failure = nvmf_auth_get_message(req, sizeof(*failure)); 594 if (failure == NULL) { 595 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 596 SPDK_NVME_SC_INVALID_FIELD, 1); 597 nvmf_auth_disconnect_qpair(qpair); 598 return; 599 } 600 601 failure->auth_type = SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE; 602 failure->auth_id = SPDK_NVMF_AUTH_ID_FAILURE1; 603 failure->t_id = auth->tid; 604 failure->rc = SPDK_NVMF_AUTH_FAILURE; 605 failure->rce = fail_reason; 606 607 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_FAILURE1); 608 nvmf_auth_recv_complete(req, sizeof(*failure)); 609 nvmf_auth_disconnect_qpair(qpair); 610 } 611 612 static int 613 nvmf_auth_get_seqnum(struct spdk_nvmf_qpair *qpair) 614 { 615 struct spdk_nvmf_subsystem *subsys = qpair->ctrlr->subsys; 616 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 617 int rc; 618 619 pthread_mutex_lock(&subsys->mutex); 620 if (subsys->auth_seqnum == 0) { 621 rc = RAND_bytes((void *)&subsys->auth_seqnum, sizeof(subsys->auth_seqnum)); 622 if (rc != 1) { 623 pthread_mutex_unlock(&subsys->mutex); 624 return -EIO; 625 } 626 } 627 if (++subsys->auth_seqnum == 0) { 628 subsys->auth_seqnum = 1; 629 630 } 631 auth->seqnum = subsys->auth_seqnum; 632 pthread_mutex_unlock(&subsys->mutex); 633 634 return 0; 635 } 636 637 static int 638 nvmf_auth_recv_challenge(struct spdk_nvmf_request *req) 639 { 640 struct spdk_nvmf_qpair *qpair = req->qpair; 641 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 642 struct spdk_nvmf_dhchap_challenge *challenge; 643 uint8_t hl, dhv[NVMF_AUTH_DH_KEY_MAX_SIZE]; 644 size_t dhvlen = 0; 645 int rc; 646 647 hl = spdk_nvme_dhchap_get_digest_length(auth->digest); 648 assert(hl > 0 && hl <= sizeof(auth->cval)); 649 650 if (auth->dhgroup != SPDK_NVMF_DHCHAP_DHGROUP_NULL) { 651 auth->dhkey = spdk_nvme_dhchap_generate_dhkey(auth->dhgroup); 652 if (auth->dhkey == NULL) { 653 AUTH_ERRLOG(qpair, "failed to generate DH key\n"); 654 return SPDK_NVMF_AUTH_FAILED; 655 } 656 657 dhvlen = sizeof(dhv); 658 rc = spdk_nvme_dhchap_dhkey_get_pubkey(auth->dhkey, dhv, &dhvlen); 659 if (rc != 0) { 660 AUTH_ERRLOG(qpair, "failed to get DH public key\n"); 661 return SPDK_NVMF_AUTH_FAILED; 662 } 663 664 AUTH_LOGDUMP("ctrlr pubkey:", dhv, dhvlen); 665 } 666 667 challenge = nvmf_auth_get_message(req, sizeof(*challenge) + hl + dhvlen); 668 if (challenge == NULL) { 669 AUTH_ERRLOG(qpair, "invalid message length: %"PRIu32"\n", req->length); 670 return SPDK_NVMF_AUTH_INCORRECT_PAYLOAD; 671 } 672 rc = nvmf_auth_get_seqnum(qpair); 673 if (rc != 0) { 674 return SPDK_NVMF_AUTH_FAILED; 675 } 676 rc = RAND_bytes(auth->cval, hl); 677 if (rc != 1) { 678 return SPDK_NVMF_AUTH_FAILED; 679 } 680 if (nvmf_auth_rearm_poller(qpair)) { 681 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 682 SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 1); 683 nvmf_auth_disconnect_qpair(qpair); 684 return 0; 685 } 686 687 memcpy(challenge->cval, auth->cval, hl); 688 memcpy(&challenge->cval[hl], dhv, dhvlen); 689 challenge->auth_type = SPDK_NVMF_AUTH_TYPE_DHCHAP; 690 challenge->auth_id = SPDK_NVMF_AUTH_ID_DHCHAP_CHALLENGE; 691 challenge->t_id = auth->tid; 692 challenge->hl = hl; 693 challenge->hash_id = (uint8_t)auth->digest; 694 challenge->dhg_id = (uint8_t)auth->dhgroup; 695 challenge->dhvlen = dhvlen; 696 challenge->seqnum = auth->seqnum; 697 698 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_REPLY); 699 nvmf_auth_recv_complete(req, sizeof(*challenge) + hl + dhvlen); 700 701 return 0; 702 } 703 704 static int 705 nvmf_auth_recv_success1(struct spdk_nvmf_request *req) 706 { 707 struct spdk_nvmf_qpair *qpair = req->qpair; 708 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 709 struct spdk_nvmf_dhchap_success1 *success; 710 uint8_t hl; 711 712 hl = spdk_nvme_dhchap_get_digest_length(auth->digest); 713 success = nvmf_auth_get_message(req, sizeof(*success) + auth->cvalid * hl); 714 if (success == NULL) { 715 AUTH_ERRLOG(qpair, "invalid message length: %"PRIu32"\n", req->length); 716 return SPDK_NVMF_AUTH_INCORRECT_PAYLOAD; 717 } 718 719 AUTH_DEBUGLOG(qpair, "host authentication successful\n"); 720 success->auth_type = SPDK_NVMF_AUTH_TYPE_DHCHAP; 721 success->auth_id = SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS1; 722 success->t_id = auth->tid; 723 /* Kernel initiator always expects hl to be set, regardless of rvalid */ 724 success->hl = hl; 725 success->rvalid = 0; 726 727 if (!auth->cvalid) { 728 /* Host didn't request to authenticate us, we're done */ 729 nvmf_qpair_set_state(qpair, SPDK_NVMF_QPAIR_ENABLED); 730 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_COMPLETED); 731 nvmf_auth_qpair_cleanup(auth); 732 } else { 733 if (nvmf_auth_rearm_poller(qpair)) { 734 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 735 SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 1); 736 nvmf_auth_disconnect_qpair(qpair); 737 return 0; 738 } 739 AUTH_DEBUGLOG(qpair, "cvalid=1, starting controller authentication\n"); 740 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_SUCCESS2); 741 memcpy(success->rval, auth->cval, hl); 742 success->rvalid = 1; 743 } 744 745 nvmf_auth_recv_complete(req, sizeof(*success) + auth->cvalid * hl); 746 return 0; 747 } 748 749 static void 750 nvmf_auth_recv_exec(struct spdk_nvmf_request *req) 751 { 752 struct spdk_nvmf_qpair *qpair = req->qpair; 753 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 754 struct spdk_nvmf_fabric_auth_recv_cmd *cmd = &req->cmd->auth_recv_cmd; 755 int rc; 756 757 rc = nvmf_auth_check_command(req, cmd->secp, cmd->spsp0, cmd->spsp1, cmd->al); 758 if (rc != 0) { 759 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 760 SPDK_NVME_SC_INVALID_FIELD, 1); 761 return; 762 } 763 764 spdk_iov_memset(req->iov, req->iovcnt, 0); 765 switch (auth->state) { 766 case NVMF_QPAIR_AUTH_CHALLENGE: 767 rc = nvmf_auth_recv_challenge(req); 768 if (rc != 0) { 769 nvmf_auth_recv_failure1(req, rc); 770 } 771 break; 772 case NVMF_QPAIR_AUTH_SUCCESS1: 773 rc = nvmf_auth_recv_success1(req); 774 if (rc != 0) { 775 nvmf_auth_recv_failure1(req, rc); 776 } 777 break; 778 case NVMF_QPAIR_AUTH_FAILURE1: 779 nvmf_auth_recv_failure1(req, auth->fail_reason); 780 break; 781 default: 782 nvmf_auth_recv_failure1(req, SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE); 783 break; 784 } 785 } 786 787 int 788 nvmf_auth_request_exec(struct spdk_nvmf_request *req) 789 { 790 struct spdk_nvmf_qpair *qpair = req->qpair; 791 union nvmf_h2c_msg *cmd = req->cmd; 792 793 /* We don't support reauthentication */ 794 if (qpair->state != SPDK_NVMF_QPAIR_AUTHENTICATING) { 795 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 796 SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR, 0); 797 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 798 } 799 800 assert(cmd->nvmf_cmd.opcode == SPDK_NVME_OPC_FABRIC); 801 switch (cmd->nvmf_cmd.fctype) { 802 case SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND: 803 nvmf_auth_send_exec(req); 804 break; 805 case SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV: 806 nvmf_auth_recv_exec(req); 807 break; 808 default: 809 assert(0 && "invalid fctype"); 810 nvmf_auth_request_complete(req, SPDK_NVME_SCT_GENERIC, 811 SPDK_NVME_SC_INTERNAL_DEVICE_ERROR, 0); 812 break; 813 } 814 815 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 816 } 817 818 int 819 nvmf_qpair_auth_init(struct spdk_nvmf_qpair *qpair) 820 { 821 struct spdk_nvmf_qpair_auth *auth; 822 int rc; 823 824 assert(qpair->auth == NULL); 825 auth = calloc(1, sizeof(*qpair->auth)); 826 if (auth == NULL) { 827 return -ENOMEM; 828 } 829 830 auth->digest = -1; 831 qpair->auth = auth; 832 nvmf_auth_set_state(qpair, NVMF_QPAIR_AUTH_NEGOTIATE); 833 834 rc = nvmf_auth_rearm_poller(qpair); 835 if (rc != 0) { 836 AUTH_ERRLOG(qpair, "failed to arm timeout poller: %s\n", spdk_strerror(-rc)); 837 nvmf_qpair_auth_destroy(qpair); 838 return rc; 839 } 840 841 return 0; 842 } 843 844 void 845 nvmf_qpair_auth_destroy(struct spdk_nvmf_qpair *qpair) 846 { 847 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 848 849 if (auth != NULL) { 850 nvmf_auth_qpair_cleanup(auth); 851 free(qpair->auth); 852 qpair->auth = NULL; 853 } 854 } 855 856 void 857 nvmf_qpair_auth_dump(struct spdk_nvmf_qpair *qpair, struct spdk_json_write_ctx *w) 858 { 859 struct spdk_nvmf_qpair_auth *auth = qpair->auth; 860 const char *digest, *dhgroup; 861 862 if (auth == NULL) { 863 return; 864 } 865 866 spdk_json_write_named_object_begin(w, "auth"); 867 spdk_json_write_named_string(w, "state", nvmf_auth_get_state_name(auth->state)); 868 digest = spdk_nvme_dhchap_get_digest_name(auth->digest); 869 spdk_json_write_named_string(w, "digest", digest ? digest : "unknown"); 870 dhgroup = spdk_nvme_dhchap_get_dhgroup_name(auth->dhgroup); 871 spdk_json_write_named_string(w, "dhgroup", dhgroup ? dhgroup : "unknown"); 872 spdk_json_write_object_end(w); 873 } 874 875 bool 876 nvmf_auth_is_supported(void) 877 { 878 return true; 879 } 880 SPDK_LOG_REGISTER_COMPONENT(nvmf_auth) 881