RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / shared / bcmwpa.c
blob83ab489ec3ff9c544dbe2651b49602262cc3f8ec
1 /*
2 * bcmwpa.c - shared WPA-related functions
4 * Copyright (C) 2010, 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,v 1.46.16.11 2010-11-30 06:34:17 Exp $
15 #include <bcmendian.h>
17 /* include wl driver config file if this file is compiled for driver */
18 #ifdef BCMDRIVER
19 #include <osl.h>
20 #elif defined(BCMEXTSUP)
21 #include <string.h>
22 #include <bcm_osl.h>
23 #else
24 #if defined(__GNUC__)
25 extern void bcopy(const void *src, void *dst, uint len);
26 extern int bcmp(const void *b1, const void *b2, uint len);
27 extern void bzero(void *b, uint len);
28 #else
29 #define bcopy(src, dst, len) memcpy((dst), (src), (len))
30 #define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
31 #define bzero(b, len) memset((b), 0, (len))
32 #endif /* defined(__GNUC__) */
34 #endif /* BCMDRIVER */
37 #include <wlioctl.h>
38 #include <proto/802.11.h>
39 #if defined(BCMSUP_PSK) || defined(BCMSUPPL) || defined(MFP) || defined(WLFBT)
40 #include <proto/eapol.h>
41 #endif /* defined(BCMSUP_PSK) || defined(BCMSUPPL) || defined(MFP) || defined(WLFBT) */
42 #include <bcmutils.h>
43 #include <bcmwpa.h>
45 #ifdef BCMSUP_PSK
47 #include <bcmcrypto/prf.h>
48 #include <bcmcrypto/rc4.h>
49 #if defined(MFP) || defined(WLFBT)
50 #include <bcmcrypto/hmac_sha256.h>
51 #endif
53 void
54 BCMROMFN(wpa_calc_pmkid)(struct ether_addr *auth_ea, struct ether_addr *sta_ea,
55 uint8 *pmk, uint pmk_len, uint8 *pmkid, uint8 *data, uint8 *digest)
57 /* PMKID = HMAC-SHA1-128(PMK, "PMK Name" | AA | SPA) */
58 const char prefix[] = "PMK Name";
59 int data_len = 0;
61 /* create the the data portion */
62 bcopy(prefix, data, strlen(prefix));
63 data_len += strlen(prefix);
64 bcopy((uint8 *)auth_ea, &data[data_len], ETHER_ADDR_LEN);
65 data_len += ETHER_ADDR_LEN;
66 bcopy((uint8 *)sta_ea, &data[data_len], ETHER_ADDR_LEN);
67 data_len += ETHER_ADDR_LEN;
69 /* generate the pmkid */
70 hmac_sha1(data, data_len, pmk, pmk_len, digest);
71 bcopy(digest, pmkid, WPA2_PMKID_LEN);
73 #if defined(MFP) || defined(WLFBT)
74 void
75 kdf_calc_pmkid(struct ether_addr *auth_ea, struct ether_addr *sta_ea,
76 uint8 *pmk, uint pmk_len, uint8 *pmkid, uint8 *data, uint8 *digest)
78 /* PMKID = Truncate-128(HMAC-SHA-256(PMK, "PMK Name" | AA | SPA)) */
79 char prefix[] = "PMK Name";
80 int data_len = 0;
82 /* create the the data portion */
83 bcopy(prefix, data, strlen(prefix));
84 data_len += strlen(prefix);
85 bcopy((uint8 *)auth_ea, &data[data_len], ETHER_ADDR_LEN);
86 data_len += ETHER_ADDR_LEN;
87 bcopy((uint8 *)sta_ea, &data[data_len], ETHER_ADDR_LEN);
88 data_len += ETHER_ADDR_LEN;
90 /* generate the pmkid */
91 hmac_sha256(pmk, pmk_len, data, data_len, digest, NULL);
92 bcopy(digest, pmkid, WPA2_PMKID_LEN);
95 #endif /* defined(MFP) || defined(WLFBT) */
98 #if defined(WLFBT)
99 void
100 wpa_calc_pmkR0(uchar *ssid, int ssid_len, uint16 mdid, uint8 *r0kh,
101 uint r0kh_len, struct ether_addr *sta_ea,
102 uint8 *pmk, uint pmk_len, uint8 *pmkr0, uint8 *pmkr0name)
104 uint8 data[128], digest[PRF_OUTBUF_LEN];
105 const char prefix[] = "FT-R0";
106 const char prefix1[] = "FT-R0N";
107 int data_len = 0;
109 bcopy(prefix, data, strlen(prefix));
110 data_len += strlen(prefix);
111 data[data_len++] = (uint8)ssid_len;
112 bcopy(ssid, &data[data_len], ssid_len);
113 data_len += ssid_len;
114 htol16_ua_store(mdid, &data[data_len]);
115 data_len += sizeof(uint16);
116 data[data_len++] = (uint8)r0kh_len; /* ROKHlength */
117 bcopy(r0kh, &data[data_len], r0kh_len);
118 data_len += r0kh_len;
119 bcopy(sta_ea, &data[data_len], ETHER_ADDR_LEN);
120 data_len += ETHER_ADDR_LEN;
122 hmac_sha256_n(pmk, pmk_len, data, data_len, digest, 48);
123 bcopy(digest, pmkr0, 32);
125 /* calc and return PMKR0Name */
126 bcopy(prefix1, data, strlen(prefix1));
127 data_len = strlen(prefix1);
128 bcopy(&digest[32], &data[data_len], 16);
129 data_len += 16;
130 sha256(data, data_len, digest, 0);
131 bcopy(digest, pmkr0name, WPA2_PMKID_LEN);
134 void
135 wpa_calc_pmkR1(struct ether_addr *r1kh, struct ether_addr *sta_ea, uint8 *pmk,
136 uint pmk_len, uint8 *pmkr0name, uint8 *pmkr1, uint8 *pmkr1name)
138 uint8 data[128], digest[PRF_OUTBUF_LEN];
139 const char prefix[] = "FT-R1";
140 const char prefix1[] = "FT-R1N";
141 int data_len = 0;
143 bcopy(prefix, data, strlen(prefix));
144 data_len += strlen(prefix);
145 bcopy(r1kh, &data[data_len], ETHER_ADDR_LEN);
146 data_len += ETHER_ADDR_LEN;
147 bcopy(sta_ea, &data[data_len], ETHER_ADDR_LEN);
148 data_len += ETHER_ADDR_LEN;
150 hmac_sha256_n(pmk, pmk_len, data, data_len, digest, 32);
151 bcopy(digest, pmkr1, 32);
153 /* calc and return PMKR1Name */
154 bcopy(prefix1, data, strlen(prefix1));
155 data_len = strlen(prefix1);
156 bcopy(pmkr0name, &data[data_len], WPA2_PMKID_LEN);
157 data_len += WPA2_PMKID_LEN;
158 bcopy(r1kh, &data[data_len], ETHER_ADDR_LEN);
159 data_len += ETHER_ADDR_LEN;
160 bcopy(sta_ea, &data[data_len], ETHER_ADDR_LEN);
161 data_len += ETHER_ADDR_LEN;
162 sha256(data, data_len, digest, 0);
163 bcopy(digest, pmkr1name, WPA2_PMKID_LEN);
166 void
167 wpa_calc_ft_ptk(struct ether_addr *bssid, struct ether_addr *sta_ea,
168 uint8 *anonce, uint8* snonce, uint8 *pmk, uint pmk_len,
169 uint8 *ptk, uint ptk_len)
171 uchar data[128], prf_buff[PRF_OUTBUF_LEN];
172 const char prefix[] = "FT-PTK";
173 uint data_len = 0;
175 bcopy(prefix, data, strlen(prefix));
176 data_len += strlen(prefix);
177 bcopy(snonce, (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
178 data_len += EAPOL_WPA_KEY_NONCE_LEN;
179 bcopy(anonce, (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
180 data_len += EAPOL_WPA_KEY_NONCE_LEN;
182 bcopy((uint8 *)bssid, (char *)&data[data_len], ETHER_ADDR_LEN);
183 data_len += ETHER_ADDR_LEN;
184 bcopy((uint8 *)sta_ea, (char *)&data[data_len], ETHER_ADDR_LEN);
185 data_len += ETHER_ADDR_LEN;
187 /* generate the PTK */
188 hmac_sha256_n(pmk, pmk_len, data, data_len, prf_buff, ptk_len);
189 bcopy(prf_buff, (char*)ptk, ptk_len);
191 #endif /* WLFBT */
193 bool
194 wpa_encr_key_data(eapol_wpa_key_header_t *body, uint16 key_info, uint8 *ekey,
195 uint8 *gtk, uint8 *data, uint8 *encrkey, rc4_ks_t *rc4key)
197 uint16 len;
199 switch (key_info & (WPA_KEY_DESC_V1 | WPA_KEY_DESC_V2)) {
200 case WPA_KEY_DESC_V1:
201 if (gtk)
202 len = ntoh16_ua((uint8 *)&body->key_len);
203 else
204 len = ntoh16_ua((uint8 *)&body->data_len);
206 /* create the iv/ptk key */
207 bcopy(body->iv, encrkey, 16);
208 bcopy(ekey, &encrkey[16], 16);
209 /* encrypt the key data */
210 prepare_key(encrkey, 32, rc4key);
211 rc4(data, WPA_KEY_DATA_LEN_256, rc4key); /* dump 256 bytes */
212 rc4(body->data, len, rc4key);
213 break;
214 case WPA_KEY_DESC_V2:
215 case WPA_KEY_DESC_V3:
216 len = ntoh16_ua((uint8 *)&body->data_len);
217 /* pad if needed - min. 16 bytes, 8 byte aligned */
218 /* padding is 0xdd followed by 0's */
219 if (len < 2*AKW_BLOCK_LEN) {
220 body->data[len] = WPA2_KEY_DATA_PAD;
221 bzero(&body->data[len+1], 2*AKW_BLOCK_LEN - (len+1));
222 len = 2*AKW_BLOCK_LEN;
223 } else if (len % AKW_BLOCK_LEN) {
224 body->data[len] = WPA2_KEY_DATA_PAD;
225 bzero(&body->data[len+1], AKW_BLOCK_LEN - ((len+1) % AKW_BLOCK_LEN));
226 len += AKW_BLOCK_LEN - (len % AKW_BLOCK_LEN);
228 if (aes_wrap(WPA_MIC_KEY_LEN, ekey, len, body->data, body->data)) {
229 return FALSE;
231 len += 8;
232 hton16_ua_store(len, (uint8 *)&body->data_len);
233 break;
234 default:
235 return FALSE;
238 return TRUE;
241 /* Decrypt a key data from a WPA key message */
242 bool
243 BCMROMFN(wpa_decr_key_data)(eapol_wpa_key_header_t *body, uint16 key_info, uint8 *ekey,
244 uint8 *gtk, uint8 *data, uint8 *encrkey, rc4_ks_t *rc4key)
246 uint16 len;
248 switch (key_info & (WPA_KEY_DESC_V1 | WPA_KEY_DESC_V2)) {
249 case WPA_KEY_DESC_V1:
250 bcopy(body->iv, encrkey, WPA_MIC_KEY_LEN);
251 bcopy(ekey, &encrkey[WPA_MIC_KEY_LEN], WPA_MIC_KEY_LEN);
252 /* decrypt the key data */
253 prepare_key(encrkey, WPA_MIC_KEY_LEN*2, rc4key);
254 rc4(data, WPA_KEY_DATA_LEN_256, rc4key); /* dump 256 bytes */
255 if (gtk)
256 len = ntoh16_ua((uint8 *)&body->key_len);
257 else
258 len = ntoh16_ua((uint8 *)&body->data_len);
259 rc4(body->data, len, rc4key);
260 if (gtk)
261 bcopy(body->data, gtk, len);
262 break;
264 case WPA_KEY_DESC_V2:
265 case WPA_KEY_DESC_V3:
266 len = ntoh16_ua((uint8 *)&body->data_len);
267 if (aes_unwrap(WPA_MIC_KEY_LEN, ekey, len, body->data,
268 gtk ? gtk : body->data)) {
269 return FALSE;
271 break;
273 default:
274 return FALSE;
276 return TRUE;
279 void
280 BCMROMFN(wpa_calc_ptk)(struct ether_addr *auth_ea, struct ether_addr *sta_ea,
281 uint8 *anonce, uint8* snonce, uint8 *pmk, uint pmk_len,
282 uint8 *ptk, uint ptk_len)
284 uchar data[128], prf_buff[PRF_OUTBUF_LEN];
285 const char prefix[] = "Pairwise key expansion";
286 uint data_len = 0;
288 /* Create the the data portion:
289 * the lesser of the EAs, followed by the greater of the EAs,
290 * followed by the lesser of the the nonces, followed by the
291 * greater of the nonces.
293 bcopy(wpa_array_cmp(MIN_ARRAY, (uint8 *)auth_ea, (uint8 *)sta_ea,
294 ETHER_ADDR_LEN),
295 (char *)&data[data_len], ETHER_ADDR_LEN);
296 data_len += ETHER_ADDR_LEN;
297 bcopy(wpa_array_cmp(MAX_ARRAY, (uint8 *)auth_ea, (uint8 *)sta_ea,
298 ETHER_ADDR_LEN),
299 (char *)&data[data_len], ETHER_ADDR_LEN);
300 data_len += ETHER_ADDR_LEN;
301 bcopy(wpa_array_cmp(MIN_ARRAY, snonce, anonce,
302 EAPOL_WPA_KEY_NONCE_LEN),
303 (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
304 data_len += EAPOL_WPA_KEY_NONCE_LEN;
305 bcopy(wpa_array_cmp(MAX_ARRAY, snonce, anonce,
306 EAPOL_WPA_KEY_NONCE_LEN),
307 (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
308 data_len += EAPOL_WPA_KEY_NONCE_LEN;
310 /* generate the PTK */
311 ASSERT(strlen(prefix) + data_len + 1 <= PRF_MAX_I_D_LEN);
312 fPRF(pmk, (int)pmk_len, (uchar *)prefix, strlen(prefix), data, data_len,
313 prf_buff, (int)ptk_len);
314 bcopy(prf_buff, (char*)ptk, ptk_len);
317 #if defined(MFP) || defined(WLFBT)
318 void
319 kdf_calc_ptk(struct ether_addr *auth_ea, struct ether_addr *sta_ea,
320 uint8 *anonce, uint8* snonce, uint8 *pmk, uint pmk_len,
321 uint8 *ptk, uint ptk_len)
323 uchar data[128], prf_buff[PRF_OUTBUF_LEN];
324 char prefix[] = "Pairwise key expansion";
325 uint data_len = 0;
327 /* Create the the data portion:
328 * the lesser of the EAs, followed by the greater of the EAs,
329 * followed by the lesser of the the nonces, followed by the
330 * greater of the nonces.
332 bcopy(wpa_array_cmp(MIN_ARRAY, (uint8 *)auth_ea, (uint8 *)sta_ea,
333 ETHER_ADDR_LEN),
334 (char *)&data[data_len], ETHER_ADDR_LEN);
335 data_len += ETHER_ADDR_LEN;
336 bcopy(wpa_array_cmp(MAX_ARRAY, (uint8 *)auth_ea, (uint8 *)sta_ea,
337 ETHER_ADDR_LEN),
338 (char *)&data[data_len], ETHER_ADDR_LEN);
339 data_len += ETHER_ADDR_LEN;
340 bcopy(wpa_array_cmp(MIN_ARRAY, snonce, anonce,
341 EAPOL_WPA_KEY_NONCE_LEN),
342 (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
343 data_len += EAPOL_WPA_KEY_NONCE_LEN;
344 bcopy(wpa_array_cmp(MAX_ARRAY, snonce, anonce,
345 EAPOL_WPA_KEY_NONCE_LEN),
346 (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN);
347 data_len += EAPOL_WPA_KEY_NONCE_LEN;
349 /* generate the PTK */
350 ASSERT(strlen(prefix) + data_len + 1 <= PRF_MAX_I_D_LEN);
351 KDF(pmk, (int)pmk_len, (uchar *)prefix, strlen(prefix), data, data_len,
352 prf_buff, (int)ptk_len);
353 bcopy(prf_buff, (char*)ptk, ptk_len);
355 #endif /* defined(MFP) || defined(WLFBT) */
356 /* Decrypt a group transient key from a WPA key message */
357 bool
358 BCMROMFN(wpa_decr_gtk)(eapol_wpa_key_header_t *body, uint16 key_info, uint8 *ekey,
359 uint8 *gtk, uint8 *data, uint8 *encrkey, rc4_ks_t *rc4key)
361 return wpa_decr_key_data(body, key_info, ekey, gtk, data, encrkey, rc4key);
364 /* Compute Message Integrity Code (MIC) over EAPOL message */
365 bool
366 BCMROMFN(wpa_make_mic)(eapol_header_t *eapol, uint key_desc, uint8 *mic_key, uchar *mic)
368 int mic_length;
370 /* length of eapol pkt from the version field on */
371 mic_length = 4 + ntoh16_ua((uint8 *)&eapol->length);
373 /* Create the MIC for the pkt */
374 switch (key_desc) {
375 case WPA_KEY_DESC_V1:
376 hmac_md5(&eapol->version, mic_length, mic_key,
377 EAPOL_WPA_KEY_MIC_LEN, mic);
378 break;
379 case WPA_KEY_DESC_V2:
380 hmac_sha1(&eapol->version, mic_length, mic_key,
381 EAPOL_WPA_KEY_MIC_LEN, mic);
382 break;
383 #if defined(MFP) || defined(WLFBT)
384 case WPA_KEY_DESC_V3:
385 aes_cmac_calc(&eapol->version, mic_length, mic_key,
386 EAPOL_WPA_KEY_MIC_LEN, mic);
387 break;
388 #endif
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((char*)&body->mic, mic, EAPOL_WPA_KEY_MIC_LEN);
405 bzero((char*)&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 /* Convert WPA/WPA2 IE cipher suite to locally used value */
415 static bool
416 rsn_cipher(wpa_suite_t *suite, ushort *cipher, const uint8 *std_oui, bool wep_ok)
418 bool ret = TRUE;
420 if (!bcmp((const char *)suite->oui, std_oui, DOT11_OUI_LEN)) {
421 switch (suite->type) {
422 case WPA_CIPHER_TKIP:
423 *cipher = CRYPTO_ALGO_TKIP;
424 break;
425 case WPA_CIPHER_AES_CCM:
426 *cipher = CRYPTO_ALGO_AES_CCM;
427 break;
428 case WPA_CIPHER_WEP_40:
429 if (wep_ok)
430 *cipher = CRYPTO_ALGO_WEP1;
431 else
432 ret = FALSE;
433 break;
434 case WPA_CIPHER_WEP_104:
435 if (wep_ok)
436 *cipher = CRYPTO_ALGO_WEP128;
437 else
438 ret = FALSE;
439 break;
440 default:
441 ret = FALSE;
442 break;
444 return ret;
447 /* check for other vendor OUIs */
448 return FALSE;
451 bool
452 BCMROMFN(wpa_cipher)(wpa_suite_t *suite, ushort *cipher, bool wep_ok)
454 return rsn_cipher(suite, cipher, (const uchar*)WPA_OUI, wep_ok);
457 bool
458 BCMROMFN(wpa2_cipher)(wpa_suite_t *suite, ushort *cipher, bool wep_ok)
460 return rsn_cipher(suite, cipher, (const uchar*)WPA2_OUI, wep_ok);
463 /* Is any of the tlvs the expected entry? If
464 * not update the tlvs buffer pointer/length.
466 bool
467 bcm_has_ie(uint8 *ie, uint8 **tlvs, uint *tlvs_len, const uint8 *oui, int oui_len, uint8 type)
469 /* If the contents match the OUI and the type */
470 if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
471 !bcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
472 type == ie[TLV_BODY_OFF + oui_len]) {
473 return TRUE;
476 /* point to the next ie */
477 ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
478 /* calculate the length of the rest of the buffer */
479 *tlvs_len -= (int)(ie - *tlvs);
480 /* update the pointer to the start of the buffer */
481 *tlvs = ie;
483 return FALSE;
486 wpa_ie_fixed_t *
487 BCMROMFN(bcm_find_wpaie)(uint8 *parse, uint len)
489 bcm_tlv_t *ie;
491 while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
492 if (bcm_is_wpa_ie((uint8 *)ie, &parse, &len)) {
493 return (wpa_ie_fixed_t *)ie;
496 return NULL;
499 wme_ie_t *
500 bcm_find_wmeie(uint8 *parse, uint len, uint8 subtype, uint8 subtype_len)
502 bcm_tlv_t *ie;
504 while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
505 if (bcm_is_wme_ie((uint8 *)ie, &parse, &len)) {
506 uint ie_len = TLV_HDR_LEN + ie->len;
507 if (ie_len >= TLV_HDR_LEN + WME_IE_LEN &&
508 ((wme_ie_t *)ie)->subtype == subtype &&
509 (uint8)ie_len == TLV_HDR_LEN + subtype_len)
510 return (wme_ie_t *)ie->data;
511 parse += ie_len;
512 len -= ie_len;
515 return NULL;
518 wps_ie_fixed_t *
519 bcm_find_wpsie(uint8 *parse, uint len)
521 bcm_tlv_t *ie;
523 while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
524 if (bcm_is_wps_ie((uint8 *)ie, &parse, &len)) {
525 return (wps_ie_fixed_t *)ie;
528 return NULL;
531 /* locate the Attribute in the WPS IE */
532 wps_at_fixed_t *
533 bcm_wps_find_at(wps_at_fixed_t *at, int len, uint16 id)
535 while (len >= WPS_AT_FIXED_LEN) {
536 int alen = WPS_AT_FIXED_LEN + ntoh16_ua(((wps_at_fixed_t *)at)->len);
537 if (ntoh16_ua(((wps_at_fixed_t *)at)->at) == id && alen <= len)
538 return at;
539 at = (wps_at_fixed_t *)((uint8 *)at + alen);
540 len -= alen;
542 return NULL;
545 #ifdef WLP2P
546 wifi_p2p_ie_t *
547 bcm_find_p2pie(uint8 *parse, uint len)
549 bcm_tlv_t *ie;
551 while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
552 if (bcm_is_p2p_ie((uint8 *)ie, &parse, &len)) {
553 return (wifi_p2p_ie_t *)ie;
556 return NULL;
558 #endif
560 #if defined(BCMSUP_PSK) || defined(BCMSUPPL) || defined(MFP) || defined(WLFBT)
561 #define wpa_is_kde(ie, tlvs, len, type) bcm_has_ie(ie, tlvs, len, \
562 (const uint8 *)WPA2_OUI, WPA2_OUI_LEN, type)
564 eapol_wpa2_encap_data_t *
565 BCMROMFN(wpa_find_kde)(uint8 *parse, uint len, uint8 type)
567 bcm_tlv_t *ie;
569 while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_PROPR_ID))) {
570 if (wpa_is_kde((uint8 *)ie, &parse, &len, type)) {
571 return (eapol_wpa2_encap_data_t *)ie;
574 return NULL;
577 bool
578 BCMROMFN(wpa_is_gtk_encap)(uint8 *ie, uint8 **tlvs, uint *tlvs_len)
580 return wpa_is_kde(ie, tlvs, tlvs_len, WPA2_KEY_DATA_SUBTYPE_GTK);
583 eapol_wpa2_encap_data_t *
584 BCMROMFN(wpa_find_gtk_encap)(uint8 *parse, uint len)
586 return wpa_find_kde(parse, len, WPA2_KEY_DATA_SUBTYPE_GTK);
588 #endif /* defined(BCMSUP_PSK) || defined(BCMSUPPL) || defined(MFP) || defined(WLFBT) */
590 #ifdef MFP
591 eapol_wpa2_encap_data_t *
592 BCMROMFN(wpa_find_igtk_encap)(uint8 *parse, uint len)
594 return wpa_find_kde(parse, len, WPA2_KEY_DATA_SUBTYPE_IGTK);
596 #endif
598 uint8 *
599 BCMROMFN(wpa_array_cmp)(int max_array, uint8 *x, uint8 *y, uint len)
601 uint i;
602 uint8 *ret = x;
604 for (i = 0; i < len; i++)
605 if (x[i] != y[i])
606 break;
608 if (i == len) {
609 return NULL;
611 if (max_array && (y[i] > x[i]))
612 ret = y;
613 if (!max_array && (y[i] < x[i]))
614 ret = y;
616 return (ret);
619 void
620 BCMROMFN(wpa_incr_array)(uint8 *array, uint len)
622 int i;
624 for (i = (len-1); i >= 0; i--)
625 if (array[i]++ != 0xff) {
626 break;
630 /* map akm suite to internal WPA_AUTH_XXXX */
631 /* akms points to 4 byte suite (oui + type) */
632 bool
633 BCMROMFN(bcmwpa_akm2WPAauth)(uint8 *akm, uint32 *auth, bool sta_iswpa)
635 if (!bcmp(akm, WPA2_OUI, DOT11_OUI_LEN)) {
636 switch (akm[DOT11_OUI_LEN]) {
637 case RSN_AKM_NONE:
638 *auth = WPA_AUTH_NONE;
639 break;
640 case RSN_AKM_UNSPECIFIED:
641 *auth = WPA2_AUTH_UNSPECIFIED;
642 break;
643 case RSN_AKM_PSK:
644 *auth = WPA2_AUTH_PSK;
645 break;
646 #ifdef WLFBT
647 case RSN_AKM_FBT_1X:
648 *auth = WPA2_AUTH_UNSPECIFIED;
649 break;
650 case RSN_AKM_FBT_PSK:
651 *auth = WPA2_AUTH_PSK;
652 break;
653 #endif
654 #ifdef MFP
655 case RSN_AKM_MFP_1X:
656 *auth = WPA2_AUTH_UNSPECIFIED;
657 break;
658 case RSN_AKM_MFP_PSK:
659 *auth = WPA2_AUTH_PSK;
660 break;
661 #endif /* MFP */
662 default:
663 return FALSE;
665 return TRUE;
667 else
668 if (!bcmp(akm, WPA_OUI, DOT11_OUI_LEN)) {
669 switch (akm[DOT11_OUI_LEN]) {
670 case RSN_AKM_NONE:
671 *auth = WPA_AUTH_NONE;
672 break;
673 case RSN_AKM_UNSPECIFIED:
674 *auth = WPA_AUTH_UNSPECIFIED;
675 break;
676 case RSN_AKM_PSK:
677 *auth = WPA_AUTH_PSK;
678 break;
679 default:
680 return FALSE;
682 return TRUE;
684 return FALSE;
687 /* map cipher suite to internal WSEC_XXXX */
688 /* cs points 4 byte cipher suite, and only the type is used for non CCX ciphers */
689 bool
690 BCMROMFN(bcmwpa_cipher2wsec)(uint8 *cipher, uint32 *wsec)
692 switch (cipher[DOT11_OUI_LEN]) {
693 case WPA_CIPHER_NONE:
694 *wsec = 0;
695 break;
696 case WPA_CIPHER_WEP_40:
697 case WPA_CIPHER_WEP_104:
698 *wsec = WEP_ENABLED;
699 break;
700 case WPA_CIPHER_TKIP:
701 *wsec = TKIP_ENABLED;
702 break;
703 case WPA_CIPHER_AES_CCM:
704 *wsec = AES_ENABLED;
705 break;
706 default:
707 return FALSE;
709 return TRUE;