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