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 crypto_err("peer obj failed status %d", status); 167 qdf_mem_free(crypto_priv); 168 } 169 170 return status; 171 } 172 173 static void wlan_crypto_free_key(struct wlan_crypto_comp_priv *crypto_priv) 174 { 175 uint8_t i; 176 177 if (!crypto_priv) { 178 crypto_err("crypto_priv NULL"); 179 return; 180 } 181 182 for (i = 0; i < WLAN_CRYPTO_MAXKEYIDX; i++) { 183 if (crypto_priv->key[i]) { 184 qdf_mem_free(crypto_priv->key[i]); 185 crypto_priv->key[i] = NULL; 186 } 187 } 188 189 for (i = 0; i < WLAN_CRYPTO_MAXIGTKKEYIDX; i++) { 190 if (crypto_priv->igtk_key[i]) { 191 qdf_mem_free(crypto_priv->igtk_key[i]); 192 crypto_priv->igtk_key[i] = NULL; 193 } 194 } 195 196 } 197 198 static QDF_STATUS wlan_crypto_vdev_obj_destroy_handler( 199 struct wlan_objmgr_vdev *vdev, 200 void *arg){ 201 struct wlan_crypto_comp_priv *crypto_priv; 202 203 if (!vdev) { 204 crypto_err("Vdev NULL"); 205 return QDF_STATUS_E_INVAL; 206 } 207 208 crypto_priv = (struct wlan_crypto_comp_priv *) 209 wlan_get_vdev_crypto_obj(vdev); 210 211 if (!crypto_priv) { 212 crypto_err("crypto_priv NULL"); 213 return QDF_STATUS_E_INVAL; 214 } 215 wlan_objmgr_vdev_component_obj_detach(vdev, 216 WLAN_UMAC_COMP_CRYPTO, 217 (void *)crypto_priv); 218 wlan_crypto_free_key(crypto_priv); 219 qdf_mem_free(crypto_priv); 220 221 return QDF_STATUS_SUCCESS; 222 } 223 224 static QDF_STATUS wlan_crypto_peer_obj_destroy_handler( 225 struct wlan_objmgr_peer *peer, 226 void *arg){ 227 struct wlan_crypto_comp_priv *crypto_priv; 228 229 if (!peer) { 230 crypto_err("Peer NULL"); 231 return QDF_STATUS_E_INVAL; 232 } 233 crypto_priv = (struct wlan_crypto_comp_priv *) 234 wlan_get_peer_crypto_obj(peer); 235 if (!crypto_priv) { 236 crypto_err("crypto_priv NULL"); 237 return QDF_STATUS_E_INVAL; 238 } 239 240 wlan_objmgr_peer_component_obj_detach(peer, 241 WLAN_UMAC_COMP_CRYPTO, 242 (void *)crypto_priv); 243 wlan_crypto_free_key(crypto_priv); 244 qdf_mem_free(crypto_priv); 245 246 return QDF_STATUS_SUCCESS; 247 } 248 /** 249 * __wlan_crypto_init - Init the crypto service with object manager 250 * Called from crypto init context. 251 * 252 * Return: QDF_STATUS_SUCCESS - in case of success 253 */ 254 QDF_STATUS __wlan_crypto_init(void) 255 { 256 QDF_STATUS status = QDF_STATUS_SUCCESS; 257 258 status = wlan_objmgr_register_vdev_create_handler( 259 WLAN_UMAC_COMP_CRYPTO, 260 wlan_crypto_vdev_obj_create_handler, NULL); 261 if (status != QDF_STATUS_SUCCESS) 262 return status; 263 264 status = wlan_objmgr_register_peer_create_handler( 265 WLAN_UMAC_COMP_CRYPTO, 266 wlan_crypto_peer_obj_create_handler, NULL); 267 if (status != QDF_STATUS_SUCCESS) 268 goto err_peer_create; 269 270 status = wlan_objmgr_register_vdev_destroy_handler( 271 WLAN_UMAC_COMP_CRYPTO, 272 wlan_crypto_vdev_obj_destroy_handler, NULL); 273 if (status != QDF_STATUS_SUCCESS) 274 goto err_vdev_delete; 275 276 status = wlan_objmgr_register_peer_destroy_handler( 277 WLAN_UMAC_COMP_CRYPTO, 278 wlan_crypto_peer_obj_destroy_handler, NULL); 279 if (status != QDF_STATUS_SUCCESS) 280 goto err_peer_delete; 281 282 goto register_success; 283 err_peer_delete: 284 wlan_objmgr_unregister_vdev_destroy_handler(WLAN_UMAC_COMP_CRYPTO, 285 wlan_crypto_vdev_obj_destroy_handler, NULL); 286 err_vdev_delete: 287 wlan_objmgr_unregister_peer_create_handler(WLAN_UMAC_COMP_CRYPTO, 288 wlan_crypto_peer_obj_create_handler, NULL); 289 err_peer_create: 290 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_CRYPTO, 291 wlan_crypto_vdev_obj_create_handler, NULL); 292 293 register_success: 294 return status; 295 } 296 297 /** 298 * __wlan_crypto_deinit - Deinit the crypto service with object manager 299 * Called from crypto context. 300 * 301 * Return: QDF_STATUS_SUCCESS - in case of success 302 */ 303 QDF_STATUS __wlan_crypto_deinit(void) 304 { 305 306 if (wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_CRYPTO, 307 wlan_crypto_vdev_obj_create_handler, NULL) 308 != QDF_STATUS_SUCCESS) { 309 return QDF_STATUS_E_FAILURE; 310 } 311 312 if (wlan_objmgr_unregister_peer_create_handler(WLAN_UMAC_COMP_CRYPTO, 313 wlan_crypto_peer_obj_create_handler, NULL) 314 != QDF_STATUS_SUCCESS) { 315 return QDF_STATUS_E_FAILURE; 316 } 317 318 if (wlan_objmgr_unregister_vdev_destroy_handler(WLAN_UMAC_COMP_CRYPTO, 319 wlan_crypto_vdev_obj_destroy_handler, NULL) 320 != QDF_STATUS_SUCCESS) { 321 return QDF_STATUS_E_FAILURE; 322 } 323 324 if (wlan_objmgr_unregister_peer_destroy_handler(WLAN_UMAC_COMP_CRYPTO, 325 wlan_crypto_peer_obj_destroy_handler, NULL) 326 != QDF_STATUS_SUCCESS) { 327 return QDF_STATUS_E_FAILURE; 328 } 329 330 return QDF_STATUS_SUCCESS; 331 } 332