1 /*
2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include "lim_process_fils.h"
21 #include <lim_send_messages.h>
22 #include <lim_types.h>
23 #include <lim_utils.h>
24 #include <lim_prop_exts_utils.h>
25 #include <lim_assoc_utils.h>
26 #include <lim_session.h>
27 #include <qdf_crypto.h>
28 #include "qdf_util.h"
29 #include "wlan_crypto_global_api.h"
30 #include "wlan_cm_roam_api.h"
31
32 #ifdef WLAN_FEATURE_FILS_SK
33
34 #ifdef WLAN_FILS_DEBUG
35 /**
36 * lim_fils_data_dump()- dump fils data
37 * @type: Data name
38 * @data: pointer to data buffer
39 * @len: data len
40 *
41 * Return: None
42 */
lim_fils_data_dump(char * type,uint8_t * data,uint32_t len)43 static void lim_fils_data_dump(char *type, uint8_t *data, uint32_t len)
44 {
45
46 pe_debug("%s : length %d", type, len);
47 qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, data, len);
48 }
49 #else
lim_fils_data_dump(char * type,uint8_t * data,uint32_t len)50 static void lim_fils_data_dump(char *type, uint8_t *data, uint32_t len)
51 { }
52 #endif
53
54 /**
55 * lim_get_crypto_digest_len()- Returns hash length based on crypto type
56 * @type: Crypto type
57 *
58 * Return: hash length
59 */
lim_get_crypto_digest_len(uint8_t * type)60 static int lim_get_crypto_digest_len(uint8_t *type)
61 {
62 if (!strcmp(type, HMAC_SHA386_CRYPTO_TYPE))
63 return SHA384_DIGEST_SIZE;
64 else if (!strcmp(type, HMAC_SHA256_CRYPTO_TYPE))
65 return SHA256_DIGEST_SIZE;
66
67 return 0;
68 }
69
70 /**
71 * lim_get_auth_tag_len()- This API returns auth tag len based on crypto suit
72 * used to encrypt erp packet.
73 * @crypto_suite: Crtpto suit
74 *
75 * Return: tag length
76 */
lim_get_auth_tag_len(enum fils_erp_cryptosuite crypto_suite)77 static uint8_t lim_get_auth_tag_len(enum fils_erp_cryptosuite crypto_suite)
78 {
79 switch (crypto_suite) {
80 case HMAC_SHA256_64:
81 return -EINVAL;
82 case HMAC_SHA256_128:
83 return FILS_SHA256_128_AUTH_TAG;
84 case HMAC_SHA256_256:
85 return FILS_SHA256_256_AUTH_TAG;
86 default:
87 return -EINVAL;
88 }
89 }
90
91
92 /**
93 * lim_get_crypto_type()- This API returns crypto type based on akm suite used
94 * @akm: akm used for authentication
95 *
96 * Return: Crypto type
97 */
lim_get_hash_crypto_type(uint8_t akm)98 static uint8_t *lim_get_hash_crypto_type(uint8_t akm)
99 {
100 switch (akm) {
101 case eCSR_AUTH_TYPE_FILS_SHA384:
102 case eCSR_AUTH_TYPE_FT_FILS_SHA384:
103 return SHA386_CRYPTO_TYPE;
104 case eCSR_AUTH_TYPE_FILS_SHA256:
105 case eCSR_AUTH_TYPE_FT_FILS_SHA256:
106 default:
107 return SHA256_CRYPTO_TYPE;
108 }
109 }
110
111 /**
112 * lim_get_hmac_crypto_type()- This API returns crypto type based on akm suite
113 * used.
114 * @akm: akm used for authentication
115 *
116 * This API is used to get the crypto type when HMAC-hash() needs to
117 * be generated.
118 * Eg: PMK = HMAC-Hash(SNonce || ANonce, rMSK [ || DHss ])
119 * Here HMAC-Hash will be either hmac(sha256) or hmac(sha384)
120 *
121 * Return: Crypto type
122 */
lim_get_hmac_crypto_type(uint8_t akm)123 static uint8_t *lim_get_hmac_crypto_type(uint8_t akm)
124 {
125 switch (akm) {
126 case eCSR_AUTH_TYPE_FILS_SHA384:
127 case eCSR_AUTH_TYPE_FT_FILS_SHA384:
128 return HMAC_SHA386_CRYPTO_TYPE;
129 case eCSR_AUTH_TYPE_FILS_SHA256:
130 case eCSR_AUTH_TYPE_FT_FILS_SHA256:
131 default:
132 return HMAC_SHA256_CRYPTO_TYPE;
133 }
134 }
135
136 /**
137 * lim_get_Q_length()- This API returns pmk length based on akm used
138 * @akm: akm used for authentication
139 *
140 * [IEEE 802.11ai - 12.7.1.7.3 PMK-R0]
141 * PMK-R0 = L(R0-Key-Data, 0, Q)
142 * where Q is 32 if AKM negotiated is 00-0F-AC:16
143 * Q is 48 if AKM negotiated is 00-0F-AC:17
144 *
145 * PMK-R0 Derivation is for FT protocol akm only.
146 * So Value of Q is not applicable for non-FT akm.
147 *
148 * Return: Q length
149 */
lim_get_Q_length(int akm_type)150 static uint8_t lim_get_Q_length(int akm_type)
151 {
152 switch (akm_type) {
153 case eCSR_AUTH_TYPE_FT_FILS_SHA256:
154 return FILS_SHA256_Q_LEN;
155 case eCSR_AUTH_TYPE_FT_FILS_SHA384:
156 return FILS_SHA384_Q_LEN;
157 default:
158 return 0;
159 }
160 }
161
162 /**
163 * lim_get_pmk_length()- This API returns pmk length based on akm used
164 * @akm: akm used for authentication
165 *
166 * Return: PMK length
167 */
lim_get_pmk_length(int akm_type)168 static uint8_t lim_get_pmk_length(int akm_type)
169 {
170 switch (akm_type) {
171 case eCSR_AUTH_TYPE_FILS_SHA256:
172 case eCSR_AUTH_TYPE_FT_FILS_SHA256:
173 return FILS_SHA256_PMK_LEN;
174 case eCSR_AUTH_TYPE_FILS_SHA384:
175 case eCSR_AUTH_TYPE_FT_FILS_SHA384:
176 return FILS_SHA384_PMK_LEN;
177 default:
178 return FILS_SHA256_PMK_LEN;
179 }
180 }
181
182 /**
183 * lim_get_fils_ft_length()- This API returns fils_ft length based on akm used
184 * @akm: akm used for authentication
185 *
186 * FILS_FT is the xx key used in derivation of the PMKR0.
187 *
188 * Return: PMK length
189 */
lim_get_fils_ft_length(int akm_type)190 static uint8_t lim_get_fils_ft_length(int akm_type)
191 {
192 switch (akm_type) {
193 case eCSR_AUTH_TYPE_FT_FILS_SHA256:
194 return FILS_FT_SHA256_LEN;
195 case eCSR_AUTH_TYPE_FT_FILS_SHA384:
196 return FILS_FT_SHA384_LEN;
197 default:
198 return 0;
199 }
200 }
201
202 /**
203 * lim_get_kek_len()- This API returns kek length based on akm used
204 * @akm: akm used for authentication
205 *
206 * Return: KEK length
207 */
lim_get_kek_len(uint8_t akm)208 static uint8_t lim_get_kek_len(uint8_t akm)
209 {
210 switch (akm) {
211 case eCSR_AUTH_TYPE_FILS_SHA384:
212 case eCSR_AUTH_TYPE_FT_FILS_SHA384:
213 return FILS_SHA384_KEK_LEN;
214 case eCSR_AUTH_TYPE_FILS_SHA256:
215 case eCSR_AUTH_TYPE_FT_FILS_SHA256:
216 return FILS_SHA256_KEK_LEN;
217 default:
218 return FILS_SHA256_KEK_LEN;
219 }
220 }
221
222 /**
223 * lim_get_tk_len()- This API returns tk length based on cypher used
224 * @akm: cypher used
225 *
226 * Return: TK length
227 */
lim_get_tk_len(int cypher_suite)228 static uint8_t lim_get_tk_len(int cypher_suite)
229 {
230 switch (cypher_suite) {
231 case eSIR_ED_TKIP:
232 return TK_LEN_TKIP;
233 case eSIR_ED_CCMP:
234 return TK_LEN_CCMP;
235 case eSIR_ED_AES_128_CMAC:
236 return TK_LEN_AES_128_CMAC;
237 default:
238 return 0;
239 }
240 }
241
242 /**
243 * lim_get_ick_len()- This API returns ick length based on akm used
244 * @akm: akm used for authentication
245 *
246 * Return: ICK length
247 */
lim_get_ick_len(uint8_t akm)248 static int lim_get_ick_len(uint8_t akm)
249 {
250 switch (akm) {
251 case eCSR_AUTH_TYPE_FILS_SHA384:
252 case eCSR_AUTH_TYPE_FT_FILS_SHA384:
253 return FILS_SHA384_ICK_LEN;
254 case eCSR_AUTH_TYPE_FILS_SHA256:
255 case eCSR_AUTH_TYPE_FT_FILS_SHA256:
256 default:
257 return FILS_SHA256_ICK_LEN;
258 }
259 }
260
261 /**
262 * lim_get_key_from_prf()- This API returns key data using PRF-X as defined in
263 * 11.6.1.7.2 ieee-80211-2012.
264 * @type: crypto type needs to be used
265 * @secret: key which needs to be used in crypto
266 * @secret_len: key_len of secret
267 * @label: PRF label
268 * @optional_data: Data used for hash
269 * @optional_data_len: data length
270 * @key: key data output
271 * @keylen: key data length
272 *
273 * Return: QDF_STATUS
274 */
lim_get_key_from_prf(uint8_t * type,uint8_t * secret,uint32_t secret_len,uint8_t * label,uint8_t * optional_data,uint32_t optional_data_len,uint8_t * key,uint32_t keylen)275 static QDF_STATUS lim_get_key_from_prf(uint8_t *type, uint8_t *secret,
276 uint32_t secret_len, uint8_t *label, uint8_t *optional_data,
277 uint32_t optional_data_len, uint8_t *key, uint32_t keylen)
278 {
279 uint8_t count[2];
280 uint8_t *addr[4];
281 uint32_t len[4];
282 uint16_t key_bit_length = keylen * 8;
283 uint8_t key_length[2];
284 uint32_t i = 0, remain_len;
285 uint16_t iteration;
286 uint8_t crypto_digest_len = lim_get_crypto_digest_len(type);
287 uint8_t tmp_hash[SHA384_DIGEST_SIZE] = {0};
288
289 if (!crypto_digest_len) {
290 pe_err("Incorrect crypto length");
291 return QDF_STATUS_E_FAILURE;
292 }
293
294 addr[0] = count;
295 len[0] = sizeof(count);
296
297 addr[1] = label;
298 len[1] = strlen(label);
299
300 addr[2] = optional_data;
301 len[2] = optional_data_len;
302
303 qdf_mem_copy(key_length, &key_bit_length, sizeof(key_bit_length));
304 addr[3] = key_length;
305 len[3] = sizeof(key_length);
306
307 for (iteration = 1; i < keylen; iteration++) {
308 remain_len = keylen - i;
309 qdf_mem_copy(count, &iteration, sizeof(iteration));
310
311 if (remain_len >= crypto_digest_len)
312 remain_len = crypto_digest_len;
313
314 if (qdf_get_hmac_hash(type, secret, secret_len, 4,
315 addr, len, tmp_hash) < 0) {
316 pe_err("qdf_get_hmac_hash failed");
317 return QDF_STATUS_E_FAILURE;
318 }
319 qdf_mem_copy(&key[i], tmp_hash, remain_len);
320 i += crypto_digest_len;
321 }
322 return QDF_STATUS_SUCCESS;
323 }
324
325 /**
326 * lim_process_fils_eap_tlv()- This API process eap tlv available in auth resp
327 * and returns remaining length.
328 * @pe_session: PE session
329 * @wrapped_data: wrapped data
330 * @data_len: length of tlv
331 *
332 * Return: remaining length
333 */
lim_process_fils_eap_tlv(struct pe_session * pe_session,uint8_t * wrapped_data,uint32_t data_len)334 static uint32_t lim_process_fils_eap_tlv(struct pe_session *pe_session,
335 uint8_t *wrapped_data, uint32_t data_len)
336 {
337 struct fils_eap_tlv *tlv;
338 struct fils_auth_rsp_info *auth_info;
339 uint8_t auth_tag_len;
340
341 auth_info = &pe_session->fils_info->auth_info;
342 /* Minimum */
343 auth_tag_len = lim_get_auth_tag_len(HMAC_SHA256_128);
344
345 while (data_len > (auth_tag_len + 1)) {
346 tlv = (struct fils_eap_tlv *) wrapped_data;
347
348 pe_debug("tlv type %x len %u total %u",
349 tlv->type, tlv->length, data_len);
350
351 if (tlv->length > (data_len - 2)) {
352 pe_err("tlv len %d greater data_len %d",
353 tlv->length, data_len);
354 return 0;
355 }
356
357 switch (tlv->type) {
358 case SIR_FILS_EAP_TLV_KEYNAME_NAI:
359 auth_info->keyname = qdf_mem_malloc(tlv->length);
360 if (!auth_info->keyname)
361 return 0;
362
363 qdf_mem_copy(auth_info->keyname,
364 tlv->data, tlv->length);
365 auth_info->keylength = tlv->length;
366 data_len -= (tlv->length + 2);
367 wrapped_data += (tlv->length + 2);
368 break;
369 case SIR_FILS_EAP_TLV_R_RK_LIFETIME:
370 /* TODO check this */
371 auth_info->r_rk_lifetime = lim_get_u32(tlv->data);
372 data_len -= (tlv->length + 2);
373 wrapped_data += (tlv->length + 2);
374 break;
375 case SIR_FILS_EAP_TLV_R_MSK_LIFETIME:
376 /* TODO check this */
377 auth_info->r_msk_lifetime = lim_get_u32(tlv->data);
378 data_len -= (tlv->length + 2);
379 wrapped_data += (tlv->length + 2);
380 break;
381 case SIR_FILS_EAP_TLV_DOMAIN_NAME:
382 auth_info->domain_name = qdf_mem_malloc(tlv->length);
383 if (!auth_info->domain_name)
384 return 0;
385
386 qdf_mem_copy(auth_info->domain_name,
387 tlv->data, tlv->length);
388 auth_info->domain_len = tlv->length;
389 data_len -= (tlv->length + 2);
390 wrapped_data += (tlv->length + 2);
391 break;
392 /* TODO process these now */
393 case SIR_FILS_EAP_TLV_CRYPTO_LIST:
394 case SIR_FILS_EAP_TLV_AUTH_INDICATION:
395 data_len -= (tlv->length + 2);
396 wrapped_data += (tlv->length + 2);
397 break;
398 default:
399 pe_debug("Unknown type");
400 return data_len;
401 }
402 }
403 return data_len;
404 }
405
406 /**
407 * lim_generate_key_data()- This API generates key data using prf
408 * FILS-Key-Data = KDF-X(PMK, "FILS PTK Derivation", SPA||AA||SNonce||ANonce)
409 * @fils_info: fils session info
410 * @key_label: label used
411 * @data: data buffer
412 * @data_len: data buffer len
413 * @key_data: hash data needs to be generated
414 * @key_data_len: hash data len
415 *
416 * Return: QDF_STATUS
417 */
418 static QDF_STATUS
lim_generate_key_data(struct pe_fils_session * fils_info,uint8_t * key_label,uint8_t * data,uint32_t data_len,uint8_t * key_data,uint32_t key_data_len)419 lim_generate_key_data(struct pe_fils_session *fils_info,
420 uint8_t *key_label, uint8_t *data, uint32_t data_len,
421 uint8_t *key_data, uint32_t key_data_len)
422 {
423 QDF_STATUS status;
424
425 if (!fils_info)
426 return QDF_STATUS_E_FAILURE;
427
428 status = lim_get_key_from_prf(lim_get_hmac_crypto_type(fils_info->akm),
429 fils_info->fils_pmk,
430 fils_info->fils_pmk_len, key_label, data,
431 data_len, key_data, key_data_len);
432 if (status != QDF_STATUS_SUCCESS)
433 pe_err("failed to generate keydata");
434
435 return status;
436 }
437
438 /**
439 * lim_generate_ap_key_auth()- This API generates ap auth data which needs to be
440 * verified in assoc response.
441 * @pe_session: pe session pointer
442 *
443 * Return: None
444 */
lim_generate_ap_key_auth(struct pe_session * pe_session)445 static void lim_generate_ap_key_auth(struct pe_session *pe_session)
446 {
447 uint8_t *buf, *addr[1];
448 uint32_t len;
449 struct pe_fils_session *fils_info = pe_session->fils_info;
450 uint8_t data[SIR_FILS_NONCE_LENGTH + SIR_FILS_NONCE_LENGTH
451 + QDF_MAC_ADDR_SIZE + QDF_MAC_ADDR_SIZE] = {0};
452
453 if (!fils_info)
454 return;
455
456 len = SIR_FILS_NONCE_LENGTH + SIR_FILS_NONCE_LENGTH +
457 QDF_MAC_ADDR_SIZE + QDF_MAC_ADDR_SIZE;
458 addr[0] = data;
459 buf = data;
460 qdf_mem_copy(buf, fils_info->auth_info.fils_nonce,
461 SIR_FILS_NONCE_LENGTH);
462 buf += SIR_FILS_NONCE_LENGTH;
463 qdf_mem_copy(buf, fils_info->fils_nonce, SIR_FILS_NONCE_LENGTH);
464 buf += SIR_FILS_NONCE_LENGTH;
465 qdf_mem_copy(buf, pe_session->bssId, QDF_MAC_ADDR_SIZE);
466 buf += QDF_MAC_ADDR_SIZE;
467 qdf_mem_copy(buf, pe_session->self_mac_addr, QDF_MAC_ADDR_SIZE);
468 buf += QDF_MAC_ADDR_SIZE;
469
470 if (qdf_get_hmac_hash(lim_get_hmac_crypto_type(fils_info->akm),
471 fils_info->ick, fils_info->ick_len, 1, &addr[0],
472 &len, fils_info->ap_key_auth_data) < 0)
473 pe_err("failed to generate PMK id");
474 fils_info->ap_key_auth_len = lim_get_crypto_digest_len(
475 lim_get_hmac_crypto_type(fils_info->akm));
476 lim_fils_data_dump("AP Key Auth", fils_info->ap_key_auth_data,
477 fils_info->ap_key_auth_len);
478 }
479
480 /**
481 * lim_generate_key_auth()- This API generates sta auth data which needs to be
482 * send to AP in assoc request, AP will generate the same the verify it.
483 * @pe_session: pe session pointer
484 *
485 * Return: None
486 */
lim_generate_key_auth(struct pe_session * pe_session)487 static void lim_generate_key_auth(struct pe_session *pe_session)
488 {
489 uint8_t *buf, *addr[1];
490 uint32_t len;
491 struct pe_fils_session *fils_info = pe_session->fils_info;
492 uint8_t data[SIR_FILS_NONCE_LENGTH + SIR_FILS_NONCE_LENGTH
493 + QDF_MAC_ADDR_SIZE + QDF_MAC_ADDR_SIZE] = {0};
494
495 if (!fils_info)
496 return;
497
498 len = SIR_FILS_NONCE_LENGTH + SIR_FILS_NONCE_LENGTH +
499 QDF_MAC_ADDR_SIZE + QDF_MAC_ADDR_SIZE;
500
501 addr[0] = data;
502 buf = data;
503 qdf_mem_copy(buf, fils_info->fils_nonce, SIR_FILS_NONCE_LENGTH);
504 buf += SIR_FILS_NONCE_LENGTH;
505 qdf_mem_copy(buf, fils_info->auth_info.fils_nonce,
506 SIR_FILS_NONCE_LENGTH);
507 buf += SIR_FILS_NONCE_LENGTH;
508 qdf_mem_copy(buf, pe_session->self_mac_addr, QDF_MAC_ADDR_SIZE);
509 buf += QDF_MAC_ADDR_SIZE;
510 qdf_mem_copy(buf, pe_session->bssId, QDF_MAC_ADDR_SIZE);
511 buf += QDF_MAC_ADDR_SIZE;
512
513 if (qdf_get_hmac_hash(lim_get_hmac_crypto_type(fils_info->akm),
514 fils_info->ick, fils_info->ick_len, 1,
515 &addr[0], &len, fils_info->key_auth) < 0)
516 pe_err("failed to generate key auth");
517 fils_info->key_auth_len = lim_get_crypto_digest_len(
518 lim_get_hmac_crypto_type(fils_info->akm));
519 lim_fils_data_dump("STA Key Auth",
520 fils_info->key_auth, fils_info->key_auth_len);
521 }
522
523 /**
524 * lim_get_keys()- This API generates keys keydata which is generated after
525 * parsing of auth response.
526 * KCK = L(FILS-Key-Data, 0, KCK_bits)
527 * KEK = L(FILS-Key-Data, KCK_bits, KEK_bits)
528 * TK = L(FILS-Key-Data, KCK_bits + KEK_bits, TK_bits)
529 * FILS-FT = L(FILS-Key-Data, KCK_bits + KEK_bits + TK_bits, FILS-FT_bits)
530 * @pe_session: pe session pointer
531 *
532 * Return: None
533 */
lim_get_keys(struct mac_context * mac_ctx,struct pe_session * pe_session)534 static void lim_get_keys(struct mac_context *mac_ctx,
535 struct pe_session *pe_session)
536 {
537 uint8_t key_label[] = PTK_KEY_LABEL;
538 uint8_t *data;
539 uint8_t data_len;
540 struct pe_fils_session *fils_info = pe_session->fils_info;
541 uint8_t key_data[FILS_MAX_KEY_DATA_LEN] = {0};
542 uint8_t key_data_len;
543 uint8_t ick_len;
544 uint8_t kek_len;
545 uint8_t fils_ft_len = 0;
546 uint8_t tk_len = lim_get_tk_len(pe_session->encryptType);
547 uint8_t *buf;
548 QDF_STATUS status;
549
550 if (!fils_info)
551 return;
552
553 ick_len = lim_get_ick_len(fils_info->akm);
554 kek_len = lim_get_kek_len(fils_info->akm);
555
556 if (pe_session->is11Rconnection)
557 fils_ft_len = lim_get_fils_ft_length(fils_info->akm);
558
559 /*
560 * [IEEE 802.11ai - 12.12.2.5.3]
561 * FILS-Key-Data = PRF-X(PMK, “FILS PTK Derivation”, SPA || AA ||
562 * SNonce || ANonce)
563 * ICK = L(FILS-Key-Data, 0, ICK_bits)
564 * KEK = L(FILS-Key-Data, ICK_bits, KEK_bits)
565 * TK = L(FILS-Key-Data, ICK_bits + KEK_bits, TK_bits)
566 * When doing FT initial mobility domain association using
567 * FILS authentication,
568 * FILS-FT = L(FILS-Key-Data, ICK_bits + KEK_bits +
569 * TK_bits, FILS-FT_bits)
570 */
571 key_data_len = ick_len + kek_len + tk_len + fils_ft_len;
572
573 data_len = 2 * SIR_FILS_NONCE_LENGTH + 2 * QDF_MAC_ADDR_SIZE;
574 data = qdf_mem_malloc(data_len);
575 if (!data)
576 return;
577
578 /* data is SPA || AA ||SNonce || ANonce */
579 buf = data;
580 qdf_mem_copy(buf, pe_session->self_mac_addr, QDF_MAC_ADDR_SIZE);
581 buf += QDF_MAC_ADDR_SIZE;
582
583 qdf_mem_copy(buf, pe_session->bssId, QDF_MAC_ADDR_SIZE);
584 buf += QDF_MAC_ADDR_SIZE;
585
586 qdf_mem_copy(buf, fils_info->fils_nonce, SIR_FILS_NONCE_LENGTH);
587 buf += SIR_FILS_NONCE_LENGTH;
588
589 qdf_mem_copy(buf, fils_info->auth_info.fils_nonce,
590 SIR_FILS_NONCE_LENGTH);
591
592 /* Derive FILS-Key-Data */
593 lim_generate_key_data(fils_info, key_label, data, data_len,
594 key_data, key_data_len);
595 buf = key_data;
596
597 qdf_mem_copy(fils_info->ick, buf, ick_len);
598 fils_info->ick_len = ick_len;
599 buf += ick_len;
600
601 qdf_mem_copy(fils_info->kek, buf, kek_len);
602 fils_info->kek_len = kek_len;
603 buf += kek_len;
604
605 qdf_mem_copy(fils_info->tk, buf, tk_len);
606 fils_info->tk_len = tk_len;
607 buf += tk_len;
608
609 /*
610 * Derive FILS-FT:
611 * FILS-FT =
612 * L(FILS-Key-Data, ICK_bits + KEK_bits + TK_bits, FILS-FT_bits)
613 */
614 if (pe_session->is11Rconnection && fils_ft_len) {
615 qdf_mem_copy(fils_info->fils_ft, buf, fils_ft_len);
616 fils_info->fils_ft_len = fils_ft_len;
617 status = wlan_cm_update_fils_ft(mac_ctx->psoc,
618 pe_session->vdev_id,
619 fils_info->fils_ft,
620 fils_ft_len);
621 if (QDF_IS_STATUS_ERROR(status))
622 pe_err("Failed to update FILS FT to mlme");
623 }
624 qdf_mem_zero(data, data_len);
625 qdf_mem_free(data);
626 }
627
628 /**
629 * lim_generate_pmkid()- This API generates PMKID using hash of erp auth packet
630 * parsing of auth response.
631 * PMKID = Truncate-128(Hash(EAP-Initiate/Reauth))
632 * @pe_session: pe session pointer
633 *
634 * Return: None
635 */
lim_generate_pmkid(struct pe_session * pe_session)636 static void lim_generate_pmkid(struct pe_session *pe_session)
637 {
638 uint8_t hash[SHA384_DIGEST_SIZE];
639 struct pe_fils_session *fils_info = pe_session->fils_info;
640
641 if (!fils_info)
642 return;
643
644 qdf_get_hash(lim_get_hash_crypto_type(fils_info->akm), 1,
645 &fils_info->fils_erp_reauth_pkt,
646 &fils_info->fils_erp_reauth_pkt_len, hash);
647 qdf_mem_copy(fils_info->fils_pmkid, hash, PMKID_LEN);
648 lim_fils_data_dump("PMKID", fils_info->fils_pmkid, PMKID_LEN);
649 }
650
651 /**
652 * lim_generate_pmk()- This API generates PMK using hmac hash of rmsk data
653 * anonce, snonce will be used as key for this
654 * PMK = HMAC-Hash(SNonce || ANonce, rMSK [ || DHss ])
655 * @pe_session: pe session pointer
656 *
657 * Return: None
658 */
lim_generate_pmk(struct pe_session * pe_session)659 static void lim_generate_pmk(struct pe_session *pe_session)
660 {
661 uint8_t nonce[2 * SIR_FILS_NONCE_LENGTH] = {0};
662 uint8_t nonce_len = 2 * SIR_FILS_NONCE_LENGTH;
663 uint8_t *addr[1];
664 uint32_t len[1];
665 struct pe_fils_session *fils_info = pe_session->fils_info;
666
667 if (!fils_info)
668 return;
669
670 /* Snonce */
671 qdf_mem_copy(nonce, pe_session->fils_info->fils_nonce,
672 SIR_FILS_NONCE_LENGTH);
673 /* anonce */
674 qdf_mem_copy(nonce + SIR_FILS_NONCE_LENGTH,
675 pe_session->fils_info->auth_info.fils_nonce,
676 SIR_FILS_NONCE_LENGTH);
677 fils_info->fils_pmk_len = lim_get_pmk_length(fils_info->akm);
678
679 if (fils_info->fils_pmk)
680 qdf_mem_free(fils_info->fils_pmk);
681
682 fils_info->fils_pmk = qdf_mem_malloc(fils_info->fils_pmk_len);
683 if (!fils_info->fils_pmk)
684 return;
685
686 addr[0] = fils_info->fils_rmsk;
687 len[0] = fils_info->fils_rmsk_len;
688 lim_fils_data_dump("Nonce", nonce, nonce_len);
689 if (qdf_get_hmac_hash(lim_get_hmac_crypto_type(fils_info->akm), nonce,
690 nonce_len, 1, &addr[0], &len[0],
691 fils_info->fils_pmk) < 0)
692 pe_err("failed to generate PMK");
693 }
694
695 /**
696 * lim_generate_rmsk_data()- This API generates RMSK data using
697 * default kdf as defined in RFC4306.
698 * @pe_session: pe session pointer
699 *
700 * Return: None
701 */
lim_generate_rmsk_data(struct pe_session * pe_session)702 static void lim_generate_rmsk_data(struct pe_session *pe_session)
703 {
704 uint8_t optional_data[4] = {0};
705 uint8_t rmsk_label[] = RMSK_LABEL;
706 struct pe_fils_session *fils_info = pe_session->fils_info;
707 struct fils_auth_rsp_info *auth_info;
708
709 if (!fils_info)
710 return;
711
712 auth_info = &(pe_session->fils_info->auth_info);
713 fils_info->fils_rmsk_len = fils_info->fils_rrk_len;
714 fils_info->fils_rmsk = qdf_mem_malloc(fils_info->fils_rrk_len);
715 if (!fils_info->fils_rmsk)
716 return;
717
718 /*
719 * Sequence number sent in EAP-INIT packet,
720 * it should be in network byte order
721 */
722 lim_copy_u16_be(&optional_data[0], fils_info->sequence_number);
723 lim_copy_u16_be(&optional_data[2], fils_info->fils_rrk_len);
724 qdf_default_hmac_sha256_kdf(
725 fils_info->fils_rrk, fils_info->fils_rrk_len, rmsk_label,
726 optional_data, sizeof(optional_data), fils_info->fils_rmsk,
727 fils_info->fils_rmsk_len);
728 }
729
730 /**
731 * lim_process_auth_wrapped_data()- This API process wrapped data element
732 * of auth response.
733 * @pe_session: pe session pointer
734 * @wrapped_data: wrapped data pointer
735 * @data_len: wrapped data len
736 *
737 * Return: None
738 */
lim_process_auth_wrapped_data(struct pe_session * pe_session,uint8_t * wrapped_data,uint32_t data_len)739 static QDF_STATUS lim_process_auth_wrapped_data(struct pe_session *pe_session,
740 uint8_t *wrapped_data, uint32_t data_len)
741 {
742 uint8_t code;
743 uint8_t identifier;
744 uint16_t length;
745 uint8_t type;
746 unsigned long flags;
747 struct pe_fils_session *fils_info;
748 uint8_t hash[32] = {0}, crypto;
749 uint32_t remaining_len = data_len, new_len;
750 uint8_t *input_data[1];
751 uint32_t input_len[1];
752 uint8_t auth_tag_len;
753
754 fils_info = pe_session->fils_info;
755 input_data[0] = wrapped_data;
756 input_len[0] = data_len;
757
758 if (!fils_info)
759 return QDF_STATUS_E_FAILURE;
760
761 pe_debug("trying to process the wrappped data");
762
763 code = *wrapped_data;
764 wrapped_data++;
765 remaining_len--;
766 identifier = *wrapped_data;
767 wrapped_data++;
768 remaining_len--;
769
770 length = lim_get_u16(wrapped_data);
771 wrapped_data += sizeof(uint16_t);
772 remaining_len -= sizeof(uint16_t);
773
774 type = *wrapped_data; /* val should be 2 here */
775 wrapped_data++;
776 remaining_len--;
777
778 flags = *wrapped_data;
779 if (test_bit(7, &flags)) {
780 pe_err("R bit is set in flag, error");
781 return QDF_STATUS_E_FAILURE;
782 }
783 wrapped_data++;
784 remaining_len--;
785
786 fils_info->auth_info.sequence = lim_get_u16_be(wrapped_data);
787 wrapped_data += sizeof(uint16_t);
788 remaining_len -= sizeof(uint16_t);
789 /* Validate Auth sequence number */
790 if (fils_info->auth_info.sequence < fils_info->sequence_number) {
791 pe_err("sequence EAP-finish:%d is less than EAP-init:%d",
792 fils_info->auth_info.sequence,
793 fils_info->sequence_number);
794 return QDF_STATUS_E_FAILURE;
795 }
796
797 /* Parse attached TLVs */
798 new_len = lim_process_fils_eap_tlv(pe_session,
799 wrapped_data, remaining_len);
800
801 wrapped_data += remaining_len - new_len;
802 remaining_len = new_len;
803 /* Remove cryptosuite */
804 crypto = *wrapped_data;
805 wrapped_data++;
806 remaining_len--;
807
808 auth_tag_len = lim_get_auth_tag_len(crypto);
809 input_len[0] -= auth_tag_len;
810 /* if we have auth tag remaining */
811 if (remaining_len == auth_tag_len) {
812 qdf_get_hmac_hash(HMAC_SHA256_CRYPTO_TYPE,
813 fils_info->fils_rik,
814 fils_info->fils_rik_len,
815 SINGLE_ELEMENT_HASH_CNT,
816 input_data, input_len, hash);
817 } else {
818 pe_err("invalid remaining len %d",
819 remaining_len);
820 }
821 if (qdf_mem_cmp(wrapped_data, hash, auth_tag_len)) {
822 pe_err("integratity check failed for auth, crypto %d",
823 crypto);
824 return QDF_STATUS_E_FAILURE;
825 }
826
827 lim_generate_rmsk_data(pe_session);
828 lim_generate_pmk(pe_session);
829 lim_generate_pmkid(pe_session);
830 return QDF_STATUS_SUCCESS;
831 }
832
833 /**
834 * lim_is_valid_fils_auth_frame()- This API check whether auth frame is a
835 * valid frame.
836 * @mac_ctx: mac context
837 * @pe_session: pe session pointer
838 * @rx_auth_frm_body: pointer to autherntication frame
839 *
840 * Return: true if frame is valid or fils is disable, false otherwise
841 */
lim_is_valid_fils_auth_frame(struct mac_context * mac_ctx,struct pe_session * pe_session,tSirMacAuthFrameBody * rx_auth_frm_body)842 bool lim_is_valid_fils_auth_frame(struct mac_context *mac_ctx,
843 struct pe_session *pe_session,
844 tSirMacAuthFrameBody *rx_auth_frm_body)
845 {
846 if (!pe_session->fils_info)
847 return true;
848
849 if (pe_session->fils_info->is_fils_connection == false)
850 return true;
851
852 if (qdf_mem_cmp(rx_auth_frm_body->session,
853 pe_session->fils_info->fils_session,
854 SIR_FILS_SESSION_LENGTH)) {
855 lim_fils_data_dump("Current FILS session",
856 pe_session->fils_info->fils_session,
857 SIR_FILS_SESSION_LENGTH);
858 lim_fils_data_dump("FILS Session in pkt",
859 rx_auth_frm_body->session,
860 SIR_FILS_SESSION_LENGTH);
861 return false;
862 }
863 qdf_mem_copy(pe_session->fils_info->auth_info.fils_nonce,
864 rx_auth_frm_body->nonce, SIR_FILS_NONCE_LENGTH);
865 pe_session->fils_info->auth_info.assoc_delay =
866 rx_auth_frm_body->assoc_delay_info;
867 return true;
868 }
869
870 /**
871 * lim_create_fils_wrapper_data()- This API create warpped data which will be
872 * sent in auth request.
873 * @fils_info: fils session info
874 *
875 * Return: length of the created wrapped data
876 */
lim_create_fils_wrapper_data(struct pe_fils_session * fils_info)877 static int lim_create_fils_wrapper_data(struct pe_fils_session *fils_info)
878 {
879 uint8_t *buf;
880 uint8_t auth_tag[FILS_AUTH_TAG_MAX_LENGTH] = {0};
881 uint32_t length = 0;
882 QDF_STATUS status;
883 int buf_len;
884
885 if (!fils_info)
886 return 0;
887
888 if (!fils_info->keyname_nai_length || !fils_info->fils_rrk_len) {
889 pe_debug("FILS_PMKSA: NO keyname nai/RRK configured. Use PMKSA caching");
890 return 0;
891 }
892
893 buf_len =
894 /* code + identifier */
895 sizeof(uint8_t) * 2 +
896 /* length */
897 sizeof(uint16_t) +
898 /* type + flags */
899 sizeof(uint8_t) * 2 +
900 /* sequence */
901 sizeof(uint16_t) +
902 /* tlv : type, length, data */
903 sizeof(uint8_t) * 2 + fils_info->keyname_nai_length +
904 /* cryptosuite + auth_tag */
905 sizeof(uint8_t) + lim_get_auth_tag_len(HMAC_SHA256_128);
906
907 fils_info->fils_erp_reauth_pkt = qdf_mem_malloc(buf_len);
908 if (!fils_info->fils_erp_reauth_pkt)
909 return -EINVAL;
910
911 buf = fils_info->fils_erp_reauth_pkt;
912 *buf = 5;
913 buf++;
914 /* Identifier */
915 *buf = 0;
916 buf++;
917 /* Length */
918 lim_copy_u16_be(buf, buf_len);
919 buf += sizeof(uint16_t);
920 /* type */
921 *buf = SIR_FILS_EAP_INIT_PACKET_TYPE;
922 buf++;
923
924 /**
925 * flag
926 * 0 1 2 <-- 5 -->
927 * ----------------
928 * |R|B|L| Reserved|
929 * -----------------
930 */
931 *buf = 0x20; /* l=1, b=0, r=0 */
932 buf++;
933 /* sequence */
934 lim_copy_u16_be(buf, fils_info->sequence_number);
935 buf += sizeof(uint16_t);
936
937 /* tlv */
938 /* Type */
939 *buf = SIR_FILS_EAP_TLV_KEYNAME_NAI;
940 buf++;
941 /* NAI Length */
942 *buf = fils_info->keyname_nai_length;
943 buf++;
944 /* NAI Data */
945 qdf_mem_copy(buf, fils_info->keyname_nai_data,
946 fils_info->keyname_nai_length);
947 buf += fils_info->keyname_nai_length;
948
949 /* cryptosuite */
950 *buf = HMAC_SHA256_128;
951 buf++;
952
953 /*
954 * This should be moved to just after sending probe to save time
955 * lim_process_switch_channel_join_req ??
956 */
957 fils_info->fils_rik = qdf_mem_malloc(fils_info->fils_rrk_len);
958 if (!fils_info->fils_rik) {
959 qdf_mem_free(fils_info->fils_erp_reauth_pkt);
960 fils_info->fils_erp_reauth_pkt = NULL;
961 return -EINVAL;
962 }
963
964 status = wlan_crypto_create_fils_rik(fils_info->fils_rrk,
965 fils_info->fils_rrk_len,
966 fils_info->fils_rik,
967 &fils_info->fils_rik_len);
968 if (QDF_IS_STATUS_ERROR(status)) {
969 pe_err("RIK create fails");
970 qdf_mem_free(fils_info->fils_erp_reauth_pkt);
971 qdf_mem_free(fils_info->fils_rik);
972 fils_info->fils_erp_reauth_pkt = NULL;
973 fils_info->fils_rik = NULL;
974 return -EINVAL;
975 }
976
977 fils_info->fils_erp_reauth_pkt_len = buf_len;
978 length = fils_info->fils_erp_reauth_pkt_len -
979 lim_get_auth_tag_len(HMAC_SHA256_128);
980 qdf_get_hmac_hash(HMAC_SHA256_CRYPTO_TYPE,
981 fils_info->fils_rik, fils_info->fils_rik_len, 1,
982 &fils_info->fils_erp_reauth_pkt, &length, auth_tag);
983
984 lim_fils_data_dump("Auth tag", auth_tag,
985 lim_get_auth_tag_len(HMAC_SHA256_128));
986 lim_fils_data_dump("EAP init pkt", fils_info->fils_erp_reauth_pkt,
987 fils_info->fils_erp_reauth_pkt_len);
988
989 qdf_mem_copy(buf, auth_tag, lim_get_auth_tag_len(HMAC_SHA256_128));
990 buf += lim_get_auth_tag_len(HMAC_SHA256_128);
991
992 return buf_len;
993 }
994
995 /**
996 * lim_add_fils_data_to_auth_frame()- This API add fils data to auth frame.
997 * Following will be added in this.
998 * RSNIE
999 * SNonce
1000 * Session
1001 * Wrapped data
1002 * @session: PE session
1003 * @body: pointer to auth frame where data needs to be added
1004 *
1005 * Return: None
1006 */
lim_add_fils_data_to_auth_frame(struct pe_session * session,uint8_t * body)1007 void lim_add_fils_data_to_auth_frame(struct pe_session *session,
1008 uint8_t *body)
1009 {
1010 struct pe_fils_session *fils_info;
1011
1012 fils_info = session->fils_info;
1013
1014 if (!fils_info)
1015 return;
1016
1017 /* RSN IE */
1018 qdf_mem_copy(body, fils_info->rsn_ie, fils_info->rsn_ie_len);
1019 body += fils_info->rsn_ie_len;
1020 lim_fils_data_dump("FILS RSN", fils_info->rsn_ie,
1021 fils_info->rsn_ie_len);
1022
1023 /*
1024 * FT-FILS IEEE-802.11ai specification mandates
1025 * MDIE to be sent in auth frame during initial
1026 * mobility domain association
1027 */
1028 if (session->is11Rconnection) {
1029 struct bss_description *bss_desc;
1030
1031 bss_desc = &session->lim_join_req->bssDescription;
1032
1033 if (bss_desc->mdiePresent) {
1034 /* Populate MDIE received from AP */
1035 *body = WLAN_ELEMID_MOBILITY_DOMAIN;
1036 body++;
1037 *body = SIR_MDIE_SIZE;
1038 body++;
1039 qdf_mem_copy(body, &bss_desc->mdie[0],
1040 SIR_MDIE_SIZE);
1041 pe_debug("FILS: mdie = %02x %02x %02x",
1042 bss_desc->mdie[0], bss_desc->mdie[1],
1043 bss_desc->mdie[2]);
1044 body += SIR_MDIE_SIZE;
1045 } else {
1046 pe_err("FT-FILS: MDIE not advertised by AP");
1047 }
1048 }
1049
1050 /* ***Nonce*** */
1051 /* Add element id */
1052 *body = SIR_MAX_ELEMENT_ID;
1053 body++;
1054 /* Add nonce length + 1 for ext element id */
1055 *body = SIR_FILS_NONCE_LENGTH + 1;
1056 body++;
1057 /* Add ext element */
1058 *body = SIR_FILS_NONCE_EXT_EID;
1059 body++;
1060 /* Add data */
1061 qdf_get_random_bytes(fils_info->fils_nonce, SIR_FILS_NONCE_LENGTH);
1062 qdf_mem_copy(body, fils_info->fils_nonce, SIR_FILS_NONCE_LENGTH);
1063 body = body + SIR_FILS_NONCE_LENGTH;
1064 /* Dump data */
1065 lim_fils_data_dump("fils anonce", fils_info->fils_nonce,
1066 SIR_FILS_NONCE_LENGTH);
1067
1068 /* *** Session *** */
1069 /* Add element id */
1070 *body = SIR_MAX_ELEMENT_ID;
1071 body++;
1072 /* Add nonce length + 1 for ext element id */
1073 *body = SIR_FILS_SESSION_LENGTH + 1;
1074 body++;
1075 /* Add ext element */
1076 *body = SIR_FILS_SESSION_EXT_EID;
1077 body++;
1078 /* Add data */
1079 qdf_get_random_bytes(fils_info->fils_session, SIR_FILS_SESSION_LENGTH);
1080 qdf_mem_copy(body, fils_info->fils_session, SIR_FILS_SESSION_LENGTH);
1081 body = body + SIR_FILS_SESSION_LENGTH;
1082 /* dump data */
1083 lim_fils_data_dump("Fils Session",
1084 fils_info->fils_session, SIR_FILS_SESSION_LENGTH);
1085
1086 if (!fils_info->fils_erp_reauth_pkt ||
1087 !fils_info->fils_erp_reauth_pkt_len) {
1088 pe_debug("FILS: No ERP data. Dont add auth wrapped data");
1089 return;
1090 }
1091
1092 /* ERP Packet */
1093 /* Add element id */
1094 *body = SIR_MAX_ELEMENT_ID;
1095 body++;
1096 /* Add packet length + 1 for ext element id */
1097 *body = fils_info->fils_erp_reauth_pkt_len + 1;
1098 body++;
1099 /* Add ext element */
1100 *body = SIR_FILS_WRAPPED_DATA_EXT_EID;
1101 body++;
1102 /* Copy data */
1103 qdf_mem_copy(body, fils_info->fils_erp_reauth_pkt,
1104 fils_info->fils_erp_reauth_pkt_len);
1105 lim_fils_data_dump("Fils ERP reauth Pkt",
1106 fils_info->fils_erp_reauth_pkt,
1107 fils_info->fils_erp_reauth_pkt_len);
1108 body = body + fils_info->fils_erp_reauth_pkt_len;
1109 }
1110
1111 /**
1112 * lim_generate_fils_pmkr0() - Derive PMKR0 and PMKR0-Name from FT-FILS
1113 * key data
1114 * @pe_session: pointer to pe_session
1115 *
1116 * Return: QDF_STATUS
1117 */
lim_generate_fils_pmkr0(struct pe_session * pe_session)1118 static QDF_STATUS lim_generate_fils_pmkr0(struct pe_session *pe_session)
1119 {
1120 uint8_t *key_data, *data_buf;
1121 uint8_t key_label[] = FT_PMK_R0_KEY_LABEL;
1122 uint8_t key_data_len, ssid_length, r0kh_len, mdid_len;
1123 uint8_t *r0_key_data;
1124 uint8_t *hash;
1125 uint8_t r0_key_data_len;
1126 uint8_t pmkr0_len;
1127 uint8_t *buf, *pmkr0_name_salt;
1128 uint8_t *scatter_list[PMKR0_SCATTER_LIST_ELEM];
1129 uint32_t len[PMKR0_SCATTER_LIST_ELEM];
1130 uint16_t data_buf_len;
1131 QDF_STATUS status = QDF_STATUS_SUCCESS;
1132 struct pe_fils_session *fils_info = pe_session->fils_info;
1133 struct bss_description *bss_desc =
1134 &pe_session->lim_join_req->bssDescription;
1135
1136 if (!fils_info)
1137 return QDF_STATUS_E_FAILURE;
1138
1139 ssid_length = pe_session->ssId.length;
1140 r0kh_len = fils_info->ft_ie.r0kh_id_len;
1141 mdid_len = (SIR_MDIE_SIZE - 1);
1142 pmkr0_len = lim_get_Q_length(fils_info->akm);
1143 r0_key_data_len = pmkr0_len + FILS_FT_PMK_R0_SALT_LEN;
1144
1145 /*
1146 * [IEEE 802.11ai 12.7.1.7.3]
1147 * R0-Key-Data = KDF-Hash-Length(XXKey, "FT-R0", SSIDlength || SSID ||
1148 * MDID || R0KHlength || R0KH-ID || S0KH-ID)
1149 * PMK-R0 = L(R0-Key-Data, 0, Q)
1150 * PMK-R0Name-Salt = L(R0-Key-Data, Q, 128)
1151 * Length = Q + 128
1152 */
1153 key_data_len = (1 + ssid_length + mdid_len + 1 + r0kh_len +
1154 QDF_MAC_ADDR_SIZE);
1155 pe_debug("FT-FILS: ssid_length:%d MDID len:%d R0KH len:%d key_data len:%d",
1156 ssid_length, mdid_len, r0kh_len, key_data_len);
1157
1158 data_buf_len = (key_data_len + FILS_FT_MAX_R0_KEY_DATA_LEN +
1159 SHA384_DIGEST_SIZE);
1160 data_buf = qdf_mem_malloc(data_buf_len);
1161 if (!data_buf)
1162 return QDF_STATUS_E_NOMEM;
1163
1164 key_data = &data_buf[0];
1165 r0_key_data = &data_buf[key_data_len];
1166 hash = &data_buf[key_data_len + FILS_FT_MAX_R0_KEY_DATA_LEN];
1167
1168 /*
1169 * key_data is (SSIDlength || SSID || MDID || R0KHlength || R0KH-ID ||
1170 * S0KH-ID)
1171 */
1172 buf = key_data;
1173
1174 *key_data = pe_session->ssId.length;
1175 key_data += 1;
1176
1177 qdf_mem_copy(key_data, pe_session->ssId.ssId, ssid_length);
1178 key_data += ssid_length;
1179
1180 qdf_mem_copy(key_data, bss_desc->mdie, mdid_len);
1181 key_data += mdid_len;
1182
1183 *key_data = r0kh_len;
1184 key_data += 1;
1185
1186 qdf_mem_copy(key_data, fils_info->ft_ie.r0kh_id, r0kh_len);
1187 key_data += r0kh_len;
1188
1189 qdf_mem_copy(key_data, pe_session->self_mac_addr, QDF_MAC_ADDR_SIZE);
1190
1191 pe_debug("FT-FILS: Derive R0-Key-Data");
1192 status = lim_get_key_from_prf(lim_get_hmac_crypto_type(fils_info->akm),
1193 fils_info->fils_ft,
1194 fils_info->fils_ft_len, key_label,
1195 buf, key_data_len, r0_key_data,
1196 r0_key_data_len);
1197 if (QDF_IS_STATUS_ERROR(status))
1198 goto free_buf;
1199
1200 /* PMK-R0 is the first Q bytes of R0-Key-Data */
1201 qdf_mem_copy(fils_info->pmkr0, r0_key_data, pmkr0_len);
1202 fils_info->pmkr0_len = pmkr0_len;
1203
1204 /* PMK-R0Name-Salt = L(R0-Key-Data, Q, 128) */
1205 pmkr0_name_salt = r0_key_data + pmkr0_len;
1206
1207 /*
1208 * [IEEE 802.11-2016 12.7.1.7.3]
1209 * PMKR0Name = Truncate-128(Hash("FT-R0N" || PMK-R0Name-Salt)
1210 * The Hash function requires the crypto type, number of scatterlist
1211 * parameters, scatterlist, lengths of scatterlist arguments, pointer
1212 * to output hash.
1213 *
1214 * The scatterlist has two arguments - label "FT-R0N" and
1215 * PMK-R0Name-Salt
1216 *
1217 */
1218 scatter_list[SCTR_LST_ELEM0] = FT_PMK_R0_NAME_KEY_LABEL;
1219 len[SCTR_LST_ELEM0] = SCTR_LST_R0_LABEL_LEN;
1220 scatter_list[SCTR_LST_ELEM1] = pmkr0_name_salt;
1221 len[SCTR_LST_ELEM1] = FILS_FT_PMK_R0_SALT_LEN;
1222
1223 pe_debug("FT-FILS: Derive PMK-R0 Name");
1224 if (qdf_get_hash(lim_get_hash_crypto_type(fils_info->akm),
1225 PMKR0_SCATTER_LIST_ELEM, scatter_list, len,
1226 hash) < 0) {
1227 pe_err("FT-FILS: PMK-R0Name derivation failed");
1228 status = QDF_STATUS_E_FAILURE;
1229 goto free_buf;
1230 }
1231 qdf_mem_copy(fils_info->pmkr0_name, hash, FILS_PMK_NAME_LEN);
1232
1233 free_buf:
1234 qdf_mem_zero(data_buf, data_buf_len);
1235 qdf_mem_free(data_buf);
1236
1237 return status;
1238 }
1239
1240 /**
1241 * lim_generate_fils_pmkr1_name() - Derive PMKR1 and PMKR1-Name from FT-FILS
1242 * key data
1243 * @pe_session: pointer to pe_session
1244 *
1245 * Return: None
1246 */
lim_generate_fils_pmkr1_name(struct mac_context * mac_ctx,struct pe_session * pe_session)1247 static QDF_STATUS lim_generate_fils_pmkr1_name(struct mac_context *mac_ctx,
1248 struct pe_session *pe_session)
1249 {
1250 uint8_t *hash;
1251 uint8_t *scatter_list[PMKR1_SCATTER_LIST_ELEM];
1252 uint32_t len[PMKR1_SCATTER_LIST_ELEM];
1253 uint8_t *buf;
1254 uint8_t gp_mgmt_cipher_suite[4];
1255 uint32_t ret;
1256 tDot11fIERSN dot11f_ie_rsn = {0};
1257 struct pe_fils_session *fils_info = pe_session->fils_info;
1258
1259 if (!fils_info)
1260 return QDF_STATUS_E_FAILURE;
1261
1262 hash = qdf_mem_malloc(SHA384_DIGEST_SIZE);
1263 if (!hash)
1264 return QDF_STATUS_E_NOMEM;
1265
1266 /*
1267 * [IEEE 802.11-2016 12.7.1.7.4]
1268 * PMKR1Name = Truncate-128(Hash("FT-R1N" || PMKR0Name ||
1269 * R1KH-ID || S1KH-ID))
1270 */
1271 scatter_list[SCTR_LST_ELEM0] = FT_PMK_R1_NAME_KEY_LABEL;
1272 len[SCTR_LST_ELEM0] = SCTR_LST_R1_LABEL_LEN;
1273 scatter_list[SCTR_LST_ELEM1] = fils_info->pmkr0_name;
1274 len[SCTR_LST_ELEM1] = FILS_PMK_NAME_LEN;
1275 scatter_list[SCTR_LST_ELEM2] = fils_info->ft_ie.r1kh_id;
1276 len[SCTR_LST_ELEM2] = FT_R1KH_ID_LEN;
1277 scatter_list[SCTR_LST_ELEM3] = pe_session->self_mac_addr;
1278 len[SCTR_LST_ELEM3] = QDF_MAC_ADDR_SIZE;
1279
1280 if (qdf_get_hash(lim_get_hash_crypto_type(fils_info->akm),
1281 PMKR1_SCATTER_LIST_ELEM, scatter_list, len,
1282 hash) < 0) {
1283 qdf_mem_zero(hash, SHA384_DIGEST_SIZE);
1284 qdf_mem_free(hash);
1285 return QDF_STATUS_E_FAILURE;
1286 }
1287 qdf_mem_copy(fils_info->pmkr1_name, hash, FILS_PMK_NAME_LEN);
1288
1289 qdf_mem_zero(hash, SHA384_DIGEST_SIZE);
1290 qdf_mem_free(hash);
1291
1292 if (!fils_info->rsn_ie_len) {
1293 pe_err("FT-FILS: RSN IE not present");
1294 return QDF_STATUS_E_FAILURE;
1295 }
1296
1297 ret = dot11f_unpack_ie_rsn(mac_ctx, fils_info->rsn_ie + 2,
1298 fils_info->rsn_ie_len - 2,
1299 &dot11f_ie_rsn, 0);
1300
1301 if (!DOT11F_SUCCEEDED(ret)) {
1302 pe_err("unpack RSN IE failed, ret: %d", ret);
1303 return QDF_STATUS_E_FAILURE;
1304 }
1305
1306 buf = fils_info->rsn_ie + fils_info->rsn_ie_len;
1307
1308 if (fils_info->group_mgmt_cipher_present) {
1309 /*
1310 * If 802.11w is enabled, group management cipher
1311 * suite is added at the end of RSN IE after
1312 * PMKID. Since the driver has opaque RSN IE
1313 * saved in fils_session, strip the last 4 bytes
1314 * of the RSN IE to get group mgmt cipher suite.
1315 * Then copy the PMKID followed by the grp mgmt cipher
1316 * suite.
1317 */
1318
1319 buf -= 4;
1320 fils_info->rsn_ie[1] -= 4; /* strip the grp mgmt cipher len */
1321 qdf_mem_copy(gp_mgmt_cipher_suite, buf, 4);
1322 }
1323
1324 if (dot11f_ie_rsn.pmkid_count || fils_info->group_mgmt_cipher_present) {
1325 /* Skip past PMKID and PMKID count */
1326 buf -= (dot11f_ie_rsn.pmkid_count * PMKID_LEN) + 2;
1327 fils_info->rsn_ie[1] -=
1328 (dot11f_ie_rsn.pmkid_count * PMKID_LEN) + 2;
1329 /* Clear the buffer occupied by PMKID */
1330 qdf_mem_zero(buf, (dot11f_ie_rsn.pmkid_count * PMKID_LEN) + 2);
1331 }
1332
1333 /*
1334 * Add PMKID count as 1. PMKID count field is 2 bytes long.
1335 * Copy the PMKR1-Name in the PMKID list at the end of the
1336 * RSN IE.
1337 */
1338 *buf = 1; /* RSNIE PMKID Count = 1 */
1339 buf += 2; /* RSNIE PMKID count field is 2 bytes */
1340 /* PMKID = fils_info->pmkr1_name */
1341 qdf_mem_copy(buf, fils_info->pmkr1_name, FILS_PMK_NAME_LEN);
1342 buf += FILS_PMK_NAME_LEN;
1343 fils_info->rsn_ie[1] += FILS_PMK_NAME_LEN + 2;
1344
1345 if (fils_info->group_mgmt_cipher_present) {
1346 qdf_mem_copy(buf, gp_mgmt_cipher_suite, 4);
1347 fils_info->rsn_ie[1] += 4; /* Add the grp mgmt cipher len */
1348 }
1349
1350 fils_info->rsn_ie_len = fils_info->rsn_ie[1] + 2;
1351
1352 pe_debug("FT-FILS: Final RSN length:%d", fils_info->rsn_ie[1]);
1353 qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
1354 fils_info->rsn_ie, fils_info->rsn_ie_len);
1355
1356 if (pe_session->lim_join_req) {
1357 qdf_mem_zero(pe_session->lim_join_req->rsnIE.rsnIEdata,
1358 WLAN_MAX_IE_LEN + 2);
1359 pe_session->lim_join_req->rsnIE.length =
1360 fils_info->rsn_ie[1] + 2;
1361 qdf_mem_copy(pe_session->lim_join_req->rsnIE.rsnIEdata,
1362 fils_info->rsn_ie,
1363 pe_session->lim_join_req->rsnIE.length);
1364 } else {
1365 pe_debug("FT-FILS: Join req is NULL");
1366 }
1367
1368 return QDF_STATUS_SUCCESS;
1369 }
1370
1371 /**
1372 * lim_process_fils_auth_frame2()- This API process fils data from auth response
1373 * @mac_ctx: mac context
1374 * @session: PE session
1375 * @rx_auth_frm_body: pointer to auth frame
1376 *
1377 * Return: true if fils data needs to be processed else false
1378 */
lim_process_fils_auth_frame2(struct mac_context * mac_ctx,struct pe_session * pe_session,tSirMacAuthFrameBody * rx_auth_frm_body)1379 bool lim_process_fils_auth_frame2(struct mac_context *mac_ctx,
1380 struct pe_session *pe_session,
1381 tSirMacAuthFrameBody *rx_auth_frm_body)
1382 {
1383 int i;
1384 uint32_t ret;
1385 bool pmkid_found = false;
1386 tDot11fIERSN dot11f_ie_rsn = {0};
1387 QDF_STATUS status;
1388
1389 if (!pe_session->fils_info)
1390 return false;
1391
1392 if (rx_auth_frm_body->authAlgoNumber != SIR_FILS_SK_WITHOUT_PFS)
1393 return false;
1394
1395 ret = dot11f_unpack_ie_rsn(mac_ctx, &rx_auth_frm_body->rsn_ie.info[0],
1396 rx_auth_frm_body->rsn_ie.length,
1397 &dot11f_ie_rsn, 0);
1398 if (!DOT11F_SUCCEEDED(ret)) {
1399 pe_err("unpack failed, ret: %d", ret);
1400 return false;
1401 }
1402
1403 /*
1404 * copy FTIE to fils_info and send it over assoc response frame
1405 * for FT-FILS connection
1406 */
1407 if (pe_session->is11Rconnection && pe_session->fils_info) {
1408 pe_session->fils_info->ft_ie = rx_auth_frm_body->ft_ie;
1409 if (!pe_session->fils_info->ft_ie.present) {
1410 pe_err("FT-FILS: NO FTIE in auth response");
1411 }
1412 }
1413
1414 for (i = 0; i < dot11f_ie_rsn.pmkid_count; i++) {
1415 if (qdf_mem_cmp(dot11f_ie_rsn.pmkid[i],
1416 pe_session->fils_info->fils_pmkid,
1417 PMKID_LEN) == 0) {
1418 pmkid_found = true;
1419 pe_debug("pmkid match in rsn ie total_count %d",
1420 dot11f_ie_rsn.pmkid_count);
1421 break;
1422 }
1423 }
1424 if (!pmkid_found) {
1425 if (QDF_STATUS_SUCCESS !=
1426 lim_process_auth_wrapped_data(pe_session,
1427 rx_auth_frm_body->wrapped_data,
1428 rx_auth_frm_body->wrapped_data_len))
1429 return false;
1430 }
1431 lim_get_keys(mac_ctx, pe_session);
1432 if (pe_session->is11Rconnection) {
1433 status = lim_generate_fils_pmkr0(pe_session);
1434 if (QDF_IS_STATUS_ERROR(status))
1435 return false;
1436
1437 status = lim_generate_fils_pmkr1_name(mac_ctx, pe_session);
1438 if (QDF_IS_STATUS_ERROR(status))
1439 return false;
1440 }
1441 lim_generate_key_auth(pe_session);
1442 lim_generate_ap_key_auth(pe_session);
1443 return true;
1444 }
1445
lim_get_auth_type(uint8_t auth_type)1446 static enum eAniAuthType lim_get_auth_type(uint8_t auth_type)
1447 {
1448 switch (auth_type) {
1449 case FILS_SK_WITHOUT_PFS:
1450 return SIR_FILS_SK_WITHOUT_PFS;
1451 case FILS_SK_WITH_PFS:
1452 return SIR_FILS_SK_WITH_PFS;
1453 case FILS_PK_AUTH:
1454 return SIR_FILS_PK_AUTH;
1455 default:
1456 return eSIR_DONOT_USE_AUTH_TYPE;
1457 }
1458 }
1459
lim_get_akm_type(struct wlan_objmgr_vdev * vdev)1460 static uint8_t lim_get_akm_type(struct wlan_objmgr_vdev *vdev)
1461 {
1462 int32_t akm;
1463
1464 akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
1465
1466 if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384))
1467 return eCSR_AUTH_TYPE_FT_FILS_SHA384;
1468 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256))
1469 return eCSR_AUTH_TYPE_FT_FILS_SHA256;
1470 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384))
1471 return eCSR_AUTH_TYPE_FILS_SHA384;
1472 else
1473 return eCSR_AUTH_TYPE_FILS_SHA256;
1474 }
1475
lim_update_fils_config(struct mac_context * mac_ctx,struct pe_session * session,struct cm_vdev_join_req * join_req)1476 void lim_update_fils_config(struct mac_context *mac_ctx,
1477 struct pe_session *session,
1478 struct cm_vdev_join_req *join_req)
1479 {
1480 struct pe_fils_session *pe_fils_info;
1481 struct wlan_fils_connection_info *fils_info = NULL;
1482 tDot11fIERSN dot11f_ie_rsn = {0};
1483 uint32_t ret;
1484 struct mlme_legacy_priv *mlme_priv;
1485
1486 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
1487 if (!mlme_priv)
1488 return;
1489 fils_info = mlme_priv->connect_info.fils_con_info;
1490 if (!fils_info)
1491 return;
1492 pe_fils_info = session->fils_info;
1493 if (!pe_fils_info)
1494 return;
1495
1496 if (!fils_info->is_fils_connection)
1497 return;
1498
1499 pe_fils_info->is_fils_connection = fils_info->is_fils_connection;
1500 pe_fils_info->keyname_nai_length = fils_info->key_nai_length;
1501 pe_fils_info->fils_rrk_len = fils_info->r_rk_length;
1502 pe_fils_info->akm = lim_get_akm_type(session->vdev);
1503 pe_fils_info->auth = lim_get_auth_type(fils_info->auth_type);
1504 pe_fils_info->sequence_number = fils_info->erp_sequence_number;
1505
1506 if (fils_info->key_nai_length > FILS_MAX_KEYNAME_NAI_LENGTH) {
1507 pe_err("Restricting the key_nai_length of %d to max %d",
1508 fils_info->key_nai_length,
1509 FILS_MAX_KEYNAME_NAI_LENGTH);
1510 fils_info->key_nai_length = FILS_MAX_KEYNAME_NAI_LENGTH;
1511 }
1512
1513 if (fils_info->key_nai_length) {
1514 pe_fils_info->keyname_nai_data =
1515 qdf_mem_malloc(fils_info->key_nai_length);
1516 if (!pe_fils_info->keyname_nai_data)
1517 return;
1518
1519 qdf_mem_copy(pe_fils_info->keyname_nai_data,
1520 fils_info->keyname_nai,
1521 fils_info->key_nai_length);
1522 }
1523
1524 if (fils_info->r_rk_length) {
1525 pe_fils_info->fils_rrk =
1526 qdf_mem_malloc(fils_info->r_rk_length);
1527 if (!pe_fils_info->fils_rrk) {
1528 qdf_mem_free(pe_fils_info->keyname_nai_data);
1529 return;
1530 }
1531
1532 if (fils_info->r_rk_length <= WLAN_FILS_MAX_RRK_LENGTH)
1533 qdf_mem_copy(pe_fils_info->fils_rrk,
1534 fils_info->r_rk,
1535 fils_info->r_rk_length);
1536 }
1537
1538 qdf_mem_copy(pe_fils_info->fils_pmkid, fils_info->pmkid,
1539 PMKID_LEN);
1540 pe_fils_info->rsn_ie_len = session->lim_join_req->rsnIE.length;
1541 qdf_mem_copy(pe_fils_info->rsn_ie,
1542 session->lim_join_req->rsnIE.rsnIEdata,
1543 session->lim_join_req->rsnIE.length);
1544
1545 /*
1546 * When AP is MFP capable and STA is also MFP capable,
1547 * the supplicant fills the RSN IE with PMKID count as 0
1548 * and PMKID as 0, then appends the group management cipher
1549 * suite. This opaque RSN IE is copied into fils_info in pe
1550 * session. For FT-FILS association, STA has to fill the
1551 * PMKR0 derived after authentication response is received from
1552 * the AP. So unpack the RSN IE to find if group management cipher
1553 * suite is present and based on this RSN IE will be constructed in
1554 * lim_generate_fils_pmkr1_name() for FT-FILS connection.
1555 */
1556 ret = dot11f_unpack_ie_rsn(mac_ctx, pe_fils_info->rsn_ie + 2,
1557 pe_fils_info->rsn_ie_len - 2,
1558 &dot11f_ie_rsn, 0);
1559 if (DOT11F_SUCCEEDED(ret))
1560 pe_fils_info->group_mgmt_cipher_present =
1561 dot11f_ie_rsn.gp_mgmt_cipher_suite_present;
1562 else
1563 pe_err("FT-FILS: Invalid RSN IE");
1564
1565 pe_fils_info->fils_pmk_len = fils_info->pmk_len;
1566 if (fils_info->pmk_len) {
1567 pe_fils_info->fils_pmk =
1568 qdf_mem_malloc(fils_info->pmk_len);
1569 if (!pe_fils_info->fils_pmk) {
1570 qdf_mem_free(pe_fils_info->keyname_nai_data);
1571 qdf_mem_free(pe_fils_info->fils_rrk);
1572 return;
1573 }
1574 qdf_mem_copy(pe_fils_info->fils_pmk, fils_info->pmk,
1575 fils_info->pmk_len);
1576 }
1577
1578 pe_debug("FILS: fils=%d nai-len=%d rrk_len=%d akm=%d auth=%d pmk_len=%d rsn_len:%d",
1579 fils_info->is_fils_connection,
1580 fils_info->key_nai_length,
1581 fils_info->r_rk_length,
1582 fils_info->akm_type,
1583 fils_info->auth_type,
1584 fils_info->pmk_len, pe_fils_info->rsn_ie_len);
1585 }
1586
1587 #define EXTENDED_IE_HEADER_LEN 3
1588 /**
1589 * lim_create_fils_auth_data()- This API creates the fils auth data
1590 * which needs to be sent in auth req.
1591 * @mac_ctx: mac context
1592 * @auth_frame: pointer to auth frame
1593 * @session: PE session
1594 *
1595 * Return: length of fils data
1596 */
lim_create_fils_auth_data(struct mac_context * mac_ctx,tpSirMacAuthFrameBody auth_frame,struct pe_session * session,uint32_t * frame_len)1597 QDF_STATUS lim_create_fils_auth_data(struct mac_context *mac_ctx,
1598 tpSirMacAuthFrameBody auth_frame,
1599 struct pe_session *session,
1600 uint32_t *frame_len)
1601 {
1602 uint16_t frm_len = 0;
1603 int32_t wrapped_data_len;
1604
1605 if (!session->fils_info)
1606 return QDF_STATUS_SUCCESS;
1607
1608 /* These memory may already been allocated if auth retry */
1609 if (session->fils_info->fils_rik) {
1610 qdf_mem_free(session->fils_info->fils_rik);
1611 session->fils_info->fils_rik = NULL;
1612 }
1613
1614 if (session->fils_info->fils_erp_reauth_pkt) {
1615 qdf_mem_free(session->fils_info->fils_erp_reauth_pkt);
1616 session->fils_info->fils_erp_reauth_pkt = NULL;
1617 }
1618
1619 if (auth_frame->authAlgoNumber == SIR_FILS_SK_WITHOUT_PFS) {
1620 frm_len += session->fils_info->rsn_ie_len;
1621 /* FILS nonce */
1622 frm_len += SIR_FILS_NONCE_LENGTH + EXTENDED_IE_HEADER_LEN;
1623 /* FILS Session */
1624 frm_len += SIR_FILS_SESSION_LENGTH + EXTENDED_IE_HEADER_LEN;
1625 /* Calculate data/length for FILS Wrapped Data */
1626 wrapped_data_len =
1627 lim_create_fils_wrapper_data(session->fils_info);
1628 if (wrapped_data_len < 0) {
1629 pe_err("failed to allocate wrapped data");
1630 return QDF_STATUS_E_FAILURE;
1631 }
1632
1633 if (wrapped_data_len)
1634 frm_len += wrapped_data_len + EXTENDED_IE_HEADER_LEN;
1635 }
1636
1637 *frame_len += frm_len;
1638
1639 return QDF_STATUS_SUCCESS;
1640 }
1641
populate_fils_connect_params(struct mac_context * mac_ctx,struct pe_session * session,struct wlan_cm_connect_resp * connect_rsp)1642 void populate_fils_connect_params(struct mac_context *mac_ctx,
1643 struct pe_session *session,
1644 struct wlan_cm_connect_resp *connect_rsp)
1645 {
1646 struct pe_fils_session *fils_info = session->fils_info;
1647 struct fils_connect_rsp_params *fils_ie;
1648
1649 if (!lim_is_fils_connection(session))
1650 return;
1651
1652 if (!fils_info->fils_pmk_len ||
1653 !fils_info->tk_len || !fils_info->gtk_len ||
1654 !fils_info->fils_pmk || !fils_info->kek_len) {
1655 pe_err("Invalid FILS info pmk len %d kek len %d tk len %d gtk len %d",
1656 fils_info->fils_pmk_len, fils_info->kek_len,
1657 fils_info->tk_len, fils_info->gtk_len);
1658 return;
1659 }
1660
1661 connect_rsp->connect_ies.fils_ie = qdf_mem_malloc(sizeof(*fils_ie));
1662 if (!connect_rsp->connect_ies.fils_ie) {
1663 pe_delete_fils_info(session);
1664 return;
1665 }
1666
1667 fils_ie = connect_rsp->connect_ies.fils_ie;
1668 fils_ie->fils_pmk = qdf_mem_malloc(fils_info->fils_pmk_len);
1669 if (!fils_ie->fils_pmk) {
1670 qdf_mem_free(fils_ie);
1671 connect_rsp->connect_ies.fils_ie = NULL;
1672 pe_delete_fils_info(session);
1673 return;
1674 }
1675 fils_ie->fils_seq_num = fils_info->sequence_number;
1676 fils_ie->fils_pmk_len = fils_info->fils_pmk_len;
1677 qdf_mem_copy(fils_ie->fils_pmk, fils_info->fils_pmk,
1678 fils_info->fils_pmk_len);
1679
1680 qdf_mem_copy(fils_ie->fils_pmkid, fils_info->fils_pmkid, PMKID_LEN);
1681
1682 fils_ie->kek_len = fils_info->kek_len;
1683 qdf_mem_copy(fils_ie->kek, fils_info->kek, fils_info->kek_len);
1684
1685 fils_ie->tk_len = fils_info->tk_len;
1686 qdf_mem_copy(fils_ie->tk, fils_info->tk, fils_info->tk_len);
1687
1688 fils_ie->gtk_len = fils_info->gtk_len;
1689 qdf_mem_copy(fils_ie->gtk, fils_info->gtk, fils_info->gtk_len);
1690
1691 cds_copy_hlp_info(&fils_info->dst_mac, &fils_info->src_mac,
1692 fils_info->hlp_data_len, fils_info->hlp_data,
1693 &fils_ie->dst_mac, &fils_ie->src_mac,
1694 &fils_ie->hlp_data_len,
1695 fils_ie->hlp_data);
1696
1697 pe_debug("FILS connect params copied lim");
1698 }
1699
1700 /**
1701 * lim_parse_kde_elements() - Parse Key Delivery Elements
1702 * @mac_ctx: mac context
1703 * @fils_info: FILS info
1704 * @kde_list: KDE list buffer
1705 * @kde_list_len: Length of @kde_list
1706 *
1707 * This API is used to parse the Key Delivery Elements from buffer
1708 * and populate them in PE FILS session struct i.e @fils_info
1709 *
1710 * Key Delivery Element[KDE] format
1711 * +----------+--------+-----------+------------+----------+
1712 * | ID(0xDD) | length | KDE OUI | data type | IE data |
1713 * |----------|--------|-----------|------------|----------|
1714 * | 1 byte | 1 byte | 3 bytes | 1 byte | variable |
1715 * +----------+--------+-----------+------------+----------+
1716 *
1717 * there can be multiple KDE present inside KDE list.
1718 * the IE data could be GTK, IGTK etc based on the data type
1719 *
1720 * Return: QDF_STATUS_SUCCESS if we parse GTK successfully,
1721 * QDF_STATUS_E_FAILURE otherwise
1722 */
lim_parse_kde_elements(struct mac_context * mac_ctx,struct pe_fils_session * fils_info,uint8_t * kde_list,uint8_t kde_list_len)1723 static QDF_STATUS lim_parse_kde_elements(struct mac_context *mac_ctx,
1724 struct pe_fils_session *fils_info,
1725 uint8_t *kde_list,
1726 uint8_t kde_list_len)
1727 {
1728 uint8_t rem_len = kde_list_len;
1729 uint8_t *temp_ie = kde_list;
1730 uint8_t elem_id, data_type, data_len, *ie_data = NULL, *current_ie;
1731 uint16_t elem_len;
1732
1733 if (!kde_list_len || !kde_list) {
1734 pe_err("kde_list NULL or kde_list_len %d", kde_list_len);
1735 return QDF_STATUS_E_FAILURE;
1736 }
1737
1738 while (rem_len >= 2) {
1739 current_ie = temp_ie;
1740 elem_id = *temp_ie++;
1741 elem_len = *temp_ie++;
1742 rem_len -= 2;
1743
1744 if (rem_len < elem_len || elem_len > kde_list_len) {
1745 pe_err("Invalid elem_len %d rem_len %d list_len %d",
1746 elem_len, rem_len, kde_list_len);
1747 return QDF_STATUS_E_FAILURE;
1748 }
1749
1750 if (elem_len < KDE_IE_DATA_OFFSET) {
1751 pe_err("Not enough len to parse elem_len %d",
1752 elem_len);
1753 return QDF_STATUS_E_FAILURE;
1754 }
1755
1756 if (lim_check_if_vendor_oui_match(mac_ctx, KDE_OUI_TYPE,
1757 KDE_OUI_TYPE_SIZE, current_ie, elem_len)) {
1758
1759 data_type = *(temp_ie + KDE_DATA_TYPE_OFFSET);
1760 ie_data = (temp_ie + KDE_IE_DATA_OFFSET);
1761 data_len = (elem_len - KDE_IE_DATA_OFFSET);
1762
1763 switch (data_type) {
1764 case DATA_TYPE_GTK:
1765 if (data_len < GTK_OFFSET) {
1766 pe_err("Invalid KDE data_len %d",
1767 data_len);
1768 return QDF_STATUS_E_FAILURE;
1769 }
1770 qdf_mem_copy(fils_info->gtk, (ie_data +
1771 GTK_OFFSET), (data_len -
1772 GTK_OFFSET));
1773 fils_info->gtk_len = (data_len - GTK_OFFSET);
1774 break;
1775
1776 case DATA_TYPE_IGTK:
1777 if (data_len < IGTK_OFFSET) {
1778 pe_err("Invalid KDE data_len %d",
1779 data_len);
1780 return QDF_STATUS_E_FAILURE;
1781 }
1782 fils_info->igtk_len = (data_len - IGTK_OFFSET);
1783 qdf_mem_copy(fils_info->igtk, (ie_data +
1784 IGTK_OFFSET), (data_len -
1785 IGTK_OFFSET));
1786 qdf_mem_copy(fils_info->ipn, (ie_data +
1787 IPN_OFFSET), IPN_LEN);
1788 break;
1789 default:
1790 pe_err("Unknown KDE data type %x", data_type);
1791 break;
1792 }
1793 }
1794
1795 temp_ie += elem_len;
1796 rem_len -= elem_len;
1797 ie_data = NULL;
1798 }
1799
1800 /* Expecting GTK in KDE */
1801 if (!fils_info->gtk_len) {
1802 pe_err("GTK not found in KDE");
1803 return QDF_STATUS_E_FAILURE;
1804 }
1805
1806 return QDF_STATUS_SUCCESS;
1807 }
1808
lim_update_fils_hlp_data(struct qdf_mac_addr * hlp_frm_src_mac,struct qdf_mac_addr * hlp_frm_dest_mac,uint16_t frm_hlp_len,uint8_t * frm_hlp_data,struct pe_session * pe_session)1809 void lim_update_fils_hlp_data(struct qdf_mac_addr *hlp_frm_src_mac,
1810 struct qdf_mac_addr *hlp_frm_dest_mac,
1811 uint16_t frm_hlp_len, uint8_t *frm_hlp_data,
1812 struct pe_session *pe_session)
1813 {
1814 struct pe_fils_session *pe_fils_info = pe_session->fils_info;
1815
1816 if (!pe_fils_info) {
1817 pe_err("Not a fils connection");
1818 return;
1819 }
1820
1821 if (frm_hlp_data && frm_hlp_len) {
1822 qdf_mem_free(pe_fils_info->hlp_data);
1823 pe_fils_info->hlp_data = qdf_mem_malloc(frm_hlp_len);
1824 if (!pe_fils_info->hlp_data)
1825 return;
1826
1827 pe_debug("FILS: hlp_data_len:%d", frm_hlp_len);
1828 cds_copy_hlp_info(hlp_frm_dest_mac, hlp_frm_src_mac,
1829 frm_hlp_len, frm_hlp_data,
1830 &pe_fils_info->dst_mac,
1831 &pe_fils_info->src_mac,
1832 &pe_fils_info->hlp_data_len,
1833 pe_fils_info->hlp_data);
1834 }
1835 }
1836
lim_verify_fils_params_assoc_rsp(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocRsp assoc_rsp,tLimMlmAssocCnf * assoc_cnf)1837 bool lim_verify_fils_params_assoc_rsp(struct mac_context *mac_ctx,
1838 struct pe_session *session_entry,
1839 tpSirAssocRsp assoc_rsp,
1840 tLimMlmAssocCnf *assoc_cnf)
1841 {
1842 struct pe_fils_session *fils_info = session_entry->fils_info;
1843 tDot11fIEfils_session fils_session = assoc_rsp->fils_session;
1844 tDot11fIEfils_key_confirmation *fils_key_auth;
1845 QDF_STATUS status;
1846
1847 if (!lim_is_fils_connection(session_entry))
1848 return true;
1849
1850 if (!fils_info) {
1851 pe_err("FILS Info not present");
1852 goto verify_fils_params_fails;
1853 }
1854
1855 if (!assoc_rsp->fils_session.present) {
1856 pe_err("FILS IE not present");
1857 goto verify_fils_params_fails;
1858 }
1859
1860 /* Compare FILS session */
1861 if (qdf_mem_cmp(fils_info->fils_session,
1862 fils_session.session, DOT11F_IE_FILS_SESSION_MAX_LEN)) {
1863 pe_err("FILS session mismatch");
1864 goto verify_fils_params_fails;
1865 }
1866
1867 fils_key_auth = qdf_mem_malloc(sizeof(*fils_key_auth));
1868 if (!fils_key_auth) {
1869 pe_err("malloc failed for fils_key_auth");
1870 goto verify_fils_params_fails;
1871 }
1872
1873 *fils_key_auth = assoc_rsp->fils_key_auth;
1874
1875 /* Compare FILS key auth */
1876 if (fils_key_auth->num_key_auth != fils_info->key_auth_len ||
1877 qdf_mem_cmp(fils_info->ap_key_auth_data,
1878 fils_key_auth->key_auth,
1879 fils_info->ap_key_auth_len)) {
1880 lim_fils_data_dump("session keyauth",
1881 fils_info->ap_key_auth_data,
1882 fils_info->ap_key_auth_len);
1883 lim_fils_data_dump("Pkt keyauth",
1884 fils_key_auth->key_auth,
1885 fils_key_auth->num_key_auth);
1886 qdf_mem_free(fils_key_auth);
1887 goto verify_fils_params_fails;
1888 }
1889
1890 qdf_mem_free(fils_key_auth);
1891
1892 /* Verify the Key Delivery Element presence */
1893 if (!assoc_rsp->fils_kde.num_kde_list) {
1894 pe_err("FILS KDE list absent");
1895 goto verify_fils_params_fails;
1896 }
1897
1898 /* Derive KDE elements */
1899 status = lim_parse_kde_elements(mac_ctx, fils_info,
1900 assoc_rsp->fils_kde.kde_list,
1901 assoc_rsp->fils_kde.num_kde_list);
1902 if (!QDF_IS_STATUS_SUCCESS(status)) {
1903 pe_err("KDE parsing fails");
1904 goto verify_fils_params_fails;
1905 }
1906
1907 lim_update_fils_hlp_data(&assoc_rsp->dst_mac,
1908 &assoc_rsp->src_mac,
1909 assoc_rsp->hlp_data_len,
1910 assoc_rsp->hlp_data,
1911 session_entry);
1912 return true;
1913
1914 verify_fils_params_fails:
1915 assoc_cnf->resultCode = eSIR_SME_ASSOC_REFUSED;
1916 assoc_cnf->protStatusCode = STATUS_UNSPECIFIED_FAILURE;
1917 return false;
1918 }
1919
1920 /**
1921 * find_ie_data_after_fils_session_ie() - Find IE pointer after FILS Session IE
1922 * @mac_ctx: MAC context
1923 * @buf: IE buffer
1924 * @buf_len: Length of @buf
1925 * @ie: Pointer to update the found IE pointer after FILS session IE
1926 * @ie_len: length of the IE data after FILS session IE
1927 *
1928 * This API is used to find the IE data ptr and length after FILS session IE
1929 *
1930 * Return: QDF_STATUS_SUCCESS if found, else QDF_STATUS_E_FAILURE
1931 */
find_ie_data_after_fils_session_ie(struct mac_context * mac_ctx,uint8_t * buf,uint32_t buf_len,uint8_t ** ie,uint32_t * ie_len)1932 static QDF_STATUS find_ie_data_after_fils_session_ie(struct mac_context *mac_ctx,
1933 uint8_t *buf,
1934 uint32_t buf_len,
1935 uint8_t **ie,
1936 uint32_t *ie_len)
1937 {
1938 uint32_t left = buf_len;
1939 uint8_t *ptr = buf;
1940 uint8_t elem_id, elem_len;
1941
1942 if (!buf || 0 == buf_len)
1943 return QDF_STATUS_E_FAILURE;
1944
1945 while (left >= 2) {
1946 elem_id = ptr[0];
1947 elem_len = ptr[1];
1948 left -= 2;
1949 if (elem_len > left)
1950 return QDF_STATUS_E_FAILURE;
1951
1952 if ((elem_id == WLAN_REQUEST_IE_MAX_LEN) &&
1953 (left >= 3 && ptr[2] == SIR_FILS_SESSION_EXT_EID)) {
1954 (*ie) = ((&ptr[1]) + ptr[1] + 1);
1955 (*ie_len) = (left - elem_len);
1956 return QDF_STATUS_SUCCESS;
1957 }
1958 left -= elem_len;
1959 ptr += (elem_len + 2);
1960 }
1961 return QDF_STATUS_E_FAILURE;
1962 }
1963
1964 /**
1965 * fils_aead_encrypt() - API to do FILS AEAD encryption
1966 *
1967 * @kek: Pointer to KEK
1968 * @kek_len: KEK length
1969 * @own_mac: Pointer to own MAC address
1970 * @bssid: Bssid
1971 * @snonce: Supplicant Nonce
1972 * @anonce: Authenticator Nonce
1973 * @data: Pointer to data after MAC header
1974 * @data_len: length of @data
1975 * @plain_text: Pointer to data after FILS Session IE
1976 * @plain_text_len: length of @plain_text
1977 * @out: Pointer to the encrypted data
1978 *
1979 * length of AEAD encryption @out is @plain_text_len + AES_BLOCK_SIZE[16 bytes]
1980 *
1981 * Return: zero on success, error otherwise
1982 */
fils_aead_encrypt(const uint8_t * kek,unsigned int kek_len,const uint8_t * own_mac,const uint8_t * bssid,const uint8_t * snonce,const uint8_t * anonce,const uint8_t * data,size_t data_len,uint8_t * plain_text,size_t plain_text_len,uint8_t * out)1983 static int fils_aead_encrypt(const uint8_t *kek, unsigned int kek_len,
1984 const uint8_t *own_mac, const uint8_t *bssid,
1985 const uint8_t *snonce, const uint8_t *anonce,
1986 const uint8_t *data, size_t data_len,
1987 uint8_t *plain_text, size_t plain_text_len,
1988 uint8_t *out)
1989 {
1990 uint8_t v[AES_BLOCK_SIZE];
1991 const uint8_t *aad[6];
1992 size_t aad_len[6];
1993 uint8_t *buf;
1994 int ret;
1995
1996 /* SIV Encrypt/Decrypt takes input key of length 256, 384 or 512 bits */
1997 if (kek_len != 32 && kek_len != 48 && kek_len != 64) {
1998 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
1999 FL("Invalid key length: %u"), kek_len);
2000 return -EINVAL;
2001 }
2002
2003 if (!own_mac || !bssid || !snonce ||
2004 !anonce || data_len == 0 || plain_text_len == 0 ||
2005 !out) {
2006 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
2007 FL("Error missing params mac:%pK bssid:%pK snonce:%pK anonce:%pK data_len:%zu plain_text_len:%zu out:%pK"),
2008 own_mac, bssid, snonce, anonce, data_len,
2009 plain_text_len, out);
2010 return -EINVAL;
2011 }
2012
2013 if (plain_text == out) {
2014 buf = qdf_mem_malloc(plain_text_len);
2015 if (!buf)
2016 return -ENOMEM;
2017 qdf_mem_copy(buf, plain_text, plain_text_len);
2018 } else {
2019 buf = plain_text;
2020 }
2021
2022 aad[0] = own_mac;
2023 aad_len[0] = QDF_MAC_ADDR_SIZE;
2024 aad[1] = bssid;
2025 aad_len[1] = QDF_MAC_ADDR_SIZE;
2026 aad[2] = snonce;
2027 aad_len[2] = SIR_FILS_NONCE_LENGTH;
2028 aad[3] = anonce;
2029 aad_len[3] = SIR_FILS_NONCE_LENGTH;
2030 aad[4] = data;
2031 aad_len[4] = data_len;
2032 /* Plain text, P, is Sn in AES-SIV */
2033 aad[5] = buf;
2034 aad_len[5] = plain_text_len;
2035
2036 /* AES-SIV S2V */
2037 /* K1 = leftmost(K, len(K)/2) */
2038 ret = qdf_aes_s2v(kek, kek_len/2, aad, aad_len, 6, v);
2039 if (ret)
2040 goto error;
2041
2042 /* out = SIV || C (Synthetic Initialization Vector || Ciphered text) */
2043 qdf_mem_copy(out, v, AES_BLOCK_SIZE);
2044
2045 /* AES-SIV CTR */
2046 /* K2 = rightmost(K, len(K)/2) */
2047 /* Clear 31st and 63rd bits in counter synthetic iv */
2048 v[12] &= 0x7F;
2049 v[8] &= 0x7F;
2050
2051 ret = qdf_aes_ctr(kek + kek_len/2, kek_len/2, v, buf, plain_text_len,
2052 out + AES_BLOCK_SIZE, true);
2053
2054 error:
2055 if (plain_text == out)
2056 qdf_mem_free(buf);
2057 return ret;
2058 }
2059
aead_encrypt_assoc_req(struct mac_context * mac_ctx,struct pe_session * pe_session,uint8_t * frm,uint32_t * frm_len)2060 QDF_STATUS aead_encrypt_assoc_req(struct mac_context *mac_ctx,
2061 struct pe_session *pe_session,
2062 uint8_t *frm, uint32_t *frm_len)
2063 {
2064 uint8_t *plain_text = NULL, *data;
2065 uint32_t plain_text_len = 0, data_len;
2066 QDF_STATUS status;
2067 struct pe_fils_session *fils_info = pe_session->fils_info;
2068
2069 /*
2070 * data is the packet data after MAC header till
2071 * FILS session IE(inclusive)
2072 */
2073 data = frm + sizeof(tSirMacMgmtHdr);
2074
2075 /*
2076 * plain_text is the packet data after FILS session IE
2077 * which needs to be encrypted. Get plain_text ptr and
2078 * plain_text_len values using find_ptr_aft_fils_session_ie()
2079 */
2080 status = find_ie_data_after_fils_session_ie(mac_ctx, data +
2081 FIXED_PARAM_OFFSET_ASSOC_REQ,
2082 (*frm_len -
2083 FIXED_PARAM_OFFSET_ASSOC_REQ),
2084 &plain_text, &plain_text_len);
2085 if (QDF_IS_STATUS_ERROR(status)) {
2086 pe_err("Could not find FILS session IE");
2087 return QDF_STATUS_E_FAILURE;
2088 }
2089 data_len = ((*frm_len) - plain_text_len);
2090
2091 lim_fils_data_dump("Plain text: ", plain_text, plain_text_len);
2092
2093 /* Overwrite the AEAD encrypted output @ plain_text */
2094 if (fils_aead_encrypt(fils_info->kek, fils_info->kek_len,
2095 pe_session->self_mac_addr, pe_session->bssId,
2096 fils_info->fils_nonce,
2097 fils_info->auth_info.fils_nonce,
2098 data, data_len, plain_text, plain_text_len,
2099 plain_text)) {
2100 pe_err("AEAD Encryption fails!");
2101 return QDF_STATUS_E_FAILURE;
2102 }
2103
2104 /*
2105 * AEAD encrypted output(cipher_text) will have length equals to
2106 * plain_text_len + AES_BLOCK_SIZE(AEAD encryption header info).
2107 * Add this to frm_len
2108 */
2109 (*frm_len) += (AES_BLOCK_SIZE);
2110
2111 return QDF_STATUS_SUCCESS;
2112 }
2113
2114 /**
2115 * fils_aead_decrypt() - API to do AEAD decryption
2116 *
2117 * @kek: Pointer to KEK
2118 * @kek_len: KEK length
2119 * @own_mac: Pointer to own MAC address
2120 * @bssid: Bssid
2121 * @snonce: Supplicant Nonce
2122 * @anonce: Authenticator Nonce
2123 * @data: Pointer to data after MAC header
2124 * @data_len: length of @data
2125 * @plain_text: Pointer to data after FILS Session IE
2126 * @plain_text_len: length of @plain_text
2127 * @out: Pointer to the encrypted data
2128 *
2129 * Return: zero on success, error otherwise
2130 */
fils_aead_decrypt(const uint8_t * kek,unsigned int kek_len,const uint8_t * own_mac,const uint8_t * bssid,const uint8_t * snonce,const uint8_t * anonce,const uint8_t * data,size_t data_len,uint8_t * ciphered_text,size_t ciphered_text_len,uint8_t * plain_text)2131 static int fils_aead_decrypt(const uint8_t *kek, unsigned int kek_len,
2132 const uint8_t *own_mac, const uint8_t *bssid,
2133 const uint8_t *snonce, const uint8_t *anonce,
2134 const uint8_t *data, size_t data_len,
2135 uint8_t *ciphered_text, size_t ciphered_text_len,
2136 uint8_t *plain_text)
2137 {
2138 const uint8_t *aad[6];
2139 size_t aad_len[6];
2140 uint8_t *buf;
2141 size_t buf_len;
2142 uint8_t v[AES_BLOCK_SIZE];
2143 uint8_t siv[AES_BLOCK_SIZE];
2144 int ret;
2145
2146 /* SIV Encrypt/Decrypt takes input key of length 256, 384 or 512 bits */
2147 if (kek_len != 32 && kek_len != 48 && kek_len != 64) {
2148 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
2149 FL("Invalid key length: %u"), kek_len);
2150 return -EINVAL;
2151 }
2152
2153 if (!own_mac || !bssid || !snonce ||
2154 !anonce || data_len == 0 || ciphered_text_len < AES_BLOCK_SIZE ||
2155 !plain_text) {
2156 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
2157 FL("Error missing params mac:%pK bssid:%pK snonce:%pK anonce:%pK data_len:%zu ciphered_text_len:%zu plain_text:%pK"),
2158 own_mac, bssid, snonce, anonce, data_len,
2159 ciphered_text_len, plain_text);
2160 return -EINVAL;
2161 }
2162
2163 qdf_mem_copy(v, ciphered_text, AES_BLOCK_SIZE);
2164 qdf_mem_copy(siv, ciphered_text, AES_BLOCK_SIZE);
2165 v[12] &= 0x7F;
2166 v[8] &= 0x7F;
2167
2168 buf_len = ciphered_text_len - AES_BLOCK_SIZE;
2169 if (ciphered_text == plain_text) {
2170 /* in place decryption */
2171 buf = qdf_mem_malloc(buf_len);
2172 if (!buf)
2173 return -ENOMEM;
2174 qdf_mem_copy(buf, ciphered_text + AES_BLOCK_SIZE, buf_len);
2175 } else {
2176 buf = ciphered_text + AES_BLOCK_SIZE;
2177 }
2178
2179 /* AES-SIV CTR */
2180 /* K2 = rightmost(K, len(K)/2) */
2181 ret = qdf_aes_ctr(kek + kek_len/2, kek_len/2, v, buf, buf_len,
2182 plain_text, false);
2183 if (ret)
2184 goto error;
2185
2186 aad[0] = bssid;
2187 aad_len[0] = QDF_MAC_ADDR_SIZE;
2188 aad[1] = own_mac;
2189 aad_len[1] = QDF_MAC_ADDR_SIZE;
2190 aad[2] = anonce;
2191 aad_len[2] = SIR_FILS_NONCE_LENGTH;
2192 aad[3] = snonce;
2193 aad_len[3] = SIR_FILS_NONCE_LENGTH;
2194 aad[4] = data;
2195 aad_len[4] = data_len;
2196 aad[5] = plain_text;
2197 aad_len[5] = buf_len;
2198
2199 /* AES-SIV S2V */
2200 /* K1 = leftmost(K, len(K)/2) */
2201 ret = qdf_aes_s2v(kek, kek_len/2, aad, aad_len, 6, v);
2202 if (ret)
2203 goto error;
2204
2205 /* compare the iv generated against the one sent by AP */
2206 if (memcmp(v, siv, AES_BLOCK_SIZE) != 0) {
2207 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
2208 FL("siv not same as frame siv"));
2209 ret = -EINVAL;
2210 }
2211
2212 error:
2213 if (ciphered_text == plain_text)
2214 qdf_mem_free(buf);
2215 return ret;
2216 }
2217
aead_decrypt_assoc_rsp(struct mac_context * mac_ctx,struct pe_session * session,tDot11fAssocResponse * ar,uint8_t * p_frame,uint32_t * n_frame)2218 QDF_STATUS aead_decrypt_assoc_rsp(struct mac_context *mac_ctx,
2219 struct pe_session *session,
2220 tDot11fAssocResponse *ar,
2221 uint8_t *p_frame, uint32_t *n_frame)
2222 {
2223 QDF_STATUS status;
2224 uint32_t data_len, fils_ies_len;
2225 uint8_t *fils_ies;
2226 struct pe_fils_session *fils_info = session->fils_info;
2227
2228 if (*n_frame < FIXED_PARAM_OFFSET_ASSOC_RSP) {
2229 pe_debug("payload len is less than ASSOC RES offset");
2230 return QDF_STATUS_E_FAILURE;
2231 }
2232
2233 status = find_ie_data_after_fils_session_ie(mac_ctx, p_frame +
2234 FIXED_PARAM_OFFSET_ASSOC_RSP,
2235 ((*n_frame) -
2236 FIXED_PARAM_OFFSET_ASSOC_RSP),
2237 &fils_ies, &fils_ies_len);
2238 if (!QDF_IS_STATUS_SUCCESS(status)) {
2239 pe_err("FILS session IE not present");
2240 return status;
2241 }
2242
2243 data_len = (*n_frame) - fils_ies_len;
2244
2245 if (fils_aead_decrypt(fils_info->kek, fils_info->kek_len,
2246 session->self_mac_addr, session->bssId,
2247 fils_info->fils_nonce,
2248 fils_info->auth_info.fils_nonce,
2249 p_frame, data_len,
2250 fils_ies, fils_ies_len, fils_ies)){
2251 pe_err("AEAD decryption fails");
2252 return QDF_STATUS_E_FAILURE;
2253 }
2254
2255 /* Dump the output of AEAD decrypt */
2256 lim_fils_data_dump("Plain text: ", fils_ies,
2257 fils_ies_len - AES_BLOCK_SIZE);
2258
2259 (*n_frame) -= AES_BLOCK_SIZE;
2260 return status;
2261 }
2262 #endif
2263