blob: 03d7ed98f8422ecd1332f5c9d14fac19702706c8 [file] [log] [blame]
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301/*
Kiran Kumar Lokere25531c42018-09-19 13:48:48 -07002 * Copyright (c) 2017-2019 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 */
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -070022
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053023#include <qdf_types.h>
24#include <wlan_cmn.h>
25#include <wlan_objmgr_cmn.h>
26#include <wlan_objmgr_global_obj.h>
27#include <wlan_objmgr_psoc_obj.h>
28#include <wlan_objmgr_pdev_obj.h>
29#include <wlan_objmgr_vdev_obj.h>
30#include <wlan_objmgr_peer_obj.h>
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -070031#include <wlan_utility.h>
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053032
33#include "wlan_crypto_global_def.h"
34#include "wlan_crypto_global_api.h"
35#include "wlan_crypto_def_i.h"
36#include "wlan_crypto_param_handling_i.h"
37#include "wlan_crypto_obj_mgr_i.h"
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +053038#include <qdf_module.h>
39
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053040const struct wlan_crypto_cipher *wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_MAX];
41
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +053042#define WPA_ADD_CIPHER_TO_SUITE(frm, cipher) \
43 WLAN_CRYPTO_ADDSELECTOR(frm,\
44 wlan_crypto_wpa_cipher_to_suite(cipher))
45
46#define RSN_ADD_CIPHER_TO_SUITE(frm, cipher) \
47 WLAN_CRYPTO_ADDSELECTOR(frm,\
48 wlan_crypto_rsn_cipher_to_suite(cipher))
49
Ashok Kumar Ponnaiah6e0a63c2018-08-24 10:16:05 +053050#define WPA_ADD_KEYMGMT_TO_SUITE(frm, keymgmt)\
51 WLAN_CRYPTO_ADDSELECTOR(frm,\
52 wlan_crypto_wpa_keymgmt_to_suite(keymgmt))
53
54#define RSN_ADD_KEYMGMT_TO_SUITE(frm, keymgmt)\
55 WLAN_CRYPTO_ADDSELECTOR(frm,\
56 wlan_crypto_rsn_keymgmt_to_suite(keymgmt))
57
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053058/**
59 * wlan_crypto_vdev_get_crypto_params - called by mlme to get crypto params
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053060 * @vdev:vdev
61 *
62 * This function gets called by mlme to get crypto params
63 *
64 * Return: wlan_crypto_params or NULL in case of failure
65 */
66static struct wlan_crypto_params *wlan_crypto_vdev_get_comp_params(
67 struct wlan_objmgr_vdev *vdev,
68 struct wlan_crypto_comp_priv **crypto_priv){
69 *crypto_priv = (struct wlan_crypto_comp_priv *)
70 wlan_get_vdev_crypto_obj(vdev);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -070071 if (!(*crypto_priv)) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +053072 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053073 return NULL;
74 }
75
76 return &((*crypto_priv)->crypto_params);
77}
78
79/**
80 * wlan_crypto_peer_get_crypto_params - called by mlme to get crypto params
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053081 * @peer:peer
82 *
83 * This function gets called by mlme to get crypto params
84 *
85 * Return: wlan_crypto_params or NULL in case of failure
86 */
87static struct wlan_crypto_params *wlan_crypto_peer_get_comp_params(
88 struct wlan_objmgr_peer *peer,
89 struct wlan_crypto_comp_priv **crypto_priv){
90
91 *crypto_priv = (struct wlan_crypto_comp_priv *)
92 wlan_get_peer_crypto_obj(peer);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -070093 if (!*crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +053094 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +053095 return NULL;
96 }
97
98 return &((*crypto_priv)->crypto_params);
99}
100
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530101static QDF_STATUS wlan_crypto_set_igtk_key(struct wlan_crypto_key *key)
102{
103 return QDF_STATUS_SUCCESS;
104}
Disha Das6419ff12018-02-02 10:21:55 +0530105
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530106/**
107 * wlan_crypto_set_param - called by ucfg to set crypto param
Disha Das6419ff12018-02-02 10:21:55 +0530108 * @crypto_params: crypto_params
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530109 * @param: param to be set.
110 * @value: value
111 *
112 * This function gets called from ucfg to set param
113 *
114 * Return: QDF_STATUS_SUCCESS - in case of success
115 */
Disha Das6419ff12018-02-02 10:21:55 +0530116static QDF_STATUS wlan_crypto_set_param(struct wlan_crypto_params *crypto_params,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530117 wlan_crypto_param_type param,
118 uint32_t value){
119 QDF_STATUS status = QDF_STATUS_E_INVAL;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530120
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -0700121 crypto_debug("param %d, value %d", param, value);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530122 switch (param) {
123 case WLAN_CRYPTO_PARAM_AUTH_MODE:
124 status = wlan_crypto_set_authmode(crypto_params, value);
125 break;
126 case WLAN_CRYPTO_PARAM_UCAST_CIPHER:
127 status = wlan_crypto_set_ucastciphers(crypto_params, value);
128 break;
129 case WLAN_CRYPTO_PARAM_MCAST_CIPHER:
130 status = wlan_crypto_set_mcastcipher(crypto_params, value);
131 break;
132 case WLAN_CRYPTO_PARAM_MGMT_CIPHER:
133 status = wlan_crypto_set_mgmtcipher(crypto_params, value);
134 break;
135 case WLAN_CRYPTO_PARAM_CIPHER_CAP:
136 status = wlan_crypto_set_cipher_cap(crypto_params, value);
137 break;
138 case WLAN_CRYPTO_PARAM_RSN_CAP:
139 status = wlan_crypto_set_rsn_cap(crypto_params, value);
140 break;
141 case WLAN_CRYPTO_PARAM_KEY_MGMT:
142 status = wlan_crypto_set_key_mgmt(crypto_params, value);
143 break;
144 default:
145 status = QDF_STATUS_E_INVAL;
146 }
Disha Das6419ff12018-02-02 10:21:55 +0530147 return status;
148}
149
150/**
151 * wlan_crypto_set_vdev_param - called by ucfg to set crypto param
152 * @vdev: vdev
153 * @param: param to be set.
154 * @value: value
155 *
156 * This function gets called from ucfg to set param
157 *
158 * Return: QDF_STATUS_SUCCESS - in case of success
159 */
160QDF_STATUS wlan_crypto_set_vdev_param(struct wlan_objmgr_vdev *vdev,
161 wlan_crypto_param_type param,
162 uint32_t value){
163 QDF_STATUS status = QDF_STATUS_E_INVAL;
164 struct wlan_crypto_comp_priv *crypto_priv;
165 struct wlan_crypto_params *crypto_params;
166
167 crypto_priv = (struct wlan_crypto_comp_priv *)
168 wlan_get_vdev_crypto_obj(vdev);
169
Jeff Johnsonf3a2b892019-03-20 12:07:03 -0700170 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530171 crypto_err("crypto_priv NULL");
Disha Das6419ff12018-02-02 10:21:55 +0530172 return QDF_STATUS_E_INVAL;
173 }
174
175 crypto_params = &(crypto_priv->crypto_params);
176
177 status = wlan_crypto_set_param(crypto_params, param, value);
178
179 return status;
180}
181
182/**
183 * wlan_crypto_set_param - called by ucfg to set crypto param
184 *
185 * @peer: peer
186 * @param: param to be set.
187 * @value: value
188 *
189 * This function gets called from ucfg to set param
190 *
191 * Return: QDF_STATUS_SUCCESS - in case of success
192 */
193QDF_STATUS wlan_crypto_set_peer_param(struct wlan_objmgr_peer *peer,
194 wlan_crypto_param_type param,
195 uint32_t value){
196 QDF_STATUS status = QDF_STATUS_E_INVAL;
197 struct wlan_crypto_comp_priv *crypto_priv;
198 struct wlan_crypto_params *crypto_params;
199
200 crypto_params = wlan_crypto_peer_get_comp_params(peer,
201 &crypto_priv);
202
Jeff Johnsonf3a2b892019-03-20 12:07:03 -0700203 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530204 crypto_err("crypto_priv NULL");
Disha Das6419ff12018-02-02 10:21:55 +0530205 return QDF_STATUS_E_INVAL;
206 }
207
208 crypto_params = &(crypto_priv->crypto_params);
209
210 status = wlan_crypto_set_param(crypto_params, param, value);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530211
212 return status;
213}
214
215/**
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530216 * wlan_crypto_get_param_value - called by crypto APIs to get value for param
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530217 * @param: Crypto param type
218 * @crypto_params: Crypto params struct
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530219 *
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530220 * This function gets called from in-within crypto layer
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530221 *
222 * Return: value or -1 for failure
223 */
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530224static int32_t wlan_crypto_get_param_value(wlan_crypto_param_type param,
225 struct wlan_crypto_params *crypto_params)
226{
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530227 int32_t value = -1;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530228
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530229 switch (param) {
230 case WLAN_CRYPTO_PARAM_AUTH_MODE:
231 value = wlan_crypto_get_authmode(crypto_params);
232 break;
233 case WLAN_CRYPTO_PARAM_UCAST_CIPHER:
234 value = wlan_crypto_get_ucastciphers(crypto_params);
235 break;
236 case WLAN_CRYPTO_PARAM_MCAST_CIPHER:
237 value = wlan_crypto_get_mcastcipher(crypto_params);
238 break;
239 case WLAN_CRYPTO_PARAM_MGMT_CIPHER:
240 value = wlan_crypto_get_mgmtciphers(crypto_params);
241 break;
242 case WLAN_CRYPTO_PARAM_CIPHER_CAP:
243 value = wlan_crypto_get_cipher_cap(crypto_params);
244 break;
245 case WLAN_CRYPTO_PARAM_RSN_CAP:
246 value = wlan_crypto_get_rsn_cap(crypto_params);
247 break;
248 case WLAN_CRYPTO_PARAM_KEY_MGMT:
249 value = wlan_crypto_get_key_mgmt(crypto_params);
250 break;
251 default:
252 value = QDF_STATUS_E_INVAL;
253 }
254
255 return value;
256}
257
Ashok Ponnaiahf9953602018-01-11 15:39:26 +0530258/**
259 * wlan_crypto_get_param - called to get value for param from vdev
260 * @vdev: vdev
261 * @param: Crypto param type
262 *
263 * This function gets called to get value for param from vdev
264 *
265 * Return: value or -1 for failure
266 */
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530267int32_t wlan_crypto_get_param(struct wlan_objmgr_vdev *vdev,
268 wlan_crypto_param_type param)
269{
270 int32_t value = -1;
271 struct wlan_crypto_comp_priv *crypto_priv;
272 struct wlan_crypto_params *crypto_params;
273 crypto_priv = (struct wlan_crypto_comp_priv *)
274 wlan_get_vdev_crypto_obj(vdev);
275
Jeff Johnsonf3a2b892019-03-20 12:07:03 -0700276 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530277 crypto_err("crypto_priv NULL");
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530278 return QDF_STATUS_E_INVAL;
279 }
280
281 crypto_params = &(crypto_priv->crypto_params);
282 value = wlan_crypto_get_param_value(param, crypto_params);
283
284 return value;
285}
Ashok Ponnaiahf9953602018-01-11 15:39:26 +0530286/**
287 * wlan_crypto_get_peer_param - called to get value for param from peer
288 * @peer: peer
289 * @param: Crypto param type
290 *
291 * This function gets called to get value for param from peer
292 *
293 * Return: value or -1 for failure
294 */
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530295int32_t wlan_crypto_get_peer_param(struct wlan_objmgr_peer *peer,
296 wlan_crypto_param_type param)
297{
298 int32_t value = -1;
299 struct wlan_crypto_comp_priv *crypto_priv;
300 struct wlan_crypto_params *crypto_params;
301
302 crypto_params = wlan_crypto_peer_get_comp_params(peer,
303 &crypto_priv);
304
Jeff Johnsonf3a2b892019-03-20 12:07:03 -0700305 if (!crypto_params) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530306 crypto_err("crypto_params NULL");
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530307 return QDF_STATUS_E_INVAL;
308 }
309 value = wlan_crypto_get_param_value(param, crypto_params);
310
311 return value;
312}
Ashok Ponnaiah455eb682018-03-19 10:33:22 +0530313qdf_export_symbol(wlan_crypto_get_peer_param);
Ashok Kumar6f8b9242018-12-10 12:26:24 +0530314
315static
316QDF_STATUS wlan_crypto_set_pmksa(struct wlan_crypto_params *crypto_params,
317 struct wlan_crypto_pmksa *pmksa)
318{
Ashok Kumar509aeeb2019-01-18 15:49:11 +0530319 uint8_t i, first_available_slot = 0;
Ashok Kumar1b913042019-02-06 09:44:44 +0530320 bool slot_found = false;
Ashok Kumar6f8b9242018-12-10 12:26:24 +0530321
322 /* find the empty slot or slot with same bssid */
323 for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) {
324 if (!crypto_params->pmksa[i]) {
325 if (!slot_found) {
Ashok Kumar1b913042019-02-06 09:44:44 +0530326 slot_found = true;
Ashok Kumar6f8b9242018-12-10 12:26:24 +0530327 first_available_slot = i;
328 }
329 continue;
330 }
331 if (qdf_is_macaddr_equal(&pmksa->bssid,
332 &crypto_params->pmksa[i]->bssid)) {
333 /* free the current pmksa and use this slot */
Liangwei Dongca4abcf2019-03-20 04:06:54 -0400334 qdf_mem_zero(crypto_params->pmksa[i],
335 sizeof(struct wlan_crypto_pmksa));
Ashok Kumar6f8b9242018-12-10 12:26:24 +0530336 qdf_mem_free(crypto_params->pmksa[i]);
337 crypto_params->pmksa[i] = pmksa;
338 return QDF_STATUS_SUCCESS;
339 }
340 }
341
342 if (i == WLAN_CRYPTO_MAX_PMKID && !slot_found) {
343 crypto_err("no entry available for pmksa");
Ashok Kumar6f8b9242018-12-10 12:26:24 +0530344 return QDF_STATUS_E_INVAL;
345 }
346 crypto_params->pmksa[first_available_slot] = pmksa;
347
348 return QDF_STATUS_SUCCESS;
349}
350
351static
352QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params,
353 struct wlan_crypto_pmksa *pmksa)
354{
355 uint8_t i;
356
357 /* find slot with same bssid */
358 for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) {
359 if (!crypto_params->pmksa[i])
360 continue;
361 if (qdf_is_macaddr_equal(&pmksa->bssid,
362 &crypto_params->pmksa[i]->bssid)) {
Liangwei Dongca4abcf2019-03-20 04:06:54 -0400363 qdf_mem_zero(crypto_params->pmksa[i],
364 sizeof(struct wlan_crypto_pmksa));
Ashok Kumar6f8b9242018-12-10 12:26:24 +0530365 qdf_mem_free(crypto_params->pmksa[i]);
366 crypto_params->pmksa[i] = NULL;
367 return QDF_STATUS_SUCCESS;
368 }
369 }
370
371 return QDF_STATUS_E_INVAL;
372}
373
374QDF_STATUS wlan_crypto_pmksa_flush(struct wlan_crypto_params *crypto_params)
375{
376 uint8_t i;
377
378 for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) {
379 if (!crypto_params->pmksa[i])
380 continue;
Liangwei Dongca4abcf2019-03-20 04:06:54 -0400381 qdf_mem_zero(crypto_params->pmksa[i],
382 sizeof(struct wlan_crypto_pmksa));
Ashok Kumar6f8b9242018-12-10 12:26:24 +0530383 qdf_mem_free(crypto_params->pmksa[i]);
384 crypto_params->pmksa[i] = NULL;
385 }
386
387 return QDF_STATUS_SUCCESS;
388}
389
390QDF_STATUS wlan_crypto_set_del_pmksa(struct wlan_objmgr_vdev *vdev,
391 struct wlan_crypto_pmksa *pmksa,
392 bool set)
393{
394 QDF_STATUS status = QDF_STATUS_E_INVAL;
395 struct wlan_crypto_comp_priv *crypto_priv;
396 struct wlan_crypto_params *crypto_params;
Min Liubc3bde32019-03-25 11:20:12 +0800397 enum QDF_OPMODE op_mode;
Ashok Kumar6f8b9242018-12-10 12:26:24 +0530398
Min Liubc3bde32019-03-25 11:20:12 +0800399 op_mode = wlan_vdev_mlme_get_opmode(vdev);
400
401 if (op_mode != QDF_STA_MODE && op_mode != QDF_SAP_MODE)
Ashok Kumar6f8b9242018-12-10 12:26:24 +0530402 return QDF_STATUS_E_NOSUPPORT;
403
404 if (!pmksa && set) {
405 crypto_err("pmksa is NULL for set operation");
406 return QDF_STATUS_E_INVAL;
407 }
408 crypto_priv = (struct wlan_crypto_comp_priv *)
409 wlan_get_vdev_crypto_obj(vdev);
410
411 if (!crypto_priv) {
412 crypto_err("crypto_priv NULL");
413 return QDF_STATUS_E_INVAL;
414 }
415
416 crypto_params = &crypto_priv->crypto_params;
417 if (set) {
418 status = wlan_crypto_set_pmksa(crypto_params, pmksa);
419 /* Set pmksa */
420 } else {
421 /* del pmksa */
422 if (!pmksa)
423 status = wlan_crypto_pmksa_flush(crypto_params);
424 else
425 status = wlan_crypto_del_pmksa(crypto_params, pmksa);
426 }
427
428 return status;
429}
430
Liangwei Dongca4abcf2019-03-20 04:06:54 -0400431struct wlan_crypto_pmksa *
Ashok Kumar6f8b9242018-12-10 12:26:24 +0530432wlan_crypto_get_pmksa(struct wlan_objmgr_vdev *vdev, struct qdf_mac_addr *bssid)
433{
434 struct wlan_crypto_comp_priv *crypto_priv;
435 struct wlan_crypto_params *crypto_params;
436 uint8_t i;
437
438 if (!bssid) {
439 crypto_err("bssid is NULL");
440 return NULL;
441 }
442 crypto_priv = (struct wlan_crypto_comp_priv *)
443 wlan_get_vdev_crypto_obj(vdev);
444
445 if (!crypto_priv) {
446 crypto_err("crypto_priv NULL");
447 return NULL;
448 }
449
450 crypto_params = &crypto_priv->crypto_params;
451
452 for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) {
453 if (!crypto_params->pmksa[i])
454 continue;
455 if (qdf_is_macaddr_equal(bssid,
456 &crypto_params->pmksa[i]->bssid)) {
457 return crypto_params->pmksa[i];
458 }
459 }
460
461 return NULL;
462}
Ashok Ponnaiahf9953602018-01-11 15:39:26 +0530463/**
464 * wlan_crypto_is_htallowed - called to check is HT allowed for cipher
465 * @vdev: vdev
466 * @peer: peer
467 *
468 * This function gets called to check is HT allowed for cipher.
469 * HT is not allowed for wep and tkip.
470 *
471 * Return: 0 - not allowed or 1 - allowed
472 */
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530473uint8_t wlan_crypto_is_htallowed(struct wlan_objmgr_vdev *vdev,
474 struct wlan_objmgr_peer *peer)
475{
476 int32_t ucast_cipher;
477
478 if (!(vdev || peer)) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530479 crypto_err("Invalid params");
Sathish Kumarc6cd8dc2017-05-31 19:01:08 +0530480 return 0;
481 }
482
483 if (vdev)
484 ucast_cipher = wlan_crypto_get_param(vdev,
485 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
486 else
487 ucast_cipher = wlan_crypto_get_peer_param(peer,
488 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
489
490 return (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP)) ||
491 ((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_TKIP)) &&
492 !(ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM)) &&
493 !(ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM)) &&
494 !(ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM_256)) &&
495 !(ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM_256)));
496}
497qdf_export_symbol(wlan_crypto_is_htallowed);
498
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530499/**
500 * wlan_crypto_setkey - called by ucfg to setkey
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530501 * @vdev: vdev
502 * @req_key: req_key with cipher type, key macaddress
503 *
504 * This function gets called from ucfg to sey key
505 *
506 * Return: QDF_STATUS_SUCCESS - in case of success
507 */
508QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev,
509 struct wlan_crypto_req_key *req_key){
510
511 QDF_STATUS status = QDF_STATUS_E_INVAL;
512 struct wlan_crypto_comp_priv *crypto_priv;
513 struct wlan_crypto_params *crypto_params;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530514 struct wlan_objmgr_psoc *psoc;
515 struct wlan_objmgr_peer *peer;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +0530516 struct wlan_crypto_key *key = NULL;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530517 const struct wlan_crypto_cipher *cipher;
Disha Dasdf10f652018-12-10 16:20:56 +0530518 uint8_t macaddr[QDF_MAC_ADDR_SIZE] =
519 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530520 bool isbcast;
Jeff Johnsona4262322017-11-09 09:54:12 -0800521 enum QDF_OPMODE vdev_mode;
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530522 uint8_t igtk_idx = 0;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530523
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530524 if (!vdev || !req_key || req_key->keylen > (sizeof(req_key->keydata))) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530525 crypto_err("Invalid params vdev%pK, req_key%pK", vdev, req_key);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530526 return QDF_STATUS_E_INVAL;
527 }
528
Keyur Parekh41386862018-04-09 23:31:39 -0700529 isbcast = qdf_is_macaddr_group(
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530530 (struct qdf_mac_addr *)req_key->macaddr);
Subrat Mishra2b75d6d2017-08-07 17:36:25 +0530531 if ((req_key->keylen == 0) && !IS_FILS_CIPHER(req_key->type)) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530532 /* zero length keys, only set default key id if flags are set*/
533 if ((req_key->flags & WLAN_CRYPTO_KEY_DEFAULT)
534 && (req_key->keyix != WLAN_CRYPTO_KEYIX_NONE)
535 && (!IS_MGMT_CIPHER(req_key->type))) {
536 wlan_crypto_default_key(vdev,
537 req_key->macaddr,
538 req_key->keyix,
539 !isbcast);
540 return QDF_STATUS_SUCCESS;
541 }
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530542 crypto_err("req_key len zero");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530543 return QDF_STATUS_E_INVAL;
544 }
545
546 cipher = wlan_crypto_cipher_ops[req_key->type];
547
548 if (!cipher && !IS_MGMT_CIPHER(req_key->type)) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530549 crypto_err("cipher invalid");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530550 return QDF_STATUS_E_INVAL;
551 }
552
Subrat Mishra2b75d6d2017-08-07 17:36:25 +0530553 if (cipher && (!IS_FILS_CIPHER(req_key->type)) &&
554 (!IS_MGMT_CIPHER(req_key->type)) &&
Varun Reddy Yeturu71742082018-06-28 11:55:15 -0700555 ((req_key->keylen != (cipher->keylen / CRYPTO_NBBY)) &&
Subrat Mishra2b75d6d2017-08-07 17:36:25 +0530556 (req_key->type != WLAN_CRYPTO_CIPHER_WEP))) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530557 crypto_err("cipher invalid");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530558 return QDF_STATUS_E_INVAL;
559 } else if ((req_key->type == WLAN_CRYPTO_CIPHER_WEP) &&
Ashok Ponnaiahb6962212017-07-31 10:12:57 +0530560 !((req_key->keylen == WLAN_CRYPTO_KEY_WEP40_LEN)
561 || (req_key->keylen == WLAN_CRYPTO_KEY_WEP104_LEN)
562 || (req_key->keylen == WLAN_CRYPTO_KEY_WEP128_LEN))) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530563 crypto_err("wep key len invalid. keylen: %d", req_key->keylen);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530564 return QDF_STATUS_E_INVAL;
565 }
566
567 if (req_key->keyix == WLAN_CRYPTO_KEYIX_NONE) {
568 if (req_key->flags != (WLAN_CRYPTO_KEY_XMIT
569 | WLAN_CRYPTO_KEY_RECV)) {
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530570 req_key->flags |= (WLAN_CRYPTO_KEY_XMIT
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530571 | WLAN_CRYPTO_KEY_RECV);
572 }
573 } else {
Gurumoorthi Gnanasambandhan17d1e0f2019-07-16 13:02:47 +0530574 if ((req_key->keyix >= WLAN_CRYPTO_MAX_VLANKEYIX)
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530575 && (!IS_MGMT_CIPHER(req_key->type))) {
576 return QDF_STATUS_E_INVAL;
577 }
578
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530579 req_key->flags |= (WLAN_CRYPTO_KEY_XMIT
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530580 | WLAN_CRYPTO_KEY_RECV);
Nandha Kishore Easwaran786c9552017-06-28 10:54:09 +0530581 if (isbcast)
582 req_key->flags |= WLAN_CRYPTO_KEY_GROUP;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530583 }
584
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530585 vdev_mode = wlan_vdev_mlme_get_opmode(vdev);
Vivekb02a6492017-06-21 08:21:58 +0530586
587 wlan_vdev_obj_lock(vdev);
Disha Dasdf10f652018-12-10 16:20:56 +0530588 qdf_mem_copy(macaddr, wlan_vdev_mlme_get_macaddr(vdev),
589 QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530590 psoc = wlan_vdev_get_psoc(vdev);
591 if (!psoc) {
592 wlan_vdev_obj_unlock(vdev);
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530593 crypto_err("psoc NULL");
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530594 return QDF_STATUS_E_INVAL;
595 }
596 wlan_vdev_obj_unlock(vdev);
597
Rohan Dutta3844c602017-09-01 16:04:25 +0530598 if (req_key->type == WLAN_CRYPTO_CIPHER_WEP) {
599 if (wlan_crypto_vdev_has_auth_mode(vdev,
600 (1 << WLAN_CRYPTO_AUTH_8021X))) {
601 req_key->flags |= WLAN_CRYPTO_KEY_DEFAULT;
Rohan Dutta3844c602017-09-01 16:04:25 +0530602 }
603 }
604
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530605 if (isbcast) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530606 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
607 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -0700608 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530609 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530610 return QDF_STATUS_E_INVAL;
611 }
612
613 if (IS_MGMT_CIPHER(req_key->type)) {
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530614 igtk_idx = req_key->keyix - WLAN_CRYPTO_MAXKEYIDX;
Disha Das76210cd2018-04-10 12:44:14 +0530615 if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530616 crypto_err("igtk key invalid keyid %d",
617 igtk_idx);
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530618 return QDF_STATUS_E_INVAL;
619 }
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530620 key = qdf_mem_malloc(sizeof(struct wlan_crypto_key));
Madhvapathi Sriramb73fc282019-01-07 09:12:25 +0530621 if (!key)
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530622 return QDF_STATUS_E_NOMEM;
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530623
624 if (crypto_priv->igtk_key[igtk_idx])
625 qdf_mem_free(crypto_priv->igtk_key[igtk_idx]);
626
627 crypto_priv->igtk_key[igtk_idx] = key;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530628 crypto_priv->igtk_key_type = req_key->type;
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530629 crypto_priv->def_igtk_tx_keyid = igtk_idx;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530630 } else {
Subrat Mishra2b75d6d2017-08-07 17:36:25 +0530631 if (IS_FILS_CIPHER(req_key->type)) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530632 crypto_err("FILS key is not for BroadCast pkt");
Subrat Mishra2b75d6d2017-08-07 17:36:25 +0530633 return QDF_STATUS_E_INVAL;
634 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530635 if (!HAS_MCAST_CIPHER(crypto_params, req_key->type)
636 && (req_key->type != WLAN_CRYPTO_CIPHER_WEP)) {
637 return QDF_STATUS_E_INVAL;
638 }
639 if (!crypto_priv->key[req_key->keyix]) {
640 crypto_priv->key[req_key->keyix]
641 = qdf_mem_malloc(
642 sizeof(struct wlan_crypto_key));
643 if (!crypto_priv->key[req_key->keyix])
644 return QDF_STATUS_E_NOMEM;
645 }
646 key = crypto_priv->key[req_key->keyix];
647 }
Nandha Kishore Easwarane9f80702017-07-21 18:00:56 +0530648 if (vdev_mode == QDF_STA_MODE) {
sheenam monga1273bce2019-05-06 11:47:08 +0530649 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev,
650 WLAN_CRYPTO_ID);
651 if (!peer) {
sheenam mongad74e1fd2019-05-20 16:31:44 +0530652 crypto_err("peer NULL");
Ashok Ponnaiahb6962212017-07-31 10:12:57 +0530653 if (IS_MGMT_CIPHER(req_key->type)) {
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530654 crypto_priv->igtk_key[igtk_idx] = NULL;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +0530655 crypto_priv->igtk_key_type
656 = WLAN_CRYPTO_CIPHER_NONE;
657 } else
658 crypto_priv->key[req_key->keyix] = NULL;
659 if (key)
660 qdf_mem_free(key);
Nandha Kishore Easwarane9f80702017-07-21 18:00:56 +0530661 return QDF_STATUS_E_INVAL;
662 }
Nandha Kishore Easwarane9f80702017-07-21 18:00:56 +0530663 qdf_mem_copy(macaddr, wlan_peer_get_macaddr(peer),
Disha Dasdf10f652018-12-10 16:20:56 +0530664 QDF_MAC_ADDR_SIZE);
Nandha Kishore Easwarane9f80702017-07-21 18:00:56 +0530665 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
666 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530667 } else {
Amir Pateld3385942018-05-03 23:01:08 +0530668 uint8_t pdev_id;
669
670 pdev_id = wlan_objmgr_pdev_get_pdev_id(
671 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530672 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530673 psoc,
Amir Pateld3385942018-05-03 23:01:08 +0530674 pdev_id,
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530675 macaddr,
Amir Pateld3385942018-05-03 23:01:08 +0530676 req_key->macaddr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530677 WLAN_CRYPTO_ID);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530678
Jeff Johnsonf3a2b892019-03-20 12:07:03 -0700679 if (!peer) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530680 crypto_err("peer NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530681 return QDF_STATUS_E_INVAL;
682 }
683
Disha Dasdf10f652018-12-10 16:20:56 +0530684 qdf_mem_copy(macaddr, req_key->macaddr, QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530685 crypto_params = wlan_crypto_peer_get_comp_params(peer,
686 &crypto_priv);
687 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
688
Jeff Johnsonf3a2b892019-03-20 12:07:03 -0700689 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530690 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530691 return QDF_STATUS_E_INVAL;
692 }
693 if (IS_MGMT_CIPHER(req_key->type)) {
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530694 igtk_idx = req_key->keyix - WLAN_CRYPTO_MAXKEYIDX;
Disha Das55b86c22018-04-20 15:22:08 +0530695 if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530696 crypto_err("igtk key invalid keyid %d",
697 igtk_idx);
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530698 return QDF_STATUS_E_INVAL;
699 }
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530700 key = qdf_mem_malloc(sizeof(struct wlan_crypto_key));
Madhvapathi Sriramb73fc282019-01-07 09:12:25 +0530701 if (!key)
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530702 return QDF_STATUS_E_NOMEM;
Madhvapathi Sriramb73fc282019-01-07 09:12:25 +0530703
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +0530704 if (crypto_priv->igtk_key[igtk_idx])
705 qdf_mem_free(crypto_priv->igtk_key[igtk_idx]);
706
707 crypto_priv->igtk_key[igtk_idx] = key;
708 crypto_priv->igtk_key_type = req_key->type;
709 crypto_priv->def_igtk_tx_keyid = igtk_idx;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530710 } else {
711 uint16_t kid = req_key->keyix;
712 if (kid == WLAN_CRYPTO_KEYIX_NONE)
713 kid = 0;
Gurumoorthi Gnanasambandhan17d1e0f2019-07-16 13:02:47 +0530714 if (kid >= WLAN_CRYPTO_MAX_VLANKEYIX) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530715 crypto_err("invalid keyid %d", kid);
Radhika Sriram00392f32018-04-04 19:04:49 +0530716 return QDF_STATUS_E_INVAL;
717 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530718 if (!crypto_priv->key[kid]) {
719 crypto_priv->key[kid]
720 = qdf_mem_malloc(
721 sizeof(struct wlan_crypto_key));
722 if (!crypto_priv->key[kid])
723 return QDF_STATUS_E_NOMEM;
724 }
725 key = crypto_priv->key[kid];
726 }
727 }
728
729 /* alloc key might not required as it is already there */
730 key->cipher_table = (void *)cipher;
731 key->keylen = req_key->keylen;
732 key->flags = req_key->flags;
733
734 if (req_key->keyix == WLAN_CRYPTO_KEYIX_NONE)
735 key->keyix = 0;
736 else
737 key->keyix = req_key->keyix;
738
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530739 if (req_key->flags & WLAN_CRYPTO_KEY_DEFAULT
740 && (!IS_MGMT_CIPHER(req_key->type))) {
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530741 crypto_priv->def_tx_keyid = key->keyix;
742 key->flags |= WLAN_CRYPTO_KEY_DEFAULT;
743 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530744 if ((req_key->type == WLAN_CRYPTO_CIPHER_WAPI_SMS4)
745 || (req_key->type == WLAN_CRYPTO_CIPHER_WAPI_GCM4)) {
746 uint8_t iv_AP[16] = { 0x5c, 0x36, 0x5c, 0x36,
747 0x5c, 0x36, 0x5c, 0x36,
748 0x5c, 0x36, 0x5c, 0x36,
749 0x5c, 0x36, 0x5c, 0x37};
750 uint8_t iv_STA[16] = { 0x5c, 0x36, 0x5c, 0x36,
751 0x5c, 0x36, 0x5c, 0x36,
752 0x5c, 0x36, 0x5c, 0x36,
753 0x5c, 0x36, 0x5c, 0x36};
754
755 /* During Tx PN should be increment and
756 * send but as per our implementation we increment only after
757 * Tx complete. So First packet PN check will be failed.
758 * To compensate increment the PN here by 2
759 */
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530760 if (vdev_mode == QDF_SAP_MODE) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530761 iv_AP[15] += 2;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530762 qdf_mem_copy(key->recviv, iv_STA,
763 WLAN_CRYPTO_WAPI_IV_SIZE);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530764 qdf_mem_copy(key->txiv, iv_AP,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530765 WLAN_CRYPTO_WAPI_IV_SIZE);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530766 } else {
767 iv_STA[15] += 2;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530768 qdf_mem_copy(key->recviv, iv_AP,
769 WLAN_CRYPTO_WAPI_IV_SIZE);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530770 qdf_mem_copy(key->txiv, iv_STA,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530771 WLAN_CRYPTO_WAPI_IV_SIZE);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530772 }
773 } else {
774 uint8_t i = 0;
775 qdf_mem_copy((uint8_t *)(&key->keytsc),
776 (uint8_t *)(&req_key->keytsc), sizeof(key->keytsc));
777 for (i = 0; i < WLAN_CRYPTO_TID_SIZE; i++) {
778 qdf_mem_copy((uint8_t *)(&key->keyrsc[i]),
779 (uint8_t *)(&req_key->keyrsc),
780 sizeof(key->keyrsc[0]));
781 }
782 }
783
784 qdf_mem_copy(key->keyval, req_key->keydata, sizeof(key->keyval));
785 key->valid = 1;
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530786 if ((IS_MGMT_CIPHER(req_key->type))) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530787 if (HAS_CIPHER_CAP(crypto_params,
788 WLAN_CRYPTO_CAP_PMF_OFFLOAD)) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530789 if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
790 WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(vdev,
791 key, macaddr, req_key->type);
792 }
793 }
Ashok Ponnaiahadfce982018-05-10 14:08:52 +0530794 wlan_crypto_set_mgmtcipher(crypto_params, req_key->type);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530795 status = wlan_crypto_set_igtk_key(key);
796 return status;
Subrat Mishra2b75d6d2017-08-07 17:36:25 +0530797 } else if (IS_FILS_CIPHER(req_key->type)) {
798 /* Take request key object to FILS setkey */
799 key->private = req_key;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530800 } else {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530801 if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
802 WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(vdev, key,
803 macaddr, req_key->type);
804 }
805 }
806 status = cipher->setkey(key);
807
Padma Raghunathan43ebaa72018-04-30 09:46:38 +0530808 if ((req_key->flags & WLAN_CRYPTO_KEY_DEFAULT) &&
809 (req_key->keyix != WLAN_CRYPTO_KEYIX_NONE) &&
810 (!IS_MGMT_CIPHER(req_key->type))) {
811 /* default xmit key */
812 wlan_crypto_default_key(vdev,
813 req_key->macaddr,
814 req_key->keyix,
815 !isbcast);
816 }
817
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530818 return status;
819}
820
821/**
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530822 * wlan_crypto_get_keytype - get keytype
823 * @key: key
824 *
825 * This function gets keytype from key
826 *
827 * Return: keytype
828 */
829wlan_crypto_cipher_type wlan_crypto_get_key_type(
830 struct wlan_crypto_key *key){
831 if (key && key->cipher_table) {
832 return ((struct wlan_crypto_cipher *)
833 (key->cipher_table))->cipher;
834 }
835 return WLAN_CRYPTO_CIPHER_NONE;
836}
837qdf_export_symbol(wlan_crypto_get_key_type);
838/**
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530839 * wlan_crypto_vdev_getkey - get key from vdev
840 * @vdev: vdev
841 * @keyix: keyix
842 *
843 * This function gets key from vdev
844 *
845 * Return: key or NULL
846 */
847struct wlan_crypto_key *wlan_crypto_vdev_getkey(struct wlan_objmgr_vdev *vdev,
848 uint16_t keyix){
849 struct wlan_crypto_comp_priv *crypto_priv;
850 struct wlan_crypto_params *crypto_params;
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530851 struct wlan_crypto_key *key = NULL;
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530852
853 crypto_params = wlan_crypto_vdev_get_comp_params(vdev, &crypto_priv);
854
Jeff Johnsonf3a2b892019-03-20 12:07:03 -0700855 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530856 crypto_err("crypto_priv NULL");
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530857 return NULL;
858 }
Rohan Dutta613f7922019-04-01 11:28:39 +0530859 /* for keyix 4,5 we return the igtk keys for keyix more than 5
860 * we return the default key, for all other keyix we return the
861 * key accordingly.
862 */
863 if (keyix == WLAN_CRYPTO_KEYIX_NONE ||
864 keyix >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX))
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530865 key = crypto_priv->key[crypto_priv->def_tx_keyid];
Rohan Dutta613f7922019-04-01 11:28:39 +0530866 else if (keyix >= WLAN_CRYPTO_MAXKEYIDX)
867 key = crypto_priv->igtk_key[keyix - WLAN_CRYPTO_MAXKEYIDX];
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530868 else
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530869 key = crypto_priv->key[keyix];
870
871 if (key && key->valid)
872 return key;
873
874 return NULL;
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530875}
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530876qdf_export_symbol(wlan_crypto_vdev_getkey);
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530877
878/**
879 * wlan_crypto_peer_getkey - get key from peer
880 * @peer: peer
881 * @keyix: keyix
882 *
883 * This function gets key from peer
884 *
885 * Return: key or NULL
886 */
887struct wlan_crypto_key *wlan_crypto_peer_getkey(struct wlan_objmgr_peer *peer,
888 uint16_t keyix){
889 struct wlan_crypto_comp_priv *crypto_priv;
890 struct wlan_crypto_params *crypto_params;
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530891 struct wlan_crypto_key *key = NULL;
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530892
893 crypto_params = wlan_crypto_peer_get_comp_params(peer, &crypto_priv);
894
Jeff Johnsonf3a2b892019-03-20 12:07:03 -0700895 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530896 crypto_err("crypto_priv NULL");
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530897 return NULL;
898 }
899
Rohan Dutta613f7922019-04-01 11:28:39 +0530900 /* for keyix 4,5 we return the igtk keys for keyix more than 5
901 * we return the default key, for all other keyix we return the
902 * key accordingly.
903 */
904 if (keyix == WLAN_CRYPTO_KEYIX_NONE ||
905 keyix >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX))
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530906 key = crypto_priv->key[crypto_priv->def_tx_keyid];
Rohan Dutta613f7922019-04-01 11:28:39 +0530907 else if (keyix >= WLAN_CRYPTO_MAXKEYIDX)
908 key = crypto_priv->igtk_key[keyix - WLAN_CRYPTO_MAXKEYIDX];
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530909 else
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530910 key = crypto_priv->key[keyix];
911
912 if (key && key->valid)
913 return key;
914
915 return NULL;
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530916}
Ashok Ponnaiah23668cd2018-04-23 14:22:27 +0530917qdf_export_symbol(wlan_crypto_peer_getkey);
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530918
919/**
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530920 * wlan_crypto_getkey - called by ucfg to get key
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530921 * @vdev: vdev
922 * @req_key: key value will be copied in this req_key
923 * @mac_address: mac address of the peer for unicast key
924 * or broadcast address if group key is requested.
Ashok Ponnaiahf9953602018-01-11 15:39:26 +0530925 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530926 * This function gets called from ucfg to get key
927 *
928 * Return: QDF_STATUS_SUCCESS - in case of success
929 */
930QDF_STATUS wlan_crypto_getkey(struct wlan_objmgr_vdev *vdev,
931 struct wlan_crypto_req_key *req_key,
932 uint8_t *mac_addr){
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530933 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530934 struct wlan_crypto_key *key;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530935 struct wlan_objmgr_psoc *psoc;
Disha Dasdf10f652018-12-10 16:20:56 +0530936 uint8_t macaddr[QDF_MAC_ADDR_SIZE] =
937 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530938
939 wlan_vdev_obj_lock(vdev);
Disha Dasdf10f652018-12-10 16:20:56 +0530940 qdf_mem_copy(macaddr, wlan_vdev_mlme_get_macaddr(vdev),
941 QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530942 psoc = wlan_vdev_get_psoc(vdev);
943 if (!psoc) {
944 wlan_vdev_obj_unlock(vdev);
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530945 crypto_err("psoc NULL");
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530946 return QDF_STATUS_E_INVAL;
947 }
948 wlan_vdev_obj_unlock(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530949
950 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac_addr)) {
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530951 key = wlan_crypto_vdev_getkey(vdev, req_key->keyix);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530952 if (!key)
953 return QDF_STATUS_E_INVAL;
954 } else {
955 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +0530956 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530957
Amir Pateld3385942018-05-03 23:01:08 +0530958 pdev_id = wlan_objmgr_pdev_get_pdev_id(
959 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530960 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530961 psoc,
Amir Pateld3385942018-05-03 23:01:08 +0530962 pdev_id,
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +0530963 macaddr,
Amir Pateld3385942018-05-03 23:01:08 +0530964 mac_addr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530965 WLAN_CRYPTO_ID);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -0700966 if (!peer) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +0530967 crypto_err("peer NULL");
Nandha Kishore Easwaran434838f2017-10-29 00:47:11 +0530968 return QDF_STATUS_E_NOENT;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530969 }
Ashok Ponnaiahafb88932018-04-17 10:15:24 +0530970 key = wlan_crypto_peer_getkey(peer, req_key->keyix);
Ashok Ponnaiahc1797fd2018-05-04 09:42:02 +0530971 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530972 if (!key)
973 return QDF_STATUS_E_INVAL;
974 }
975
976 if (key->valid) {
977 qdf_mem_copy(req_key->keydata,
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530978 key->keyval, key->keylen);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +0530979 qdf_mem_copy((uint8_t *)(&req_key->keytsc),
980 (uint8_t *)(&key->keytsc),
981 sizeof(req_key->keytsc));
982 qdf_mem_copy((uint8_t *)(&req_key->keyrsc),
983 (uint8_t *)(&key->keyrsc[0]),
984 sizeof(req_key->keyrsc));
985 req_key->keylen = key->keylen;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530986 req_key->flags = key->flags;
987 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +0530988
989 if (!cipher_table)
990 return QDF_STATUS_SUCCESS;
991
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +0530992 req_key->type = cipher_table->cipher;
Rohan Duttabec3ab72017-09-22 12:32:23 +0530993 if (req_key->type == WLAN_CRYPTO_CIPHER_WAPI_SMS4) {
994 qdf_mem_copy((uint8_t *)(&req_key->txiv),
995 (uint8_t *)(key->txiv),
996 sizeof(req_key->txiv));
997 qdf_mem_copy((uint8_t *)(&req_key->recviv),
998 (uint8_t *)(key->recviv),
999 sizeof(req_key->recviv));
1000 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301001 }
1002
1003 return QDF_STATUS_SUCCESS;
1004}
1005
1006/**
1007 * wlan_crypto_delkey - called by ucfg to delete key
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301008 * @vdev: vdev
1009 * @mac_address: mac address of the peer for unicast key
1010 * or broadcast address if group key is deleted.
1011 * @key_idx: key index to be deleted
Ashok Ponnaiahf9953602018-01-11 15:39:26 +05301012 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301013 * This function gets called from ucfg to delete key
1014 *
1015 * Return: QDF_STATUS_SUCCESS - in case of success
1016 */
1017QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev,
1018 uint8_t *macaddr,
1019 uint8_t key_idx){
1020 struct wlan_crypto_comp_priv *crypto_priv;
1021 struct wlan_crypto_params *crypto_params;
1022 struct wlan_crypto_key *key;
1023 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301024 struct wlan_objmgr_psoc *psoc;
Disha Dasdf10f652018-12-10 16:20:56 +05301025 uint8_t bssid_mac[QDF_MAC_ADDR_SIZE];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301026
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301027 if (!vdev || !macaddr ||
Disha Das76210cd2018-04-10 12:44:14 +05301028 (key_idx >=
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301029 (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX))) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301030 crypto_err("Invalid param vdev %pK macaddr %pK keyidx %d",
1031 vdev, macaddr, key_idx);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301032 return QDF_STATUS_E_INVAL;
1033 }
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301034
1035 wlan_vdev_obj_lock(vdev);
Disha Dasdf10f652018-12-10 16:20:56 +05301036 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev),
1037 QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301038 psoc = wlan_vdev_get_psoc(vdev);
1039 if (!psoc) {
1040 wlan_vdev_obj_unlock(vdev);
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301041 crypto_err("psoc NULL");
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301042 return QDF_STATUS_E_INVAL;
1043 }
1044 wlan_vdev_obj_unlock(vdev);
1045
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301046 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)macaddr)) {
1047 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1048 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001049 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301050 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301051 return QDF_STATUS_E_INVAL;
1052 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301053 } else {
1054 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +05301055 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301056
Amir Pateld3385942018-05-03 23:01:08 +05301057 pdev_id = wlan_objmgr_pdev_get_pdev_id(
1058 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301059 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Amir Pateld3385942018-05-03 23:01:08 +05301060 psoc, pdev_id,
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301061 bssid_mac,
Amir Pateld3385942018-05-03 23:01:08 +05301062 macaddr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301063 WLAN_CRYPTO_ID);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001064 if (!peer) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301065 return QDF_STATUS_E_INVAL;
1066 }
1067 crypto_params = wlan_crypto_peer_get_comp_params(peer,
1068 &crypto_priv);
1069 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001070 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301071 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301072 return QDF_STATUS_E_INVAL;
1073 }
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301074 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301075
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301076 if (key_idx >= WLAN_CRYPTO_MAXKEYIDX) {
1077 uint8_t igtk_idx = key_idx - WLAN_CRYPTO_MAXKEYIDX;
Radhika Sriram00392f32018-04-04 19:04:49 +05301078 if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301079 crypto_err("Igtk key invalid keyid %d", igtk_idx);
Radhika Sriram00392f32018-04-04 19:04:49 +05301080 return QDF_STATUS_E_INVAL;
1081 }
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301082 key = crypto_priv->igtk_key[igtk_idx];
1083 crypto_priv->igtk_key[igtk_idx] = NULL;
Nandha Kishore Easwaranf832d982017-12-18 10:42:15 +05301084 if (key)
1085 key->valid = 0;
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301086 } else {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301087 key = crypto_priv->key[key_idx];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301088 crypto_priv->key[key_idx] = NULL;
1089 }
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301090
1091 if (!key)
1092 return QDF_STATUS_E_INVAL;
1093
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301094 if (key->valid) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301095 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
Gurumoorthi Gnanasambandhan612a9062019-02-08 16:26:42 +05301096 qdf_mem_zero(key->keyval, sizeof(key->keyval));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301097
Ashok Kumar39c0fea2019-09-06 16:42:20 +05301098 if (!IS_FILS_CIPHER(cipher_table->cipher) &&
1099 WLAN_CRYPTO_TX_OPS_DELKEY(psoc)) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301100 WLAN_CRYPTO_TX_OPS_DELKEY(psoc)(vdev, key,
1101 macaddr, cipher_table->cipher);
Ashok Kumar39c0fea2019-09-06 16:42:20 +05301102 } else if (IS_FILS_CIPHER(cipher_table->cipher)) {
1103 if (key->private)
1104 qdf_mem_free(key->private);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301105 }
1106 }
1107 qdf_mem_free(key);
1108
1109 return QDF_STATUS_SUCCESS;
1110}
1111
Kiran Kumar Lokere25531c42018-09-19 13:48:48 -07001112#ifdef CRYPTO_SET_KEY_CONVERGED
1113static QDF_STATUS wlan_crypto_set_default_key(struct wlan_objmgr_vdev *vdev,
1114 uint8_t key_idx, uint8_t *macaddr)
1115{
1116 return QDF_STATUS_SUCCESS;
1117}
1118#else
1119static QDF_STATUS wlan_crypto_set_default_key(struct wlan_objmgr_vdev *vdev,
1120 uint8_t key_idx, uint8_t *macaddr)
1121{
1122 struct wlan_objmgr_psoc *psoc;
1123
1124 psoc = wlan_vdev_get_psoc(vdev);
1125 if (!psoc) {
1126 crypto_err("psoc is NULL");
1127 return QDF_STATUS_E_INVAL;
1128 }
1129 if (WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)) {
1130 WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)(vdev, key_idx,
1131 macaddr);
1132 }
1133
1134 return QDF_STATUS_SUCCESS;
1135}
1136#endif
1137
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301138/**
1139 * wlan_crypto_default_key - called by ucfg to set default tx key
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301140 * @vdev: vdev
1141 * @mac_address: mac address of the peer for unicast key
1142 * or broadcast address if group key need to made default.
1143 * @key_idx: key index to be made as default key
1144 * @unicast: is key was unicast or group key.
Ashok Ponnaiahf9953602018-01-11 15:39:26 +05301145 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301146 * This function gets called from ucfg to set default key
1147 *
1148 * Return: QDF_STATUS_SUCCESS - in case of success
1149 */
1150QDF_STATUS wlan_crypto_default_key(struct wlan_objmgr_vdev *vdev,
1151 uint8_t *macaddr,
1152 uint8_t key_idx,
1153 bool unicast){
1154 struct wlan_crypto_comp_priv *crypto_priv;
1155 struct wlan_crypto_params *crypto_params;
1156 struct wlan_crypto_key *key;
1157 struct wlan_objmgr_psoc *psoc;
Disha Dasdf10f652018-12-10 16:20:56 +05301158 uint8_t bssid_mac[QDF_MAC_ADDR_SIZE];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301159
Disha Das55b86c22018-04-20 15:22:08 +05301160 if (!vdev || !macaddr || (key_idx >= WLAN_CRYPTO_MAXKEYIDX)) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301161 crypto_err("Invalid param vdev %pK macaddr %pK keyidx %d",
1162 vdev, macaddr, key_idx);
Disha Das55b86c22018-04-20 15:22:08 +05301163 return QDF_STATUS_E_INVAL;
1164 }
1165
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301166 wlan_vdev_obj_lock(vdev);
Disha Dasdf10f652018-12-10 16:20:56 +05301167 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev),
1168 QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301169 psoc = wlan_vdev_get_psoc(vdev);
1170 if (!psoc) {
1171 wlan_vdev_obj_unlock(vdev);
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301172 crypto_err("psoc NULL");
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301173 return QDF_STATUS_E_INVAL;
1174 }
1175 wlan_vdev_obj_unlock(vdev);
1176
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301177 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)macaddr)) {
1178 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1179 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001180 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301181 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301182 return QDF_STATUS_E_INVAL;
1183 }
1184
1185 key = crypto_priv->key[key_idx];
1186 if (!key)
1187 return QDF_STATUS_E_INVAL;
1188 } else {
1189 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +05301190 uint8_t pdev_id;
1191
1192 pdev_id = wlan_objmgr_pdev_get_pdev_id(
1193 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301194 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Amir Pateld3385942018-05-03 23:01:08 +05301195 psoc, pdev_id,
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301196 bssid_mac,
Amir Pateld3385942018-05-03 23:01:08 +05301197 macaddr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301198 WLAN_CRYPTO_ID);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301199
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001200 if (!peer) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301201 crypto_err("peer NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301202 return QDF_STATUS_E_INVAL;
1203 }
1204 crypto_params = wlan_crypto_peer_get_comp_params(peer,
1205 &crypto_priv);
1206 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001207 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301208 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301209 return QDF_STATUS_E_INVAL;
1210 }
1211
1212 key = crypto_priv->key[key_idx];
1213 if (!key)
1214 return QDF_STATUS_E_INVAL;
1215 }
1216 if (!key->valid)
1217 return QDF_STATUS_E_INVAL;
1218
Kiran Kumar Lokere25531c42018-09-19 13:48:48 -07001219 if (wlan_crypto_set_default_key(vdev, key_idx, macaddr) !=
1220 QDF_STATUS_SUCCESS)
1221 return QDF_STATUS_E_INVAL;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301222 crypto_priv->def_tx_keyid = key_idx;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301223
1224 return QDF_STATUS_SUCCESS;
1225}
1226
1227/**
1228 * wlan_crypto_encap - called by mgmt for encap the frame based on cipher
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301229 * @vdev: vdev
1230 * @wbuf: wbuf
1231 * @macaddr: macaddr
1232 * @encapdone: is encapdone already or not.
Ashok Ponnaiahf9953602018-01-11 15:39:26 +05301233 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301234 * This function gets called from mgmt txrx to encap frame.
1235 *
1236 * Return: QDF_STATUS_SUCCESS - in case of success
1237 */
1238QDF_STATUS wlan_crypto_encap(struct wlan_objmgr_vdev *vdev,
1239 qdf_nbuf_t wbuf,
1240 uint8_t *mac_addr,
1241 uint8_t encapdone){
1242 struct wlan_crypto_comp_priv *crypto_priv;
1243 struct wlan_crypto_params *crypto_params;
1244 struct wlan_crypto_key *key;
1245 QDF_STATUS status;
1246 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301247 struct wlan_objmgr_psoc *psoc;
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301248 struct wlan_objmgr_peer *peer;
Disha Dasdf10f652018-12-10 16:20:56 +05301249 uint8_t bssid_mac[QDF_MAC_ADDR_SIZE];
Amir Pateld3385942018-05-03 23:01:08 +05301250 uint8_t pdev_id;
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301251 uint8_t hdrlen;
1252 enum QDF_OPMODE opmode;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301253
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301254 opmode = wlan_vdev_mlme_get_opmode(vdev);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301255 wlan_vdev_obj_lock(vdev);
Disha Dasdf10f652018-12-10 16:20:56 +05301256 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev),
1257 QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301258 psoc = wlan_vdev_get_psoc(vdev);
1259 if (!psoc) {
1260 wlan_vdev_obj_unlock(vdev);
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301261 crypto_err("psoc NULL");
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301262 return QDF_STATUS_E_INVAL;
1263 }
1264 wlan_vdev_obj_unlock(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301265
Amir Pateld3385942018-05-03 23:01:08 +05301266 pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301267 /* FILS Encap required only for (Re-)Assoc response */
Amir Pateld3385942018-05-03 23:01:08 +05301268 peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr, WLAN_CRYPTO_ID);
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301269
1270 if (!wlan_crypto_is_data_protected((uint8_t *)qdf_nbuf_data(wbuf)) &&
1271 peer && !wlan_crypto_get_peer_fils_aead(peer)) {
1272 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1273 return QDF_STATUS_E_INVAL;
1274 }
1275
1276 if (peer)
1277 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1278
Keyur Parekh41386862018-04-09 23:31:39 -07001279 if (qdf_is_macaddr_group((struct qdf_mac_addr *)mac_addr)) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301280 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1281 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001282 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301283 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301284 return QDF_STATUS_E_INVAL;
1285 }
1286
1287 key = crypto_priv->key[crypto_priv->def_tx_keyid];
1288 if (!key)
1289 return QDF_STATUS_E_INVAL;
1290
1291 } else {
1292 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +05301293 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301294
Amir Pateld3385942018-05-03 23:01:08 +05301295 pdev_id = wlan_objmgr_pdev_get_pdev_id(
1296 wlan_vdev_get_pdev(vdev));
1297 peer = wlan_objmgr_get_peer_by_mac_n_vdev(psoc, pdev_id,
1298 bssid_mac, mac_addr,
1299 WLAN_CRYPTO_ID);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301300
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001301 if (!peer) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301302 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301303 return QDF_STATUS_E_INVAL;
1304 }
1305 crypto_params = wlan_crypto_peer_get_comp_params(peer,
1306 &crypto_priv);
1307 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1308
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001309 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301310 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301311 return QDF_STATUS_E_INVAL;
1312 }
1313
1314 key = crypto_priv->key[crypto_priv->def_tx_keyid];
1315 if (!key)
1316 return QDF_STATUS_E_INVAL;
1317 }
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301318 if (opmode == QDF_MONITOR_MODE)
1319 hdrlen = ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf));
1320 else
1321 hdrlen = ieee80211_hdrspace(wlan_vdev_get_pdev(vdev),
1322 (uint8_t *)qdf_nbuf_data(wbuf));
1323
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301324 /* if tkip, is counter measures enabled, then drop the frame */
1325 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
1326 status = cipher_table->encap(key, wbuf, encapdone,
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301327 hdrlen);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301328
1329 return status;
1330}
Manikandan Mohana2993a52018-03-01 16:21:55 -08001331qdf_export_symbol(wlan_crypto_encap);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301332
1333/**
1334 * wlan_crypto_decap - called by mgmt for decap the frame based on cipher
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301335 * @vdev: vdev
1336 * @wbuf: wbuf
1337 * @macaddr: macaddr
1338 * @tid: tid of the frame
Ashok Ponnaiahf9953602018-01-11 15:39:26 +05301339 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301340 * This function gets called from mgmt txrx to decap frame.
1341 *
1342 * Return: QDF_STATUS_SUCCESS - in case of success
1343 */
1344QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev,
1345 qdf_nbuf_t wbuf,
1346 uint8_t *mac_addr,
1347 uint8_t tid){
1348 struct wlan_crypto_comp_priv *crypto_priv;
1349 struct wlan_crypto_params *crypto_params;
1350 struct wlan_crypto_key *key;
1351 QDF_STATUS status;
1352 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301353 struct wlan_objmgr_psoc *psoc;
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301354 struct wlan_objmgr_peer *peer;
Disha Dasdf10f652018-12-10 16:20:56 +05301355 uint8_t bssid_mac[QDF_MAC_ADDR_SIZE];
Ashok Ponnaiahe25c64c2018-04-09 15:34:14 +05301356 uint8_t keyid;
Amir Pateld3385942018-05-03 23:01:08 +05301357 uint8_t pdev_id;
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301358 uint8_t hdrlen;
1359 enum QDF_OPMODE opmode;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301360
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301361 opmode = wlan_vdev_mlme_get_opmode(vdev);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301362 wlan_vdev_obj_lock(vdev);
Disha Dasdf10f652018-12-10 16:20:56 +05301363 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev),
1364 QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301365 psoc = wlan_vdev_get_psoc(vdev);
1366 if (!psoc) {
1367 wlan_vdev_obj_unlock(vdev);
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301368 crypto_err("psoc NULL");
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301369 return QDF_STATUS_E_INVAL;
1370 }
1371 wlan_vdev_obj_unlock(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301372
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301373 if (opmode == QDF_MONITOR_MODE)
1374 hdrlen = ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf));
1375 else
1376 hdrlen = ieee80211_hdrspace(wlan_vdev_get_pdev(vdev),
1377 (uint8_t *)qdf_nbuf_data(wbuf));
1378
Padma Raghunathan51d11032018-04-09 10:21:37 +05301379 keyid = wlan_crypto_get_keyid((uint8_t *)qdf_nbuf_data(wbuf), hdrlen);
Ashok Ponnaiahe25c64c2018-04-09 15:34:14 +05301380
1381 if (keyid >= WLAN_CRYPTO_MAXKEYIDX)
1382 return QDF_STATUS_E_INVAL;
1383
Amir Pateld3385942018-05-03 23:01:08 +05301384 pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301385 /* FILS Decap required only for (Re-)Assoc request */
Amir Pateld3385942018-05-03 23:01:08 +05301386 peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr, WLAN_CRYPTO_ID);
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05301387
1388 if (!wlan_crypto_is_data_protected((uint8_t *)qdf_nbuf_data(wbuf)) &&
1389 peer && !wlan_crypto_get_peer_fils_aead(peer)) {
1390 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1391 return QDF_STATUS_E_INVAL;
1392 }
1393
1394 if (peer)
1395 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1396
Keyur Parekh41386862018-04-09 23:31:39 -07001397 if (qdf_is_macaddr_group((struct qdf_mac_addr *)mac_addr)) {
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301398 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1399 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001400 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301401 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301402 return QDF_STATUS_E_INVAL;
1403 }
1404
Ashok Ponnaiahe25c64c2018-04-09 15:34:14 +05301405 key = crypto_priv->key[keyid];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301406 if (!key)
1407 return QDF_STATUS_E_INVAL;
1408
1409 } else {
1410 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +05301411 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301412
Amir Pateld3385942018-05-03 23:01:08 +05301413 pdev_id = wlan_objmgr_pdev_get_pdev_id(
1414 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301415 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Amir Pateld3385942018-05-03 23:01:08 +05301416 psoc, pdev_id, bssid_mac,
1417 mac_addr, WLAN_CRYPTO_ID);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001418 if (!peer) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301419 crypto_err("peer NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301420 return QDF_STATUS_E_INVAL;
1421 }
1422
1423 crypto_params = wlan_crypto_peer_get_comp_params(peer,
1424 &crypto_priv);
1425 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1426
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001427 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301428 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301429 return QDF_STATUS_E_INVAL;
1430 }
1431
Ashok Ponnaiahe25c64c2018-04-09 15:34:14 +05301432 key = crypto_priv->key[keyid];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301433 if (!key)
1434 return QDF_STATUS_E_INVAL;
1435 }
1436 /* if tkip, is counter measures enabled, then drop the frame */
1437 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301438 status = cipher_table->decap(key, wbuf, tid, hdrlen);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301439
1440 return status;
1441}
Manikandan Mohana2993a52018-03-01 16:21:55 -08001442qdf_export_symbol(wlan_crypto_decap);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301443/**
1444 * wlan_crypto_enmic - called by mgmt for adding mic in frame based on cipher
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301445 * @vdev: vdev
1446 * @wbuf: wbuf
1447 * @macaddr: macaddr
1448 * @encapdone: is encapdone already or not.
Ashok Ponnaiahf9953602018-01-11 15:39:26 +05301449 *
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301450 * This function gets called from mgmt txrx to adding mic to the frame.
1451 *
1452 * Return: QDF_STATUS_SUCCESS - in case of success
1453 */
1454QDF_STATUS wlan_crypto_enmic(struct wlan_objmgr_vdev *vdev,
1455 qdf_nbuf_t wbuf,
1456 uint8_t *mac_addr,
1457 uint8_t encapdone){
1458 struct wlan_crypto_comp_priv *crypto_priv;
1459 struct wlan_crypto_params *crypto_params;
1460 struct wlan_crypto_key *key;
1461 QDF_STATUS status;
1462 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301463 struct wlan_objmgr_psoc *psoc;
Disha Dasdf10f652018-12-10 16:20:56 +05301464 uint8_t bssid_mac[QDF_MAC_ADDR_SIZE];
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301465 uint8_t hdrlen;
1466 enum QDF_OPMODE opmode;
1467
1468 opmode = wlan_vdev_mlme_get_opmode(vdev);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301469
Amir Pateld3385942018-05-03 23:01:08 +05301470
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301471 wlan_vdev_obj_lock(vdev);
Disha Dasdf10f652018-12-10 16:20:56 +05301472 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev),
1473 QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301474 psoc = wlan_vdev_get_psoc(vdev);
1475 if (!psoc) {
1476 wlan_vdev_obj_unlock(vdev);
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301477 crypto_err("psoc NULL");
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301478 return QDF_STATUS_E_INVAL;
1479 }
1480 wlan_vdev_obj_unlock(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301481
1482 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac_addr)) {
1483 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1484 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001485 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301486 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301487 return QDF_STATUS_E_INVAL;
1488 }
1489
1490 key = crypto_priv->key[crypto_priv->def_tx_keyid];
1491 if (!key)
1492 return QDF_STATUS_E_INVAL;
1493
1494 } else {
1495 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +05301496 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301497
Amir Pateld3385942018-05-03 23:01:08 +05301498 pdev_id = wlan_objmgr_pdev_get_pdev_id(
1499 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301500 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Amir Pateld3385942018-05-03 23:01:08 +05301501 psoc, pdev_id, bssid_mac,
1502 mac_addr, WLAN_CRYPTO_ID);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001503 if (!peer) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301504 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301505 return QDF_STATUS_E_INVAL;
1506 }
1507
1508 crypto_params = wlan_crypto_peer_get_comp_params(peer,
1509 &crypto_priv);
1510 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1511
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001512 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301513 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301514 return QDF_STATUS_E_INVAL;
1515 }
1516
1517 key = crypto_priv->key[crypto_priv->def_tx_keyid];
1518 if (!key)
1519 return QDF_STATUS_E_INVAL;
1520 }
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301521 if (opmode == QDF_MONITOR_MODE)
1522 hdrlen = ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf));
1523 else
1524 hdrlen = ieee80211_hdrspace(wlan_vdev_get_pdev(vdev),
1525 (uint8_t *)qdf_nbuf_data(wbuf));
1526
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301527 /* if tkip, is counter measures enabled, then drop the frame */
1528 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301529 status = cipher_table->enmic(key, wbuf, encapdone, hdrlen);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301530
1531 return status;
1532}
1533
1534/**
1535 * wlan_crypto_demic - called by mgmt for remove and check mic for
1536 * the frame based on cipher
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301537 * @vdev: vdev
1538 * @wbuf: wbuf
1539 * @macaddr: macaddr
1540 * @tid: tid of the frame
Padma Raghunathan43ebaa72018-04-30 09:46:38 +05301541 * @keyid: keyid in the received frame
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301542 * This function gets called from mgmt txrx to decap frame.
1543 *
1544 * Return: QDF_STATUS_SUCCESS - in case of success
1545 */
1546QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev,
Padma Raghunathan43ebaa72018-04-30 09:46:38 +05301547 qdf_nbuf_t wbuf,
1548 uint8_t *mac_addr,
1549 uint8_t tid,
1550 uint8_t keyid){
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301551 struct wlan_crypto_comp_priv *crypto_priv;
1552 struct wlan_crypto_params *crypto_params;
1553 struct wlan_crypto_key *key;
1554 QDF_STATUS status;
1555 struct wlan_crypto_cipher *cipher_table;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301556 struct wlan_objmgr_psoc *psoc;
Disha Dasdf10f652018-12-10 16:20:56 +05301557 uint8_t bssid_mac[QDF_MAC_ADDR_SIZE];
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301558 uint8_t hdrlen;
1559 enum QDF_OPMODE opmode;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301560
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301561 opmode = wlan_vdev_mlme_get_opmode(vdev);
1562
1563 if (opmode == QDF_MONITOR_MODE)
1564 hdrlen = ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf));
1565 else
1566 hdrlen = ieee80211_hdrspace(wlan_vdev_get_pdev(vdev),
1567 (uint8_t *)qdf_nbuf_data(wbuf));
Amir Pateld3385942018-05-03 23:01:08 +05301568
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301569 wlan_vdev_obj_lock(vdev);
Disha Dasdf10f652018-12-10 16:20:56 +05301570 qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev),
1571 QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301572 psoc = wlan_vdev_get_psoc(vdev);
1573 if (!psoc) {
1574 wlan_vdev_obj_unlock(vdev);
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301575 crypto_err("psoc NULL");
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05301576 return QDF_STATUS_E_INVAL;
1577 }
1578 wlan_vdev_obj_unlock(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301579
1580 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac_addr)) {
1581 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1582 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001583 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301584 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301585 return QDF_STATUS_E_INVAL;
1586 }
1587
Padma Raghunathan43ebaa72018-04-30 09:46:38 +05301588 key = crypto_priv->key[keyid];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301589 if (!key)
1590 return QDF_STATUS_E_INVAL;
1591
1592 } else {
1593 struct wlan_objmgr_peer *peer;
Amir Pateld3385942018-05-03 23:01:08 +05301594 uint8_t pdev_id;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301595
Amir Pateld3385942018-05-03 23:01:08 +05301596 pdev_id = wlan_objmgr_pdev_get_pdev_id(
1597 wlan_vdev_get_pdev(vdev));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301598 peer = wlan_objmgr_get_peer_by_mac_n_vdev(
Amir Pateld3385942018-05-03 23:01:08 +05301599 psoc, pdev_id, bssid_mac,
1600 mac_addr, WLAN_CRYPTO_ID);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001601 if (!peer) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301602 crypto_err("peer NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301603 return QDF_STATUS_E_INVAL;
1604 }
1605
1606 crypto_params = wlan_crypto_peer_get_comp_params(peer,
1607 &crypto_priv);
1608 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
1609
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001610 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301611 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301612 return QDF_STATUS_E_INVAL;
1613 }
1614
Padma Raghunathan43ebaa72018-04-30 09:46:38 +05301615 key = crypto_priv->key[keyid];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301616 if (!key)
1617 return QDF_STATUS_E_INVAL;
1618 }
1619 /* if tkip, is counter measures enabled, then drop the frame */
1620 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
Padma Raghunathan6ac61432018-04-27 15:01:25 +05301621 status = cipher_table->demic(key, wbuf, tid, hdrlen);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301622
1623 return status;
1624}
1625
1626/**
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301627 * wlan_crypto_vdev_is_pmf_enabled - called to check is pmf enabled in vdev
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301628 * @vdev: vdev
1629 *
1630 * This function gets called to check is pmf enabled or not in vdev.
1631 *
1632 * Return: true or false
1633 */
1634bool wlan_crypto_vdev_is_pmf_enabled(struct wlan_objmgr_vdev *vdev)
1635{
1636
1637 struct wlan_crypto_comp_priv *crypto_priv;
1638 struct wlan_crypto_params *vdev_crypto_params;
1639
1640 if (!vdev)
1641 return false;
1642 vdev_crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1643 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001644 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301645 crypto_err("crypto_priv NULL");
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301646 return QDF_STATUS_E_INVAL;
1647 }
1648
1649 if ((vdev_crypto_params->rsn_caps &
1650 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)
1651 || (vdev_crypto_params->rsn_caps &
1652 WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)) {
1653 return true;
1654 }
1655
1656 return false;
1657}
Min Liua3bad2b2019-03-25 11:48:49 +08001658
1659/**
1660 * wlan_crypto_vdev_is_pmf_required - called to check is pmf required in vdev
1661 * @vdev: vdev
1662 *
1663 * This function gets called to check is pmf required or not in vdev.
1664 *
1665 * Return: true or false
1666 */
1667bool wlan_crypto_vdev_is_pmf_required(struct wlan_objmgr_vdev *vdev)
1668{
1669 struct wlan_crypto_comp_priv *crypto_priv;
1670 struct wlan_crypto_params *vdev_crypto_params;
1671
1672 if (!vdev)
1673 return false;
1674
1675 vdev_crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1676 &crypto_priv);
1677 if (!crypto_priv) {
1678 crypto_err("crypto_priv NULL");
1679 return QDF_STATUS_E_INVAL;
1680 }
1681
1682 if (vdev_crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)
1683 return true;
1684
1685 return false;
1686}
1687
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301688/**
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301689 * wlan_crypto_is_pmf_enabled - called by mgmt txrx to check is pmf enabled
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301690 * @vdev: vdev
1691 * @peer: peer
1692 *
1693 * This function gets called by mgmt txrx to check is pmf enabled or not.
1694 *
1695 * Return: true or false
1696 */
1697bool wlan_crypto_is_pmf_enabled(struct wlan_objmgr_vdev *vdev,
1698 struct wlan_objmgr_peer *peer){
1699
1700 struct wlan_crypto_comp_priv *crypto_priv;
1701 struct wlan_crypto_params *vdev_crypto_params;
1702 struct wlan_crypto_params *peer_crypto_params;
1703
1704 if (!vdev || !peer)
1705 return false;
1706 vdev_crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1707 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001708 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301709 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301710 return QDF_STATUS_E_INVAL;
1711 }
1712
1713 peer_crypto_params = wlan_crypto_peer_get_comp_params(peer,
1714 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001715 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301716 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301717 return QDF_STATUS_E_INVAL;
1718 }
1719 if (((vdev_crypto_params->rsn_caps &
1720 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) &&
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301721 (peer_crypto_params->rsn_caps &
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301722 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED))
1723 || (vdev_crypto_params->rsn_caps &
1724 WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)) {
1725 return true;
1726 }
1727
1728 return false;
1729}
Ashok Ponnaiah7a41e8c2017-12-28 17:13:40 +05301730
Disha Das07721fc2019-07-26 10:49:12 +05301731/**
1732 * wlan_crypto_is_key_valid - called by mgmt txrx to check if key is valid
1733 * @vdev: vdev
1734 * @peer: peer
1735 * @keyidx : key index
1736 *
1737 * This function gets called by mgmt txrx to check if key is valid
1738 *
1739 * Return: true or false
1740 */
1741bool wlan_crypto_is_key_valid(struct wlan_objmgr_vdev *vdev,
1742 struct wlan_objmgr_peer *peer,
1743 uint16_t keyidx)
1744{
1745 struct wlan_crypto_key *key = NULL;
1746
1747 if (!vdev && !peer)
1748 return false;
1749
1750 if (peer)
1751 key = wlan_crypto_peer_getkey(peer, keyidx);
1752 else if (vdev)
1753 key = wlan_crypto_vdev_getkey(vdev, keyidx);
1754
1755 if ((key) && key->valid)
1756 return true;
1757
1758 return false;
1759}
1760
Ashok Ponnaiah7a41e8c2017-12-28 17:13:40 +05301761static void wlan_crypto_gmac_pn_swap(uint8_t *a, uint8_t *b)
1762{
1763 a[0] = b[5];
1764 a[1] = b[4];
1765 a[2] = b[3];
1766 a[3] = b[2];
1767 a[4] = b[1];
1768 a[5] = b[0];
1769}
1770
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301771/**
1772 * wlan_crypto_add_mmie - called by mgmt txrx to add mmie in frame
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301773 * @vdev: vdev
1774 * @bfrm: frame starting pointer
1775 * @len: length of the frame
1776 *
1777 * This function gets called by mgmt txrx to add mmie in frame
1778 *
1779 * Return: end of frame or NULL in case failure
1780 */
1781uint8_t *wlan_crypto_add_mmie(struct wlan_objmgr_vdev *vdev,
1782 uint8_t *bfrm,
1783 uint32_t len) {
1784 struct wlan_crypto_key *key;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301785 struct wlan_crypto_mmie *mmie;
1786 uint8_t *pn, *aad, *buf, *efrm, nounce[12];
Disha Dasdf10f652018-12-10 16:20:56 +05301787 struct wlan_frame_hdr *hdr;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301788 uint32_t i, hdrlen, mic_len, aad_len;
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301789 uint8_t mic[16];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301790 struct wlan_crypto_comp_priv *crypto_priv;
1791 struct wlan_crypto_params *crypto_params;
Disha Das55b86c22018-04-20 15:22:08 +05301792 int32_t ret = -1;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301793
1794 if (!bfrm) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301795 crypto_err("frame is NULL");
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301796 return NULL;
1797 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301798
1799 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
1800 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001801 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301802 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301803 return NULL;
1804 }
1805
Disha Das76210cd2018-04-10 12:44:14 +05301806 if (crypto_priv->def_igtk_tx_keyid >= WLAN_CRYPTO_MAXIGTKKEYIDX) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301807 crypto_err("igtk key invalid keyid %d",
1808 crypto_priv->def_igtk_tx_keyid);
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301809 return NULL;
1810 }
1811
1812 key = crypto_priv->igtk_key[crypto_priv->def_igtk_tx_keyid];
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301813 if (!key) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301814 crypto_err("No igtk key present");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301815 return NULL;
1816 }
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301817 mic_len = (crypto_priv->igtk_key_type
1818 == WLAN_CRYPTO_CIPHER_AES_CMAC) ? 8 : 16;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301819
1820 efrm = bfrm + len;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301821 aad_len = 20;
Disha Dasdf10f652018-12-10 16:20:56 +05301822 hdrlen = sizeof(struct wlan_frame_hdr);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301823 len += sizeof(struct wlan_crypto_mmie);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301824
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301825 mmie = (struct wlan_crypto_mmie *) efrm;
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301826 qdf_mem_zero((unsigned char *)mmie, sizeof(*mmie));
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301827 mmie->element_id = WLAN_ELEMID_MMIE;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301828 mmie->length = sizeof(*mmie) - 2;
1829 mmie->key_id = qdf_cpu_to_le16(key->keyix);
1830
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301831 mic_len = (crypto_priv->igtk_key_type
1832 == WLAN_CRYPTO_CIPHER_AES_CMAC) ? 8 : 16;
1833 if (mic_len == 8) {
1834 mmie->length -= 8;
1835 len -= 8;
1836 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301837 /* PN = PN + 1 */
1838 pn = (uint8_t *)&key->keytsc;
1839
1840 for (i = 0; i <= 5; i++) {
1841 pn[i]++;
1842 if (pn[i])
1843 break;
1844 }
1845
1846 /* Copy IPN */
1847 qdf_mem_copy(mmie->sequence_number, pn, 6);
1848
Disha Dasdf10f652018-12-10 16:20:56 +05301849 hdr = (struct wlan_frame_hdr *) bfrm;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301850
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301851 buf = qdf_mem_malloc(len - hdrlen + 20);
Madhvapathi Sriramb73fc282019-01-07 09:12:25 +05301852 if (!buf)
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301853 return NULL;
Madhvapathi Sriramb73fc282019-01-07 09:12:25 +05301854
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301855 qdf_mem_zero(buf, len - hdrlen + 20);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301856 aad = buf;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301857 /* generate BIP AAD: FC(masked) || A1 || A2 || A3 */
1858
1859 /* FC type/subtype */
Disha Dasdf10f652018-12-10 16:20:56 +05301860 aad[0] = hdr->i_fc[0];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301861 /* Mask FC Retry, PwrMgt, MoreData flags to zero */
Disha Dasdf10f652018-12-10 16:20:56 +05301862 aad[1] = (hdr->i_fc[1] & ~(WLAN_FC1_RETRY | WLAN_FC1_PWRMGT
Padma Raghunathan94921612018-04-30 10:02:09 +05301863 | WLAN_FC1_MOREDATA));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301864 /* A1 || A2 || A3 */
Disha Dasdf10f652018-12-10 16:20:56 +05301865 qdf_mem_copy(aad + 2, hdr->i_addr1, QDF_MAC_ADDR_SIZE);
1866 qdf_mem_copy(aad + 8, hdr->i_addr2, QDF_MAC_ADDR_SIZE);
1867 qdf_mem_copy(aad + 14, hdr->i_addr3, QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301868 qdf_mem_zero(mic, 16);
1869
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301870 /*
1871 * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
1872 */
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301873
1874 qdf_mem_copy(buf + aad_len, bfrm + hdrlen, len - hdrlen);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301875 if (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_CMAC) {
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301876
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301877 ret = omac1_aes_128(key->keyval, buf,
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301878 len + aad_len - hdrlen, mic);
1879 qdf_mem_copy(mmie->mic, mic, 8);
1880
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301881 } else if (crypto_priv->igtk_key_type
1882 == WLAN_CRYPTO_CIPHER_AES_CMAC_256) {
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301883
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301884 ret = omac1_aes_256(key->keyval, buf,
1885 len + aad_len - hdrlen, mmie->mic);
1886 } else if ((crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_GMAC)
1887 || (crypto_priv->igtk_key_type
1888 == WLAN_CRYPTO_CIPHER_AES_GMAC_256)) {
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301889
Disha Dasdf10f652018-12-10 16:20:56 +05301890 qdf_mem_copy(nounce, hdr->i_addr2, QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah7a41e8c2017-12-28 17:13:40 +05301891 wlan_crypto_gmac_pn_swap(nounce + 6, pn);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301892 ret = wlan_crypto_aes_gmac(key->keyval, key->keylen, nounce,
1893 sizeof(nounce), buf,
1894 len + aad_len - hdrlen, mmie->mic);
1895 }
1896 qdf_mem_free(buf);
1897 if (ret < 0) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301898 crypto_err("add mmie failed");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301899 return NULL;
1900 }
1901
1902 return bfrm + len;
1903}
1904
1905/**
1906 * wlan_crypto_is_mmie_valid - called by mgmt txrx to check mmie of the frame
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301907 * @vdev: vdev
1908 * @frm: frame starting pointer
1909 * @efrm: end of frame pointer
1910 *
1911 * This function gets called by mgmt txrx to check mmie of the frame
1912 *
1913 * Return: true or false
1914 */
1915bool wlan_crypto_is_mmie_valid(struct wlan_objmgr_vdev *vdev,
1916 uint8_t *frm,
1917 uint8_t *efrm){
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301918 struct wlan_crypto_mmie *mmie = NULL;
1919 uint8_t *ipn, *aad, *buf, mic[16], nounce[12];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301920 struct wlan_crypto_key *key;
Disha Dasdf10f652018-12-10 16:20:56 +05301921 struct wlan_frame_hdr *hdr;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301922 uint16_t mic_len, hdrlen, len;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301923 struct wlan_crypto_comp_priv *crypto_priv;
1924 struct wlan_crypto_params *crypto_params;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301925 uint8_t aad_len = 20;
Disha Das55b86c22018-04-20 15:22:08 +05301926 int32_t ret = -1;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301927
1928 /* check if frame is illegal length */
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301929 if (!frm || !efrm || (efrm < frm)
Disha Dasdf10f652018-12-10 16:20:56 +05301930 || ((efrm - frm) < sizeof(struct wlan_frame_hdr))) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301931 crypto_err("Invalid params");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301932 return false;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301933 }
1934 len = efrm - frm;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301935 crypto_priv = (struct wlan_crypto_comp_priv *)
1936 wlan_get_vdev_crypto_obj(vdev);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001937 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301938 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301939 return false;
1940 }
1941
1942 crypto_params = &(crypto_priv->crypto_params);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301943
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301944
1945 mic_len = (crypto_priv->igtk_key_type
1946 == WLAN_CRYPTO_CIPHER_AES_CMAC) ? 8 : 16;
Disha Dasdf10f652018-12-10 16:20:56 +05301947 hdrlen = sizeof(struct wlan_frame_hdr);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301948
1949 if (mic_len == 8)
1950 mmie = (struct wlan_crypto_mmie *)(efrm - sizeof(*mmie) + 8);
1951 else
1952 mmie = (struct wlan_crypto_mmie *)(efrm - sizeof(*mmie));
1953
1954
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301955 /* check Elem ID*/
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07001956 if ((!mmie) || (mmie->element_id != WLAN_ELEMID_MMIE)) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301957 crypto_err("IE is not MMIE");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301958 return false;
1959 }
1960
Disha Das76210cd2018-04-10 12:44:14 +05301961 if (mmie->key_id >= (WLAN_CRYPTO_MAXKEYIDX +
Disha Das55b86c22018-04-20 15:22:08 +05301962 WLAN_CRYPTO_MAXIGTKKEYIDX) ||
1963 (mmie->key_id < WLAN_CRYPTO_MAXKEYIDX)) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301964 crypto_err("keyid not valid");
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301965 return false;
1966 }
1967
1968 key = crypto_priv->igtk_key[mmie->key_id - WLAN_CRYPTO_MAXKEYIDX];
1969 if (!key) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301970 crypto_err("No igtk key present");
Nandha Kishore Easwaranb0ac3692017-12-08 10:39:00 +05301971 return false;
1972 }
1973
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301974 /* validate ipn */
1975 ipn = mmie->sequence_number;
1976 if (qdf_mem_cmp(ipn, key->keyrsc, 6) <= 0) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05301977 uint8_t *su = (uint8_t *)key->keyrsc;
1978 uint8_t *end = ipn + 6;
1979
1980 crypto_err("replay error :");
1981 while (ipn < end) {
1982 crypto_err("expected pn = %x received pn = %x",
1983 *ipn++, *su++);
1984 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301985 return false;
1986 }
1987
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05301988 buf = qdf_mem_malloc(len - hdrlen + 20);
Madhvapathi Sriramb73fc282019-01-07 09:12:25 +05301989 if (!buf)
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301990 return false;
Madhvapathi Sriramb73fc282019-01-07 09:12:25 +05301991
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05301992 aad = buf;
1993
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301994 /* construct AAD */
Disha Dasdf10f652018-12-10 16:20:56 +05301995 hdr = (struct wlan_frame_hdr *)frm;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05301996 /* generate BIP AAD: FC(masked) || A1 || A2 || A3 */
1997
1998 /* FC type/subtype */
Disha Dasdf10f652018-12-10 16:20:56 +05301999 aad[0] = hdr->i_fc[0];
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302000 /* Mask FC Retry, PwrMgt, MoreData flags to zero */
Disha Dasdf10f652018-12-10 16:20:56 +05302001 aad[1] = (hdr->i_fc[1] & ~(WLAN_FC1_RETRY | WLAN_FC1_PWRMGT
Padma Raghunathan94921612018-04-30 10:02:09 +05302002 | WLAN_FC1_MOREDATA));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302003 /* A1 || A2 || A3 */
Disha Dasdf10f652018-12-10 16:20:56 +05302004 qdf_mem_copy(aad + 2, hdr->i_addr1, 3 * QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302005
2006 /*
2007 * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
2008 */
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302009 qdf_mem_copy(buf + 20, frm + hdrlen, len - hdrlen);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05302010 qdf_mem_zero(buf + (len - hdrlen + 20 - mic_len), mic_len);
2011 qdf_mem_zero(mic, 16);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302012 if (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_CMAC) {
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302013 ret = omac1_aes_128(key->keyval, buf,
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05302014 len - hdrlen + aad_len, mic);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302015 } else if (crypto_priv->igtk_key_type
2016 == WLAN_CRYPTO_CIPHER_AES_CMAC_256) {
2017 ret = omac1_aes_256(key->keyval, buf,
2018 len + aad_len - hdrlen, mic);
2019 } else if ((crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_GMAC)
2020 || (crypto_priv->igtk_key_type
2021 == WLAN_CRYPTO_CIPHER_AES_GMAC_256)) {
Disha Dasdf10f652018-12-10 16:20:56 +05302022 qdf_mem_copy(nounce, hdr->i_addr2, QDF_MAC_ADDR_SIZE);
Ashok Ponnaiah7a41e8c2017-12-28 17:13:40 +05302023 wlan_crypto_gmac_pn_swap(nounce + 6, ipn);
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302024 ret = wlan_crypto_aes_gmac(key->keyval, key->keylen, nounce,
2025 sizeof(nounce), buf,
2026 len + aad_len - hdrlen, mic);
2027 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302028
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302029 qdf_mem_free(buf);
2030
2031 if (ret < 0) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05302032 crypto_err("genarate mmie failed");
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302033 return false;
2034 }
2035
2036 if (qdf_mem_cmp(mic, mmie->mic, mic_len) != 0) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05302037 crypto_err("mmie mismatch");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302038 /* MMIE MIC mismatch */
2039 return false;
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302040 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302041
2042 /* Update the receive sequence number */
2043 qdf_mem_copy(key->keyrsc, ipn, 6);
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05302044 crypto_debug("mmie matched");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302045
2046 return true;
2047}
2048
2049
2050static int32_t wlan_crypto_wpa_cipher_to_suite(uint32_t cipher)
2051{
2052 int32_t status = -1;
2053
2054 switch (cipher) {
2055 case WLAN_CRYPTO_CIPHER_TKIP:
2056 return WPA_CIPHER_SUITE_TKIP;
2057 case WLAN_CRYPTO_CIPHER_AES_CCM:
2058 return WPA_CIPHER_SUITE_CCMP;
2059 case WLAN_CRYPTO_CIPHER_NONE:
2060 return WPA_CIPHER_SUITE_NONE;
2061 }
2062
2063 return status;
2064}
2065
2066static int32_t wlan_crypto_rsn_cipher_to_suite(uint32_t cipher)
2067{
2068 int32_t status = -1;
2069
2070 switch (cipher) {
2071 case WLAN_CRYPTO_CIPHER_TKIP:
2072 return RSN_CIPHER_SUITE_TKIP;
2073 case WLAN_CRYPTO_CIPHER_AES_CCM:
2074 return RSN_CIPHER_SUITE_CCMP;
2075 case WLAN_CRYPTO_CIPHER_AES_CCM_256:
2076 return RSN_CIPHER_SUITE_CCMP_256;
2077 case WLAN_CRYPTO_CIPHER_AES_GCM:
2078 return RSN_CIPHER_SUITE_GCMP;
2079 case WLAN_CRYPTO_CIPHER_AES_GCM_256:
2080 return RSN_CIPHER_SUITE_GCMP_256;
2081 case WLAN_CRYPTO_CIPHER_AES_CMAC:
2082 return RSN_CIPHER_SUITE_AES_CMAC;
2083 case WLAN_CRYPTO_CIPHER_AES_CMAC_256:
2084 return RSN_CIPHER_SUITE_BIP_CMAC_256;
2085 case WLAN_CRYPTO_CIPHER_AES_GMAC:
2086 return RSN_CIPHER_SUITE_BIP_GMAC_128;
2087 case WLAN_CRYPTO_CIPHER_AES_GMAC_256:
2088 return RSN_CIPHER_SUITE_BIP_GMAC_256;
2089 case WLAN_CRYPTO_CIPHER_NONE:
2090 return RSN_CIPHER_SUITE_NONE;
2091 }
2092
2093 return status;
2094}
2095
2096/*
2097 * Convert an RSN key management/authentication algorithm
2098 * to an internal code.
2099 */
2100static int32_t
2101wlan_crypto_rsn_keymgmt_to_suite(uint32_t keymgmt)
2102{
2103 int32_t status = -1;
2104
2105 switch (keymgmt) {
2106 case WLAN_CRYPTO_KEY_MGMT_NONE:
2107 return RSN_AUTH_KEY_MGMT_NONE;
2108 case WLAN_CRYPTO_KEY_MGMT_IEEE8021X:
2109 return RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
2110 case WLAN_CRYPTO_KEY_MGMT_PSK:
2111 return RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
2112 case WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X:
2113 return RSN_AUTH_KEY_MGMT_FT_802_1X;
2114 case WLAN_CRYPTO_KEY_MGMT_FT_PSK:
2115 return RSN_AUTH_KEY_MGMT_FT_PSK;
2116 case WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256:
2117 return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
2118 case WLAN_CRYPTO_KEY_MGMT_PSK_SHA256:
2119 return RSN_AUTH_KEY_MGMT_PSK_SHA256;
2120 case WLAN_CRYPTO_KEY_MGMT_SAE:
2121 return RSN_AUTH_KEY_MGMT_SAE;
2122 case WLAN_CRYPTO_KEY_MGMT_FT_SAE:
2123 return RSN_AUTH_KEY_MGMT_FT_SAE;
2124 case WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B:
2125 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
2126 case WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192:
2127 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
2128 case WLAN_CRYPTO_KEY_MGMT_CCKM:
2129 return RSN_AUTH_KEY_MGMT_CCKM;
2130 case WLAN_CRYPTO_KEY_MGMT_OSEN:
2131 return RSN_AUTH_KEY_MGMT_OSEN;
Ashok Ponnaiahc6d59102018-05-16 16:25:05 +05302132 case WLAN_CRYPTO_KEY_MGMT_FILS_SHA256:
2133 return RSN_AUTH_KEY_MGMT_FILS_SHA256;
2134 case WLAN_CRYPTO_KEY_MGMT_FILS_SHA384:
2135 return RSN_AUTH_KEY_MGMT_FILS_SHA384;
2136 case WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256:
2137 return RSN_AUTH_KEY_MGMT_FT_FILS_SHA256;
2138 case WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384:
2139 return RSN_AUTH_KEY_MGMT_FT_FILS_SHA384;
2140 case WLAN_CRYPTO_KEY_MGMT_OWE:
2141 return RSN_AUTH_KEY_MGMT_OWE;
2142 case WLAN_CRYPTO_KEY_MGMT_DPP:
2143 return RSN_AUTH_KEY_MGMT_DPP;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302144 }
2145
2146 return status;
2147}
2148
2149/*
2150 * Convert an RSN key management/authentication algorithm
2151 * to an internal code.
2152 */
2153static int32_t
2154wlan_crypto_wpa_keymgmt_to_suite(uint32_t keymgmt)
2155{
2156 int32_t status = -1;
2157
2158 switch (keymgmt) {
2159 case WLAN_CRYPTO_KEY_MGMT_NONE:
2160 return WPA_AUTH_KEY_MGMT_NONE;
2161 case WLAN_CRYPTO_KEY_MGMT_IEEE8021X:
2162 return WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
2163 case WLAN_CRYPTO_KEY_MGMT_PSK:
2164 return WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;
2165 case WLAN_CRYPTO_KEY_MGMT_CCKM:
2166 return WPA_AUTH_KEY_MGMT_CCKM;
2167 }
2168
2169 return status;
2170}
2171/**
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302172 * Convert a WPA cipher selector OUI to an internal
2173 * cipher algorithm. Where appropriate we also
2174 * record any key length.
2175 */
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302176static int32_t wlan_crypto_wpa_suite_to_cipher(uint8_t *sel)
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302177{
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302178 uint32_t w = LE_READ_4(sel);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302179 int32_t status = -1;
2180
2181 switch (w) {
2182 case WPA_CIPHER_SUITE_TKIP:
2183 return WLAN_CRYPTO_CIPHER_TKIP;
2184 case WPA_CIPHER_SUITE_CCMP:
2185 return WLAN_CRYPTO_CIPHER_AES_CCM;
2186 case WPA_CIPHER_SUITE_NONE:
2187 return WLAN_CRYPTO_CIPHER_NONE;
2188 }
2189
2190 return status;
2191}
2192
2193/*
2194 * Convert a WPA key management/authentication algorithm
2195 * to an internal code.
2196 */
2197static int32_t wlan_crypto_wpa_suite_to_keymgmt(uint8_t *sel)
2198{
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302199 uint32_t w = LE_READ_4(sel);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302200 int32_t status = -1;
2201
2202 switch (w) {
2203 case WPA_AUTH_KEY_MGMT_UNSPEC_802_1X:
2204 return WLAN_CRYPTO_KEY_MGMT_IEEE8021X;
2205 case WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X:
2206 return WLAN_CRYPTO_KEY_MGMT_PSK;
2207 case WPA_AUTH_KEY_MGMT_CCKM:
2208 return WLAN_CRYPTO_KEY_MGMT_CCKM;
2209 case WPA_AUTH_KEY_MGMT_NONE:
2210 return WLAN_CRYPTO_KEY_MGMT_NONE;
2211 }
2212 return status;
2213}
2214
2215/*
2216 * Convert a RSN cipher selector OUI to an internal
2217 * cipher algorithm. Where appropriate we also
2218 * record any key length.
2219 */
2220static int32_t wlan_crypto_rsn_suite_to_cipher(uint8_t *sel)
2221{
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302222 uint32_t w = LE_READ_4(sel);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302223 int32_t status = -1;
2224
2225 switch (w) {
2226 case RSN_CIPHER_SUITE_TKIP:
2227 return WLAN_CRYPTO_CIPHER_TKIP;
2228 case RSN_CIPHER_SUITE_CCMP:
2229 return WLAN_CRYPTO_CIPHER_AES_CCM;
2230 case RSN_CIPHER_SUITE_CCMP_256:
2231 return WLAN_CRYPTO_CIPHER_AES_CCM_256;
2232 case RSN_CIPHER_SUITE_GCMP:
2233 return WLAN_CRYPTO_CIPHER_AES_GCM;
2234 case RSN_CIPHER_SUITE_GCMP_256:
2235 return WLAN_CRYPTO_CIPHER_AES_GCM_256;
2236 case RSN_CIPHER_SUITE_AES_CMAC:
2237 return WLAN_CRYPTO_CIPHER_AES_CMAC;
2238 case RSN_CIPHER_SUITE_BIP_CMAC_256:
2239 return WLAN_CRYPTO_CIPHER_AES_CMAC_256;
2240 case RSN_CIPHER_SUITE_BIP_GMAC_128:
2241 return WLAN_CRYPTO_CIPHER_AES_GMAC;
2242 case RSN_CIPHER_SUITE_BIP_GMAC_256:
2243 return WLAN_CRYPTO_CIPHER_AES_GMAC_256;
2244 case RSN_CIPHER_SUITE_NONE:
2245 return WLAN_CRYPTO_CIPHER_NONE;
2246 }
2247
2248 return status;
2249}
2250/*
2251 * Convert an RSN key management/authentication algorithm
2252 * to an internal code.
2253 */
2254static int32_t wlan_crypto_rsn_suite_to_keymgmt(uint8_t *sel)
2255{
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302256 uint32_t w = LE_READ_4(sel);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302257 int32_t status = -1;
2258
2259 switch (w) {
2260 case RSN_AUTH_KEY_MGMT_UNSPEC_802_1X:
2261 return WLAN_CRYPTO_KEY_MGMT_IEEE8021X;
2262 case RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X:
2263 return WLAN_CRYPTO_KEY_MGMT_PSK;
2264 case RSN_AUTH_KEY_MGMT_FT_802_1X:
2265 return WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X;
2266 case RSN_AUTH_KEY_MGMT_FT_PSK:
2267 return WLAN_CRYPTO_KEY_MGMT_FT_PSK;
2268 case RSN_AUTH_KEY_MGMT_802_1X_SHA256:
2269 return WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256;
2270 case RSN_AUTH_KEY_MGMT_PSK_SHA256:
2271 return WLAN_CRYPTO_KEY_MGMT_PSK_SHA256;
2272 case RSN_AUTH_KEY_MGMT_SAE:
2273 return WLAN_CRYPTO_KEY_MGMT_SAE;
2274 case RSN_AUTH_KEY_MGMT_FT_SAE:
2275 return WLAN_CRYPTO_KEY_MGMT_FT_SAE;
2276 case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B:
2277 return WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B;
2278 case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192:
2279 return WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192;
2280 case RSN_AUTH_KEY_MGMT_CCKM:
2281 return WLAN_CRYPTO_KEY_MGMT_CCKM;
2282 case RSN_AUTH_KEY_MGMT_OSEN:
2283 return WLAN_CRYPTO_KEY_MGMT_OSEN;
Ashok Ponnaiahc6d59102018-05-16 16:25:05 +05302284 case RSN_AUTH_KEY_MGMT_FILS_SHA256:
2285 return WLAN_CRYPTO_KEY_MGMT_FILS_SHA256;
2286 case RSN_AUTH_KEY_MGMT_FILS_SHA384:
2287 return WLAN_CRYPTO_KEY_MGMT_FILS_SHA384;
2288 case RSN_AUTH_KEY_MGMT_FT_FILS_SHA256:
2289 return WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256;
2290 case RSN_AUTH_KEY_MGMT_FT_FILS_SHA384:
2291 return WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384;
2292 case RSN_AUTH_KEY_MGMT_OWE:
2293 return WLAN_CRYPTO_KEY_MGMT_OWE;
2294 case RSN_AUTH_KEY_MGMT_DPP:
2295 return WLAN_CRYPTO_KEY_MGMT_DPP;
Ashok Kumarcff882e2019-06-07 17:04:00 +05302296 case RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_384:
2297 return WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302298 }
2299
2300 return status;
2301}
2302
2303/**
2304 * wlan_crypto_wpaie_check - called by mlme to check the wpaie
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302305 * @crypto params: crypto params
2306 * @iebuf: ie buffer
2307 *
2308 * This function gets called by mlme to check the contents of wpa is
2309 * matching with given crypto params
2310 *
2311 * Return: QDF_STATUS_SUCCESS - in case of success
2312 */
2313QDF_STATUS wlan_crypto_wpaie_check(struct wlan_crypto_params *crypto_params,
2314 uint8_t *frm){
2315 uint8_t len = frm[1];
2316 int32_t w;
2317 int n;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302318
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302319 /*
2320 * Check the length once for fixed parts: OUI, type,
2321 * version, mcast cipher, and 2 selector counts.
2322 * Other, variable-length data, must be checked separately.
2323 */
2324 RESET_AUTHMODE(crypto_params);
2325 SET_AUTHMODE(crypto_params, WLAN_CRYPTO_AUTH_WPA);
2326
2327 if (len < 14)
2328 return QDF_STATUS_E_INVAL;
2329
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302330 frm += 6, len -= 4;
2331
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302332 w = LE_READ_2(frm);
2333 if (w != WPA_VERSION)
2334 return QDF_STATUS_E_INVAL;
2335
2336 frm += 2, len -= 2;
2337
2338 /* multicast/group cipher */
2339 RESET_MCAST_CIPHERS(crypto_params);
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302340 w = wlan_crypto_wpa_suite_to_cipher(frm);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302341 if (w < 0)
2342 return QDF_STATUS_E_INVAL;
2343 SET_MCAST_CIPHER(crypto_params, w);
2344 frm += 4, len -= 4;
2345
2346 /* unicast ciphers */
2347 n = LE_READ_2(frm);
2348 frm += 2, len -= 2;
2349 if (len < n*4+2)
2350 return QDF_STATUS_E_INVAL;
2351
2352 RESET_UCAST_CIPHERS(crypto_params);
2353 for (; n > 0; n--) {
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302354 w = wlan_crypto_wpa_suite_to_cipher(frm);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302355 if (w < 0)
2356 return QDF_STATUS_E_INVAL;
2357 SET_UCAST_CIPHER(crypto_params, w);
2358 frm += 4, len -= 4;
2359 }
2360
2361 if (!crypto_params->ucastcipherset)
2362 return QDF_STATUS_E_INVAL;
2363
2364 /* key management algorithms */
2365 n = LE_READ_2(frm);
2366 frm += 2, len -= 2;
2367 if (len < n*4)
2368 return QDF_STATUS_E_INVAL;
2369
2370 w = 0;
2371 RESET_KEY_MGMT(crypto_params);
2372 for (; n > 0; n--) {
2373 w = wlan_crypto_wpa_suite_to_keymgmt(frm);
2374 if (w < 0)
2375 return QDF_STATUS_E_INVAL;
2376 SET_KEY_MGMT(crypto_params, w);
2377 frm += 4, len -= 4;
2378 }
2379
2380 /* optional capabilities */
2381 if (len >= 2) {
2382 crypto_params->rsn_caps = LE_READ_2(frm);
2383 frm += 2, len -= 2;
2384 }
2385
2386 return 0;
2387}
2388
2389/**
2390 * wlan_crypto_rsnie_check - called by mlme to check the rsnie
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302391 * @crypto params: crypto params
2392 * @iebuf: ie buffer
2393 *
2394 * This function gets called by mlme to check the contents of wpa is
2395 * matching with given crypto params
2396 *
2397 * Return: QDF_STATUS_SUCCESS - in case of success
2398 */
2399QDF_STATUS wlan_crypto_rsnie_check(struct wlan_crypto_params *crypto_params,
2400 uint8_t *frm){
2401 uint8_t len = frm[1];
2402 int32_t w;
2403 int n;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05302404
Ashok Ponnaiahb4c573c2018-05-18 12:48:44 +05302405 /* Check the length once for fixed parts: OUI, type & version */
2406 if (len < 2)
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302407 return QDF_STATUS_E_INVAL;
2408
Ashok Ponnaiahb4c573c2018-05-18 12:48:44 +05302409 /* initialize crypto params */
2410 qdf_mem_zero(crypto_params, sizeof(struct wlan_crypto_params));
2411
2412 SET_AUTHMODE(crypto_params, WLAN_CRYPTO_AUTH_RSNA);
2413
Rohan Duttaf8ce8102018-01-18 10:17:47 +05302414 frm += 2;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302415 /* NB: iswapoui already validated the OUI and type */
2416 w = LE_READ_2(frm);
2417 if (w != RSN_VERSION)
2418 return QDF_STATUS_E_INVAL;
2419
2420 frm += 2, len -= 2;
2421
Ashok Ponnaiahb4c573c2018-05-18 12:48:44 +05302422 if (!len) {
2423 /* set defaults */
2424 /* default group cipher CCMP-128 */
2425 SET_MCAST_CIPHER(crypto_params, WLAN_CRYPTO_CIPHER_AES_CCM);
2426 /* default ucast cipher CCMP-128 */
2427 SET_UCAST_CIPHER(crypto_params, WLAN_CRYPTO_CIPHER_AES_CCM);
2428 /* default key mgmt 8021x */
2429 SET_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_IEEE8021X);
2430 return QDF_STATUS_SUCCESS;
2431 } else if (len < 4) {
2432 return QDF_STATUS_E_INVAL;
2433 }
2434
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302435 /* multicast/group cipher */
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302436 w = wlan_crypto_rsn_suite_to_cipher(frm);
2437 if (w < 0)
2438 return QDF_STATUS_E_INVAL;
Ashok Ponnaiahb4c573c2018-05-18 12:48:44 +05302439 else {
2440 SET_MCAST_CIPHER(crypto_params, w);
2441 frm += 4, len -= 4;
2442 }
2443
2444 if (crypto_params->mcastcipherset == 0)
2445 return QDF_STATUS_E_INVAL;
2446
2447 if (!len) {
2448 /* default ucast cipher CCMP-128 */
2449 SET_UCAST_CIPHER(crypto_params, WLAN_CRYPTO_CIPHER_AES_CCM);
2450 /* default key mgmt 8021x */
2451 SET_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_IEEE8021X);
2452 return QDF_STATUS_SUCCESS;
2453 } else if (len < 2) {
2454 return QDF_STATUS_E_INVAL;
2455 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302456
2457 /* unicast ciphers */
2458 n = LE_READ_2(frm);
2459 frm += 2, len -= 2;
Ashok Ponnaiahb4c573c2018-05-18 12:48:44 +05302460 if (n) {
2461 if (len < n * 4)
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302462 return QDF_STATUS_E_INVAL;
Ashok Ponnaiahb4c573c2018-05-18 12:48:44 +05302463
2464 for (; n > 0; n--) {
2465 w = wlan_crypto_rsn_suite_to_cipher(frm);
2466 if (w < 0)
2467 return QDF_STATUS_E_INVAL;
2468 SET_UCAST_CIPHER(crypto_params, w);
2469 frm += 4, len -= 4;
2470 }
2471 } else {
2472 /* default ucast cipher CCMP-128 */
2473 SET_UCAST_CIPHER(crypto_params, WLAN_CRYPTO_CIPHER_AES_CCM);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302474 }
2475
2476 if (crypto_params->ucastcipherset == 0)
2477 return QDF_STATUS_E_INVAL;
2478
Ashok Ponnaiahb4c573c2018-05-18 12:48:44 +05302479 if (!len) {
2480 /* default key mgmt 8021x */
2481 SET_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_IEEE8021X);
2482 return QDF_STATUS_SUCCESS;
2483 } else if (len < 2) {
2484 return QDF_STATUS_E_INVAL;
2485 }
2486
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302487 /* key management algorithms */
2488 n = LE_READ_2(frm);
2489 frm += 2, len -= 2;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302490
Ashok Ponnaiahb4c573c2018-05-18 12:48:44 +05302491 if (n) {
2492 if (len < n * 4)
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302493 return QDF_STATUS_E_INVAL;
Ashok Ponnaiahb4c573c2018-05-18 12:48:44 +05302494
2495 for (; n > 0; n--) {
2496 w = wlan_crypto_rsn_suite_to_keymgmt(frm);
2497 if (w < 0)
2498 return QDF_STATUS_E_INVAL;
2499 SET_KEY_MGMT(crypto_params, w);
2500 frm += 4, len -= 4;
2501 }
2502 } else {
2503 /* default key mgmt 8021x */
2504 SET_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_IEEE8021X);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302505 }
2506
Ashok Ponnaiahb4c573c2018-05-18 12:48:44 +05302507 if (crypto_params->key_mgmt == 0)
2508 return QDF_STATUS_E_INVAL;
2509
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302510 /* optional capabilities */
2511 if (len >= 2) {
2512 crypto_params->rsn_caps = LE_READ_2(frm);
2513 frm += 2, len -= 2;
Ashok Ponnaiahb4c573c2018-05-18 12:48:44 +05302514 } else if (len && len < 2) {
2515 return QDF_STATUS_E_INVAL;
2516 }
2517
2518
2519 /* PMKID */
2520 if (len >= 2) {
2521 n = LE_READ_2(frm);
2522 frm += 2, len -= 2;
2523 if (n && len) {
2524 if (len >= n * PMKID_LEN)
2525 frm += (n * PMKID_LEN), len -= (n * PMKID_LEN);
2526 else
2527 return QDF_STATUS_E_INVAL;
2528 } else if (n && !len) {
2529 return QDF_STATUS_E_INVAL;
2530 }
2531 /*TODO: Save pmkid in params for further reference */
2532 }
2533
2534 /* BIP */
2535 if (!len &&
2536 (crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) {
2537 /* when no BIP mentioned and MFP capable use CMAC as default*/
2538 SET_MGMT_CIPHER(crypto_params, WLAN_CRYPTO_CIPHER_AES_CMAC);
2539 return QDF_STATUS_SUCCESS;
2540 } else if (len >= 4) {
2541 w = wlan_crypto_rsn_suite_to_cipher(frm);
2542 frm += 4, len -= 4;
2543 SET_MGMT_CIPHER(crypto_params, w);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302544 }
2545
2546 return QDF_STATUS_SUCCESS;
2547}
2548
2549/**
2550 * wlan_crypto_build_wpaie - called by mlme to build wpaie
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302551 * @vdev: vdev
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302552 * @iebuf: ie buffer
2553 *
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302554 * This function gets called by mlme to build wpaie from given vdev
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302555 *
2556 * Return: end of buffer
2557 */
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302558uint8_t *wlan_crypto_build_wpaie(struct wlan_objmgr_vdev *vdev,
2559 uint8_t *iebuf){
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302560 uint8_t *frm = iebuf;
2561 uint8_t *selcnt;
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302562 struct wlan_crypto_comp_priv *crypto_priv;
2563 struct wlan_crypto_params *crypto_params;
2564
2565 if (!frm)
2566 return NULL;
2567
2568 crypto_params = wlan_crypto_vdev_get_comp_params(vdev, &crypto_priv);
2569
2570 if (!crypto_params)
2571 return NULL;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302572
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302573 *frm++ = WLAN_ELEMID_VENDOR;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302574 *frm++ = 0;
2575 WLAN_CRYPTO_ADDSELECTOR(frm, WPA_TYPE_OUI);
2576 WLAN_CRYPTO_ADDSHORT(frm, WPA_VERSION);
2577
2578
2579 /* multicast cipher */
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +05302580 if (MCIPHER_IS_TKIP(crypto_params))
2581 WPA_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_TKIP);
2582 else if (MCIPHER_IS_CCMP128(crypto_params))
2583 WPA_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_AES_CCM);
2584
Rohan Duttaa301c832017-11-30 20:29:26 +05302585 /* unicast cipher list */
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302586 selcnt = frm;
2587 WLAN_CRYPTO_ADDSHORT(frm, 0);
2588 /* do not use CCMP unicast cipher in WPA mode */
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302589 if (UCIPHER_IS_CCMP128(crypto_params)) {
2590 selcnt[0]++;
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +05302591 WPA_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_AES_CCM);
2592 }
2593 if (UCIPHER_IS_TKIP(crypto_params)) {
2594 selcnt[0]++;
2595 WPA_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_TKIP);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302596 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302597
2598 /* authenticator selector list */
2599 selcnt = frm;
2600 WLAN_CRYPTO_ADDSHORT(frm, 0);
2601
2602 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_IEEE8021X)) {
2603 selcnt[0]++;
Ashok Kumar Ponnaiah6e0a63c2018-08-24 10:16:05 +05302604 WPA_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302605 } else if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_PSK)) {
2606 selcnt[0]++;
Ashok Kumar Ponnaiah6e0a63c2018-08-24 10:16:05 +05302607 WPA_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_PSK);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302608 } else if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_CCKM)) {
2609 selcnt[0]++;
Ashok Kumar Ponnaiah6e0a63c2018-08-24 10:16:05 +05302610 WPA_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_CCKM);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302611 } else {
2612 selcnt[0]++;
Ashok Kumar Ponnaiah6e0a63c2018-08-24 10:16:05 +05302613 WPA_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_NONE);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302614 }
Ashok Kumar Ponnaiahac40b6b2018-09-05 10:16:23 +05302615
2616 /* optional capabilities */
2617 if (crypto_params->rsn_caps != 0 &&
2618 crypto_params->rsn_caps != WLAN_CRYPTO_RSN_CAP_PREAUTH) {
2619 WLAN_CRYPTO_ADDSHORT(frm, crypto_params->rsn_caps);
2620 }
2621
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302622 /* calculate element length */
2623 iebuf[1] = frm - iebuf - 2;
2624
2625 return frm;
2626}
2627
2628/**
2629 * wlan_crypto_build_rsnie - called by mlme to build rsnie
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302630 * @vdev: vdev
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302631 * @iebuf: ie buffer
Ashok Kumar6f8b9242018-12-10 12:26:24 +05302632 * @bssid: bssid mac address to add pmkid in rsnie
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302633 *
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302634 * This function gets called by mlme to build rsnie from given vdev
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302635 *
2636 * Return: end of buffer
2637 */
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302638uint8_t *wlan_crypto_build_rsnie(struct wlan_objmgr_vdev *vdev,
Ashok Kumar6f8b9242018-12-10 12:26:24 +05302639 uint8_t *iebuf,
2640 struct qdf_mac_addr *bssid)
2641{
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302642 uint8_t *frm = iebuf;
2643 uint8_t *selcnt;
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302644 struct wlan_crypto_comp_priv *crypto_priv;
2645 struct wlan_crypto_params *crypto_params;
2646
2647 if (!frm) {
2648 return NULL;
2649 }
2650
2651 crypto_params = wlan_crypto_vdev_get_comp_params(vdev, &crypto_priv);
2652
2653 if (!crypto_params) {
2654 return NULL;
2655 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302656
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05302657 *frm++ = WLAN_ELEMID_RSN;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302658 *frm++ = 0;
2659 WLAN_CRYPTO_ADDSHORT(frm, RSN_VERSION);
2660
2661
2662 /* multicast cipher */
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +05302663 if (MCIPHER_IS_TKIP(crypto_params))
2664 RSN_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_TKIP);
2665 else if (MCIPHER_IS_CCMP128(crypto_params))
2666 RSN_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_AES_CCM);
2667 else if (MCIPHER_IS_CCMP256(crypto_params))
2668 RSN_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_AES_CCM_256);
2669 else if (MCIPHER_IS_GCMP128(crypto_params))
2670 RSN_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_AES_GCM);
2671 else if (MCIPHER_IS_GCMP256(crypto_params))
2672 RSN_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_AES_GCM_256);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302673
2674 /* unicast cipher list */
2675 selcnt = frm;
2676 WLAN_CRYPTO_ADDSHORT(frm, 0);
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +05302677
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302678 if (UCIPHER_IS_CCMP256(crypto_params)) {
2679 selcnt[0]++;
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +05302680 RSN_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_AES_CCM_256);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302681 }
2682 if (UCIPHER_IS_GCMP256(crypto_params)) {
2683 selcnt[0]++;
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +05302684 RSN_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_AES_GCM_256);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302685 }
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +05302686 if (UCIPHER_IS_CCMP128(crypto_params)) {
2687 selcnt[0]++;
2688 RSN_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_AES_CCM);
2689 }
2690 if (UCIPHER_IS_GCMP128(crypto_params)) {
2691 selcnt[0]++;
2692 RSN_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_AES_GCM);
2693 }
2694 if (UCIPHER_IS_TKIP(crypto_params)) {
2695 selcnt[0]++;
2696 RSN_ADD_CIPHER_TO_SUITE(frm, WLAN_CRYPTO_CIPHER_TKIP);
2697 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302698
2699 /* authenticator selector list */
2700 selcnt = frm;
2701 WLAN_CRYPTO_ADDSHORT(frm, 0);
2702 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_CCKM)) {
2703 selcnt[0]++;
Ashok Kumar Ponnaiah6e0a63c2018-08-24 10:16:05 +05302704 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_CCKM);
2705 /* Other key mgmt should not be added after CCKM */
2706 goto add_rsn_caps;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302707 }
Ashok Kumar Ponnaiah6e0a63c2018-08-24 10:16:05 +05302708 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_IEEE8021X)) {
2709 selcnt[0]++;
2710 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X);
2711 }
2712 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_PSK)) {
2713 selcnt[0]++;
2714 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_PSK);
2715 }
2716 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X)) {
2717 selcnt[0]++;
2718 RSN_ADD_KEYMGMT_TO_SUITE(frm,
2719 WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X);
2720 }
2721 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_FT_PSK)) {
2722 selcnt[0]++;
2723 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_FT_PSK);
2724 }
2725 if (HAS_KEY_MGMT(crypto_params,
2726 WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256)) {
2727 selcnt[0]++;
2728 RSN_ADD_KEYMGMT_TO_SUITE(frm,
2729 WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256);
2730 }
2731 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256)) {
2732 selcnt[0]++;
2733 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256);
2734 }
2735 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_SAE)) {
2736 selcnt[0]++;
2737 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_SAE);
2738 }
2739 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_FT_SAE)) {
2740 selcnt[0]++;
2741 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_FT_SAE);
2742 }
2743 if (HAS_KEY_MGMT(crypto_params,
2744 WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B)) {
2745 uint32_t kmgmt = WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302746
Ashok Kumar Ponnaiah6e0a63c2018-08-24 10:16:05 +05302747 selcnt[0]++;
2748 RSN_ADD_KEYMGMT_TO_SUITE(frm, kmgmt);
2749 }
2750 if (HAS_KEY_MGMT(crypto_params,
2751 WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192)) {
2752 uint32_t kmgmt = WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192;
2753
2754 selcnt[0]++;
2755 RSN_ADD_KEYMGMT_TO_SUITE(frm, kmgmt);
2756 }
2757 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256)) {
2758 selcnt[0]++;
2759 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256);
2760 }
2761 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384)) {
2762 selcnt[0]++;
2763 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384);
2764 }
2765 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256)) {
2766 selcnt[0]++;
2767 RSN_ADD_KEYMGMT_TO_SUITE(frm,
2768 WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256);
2769 }
2770 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384)) {
2771 selcnt[0]++;
2772 RSN_ADD_KEYMGMT_TO_SUITE(frm,
2773 WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384);
2774 }
2775 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_OWE)) {
2776 selcnt[0]++;
2777 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_OWE);
2778 }
2779 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_DPP)) {
2780 selcnt[0]++;
2781 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_DPP);
2782 }
2783 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_OSEN)) {
2784 selcnt[0]++;
2785 RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_OSEN);
2786 }
2787add_rsn_caps:
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302788 WLAN_CRYPTO_ADDSHORT(frm, crypto_params->rsn_caps);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302789 /* optional capabilities */
Ashok Ponnaiahadfce982018-05-10 14:08:52 +05302790 if (crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) {
2791 /* PMK list */
Ashok Kumar6f8b9242018-12-10 12:26:24 +05302792 if (bssid) {
2793 struct wlan_crypto_pmksa *pmksa;
2794
2795 pmksa = wlan_crypto_get_pmksa(vdev, bssid);
2796
2797 if (pmksa) {
2798 WLAN_CRYPTO_ADDSHORT(frm, 1);
2799 qdf_mem_copy(frm, pmksa->pmkid, PMKID_LEN);
2800 frm += PMKID_LEN;
2801 } else {
2802 WLAN_CRYPTO_ADDSHORT(frm, 0);
2803 }
2804 } else
2805 WLAN_CRYPTO_ADDSHORT(frm, 0);
2806
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302807 if (HAS_MGMT_CIPHER(crypto_params,
2808 WLAN_CRYPTO_CIPHER_AES_CMAC)) {
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +05302809 RSN_ADD_CIPHER_TO_SUITE(frm,
2810 WLAN_CRYPTO_CIPHER_AES_CMAC);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302811 }
2812 if (HAS_MGMT_CIPHER(crypto_params,
2813 WLAN_CRYPTO_CIPHER_AES_GMAC)) {
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +05302814 RSN_ADD_CIPHER_TO_SUITE(frm,
2815 WLAN_CRYPTO_CIPHER_AES_GMAC);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302816 }
2817 if (HAS_MGMT_CIPHER(crypto_params,
2818 WLAN_CRYPTO_CIPHER_AES_CMAC_256)) {
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +05302819 RSN_ADD_CIPHER_TO_SUITE(frm,
2820 WLAN_CRYPTO_CIPHER_AES_CMAC_256
2821 );
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302822 }
2823
2824 if (HAS_MGMT_CIPHER(crypto_params,
2825 WLAN_CRYPTO_CIPHER_AES_GMAC_256)) {
Ashok Kumar Ponnaiahd652f8f2018-08-24 10:09:32 +05302826 RSN_ADD_CIPHER_TO_SUITE(frm,
2827 WLAN_CRYPTO_CIPHER_AES_GMAC_256
2828 );
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302829 }
Ashok Kumar6f8b9242018-12-10 12:26:24 +05302830 } else {
2831 /* PMK list */
2832 if (bssid) {
2833 struct wlan_crypto_pmksa *pmksa;
2834
2835 pmksa = wlan_crypto_get_pmksa(vdev, bssid);
2836 if (pmksa) {
2837 WLAN_CRYPTO_ADDSHORT(frm, 1);
2838 qdf_mem_copy(frm, pmksa->pmkid, PMKID_LEN);
2839 frm += PMKID_LEN;
2840 } else {
2841 WLAN_CRYPTO_ADDSHORT(frm, 0);
2842 }
2843 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302844 }
Rohan Dutta8b8f00f2017-12-13 11:04:14 +05302845
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302846 /* calculate element length */
2847 iebuf[1] = frm - iebuf - 2;
2848
2849 return frm;
2850}
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05302851
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302852bool wlan_crypto_rsn_info(struct wlan_objmgr_vdev *vdev,
2853 struct wlan_crypto_params *crypto_params){
2854 struct wlan_crypto_params *my_crypto_params;
2855 my_crypto_params = wlan_crypto_vdev_get_crypto_params(vdev);
2856
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07002857 if (!my_crypto_params) {
2858 crypto_debug("vdev crypto params is NULL");
Disha Das76210cd2018-04-10 12:44:14 +05302859 return false;
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07002860 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302861 /*
2862 * Check peer's pairwise ciphers.
2863 * At least one must match with our unicast cipher
2864 */
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07002865 if (!UCAST_CIPHER_MATCH(crypto_params, my_crypto_params)) {
2866 crypto_debug("Unicast cipher match failed");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302867 return false;
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07002868 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302869 /*
2870 * Check peer's group cipher is our enabled multicast cipher.
2871 */
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07002872 if (!MCAST_CIPHER_MATCH(crypto_params, my_crypto_params)) {
2873 crypto_debug("Multicast cipher match failed");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302874 return false;
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07002875 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302876 /*
2877 * Check peer's key management class set (PSK or UNSPEC)
2878 */
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07002879 if (!KEY_MGMTSET_MATCH(crypto_params, my_crypto_params)) {
2880 crypto_debug("Key mgmt match failed");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302881 return false;
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07002882 }
Min Liua3bad2b2019-03-25 11:48:49 +08002883 if (wlan_crypto_vdev_is_pmf_required(vdev) &&
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07002884 !(crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) {
2885 crypto_debug("Peer is not PMF capable");
2886 return false;
2887 }
2888 if (!wlan_crypto_vdev_is_pmf_enabled(vdev) &&
2889 (crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)) {
2890 crypto_debug("Peer needs PMF, but vdev is not capable");
2891 return false;
2892 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05302893
2894 return true;
2895}
2896
Ashok Ponnaiah26e6be42017-07-14 18:13:23 +05302897/*
2898 * Convert an WAPI CIPHER suite to to an internal code.
2899 */
2900static int32_t wlan_crypto_wapi_suite_to_cipher(uint8_t *sel)
2901{
2902 uint32_t w = LE_READ_4(sel);
2903 int32_t status = -1;
2904
2905 switch (w) {
2906 case (WLAN_WAPI_SEL(WLAN_CRYPTO_WAPI_SMS4_CIPHER)):
2907 return WLAN_CRYPTO_CIPHER_WAPI_SMS4;
2908 }
2909
2910 return status;
2911}
2912
2913/*
2914 * Convert an WAPI key management/authentication algorithm
2915 * to an internal code.
2916 */
2917static int32_t wlan_crypto_wapi_keymgmt(u_int8_t *sel)
2918{
2919 uint32_t w = LE_READ_4(sel);
2920 int32_t status = -1;
2921
2922 switch (w) {
2923 case (WLAN_WAPI_SEL(WLAN_WAI_PSK)):
2924 return WLAN_CRYPTO_KEY_MGMT_WAPI_PSK;
2925 case (WLAN_WAPI_SEL(WLAN_WAI_CERT_OR_SMS4)):
2926 return WLAN_CRYPTO_KEY_MGMT_WAPI_CERT;
2927 }
2928
2929 return status;
2930}
2931/**
2932 * wlan_crypto_wapiie_check - called by mlme to check the wapiie
Ashok Ponnaiah26e6be42017-07-14 18:13:23 +05302933 * @crypto params: crypto params
2934 * @iebuf: ie buffer
2935 *
2936 * This function gets called by mlme to check the contents of wapi is
2937 * matching with given crypto params
2938 *
2939 * Return: QDF_STATUS_SUCCESS - in case of success
2940 */
2941QDF_STATUS wlan_crypto_wapiie_check(struct wlan_crypto_params *crypto_params,
2942 uint8_t *frm)
2943{
2944 uint8_t len = frm[1];
2945 int32_t w;
2946 int n;
2947
2948 /*
2949 * Check the length once for fixed parts: OUI, type,
2950 * version, mcast cipher, and 2 selector counts.
2951 * Other, variable-length data, must be checked separately.
2952 */
2953 RESET_AUTHMODE(crypto_params);
2954 SET_AUTHMODE(crypto_params, WLAN_CRYPTO_AUTH_WAPI);
2955
2956 if (len < WLAN_CRYPTO_WAPI_IE_LEN)
2957 return QDF_STATUS_E_INVAL;
2958
2959
2960 frm += 2;
2961
2962 w = LE_READ_2(frm);
2963 frm += 2, len -= 2;
2964 if (w != WAPI_VERSION)
2965 return QDF_STATUS_E_INVAL;
2966
2967 n = LE_READ_2(frm);
2968 frm += 2, len -= 2;
2969 if (len < n*4+2)
2970 return QDF_STATUS_E_INVAL;
2971
2972 RESET_KEY_MGMT(crypto_params);
2973 for (; n > 0; n--) {
2974 w = wlan_crypto_wapi_keymgmt(frm);
2975 if (w < 0)
2976 return QDF_STATUS_E_INVAL;
2977
2978 SET_KEY_MGMT(crypto_params, w);
2979 frm += 4, len -= 4;
2980 }
2981
2982 /* unicast ciphers */
2983 n = LE_READ_2(frm);
2984 frm += 2, len -= 2;
2985 if (len < n*4+2)
2986 return QDF_STATUS_E_INVAL;
2987
2988 RESET_UCAST_CIPHERS(crypto_params);
2989 for (; n > 0; n--) {
2990 w = wlan_crypto_wapi_suite_to_cipher(frm);
2991 if (w < 0)
2992 return QDF_STATUS_E_INVAL;
2993 SET_UCAST_CIPHER(crypto_params, w);
2994 frm += 4, len -= 4;
2995 }
2996
2997 if (!crypto_params->ucastcipherset)
2998 return QDF_STATUS_E_INVAL;
2999
3000 /* multicast/group cipher */
3001 RESET_MCAST_CIPHERS(crypto_params);
3002 w = wlan_crypto_wapi_suite_to_cipher(frm);
3003
3004 if (w < 0)
3005 return QDF_STATUS_E_INVAL;
3006
3007 SET_MCAST_CIPHER(crypto_params, w);
3008 frm += 4, len -= 4;
3009
3010 return QDF_STATUS_SUCCESS;
3011}
3012
3013/**
3014 * wlan_crypto_build_wapiie - called by mlme to build wapi ie
Ashok Ponnaiah26e6be42017-07-14 18:13:23 +05303015 * @vdev: vdev
3016 * @iebuf: ie buffer
3017 *
3018 * This function gets called by mlme to build wapi ie from given vdev
3019 *
3020 * Return: end of buffer
3021 */
3022uint8_t *wlan_crypto_build_wapiie(struct wlan_objmgr_vdev *vdev,
3023 uint8_t *iebuf)
3024{
3025 uint8_t *frm;
3026 uint8_t *selcnt;
3027 struct wlan_crypto_comp_priv *crypto_priv;
3028 struct wlan_crypto_params *crypto_params;
3029
3030 frm = iebuf;
3031 if (!frm) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303032 crypto_err("ie buffer NULL");
Ashok Ponnaiah26e6be42017-07-14 18:13:23 +05303033 return NULL;
3034 }
3035
3036 crypto_params = wlan_crypto_vdev_get_comp_params(vdev, &crypto_priv);
3037
3038 if (!crypto_params) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303039 crypto_err("crypto_params NULL");
Ashok Ponnaiah26e6be42017-07-14 18:13:23 +05303040 return NULL;
3041 }
3042
3043 *frm++ = WLAN_ELEMID_WAPI;
3044 *frm++ = 0;
3045
3046 WLAN_CRYPTO_ADDSHORT(frm, WAPI_VERSION);
3047
3048 /* authenticator selector list */
3049 selcnt = frm;
3050 WLAN_CRYPTO_ADDSHORT(frm, 0);
3051
3052 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK)) {
3053 selcnt[0]++;
3054 WLAN_CRYPTO_ADDSELECTOR(frm,
3055 WLAN_WAPI_SEL(WLAN_WAI_PSK));
3056 }
3057
3058 if (HAS_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT)) {
3059 selcnt[0]++;
3060 WLAN_CRYPTO_ADDSELECTOR(frm,
3061 WLAN_WAPI_SEL(WLAN_WAI_CERT_OR_SMS4));
3062 }
3063
3064 /* unicast cipher list */
3065 selcnt = frm;
3066 WLAN_CRYPTO_ADDSHORT(frm, 0);
3067
3068 if (UCIPHER_IS_SMS4(crypto_params)) {
3069 selcnt[0]++;
3070 WLAN_CRYPTO_ADDSELECTOR(frm,
3071 WLAN_WAPI_SEL(WLAN_CRYPTO_WAPI_SMS4_CIPHER));
3072 }
3073
3074 WLAN_CRYPTO_ADDSELECTOR(frm,
3075 WLAN_WAPI_SEL(WLAN_CRYPTO_WAPI_SMS4_CIPHER));
3076
3077 /* optional capabilities */
3078 WLAN_CRYPTO_ADDSHORT(frm, crypto_params->rsn_caps);
3079
Arif Hussainc1e78772019-01-10 19:49:57 -08003080 /* bkid count */
Arif Hussain20a228a2019-02-12 17:51:44 -08003081 if (vdev->vdev_mlme.vdev_opmode == QDF_STA_MODE ||
3082 vdev->vdev_mlme.vdev_opmode == QDF_P2P_CLIENT_MODE)
3083 WLAN_CRYPTO_ADDSHORT(frm, 0);
Arif Hussainc1e78772019-01-10 19:49:57 -08003084
Ashok Ponnaiah26e6be42017-07-14 18:13:23 +05303085 /* calculate element length */
3086 iebuf[1] = frm - iebuf - 2;
3087
3088 return frm;
3089
3090}
3091
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303092/**
3093 * wlan_crypto_pn_check - called by data patch for PN check
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303094 * @vdev: vdev
3095 * @wbuf: wbuf
3096 *
3097 * This function gets called by data patch for PN check
3098 *
3099 * Return: QDF_STATUS
3100 */
3101QDF_STATUS wlan_crypto_pn_check(struct wlan_objmgr_vdev *vdev,
3102 qdf_nbuf_t wbuf){
3103 /* Need to check is there real requirement for this function
3104 * as PN check is already handled in decap function.
3105 */
3106 return QDF_STATUS_SUCCESS;
3107}
3108
3109/**
3110 * wlan_crypto_vdev_get_crypto_params - called by mlme to get crypto params
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303111 * @vdev:vdev
3112 *
3113 * This function gets called by mlme to get crypto params
3114 *
3115 * Return: wlan_crypto_params or NULL in case of failure
3116 */
3117struct wlan_crypto_params *wlan_crypto_vdev_get_crypto_params(
3118 struct wlan_objmgr_vdev *vdev){
3119 struct wlan_crypto_comp_priv *crypto_priv;
3120
3121 return wlan_crypto_vdev_get_comp_params(vdev, &crypto_priv);
3122}
3123
3124/**
3125 * wlan_crypto_peer_get_crypto_params - called by mlme to get crypto params
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303126 * @peer:peer
3127 *
3128 * This function gets called by mlme to get crypto params
3129 *
3130 * Return: wlan_crypto_params or NULL in case of failure
3131 */
3132struct wlan_crypto_params *wlan_crypto_peer_get_crypto_params(
3133 struct wlan_objmgr_peer *peer){
3134 struct wlan_crypto_comp_priv *crypto_priv;
3135
3136 return wlan_crypto_peer_get_comp_params(peer, &crypto_priv);
3137}
3138
3139
3140QDF_STATUS wlan_crypto_set_peer_wep_keys(struct wlan_objmgr_vdev *vdev,
Srinivas Pitlaea71ebf2018-01-04 17:07:42 +05303141 struct wlan_objmgr_peer *peer)
3142{
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303143 struct wlan_crypto_comp_priv *crypto_priv;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303144 struct wlan_crypto_comp_priv *sta_crypto_priv;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303145 struct wlan_crypto_params *crypto_params;
3146 struct wlan_crypto_key *key;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303147 struct wlan_crypto_key *sta_key;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303148 struct wlan_crypto_cipher *cipher_table;
3149 struct wlan_objmgr_psoc *psoc;
Srinivas Pitlaea71ebf2018-01-04 17:07:42 +05303150 uint8_t *mac_addr;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303151 int i;
Jeff Johnsona4262322017-11-09 09:54:12 -08003152 enum QDF_OPMODE opmode;
sheenam monga1273bce2019-05-06 11:47:08 +05303153 QDF_STATUS status = QDF_STATUS_SUCCESS;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303154
3155 if (!vdev)
3156 return QDF_STATUS_E_NULL_VALUE;
Srinivas Pitlaea71ebf2018-01-04 17:07:42 +05303157
3158 if (!peer) {
Bala Venkateshae946e32019-08-26 19:14:14 +05303159 crypto_debug("peer NULL");
Srinivas Pitlaea71ebf2018-01-04 17:07:42 +05303160 return QDF_STATUS_E_INVAL;
3161 }
3162
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05303163 opmode = wlan_vdev_mlme_get_opmode(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303164 psoc = wlan_vdev_get_psoc(vdev);
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303165
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05303166 if (!psoc) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303167 crypto_err("psoc NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303168 return QDF_STATUS_E_NULL_VALUE;
Ashok Ponnaiah439d7b52017-03-21 11:20:36 +05303169 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303170
Srinivas Pitlaea71ebf2018-01-04 17:07:42 +05303171 wlan_peer_obj_lock(peer);
3172 mac_addr = wlan_peer_get_macaddr(peer);
3173 wlan_peer_obj_unlock(peer);
3174
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303175 crypto_params = wlan_crypto_vdev_get_comp_params(vdev,
3176 &crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07003177 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303178 crypto_err("crypto_priv NULL");
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303179 return QDF_STATUS_E_NULL_VALUE;
3180 }
3181
3182 /* push only valid static WEP keys from vap */
3183 if (AUTH_IS_8021X(crypto_params))
3184 return QDF_STATUS_E_INVAL;
3185
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303186 if (opmode == QDF_STA_MODE) {
sheenam monga1273bce2019-05-06 11:47:08 +05303187 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CRYPTO_ID);
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303188 if (!peer) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303189 crypto_err("peer NULL");
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303190 return QDF_STATUS_E_INVAL;
3191 }
3192 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303193
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303194 wlan_crypto_peer_get_comp_params(peer, &sta_crypto_priv);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07003195 if (!sta_crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303196 crypto_err("sta priv is null");
sheenam monga1273bce2019-05-06 11:47:08 +05303197 status = QDF_STATUS_E_INVAL;
3198 goto exit;
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303199 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303200
3201 for (i = 0; i < WLAN_CRYPTO_MAXKEYIDX; i++) {
3202 if (crypto_priv->key[i]) {
3203 key = crypto_priv->key[i];
3204 if (!key || !key->valid)
3205 continue;
3206
3207 cipher_table = (struct wlan_crypto_cipher *)
3208 key->cipher_table;
3209
3210 if (cipher_table->cipher == WLAN_CRYPTO_CIPHER_WEP) {
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303211 sta_key = qdf_mem_malloc(
3212 sizeof(struct wlan_crypto_key));
sheenam monga1273bce2019-05-06 11:47:08 +05303213 if (!sta_key) {
3214 status = QDF_STATUS_E_NOMEM;
3215 goto exit;
3216 }
Madhvapathi Sriramb73fc282019-01-07 09:12:25 +05303217
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303218 sta_crypto_priv->key[i] = sta_key;
3219 qdf_mem_copy(sta_key, key,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303220 sizeof(struct wlan_crypto_key));
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303221
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303222 sta_key->flags &= ~WLAN_CRYPTO_KEY_DEFAULT;
Ashok Ponnaiah4db9b8f2017-07-05 16:09:29 +05303223
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303224 if (crypto_priv->def_tx_keyid == i) {
3225 sta_key->flags
3226 |= WLAN_CRYPTO_KEY_DEFAULT;
3227 sta_crypto_priv->def_tx_keyid =
3228 crypto_priv->def_tx_keyid;
3229 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303230 /* setting the broadcast/multicast key for sta*/
3231 if (opmode == QDF_STA_MODE ||
3232 opmode == QDF_IBSS_MODE){
3233 if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
3234 WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303235 vdev, sta_key, mac_addr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303236 cipher_table->cipher);
3237 }
3238 }
3239
3240 /* setting unicast key */
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303241 sta_key->flags &= ~WLAN_CRYPTO_KEY_GROUP;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303242 if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
3243 WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(vdev,
Ashok Ponnaiahb6962212017-07-31 10:12:57 +05303244 sta_key, mac_addr,
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303245 cipher_table->cipher);
3246 }
3247 }
3248 }
3249 }
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303250
sheenam monga1273bce2019-05-06 11:47:08 +05303251exit:
3252 if (opmode == QDF_STA_MODE)
3253 wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
3254
3255 return status;
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303256}
3257
3258/**
3259 * wlan_crypto_register_crypto_rx_ops - set crypto_rx_ops
Ashok Ponnaiah89d28812017-02-17 22:10:20 +05303260 * @crypto_rx_ops: crypto_rx_ops
3261 *
3262 * This function gets called by object manger to register crypto rx ops.
3263 *
3264 * Return: QDF_STATUS
3265 */
3266QDF_STATUS wlan_crypto_register_crypto_rx_ops(
3267 struct wlan_lmac_if_crypto_rx_ops *crypto_rx_ops){
3268 crypto_rx_ops->crypto_encap = wlan_crypto_encap;
3269 crypto_rx_ops->crypto_decap = wlan_crypto_decap;
3270 crypto_rx_ops->crypto_enmic = wlan_crypto_enmic;
3271 crypto_rx_ops->crypto_demic = wlan_crypto_demic;
3272 crypto_rx_ops->set_peer_wep_keys = wlan_crypto_set_peer_wep_keys;
3273
3274 return QDF_STATUS_SUCCESS;
3275}
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05303276
3277/**
3278 * wlan_crypto_get_crypto_rx_ops - get crypto_rx_ops from psoc
Ashok Ponnaiah13e9f9b2017-03-14 04:45:29 +05303279 * @psoc: psoc
3280 *
3281 * This function gets called by umac to get the crypto_rx_ops
3282 *
3283 * Return: crypto_rx_ops
3284 */
3285struct wlan_lmac_if_crypto_rx_ops *wlan_crypto_get_crypto_rx_ops(
3286 struct wlan_objmgr_psoc *psoc)
3287{
3288
3289 return &(psoc->soc_cb.rx_ops.crypto_rx_ops);
3290}
Manikandan Mohana2993a52018-03-01 16:21:55 -08003291qdf_export_symbol(wlan_crypto_get_crypto_rx_ops);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05303292
3293/**
3294 * wlan_crypto_vdev_has_auth_mode - check authmode for vdev
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05303295 * @vdev: vdev
3296 * @authvalue: authvalue to be checked
3297 *
3298 * This function check is authvalue passed is set in vdev or not
3299 *
3300 * Return: true or false
3301 */
3302bool wlan_crypto_vdev_has_auth_mode(struct wlan_objmgr_vdev *vdev,
3303 wlan_crypto_auth_mode authvalue)
3304{
3305 return wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_AUTH_MODE)
3306 & authvalue;
3307}
Ashok Ponnaiah455eb682018-03-19 10:33:22 +05303308qdf_export_symbol(wlan_crypto_vdev_has_auth_mode);
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05303309
3310/**
3311 * wlan_crypto_peer_has_auth_mode - check authmode for peer
Ashok Ponnaiah2a3df502017-07-07 17:01:41 +05303312 * @peer: peer
3313 * @authvalue: authvalue to be checked
3314 *
3315 * This function check is authvalue passed is set in peer or not
3316 *
3317 * Return: true or false
3318 */
3319bool wlan_crypto_peer_has_auth_mode(struct wlan_objmgr_peer *peer,
3320 wlan_crypto_auth_mode authvalue)
3321{
3322 return wlan_crypto_get_peer_param(peer, WLAN_CRYPTO_PARAM_AUTH_MODE)
3323 & authvalue;
3324}
Ashok Ponnaiah455eb682018-03-19 10:33:22 +05303325qdf_export_symbol(wlan_crypto_peer_has_auth_mode);
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05303326
Ashok Ponnaiahafb88932018-04-17 10:15:24 +05303327/**
3328 * wlan_crypto_vdev_has_ucastcipher - check ucastcipher for vdev
3329 * @vdev: vdev
3330 * @ucastcipher: ucastcipher to be checked
3331 *
3332 * This function check is ucastcipher passed is set in vdev or not
3333 *
3334 * Return: true or false
3335 */
3336bool wlan_crypto_vdev_has_ucastcipher(struct wlan_objmgr_vdev *vdev,
3337 wlan_crypto_cipher_type ucastcipher)
3338{
3339 return wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER)
3340 & ucastcipher;
3341}
3342qdf_export_symbol(wlan_crypto_vdev_has_ucastcipher);
3343
3344/**
3345 * wlan_crypto_peer_has_ucastcipher - check ucastcipher for peer
3346 * @peer: peer
3347 * @ucastcipher: ucastcipher to be checked
3348 *
3349 * This function check is ucastcipher passed is set in peer or not
3350 *
3351 * Return: true or false
3352 */
3353bool wlan_crypto_peer_has_ucastcipher(struct wlan_objmgr_peer *peer,
3354 wlan_crypto_cipher_type ucastcipher)
3355{
3356 return wlan_crypto_get_peer_param(peer, WLAN_CRYPTO_PARAM_UCAST_CIPHER)
3357 & ucastcipher;
3358}
3359qdf_export_symbol(wlan_crypto_peer_has_ucastcipher);
3360
3361/**
3362 * wlan_crypto_vdev_has_mcastcipher - check mcastcipher for vdev
3363 * @vdev: vdev
3364 * @mcastcipher: mcastcipher to be checked
3365 *
3366 * This function check is mcastcipher passed is set in vdev or not
3367 *
3368 * Return: true or false
3369 */
3370bool wlan_crypto_vdev_has_mcastcipher(struct wlan_objmgr_vdev *vdev,
3371 wlan_crypto_cipher_type mcastcipher)
3372{
3373 return wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MCAST_CIPHER)
3374 & mcastcipher;
3375}
3376qdf_export_symbol(wlan_crypto_vdev_has_mcastcipher);
3377
3378/**
3379 * wlan_crypto_peer_has_mcastcipher - check mcastcipher for peer
3380 * @peer: peer
3381 * @mcastcipher: mcastcipher to be checked
3382 *
3383 * This function check is mcastcipher passed is set in peer or not
3384 *
3385 * Return: true or false
3386 */
3387bool wlan_crypto_peer_has_mcastcipher(struct wlan_objmgr_peer *peer,
3388 wlan_crypto_cipher_type mcastcipher)
3389{
Rohan Dutta0bdfabf2018-08-01 03:22:36 +05303390 return wlan_crypto_get_peer_param(peer, WLAN_CRYPTO_PARAM_MCAST_CIPHER)
Ashok Ponnaiahafb88932018-04-17 10:15:24 +05303391 & mcastcipher;
3392}
3393qdf_export_symbol(wlan_crypto_peer_has_mcastcipher);
3394
Liangwei Dong51cff6d2019-03-27 05:18:47 -04003395/**
3396 * wlan_crypto_vdev_has_mgmtcipher - check mgmtcipher for vdev
3397 * @vdev: vdev
3398 * @mgmtcipher: mgmtcipher to be checked
3399 *
3400 * This function checks any one of mgmtciphers are supported by vdev or not.
3401 *
3402 * Return: true or false
3403 */
3404bool wlan_crypto_vdev_has_mgmtcipher(struct wlan_objmgr_vdev *vdev,
3405 uint32_t mgmtcipher)
3406{
3407 return (wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MGMT_CIPHER)
3408 & mgmtcipher) != 0;
3409}
3410
3411qdf_export_symbol(wlan_crypto_vdev_has_mgmtcipher);
3412
3413/**
3414 * wlan_crypto_peer_has_mgmtcipher - check mgmtcipher for peer
3415 * @peer: peer
3416 * @mgmtcipher: mgmtcipher to be checked
3417 *
3418 * This function checks any one of mgmtciphers are supported by peer or not
3419 *
3420 * Return: true or false
3421 */
3422bool wlan_crypto_peer_has_mgmtcipher(struct wlan_objmgr_peer *peer,
3423 uint32_t mgmtcipher)
3424{
3425 return (wlan_crypto_get_peer_param(peer, WLAN_CRYPTO_PARAM_MGMT_CIPHER)
3426 & mgmtcipher) != 0;
3427}
3428
3429qdf_export_symbol(wlan_crypto_peer_has_mgmtcipher);
3430
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05303431uint8_t wlan_crypto_get_peer_fils_aead(struct wlan_objmgr_peer *peer)
3432{
3433 struct wlan_crypto_comp_priv *crypto_priv = NULL;
3434
3435 if (!peer) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303436 crypto_err("Invalid Input");
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05303437 return 0;
3438 }
3439
3440 crypto_priv = wlan_get_peer_crypto_obj(peer);
3441 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303442 crypto_err("crypto_priv NULL");
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05303443 return 0;
3444 }
3445
3446 return crypto_priv->fils_aead_set;
3447}
3448
3449void
3450wlan_crypto_set_peer_fils_aead(struct wlan_objmgr_peer *peer, uint8_t value)
3451{
3452 struct wlan_crypto_comp_priv *crypto_priv = NULL;
3453
3454 if (!peer) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303455 crypto_err("Invalid Input");
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05303456 return;
3457 }
3458
3459 crypto_priv = wlan_get_peer_crypto_obj(peer);
3460 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303461 crypto_err("crypto_priv NULL");
Subrat Mishra2b75d6d2017-08-07 17:36:25 +05303462 return;
3463 }
3464
3465 crypto_priv->fils_aead_set = value;
3466}
Padma Raghunathan94921612018-04-30 10:02:09 +05303467
3468/**
Padma Raghunathan51d11032018-04-09 10:21:37 +05303469 * wlan_crypto_get_key_header - get header length
3470 * @key: key
3471 *
3472 * This function gets header length based on keytype
3473 *
3474 * Return: header length
3475 */
3476uint8_t wlan_crypto_get_key_header(struct wlan_crypto_key *key)
3477{
3478 struct wlan_crypto_cipher *cipher_table;
3479
3480 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
3481 if (cipher_table)
3482 return cipher_table->header;
3483 else
3484 return 0;
3485}
3486
3487qdf_export_symbol(wlan_crypto_get_key_header);
3488
3489/**
3490 * wlan_crypto_get_key_trailer - get cipher trailer length
3491 * @key: key
3492 *
3493 * This function gets cipher trailer length based on keytype
3494 *
3495 * Return: cipher trailer length
3496 */
3497uint8_t wlan_crypto_get_key_trailer(struct wlan_crypto_key *key)
3498{
3499 struct wlan_crypto_cipher *cipher_table;
3500
3501 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
3502 if (cipher_table)
3503 return cipher_table->trailer;
3504 else
3505 return 0;
3506}
3507
3508qdf_export_symbol(wlan_crypto_get_key_trailer);
3509
3510/**
3511 * wlan_crypto_get_key_miclen - get cipher miclen length
3512 * @key: key
3513 *
3514 * This function gets cipher miclen length based on keytype
3515 *
3516 * Return: cipher miclen length
3517 */
3518uint8_t wlan_crypto_get_key_miclen(struct wlan_crypto_key *key)
3519{
3520 struct wlan_crypto_cipher *cipher_table;
3521
3522 cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
3523 if (cipher_table)
3524 return cipher_table->miclen;
3525 else
3526 return 0;
3527}
3528
3529qdf_export_symbol(wlan_crypto_get_key_miclen);
3530
3531/**
Padma Raghunathan94921612018-04-30 10:02:09 +05303532 * wlan_crypto_get_keyid - get keyid from frame
3533 * @data: frame
3534 *
3535 * This function parse frame and returns keyid
3536 *
3537 * Return: keyid
3538 */
3539uint16_t wlan_crypto_get_keyid(uint8_t *data, int hdrlen)
3540{
Disha Dasdf10f652018-12-10 16:20:56 +05303541 struct wlan_frame_hdr *hdr = (struct wlan_frame_hdr *)data;
Padma Raghunathan94921612018-04-30 10:02:09 +05303542 uint8_t *iv;
Disha Dasdf10f652018-12-10 16:20:56 +05303543 uint8_t stype = WLAN_FC0_GET_STYPE(hdr->i_fc[0]);
Subrat Mishra4493d2d2018-05-21 12:20:52 +05303544
3545 /*
3546 * In FILS SK (Re)Association request/response frame has
3547 * to be decrypted
3548 */
3549 if ((stype == WLAN_FC0_STYPE_ASSOC_REQ) ||
3550 (stype == WLAN_FC0_STYPE_REASSOC_REQ) ||
3551 (stype == WLAN_FC0_STYPE_ASSOC_RESP) ||
3552 (stype == WLAN_FC0_STYPE_REASSOC_RESP)) {
3553 return 0;
3554 }
Padma Raghunathan94921612018-04-30 10:02:09 +05303555
Disha Dasdf10f652018-12-10 16:20:56 +05303556 if (hdr->i_fc[1] & WLAN_FC1_ISWEP) {
Padma Raghunathan94921612018-04-30 10:02:09 +05303557 iv = data + hdrlen;
3558 /*
3559 * iv[3] is the Key ID octet in the CCMP/TKIP/WEP headers
3560 * Bits 6–7 of the Key ID octet are for the Key ID subfield
3561 */
3562 return ((iv[3] >> 6) & 0x3);
3563 } else {
3564 return WLAN_CRYPTO_KEYIX_NONE;
3565 }
3566}
3567
3568qdf_export_symbol(wlan_crypto_get_keyid);
Padma Raghunathan43ebaa72018-04-30 09:46:38 +05303569
3570/**
3571 * crypto_plumb_peer_keys - called during radio reset
3572 * @vdev: vdev
3573 * @object: peer
3574 * @arg: psoc
3575 *
3576 * Restore unicast and persta hardware keys
3577 *
3578 * Return: void
3579 */
3580static void crypto_plumb_peer_keys(struct wlan_objmgr_vdev *vdev,
3581 void *object, void *arg) {
3582 struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)object;
3583 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)arg;
3584 struct wlan_crypto_comp_priv *crypto_priv;
3585 struct wlan_crypto_params *crypto_params;
3586 struct wlan_crypto_key *key = NULL;
3587 int i;
3588
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07003589 if ((!peer) || (!vdev) || (!psoc)) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303590 crypto_err("Peer or vdev or psoc objects are null!");
Padma Raghunathan43ebaa72018-04-30 09:46:38 +05303591 return;
3592 }
3593
3594 crypto_params = wlan_crypto_peer_get_comp_params(peer,
3595 &crypto_priv);
3596
3597 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303598 crypto_err("crypto_priv NULL");
Padma Raghunathan43ebaa72018-04-30 09:46:38 +05303599 return;
3600 }
3601
3602 for (i = 0; i < WLAN_CRYPTO_MAXKEYIDX; i++) {
3603 key = crypto_priv->key[i];
3604 if (key && key->valid) {
3605 if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
3606 WLAN_CRYPTO_TX_OPS_SETKEY(psoc)
3607 (
3608 vdev,
3609 key,
3610 wlan_peer_get_macaddr(peer),
3611 wlan_crypto_get_key_type(key)
3612 );
3613 }
3614 }
3615 }
3616}
3617
3618/**
3619 * wlan_crypto_restore_keys - called during radio reset
3620 * @vdev: vdev
3621 *
3622 * Clear and restore keycache, needed for some DA chipsets which put
3623 * random values in keycache when phy reset is triggered
3624 *
3625 * Return: void
3626 */
3627void wlan_crypto_restore_keys(struct wlan_objmgr_vdev *vdev)
3628{
3629 int i;
3630 struct wlan_crypto_comp_priv *crypto_priv;
3631 struct wlan_crypto_params *crypto_params;
3632 struct wlan_crypto_key *key;
Disha Dasdf10f652018-12-10 16:20:56 +05303633 uint8_t macaddr[QDF_MAC_ADDR_SIZE] =
3634 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Padma Raghunathan43ebaa72018-04-30 09:46:38 +05303635 struct wlan_objmgr_pdev *pdev = NULL;
3636 struct wlan_objmgr_psoc *psoc = NULL;
3637
3638 pdev = wlan_vdev_get_pdev(vdev);
3639 psoc = wlan_vdev_get_psoc(vdev);
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07003640 if (!pdev) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303641 crypto_err("pdev is NULL");
Padma Raghunathan43ebaa72018-04-30 09:46:38 +05303642 return;
3643 }
Jeff Johnsonf3a2b892019-03-20 12:07:03 -07003644 if (!psoc) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303645 crypto_err("psoc is NULL");
Padma Raghunathan43ebaa72018-04-30 09:46:38 +05303646 return;
3647 }
3648
3649 /* TBD: QWRAP key restore*/
3650 /* crypto is on */
3651 if (wlan_vdev_mlme_feat_cap_get(vdev, WLAN_VDEV_F_PRIVACY)) {
3652 /* restore static shared keys */
3653 for (i = 0; i < WLAN_CRYPTO_MAXKEYIDX; i++) {
3654 crypto_params = wlan_crypto_vdev_get_comp_params
3655 (
3656 vdev,
3657 &crypto_priv
3658 );
3659 if (!crypto_priv) {
Vignesh Mohan9d1c7a22018-08-20 16:35:00 +05303660 crypto_err("crypto_priv is NULL");
Padma Raghunathan43ebaa72018-04-30 09:46:38 +05303661 return;
3662 }
3663 key = crypto_priv->key[i];
3664 if (key && key->valid) {
3665 if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
3666 WLAN_CRYPTO_TX_OPS_SETKEY(psoc)
3667 (
3668 vdev,
3669 key,
3670 macaddr,
3671 wlan_crypto_get_key_type(key)
3672 );
3673 }
3674 }
3675 }
3676
3677 wlan_objmgr_iterate_peerobj_list(vdev,
3678 crypto_plumb_peer_keys,
3679 psoc,
3680 WLAN_CRYPTO_ID);
3681 }
3682}
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07003683
3684/**
3685 * wlan_crypto_check_open_none - called by ucfg to check for open security
3686 * @psoc: psoc pointer
3687 * @vdev_id: vdev id
3688 *
3689 * This function gets called from ucfg to check open security.
3690 *
3691 * Return: true or false
3692 */
3693bool wlan_crypto_check_open_none(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
3694{
3695 struct wlan_crypto_comp_priv *crypto_priv;
3696 struct wlan_crypto_params *crypto_params;
3697 struct wlan_objmgr_vdev *vdev;
3698 bool match = true;
3699
3700 if (!psoc) {
3701 crypto_err("PSOC is NULL");
3702 return false;
3703 }
3704 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
3705 WLAN_CRYPTO_ID);
3706 if (!vdev) {
3707 crypto_err("vdev is NULL");
3708 return false;
3709 }
3710
3711 crypto_priv = (struct wlan_crypto_comp_priv *)
3712 wlan_get_vdev_crypto_obj(vdev);
3713
3714 if (!crypto_priv) {
3715 crypto_err("crypto_priv NULL");
3716 match = false;
3717 goto send_res;
3718 }
3719
3720 crypto_params = &crypto_priv->crypto_params;
3721
3722 if (crypto_params->mcastcipherset != WLAN_CRYPTO_CIPHER_NONE) {
3723 match = false;
3724 goto send_res;
3725 }
3726
3727 if ((crypto_params->authmodeset != WLAN_CRYPTO_AUTH_AUTO) &&
3728 (crypto_params->authmodeset != WLAN_CRYPTO_AUTH_NONE))
3729 match = false;
3730
3731send_res:
3732 wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
3733
3734 return match;
3735}
3736
3737/**
3738 * wlan_crypto_check_wep - called by ucfg to check for WEP security
3739 * @psoc: psoc pointer
3740 * @vdev_id: vdev id
3741 *
3742 * This function gets called from ucfg to check WEP security.
3743 *
3744 * Return: true or false
3745 */
3746bool wlan_crypto_check_wep(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
3747{
3748 struct wlan_crypto_comp_priv *crypto_priv;
3749 struct wlan_crypto_params *crypto_params;
3750 struct wlan_objmgr_vdev *vdev;
3751 bool match = true;
3752
3753 if (!psoc) {
3754 crypto_err("PSOC is NULL");
3755 return false;
3756 }
3757 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
3758 WLAN_CRYPTO_ID);
3759 if (!vdev) {
3760 crypto_err("vdev is NULL");
3761 return false;
3762 }
3763
3764 crypto_priv = (struct wlan_crypto_comp_priv *)
3765 wlan_get_vdev_crypto_obj(vdev);
3766
3767 if (!crypto_priv) {
3768 crypto_err("crypto_priv NULL");
3769 match = false;
3770 goto send_res;
3771 }
3772
3773 crypto_params = &crypto_priv->crypto_params;
3774
3775 if ((crypto_params->ucastcipherset != WLAN_CRYPTO_CIPHER_WEP) &&
3776 (crypto_params->ucastcipherset != WLAN_CRYPTO_CIPHER_WEP_40) &&
3777 (crypto_params->ucastcipherset != WLAN_CRYPTO_CIPHER_WEP_104)) {
3778 match = false;
3779 goto send_res;
3780 }
3781 if ((crypto_params->mcastcipherset != WLAN_CRYPTO_CIPHER_WEP) &&
3782 (crypto_params->mcastcipherset != WLAN_CRYPTO_CIPHER_WEP_40) &&
3783 (crypto_params->mcastcipherset != WLAN_CRYPTO_CIPHER_WEP_104)) {
3784 match = false;
3785 goto send_res;
3786 }
3787 if (crypto_params->ucastcipherset != crypto_params->mcastcipherset) {
3788 match = false;
3789 goto send_res;
3790 }
3791 if ((crypto_params->authmodeset != WLAN_CRYPTO_AUTH_AUTO) &&
3792 (crypto_params->authmodeset != WLAN_CRYPTO_AUTH_OPEN) &&
3793 (crypto_params->authmodeset != WLAN_CRYPTO_AUTH_SHARED)) {
3794 match = false;
3795 }
3796send_res:
3797 wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
3798
3799 return match;
3800}
3801
3802static QDF_STATUS
3803wlan_get_crypto_params_from_rsn_ie(struct wlan_crypto_params *crypto_params,
3804 uint8_t *ie_ptr, uint16_t ie_len)
3805{
3806 const uint8_t *rsn_ie = NULL;
3807 QDF_STATUS status;
3808
3809 qdf_mem_zero(crypto_params, sizeof(struct wlan_crypto_params));
3810 rsn_ie = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSN, ie_ptr, ie_len);
3811 if (!rsn_ie) {
3812 crypto_err("RSN IE NULL");
3813 return QDF_STATUS_E_INVAL;
3814 }
3815
3816 status = wlan_crypto_rsnie_check(crypto_params, (uint8_t *)rsn_ie);
3817 if (QDF_STATUS_SUCCESS != status) {
3818 crypto_err("RSN IE check failed");
3819 return status;
3820 }
3821
3822 return QDF_STATUS_SUCCESS;
3823}
3824
3825static QDF_STATUS
3826wlan_get_crypto_params_from_wpa_ie(struct wlan_crypto_params *crypto_params,
3827 uint8_t *ie_ptr, uint16_t ie_len)
3828{
3829 const uint8_t *wpa_ie = NULL;
3830 uint32_t wpa_oui;
3831 QDF_STATUS status;
3832
3833 qdf_mem_zero(crypto_params, sizeof(struct wlan_crypto_params));
3834
3835 wpa_oui = WLAN_WPA_SEL(WLAN_WPA_OUI_TYPE);
3836 wpa_ie = wlan_get_vendor_ie_ptr_from_oui((uint8_t *)&wpa_oui,
3837 WLAN_OUI_SIZE, ie_ptr, ie_len);
3838 if (!wpa_ie) {
3839 crypto_err("WPA IE NULL");
3840 return QDF_STATUS_E_INVAL;
3841 }
3842
3843 status = wlan_crypto_wpaie_check(crypto_params, (uint8_t *)wpa_ie);
3844 if (QDF_STATUS_SUCCESS != status) {
3845 crypto_err("WPA IE check failed");
3846 return status;
3847 }
3848
3849 return QDF_STATUS_SUCCESS;
3850}
3851/**
3852 * wlan_crypto_check_rsn_match - called by ucfg to check for RSN match
3853 * @psoc: psoc pointer
3854 * @vdev_id: vdev id
3855 * @ie_ptr: pointer to IEs
3856 * @ie_len: IE length
3857 *
3858 * This function gets called from ucfg to check RSN match.
3859 *
3860 * Return: true or false
3861 */
3862bool wlan_crypto_check_rsn_match(struct wlan_objmgr_psoc *psoc,
3863 uint8_t vdev_id, uint8_t *ie_ptr,
3864 uint16_t ie_len)
3865{
3866 struct wlan_crypto_params peer_crypto_params;
3867 struct wlan_objmgr_vdev *vdev;
3868 bool match = true;
3869 QDF_STATUS status;
3870
3871 if (!psoc) {
3872 crypto_err("PSOC is NULL");
3873 return false;
3874 }
3875 status = wlan_get_crypto_params_from_rsn_ie(&peer_crypto_params,
3876 ie_ptr, ie_len);
3877 if (QDF_STATUS_SUCCESS != status) {
3878 crypto_err("get crypto prarams from RSN IE failed");
3879 return false;
3880 }
3881 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
3882 WLAN_CRYPTO_ID);
3883 if (!vdev) {
3884 crypto_err("vdev is NULL");
3885 return false;
3886 }
3887
3888 match = wlan_crypto_rsn_info(vdev, &peer_crypto_params);
3889 wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
3890
3891 return match;
3892}
3893
3894/**
3895 * wlan_crypto_check_wpa_match - called by ucfg to check for WPA match
3896 * @psoc: psoc pointer
3897 * @vdev_id: vdev id
3898 * @ie_ptr: pointer to IEs
3899 * @ie_len: IE length
3900 *
3901 * This function gets called from ucfg to check WPA match.
3902 *
3903 * Return: true or false
3904 */
3905bool wlan_crypto_check_wpa_match(struct wlan_objmgr_psoc *psoc,
3906 uint8_t vdev_id, uint8_t *ie_ptr,
3907 uint16_t ie_len)
3908{
3909 struct wlan_crypto_params peer_crypto_params;
3910 struct wlan_objmgr_vdev *vdev;
3911 bool match = true;
3912 QDF_STATUS status;
3913
3914 if (!psoc) {
3915 crypto_err("PSOC is NULL");
3916 return false;
3917 }
3918 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
3919 WLAN_CRYPTO_ID);
3920 if (!vdev) {
3921 crypto_err("vdev is NULL");
3922 return false;
3923 }
3924
3925 status = wlan_get_crypto_params_from_wpa_ie(&peer_crypto_params,
3926 ie_ptr, ie_len);
3927 if (QDF_STATUS_SUCCESS != status) {
3928 crypto_err("get crypto prarams from WPA IE failed");
3929 match = false;
3930 goto send_res;
3931 }
3932 match = wlan_crypto_rsn_info(vdev, &peer_crypto_params);
3933send_res:
3934 wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
3935
3936 return match;
3937}
3938
3939
3940static void
3941wlan_crypto_merge_prarams(struct wlan_crypto_params *dst_params,
3942 struct wlan_crypto_params *src_params)
3943{
3944 dst_params->authmodeset |= src_params->authmodeset;
3945 dst_params->ucastcipherset |= src_params->ucastcipherset;
3946 dst_params->mcastcipherset |= src_params->mcastcipherset;
3947 dst_params->mgmtcipherset |= src_params->mgmtcipherset;
3948 dst_params->cipher_caps |= src_params->cipher_caps;
3949 dst_params->key_mgmt |= src_params->key_mgmt;
3950 dst_params->rsn_caps |= src_params->rsn_caps;
3951}
3952
Liangwei Dongca4abcf2019-03-20 04:06:54 -04003953static void
3954wlan_crypto_reset_prarams(struct wlan_crypto_params *params)
3955{
3956 params->authmodeset = 0;
3957 params->ucastcipherset = 0;
3958 params->mcastcipherset = 0;
3959 params->mgmtcipherset = 0;
3960 params->cipher_caps = 0;
3961 params->key_mgmt = 0;
3962 params->rsn_caps = 0;
3963}
3964
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07003965QDF_STATUS wlan_set_vdev_crypto_prarams_from_ie(struct wlan_objmgr_vdev *vdev,
3966 uint8_t *ie_ptr,
3967 uint16_t ie_len)
3968{
3969 struct wlan_crypto_params crypto_params;
3970 QDF_STATUS status;
3971 struct wlan_crypto_params *vdev_crypto_params;
3972 struct wlan_crypto_comp_priv *crypto_priv;
3973 bool send_fail = false;
3974
3975 if (!vdev) {
3976 crypto_err("VDEV is NULL");
3977 return QDF_STATUS_E_FAILURE;
3978 }
3979
3980 if (!ie_ptr) {
3981 crypto_err("IE ptr is NULL");
3982 return QDF_STATUS_E_FAILURE;
3983 }
3984
3985 crypto_priv = (struct wlan_crypto_comp_priv *)
3986 wlan_get_vdev_crypto_obj(vdev);
3987
3988 if (!crypto_priv) {
3989 crypto_err("crypto_priv NULL");
3990 return QDF_STATUS_E_FAILURE;
3991 }
3992
3993 vdev_crypto_params = &crypto_priv->crypto_params;
3994
Liangwei Dongca4abcf2019-03-20 04:06:54 -04003995 wlan_crypto_reset_prarams(vdev_crypto_params);
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07003996 status = wlan_get_crypto_params_from_rsn_ie(&crypto_params,
3997 ie_ptr, ie_len);
3998 if (QDF_STATUS_SUCCESS == status) {
3999 wlan_crypto_merge_prarams(vdev_crypto_params, &crypto_params);
4000 } else {
4001 crypto_err("get crypto prarams from RSN IE failed");
4002 send_fail = true;
4003 }
4004
4005 status = wlan_get_crypto_params_from_wpa_ie(&crypto_params,
4006 ie_ptr, ie_len);
4007 if (QDF_STATUS_SUCCESS == status) {
4008 wlan_crypto_merge_prarams(vdev_crypto_params, &crypto_params);
4009 send_fail = false;
4010 } else {
Bala Venkateshae946e32019-08-26 19:14:14 +05304011 crypto_debug("get crypto prarams from WPA IE failed");
Kiran Kumar Lokere605e7a72018-08-30 16:33:26 -07004012 }
4013
4014 return send_fail ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
4015}
Kiran Kumar Lokere25531c42018-09-19 13:48:48 -07004016
4017int8_t wlan_crypto_get_default_key_idx(struct wlan_objmgr_vdev *vdev, bool igtk)
4018{
4019 struct wlan_crypto_comp_priv *crypto_priv;
4020
4021 crypto_priv = wlan_get_vdev_crypto_obj(vdev);
4022 if (!crypto_priv) {
4023 crypto_err("crypto_priv NULL");
4024 return QDF_STATUS_E_FAILURE;
4025 }
4026
4027 if (igtk)
4028 return crypto_priv->def_igtk_tx_keyid;
4029 else
4030 return crypto_priv->def_tx_keyid;
4031}
4032
4033enum wlan_crypto_cipher_type
4034wlan_crypto_get_cipher(struct wlan_objmgr_vdev *vdev,
4035 bool pairwise, uint8_t key_index)
4036{
4037 struct wlan_crypto_key *crypto_key;
4038
4039 crypto_key = wlan_crypto_get_key(vdev, key_index);
4040
4041 if (crypto_key)
4042 return crypto_key->cipher_type;
4043 else
4044 return WLAN_CRYPTO_CIPHER_INVALID;
4045}
4046
4047#ifdef CRYPTO_SET_KEY_CONVERGED
4048QDF_STATUS wlan_crypto_validate_key_params(enum wlan_crypto_cipher_type cipher,
4049 uint8_t key_index, uint8_t key_len,
4050 uint8_t seq_len)
4051{
4052 if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) {
4053 crypto_err("Invalid Key index %d", key_index);
4054 return QDF_STATUS_E_INVAL;
4055 }
4056 if (cipher == WLAN_CRYPTO_CIPHER_INVALID) {
4057 crypto_err("Invalid Cipher %d", cipher);
4058 return QDF_STATUS_E_INVAL;
4059 }
4060 if ((!(cipher == WLAN_CRYPTO_CIPHER_AES_CMAC ||
4061 cipher == WLAN_CRYPTO_CIPHER_AES_CMAC_256 ||
4062 cipher == WLAN_CRYPTO_CIPHER_AES_GMAC ||
4063 cipher == WLAN_CRYPTO_CIPHER_AES_GMAC_256)) &&
4064 (key_index >= WLAN_CRYPTO_MAXKEYIDX)) {
4065 crypto_err("Invalid key index %d for cipher %d",
4066 key_index, cipher);
4067 return QDF_STATUS_E_INVAL;
4068 }
4069 if (key_len > (WLAN_CRYPTO_KEYBUF_SIZE + WLAN_CRYPTO_MICBUF_SIZE)) {
4070 crypto_err("Invalid key length %d", key_len);
4071 return QDF_STATUS_E_INVAL;
4072 }
4073
4074 if (seq_len > WLAN_CRYPTO_RSC_SIZE) {
4075 crypto_err("Invalid seq length %d", seq_len);
4076 return QDF_STATUS_E_INVAL;
4077 }
4078
4079 crypto_debug("key: idx:%d, len:%d, seq len:%d",
4080 key_index, key_len, seq_len);
4081
4082 return QDF_STATUS_SUCCESS;
4083}
4084
4085QDF_STATUS wlan_crypto_save_key(struct wlan_objmgr_vdev *vdev,
4086 uint8_t key_index,
4087 struct wlan_crypto_key *crypto_key)
4088{
4089 struct wlan_crypto_comp_priv *crypto_priv;
4090
4091 crypto_priv = wlan_get_vdev_crypto_obj(vdev);
4092 if (!crypto_priv) {
4093 crypto_err("crypto_priv NULL");
4094 return QDF_STATUS_E_FAILURE;
4095 }
4096 if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) {
4097 crypto_err("Invalid Key index %d", key_index);
4098 return QDF_STATUS_E_FAILURE;
4099 }
4100 if (key_index < WLAN_CRYPTO_MAXKEYIDX)
4101 crypto_priv->key[key_index] = crypto_key;
4102 else
4103 crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX] =
4104 crypto_key;
4105
4106 return QDF_STATUS_SUCCESS;
4107}
4108
4109struct wlan_crypto_key *wlan_crypto_get_key(struct wlan_objmgr_vdev *vdev,
4110 uint8_t key_index)
4111{
4112 struct wlan_crypto_comp_priv *crypto_priv;
4113
4114 crypto_priv = wlan_get_vdev_crypto_obj(vdev);
4115 if (!crypto_priv) {
4116 crypto_err("crypto_priv NULL");
4117 return NULL;
4118 }
4119 if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) {
4120 crypto_err("Invalid Key index %d", key_index);
4121 return NULL;
4122 }
4123 if (key_index < WLAN_CRYPTO_MAXKEYIDX)
4124 return crypto_priv->key[key_index];
4125
4126 return crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX];
4127}
4128
4129QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev,
4130 struct wlan_crypto_key *req,
Kiran Kumar Lokereb4d634f2019-01-11 18:32:32 -08004131 enum wlan_crypto_key_type key_type)
Kiran Kumar Lokere25531c42018-09-19 13:48:48 -07004132{
4133 struct wlan_objmgr_psoc *psoc;
4134
4135 psoc = wlan_vdev_get_psoc(vdev);
4136 if (psoc && WLAN_CRYPTO_TX_OPS_SET_KEY(psoc))
Kiran Kumar Lokereb4d634f2019-01-11 18:32:32 -08004137 WLAN_CRYPTO_TX_OPS_SET_KEY(psoc)(vdev, req, key_type);
Kiran Kumar Lokere25531c42018-09-19 13:48:48 -07004138 else
4139 return QDF_STATUS_E_FAILURE;
4140
4141 return QDF_STATUS_SUCCESS;
4142}
4143
4144void wlan_crypto_update_set_key_peer(struct wlan_objmgr_vdev *vdev,
4145 bool pairwise, uint8_t key_index,
4146 struct qdf_mac_addr *peer_mac)
4147{
4148 struct wlan_crypto_key *crypto_key;
4149
4150 crypto_key = wlan_crypto_get_key(vdev, key_index);
4151 if (!crypto_key) {
4152 crypto_err("crypto_key not present for key_idx %d", key_index);
4153 return;
4154 }
4155
4156 qdf_mem_copy(crypto_key->macaddr, peer_mac, QDF_MAC_ADDR_SIZE);
4157}
4158#endif