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