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(¶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 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 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, ¶m); 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(¶ms.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, ¶ms); 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(¶ms.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], ¶ms.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 ¶ms.key_rsc_counter, sizeof(uint64_t)); 289 status = wmi_unified_setup_install_key_cmd(pdev_wmi_handle, ¶ms); 290 291 /* Zero-out local key variables */ 292 qdf_mem_zero(¶ms, 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, ¶ms); 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