xref: /wlan-driver/qcacld-3.0/core/hdd/src/wlan_hdd_disa.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: wlan_hdd_disa.c
22*5113495bSYour Name  *
23*5113495bSYour Name  * WLAN Host Device Driver file for DISA certification
24*5113495bSYour Name  *
25*5113495bSYour Name  */
26*5113495bSYour Name 
27*5113495bSYour Name #include "wlan_hdd_disa.h"
28*5113495bSYour Name #include "osif_sync.h"
29*5113495bSYour Name #include "wlan_disa_ucfg_api.h"
30*5113495bSYour Name #include "wlan_osif_request_manager.h"
31*5113495bSYour Name #include "sme_api.h"
32*5113495bSYour Name #include <qca_vendor.h>
33*5113495bSYour Name 
34*5113495bSYour Name #define WLAN_WAIT_TIME_ENCRYPT_DECRYPT 1000
35*5113495bSYour Name 
36*5113495bSYour Name 
37*5113495bSYour Name /**
38*5113495bSYour Name  * struct hdd_encrypt_decrypt_msg_context - hdd encrypt/decrypt message context
39*5113495bSYour Name  * @status: status of response. 0: no error, -ENOMEM: unable to allocate
40*5113495bSYour Name  *   memory for the response payload
41*5113495bSYour Name  * @request: encrypt/decrypt request
42*5113495bSYour Name  * @response: encrypt/decrypt response
43*5113495bSYour Name  */
44*5113495bSYour Name struct hdd_encrypt_decrypt_msg_context {
45*5113495bSYour Name 	int status;
46*5113495bSYour Name 	struct disa_encrypt_decrypt_req_params request;
47*5113495bSYour Name 	struct disa_encrypt_decrypt_resp_params response;
48*5113495bSYour Name };
49*5113495bSYour Name 
50*5113495bSYour Name /**
51*5113495bSYour Name  * hdd_encrypt_decrypt_msg_cb () - encrypt/decrypt response message handler
52*5113495bSYour Name  * @cookie: hdd request cookie
53*5113495bSYour Name  * @resp: encrypt/decrypt response parameters
54*5113495bSYour Name  *
55*5113495bSYour Name  * Return: none
56*5113495bSYour Name  */
hdd_encrypt_decrypt_msg_cb(void * cookie,struct disa_encrypt_decrypt_resp_params * resp)57*5113495bSYour Name static void hdd_encrypt_decrypt_msg_cb(void *cookie,
58*5113495bSYour Name 	struct disa_encrypt_decrypt_resp_params *resp)
59*5113495bSYour Name {
60*5113495bSYour Name 	struct osif_request *request;
61*5113495bSYour Name 	struct hdd_encrypt_decrypt_msg_context *context;
62*5113495bSYour Name 
63*5113495bSYour Name 	hdd_enter();
64*5113495bSYour Name 
65*5113495bSYour Name 	if (!resp) {
66*5113495bSYour Name 		hdd_err("rsp params is NULL");
67*5113495bSYour Name 		return;
68*5113495bSYour Name 	}
69*5113495bSYour Name 
70*5113495bSYour Name 	request = osif_request_get(cookie);
71*5113495bSYour Name 	if (!request) {
72*5113495bSYour Name 		hdd_err("Obsolete request");
73*5113495bSYour Name 		return;
74*5113495bSYour Name 	}
75*5113495bSYour Name 
76*5113495bSYour Name 	print_hex_dump(KERN_INFO, "Data in hdd_encrypt_decrypt_msg_cb: ",
77*5113495bSYour Name 		DUMP_PREFIX_NONE, 16, 1,
78*5113495bSYour Name 		resp->data,
79*5113495bSYour Name 		resp->data_len, 0);
80*5113495bSYour Name 
81*5113495bSYour Name 	hdd_debug("vdev_id: %d status:%d data_length: %d",
82*5113495bSYour Name 		resp->vdev_id,
83*5113495bSYour Name 		resp->status,
84*5113495bSYour Name 		resp->data_len);
85*5113495bSYour Name 
86*5113495bSYour Name 	context = osif_request_priv(request);
87*5113495bSYour Name 	context->response = *resp;
88*5113495bSYour Name 	context->status = 0;
89*5113495bSYour Name 	if (resp->data_len) {
90*5113495bSYour Name 		context->response.data =
91*5113495bSYour Name 			qdf_mem_malloc(sizeof(uint8_t) *
92*5113495bSYour Name 				resp->data_len);
93*5113495bSYour Name 		if (!context->response.data) {
94*5113495bSYour Name 			context->status = -ENOMEM;
95*5113495bSYour Name 		} else {
96*5113495bSYour Name 			qdf_mem_copy(context->response.data,
97*5113495bSYour Name 				     resp->data,
98*5113495bSYour Name 				     resp->data_len);
99*5113495bSYour Name 		}
100*5113495bSYour Name 	} else {
101*5113495bSYour Name 		/* make sure we don't have a rogue pointer */
102*5113495bSYour Name 		context->response.data = NULL;
103*5113495bSYour Name 	}
104*5113495bSYour Name 
105*5113495bSYour Name 	osif_request_complete(request);
106*5113495bSYour Name 	osif_request_put(request);
107*5113495bSYour Name 	hdd_exit();
108*5113495bSYour Name }
109*5113495bSYour Name 
110*5113495bSYour Name /**
111*5113495bSYour Name  * hdd_post_encrypt_decrypt_msg_rsp () - send encrypt/decrypt data to user space
112*5113495bSYour Name  * @hdd_ctx: HDD context
113*5113495bSYour Name  * @resp: encrypt/decrypt response parameters
114*5113495bSYour Name  *
115*5113495bSYour Name  * Return: none
116*5113495bSYour Name  */
hdd_post_encrypt_decrypt_msg_rsp(struct hdd_context * hdd_ctx,struct disa_encrypt_decrypt_resp_params * resp)117*5113495bSYour Name static int hdd_post_encrypt_decrypt_msg_rsp(struct hdd_context *hdd_ctx,
118*5113495bSYour Name 	struct disa_encrypt_decrypt_resp_params *resp)
119*5113495bSYour Name {
120*5113495bSYour Name 	struct sk_buff *skb;
121*5113495bSYour Name 	uint32_t nl_buf_len;
122*5113495bSYour Name 
123*5113495bSYour Name 	hdd_enter();
124*5113495bSYour Name 
125*5113495bSYour Name 	nl_buf_len = resp->data_len + NLA_HDRLEN;
126*5113495bSYour Name 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
127*5113495bSYour Name 						       nl_buf_len);
128*5113495bSYour Name 	if (!skb) {
129*5113495bSYour Name 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
130*5113495bSYour Name 		return -ENOMEM;
131*5113495bSYour Name 	}
132*5113495bSYour Name 
133*5113495bSYour Name 	if (resp->data_len) {
134*5113495bSYour Name 		if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA,
135*5113495bSYour Name 			    resp->data_len, resp->data)) {
136*5113495bSYour Name 			hdd_err("put fail");
137*5113495bSYour Name 			goto nla_put_failure;
138*5113495bSYour Name 		}
139*5113495bSYour Name 	}
140*5113495bSYour Name 
141*5113495bSYour Name 	wlan_cfg80211_vendor_cmd_reply(skb);
142*5113495bSYour Name 	hdd_exit();
143*5113495bSYour Name 	return 0;
144*5113495bSYour Name 
145*5113495bSYour Name nla_put_failure:
146*5113495bSYour Name 	wlan_cfg80211_vendor_free_skb(skb);
147*5113495bSYour Name 	return -EINVAL;
148*5113495bSYour Name }
149*5113495bSYour Name 
150*5113495bSYour Name const struct nla_policy
151*5113495bSYour Name encrypt_decrypt_policy[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_MAX + 1] = {
152*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_NEEDS_DECRYPTION] = {
153*5113495bSYour Name 		.type = NLA_FLAG},
154*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_CIPHER] = {
155*5113495bSYour Name 		.type = NLA_U32},
156*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_KEYID] = {
157*5113495bSYour Name 		.type = NLA_U8},
158*5113495bSYour Name };
159*5113495bSYour Name 
160*5113495bSYour Name /**
161*5113495bSYour Name  * hdd_fill_encrypt_decrypt_params () - parses data from user space
162*5113495bSYour Name  * and fills encrypt/decrypt parameters
163*5113495bSYour Name  * @encrypt_decrypt_params: encrypt/decrypt request parameters
164*5113495bSYour Name  * @adapter : adapter context
165*5113495bSYour Name  * @data: Pointer to data
166*5113495bSYour Name  * @data_len: Data length
167*5113495bSYour Name  *
168*5113495bSYour Name  * Return: 0 on success, negative errno on failure
169*5113495bSYour Name  */
170*5113495bSYour Name static int
hdd_fill_encrypt_decrypt_params(struct disa_encrypt_decrypt_req_params * encrypt_decrypt_params,struct hdd_adapter * adapter,const void * data,int data_len)171*5113495bSYour Name hdd_fill_encrypt_decrypt_params(struct disa_encrypt_decrypt_req_params
172*5113495bSYour Name 				*encrypt_decrypt_params,
173*5113495bSYour Name 				struct hdd_adapter *adapter,
174*5113495bSYour Name 				const void *data,
175*5113495bSYour Name 				int data_len)
176*5113495bSYour Name {
177*5113495bSYour Name 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_MAX + 1];
178*5113495bSYour Name 	uint8_t len, mac_hdr_len;
179*5113495bSYour Name 	uint8_t *tmp;
180*5113495bSYour Name 	uint8_t fc[2];
181*5113495bSYour Name 
182*5113495bSYour Name 	if (wlan_cfg80211_nla_parse(tb,
183*5113495bSYour Name 				    QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_MAX,
184*5113495bSYour Name 				    data, data_len, encrypt_decrypt_policy)) {
185*5113495bSYour Name 		hdd_err("Invalid ATTR");
186*5113495bSYour Name 		return -EINVAL;
187*5113495bSYour Name 	}
188*5113495bSYour Name 
189*5113495bSYour Name 	encrypt_decrypt_params->vdev_id = adapter->deflink->vdev_id;
190*5113495bSYour Name 	hdd_debug("vdev_id: %d", encrypt_decrypt_params->vdev_id);
191*5113495bSYour Name 
192*5113495bSYour Name 	if (!tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_NEEDS_DECRYPTION]) {
193*5113495bSYour Name 		hdd_err("attr flag NEEDS_DECRYPTION not present");
194*5113495bSYour Name 		encrypt_decrypt_params->key_flag = WMI_ENCRYPT;
195*5113495bSYour Name 	} else {
196*5113495bSYour Name 		hdd_err("attr flag NEEDS_DECRYPTION present");
197*5113495bSYour Name 		encrypt_decrypt_params->key_flag = WMI_DECRYPT;
198*5113495bSYour Name 	}
199*5113495bSYour Name 	hdd_debug("Key flag: %d", encrypt_decrypt_params->key_flag);
200*5113495bSYour Name 
201*5113495bSYour Name 	if (!tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_KEYID]) {
202*5113495bSYour Name 		hdd_err("attr key id failed");
203*5113495bSYour Name 		return -EINVAL;
204*5113495bSYour Name 	}
205*5113495bSYour Name 	encrypt_decrypt_params->key_idx = nla_get_u8(tb
206*5113495bSYour Name 		    [QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_KEYID]);
207*5113495bSYour Name 	hdd_debug("Key Idx: %d", encrypt_decrypt_params->key_idx);
208*5113495bSYour Name 
209*5113495bSYour Name 	if (!tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_CIPHER]) {
210*5113495bSYour Name 		hdd_err("attr Cipher failed");
211*5113495bSYour Name 		return -EINVAL;
212*5113495bSYour Name 	}
213*5113495bSYour Name 	encrypt_decrypt_params->key_cipher = nla_get_u32(tb
214*5113495bSYour Name 		    [QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_CIPHER]);
215*5113495bSYour Name 	hdd_debug("key_cipher: %d", encrypt_decrypt_params->key_cipher);
216*5113495bSYour Name 
217*5113495bSYour Name 	if (!tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_TK]) {
218*5113495bSYour Name 		hdd_err("attr TK failed");
219*5113495bSYour Name 		return -EINVAL;
220*5113495bSYour Name 	}
221*5113495bSYour Name 	encrypt_decrypt_params->key_len =
222*5113495bSYour Name 		nla_len(tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_TK]);
223*5113495bSYour Name 	if (!encrypt_decrypt_params->key_len) {
224*5113495bSYour Name 		hdd_err("Invalid TK length");
225*5113495bSYour Name 		return -EINVAL;
226*5113495bSYour Name 	}
227*5113495bSYour Name 	hdd_debug("Key len: %d", encrypt_decrypt_params->key_len);
228*5113495bSYour Name 
229*5113495bSYour Name 	if (encrypt_decrypt_params->key_len > SIR_MAC_MAX_KEY_LENGTH)
230*5113495bSYour Name 		encrypt_decrypt_params->key_len = SIR_MAC_MAX_KEY_LENGTH;
231*5113495bSYour Name 
232*5113495bSYour Name 	tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_TK]);
233*5113495bSYour Name 
234*5113495bSYour Name 	qdf_mem_copy(encrypt_decrypt_params->key_data, tmp,
235*5113495bSYour Name 			encrypt_decrypt_params->key_len);
236*5113495bSYour Name 
237*5113495bSYour Name 	print_hex_dump(KERN_INFO, "Key : ", DUMP_PREFIX_NONE, 16, 1,
238*5113495bSYour Name 			&encrypt_decrypt_params->key_data,
239*5113495bSYour Name 			encrypt_decrypt_params->key_len, 0);
240*5113495bSYour Name 
241*5113495bSYour Name 	if (!tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN]) {
242*5113495bSYour Name 		hdd_err("attr PN failed");
243*5113495bSYour Name 		return -EINVAL;
244*5113495bSYour Name 	}
245*5113495bSYour Name 	len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN]);
246*5113495bSYour Name 	if (!len || len > sizeof(encrypt_decrypt_params->pn)) {
247*5113495bSYour Name 		hdd_err("Invalid PN length %u", len);
248*5113495bSYour Name 		return -EINVAL;
249*5113495bSYour Name 	}
250*5113495bSYour Name 
251*5113495bSYour Name 	tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN]);
252*5113495bSYour Name 
253*5113495bSYour Name 	qdf_mem_copy(encrypt_decrypt_params->pn, tmp, len);
254*5113495bSYour Name 
255*5113495bSYour Name 	print_hex_dump(KERN_INFO, "PN received : ", DUMP_PREFIX_NONE, 16, 1,
256*5113495bSYour Name 			&encrypt_decrypt_params->pn, len, 0);
257*5113495bSYour Name 
258*5113495bSYour Name 	if (!tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA]) {
259*5113495bSYour Name 		hdd_err("attr header failed");
260*5113495bSYour Name 		return -EINVAL;
261*5113495bSYour Name 	}
262*5113495bSYour Name 	len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA]);
263*5113495bSYour Name 	if (len < MIN_MAC_HEADER_LEN) {
264*5113495bSYour Name 		hdd_err("Invalid header and payload length %u", len);
265*5113495bSYour Name 		return -EINVAL;
266*5113495bSYour Name 	}
267*5113495bSYour Name 
268*5113495bSYour Name 	hdd_debug("Header and Payload length: %d", len);
269*5113495bSYour Name 
270*5113495bSYour Name 	tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA]);
271*5113495bSYour Name 
272*5113495bSYour Name 	print_hex_dump(KERN_INFO, "Header and Payload received: ",
273*5113495bSYour Name 			DUMP_PREFIX_NONE, 16, 1,
274*5113495bSYour Name 			tmp, len, 0);
275*5113495bSYour Name 
276*5113495bSYour Name 	mac_hdr_len = MIN_MAC_HEADER_LEN;
277*5113495bSYour Name 
278*5113495bSYour Name 	/*
279*5113495bSYour Name 	 * Check to find out address 4. Address 4 is present if ToDS and FromDS
280*5113495bSYour Name 	 * are 1 and data representation is little endian.
281*5113495bSYour Name 	 */
282*5113495bSYour Name 	fc[1] = *tmp;
283*5113495bSYour Name 	fc[0] = *(tmp + 1);
284*5113495bSYour Name 	if ((fc[0] & 0x03) == 0x03) {
285*5113495bSYour Name 		hdd_err("Address 4 is present");
286*5113495bSYour Name 		mac_hdr_len += QDF_MAC_ADDR_SIZE;
287*5113495bSYour Name 	}
288*5113495bSYour Name 
289*5113495bSYour Name 	/*
290*5113495bSYour Name 	 * Check to find out Qos control field. Qos control field is present
291*5113495bSYour Name 	 * if msb of subtype field is 1 and data representation is
292*5113495bSYour Name 	 * little endian.
293*5113495bSYour Name 	 */
294*5113495bSYour Name 	if (fc[1] & 0x80) {
295*5113495bSYour Name 		hdd_err("Qos control is present");
296*5113495bSYour Name 		mac_hdr_len += QOS_CONTROL_LEN;
297*5113495bSYour Name 	}
298*5113495bSYour Name 
299*5113495bSYour Name 	hdd_debug("mac_hdr_len: %d", mac_hdr_len);
300*5113495bSYour Name 
301*5113495bSYour Name 	if (len < mac_hdr_len) {
302*5113495bSYour Name 		hdd_err("Invalid header and payload length %u", len);
303*5113495bSYour Name 		return -EINVAL;
304*5113495bSYour Name 	}
305*5113495bSYour Name 	qdf_mem_copy(encrypt_decrypt_params->mac_header,
306*5113495bSYour Name 			tmp, mac_hdr_len);
307*5113495bSYour Name 
308*5113495bSYour Name 	print_hex_dump(KERN_INFO, "Header received in request: ",
309*5113495bSYour Name 			DUMP_PREFIX_NONE, 16, 1,
310*5113495bSYour Name 			encrypt_decrypt_params->mac_header,
311*5113495bSYour Name 			mac_hdr_len, 0);
312*5113495bSYour Name 
313*5113495bSYour Name 	encrypt_decrypt_params->data_len =
314*5113495bSYour Name 			len - mac_hdr_len;
315*5113495bSYour Name 
316*5113495bSYour Name 	hdd_debug("Payload length: %d", encrypt_decrypt_params->data_len);
317*5113495bSYour Name 
318*5113495bSYour Name 	if (encrypt_decrypt_params->data_len) {
319*5113495bSYour Name 		encrypt_decrypt_params->data =
320*5113495bSYour Name 			qdf_mem_malloc(sizeof(uint8_t) *
321*5113495bSYour Name 				encrypt_decrypt_params->data_len);
322*5113495bSYour Name 
323*5113495bSYour Name 		if (!encrypt_decrypt_params->data)
324*5113495bSYour Name 			return -ENOMEM;
325*5113495bSYour Name 
326*5113495bSYour Name 		qdf_mem_copy(encrypt_decrypt_params->data,
327*5113495bSYour Name 			tmp + mac_hdr_len,
328*5113495bSYour Name 			encrypt_decrypt_params->data_len);
329*5113495bSYour Name 
330*5113495bSYour Name 		print_hex_dump(KERN_INFO, "Data received in request: ",
331*5113495bSYour Name 			DUMP_PREFIX_NONE, 16, 1,
332*5113495bSYour Name 			encrypt_decrypt_params->data,
333*5113495bSYour Name 			encrypt_decrypt_params->data_len, 0);
334*5113495bSYour Name 	}
335*5113495bSYour Name 
336*5113495bSYour Name 	return 0;
337*5113495bSYour Name }
338*5113495bSYour Name 
hdd_encrypt_decrypt_context_dealloc(void * priv)339*5113495bSYour Name static void hdd_encrypt_decrypt_context_dealloc(void *priv)
340*5113495bSYour Name {
341*5113495bSYour Name 	struct hdd_encrypt_decrypt_msg_context *context = priv;
342*5113495bSYour Name 
343*5113495bSYour Name 	qdf_mem_free(context->request.data);
344*5113495bSYour Name 	qdf_mem_free(context->response.data);
345*5113495bSYour Name }
346*5113495bSYour Name 
347*5113495bSYour Name /**
348*5113495bSYour Name  * hdd_encrypt_decrypt_msg () - process encrypt/decrypt message
349*5113495bSYour Name  * @adapter : adapter context
350*5113495bSYour Name  * @hdd_ctx: hdd context
351*5113495bSYour Name  * @data: Pointer to data
352*5113495bSYour Name  * @data_len: Data length
353*5113495bSYour Name  *
354*5113495bSYour Name  * Return: 0 on success, negative errno on failure
355*5113495bSYour Name  */
hdd_encrypt_decrypt_msg(struct hdd_adapter * adapter,struct hdd_context * hdd_ctx,const void * data,int data_len)356*5113495bSYour Name static int hdd_encrypt_decrypt_msg(struct hdd_adapter *adapter,
357*5113495bSYour Name 				   struct hdd_context *hdd_ctx,
358*5113495bSYour Name 				   const void *data,
359*5113495bSYour Name 				   int data_len)
360*5113495bSYour Name {
361*5113495bSYour Name 	QDF_STATUS qdf_status;
362*5113495bSYour Name 	int ret;
363*5113495bSYour Name 	void *cookie;
364*5113495bSYour Name 	struct osif_request *request;
365*5113495bSYour Name 	struct hdd_encrypt_decrypt_msg_context *context;
366*5113495bSYour Name 	static const struct osif_request_params params = {
367*5113495bSYour Name 		.priv_size = sizeof(*context),
368*5113495bSYour Name 		.timeout_ms = WLAN_WAIT_TIME_ENCRYPT_DECRYPT,
369*5113495bSYour Name 		.dealloc = hdd_encrypt_decrypt_context_dealloc,
370*5113495bSYour Name 	};
371*5113495bSYour Name 
372*5113495bSYour Name 	request = osif_request_alloc(&params);
373*5113495bSYour Name 	if (!request) {
374*5113495bSYour Name 		hdd_err("Request allocation failure");
375*5113495bSYour Name 		return -ENOMEM;
376*5113495bSYour Name 	}
377*5113495bSYour Name 	context = osif_request_priv(request);
378*5113495bSYour Name 
379*5113495bSYour Name 	ret = hdd_fill_encrypt_decrypt_params(&context->request, adapter,
380*5113495bSYour Name 					      data, data_len);
381*5113495bSYour Name 	if (ret)
382*5113495bSYour Name 		goto cleanup;
383*5113495bSYour Name 
384*5113495bSYour Name 	cookie = osif_request_cookie(request);
385*5113495bSYour Name 
386*5113495bSYour Name 	qdf_status = ucfg_disa_encrypt_decrypt_req(hdd_ctx->psoc,
387*5113495bSYour Name 				&context->request,
388*5113495bSYour Name 				hdd_encrypt_decrypt_msg_cb,
389*5113495bSYour Name 				cookie);
390*5113495bSYour Name 
391*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
392*5113495bSYour Name 		hdd_err("Unable to post encrypt/decrypt message");
393*5113495bSYour Name 		ret = -EINVAL;
394*5113495bSYour Name 		goto cleanup;
395*5113495bSYour Name 	}
396*5113495bSYour Name 
397*5113495bSYour Name 	ret = osif_request_wait_for_response(request);
398*5113495bSYour Name 	if (ret) {
399*5113495bSYour Name 		hdd_err("Target response timed out");
400*5113495bSYour Name 		goto cleanup;
401*5113495bSYour Name 	}
402*5113495bSYour Name 
403*5113495bSYour Name 	ret = context->status;
404*5113495bSYour Name 	if (ret) {
405*5113495bSYour Name 		hdd_err("Target response processing failed");
406*5113495bSYour Name 		goto cleanup;
407*5113495bSYour Name 	}
408*5113495bSYour Name 
409*5113495bSYour Name 	ret = hdd_post_encrypt_decrypt_msg_rsp(hdd_ctx, &context->response);
410*5113495bSYour Name 	if (ret)
411*5113495bSYour Name 		hdd_err("Failed to post encrypt/decrypt message response");
412*5113495bSYour Name 
413*5113495bSYour Name cleanup:
414*5113495bSYour Name 	osif_request_put(request);
415*5113495bSYour Name 
416*5113495bSYour Name 	hdd_exit();
417*5113495bSYour Name 	return ret;
418*5113495bSYour Name }
419*5113495bSYour Name 
420*5113495bSYour Name /**
421*5113495bSYour Name  * __wlan_hdd_cfg80211_encrypt_decrypt_msg () - Encrypt/Decrypt msg
422*5113495bSYour Name  * @wiphy: Pointer to wireless phy
423*5113495bSYour Name  * @wdev: Pointer to wireless device
424*5113495bSYour Name  * @data: Pointer to data
425*5113495bSYour Name  * @data_len: Data length
426*5113495bSYour Name  *
427*5113495bSYour Name  * Return: 0 on success, negative errno on failure
428*5113495bSYour Name  */
__wlan_hdd_cfg80211_encrypt_decrypt_msg(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)429*5113495bSYour Name static int __wlan_hdd_cfg80211_encrypt_decrypt_msg(struct wiphy *wiphy,
430*5113495bSYour Name 						struct wireless_dev *wdev,
431*5113495bSYour Name 						const void *data,
432*5113495bSYour Name 						int data_len)
433*5113495bSYour Name {
434*5113495bSYour Name 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
435*5113495bSYour Name 	struct net_device *dev = wdev->netdev;
436*5113495bSYour Name 	struct hdd_adapter *adapter = NULL;
437*5113495bSYour Name 	int ret;
438*5113495bSYour Name 	bool is_bmps_enabled;
439*5113495bSYour Name 
440*5113495bSYour Name 	hdd_enter_dev(dev);
441*5113495bSYour Name 
442*5113495bSYour Name 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
443*5113495bSYour Name 		hdd_err("Command not allowed in FTM mode");
444*5113495bSYour Name 		return -EPERM;
445*5113495bSYour Name 	}
446*5113495bSYour Name 
447*5113495bSYour Name 	ret = wlan_hdd_validate_context(hdd_ctx);
448*5113495bSYour Name 	if (ret)
449*5113495bSYour Name 		return ret;
450*5113495bSYour Name 
451*5113495bSYour Name 	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
452*5113495bSYour Name 
453*5113495bSYour Name 	ucfg_mlme_is_bmps_enabled(hdd_ctx->psoc, &is_bmps_enabled);
454*5113495bSYour Name 	if (is_bmps_enabled) {
455*5113495bSYour Name 		hdd_debug("DISA is not supported when PS is enabled");
456*5113495bSYour Name 		return -EINVAL;
457*5113495bSYour Name 	}
458*5113495bSYour Name 
459*5113495bSYour Name 	ret = hdd_encrypt_decrypt_msg(adapter, hdd_ctx, data, data_len);
460*5113495bSYour Name 
461*5113495bSYour Name 	return ret;
462*5113495bSYour Name }
463*5113495bSYour Name 
464*5113495bSYour Name /**
465*5113495bSYour Name  * wlan_hdd_cfg80211_encrypt_decrypt_msg () - Encrypt/Decrypt msg
466*5113495bSYour Name  * @wiphy: Pointer to wireless phy
467*5113495bSYour Name  * @wdev: Pointer to wireless device
468*5113495bSYour Name  * @data: Pointer to data
469*5113495bSYour Name  * @data_len: Data length
470*5113495bSYour Name  *
471*5113495bSYour Name  * Return: 0 on success, negative errno on failure
472*5113495bSYour Name  */
wlan_hdd_cfg80211_encrypt_decrypt_msg(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)473*5113495bSYour Name int wlan_hdd_cfg80211_encrypt_decrypt_msg(struct wiphy *wiphy,
474*5113495bSYour Name 						struct wireless_dev *wdev,
475*5113495bSYour Name 						const void *data,
476*5113495bSYour Name 						int data_len)
477*5113495bSYour Name {
478*5113495bSYour Name 	int errno;
479*5113495bSYour Name 	struct osif_vdev_sync *vdev_sync;
480*5113495bSYour Name 
481*5113495bSYour Name 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
482*5113495bSYour Name 	if (errno)
483*5113495bSYour Name 		return errno;
484*5113495bSYour Name 
485*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_encrypt_decrypt_msg(wiphy, wdev,
486*5113495bSYour Name 							data, data_len);
487*5113495bSYour Name 
488*5113495bSYour Name 	osif_vdev_sync_op_stop(vdev_sync);
489*5113495bSYour Name 
490*5113495bSYour Name 	return errno;
491*5113495bSYour Name }
492