xref: /wlan-dirver/qca-wifi-host-cmn/target_if/crypto/src/target_if_crypto.c (revision 6a00a21f34357356c1570249df5fbd95947e02e6)
1 /*
2  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: offload lmac interface APIs definitions for crypto
22  */
23 
24 #include <qdf_mem.h>
25 #include <qdf_status.h>
26 #include <target_if_crypto.h>
27 #include <wmi_unified_priv.h>
28 #include <wmi_unified_param.h>
29 #include <wlan_objmgr_psoc_obj.h>
30 #include <target_if.h>
31 #include <wlan_crypto_global_def.h>
32 #include <wlan_crypto_global_api.h>
33 #include <wlan_objmgr_vdev_obj.h>
34 #include <cdp_txrx_cmn_struct.h>
35 #include <cds_api.h>
36 #include <cdp_txrx_cmn.h>
37 #include <wmi_unified_api.h>
38 #include <wmi_unified_crypto_api.h>
39 #include <cdp_txrx_peer_ops.h>
40 #include <wlan_objmgr_pdev_obj.h>
41 #include <wlan_objmgr_peer_obj.h>
42 #include "wlan_crypto_def_i.h"
43 #include "wlan_crypto_obj_mgr_i.h"
44 
45 #ifdef FEATURE_WLAN_WAPI
46 #ifdef FEATURE_WAPI_BIG_ENDIAN
47 /*
48  * All lithium firmware expects WAPI in big endian
49  * format , whereas helium firmware's expect otherwise
50  */
51 
52 static void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev,
53 				     bool pairwise,
54 				     enum wlan_crypto_cipher_type cipher_type,
55 				     struct set_key_params *params)
56 {
57 	static const unsigned char tx_iv[16] = {0x5c, 0x36, 0x5c, 0x36, 0x5c,
58 						0x36, 0x5c, 0x36, 0x5c, 0x36,
59 						0x5c, 0x36, 0x5c, 0x36, 0x5c,
60 						0x36};
61 
62 	static const unsigned char rx_iv[16] = {0x5c, 0x36, 0x5c, 0x36, 0x5c,
63 						0x36, 0x5c, 0x36, 0x5c, 0x36,
64 						0x5c, 0x36, 0x5c, 0x36, 0x5c,
65 						0x37};
66 
67 	if (cipher_type != WLAN_CRYPTO_CIPHER_WAPI_SMS4 &&
68 	    cipher_type != WLAN_CRYPTO_CIPHER_WAPI_GCM4)
69 		return;
70 
71 	if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE ||
72 	    vdev->vdev_mlme.vdev_opmode == QDF_P2P_GO_MODE) {
73 			qdf_mem_copy(&params->rx_iv, &tx_iv,
74 					 WLAN_CRYPTO_WAPI_IV_SIZE);
75 			qdf_mem_copy(params->tx_iv, &rx_iv,
76 					 WLAN_CRYPTO_WAPI_IV_SIZE);
77 	} else {
78 			qdf_mem_copy(params->rx_iv, &rx_iv,
79 					 WLAN_CRYPTO_WAPI_IV_SIZE);
80 			qdf_mem_copy(params->tx_iv, &tx_iv,
81 					 WLAN_CRYPTO_WAPI_IV_SIZE);
82 		}
83 
84 	params->key_txmic_len = WLAN_CRYPTO_MIC_LEN;
85 	params->key_rxmic_len = WLAN_CRYPTO_MIC_LEN;
86 }
87 #else
88 static void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev,
89 				     bool pairwise,
90 				     enum wlan_crypto_cipher_type cipher_type,
91 				     struct set_key_params *params)
92 {
93 	static const unsigned char tx_iv[16] = {0x36, 0x5c, 0x36, 0x5c, 0x36,
94 						0x5c, 0x36, 0x5c, 0x36, 0x5c,
95 						0x36, 0x5c, 0x36, 0x5c, 0x36,
96 						0x5c};
97 
98 	static const unsigned char rx_iv[16] = {0x5c, 0x36, 0x5c, 0x36, 0x5c,
99 						0x36, 0x5c, 0x36, 0x5c, 0x36,
100 						0x5c, 0x36, 0x5c, 0x36, 0x5c,
101 						0x37};
102 
103 	if (cipher_type != WLAN_CRYPTO_CIPHER_WAPI_SMS4 &&
104 	    cipher_type != WLAN_CRYPTO_CIPHER_WAPI_GCM4)
105 		return;
106 
107 	qdf_mem_copy(&params->rx_iv, &rx_iv,
108 		     WLAN_CRYPTO_WAPI_IV_SIZE);
109 	qdf_mem_copy(&params->tx_iv, &tx_iv,
110 		     WLAN_CRYPTO_WAPI_IV_SIZE);
111 
112 	if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) {
113 		if (pairwise)
114 			params->tx_iv[0] = 0x37;
115 
116 		params->rx_iv[WLAN_CRYPTO_WAPI_IV_SIZE - 1] = 0x36;
117 	} else {
118 		if (!pairwise)
119 			params->rx_iv[WLAN_CRYPTO_WAPI_IV_SIZE - 1] = 0x36;
120 	}
121 
122 	params->key_txmic_len = WLAN_CRYPTO_MIC_LEN;
123 	params->key_rxmic_len = WLAN_CRYPTO_MIC_LEN;
124 }
125 #endif /* FEATURE_WAPI_BIG_ENDIAN */
126 #else
127 static inline void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev,
128 					    bool pairwise,
129 					    enum wlan_crypto_cipher_type cipher,
130 					    struct set_key_params *params)
131 {
132 }
133 #endif /* FEATURE_WLAN_WAPI */
134 
135 QDF_STATUS
136 target_if_crypto_vdev_set_param(struct wlan_objmgr_psoc *psoc, uint32_t vdev_id,
137 				uint32_t param_id, uint32_t param_value)
138 {
139 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
140 	struct vdev_set_params param = {0};
141 
142 	if (!wmi_handle) {
143 		target_if_err("Invalid wmi handle");
144 		return QDF_STATUS_E_INVAL;
145 	}
146 
147 	if (vdev_id >= WLAN_MAX_VDEVS) {
148 		target_if_err("vdev_id: %d is invalid, reject the req: param id %d val %d",
149 			      vdev_id, param_id, param_value);
150 		return QDF_STATUS_E_INVAL;
151 	}
152 
153 	param.vdev_id = vdev_id;
154 	param.param_id = param_id;
155 	param.param_value = param_value;
156 
157 	return wmi_unified_vdev_set_param_send(wmi_handle, &param);
158 }
159 
160 QDF_STATUS target_if_crypto_set_key(struct wlan_objmgr_vdev *vdev,
161 				    struct wlan_crypto_key *req,
162 				    enum wlan_crypto_key_type key_type)
163 {
164 	struct set_key_params params = {0};
165 	struct wlan_objmgr_psoc *psoc;
166 	struct wlan_objmgr_pdev *pdev;
167 	struct wlan_objmgr_peer *peer;
168 	enum cdp_sec_type sec_type = cdp_sec_type_none;
169 	enum wlan_peer_type peer_type = 0;
170 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
171 	uint32_t pn[4] = {0, 0, 0, 0};
172 	bool peer_exist = false;
173 	uint8_t def_tx_idx;
174 	wmi_unified_t pdev_wmi_handle;
175 	bool pairwise;
176 	QDF_STATUS status;
177 
178 	pdev = wlan_vdev_get_pdev(vdev);
179 	if (!pdev) {
180 		target_if_err("Invalid PDEV");
181 		return QDF_STATUS_E_FAILURE;
182 	}
183 	psoc = wlan_vdev_get_psoc(vdev);
184 	if (!psoc) {
185 		target_if_err("Invalid PSOC");
186 		return QDF_STATUS_E_FAILURE;
187 	}
188 	soc = wlan_psoc_get_dp_handle(psoc);
189 	if (!soc) {
190 		target_if_err("Invalid DP Handle");
191 		return QDF_STATUS_E_FAILURE;
192 	}
193 	params.vdev_id = wlan_vdev_get_id(vdev);
194 	params.key_idx = req->keyix;
195 	qdf_mem_copy(params.peer_mac, req->macaddr, QDF_MAC_ADDR_SIZE);
196 	pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
197 	if (!pdev_wmi_handle) {
198 		target_if_err("Invalid PDEV WMI handle");
199 		return QDF_STATUS_E_FAILURE;
200 	}
201 
202 	params.key_flags = req->flags;
203 	if (key_type != WLAN_CRYPTO_KEY_TYPE_UNICAST) {
204 		pairwise = false;
205 		params.key_flags |= GROUP_USAGE;
206 
207 	} else {
208 		pairwise = true;
209 		params.key_flags |= PAIRWISE_USAGE;
210 	}
211 	qdf_mem_copy(&params.key_rsc_counter,
212 		     &req->keyrsc[0], sizeof(uint64_t));
213 
214 	target_if_debug("key_type %d, mac: " QDF_MAC_ADDR_FMT,
215 			key_type, QDF_MAC_ADDR_REF(req->macaddr));
216 
217 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_NAN_DISC_MODE) {
218 		peer_exist = cdp_find_peer_exist(soc,
219 						 pdev->pdev_objmgr.wlan_pdev_id,
220 						 req->macaddr);
221 
222 		peer = wlan_objmgr_get_peer_by_mac(psoc, req->macaddr,
223 						   WLAN_CRYPTO_ID);
224 		if (peer) {
225 			peer_type = wlan_peer_get_peer_type(peer);
226 			if (peer_type == WLAN_PEER_RTT_PASN &&
227 			    key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST)
228 				peer_exist = true;
229 
230 			wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
231 		}
232 
233 		if ((key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) && !peer_exist) {
234 			target_if_err("Invalid peer");
235 			return QDF_STATUS_E_FAILURE;
236 		}
237 	}
238 
239 	params.key_cipher = wlan_crypto_cipher_to_wmi_cipher(req->cipher_type);
240 	sec_type = wlan_crypto_cipher_to_cdp_sec_type(req->cipher_type);
241 	wlan_crypto_set_wapi_key(vdev, pairwise, req->cipher_type, &params);
242 
243 	switch (req->cipher_type) {
244 	case WLAN_CRYPTO_CIPHER_WEP:
245 	case WLAN_CRYPTO_CIPHER_WEP_40:
246 	case WLAN_CRYPTO_CIPHER_WEP_104:
247 		def_tx_idx = wlan_crypto_get_default_key_idx(vdev, false);
248 		if (pairwise && params.key_idx == def_tx_idx)
249 			params.key_flags |= TX_USAGE;
250 		else if ((vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) &&
251 			 (params.key_idx == def_tx_idx))
252 			params.key_flags |= TX_USAGE;
253 		break;
254 	case WLAN_CRYPTO_CIPHER_TKIP:
255 		params.key_txmic_len = WLAN_CRYPTO_MIC_LEN;
256 		params.key_rxmic_len = WLAN_CRYPTO_MIC_LEN;
257 		break;
258 	default:
259 		break;
260 	}
261 
262 	qdf_mem_copy(&params.key_data[0], &req->keyval[0], req->keylen);
263 	params.key_len = req->keylen;
264 
265 	/* Set PN check & security type in data path */
266 	qdf_mem_copy(&pn[0], &params.key_rsc_counter, sizeof(uint64_t));
267 
268 	if (peer_type == WLAN_PEER_RTT_PASN)
269 		goto send_install_key;
270 
271 	cdp_set_pn_check(soc, vdev->vdev_objmgr.vdev_id, req->macaddr,
272 			 sec_type, pn);
273 
274 	cdp_set_key_sec_type(soc, vdev->vdev_objmgr.vdev_id, req->macaddr,
275 			     sec_type, pairwise);
276 
277 	cdp_set_key(soc, vdev->vdev_objmgr.vdev_id, req->macaddr, pairwise,
278 		    (uint32_t *)(req->keyval + WLAN_CRYPTO_IV_SIZE +
279 		     WLAN_CRYPTO_MIC_LEN));
280 send_install_key:
281 	target_if_debug("vdev_id:%d, key: idx:%d,len:%d", params.vdev_id,
282 			params.key_idx, params.key_len);
283 	target_if_debug("peer mac "QDF_MAC_ADDR_FMT,
284 			QDF_MAC_ADDR_REF(params.peer_mac));
285 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_DEBUG,
286 			   &params.key_rsc_counter, sizeof(uint64_t));
287 	status = wmi_unified_setup_install_key_cmd(pdev_wmi_handle, &params);
288 
289 	/* Zero-out local key variables */
290 	qdf_mem_zero(&params, sizeof(struct set_key_params));
291 
292 	return status;
293 }
294 
295 /**
296  * target_if_crypto_install_key_comp_evt_handler() - install key complete
297  *   handler
298  * @handle: wma handle
299  * @event: event data
300  * @len: data length
301  *
302  * This event is sent by fw once WPA/WPA2 keys are installed in fw.
303  *
304  * Return: 0 for success or error code
305  */
306 static int
307 target_if_crypto_install_key_comp_evt_handler(void *handle, uint8_t *event,
308 					      uint32_t len)
309 {
310 	struct wlan_crypto_comp_priv *priv_obj;
311 	struct wlan_objmgr_psoc *psoc;
312 	struct wlan_objmgr_vdev *vdev;
313 	struct wmi_install_key_comp_event params;
314 	QDF_STATUS status;
315 	wmi_unified_t wmi_handle;
316 	struct crypto_add_key_result result;
317 
318 	if (!event || !handle) {
319 		target_if_err("invalid param");
320 		return -EINVAL;
321 	}
322 
323 	psoc = target_if_get_psoc_from_scn_hdl(handle);
324 	if (!psoc) {
325 		target_if_err("psoc is null");
326 		return -EINVAL;
327 	}
328 
329 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
330 	if (!wmi_handle) {
331 		target_if_err("invalid wmi handle");
332 		return -EINVAL;
333 	}
334 
335 	status = wmi_extract_install_key_comp_event(wmi_handle, event,
336 						    len, &params);
337 	if (QDF_IS_STATUS_ERROR(status)) {
338 		target_if_err("received invalid buf from target");
339 		return -EINVAL;
340 	}
341 
342 	target_if_debug("vdev %d mac " QDF_MAC_ADDR_FMT " ix %x flags %x status %d",
343 			params.vdev_id,
344 			QDF_MAC_ADDR_REF(params.peer_macaddr),
345 			params.key_ix, params.key_flags, params.status);
346 
347 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, params.vdev_id,
348 						    WLAN_CRYPTO_ID);
349 	if (!vdev) {
350 		target_if_err("vdev %d is null", params.vdev_id);
351 		return -EINVAL;
352 	}
353 
354 	priv_obj = wlan_get_vdev_crypto_obj(vdev);
355 	if (!priv_obj) {
356 		target_if_err("priv_obj is null");
357 		wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
358 		return -EINVAL;
359 	}
360 
361 	result.vdev_id = params.vdev_id;
362 	result.key_ix = params.key_ix;
363 	result.key_flags = params.key_flags;
364 	result.status = params.status;
365 	qdf_mem_copy(result.peer_macaddr, params.peer_macaddr,
366 		     QDF_MAC_ADDR_SIZE);
367 
368 	if (priv_obj->add_key_cb)
369 		priv_obj->add_key_cb(priv_obj->add_key_ctx, &result);
370 
371 	wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
372 
373 	return 0;
374 }
375 
376 static QDF_STATUS
377 target_if_crypto_register_events(struct wlan_objmgr_psoc *psoc)
378 {
379 	QDF_STATUS status;
380 
381 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
382 		target_if_err("psoc or psoc->tgt_if_handle is null");
383 		return QDF_STATUS_E_INVAL;
384 	}
385 
386 	status = wmi_unified_register_event_handler(
387 			get_wmi_unified_hdl_from_psoc(psoc),
388 			wmi_vdev_install_key_complete_event_id,
389 			target_if_crypto_install_key_comp_evt_handler,
390 			WMI_RX_WORK_CTX);
391 	if (QDF_IS_STATUS_ERROR(status)) {
392 		target_if_err("register_event_handler failed: err %d", status);
393 		return status;
394 	}
395 
396 	return QDF_STATUS_SUCCESS;
397 }
398 
399 static QDF_STATUS
400 target_if_crypto_deregister_events(struct wlan_objmgr_psoc *psoc)
401 {
402 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
403 		target_if_err("psoc or psoc->tgt_if_handle is null");
404 		return QDF_STATUS_E_INVAL;
405 	}
406 
407 	wmi_unified_unregister_event_handler(
408 			get_wmi_unified_hdl_from_psoc(psoc),
409 			wmi_vdev_install_key_complete_event_id);
410 
411 	return QDF_STATUS_SUCCESS;
412 }
413 
414 static QDF_STATUS
415 target_if_crypto_set_ltf_keyseed(struct wlan_objmgr_psoc *psoc,
416 				 struct wlan_crypto_ltf_keyseed_data *data)
417 {
418 	QDF_STATUS status;
419 	wmi_unified_t wmi = GET_WMI_HDL_FROM_PSOC(psoc);
420 
421 	if (!psoc || !wmi) {
422 		target_if_err("%s is null", !psoc ? "psoc" : "wmi_handle");
423 		return QDF_STATUS_E_INVAL;
424 	}
425 
426 	status = wmi_send_vdev_set_ltf_key_seed_cmd(wmi, data);
427 	if (QDF_IS_STATUS_ERROR(status))
428 		target_if_err("set LTF keyseed failed");
429 
430 	return status;
431 }
432 
433 QDF_STATUS target_if_crypto_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
434 {
435 	struct wlan_lmac_if_crypto_tx_ops *crypto;
436 
437 	if (!tx_ops) {
438 		target_if_err("txops NULL");
439 		return QDF_STATUS_E_FAILURE;
440 	}
441 	crypto = &tx_ops->crypto_tx_ops;
442 
443 	crypto->set_key = target_if_crypto_set_key;
444 	crypto->set_ltf_keyseed = target_if_crypto_set_ltf_keyseed;
445 	crypto->set_vdev_param  = target_if_crypto_vdev_set_param;
446 	crypto->register_events = target_if_crypto_register_events;
447 	crypto->deregister_events = target_if_crypto_deregister_events;
448 
449 	return QDF_STATUS_SUCCESS;
450 }
451 
452