fabrics-cmd-auth.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * NVMe over Fabrics DH-HMAC-CHAP authentication command handling.
  4. * Copyright (c) 2020 Hannes Reinecke, SUSE Software Solutions.
  5. * All rights reserved.
  6. */
  7. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  8. #include <linux/blkdev.h>
  9. #include <linux/random.h>
  10. #include <linux/nvme-auth.h>
  11. #include <crypto/hash.h>
  12. #include <crypto/kpp.h>
  13. #include "nvmet.h"
  14. static void nvmet_auth_expired_work(struct work_struct *work)
  15. {
  16. struct nvmet_sq *sq = container_of(to_delayed_work(work),
  17. struct nvmet_sq, auth_expired_work);
  18. pr_debug("%s: ctrl %d qid %d transaction %u expired, resetting\n",
  19. __func__, sq->ctrl->cntlid, sq->qid, sq->dhchap_tid);
  20. sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
  21. sq->dhchap_tid = -1;
  22. }
  23. void nvmet_auth_sq_init(struct nvmet_sq *sq)
  24. {
  25. /* Initialize in-band authentication */
  26. INIT_DELAYED_WORK(&sq->auth_expired_work, nvmet_auth_expired_work);
  27. sq->authenticated = false;
  28. sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
  29. }
  30. static u16 nvmet_auth_negotiate(struct nvmet_req *req, void *d)
  31. {
  32. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  33. struct nvmf_auth_dhchap_negotiate_data *data = d;
  34. int i, hash_id = 0, fallback_hash_id = 0, dhgid, fallback_dhgid;
  35. pr_debug("%s: ctrl %d qid %d: data sc_d %d napd %d authid %d halen %d dhlen %d\n",
  36. __func__, ctrl->cntlid, req->sq->qid,
  37. data->sc_c, data->napd, data->auth_protocol[0].dhchap.authid,
  38. data->auth_protocol[0].dhchap.halen,
  39. data->auth_protocol[0].dhchap.dhlen);
  40. req->sq->dhchap_tid = le16_to_cpu(data->t_id);
  41. if (data->sc_c)
  42. return NVME_AUTH_DHCHAP_FAILURE_CONCAT_MISMATCH;
  43. if (data->napd != 1)
  44. return NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
  45. if (data->auth_protocol[0].dhchap.authid !=
  46. NVME_AUTH_DHCHAP_AUTH_ID)
  47. return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
  48. for (i = 0; i < data->auth_protocol[0].dhchap.halen; i++) {
  49. u8 host_hmac_id = data->auth_protocol[0].dhchap.idlist[i];
  50. if (!fallback_hash_id &&
  51. crypto_has_shash(nvme_auth_hmac_name(host_hmac_id), 0, 0))
  52. fallback_hash_id = host_hmac_id;
  53. if (ctrl->shash_id != host_hmac_id)
  54. continue;
  55. hash_id = ctrl->shash_id;
  56. break;
  57. }
  58. if (hash_id == 0) {
  59. if (fallback_hash_id == 0) {
  60. pr_debug("%s: ctrl %d qid %d: no usable hash found\n",
  61. __func__, ctrl->cntlid, req->sq->qid);
  62. return NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
  63. }
  64. pr_debug("%s: ctrl %d qid %d: no usable hash found, falling back to %s\n",
  65. __func__, ctrl->cntlid, req->sq->qid,
  66. nvme_auth_hmac_name(fallback_hash_id));
  67. ctrl->shash_id = fallback_hash_id;
  68. }
  69. dhgid = -1;
  70. fallback_dhgid = -1;
  71. for (i = 0; i < data->auth_protocol[0].dhchap.dhlen; i++) {
  72. int tmp_dhgid = data->auth_protocol[0].dhchap.idlist[i + 30];
  73. if (tmp_dhgid != ctrl->dh_gid) {
  74. dhgid = tmp_dhgid;
  75. break;
  76. }
  77. if (fallback_dhgid < 0) {
  78. const char *kpp = nvme_auth_dhgroup_kpp(tmp_dhgid);
  79. if (crypto_has_kpp(kpp, 0, 0))
  80. fallback_dhgid = tmp_dhgid;
  81. }
  82. }
  83. if (dhgid < 0) {
  84. if (fallback_dhgid < 0) {
  85. pr_debug("%s: ctrl %d qid %d: no usable DH group found\n",
  86. __func__, ctrl->cntlid, req->sq->qid);
  87. return NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;
  88. }
  89. pr_debug("%s: ctrl %d qid %d: configured DH group %s not found\n",
  90. __func__, ctrl->cntlid, req->sq->qid,
  91. nvme_auth_dhgroup_name(fallback_dhgid));
  92. ctrl->dh_gid = fallback_dhgid;
  93. }
  94. pr_debug("%s: ctrl %d qid %d: selected DH group %s (%d)\n",
  95. __func__, ctrl->cntlid, req->sq->qid,
  96. nvme_auth_dhgroup_name(ctrl->dh_gid), ctrl->dh_gid);
  97. return 0;
  98. }
  99. static u16 nvmet_auth_reply(struct nvmet_req *req, void *d)
  100. {
  101. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  102. struct nvmf_auth_dhchap_reply_data *data = d;
  103. u16 dhvlen = le16_to_cpu(data->dhvlen);
  104. u8 *response;
  105. pr_debug("%s: ctrl %d qid %d: data hl %d cvalid %d dhvlen %u\n",
  106. __func__, ctrl->cntlid, req->sq->qid,
  107. data->hl, data->cvalid, dhvlen);
  108. if (dhvlen) {
  109. if (!ctrl->dh_tfm)
  110. return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
  111. if (nvmet_auth_ctrl_sesskey(req, data->rval + 2 * data->hl,
  112. dhvlen) < 0)
  113. return NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;
  114. }
  115. response = kmalloc(data->hl, GFP_KERNEL);
  116. if (!response)
  117. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  118. if (!ctrl->host_key) {
  119. pr_warn("ctrl %d qid %d no host key\n",
  120. ctrl->cntlid, req->sq->qid);
  121. kfree(response);
  122. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  123. }
  124. if (nvmet_auth_host_hash(req, response, data->hl) < 0) {
  125. pr_debug("ctrl %d qid %d host hash failed\n",
  126. ctrl->cntlid, req->sq->qid);
  127. kfree(response);
  128. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  129. }
  130. if (memcmp(data->rval, response, data->hl)) {
  131. pr_info("ctrl %d qid %d host response mismatch\n",
  132. ctrl->cntlid, req->sq->qid);
  133. kfree(response);
  134. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  135. }
  136. kfree(response);
  137. pr_debug("%s: ctrl %d qid %d host authenticated\n",
  138. __func__, ctrl->cntlid, req->sq->qid);
  139. if (data->cvalid) {
  140. req->sq->dhchap_c2 = kmemdup(data->rval + data->hl, data->hl,
  141. GFP_KERNEL);
  142. if (!req->sq->dhchap_c2)
  143. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  144. pr_debug("%s: ctrl %d qid %d challenge %*ph\n",
  145. __func__, ctrl->cntlid, req->sq->qid, data->hl,
  146. req->sq->dhchap_c2);
  147. req->sq->dhchap_s2 = le32_to_cpu(data->seqnum);
  148. } else {
  149. req->sq->authenticated = true;
  150. req->sq->dhchap_c2 = NULL;
  151. }
  152. return 0;
  153. }
  154. static u16 nvmet_auth_failure2(void *d)
  155. {
  156. struct nvmf_auth_dhchap_failure_data *data = d;
  157. return data->rescode_exp;
  158. }
  159. void nvmet_execute_auth_send(struct nvmet_req *req)
  160. {
  161. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  162. struct nvmf_auth_dhchap_success2_data *data;
  163. void *d;
  164. u32 tl;
  165. u16 status = 0;
  166. if (req->cmd->auth_send.secp != NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER) {
  167. status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
  168. req->error_loc =
  169. offsetof(struct nvmf_auth_send_command, secp);
  170. goto done;
  171. }
  172. if (req->cmd->auth_send.spsp0 != 0x01) {
  173. status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
  174. req->error_loc =
  175. offsetof(struct nvmf_auth_send_command, spsp0);
  176. goto done;
  177. }
  178. if (req->cmd->auth_send.spsp1 != 0x01) {
  179. status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
  180. req->error_loc =
  181. offsetof(struct nvmf_auth_send_command, spsp1);
  182. goto done;
  183. }
  184. tl = le32_to_cpu(req->cmd->auth_send.tl);
  185. if (!tl) {
  186. status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
  187. req->error_loc =
  188. offsetof(struct nvmf_auth_send_command, tl);
  189. goto done;
  190. }
  191. if (!nvmet_check_transfer_len(req, tl)) {
  192. pr_debug("%s: transfer length mismatch (%u)\n", __func__, tl);
  193. return;
  194. }
  195. d = kmalloc(tl, GFP_KERNEL);
  196. if (!d) {
  197. status = NVME_SC_INTERNAL;
  198. goto done;
  199. }
  200. status = nvmet_copy_from_sgl(req, 0, d, tl);
  201. if (status)
  202. goto done_kfree;
  203. data = d;
  204. pr_debug("%s: ctrl %d qid %d type %d id %d step %x\n", __func__,
  205. ctrl->cntlid, req->sq->qid, data->auth_type, data->auth_id,
  206. req->sq->dhchap_step);
  207. if (data->auth_type != NVME_AUTH_COMMON_MESSAGES &&
  208. data->auth_type != NVME_AUTH_DHCHAP_MESSAGES)
  209. goto done_failure1;
  210. if (data->auth_type == NVME_AUTH_COMMON_MESSAGES) {
  211. if (data->auth_id == NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE) {
  212. /* Restart negotiation */
  213. pr_debug("%s: ctrl %d qid %d reset negotiation\n", __func__,
  214. ctrl->cntlid, req->sq->qid);
  215. if (!req->sq->qid) {
  216. if (nvmet_setup_auth(ctrl) < 0) {
  217. status = NVME_SC_INTERNAL;
  218. pr_err("ctrl %d qid 0 failed to setup"
  219. "re-authentication",
  220. ctrl->cntlid);
  221. goto done_failure1;
  222. }
  223. }
  224. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
  225. } else if (data->auth_id != req->sq->dhchap_step)
  226. goto done_failure1;
  227. /* Validate negotiation parameters */
  228. status = nvmet_auth_negotiate(req, d);
  229. if (status == 0)
  230. req->sq->dhchap_step =
  231. NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE;
  232. else {
  233. req->sq->dhchap_step =
  234. NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  235. req->sq->dhchap_status = status;
  236. status = 0;
  237. }
  238. goto done_kfree;
  239. }
  240. if (data->auth_id != req->sq->dhchap_step) {
  241. pr_debug("%s: ctrl %d qid %d step mismatch (%d != %d)\n",
  242. __func__, ctrl->cntlid, req->sq->qid,
  243. data->auth_id, req->sq->dhchap_step);
  244. goto done_failure1;
  245. }
  246. if (le16_to_cpu(data->t_id) != req->sq->dhchap_tid) {
  247. pr_debug("%s: ctrl %d qid %d invalid transaction %d (expected %d)\n",
  248. __func__, ctrl->cntlid, req->sq->qid,
  249. le16_to_cpu(data->t_id),
  250. req->sq->dhchap_tid);
  251. req->sq->dhchap_step =
  252. NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  253. req->sq->dhchap_status =
  254. NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
  255. goto done_kfree;
  256. }
  257. switch (data->auth_id) {
  258. case NVME_AUTH_DHCHAP_MESSAGE_REPLY:
  259. status = nvmet_auth_reply(req, d);
  260. if (status == 0)
  261. req->sq->dhchap_step =
  262. NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1;
  263. else {
  264. req->sq->dhchap_step =
  265. NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  266. req->sq->dhchap_status = status;
  267. status = 0;
  268. }
  269. goto done_kfree;
  270. break;
  271. case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2:
  272. req->sq->authenticated = true;
  273. pr_debug("%s: ctrl %d qid %d ctrl authenticated\n",
  274. __func__, ctrl->cntlid, req->sq->qid);
  275. goto done_kfree;
  276. break;
  277. case NVME_AUTH_DHCHAP_MESSAGE_FAILURE2:
  278. status = nvmet_auth_failure2(d);
  279. if (status) {
  280. pr_warn("ctrl %d qid %d: authentication failed (%d)\n",
  281. ctrl->cntlid, req->sq->qid, status);
  282. req->sq->dhchap_status = status;
  283. req->sq->authenticated = false;
  284. status = 0;
  285. }
  286. goto done_kfree;
  287. break;
  288. default:
  289. req->sq->dhchap_status =
  290. NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE;
  291. req->sq->dhchap_step =
  292. NVME_AUTH_DHCHAP_MESSAGE_FAILURE2;
  293. req->sq->authenticated = false;
  294. goto done_kfree;
  295. break;
  296. }
  297. done_failure1:
  298. req->sq->dhchap_status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE;
  299. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_FAILURE2;
  300. done_kfree:
  301. kfree(d);
  302. done:
  303. pr_debug("%s: ctrl %d qid %d dhchap status %x step %x\n", __func__,
  304. ctrl->cntlid, req->sq->qid,
  305. req->sq->dhchap_status, req->sq->dhchap_step);
  306. if (status)
  307. pr_debug("%s: ctrl %d qid %d nvme status %x error loc %d\n",
  308. __func__, ctrl->cntlid, req->sq->qid,
  309. status, req->error_loc);
  310. req->cqe->result.u64 = 0;
  311. if (req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2 &&
  312. req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) {
  313. unsigned long auth_expire_secs = ctrl->kato ? ctrl->kato : 120;
  314. mod_delayed_work(system_wq, &req->sq->auth_expired_work,
  315. auth_expire_secs * HZ);
  316. goto complete;
  317. }
  318. /* Final states, clear up variables */
  319. nvmet_auth_sq_free(req->sq);
  320. if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2)
  321. nvmet_ctrl_fatal_error(ctrl);
  322. complete:
  323. nvmet_req_complete(req, status);
  324. }
  325. static int nvmet_auth_challenge(struct nvmet_req *req, void *d, int al)
  326. {
  327. struct nvmf_auth_dhchap_challenge_data *data = d;
  328. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  329. int ret = 0;
  330. int hash_len = nvme_auth_hmac_hash_len(ctrl->shash_id);
  331. int data_size = sizeof(*d) + hash_len;
  332. if (ctrl->dh_tfm)
  333. data_size += ctrl->dh_keysize;
  334. if (al < data_size) {
  335. pr_debug("%s: buffer too small (al %d need %d)\n", __func__,
  336. al, data_size);
  337. return -EINVAL;
  338. }
  339. memset(data, 0, data_size);
  340. req->sq->dhchap_s1 = nvme_auth_get_seqnum();
  341. data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
  342. data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE;
  343. data->t_id = cpu_to_le16(req->sq->dhchap_tid);
  344. data->hashid = ctrl->shash_id;
  345. data->hl = hash_len;
  346. data->seqnum = cpu_to_le32(req->sq->dhchap_s1);
  347. req->sq->dhchap_c1 = kmalloc(data->hl, GFP_KERNEL);
  348. if (!req->sq->dhchap_c1)
  349. return -ENOMEM;
  350. get_random_bytes(req->sq->dhchap_c1, data->hl);
  351. memcpy(data->cval, req->sq->dhchap_c1, data->hl);
  352. if (ctrl->dh_tfm) {
  353. data->dhgid = ctrl->dh_gid;
  354. data->dhvlen = cpu_to_le16(ctrl->dh_keysize);
  355. ret = nvmet_auth_ctrl_exponential(req, data->cval + data->hl,
  356. ctrl->dh_keysize);
  357. }
  358. pr_debug("%s: ctrl %d qid %d seq %d transaction %d hl %d dhvlen %zu\n",
  359. __func__, ctrl->cntlid, req->sq->qid, req->sq->dhchap_s1,
  360. req->sq->dhchap_tid, data->hl, ctrl->dh_keysize);
  361. return ret;
  362. }
  363. static int nvmet_auth_success1(struct nvmet_req *req, void *d, int al)
  364. {
  365. struct nvmf_auth_dhchap_success1_data *data = d;
  366. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  367. int hash_len = nvme_auth_hmac_hash_len(ctrl->shash_id);
  368. WARN_ON(al < sizeof(*data));
  369. memset(data, 0, sizeof(*data));
  370. data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
  371. data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1;
  372. data->t_id = cpu_to_le16(req->sq->dhchap_tid);
  373. data->hl = hash_len;
  374. if (req->sq->dhchap_c2) {
  375. if (!ctrl->ctrl_key) {
  376. pr_warn("ctrl %d qid %d no ctrl key\n",
  377. ctrl->cntlid, req->sq->qid);
  378. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  379. }
  380. if (nvmet_auth_ctrl_hash(req, data->rval, data->hl))
  381. return NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
  382. data->rvalid = 1;
  383. pr_debug("ctrl %d qid %d response %*ph\n",
  384. ctrl->cntlid, req->sq->qid, data->hl, data->rval);
  385. }
  386. return 0;
  387. }
  388. static void nvmet_auth_failure1(struct nvmet_req *req, void *d, int al)
  389. {
  390. struct nvmf_auth_dhchap_failure_data *data = d;
  391. WARN_ON(al < sizeof(*data));
  392. data->auth_type = NVME_AUTH_COMMON_MESSAGES;
  393. data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  394. data->t_id = cpu_to_le16(req->sq->dhchap_tid);
  395. data->rescode = NVME_AUTH_DHCHAP_FAILURE_REASON_FAILED;
  396. data->rescode_exp = req->sq->dhchap_status;
  397. }
  398. void nvmet_execute_auth_receive(struct nvmet_req *req)
  399. {
  400. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  401. void *d;
  402. u32 al;
  403. u16 status = 0;
  404. if (req->cmd->auth_receive.secp != NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER) {
  405. status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
  406. req->error_loc =
  407. offsetof(struct nvmf_auth_receive_command, secp);
  408. goto done;
  409. }
  410. if (req->cmd->auth_receive.spsp0 != 0x01) {
  411. status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
  412. req->error_loc =
  413. offsetof(struct nvmf_auth_receive_command, spsp0);
  414. goto done;
  415. }
  416. if (req->cmd->auth_receive.spsp1 != 0x01) {
  417. status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
  418. req->error_loc =
  419. offsetof(struct nvmf_auth_receive_command, spsp1);
  420. goto done;
  421. }
  422. al = le32_to_cpu(req->cmd->auth_receive.al);
  423. if (!al) {
  424. status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
  425. req->error_loc =
  426. offsetof(struct nvmf_auth_receive_command, al);
  427. goto done;
  428. }
  429. if (!nvmet_check_transfer_len(req, al)) {
  430. pr_debug("%s: transfer length mismatch (%u)\n", __func__, al);
  431. return;
  432. }
  433. d = kmalloc(al, GFP_KERNEL);
  434. if (!d) {
  435. status = NVME_SC_INTERNAL;
  436. goto done;
  437. }
  438. pr_debug("%s: ctrl %d qid %d step %x\n", __func__,
  439. ctrl->cntlid, req->sq->qid, req->sq->dhchap_step);
  440. switch (req->sq->dhchap_step) {
  441. case NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE:
  442. if (nvmet_auth_challenge(req, d, al) < 0) {
  443. pr_warn("ctrl %d qid %d: challenge error (%d)\n",
  444. ctrl->cntlid, req->sq->qid, status);
  445. status = NVME_SC_INTERNAL;
  446. break;
  447. }
  448. if (status) {
  449. req->sq->dhchap_status = status;
  450. nvmet_auth_failure1(req, d, al);
  451. pr_warn("ctrl %d qid %d: challenge status (%x)\n",
  452. ctrl->cntlid, req->sq->qid,
  453. req->sq->dhchap_status);
  454. status = 0;
  455. break;
  456. }
  457. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_REPLY;
  458. break;
  459. case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1:
  460. status = nvmet_auth_success1(req, d, al);
  461. if (status) {
  462. req->sq->dhchap_status = status;
  463. req->sq->authenticated = false;
  464. nvmet_auth_failure1(req, d, al);
  465. pr_warn("ctrl %d qid %d: success1 status (%x)\n",
  466. ctrl->cntlid, req->sq->qid,
  467. req->sq->dhchap_status);
  468. break;
  469. }
  470. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2;
  471. break;
  472. case NVME_AUTH_DHCHAP_MESSAGE_FAILURE1:
  473. req->sq->authenticated = false;
  474. nvmet_auth_failure1(req, d, al);
  475. pr_warn("ctrl %d qid %d failure1 (%x)\n",
  476. ctrl->cntlid, req->sq->qid, req->sq->dhchap_status);
  477. break;
  478. default:
  479. pr_warn("ctrl %d qid %d unhandled step (%d)\n",
  480. ctrl->cntlid, req->sq->qid, req->sq->dhchap_step);
  481. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  482. req->sq->dhchap_status = NVME_AUTH_DHCHAP_FAILURE_FAILED;
  483. nvmet_auth_failure1(req, d, al);
  484. status = 0;
  485. break;
  486. }
  487. status = nvmet_copy_to_sgl(req, 0, d, al);
  488. kfree(d);
  489. done:
  490. req->cqe->result.u64 = 0;
  491. if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2)
  492. nvmet_auth_sq_free(req->sq);
  493. else if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) {
  494. nvmet_auth_sq_free(req->sq);
  495. nvmet_ctrl_fatal_error(ctrl);
  496. }
  497. nvmet_req_complete(req, status);
  498. }