1 /*
2 * bcmwpa.c - shared WPA-related functions
3 *
4 * Broadcom Proprietary and Confidential. Copyright (C) 2020,
5 * All Rights Reserved.
6 *
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
8 * the contents of this file may not be disclosed to third parties,
9 * copied or duplicated in any form, in whole or in part, without
10 * the prior written permission of Broadcom.
11 *
12 *
13 * <<Broadcom-WL-IPTag/Proprietary:>>
14 */
15
16 /* include wl driver config file if this file is compiled for driver */
17 #ifdef BCMDRIVER
18 #include <osl.h>
19 /* HACK: this case for external supplicant use */
20 #else
21 #include <string.h>
22 #if defined(BCMEXTSUP)
23 #include <bcm_osl.h>
24 #else
25 #ifndef ASSERT
26 #define ASSERT(exp)
27 #endif
28 #endif /* BCMEXTSUP */
29 #endif /* BCMDRIVER */
30
31 #include <ethernet.h>
32 #include <eapol.h>
33 #include <802.11.h>
34 #include <wpa.h>
35 #include <802.11r.h>
36
37 #include <bcmutils.h>
38 #include <bcmendian.h>
39 #include <bcmwpa.h>
40 #include <aeskeywrap.h>
41
42 #include <bcmstdlib_s.h>
43
44 #include <wlioctl.h>
45
46 #include <bcmutils.h>
47 #include <bcmwpa.h>
48 #ifdef WL_OCV
49 #include <bcm_ocv.h>
50 #endif /* WL_OCV */
51
52 #if defined(BCMSUP_PSK) || defined(WLFBT) || defined(BCMAUTH_PSK) || \
53 defined(WL_OKC) || defined(WLTDLS) || defined(GTKOE) || defined(WLHOSTFBT)
54 #ifdef WLHOSTFBT
55 #include <string.h>
56 #endif
57 #endif /* defined(BCMSUP_PSK) || defined(WLFBT) || defined(BCMAUTH_PSK) ||
58 * defined(WL_OKC) || defined(WLTDLS) || defined(GTKOE) || defined(WLHOSTFBT)
59 */
60
61 /* prefix strings */
62 #define PMK_NAME_PFX "PMK Name"
63 #define FT_PTK_PFX "FT-PTK"
64 #define FT_R0_PFX "FT-R0"
65 #define FT_R0N_PFX "FT-R0N"
66 #define FT_R1_PFX "FT-R1"
67 #define FT_R1N_PFX "FT-R1N"
68 #define WPA_PTK_PFX "Pairwise key expansion"
69 #define TDLS_PMK_PFX "TDLS PMK"
70 /* end prefix strings */
71
72 #ifndef BIT
73 #define BIT(x) (1 << (x))
74 #endif
75
76 #define PRF_PREFIXES_NUM 5u
77
78 typedef struct key_length_entry {
79 uint8 suite;
80 uint8 len;
81 } key_length_entry_t;
82
83 /* EAPOL key(PMK/KCK/KEK/TK) length lookup tables */
84 static const key_length_entry_t eapol_pmk_len[] = {
85 {RSN_AKM_SUITEB_SHA384_1X, EAPOL_WPA_PMK_SHA384_LEN},
86 {RSN_AKM_FBT_SHA384_1X, EAPOL_WPA_PMK_SHA384_LEN},
87 {RSN_AKM_FBT_SHA384_PSK, EAPOL_WPA_PMK_SHA384_LEN},
88 {0u, EAPOL_WPA_PMK_DEFAULT_LEN} /* default */
89 };
90
91 static const key_length_entry_t eapol_kck_mic_len[] = {
92 {RSN_AKM_SUITEB_SHA384_1X, EAPOL_WPA_KCK_MIC_SHA384_LEN},
93 {RSN_AKM_FILS_SHA256, 0u},
94 {RSN_AKM_FILS_SHA384, 0u},
95 {RSN_AKM_FBT_SHA256_FILS, EAPOL_WPA_KCK_MIC_DEFAULT_LEN},
96 {RSN_AKM_FBT_SHA384_FILS, EAPOL_WPA_KCK2_SHA384_LEN},
97 {RSN_AKM_OWE, EAPOL_WPA_KCK_MIC_DEFAULT_LEN},
98 {RSN_AKM_FBT_SHA384_1X, EAPOL_WPA_KCK_MIC_SHA384_LEN},
99 {RSN_AKM_FBT_SHA384_PSK, EAPOL_WPA_KCK_MIC_SHA384_LEN},
100 {0u, EAPOL_WPA_KCK_MIC_DEFAULT_LEN} /* default */
101 };
102
103 static const key_length_entry_t eapol_kck_len[] = {
104 {RSN_AKM_SUITEB_SHA384_1X, EAPOL_WPA_KCK_SHA384_LEN},
105 {RSN_AKM_FILS_SHA256, 0u},
106 {RSN_AKM_FILS_SHA384, 0u},
107 {RSN_AKM_FBT_SHA256_FILS, 0u},
108 {RSN_AKM_FBT_SHA384_FILS, 0u},
109 {RSN_AKM_OWE, EAPOL_WPA_KCK_DEFAULT_LEN},
110 {RSN_AKM_FBT_SHA384_1X, EAPOL_WPA_KCK_SHA384_LEN},
111 {RSN_AKM_FBT_SHA384_PSK, EAPOL_WPA_KCK_SHA384_LEN},
112 {0u, EAPOL_WPA_KCK_DEFAULT_LEN} /* default */
113 };
114
115 static const key_length_entry_t eapol_kek_len[] = {
116 {RSN_AKM_FILS_SHA384, EAPOL_WPA_ENCR_KEY_MAX_LEN},
117 {RSN_AKM_FBT_SHA384_FILS, EAPOL_WPA_ENCR_KEY_MAX_LEN},
118 {RSN_AKM_SUITEB_SHA384_1X, EAPOL_WPA_ENCR_KEY_MAX_LEN / 2},
119 {RSN_AKM_FILS_SHA256, EAPOL_WPA_ENCR_KEY_MAX_LEN / 2},
120 {RSN_AKM_FBT_SHA256_FILS, EAPOL_WPA_ENCR_KEY_MAX_LEN / 2},
121 {RSN_AKM_OWE, EAPOL_WPA_ENCR_KEY_DEFAULT_LEN},
122 {RSN_AKM_FBT_SHA384_1X, EAPOL_WPA_ENCR_KEY_MAX_LEN / 2},
123 {RSN_AKM_FBT_SHA384_PSK, EAPOL_WPA_ENCR_KEY_MAX_LEN / 2},
124 {0u, EAPOL_WPA_ENCR_KEY_DEFAULT_LEN} /* default */
125 };
126
127 static const key_length_entry_t eapol_tk_len[] = {
128 {WPA_CIPHER_CCMP_256, EAPOL_WPA_TEMP_ENCR_KEY_MAX_LEN},
129 {WPA_CIPHER_AES_GCM256, EAPOL_WPA_TEMP_ENCR_KEY_MAX_LEN},
130 {WPA_CIPHER_BIP_GMAC_256, EAPOL_WPA_TEMP_ENCR_KEY_MAX_LEN},
131 {WPA_CIPHER_BIP_CMAC_256, EAPOL_WPA_TEMP_ENCR_KEY_MAX_LEN},
132 {WPA_CIPHER_AES_CCM, EAPOL_WPA_TEMP_ENCR_KEY_MAX_LEN / 2},
133 {WPA_CIPHER_AES_GCM, EAPOL_WPA_TEMP_ENCR_KEY_MAX_LEN / 2},
134 {WPA_CIPHER_BIP_GMAC_128, EAPOL_WPA_TEMP_ENCR_KEY_MAX_LEN / 2},
135 {WPA_CIPHER_TKIP, EAPOL_WPA_TEMP_ENCR_KEY_MAX_LEN},
136 {0u, 0u} /* default */
137 };
138
139 #if defined(WL_FILS) && defined(WLFBT)
140 static const key_length_entry_t eapol_kck2_len[] = {
141 {RSN_AKM_FBT_SHA256_FILS, EAPOL_WPA_KCK2_SHA256_LEN},
142 {RSN_AKM_FBT_SHA384_FILS, EAPOL_WPA_KCK2_SHA384_LEN},
143 {0u, 0u} /* default */
144 };
145
146 static const key_length_entry_t eapol_kek2_len[] = {
147 {RSN_AKM_FBT_SHA256_FILS, EAPOL_WPA_KEK2_SHA256_LEN},
148 {RSN_AKM_FBT_SHA384_FILS, EAPOL_WPA_KEK2_SHA384_LEN},
149 {0u, 0u} /* default */
150 };
151 #endif /* WL_FILS && WLFBT */
152
153 typedef struct key_length_lookup {
154 const eapol_key_type_t key;
155 const key_length_entry_t *key_entry;
156 } key_length_lookup_t;
157
158 static const key_length_lookup_t eapol_key_lookup_tbl[] = {
159 {EAPOL_KEY_PMK, eapol_pmk_len},
160 {EAPOL_KEY_KCK_MIC, eapol_kck_mic_len},
161 {EAPOL_KEY_KCK, eapol_kck_len},
162 {EAPOL_KEY_KEK, eapol_kek_len},
163 {EAPOL_KEY_TK, eapol_tk_len},
164 #if defined(WL_FILS) && defined(WLFBT)
165 {EAPOL_KEY_KCK2, eapol_kck2_len},
166 {EAPOL_KEY_KEK2, eapol_kek2_len},
167 #endif /* WL_FILS && WLFBT */
168 };
169
170 typedef struct rsn_akm_lookup_entry {
171 const rsn_akm_t rsn_akm;
172 const sha2_hash_type_t hash_type;
173 } rsn_akm_lookup_entry_t;
174
175 static const rsn_akm_lookup_entry_t rsn_akm_lookup_tbl[] = {
176 {RSN_AKM_NONE, HASH_SHA1},
177 {RSN_AKM_UNSPECIFIED, HASH_SHA1},
178 {RSN_AKM_PSK, HASH_SHA1},
179 {RSN_AKM_FBT_1X, HASH_SHA256},
180 {RSN_AKM_FBT_PSK, HASH_SHA256},
181 {RSN_AKM_MFP_1X, HASH_SHA256},
182 {RSN_AKM_MFP_PSK, HASH_SHA256},
183 {RSN_AKM_SHA256_1X, HASH_SHA256},
184 {RSN_AKM_SHA256_PSK, HASH_SHA256},
185 {RSN_AKM_TPK, HASH_SHA256},
186 {RSN_AKM_SAE_PSK, HASH_SHA256},
187 {RSN_AKM_SAE_FBT, HASH_SHA256},
188 {RSN_AKM_SUITEB_SHA256_1X, HASH_SHA256},
189 {RSN_AKM_SUITEB_SHA384_1X, HASH_SHA384},
190 {RSN_AKM_FBT_SHA384_1X, HASH_SHA384},
191 {RSN_AKM_FILS_SHA256, HASH_SHA256},
192 {RSN_AKM_FILS_SHA384, HASH_SHA384},
193 {RSN_AKM_FBT_SHA256_FILS, HASH_SHA256},
194 {RSN_AKM_FBT_SHA384_FILS, HASH_SHA384},
195 {RSN_AKM_OWE, HASH_SHA256},
196 {RSN_AKM_FBT_SHA384_PSK, HASH_SHA384},
197 {RSN_AKM_PSK_SHA384, HASH_SHA384},
198 };
199
200 typedef struct rsn_akm_cipher_match_entry {
201 uint16 akm_type;
202 uint32 u_cast; /* BITMAP */
203 uint32 m_cast; /* BITMAP */
204 uint32 g_mgmt; /* BITMAP */
205 } rsn_akm_cipher_match_entry_t;
206
207 /* list only explicit cipher restriction for given AKM (e.g SuiteB)
208 * refer to 802.11 spec 9.4.2.24.3
209 * If not listed here, it means no restriction in using any ciphers.
210 */
211 static const rsn_akm_cipher_match_entry_t rsn_akm_cipher_match_table[] = {
212 {RSN_AKM_SUITEB_SHA256_1X,
213 BCM_BIT(WPA_CIPHER_AES_GCM),
214 BCM_BIT(WPA_CIPHER_AES_GCM),
215 BCM_BIT(WPA_CIPHER_BIP_GMAC_128)},
216 {RSN_AKM_SUITEB_SHA384_1X,
217 BCM_BIT(WPA_CIPHER_AES_GCM256) | BCM_BIT(WPA_CIPHER_CCMP_256),
218 BCM_BIT(WPA_CIPHER_AES_GCM256) | BCM_BIT(WPA_CIPHER_AES_GCM256),
219 BCM_BIT(WPA_CIPHER_BIP_GMAC_256) | BCM_BIT(WPA_CIPHER_BIP_CMAC_256)},
220 {RSN_AKM_FBT_SHA384_1X,
221 BCM_BIT(WPA_CIPHER_AES_GCM256) | BCM_BIT(WPA_CIPHER_CCMP_256),
222 BCM_BIT(WPA_CIPHER_AES_GCM256) | BCM_BIT(WPA_CIPHER_AES_GCM256),
223 BCM_BIT(WPA_CIPHER_BIP_GMAC_256) | BCM_BIT(WPA_CIPHER_BIP_CMAC_256)}
224 };
225
226 #if defined(WL_BAND6G)
227 static const rsn_akm_mask_t rsn_akm_6g_inval_mask =
228 BCM_BIT(RSN_AKM_PSK) |
229 BCM_BIT(RSN_AKM_FBT_PSK) |
230 BCM_BIT(RSN_AKM_SHA256_PSK) |
231 BCM_BIT(RSN_AKM_FBT_SHA384_PSK) |
232 BCM_BIT(RSN_AKM_PSK_SHA384);
233
234 static const rsn_ciphers_t cipher_6g_inval_mask =
235 BCM_BIT(WPA_CIPHER_NONE) |
236 BCM_BIT(WPA_CIPHER_WEP_40) |
237 BCM_BIT(WPA_CIPHER_TKIP) |
238 BCM_BIT(WPA_CIPHER_WEP_104);
239 #endif /* WL_BAND6G */
240
241 #if defined(BCMSUP_PSK) || defined(BCMSUPPL)
242 typedef struct group_cipher_algo_entry {
243 rsn_cipher_t g_mgmt_cipher;
244 uint8 bip_algo;
245 } group_cipher_algo_entry_t;
246
247 static const group_cipher_algo_entry_t group_mgmt_cipher_algo[] = {
248 {WPA_CIPHER_BIP_GMAC_256, CRYPTO_ALGO_BIP_GMAC256},
249 {WPA_CIPHER_BIP_CMAC_256, CRYPTO_ALGO_BIP_CMAC256},
250 {WPA_CIPHER_BIP_GMAC_128, CRYPTO_ALGO_BIP_GMAC},
251 {WPA_CIPHER_BIP, CRYPTO_ALGO_BIP},
252 };
253 #endif /* defined(BCMSUP_PSK) || defined(BCMSUPPL) */
254
255 static uint16 wlc_calc_rsn_desc_version(const rsn_ie_info_t *rsn_info);
256 static int bcmwpa_is_valid_akm(const rsn_akm_t akm);
257 #if defined(BCMSUP_PSK) || defined(BCMAUTH_PSK) || defined(WLFBT) || defined(GTKOE)
258 static sha2_hash_type_t bcmwpa_rsn_akm_to_hash(const rsn_akm_t akm);
259 #ifdef RSN_IE_INFO_STRUCT_RELOCATED
260 static int bcmwpa_decode_cipher_suite(rsn_ie_info_t *info, const uint8 **ptr, uint ie_len, uint
261 *remain_len, uint16 *p_count);
262 #endif
263 #endif /* defined(BCMSUP_PSK) || defined(BCMAUTH_PSK) || defined(WLFBT) || defined(GTKOE) */
264 #if defined(BCMSUP_PSK) || defined(WLFBT) || defined(WL_OKC) || defined(WLHOSTFBT)
265 #include <rc4.h>
266
267 /* calculate wpa PMKID: HMAC-SHA1-128(PMK, "PMK Name" | AA | SPA) */
268 static void
wpa_calc_pmkid_impl(sha2_hash_type_t hash_type,const struct ether_addr * auth_ea,const struct ether_addr * sta_ea,const uint8 * pmk,uint pmk_len,uint8 * pmkid)269 wpa_calc_pmkid_impl(sha2_hash_type_t hash_type,
270 const struct ether_addr *auth_ea, const struct ether_addr *sta_ea,
271 const uint8 *pmk, uint pmk_len, uint8 *pmkid)
272 {
273 int err;
274 hmac_sha2_ctx_t ctx;
275
276 err = hmac_sha2_init(&ctx, hash_type, pmk, pmk_len);
277 if (err != BCME_OK)
278 goto done;
279 hmac_sha2_update(&ctx, (const uint8 *)PMK_NAME_PFX, sizeof(PMK_NAME_PFX) - 1);
280 hmac_sha2_update(&ctx, (const uint8 *)auth_ea, ETHER_ADDR_LEN);
281 hmac_sha2_update(&ctx, (const uint8 *)sta_ea, ETHER_ADDR_LEN);
282 hmac_sha2_final(&ctx, pmkid, WPA2_PMKID_LEN);
283 done:;
284 }
285
286 void
wpa_calc_pmkid(const struct ether_addr * auth_ea,const struct ether_addr * sta_ea,const uint8 * pmk,uint pmk_len,uint8 * pmkid)287 wpa_calc_pmkid(const struct ether_addr *auth_ea, const struct ether_addr *sta_ea,
288 const uint8 *pmk, uint pmk_len, uint8 *pmkid)
289 {
290 wpa_calc_pmkid_impl(HASH_SHA1, auth_ea, sta_ea, pmk, pmk_len, pmkid);
291 }
292
293 void
kdf_calc_pmkid(const struct ether_addr * auth_ea,const struct ether_addr * sta_ea,const uint8 * key,uint key_len,uint8 * pmkid,rsn_ie_info_t * rsn_info)294 kdf_calc_pmkid(const struct ether_addr *auth_ea, const struct ether_addr *sta_ea,
295 const uint8 *key, uint key_len, uint8 *pmkid, rsn_ie_info_t *rsn_info)
296 {
297 sha2_hash_type_t hash_type;
298
299 if (rsn_info->sta_akm == RSN_AKM_SUITEB_SHA384_1X) {
300 hash_type = HASH_SHA384;
301 } else {
302 hash_type = HASH_SHA256;
303 }
304
305 wpa_calc_pmkid_impl(hash_type, auth_ea, sta_ea, key, key_len, pmkid);
306 }
307
308 #if defined(WLFBT) || defined(WLHOSTFBT)
309 void
wpa_calc_pmkR0(sha2_hash_type_t hash_type,const uint8 * ssid,uint ssid_len,uint16 mdid,const uint8 * r0kh,uint r0kh_len,const struct ether_addr * sta_ea,const uint8 * pmk,uint pmk_len,uint8 * pmkr0,uint8 * pmkr0name)310 wpa_calc_pmkR0(sha2_hash_type_t hash_type, const uint8 *ssid, uint ssid_len,
311 uint16 mdid, const uint8 *r0kh, uint r0kh_len, const struct ether_addr *sta_ea,
312 const uint8 *pmk, uint pmk_len, uint8 *pmkr0, uint8 *pmkr0name)
313 {
314 uint8 out[FBT_R0KH_ID_LEN + WPA2_PMKID_LEN - 1];
315 int out_len = FBT_R0KH_ID_LEN - 1;
316 bcm_const_xlvp_t pfx[7];
317 bcm_const_xlvp_t pfx2[2];
318 int npfx = 0;
319 int npfx2 = 0;
320 uint8 mdid_le[2];
321 uint8 pfx_ssid_len;
322 uint8 pfx_r0kh_len;
323
324 if (hash_type == HASH_SHA384) {
325 out_len += WPA2_PMKID_LEN;
326 }
327
328 /* create prefixes for pmkr0 */
329 pfx[npfx].len = sizeof(FT_R0_PFX) - 1;
330 pfx[npfx++].data = (uint8 *)FT_R0_PFX;
331
332 /* ssid length and ssid */
333 pfx_ssid_len = ssid_len & 0xff;
334 pfx[npfx].len = (uint16)sizeof(pfx_ssid_len);
335 pfx[npfx++].data = &pfx_ssid_len;
336
337 pfx[npfx].len = (uint16)(ssid_len & 0xffff);
338 pfx[npfx++].data = ssid;
339
340 /* mdid */
341 htol16_ua_store(mdid, mdid_le);
342 pfx[npfx].len = sizeof(mdid_le);
343 pfx[npfx++].data = mdid_le;
344
345 /* r0kh len and r0kh */
346 pfx_r0kh_len = r0kh_len & 0xff;
347 pfx[npfx].len = sizeof(pfx_r0kh_len);
348 pfx[npfx++].data = &pfx_r0kh_len;
349
350 pfx[npfx].len = (uint16)(r0kh_len & 0xffff);
351 pfx[npfx++].data = r0kh;
352
353 /* sta addr */
354 pfx[npfx].len = ETHER_ADDR_LEN;
355 pfx[npfx++].data = (const uint8 *)sta_ea;
356
357 hmac_sha2_n(hash_type, pmk, pmk_len, pfx, npfx, NULL, 0, out, out_len);
358 (void)memcpy_s(pmkr0, pmk_len, out, pmk_len);
359
360 /* coverity checks overflow if pfx size changes */
361
362 /* create prefixes for pmkr0 name */
363 pfx2[npfx2].len = sizeof(FT_R0N_PFX) - 1;
364 pfx2[npfx2++].data = (uint8 *)FT_R0N_PFX;
365 pfx2[npfx2].len = WPA2_PMKID_LEN;
366 pfx2[npfx2++].data = &out[pmk_len];
367
368 (void)sha2(hash_type, pfx2, npfx2, NULL, 0, pmkr0name, WPA2_PMKID_LEN);
369 }
370
371 void
wpa_calc_pmkR1(sha2_hash_type_t hash_type,const struct ether_addr * r1kh,const struct ether_addr * sta_ea,const uint8 * pmk,uint pmk_len,const uint8 * pmkr0name,uint8 * pmkr1,uint8 * pmkr1name)372 wpa_calc_pmkR1(sha2_hash_type_t hash_type, const struct ether_addr *r1kh,
373 const struct ether_addr *sta_ea, const uint8 *pmk, uint pmk_len, const uint8 *pmkr0name,
374 uint8 *pmkr1, uint8 *pmkr1name)
375 {
376 bcm_const_xlvp_t pfx[3];
377 bcm_const_xlvp_t pfx2[4];
378 int npfx = 0;
379 int npfx2 = 0;
380
381 if (!pmkr1 && !pmkr1name)
382 goto done;
383 else if (!pmkr1)
384 goto calc_r1name;
385
386 /* create prefixes for pmkr1 */
387 pfx[npfx].len = sizeof(FT_R1_PFX) - 1;
388 pfx[npfx++].data = (uint8 *)FT_R1_PFX;
389
390 pfx[npfx].len = ETHER_ADDR_LEN;
391 pfx[npfx++].data = (const uint8 *)r1kh;
392
393 pfx[npfx].len = ETHER_ADDR_LEN;
394 pfx[npfx++].data = (const uint8 *)sta_ea;
395
396 hmac_sha2_n(hash_type, pmk, pmk_len, pfx, npfx, NULL, 0,
397 pmkr1, sha2_digest_len(hash_type));
398
399 calc_r1name:
400 /* create prefixes for pmkr1 name */
401 pfx2[npfx2].len = sizeof(FT_R1N_PFX) - 1;
402 pfx2[npfx2++].data = (uint8 *)FT_R1N_PFX;
403
404 pfx2[npfx2].len = WPA2_PMKID_LEN;
405 pfx2[npfx2++].data = pmkr0name;
406
407 pfx2[npfx2].len = ETHER_ADDR_LEN;
408 pfx2[npfx2++].data = (const uint8 *)r1kh;
409
410 pfx2[npfx2].len = ETHER_ADDR_LEN;
411 pfx2[npfx2++].data = (const uint8 *)sta_ea;
412
413 sha2(hash_type, pfx2, npfx2, NULL, 0, pmkr1name, WPA2_PMKID_LEN);
414 done:;
415 }
416
417 void
wpa_calc_ft_ptk(sha2_hash_type_t hash_type,const struct ether_addr * bssid,const struct ether_addr * sta_ea,const uint8 * anonce,const uint8 * snonce,const uint8 * pmk,uint pmk_len,uint8 * ptk,uint ptk_len)418 wpa_calc_ft_ptk(sha2_hash_type_t hash_type,
419 const struct ether_addr *bssid, const struct ether_addr *sta_ea,
420 const uint8 *anonce, const uint8* snonce,
421 const uint8 *pmk, uint pmk_len, uint8 *ptk, uint ptk_len)
422 {
423 bcm_const_xlvp_t pfx[5];
424 int npfx = 0;
425
426 /* FT-PTK||SNONCE||ANONCE||BSSID||STA Addr */
427
428 pfx[npfx].len = sizeof(FT_PTK_PFX) - 1;
429 pfx[npfx++].data = (uint8 *)FT_PTK_PFX;
430
431 pfx[npfx].len = EAPOL_WPA_KEY_NONCE_LEN;
432 pfx[npfx++].data = snonce;
433
434 pfx[npfx].len = EAPOL_WPA_KEY_NONCE_LEN;
435 pfx[npfx++].data = anonce;
436
437 pfx[npfx].len = ETHER_ADDR_LEN;
438 pfx[npfx++].data = (const uint8 *)bssid;
439
440 pfx[npfx].len = ETHER_ADDR_LEN;
441 pfx[npfx++].data = (const uint8 *)sta_ea;
442
443 hmac_sha2_n(hash_type, pmk, pmk_len, pfx, npfx, NULL, 0, ptk, ptk_len);
444 }
445
446 void
wpa_derive_pmkR1_name(sha2_hash_type_t hash_type,struct ether_addr * r1kh,struct ether_addr * sta_ea,uint8 * pmkr0name,uint8 * pmkr1name)447 wpa_derive_pmkR1_name(sha2_hash_type_t hash_type,
448 struct ether_addr *r1kh, struct ether_addr *sta_ea,
449 uint8 *pmkr0name, uint8 *pmkr1name)
450 {
451 wpa_calc_pmkR1(hash_type, r1kh, sta_ea, NULL /* pmk */, 0,
452 pmkr0name, NULL /* pmkr1 */, pmkr1name);
453 }
454 #endif /* WLFBT || WLHOSTFBT */
455 #endif /* BCMSUP_PSK || WLFBT || WL_OKC */
456
457 #if defined(BCMSUP_PSK) || defined(GTKOE) || defined(BCMAUTH_PSK) || defined(WLFBT)
458 /* Decrypt a key data from a WPA key message */
459 int
wpa_decr_key_data(eapol_wpa_key_header_t * body,uint16 key_info,uint8 * ekey,uint8 * encrkey,rc4_ks_t * rc4key,const rsn_ie_info_t * rsn_info,uint16 * dec_len)460 wpa_decr_key_data(eapol_wpa_key_header_t *body, uint16 key_info, uint8 *ekey,
461 uint8 *encrkey, rc4_ks_t *rc4key, const rsn_ie_info_t *rsn_info, uint16 *dec_len)
462 {
463 uint16 len;
464 int err = BCME_OK;
465 uint8 *key_data;
466
467 switch (key_info & (WPA_KEY_DESC_V1 | WPA_KEY_DESC_V2)) {
468 case WPA_KEY_DESC_V1:
469 err = memcpy_s(encrkey, EAPOL_WPA_KEY_IV_LEN + EAPOL_WPA_ENCR_KEY_MAX_LEN,
470 body->iv, EAPOL_WPA_KEY_IV_LEN);
471 if (err) {
472 ASSERT(0);
473 return err;
474 }
475 err = memcpy_s(&encrkey[EAPOL_WPA_KEY_IV_LEN], EAPOL_WPA_ENCR_KEY_MAX_LEN,
476 ekey, rsn_info->kek_len);
477 if (err) {
478 ASSERT(0);
479 return err;
480 }
481 /* decrypt the key data */
482 prepare_key(encrkey, EAPOL_WPA_KEY_IV_LEN + rsn_info->kek_len, rc4key);
483 rc4(NULL, WPA_KEY_DATA_LEN_256, rc4key); /* dump 256 bytes */
484 len = ntoh16_ua(EAPOL_WPA_KEY_HDR_DATA_LEN_PTR(body, rsn_info->kck_mic_len));
485 key_data = EAPOL_WPA_KEY_HDR_DATA_PTR(body, rsn_info->kck_mic_len);
486 rc4(key_data, len, rc4key);
487 break;
488
489 case WPA_KEY_DESC_V2:
490 case WPA_KEY_DESC_V3:
491 case WPA_KEY_DESC_V0:
492 /* fallthrough */
493 len = ntoh16_ua(EAPOL_WPA_KEY_HDR_DATA_LEN_PTR(body, rsn_info->kck_mic_len));
494 if (!len) {
495 *dec_len = 0;
496 break; /* ignore zero length */
497 }
498 key_data = EAPOL_WPA_KEY_HDR_DATA_PTR(body, rsn_info->kck_mic_len);
499 if (aes_unwrap(rsn_info->kek_len, ekey, len, key_data, key_data)) {
500 *dec_len = 0;
501 err = BCME_DECERR;
502 break;
503 }
504 *dec_len = (len > AKW_BLOCK_LEN) ? (len - AKW_BLOCK_LEN) : 0;
505 break;
506
507 default:
508 *dec_len = 0;
509 err = BCME_UNSUPPORTED; /* may need revisiting - see 802.11-2016 */
510 break;
511 }
512
513 return err;
514 }
515
516 /* internal function - assumes enouch space allocated, retuns written number */
517 static int
wpa_calc_ptk_prefixes(const uint8 * prefix,uint prefix_len,const struct ether_addr * auth_ea,const struct ether_addr * sta_ea,const uint8 * anonce,uint8 anonce_len,const uint8 * snonce,uint8 snonce_len,bcm_const_xlvp_t * pfx)518 wpa_calc_ptk_prefixes(const uint8 *prefix, uint prefix_len,
519 const struct ether_addr *auth_ea, const struct ether_addr *sta_ea,
520 const uint8 *anonce, uint8 anonce_len, const uint8 *snonce, uint8 snonce_len,
521 bcm_const_xlvp_t *pfx)
522 {
523 int npfx = 0;
524 const uint8 *nonce;
525
526 /* prefix || min ea || max ea || min nonce || max nonce */
527 pfx[npfx].len = (uint16)(prefix_len & 0xffff);
528 pfx[npfx++].data = prefix;
529
530 pfx[npfx].len = ETHER_ADDR_LEN;
531 pfx[npfx++].data = (const uint8 *) wpa_array_cmp(MIN_ARRAY,
532 (const uint8 *)auth_ea, (const uint8 *)sta_ea, ETHER_ADDR_LEN);
533
534 pfx[npfx].len = ETHER_ADDR_LEN;
535 pfx[npfx++].data = (const uint8 *) wpa_array_cmp(MAX_ARRAY,
536 (const uint8 *)auth_ea, (const uint8 *)sta_ea, ETHER_ADDR_LEN);
537
538 nonce = (const uint8 *)wpa_array_cmp(MIN_ARRAY, snonce, anonce, snonce_len);
539
540 if (nonce == snonce) {
541 pfx[npfx].len = snonce_len;
542 pfx[npfx++].data = snonce;
543 pfx[npfx].len = anonce_len;
544 pfx[npfx++].data = anonce;
545 } else {
546 pfx[npfx].len = anonce_len;
547 pfx[npfx++].data = anonce;
548 pfx[npfx].len = snonce_len;
549 pfx[npfx++].data = snonce;
550 }
551
552 return npfx;
553 }
554
555 void
kdf_calc_ptk(const struct ether_addr * auth_ea,const struct ether_addr * sta_ea,const uint8 * anonce,const uint8 * snonce,const uint8 * pmk,uint pmk_len,uint8 * ptk,uint ptk_len)556 kdf_calc_ptk(const struct ether_addr *auth_ea, const struct ether_addr *sta_ea,
557 const uint8 *anonce, const uint8* snonce,
558 const uint8 *pmk, uint pmk_len, uint8 *ptk, uint ptk_len)
559 {
560 bcm_const_xlvp_t pfx[5];
561 int npfx;
562
563 /* note: kdf omits trailing NULL in prefix */
564 npfx = wpa_calc_ptk_prefixes((uint8 *)WPA_PTK_PFX, sizeof(WPA_PTK_PFX) - 1,
565 auth_ea, sta_ea, anonce, EAPOL_WPA_KEY_NONCE_LEN, snonce,
566 EAPOL_WPA_KEY_NONCE_LEN, pfx);
567 hmac_sha2_n(HASH_SHA256, pmk, pmk_len, pfx, npfx, NULL, 0, ptk, ptk_len);
568 }
569 #endif /* BCMSUP_PSK || GTKOE || BCMAUTH_PSK || WLFBT */
570
571 #if defined(BCMSUP_PSK) || defined(BCMAUTH_PSK) || defined(WLFBT) || defined(GTKOE)
572 /* Compute Message Integrity Code (MIC) over EAPOL message */
573 int
wpa_make_mic(eapol_header_t * eapol,uint key_desc,uint8 * mic_key,rsn_ie_info_t * rsn_info,uchar * mic,uint mic_len)574 wpa_make_mic(eapol_header_t *eapol, uint key_desc, uint8 *mic_key,
575 rsn_ie_info_t *rsn_info, uchar *mic, uint mic_len)
576 {
577 uint data_len;
578 int err = BCME_OK;
579 sha2_hash_type_t type = HASH_NONE;
580
581 /* length of eapol pkt from the version field on */
582 data_len = 4 + ntoh16_ua((uint8 *)&eapol->length);
583
584 /* Create the MIC for the pkt */
585 switch (key_desc) {
586 case WPA_KEY_DESC_V1:
587 type = HASH_MD5;
588 break;
589 case WPA_KEY_DESC_V2:
590 /* note: transparent truncation to mic_len */
591 type = HASH_SHA1;
592 break;
593 case WPA_KEY_DESC_V3:
594 aes_cmac_calc(NULL, 0, &eapol->version, data_len, mic_key,
595 mic_len, mic, AES_BLOCK_SZ);
596 goto exit;
597 case WPA_KEY_DESC_V0:
598 ASSERT(rsn_info != NULL);
599 if (rsn_info == NULL) {
600 return BCME_BADARG;
601 }
602 if (IS_SAE_AKM(rsn_info->sta_akm)) {
603 aes_cmac_calc(NULL, 0, &eapol->version, data_len, mic_key,
604 mic_len, mic, AES_BLOCK_SZ);
605 goto exit;
606 }
607 type = bcmwpa_rsn_akm_to_hash(rsn_info->sta_akm);
608 break;
609 default:
610 /* 11mc D8.0 some AKMs use descriptor version 0 */
611 err = BCME_UNSUPPORTED;
612 goto exit;
613 }
614
615 if (type) {
616 err = hmac_sha2(type, mic_key, mic_len, NULL, 0, (uint8 *)&eapol->version, data_len,
617 mic, mic_len);
618 }
619 exit:
620 return err;
621 }
622
623 int
wpa_calc_ptk(rsn_akm_t akm,const struct ether_addr * auth_ea,const struct ether_addr * sta_ea,const uint8 * anonce,uint8 anon_len,const uint8 * snonce,uint8 snon_len,const uint8 * pmk,uint pmk_len,uint8 * ptk,uint ptk_len)624 wpa_calc_ptk(rsn_akm_t akm, const struct ether_addr *auth_ea, const struct ether_addr *sta_ea,
625 const uint8 *anonce, uint8 anon_len, const uint8 *snonce, uint8 snon_len, const uint8 *pmk,
626 uint pmk_len, uint8 *ptk, uint ptk_len)
627 {
628 bcm_const_xlvp_t pfx[PRF_PREFIXES_NUM];
629 int npfx;
630 int ret = BCME_OK;
631 sha2_hash_type_t hash_type;
632 uint label_len;
633
634 if (RSN_AKM_USE_KDF(akm)) {
635 label_len = sizeof(WPA_PTK_PFX) - 1u;
636 } else { //WPA AKMS
637 label_len = sizeof(WPA_PTK_PFX); /* note: wpa needs trailing NULL in prefix */
638 }
639
640 hash_type = bcmwpa_rsn_akm_to_hash(akm);
641
642 npfx = wpa_calc_ptk_prefixes((uint8 *)WPA_PTK_PFX, label_len,
643 auth_ea, sta_ea, anonce, anon_len, snonce, snon_len, pfx);
644 ret = hmac_sha2_n(hash_type, pmk, pmk_len, pfx, npfx, NULL, 0, ptk, ptk_len);
645 return ret;
646 }
647
648 bool
wpa_encr_key_data(eapol_wpa_key_header_t * body,uint16 key_info,uint8 * ekey,uint8 * gtk,uint8 * data,uint8 * encrkey,rc4_ks_t * rc4key,const rsn_ie_info_t * rsn_info)649 wpa_encr_key_data(eapol_wpa_key_header_t *body, uint16 key_info, uint8 *ekey,
650 uint8 *gtk, uint8 *data, uint8 *encrkey, rc4_ks_t *rc4key, const rsn_ie_info_t *rsn_info)
651 {
652 uint16 len;
653 uint8 *key_data;
654
655 switch (key_info & (WPA_KEY_DESC_V1 | WPA_KEY_DESC_V2)) {
656 case WPA_KEY_DESC_V1:
657 if (gtk) {
658 len = ntoh16_ua((uint8 *)&body->key_len);
659 } else {
660 len = ntoh16_ua(EAPOL_WPA_KEY_HDR_DATA_LEN_PTR(body,
661 rsn_info->kck_mic_len));
662 }
663
664 /* create the iv/ptk key */
665 if (memcpy_s(encrkey, EAPOL_WPA_KEY_IV_LEN, body->iv, sizeof(body->iv))) {
666 return FALSE;
667 }
668 if (memcpy_s(&encrkey[EAPOL_WPA_KEY_IV_LEN], EAPOL_WPA_ENCR_KEY_DEFAULT_LEN,
669 ekey, EAPOL_WPA_ENCR_KEY_DEFAULT_LEN)) {
670 return FALSE;
671 }
672 /* encrypt the key data */
673 prepare_key(encrkey, EAPOL_WPA_KEY_IV_LEN + EAPOL_WPA_ENCR_KEY_DEFAULT_LEN,
674 rc4key);
675 rc4(data, WPA_KEY_DATA_LEN_256, rc4key); /* dump 256 bytes */
676 key_data = EAPOL_WPA_KEY_HDR_DATA_PTR(body, rsn_info->kck_mic_len);
677 rc4(key_data, len, rc4key);
678 break;
679 case WPA_KEY_DESC_V2: /* fall through */
680 case WPA_KEY_DESC_V3:
681 case WPA_KEY_DESC_V0:
682 len = ntoh16_ua(EAPOL_WPA_KEY_HDR_DATA_LEN_PTR(body,
683 rsn_info->kck_mic_len));
684 /* FIXME: data_len is length to encrypt, but need to make sure
685 * buffer is big enought
686 * for expansion. how? problem for caller?
687 */
688 key_data = EAPOL_WPA_KEY_HDR_DATA_PTR(body, rsn_info->kck_mic_len);
689 /* pad if needed - min. 16 bytes, 8 byte aligned */
690 /* padding is 0xdd followed by 0's */
691 if (len < 2u *AKW_BLOCK_LEN) {
692 key_data[len] = WPA2_KEY_DATA_PAD;
693 bzero(&key_data[len + 1u], 2u * AKW_BLOCK_LEN - (len + 1u));
694 len = 2u *AKW_BLOCK_LEN;
695 } else if (len % AKW_BLOCK_LEN) {
696 key_data[len] = WPA2_KEY_DATA_PAD;
697 bzero(&key_data[len + 1u],
698 AKW_BLOCK_LEN - ((len + 1u) % AKW_BLOCK_LEN));
699 len += AKW_BLOCK_LEN - (len % AKW_BLOCK_LEN);
700 }
701 if (aes_wrap(rsn_info->kek_len, ekey, len, key_data, key_data)) {
702 return FALSE;
703 }
704 len += AKW_BLOCK_LEN;
705 hton16_ua_store(len,
706 (uint8 *)EAPOL_WPA_KEY_HDR_DATA_LEN_PTR(body,
707 rsn_info->kck_mic_len));
708 break;
709 default:
710 /* 11mc D8.0 key descriptor version 0 used */
711 return FALSE;
712 }
713
714 return TRUE;
715 }
716
717 /* Check MIC of EAPOL message */
718 bool
wpa_check_mic(eapol_header_t * eapol,uint key_desc,uint8 * mic_key,rsn_ie_info_t * rsn_info)719 wpa_check_mic(eapol_header_t *eapol, uint key_desc, uint8 *mic_key, rsn_ie_info_t *rsn_info)
720 {
721 eapol_wpa_key_header_t *body = NULL;
722 uchar digest[SHA2_MAX_DIGEST_LEN];
723 uchar mic[EAPOL_WPA_KEY_MAX_MIC_LEN];
724
725 if (!mic_key || !rsn_info || !eapol) {
726 return FALSE;
727 }
728
729 body = (eapol_wpa_key_header_t *)eapol->body;
730
731 #ifndef EAPOL_KEY_HDR_VER_V2
732 if (rsn_info->kck_mic_len != EAPOL_WPA_KCK_DEFAULT_LEN)
733 #else
734 if (rsn_info->kck_mic_len > EAPOL_WPA_KEY_MAX_MIC_LEN)
735 #endif /* EAPOL_KEY_HDR_VER_V2 */
736 {
737 ASSERT(0);
738 return FALSE;
739 }
740 /* save MIC and clear its space in message */
741 if (memcpy_s(mic, sizeof(mic), EAPOL_WPA_KEY_HDR_MIC_PTR(body),
742 rsn_info->kck_mic_len)) {
743 return FALSE;
744 }
745 bzero(EAPOL_WPA_KEY_HDR_MIC_PTR(body), rsn_info->kck_mic_len);
746 if (wpa_make_mic(eapol, key_desc, mic_key, rsn_info, digest, rsn_info->kck_mic_len)
747 != BCME_OK) {
748 return FALSE;
749 }
750 return !memcmp(digest, mic, rsn_info->kck_mic_len);
751 }
752
bcmwpa_rsn_akm_to_hash(const rsn_akm_t akm)753 static sha2_hash_type_t bcmwpa_rsn_akm_to_hash(const rsn_akm_t akm)
754 {
755 uint i = 0;
756 sha2_hash_type_t type = HASH_NONE;
757
758 for (i = 0; i < ARRAYSIZE(rsn_akm_lookup_tbl); i++) {
759 if (akm == rsn_akm_lookup_tbl[i].rsn_akm) {
760 type = rsn_akm_lookup_tbl[i].hash_type;
761 break;
762 }
763 }
764 return type;
765 }
766 #endif /* BCMSUP_PSK || BCMAUTH_PSK || WLFBT || GTKOE */
767
768 #ifdef WLTDLS
769 void
wpa_calc_tpk(const struct ether_addr * init_ea,const struct ether_addr * resp_ea,const struct ether_addr * bssid,const uint8 * anonce,const uint8 * snonce,uint8 * tpk,uint tpk_len)770 wpa_calc_tpk(const struct ether_addr *init_ea, const struct ether_addr *resp_ea,
771 const struct ether_addr *bssid, const uint8 *anonce, const uint8* snonce,
772 uint8 *tpk, uint tpk_len)
773 {
774 uint8 pmk[SHA2_MAX_DIGEST_LEN];
775 uint pmk_len;
776 bcm_const_xlvp_t ikpfx[2];
777 int nikpfx = 0;
778 bcm_const_xlvp_t tpkpfx[4];
779 int ntpkpfx = 0;
780
781 pmk_len = sha2_digest_len(HASH_SHA256);
782
783 /* compute pmk to use - using anonce and snonce - min and then max */
784 ikpfx[nikpfx].len = EAPOL_WPA_KEY_NONCE_LEN;
785 ikpfx[nikpfx++].data = wpa_array_cmp(MIN_ARRAY, snonce, anonce,
786 EAPOL_WPA_KEY_NONCE_LEN),
787
788 ikpfx[nikpfx].len = EAPOL_WPA_KEY_NONCE_LEN;
789 ikpfx[nikpfx++].data = wpa_array_cmp(MAX_ARRAY, snonce, anonce,
790 EAPOL_WPA_KEY_NONCE_LEN),
791
792 (void)sha2(HASH_SHA256, ikpfx, nikpfx, NULL, 0, pmk, SHA2_SHA256_DIGEST_LEN);
793
794 /* compute the tpk - using prefix, min ea, max ea, bssid */
795 tpkpfx[ntpkpfx].len = sizeof(TDLS_PMK_PFX) - 1;
796 tpkpfx[ntpkpfx++].data = (const uint8 *)TDLS_PMK_PFX;
797
798 tpkpfx[ntpkpfx].len = ETHER_ADDR_LEN;
799 tpkpfx[ntpkpfx++].data = wpa_array_cmp(MIN_ARRAY, (const uint8 *)init_ea,
800 (const uint8 *)resp_ea, ETHER_ADDR_LEN),
801
802 tpkpfx[ntpkpfx].len = ETHER_ADDR_LEN;
803 tpkpfx[ntpkpfx++].data = wpa_array_cmp(MAX_ARRAY, (const uint8 *)init_ea,
804 (const uint8 *)resp_ea, ETHER_ADDR_LEN),
805
806 tpkpfx[ntpkpfx].len = ETHER_ADDR_LEN;
807 tpkpfx[ntpkpfx++].data = (const uint8 *)bssid;
808
809 (void)hmac_sha2_n(HASH_SHA256, pmk, pmk_len, tpkpfx, ntpkpfx, NULL, 0, tpk, tpk_len);
810 }
811 #endif /* WLTDLS */
812
813 /* Convert WPA/WPA2 IE cipher suite to locally used value */
814 static bool
rsn_cipher(wpa_suite_t * suite,ushort * cipher,const uint8 * std_oui,bool wep_ok)815 rsn_cipher(wpa_suite_t *suite, ushort *cipher, const uint8 *std_oui, bool wep_ok)
816 {
817 bool ret = TRUE;
818
819 if (!memcmp((const char *)suite->oui, std_oui, DOT11_OUI_LEN)) {
820 switch (suite->type) {
821 case WPA_CIPHER_TKIP:
822 *cipher = CRYPTO_ALGO_TKIP;
823 break;
824 case WPA_CIPHER_AES_CCM:
825 *cipher = CRYPTO_ALGO_AES_CCM;
826 break;
827 case WPA_CIPHER_AES_GCM:
828 *cipher = CRYPTO_ALGO_AES_GCM;
829 break;
830 case WPA_CIPHER_AES_GCM256:
831 *cipher = CRYPTO_ALGO_AES_GCM256;
832 break;
833 case WPA_CIPHER_WEP_40:
834 if (wep_ok)
835 *cipher = CRYPTO_ALGO_WEP1;
836 else
837 ret = FALSE;
838 break;
839 case WPA_CIPHER_WEP_104:
840 if (wep_ok)
841 *cipher = CRYPTO_ALGO_WEP128;
842 else
843 ret = FALSE;
844 break;
845 default:
846 ret = FALSE;
847 break;
848 }
849 return ret;
850 }
851
852 return FALSE;
853 }
854
855 bool
wpa_cipher(wpa_suite_t * suite,ushort * cipher,bool wep_ok)856 wpa_cipher(wpa_suite_t *suite, ushort *cipher, bool wep_ok)
857 {
858 return rsn_cipher(suite, cipher, (const uchar*)WPA_OUI, wep_ok);
859 }
860
861 bool
wpa2_cipher(wpa_suite_t * suite,ushort * cipher,bool wep_ok)862 wpa2_cipher(wpa_suite_t *suite, ushort *cipher, bool wep_ok)
863 {
864 return rsn_cipher(suite, cipher, (const uchar*)WPA2_OUI, wep_ok);
865 }
866
867 /* Is any of the tlvs the expected entry? If
868 * not update the tlvs buffer pointer/length.
869 */
870 bool
bcm_has_ie(uint8 * ie,uint8 ** tlvs,uint * tlvs_len,const uint8 * oui,uint oui_len,uint8 type)871 bcm_has_ie(uint8 *ie, uint8 **tlvs, uint *tlvs_len, const uint8 *oui, uint oui_len, uint8 type)
872 {
873 /* If the contents match the OUI and the type */
874 if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
875 !memcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
876 type == ie[TLV_BODY_OFF + oui_len]) {
877 return TRUE;
878 }
879
880 /* point to the next ie */
881 ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
882 /* calculate the length of the rest of the buffer */
883 *tlvs_len -= (uint)(ie - *tlvs);
884 /* update the pointer to the start of the buffer */
885 *tlvs = ie;
886
887 return FALSE;
888 }
889
890 wpa_ie_fixed_t *
bcm_find_wpaie(uint8 * parse,uint len)891 bcm_find_wpaie(uint8 *parse, uint len)
892 {
893 return (wpa_ie_fixed_t *) bcm_find_ie(parse, len, DOT11_MNG_VS_ID,
894 WPA_OUI_LEN, (const char*) WPA_OUI, WPA_OUI_TYPE);
895 }
896
897 int
bcm_find_security_ies(uint8 * buf,uint buflen,void ** wpa_ie,void ** rsn_ie)898 bcm_find_security_ies(uint8 *buf, uint buflen, void **wpa_ie,
899 void **rsn_ie)
900 {
901 bcm_tlv_t *tlv = NULL;
902 uint totlen = 0;
903 uint8 *end = NULL;
904 uint len = 0;
905 uint tlvs_len = 0;
906 uint8 *tlvs = NULL;
907
908 if ((tlv = (bcm_tlv_t*)buf) == NULL ||
909 !wpa_ie || !rsn_ie || buflen == 0) {
910 return BCME_BADARG;
911 }
912
913 totlen = buflen;
914 *rsn_ie = *wpa_ie = NULL;
915 end = buf;
916 end += buflen;
917
918 /* find rsn ie and wpa ie */
919 while (totlen >= TLV_HDR_LEN) {
920 len = tlv->len;
921 tlvs_len = buflen;
922 tlvs = buf;
923
924 /* check if tlv overruns buffer */
925 if (totlen < (len + TLV_HDR_LEN)) {
926 return BCME_BUFTOOSHORT;
927 }
928
929 /* validate remaining totlen */
930 if (totlen >= (len + TLV_HDR_LEN)) {
931 if ((*rsn_ie == NULL) && (tlv->id == DOT11_MNG_RSN_ID)) {
932 *rsn_ie = tlv;
933 } else if ((*wpa_ie == NULL) && (tlv->id == DOT11_MNG_VS_ID)) {
934 /* if vendor ie, check if its wpa ie */
935 if (bcm_is_wpa_ie((uint8 *)tlv, &tlvs, &tlvs_len))
936 *wpa_ie = tlv;
937 }
938 }
939
940 if (*rsn_ie && *wpa_ie)
941 break;
942
943 tlv = (bcm_tlv_t*)((uint8*)tlv + (len + TLV_HDR_LEN));
944 totlen -= (len + TLV_HDR_LEN);
945
946 if (totlen > buflen) {
947 return BCME_BUFTOOLONG;
948 }
949
950 if ((uint8 *)tlv > end) {
951 return BCME_BUFTOOSHORT;
952 }
953
954 }
955
956 if (*wpa_ie || *rsn_ie)
957 return BCME_OK;
958 else
959 return BCME_NOTFOUND;
960 }
961
962 bcm_tlv_t *
bcm_find_wmeie(uint8 * parse,uint len,uint8 subtype,uint8 subtype_len)963 bcm_find_wmeie(uint8 *parse, uint len, uint8 subtype, uint8 subtype_len)
964 {
965 bcm_tlv_t *ie;
966 if ((ie = bcm_find_ie(parse, len, DOT11_MNG_VS_ID, WME_OUI_LEN,
967 (const char*) WME_OUI, WME_OUI_TYPE))) {
968 uint ie_len = TLV_HDR_LEN + ie->len;
969 wme_ie_t *ie_data = (wme_ie_t *)ie->data;
970 /* the subtype_len must include OUI+type+subtype */
971 if (subtype_len > WME_OUI_LEN + 1 &&
972 ie_len == (uint)TLV_HDR_LEN + subtype_len &&
973 ie_data->subtype == subtype) {
974 return ie;
975 }
976 /* move to next IE */
977 len -= (uint)((uint8 *)ie + ie_len - parse);
978 parse = (uint8 *)ie + ie_len;
979 }
980 return NULL;
981 }
982
983 wps_ie_fixed_t *
bcm_find_wpsie(const uint8 * parse,uint len)984 bcm_find_wpsie(const uint8 *parse, uint len)
985 {
986 uint8 type = WPS_OUI_TYPE;
987
988 return (wps_ie_fixed_t *)bcm_find_vendor_ie(parse, len, WPS_OUI, &type, sizeof(type));
989 }
990
991 /* locate the Attribute in the WPS IE */
992 /* assume the caller has validated the WPS IE tag and length */
993 wps_at_fixed_t *
bcm_wps_find_at(wps_at_fixed_t * at,uint len,uint16 id)994 bcm_wps_find_at(wps_at_fixed_t *at, uint len, uint16 id)
995 {
996 while ((int)len >= WPS_AT_FIXED_LEN) {
997 uint alen = WPS_AT_FIXED_LEN + ntoh16_ua(((wps_at_fixed_t *)at)->len);
998 if (ntoh16_ua(((wps_at_fixed_t *)at)->at) == id && alen <= len)
999 return at;
1000 at = (wps_at_fixed_t *)((uint8 *)at + alen);
1001 len -= alen;
1002 }
1003 return NULL;
1004 }
1005
1006 #ifdef WLP2P
1007 wifi_p2p_ie_t *
bcm_find_p2pie(const uint8 * parse,uint len)1008 bcm_find_p2pie(const uint8 *parse, uint len)
1009 {
1010 uint8 type = P2P_OUI_TYPE;
1011
1012 return (wifi_p2p_ie_t *)bcm_find_vendor_ie(parse, len, P2P_OUI, &type, sizeof(type));
1013 }
1014 #endif
1015
1016 bcm_tlv_t *
bcm_find_hs20ie(uint8 * parse,uint len)1017 bcm_find_hs20ie(uint8 *parse, uint len)
1018 {
1019 return bcm_find_ie(parse, len, DOT11_MNG_VS_ID, WFA_OUI_LEN,
1020 (const char *)WFA_OUI, WFA_OUI_TYPE_HS20);
1021 }
1022
1023 bcm_tlv_t *
bcm_find_osenie(uint8 * parse,uint len)1024 bcm_find_osenie(uint8 *parse, uint len)
1025 {
1026 return bcm_find_ie(parse, len, DOT11_MNG_VS_ID, WFA_OUI_LEN,
1027 (const char *) WFA_OUI, WFA_OUI_TYPE_OSEN);
1028 }
1029
1030 #if defined(BCMSUP_PSK) || defined(BCMSUPPL) || defined(GTKOE) || defined(WL_FILS)
1031 #define wpa_is_kde(ie, tlvs, len, type) bcm_has_ie(ie, tlvs, len, \
1032 (const uint8 *)WPA2_OUI, WPA2_OUI_LEN, type)
1033
1034 eapol_wpa2_encap_data_t *
wpa_find_kde(const uint8 * parse,uint len,uint8 type)1035 wpa_find_kde(const uint8 *parse, uint len, uint8 type)
1036 {
1037 return (eapol_wpa2_encap_data_t *) bcm_find_ie(parse, len,
1038 DOT11_MNG_PROPR_ID, WPA2_OUI_LEN, (const char *) WPA2_OUI, type);
1039 }
1040
1041 bool
wpa_is_gtk_encap(uint8 * ie,uint8 ** tlvs,uint * tlvs_len)1042 wpa_is_gtk_encap(uint8 *ie, uint8 **tlvs, uint *tlvs_len)
1043 {
1044 return wpa_is_kde(ie, tlvs, tlvs_len, WPA2_KEY_DATA_SUBTYPE_GTK);
1045 }
1046
1047 eapol_wpa2_encap_data_t *
wpa_find_gtk_encap(uint8 * parse,uint len)1048 wpa_find_gtk_encap(uint8 *parse, uint len)
1049 {
1050 eapol_wpa2_encap_data_t *data;
1051
1052 /* minimum length includes kde upto gtk field in eapol_wpa2_key_gtk_encap_t */
1053 data = wpa_find_kde(parse, len, WPA2_KEY_DATA_SUBTYPE_GTK);
1054 if (data && (data->length < EAPOL_WPA2_GTK_ENCAP_MIN_LEN)) {
1055 data = NULL;
1056 }
1057
1058 return data;
1059 }
1060
1061 int
wpa_find_eapol_kde_data(eapol_header_t * eapol,uint8 eapol_mic_len,uint8 subtype,eapol_wpa2_encap_data_t ** out_data)1062 wpa_find_eapol_kde_data(eapol_header_t* eapol, uint8 eapol_mic_len,
1063 uint8 subtype, eapol_wpa2_encap_data_t **out_data)
1064 {
1065 eapol_wpa_key_header_t *body;
1066 uint8 *parse;
1067 uint16 body_len;
1068 uint16 data_len;
1069
1070 if (!eapol) {
1071 return BCME_BADARG;
1072 }
1073
1074 body = (eapol_wpa_key_header_t *)eapol->body;
1075 body_len = ntoh16_ua(&eapol->length);
1076
1077 data_len = ntoh16_ua(EAPOL_WPA_KEY_HDR_DATA_LEN_PTR(body,
1078 eapol_mic_len));
1079
1080 parse = EAPOL_WPA_KEY_HDR_DATA_PTR(body, eapol_mic_len);
1081
1082 if (((uint8 *)body + body_len) < ((uint8 *)parse + data_len)) {
1083 return BCME_BUFTOOSHORT;
1084 }
1085
1086 return wpa_find_kde_data(parse, data_len, subtype, out_data);
1087 }
1088
1089 int
wpa_find_kde_data(const uint8 * kde_buf,uint16 buf_len,uint8 subtype,eapol_wpa2_encap_data_t ** out_data)1090 wpa_find_kde_data(const uint8 *kde_buf, uint16 buf_len,
1091 uint8 subtype, eapol_wpa2_encap_data_t **out_data)
1092 {
1093 eapol_wpa2_encap_data_t *data;
1094 uint8 min_len;
1095
1096 if (!kde_buf) {
1097 return BCME_BADARG;
1098 }
1099
1100 /* minimum length includes kde upto gtk field in eapol_wpa2_key_gtk_encap_t */
1101 data = wpa_find_kde(kde_buf, buf_len, subtype);
1102 if (!data) {
1103 return BCME_IE_NOTFOUND;
1104 }
1105
1106 switch (subtype) {
1107 case WPA2_KEY_DATA_SUBTYPE_GTK:
1108 min_len = EAPOL_WPA2_GTK_ENCAP_MIN_LEN;
1109 break;
1110 case WPA2_KEY_DATA_SUBTYPE_IGTK:
1111 min_len = EAPOL_WPA2_BIGTK_ENCAP_MIN_LEN;
1112 break;
1113 case WPA2_KEY_DATA_SUBTYPE_BIGTK:
1114 min_len = EAPOL_WPA2_IGTK_ENCAP_MIN_LEN;
1115 break;
1116 #ifdef WL_OCV
1117 case WPA2_KEY_DATA_SUBTYPE_OCI:
1118 min_len = EAPOL_WPA2_OCI_ENCAP_MIN_LEN;
1119 break;
1120 #endif /* WL_OCV */
1121 default:
1122 return BCME_UNSUPPORTED;
1123 }
1124
1125 if (data->length < min_len) {
1126 return BCME_BADLEN;
1127 }
1128
1129 *out_data = data;
1130
1131 return BCME_OK;
1132 }
1133
1134 #ifdef WL_OCV
1135 bool
wpa_check_ocv_caps(uint16 local_caps,uint16 peer_caps)1136 wpa_check_ocv_caps(uint16 local_caps, uint16 peer_caps)
1137 {
1138 bool ocv_enabled =
1139 ((local_caps & RSN_CAP_OCVC) &&
1140 (peer_caps & RSN_CAP_OCVC));
1141 bool mfp_enabled =
1142 ((peer_caps & RSN_CAP_MFPC) ||
1143 (peer_caps & RSN_CAP_MFPR));
1144
1145 return (ocv_enabled && mfp_enabled);
1146 }
1147
1148 int
wpa_add_oci_encap(chanspec_t chspec,uint8 * buf,uint buf_len)1149 wpa_add_oci_encap(chanspec_t chspec, uint8* buf, uint buf_len)
1150 {
1151 int retval = BCME_OK;
1152 eapol_wpa2_encap_data_t* oci_kde;
1153 uint len = buf_len;
1154
1155 if (buf_len < WPA_OCV_OCI_KDE_SIZE) {
1156 retval = BCME_BUFTOOSHORT;
1157 goto done;
1158 }
1159
1160 oci_kde = (eapol_wpa2_encap_data_t*)buf;
1161
1162 oci_kde->type = DOT11_MNG_WPA_ID;
1163 oci_kde->subtype = WPA2_KEY_DATA_SUBTYPE_OCI;
1164 oci_kde->length = (WPA_OCV_OCI_KDE_SIZE - TLV_HDR_LEN);
1165
1166 oci_kde->oui[0u] = WPA2_OUI[0u];
1167 oci_kde->oui[1u] = WPA2_OUI[1u];
1168 oci_kde->oui[2u] = WPA2_OUI[2u];
1169
1170 buf += EAPOL_WPA2_ENCAP_DATA_HDR_LEN;
1171 len -= EAPOL_WPA2_ENCAP_DATA_HDR_LEN;
1172
1173 retval = bcm_ocv_write_oci(chspec, buf, len);
1174 if (retval != BCME_OK) {
1175 goto done;
1176 }
1177
1178 done:
1179 return retval;
1180 }
1181
1182 int
wpa_add_oci_ie(chanspec_t chspec,uint8 * buf,uint buf_len)1183 wpa_add_oci_ie(chanspec_t chspec, uint8* buf, uint buf_len)
1184 {
1185 int retval = BCME_OK;
1186 uint8* oci_buf = buf + BCM_TLV_EXT_HDR_SIZE;
1187
1188 if (buf_len < (bcm_ocv_get_oci_len() + BCM_TLV_EXT_HDR_SIZE)) {
1189 retval = BCME_BUFTOOSHORT;
1190 goto done;
1191 }
1192
1193 retval = bcm_ocv_write_oci(chspec, oci_buf, bcm_ocv_get_oci_len());
1194 if (retval != BCME_OK) {
1195 goto done;
1196 }
1197
1198 (void)bcm_write_tlv_ext(DOT11_MNG_ID_EXT_ID,
1199 OCV_EXTID_MNG_OCI_ID, oci_buf, bcm_ocv_get_oci_len(), buf);
1200
1201 done:
1202 return retval;
1203 }
1204
1205 int
wpa_add_oci_ft_subelem(chanspec_t chspec,uint8 * buf,uint buf_len)1206 wpa_add_oci_ft_subelem(chanspec_t chspec, uint8* buf, uint buf_len)
1207 {
1208 int retval = BCME_OK;
1209 uint8* oci_buf = buf + BCM_TLV_HDR_SIZE;
1210
1211 if (buf_len < (bcm_ocv_get_oci_len() + BCM_TLV_HDR_SIZE)) {
1212 retval = BCME_BUFTOOSHORT;
1213 goto done;
1214 }
1215
1216 retval = bcm_ocv_write_oci(chspec, oci_buf, bcm_ocv_get_oci_len());
1217 if (retval != BCME_OK) {
1218 goto done;
1219 }
1220
1221 bcm_write_tlv_safe(DOT11_FBT_SUBELEM_ID_OCI,
1222 oci_buf, bcm_ocv_get_oci_len(), buf, buf_len);
1223
1224 done:
1225 return retval;
1226 }
1227
wpa_validate_oci_encap(chanspec_t chspec,const uint8 * buf,uint buf_len)1228 int wpa_validate_oci_encap(chanspec_t chspec, const uint8* buf, uint buf_len)
1229 {
1230 int retval = BCME_OK;
1231 eapol_wpa2_encap_data_t *encap = NULL;
1232
1233 retval = wpa_find_kde_data(buf, buf_len, WPA2_KEY_DATA_SUBTYPE_OCI, &encap);
1234 if (retval != BCME_OK) {
1235 retval = BCME_NOTFOUND;
1236 goto done;
1237 }
1238
1239 retval = bcm_ocv_validate_oci(chspec,
1240 encap->data, encap->length);
1241 if (retval != BCME_OK) {
1242 goto done;
1243 }
1244
1245 done:
1246 return retval;
1247 }
1248
wpa_validate_oci_ie(chanspec_t chspec,const uint8 * buf,uint buf_len)1249 int wpa_validate_oci_ie(chanspec_t chspec, const uint8* buf, uint buf_len)
1250 {
1251 int retval = BCME_OK;
1252 bcm_tlv_ext_t *oci_ie;
1253
1254 oci_ie = (bcm_tlv_ext_t *)bcm_parse_tlvs_dot11(buf, buf_len,
1255 OCV_EXTID_MNG_OCI_ID, TRUE);
1256
1257 if (!oci_ie) {
1258 retval = BCME_NOTFOUND;
1259 goto done;
1260 }
1261
1262 retval = bcm_ocv_validate_oci(chspec, oci_ie->data, oci_ie->len);
1263 if (retval != BCME_OK) {
1264 goto done;
1265 }
1266
1267 done:
1268 return retval;
1269 }
1270
wpa_validate_oci_ft_subelem(chanspec_t chspec,const uint8 * buf,uint buf_len)1271 int wpa_validate_oci_ft_subelem(chanspec_t chspec, const uint8* buf, uint buf_len)
1272 {
1273 int retval = BCME_OK;
1274 bcm_tlv_t *oci_ie;
1275
1276 oci_ie = (bcm_tlv_t *)bcm_parse_tlvs_dot11(buf, buf_len,
1277 DOT11_FBT_SUBELEM_ID_OCI, FALSE);
1278
1279 if (!oci_ie) {
1280 retval = BCME_NOTFOUND;
1281 goto done;
1282 }
1283
1284 retval = bcm_ocv_validate_oci(chspec, oci_ie->data, oci_ie->len);
1285 if (retval != BCME_OK) {
1286 goto done;
1287 }
1288
1289 done:
1290 return retval;
1291 }
1292 #endif /* WL_OCV */
1293 #endif /* defined(BCMSUP_PSK) || defined(BCMSUPPL) || defined(GTKOE) || defined(WL_FILS) */
1294
1295 const uint8 *
wpa_array_cmp(int max_array,const uint8 * x,const uint8 * y,uint len)1296 wpa_array_cmp(int max_array, const uint8 *x, const uint8 *y, uint len)
1297 {
1298 uint i;
1299 const uint8 *ret = x;
1300
1301 for (i = 0; i < len; i++)
1302 if (x[i] != y[i])
1303 break;
1304
1305 if (i == len) {
1306 /* returning null will cause crash, return value used for copying */
1307 /* return first param in this case to close security loophole */
1308 return x;
1309 }
1310 if (max_array && (y[i] > x[i]))
1311 ret = y;
1312 if (!max_array && (y[i] < x[i]))
1313 ret = y;
1314
1315 return (ret);
1316 }
1317
1318 void
wpa_incr_array(uint8 * array,uint len)1319 wpa_incr_array(uint8 *array, uint len)
1320 {
1321 int i;
1322
1323 for (i = (len-1); i >= 0; i--)
1324 if (array[i]++ != 0xff) {
1325 break;
1326 }
1327 }
1328
1329 bool
bcmwpa_akm2WPAauth(uint8 * akm,uint32 * auth,bool sta_iswpa)1330 bcmwpa_akm2WPAauth(uint8 *akm, uint32 *auth, bool sta_iswpa)
1331 {
1332 uint i;
1333 oui_akm_wpa_tbl_t wpa_auth_tbl_match[] = {
1334 {WPA2_OUI, RSN_AKM_NONE, WPA_AUTH_NONE},
1335 {WPA2_OUI, RSN_AKM_UNSPECIFIED, WPA2_AUTH_UNSPECIFIED},
1336 {WPA2_OUI, RSN_AKM_PSK, WPA2_AUTH_PSK},
1337 {WPA2_OUI, RSN_AKM_FBT_1X, WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_FT},
1338 {WPA2_OUI, RSN_AKM_FBT_PSK, WPA2_AUTH_PSK | WPA2_AUTH_FT},
1339 {WPA2_OUI, RSN_AKM_SHA256_1X, WPA2_AUTH_1X_SHA256},
1340 {WPA2_OUI, RSN_AKM_SHA256_PSK, WPA2_AUTH_PSK_SHA256},
1341 {WPA2_OUI, RSN_AKM_FILS_SHA256, WPA2_AUTH_FILS_SHA256},
1342 {WPA2_OUI, RSN_AKM_FILS_SHA384, WPA2_AUTH_FILS_SHA384},
1343 {WPA2_OUI, RSN_AKM_FBT_SHA256_FILS, WPA2_AUTH_FILS_SHA256 | WPA2_AUTH_FT},
1344 {WPA2_OUI, RSN_AKM_FBT_SHA384_FILS, WPA2_AUTH_FILS_SHA384 | WPA2_AUTH_FT},
1345 {WPA2_OUI, RSN_AKM_SAE_PSK, WPA3_AUTH_SAE_PSK},
1346 {WPA2_OUI, RSN_AKM_SAE_FBT, WPA3_AUTH_SAE_PSK | WPA2_AUTH_FT},
1347 {WPA2_OUI, RSN_AKM_OWE, WPA3_AUTH_OWE},
1348 {WPA2_OUI, RSN_AKM_SUITEB_SHA256_1X, WPA3_AUTH_1X_SUITE_B_SHA256},
1349 {WPA2_OUI, RSN_AKM_SUITEB_SHA384_1X, WPA3_AUTH_1X_SUITE_B_SHA384},
1350 {WFA_OUI, OSEN_AKM_UNSPECIFIED, WPA2_AUTH_UNSPECIFIED},
1351 {WFA_OUI, RSN_AKM_FBT_SHA256_FILS, WPA2_AUTH_FILS_SHA256 | WPA2_AUTH_FT},
1352 {WFA_OUI, RSN_AKM_FBT_SHA384_FILS, WPA2_AUTH_FILS_SHA384 | WPA2_AUTH_FT},
1353 {WFA_OUI, RSN_AKM_DPP, WPA3_AUTH_DPP_AKM},
1354
1355 #ifdef BCMWAPI_WAI
1356 {WAPI_OUI, RSN_AKM_NONE, WAPI_AUTH_NONE},
1357 {WAPI_OUI, RSN_AKM_UNSPECIFIED, WAPI_AUTH_UNSPECIFIED},
1358 {WAPI_OUI, RSN_AKM_PSK, WAPI_AUTH_PSK},
1359 #endif /* BCMWAPI_WAI */
1360
1361 {WPA_OUI, RSN_AKM_NONE, WPA_AUTH_NONE},
1362 {WPA_OUI, RSN_AKM_UNSPECIFIED, WPA_AUTH_UNSPECIFIED},
1363 {WPA_OUI, RSN_AKM_PSK, WPA_AUTH_PSK},
1364 };
1365
1366 BCM_REFERENCE(sta_iswpa);
1367
1368 for (i = 0; i < ARRAYSIZE(wpa_auth_tbl_match); i++) {
1369 if (!memcmp(akm, wpa_auth_tbl_match[i].oui, DOT11_OUI_LEN)) {
1370 if (wpa_auth_tbl_match[i].rsn_akm == akm[DOT11_OUI_LEN]) {
1371 *auth = wpa_auth_tbl_match[i].wpa_auth;
1372 return TRUE;
1373 }
1374 }
1375 }
1376 return FALSE;
1377 }
1378
1379 /* map cipher suite to internal WSEC_XXXX */
1380 /* cs points 4 byte cipher suite, and only the type is used for non CCX ciphers */
1381 bool
bcmwpa_cipher2wsec(uint8 * cipher,uint32 * wsec)1382 bcmwpa_cipher2wsec(uint8 *cipher, uint32 *wsec)
1383 {
1384
1385 #ifdef BCMWAPI_WAI
1386 if (!memcmp(cipher, WAPI_OUI, DOT11_OUI_LEN)) {
1387 switch (WAPI_CSE_WPI_2_CIPHER(cipher[DOT11_OUI_LEN])) {
1388 case WAPI_CIPHER_NONE:
1389 *wsec = 0;
1390 break;
1391 case WAPI_CIPHER_SMS4:
1392 *wsec = SMS4_ENABLED;
1393 break;
1394 default:
1395 return FALSE;
1396 }
1397 return TRUE;
1398 }
1399 #endif /* BCMWAPI_WAI */
1400
1401 switch (cipher[DOT11_OUI_LEN]) {
1402 case WPA_CIPHER_NONE:
1403 *wsec = 0;
1404 break;
1405 case WPA_CIPHER_WEP_40:
1406 case WPA_CIPHER_WEP_104:
1407 *wsec = WEP_ENABLED;
1408 break;
1409 case WPA_CIPHER_TKIP:
1410 *wsec = TKIP_ENABLED;
1411 break;
1412 case WPA_CIPHER_AES_CCM:
1413 /* fall through */
1414 case WPA_CIPHER_AES_GCM:
1415 /* fall through */
1416 case WPA_CIPHER_AES_GCM256:
1417 *wsec = AES_ENABLED;
1418 break;
1419
1420 #ifdef BCMWAPI_WAI
1421 case WAPI_CIPHER_SMS4:
1422 *wsec = SMS4_ENABLED;
1423 break;
1424 #endif /* BCMWAPI_WAI */
1425
1426 default:
1427 return FALSE;
1428 }
1429 return TRUE;
1430 }
1431
1432 #ifdef RSN_IE_INFO_STRUCT_RELOCATED
1433 /* map WPA/RSN cipher to internal WSEC */
1434 uint32
bcmwpa_wpaciphers2wsec(uint32 wpacipher)1435 bcmwpa_wpaciphers2wsec(uint32 wpacipher)
1436 {
1437 uint32 wsec = 0;
1438
1439 switch (wpacipher) {
1440 case BCM_BIT(WPA_CIPHER_WEP_40):
1441 case BCM_BIT(WPA_CIPHER_WEP_104):
1442 wsec = WEP_ENABLED;
1443 break;
1444 case BCM_BIT(WPA_CIPHER_TKIP):
1445 wsec = TKIP_ENABLED;
1446 break;
1447 case BCM_BIT(WPA_CIPHER_AES_OCB):
1448 /* fall through */
1449 case BCM_BIT(WPA_CIPHER_AES_CCM):
1450 wsec = AES_ENABLED;
1451 break;
1452 case BCM_BIT(WPA_CIPHER_AES_GCM):
1453 /* fall through */
1454 case BCM_BIT(WPA_CIPHER_AES_GCM256):
1455 wsec = AES_ENABLED;
1456 break;
1457
1458 #ifdef BCMWAPI_WAI
1459 case BCM_BIT(WAPI_CIPHER_SMS4):
1460 wsec = SMS4_ENABLED;
1461 break;
1462 #endif /* BCMWAPI_WAI */
1463
1464 default:
1465 break;
1466 }
1467
1468 return wsec;
1469 }
1470
1471 uint32
wlc_convert_rsn_to_wsec_bitmap(uint32 ap_cipher_mask)1472 wlc_convert_rsn_to_wsec_bitmap(uint32 ap_cipher_mask)
1473 {
1474
1475 uint32 ap_wsec = 0;
1476 uint32 tmp_mask = ap_cipher_mask;
1477 uint32 c;
1478
1479 FOREACH_BIT(c, tmp_mask) {
1480 ap_wsec |= bcmwpa_wpaciphers2wsec(c);
1481 }
1482
1483 return ap_wsec;
1484 }
1485
1486 #else /* Not RSN_IE_INFO_STRUCT_RELOCATED */
1487 uint32
bcmwpa_wpaciphers2wsec(uint8 wpacipher)1488 bcmwpa_wpaciphers2wsec(uint8 wpacipher)
1489 {
1490 uint32 wsec = 0;
1491
1492 switch (wpacipher) {
1493 case WPA_CIPHER_NONE:
1494 break;
1495 case WPA_CIPHER_WEP_40:
1496 case WPA_CIPHER_WEP_104:
1497 wsec = WEP_ENABLED;
1498 break;
1499 case WPA_CIPHER_TKIP:
1500 wsec = TKIP_ENABLED;
1501 break;
1502 case WPA_CIPHER_AES_OCB:
1503 /* fall through */
1504 case WPA_CIPHER_AES_CCM:
1505 wsec = AES_ENABLED;
1506 break;
1507 case WPA_CIPHER_AES_GCM:
1508 /* fall through */
1509 case WPA_CIPHER_AES_GCM256:
1510 wsec = AES_ENABLED;
1511 break;
1512
1513 #ifdef BCMWAPI_WAI
1514 case WAPI_CIPHER_SMS4:
1515 wsec = SMS4_ENABLED;
1516 break;
1517 #endif /* BCMWAPI_WAI */
1518
1519 default:
1520 break;
1521 }
1522
1523 return wsec;
1524 }
1525 #endif /* RSN_IE_INFO_STRUCT_RELOCATED */
1526
1527 bool
bcmwpa_is_wpa_auth(uint32 auth)1528 bcmwpa_is_wpa_auth(uint32 auth)
1529 {
1530 if ((auth == WPA_AUTH_NONE) ||
1531 (auth == WPA_AUTH_UNSPECIFIED) ||
1532 (auth == WPA_AUTH_PSK))
1533 return TRUE;
1534 else
1535 return FALSE;
1536 }
1537
1538 bool
bcmwpa_includes_wpa_auth(uint32 auth)1539 bcmwpa_includes_wpa_auth(uint32 auth)
1540 {
1541 if (auth & (WPA_AUTH_NONE |
1542 WPA_AUTH_UNSPECIFIED |
1543 WPA_AUTH_PSK))
1544 return TRUE;
1545 else
1546 return FALSE;
1547 }
1548
1549 bool
bcmwpa_is_rsn_auth(uint32 auth)1550 bcmwpa_is_rsn_auth(uint32 auth)
1551 {
1552 auth = auth & ~WPA2_AUTH_FT;
1553
1554 if ((auth == WPA2_AUTH_UNSPECIFIED) ||
1555 (auth == WPA2_AUTH_PSK) ||
1556 (auth == BRCM_AUTH_PSK) ||
1557 (auth == WPA2_AUTH_1X_SHA256) ||
1558 (auth == WPA2_AUTH_PSK_SHA256) ||
1559 (auth == WPA3_AUTH_SAE_PSK) ||
1560 (auth == WPA3_AUTH_OWE) ||
1561 WPA2_AUTH_IS_FILS(auth) ||
1562 (auth == WPA3_AUTH_1X_SUITE_B_SHA256) ||
1563 (auth == WPA3_AUTH_1X_SUITE_B_SHA384) ||
1564 (auth == WPA3_AUTH_PSK_SHA384) ||
1565 (auth == WPA3_AUTH_DPP_AKM)) {
1566 return TRUE;
1567 } else {
1568 return FALSE;
1569 }
1570 }
1571
1572 bool
bcmwpa_includes_rsn_auth(uint32 auth)1573 bcmwpa_includes_rsn_auth(uint32 auth)
1574 {
1575 if (auth & (WPA2_AUTH_UNSPECIFIED |
1576 WPA2_AUTH_PSK |
1577 BRCM_AUTH_PSK | WPA2_AUTH_1X_SHA256 | WPA2_AUTH_PSK_SHA256 |
1578 WPA2_AUTH_IS_FILS(auth) | WPA3_AUTH_SAE_PSK | WPA3_AUTH_OWE |
1579 WPA3_AUTH_1X_SUITE_B_SHA256 | WPA3_AUTH_1X_SUITE_B_SHA384 |
1580 WPA3_AUTH_PSK_SHA384 | WPA3_AUTH_DPP_AKM))
1581 return TRUE;
1582 else
1583 return FALSE;
1584 }
1585
1586 #ifdef RSN_IE_INFO_STRUCT_RELOCATED
1587 /* decode unicast/multicast cipher in RSNIE */
1588 static int
bcmwpa_decode_cipher_suite(rsn_ie_info_t * info,const uint8 ** ptr_inc,uint ie_len,uint * remain_len,uint16 * p_count)1589 bcmwpa_decode_cipher_suite(rsn_ie_info_t *info, const uint8 **ptr_inc, uint ie_len, uint
1590 *remain_len, uint16 *p_count)
1591 {
1592 const wpa_suite_ucast_t *ucast;
1593 const wpa_suite_mcast_t *mcast;
1594 uint i;
1595
1596 if (!(*remain_len)) {
1597 info->g_cipher = WPA_CIPHER_UNSPECIFIED;
1598 info->p_ciphers = WPA_P_CIPHERS_UNSPECIFIED;
1599 goto done; /* only have upto ver */
1600 }
1601 *ptr_inc += ie_len - *remain_len;
1602
1603 if (*remain_len < sizeof(wpa_suite_mcast_t)) {
1604 info->parse_status = BCME_BADLEN;
1605 goto done;
1606 }
1607 mcast = (const wpa_suite_mcast_t *)*ptr_inc;
1608
1609 if (IS_WPA_CIPHER(mcast->type)) {
1610 info->g_cipher = mcast->type;
1611 } else {
1612 info->parse_status = BCME_BAD_IE_DATA;
1613 goto done;
1614 }
1615
1616 /* for rsn pairwise cipher suite */
1617 *ptr_inc += sizeof(wpa_suite_mcast_t);
1618 *remain_len -= sizeof(wpa_suite_mcast_t);
1619
1620 if (!(*remain_len)) {
1621 info->p_ciphers = WPA_P_CIPHERS_UNSPECIFIED;
1622 info->sta_akm = WPA_CIPHER_UNSPECIFIED;
1623 goto done;
1624 }
1625
1626 ucast = (const wpa_suite_ucast_t *)*ptr_inc;
1627
1628 if ((*remain_len) < sizeof(ucast->count)) {
1629 info->parse_status = BCME_BADLEN;
1630 goto done;
1631 }
1632
1633 if (!ucast->count.low && !ucast->count.high) {
1634 info->parse_status = BCME_BADLEN;
1635 goto done;
1636 }
1637
1638 *p_count = ltoh16_ua(&ucast->count);
1639 if (info->dev_type == DEV_STA && *p_count != 1u) {
1640 info->parse_status = BCME_BAD_IE_DATA;
1641 goto done;
1642 }
1643 if ((*remain_len) < (*p_count * WPA_SUITE_LEN + sizeof(ucast->count))) {
1644 info->parse_status = BCME_BADLEN;
1645 goto done;
1646 }
1647
1648 if (info->dev_type == DEV_STA) {
1649 if (IS_WPA_CIPHER(ucast->list[0].type)) {
1650 /* update the pairwise cipher */
1651 info->sta_cipher = ucast->list[0].type;
1652 } else {
1653 info->parse_status = BCME_BAD_IE_DATA;
1654 goto done;
1655 }
1656 } else {
1657 for (i = 0; i < *p_count; i++) {
1658 if (IS_WPA_CIPHER(ucast->list[i].type)) {
1659 info->p_ciphers |= BIT(ucast->list[i].type);
1660 info->rsn_p_ciphers = info->p_ciphers;
1661 } else {
1662 info->parse_status = BCME_BAD_IE_DATA;
1663 goto done;
1664 }
1665 }
1666 }
1667
1668 /* update buffer ptr and remaining length */
1669 *ptr_inc += (*p_count * WPA_SUITE_LEN) + sizeof(ucast->count);
1670 *remain_len -= (*p_count * WPA_SUITE_LEN) + sizeof(ucast->count);
1671
1672 done:
1673
1674 if (info->parse_status == BCME_OK) {
1675 if (info->g_cipher == WPA_CIPHER_UNSPECIFIED) {
1676 info->g_cipher = WPA_CIPHER_AES_CCM;
1677 }
1678 if (info->p_ciphers == WPA_P_CIPHERS_UNSPECIFIED) {
1679 info->p_ciphers = BIT(WPA_CIPHER_AES_CCM);
1680 info->rsn_p_ciphers = info->p_ciphers;
1681 }
1682 }
1683
1684 return info->parse_status;
1685 }
1686 /* sta_akm/sta_cipher must be set before this call */
1687 int
bcmwpa_rsnie_eapol_key_len(rsn_ie_info_t * info)1688 bcmwpa_rsnie_eapol_key_len(rsn_ie_info_t *info)
1689 {
1690 info->pmk_len = bcmwpa_eapol_key_length(EAPOL_KEY_PMK, info->sta_akm, 0);
1691 info->kck_mic_len = bcmwpa_eapol_key_length(EAPOL_KEY_KCK_MIC, info->sta_akm, 0);
1692 info->kck_len = bcmwpa_eapol_key_length(EAPOL_KEY_KCK, info->sta_akm, 0);
1693 info->kek_len = bcmwpa_eapol_key_length(EAPOL_KEY_KEK, info->sta_akm, 0);
1694 info->tk_len = bcmwpa_eapol_key_length(EAPOL_KEY_TK, 0, info->sta_cipher);
1695 info->ptk_len = info->kck_len + info->kek_len + info->tk_len;
1696 #if defined(WL_FILS) && defined(WLFBT)
1697 info->kck2_len = bcmwpa_eapol_key_length(EAPOL_KEY_KCK2, info->sta_akm, 0);
1698 info->kek2_len = bcmwpa_eapol_key_length(EAPOL_KEY_KEK2, info->sta_akm, 0);
1699 if (WPA_IS_FILS_FT_AKM(info->sta_akm)) {
1700 info->ptk_len += (info->kck2_len + info->kek2_len);
1701 }
1702 #endif /* WL_FILS && WLFBT */
1703 return BCME_OK;
1704 }
1705 /* Extract and store information from WPA or RSN IEs
1706 *
1707 * called after either
1708 * -an association request has been built (STA),
1709 * - an association was received (AP)
1710 * - a probe request has been built (AP)
1711 * - a probe response was received (STA)
1712 *
1713 * All available information is extracted to be used for subsequent
1714 * bss pruning, association request validation, key descriptor compuation etc.
1715 *
1716 * To be expanded as needed.
1717 *
1718 * ie: RSN IE input
1719 * rsn_info: parsed information. Placed in either bsscfg for self, or scb for peer.
1720 * dev_type: STA_RSN or AP_RSN
1721 *
1722 * Return : parse status.
1723 * NOTE: the parse status is also saved in the the parse_status field.
1724 * NOTE 2 : the IE itself is copied at the end of the structure. Since there is
1725 * no reference to the osh available here, the allocation has to happen outside
1726 * and so the structure cannot be zeroed in this function.
1727 * For the STA, it should happen everytime.
1728 * For the AP, it should happen right after a new beacon/probe has been acquired.
1729 */
1730
1731 int
bcmwpa_parse_rsnie(const bcm_tlv_t * ie,rsn_ie_info_t * info,device_type_t dev_type)1732 bcmwpa_parse_rsnie(const bcm_tlv_t *ie, rsn_ie_info_t *info, device_type_t dev_type)
1733 {
1734
1735 const uint8 *ptr_inc = NULL;
1736 const wpa_suite_mcast_t *mcast;
1737 const wpa_suite_auth_key_mgmt_t *mgmt;
1738 const wpa_pmkid_list_t *pmkid_list;
1739 uint32 remain_len = 0, i;
1740 uint8 auth_ie_type;
1741 uint16 p_count = 0;
1742 uint16 akm_count;
1743
1744 ASSERT(info != NULL);
1745
1746 /* this function might be called from place where there
1747 * is no error detection.
1748 * e.g. fron the iem callback. Store status here.
1749 */
1750
1751 info->parse_status = BCME_OK;
1752
1753 if (!ie) {
1754 info->parse_status = BCME_BADARG;
1755 goto done;
1756 }
1757
1758 /* For AP, do not zero this structure since there could be multiple
1759 * IEs. In that case, add to the existing
1760 * bits in field (ciphers, akms) as necessary.
1761 */
1762 if (dev_type == DEV_AP) {
1763 /* if already created, check device type */
1764 if (info->dev_type != DEV_NONE) {
1765 if (info->dev_type != DEV_AP) {
1766 info->parse_status = BCME_BADARG;
1767 goto done;
1768 }
1769 }
1770 }
1771 info->dev_type = dev_type;
1772 ptr_inc = ie->data;
1773
1774 /* decode auth IE (WPA vs RSN). Fill in the auth_ie_type and version.
1775 * Modify remain_len to indicate the position of the pointer.
1776 */
1777 /* NOTE the status field will be updated in this call */
1778 if (bcmwpa_decode_ie_type(ie, info, &remain_len, &auth_ie_type) != BCME_OK) {
1779 goto done;
1780 }
1781
1782 /* decode multicast, unicast ciphers */
1783 if (bcmwpa_decode_cipher_suite(info, &ptr_inc, ie->len, &remain_len, &p_count) != BCME_OK) {
1784 goto done;
1785 }
1786
1787 if (!(remain_len)) {
1788 info->akms = BIT(RSN_AKM_UNSPECIFIED);
1789 goto done;
1790 }
1791
1792 mgmt = (const wpa_suite_auth_key_mgmt_t *)ptr_inc;
1793
1794 if (remain_len < sizeof(mgmt->count)) {
1795 info->parse_status = BCME_BADLEN;
1796 goto done;
1797 }
1798
1799 akm_count = ltoh16_ua(&mgmt->count);
1800
1801 if (!akm_count) {
1802 info->parse_status = BCME_BADARG;
1803 goto done;
1804 }
1805
1806 if (dev_type == DEV_STA && akm_count != 1) {
1807 info->parse_status = BCME_BADARG;
1808 goto done;
1809 }
1810
1811 if ((remain_len) < (akm_count * WPA_SUITE_LEN + sizeof(mgmt->count))) {
1812 info->parse_status = BCME_BADLEN;
1813 goto done;
1814 }
1815
1816 if (dev_type == DEV_STA) {
1817 info->sta_akm = mgmt->list[0].type;
1818 }
1819 for (i = 0; i < akm_count; i++) {
1820 if (bcmwpa_is_valid_akm(mgmt->list[i].type) == BCME_OK) {
1821 ASSERT((mgmt->list[i].type) <
1822 (sizeof(info->akms) * NBBY));
1823 info->akms |= BIT(mgmt->list[i].type);
1824 }
1825 }
1826
1827 /* save IE dependent values in their respective fields */
1828 if (dev_type == DEV_AP) {
1829 if (auth_ie_type == RSN_AUTH_IE) {
1830 info->rsn_akms = info->akms;
1831 } else if (auth_ie_type == WPA_AUTH_IE) {
1832 info->wpa_akms = info->akms;
1833 info->wpa_p_ciphers = info->p_ciphers;
1834 }
1835 }
1836
1837 /* as a STA, at this point, we can compute the key descriptor version */
1838 if (dev_type == DEV_STA) {
1839 info->key_desc = wlc_calc_rsn_desc_version(info);
1840 /* For STA, we can set the auth ie */
1841 if (auth_ie_type == RSN_AUTH_IE) {
1842 info->auth_ie = info->rsn_ie;
1843 info->auth_ie_len = info->rsn_ie_len;
1844 } else {
1845 info->auth_ie = info->wpa_ie;
1846 info->auth_ie_len = info->wpa_ie_len;
1847 }
1848 }
1849
1850 /* RSN AKM/cipher suite related EAPOL key length update */
1851 bcmwpa_rsnie_eapol_key_len(info);
1852
1853 /* for rsn capabilities */
1854 ptr_inc += akm_count * WPA_SUITE_LEN + sizeof(mgmt->count);
1855 remain_len -= akm_count * WPA_SUITE_LEN + sizeof(mgmt->count);
1856
1857 if (!(remain_len)) {
1858 goto done;
1859 }
1860 if (remain_len < RSN_CAP_LEN) {
1861 info->parse_status = BCME_BADLEN;
1862 goto done;
1863 }
1864
1865 if (ie->id == DOT11_MNG_RSN_ID) {
1866 info->caps = ltoh16_ua(ptr_inc);
1867 }
1868
1869 /* check if AKMs require MFP capable to be set */
1870 if ((info->akms & RSN_MFPC_AKM_MASK) && !(info->caps & RSN_CAP_MFPC)) {
1871 /* NOTE: Acting as WPA3 CTT testbed device, it requires to send assoc request frame
1872 with user provided mfp value as is. So should not return error here.
1873 */
1874 #ifndef WPA3_CTT
1875 info->parse_status = BCME_EPERM;
1876 goto done;
1877 #endif /* WPA3_CTT */
1878 }
1879
1880 /* for rsn PMKID */
1881 ptr_inc += RSN_CAP_LEN;
1882 remain_len -= RSN_CAP_LEN;
1883
1884 if (!(remain_len)) {
1885 goto done;
1886 }
1887
1888 /* here's possible cases after RSN_CAP parsed
1889 * a) pmkid_count 2B(00 00)
1890 * b) pmkid_count 2B(00 00) + BIP 4B
1891 * c) pmkid_count 2B(non zero) + pmkid_count * 16B
1892 * d) pmkid_count 2B(non zero) + pmkid_count * 16B + BIP 4B
1893 */
1894
1895 /* pmkids_offset set to
1896 * 1) if pmkid_count field(2B) present, point to first PMKID offset in the RSN ID
1897 * no matter what pmkid_count value is. (true, even if pmkid_count == 00 00)
1898 * 2) if pmkid_count field(2B) not present, it shall be zero.
1899 */
1900
1901 pmkid_list = (const wpa_pmkid_list_t*)ptr_inc;
1902
1903 if ((remain_len) < sizeof(pmkid_list->count)) {
1904 info->parse_status = BCME_BADLEN;
1905 goto done;
1906 }
1907
1908 info->pmkid_count = (uint8)ltoh16_ua(&pmkid_list->count);
1909 ptr_inc += sizeof(pmkid_list->count);
1910 remain_len -= sizeof(pmkid_list->count);
1911
1912 if (remain_len < (uint32)(info->pmkid_count * WPA2_PMKID_LEN)) {
1913 info->parse_status = BCME_BADLEN;
1914 goto done;
1915 }
1916
1917 info->pmkids_offset = ie->len + TLV_HDR_LEN - remain_len;
1918 /* for rsn group management cipher suite */
1919 ptr_inc += info->pmkid_count * WPA2_PMKID_LEN;
1920 remain_len -= info->pmkid_count * WPA2_PMKID_LEN;
1921
1922 if (!(remain_len)) {
1923 goto done;
1924 }
1925 /*
1926 * from WPA2_Security_Improvements_Test_Plan_v1.0
1927 * 4.2.4 APUT RSNE bounds verification using WPA2-PSK
1928 * May content RSNE extensibile element ay this point
1929 */
1930 if (remain_len < sizeof(wpa_suite_mcast_t)) {
1931 info->parse_status = BCME_BADLEN;
1932 goto done;
1933 }
1934
1935 mcast = (const wpa_suite_mcast_t *)ptr_inc;
1936 if (IS_VALID_BIP_CIPHER((rsn_cipher_t)mcast->type)) {
1937 info->g_mgmt_cipher = (rsn_cipher_t)mcast->type;
1938 }
1939
1940 done:
1941 return info->parse_status;
1942 }
1943
1944 /* Determine if the IE is of WPA or RSN type. Decode
1945 * up to version field. Modify the remaining len parameter to
1946 * indicate where the next field is.
1947 * Store and return error status.
1948 */
1949
1950 int
bcmwpa_decode_ie_type(const bcm_tlv_t * ie,rsn_ie_info_t * info,uint32 * remaining,uint8 * type)1951 bcmwpa_decode_ie_type(const bcm_tlv_t *ie, rsn_ie_info_t *info, uint32 *remaining,
1952 uint8 *type)
1953 {
1954 const uint8 * ptr_inc = (const uint8 *)ie->data;
1955 uint32 remain_len = ie->len;
1956 uint8 version, version_len;
1957
1958 if (ie->id == DOT11_MNG_WPA_ID) {
1959 /* min len check */
1960 if (remain_len < WPA_IE_FIXED_LEN) {
1961 info->parse_status = BCME_BADLEN;
1962 goto done;
1963 }
1964 /* WPA IE */
1965 if (memcmp(WPA_OUI, ie->data, WPA_OUI_LEN)) {
1966 /* bad OUI */
1967 info->parse_status = BCME_BADARG;
1968 goto done;
1969 }
1970 ptr_inc += WPA_OUI_LEN;
1971 if (*ptr_inc == WPA_OUI_TYPE) {
1972 *type = WPA_AUTH_IE;
1973 } else if (*ptr_inc == WFA_OUI_TYPE_OSEN) {
1974 *type = OSEN_AUTH_IE;
1975 }
1976 else {
1977 /* wrong type */
1978 info->parse_status = BCME_BADARG;
1979 goto done;
1980 }
1981
1982 ptr_inc ++;
1983 remain_len -= WPA_OUI_LEN + 1u;
1984 version_len = WPA_VERSION_LEN;
1985 }
1986 else if (ie->id == DOT11_MNG_RSN_ID) {
1987 if (remain_len < WPA2_VERSION_LEN) {
1988 info->parse_status = BCME_BADLEN;
1989 goto done;
1990 }
1991 /* RSN IE */
1992 *type = RSN_AUTH_IE;
1993 version_len = WPA2_VERSION_LEN;
1994 } else {
1995 printf("IE ID %d\n", ie->id);
1996 /* TODO : add support for CCX, WAPI ? */
1997 info->parse_status = BCME_UNSUPPORTED;
1998 goto done;
1999 }
2000 info->auth_ie_type |= *type;
2001 /* mask down to uint8 for Windows build */
2002 version = 0xff & ltoh16_ua(ptr_inc);
2003 if (version > MAX_RSNE_SUPPORTED_VERSION) {
2004 info->parse_status = BCME_UNSUPPORTED;
2005 goto done;
2006 }
2007
2008 info->version = (uint8)version;
2009 *remaining = remain_len - version_len;
2010 done:
2011 return info->parse_status;
2012 }
2013
2014 /* rsn info allocation management.
2015 *
2016 * In some cases, the rsn ie info structures are embedded in the scan results
2017 * which can be shared by different lists.
2018 * To keep track of their allocation, we use a reference counter.
2019 * The counter is incremented on demand by rsn_ie_info_add_ref()
2020 * at the time the reference is shared.
2021 * It is decremented in rsn_ie_info_rel_ref
2022 * When ref_count gets to 0, bcmwpa_rsn_ie_info_free_mem
2023 * is called to free the whole structure.
2024 */
2025
2026 /* free rsn_ie and wpa_ie, if any, and zero the rsn_info */
2027 void
bcmwpa_rsn_ie_info_reset(rsn_ie_info_t * rsn_info,osl_t * osh)2028 bcmwpa_rsn_ie_info_reset(rsn_ie_info_t *rsn_info, osl_t *osh)
2029 {
2030 uint8 ref_count;
2031 if (rsn_info == NULL) {
2032 return;
2033 }
2034 ref_count = rsn_info->ref_count;
2035 MFREE(osh, rsn_info->rsn_ie, rsn_info->rsn_ie_len);
2036 MFREE(osh, rsn_info->wpa_ie, rsn_info->wpa_ie_len);
2037 MFREE(osh, rsn_info->rsnxe, rsn_info->rsnxe_len);
2038 bzero(rsn_info, sizeof(*rsn_info));
2039 rsn_info->ref_count = ref_count;
2040
2041 }
2042
2043 static
bcmwpa_rsn_ie_info_free_mem(rsn_ie_info_t ** rsn_info,osl_t * osh)2044 void bcmwpa_rsn_ie_info_free_mem(rsn_ie_info_t **rsn_info, osl_t *osh)
2045 {
2046 bcmwpa_rsn_ie_info_reset(*rsn_info, osh);
2047 MFREE(osh, *rsn_info, sizeof(**rsn_info));
2048 *rsn_info = NULL;
2049 }
2050
bcmwpa_rsn_ie_info_rel_ref(rsn_ie_info_t ** rsn_info,osl_t * osh)2051 void bcmwpa_rsn_ie_info_rel_ref(rsn_ie_info_t **rsn_info, osl_t *osh)
2052 {
2053
2054 if (rsn_info == NULL || *rsn_info == NULL) {
2055 return;
2056 }
2057
2058 /* already freed ? */
2059 if ((*rsn_info)->ref_count == 0) {
2060 ASSERT(0);
2061 return;
2062 }
2063 /* decrement ref count */
2064 (*rsn_info)->ref_count -= 1;
2065 /* clear reference. */
2066 if ((*rsn_info)->ref_count > 0) {
2067 *rsn_info = NULL;
2068 return;
2069 }
2070 /* free memory and clear reference */
2071 bcmwpa_rsn_ie_info_free_mem(rsn_info, osh);
2072 }
2073
2074 int
bcmwpa_rsn_ie_info_add_ref(rsn_ie_info_t * rsn_info)2075 bcmwpa_rsn_ie_info_add_ref(rsn_ie_info_t *rsn_info)
2076 {
2077 int status = BCME_OK;
2078 if (rsn_info == NULL) {
2079 goto done;
2080 }
2081 if (rsn_info->ref_count == 0) {
2082 /* don't increase from 0, which means this structure has been freed earlier.
2083 * That reference should not exist anymore.
2084 */
2085 ASSERT(0);
2086 status = BCME_BADARG;
2087 goto done;
2088 }
2089 rsn_info->ref_count++;
2090 done:
2091 return status;
2092 }
2093
2094 #else /* Not RSN_IE_INFO_STRUCT_RELOCATED */
2095
2096 int
bcmwpa_parse_rsnie(const bcm_tlv_t * ie,rsn_ie_info_t * info,device_type_t dev_type)2097 bcmwpa_parse_rsnie(const bcm_tlv_t *ie, rsn_ie_info_t *info, device_type_t dev_type)
2098 {
2099
2100 const uint8 *ptr_inc = NULL;
2101 const wpa_suite_ucast_t *ucast;
2102 const wpa_suite_mcast_t *mcast;
2103 const wpa_suite_auth_key_mgmt_t *mgmt;
2104 const wpa_pmkid_list_t *pmkid_list;
2105 uint32 remain_len = 0, i;
2106
2107 ASSERT(info != NULL);
2108
2109 /* this function might be called from place where there
2110 * is no error detection.
2111 * e.g. fron the iem callback. Store status here.
2112 */
2113
2114 info->parse_status = BCME_OK;
2115
2116 if (!ie) {
2117 info->parse_status = BCME_BADARG;
2118 goto done;
2119 }
2120
2121 /* For AP, do not zero this structure since there could be multiple
2122 * IEs. In that case, add to the existing
2123 * bits in field (ciphers, akms) as necessary.
2124 */
2125 if (dev_type != DEV_AP) {
2126 bzero(info, sizeof(*info));
2127 } else {
2128 /* if already created, check device type */
2129 if (info->dev_type != DEV_NONE) {
2130 if (info->dev_type != DEV_AP) {
2131 info->parse_status = BCME_BADARG;
2132 goto done;
2133 }
2134 }
2135 }
2136 info->dev_type = dev_type;
2137 ptr_inc = ie->data;
2138
2139 /* decode auth IE (WPA vs RSN). Fill in the auth_ie_type and version.
2140 * Modify remain_len to indicate the position of the pointer.
2141 */
2142 /* NOTE the status field will be updated in this call */
2143 if (bcmwpa_decode_ie_type(ie, info, &remain_len) != BCME_OK) {
2144 goto done;
2145 }
2146
2147 if (!(remain_len)) {
2148 info->g_cipher = WPA_CIPHER_NONE;
2149 goto done; /* only have upto ver */
2150 }
2151 ptr_inc += ie->len - remain_len;
2152
2153 if (remain_len < sizeof(wpa_suite_mcast_t)) {
2154 info->parse_status = BCME_BADLEN;
2155 goto done;
2156 }
2157 mcast = (const wpa_suite_mcast_t *)ptr_inc;
2158
2159 if (IS_WPA_CIPHER(mcast->type)) {
2160 info->g_cipher = mcast->type;
2161 }
2162
2163 /* for rsn pairwise cipher suite */
2164 ptr_inc += sizeof(wpa_suite_mcast_t);
2165 remain_len -= sizeof(wpa_suite_mcast_t);
2166
2167 if (!(remain_len)) {
2168 goto done;
2169 }
2170
2171 ucast = (const wpa_suite_ucast_t *)ptr_inc;
2172
2173 if ((remain_len) < sizeof(ucast->count)) {
2174 info->parse_status = BCME_BADLEN;
2175 goto done;
2176 }
2177
2178 if (!ucast->count.low && !ucast->count.high) {
2179 info->parse_status = BCME_BADLEN;
2180 goto done;
2181 }
2182
2183 info->p_count = (uint8)ltoh16_ua(&ucast->count);
2184
2185 if (dev_type == DEV_STA && info->p_count != 1) {
2186 info->parse_status = BCME_BADARG;
2187 goto done;
2188 }
2189 if ((remain_len) < (info->p_count * WPA_SUITE_LEN + sizeof(ucast->count))) {
2190 info->parse_status = BCME_BADLEN;
2191 goto done;
2192 }
2193
2194 if (IS_WPA_CIPHER(ucast->list[0].type)) {
2195 /* update the pairwise cipher */
2196 /* set cipher to invald value */
2197 if (dev_type == DEV_STA) {
2198 info->sta_cipher = ucast->list[0].type;
2199 } else {
2200 for (i = 0; i < info->p_count; i++) {
2201 if (IS_WPA_CIPHER(ucast->list[i].type)) {
2202 info->p_ciphers |= BIT(ucast->list[i].type);
2203 } else {
2204 info->parse_status = BCME_BAD_IE_DATA;
2205 goto done;
2206 }
2207 }
2208 }
2209 } else {
2210 info->parse_status = BCME_BAD_IE_DATA;
2211 goto done;
2212 }
2213
2214 /* for rsn AKM authentication */
2215 ptr_inc += info->p_count * WPA_SUITE_LEN + sizeof(ucast->count);
2216 remain_len -= (info->p_count * WPA_SUITE_LEN + sizeof(ucast->count));
2217
2218 mgmt = (const wpa_suite_auth_key_mgmt_t *)ptr_inc;
2219
2220 if (remain_len < sizeof(mgmt->count)) {
2221 info->parse_status = BCME_BADLEN;
2222 goto done;
2223 }
2224
2225 info->akm_count = (uint8)ltoh16_ua(&mgmt->count);
2226
2227 if (!info->akm_count) {
2228 info->parse_status = BCME_BADARG;
2229 goto done;
2230 }
2231
2232 if (dev_type == DEV_STA && info->akm_count != 1) {
2233 info->parse_status = BCME_BADARG;
2234 goto done;
2235 }
2236
2237 if ((remain_len) < (info->akm_count * WPA_SUITE_LEN + sizeof(mgmt->count))) {
2238 info->parse_status = BCME_BADLEN;
2239 goto done;
2240 }
2241
2242 if (dev_type == DEV_STA) {
2243 info->sta_akm = mgmt->list[0].type;
2244 }
2245 for (i = 0; i < info->akm_count; i++) {
2246 if (bcmwpa_is_valid_akm(mgmt->list[i].type) == BCME_OK) {
2247 ASSERT((mgmt->list[i].type) <
2248 (sizeof(info->akms) * NBBY));
2249 info->akms |= BIT(mgmt->list[i].type);
2250 }
2251 }
2252
2253 /* RSN AKM/cipher suite related EAPOL key length update */
2254 info->pmk_len = bcmwpa_eapol_key_length(EAPOL_KEY_PMK, info->sta_akm, 0);
2255 info->kck_mic_len = bcmwpa_eapol_key_length(EAPOL_KEY_KCK_MIC, info->sta_akm, 0);
2256 info->kck_len = bcmwpa_eapol_key_length(EAPOL_KEY_KCK, info->sta_akm, 0);
2257 info->kek_len = bcmwpa_eapol_key_length(EAPOL_KEY_KEK, info->sta_akm, 0);
2258 info->tk_len = bcmwpa_eapol_key_length(EAPOL_KEY_TK, 0, info->sta_cipher);
2259 info->ptk_len = info->kck_mic_len + info->kek_len + info->tk_len;
2260 #if defined(WL_FILS) && defined(WLFBT)
2261 info->kck2_len = bcmwpa_eapol_key_length(EAPOL_KEY_KCK2, info->sta_akm, 0);
2262 info->kek2_len = bcmwpa_eapol_key_length(EAPOL_KEY_KEK2, info->sta_akm, 0);
2263 #endif /* WL_FILS && WLFBT */
2264
2265 /* for rsn capabilities */
2266 ptr_inc += info->akm_count * WPA_SUITE_LEN + sizeof(mgmt->count);
2267 remain_len -= info->akm_count * WPA_SUITE_LEN + sizeof(mgmt->count);
2268
2269 /* as a STA, at this point, we can compute the key descriptor version */
2270 if (dev_type == DEV_STA) {
2271 info->key_desc = wlc_calc_rsn_desc_version(info);
2272 }
2273
2274 if (!(remain_len)) {
2275 goto done;
2276 }
2277 if (remain_len < RSN_CAP_LEN) {
2278 info->parse_status = BCME_BADLEN;
2279 goto done;
2280 }
2281
2282 if (ie->id == DOT11_MNG_RSN_ID) {
2283 info->caps = ltoh16_ua(ptr_inc);
2284 }
2285
2286 /* for WFA If MFP required, check that we are using a SHA256 AKM
2287 * or higher and nothing else.
2288 * In case MFP Required and MFP Capable do not enforce check of AKM.
2289 */
2290 if ((info->caps & RSN_CAP_MFPR) && !(info->akms & (1u << RSN_AKM_PSK))) {
2291 if ((info->akms & (AKM_SHA256_MASK | AKM_SHA384_MASK)) == 0 ||
2292 (info->akms & ~(AKM_SHA256_MASK | AKM_SHA384_MASK))) {
2293 info->parse_status = BCME_EPERM;
2294 goto done;
2295 }
2296 }
2297
2298 /* check if AKMs require MFP capable to be set */
2299 if ((info->akms & RSN_MFPC_AKM_MASK) && !(info->caps & RSN_CAP_MFPC)) {
2300 info->parse_status = BCME_EPERM;
2301 goto done;
2302 }
2303
2304 /* for rsn PMKID */
2305 ptr_inc += RSN_CAP_LEN;
2306 remain_len -= RSN_CAP_LEN;
2307
2308 if (!(remain_len)) {
2309 goto done;
2310 }
2311
2312 pmkid_list = (const wpa_pmkid_list_t*)ptr_inc;
2313
2314 if ((remain_len) < sizeof(pmkid_list->count)) {
2315 info->parse_status = BCME_BADLEN;
2316 goto done;
2317 }
2318
2319 info->pmkid_count = (uint8)ltoh16_ua(&pmkid_list->count);
2320 ptr_inc += sizeof(pmkid_list->count);
2321 remain_len -= sizeof(pmkid_list->count);
2322
2323 if (info->pmkid_count) {
2324 if (remain_len < (uint32)(info->pmkid_count * WPA2_PMKID_LEN)) {
2325 info->parse_status = BCME_BADLEN;
2326 goto done;
2327 }
2328 info->pmkids_offset = ie->len + TLV_HDR_LEN - remain_len;
2329 /* for rsn group management cipher suite */
2330 ptr_inc += info->pmkid_count * WPA2_PMKID_LEN;
2331 remain_len -= info->pmkid_count * WPA2_PMKID_LEN;
2332 }
2333
2334 if (!(remain_len)) {
2335 goto done;
2336 }
2337 /*
2338 * from WPA2_Security_Improvements_Test_Plan_v1.0
2339 * 4.2.4 APUT RSNE bounds verification using WPA2-PSK
2340 * May content RSNE extensibile element ay this point
2341 */
2342 if (remain_len < sizeof(wpa_suite_mcast_t)) {
2343 info->parse_status = BCME_BADLEN;
2344 goto done;
2345 }
2346
2347 mcast = (const wpa_suite_mcast_t *)ptr_inc;
2348 if (IS_VALID_BIP_CIPHER((rsn_cipher_t)mcast->type)) {
2349 info->g_mgmt_cipher = (rsn_cipher_t)mcast->type;
2350 }
2351
2352 done:
2353 return info->parse_status;
2354 }
2355
2356 /* Determine if the IE is of WPA or RSN type. Decode
2357 * up to version field. Modify the remaining len parameter to
2358 * indicate where the next field is.
2359 * Store and return error status.
2360 */
2361
2362 int
bcmwpa_decode_ie_type(const bcm_tlv_t * ie,rsn_ie_info_t * info,uint32 * remaining)2363 bcmwpa_decode_ie_type(const bcm_tlv_t *ie, rsn_ie_info_t *info, uint32 *remaining)
2364 {
2365 const uint8 * ptr_inc = (const uint8 *)ie->data;
2366 uint32 remain_len = ie->len;
2367 uint8 version, version_len;
2368
2369 if (ie->id == DOT11_MNG_WPA_ID) {
2370 /* min len check */
2371 if (remain_len < WPA_IE_FIXED_LEN) {
2372 info->parse_status = BCME_BADLEN;
2373 goto done;
2374 }
2375 /* WPA IE */
2376 if (memcmp(WPA_OUI, ie->data, WPA_OUI_LEN)) {
2377 /* bad OUI */
2378 info->parse_status = BCME_BADARG;
2379 goto done;
2380 }
2381 ptr_inc += WPA_OUI_LEN;
2382 if (*ptr_inc != WPA_OUI_TYPE) {
2383 /* wrong type */
2384 info->parse_status = BCME_BADARG;
2385 goto done;
2386 }
2387 ptr_inc ++;
2388 remain_len -= WPA_OUI_LEN + 1u;
2389 info->auth_ie_type |= WPA_AUTH_IE;
2390 version_len = WPA_VERSION_LEN;
2391 }
2392 else if (ie->id == DOT11_MNG_RSN_ID) {
2393 if (remain_len < WPA2_VERSION_LEN) {
2394 info->parse_status = BCME_BADLEN;
2395 goto done;
2396 }
2397 /* RSN IE */
2398 info->auth_ie_type |= RSN_AUTH_IE;
2399 version_len = WPA2_VERSION_LEN;
2400 } else {
2401 /* TODO : add support for CCX, WAPI ? */
2402 info->parse_status = BCME_UNSUPPORTED;
2403 goto done;
2404 }
2405
2406 /* mask down to uint8 for Windows build */
2407 version = 0xff & ltoh16_ua(ptr_inc);
2408 if (version > MAX_RSNE_SUPPORTED_VERSION) {
2409 info->parse_status = BCME_UNSUPPORTED;
2410 goto done;
2411 }
2412
2413 info->version = (uint8)version;
2414 *remaining = remain_len - version_len;
2415 done:
2416 return info->parse_status;
2417 }
2418
2419 #endif /* RSN_IE_INFO_STRUCT_RELOCATED */
2420
2421 /* return the key descriptor version based on the AKM suite
2422 * applicable only for STA with RSN
2423 */
2424 static uint16
wlc_calc_rsn_desc_version(const rsn_ie_info_t * rsn_info)2425 wlc_calc_rsn_desc_version(const rsn_ie_info_t *rsn_info)
2426 {
2427 uint16 key_desc_ver = WPA_KEY_DESC_V0;
2428 uint8 akm;
2429
2430 ASSERT(rsn_info != NULL);
2431 ASSERT(rsn_info->dev_type == DEV_STA);
2432 akm = rsn_info->sta_akm;
2433
2434 /* Refer Draft 802.11REVmd_D1.0.pdf Section 12.7.2 */
2435 if ((akm == RSN_AKM_UNSPECIFIED) ||
2436 (akm == RSN_AKM_PSK)) {
2437 if ((rsn_info->sta_cipher == WPA_CIPHER_TKIP) ||
2438 (rsn_info->sta_cipher == WPA_CIPHER_NONE)) {
2439 key_desc_ver = WPA_KEY_DESC_V1;
2440 } else if ((rsn_info->sta_cipher != WPA_CIPHER_TKIP) ||
2441 (rsn_info->g_cipher != WPA_CIPHER_TKIP)) {
2442 key_desc_ver = WPA_KEY_DESC_V2;
2443 }
2444 } else if ((akm == RSN_AKM_FBT_1X) ||
2445 (akm == RSN_AKM_FBT_PSK) ||
2446 (akm == RSN_AKM_SHA256_1X) ||
2447 (akm == RSN_AKM_SHA256_PSK)) {
2448 key_desc_ver = WPA_KEY_DESC_V3;
2449 }
2450 return key_desc_ver;
2451 }
2452
2453 /* get EAPOL key length based on RSN IE AKM/Cipher(unicast) suite
2454 * key: EAPOL key type
2455 * akm: RSN AKM suite selector
2456 * cipher: RSN unicast cipher suite selector
2457 * return: key length found in matching key_length_entry table
2458 */
2459 uint8
bcmwpa_eapol_key_length(eapol_key_type_t key,rsn_akm_t akm,rsn_cipher_t cipher)2460 bcmwpa_eapol_key_length(eapol_key_type_t key, rsn_akm_t akm, rsn_cipher_t cipher)
2461 {
2462 uint i;
2463 uint8 key_length = 0;
2464 uint8 suite;
2465 const key_length_entry_t *key_entry = NULL;
2466
2467 if (key == EAPOL_KEY_TK) {
2468 suite = cipher;
2469 } else {
2470 suite = akm;
2471 }
2472 for (i = 0; i < ARRAYSIZE(eapol_key_lookup_tbl); i++) {
2473 if (eapol_key_lookup_tbl[i].key == key) {
2474 key_entry = eapol_key_lookup_tbl[i].key_entry;
2475 break;
2476 }
2477 }
2478
2479 if (key_entry) {
2480 i = 0;
2481 do {
2482 if (key_entry[i].suite == suite || key_entry[i].suite == 0) {
2483 key_length = key_entry[i].len;
2484 break;
2485 }
2486 i++;
2487 } while (i > 0);
2488 }
2489
2490 return key_length;
2491 }
2492
2493 /* check if RSM AKM suite is valid */
bcmwpa_is_valid_akm(const rsn_akm_t akm)2494 static int bcmwpa_is_valid_akm(const rsn_akm_t akm)
2495 {
2496 uint i = 0;
2497 for (i = 0; i < ARRAYSIZE(rsn_akm_lookup_tbl); i++) {
2498 if (akm == rsn_akm_lookup_tbl[i].rsn_akm) {
2499 return BCME_OK;
2500 }
2501 }
2502 return BCME_ERROR;
2503 }
2504
2505 /* checking cipher suite selector restriction based on AKM */
2506 int
bcmwpa_rsn_akm_cipher_match(rsn_ie_info_t * rsn_info)2507 bcmwpa_rsn_akm_cipher_match(rsn_ie_info_t *rsn_info)
2508 {
2509 uint i;
2510 const rsn_akm_cipher_match_entry_t *p_entry = NULL;
2511
2512 for (i = 0; i < ARRAYSIZE(rsn_akm_cipher_match_table); i++) {
2513 /* akm match */
2514 if (rsn_info->sta_akm == rsn_akm_cipher_match_table[i].akm_type) {
2515 p_entry = &rsn_akm_cipher_match_table[i];
2516 break;
2517 }
2518 }
2519
2520 if (p_entry) {
2521 /* unicast cipher match */
2522 if (!(rsn_info->p_ciphers & p_entry->u_cast)) {
2523 return BCME_UNSUPPORTED;
2524 }
2525 /* multicast cipher match */
2526 if (!(BCM_BIT(rsn_info->g_cipher) & p_entry->m_cast)) {
2527 return BCME_UNSUPPORTED;
2528 }
2529 /* group management cipher match */
2530 if (!(BCM_BIT(rsn_info->g_mgmt_cipher) & p_entry->g_mgmt)) {
2531 return BCME_UNSUPPORTED;
2532 }
2533 }
2534 return BCME_OK;
2535 }
2536
2537 #if defined(BCMSUP_PSK) || defined(BCMSUPPL)
bcmwpa_find_group_mgmt_algo(rsn_cipher_t g_mgmt_cipher)2538 uint8 bcmwpa_find_group_mgmt_algo(rsn_cipher_t g_mgmt_cipher)
2539 {
2540 uint8 i;
2541 uint8 algo = CRYPTO_ALGO_BIP;
2542
2543 for (i = 0; i < ARRAYSIZE(group_mgmt_cipher_algo); i++) {
2544 if ((group_mgmt_cipher_algo[i].g_mgmt_cipher == g_mgmt_cipher)) {
2545 algo = group_mgmt_cipher_algo[i].bip_algo;
2546 break;
2547 }
2548 }
2549
2550 return algo;
2551 }
2552 #endif /* defined(BCMSUP_PSK) || defined(BCMSUPPL) */
2553
2554 #if defined(WL_BAND6G)
2555 bool
bcmwpa_is_invalid_6g_akm(const rsn_akm_mask_t akms_bmp)2556 bcmwpa_is_invalid_6g_akm(const rsn_akm_mask_t akms_bmp)
2557 {
2558 if (akms_bmp & rsn_akm_6g_inval_mask) {
2559 return TRUE;
2560 }
2561 return FALSE;
2562 }
2563
2564 bool
bcmwpa_is_invalid_6g_cipher(const rsn_ciphers_t ciphers_bmp)2565 bcmwpa_is_invalid_6g_cipher(const rsn_ciphers_t ciphers_bmp)
2566 {
2567 if (ciphers_bmp & cipher_6g_inval_mask) {
2568 return TRUE;
2569 }
2570 return FALSE;
2571 }
2572 #endif /* WL_BAND6G */
2573
2574 /*
2575 * bcmwpa_get_algo_key_len returns the key_length for the algorithm.
2576 * API : bcm_get_algorithm key length
2577 * input: algo: Get the crypto algorithm.
2578 * km: Keymgmt information.
2579 * output: returns the key length and error status.
2580 * BCME_OK is valid else BCME_UNSUPPORTED if not supported
2581 */
2582 int
bcmwpa_get_algo_key_len(uint8 algo,uint16 * key_len)2583 bcmwpa_get_algo_key_len(uint8 algo, uint16 *key_len)
2584 {
2585 int err = BCME_OK;
2586
2587 if (key_len == NULL) {
2588 return BCME_BADARG;
2589 }
2590
2591 switch (algo) {
2592 case CRYPTO_ALGO_WEP1:
2593 *key_len = WEP1_KEY_SIZE;
2594 break;
2595
2596 case CRYPTO_ALGO_TKIP:
2597 *key_len = TKIP_KEY_SIZE;
2598 break;
2599
2600 case CRYPTO_ALGO_WEP128:
2601 *key_len = WEP128_KEY_SIZE;
2602 break;
2603
2604 case CRYPTO_ALGO_AES_CCM: /* fall through */
2605 case CRYPTO_ALGO_AES_GCM: /* fall through */
2606 case CRYPTO_ALGO_AES_OCB_MSDU : /* fall through */
2607 case CRYPTO_ALGO_AES_OCB_MPDU:
2608 *key_len = AES_KEY_SIZE;
2609 break;
2610
2611 #ifdef BCMWAPI_WPI
2612 /* TODO: Need to double check */
2613 case CRYPTO_ALGO_SMS4:
2614 *key_len = SMS4_KEY_LEN + SMS4_WPI_CBC_MAC_LEN;
2615 break;
2616 #endif /* BCMWAPI_WPI */
2617
2618 case CRYPTO_ALGO_BIP: /* fall through */
2619 case CRYPTO_ALGO_BIP_GMAC:
2620 *key_len = BIP_KEY_SIZE;
2621 break;
2622
2623 case CRYPTO_ALGO_AES_CCM256: /* fall through */
2624 case CRYPTO_ALGO_AES_GCM256: /* fall through */
2625 case CRYPTO_ALGO_BIP_CMAC256: /* fall through */
2626 case CRYPTO_ALGO_BIP_GMAC256:
2627 *key_len = AES256_KEY_SIZE;
2628 break;
2629
2630 case CRYPTO_ALGO_OFF:
2631 *key_len = 0;
2632 break;
2633
2634 #if !defined(BCMCCX) && !defined(BCMEXTCCX)
2635 case CRYPTO_ALGO_NALG: /* fall through */
2636 #else
2637 case CRYPTO_ALGO_CKIP: /* fall through */
2638 case CRYPTO_ALGO_CKIP_MMH: /* fall through */
2639 case CRYPTO_ALGO_WEP_MMH: /* fall through */
2640 case CRYPTO_ALGO_PMK: /* fall through default */
2641 #endif /* !defined(BCMCCX) && !defined(BCMEXTCCX) */
2642 default:
2643 *key_len = 0;
2644 err = BCME_UNSUPPORTED;
2645 break;
2646 }
2647 return err;
2648 }
2649