blob: 382b65f751cae8d2afc6117437b40992106939a3 [file] [log] [blame]
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301/*
Ashok Ponnaiah7a41e8c2017-12-28 17:13:40 +05302 * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303 *
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 APIs for crypto service
21 */
22#include <qdf_types.h>
23#include <wlan_cmn.h>
24#include <wlan_objmgr_cmn.h>
25#include <wlan_objmgr_global_obj.h>
26#include <wlan_objmgr_psoc_obj.h>
27#include <wlan_objmgr_pdev_obj.h>
28#include <wlan_objmgr_vdev_obj.h>
29#include <wlan_objmgr_peer_obj.h>
30
31#include "wlan_crypto_global_def.h"
32#include "wlan_crypto_global_api.h"
33#include "wlan_crypto_def_i.h"
34#include "wlan_crypto_param_handling_i.h"
35#include "wlan_crypto_obj_mgr_i.h"
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053036
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +053037#include <qdf_module.h>
38
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053039
40const struct wlan_crypto_cipher *wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_MAX];
41
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053042/**
43 * wlan_crypto_vdev_get_crypto_params - called by mlme to get crypto params
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053044 * @vdev:vdev
45 *
46 * This function gets called by mlme to get crypto params
47 *
48 * Return: wlan_crypto_params or NULL in case of failure
49 */
50static struct wlan_crypto_params *wlan_crypto_vdev_get_comp_params(
51 struct wlan_objmgr_vdev *vdev,
52 struct wlan_crypto_comp_priv **crypto_priv){
53 *crypto_priv = (struct wlan_crypto_comp_priv *)
54 wlan_get_vdev_crypto_obj(vdev);
55 if (*crypto_priv == NULL) {
56 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
57 return NULL;
58 }
59
60 return &((*crypto_priv)->crypto_params);
61}
62
63/**
64 * wlan_crypto_peer_get_crypto_params - called by mlme to get crypto params
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053065 * @peer:peer
66 *
67 * This function gets called by mlme to get crypto params
68 *
69 * Return: wlan_crypto_params or NULL in case of failure
70 */
71static struct wlan_crypto_params *wlan_crypto_peer_get_comp_params(
72 struct wlan_objmgr_peer *peer,
73 struct wlan_crypto_comp_priv **crypto_priv){
74
75 *crypto_priv = (struct wlan_crypto_comp_priv *)
76 wlan_get_peer_crypto_obj(peer);
77 if (*crypto_priv == NULL) {
78 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
79 return NULL;
80 }
81
82 return &((*crypto_priv)->crypto_params);
83}
84
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +053085static QDF_STATUS wlan_crypto_set_igtk_key(struct wlan_crypto_key *key)
86{
87 return QDF_STATUS_SUCCESS;
88}
Disha Das6419ff12018-02-02 10:21:55 +053089
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053090/**
91 * wlan_crypto_set_param - called by ucfg to set crypto param
Disha Das6419ff12018-02-02 10:21:55 +053092 * @crypto_params: crypto_params
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053093 * @param: param to be set.
94 * @value: value
95 *
96 * This function gets called from ucfg to set param
97 *
98 * Return: QDF_STATUS_SUCCESS - in case of success
99 */
Disha Das6419ff12018-02-02 10:21:55 +0530100static QDF_STATUS wlan_crypto_set_param(struct wlan_crypto_params *crypto_params,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530101 wlan_crypto_param_type param,
102 uint32_t value){
103 QDF_STATUS status = QDF_STATUS_E_INVAL;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530104
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530105 switch (param) {
106 case WLAN_CRYPTO_PARAM_AUTH_MODE:
107 status = wlan_crypto_set_authmode(crypto_params, value);
108 break;
109 case WLAN_CRYPTO_PARAM_UCAST_CIPHER:
110 status = wlan_crypto_set_ucastciphers(crypto_params, value);
111 break;
112 case WLAN_CRYPTO_PARAM_MCAST_CIPHER:
113 status = wlan_crypto_set_mcastcipher(crypto_params, value);
114 break;
115 case WLAN_CRYPTO_PARAM_MGMT_CIPHER:
116 status = wlan_crypto_set_mgmtcipher(crypto_params, value);
117 break;
118 case WLAN_CRYPTO_PARAM_CIPHER_CAP:
119 status = wlan_crypto_set_cipher_cap(crypto_params, value);
120 break;
121 case WLAN_CRYPTO_PARAM_RSN_CAP:
122 status = wlan_crypto_set_rsn_cap(crypto_params, value);
123 break;
124 case WLAN_CRYPTO_PARAM_KEY_MGMT:
125 status = wlan_crypto_set_key_mgmt(crypto_params, value);
126 break;
127 default:
128 status = QDF_STATUS_E_INVAL;
129 }
Disha Das6419ff12018-02-02 10:21:55 +0530130 return status;
131}
132
133/**
134 * wlan_crypto_set_vdev_param - called by ucfg to set crypto param
135 * @vdev: vdev
136 * @param: param to be set.
137 * @value: value
138 *
139 * This function gets called from ucfg to set param
140 *
141 * Return: QDF_STATUS_SUCCESS - in case of success
142 */
143QDF_STATUS wlan_crypto_set_vdev_param(struct wlan_objmgr_vdev *vdev,
144 wlan_crypto_param_type param,
145 uint32_t value){
146 QDF_STATUS status = QDF_STATUS_E_INVAL;
147 struct wlan_crypto_comp_priv *crypto_priv;
148 struct wlan_crypto_params *crypto_params;
149
150 crypto_priv = (struct wlan_crypto_comp_priv *)
151 wlan_get_vdev_crypto_obj(vdev);
152
153 if (crypto_priv == NULL) {
154 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
155 return QDF_STATUS_E_INVAL;
156 }
157
158 crypto_params = &(crypto_priv->crypto_params);
159
160 status = wlan_crypto_set_param(crypto_params, param, value);
161
162 return status;
163}
164
165/**
166 * wlan_crypto_set_param - called by ucfg to set crypto param
167 *
168 * @peer: peer
169 * @param: param to be set.
170 * @value: value
171 *
172 * This function gets called from ucfg to set param
173 *
174 * Return: QDF_STATUS_SUCCESS - in case of success
175 */
176QDF_STATUS wlan_crypto_set_peer_param(struct wlan_objmgr_peer *peer,
177 wlan_crypto_param_type param,
178 uint32_t value){
179 QDF_STATUS status = QDF_STATUS_E_INVAL;
180 struct wlan_crypto_comp_priv *crypto_priv;
181 struct wlan_crypto_params *crypto_params;
182
183 crypto_params = wlan_crypto_peer_get_comp_params(peer,
184 &crypto_priv);
185
186 if (crypto_priv == NULL) {
187 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
188 return QDF_STATUS_E_INVAL;
189 }
190
191 crypto_params = &(crypto_priv->crypto_params);
192
193 status = wlan_crypto_set_param(crypto_params, param, value);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530194
195 return status;
196}
197
198/**
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530199 * wlan_crypto_get_param_value - called by crypto APIs to get value for param
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530200 * @param: Crypto param type
201 * @crypto_params: Crypto params struct
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530202 *
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530203 * This function gets called from in-within crypto layer
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530204 *
205 * Return: value or -1 for failure
206 */
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530207static int32_t wlan_crypto_get_param_value(wlan_crypto_param_type param,
208 struct wlan_crypto_params *crypto_params)
209{
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530210 int32_t value = -1;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530211
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530212 switch (param) {
213 case WLAN_CRYPTO_PARAM_AUTH_MODE:
214 value = wlan_crypto_get_authmode(crypto_params);
215 break;
216 case WLAN_CRYPTO_PARAM_UCAST_CIPHER:
217 value = wlan_crypto_get_ucastciphers(crypto_params);
218 break;
219 case WLAN_CRYPTO_PARAM_MCAST_CIPHER:
220 value = wlan_crypto_get_mcastcipher(crypto_params);
221 break;
222 case WLAN_CRYPTO_PARAM_MGMT_CIPHER:
223 value = wlan_crypto_get_mgmtciphers(crypto_params);
224 break;
225 case WLAN_CRYPTO_PARAM_CIPHER_CAP:
226 value = wlan_crypto_get_cipher_cap(crypto_params);
227 break;
228 case WLAN_CRYPTO_PARAM_RSN_CAP:
229 value = wlan_crypto_get_rsn_cap(crypto_params);
230 break;
231 case WLAN_CRYPTO_PARAM_KEY_MGMT:
232 value = wlan_crypto_get_key_mgmt(crypto_params);
233 break;
234 default:
235 value = QDF_STATUS_E_INVAL;
236 }
237
238 return value;
239}
240
Ashok Ponnaiahf9953602018-01-11 15:39:26 +0530241/**
242 * wlan_crypto_get_param - called to get value for param from vdev
243 * @vdev: vdev
244 * @param: Crypto param type
245 *
246 * This function gets called to get value for param from vdev
247 *
248 * Return: value or -1 for failure
249 */
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530250int32_t wlan_crypto_get_param(struct wlan_objmgr_vdev *vdev,
251 wlan_crypto_param_type param)
252{
253 int32_t value = -1;
254 struct wlan_crypto_comp_priv *crypto_priv;
255 struct wlan_crypto_params *crypto_params;
256 crypto_priv = (struct wlan_crypto_comp_priv *)
257 wlan_get_vdev_crypto_obj(vdev);
258
259 if (crypto_priv == NULL) {
260 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
261 return QDF_STATUS_E_INVAL;
262 }
263
264 crypto_params = &(crypto_priv->crypto_params);
265 value = wlan_crypto_get_param_value(param, crypto_params);
266
267 return value;
268}
Ashok Ponnaiahf9953602018-01-11 15:39:26 +0530269/**
270 * wlan_crypto_get_peer_param - called to get value for param from peer
271 * @peer: peer
272 * @param: Crypto param type
273 *
274 * This function gets called to get value for param from peer
275 *
276 * Return: value or -1 for failure
277 */
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530278int32_t wlan_crypto_get_peer_param(struct wlan_objmgr_peer *peer,
279 wlan_crypto_param_type param)
280{
281 int32_t value = -1;
282 struct wlan_crypto_comp_priv *crypto_priv;
283 struct wlan_crypto_params *crypto_params;
284
285 crypto_params = wlan_crypto_peer_get_comp_params(peer,
286 &crypto_priv);
287
288 if (crypto_params == NULL) {
289 qdf_print("%s[%d] crypto_params NULL\n", __func__, __LINE__);
290 return QDF_STATUS_E_INVAL;
291 }
292 value = wlan_crypto_get_param_value(param, crypto_params);
293
294 return value;
295}
Ashok Ponnaiah455eb682018-03-19 10:33:22 +0530296qdf_export_symbol(wlan_crypto_get_peer_param);
Ashok Ponnaiahf9953602018-01-11 15:39:26 +0530297/**
298 * wlan_crypto_is_htallowed - called to check is HT allowed for cipher
299 * @vdev: vdev
300 * @peer: peer
301 *
302 * This function gets called to check is HT allowed for cipher.
303 * HT is not allowed for wep and tkip.
304 *
305 * Return: 0 - not allowed or 1 - allowed
306 */
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530307uint8_t wlan_crypto_is_htallowed(struct wlan_objmgr_vdev *vdev,
308 struct wlan_objmgr_peer *peer)
309{
310 int32_t ucast_cipher;
311
312 if (!(vdev || peer)) {
313 qdf_print("%s[%d] Invalid params\n", __func__, __LINE__);
314 return 0;
315 }
316
317 if (vdev)
318 ucast_cipher = wlan_crypto_get_param(vdev,
319 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
320 else
321 ucast_cipher = wlan_crypto_get_peer_param(peer,
322 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
323
324 return (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP)) ||
325 ((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_TKIP)) &&
326 !(ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM)) &&
327 !(ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM)) &&
328 !(ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM_256)) &&
329 !(ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM_256)));
330}
331qdf_export_symbol(wlan_crypto_is_htallowed);
332
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530333/**
334 * wlan_crypto_setkey - called by ucfg to setkey
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530335 * @vdev: vdev
336 * @req_key: req_key with cipher type, key macaddress
337 *
338 * This function gets called from ucfg to sey key
339 *
340 * Return: QDF_STATUS_SUCCESS - in case of success
341 */
342QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev,
343 struct wlan_crypto_req_key *req_key){
344
345 QDF_STATUS status = QDF_STATUS_E_INVAL;
346 struct wlan_crypto_comp_priv *crypto_priv;
347 struct wlan_crypto_params *crypto_params;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530348 struct wlan_objmgr_psoc *psoc;
349 struct wlan_objmgr_peer *peer;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +0530350 struct wlan_crypto_key *key = NULL;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530351 const struct wlan_crypto_cipher *cipher;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530352 uint8_t macaddr[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530353 bool isbcast;
Jeff Johnsona4262322017-11-09 09:54:12 -0800354 enum QDF_OPMODE vdev_mode;
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530355 uint8_t igtk_idx = 0;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530356
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530357 if (!vdev || !req_key || req_key->keylen > (sizeof(req_key->keydata))) {
Jeff Johnson878533e2017-09-18 10:07:54 -0700358 qdf_print("%s[%d] Invalid params vdev%pK, req_key%pK\n",
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530359 __func__, __LINE__, vdev, req_key);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530360 return QDF_STATUS_E_INVAL;
361 }
362
363 isbcast = qdf_is_macaddr_broadcast(
364 (struct qdf_mac_addr *)req_key->macaddr);
Subrat Mishra2b75d6d2017-08-07 17:36:25 +0530365 if ((req_key->keylen == 0) && !IS_FILS_CIPHER(req_key->type)) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530366 /* zero length keys, only set default key id if flags are set*/
367 if ((req_key->flags & WLAN_CRYPTO_KEY_DEFAULT)
368 && (req_key->keyix != WLAN_CRYPTO_KEYIX_NONE)
369 && (!IS_MGMT_CIPHER(req_key->type))) {
370 wlan_crypto_default_key(vdev,
371 req_key->macaddr,
372 req_key->keyix,
373 !isbcast);
374 return QDF_STATUS_SUCCESS;
375 }
376 qdf_print("%s[%d] req_key len zero\n", __func__, __LINE__);
377 return QDF_STATUS_E_INVAL;
378 }
379
380 cipher = wlan_crypto_cipher_ops[req_key->type];
381
382 if (!cipher && !IS_MGMT_CIPHER(req_key->type)) {
383 qdf_print("%s[%d] cipher invalid\n", __func__, __LINE__);
384 return QDF_STATUS_E_INVAL;
385 }
386
Subrat Mishra2b75d6d2017-08-07 17:36:25 +0530387 if (cipher && (!IS_FILS_CIPHER(req_key->type)) &&
388 (!IS_MGMT_CIPHER(req_key->type)) &&
389 ((req_key->keylen != (cipher->keylen / NBBY)) &&
390 (req_key->type != WLAN_CRYPTO_CIPHER_WEP))) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530391 qdf_print("%s[%d] cipher invalid\n", __func__, __LINE__);
392 return QDF_STATUS_E_INVAL;
393 } else if ((req_key->type == WLAN_CRYPTO_CIPHER_WEP) &&
Ashok Ponnaiahb6962212017-07-31 10:12:57 +0530394 !((req_key->keylen == WLAN_CRYPTO_KEY_WEP40_LEN)
395 || (req_key->keylen == WLAN_CRYPTO_KEY_WEP104_LEN)
396 || (req_key->keylen == WLAN_CRYPTO_KEY_WEP128_LEN))) {
397 qdf_print("%s[%d] wep key len invalid\n", __func__, __LINE__);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530398 return QDF_STATUS_E_INVAL;
399 }
400
401 if (req_key->keyix == WLAN_CRYPTO_KEYIX_NONE) {
402 if (req_key->flags != (WLAN_CRYPTO_KEY_XMIT
403 | WLAN_CRYPTO_KEY_RECV)) {
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530404 req_key->flags |= (WLAN_CRYPTO_KEY_XMIT
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530405 | WLAN_CRYPTO_KEY_RECV);
406 }
407 } else {
Disha Das55b86c22018-04-20 15:22:08 +0530408 if ((req_key->keyix >= WLAN_CRYPTO_MAXKEYIDX)
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530409 && (!IS_MGMT_CIPHER(req_key->type))) {
410 return QDF_STATUS_E_INVAL;
411 }
412
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530413 req_key->flags |= (WLAN_CRYPTO_KEY_XMIT
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530414 | WLAN_CRYPTO_KEY_RECV);
Nandha Kishore Easwaran786c9552017-06-28 10:54:09 +0530415 if (isbcast)
416 req_key->flags |= WLAN_CRYPTO_KEY_GROUP;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530417 }
418
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530419 vdev_mode = wlan_vdev_mlme_get_opmode(vdev);
Vivekb02a6492017-06-21 08:21:58 +0530420
421 wlan_vdev_obj_lock(vdev);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530422 qdf_mem_copy(macaddr, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
423 psoc = wlan_vdev_get_psoc(vdev);
424 if (!psoc) {
425 wlan_vdev_obj_unlock(vdev);
426 qdf_print("%s[%d] psoc NULL\n", __func__, __LINE__);
427 return QDF_STATUS_E_INVAL;
428 }
429 wlan_vdev_obj_unlock(vdev);
430
Rohan Dutta3844c602017-09-01 16:04:25 +0530431 if (req_key->type == WLAN_CRYPTO_CIPHER_WEP) {
432 if (wlan_crypto_vdev_has_auth_mode(vdev,
433 (1 << WLAN_CRYPTO_AUTH_8021X))) {
434 req_key->flags |= WLAN_CRYPTO_KEY_DEFAULT;
Rohan Dutta3844c602017-09-01 16:04:25 +0530435 }
436 }
437
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530438 if (isbcast) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530439 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
440 &crypto_priv);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530441 if (crypto_priv == NULL) {
442 qdf_print("%s[%d] crypto_priv NULL\n",
443 __func__, __LINE__);
444 return QDF_STATUS_E_INVAL;
445 }
446
447 if (IS_MGMT_CIPHER(req_key->type)) {
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530448 igtk_idx = req_key->keyix - WLAN_CRYPTO_MAXKEYIDX;
Disha Das76210cd2018-04-10 12:44:14 +0530449 if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) {
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530450 qdf_print("%s[%d] igtk key invalid keyid %d \n",
451 __func__, __LINE__, igtk_idx);
452 return QDF_STATUS_E_INVAL;
453 }
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530454 key = qdf_mem_malloc(sizeof(struct wlan_crypto_key));
455 if (key == NULL) {
456 qdf_print("%s[%d] igtk key alloc failed\n",
457 __func__, __LINE__);
458 return QDF_STATUS_E_NOMEM;
459 }
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530460
461 if (crypto_priv->igtk_key[igtk_idx])
462 qdf_mem_free(crypto_priv->igtk_key[igtk_idx]);
463
464 crypto_priv->igtk_key[igtk_idx] = key;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530465 crypto_priv->igtk_key_type = req_key->type;
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530466 crypto_priv->def_igtk_tx_keyid = igtk_idx;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530467 } else {
Subrat Mishra2b75d6d2017-08-07 17:36:25 +0530468 if (IS_FILS_CIPHER(req_key->type)) {
469 qdf_print(FL(
470 "FILS key is not for BroadCast packet\n"));
471 return QDF_STATUS_E_INVAL;
472 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530473 if (!HAS_MCAST_CIPHER(crypto_params, req_key->type)
474 && (req_key->type != WLAN_CRYPTO_CIPHER_WEP)) {
475 return QDF_STATUS_E_INVAL;
476 }
477 if (!crypto_priv->key[req_key->keyix]) {
478 crypto_priv->key[req_key->keyix]
479 = qdf_mem_malloc(
480 sizeof(struct wlan_crypto_key));
481 if (!crypto_priv->key[req_key->keyix])
482 return QDF_STATUS_E_NOMEM;
483 }
484 key = crypto_priv->key[req_key->keyix];
485 }
Nandha Kishore Easwarane9f80702017-07-21 18:00:56 +0530486 if (vdev_mode == QDF_STA_MODE) {
487 peer = wlan_vdev_get_bsspeer(vdev);
Ashok Ponnaiahb6962212017-07-31 10:12:57 +0530488 if (!(peer && (QDF_STATUS_SUCCESS
489 == wlan_objmgr_peer_try_get_ref(peer,
490 WLAN_CRYPTO_ID)))) {
Jeff Johnson878533e2017-09-18 10:07:54 -0700491 qdf_print("%s[%d] peer %pK failed\n",
Ashok Ponnaiahb6962212017-07-31 10:12:57 +0530492 __func__, __LINE__, peer);
493 if (IS_MGMT_CIPHER(req_key->type)) {
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530494 crypto_priv->igtk_key[igtk_idx] = NULL;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +0530495 crypto_priv->igtk_key_type
496 = WLAN_CRYPTO_CIPHER_NONE;
497 } else
498 crypto_priv->key[req_key->keyix] = NULL;
499 if (key)
500 qdf_mem_free(key);
Nandha Kishore Easwarane9f80702017-07-21 18:00:56 +0530501 return QDF_STATUS_E_INVAL;
502 }
Nandha Kishore Easwarane9f80702017-07-21 18:00:56 +0530503 qdf_mem_copy(macaddr, wlan_peer_get_macaddr(peer),
504 WLAN_ALEN);
Nandha Kishore Easwarane9f80702017-07-21 18:00:56 +0530505 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
506 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530507 } else {
Amir Pateld3385942018-05-03 23:01:08 +0530508 uint8_t pdev_id;
509
510 pdev_id = wlan_objmgr_pdev_get_pdev_id(
511 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530512 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530513 psoc,
Amir Pateld3385942018-05-03 23:01:08 +0530514 pdev_id,
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530515 macaddr,
Amir Pateld3385942018-05-03 23:01:08 +0530516 req_key->macaddr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530517 WLAN_CRYPTO_ID);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530518
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530519 if (peer == NULL) {
520 qdf_print("%s[%d] peer NULL\n", __func__, __LINE__);
521 return QDF_STATUS_E_INVAL;
522 }
523
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530524 qdf_mem_copy(macaddr, req_key->macaddr, WLAN_ALEN);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530525 crypto_params = wlan_crypto_peer_get_comp_params(peer,
526 &crypto_priv);
527 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
528
529 if (crypto_priv == NULL) {
530 qdf_print("%s[%d] crypto_priv NULL\n",
531 __func__, __LINE__);
532 return QDF_STATUS_E_INVAL;
533 }
534 if (IS_MGMT_CIPHER(req_key->type)) {
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530535 igtk_idx = req_key->keyix - WLAN_CRYPTO_MAXKEYIDX;
Disha Das55b86c22018-04-20 15:22:08 +0530536 if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) {
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530537 qdf_print("%s[%d] igtk key invalid keyid %d \n",
538 __func__, __LINE__, igtk_idx);
539 return QDF_STATUS_E_INVAL;
540 }
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530541 key = qdf_mem_malloc(sizeof(struct wlan_crypto_key));
542 if (key == NULL) {
543 qdf_print("%s[%d] igtk key alloc failed\n",
544 __func__, __LINE__);
545 return QDF_STATUS_E_NOMEM;
546 }
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530547 if (crypto_priv->igtk_key[igtk_idx])
548 qdf_mem_free(crypto_priv->igtk_key[igtk_idx]);
549
550 crypto_priv->igtk_key[igtk_idx] = key;
551 crypto_priv->igtk_key_type = req_key->type;
552 crypto_priv->def_igtk_tx_keyid = igtk_idx;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530553 } else {
554 uint16_t kid = req_key->keyix;
555 if (kid == WLAN_CRYPTO_KEYIX_NONE)
556 kid = 0;
Radhika Sriram00392f32018-04-04 19:04:49 +0530557 if (kid >= WLAN_CRYPTO_MAXKEYIDX) {
558 qdf_print("%s[%d] invalid keyid %d \n",
559 __func__, __LINE__, kid);
560 return QDF_STATUS_E_INVAL;
561 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530562 if (!crypto_priv->key[kid]) {
563 crypto_priv->key[kid]
564 = qdf_mem_malloc(
565 sizeof(struct wlan_crypto_key));
566 if (!crypto_priv->key[kid])
567 return QDF_STATUS_E_NOMEM;
568 }
569 key = crypto_priv->key[kid];
570 }
571 }
572
573 /* alloc key might not required as it is already there */
574 key->cipher_table = (void *)cipher;
575 key->keylen = req_key->keylen;
576 key->flags = req_key->flags;
577
578 if (req_key->keyix == WLAN_CRYPTO_KEYIX_NONE)
579 key->keyix = 0;
580 else
581 key->keyix = req_key->keyix;
582
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530583 if (req_key->flags & WLAN_CRYPTO_KEY_DEFAULT
584 && (!IS_MGMT_CIPHER(req_key->type))) {
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530585 crypto_priv->def_tx_keyid = key->keyix;
586 key->flags |= WLAN_CRYPTO_KEY_DEFAULT;
587 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530588 if ((req_key->type == WLAN_CRYPTO_CIPHER_WAPI_SMS4)
589 || (req_key->type == WLAN_CRYPTO_CIPHER_WAPI_GCM4)) {
590 uint8_t iv_AP[16] = { 0x5c, 0x36, 0x5c, 0x36,
591 0x5c, 0x36, 0x5c, 0x36,
592 0x5c, 0x36, 0x5c, 0x36,
593 0x5c, 0x36, 0x5c, 0x37};
594 uint8_t iv_STA[16] = { 0x5c, 0x36, 0x5c, 0x36,
595 0x5c, 0x36, 0x5c, 0x36,
596 0x5c, 0x36, 0x5c, 0x36,
597 0x5c, 0x36, 0x5c, 0x36};
598
599 /* During Tx PN should be increment and
600 * send but as per our implementation we increment only after
601 * Tx complete. So First packet PN check will be failed.
602 * To compensate increment the PN here by 2
603 */
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530604 if (vdev_mode == QDF_SAP_MODE) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530605 iv_AP[15] += 2;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530606 qdf_mem_copy(key->recviv, iv_STA,
607 WLAN_CRYPTO_WAPI_IV_SIZE);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530608 qdf_mem_copy(key->txiv, iv_AP,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530609 WLAN_CRYPTO_WAPI_IV_SIZE);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530610 } else {
611 iv_STA[15] += 2;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530612 qdf_mem_copy(key->recviv, iv_AP,
613 WLAN_CRYPTO_WAPI_IV_SIZE);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530614 qdf_mem_copy(key->txiv, iv_STA,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530615 WLAN_CRYPTO_WAPI_IV_SIZE);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530616 }
617 } else {
618 uint8_t i = 0;
619 qdf_mem_copy((uint8_t *)(&key->keytsc),
620 (uint8_t *)(&req_key->keytsc), sizeof(key->keytsc));
621 for (i = 0; i < WLAN_CRYPTO_TID_SIZE; i++) {
622 qdf_mem_copy((uint8_t *)(&key->keyrsc[i]),
623 (uint8_t *)(&req_key->keyrsc),
624 sizeof(key->keyrsc[0]));
625 }
626 }
627
628 qdf_mem_copy(key->keyval, req_key->keydata, sizeof(key->keyval));
629 key->valid = 1;
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530630 if ((IS_MGMT_CIPHER(req_key->type))) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530631 if (HAS_CIPHER_CAP(crypto_params,
632 WLAN_CRYPTO_CAP_PMF_OFFLOAD)) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530633 if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
634 WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(vdev,
635 key, macaddr, req_key->type);
636 }
637 }
638 status = wlan_crypto_set_igtk_key(key);
639 return status;
Subrat Mishra2b75d6d2017-08-07 17:36:25 +0530640 } else if (IS_FILS_CIPHER(req_key->type)) {
641 /* Take request key object to FILS setkey */
642 key->private = req_key;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530643 } else {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530644 if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
645 WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(vdev, key,
646 macaddr, req_key->type);
647 }
648 }
649 status = cipher->setkey(key);
650
651 return status;
652}
653
654/**
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530655 * wlan_crypto_get_keytype - get keytype
656 * @key: key
657 *
658 * This function gets keytype from key
659 *
660 * Return: keytype
661 */
662wlan_crypto_cipher_type wlan_crypto_get_key_type(
663 struct wlan_crypto_key *key){
664 if (key && key->cipher_table) {
665 return ((struct wlan_crypto_cipher *)
666 (key->cipher_table))->cipher;
667 }
668 return WLAN_CRYPTO_CIPHER_NONE;
669}
670qdf_export_symbol(wlan_crypto_get_key_type);
671/**
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530672 * wlan_crypto_vdev_getkey - get key from vdev
673 * @vdev: vdev
674 * @keyix: keyix
675 *
676 * This function gets key from vdev
677 *
678 * Return: key or NULL
679 */
680struct wlan_crypto_key *wlan_crypto_vdev_getkey(struct wlan_objmgr_vdev *vdev,
681 uint16_t keyix){
682 struct wlan_crypto_comp_priv *crypto_priv;
683 struct wlan_crypto_params *crypto_params;
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530684 struct wlan_crypto_key *key = NULL;
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530685
686 crypto_params = wlan_crypto_vdev_get_comp_params(vdev, &crypto_priv);
687
688 if (crypto_priv == NULL) {
689 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
690 return NULL;
691 }
692
693 if (keyix == WLAN_CRYPTO_KEYIX_NONE || keyix >= WLAN_CRYPTO_MAXKEYIDX)
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530694 key = crypto_priv->key[crypto_priv->def_tx_keyid];
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530695 else
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530696 key = crypto_priv->key[keyix];
697
698 if (key && key->valid)
699 return key;
700
701 return NULL;
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530702}
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530703qdf_export_symbol(wlan_crypto_vdev_getkey);
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530704
705/**
706 * wlan_crypto_peer_getkey - get key from peer
707 * @peer: peer
708 * @keyix: keyix
709 *
710 * This function gets key from peer
711 *
712 * Return: key or NULL
713 */
714struct wlan_crypto_key *wlan_crypto_peer_getkey(struct wlan_objmgr_peer *peer,
715 uint16_t keyix){
716 struct wlan_crypto_comp_priv *crypto_priv;
717 struct wlan_crypto_params *crypto_params;
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530718 struct wlan_crypto_key *key = NULL;
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530719
720 crypto_params = wlan_crypto_peer_get_comp_params(peer, &crypto_priv);
721
722 if (crypto_priv == NULL) {
723 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
724 return NULL;
725 }
726
727 if (keyix == WLAN_CRYPTO_KEYIX_NONE || keyix >= WLAN_CRYPTO_MAXKEYIDX)
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530728 key = crypto_priv->key[crypto_priv->def_tx_keyid];
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530729 else
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530730 key = crypto_priv->key[keyix];
731
732 if (key && key->valid)
733 return key;
734
735 return NULL;
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530736}
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530737qdf_export_symbol(wlan_crypto_peer_getkey);
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530738
739/**
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530740 * wlan_crypto_getkey - called by ucfg to get key
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530741 * @vdev: vdev
742 * @req_key: key value will be copied in this req_key
743 * @mac_address: mac address of the peer for unicast key
744 * or broadcast address if group key is requested.
Ashok Ponnaiahf9953602018-01-11 15:39:26 +0530745 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530746 * This function gets called from ucfg to get key
747 *
748 * Return: QDF_STATUS_SUCCESS - in case of success
749 */
750QDF_STATUS wlan_crypto_getkey(struct wlan_objmgr_vdev *vdev,
751 struct wlan_crypto_req_key *req_key,
752 uint8_t *mac_addr){
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530753 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530754 struct wlan_crypto_key *key;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530755 struct wlan_objmgr_psoc *psoc;
756 uint8_t macaddr[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
757
Ashok Ponnaiah150a2942017-07-10 17:19:47 +0530758 if ((req_key->keyix != WLAN_CRYPTO_KEYIX_NONE) &&
759 (req_key->keyix >= WLAN_CRYPTO_MAXKEYIDX)) {
760 qdf_print("%s[%d] invalid keyix %d\n", __func__, __LINE__,
761 req_key->keyix);
762 return QDF_STATUS_E_INVAL;
763 }
764
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530765 wlan_vdev_obj_lock(vdev);
766 qdf_mem_copy(macaddr, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
767 psoc = wlan_vdev_get_psoc(vdev);
768 if (!psoc) {
769 wlan_vdev_obj_unlock(vdev);
770 qdf_print("%s[%d] psoc NULL\n", __func__, __LINE__);
771 return QDF_STATUS_E_INVAL;
772 }
773 wlan_vdev_obj_unlock(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530774
775 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac_addr)) {
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530776 key = wlan_crypto_vdev_getkey(vdev, req_key->keyix);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530777 if (!key)
778 return QDF_STATUS_E_INVAL;
779 } else {
780 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +0530781 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530782
Amir Pateld3385942018-05-03 23:01:08 +0530783 pdev_id = wlan_objmgr_pdev_get_pdev_id(
784 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530785 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530786 psoc,
Amir Pateld3385942018-05-03 23:01:08 +0530787 pdev_id,
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530788 macaddr,
Amir Pateld3385942018-05-03 23:01:08 +0530789 mac_addr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530790 WLAN_CRYPTO_ID);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530791 if (peer == NULL) {
Nandha Kishore Easwaran434838f2017-10-29 00:47:11 +0530792 QDF_TRACE(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_ERROR,
793 "%s[%d] peer NULL\n", __func__, __LINE__);
794 return QDF_STATUS_E_NOENT;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530795 }
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530796 key = wlan_crypto_peer_getkey(peer, req_key->keyix);
Ashok Ponnaiahc1797fd2018-05-04 09:42:02 +0530797 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530798 if (!key)
799 return QDF_STATUS_E_INVAL;
800 }
801
802 if (key->valid) {
803 qdf_mem_copy(req_key->keydata,
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530804 key->keyval, key->keylen);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530805 qdf_mem_copy((uint8_t *)(&req_key->keytsc),
806 (uint8_t *)(&key->keytsc),
807 sizeof(req_key->keytsc));
808 qdf_mem_copy((uint8_t *)(&req_key->keyrsc),
809 (uint8_t *)(&key->keyrsc[0]),
810 sizeof(req_key->keyrsc));
811 req_key->keylen = key->keylen;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530812 req_key->flags = key->flags;
813 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530814
815 if (!cipher_table)
816 return QDF_STATUS_SUCCESS;
817
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530818 req_key->type = cipher_table->cipher;
Rohan Duttabec3ab72017-09-22 12:32:23 +0530819 if (req_key->type == WLAN_CRYPTO_CIPHER_WAPI_SMS4) {
820 qdf_mem_copy((uint8_t *)(&req_key->txiv),
821 (uint8_t *)(key->txiv),
822 sizeof(req_key->txiv));
823 qdf_mem_copy((uint8_t *)(&req_key->recviv),
824 (uint8_t *)(key->recviv),
825 sizeof(req_key->recviv));
826 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530827 }
828
829 return QDF_STATUS_SUCCESS;
830}
831
832/**
833 * wlan_crypto_delkey - called by ucfg to delete key
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530834 * @vdev: vdev
835 * @mac_address: mac address of the peer for unicast key
836 * or broadcast address if group key is deleted.
837 * @key_idx: key index to be deleted
Ashok Ponnaiahf9953602018-01-11 15:39:26 +0530838 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530839 * This function gets called from ucfg to delete key
840 *
841 * Return: QDF_STATUS_SUCCESS - in case of success
842 */
843QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev,
844 uint8_t *macaddr,
845 uint8_t key_idx){
846 struct wlan_crypto_comp_priv *crypto_priv;
847 struct wlan_crypto_params *crypto_params;
848 struct wlan_crypto_key *key;
849 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530850 struct wlan_objmgr_psoc *psoc;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +0530851 uint8_t bssid_mac[WLAN_ALEN];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530852
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530853 if (!vdev || !macaddr ||
Disha Das76210cd2018-04-10 12:44:14 +0530854 (key_idx >=
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530855 (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX))) {
Disha Das19fa3232018-02-16 14:58:19 +0530856 QDF_TRACE(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_ERROR,
857 "%s[%d] Invalid params vdev %pK, macaddr %pK"
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530858 "keyidx %d\n", __func__, __LINE__, vdev,
859 macaddr, key_idx);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530860 return QDF_STATUS_E_INVAL;
861 }
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530862
863 wlan_vdev_obj_lock(vdev);
864 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
865 psoc = wlan_vdev_get_psoc(vdev);
866 if (!psoc) {
867 wlan_vdev_obj_unlock(vdev);
868 qdf_print("%s[%d] psoc NULL\n", __func__, __LINE__);
869 return QDF_STATUS_E_INVAL;
870 }
871 wlan_vdev_obj_unlock(vdev);
872
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530873 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)macaddr)) {
874 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
875 &crypto_priv);
876 if (crypto_priv == NULL) {
877 qdf_print("%s[%d] crypto_priv NULL\n",
878 __func__, __LINE__);
879 return QDF_STATUS_E_INVAL;
880 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530881 } else {
882 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +0530883 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530884
Amir Pateld3385942018-05-03 23:01:08 +0530885 pdev_id = wlan_objmgr_pdev_get_pdev_id(
886 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530887 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Amir Pateld3385942018-05-03 23:01:08 +0530888 psoc, pdev_id,
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530889 bssid_mac,
Amir Pateld3385942018-05-03 23:01:08 +0530890 macaddr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530891 WLAN_CRYPTO_ID);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530892 if (peer == NULL) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530893 return QDF_STATUS_E_INVAL;
894 }
895 crypto_params = wlan_crypto_peer_get_comp_params(peer,
896 &crypto_priv);
897 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
898 if (crypto_priv == NULL) {
899 qdf_print("%s[%d] crypto_priv NULL\n",
900 __func__, __LINE__);
901 return QDF_STATUS_E_INVAL;
902 }
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530903 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530904
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530905 if (key_idx >= WLAN_CRYPTO_MAXKEYIDX) {
906 uint8_t igtk_idx = key_idx - WLAN_CRYPTO_MAXKEYIDX;
Radhika Sriram00392f32018-04-04 19:04:49 +0530907 if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) {
908 qdf_print("%s[%d] Igtk key invalid keyid %d\n",
909 __func__, __LINE__, igtk_idx);
910 return QDF_STATUS_E_INVAL;
911 }
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530912 key = crypto_priv->igtk_key[igtk_idx];
913 crypto_priv->igtk_key[igtk_idx] = NULL;
Nandha Kishore Easwaranf832d982017-12-18 10:42:15 +0530914 if (key)
915 key->valid = 0;
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530916 } else {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530917 key = crypto_priv->key[key_idx];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530918 crypto_priv->key[key_idx] = NULL;
919 }
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530920
921 if (!key)
922 return QDF_STATUS_E_INVAL;
923
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530924 if (key->valid) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530925 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
926
927 if (WLAN_CRYPTO_TX_OPS_DELKEY(psoc)) {
928 WLAN_CRYPTO_TX_OPS_DELKEY(psoc)(vdev, key,
929 macaddr, cipher_table->cipher);
930 }
931 }
932 qdf_mem_free(key);
933
934 return QDF_STATUS_SUCCESS;
935}
936
937/**
938 * wlan_crypto_default_key - called by ucfg to set default tx key
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530939 * @vdev: vdev
940 * @mac_address: mac address of the peer for unicast key
941 * or broadcast address if group key need to made default.
942 * @key_idx: key index to be made as default key
943 * @unicast: is key was unicast or group key.
Ashok Ponnaiahf9953602018-01-11 15:39:26 +0530944 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530945 * This function gets called from ucfg to set default key
946 *
947 * Return: QDF_STATUS_SUCCESS - in case of success
948 */
949QDF_STATUS wlan_crypto_default_key(struct wlan_objmgr_vdev *vdev,
950 uint8_t *macaddr,
951 uint8_t key_idx,
952 bool unicast){
953 struct wlan_crypto_comp_priv *crypto_priv;
954 struct wlan_crypto_params *crypto_params;
955 struct wlan_crypto_key *key;
956 struct wlan_objmgr_psoc *psoc;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +0530957 uint8_t bssid_mac[WLAN_ALEN];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530958
Disha Das55b86c22018-04-20 15:22:08 +0530959 if (!vdev || !macaddr || (key_idx >= WLAN_CRYPTO_MAXKEYIDX)) {
960 qdf_print("%s[%d] Invalid params vdev %pK, macaddr %pK"
961 "keyidx %d\n", __func__, __LINE__,
962 vdev, macaddr, key_idx);
963 return QDF_STATUS_E_INVAL;
964 }
965
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530966 wlan_vdev_obj_lock(vdev);
967 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
968 psoc = wlan_vdev_get_psoc(vdev);
969 if (!psoc) {
970 wlan_vdev_obj_unlock(vdev);
971 qdf_print("%s[%d] psoc NULL\n", __func__, __LINE__);
972 return QDF_STATUS_E_INVAL;
973 }
974 wlan_vdev_obj_unlock(vdev);
975
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530976 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)macaddr)) {
977 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
978 &crypto_priv);
979 if (crypto_priv == NULL) {
980 qdf_print("%s[%d] crypto_priv NULL\n",
981 __func__, __LINE__);
982 return QDF_STATUS_E_INVAL;
983 }
984
985 key = crypto_priv->key[key_idx];
986 if (!key)
987 return QDF_STATUS_E_INVAL;
988 } else {
989 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +0530990 uint8_t pdev_id;
991
992 pdev_id = wlan_objmgr_pdev_get_pdev_id(
993 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530994 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Amir Pateld3385942018-05-03 23:01:08 +0530995 psoc, pdev_id,
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530996 bssid_mac,
Amir Pateld3385942018-05-03 23:01:08 +0530997 macaddr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530998 WLAN_CRYPTO_ID);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530999
1000 if (peer == NULL) {
1001 qdf_print("%s[%d] peer NULL\n", __func__, __LINE__);
1002 return QDF_STATUS_E_INVAL;
1003 }
1004 crypto_params = wlan_crypto_peer_get_comp_params(peer,
1005 &crypto_priv);
1006 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1007 if (crypto_priv == NULL) {
1008 qdf_print("%s[%d] crypto_priv NULL\n",
1009 __func__, __LINE__);
1010 return QDF_STATUS_E_INVAL;
1011 }
1012
1013 key = crypto_priv->key[key_idx];
1014 if (!key)
1015 return QDF_STATUS_E_INVAL;
1016 }
1017 if (!key->valid)
1018 return QDF_STATUS_E_INVAL;
1019
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301020 if (WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)) {
1021 WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)(vdev, key_idx,
1022 macaddr);
1023 }
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301024 crypto_priv->def_tx_keyid = key_idx;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301025
1026 return QDF_STATUS_SUCCESS;
1027}
1028
1029/**
1030 * wlan_crypto_encap - called by mgmt for encap the frame based on cipher
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301031 * @vdev: vdev
1032 * @wbuf: wbuf
1033 * @macaddr: macaddr
1034 * @encapdone: is encapdone already or not.
Ashok Ponnaiahf9953602018-01-11 15:39:26 +05301035 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301036 * This function gets called from mgmt txrx to encap frame.
1037 *
1038 * Return: QDF_STATUS_SUCCESS - in case of success
1039 */
1040QDF_STATUS wlan_crypto_encap(struct wlan_objmgr_vdev *vdev,
1041 qdf_nbuf_t wbuf,
1042 uint8_t *mac_addr,
1043 uint8_t encapdone){
1044 struct wlan_crypto_comp_priv *crypto_priv;
1045 struct wlan_crypto_params *crypto_params;
1046 struct wlan_crypto_key *key;
1047 QDF_STATUS status;
1048 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301049 struct wlan_objmgr_psoc *psoc;
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301050 struct wlan_objmgr_peer *peer;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05301051 uint8_t bssid_mac[WLAN_ALEN];
Amir Pateld3385942018-05-03 23:01:08 +05301052 uint8_t pdev_id;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301053
1054 wlan_vdev_obj_lock(vdev);
1055 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
1056 psoc = wlan_vdev_get_psoc(vdev);
1057 if (!psoc) {
1058 wlan_vdev_obj_unlock(vdev);
1059 qdf_print("%s[%d] psoc NULL\n", __func__, __LINE__);
1060 return QDF_STATUS_E_INVAL;
1061 }
1062 wlan_vdev_obj_unlock(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301063
Amir Pateld3385942018-05-03 23:01:08 +05301064 pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301065 /* FILS Encap required only for (Re-)Assoc response */
Amir Pateld3385942018-05-03 23:01:08 +05301066 peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr, WLAN_CRYPTO_ID);
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301067
1068 if (!wlan_crypto_is_data_protected((uint8_t *)qdf_nbuf_data(wbuf)) &&
1069 peer && !wlan_crypto_get_peer_fils_aead(peer)) {
1070 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1071 return QDF_STATUS_E_INVAL;
1072 }
1073
1074 if (peer)
1075 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1076
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301077 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac_addr)) {
1078 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1079 &crypto_priv);
1080 if (crypto_priv == NULL) {
1081 qdf_print("%s[%d] crypto_priv NULL\n",
1082 __func__, __LINE__);
1083 return QDF_STATUS_E_INVAL;
1084 }
1085
1086 key = crypto_priv->key[crypto_priv->def_tx_keyid];
1087 if (!key)
1088 return QDF_STATUS_E_INVAL;
1089
1090 } else {
1091 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +05301092 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301093
Amir Pateld3385942018-05-03 23:01:08 +05301094 pdev_id = wlan_objmgr_pdev_get_pdev_id(
1095 wlan_vdev_get_pdev(vdev));
1096 peer = wlan_objmgr_get_peer_by_mac_n_vdev(psoc, pdev_id,
1097 bssid_mac, mac_addr,
1098 WLAN_CRYPTO_ID);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301099
1100 if (peer == NULL) {
1101 qdf_print("%s[%d] crypto_priv NULL\n",
1102 __func__, __LINE__);
1103 return QDF_STATUS_E_INVAL;
1104 }
1105 crypto_params = wlan_crypto_peer_get_comp_params(peer,
1106 &crypto_priv);
1107 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1108
1109 if (crypto_priv == NULL) {
1110 qdf_print("%s[%d] crypto_priv NULL\n",
1111 __func__, __LINE__);
1112 return QDF_STATUS_E_INVAL;
1113 }
1114
1115 key = crypto_priv->key[crypto_priv->def_tx_keyid];
1116 if (!key)
1117 return QDF_STATUS_E_INVAL;
1118 }
1119 /* if tkip, is counter measures enabled, then drop the frame */
1120 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
1121 status = cipher_table->encap(key, wbuf, encapdone,
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301122 ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf)));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301123
1124 return status;
1125}
Manikandan Mohana2993a52018-03-01 16:21:55 -08001126qdf_export_symbol(wlan_crypto_encap);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301127
1128/**
1129 * wlan_crypto_decap - called by mgmt for decap the frame based on cipher
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301130 * @vdev: vdev
1131 * @wbuf: wbuf
1132 * @macaddr: macaddr
1133 * @tid: tid of the frame
Ashok Ponnaiahf9953602018-01-11 15:39:26 +05301134 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301135 * This function gets called from mgmt txrx to decap frame.
1136 *
1137 * Return: QDF_STATUS_SUCCESS - in case of success
1138 */
1139QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev,
1140 qdf_nbuf_t wbuf,
1141 uint8_t *mac_addr,
1142 uint8_t tid){
1143 struct wlan_crypto_comp_priv *crypto_priv;
1144 struct wlan_crypto_params *crypto_params;
1145 struct wlan_crypto_key *key;
1146 QDF_STATUS status;
1147 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301148 struct wlan_objmgr_psoc *psoc;
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301149 struct wlan_objmgr_peer *peer;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05301150 uint8_t bssid_mac[WLAN_ALEN];
Ashok Ponnaiahe25c64c2018-04-09 15:34:14 +05301151 uint8_t keyid;
Amir Pateld3385942018-05-03 23:01:08 +05301152 uint8_t pdev_id;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301153
1154 wlan_vdev_obj_lock(vdev);
1155 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
1156 psoc = wlan_vdev_get_psoc(vdev);
1157 if (!psoc) {
1158 wlan_vdev_obj_unlock(vdev);
1159 qdf_print("%s[%d] psoc NULL\n", __func__, __LINE__);
1160 return QDF_STATUS_E_INVAL;
1161 }
1162 wlan_vdev_obj_unlock(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301163
Ashok Ponnaiahe25c64c2018-04-09 15:34:14 +05301164 keyid = wlan_crypto_get_keyid((uint8_t *)qdf_nbuf_data(wbuf));
1165
1166 if (keyid >= WLAN_CRYPTO_MAXKEYIDX)
1167 return QDF_STATUS_E_INVAL;
1168
Amir Pateld3385942018-05-03 23:01:08 +05301169 pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301170 /* FILS Decap required only for (Re-)Assoc request */
Amir Pateld3385942018-05-03 23:01:08 +05301171 peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr, WLAN_CRYPTO_ID);
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301172
1173 if (!wlan_crypto_is_data_protected((uint8_t *)qdf_nbuf_data(wbuf)) &&
1174 peer && !wlan_crypto_get_peer_fils_aead(peer)) {
1175 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1176 return QDF_STATUS_E_INVAL;
1177 }
1178
1179 if (peer)
1180 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1181
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301182 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac_addr)) {
1183 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1184 &crypto_priv);
1185 if (crypto_priv == NULL) {
1186 qdf_print("%s[%d] crypto_priv NULL\n",
1187 __func__, __LINE__);
1188 return QDF_STATUS_E_INVAL;
1189 }
1190
Ashok Ponnaiahe25c64c2018-04-09 15:34:14 +05301191 key = crypto_priv->key[keyid];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301192 if (!key)
1193 return QDF_STATUS_E_INVAL;
1194
1195 } else {
1196 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +05301197 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301198
Amir Pateld3385942018-05-03 23:01:08 +05301199 pdev_id = wlan_objmgr_pdev_get_pdev_id(
1200 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301201 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Amir Pateld3385942018-05-03 23:01:08 +05301202 psoc, pdev_id, bssid_mac,
1203 mac_addr, WLAN_CRYPTO_ID);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301204 if (peer == NULL) {
1205 qdf_print("%s[%d] peer NULL\n", __func__, __LINE__);
1206 return QDF_STATUS_E_INVAL;
1207 }
1208
1209 crypto_params = wlan_crypto_peer_get_comp_params(peer,
1210 &crypto_priv);
1211 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1212
1213 if (crypto_priv == NULL) {
1214 qdf_print("%s[%d] crypto_priv NULL\n",
1215 __func__, __LINE__);
1216 return QDF_STATUS_E_INVAL;
1217 }
1218
Ashok Ponnaiahe25c64c2018-04-09 15:34:14 +05301219 key = crypto_priv->key[keyid];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301220 if (!key)
1221 return QDF_STATUS_E_INVAL;
1222 }
1223 /* if tkip, is counter measures enabled, then drop the frame */
1224 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301225 status = cipher_table->decap(key, wbuf, tid,
1226 ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf)));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301227
1228 return status;
1229}
Manikandan Mohana2993a52018-03-01 16:21:55 -08001230qdf_export_symbol(wlan_crypto_decap);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301231/**
1232 * wlan_crypto_enmic - called by mgmt for adding mic in frame based on cipher
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301233 * @vdev: vdev
1234 * @wbuf: wbuf
1235 * @macaddr: macaddr
1236 * @encapdone: is encapdone already or not.
Ashok Ponnaiahf9953602018-01-11 15:39:26 +05301237 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301238 * This function gets called from mgmt txrx to adding mic to the frame.
1239 *
1240 * Return: QDF_STATUS_SUCCESS - in case of success
1241 */
1242QDF_STATUS wlan_crypto_enmic(struct wlan_objmgr_vdev *vdev,
1243 qdf_nbuf_t wbuf,
1244 uint8_t *mac_addr,
1245 uint8_t encapdone){
1246 struct wlan_crypto_comp_priv *crypto_priv;
1247 struct wlan_crypto_params *crypto_params;
1248 struct wlan_crypto_key *key;
1249 QDF_STATUS status;
1250 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301251 struct wlan_objmgr_psoc *psoc;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05301252 uint8_t bssid_mac[WLAN_ALEN];
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301253
Amir Pateld3385942018-05-03 23:01:08 +05301254
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301255 wlan_vdev_obj_lock(vdev);
1256 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
1257 psoc = wlan_vdev_get_psoc(vdev);
1258 if (!psoc) {
1259 wlan_vdev_obj_unlock(vdev);
1260 qdf_print("%s[%d] psoc NULL\n", __func__, __LINE__);
1261 return QDF_STATUS_E_INVAL;
1262 }
1263 wlan_vdev_obj_unlock(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301264
1265 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac_addr)) {
1266 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1267 &crypto_priv);
1268 if (crypto_priv == NULL) {
1269 qdf_print("%s[%d] crypto_priv NULL\n",
1270 __func__, __LINE__);
1271 return QDF_STATUS_E_INVAL;
1272 }
1273
1274 key = crypto_priv->key[crypto_priv->def_tx_keyid];
1275 if (!key)
1276 return QDF_STATUS_E_INVAL;
1277
1278 } else {
1279 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +05301280 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301281
Amir Pateld3385942018-05-03 23:01:08 +05301282 pdev_id = wlan_objmgr_pdev_get_pdev_id(
1283 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301284 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Amir Pateld3385942018-05-03 23:01:08 +05301285 psoc, pdev_id, bssid_mac,
1286 mac_addr, WLAN_CRYPTO_ID);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301287 if (peer == NULL) {
1288 qdf_print("%s[%d] crypto_priv NULL\n",
1289 __func__, __LINE__);
1290 return QDF_STATUS_E_INVAL;
1291 }
1292
1293 crypto_params = wlan_crypto_peer_get_comp_params(peer,
1294 &crypto_priv);
1295 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1296
1297 if (crypto_priv == NULL) {
1298 qdf_print("%s[%d] crypto_priv NULL\n",
1299 __func__, __LINE__);
1300 return QDF_STATUS_E_INVAL;
1301 }
1302
1303 key = crypto_priv->key[crypto_priv->def_tx_keyid];
1304 if (!key)
1305 return QDF_STATUS_E_INVAL;
1306 }
1307 /* if tkip, is counter measures enabled, then drop the frame */
1308 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
1309 status = cipher_table->enmic(key, wbuf, encapdone,
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301310 ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf)));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301311
1312 return status;
1313}
1314
1315/**
1316 * wlan_crypto_demic - called by mgmt for remove and check mic for
1317 * the frame based on cipher
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301318 * @vdev: vdev
1319 * @wbuf: wbuf
1320 * @macaddr: macaddr
1321 * @tid: tid of the frame
Ashok Ponnaiahf9953602018-01-11 15:39:26 +05301322 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301323 * This function gets called from mgmt txrx to decap frame.
1324 *
1325 * Return: QDF_STATUS_SUCCESS - in case of success
1326 */
1327QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev,
1328 qdf_nbuf_t wbuf,
1329 uint8_t *mac_addr,
1330 uint8_t tid){
1331 struct wlan_crypto_comp_priv *crypto_priv;
1332 struct wlan_crypto_params *crypto_params;
1333 struct wlan_crypto_key *key;
1334 QDF_STATUS status;
1335 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301336 struct wlan_objmgr_psoc *psoc;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05301337 uint8_t bssid_mac[WLAN_ALEN];
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301338
Amir Pateld3385942018-05-03 23:01:08 +05301339
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301340 wlan_vdev_obj_lock(vdev);
1341 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
1342 psoc = wlan_vdev_get_psoc(vdev);
1343 if (!psoc) {
1344 wlan_vdev_obj_unlock(vdev);
1345 qdf_print("%s[%d] psoc NULL\n", __func__, __LINE__);
1346 return QDF_STATUS_E_INVAL;
1347 }
1348 wlan_vdev_obj_unlock(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301349
1350 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac_addr)) {
1351 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1352 &crypto_priv);
1353 if (crypto_priv == NULL) {
1354 qdf_print("%s[%d] crypto_priv NULL\n",
1355 __func__, __LINE__);
1356 return QDF_STATUS_E_INVAL;
1357 }
1358
1359 key = crypto_priv->key[crypto_priv->def_tx_keyid];
1360 if (!key)
1361 return QDF_STATUS_E_INVAL;
1362
1363 } else {
1364 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +05301365 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301366
Amir Pateld3385942018-05-03 23:01:08 +05301367 pdev_id = wlan_objmgr_pdev_get_pdev_id(
1368 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301369 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Amir Pateld3385942018-05-03 23:01:08 +05301370 psoc, pdev_id, bssid_mac,
1371 mac_addr, WLAN_CRYPTO_ID);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301372 if (peer == NULL) {
1373 qdf_print("%s[%d] peer NULL\n", __func__, __LINE__);
1374 return QDF_STATUS_E_INVAL;
1375 }
1376
1377 crypto_params = wlan_crypto_peer_get_comp_params(peer,
1378 &crypto_priv);
1379 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1380
1381 if (crypto_priv == NULL) {
1382 qdf_print("%s[%d] crypto_priv NULL\n",
1383 __func__, __LINE__);
1384 return QDF_STATUS_E_INVAL;
1385 }
1386
1387 key = crypto_priv->key[crypto_priv->def_tx_keyid];
1388 if (!key)
1389 return QDF_STATUS_E_INVAL;
1390 }
1391 /* if tkip, is counter measures enabled, then drop the frame */
1392 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301393 status = cipher_table->demic(key, wbuf, tid,
1394 ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf)));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301395
1396 return status;
1397}
1398
1399/**
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301400 * wlan_crypto_vdev_is_pmf_enabled - called to check is pmf enabled in vdev
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301401 * @vdev: vdev
1402 *
1403 * This function gets called to check is pmf enabled or not in vdev.
1404 *
1405 * Return: true or false
1406 */
1407bool wlan_crypto_vdev_is_pmf_enabled(struct wlan_objmgr_vdev *vdev)
1408{
1409
1410 struct wlan_crypto_comp_priv *crypto_priv;
1411 struct wlan_crypto_params *vdev_crypto_params;
1412
1413 if (!vdev)
1414 return false;
1415 vdev_crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1416 &crypto_priv);
1417 if (crypto_priv == NULL) {
1418 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
1419 return QDF_STATUS_E_INVAL;
1420 }
1421
1422 if ((vdev_crypto_params->rsn_caps &
1423 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)
1424 || (vdev_crypto_params->rsn_caps &
1425 WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)) {
1426 return true;
1427 }
1428
1429 return false;
1430}
1431/**
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301432 * wlan_crypto_is_pmf_enabled - called by mgmt txrx to check is pmf enabled
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301433 * @vdev: vdev
1434 * @peer: peer
1435 *
1436 * This function gets called by mgmt txrx to check is pmf enabled or not.
1437 *
1438 * Return: true or false
1439 */
1440bool wlan_crypto_is_pmf_enabled(struct wlan_objmgr_vdev *vdev,
1441 struct wlan_objmgr_peer *peer){
1442
1443 struct wlan_crypto_comp_priv *crypto_priv;
1444 struct wlan_crypto_params *vdev_crypto_params;
1445 struct wlan_crypto_params *peer_crypto_params;
1446
1447 if (!vdev || !peer)
1448 return false;
1449 vdev_crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1450 &crypto_priv);
1451 if (crypto_priv == NULL) {
1452 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
1453 return QDF_STATUS_E_INVAL;
1454 }
1455
1456 peer_crypto_params = wlan_crypto_peer_get_comp_params(peer,
1457 &crypto_priv);
1458 if (crypto_priv == NULL) {
1459 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
1460 return QDF_STATUS_E_INVAL;
1461 }
1462 if (((vdev_crypto_params->rsn_caps &
1463 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) &&
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301464 (peer_crypto_params->rsn_caps &
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301465 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED))
1466 || (vdev_crypto_params->rsn_caps &
1467 WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)) {
1468 return true;
1469 }
1470
1471 return false;
1472}
Ashok Ponnaiah7a41e8c2017-12-28 17:13:40 +05301473
1474static void wlan_crypto_gmac_pn_swap(uint8_t *a, uint8_t *b)
1475{
1476 a[0] = b[5];
1477 a[1] = b[4];
1478 a[2] = b[3];
1479 a[3] = b[2];
1480 a[4] = b[1];
1481 a[5] = b[0];
1482}
1483
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301484/**
1485 * wlan_crypto_add_mmie - called by mgmt txrx to add mmie in frame
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301486 * @vdev: vdev
1487 * @bfrm: frame starting pointer
1488 * @len: length of the frame
1489 *
1490 * This function gets called by mgmt txrx to add mmie in frame
1491 *
1492 * Return: end of frame or NULL in case failure
1493 */
1494uint8_t *wlan_crypto_add_mmie(struct wlan_objmgr_vdev *vdev,
1495 uint8_t *bfrm,
1496 uint32_t len) {
1497 struct wlan_crypto_key *key;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301498 struct wlan_crypto_mmie *mmie;
1499 uint8_t *pn, *aad, *buf, *efrm, nounce[12];
1500 struct ieee80211_hdr *hdr;
1501 uint32_t i, hdrlen, mic_len, aad_len;
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301502 uint8_t mic[16];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301503 struct wlan_crypto_comp_priv *crypto_priv;
1504 struct wlan_crypto_params *crypto_params;
Disha Das55b86c22018-04-20 15:22:08 +05301505 int32_t ret = -1;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301506
1507 if (!bfrm) {
1508 qdf_print("%s[%d] frame is NULL\n", __func__, __LINE__);
1509 return NULL;
1510 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301511
1512 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1513 &crypto_priv);
1514 if (crypto_priv == NULL) {
1515 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
1516 return NULL;
1517 }
1518
Disha Das76210cd2018-04-10 12:44:14 +05301519 if (crypto_priv->def_igtk_tx_keyid >= WLAN_CRYPTO_MAXIGTKKEYIDX) {
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301520 qdf_print("%s[%d] igtk key invalid keyid %d \n",
1521 __func__, __LINE__, crypto_priv->def_igtk_tx_keyid);
1522 return NULL;
1523 }
1524
1525 key = crypto_priv->igtk_key[crypto_priv->def_igtk_tx_keyid];
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301526 if (!key) {
1527 qdf_print("%s[%d] No igtk key present\n", __func__, __LINE__);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301528 return NULL;
1529 }
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301530 mic_len = (crypto_priv->igtk_key_type
1531 == WLAN_CRYPTO_CIPHER_AES_CMAC) ? 8 : 16;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301532
1533 efrm = bfrm + len;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301534 aad_len = 20;
1535 hdrlen = sizeof(struct ieee80211_hdr);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301536 len += sizeof(struct wlan_crypto_mmie);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301537
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301538 mmie = (struct wlan_crypto_mmie *) efrm;
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301539 qdf_mem_zero((unsigned char *)mmie, sizeof(*mmie));
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301540 mmie->element_id = WLAN_ELEMID_MMIE;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301541 mmie->length = sizeof(*mmie) - 2;
1542 mmie->key_id = qdf_cpu_to_le16(key->keyix);
1543
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301544 mic_len = (crypto_priv->igtk_key_type
1545 == WLAN_CRYPTO_CIPHER_AES_CMAC) ? 8 : 16;
1546 if (mic_len == 8) {
1547 mmie->length -= 8;
1548 len -= 8;
1549 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301550 /* PN = PN + 1 */
1551 pn = (uint8_t *)&key->keytsc;
1552
1553 for (i = 0; i <= 5; i++) {
1554 pn[i]++;
1555 if (pn[i])
1556 break;
1557 }
1558
1559 /* Copy IPN */
1560 qdf_mem_copy(mmie->sequence_number, pn, 6);
1561
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301562 hdr = (struct ieee80211_hdr *) bfrm;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301563
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301564 buf = qdf_mem_malloc(len - hdrlen + 20);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301565 if (!buf) {
1566 qdf_print("%s[%d] malloc failed\n", __func__, __LINE__);
1567 return NULL;
1568 }
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301569 qdf_mem_zero(buf, len - hdrlen + 20);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301570 aad = buf;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301571 /* generate BIP AAD: FC(masked) || A1 || A2 || A3 */
1572
1573 /* FC type/subtype */
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301574 aad[0] = hdr->frame_control & 0xff;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301575 /* Mask FC Retry, PwrMgt, MoreData flags to zero */
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301576 aad[1] = (hdr->frame_control & ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT
1577 | WLAN_FC_MOREDATA)) >> 8;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301578 /* A1 || A2 || A3 */
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301579 qdf_mem_copy(aad + 2, hdr->addr1, WLAN_ALEN);
1580 qdf_mem_copy(aad + 8, hdr->addr2, WLAN_ALEN);
1581 qdf_mem_copy(aad + 14, hdr->addr3, WLAN_ALEN);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301582 qdf_mem_zero(mic, 16);
1583
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301584 /*
1585 * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
1586 */
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301587
1588 qdf_mem_copy(buf + aad_len, bfrm + hdrlen, len - hdrlen);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301589 if (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_CMAC) {
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301590
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301591 ret = omac1_aes_128(key->keyval, buf,
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301592 len + aad_len - hdrlen, mic);
1593 qdf_mem_copy(mmie->mic, mic, 8);
1594
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301595 } else if (crypto_priv->igtk_key_type
1596 == WLAN_CRYPTO_CIPHER_AES_CMAC_256) {
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301597
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301598 ret = omac1_aes_256(key->keyval, buf,
1599 len + aad_len - hdrlen, mmie->mic);
1600 } else if ((crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_GMAC)
1601 || (crypto_priv->igtk_key_type
1602 == WLAN_CRYPTO_CIPHER_AES_GMAC_256)) {
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301603
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301604 qdf_mem_copy(nounce, hdr->addr2, WLAN_ALEN);
Ashok Ponnaiah7a41e8c2017-12-28 17:13:40 +05301605 wlan_crypto_gmac_pn_swap(nounce + 6, pn);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301606 ret = wlan_crypto_aes_gmac(key->keyval, key->keylen, nounce,
1607 sizeof(nounce), buf,
1608 len + aad_len - hdrlen, mmie->mic);
1609 }
1610 qdf_mem_free(buf);
1611 if (ret < 0) {
1612 qdf_print("%s[%d] add mmie failed\n", __func__, __LINE__);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301613 return NULL;
1614 }
1615
1616 return bfrm + len;
1617}
1618
1619/**
1620 * wlan_crypto_is_mmie_valid - called by mgmt txrx to check mmie of the frame
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301621 * @vdev: vdev
1622 * @frm: frame starting pointer
1623 * @efrm: end of frame pointer
1624 *
1625 * This function gets called by mgmt txrx to check mmie of the frame
1626 *
1627 * Return: true or false
1628 */
1629bool wlan_crypto_is_mmie_valid(struct wlan_objmgr_vdev *vdev,
1630 uint8_t *frm,
1631 uint8_t *efrm){
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301632 struct wlan_crypto_mmie *mmie = NULL;
1633 uint8_t *ipn, *aad, *buf, mic[16], nounce[12];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301634 struct wlan_crypto_key *key;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301635 struct ieee80211_hdr *hdr;
1636 uint16_t mic_len, hdrlen, len;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301637 struct wlan_crypto_comp_priv *crypto_priv;
1638 struct wlan_crypto_params *crypto_params;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301639 uint8_t aad_len = 20;
Disha Das55b86c22018-04-20 15:22:08 +05301640 int32_t ret = -1;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301641
1642 /* check if frame is illegal length */
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301643 if (!frm || !efrm || (efrm < frm)
1644 || ((efrm - frm) < sizeof(struct ieee80211_hdr))) {
1645 qdf_print("%s[%d] Invalid params\n", __func__, __LINE__);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301646 return false;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301647 }
1648 len = efrm - frm;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301649 crypto_priv = (struct wlan_crypto_comp_priv *)
1650 wlan_get_vdev_crypto_obj(vdev);
1651 if (crypto_priv == NULL) {
1652 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
1653 return false;
1654 }
1655
1656 crypto_params = &(crypto_priv->crypto_params);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301657
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301658
1659 mic_len = (crypto_priv->igtk_key_type
1660 == WLAN_CRYPTO_CIPHER_AES_CMAC) ? 8 : 16;
1661 hdrlen = sizeof(struct ieee80211_hdr);
1662
1663 if (mic_len == 8)
1664 mmie = (struct wlan_crypto_mmie *)(efrm - sizeof(*mmie) + 8);
1665 else
1666 mmie = (struct wlan_crypto_mmie *)(efrm - sizeof(*mmie));
1667
1668
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301669 /* check Elem ID*/
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301670 if ((mmie == NULL) || (mmie->element_id != WLAN_ELEMID_MMIE)) {
1671 qdf_print("%s[%d] IE is not MMIE\n", __func__, __LINE__);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301672 return false;
1673 }
1674
Disha Das76210cd2018-04-10 12:44:14 +05301675 if (mmie->key_id >= (WLAN_CRYPTO_MAXKEYIDX +
Disha Das55b86c22018-04-20 15:22:08 +05301676 WLAN_CRYPTO_MAXIGTKKEYIDX) ||
1677 (mmie->key_id < WLAN_CRYPTO_MAXKEYIDX)) {
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301678 qdf_print("%s[%d] keyid not valid\n", __func__, __LINE__);
1679 return false;
1680 }
1681
1682 key = crypto_priv->igtk_key[mmie->key_id - WLAN_CRYPTO_MAXKEYIDX];
1683 if (!key) {
1684 qdf_print("%s[%d] No igtk key present\n", __func__, __LINE__);
1685 return false;
1686 }
1687
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301688 /* validate ipn */
1689 ipn = mmie->sequence_number;
1690 if (qdf_mem_cmp(ipn, key->keyrsc, 6) <= 0) {
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301691 qdf_print("%s[%d] replay error\n", __func__, __LINE__);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301692 return false;
1693 }
1694
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301695 buf = qdf_mem_malloc(len - hdrlen + 20);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301696 if (!buf) {
1697 qdf_print("%s[%d] malloc failed\n", __func__, __LINE__);
1698 return false;
1699 }
1700 aad = buf;
1701
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301702 /* construct AAD */
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301703 hdr = (struct ieee80211_hdr *)frm;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301704 /* generate BIP AAD: FC(masked) || A1 || A2 || A3 */
1705
1706 /* FC type/subtype */
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301707 aad[0] = hdr->frame_control & 0xff;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301708 /* Mask FC Retry, PwrMgt, MoreData flags to zero */
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301709 aad[1] = (hdr->frame_control & ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT
1710 | WLAN_FC_MOREDATA)) >> 8;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301711 /* A1 || A2 || A3 */
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301712 qdf_mem_copy(aad + 2, hdr->addr1, 3 * WLAN_ALEN);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301713
1714 /*
1715 * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
1716 */
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301717 qdf_mem_copy(buf + 20, frm + hdrlen, len - hdrlen);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301718 qdf_mem_zero(buf + (len - hdrlen + 20 - mic_len), mic_len);
1719 qdf_mem_zero(mic, 16);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301720 if (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_CMAC) {
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301721 ret = omac1_aes_128(key->keyval, buf,
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301722 len - hdrlen + aad_len, mic);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301723 } else if (crypto_priv->igtk_key_type
1724 == WLAN_CRYPTO_CIPHER_AES_CMAC_256) {
1725 ret = omac1_aes_256(key->keyval, buf,
1726 len + aad_len - hdrlen, mic);
1727 } else if ((crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_GMAC)
1728 || (crypto_priv->igtk_key_type
1729 == WLAN_CRYPTO_CIPHER_AES_GMAC_256)) {
1730 qdf_mem_copy(nounce, hdr->addr2, WLAN_ALEN);
Ashok Ponnaiah7a41e8c2017-12-28 17:13:40 +05301731 wlan_crypto_gmac_pn_swap(nounce + 6, ipn);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301732 ret = wlan_crypto_aes_gmac(key->keyval, key->keylen, nounce,
1733 sizeof(nounce), buf,
1734 len + aad_len - hdrlen, mic);
1735 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301736
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301737 qdf_mem_free(buf);
1738
1739 if (ret < 0) {
1740 qdf_print("%s[%d] genarate mmie failed\n", __func__, __LINE__);
1741 return false;
1742 }
1743
1744 if (qdf_mem_cmp(mic, mmie->mic, mic_len) != 0) {
1745 qdf_print("%s[%d] mmie mismatch\n", __func__, __LINE__);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301746 /* MMIE MIC mismatch */
1747 return false;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301748 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301749
1750 /* Update the receive sequence number */
1751 qdf_mem_copy(key->keyrsc, ipn, 6);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301752 qdf_print("%s[%d] mmie matched\n", __func__, __LINE__);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301753
1754 return true;
1755}
1756
1757
1758static int32_t wlan_crypto_wpa_cipher_to_suite(uint32_t cipher)
1759{
1760 int32_t status = -1;
1761
1762 switch (cipher) {
1763 case WLAN_CRYPTO_CIPHER_TKIP:
1764 return WPA_CIPHER_SUITE_TKIP;
1765 case WLAN_CRYPTO_CIPHER_AES_CCM:
1766 return WPA_CIPHER_SUITE_CCMP;
1767 case WLAN_CRYPTO_CIPHER_NONE:
1768 return WPA_CIPHER_SUITE_NONE;
1769 }
1770
1771 return status;
1772}
1773
1774static int32_t wlan_crypto_rsn_cipher_to_suite(uint32_t cipher)
1775{
1776 int32_t status = -1;
1777
1778 switch (cipher) {
1779 case WLAN_CRYPTO_CIPHER_TKIP:
1780 return RSN_CIPHER_SUITE_TKIP;
1781 case WLAN_CRYPTO_CIPHER_AES_CCM:
1782 return RSN_CIPHER_SUITE_CCMP;
1783 case WLAN_CRYPTO_CIPHER_AES_CCM_256:
1784 return RSN_CIPHER_SUITE_CCMP_256;
1785 case WLAN_CRYPTO_CIPHER_AES_GCM:
1786 return RSN_CIPHER_SUITE_GCMP;
1787 case WLAN_CRYPTO_CIPHER_AES_GCM_256:
1788 return RSN_CIPHER_SUITE_GCMP_256;
1789 case WLAN_CRYPTO_CIPHER_AES_CMAC:
1790 return RSN_CIPHER_SUITE_AES_CMAC;
1791 case WLAN_CRYPTO_CIPHER_AES_CMAC_256:
1792 return RSN_CIPHER_SUITE_BIP_CMAC_256;
1793 case WLAN_CRYPTO_CIPHER_AES_GMAC:
1794 return RSN_CIPHER_SUITE_BIP_GMAC_128;
1795 case WLAN_CRYPTO_CIPHER_AES_GMAC_256:
1796 return RSN_CIPHER_SUITE_BIP_GMAC_256;
1797 case WLAN_CRYPTO_CIPHER_NONE:
1798 return RSN_CIPHER_SUITE_NONE;
1799 }
1800
1801 return status;
1802}
1803
1804/*
1805 * Convert an RSN key management/authentication algorithm
1806 * to an internal code.
1807 */
1808static int32_t
1809wlan_crypto_rsn_keymgmt_to_suite(uint32_t keymgmt)
1810{
1811 int32_t status = -1;
1812
1813 switch (keymgmt) {
1814 case WLAN_CRYPTO_KEY_MGMT_NONE:
1815 return RSN_AUTH_KEY_MGMT_NONE;
1816 case WLAN_CRYPTO_KEY_MGMT_IEEE8021X:
1817 return RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
1818 case WLAN_CRYPTO_KEY_MGMT_PSK:
1819 return RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
1820 case WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X:
1821 return RSN_AUTH_KEY_MGMT_FT_802_1X;
1822 case WLAN_CRYPTO_KEY_MGMT_FT_PSK:
1823 return RSN_AUTH_KEY_MGMT_FT_PSK;
1824 case WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256:
1825 return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
1826 case WLAN_CRYPTO_KEY_MGMT_PSK_SHA256:
1827 return RSN_AUTH_KEY_MGMT_PSK_SHA256;
1828 case WLAN_CRYPTO_KEY_MGMT_SAE:
1829 return RSN_AUTH_KEY_MGMT_SAE;
1830 case WLAN_CRYPTO_KEY_MGMT_FT_SAE:
1831 return RSN_AUTH_KEY_MGMT_FT_SAE;
1832 case WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B:
1833 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
1834 case WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192:
1835 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
1836 case WLAN_CRYPTO_KEY_MGMT_CCKM:
1837 return RSN_AUTH_KEY_MGMT_CCKM;
1838 case WLAN_CRYPTO_KEY_MGMT_OSEN:
1839 return RSN_AUTH_KEY_MGMT_OSEN;
1840 }
1841
1842 return status;
1843}
1844
1845/*
1846 * Convert an RSN key management/authentication algorithm
1847 * to an internal code.
1848 */
1849static int32_t
1850wlan_crypto_wpa_keymgmt_to_suite(uint32_t keymgmt)
1851{
1852 int32_t status = -1;
1853
1854 switch (keymgmt) {
1855 case WLAN_CRYPTO_KEY_MGMT_NONE:
1856 return WPA_AUTH_KEY_MGMT_NONE;
1857 case WLAN_CRYPTO_KEY_MGMT_IEEE8021X:
1858 return WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
1859 case WLAN_CRYPTO_KEY_MGMT_PSK:
1860 return WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;
1861 case WLAN_CRYPTO_KEY_MGMT_CCKM:
1862 return WPA_AUTH_KEY_MGMT_CCKM;
1863 }
1864
1865 return status;
1866}
1867/**
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301868 * Convert a WPA cipher selector OUI to an internal
1869 * cipher algorithm. Where appropriate we also
1870 * record any key length.
1871 */
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301872static int32_t wlan_crypto_wpa_suite_to_cipher(uint8_t *sel)
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301873{
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05301874 uint32_t w = LE_READ_4(sel);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301875 int32_t status = -1;
1876
1877 switch (w) {
1878 case WPA_CIPHER_SUITE_TKIP:
1879 return WLAN_CRYPTO_CIPHER_TKIP;
1880 case WPA_CIPHER_SUITE_CCMP:
1881 return WLAN_CRYPTO_CIPHER_AES_CCM;
1882 case WPA_CIPHER_SUITE_NONE:
1883 return WLAN_CRYPTO_CIPHER_NONE;
1884 }
1885
1886 return status;
1887}
1888
1889/*
1890 * Convert a WPA key management/authentication algorithm
1891 * to an internal code.
1892 */
1893static int32_t wlan_crypto_wpa_suite_to_keymgmt(uint8_t *sel)
1894{
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05301895 uint32_t w = LE_READ_4(sel);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301896 int32_t status = -1;
1897
1898 switch (w) {
1899 case WPA_AUTH_KEY_MGMT_UNSPEC_802_1X:
1900 return WLAN_CRYPTO_KEY_MGMT_IEEE8021X;
1901 case WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X:
1902 return WLAN_CRYPTO_KEY_MGMT_PSK;
1903 case WPA_AUTH_KEY_MGMT_CCKM:
1904 return WLAN_CRYPTO_KEY_MGMT_CCKM;
1905 case WPA_AUTH_KEY_MGMT_NONE:
1906 return WLAN_CRYPTO_KEY_MGMT_NONE;
1907 }
1908 return status;
1909}
1910
1911/*
1912 * Convert a RSN cipher selector OUI to an internal
1913 * cipher algorithm. Where appropriate we also
1914 * record any key length.
1915 */
1916static int32_t wlan_crypto_rsn_suite_to_cipher(uint8_t *sel)
1917{
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05301918 uint32_t w = LE_READ_4(sel);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301919 int32_t status = -1;
1920
1921 switch (w) {
1922 case RSN_CIPHER_SUITE_TKIP:
1923 return WLAN_CRYPTO_CIPHER_TKIP;
1924 case RSN_CIPHER_SUITE_CCMP:
1925 return WLAN_CRYPTO_CIPHER_AES_CCM;
1926 case RSN_CIPHER_SUITE_CCMP_256:
1927 return WLAN_CRYPTO_CIPHER_AES_CCM_256;
1928 case RSN_CIPHER_SUITE_GCMP:
1929 return WLAN_CRYPTO_CIPHER_AES_GCM;
1930 case RSN_CIPHER_SUITE_GCMP_256:
1931 return WLAN_CRYPTO_CIPHER_AES_GCM_256;
1932 case RSN_CIPHER_SUITE_AES_CMAC:
1933 return WLAN_CRYPTO_CIPHER_AES_CMAC;
1934 case RSN_CIPHER_SUITE_BIP_CMAC_256:
1935 return WLAN_CRYPTO_CIPHER_AES_CMAC_256;
1936 case RSN_CIPHER_SUITE_BIP_GMAC_128:
1937 return WLAN_CRYPTO_CIPHER_AES_GMAC;
1938 case RSN_CIPHER_SUITE_BIP_GMAC_256:
1939 return WLAN_CRYPTO_CIPHER_AES_GMAC_256;
1940 case RSN_CIPHER_SUITE_NONE:
1941 return WLAN_CRYPTO_CIPHER_NONE;
1942 }
1943
1944 return status;
1945}
1946/*
1947 * Convert an RSN key management/authentication algorithm
1948 * to an internal code.
1949 */
1950static int32_t wlan_crypto_rsn_suite_to_keymgmt(uint8_t *sel)
1951{
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05301952 uint32_t w = LE_READ_4(sel);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301953 int32_t status = -1;
1954
1955 switch (w) {
1956 case RSN_AUTH_KEY_MGMT_UNSPEC_802_1X:
1957 return WLAN_CRYPTO_KEY_MGMT_IEEE8021X;
1958 case RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X:
1959 return WLAN_CRYPTO_KEY_MGMT_PSK;
1960 case RSN_AUTH_KEY_MGMT_FT_802_1X:
1961 return WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X;
1962 case RSN_AUTH_KEY_MGMT_FT_PSK:
1963 return WLAN_CRYPTO_KEY_MGMT_FT_PSK;
1964 case RSN_AUTH_KEY_MGMT_802_1X_SHA256:
1965 return WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256;
1966 case RSN_AUTH_KEY_MGMT_PSK_SHA256:
1967 return WLAN_CRYPTO_KEY_MGMT_PSK_SHA256;
1968 case RSN_AUTH_KEY_MGMT_SAE:
1969 return WLAN_CRYPTO_KEY_MGMT_SAE;
1970 case RSN_AUTH_KEY_MGMT_FT_SAE:
1971 return WLAN_CRYPTO_KEY_MGMT_FT_SAE;
1972 case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B:
1973 return WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B;
1974 case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192:
1975 return WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192;
1976 case RSN_AUTH_KEY_MGMT_CCKM:
1977 return WLAN_CRYPTO_KEY_MGMT_CCKM;
1978 case RSN_AUTH_KEY_MGMT_OSEN:
1979 return WLAN_CRYPTO_KEY_MGMT_OSEN;
1980 }
1981
1982 return status;
1983}
1984
1985/**
1986 * wlan_crypto_wpaie_check - called by mlme to check the wpaie
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301987 * @crypto params: crypto params
1988 * @iebuf: ie buffer
1989 *
1990 * This function gets called by mlme to check the contents of wpa is
1991 * matching with given crypto params
1992 *
1993 * Return: QDF_STATUS_SUCCESS - in case of success
1994 */
1995QDF_STATUS wlan_crypto_wpaie_check(struct wlan_crypto_params *crypto_params,
1996 uint8_t *frm){
1997 uint8_t len = frm[1];
1998 int32_t w;
1999 int n;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302000
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302001 /*
2002 * Check the length once for fixed parts: OUI, type,
2003 * version, mcast cipher, and 2 selector counts.
2004 * Other, variable-length data, must be checked separately.
2005 */
2006 RESET_AUTHMODE(crypto_params);
2007 SET_AUTHMODE(crypto_params, WLAN_CRYPTO_AUTH_WPA);
2008
2009 if (len < 14)
2010 return QDF_STATUS_E_INVAL;
2011
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302012 frm += 6, len -= 4;
2013
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302014 w = LE_READ_2(frm);
2015 if (w != WPA_VERSION)
2016 return QDF_STATUS_E_INVAL;
2017
2018 frm += 2, len -= 2;
2019
2020 /* multicast/group cipher */
2021 RESET_MCAST_CIPHERS(crypto_params);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302022 w = wlan_crypto_wpa_suite_to_cipher(frm);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302023 if (w < 0)
2024 return QDF_STATUS_E_INVAL;
2025 SET_MCAST_CIPHER(crypto_params, w);
2026 frm += 4, len -= 4;
2027
2028 /* unicast ciphers */
2029 n = LE_READ_2(frm);
2030 frm += 2, len -= 2;
2031 if (len < n*4+2)
2032 return QDF_STATUS_E_INVAL;
2033
2034 RESET_UCAST_CIPHERS(crypto_params);
2035 for (; n > 0; n--) {
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302036 w = wlan_crypto_wpa_suite_to_cipher(frm);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302037 if (w < 0)
2038 return QDF_STATUS_E_INVAL;
2039 SET_UCAST_CIPHER(crypto_params, w);
2040 frm += 4, len -= 4;
2041 }
2042
2043 if (!crypto_params->ucastcipherset)
2044 return QDF_STATUS_E_INVAL;
2045
2046 /* key management algorithms */
2047 n = LE_READ_2(frm);
2048 frm += 2, len -= 2;
2049 if (len < n*4)
2050 return QDF_STATUS_E_INVAL;
2051
2052 w = 0;
2053 RESET_KEY_MGMT(crypto_params);
2054 for (; n > 0; n--) {
2055 w = wlan_crypto_wpa_suite_to_keymgmt(frm);
2056 if (w < 0)
2057 return QDF_STATUS_E_INVAL;
2058 SET_KEY_MGMT(crypto_params, w);
2059 frm += 4, len -= 4;
2060 }
2061
2062 /* optional capabilities */
2063 if (len >= 2) {
2064 crypto_params->rsn_caps = LE_READ_2(frm);
2065 frm += 2, len -= 2;
2066 }
2067
2068 return 0;
2069}
2070
2071/**
2072 * wlan_crypto_rsnie_check - called by mlme to check the rsnie
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302073 * @crypto params: crypto params
2074 * @iebuf: ie buffer
2075 *
2076 * This function gets called by mlme to check the contents of wpa is
2077 * matching with given crypto params
2078 *
2079 * Return: QDF_STATUS_SUCCESS - in case of success
2080 */
2081QDF_STATUS wlan_crypto_rsnie_check(struct wlan_crypto_params *crypto_params,
2082 uint8_t *frm){
2083 uint8_t len = frm[1];
2084 int32_t w;
2085 int n;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302086
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302087 /*
2088 * Check the length once for fixed parts: OUI, type,
2089 * version, mcast cipher, and 2 selector counts.
2090 * Other, variable-length data, must be checked separately.
2091 */
2092 RESET_AUTHMODE(crypto_params);
2093 SET_AUTHMODE(crypto_params, WLAN_CRYPTO_AUTH_RSNA);
2094
2095 if (len < 14)
2096 return QDF_STATUS_E_INVAL;
2097
Rohan Duttaf8ce8102018-01-18 10:17:47 +05302098 frm += 2;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302099 /* NB: iswapoui already validated the OUI and type */
2100 w = LE_READ_2(frm);
2101 if (w != RSN_VERSION)
2102 return QDF_STATUS_E_INVAL;
2103
2104 frm += 2, len -= 2;
2105
2106 /* multicast/group cipher */
2107 RESET_MCAST_CIPHERS(crypto_params);
2108 w = wlan_crypto_rsn_suite_to_cipher(frm);
2109 if (w < 0)
2110 return QDF_STATUS_E_INVAL;
2111 SET_MCAST_CIPHER(crypto_params, w);
2112 frm += 4, len -= 4;
2113
2114 /* unicast ciphers */
2115 n = LE_READ_2(frm);
2116 frm += 2, len -= 2;
2117 if (len < n*4+2)
2118 return QDF_STATUS_E_INVAL;
2119
2120 RESET_UCAST_CIPHERS(crypto_params);
2121 for (; n > 0; n--) {
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302122 w = wlan_crypto_rsn_suite_to_cipher(frm);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302123 if (w < 0)
2124 return QDF_STATUS_E_INVAL;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302125 SET_UCAST_CIPHER(crypto_params, w);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302126 frm += 4, len -= 4;
2127 }
2128
2129 if (crypto_params->ucastcipherset == 0)
2130 return QDF_STATUS_E_INVAL;
2131
2132 /* key management algorithms */
2133 n = LE_READ_2(frm);
2134 frm += 2, len -= 2;
2135 if (len < n*4)
2136 return QDF_STATUS_E_INVAL;
2137 w = 0;
2138
2139 RESET_KEY_MGMT(crypto_params);
2140 for (; n > 0; n--) {
2141 w = wlan_crypto_rsn_suite_to_keymgmt(frm);
2142 if (w < 0)
2143 return QDF_STATUS_E_INVAL;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302144 SET_KEY_MGMT(crypto_params, (1 << w));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302145 frm += 4, len -= 4;
2146 }
2147
2148 /* optional capabilities */
2149 if (len >= 2) {
2150 crypto_params->rsn_caps = LE_READ_2(frm);
2151 frm += 2, len -= 2;
2152 }
2153
2154 return QDF_STATUS_SUCCESS;
2155}
2156
2157/**
2158 * wlan_crypto_build_wpaie - called by mlme to build wpaie
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302159 * @vdev: vdev
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302160 * @iebuf: ie buffer
2161 *
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302162 * This function gets called by mlme to build wpaie from given vdev
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302163 *
2164 * Return: end of buffer
2165 */
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302166uint8_t *wlan_crypto_build_wpaie(struct wlan_objmgr_vdev *vdev,
2167 uint8_t *iebuf){
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302168 uint8_t *frm = iebuf;
2169 uint8_t *selcnt;
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302170 struct wlan_crypto_comp_priv *crypto_priv;
2171 struct wlan_crypto_params *crypto_params;
2172
2173 if (!frm)
2174 return NULL;
2175
2176 crypto_params = wlan_crypto_vdev_get_comp_params(vdev, &crypto_priv);
2177
2178 if (!crypto_params)
2179 return NULL;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302180
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302181 *frm++ = WLAN_ELEMID_VENDOR;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302182 *frm++ = 0;
2183 WLAN_CRYPTO_ADDSELECTOR(frm, WPA_TYPE_OUI);
2184 WLAN_CRYPTO_ADDSHORT(frm, WPA_VERSION);
2185
2186
2187 /* multicast cipher */
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302188 if (MCIPHER_IS_TKIP(crypto_params)) {
2189 WLAN_CRYPTO_ADDSELECTOR(frm,
2190 wlan_crypto_wpa_cipher_to_suite(
2191 WLAN_CRYPTO_CIPHER_TKIP));
2192 } else if (MCIPHER_IS_CCMP128(crypto_params)) {
2193 WLAN_CRYPTO_ADDSELECTOR(frm,
2194 wlan_crypto_wpa_cipher_to_suite(
2195 WLAN_CRYPTO_CIPHER_AES_CCM));
2196 }
Rohan Duttaa301c832017-11-30 20:29:26 +05302197 /* unicast cipher list */
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302198 selcnt = frm;
2199 WLAN_CRYPTO_ADDSHORT(frm, 0);
2200 /* do not use CCMP unicast cipher in WPA mode */
2201 if (UCIPHER_IS_TKIP(crypto_params)) {
2202 selcnt[0]++;
2203 WLAN_CRYPTO_ADDSELECTOR(frm,
2204 wlan_crypto_wpa_cipher_to_suite(
2205 WLAN_CRYPTO_CIPHER_TKIP));
2206 }
2207 if (UCIPHER_IS_CCMP128(crypto_params)) {
2208 selcnt[0]++;
2209 WLAN_CRYPTO_ADDSELECTOR(frm,
2210 wlan_crypto_wpa_cipher_to_suite(
2211 WLAN_CRYPTO_CIPHER_AES_CCM));
2212 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302213
2214 /* authenticator selector list */
2215 selcnt = frm;
2216 WLAN_CRYPTO_ADDSHORT(frm, 0);
2217
2218 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_IEEE8021X)) {
2219 selcnt[0]++;
2220 WLAN_CRYPTO_ADDSELECTOR(frm,
2221 wlan_crypto_wpa_keymgmt_to_suite(
2222 WLAN_CRYPTO_KEY_MGMT_IEEE8021X));
2223 } else if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_PSK)) {
2224 selcnt[0]++;
2225 WLAN_CRYPTO_ADDSELECTOR(frm,
2226 wlan_crypto_wpa_keymgmt_to_suite(
2227 WLAN_CRYPTO_KEY_MGMT_PSK));
2228 } else if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_CCKM)) {
2229 selcnt[0]++;
2230 WLAN_CRYPTO_ADDSELECTOR(frm,
2231 wlan_crypto_wpa_keymgmt_to_suite(
2232 WLAN_CRYPTO_KEY_MGMT_CCKM));
2233 } else {
2234 selcnt[0]++;
2235 WLAN_CRYPTO_ADDSELECTOR(frm,
2236 wlan_crypto_wpa_keymgmt_to_suite(
2237 WLAN_CRYPTO_KEY_MGMT_NONE));
2238 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302239 /* calculate element length */
2240 iebuf[1] = frm - iebuf - 2;
2241
2242 return frm;
2243}
2244
2245/**
2246 * wlan_crypto_build_rsnie - called by mlme to build rsnie
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302247 * @vdev: vdev
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302248 * @iebuf: ie buffer
2249 *
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302250 * This function gets called by mlme to build rsnie from given vdev
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302251 *
2252 * Return: end of buffer
2253 */
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302254uint8_t *wlan_crypto_build_rsnie(struct wlan_objmgr_vdev *vdev,
2255 uint8_t *iebuf){
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302256 uint8_t *frm = iebuf;
2257 uint8_t *selcnt;
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302258 struct wlan_crypto_comp_priv *crypto_priv;
2259 struct wlan_crypto_params *crypto_params;
2260
2261 if (!frm) {
2262 return NULL;
2263 }
2264
2265 crypto_params = wlan_crypto_vdev_get_comp_params(vdev, &crypto_priv);
2266
2267 if (!crypto_params) {
2268 return NULL;
2269 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302270
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302271 *frm++ = WLAN_ELEMID_RSN;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302272 *frm++ = 0;
2273 WLAN_CRYPTO_ADDSHORT(frm, RSN_VERSION);
2274
2275
2276 /* multicast cipher */
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302277 if (MCIPHER_IS_TKIP(crypto_params)) {
2278 WLAN_CRYPTO_ADDSELECTOR(frm,
2279 wlan_crypto_rsn_cipher_to_suite(
2280 WLAN_CRYPTO_CIPHER_TKIP));
2281 } else if (MCIPHER_IS_CCMP128(crypto_params)) {
2282 WLAN_CRYPTO_ADDSELECTOR(frm,
2283 wlan_crypto_rsn_cipher_to_suite(
2284 WLAN_CRYPTO_CIPHER_AES_CCM));
2285 } else if (MCIPHER_IS_CCMP256(crypto_params)) {
2286 WLAN_CRYPTO_ADDSELECTOR(frm,
2287 wlan_crypto_rsn_cipher_to_suite(
2288 WLAN_CRYPTO_CIPHER_AES_CCM_256));
2289 } else if (MCIPHER_IS_GCMP128(crypto_params)) {
2290 WLAN_CRYPTO_ADDSELECTOR(frm,
2291 wlan_crypto_rsn_cipher_to_suite(
2292 WLAN_CRYPTO_CIPHER_AES_GCM));
2293 } else if (MCIPHER_IS_GCMP256(crypto_params)) {
2294 WLAN_CRYPTO_ADDSELECTOR(frm,
2295 wlan_crypto_rsn_cipher_to_suite(
2296 WLAN_CRYPTO_CIPHER_AES_GCM_256));
2297 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302298
2299 /* unicast cipher list */
2300 selcnt = frm;
2301 WLAN_CRYPTO_ADDSHORT(frm, 0);
2302 /* do not use CCMP unicast cipher in WPA mode */
2303 if (UCIPHER_IS_TKIP(crypto_params)) {
2304 selcnt[0]++;
2305 WLAN_CRYPTO_ADDSELECTOR(frm,
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302306 wlan_crypto_rsn_cipher_to_suite(
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302307 WLAN_CRYPTO_CIPHER_TKIP));
2308 }
2309 if (UCIPHER_IS_CCMP128(crypto_params)) {
2310 selcnt[0]++;
2311 WLAN_CRYPTO_ADDSELECTOR(frm,
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302312 wlan_crypto_rsn_cipher_to_suite(
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302313 WLAN_CRYPTO_CIPHER_AES_CCM));
2314 }
2315 if (UCIPHER_IS_CCMP256(crypto_params)) {
2316 selcnt[0]++;
2317 WLAN_CRYPTO_ADDSELECTOR(frm,
2318 wlan_crypto_rsn_cipher_to_suite(
2319 WLAN_CRYPTO_CIPHER_AES_CCM_256));
2320 }
2321
2322 if (UCIPHER_IS_GCMP128(crypto_params)) {
2323 selcnt[0]++;
2324 WLAN_CRYPTO_ADDSELECTOR(frm,
2325 wlan_crypto_rsn_cipher_to_suite(
2326 WLAN_CRYPTO_CIPHER_AES_GCM));
2327 }
2328 if (UCIPHER_IS_GCMP256(crypto_params)) {
2329 selcnt[0]++;
2330 WLAN_CRYPTO_ADDSELECTOR(frm,
2331 wlan_crypto_rsn_cipher_to_suite(
2332 WLAN_CRYPTO_CIPHER_AES_GCM_256));
2333 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302334
2335
2336 /* authenticator selector list */
2337 selcnt = frm;
2338 WLAN_CRYPTO_ADDSHORT(frm, 0);
2339 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_CCKM)) {
2340 selcnt[0]++;
2341 WLAN_CRYPTO_ADDSELECTOR(frm,
2342 wlan_crypto_rsn_keymgmt_to_suite(
2343 WLAN_CRYPTO_KEY_MGMT_CCKM));
2344 } else {
2345 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_PSK)) {
2346 selcnt[0]++;
2347 WLAN_CRYPTO_ADDSELECTOR(frm,
2348 wlan_crypto_rsn_keymgmt_to_suite(
2349 WLAN_CRYPTO_KEY_MGMT_PSK));
2350 }
2351 if (HAS_KEY_MGMT(crypto_params,
2352 WLAN_CRYPTO_KEY_MGMT_IEEE8021X)) {
2353 selcnt[0]++;
2354 WLAN_CRYPTO_ADDSELECTOR(frm,
2355 wlan_crypto_rsn_keymgmt_to_suite(
2356 WLAN_CRYPTO_KEY_MGMT_IEEE8021X));
2357 }
2358 if (HAS_KEY_MGMT(crypto_params,
2359 WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X)) {
2360 selcnt[0]++;
2361 WLAN_CRYPTO_ADDSELECTOR(frm,
2362 wlan_crypto_rsn_keymgmt_to_suite(
2363 WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X));
2364 }
2365 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_FT_PSK)) {
2366 selcnt[0]++;
2367 WLAN_CRYPTO_ADDSELECTOR(frm,
2368 wlan_crypto_rsn_keymgmt_to_suite(
2369 WLAN_CRYPTO_KEY_MGMT_FT_PSK));
2370 }
2371 if (HAS_KEY_MGMT(crypto_params,
2372 WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256)) {
2373 selcnt[0]++;
2374 WLAN_CRYPTO_ADDSELECTOR(frm,
2375 wlan_crypto_rsn_keymgmt_to_suite(
2376 WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256));
2377 }
2378 if (HAS_KEY_MGMT(crypto_params,
2379 WLAN_CRYPTO_KEY_MGMT_PSK_SHA256)) {
2380 selcnt[0]++;
2381 WLAN_CRYPTO_ADDSELECTOR(frm,
2382 wlan_crypto_rsn_keymgmt_to_suite(
2383 WLAN_CRYPTO_KEY_MGMT_PSK_SHA256));
2384 }
2385 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_OSEN)) {
2386 selcnt[0]++;
2387 WLAN_CRYPTO_ADDSELECTOR(frm,
2388 wlan_crypto_rsn_keymgmt_to_suite(
2389 WLAN_CRYPTO_KEY_MGMT_OSEN));
2390 }
2391 }
2392
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302393 WLAN_CRYPTO_ADDSHORT(frm, crypto_params->rsn_caps);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302394 /* optional capabilities */
2395 if (crypto_params->rsn_caps != 0 &&
2396 crypto_params->rsn_caps != WLAN_CRYPTO_RSN_CAP_PREAUTH){
2397
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302398 if (HAS_MGMT_CIPHER(crypto_params,
2399 WLAN_CRYPTO_CIPHER_AES_CMAC)) {
2400 selcnt[0]++;
2401 WLAN_CRYPTO_ADDSELECTOR(frm,
2402 wlan_crypto_rsn_cipher_to_suite(
2403 WLAN_CRYPTO_CIPHER_AES_CMAC));
2404 }
2405 if (HAS_MGMT_CIPHER(crypto_params,
2406 WLAN_CRYPTO_CIPHER_AES_GMAC)) {
2407 selcnt[0]++;
2408 WLAN_CRYPTO_ADDSELECTOR(frm,
2409 wlan_crypto_rsn_cipher_to_suite(
2410 WLAN_CRYPTO_CIPHER_AES_GMAC));
2411 }
2412 if (HAS_MGMT_CIPHER(crypto_params,
2413 WLAN_CRYPTO_CIPHER_AES_CMAC_256)) {
2414 selcnt[0]++;
2415 WLAN_CRYPTO_ADDSELECTOR(frm,
2416 wlan_crypto_rsn_cipher_to_suite(
2417 WLAN_CRYPTO_CIPHER_AES_CMAC_256));
2418 }
2419
2420 if (HAS_MGMT_CIPHER(crypto_params,
2421 WLAN_CRYPTO_CIPHER_AES_GMAC_256)) {
2422 selcnt[0]++;
2423 WLAN_CRYPTO_ADDSELECTOR(frm,
2424 wlan_crypto_rsn_cipher_to_suite(
2425 WLAN_CRYPTO_CIPHER_AES_GMAC_256));
2426 }
2427 }
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302428
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302429 /* calculate element length */
2430 iebuf[1] = frm - iebuf - 2;
2431
2432 return frm;
2433}
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05302434
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302435bool wlan_crypto_rsn_info(struct wlan_objmgr_vdev *vdev,
2436 struct wlan_crypto_params *crypto_params){
2437 struct wlan_crypto_params *my_crypto_params;
2438 my_crypto_params = wlan_crypto_vdev_get_crypto_params(vdev);
2439
Disha Das76210cd2018-04-10 12:44:14 +05302440 if (!my_crypto_params)
2441 return false;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302442 /*
2443 * Check peer's pairwise ciphers.
2444 * At least one must match with our unicast cipher
2445 */
2446 if (!UCAST_CIPHER_MATCH(crypto_params, my_crypto_params))
2447 return false;
2448 /*
2449 * Check peer's group cipher is our enabled multicast cipher.
2450 */
2451 if (!MCAST_CIPHER_MATCH(crypto_params, my_crypto_params))
2452 return false;
2453 /*
2454 * Check peer's key management class set (PSK or UNSPEC)
2455 */
2456 if (!KEY_MGMTSET_MATCH(crypto_params, my_crypto_params))
2457 return false;
2458
2459 return true;
2460}
2461
Ashok Ponnaiah26e6be42017-07-14 18:13:23 +05302462/*
2463 * Convert an WAPI CIPHER suite to to an internal code.
2464 */
2465static int32_t wlan_crypto_wapi_suite_to_cipher(uint8_t *sel)
2466{
2467 uint32_t w = LE_READ_4(sel);
2468 int32_t status = -1;
2469
2470 switch (w) {
2471 case (WLAN_WAPI_SEL(WLAN_CRYPTO_WAPI_SMS4_CIPHER)):
2472 return WLAN_CRYPTO_CIPHER_WAPI_SMS4;
2473 }
2474
2475 return status;
2476}
2477
2478/*
2479 * Convert an WAPI key management/authentication algorithm
2480 * to an internal code.
2481 */
2482static int32_t wlan_crypto_wapi_keymgmt(u_int8_t *sel)
2483{
2484 uint32_t w = LE_READ_4(sel);
2485 int32_t status = -1;
2486
2487 switch (w) {
2488 case (WLAN_WAPI_SEL(WLAN_WAI_PSK)):
2489 return WLAN_CRYPTO_KEY_MGMT_WAPI_PSK;
2490 case (WLAN_WAPI_SEL(WLAN_WAI_CERT_OR_SMS4)):
2491 return WLAN_CRYPTO_KEY_MGMT_WAPI_CERT;
2492 }
2493
2494 return status;
2495}
2496/**
2497 * wlan_crypto_wapiie_check - called by mlme to check the wapiie
Ashok Ponnaiah26e6be42017-07-14 18:13:23 +05302498 * @crypto params: crypto params
2499 * @iebuf: ie buffer
2500 *
2501 * This function gets called by mlme to check the contents of wapi is
2502 * matching with given crypto params
2503 *
2504 * Return: QDF_STATUS_SUCCESS - in case of success
2505 */
2506QDF_STATUS wlan_crypto_wapiie_check(struct wlan_crypto_params *crypto_params,
2507 uint8_t *frm)
2508{
2509 uint8_t len = frm[1];
2510 int32_t w;
2511 int n;
2512
2513 /*
2514 * Check the length once for fixed parts: OUI, type,
2515 * version, mcast cipher, and 2 selector counts.
2516 * Other, variable-length data, must be checked separately.
2517 */
2518 RESET_AUTHMODE(crypto_params);
2519 SET_AUTHMODE(crypto_params, WLAN_CRYPTO_AUTH_WAPI);
2520
2521 if (len < WLAN_CRYPTO_WAPI_IE_LEN)
2522 return QDF_STATUS_E_INVAL;
2523
2524
2525 frm += 2;
2526
2527 w = LE_READ_2(frm);
2528 frm += 2, len -= 2;
2529 if (w != WAPI_VERSION)
2530 return QDF_STATUS_E_INVAL;
2531
2532 n = LE_READ_2(frm);
2533 frm += 2, len -= 2;
2534 if (len < n*4+2)
2535 return QDF_STATUS_E_INVAL;
2536
2537 RESET_KEY_MGMT(crypto_params);
2538 for (; n > 0; n--) {
2539 w = wlan_crypto_wapi_keymgmt(frm);
2540 if (w < 0)
2541 return QDF_STATUS_E_INVAL;
2542
2543 SET_KEY_MGMT(crypto_params, w);
2544 frm += 4, len -= 4;
2545 }
2546
2547 /* unicast ciphers */
2548 n = LE_READ_2(frm);
2549 frm += 2, len -= 2;
2550 if (len < n*4+2)
2551 return QDF_STATUS_E_INVAL;
2552
2553 RESET_UCAST_CIPHERS(crypto_params);
2554 for (; n > 0; n--) {
2555 w = wlan_crypto_wapi_suite_to_cipher(frm);
2556 if (w < 0)
2557 return QDF_STATUS_E_INVAL;
2558 SET_UCAST_CIPHER(crypto_params, w);
2559 frm += 4, len -= 4;
2560 }
2561
2562 if (!crypto_params->ucastcipherset)
2563 return QDF_STATUS_E_INVAL;
2564
2565 /* multicast/group cipher */
2566 RESET_MCAST_CIPHERS(crypto_params);
2567 w = wlan_crypto_wapi_suite_to_cipher(frm);
2568
2569 if (w < 0)
2570 return QDF_STATUS_E_INVAL;
2571
2572 SET_MCAST_CIPHER(crypto_params, w);
2573 frm += 4, len -= 4;
2574
2575 return QDF_STATUS_SUCCESS;
2576}
2577
2578/**
2579 * wlan_crypto_build_wapiie - called by mlme to build wapi ie
Ashok Ponnaiah26e6be42017-07-14 18:13:23 +05302580 * @vdev: vdev
2581 * @iebuf: ie buffer
2582 *
2583 * This function gets called by mlme to build wapi ie from given vdev
2584 *
2585 * Return: end of buffer
2586 */
2587uint8_t *wlan_crypto_build_wapiie(struct wlan_objmgr_vdev *vdev,
2588 uint8_t *iebuf)
2589{
2590 uint8_t *frm;
2591 uint8_t *selcnt;
2592 struct wlan_crypto_comp_priv *crypto_priv;
2593 struct wlan_crypto_params *crypto_params;
2594
2595 frm = iebuf;
2596 if (!frm) {
2597 qdf_print("%s[%d] ie buffer NULL\n", __func__, __LINE__);
2598 return NULL;
2599 }
2600
2601 crypto_params = wlan_crypto_vdev_get_comp_params(vdev, &crypto_priv);
2602
2603 if (!crypto_params) {
2604 qdf_print("%s[%d] crypto_params NULL\n", __func__, __LINE__);
2605 return NULL;
2606 }
2607
2608 *frm++ = WLAN_ELEMID_WAPI;
2609 *frm++ = 0;
2610
2611 WLAN_CRYPTO_ADDSHORT(frm, WAPI_VERSION);
2612
2613 /* authenticator selector list */
2614 selcnt = frm;
2615 WLAN_CRYPTO_ADDSHORT(frm, 0);
2616
2617 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK)) {
2618 selcnt[0]++;
2619 WLAN_CRYPTO_ADDSELECTOR(frm,
2620 WLAN_WAPI_SEL(WLAN_WAI_PSK));
2621 }
2622
2623 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT)) {
2624 selcnt[0]++;
2625 WLAN_CRYPTO_ADDSELECTOR(frm,
2626 WLAN_WAPI_SEL(WLAN_WAI_CERT_OR_SMS4));
2627 }
2628
2629 /* unicast cipher list */
2630 selcnt = frm;
2631 WLAN_CRYPTO_ADDSHORT(frm, 0);
2632
2633 if (UCIPHER_IS_SMS4(crypto_params)) {
2634 selcnt[0]++;
2635 WLAN_CRYPTO_ADDSELECTOR(frm,
2636 WLAN_WAPI_SEL(WLAN_CRYPTO_WAPI_SMS4_CIPHER));
2637 }
2638
2639 WLAN_CRYPTO_ADDSELECTOR(frm,
2640 WLAN_WAPI_SEL(WLAN_CRYPTO_WAPI_SMS4_CIPHER));
2641
2642 /* optional capabilities */
2643 WLAN_CRYPTO_ADDSHORT(frm, crypto_params->rsn_caps);
2644
2645 /* calculate element length */
2646 iebuf[1] = frm - iebuf - 2;
2647
2648 return frm;
2649
2650}
2651
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302652/**
2653 * wlan_crypto_pn_check - called by data patch for PN check
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302654 * @vdev: vdev
2655 * @wbuf: wbuf
2656 *
2657 * This function gets called by data patch for PN check
2658 *
2659 * Return: QDF_STATUS
2660 */
2661QDF_STATUS wlan_crypto_pn_check(struct wlan_objmgr_vdev *vdev,
2662 qdf_nbuf_t wbuf){
2663 /* Need to check is there real requirement for this function
2664 * as PN check is already handled in decap function.
2665 */
2666 return QDF_STATUS_SUCCESS;
2667}
2668
2669/**
2670 * wlan_crypto_vdev_get_crypto_params - called by mlme to get crypto params
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302671 * @vdev:vdev
2672 *
2673 * This function gets called by mlme to get crypto params
2674 *
2675 * Return: wlan_crypto_params or NULL in case of failure
2676 */
2677struct wlan_crypto_params *wlan_crypto_vdev_get_crypto_params(
2678 struct wlan_objmgr_vdev *vdev){
2679 struct wlan_crypto_comp_priv *crypto_priv;
2680
2681 return wlan_crypto_vdev_get_comp_params(vdev, &crypto_priv);
2682}
2683
2684/**
2685 * wlan_crypto_peer_get_crypto_params - called by mlme to get crypto params
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302686 * @peer:peer
2687 *
2688 * This function gets called by mlme to get crypto params
2689 *
2690 * Return: wlan_crypto_params or NULL in case of failure
2691 */
2692struct wlan_crypto_params *wlan_crypto_peer_get_crypto_params(
2693 struct wlan_objmgr_peer *peer){
2694 struct wlan_crypto_comp_priv *crypto_priv;
2695
2696 return wlan_crypto_peer_get_comp_params(peer, &crypto_priv);
2697}
2698
2699
2700QDF_STATUS wlan_crypto_set_peer_wep_keys(struct wlan_objmgr_vdev *vdev,
Srinivas Pitlaea71ebf2018-01-04 17:07:42 +05302701 struct wlan_objmgr_peer *peer)
2702{
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302703 struct wlan_crypto_comp_priv *crypto_priv;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302704 struct wlan_crypto_comp_priv *sta_crypto_priv;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302705 struct wlan_crypto_params *crypto_params;
2706 struct wlan_crypto_key *key;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302707 struct wlan_crypto_key *sta_key;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302708 struct wlan_crypto_cipher *cipher_table;
2709 struct wlan_objmgr_psoc *psoc;
Srinivas Pitlaea71ebf2018-01-04 17:07:42 +05302710 uint8_t *mac_addr;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302711 int i;
Jeff Johnsona4262322017-11-09 09:54:12 -08002712 enum QDF_OPMODE opmode;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302713
2714 if (!vdev)
2715 return QDF_STATUS_E_NULL_VALUE;
Srinivas Pitlaea71ebf2018-01-04 17:07:42 +05302716
2717 if (!peer) {
2718 qdf_print("%s[%d] peer NULL\n", __func__, __LINE__);
2719 return QDF_STATUS_E_INVAL;
2720 }
2721
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302722 opmode = wlan_vdev_mlme_get_opmode(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302723 psoc = wlan_vdev_get_psoc(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302724
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302725 if (!psoc) {
2726 qdf_print("%s[%d] psoc NULL\n", __func__, __LINE__);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302727 return QDF_STATUS_E_NULL_VALUE;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302728 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302729
Srinivas Pitlaea71ebf2018-01-04 17:07:42 +05302730 wlan_peer_obj_lock(peer);
2731 mac_addr = wlan_peer_get_macaddr(peer);
2732 wlan_peer_obj_unlock(peer);
2733
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302734 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
2735 &crypto_priv);
2736 if (crypto_priv == NULL) {
2737 qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__);
2738 return QDF_STATUS_E_NULL_VALUE;
2739 }
2740
2741 /* push only valid static WEP keys from vap */
2742 if (AUTH_IS_8021X(crypto_params))
2743 return QDF_STATUS_E_INVAL;
2744
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302745 if (opmode == QDF_STA_MODE) {
2746 peer = wlan_vdev_get_bsspeer(vdev);
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302747 if (!peer) {
2748 qdf_print("%s[%d] peer NULL\n", __func__, __LINE__);
2749 return QDF_STATUS_E_INVAL;
2750 }
2751 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302752
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302753 wlan_crypto_peer_get_comp_params(peer, &sta_crypto_priv);
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302754 if (sta_crypto_priv == NULL) {
2755 qdf_print("%s[%d] sta priv is null\n", __func__, __LINE__);
2756 return QDF_STATUS_E_INVAL;
2757 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302758
2759 for (i = 0; i < WLAN_CRYPTO_MAXKEYIDX; i++) {
2760 if (crypto_priv->key[i]) {
2761 key = crypto_priv->key[i];
2762 if (!key || !key->valid)
2763 continue;
2764
2765 cipher_table = (struct wlan_crypto_cipher *)
2766 key->cipher_table;
2767
2768 if (cipher_table->cipher == WLAN_CRYPTO_CIPHER_WEP) {
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302769 sta_key = qdf_mem_malloc(
2770 sizeof(struct wlan_crypto_key));
2771 if (!sta_key) {
2772 qdf_print("%s[%d] key alloc failed\n",
2773 __func__, __LINE__);
2774 return QDF_STATUS_E_NOMEM;
2775 }
2776 sta_crypto_priv->key[i] = sta_key;
2777 qdf_mem_copy(sta_key, key,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302778 sizeof(struct wlan_crypto_key));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302779
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302780 sta_key->flags &= ~WLAN_CRYPTO_KEY_DEFAULT;
Ashok Ponnaiah4db9b8f2017-07-05 16:09:29 +05302781
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302782 if (crypto_priv->def_tx_keyid == i) {
2783 sta_key->flags
2784 |= WLAN_CRYPTO_KEY_DEFAULT;
2785 sta_crypto_priv->def_tx_keyid =
2786 crypto_priv->def_tx_keyid;
2787 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302788 /* setting the broadcast/multicast key for sta*/
2789 if (opmode == QDF_STA_MODE ||
2790 opmode == QDF_IBSS_MODE){
2791 if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
2792 WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302793 vdev, sta_key, mac_addr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302794 cipher_table->cipher);
2795 }
2796 }
2797
2798 /* setting unicast key */
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302799 sta_key->flags &= ~WLAN_CRYPTO_KEY_GROUP;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302800 if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
2801 WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(vdev,
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05302802 sta_key, mac_addr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302803 cipher_table->cipher);
2804 }
2805 }
2806 }
2807 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302808
2809 return QDF_STATUS_SUCCESS;
2810}
2811
2812/**
2813 * wlan_crypto_register_crypto_rx_ops - set crypto_rx_ops
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302814 * @crypto_rx_ops: crypto_rx_ops
2815 *
2816 * This function gets called by object manger to register crypto rx ops.
2817 *
2818 * Return: QDF_STATUS
2819 */
2820QDF_STATUS wlan_crypto_register_crypto_rx_ops(
2821 struct wlan_lmac_if_crypto_rx_ops *crypto_rx_ops){
2822 crypto_rx_ops->crypto_encap = wlan_crypto_encap;
2823 crypto_rx_ops->crypto_decap = wlan_crypto_decap;
2824 crypto_rx_ops->crypto_enmic = wlan_crypto_enmic;
2825 crypto_rx_ops->crypto_demic = wlan_crypto_demic;
2826 crypto_rx_ops->set_peer_wep_keys = wlan_crypto_set_peer_wep_keys;
2827
2828 return QDF_STATUS_SUCCESS;
2829}
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302830
2831/**
2832 * wlan_crypto_get_crypto_rx_ops - get crypto_rx_ops from psoc
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302833 * @psoc: psoc
2834 *
2835 * This function gets called by umac to get the crypto_rx_ops
2836 *
2837 * Return: crypto_rx_ops
2838 */
2839struct wlan_lmac_if_crypto_rx_ops *wlan_crypto_get_crypto_rx_ops(
2840 struct wlan_objmgr_psoc *psoc)
2841{
2842
2843 return &(psoc->soc_cb.rx_ops.crypto_rx_ops);
2844}
Manikandan Mohana2993a52018-03-01 16:21:55 -08002845qdf_export_symbol(wlan_crypto_get_crypto_rx_ops);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05302846
2847/**
2848 * wlan_crypto_vdev_has_auth_mode - check authmode for vdev
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05302849 * @vdev: vdev
2850 * @authvalue: authvalue to be checked
2851 *
2852 * This function check is authvalue passed is set in vdev or not
2853 *
2854 * Return: true or false
2855 */
2856bool wlan_crypto_vdev_has_auth_mode(struct wlan_objmgr_vdev *vdev,
2857 wlan_crypto_auth_mode authvalue)
2858{
2859 return wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_AUTH_MODE)
2860 & authvalue;
2861}
Ashok Ponnaiah455eb682018-03-19 10:33:22 +05302862qdf_export_symbol(wlan_crypto_vdev_has_auth_mode);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05302863
2864/**
2865 * wlan_crypto_peer_has_auth_mode - check authmode for peer
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05302866 * @peer: peer
2867 * @authvalue: authvalue to be checked
2868 *
2869 * This function check is authvalue passed is set in peer or not
2870 *
2871 * Return: true or false
2872 */
2873bool wlan_crypto_peer_has_auth_mode(struct wlan_objmgr_peer *peer,
2874 wlan_crypto_auth_mode authvalue)
2875{
2876 return wlan_crypto_get_peer_param(peer, WLAN_CRYPTO_PARAM_AUTH_MODE)
2877 & authvalue;
2878}
Ashok Ponnaiah455eb682018-03-19 10:33:22 +05302879qdf_export_symbol(wlan_crypto_peer_has_auth_mode);
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05302880
Ashok Ponnaiahafb88932018-04-17 10:15:24 +05302881/**
2882 * wlan_crypto_vdev_has_ucastcipher - check ucastcipher for vdev
2883 * @vdev: vdev
2884 * @ucastcipher: ucastcipher to be checked
2885 *
2886 * This function check is ucastcipher passed is set in vdev or not
2887 *
2888 * Return: true or false
2889 */
2890bool wlan_crypto_vdev_has_ucastcipher(struct wlan_objmgr_vdev *vdev,
2891 wlan_crypto_cipher_type ucastcipher)
2892{
2893 return wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER)
2894 & ucastcipher;
2895}
2896qdf_export_symbol(wlan_crypto_vdev_has_ucastcipher);
2897
2898/**
2899 * wlan_crypto_peer_has_ucastcipher - check ucastcipher for peer
2900 * @peer: peer
2901 * @ucastcipher: ucastcipher to be checked
2902 *
2903 * This function check is ucastcipher passed is set in peer or not
2904 *
2905 * Return: true or false
2906 */
2907bool wlan_crypto_peer_has_ucastcipher(struct wlan_objmgr_peer *peer,
2908 wlan_crypto_cipher_type ucastcipher)
2909{
2910 return wlan_crypto_get_peer_param(peer, WLAN_CRYPTO_PARAM_UCAST_CIPHER)
2911 & ucastcipher;
2912}
2913qdf_export_symbol(wlan_crypto_peer_has_ucastcipher);
2914
2915/**
2916 * wlan_crypto_vdev_has_mcastcipher - check mcastcipher for vdev
2917 * @vdev: vdev
2918 * @mcastcipher: mcastcipher to be checked
2919 *
2920 * This function check is mcastcipher passed is set in vdev or not
2921 *
2922 * Return: true or false
2923 */
2924bool wlan_crypto_vdev_has_mcastcipher(struct wlan_objmgr_vdev *vdev,
2925 wlan_crypto_cipher_type mcastcipher)
2926{
2927 return wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MCAST_CIPHER)
2928 & mcastcipher;
2929}
2930qdf_export_symbol(wlan_crypto_vdev_has_mcastcipher);
2931
2932/**
2933 * wlan_crypto_peer_has_mcastcipher - check mcastcipher for peer
2934 * @peer: peer
2935 * @mcastcipher: mcastcipher to be checked
2936 *
2937 * This function check is mcastcipher passed is set in peer or not
2938 *
2939 * Return: true or false
2940 */
2941bool wlan_crypto_peer_has_mcastcipher(struct wlan_objmgr_peer *peer,
2942 wlan_crypto_cipher_type mcastcipher)
2943{
2944 return wlan_crypto_get_peer_param(peer, WLAN_CRYPTO_PARAM_UCAST_CIPHER)
2945 & mcastcipher;
2946}
2947qdf_export_symbol(wlan_crypto_peer_has_mcastcipher);
2948
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05302949uint8_t wlan_crypto_get_peer_fils_aead(struct wlan_objmgr_peer *peer)
2950{
2951 struct wlan_crypto_comp_priv *crypto_priv = NULL;
2952
2953 if (!peer) {
2954 qdf_print(FL("Invalid Input\n"));
2955 return 0;
2956 }
2957
2958 crypto_priv = wlan_get_peer_crypto_obj(peer);
2959 if (!crypto_priv) {
2960 qdf_print(FL("crypto_priv NULL\n"));
2961 return 0;
2962 }
2963
2964 return crypto_priv->fils_aead_set;
2965}
2966
2967void
2968wlan_crypto_set_peer_fils_aead(struct wlan_objmgr_peer *peer, uint8_t value)
2969{
2970 struct wlan_crypto_comp_priv *crypto_priv = NULL;
2971
2972 if (!peer) {
2973 qdf_print(FL("Invalid Input\n"));
2974 return;
2975 }
2976
2977 crypto_priv = wlan_get_peer_crypto_obj(peer);
2978 if (!crypto_priv) {
2979 qdf_print(FL("crypto_priv NULL\n"));
2980 return;
2981 }
2982
2983 crypto_priv->fils_aead_set = value;
2984}