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(¶ms->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(¶ms->rx_iv, &rx_iv, 107 WLAN_CRYPTO_WAPI_IV_SIZE); 108 qdf_mem_copy(¶ms->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(¶ms.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, ¶ms); 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(¶ms.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], ¶ms.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 ¶ms.key_rsc_ctr, sizeof(uint64_t)); 242 status = wmi_unified_setup_install_key_cmd(pdev_wmi_handle, ¶ms); 243 244 /* Zero-out local key variables */ 245 qdf_mem_zero(¶ms, 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, ¶ms); 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