fabrics-cmd-auth.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  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 u8 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 u8 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. } else {
  148. req->sq->authenticated = true;
  149. req->sq->dhchap_c2 = NULL;
  150. }
  151. req->sq->dhchap_s2 = le32_to_cpu(data->seqnum);
  152. return 0;
  153. }
  154. static u8 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. u8 dhchap_status;
  167. if (req->cmd->auth_send.secp != NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER) {
  168. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  169. req->error_loc =
  170. offsetof(struct nvmf_auth_send_command, secp);
  171. goto done;
  172. }
  173. if (req->cmd->auth_send.spsp0 != 0x01) {
  174. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  175. req->error_loc =
  176. offsetof(struct nvmf_auth_send_command, spsp0);
  177. goto done;
  178. }
  179. if (req->cmd->auth_send.spsp1 != 0x01) {
  180. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  181. req->error_loc =
  182. offsetof(struct nvmf_auth_send_command, spsp1);
  183. goto done;
  184. }
  185. tl = le32_to_cpu(req->cmd->auth_send.tl);
  186. if (!tl) {
  187. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  188. req->error_loc =
  189. offsetof(struct nvmf_auth_send_command, tl);
  190. goto done;
  191. }
  192. if (!nvmet_check_transfer_len(req, tl)) {
  193. pr_debug("%s: transfer length mismatch (%u)\n", __func__, tl);
  194. return;
  195. }
  196. d = kmalloc(tl, GFP_KERNEL);
  197. if (!d) {
  198. status = NVME_SC_INTERNAL;
  199. goto done;
  200. }
  201. status = nvmet_copy_from_sgl(req, 0, d, tl);
  202. if (status)
  203. goto done_kfree;
  204. data = d;
  205. pr_debug("%s: ctrl %d qid %d type %d id %d step %x\n", __func__,
  206. ctrl->cntlid, req->sq->qid, data->auth_type, data->auth_id,
  207. req->sq->dhchap_step);
  208. if (data->auth_type != NVME_AUTH_COMMON_MESSAGES &&
  209. data->auth_type != NVME_AUTH_DHCHAP_MESSAGES)
  210. goto done_failure1;
  211. if (data->auth_type == NVME_AUTH_COMMON_MESSAGES) {
  212. if (data->auth_id == NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE) {
  213. /* Restart negotiation */
  214. pr_debug("%s: ctrl %d qid %d reset negotiation\n",
  215. __func__, ctrl->cntlid, req->sq->qid);
  216. if (!req->sq->qid) {
  217. dhchap_status = nvmet_setup_auth(ctrl);
  218. if (dhchap_status) {
  219. pr_err("ctrl %d qid 0 failed to setup re-authentication\n",
  220. ctrl->cntlid);
  221. req->sq->dhchap_status = dhchap_status;
  222. req->sq->dhchap_step =
  223. NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  224. goto done_kfree;
  225. }
  226. }
  227. req->sq->dhchap_step =
  228. NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
  229. } else if (data->auth_id != req->sq->dhchap_step)
  230. goto done_failure1;
  231. /* Validate negotiation parameters */
  232. dhchap_status = nvmet_auth_negotiate(req, d);
  233. if (dhchap_status == 0)
  234. req->sq->dhchap_step =
  235. NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE;
  236. else {
  237. req->sq->dhchap_step =
  238. NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  239. req->sq->dhchap_status = dhchap_status;
  240. }
  241. goto done_kfree;
  242. }
  243. if (data->auth_id != req->sq->dhchap_step) {
  244. pr_debug("%s: ctrl %d qid %d step mismatch (%d != %d)\n",
  245. __func__, ctrl->cntlid, req->sq->qid,
  246. data->auth_id, req->sq->dhchap_step);
  247. goto done_failure1;
  248. }
  249. if (le16_to_cpu(data->t_id) != req->sq->dhchap_tid) {
  250. pr_debug("%s: ctrl %d qid %d invalid transaction %d (expected %d)\n",
  251. __func__, ctrl->cntlid, req->sq->qid,
  252. le16_to_cpu(data->t_id),
  253. req->sq->dhchap_tid);
  254. req->sq->dhchap_step =
  255. NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  256. req->sq->dhchap_status =
  257. NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
  258. goto done_kfree;
  259. }
  260. switch (data->auth_id) {
  261. case NVME_AUTH_DHCHAP_MESSAGE_REPLY:
  262. dhchap_status = nvmet_auth_reply(req, d);
  263. if (dhchap_status == 0)
  264. req->sq->dhchap_step =
  265. NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1;
  266. else {
  267. req->sq->dhchap_step =
  268. NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  269. req->sq->dhchap_status = dhchap_status;
  270. }
  271. goto done_kfree;
  272. case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2:
  273. req->sq->authenticated = true;
  274. pr_debug("%s: ctrl %d qid %d ctrl authenticated\n",
  275. __func__, ctrl->cntlid, req->sq->qid);
  276. goto done_kfree;
  277. case NVME_AUTH_DHCHAP_MESSAGE_FAILURE2:
  278. dhchap_status = nvmet_auth_failure2(d);
  279. if (dhchap_status) {
  280. pr_warn("ctrl %d qid %d: authentication failed (%d)\n",
  281. ctrl->cntlid, req->sq->qid, dhchap_status);
  282. req->sq->dhchap_status = dhchap_status;
  283. req->sq->authenticated = false;
  284. }
  285. goto done_kfree;
  286. default:
  287. req->sq->dhchap_status =
  288. NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE;
  289. req->sq->dhchap_step =
  290. NVME_AUTH_DHCHAP_MESSAGE_FAILURE2;
  291. req->sq->authenticated = false;
  292. goto done_kfree;
  293. }
  294. done_failure1:
  295. req->sq->dhchap_status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE;
  296. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_FAILURE2;
  297. done_kfree:
  298. kfree(d);
  299. done:
  300. pr_debug("%s: ctrl %d qid %d dhchap status %x step %x\n", __func__,
  301. ctrl->cntlid, req->sq->qid,
  302. req->sq->dhchap_status, req->sq->dhchap_step);
  303. if (status)
  304. pr_debug("%s: ctrl %d qid %d nvme status %x error loc %d\n",
  305. __func__, ctrl->cntlid, req->sq->qid,
  306. status, req->error_loc);
  307. if (req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2 &&
  308. req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) {
  309. unsigned long auth_expire_secs = ctrl->kato ? ctrl->kato : 120;
  310. mod_delayed_work(system_wq, &req->sq->auth_expired_work,
  311. auth_expire_secs * HZ);
  312. goto complete;
  313. }
  314. /* Final states, clear up variables */
  315. nvmet_auth_sq_free(req->sq);
  316. if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2)
  317. nvmet_ctrl_fatal_error(ctrl);
  318. complete:
  319. nvmet_req_complete(req, status);
  320. }
  321. static int nvmet_auth_challenge(struct nvmet_req *req, void *d, int al)
  322. {
  323. struct nvmf_auth_dhchap_challenge_data *data = d;
  324. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  325. int ret = 0;
  326. int hash_len = nvme_auth_hmac_hash_len(ctrl->shash_id);
  327. int data_size = sizeof(*d) + hash_len;
  328. if (ctrl->dh_tfm)
  329. data_size += ctrl->dh_keysize;
  330. if (al < data_size) {
  331. pr_debug("%s: buffer too small (al %d need %d)\n", __func__,
  332. al, data_size);
  333. return -EINVAL;
  334. }
  335. memset(data, 0, data_size);
  336. req->sq->dhchap_s1 = nvme_auth_get_seqnum();
  337. data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
  338. data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE;
  339. data->t_id = cpu_to_le16(req->sq->dhchap_tid);
  340. data->hashid = ctrl->shash_id;
  341. data->hl = hash_len;
  342. data->seqnum = cpu_to_le32(req->sq->dhchap_s1);
  343. req->sq->dhchap_c1 = kmalloc(data->hl, GFP_KERNEL);
  344. if (!req->sq->dhchap_c1)
  345. return -ENOMEM;
  346. get_random_bytes(req->sq->dhchap_c1, data->hl);
  347. memcpy(data->cval, req->sq->dhchap_c1, data->hl);
  348. if (ctrl->dh_tfm) {
  349. data->dhgid = ctrl->dh_gid;
  350. data->dhvlen = cpu_to_le16(ctrl->dh_keysize);
  351. ret = nvmet_auth_ctrl_exponential(req, data->cval + data->hl,
  352. ctrl->dh_keysize);
  353. }
  354. pr_debug("%s: ctrl %d qid %d seq %d transaction %d hl %d dhvlen %zu\n",
  355. __func__, ctrl->cntlid, req->sq->qid, req->sq->dhchap_s1,
  356. req->sq->dhchap_tid, data->hl, ctrl->dh_keysize);
  357. return ret;
  358. }
  359. static int nvmet_auth_success1(struct nvmet_req *req, void *d, int al)
  360. {
  361. struct nvmf_auth_dhchap_success1_data *data = d;
  362. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  363. int hash_len = nvme_auth_hmac_hash_len(ctrl->shash_id);
  364. WARN_ON(al < sizeof(*data));
  365. memset(data, 0, sizeof(*data));
  366. data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
  367. data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1;
  368. data->t_id = cpu_to_le16(req->sq->dhchap_tid);
  369. data->hl = hash_len;
  370. if (req->sq->dhchap_c2) {
  371. if (!ctrl->ctrl_key) {
  372. pr_warn("ctrl %d qid %d no ctrl key\n",
  373. ctrl->cntlid, req->sq->qid);
  374. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  375. }
  376. if (nvmet_auth_ctrl_hash(req, data->rval, data->hl))
  377. return NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
  378. data->rvalid = 1;
  379. pr_debug("ctrl %d qid %d response %*ph\n",
  380. ctrl->cntlid, req->sq->qid, data->hl, data->rval);
  381. }
  382. return 0;
  383. }
  384. static void nvmet_auth_failure1(struct nvmet_req *req, void *d, int al)
  385. {
  386. struct nvmf_auth_dhchap_failure_data *data = d;
  387. WARN_ON(al < sizeof(*data));
  388. data->auth_type = NVME_AUTH_COMMON_MESSAGES;
  389. data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  390. data->t_id = cpu_to_le16(req->sq->dhchap_tid);
  391. data->rescode = NVME_AUTH_DHCHAP_FAILURE_REASON_FAILED;
  392. data->rescode_exp = req->sq->dhchap_status;
  393. }
  394. void nvmet_execute_auth_receive(struct nvmet_req *req)
  395. {
  396. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  397. void *d;
  398. u32 al;
  399. u16 status = 0;
  400. if (req->cmd->auth_receive.secp != NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER) {
  401. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  402. req->error_loc =
  403. offsetof(struct nvmf_auth_receive_command, secp);
  404. goto done;
  405. }
  406. if (req->cmd->auth_receive.spsp0 != 0x01) {
  407. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  408. req->error_loc =
  409. offsetof(struct nvmf_auth_receive_command, spsp0);
  410. goto done;
  411. }
  412. if (req->cmd->auth_receive.spsp1 != 0x01) {
  413. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  414. req->error_loc =
  415. offsetof(struct nvmf_auth_receive_command, spsp1);
  416. goto done;
  417. }
  418. al = le32_to_cpu(req->cmd->auth_receive.al);
  419. if (!al) {
  420. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  421. req->error_loc =
  422. offsetof(struct nvmf_auth_receive_command, al);
  423. goto done;
  424. }
  425. if (!nvmet_check_transfer_len(req, al)) {
  426. pr_debug("%s: transfer length mismatch (%u)\n", __func__, al);
  427. return;
  428. }
  429. d = kmalloc(al, GFP_KERNEL);
  430. if (!d) {
  431. status = NVME_SC_INTERNAL;
  432. goto done;
  433. }
  434. pr_debug("%s: ctrl %d qid %d step %x\n", __func__,
  435. ctrl->cntlid, req->sq->qid, req->sq->dhchap_step);
  436. switch (req->sq->dhchap_step) {
  437. case NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE:
  438. if (nvmet_auth_challenge(req, d, al) < 0) {
  439. pr_warn("ctrl %d qid %d: challenge error (%d)\n",
  440. ctrl->cntlid, req->sq->qid, status);
  441. status = NVME_SC_INTERNAL;
  442. break;
  443. }
  444. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_REPLY;
  445. break;
  446. case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1:
  447. status = nvmet_auth_success1(req, d, al);
  448. if (status) {
  449. req->sq->dhchap_status = status;
  450. req->sq->authenticated = false;
  451. nvmet_auth_failure1(req, d, al);
  452. pr_warn("ctrl %d qid %d: success1 status (%x)\n",
  453. ctrl->cntlid, req->sq->qid,
  454. req->sq->dhchap_status);
  455. break;
  456. }
  457. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2;
  458. break;
  459. case NVME_AUTH_DHCHAP_MESSAGE_FAILURE1:
  460. req->sq->authenticated = false;
  461. nvmet_auth_failure1(req, d, al);
  462. pr_warn("ctrl %d qid %d failure1 (%x)\n",
  463. ctrl->cntlid, req->sq->qid, req->sq->dhchap_status);
  464. break;
  465. default:
  466. pr_warn("ctrl %d qid %d unhandled step (%d)\n",
  467. ctrl->cntlid, req->sq->qid, req->sq->dhchap_step);
  468. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  469. req->sq->dhchap_status = NVME_AUTH_DHCHAP_FAILURE_FAILED;
  470. nvmet_auth_failure1(req, d, al);
  471. status = 0;
  472. break;
  473. }
  474. status = nvmet_copy_to_sgl(req, 0, d, al);
  475. kfree(d);
  476. done:
  477. if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2)
  478. nvmet_auth_sq_free(req->sq);
  479. else if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) {
  480. nvmet_auth_sq_free(req->sq);
  481. nvmet_ctrl_fatal_error(ctrl);
  482. }
  483. nvmet_req_complete(req, status);
  484. }