1 /* 2 * Copyright (c) 2017-2018 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: Public API intialization of crypto service with object manager 21 */ 22 #include <qdf_types.h> 23 #include <wlan_cmn.h> 24 #include <wlan_objmgr_cmn.h> 25 26 #include <wlan_objmgr_global_obj.h> 27 #include <wlan_objmgr_psoc_obj.h> 28 #include <wlan_objmgr_pdev_obj.h> 29 #include <wlan_objmgr_vdev_obj.h> 30 #include <wlan_objmgr_peer_obj.h> 31 32 #include "wlan_crypto_global_def.h" 33 #include "wlan_crypto_global_api.h" 34 #include "wlan_crypto_def_i.h" 35 #include "wlan_crypto_main_i.h" 36 #include "wlan_crypto_obj_mgr_i.h" 37 #include "wlan_crypto_fils_api.h" 38 39 40 extern const struct wlan_crypto_cipher 41 *wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_MAX]; 42 43 static QDF_STATUS wlan_crypto_register_all_ciphers( 44 struct wlan_crypto_params *crypto_param) 45 { 46 47 if (HAS_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_WEP)) { 48 wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_WEP] 49 = wep_register(); 50 } 51 if (HAS_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_TKIP_MIC)) { 52 wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_TKIP] 53 = tkip_register(); 54 } 55 if (HAS_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_AES)) { 56 wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_AES_CCM] 57 = ccmp_register(); 58 wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_AES_CCM_256] 59 = ccmp256_register(); 60 wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_AES_GCM] 61 = gcmp_register(); 62 wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_AES_GCM_256] 63 = gcmp256_register(); 64 } 65 if (HAS_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_WAPI_SMS4)) { 66 wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_WAPI_SMS4] 67 = wapi_register(); 68 } 69 if (HAS_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_FILS_AEAD)) { 70 wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_FILS_AEAD] 71 = fils_register(); 72 } 73 74 return QDF_STATUS_SUCCESS; 75 } 76 77 static QDF_STATUS wlan_crypto_vdev_obj_create_handler( 78 struct wlan_objmgr_vdev *vdev, 79 void *arg) 80 { 81 struct wlan_crypto_comp_priv *crypto_priv; 82 struct wlan_objmgr_pdev *pdev; 83 struct wlan_crypto_params *crypto_param; 84 QDF_STATUS status; 85 86 if (!vdev) 87 return QDF_STATUS_E_INVAL; 88 89 crypto_priv = qdf_mem_malloc(sizeof(struct wlan_crypto_comp_priv)); 90 if (!crypto_priv) 91 return QDF_STATUS_E_NOMEM; 92 93 crypto_param = &(crypto_priv->crypto_params); 94 95 RESET_AUTHMODE(crypto_param); 96 RESET_UCAST_CIPHERS(crypto_param); 97 RESET_MCAST_CIPHERS(crypto_param); 98 RESET_MGMT_CIPHERS(crypto_param); 99 RESET_KEY_MGMT(crypto_param); 100 RESET_CIPHER_CAP(crypto_param); 101 102 pdev = wlan_vdev_get_pdev(vdev); 103 wlan_pdev_obj_lock(pdev); 104 if (wlan_pdev_nif_fw_cap_get(pdev, WLAN_SOC_C_WEP)) 105 SET_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_WEP); 106 if (wlan_pdev_nif_fw_cap_get(pdev, WLAN_SOC_C_TKIP)) 107 SET_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_TKIP_MIC); 108 if (wlan_pdev_nif_fw_cap_get(pdev, WLAN_SOC_C_AES)) { 109 SET_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_AES); 110 SET_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_CCM256); 111 SET_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_GCM); 112 SET_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_GCM_256); 113 } 114 if (wlan_pdev_nif_fw_cap_get(pdev, WLAN_SOC_C_CKIP)) 115 SET_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_CKIP); 116 if (wlan_pdev_nif_fw_cap_get(pdev, WLAN_SOC_C_WAPI)) 117 SET_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_WAPI_SMS4); 118 SET_CIPHER_CAP(crypto_param, WLAN_CRYPTO_CAP_FILS_AEAD); 119 wlan_pdev_obj_unlock(pdev); 120 /* update the crypto cipher table based on the fw caps*/ 121 /* update the fw_caps into ciphercaps then attach to objmgr*/ 122 wlan_crypto_register_all_ciphers(crypto_param); 123 124 status = wlan_objmgr_vdev_component_obj_attach(vdev, 125 WLAN_UMAC_COMP_CRYPTO, 126 (void *)crypto_priv, 127 QDF_STATUS_SUCCESS); 128 if (status != QDF_STATUS_SUCCESS) 129 qdf_mem_free(crypto_priv); 130 131 return status; 132 } 133 134 static QDF_STATUS wlan_crypto_peer_obj_create_handler( 135 struct wlan_objmgr_peer *peer, 136 void *arg) 137 { 138 struct wlan_crypto_comp_priv *crypto_priv; 139 struct wlan_crypto_params *crypto_param; 140 QDF_STATUS status; 141 142 if (!peer) 143 return QDF_STATUS_E_INVAL; 144 145 crypto_priv = qdf_mem_malloc(sizeof(struct wlan_crypto_comp_priv)); 146 if (!crypto_priv) 147 return QDF_STATUS_E_NOMEM; 148 149 status = wlan_objmgr_peer_component_obj_attach(peer, 150 WLAN_UMAC_COMP_CRYPTO, (void *)crypto_priv, 151 QDF_STATUS_SUCCESS); 152 153 if (status == QDF_STATUS_SUCCESS) { 154 crypto_param = &crypto_priv->crypto_params; 155 RESET_AUTHMODE(crypto_param); 156 RESET_UCAST_CIPHERS(crypto_param); 157 RESET_MCAST_CIPHERS(crypto_param); 158 RESET_MGMT_CIPHERS(crypto_param); 159 RESET_KEY_MGMT(crypto_param); 160 RESET_CIPHER_CAP(crypto_param); 161 if (wlan_vdev_get_selfpeer(peer->peer_objmgr.vdev) != peer) { 162 wlan_crypto_set_peer_wep_keys( 163 wlan_peer_get_vdev(peer), peer); 164 } 165 } else { 166 qdf_print("%s[%d] peer obj failed status %d", 167 __func__, __LINE__, status); 168 qdf_mem_free(crypto_priv); 169 } 170 171 return status; 172 } 173 174 static void wlan_crypto_free_key(struct wlan_crypto_comp_priv *crypto_priv) 175 { 176 uint8_t i; 177 178 if (!crypto_priv) { 179 qdf_print("%s[%d] crypto_priv NULL", __func__, __LINE__); 180 return; 181 } 182 183 for (i = 0; i < WLAN_CRYPTO_MAXKEYIDX; i++) { 184 if (crypto_priv->key[i]) { 185 qdf_mem_free(crypto_priv->key[i]); 186 crypto_priv->key[i] = NULL; 187 } 188 } 189 190 for (i = 0; i < WLAN_CRYPTO_MAXIGTKKEYIDX; i++) { 191 if (crypto_priv->igtk_key[i]) { 192 qdf_mem_free(crypto_priv->igtk_key[i]); 193 crypto_priv->igtk_key[i] = NULL; 194 } 195 } 196 197 } 198 199 static QDF_STATUS wlan_crypto_vdev_obj_destroy_handler( 200 struct wlan_objmgr_vdev *vdev, 201 void *arg){ 202 struct wlan_crypto_comp_priv *crypto_priv; 203 204 if (!vdev) { 205 qdf_print("%s[%d] Vdev NULL", __func__, __LINE__); 206 return QDF_STATUS_E_INVAL; 207 } 208 209 crypto_priv = (struct wlan_crypto_comp_priv *) 210 wlan_get_vdev_crypto_obj(vdev); 211 212 if (!crypto_priv) { 213 qdf_print("%s[%d] crypto_priv NULL", __func__, __LINE__); 214 return QDF_STATUS_E_INVAL; 215 } 216 wlan_objmgr_vdev_component_obj_detach(vdev, 217 WLAN_UMAC_COMP_CRYPTO, 218 (void *)crypto_priv); 219 wlan_crypto_free_key(crypto_priv); 220 qdf_mem_free(crypto_priv); 221 222 return QDF_STATUS_SUCCESS; 223 } 224 225 static QDF_STATUS wlan_crypto_peer_obj_destroy_handler( 226 struct wlan_objmgr_peer *peer, 227 void *arg){ 228 struct wlan_crypto_comp_priv *crypto_priv; 229 230 if (!peer) { 231 qdf_print("%s[%d] Peer NULL", __func__, __LINE__); 232 return QDF_STATUS_E_INVAL; 233 } 234 crypto_priv = (struct wlan_crypto_comp_priv *) 235 wlan_get_peer_crypto_obj(peer); 236 if (!crypto_priv) { 237 qdf_print("%s[%d] crypto_priv NULL", __func__, __LINE__); 238 return QDF_STATUS_E_INVAL; 239 } 240 241 wlan_objmgr_peer_component_obj_detach(peer, 242 WLAN_UMAC_COMP_CRYPTO, 243 (void *)crypto_priv); 244 wlan_crypto_free_key(crypto_priv); 245 qdf_mem_free(crypto_priv); 246 247 return QDF_STATUS_SUCCESS; 248 } 249 /** 250 * __wlan_crypto_init - Init the crypto service with object manager 251 * Called from crypto init context. 252 * 253 * Return: QDF_STATUS_SUCCESS - in case of success 254 */ 255 QDF_STATUS __wlan_crypto_init(void) 256 { 257 QDF_STATUS status = QDF_STATUS_SUCCESS; 258 259 status = wlan_objmgr_register_vdev_create_handler( 260 WLAN_UMAC_COMP_CRYPTO, 261 wlan_crypto_vdev_obj_create_handler, NULL); 262 if (status != QDF_STATUS_SUCCESS) 263 return status; 264 265 status = wlan_objmgr_register_peer_create_handler( 266 WLAN_UMAC_COMP_CRYPTO, 267 wlan_crypto_peer_obj_create_handler, NULL); 268 if (status != QDF_STATUS_SUCCESS) 269 goto err_peer_create; 270 271 status = wlan_objmgr_register_vdev_destroy_handler( 272 WLAN_UMAC_COMP_CRYPTO, 273 wlan_crypto_vdev_obj_destroy_handler, NULL); 274 if (status != QDF_STATUS_SUCCESS) 275 goto err_vdev_delete; 276 277 status = wlan_objmgr_register_peer_destroy_handler( 278 WLAN_UMAC_COMP_CRYPTO, 279 wlan_crypto_peer_obj_destroy_handler, NULL); 280 if (status != QDF_STATUS_SUCCESS) 281 goto err_peer_delete; 282 283 goto register_success; 284 err_peer_delete: 285 wlan_objmgr_unregister_vdev_destroy_handler(WLAN_UMAC_COMP_CRYPTO, 286 wlan_crypto_vdev_obj_destroy_handler, NULL); 287 err_vdev_delete: 288 wlan_objmgr_unregister_peer_create_handler(WLAN_UMAC_COMP_CRYPTO, 289 wlan_crypto_peer_obj_create_handler, NULL); 290 err_peer_create: 291 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_CRYPTO, 292 wlan_crypto_vdev_obj_create_handler, NULL); 293 294 register_success: 295 return status; 296 } 297 298 /** 299 * __wlan_crypto_deinit - Deinit the crypto service with object manager 300 * Called from crypto context. 301 * 302 * Return: QDF_STATUS_SUCCESS - in case of success 303 */ 304 QDF_STATUS __wlan_crypto_deinit(void) 305 { 306 307 if (wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_CRYPTO, 308 wlan_crypto_vdev_obj_create_handler, NULL) 309 != QDF_STATUS_SUCCESS) { 310 return QDF_STATUS_E_FAILURE; 311 } 312 313 if (wlan_objmgr_unregister_peer_create_handler(WLAN_UMAC_COMP_CRYPTO, 314 wlan_crypto_peer_obj_create_handler, NULL) 315 != QDF_STATUS_SUCCESS) { 316 return QDF_STATUS_E_FAILURE; 317 } 318 319 if (wlan_objmgr_unregister_vdev_destroy_handler(WLAN_UMAC_COMP_CRYPTO, 320 wlan_crypto_vdev_obj_destroy_handler, NULL) 321 != QDF_STATUS_SUCCESS) { 322 return QDF_STATUS_E_FAILURE; 323 } 324 325 if (wlan_objmgr_unregister_peer_destroy_handler(WLAN_UMAC_COMP_CRYPTO, 326 wlan_crypto_peer_obj_destroy_handler, NULL) 327 != QDF_STATUS_SUCCESS) { 328 return QDF_STATUS_E_FAILURE; 329 } 330 331 return QDF_STATUS_SUCCESS; 332 } 333