xref: /wlan-driver/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
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