fabrics-cmd-auth.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  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. req->sq->sc_c = data->sc_c;
  42. if (data->sc_c != NVME_AUTH_SECP_NOSC) {
  43. if (!IS_ENABLED(CONFIG_NVME_TARGET_TCP_TLS))
  44. return NVME_AUTH_DHCHAP_FAILURE_CONCAT_MISMATCH;
  45. /* Secure concatenation can only be enabled on the admin queue */
  46. if (req->sq->qid)
  47. return NVME_AUTH_DHCHAP_FAILURE_CONCAT_MISMATCH;
  48. switch (data->sc_c) {
  49. case NVME_AUTH_SECP_NEWTLSPSK:
  50. if (nvmet_queue_tls_keyid(req->sq))
  51. return NVME_AUTH_DHCHAP_FAILURE_CONCAT_MISMATCH;
  52. break;
  53. case NVME_AUTH_SECP_REPLACETLSPSK:
  54. if (!nvmet_queue_tls_keyid(req->sq))
  55. return NVME_AUTH_DHCHAP_FAILURE_CONCAT_MISMATCH;
  56. break;
  57. default:
  58. return NVME_AUTH_DHCHAP_FAILURE_CONCAT_MISMATCH;
  59. }
  60. ctrl->concat = true;
  61. }
  62. if (data->napd != 1)
  63. return NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
  64. if (data->auth_protocol[0].dhchap.authid !=
  65. NVME_AUTH_DHCHAP_AUTH_ID)
  66. return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
  67. for (i = 0; i < data->auth_protocol[0].dhchap.halen; i++) {
  68. u8 host_hmac_id = data->auth_protocol[0].dhchap.idlist[i];
  69. if (!fallback_hash_id &&
  70. crypto_has_shash(nvme_auth_hmac_name(host_hmac_id), 0, 0))
  71. fallback_hash_id = host_hmac_id;
  72. if (ctrl->shash_id != host_hmac_id)
  73. continue;
  74. hash_id = ctrl->shash_id;
  75. break;
  76. }
  77. if (hash_id == 0) {
  78. if (fallback_hash_id == 0) {
  79. pr_debug("%s: ctrl %d qid %d: no usable hash found\n",
  80. __func__, ctrl->cntlid, req->sq->qid);
  81. return NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
  82. }
  83. pr_debug("%s: ctrl %d qid %d: no usable hash found, falling back to %s\n",
  84. __func__, ctrl->cntlid, req->sq->qid,
  85. nvme_auth_hmac_name(fallback_hash_id));
  86. ctrl->shash_id = fallback_hash_id;
  87. }
  88. dhgid = -1;
  89. fallback_dhgid = -1;
  90. for (i = 0; i < data->auth_protocol[0].dhchap.dhlen; i++) {
  91. int tmp_dhgid = data->auth_protocol[0].dhchap.idlist[i + 30];
  92. if (tmp_dhgid != ctrl->dh_gid) {
  93. dhgid = tmp_dhgid;
  94. break;
  95. }
  96. if (fallback_dhgid < 0) {
  97. const char *kpp = nvme_auth_dhgroup_kpp(tmp_dhgid);
  98. if (crypto_has_kpp(kpp, 0, 0))
  99. fallback_dhgid = tmp_dhgid;
  100. }
  101. }
  102. if (dhgid < 0) {
  103. if (fallback_dhgid < 0) {
  104. pr_debug("%s: ctrl %d qid %d: no usable DH group found\n",
  105. __func__, ctrl->cntlid, req->sq->qid);
  106. return NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;
  107. }
  108. pr_debug("%s: ctrl %d qid %d: configured DH group %s not found\n",
  109. __func__, ctrl->cntlid, req->sq->qid,
  110. nvme_auth_dhgroup_name(fallback_dhgid));
  111. ctrl->dh_gid = fallback_dhgid;
  112. }
  113. if (ctrl->dh_gid == NVME_AUTH_DHGROUP_NULL && ctrl->concat) {
  114. pr_debug("%s: ctrl %d qid %d: NULL DH group invalid "
  115. "for secure channel concatenation\n", __func__,
  116. ctrl->cntlid, req->sq->qid);
  117. return NVME_AUTH_DHCHAP_FAILURE_CONCAT_MISMATCH;
  118. }
  119. pr_debug("%s: ctrl %d qid %d: selected DH group %s (%d)\n",
  120. __func__, ctrl->cntlid, req->sq->qid,
  121. nvme_auth_dhgroup_name(ctrl->dh_gid), ctrl->dh_gid);
  122. return 0;
  123. }
  124. static u8 nvmet_auth_reply(struct nvmet_req *req, void *d)
  125. {
  126. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  127. struct nvmf_auth_dhchap_reply_data *data = d;
  128. u16 dhvlen = le16_to_cpu(data->dhvlen);
  129. u8 *response;
  130. pr_debug("%s: ctrl %d qid %d: data hl %d cvalid %d dhvlen %u\n",
  131. __func__, ctrl->cntlid, req->sq->qid,
  132. data->hl, data->cvalid, dhvlen);
  133. if (dhvlen) {
  134. if (!ctrl->dh_tfm)
  135. return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
  136. if (nvmet_auth_ctrl_sesskey(req, data->rval + 2 * data->hl,
  137. dhvlen) < 0)
  138. return NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;
  139. }
  140. response = kmalloc(data->hl, GFP_KERNEL);
  141. if (!response)
  142. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  143. if (!ctrl->host_key) {
  144. pr_warn("ctrl %d qid %d no host key\n",
  145. ctrl->cntlid, req->sq->qid);
  146. kfree(response);
  147. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  148. }
  149. if (nvmet_auth_host_hash(req, response, data->hl) < 0) {
  150. pr_debug("ctrl %d qid %d host hash failed\n",
  151. ctrl->cntlid, req->sq->qid);
  152. kfree(response);
  153. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  154. }
  155. if (memcmp(data->rval, response, data->hl)) {
  156. pr_info("ctrl %d qid %d host response mismatch\n",
  157. ctrl->cntlid, req->sq->qid);
  158. pr_debug("ctrl %d qid %d rval %*ph\n",
  159. ctrl->cntlid, req->sq->qid, data->hl, data->rval);
  160. pr_debug("ctrl %d qid %d response %*ph\n",
  161. ctrl->cntlid, req->sq->qid, data->hl, response);
  162. kfree(response);
  163. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  164. }
  165. kfree(response);
  166. pr_debug("%s: ctrl %d qid %d host authenticated\n",
  167. __func__, ctrl->cntlid, req->sq->qid);
  168. if (!data->cvalid && ctrl->concat) {
  169. pr_debug("%s: ctrl %d qid %d invalid challenge\n",
  170. __func__, ctrl->cntlid, req->sq->qid);
  171. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  172. }
  173. req->sq->dhchap_s2 = le32_to_cpu(data->seqnum);
  174. if (data->cvalid) {
  175. req->sq->dhchap_c2 = kmemdup(data->rval + data->hl, data->hl,
  176. GFP_KERNEL);
  177. if (!req->sq->dhchap_c2)
  178. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  179. pr_debug("%s: ctrl %d qid %d challenge %*ph\n",
  180. __func__, ctrl->cntlid, req->sq->qid, data->hl,
  181. req->sq->dhchap_c2);
  182. }
  183. /*
  184. * NVMe Base Spec 2.2 section 8.3.4.5.4: DH-HMAC-CHAP_Reply message
  185. * Sequence Number (SEQNUM): [ .. ]
  186. * The value 0h is used to indicate that bidirectional authentication
  187. * is not performed, but a challenge value C2 is carried in order to
  188. * generate a pre-shared key (PSK) for subsequent establishment of a
  189. * secure channel.
  190. */
  191. if (req->sq->dhchap_s2 == 0) {
  192. if (ctrl->concat)
  193. nvmet_auth_insert_psk(req->sq);
  194. req->sq->authenticated = true;
  195. kfree(req->sq->dhchap_c2);
  196. req->sq->dhchap_c2 = NULL;
  197. } else if (!data->cvalid)
  198. req->sq->authenticated = true;
  199. return 0;
  200. }
  201. static u8 nvmet_auth_failure2(void *d)
  202. {
  203. struct nvmf_auth_dhchap_failure_data *data = d;
  204. return data->rescode_exp;
  205. }
  206. u32 nvmet_auth_send_data_len(struct nvmet_req *req)
  207. {
  208. return le32_to_cpu(req->cmd->auth_send.tl);
  209. }
  210. void nvmet_execute_auth_send(struct nvmet_req *req)
  211. {
  212. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  213. struct nvmf_auth_dhchap_success2_data *data;
  214. void *d;
  215. u32 tl;
  216. u16 status = 0;
  217. u8 dhchap_status;
  218. if (req->cmd->auth_send.secp != NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER) {
  219. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  220. req->error_loc =
  221. offsetof(struct nvmf_auth_send_command, secp);
  222. goto done;
  223. }
  224. if (req->cmd->auth_send.spsp0 != 0x01) {
  225. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  226. req->error_loc =
  227. offsetof(struct nvmf_auth_send_command, spsp0);
  228. goto done;
  229. }
  230. if (req->cmd->auth_send.spsp1 != 0x01) {
  231. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  232. req->error_loc =
  233. offsetof(struct nvmf_auth_send_command, spsp1);
  234. goto done;
  235. }
  236. tl = nvmet_auth_send_data_len(req);
  237. if (!tl) {
  238. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  239. req->error_loc =
  240. offsetof(struct nvmf_auth_send_command, tl);
  241. goto done;
  242. }
  243. if (!nvmet_check_transfer_len(req, tl)) {
  244. pr_debug("%s: transfer length mismatch (%u)\n", __func__, tl);
  245. return;
  246. }
  247. d = kmalloc(tl, GFP_KERNEL);
  248. if (!d) {
  249. status = NVME_SC_INTERNAL;
  250. goto done;
  251. }
  252. status = nvmet_copy_from_sgl(req, 0, d, tl);
  253. if (status)
  254. goto done_kfree;
  255. data = d;
  256. pr_debug("%s: ctrl %d qid %d type %d id %d step %x\n", __func__,
  257. ctrl->cntlid, req->sq->qid, data->auth_type, data->auth_id,
  258. req->sq->dhchap_step);
  259. if (data->auth_type != NVME_AUTH_COMMON_MESSAGES &&
  260. data->auth_type != NVME_AUTH_DHCHAP_MESSAGES)
  261. goto done_failure1;
  262. if (data->auth_type == NVME_AUTH_COMMON_MESSAGES) {
  263. if (data->auth_id == NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE) {
  264. /* Restart negotiation */
  265. pr_debug("%s: ctrl %d qid %d reset negotiation\n",
  266. __func__, ctrl->cntlid, req->sq->qid);
  267. if (!req->sq->qid) {
  268. dhchap_status = nvmet_setup_auth(ctrl, req->sq);
  269. if (dhchap_status) {
  270. pr_err("ctrl %d qid 0 failed to setup re-authentication\n",
  271. ctrl->cntlid);
  272. req->sq->dhchap_status = dhchap_status;
  273. req->sq->dhchap_step =
  274. NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  275. goto done_kfree;
  276. }
  277. }
  278. req->sq->dhchap_step =
  279. NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
  280. } else if (data->auth_id != req->sq->dhchap_step)
  281. goto done_failure1;
  282. /* Validate negotiation parameters */
  283. dhchap_status = nvmet_auth_negotiate(req, d);
  284. if (dhchap_status == 0)
  285. req->sq->dhchap_step =
  286. NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE;
  287. else {
  288. req->sq->dhchap_step =
  289. NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  290. req->sq->dhchap_status = dhchap_status;
  291. }
  292. goto done_kfree;
  293. }
  294. if (data->auth_id != req->sq->dhchap_step) {
  295. pr_debug("%s: ctrl %d qid %d step mismatch (%d != %d)\n",
  296. __func__, ctrl->cntlid, req->sq->qid,
  297. data->auth_id, req->sq->dhchap_step);
  298. goto done_failure1;
  299. }
  300. if (le16_to_cpu(data->t_id) != req->sq->dhchap_tid) {
  301. pr_debug("%s: ctrl %d qid %d invalid transaction %d (expected %d)\n",
  302. __func__, ctrl->cntlid, req->sq->qid,
  303. le16_to_cpu(data->t_id),
  304. req->sq->dhchap_tid);
  305. req->sq->dhchap_step =
  306. NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  307. req->sq->dhchap_status =
  308. NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
  309. goto done_kfree;
  310. }
  311. switch (data->auth_id) {
  312. case NVME_AUTH_DHCHAP_MESSAGE_REPLY:
  313. dhchap_status = nvmet_auth_reply(req, d);
  314. if (dhchap_status == 0)
  315. req->sq->dhchap_step =
  316. NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1;
  317. else {
  318. req->sq->dhchap_step =
  319. NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  320. req->sq->dhchap_status = dhchap_status;
  321. }
  322. goto done_kfree;
  323. case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2:
  324. if (ctrl->concat)
  325. nvmet_auth_insert_psk(req->sq);
  326. req->sq->authenticated = true;
  327. pr_debug("%s: ctrl %d qid %d ctrl authenticated\n",
  328. __func__, ctrl->cntlid, req->sq->qid);
  329. goto done_kfree;
  330. case NVME_AUTH_DHCHAP_MESSAGE_FAILURE2:
  331. dhchap_status = nvmet_auth_failure2(d);
  332. if (dhchap_status) {
  333. pr_warn("ctrl %d qid %d: authentication failed (%d)\n",
  334. ctrl->cntlid, req->sq->qid, dhchap_status);
  335. req->sq->dhchap_status = dhchap_status;
  336. req->sq->authenticated = false;
  337. }
  338. goto done_kfree;
  339. default:
  340. req->sq->dhchap_status =
  341. NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE;
  342. req->sq->dhchap_step =
  343. NVME_AUTH_DHCHAP_MESSAGE_FAILURE2;
  344. req->sq->authenticated = false;
  345. goto done_kfree;
  346. }
  347. done_failure1:
  348. req->sq->dhchap_status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE;
  349. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_FAILURE2;
  350. done_kfree:
  351. kfree(d);
  352. done:
  353. pr_debug("%s: ctrl %d qid %d dhchap status %x step %x\n", __func__,
  354. ctrl->cntlid, req->sq->qid,
  355. req->sq->dhchap_status, req->sq->dhchap_step);
  356. if (status)
  357. pr_debug("%s: ctrl %d qid %d nvme status %x error loc %d\n",
  358. __func__, ctrl->cntlid, req->sq->qid,
  359. status, req->error_loc);
  360. if (req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2 &&
  361. req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) {
  362. unsigned long auth_expire_secs = ctrl->kato ? ctrl->kato : 120;
  363. mod_delayed_work(system_wq, &req->sq->auth_expired_work,
  364. auth_expire_secs * HZ);
  365. goto complete;
  366. }
  367. /* Final states, clear up variables */
  368. nvmet_auth_sq_free(req->sq);
  369. if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2)
  370. nvmet_ctrl_fatal_error(ctrl);
  371. complete:
  372. nvmet_req_complete(req, status);
  373. }
  374. static int nvmet_auth_challenge(struct nvmet_req *req, void *d, int al)
  375. {
  376. struct nvmf_auth_dhchap_challenge_data *data = d;
  377. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  378. int ret = 0;
  379. int hash_len = nvme_auth_hmac_hash_len(ctrl->shash_id);
  380. int data_size = sizeof(*d) + hash_len;
  381. if (ctrl->dh_tfm)
  382. data_size += ctrl->dh_keysize;
  383. if (al < data_size) {
  384. pr_debug("%s: buffer too small (al %d need %d)\n", __func__,
  385. al, data_size);
  386. return -EINVAL;
  387. }
  388. memset(data, 0, data_size);
  389. req->sq->dhchap_s1 = nvme_auth_get_seqnum();
  390. data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
  391. data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE;
  392. data->t_id = cpu_to_le16(req->sq->dhchap_tid);
  393. data->hashid = ctrl->shash_id;
  394. data->hl = hash_len;
  395. data->seqnum = cpu_to_le32(req->sq->dhchap_s1);
  396. req->sq->dhchap_c1 = kmalloc(data->hl, GFP_KERNEL);
  397. if (!req->sq->dhchap_c1)
  398. return -ENOMEM;
  399. get_random_bytes(req->sq->dhchap_c1, data->hl);
  400. memcpy(data->cval, req->sq->dhchap_c1, data->hl);
  401. if (ctrl->dh_tfm) {
  402. data->dhgid = ctrl->dh_gid;
  403. data->dhvlen = cpu_to_le16(ctrl->dh_keysize);
  404. ret = nvmet_auth_ctrl_exponential(req, data->cval + data->hl,
  405. ctrl->dh_keysize);
  406. }
  407. pr_debug("%s: ctrl %d qid %d seq %d transaction %d hl %d dhvlen %zu\n",
  408. __func__, ctrl->cntlid, req->sq->qid, req->sq->dhchap_s1,
  409. req->sq->dhchap_tid, data->hl, ctrl->dh_keysize);
  410. return ret;
  411. }
  412. static int nvmet_auth_success1(struct nvmet_req *req, void *d, int al)
  413. {
  414. struct nvmf_auth_dhchap_success1_data *data = d;
  415. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  416. int hash_len = nvme_auth_hmac_hash_len(ctrl->shash_id);
  417. WARN_ON(al < sizeof(*data));
  418. memset(data, 0, sizeof(*data));
  419. data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
  420. data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1;
  421. data->t_id = cpu_to_le16(req->sq->dhchap_tid);
  422. data->hl = hash_len;
  423. if (req->sq->dhchap_c2) {
  424. if (!ctrl->ctrl_key) {
  425. pr_warn("ctrl %d qid %d no ctrl key\n",
  426. ctrl->cntlid, req->sq->qid);
  427. return NVME_AUTH_DHCHAP_FAILURE_FAILED;
  428. }
  429. if (nvmet_auth_ctrl_hash(req, data->rval, data->hl))
  430. return NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
  431. data->rvalid = 1;
  432. pr_debug("ctrl %d qid %d response %*ph\n",
  433. ctrl->cntlid, req->sq->qid, data->hl, data->rval);
  434. }
  435. return 0;
  436. }
  437. static void nvmet_auth_failure1(struct nvmet_req *req, void *d, int al)
  438. {
  439. struct nvmf_auth_dhchap_failure_data *data = d;
  440. WARN_ON(al < sizeof(*data));
  441. data->auth_type = NVME_AUTH_COMMON_MESSAGES;
  442. data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  443. data->t_id = cpu_to_le16(req->sq->dhchap_tid);
  444. data->rescode = NVME_AUTH_DHCHAP_FAILURE_REASON_FAILED;
  445. data->rescode_exp = req->sq->dhchap_status;
  446. }
  447. u32 nvmet_auth_receive_data_len(struct nvmet_req *req)
  448. {
  449. return le32_to_cpu(req->cmd->auth_receive.al);
  450. }
  451. void nvmet_execute_auth_receive(struct nvmet_req *req)
  452. {
  453. struct nvmet_ctrl *ctrl = req->sq->ctrl;
  454. void *d;
  455. u32 al;
  456. u16 status = 0;
  457. if (req->cmd->auth_receive.secp != NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER) {
  458. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  459. req->error_loc =
  460. offsetof(struct nvmf_auth_receive_command, secp);
  461. goto done;
  462. }
  463. if (req->cmd->auth_receive.spsp0 != 0x01) {
  464. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  465. req->error_loc =
  466. offsetof(struct nvmf_auth_receive_command, spsp0);
  467. goto done;
  468. }
  469. if (req->cmd->auth_receive.spsp1 != 0x01) {
  470. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  471. req->error_loc =
  472. offsetof(struct nvmf_auth_receive_command, spsp1);
  473. goto done;
  474. }
  475. al = nvmet_auth_receive_data_len(req);
  476. if (!al) {
  477. status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
  478. req->error_loc =
  479. offsetof(struct nvmf_auth_receive_command, al);
  480. goto done;
  481. }
  482. if (!nvmet_check_transfer_len(req, al)) {
  483. pr_debug("%s: transfer length mismatch (%u)\n", __func__, al);
  484. return;
  485. }
  486. d = kmalloc(al, GFP_KERNEL);
  487. if (!d) {
  488. status = NVME_SC_INTERNAL;
  489. goto done;
  490. }
  491. pr_debug("%s: ctrl %d qid %d step %x\n", __func__,
  492. ctrl->cntlid, req->sq->qid, req->sq->dhchap_step);
  493. switch (req->sq->dhchap_step) {
  494. case NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE:
  495. if (nvmet_auth_challenge(req, d, al) < 0) {
  496. pr_warn("ctrl %d qid %d: challenge error (%d)\n",
  497. ctrl->cntlid, req->sq->qid, status);
  498. status = NVME_SC_INTERNAL;
  499. break;
  500. }
  501. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_REPLY;
  502. break;
  503. case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1:
  504. status = nvmet_auth_success1(req, d, al);
  505. if (status) {
  506. req->sq->dhchap_status = status;
  507. req->sq->authenticated = false;
  508. nvmet_auth_failure1(req, d, al);
  509. pr_warn("ctrl %d qid %d: success1 status (%x)\n",
  510. ctrl->cntlid, req->sq->qid,
  511. req->sq->dhchap_status);
  512. break;
  513. }
  514. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2;
  515. break;
  516. case NVME_AUTH_DHCHAP_MESSAGE_FAILURE1:
  517. req->sq->authenticated = false;
  518. nvmet_auth_failure1(req, d, al);
  519. pr_warn("ctrl %d qid %d failure1 (%x)\n",
  520. ctrl->cntlid, req->sq->qid, req->sq->dhchap_status);
  521. break;
  522. default:
  523. pr_warn("ctrl %d qid %d unhandled step (%d)\n",
  524. ctrl->cntlid, req->sq->qid, req->sq->dhchap_step);
  525. req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_FAILURE1;
  526. req->sq->dhchap_status = NVME_AUTH_DHCHAP_FAILURE_FAILED;
  527. nvmet_auth_failure1(req, d, al);
  528. status = 0;
  529. break;
  530. }
  531. status = nvmet_copy_to_sgl(req, 0, d, al);
  532. kfree(d);
  533. done:
  534. if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2)
  535. nvmet_auth_sq_free(req->sq);
  536. else if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) {
  537. nvmet_auth_sq_free(req->sq);
  538. nvmet_ctrl_fatal_error(ctrl);
  539. }
  540. nvmet_req_complete(req, status);
  541. }