2 * bcmwpa.c - shared WPA-related functions
4 * Copyright (C) 2010, 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,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 */
20 #elif defined(BCMEXTSUP)
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
);
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 */
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) */
47 #include <bcmcrypto/prf.h>
48 #include <bcmcrypto/rc4.h>
49 #if defined(MFP) || defined(WLFBT)
50 #include <bcmcrypto/hmac_sha256.h>
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";
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)
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";
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) */
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";
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);
130 sha256(data
, data_len
, digest
, 0);
131 bcopy(digest
, pmkr0name
, WPA2_PMKID_LEN
);
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";
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
);
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";
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
);
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
)
199 switch (key_info
& (WPA_KEY_DESC_V1
| WPA_KEY_DESC_V2
)) {
200 case WPA_KEY_DESC_V1
:
202 len
= ntoh16_ua((uint8
*)&body
->key_len
);
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
);
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
)) {
232 hton16_ua_store(len
, (uint8
*)&body
->data_len
);
241 /* Decrypt a key data from a WPA key message */
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
)
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 */
256 len
= ntoh16_ua((uint8
*)&body
->key_len
);
258 len
= ntoh16_ua((uint8
*)&body
->data_len
);
259 rc4(body
->data
, len
, rc4key
);
261 bcopy(body
->data
, gtk
, len
);
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
)) {
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";
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
,
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
,
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)
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";
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
,
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
,
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 */
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 */
366 BCMROMFN(wpa_make_mic
)(eapol_header_t
*eapol
, uint key_desc
, uint8
*mic_key
, uchar
*mic
)
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 */
375 case WPA_KEY_DESC_V1
:
376 hmac_md5(&eapol
->version
, mic_length
, mic_key
,
377 EAPOL_WPA_KEY_MIC_LEN
, mic
);
379 case WPA_KEY_DESC_V2
:
380 hmac_sha1(&eapol
->version
, mic_length
, mic_key
,
381 EAPOL_WPA_KEY_MIC_LEN
, mic
);
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
);
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((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
)) {
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 */
416 rsn_cipher(wpa_suite_t
*suite
, ushort
*cipher
, const uint8
*std_oui
, bool wep_ok
)
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
;
425 case WPA_CIPHER_AES_CCM
:
426 *cipher
= CRYPTO_ALGO_AES_CCM
;
428 case WPA_CIPHER_WEP_40
:
430 *cipher
= CRYPTO_ALGO_WEP1
;
434 case WPA_CIPHER_WEP_104
:
436 *cipher
= CRYPTO_ALGO_WEP128
;
447 /* check for other vendor OUIs */
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
);
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.
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
]) {
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 */
487 BCMROMFN(bcm_find_wpaie
)(uint8
*parse
, uint len
)
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
;
500 bcm_find_wmeie(uint8
*parse
, uint len
, uint8 subtype
, uint8 subtype_len
)
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
;
519 bcm_find_wpsie(uint8
*parse
, uint len
)
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
;
531 /* locate the Attribute in the WPS IE */
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
)
539 at
= (wps_at_fixed_t
*)((uint8
*)at
+ alen
);
547 bcm_find_p2pie(uint8
*parse
, uint len
)
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
;
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
)
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
;
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) */
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
);
599 BCMROMFN(wpa_array_cmp
)(int max_array
, uint8
*x
, uint8
*y
, uint len
)
604 for (i
= 0; i
< len
; i
++)
611 if (max_array
&& (y
[i
] > x
[i
]))
613 if (!max_array
&& (y
[i
] < x
[i
]))
620 BCMROMFN(wpa_incr_array
)(uint8
*array
, uint len
)
624 for (i
= (len
-1); i
>= 0; i
--)
625 if (array
[i
]++ != 0xff) {
630 /* map akm suite to internal WPA_AUTH_XXXX */
631 /* akms points to 4 byte suite (oui + type) */
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
]) {
638 *auth
= WPA_AUTH_NONE
;
640 case RSN_AKM_UNSPECIFIED
:
641 *auth
= WPA2_AUTH_UNSPECIFIED
;
644 *auth
= WPA2_AUTH_PSK
;
648 *auth
= WPA2_AUTH_UNSPECIFIED
;
650 case RSN_AKM_FBT_PSK
:
651 *auth
= WPA2_AUTH_PSK
;
656 *auth
= WPA2_AUTH_UNSPECIFIED
;
658 case RSN_AKM_MFP_PSK
:
659 *auth
= WPA2_AUTH_PSK
;
668 if (!bcmp(akm
, WPA_OUI
, DOT11_OUI_LEN
)) {
669 switch (akm
[DOT11_OUI_LEN
]) {
671 *auth
= WPA_AUTH_NONE
;
673 case RSN_AKM_UNSPECIFIED
:
674 *auth
= WPA_AUTH_UNSPECIFIED
;
677 *auth
= WPA_AUTH_PSK
;
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 */
690 BCMROMFN(bcmwpa_cipher2wsec
)(uint8
*cipher
, uint32
*wsec
)
692 switch (cipher
[DOT11_OUI_LEN
]) {
693 case WPA_CIPHER_NONE
:
696 case WPA_CIPHER_WEP_40
:
697 case WPA_CIPHER_WEP_104
:
700 case WPA_CIPHER_TKIP
:
701 *wsec
= TKIP_ENABLED
;
703 case WPA_CIPHER_AES_CCM
: