xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c (revision 1b9674e21e24478fba4530f5ae7396b9555e9c6a)
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