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  
wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev * vdev,bool pairwise,enum wlan_crypto_cipher_type cipher_type,struct set_key_params * params)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
wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev * vdev,bool pairwise,enum wlan_crypto_cipher_type cipher_type,struct set_key_params * params)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
wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev * vdev,bool pairwise,enum wlan_crypto_cipher_type cipher,struct set_key_params * params)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
target_if_crypto_vdev_set_param(struct wlan_objmgr_psoc * psoc,uint32_t vdev_id,uint32_t param_id,uint32_t param_value)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  
target_if_crypto_set_key(struct wlan_objmgr_vdev * vdev,struct wlan_crypto_key * req,enum wlan_crypto_key_type key_type)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
target_if_crypto_install_key_comp_evt_handler(void * handle,uint8_t * event,uint32_t len)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
target_if_crypto_register_events(struct wlan_objmgr_psoc * psoc)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
target_if_crypto_deregister_events(struct wlan_objmgr_psoc * psoc)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
target_if_crypto_set_ltf_keyseed(struct wlan_objmgr_psoc * psoc,struct wlan_crypto_ltf_keyseed_data * data)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  
target_if_crypto_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)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