GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / shared / bcmwpa.c
blob5a148108e9d2cfe80e49ebdda2d0e59063c5263f
1 /*
2 * bcmwpa.c - shared WPA-related functions
4 * Copyright (C) 2012, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
8 * the contents of this file may not be disclosed to third parties, copied
9 * or duplicated in any form, in whole or in part, without the prior
10 * written permission of Broadcom Corporation.
12 * $Id: bcmwpa.c 358033 2012-09-20 23:57:22Z $
15 #include <bcm_cfg.h>
16 #include <bcmendian.h>
18 /* include wl driver config file if this file is compiled for driver */
19 #ifdef BCMDRIVER
20 #include <osl.h>
21 #elif defined(BCMEXTSUP)
22 #include <string.h>
23 #include <bcm_osl.h>
24 #else
25 #if defined(__GNUC__)
26 extern void bcopy(const void *src, void *dst, uint len);
27 extern int bcmp(const void *b1, const void *b2, uint len);
28 extern void bzero(void *b, uint len);
29 #else
30 #define bcopy(src, dst, len) memcpy((dst), (src), (len))
31 #define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
32 #define bzero(b, len) memset((b), 0, (len))
33 #endif /* defined(__GNUC__) */
35 #endif /* BCMDRIVER */
38 #include <wlioctl.h>
39 #include <proto/802.11.h>
40 #if defined(BCMSUP_PSK) || defined(BCMSUPPL)
41 #include <proto/eapol.h>
42 #endif /* defined(BCMSUP_PSK) || defined(BCMSUPPL) */
43 #include <bcmutils.h>
44 #include <bcmwpa.h>
46 #ifdef BCMSUP_PSK
48 #include <bcmcrypto/prf.h>
49 #include <bcmcrypto/rc4.h>
51 #include <bcmcrypto/hmac_sha256.h>
52 #ifdef WLTDLS
53 #include <bcmcrypto/sha256.h>
54 #endif
56 void
57 BCMROMFN(wpa_calc_pmkid)(struct ether_addr *auth_ea, struct ether_addr *sta_ea,
58 uint8 *pmk, uint pmk_len, uint8 *pmkid, uint8 *data, uint8 *digest)
60 /* PMKID = HMAC-SHA1-128(PMK, "PMK Name" | AA | SPA) */
61 const char prefix[] = "PMK Name";
62 int data_len = 0;
64 /* create the the data portion */
65 bcopy(prefix, data, strlen(prefix));
66 data_len += strlen(prefix);
67 bcopy((uint8 *)auth_ea, &data[data_len], ETHER_ADDR_LEN);
68 data_len += ETHER_ADDR_LEN;
69 bcopy((uint8 *)sta_ea, &data[data_len], ETHER_ADDR_LEN);
70 data_len += ETHER_ADDR_LEN;
72 /* generate the pmkid */
73 hmac_sha1(data, data_len, pmk, pmk_len, digest);
74 bcopy(digest, pmkid, WPA2_PMKID_LEN);
77 #ifdef MFP
78 void
79 kdf_calc_pmkid(struct ether_addr *auth_ea, struct ether_addr *sta_ea,
80 uint8 *pmk, uint pmk_len, uint8 *pmkid, uint8 *data, uint8 *digest)
82 /* PMKID = Truncate-128(HMAC-SHA-256(PMK, "PMK Name" | AA | SPA)) */
83 char prefix[] = "PMK Name";
84 int data_len = 0;
86 /* create the the data portion */
87 bcopy(prefix, data, strlen(prefix));
88 data_len += strlen(prefix);
89 bcopy((uint8 *)auth_ea, &data[data_len], ETHER_ADDR_LEN);
90 data_len += ETHER_ADDR_LEN;
91 bcopy((uint8 *)sta_ea, &data[data_len], ETHER_ADDR_LEN);
92 data_len += ETHER_ADDR_LEN;
94 /* generate the pmkid */
95 hmac_sha256(pmk, pmk_len, data, data_len, digest, NULL);
96 bcopy(digest, pmkid, WPA2_PMKID_LEN);
98 #endif /* MFP */
100 #ifdef WLFBT
101 void
102 wpa_calc_pmkR0(uchar *ssid, int ssid_len, uint16 mdid, uint8 *r0kh,
103 uint r0kh_len, struct ether_addr *sta_ea,
104 uint8 *pmk, uint pmk_len, uint8 *pmkr0, uint8 *pmkr0name)
106 uint8 data[128], digest[PRF_OUTBUF_LEN];
107 const char prefix[] = "FT-R0";
108 const char prefix1[] = "FT-R0N";
109 int data_len = 0;
111 bcopy(prefix, data, strlen(prefix));
112 data_len += strlen(prefix);
113 data[data_len++] = (uint8)ssid_len;
114 bcopy(ssid, &data[data_len], ssid_len);
115 data_len += ssid_len;
116 htol16_ua_store(mdid, &data[data_len]);
117 data_len += sizeof(uint16);
118 data[data_len++] = (uint8)r0kh_len; /* ROKHlength */
119 bcopy(r0kh, &data[data_len], r0kh_len);
120 data_len += r0kh_len;
121 bcopy(sta_ea, &data[data_len], ETHER_ADDR_LEN);
122 data_len += ETHER_ADDR_LEN;
124 hmac_sha256_n(pmk, pmk_len, data, data_len, digest, 48);
125 bcopy(digest, pmkr0, 32);
127 /* calc and return PMKR0Name */
128 bcopy(prefix1, data, strlen(prefix1));
129 data_len = strlen(prefix1);
130 bcopy(&digest[32], &data[data_len], 16);
131 data_len += 16;
132 sha256(data, data_len, digest, 0);
133 bcopy(digest, pmkr0name, WPA2_PMKID_LEN);
136 void
137 wpa_calc_pmkR1(struct ether_addr *r1kh, struct ether_addr *sta_ea, uint8 *pmk,
138 uint pmk_len, uint8 *pmkr0name, uint8 *pmkr1, uint8 *pmkr1name)
140 uint8 data[128], digest[PRF_OUTBUF_LEN];
141 const char prefix[] = "FT-R1";
142 const char prefix1[] = "FT-R1N";
143 int data_len = 0;
145 bcopy(prefix, data, strlen(prefix));
146 data_len += strlen(prefix);
147 bcopy(r1kh, &data[data_len], ETHER_ADDR_LEN);
148 data_len += ETHER_ADDR_LEN;
149 bcopy(sta_ea, &data[data_len], ETHER_ADDR_LEN);
150 data_len += ETHER_ADDR_LEN;
152 hmac_sha256_n(pmk, pmk_len, data, data_len, digest, 32);
153 bcopy(digest, pmkr1, 32);
155 /* calc and return PMKR1Name */
156 bcopy(prefix1, data, strlen(prefix1));
157 data_len = strlen(prefix1);
158 bcopy(pmkr0name, &data[data_len], WPA2_PMKID_LEN);
159 data_len += WPA2_PMKID_LEN;
160 bcopy(r1kh, &data[data_len], ETHER_ADDR_LEN);
161 data_len += ETHER_ADDR_LEN;
162 bcopy(sta_ea, &data[data_len], ETHER_ADDR_LEN);
163 data_len += ETHER_ADDR_LEN;
164 sha256(data, data_len, digest, 0);
165 bcopy(digest, pmkr1name, WPA2_PMKID_LEN);
168 void
169 wpa_calc_ft_ptk(struct ether_addr *bssid, struct ether_addr *sta_ea,
170 uint8 *anonce, uint8* snonce, uint8 *pmk, uint pmk_len,
171 uint8 *ptk, uint ptk_len)
173 uchar data[128], prf_buff[PRF_OUTBUF_LEN];
174 const char prefix[] = "FT-PTK";
175 uint data_len = 0;
177 bcopy(prefix, data, strlen(prefix));
178 data_len += strlen(prefix);
179 bcopy(snonce, (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
180 data_len += EAPOL_WPA_KEY_NONCE_LEN;
181 bcopy(anonce, (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
182 data_len += EAPOL_WPA_KEY_NONCE_LEN;
184 bcopy((uint8 *)bssid, (char *)&data[data_len], ETHER_ADDR_LEN);
185 data_len += ETHER_ADDR_LEN;
186 bcopy((uint8 *)sta_ea, (char *)&data[data_len], ETHER_ADDR_LEN);
187 data_len += ETHER_ADDR_LEN;
189 /* generate the PTK */
190 hmac_sha256_n(pmk, pmk_len, data, data_len, prf_buff, ptk_len);
191 bcopy(prf_buff, (char*)ptk, ptk_len);
193 #endif /* WLFBT */
195 bool
196 wpa_encr_key_data(eapol_wpa_key_header_t *body, uint16 key_info, uint8 *ekey,
197 uint8 *gtk, uint8 *data, uint8 *encrkey, rc4_ks_t *rc4key)
199 uint16 len;
201 switch (key_info & (WPA_KEY_DESC_V1 | WPA_KEY_DESC_V2)) {
202 case WPA_KEY_DESC_V1:
203 if (gtk)
204 len = ntoh16_ua((uint8 *)&body->key_len);
205 else
206 len = ntoh16_ua((uint8 *)&body->data_len);
208 /* create the iv/ptk key */
209 bcopy(body->iv, encrkey, 16);
210 bcopy(ekey, &encrkey[16], 16);
211 /* encrypt the key data */
212 prepare_key(encrkey, 32, rc4key);
213 rc4(data, WPA_KEY_DATA_LEN_256, rc4key); /* dump 256 bytes */
214 rc4(body->data, len, rc4key);
215 break;
216 case WPA_KEY_DESC_V2:
217 case WPA_KEY_DESC_V3:
218 len = ntoh16_ua((uint8 *)&body->data_len);
219 /* pad if needed - min. 16 bytes, 8 byte aligned */
220 /* padding is 0xdd followed by 0's */
221 if (len < 2*AKW_BLOCK_LEN) {
222 body->data[len] = WPA2_KEY_DATA_PAD;
223 bzero(&body->data[len+1], 2*AKW_BLOCK_LEN - (len+1));
224 len = 2*AKW_BLOCK_LEN;
225 } else if (len % AKW_BLOCK_LEN) {
226 body->data[len] = WPA2_KEY_DATA_PAD;
227 bzero(&body->data[len+1], AKW_BLOCK_LEN - ((len+1) % AKW_BLOCK_LEN));
228 len += AKW_BLOCK_LEN - (len % AKW_BLOCK_LEN);
230 if (aes_wrap(WPA_MIC_KEY_LEN, ekey, len, body->data, body->data)) {
231 return FALSE;
233 len += 8;
234 hton16_ua_store(len, (uint8 *)&body->data_len);
235 break;
236 default:
237 return FALSE;
240 return TRUE;
243 /* Decrypt a key data from a WPA key message */
244 bool
245 BCMROMFN(wpa_decr_key_data)(eapol_wpa_key_header_t *body, uint16 key_info, uint8 *ekey,
246 uint8 *gtk, uint8 *data, uint8 *encrkey, rc4_ks_t *rc4key)
248 uint16 len;
250 switch (key_info & (WPA_KEY_DESC_V1 | WPA_KEY_DESC_V2)) {
251 case WPA_KEY_DESC_V1:
252 bcopy(body->iv, encrkey, WPA_MIC_KEY_LEN);
253 bcopy(ekey, &encrkey[WPA_MIC_KEY_LEN], WPA_MIC_KEY_LEN);
254 /* decrypt the key data */
255 prepare_key(encrkey, WPA_MIC_KEY_LEN*2, rc4key);
256 rc4(data, WPA_KEY_DATA_LEN_256, rc4key); /* dump 256 bytes */
257 if (gtk)
258 len = ntoh16_ua((uint8 *)&body->key_len);
259 else
260 len = ntoh16_ua((uint8 *)&body->data_len);
261 rc4(body->data, len, rc4key);
262 if (gtk)
263 bcopy(body->data, gtk, len);
264 break;
266 case WPA_KEY_DESC_V2:
267 case WPA_KEY_DESC_V3:
268 len = ntoh16_ua((uint8 *)&body->data_len);
269 if (aes_unwrap(WPA_MIC_KEY_LEN, ekey, len, body->data,
270 gtk ? gtk : body->data)) {
271 return FALSE;
273 break;
275 default:
276 return FALSE;
278 return TRUE;
281 void
282 BCMROMFN(wpa_calc_ptk)(struct ether_addr *auth_ea, struct ether_addr *sta_ea,
283 uint8 *anonce, uint8* snonce, uint8 *pmk, uint pmk_len,
284 uint8 *ptk, uint ptk_len)
286 uchar data[128], prf_buff[PRF_OUTBUF_LEN];
287 const char prefix[] = "Pairwise key expansion";
288 uint data_len = 0;
290 /* Create the the data portion:
291 * the lesser of the EAs, followed by the greater of the EAs,
292 * followed by the lesser of the the nonces, followed by the
293 * greater of the nonces.
295 bcopy(wpa_array_cmp(MIN_ARRAY, (uint8 *)auth_ea, (uint8 *)sta_ea,
296 ETHER_ADDR_LEN),
297 (char *)&data[data_len], ETHER_ADDR_LEN);
298 data_len += ETHER_ADDR_LEN;
299 bcopy(wpa_array_cmp(MAX_ARRAY, (uint8 *)auth_ea, (uint8 *)sta_ea,
300 ETHER_ADDR_LEN),
301 (char *)&data[data_len], ETHER_ADDR_LEN);
302 data_len += ETHER_ADDR_LEN;
303 bcopy(wpa_array_cmp(MIN_ARRAY, snonce, anonce,
304 EAPOL_WPA_KEY_NONCE_LEN),
305 (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
306 data_len += EAPOL_WPA_KEY_NONCE_LEN;
307 bcopy(wpa_array_cmp(MAX_ARRAY, snonce, anonce,
308 EAPOL_WPA_KEY_NONCE_LEN),
309 (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
310 data_len += EAPOL_WPA_KEY_NONCE_LEN;
312 /* generate the PTK */
313 ASSERT(strlen(prefix) + data_len + 1 <= PRF_MAX_I_D_LEN);
314 fPRF(pmk, (int)pmk_len, (uchar *)prefix, strlen(prefix), data, data_len,
315 prf_buff, (int)ptk_len);
316 bcopy(prf_buff, (char*)ptk, ptk_len);
319 #ifdef MFP
320 void
321 kdf_calc_ptk(struct ether_addr *auth_ea, struct ether_addr *sta_ea,
322 uint8 *anonce, uint8* snonce, uint8 *pmk, uint pmk_len,
323 uint8 *ptk, uint ptk_len)
325 uchar data[128], prf_buff[PRF_OUTBUF_LEN];
326 char prefix[] = "Pairwise key expansion";
327 uint data_len = 0;
329 /* Create the the data portion:
330 * the lesser of the EAs, followed by the greater of the EAs,
331 * followed by the lesser of the the nonces, followed by the
332 * greater of the nonces.
334 bcopy(wpa_array_cmp(MIN_ARRAY, (uint8 *)auth_ea, (uint8 *)sta_ea,
335 ETHER_ADDR_LEN),
336 (char *)&data[data_len], ETHER_ADDR_LEN);
337 data_len += ETHER_ADDR_LEN;
338 bcopy(wpa_array_cmp(MAX_ARRAY, (uint8 *)auth_ea, (uint8 *)sta_ea,
339 ETHER_ADDR_LEN),
340 (char *)&data[data_len], ETHER_ADDR_LEN);
341 data_len += ETHER_ADDR_LEN;
342 bcopy(wpa_array_cmp(MIN_ARRAY, snonce, anonce,
343 EAPOL_WPA_KEY_NONCE_LEN),
344 (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
345 data_len += EAPOL_WPA_KEY_NONCE_LEN;
346 bcopy(wpa_array_cmp(MAX_ARRAY, snonce, anonce,
347 EAPOL_WPA_KEY_NONCE_LEN),
348 (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
349 data_len += EAPOL_WPA_KEY_NONCE_LEN;
351 /* generate the PTK */
352 ASSERT(strlen(prefix) + data_len + 1 <= PRF_MAX_I_D_LEN);
353 KDF(pmk, (int)pmk_len, (uchar *)prefix, strlen(prefix), data, data_len,
354 prf_buff, (int)ptk_len);
355 bcopy(prf_buff, (char*)ptk, ptk_len);
357 #endif /* MFP */
358 /* Decrypt a group transient key from a WPA key message */
359 bool
360 BCMROMFN(wpa_decr_gtk)(eapol_wpa_key_header_t *body, uint16 key_info, uint8 *ekey,
361 uint8 *gtk, uint8 *data, uint8 *encrkey, rc4_ks_t *rc4key)
363 return wpa_decr_key_data(body, key_info, ekey, gtk, data, encrkey, rc4key);
366 /* Compute Message Integrity Code (MIC) over EAPOL message */
367 bool
368 BCMROMFN(wpa_make_mic)(eapol_header_t *eapol, uint key_desc, uint8 *mic_key, uchar *mic)
370 int mic_length;
372 /* length of eapol pkt from the version field on */
373 mic_length = 4 + ntoh16_ua((uint8 *)&eapol->length);
375 /* Create the MIC for the pkt */
376 switch (key_desc) {
377 case WPA_KEY_DESC_V1:
378 hmac_md5(&eapol->version, mic_length, mic_key,
379 EAPOL_WPA_KEY_MIC_LEN, mic);
380 break;
381 case WPA_KEY_DESC_V2:
382 hmac_sha1(&eapol->version, mic_length, mic_key,
383 EAPOL_WPA_KEY_MIC_LEN, mic);
384 break;
385 case WPA_KEY_DESC_V3:
386 aes_cmac_calc(&eapol->version, mic_length, mic_key,
387 EAPOL_WPA_KEY_MIC_LEN, mic);
388 break;
389 default:
390 return FALSE;
392 return TRUE;
395 /* Check MIC of EAPOL message */
396 bool
397 BCMROMFN(wpa_check_mic)(eapol_header_t *eapol, uint key_desc, uint8 *mic_key)
399 eapol_wpa_key_header_t *body = (eapol_wpa_key_header_t *)eapol->body;
400 uchar digest[PRF_OUTBUF_LEN];
401 uchar mic[EAPOL_WPA_KEY_MIC_LEN];
403 /* save MIC and clear its space in message */
404 bcopy(&body->mic, mic, EAPOL_WPA_KEY_MIC_LEN);
405 bzero(&body->mic, EAPOL_WPA_KEY_MIC_LEN);
407 if (!wpa_make_mic(eapol, key_desc, mic_key, digest)) {
408 return FALSE;
410 return !bcmp(digest, mic, EAPOL_WPA_KEY_MIC_LEN);
412 #endif /* BCMSUP_PSK */
414 #ifdef WLTDLS
415 void
416 wpa_calc_tpk(struct ether_addr *init_ea, struct ether_addr *resp_ea,
417 struct ether_addr *bssid, uint8 *anonce, uint8* snonce,
418 uint8 *tpk, uint tpk_len)
420 uchar key_input[SHA256_DIGEST_LENGTH];
421 uchar data[128], tpk_buff[160]; /* TK_bits + 128, where TK_bits is 16 bytes for CCMP */
422 char prefix[] = "TDLS PMK";
423 uint data_len = 0;
425 /* Generate TPK-Key-Input = SHA-256(min(SN, AN) || max(SN, AN)) first */
426 bcopy(wpa_array_cmp(MIN_ARRAY, snonce, anonce,
427 EAPOL_WPA_KEY_NONCE_LEN),
428 (char *)&data[0], EAPOL_WPA_KEY_NONCE_LEN);
429 prhex("min(sn,an):", data, EAPOL_WPA_KEY_NONCE_LEN);
430 data_len += EAPOL_WPA_KEY_NONCE_LEN;
431 bcopy(wpa_array_cmp(MAX_ARRAY, snonce, anonce,
432 EAPOL_WPA_KEY_NONCE_LEN),
433 (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
434 prhex("max(sn,an):", &data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
435 data_len += EAPOL_WPA_KEY_NONCE_LEN;
436 prhex("data:", &data[data_len], 2*EAPOL_WPA_KEY_NONCE_LEN);
437 sha256(data, data_len, key_input, SHA256_DIGEST_LENGTH);
438 prhex("input_key", key_input, SHA256_DIGEST_LENGTH);
440 /* Create the the data portion:
441 * the lesser of the EAs, followed by the greater of the EAs,
442 * followed by BSSID
444 data_len = 0;
445 bcopy(prefix, data, strlen(prefix));
446 prhex("prefix:", data, strlen(prefix));
447 data_len += strlen(prefix);
449 bcopy(wpa_array_cmp(MIN_ARRAY, (uint8 *)init_ea, (uint8 *)resp_ea,
450 ETHER_ADDR_LEN),
451 (char *)&data[data_len], ETHER_ADDR_LEN);
452 prhex("min(init_ea, resp_ea:", &data[data_len], ETHER_ADDR_LEN);
453 data_len += ETHER_ADDR_LEN;
454 bcopy(wpa_array_cmp(MAX_ARRAY, (uint8 *)init_ea, (uint8 *)resp_ea,
455 ETHER_ADDR_LEN),
456 (char *)&data[data_len], ETHER_ADDR_LEN);
457 prhex("min(init_ea, resp_ea:", &data[data_len], ETHER_ADDR_LEN);
458 data_len += ETHER_ADDR_LEN;
459 bcopy((char*)bssid, (char *)&data[data_len], ETHER_ADDR_LEN);
460 data_len += ETHER_ADDR_LEN;
461 prhex("data", data, data_len);
463 /* generate the TPK */
464 hmac_sha256_n(key_input, SHA256_DIGEST_LENGTH, data, data_len, tpk_buff, tpk_len);
465 bcopy(tpk_buff, (char*)tpk, tpk_len);
467 #endif /* WLTDLS */
469 /* Convert WPA/WPA2 IE cipher suite to locally used value */
470 static bool
471 rsn_cipher(wpa_suite_t *suite, ushort *cipher, const uint8 *std_oui, bool wep_ok)
473 bool ret = TRUE;
475 if (!bcmp((const char *)suite->oui, std_oui, DOT11_OUI_LEN)) {
476 switch (suite->type) {
477 case WPA_CIPHER_TKIP:
478 *cipher = CRYPTO_ALGO_TKIP;
479 break;
480 case WPA_CIPHER_AES_CCM:
481 *cipher = CRYPTO_ALGO_AES_CCM;
482 break;
483 case WPA_CIPHER_WEP_40:
484 if (wep_ok)
485 *cipher = CRYPTO_ALGO_WEP1;
486 else
487 ret = FALSE;
488 break;
489 case WPA_CIPHER_WEP_104:
490 if (wep_ok)
491 *cipher = CRYPTO_ALGO_WEP128;
492 else
493 ret = FALSE;
494 break;
495 default:
496 ret = FALSE;
497 break;
499 return ret;
502 /* check for other vendor OUIs */
503 return FALSE;
506 bool
507 BCMROMFN(wpa_cipher)(wpa_suite_t *suite, ushort *cipher, bool wep_ok)
509 return rsn_cipher(suite, cipher, (const uchar*)WPA_OUI, wep_ok);
512 bool
513 BCMROMFN(wpa2_cipher)(wpa_suite_t *suite, ushort *cipher, bool wep_ok)
515 return rsn_cipher(suite, cipher, (const uchar*)WPA2_OUI, wep_ok);
518 /* Is any of the tlvs the expected entry? If
519 * not update the tlvs buffer pointer/length.
521 bool
522 bcm_has_ie(uint8 *ie, uint8 **tlvs, uint *tlvs_len, const uint8 *oui, int oui_len, uint8 type)
524 /* If the contents match the OUI and the type */
525 if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
526 !bcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
527 type == ie[TLV_BODY_OFF + oui_len]) {
528 return TRUE;
531 /* point to the next ie */
532 ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
533 /* calculate the length of the rest of the buffer */
534 *tlvs_len -= (int)(ie - *tlvs);
535 /* update the pointer to the start of the buffer */
536 *tlvs = ie;
538 return FALSE;
541 wpa_ie_fixed_t *
542 BCMROMFN(bcm_find_wpaie)(uint8 *parse, uint len)
544 bcm_tlv_t *ie;
546 while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
547 if (bcm_is_wpa_ie((uint8 *)ie, &parse, &len)) {
548 return (wpa_ie_fixed_t *)ie;
551 return NULL;
554 bcm_tlv_t *
555 bcm_find_wmeie(uint8 *parse, uint len, uint8 subtype, uint8 subtype_len)
557 bcm_tlv_t *ie;
559 while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
560 if (bcm_is_wme_ie((uint8 *)ie, &parse, &len)) {
561 uint ie_len = TLV_HDR_LEN + ie->len;
562 if (ie_len > TLV_HDR_LEN + WME_OUI_LEN &&
563 ((wme_ie_t *)ie->data)->subtype == subtype &&
564 ie_len == (uint)TLV_HDR_LEN + subtype_len)
565 return ie;
566 parse += ie_len;
567 len -= ie_len;
570 return NULL;
573 wps_ie_fixed_t *
574 bcm_find_wpsie(uint8 *parse, uint len)
576 bcm_tlv_t *ie;
578 while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
579 if (bcm_is_wps_ie((uint8 *)ie, &parse, &len)) {
580 return (wps_ie_fixed_t *)ie;
583 return NULL;
586 /* locate the Attribute in the WPS IE */
587 wps_at_fixed_t *
588 bcm_wps_find_at(wps_at_fixed_t *at, int len, uint16 id)
590 while (len >= WPS_AT_FIXED_LEN) {
591 int alen = WPS_AT_FIXED_LEN + ntoh16_ua(((wps_at_fixed_t *)at)->len);
592 if (ntoh16_ua(((wps_at_fixed_t *)at)->at) == id && alen <= len)
593 return at;
594 at = (wps_at_fixed_t *)((uint8 *)at + alen);
595 len -= alen;
597 return NULL;
600 #ifdef WLP2P
601 wifi_p2p_ie_t *
602 bcm_find_p2pie(uint8 *parse, uint len)
604 bcm_tlv_t *ie;
606 while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
607 if (bcm_is_p2p_ie((uint8 *)ie, &parse, &len)) {
608 return (wifi_p2p_ie_t *)ie;
611 return NULL;
613 #endif
615 #if defined(BCMSUP_PSK) || defined(BCMSUPPL)
616 #define wpa_is_kde(ie, tlvs, len, type) bcm_has_ie(ie, tlvs, len, \
617 (const uint8 *)WPA2_OUI, WPA2_OUI_LEN, type)
619 eapol_wpa2_encap_data_t *
620 BCMROMFN(wpa_find_kde)(uint8 *parse, uint len, uint8 type)
622 bcm_tlv_t *ie;
624 while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_PROPR_ID))) {
625 if (wpa_is_kde((uint8 *)ie, &parse, &len, type)) {
626 return (eapol_wpa2_encap_data_t *)ie;
629 return NULL;
632 bool
633 BCMROMFN(wpa_is_gtk_encap)(uint8 *ie, uint8 **tlvs, uint *tlvs_len)
635 return wpa_is_kde(ie, tlvs, tlvs_len, WPA2_KEY_DATA_SUBTYPE_GTK);
638 eapol_wpa2_encap_data_t *
639 BCMROMFN(wpa_find_gtk_encap)(uint8 *parse, uint len)
641 return wpa_find_kde(parse, len, WPA2_KEY_DATA_SUBTYPE_GTK);
643 #endif /* defined(BCMSUP_PSK) || defined(BCMSUPPL) */
645 uint8 *
646 BCMROMFN(wpa_array_cmp)(int max_array, uint8 *x, uint8 *y, uint len)
648 uint i;
649 uint8 *ret = x;
651 for (i = 0; i < len; i++)
652 if (x[i] != y[i])
653 break;
655 if (i == len) {
656 /* returning null will cause crash, return value used for bcopy */
657 /* return first param in this case to close security loophole */
658 return x;
660 if (max_array && (y[i] > x[i]))
661 ret = y;
662 if (!max_array && (y[i] < x[i]))
663 ret = y;
665 return (ret);
668 void
669 BCMROMFN(wpa_incr_array)(uint8 *array, uint len)
671 int i;
673 for (i = (len-1); i >= 0; i--)
674 if (array[i]++ != 0xff) {
675 break;
679 /* map akm suite to internal WPA_AUTH_XXXX */
680 /* akms points to 4 byte suite (oui + type) */
681 bool
682 BCMROMFN(bcmwpa_akm2WPAauth)(uint8 *akm, uint32 *auth, bool sta_iswpa)
684 if (!bcmp(akm, WPA2_OUI, DOT11_OUI_LEN)) {
685 switch (akm[DOT11_OUI_LEN]) {
686 case RSN_AKM_NONE:
687 *auth = WPA_AUTH_NONE;
688 break;
689 case RSN_AKM_UNSPECIFIED:
690 *auth = WPA2_AUTH_UNSPECIFIED;
691 break;
692 case RSN_AKM_PSK:
693 *auth = WPA2_AUTH_PSK;
694 break;
695 case RSN_AKM_FBT_1X:
696 *auth = WPA2_AUTH_UNSPECIFIED;
697 break;
698 case RSN_AKM_FBT_PSK:
699 *auth = WPA2_AUTH_PSK;
700 break;
701 case RSN_AKM_MFP_1X:
702 *auth = WPA2_AUTH_UNSPECIFIED;
703 break;
704 case RSN_AKM_MFP_PSK:
705 *auth = WPA2_AUTH_PSK;
706 break;
708 default:
709 return FALSE;
711 return TRUE;
713 else
714 if (!bcmp(akm, WPA_OUI, DOT11_OUI_LEN)) {
715 switch (akm[DOT11_OUI_LEN]) {
716 case RSN_AKM_NONE:
717 *auth = WPA_AUTH_NONE;
718 break;
719 case RSN_AKM_UNSPECIFIED:
720 *auth = WPA_AUTH_UNSPECIFIED;
721 break;
722 case RSN_AKM_PSK:
723 *auth = WPA_AUTH_PSK;
724 break;
725 default:
726 return FALSE;
728 return TRUE;
730 return FALSE;
733 /* map cipher suite to internal WSEC_XXXX */
734 /* cs points 4 byte cipher suite, and only the type is used for non CCX ciphers */
735 bool
736 BCMROMFN(bcmwpa_cipher2wsec)(uint8 *cipher, uint32 *wsec)
738 switch (cipher[DOT11_OUI_LEN]) {
739 case WPA_CIPHER_NONE:
740 *wsec = 0;
741 break;
742 case WPA_CIPHER_WEP_40:
743 case WPA_CIPHER_WEP_104:
744 *wsec = WEP_ENABLED;
745 break;
746 case WPA_CIPHER_TKIP:
747 *wsec = TKIP_ENABLED;
748 break;
749 case WPA_CIPHER_AES_CCM:
750 *wsec = AES_ENABLED;
751 break;
752 default:
753 return FALSE;
755 return TRUE;