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(¶ms->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(¶ms->rx_iv, &rx_iv,
108 WLAN_CRYPTO_WAPI_IV_SIZE);
109 qdf_mem_copy(¶ms->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, ¶m);
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(¶ms.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, ¶ms);
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(¶ms.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], ¶ms.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 ¶ms.key_rsc_counter, sizeof(uint64_t));
287 status = wmi_unified_setup_install_key_cmd(pdev_wmi_handle, ¶ms);
288
289 /* Zero-out local key variables */
290 qdf_mem_zero(¶ms, 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, ¶ms);
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