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