2 * bcmwpa.c - shared WPA-related functions
4 * Copyright (C) 2012, Broadcom Corporation
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 $
16 #include <bcmendian.h>
18 /* include wl driver config file if this file is compiled for driver */
21 #elif defined(BCMEXTSUP)
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
);
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 */
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) */
48 #include <bcmcrypto/prf.h>
49 #include <bcmcrypto/rc4.h>
51 #include <bcmcrypto/hmac_sha256.h>
53 #include <bcmcrypto/sha256.h>
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";
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
);
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";
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
);
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";
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);
132 sha256(data
, data_len
, digest
, 0);
133 bcopy(digest
, pmkr0name
, WPA2_PMKID_LEN
);
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";
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
);
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";
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
);
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
)
201 switch (key_info
& (WPA_KEY_DESC_V1
| WPA_KEY_DESC_V2
)) {
202 case WPA_KEY_DESC_V1
:
204 len
= ntoh16_ua((uint8
*)&body
->key_len
);
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
);
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
)) {
234 hton16_ua_store(len
, (uint8
*)&body
->data_len
);
243 /* Decrypt a key data from a WPA key message */
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
)
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 */
258 len
= ntoh16_ua((uint8
*)&body
->key_len
);
260 len
= ntoh16_ua((uint8
*)&body
->data_len
);
261 rc4(body
->data
, len
, rc4key
);
263 bcopy(body
->data
, gtk
, len
);
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
)) {
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";
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
,
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
,
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
);
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";
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
,
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
,
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
);
358 /* Decrypt a group transient key from a WPA key message */
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 */
368 BCMROMFN(wpa_make_mic
)(eapol_header_t
*eapol
, uint key_desc
, uint8
*mic_key
, uchar
*mic
)
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 */
377 case WPA_KEY_DESC_V1
:
378 hmac_md5(&eapol
->version
, mic_length
, mic_key
,
379 EAPOL_WPA_KEY_MIC_LEN
, mic
);
381 case WPA_KEY_DESC_V2
:
382 hmac_sha1(&eapol
->version
, mic_length
, mic_key
,
383 EAPOL_WPA_KEY_MIC_LEN
, mic
);
385 case WPA_KEY_DESC_V3
:
386 aes_cmac_calc(&eapol
->version
, mic_length
, mic_key
,
387 EAPOL_WPA_KEY_MIC_LEN
, mic
);
395 /* Check MIC of EAPOL message */
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
)) {
410 return !bcmp(digest
, mic
, EAPOL_WPA_KEY_MIC_LEN
);
412 #endif /* BCMSUP_PSK */
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";
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,
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
,
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
,
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
);
469 /* Convert WPA/WPA2 IE cipher suite to locally used value */
471 rsn_cipher(wpa_suite_t
*suite
, ushort
*cipher
, const uint8
*std_oui
, bool wep_ok
)
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
;
480 case WPA_CIPHER_AES_CCM
:
481 *cipher
= CRYPTO_ALGO_AES_CCM
;
483 case WPA_CIPHER_WEP_40
:
485 *cipher
= CRYPTO_ALGO_WEP1
;
489 case WPA_CIPHER_WEP_104
:
491 *cipher
= CRYPTO_ALGO_WEP128
;
502 /* check for other vendor OUIs */
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
);
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.
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
]) {
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 */
542 BCMROMFN(bcm_find_wpaie
)(uint8
*parse
, uint len
)
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
;
555 bcm_find_wmeie(uint8
*parse
, uint len
, uint8 subtype
, uint8 subtype_len
)
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
)
574 bcm_find_wpsie(uint8
*parse
, uint len
)
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
;
586 /* locate the Attribute in the WPS IE */
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
)
594 at
= (wps_at_fixed_t
*)((uint8
*)at
+ alen
);
602 bcm_find_p2pie(uint8
*parse
, uint len
)
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
;
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
)
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
;
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) */
646 BCMROMFN(wpa_array_cmp
)(int max_array
, uint8
*x
, uint8
*y
, uint len
)
651 for (i
= 0; i
< len
; i
++)
656 /* returning null will cause crash, return value used for bcopy */
657 /* return first param in this case to close security loophole */
660 if (max_array
&& (y
[i
] > x
[i
]))
662 if (!max_array
&& (y
[i
] < x
[i
]))
669 BCMROMFN(wpa_incr_array
)(uint8
*array
, uint len
)
673 for (i
= (len
-1); i
>= 0; i
--)
674 if (array
[i
]++ != 0xff) {
679 /* map akm suite to internal WPA_AUTH_XXXX */
680 /* akms points to 4 byte suite (oui + type) */
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
]) {
687 *auth
= WPA_AUTH_NONE
;
689 case RSN_AKM_UNSPECIFIED
:
690 *auth
= WPA2_AUTH_UNSPECIFIED
;
693 *auth
= WPA2_AUTH_PSK
;
696 *auth
= WPA2_AUTH_UNSPECIFIED
;
698 case RSN_AKM_FBT_PSK
:
699 *auth
= WPA2_AUTH_PSK
;
702 *auth
= WPA2_AUTH_UNSPECIFIED
;
704 case RSN_AKM_MFP_PSK
:
705 *auth
= WPA2_AUTH_PSK
;
714 if (!bcmp(akm
, WPA_OUI
, DOT11_OUI_LEN
)) {
715 switch (akm
[DOT11_OUI_LEN
]) {
717 *auth
= WPA_AUTH_NONE
;
719 case RSN_AKM_UNSPECIFIED
:
720 *auth
= WPA_AUTH_UNSPECIFIED
;
723 *auth
= WPA_AUTH_PSK
;
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 */
736 BCMROMFN(bcmwpa_cipher2wsec
)(uint8
*cipher
, uint32
*wsec
)
738 switch (cipher
[DOT11_OUI_LEN
]) {
739 case WPA_CIPHER_NONE
:
742 case WPA_CIPHER_WEP_40
:
743 case WPA_CIPHER_WEP_104
:
746 case WPA_CIPHER_TKIP
:
747 *wsec
= TKIP_ENABLED
;
749 case WPA_CIPHER_AES_CCM
: