1 /* 2 * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 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: defines crypto driver functions interfacing with linux kernel 22 */ 23 #include <wlan_crypto_global_def.h> 24 #include <wlan_crypto_global_api.h> 25 #include <wlan_objmgr_vdev_obj.h> 26 #include <wlan_crypto_main_i.h> 27 #include <wlan_objmgr_pdev_obj.h> 28 #include <wlan_objmgr_peer_obj.h> 29 #include <wlan_crypto_def_i.h> 30 #include <wlan_crypto_obj_mgr_i.h> 31 #include <net/cfg80211.h> 32 #include <wlan_nl_to_crypto_params.h> 33 #include "wlan_cfg80211_crypto.h" 34 #include <wlan_cfg80211.h> 35 #include <wlan_osif_request_manager.h> 36 37 void wlan_cfg80211_translate_ml_sta_key(uint8_t key_index, 38 enum wlan_crypto_key_type key_type, 39 const u8 *mac_addr, 40 struct key_params *params, 41 struct wlan_crypto_key *crypto_key) 42 { 43 qdf_mem_zero(crypto_key, sizeof(*crypto_key)); 44 crypto_key->keylen = params->key_len; 45 crypto_key->keyix = key_index; 46 osif_debug("key_type %d, key_len %d, seq_len %d", 47 key_type, 48 params->key_len, params->seq_len); 49 qdf_mem_copy(&crypto_key->keyval[0], params->key, params->key_len); 50 qdf_mem_copy(&crypto_key->keyrsc[0], params->seq, params->seq_len); 51 52 crypto_key->key_type = key_type; 53 crypto_key->cipher_type = osif_nl_to_crypto_cipher_type(params->cipher); 54 55 if (IS_WEP_CIPHER(crypto_key->cipher_type) && !mac_addr) { 56 /* 57 * This is a valid scenario in case of WEP, where-in the 58 * keys are passed by the user space during the connect request 59 * but since we did not connect yet, so we do not know the peer 60 * address yet. 61 */ 62 osif_debug("No Mac Address to copy"); 63 return; 64 } 65 qdf_mem_copy(&crypto_key->macaddr, mac_addr, 66 QDF_MAC_ADDR_SIZE); 67 osif_debug("crypto key mac " QDF_MAC_ADDR_FMT, 68 QDF_MAC_ADDR_REF(crypto_key->macaddr)); 69 } 70 71 void wlan_cfg80211_translate_key(struct wlan_objmgr_vdev *vdev, 72 uint8_t key_index, 73 enum wlan_crypto_key_type key_type, 74 const u8 *mac_addr, 75 struct key_params *params, 76 struct wlan_crypto_key *crypto_key) 77 { 78 qdf_mem_zero(crypto_key, sizeof(*crypto_key)); 79 crypto_key->keylen = params->key_len; 80 crypto_key->keyix = key_index; 81 osif_debug("key_type %d, opmode %d, key_len %d, seq_len %d", 82 key_type, vdev->vdev_mlme.vdev_opmode, 83 params->key_len, params->seq_len); 84 qdf_mem_copy(&crypto_key->keyval[0], params->key, params->key_len); 85 qdf_mem_copy(&crypto_key->keyrsc[0], params->seq, params->seq_len); 86 87 crypto_key->key_type = key_type; 88 crypto_key->cipher_type = osif_nl_to_crypto_cipher_type(params->cipher); 89 if (IS_WEP_CIPHER(crypto_key->cipher_type) && !mac_addr) { 90 /* 91 * This is a valid scenario in case of WEP, where-in the 92 * keys are passed by the user space during the connect request 93 * but since we did not connect yet, so we do not know the peer 94 * address yet. 95 */ 96 osif_debug("No Mac Address to copy"); 97 return; 98 } 99 if (key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) { 100 qdf_mem_copy(&crypto_key->macaddr, mac_addr, QDF_MAC_ADDR_SIZE); 101 } else { 102 if ((vdev->vdev_mlme.vdev_opmode == QDF_STA_MODE) || 103 (vdev->vdev_mlme.vdev_opmode == QDF_P2P_CLIENT_MODE)) 104 qdf_mem_copy(&crypto_key->macaddr, mac_addr, 105 QDF_MAC_ADDR_SIZE); 106 else 107 qdf_mem_copy(&crypto_key->macaddr, 108 vdev->vdev_mlme.macaddr, 109 QDF_MAC_ADDR_SIZE); 110 } 111 osif_debug("mac "QDF_MAC_ADDR_FMT, 112 QDF_MAC_ADDR_REF(crypto_key->macaddr)); 113 } 114 115 int wlan_cfg80211_store_link_key(struct wlan_objmgr_psoc *psoc, 116 uint8_t key_index, 117 enum wlan_crypto_key_type key_type, 118 const u8 *mac_addr, struct key_params *params, 119 struct qdf_mac_addr *link_addr, 120 uint8_t link_id) 121 { 122 struct wlan_crypto_key *crypto_key = NULL; 123 enum wlan_crypto_cipher_type cipher; 124 int cipher_len; 125 QDF_STATUS status; 126 127 if (!psoc) { 128 osif_err("psoc is NULL"); 129 return -EINVAL; 130 } 131 if (!params) { 132 osif_err("Key params is NULL"); 133 return -EINVAL; 134 } 135 cipher_len = osif_nl_to_crypto_cipher_len(params->cipher); 136 if (cipher_len < 0 || params->key_len < cipher_len) { 137 osif_err("cipher length %d less than reqd len %d", 138 params->key_len, cipher_len); 139 return -EINVAL; 140 } 141 cipher = osif_nl_to_crypto_cipher_type(params->cipher); 142 if (!IS_WEP_CIPHER(cipher)) { 143 if ((key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) && 144 !mac_addr) { 145 osif_err("mac_addr is NULL for pairwise Key"); 146 return -EINVAL; 147 } 148 } 149 status = wlan_crypto_validate_key_params(cipher, key_index, 150 params->key_len, 151 params->seq_len); 152 if (QDF_IS_STATUS_ERROR(status)) { 153 osif_err("Invalid key params"); 154 return -EINVAL; 155 } 156 157 /* 158 * key may already exist at times and may be retrieved only to 159 * update it. 160 */ 161 wlan_crypto_aquire_lock(); 162 crypto_key = wlan_crypto_get_ml_sta_link_key(psoc, key_index, 163 link_addr, link_id); 164 if (!crypto_key) { 165 wlan_crypto_release_lock(); 166 crypto_key = qdf_mem_malloc(sizeof(*crypto_key)); 167 if (!crypto_key) 168 return -EINVAL; 169 wlan_crypto_aquire_lock(); 170 } 171 172 wlan_cfg80211_translate_ml_sta_key(key_index, key_type, mac_addr, 173 params, crypto_key); 174 175 status = wlan_crypto_save_ml_sta_key(psoc, key_index, crypto_key, 176 link_addr, link_id); 177 if (QDF_IS_STATUS_ERROR(status)) { 178 wlan_crypto_release_lock(); 179 osif_err("Failed to save key"); 180 qdf_mem_free(crypto_key); 181 return -EINVAL; 182 } 183 wlan_crypto_release_lock(); 184 return 0; 185 } 186 187 int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev, 188 uint8_t key_index, 189 enum wlan_crypto_key_type key_type, 190 const u8 *mac_addr, struct key_params *params) 191 { 192 struct wlan_crypto_key *crypto_key = NULL; 193 enum wlan_crypto_cipher_type cipher; 194 int cipher_len; 195 QDF_STATUS status; 196 197 if (!vdev) { 198 osif_err("vdev is NULL"); 199 return -EINVAL; 200 } 201 if (!params) { 202 osif_err("Key params is NULL"); 203 return -EINVAL; 204 } 205 cipher_len = osif_nl_to_crypto_cipher_len(params->cipher); 206 if (cipher_len < 0 || params->key_len < cipher_len) { 207 osif_err("cipher length %d less than reqd len %d", 208 params->key_len, cipher_len); 209 return -EINVAL; 210 } 211 cipher = osif_nl_to_crypto_cipher_type(params->cipher); 212 if (!IS_WEP_CIPHER(cipher)) { 213 if ((key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) && 214 !mac_addr) { 215 osif_err("mac_addr is NULL for pairwise Key"); 216 return -EINVAL; 217 } 218 } 219 status = wlan_crypto_validate_key_params(cipher, key_index, 220 params->key_len, 221 params->seq_len); 222 if (QDF_IS_STATUS_ERROR(status)) { 223 osif_err("Invalid key params"); 224 return -EINVAL; 225 } 226 227 /* 228 * key may already exist at times and may be retrieved only to 229 * update it. 230 */ 231 wlan_crypto_aquire_lock(); 232 crypto_key = wlan_crypto_get_key(vdev, key_index); 233 if (!crypto_key) { 234 wlan_crypto_release_lock(); 235 crypto_key = qdf_mem_malloc(sizeof(*crypto_key)); 236 if (!crypto_key) 237 return -EINVAL; 238 wlan_crypto_aquire_lock(); 239 } 240 241 wlan_cfg80211_translate_key(vdev, key_index, key_type, mac_addr, 242 params, crypto_key); 243 244 status = wlan_crypto_save_key(vdev, key_index, crypto_key); 245 if (QDF_IS_STATUS_ERROR(status)) { 246 wlan_crypto_release_lock(); 247 osif_err("Failed to save key"); 248 qdf_mem_free(crypto_key); 249 return -EINVAL; 250 } 251 wlan_crypto_release_lock(); 252 return 0; 253 } 254 255 #define WLAN_WAIT_TIME_ADD_KEY 100 256 257 static void 258 wlan_cfg80211_crypto_add_key_cb(void *context, 259 struct crypto_add_key_result *result) 260 { 261 struct osif_request *request; 262 struct crypto_add_key_result *priv; 263 264 request = osif_request_get(context); 265 if (!request) { 266 osif_err("Obsolete request"); 267 return; 268 } 269 270 priv = osif_request_priv(request); 271 qdf_mem_copy(priv, result, sizeof(*priv)); 272 osif_request_complete(request); 273 osif_request_put(request); 274 } 275 276 int wlan_cfg80211_crypto_add_key(struct wlan_objmgr_vdev *vdev, 277 enum wlan_crypto_key_type key_type, 278 uint8_t key_index, bool sync) 279 { 280 struct wlan_crypto_key *crypto_key; 281 QDF_STATUS status; 282 struct osif_request *request; 283 struct crypto_add_key_result *result; 284 struct wlan_crypto_comp_priv *priv; 285 int ret; 286 static const struct osif_request_params params = { 287 .priv_size = sizeof(*result), 288 .timeout_ms = WLAN_WAIT_TIME_ADD_KEY, 289 }; 290 291 wlan_crypto_aquire_lock(); 292 crypto_key = wlan_crypto_get_key(vdev, key_index); 293 if (!crypto_key) { 294 wlan_crypto_release_lock(); 295 osif_err("Crypto KEY is NULL"); 296 return -EINVAL; 297 } 298 wlan_crypto_release_lock(); 299 300 if (sync) { 301 priv = wlan_get_vdev_crypto_obj(vdev); 302 if (!priv) { 303 osif_err("Invalid crypto_priv"); 304 return -EINVAL; 305 } 306 307 request = osif_request_alloc(¶ms); 308 if (!request) { 309 osif_err("Request allocation failure"); 310 return -ENOMEM; 311 } 312 313 priv->add_key_ctx = osif_request_cookie(request);; 314 priv->add_key_cb = wlan_cfg80211_crypto_add_key_cb; 315 316 status = ucfg_crypto_set_key_req(vdev, crypto_key, key_type); 317 if (QDF_IS_STATUS_SUCCESS(status)) { 318 ret = osif_request_wait_for_response(request); 319 if (ret) { 320 osif_err("Target response timed out"); 321 } else { 322 result = osif_request_priv(request); 323 osif_debug("complete, vdev_id %u, ix: %u, flags: %u, status: %u", 324 result->vdev_id, result->key_ix, 325 result->key_flags, result->status); 326 } 327 } 328 329 priv->add_key_ctx = NULL; 330 priv->add_key_cb = NULL; 331 osif_request_put(request); 332 } else { 333 status = ucfg_crypto_set_key_req(vdev, crypto_key, key_type); 334 } 335 return qdf_status_to_os_return(status); 336 } 337 338 int wlan_cfg80211_set_default_key(struct wlan_objmgr_vdev *vdev, 339 uint8_t key_index, struct qdf_mac_addr *bssid) 340 { 341 return wlan_crypto_default_key(vdev, (uint8_t *)bssid, 342 key_index, true); 343 } 344