xref: /wlan-dirver/qca-wifi-host-cmn/target_if/crypto/src/target_if_crypto.c (revision d93db0f70eb35f5bb04948516ece4686b81fc044)
1 /*
2  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 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: %02x:%02x:%02x:%02x:%02x:%02x",
215 			key_type, req->macaddr[0], req->macaddr[1],
216 			req->macaddr[2], req->macaddr[3], req->macaddr[4],
217 			req->macaddr[5]);
218 
219 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_NAN_DISC_MODE) {
220 		peer_exist = cdp_find_peer_exist(soc,
221 						 pdev->pdev_objmgr.wlan_pdev_id,
222 						 req->macaddr);
223 
224 		peer = wlan_objmgr_get_peer_by_mac(psoc, req->macaddr,
225 						   WLAN_CRYPTO_ID);
226 		if (peer) {
227 			peer_type = wlan_peer_get_peer_type(peer);
228 			if (peer_type == WLAN_PEER_RTT_PASN &&
229 			    key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST)
230 				peer_exist = true;
231 
232 			wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
233 		}
234 
235 		if ((key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) && !peer_exist) {
236 			target_if_err("Invalid peer");
237 			return QDF_STATUS_E_FAILURE;
238 		}
239 	}
240 
241 	params.key_cipher = wlan_crypto_cipher_to_wmi_cipher(req->cipher_type);
242 	sec_type = wlan_crypto_cipher_to_cdp_sec_type(req->cipher_type);
243 	wlan_crypto_set_wapi_key(vdev, pairwise, req->cipher_type, &params);
244 
245 	switch (req->cipher_type) {
246 	case WLAN_CRYPTO_CIPHER_WEP:
247 	case WLAN_CRYPTO_CIPHER_WEP_40:
248 	case WLAN_CRYPTO_CIPHER_WEP_104:
249 		def_tx_idx = wlan_crypto_get_default_key_idx(vdev, false);
250 		if (pairwise && params.key_idx == def_tx_idx)
251 			params.key_flags |= TX_USAGE;
252 		else if ((vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) &&
253 			 (params.key_idx == def_tx_idx))
254 			params.key_flags |= TX_USAGE;
255 		break;
256 	case WLAN_CRYPTO_CIPHER_TKIP:
257 		params.key_txmic_len = WLAN_CRYPTO_MIC_LEN;
258 		params.key_rxmic_len = WLAN_CRYPTO_MIC_LEN;
259 		break;
260 	default:
261 		break;
262 	}
263 
264 	qdf_mem_copy(&params.key_data[0], &req->keyval[0], req->keylen);
265 	params.key_len = req->keylen;
266 
267 	/* Set PN check & security type in data path */
268 	qdf_mem_copy(&pn[0], &params.key_rsc_counter, sizeof(uint64_t));
269 
270 	if (peer_type == WLAN_PEER_RTT_PASN)
271 		goto send_install_key;
272 
273 	cdp_set_pn_check(soc, vdev->vdev_objmgr.vdev_id, req->macaddr,
274 			 sec_type, pn);
275 
276 	cdp_set_key_sec_type(soc, vdev->vdev_objmgr.vdev_id, req->macaddr,
277 			     sec_type, pairwise);
278 
279 	cdp_set_key(soc, vdev->vdev_objmgr.vdev_id, req->macaddr, pairwise,
280 		    (uint32_t *)(req->keyval + WLAN_CRYPTO_IV_SIZE +
281 		     WLAN_CRYPTO_MIC_LEN));
282 send_install_key:
283 	target_if_debug("vdev_id:%d, key: idx:%d,len:%d", params.vdev_id,
284 			params.key_idx, params.key_len);
285 	target_if_debug("peer mac "QDF_MAC_ADDR_FMT,
286 			QDF_MAC_ADDR_REF(params.peer_mac));
287 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_DEBUG,
288 			   &params.key_rsc_counter, sizeof(uint64_t));
289 	status = wmi_unified_setup_install_key_cmd(pdev_wmi_handle, &params);
290 
291 	/* Zero-out local key variables */
292 	qdf_mem_zero(&params, sizeof(struct set_key_params));
293 
294 	return status;
295 }
296 
297 /**
298  * target_if_crypto_install_key_comp_evt_handler() - install key complete
299  *   handler
300  * @handle: wma handle
301  * @event: event data
302  * @len: data length
303  *
304  * This event is sent by fw once WPA/WPA2 keys are installed in fw.
305  *
306  * Return: 0 for success or error code
307  */
308 static int
309 target_if_crypto_install_key_comp_evt_handler(void *handle, uint8_t *event,
310 					      uint32_t len)
311 {
312 	struct wlan_crypto_comp_priv *priv_obj;
313 	struct wlan_objmgr_psoc *psoc;
314 	struct wlan_objmgr_vdev *vdev;
315 	struct wmi_install_key_comp_event params;
316 	QDF_STATUS status;
317 	wmi_unified_t wmi_handle;
318 	struct crypto_add_key_result result;
319 
320 	if (!event || !handle) {
321 		target_if_err("invalid param");
322 		return -EINVAL;
323 	}
324 
325 	psoc = target_if_get_psoc_from_scn_hdl(handle);
326 	if (!psoc) {
327 		target_if_err("psoc is null");
328 		return -EINVAL;
329 	}
330 
331 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
332 	if (!wmi_handle) {
333 		target_if_err("invalid wmi handle");
334 		return -EINVAL;
335 	}
336 
337 	status = wmi_extract_install_key_comp_event(wmi_handle, event,
338 						    len, &params);
339 	if (QDF_IS_STATUS_ERROR(status)) {
340 		target_if_err("received invalid buf from target");
341 		return -EINVAL;
342 	}
343 
344 	target_if_debug("vdev %d mac " QDF_MAC_ADDR_FMT " ix %x flags %x status %d",
345 			params.vdev_id,
346 			QDF_MAC_ADDR_REF(params.peer_macaddr),
347 			params.key_ix, params.key_flags, params.status);
348 
349 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, params.vdev_id,
350 						    WLAN_CRYPTO_ID);
351 	if (!vdev) {
352 		target_if_err("vdev %d is null", params.vdev_id);
353 		return -EINVAL;
354 	}
355 
356 	priv_obj = wlan_get_vdev_crypto_obj(vdev);
357 	if (!priv_obj) {
358 		target_if_err("priv_obj is null");
359 		wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
360 		return -EINVAL;
361 	}
362 
363 	result.vdev_id = params.vdev_id;
364 	result.key_ix = params.key_ix;
365 	result.key_flags = params.key_flags;
366 	result.status = params.status;
367 	qdf_mem_copy(result.peer_macaddr, params.peer_macaddr,
368 		     QDF_MAC_ADDR_SIZE);
369 
370 	if (priv_obj->add_key_cb)
371 		priv_obj->add_key_cb(priv_obj->add_key_ctx, &result);
372 
373 	wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
374 
375 	return 0;
376 }
377 
378 static QDF_STATUS
379 target_if_crypto_register_events(struct wlan_objmgr_psoc *psoc)
380 {
381 	QDF_STATUS status;
382 
383 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
384 		target_if_err("psoc or psoc->tgt_if_handle is null");
385 		return QDF_STATUS_E_INVAL;
386 	}
387 
388 	status = wmi_unified_register_event_handler(
389 			get_wmi_unified_hdl_from_psoc(psoc),
390 			wmi_vdev_install_key_complete_event_id,
391 			target_if_crypto_install_key_comp_evt_handler,
392 			WMI_RX_WORK_CTX);
393 	if (QDF_IS_STATUS_ERROR(status)) {
394 		target_if_err("register_event_handler failed: err %d", status);
395 		return status;
396 	}
397 
398 	return QDF_STATUS_SUCCESS;
399 }
400 
401 static QDF_STATUS
402 target_if_crypto_deregister_events(struct wlan_objmgr_psoc *psoc)
403 {
404 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
405 		target_if_err("psoc or psoc->tgt_if_handle is null");
406 		return QDF_STATUS_E_INVAL;
407 	}
408 
409 	wmi_unified_unregister_event_handler(
410 			get_wmi_unified_hdl_from_psoc(psoc),
411 			wmi_vdev_install_key_complete_event_id);
412 
413 	return QDF_STATUS_SUCCESS;
414 }
415 
416 static QDF_STATUS
417 target_if_crypto_set_ltf_keyseed(struct wlan_objmgr_psoc *psoc,
418 				 struct wlan_crypto_ltf_keyseed_data *data)
419 {
420 	QDF_STATUS status;
421 	wmi_unified_t wmi = GET_WMI_HDL_FROM_PSOC(psoc);
422 
423 	if (!psoc || !wmi) {
424 		target_if_err("%s is null", !psoc ? "psoc" : "wmi_handle");
425 		return QDF_STATUS_E_INVAL;
426 	}
427 
428 	status = wmi_send_vdev_set_ltf_key_seed_cmd(wmi, data);
429 	if (QDF_IS_STATUS_ERROR(status))
430 		target_if_err("set LTF keyseed failed");
431 
432 	return status;
433 }
434 
435 QDF_STATUS target_if_crypto_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
436 {
437 	struct wlan_lmac_if_crypto_tx_ops *crypto;
438 
439 	if (!tx_ops) {
440 		target_if_err("txops NULL");
441 		return QDF_STATUS_E_FAILURE;
442 	}
443 	crypto = &tx_ops->crypto_tx_ops;
444 
445 	crypto->set_key = target_if_crypto_set_key;
446 	crypto->set_ltf_keyseed = target_if_crypto_set_ltf_keyseed;
447 	crypto->set_vdev_param  = target_if_crypto_vdev_set_param;
448 	crypto->register_events = target_if_crypto_register_events;
449 	crypto->deregister_events = target_if_crypto_deregister_events;
450 
451 	return QDF_STATUS_SUCCESS;
452 }
453 
454