]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/common/wpa_common.c
FT: EAPOL-Key MIC calculation using SHA384-based AKM
[thirdparty/hostap.git] / src / common / wpa_common.c
CommitLineData
6fc6879b
JM
1/*
2 * WPA/RSN - Shared functions for supplicant and authenticator
c22bb5bb 3 * Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi>
6fc6879b 4 *
0f3d578e
JM
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
6fc6879b
JM
7 */
8
9#include "includes.h"
10
11#include "common.h"
03da66bd
JM
12#include "crypto/md5.h"
13#include "crypto/sha1.h"
14#include "crypto/sha256.h"
5e3b5197 15#include "crypto/sha384.h"
567da5bb 16#include "crypto/sha512.h"
03da66bd
JM
17#include "crypto/aes_wrap.h"
18#include "crypto/crypto.h"
6fc6879b
JM
19#include "ieee802_11_defs.h"
20#include "defs.h"
21#include "wpa_common.h"
22
23
567da5bb 24static unsigned int wpa_kck_len(int akmp, size_t pmk_len)
98cd3d1c 25{
94318a0d
JM
26 switch (akmp) {
27 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
c22bb5bb 28 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
5e3b5197 29 return 24;
94318a0d
JM
30 case WPA_KEY_MGMT_FILS_SHA256:
31 case WPA_KEY_MGMT_FT_FILS_SHA256:
32 case WPA_KEY_MGMT_FILS_SHA384:
33 case WPA_KEY_MGMT_FT_FILS_SHA384:
34 return 0;
567da5bb
JM
35 case WPA_KEY_MGMT_DPP:
36 return pmk_len / 2;
6c472618
JM
37 case WPA_KEY_MGMT_OWE:
38 return pmk_len / 2;
94318a0d
JM
39 default:
40 return 16;
41 }
98cd3d1c
JM
42}
43
44
2f373878
JM
45#ifdef CONFIG_IEEE80211R
46static unsigned int wpa_kck2_len(int akmp)
47{
48 switch (akmp) {
49 case WPA_KEY_MGMT_FT_FILS_SHA256:
50 return 16;
51 case WPA_KEY_MGMT_FT_FILS_SHA384:
52 return 24;
53 default:
54 return 0;
55 }
56}
57#endif /* CONFIG_IEEE80211R */
58
59
567da5bb 60static unsigned int wpa_kek_len(int akmp, size_t pmk_len)
98cd3d1c 61{
94318a0d
JM
62 switch (akmp) {
63 case WPA_KEY_MGMT_FILS_SHA384:
64 case WPA_KEY_MGMT_FT_FILS_SHA384:
65 return 64;
66 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
67 case WPA_KEY_MGMT_FILS_SHA256:
68 case WPA_KEY_MGMT_FT_FILS_SHA256:
c22bb5bb 69 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
5e3b5197 70 return 32;
567da5bb
JM
71 case WPA_KEY_MGMT_DPP:
72 return pmk_len <= 32 ? 16 : 32;
6c472618
JM
73 case WPA_KEY_MGMT_OWE:
74 return pmk_len <= 32 ? 16 : 32;
94318a0d
JM
75 default:
76 return 16;
77 }
5e3b5197
JM
78}
79
80
2f373878
JM
81#ifdef CONFIG_IEEE80211R
82static unsigned int wpa_kek2_len(int akmp)
83{
84 switch (akmp) {
85 case WPA_KEY_MGMT_FT_FILS_SHA256:
86 return 16;
87 case WPA_KEY_MGMT_FT_FILS_SHA384:
88 return 32;
89 default:
90 return 0;
91 }
92}
93#endif /* CONFIG_IEEE80211R */
94
95
567da5bb 96unsigned int wpa_mic_len(int akmp, size_t pmk_len)
5e3b5197 97{
94318a0d
JM
98 switch (akmp) {
99 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
c22bb5bb 100 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
5e3b5197 101 return 24;
94318a0d
JM
102 case WPA_KEY_MGMT_FILS_SHA256:
103 case WPA_KEY_MGMT_FILS_SHA384:
104 case WPA_KEY_MGMT_FT_FILS_SHA256:
105 case WPA_KEY_MGMT_FT_FILS_SHA384:
106 return 0;
567da5bb
JM
107 case WPA_KEY_MGMT_DPP:
108 return pmk_len / 2;
6c472618
JM
109 case WPA_KEY_MGMT_OWE:
110 return pmk_len / 2;
94318a0d
JM
111 default:
112 return 16;
113 }
98cd3d1c
JM
114}
115
116
4bc801ab
JM
117/**
118 * wpa_use_akm_defined - Is AKM-defined Key Descriptor Version used
119 * @akmp: WPA_KEY_MGMT_* used in key derivation
120 * Returns: 1 if AKM-defined Key Descriptor Version is used; 0 otherwise
121 */
122int wpa_use_akm_defined(int akmp)
123{
124 return akmp == WPA_KEY_MGMT_OSEN ||
125 akmp == WPA_KEY_MGMT_OWE ||
126 akmp == WPA_KEY_MGMT_DPP ||
c22bb5bb 127 akmp == WPA_KEY_MGMT_FT_IEEE8021X_SHA384 ||
4bc801ab
JM
128 wpa_key_mgmt_sae(akmp) ||
129 wpa_key_mgmt_suite_b(akmp) ||
130 wpa_key_mgmt_fils(akmp);
131}
132
133
134/**
135 * wpa_use_cmac - Is CMAC integrity algorithm used for EAPOL-Key MIC
136 * @akmp: WPA_KEY_MGMT_* used in key derivation
137 * Returns: 1 if CMAC is used; 0 otherwise
138 */
139int wpa_use_cmac(int akmp)
140{
141 return akmp == WPA_KEY_MGMT_OSEN ||
142 akmp == WPA_KEY_MGMT_OWE ||
143 akmp == WPA_KEY_MGMT_DPP ||
144 wpa_key_mgmt_ft(akmp) ||
145 wpa_key_mgmt_sha256(akmp) ||
146 wpa_key_mgmt_sae(akmp) ||
147 wpa_key_mgmt_suite_b(akmp);
148}
149
150
151/**
152 * wpa_use_aes_key_wrap - Is AES Keywrap algorithm used for EAPOL-Key Key Data
153 * @akmp: WPA_KEY_MGMT_* used in key derivation
154 * Returns: 1 if AES Keywrap is used; 0 otherwise
155 *
156 * Note: AKM 00-0F-AC:1 and 00-0F-AC:2 have special rules for selecting whether
157 * to use AES Keywrap based on the negotiated pairwise cipher. This function
158 * does not cover those special cases.
159 */
160int wpa_use_aes_key_wrap(int akmp)
161{
162 return akmp == WPA_KEY_MGMT_OSEN ||
163 akmp == WPA_KEY_MGMT_OWE ||
164 akmp == WPA_KEY_MGMT_DPP ||
165 wpa_key_mgmt_ft(akmp) ||
166 wpa_key_mgmt_sha256(akmp) ||
167 wpa_key_mgmt_sae(akmp) ||
168 wpa_key_mgmt_suite_b(akmp);
169}
170
171
6fc6879b
JM
172/**
173 * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
174 * @key: EAPOL-Key Key Confirmation Key (KCK)
98cd3d1c 175 * @key_len: KCK length in octets
929a2ea5 176 * @akmp: WPA_KEY_MGMT_* used in key derivation
6fc6879b
JM
177 * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
178 * @buf: Pointer to the beginning of the EAPOL header (version field)
179 * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
180 * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written
181 * Returns: 0 on success, -1 on failure
182 *
183 * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has
184 * to be cleared (all zeroes) when calling this function.
185 *
186 * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the
187 * description of the Key MIC calculation. It includes packet data from the
188 * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change
189 * happened during final editing of the standard and the correct behavior is
190 * defined in the last draft (IEEE 802.11i/D10).
191 */
98cd3d1c
JM
192int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
193 const u8 *buf, size_t len, u8 *mic)
6fc6879b 194{
567da5bb 195 u8 hash[SHA512_MAC_LEN];
6fc6879b 196
a6ea6653
JM
197 if (key_len == 0) {
198 wpa_printf(MSG_DEBUG,
199 "WPA: KCK not set - cannot calculate MIC");
200 return -1;
201 }
202
6fc6879b 203 switch (ver) {
6e6909a9 204#ifndef CONFIG_FIPS
6fc6879b 205 case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
ef9627cb 206 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-MD5");
98cd3d1c 207 return hmac_md5(key, key_len, buf, len, mic);
6e6909a9 208#endif /* CONFIG_FIPS */
6fc6879b 209 case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
ef9627cb 210 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-SHA1");
98cd3d1c 211 if (hmac_sha1(key, key_len, buf, len, hash))
04b6b3ed 212 return -1;
6fc6879b
JM
213 os_memcpy(mic, hash, MD5_MAC_LEN);
214 break;
a20088e5 215#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
6fc6879b 216 case WPA_KEY_INFO_TYPE_AES_128_CMAC:
ef9627cb 217 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using AES-CMAC");
6fc6879b 218 return omac1_aes_128(key, buf, len, mic);
a20088e5 219#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
a5d75636 220 case WPA_KEY_INFO_TYPE_AKM_DEFINED:
929a2ea5 221 switch (akmp) {
4bc801ab
JM
222#ifdef CONFIG_SAE
223 case WPA_KEY_MGMT_SAE:
224 case WPA_KEY_MGMT_FT_SAE:
225 wpa_printf(MSG_DEBUG,
226 "WPA: EAPOL-Key MIC using AES-CMAC (AKM-defined - SAE)");
227 return omac1_aes_128(key, buf, len, mic);
228#endif /* CONFIG_SAE */
929a2ea5
JM
229#ifdef CONFIG_HS20
230 case WPA_KEY_MGMT_OSEN:
ef9627cb
JM
231 wpa_printf(MSG_DEBUG,
232 "WPA: EAPOL-Key MIC using AES-CMAC (AKM-defined - OSEN)");
929a2ea5 233 return omac1_aes_128(key, buf, len, mic);
a5d75636 234#endif /* CONFIG_HS20 */
929a2ea5
JM
235#ifdef CONFIG_SUITEB
236 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
ef9627cb
JM
237 wpa_printf(MSG_DEBUG,
238 "WPA: EAPOL-Key MIC using HMAC-SHA256 (AKM-defined - Suite B)");
98cd3d1c 239 if (hmac_sha256(key, key_len, buf, len, hash))
929a2ea5
JM
240 return -1;
241 os_memcpy(mic, hash, MD5_MAC_LEN);
242 break;
243#endif /* CONFIG_SUITEB */
5e3b5197
JM
244#ifdef CONFIG_SUITEB192
245 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
ef9627cb
JM
246 wpa_printf(MSG_DEBUG,
247 "WPA: EAPOL-Key MIC using HMAC-SHA384 (AKM-defined - Suite B 192-bit)");
5e3b5197
JM
248 if (hmac_sha384(key, key_len, buf, len, hash))
249 return -1;
250 os_memcpy(mic, hash, 24);
251 break;
252#endif /* CONFIG_SUITEB192 */
07a5fe82
JM
253#ifdef CONFIG_OWE
254 case WPA_KEY_MGMT_OWE:
255 wpa_printf(MSG_DEBUG,
6c472618
JM
256 "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - OWE)",
257 (unsigned int) key_len * 8 * 2);
258 if (key_len == 128 / 8) {
259 if (hmac_sha256(key, key_len, buf, len, hash))
260 return -1;
261 } else if (key_len == 192 / 8) {
262 if (hmac_sha384(key, key_len, buf, len, hash))
263 return -1;
264 } else if (key_len == 256 / 8) {
265 if (hmac_sha512(key, key_len, buf, len, hash))
266 return -1;
267 } else {
268 wpa_printf(MSG_INFO,
269 "OWE: Unsupported KCK length: %u",
270 (unsigned int) key_len);
07a5fe82 271 return -1;
6c472618
JM
272 }
273 os_memcpy(mic, hash, key_len);
07a5fe82
JM
274 break;
275#endif /* CONFIG_OWE */
567da5bb
JM
276#ifdef CONFIG_DPP
277 case WPA_KEY_MGMT_DPP:
278 wpa_printf(MSG_DEBUG,
279 "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - DPP)",
280 (unsigned int) key_len * 8 * 2);
281 if (key_len == 128 / 8) {
282 if (hmac_sha256(key, key_len, buf, len, hash))
283 return -1;
284 } else if (key_len == 192 / 8) {
285 if (hmac_sha384(key, key_len, buf, len, hash))
286 return -1;
287 } else if (key_len == 256 / 8) {
8b5579e1 288 if (hmac_sha512(key, key_len, buf, len, hash))
567da5bb
JM
289 return -1;
290 } else {
291 wpa_printf(MSG_INFO,
292 "DPP: Unsupported KCK length: %u",
293 (unsigned int) key_len);
294 return -1;
295 }
8b5579e1 296 os_memcpy(mic, hash, key_len);
567da5bb
JM
297 break;
298#endif /* CONFIG_DPP */
c49a9d6b
JM
299#if defined(CONFIG_IEEE80211R) && defined(CONFIG_SHA384)
300 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
301 wpa_printf(MSG_DEBUG,
302 "WPA: EAPOL-Key MIC using HMAC-SHA384 (AKM-defined - FT 802.1X SHA384)");
303 if (hmac_sha384(key, key_len, buf, len, hash))
304 return -1;
305 os_memcpy(mic, hash, 24);
306 break;
307#endif /* CONFIG_IEEE80211R && CONFIG_SHA384 */
929a2ea5 308 default:
ef9627cb
JM
309 wpa_printf(MSG_DEBUG,
310 "WPA: EAPOL-Key MIC algorithm not known (AKM-defined - akmp=0x%x)",
311 akmp);
929a2ea5
JM
312 return -1;
313 }
314 break;
6fc6879b 315 default:
ef9627cb
JM
316 wpa_printf(MSG_DEBUG,
317 "WPA: EAPOL-Key MIC algorithm not known (ver=%d)",
318 ver);
6fc6879b
JM
319 return -1;
320 }
321
322 return 0;
323}
324
325
326/**
327 * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces
328 * @pmk: Pairwise master key
329 * @pmk_len: Length of PMK
330 * @label: Label to use in derivation
331 * @addr1: AA or SA
332 * @addr2: SA or AA
333 * @nonce1: ANonce or SNonce
334 * @nonce2: SNonce or ANonce
335 * @ptk: Buffer for pairwise transient key
98cd3d1c
JM
336 * @akmp: Negotiated AKM
337 * @cipher: Negotiated pairwise cipher
338 * Returns: 0 on success, -1 on failure
6fc6879b
JM
339 *
340 * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
341 * PTK = PRF-X(PMK, "Pairwise key expansion",
342 * Min(AA, SA) || Max(AA, SA) ||
343 * Min(ANonce, SNonce) || Max(ANonce, SNonce))
6fc6879b 344 */
98cd3d1c
JM
345int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
346 const u8 *addr1, const u8 *addr2,
347 const u8 *nonce1, const u8 *nonce2,
348 struct wpa_ptk *ptk, int akmp, int cipher)
6fc6879b
JM
349{
350 u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
98cd3d1c
JM
351 u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
352 size_t ptk_len;
6fc6879b 353
b488a129 354 if (pmk_len == 0) {
8e402d16 355 wpa_printf(MSG_ERROR, "WPA: No PMK set for PTK derivation");
b488a129
JM
356 return -1;
357 }
358
6fc6879b
JM
359 if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
360 os_memcpy(data, addr1, ETH_ALEN);
361 os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
362 } else {
363 os_memcpy(data, addr2, ETH_ALEN);
364 os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
365 }
366
367 if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) {
368 os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);
369 os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,
370 WPA_NONCE_LEN);
371 } else {
372 os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);
373 os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,
374 WPA_NONCE_LEN);
375 }
376
567da5bb
JM
377 ptk->kck_len = wpa_kck_len(akmp, pmk_len);
378 ptk->kek_len = wpa_kek_len(akmp, pmk_len);
98cd3d1c 379 ptk->tk_len = wpa_cipher_key_len(cipher);
1d624a07
JM
380 if (ptk->tk_len == 0) {
381 wpa_printf(MSG_ERROR,
382 "WPA: Unsupported cipher (0x%x) used in PTK derivation",
383 cipher);
384 return -1;
385 }
98cd3d1c
JM
386 ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
387
ef9627cb 388 if (wpa_key_mgmt_sha384(akmp)) {
e491389e 389#if defined(CONFIG_SUITEB192) || defined(CONFIG_FILS)
ef9627cb
JM
390 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)");
391 if (sha384_prf(pmk, pmk_len, label, data, sizeof(data),
392 tmp, ptk_len) < 0)
393 return -1;
394#else /* CONFIG_SUITEB192 || CONFIG_FILS */
395 return -1;
e491389e 396#endif /* CONFIG_SUITEB192 || CONFIG_FILS */
07a5fe82 397 } else if (wpa_key_mgmt_sha256(akmp) || akmp == WPA_KEY_MGMT_OWE) {
2598e693 398#if defined(CONFIG_IEEE80211W) || defined(CONFIG_SAE) || defined(CONFIG_FILS)
ef9627cb
JM
399 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)");
400 if (sha256_prf(pmk, pmk_len, label, data, sizeof(data),
401 tmp, ptk_len) < 0)
402 return -1;
2598e693 403#else /* CONFIG_IEEE80211W or CONFIG_SAE or CONFIG_FILS */
ef9627cb 404 return -1;
2598e693 405#endif /* CONFIG_IEEE80211W or CONFIG_SAE or CONFIG_FILS */
567da5bb
JM
406#ifdef CONFIG_DPP
407 } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 32) {
408 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)");
409 if (sha256_prf(pmk, pmk_len, label, data, sizeof(data),
410 tmp, ptk_len) < 0)
411 return -1;
412 } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 48) {
413 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)");
414 if (sha384_prf(pmk, pmk_len, label, data, sizeof(data),
415 tmp, ptk_len) < 0)
416 return -1;
417 } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 64) {
418 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA512)");
419 if (sha512_prf(pmk, pmk_len, label, data, sizeof(data),
420 tmp, ptk_len) < 0)
421 return -1;
422 } else if (akmp == WPA_KEY_MGMT_DPP) {
423 wpa_printf(MSG_INFO, "DPP: Unknown PMK length %u",
424 (unsigned int) pmk_len);
425 return -1;
426#endif /* CONFIG_DPP */
ef9627cb
JM
427 } else {
428 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA1)");
429 if (sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp,
430 ptk_len) < 0)
431 return -1;
432 }
6fc6879b
JM
433
434 wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
435 MAC2STR(addr1), MAC2STR(addr2));
bc8318ac
JM
436 wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
437 wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN);
6fc6879b 438 wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
98cd3d1c
JM
439 wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", tmp, ptk_len);
440
441 os_memcpy(ptk->kck, tmp, ptk->kck_len);
442 wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", ptk->kck, ptk->kck_len);
443
444 os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len);
445 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len);
446
447 os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len);
448 wpa_hexdump_key(MSG_DEBUG, "WPA: TK", ptk->tk, ptk->tk_len);
449
2f373878
JM
450 ptk->kek2_len = 0;
451 ptk->kck2_len = 0;
452
98cd3d1c
JM
453 os_memset(tmp, 0, sizeof(tmp));
454 return 0;
6fc6879b
JM
455}
456
c089bc57 457#ifdef CONFIG_FILS
a852ab4c 458
fcd3d6ce
JM
459int fils_rmsk_to_pmk(int akmp, const u8 *rmsk, size_t rmsk_len,
460 const u8 *snonce, const u8 *anonce, const u8 *dh_ss,
461 size_t dh_ss_len, u8 *pmk, size_t *pmk_len)
462{
463 u8 nonces[2 * FILS_NONCE_LEN];
464 const u8 *addr[2];
465 size_t len[2];
466 size_t num_elem;
467 int res;
468
469 /* PMK = HMAC-Hash(SNonce || ANonce, rMSK [ || DHss ]) */
470 wpa_printf(MSG_DEBUG, "FILS: rMSK to PMK derivation");
471
472 if (wpa_key_mgmt_sha384(akmp))
473 *pmk_len = SHA384_MAC_LEN;
474 else if (wpa_key_mgmt_sha256(akmp))
475 *pmk_len = SHA256_MAC_LEN;
476 else
477 return -1;
478
479 wpa_hexdump_key(MSG_DEBUG, "FILS: rMSK", rmsk, rmsk_len);
480 wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN);
481 wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN);
482 wpa_hexdump(MSG_DEBUG, "FILS: DHss", dh_ss, dh_ss_len);
483
484 os_memcpy(nonces, snonce, FILS_NONCE_LEN);
485 os_memcpy(&nonces[FILS_NONCE_LEN], anonce, FILS_NONCE_LEN);
486 addr[0] = rmsk;
487 len[0] = rmsk_len;
488 num_elem = 1;
489 if (dh_ss) {
490 addr[1] = dh_ss;
491 len[1] = dh_ss_len;
492 num_elem++;
493 }
494 if (wpa_key_mgmt_sha384(akmp))
495 res = hmac_sha384_vector(nonces, 2 * FILS_NONCE_LEN, num_elem,
496 addr, len, pmk);
497 else
498 res = hmac_sha256_vector(nonces, 2 * FILS_NONCE_LEN, num_elem,
499 addr, len, pmk);
500 if (res == 0)
501 wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, *pmk_len);
1bd13110
JM
502 else
503 *pmk_len = 0;
fcd3d6ce
JM
504 return res;
505}
506
507
508int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len,
509 u8 *pmkid)
510{
511 const u8 *addr[1];
512 size_t len[1];
513 u8 hash[SHA384_MAC_LEN];
514 int res;
515
516 /* PMKID = Truncate-128(Hash(EAP-Initiate/Reauth)) */
517 addr[0] = reauth;
518 len[0] = reauth_len;
519 if (wpa_key_mgmt_sha384(akmp))
520 res = sha384_vector(1, addr, len, hash);
521 else if (wpa_key_mgmt_sha256(akmp))
522 res = sha256_vector(1, addr, len, hash);
523 else
524 return -1;
525 if (res)
526 return res;
527 os_memcpy(pmkid, hash, PMKID_LEN);
528 wpa_hexdump(MSG_DEBUG, "FILS: PMKID", pmkid, PMKID_LEN);
529 return 0;
530}
531
532
c089bc57 533int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
4cada9dc
JM
534 const u8 *snonce, const u8 *anonce, const u8 *dhss,
535 size_t dhss_len, struct wpa_ptk *ptk,
215eaa74
JM
536 u8 *ick, size_t *ick_len, int akmp, int cipher,
537 u8 *fils_ft, size_t *fils_ft_len)
c089bc57 538{
4cada9dc
JM
539 u8 *data, *pos;
540 size_t data_len;
215eaa74
JM
541 u8 tmp[FILS_ICK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN +
542 FILS_FT_MAX_LEN];
c089bc57
JM
543 size_t key_data_len;
544 const char *label = "FILS PTK Derivation";
4cada9dc 545 int ret = -1;
c089bc57
JM
546
547 /*
548 * FILS-Key-Data = PRF-X(PMK, "FILS PTK Derivation",
4cada9dc 549 * SPA || AA || SNonce || ANonce [ || DHss ])
c089bc57
JM
550 * ICK = L(FILS-Key-Data, 0, ICK_bits)
551 * KEK = L(FILS-Key-Data, ICK_bits, KEK_bits)
552 * TK = L(FILS-Key-Data, ICK_bits + KEK_bits, TK_bits)
553 * If doing FT initial mobility domain association:
554 * FILS-FT = L(FILS-Key-Data, ICK_bits + KEK_bits + TK_bits,
555 * FILS-FT_bits)
556 */
4cada9dc
JM
557 data_len = 2 * ETH_ALEN + 2 * FILS_NONCE_LEN + dhss_len;
558 data = os_malloc(data_len);
559 if (!data)
560 goto err;
561 pos = data;
562 os_memcpy(pos, spa, ETH_ALEN);
563 pos += ETH_ALEN;
564 os_memcpy(pos, aa, ETH_ALEN);
565 pos += ETH_ALEN;
566 os_memcpy(pos, snonce, FILS_NONCE_LEN);
567 pos += FILS_NONCE_LEN;
568 os_memcpy(pos, anonce, FILS_NONCE_LEN);
569 pos += FILS_NONCE_LEN;
570 if (dhss)
571 os_memcpy(pos, dhss, dhss_len);
c089bc57
JM
572
573 ptk->kck_len = 0;
567da5bb 574 ptk->kek_len = wpa_kek_len(akmp, pmk_len);
c089bc57
JM
575 ptk->tk_len = wpa_cipher_key_len(cipher);
576 if (wpa_key_mgmt_sha384(akmp))
577 *ick_len = 48;
578 else if (wpa_key_mgmt_sha256(akmp))
579 *ick_len = 32;
580 else
4cada9dc 581 goto err;
c089bc57
JM
582 key_data_len = *ick_len + ptk->kek_len + ptk->tk_len;
583
215eaa74
JM
584 if (fils_ft && fils_ft_len) {
585 if (akmp == WPA_KEY_MGMT_FT_FILS_SHA256) {
586 *fils_ft_len = 32;
587 } else if (akmp == WPA_KEY_MGMT_FT_FILS_SHA384) {
588 *fils_ft_len = 48;
589 } else {
590 *fils_ft_len = 0;
591 fils_ft = NULL;
592 }
593 key_data_len += *fils_ft_len;
594 }
595
ef9627cb
JM
596 if (wpa_key_mgmt_sha384(akmp)) {
597 wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA384)");
4cada9dc 598 if (sha384_prf(pmk, pmk_len, label, data, data_len,
ef9627cb 599 tmp, key_data_len) < 0)
4cada9dc 600 goto err;
ef9627cb
JM
601 } else {
602 wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA256)");
4cada9dc 603 if (sha256_prf(pmk, pmk_len, label, data, data_len,
ef9627cb 604 tmp, key_data_len) < 0)
4cada9dc 605 goto err;
ef9627cb 606 }
c089bc57
JM
607
608 wpa_printf(MSG_DEBUG, "FILS: PTK derivation - SPA=" MACSTR
609 " AA=" MACSTR, MAC2STR(spa), MAC2STR(aa));
610 wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN);
611 wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN);
4cada9dc
JM
612 if (dhss)
613 wpa_hexdump_key(MSG_DEBUG, "FILS: DHss", dhss, dhss_len);
c089bc57
JM
614 wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, pmk_len);
615 wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-Key-Data", tmp, key_data_len);
616
617 os_memcpy(ick, tmp, *ick_len);
618 wpa_hexdump_key(MSG_DEBUG, "FILS: ICK", ick, *ick_len);
619
620 os_memcpy(ptk->kek, tmp + *ick_len, ptk->kek_len);
621 wpa_hexdump_key(MSG_DEBUG, "FILS: KEK", ptk->kek, ptk->kek_len);
622
623 os_memcpy(ptk->tk, tmp + *ick_len + ptk->kek_len, ptk->tk_len);
624 wpa_hexdump_key(MSG_DEBUG, "FILS: TK", ptk->tk, ptk->tk_len);
625
215eaa74
JM
626 if (fils_ft && fils_ft_len) {
627 os_memcpy(fils_ft, tmp + *ick_len + ptk->kek_len + ptk->tk_len,
628 *fils_ft_len);
629 wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-FT",
630 fils_ft, *fils_ft_len);
631 }
c089bc57 632
2f373878
JM
633 ptk->kek2_len = 0;
634 ptk->kck2_len = 0;
635
c089bc57 636 os_memset(tmp, 0, sizeof(tmp));
4cada9dc
JM
637 ret = 0;
638err:
639 bin_clear_free(data, data_len);
640 return ret;
c089bc57
JM
641}
642
a852ab4c
JM
643
644int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce,
645 const u8 *anonce, const u8 *sta_addr, const u8 *bssid,
646 const u8 *g_sta, size_t g_sta_len,
647 const u8 *g_ap, size_t g_ap_len,
648 int akmp, u8 *key_auth_sta, u8 *key_auth_ap,
649 size_t *key_auth_len)
650{
651 const u8 *addr[6];
652 size_t len[6];
653 size_t num_elem = 4;
654 int res;
655
4d0a61c5
JM
656 wpa_printf(MSG_DEBUG, "FILS: Key-Auth derivation: STA-MAC=" MACSTR
657 " AP-BSSID=" MACSTR, MAC2STR(sta_addr), MAC2STR(bssid));
658 wpa_hexdump_key(MSG_DEBUG, "FILS: ICK", ick, ick_len);
659 wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN);
660 wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN);
661 wpa_hexdump(MSG_DEBUG, "FILS: gSTA", g_sta, g_sta_len);
662 wpa_hexdump(MSG_DEBUG, "FILS: gAP", g_ap, g_ap_len);
663
a852ab4c
JM
664 /*
665 * For (Re)Association Request frame (STA->AP):
666 * Key-Auth = HMAC-Hash(ICK, SNonce || ANonce || STA-MAC || AP-BSSID
667 * [ || gSTA || gAP ])
668 */
669 addr[0] = snonce;
670 len[0] = FILS_NONCE_LEN;
671 addr[1] = anonce;
672 len[1] = FILS_NONCE_LEN;
673 addr[2] = sta_addr;
674 len[2] = ETH_ALEN;
675 addr[3] = bssid;
676 len[3] = ETH_ALEN;
677 if (g_sta && g_ap_len && g_ap && g_ap_len) {
678 addr[4] = g_sta;
679 len[4] = g_sta_len;
680 addr[5] = g_ap;
681 len[5] = g_ap_len;
682 num_elem = 6;
683 }
684
685 if (wpa_key_mgmt_sha384(akmp)) {
686 *key_auth_len = 48;
687 res = hmac_sha384_vector(ick, ick_len, num_elem, addr, len,
688 key_auth_sta);
689 } else if (wpa_key_mgmt_sha256(akmp)) {
690 *key_auth_len = 32;
691 res = hmac_sha256_vector(ick, ick_len, num_elem, addr, len,
692 key_auth_sta);
693 } else {
694 return -1;
695 }
696 if (res < 0)
697 return res;
698
699 /*
700 * For (Re)Association Response frame (AP->STA):
701 * Key-Auth = HMAC-Hash(ICK, ANonce || SNonce || AP-BSSID || STA-MAC
702 * [ || gAP || gSTA ])
703 */
704 addr[0] = anonce;
705 addr[1] = snonce;
706 addr[2] = bssid;
707 addr[3] = sta_addr;
708 if (g_sta && g_ap_len && g_ap && g_ap_len) {
709 addr[4] = g_ap;
710 len[4] = g_ap_len;
711 addr[5] = g_sta;
712 len[5] = g_sta_len;
713 }
714
715 if (wpa_key_mgmt_sha384(akmp))
716 res = hmac_sha384_vector(ick, ick_len, num_elem, addr, len,
717 key_auth_ap);
718 else if (wpa_key_mgmt_sha256(akmp))
719 res = hmac_sha256_vector(ick, ick_len, num_elem, addr, len,
720 key_auth_ap);
721 if (res < 0)
722 return res;
723
724 wpa_hexdump(MSG_DEBUG, "FILS: Key-Auth (STA)",
725 key_auth_sta, *key_auth_len);
726 wpa_hexdump(MSG_DEBUG, "FILS: Key-Auth (AP)",
727 key_auth_ap, *key_auth_len);
728
729 return 0;
730}
731
c089bc57
JM
732#endif /* CONFIG_FILS */
733
6fc6879b
JM
734
735#ifdef CONFIG_IEEE80211R
98cd3d1c
JM
736int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
737 const u8 *ap_addr, u8 transaction_seqnum,
738 const u8 *mdie, size_t mdie_len,
6fc6879b
JM
739 const u8 *ftie, size_t ftie_len,
740 const u8 *rsnie, size_t rsnie_len,
741 const u8 *ric, size_t ric_len, u8 *mic)
742{
8b949804
JM
743 const u8 *addr[9];
744 size_t len[9];
745 size_t i, num_elem = 0;
746 u8 zero_mic[16];
6fc6879b 747
98cd3d1c
JM
748 if (kck_len != 16) {
749 wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u",
750 (unsigned int) kck_len);
751 return -1;
752 }
753
8b949804
JM
754 addr[num_elem] = sta_addr;
755 len[num_elem] = ETH_ALEN;
756 num_elem++;
757
758 addr[num_elem] = ap_addr;
759 len[num_elem] = ETH_ALEN;
760 num_elem++;
761
762 addr[num_elem] = &transaction_seqnum;
763 len[num_elem] = 1;
764 num_elem++;
6fc6879b 765
6fc6879b 766 if (rsnie) {
8b949804
JM
767 addr[num_elem] = rsnie;
768 len[num_elem] = rsnie_len;
769 num_elem++;
6fc6879b
JM
770 }
771 if (mdie) {
8b949804
JM
772 addr[num_elem] = mdie;
773 len[num_elem] = mdie_len;
774 num_elem++;
6fc6879b
JM
775 }
776 if (ftie) {
8b949804 777 if (ftie_len < 2 + sizeof(struct rsn_ftie))
6fc6879b 778 return -1;
8b949804
JM
779
780 /* IE hdr and mic_control */
781 addr[num_elem] = ftie;
782 len[num_elem] = 2 + 2;
783 num_elem++;
784
785 /* MIC field with all zeros */
786 os_memset(zero_mic, 0, sizeof(zero_mic));
787 addr[num_elem] = zero_mic;
788 len[num_elem] = sizeof(zero_mic);
789 num_elem++;
790
791 /* Rest of FTIE */
792 addr[num_elem] = ftie + 2 + 2 + 16;
793 len[num_elem] = ftie_len - (2 + 2 + 16);
794 num_elem++;
6fc6879b
JM
795 }
796 if (ric) {
8b949804
JM
797 addr[num_elem] = ric;
798 len[num_elem] = ric_len;
799 num_elem++;
6fc6879b
JM
800 }
801
8b949804
JM
802 for (i = 0; i < num_elem; i++)
803 wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", addr[i], len[i]);
804 if (omac1_aes_128_vector(kck, num_elem, addr, len, mic))
6fc6879b 805 return -1;
6fc6879b
JM
806
807 return 0;
808}
6554237f
JM
809
810
811static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
812 struct wpa_ft_ies *parse)
813{
814 const u8 *end, *pos;
815
816 parse->ftie = ie;
817 parse->ftie_len = ie_len;
818
819 pos = ie + sizeof(struct rsn_ftie);
820 end = ie + ie_len;
821
7b5880fc
JM
822 while (end - pos >= 2) {
823 u8 id, len;
824
825 id = *pos++;
826 len = *pos++;
827 if (len > end - pos)
828 break;
829
830 switch (id) {
6554237f 831 case FTIE_SUBELEM_R1KH_ID:
7b5880fc
JM
832 if (len != FT_R1KH_ID_LEN) {
833 wpa_printf(MSG_DEBUG,
834 "FT: Invalid R1KH-ID length in FTIE: %d",
835 len);
6554237f
JM
836 return -1;
837 }
7b5880fc 838 parse->r1kh_id = pos;
6554237f
JM
839 break;
840 case FTIE_SUBELEM_GTK:
7b5880fc
JM
841 parse->gtk = pos;
842 parse->gtk_len = len;
6554237f
JM
843 break;
844 case FTIE_SUBELEM_R0KH_ID:
7b5880fc
JM
845 if (len < 1 || len > FT_R0KH_ID_MAX_LEN) {
846 wpa_printf(MSG_DEBUG,
847 "FT: Invalid R0KH-ID length in FTIE: %d",
848 len);
6554237f
JM
849 return -1;
850 }
7b5880fc
JM
851 parse->r0kh_id = pos;
852 parse->r0kh_id_len = len;
6554237f
JM
853 break;
854#ifdef CONFIG_IEEE80211W
855 case FTIE_SUBELEM_IGTK:
7b5880fc
JM
856 parse->igtk = pos;
857 parse->igtk_len = len;
6554237f
JM
858 break;
859#endif /* CONFIG_IEEE80211W */
860 }
861
7b5880fc 862 pos += len;
6554237f
JM
863 }
864
865 return 0;
866}
867
868
869int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
870 struct wpa_ft_ies *parse)
871{
872 const u8 *end, *pos;
873 struct wpa_ie_data data;
874 int ret;
875 const struct rsn_ftie *ftie;
876 int prot_ie_count = 0;
877
878 os_memset(parse, 0, sizeof(*parse));
879 if (ies == NULL)
880 return 0;
881
882 pos = ies;
883 end = ies + ies_len;
7b5880fc
JM
884 while (end - pos >= 2) {
885 u8 id, len;
886
887 id = *pos++;
888 len = *pos++;
889 if (len > end - pos)
890 break;
891
892 switch (id) {
6554237f 893 case WLAN_EID_RSN:
7b5880fc
JM
894 parse->rsn = pos;
895 parse->rsn_len = len;
6554237f
JM
896 ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
897 parse->rsn_len + 2,
898 &data);
899 if (ret < 0) {
900 wpa_printf(MSG_DEBUG, "FT: Failed to parse "
901 "RSN IE: %d", ret);
902 return -1;
903 }
904 if (data.num_pmkid == 1 && data.pmkid)
905 parse->rsn_pmkid = data.pmkid;
96590564
MB
906 parse->key_mgmt = data.key_mgmt;
907 parse->pairwise_cipher = data.pairwise_cipher;
6554237f
JM
908 break;
909 case WLAN_EID_MOBILITY_DOMAIN:
7b5880fc 910 if (len < sizeof(struct rsn_mdie))
ae7a42bd 911 return -1;
7b5880fc
JM
912 parse->mdie = pos;
913 parse->mdie_len = len;
6554237f
JM
914 break;
915 case WLAN_EID_FAST_BSS_TRANSITION:
7b5880fc 916 if (len < sizeof(*ftie))
6554237f 917 return -1;
7b5880fc 918 ftie = (const struct rsn_ftie *) pos;
6554237f 919 prot_ie_count = ftie->mic_control[1];
7b5880fc 920 if (wpa_ft_parse_ftie(pos, len, parse) < 0)
6554237f
JM
921 return -1;
922 break;
923 case WLAN_EID_TIMEOUT_INTERVAL:
7b5880fc 924 if (len != 5)
ae7a42bd 925 break;
7b5880fc
JM
926 parse->tie = pos;
927 parse->tie_len = len;
6554237f
JM
928 break;
929 case WLAN_EID_RIC_DATA:
930 if (parse->ric == NULL)
7b5880fc 931 parse->ric = pos - 2;
6554237f
JM
932 break;
933 }
934
7b5880fc 935 pos += len;
6554237f
JM
936 }
937
938 if (prot_ie_count == 0)
939 return 0; /* no MIC */
940
941 /*
942 * Check that the protected IE count matches with IEs included in the
943 * frame.
944 */
945 if (parse->rsn)
946 prot_ie_count--;
947 if (parse->mdie)
948 prot_ie_count--;
949 if (parse->ftie)
950 prot_ie_count--;
951 if (prot_ie_count < 0) {
952 wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
953 "the protected IE count");
954 return -1;
955 }
956
957 if (prot_ie_count == 0 && parse->ric) {
958 wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
959 "included in protected IE count");
960 return -1;
961 }
962
963 /* Determine the end of the RIC IE(s) */
7b5880fc
JM
964 if (parse->ric) {
965 pos = parse->ric;
966 while (end - pos >= 2 && 2 + pos[1] <= end - pos &&
967 prot_ie_count) {
968 prot_ie_count--;
969 pos += 2 + pos[1];
970 }
971 parse->ric_len = pos - parse->ric;
6554237f 972 }
6554237f
JM
973 if (prot_ie_count) {
974 wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
975 "frame", (int) prot_ie_count);
976 return -1;
977 }
978
979 return 0;
980}
6fc6879b
JM
981#endif /* CONFIG_IEEE80211R */
982
983
6fc6879b
JM
984static int rsn_selector_to_bitfield(const u8 *s)
985{
986 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
987 return WPA_CIPHER_NONE;
6fc6879b
JM
988 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
989 return WPA_CIPHER_TKIP;
990 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
991 return WPA_CIPHER_CCMP;
6fc6879b
JM
992#ifdef CONFIG_IEEE80211W
993 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
994 return WPA_CIPHER_AES_128_CMAC;
995#endif /* CONFIG_IEEE80211W */
eb7719ff
JM
996 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
997 return WPA_CIPHER_GCMP;
30675c34
JM
998 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256)
999 return WPA_CIPHER_CCMP_256;
1000 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256)
1001 return WPA_CIPHER_GCMP_256;
1002 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128)
1003 return WPA_CIPHER_BIP_GMAC_128;
1004 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256)
1005 return WPA_CIPHER_BIP_GMAC_256;
1006 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256)
1007 return WPA_CIPHER_BIP_CMAC_256;
8dd9f9cd
JM
1008 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED)
1009 return WPA_CIPHER_GTK_NOT_USED;
6fc6879b
JM
1010 return 0;
1011}
1012
1013
1014static int rsn_key_mgmt_to_bitfield(const u8 *s)
1015{
1016 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
1017 return WPA_KEY_MGMT_IEEE8021X;
1018 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
1019 return WPA_KEY_MGMT_PSK;
1020#ifdef CONFIG_IEEE80211R
1021 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
1022 return WPA_KEY_MGMT_FT_IEEE8021X;
1023 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
1024 return WPA_KEY_MGMT_FT_PSK;
c22bb5bb
JM
1025#ifdef CONFIG_SHA384
1026 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384)
1027 return WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1028#endif /* CONFIG_SHA384 */
6fc6879b 1029#endif /* CONFIG_IEEE80211R */
56586197
JM
1030#ifdef CONFIG_IEEE80211W
1031 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
1032 return WPA_KEY_MGMT_IEEE8021X_SHA256;
1033 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
1034 return WPA_KEY_MGMT_PSK_SHA256;
1035#endif /* CONFIG_IEEE80211W */
c10347f2
JM
1036#ifdef CONFIG_SAE
1037 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
1038 return WPA_KEY_MGMT_SAE;
1039 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
1040 return WPA_KEY_MGMT_FT_SAE;
1041#endif /* CONFIG_SAE */
666497c8
JM
1042 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B)
1043 return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
5e3b5197
JM
1044 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
1045 return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
94318a0d
JM
1046 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA256)
1047 return WPA_KEY_MGMT_FILS_SHA256;
1048 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA384)
1049 return WPA_KEY_MGMT_FILS_SHA384;
1050 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA256)
1051 return WPA_KEY_MGMT_FT_FILS_SHA256;
1052 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA384)
1053 return WPA_KEY_MGMT_FT_FILS_SHA384;
a1ea1b45
JM
1054#ifdef CONFIG_OWE
1055 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE)
1056 return WPA_KEY_MGMT_OWE;
1057#endif /* CONFIG_OWE */
567da5bb
JM
1058#ifdef CONFIG_DPP
1059 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_DPP)
1060 return WPA_KEY_MGMT_DPP;
1061#endif /* CONFIG_DPP */
0f8385e6
BG
1062 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN)
1063 return WPA_KEY_MGMT_OSEN;
6fc6879b
JM
1064 return 0;
1065}
6fc6879b
JM
1066
1067
05a90d78 1068int wpa_cipher_valid_group(int cipher)
8dd9f9cd
JM
1069{
1070 return wpa_cipher_valid_pairwise(cipher) ||
8dd9f9cd
JM
1071 cipher == WPA_CIPHER_GTK_NOT_USED;
1072}
1073
1074
1075#ifdef CONFIG_IEEE80211W
1076int wpa_cipher_valid_mgmt_group(int cipher)
1077{
1078 return cipher == WPA_CIPHER_AES_128_CMAC ||
1079 cipher == WPA_CIPHER_BIP_GMAC_128 ||
1080 cipher == WPA_CIPHER_BIP_GMAC_256 ||
1081 cipher == WPA_CIPHER_BIP_CMAC_256;
1082}
1083#endif /* CONFIG_IEEE80211W */
1084
1085
6fc6879b
JM
1086/**
1087 * wpa_parse_wpa_ie_rsn - Parse RSN IE
1088 * @rsn_ie: Buffer containing RSN IE
1089 * @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
1090 * @data: Pointer to structure that will be filled in with parsed data
1091 * Returns: 0 on success, <0 on failure
1092 */
1093int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
1094 struct wpa_ie_data *data)
1095{
6fc6879b
JM
1096 const u8 *pos;
1097 int left;
1098 int i, count;
1099
1100 os_memset(data, 0, sizeof(*data));
1101 data->proto = WPA_PROTO_RSN;
1102 data->pairwise_cipher = WPA_CIPHER_CCMP;
1103 data->group_cipher = WPA_CIPHER_CCMP;
1104 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1105 data->capabilities = 0;
1106 data->pmkid = NULL;
1107 data->num_pmkid = 0;
1108#ifdef CONFIG_IEEE80211W
1109 data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1110#else /* CONFIG_IEEE80211W */
1111 data->mgmt_group_cipher = 0;
1112#endif /* CONFIG_IEEE80211W */
1113
1114 if (rsn_ie_len == 0) {
1115 /* No RSN IE - fail silently */
1116 return -1;
1117 }
1118
1119 if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
1120 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
1121 __func__, (unsigned long) rsn_ie_len);
1122 return -1;
1123 }
1124
0f8385e6
BG
1125 if (rsn_ie_len >= 6 && rsn_ie[1] >= 4 &&
1126 rsn_ie[1] == rsn_ie_len - 2 &&
1127 WPA_GET_BE32(&rsn_ie[2]) == OSEN_IE_VENDOR_TYPE) {
1128 pos = rsn_ie + 6;
1129 left = rsn_ie_len - 6;
6fc6879b 1130
0f8385e6
BG
1131 data->proto = WPA_PROTO_OSEN;
1132 } else {
1133 const struct rsn_ie_hdr *hdr;
1134
1135 hdr = (const struct rsn_ie_hdr *) rsn_ie;
6fc6879b 1136
0f8385e6
BG
1137 if (hdr->elem_id != WLAN_EID_RSN ||
1138 hdr->len != rsn_ie_len - 2 ||
1139 WPA_GET_LE16(hdr->version) != RSN_VERSION) {
1140 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
1141 __func__);
1142 return -2;
1143 }
1144
1145 pos = (const u8 *) (hdr + 1);
1146 left = rsn_ie_len - sizeof(*hdr);
1147 }
6fc6879b
JM
1148
1149 if (left >= RSN_SELECTOR_LEN) {
1150 data->group_cipher = rsn_selector_to_bitfield(pos);
8dd9f9cd 1151 if (!wpa_cipher_valid_group(data->group_cipher)) {
0b905c8a
JM
1152 wpa_printf(MSG_DEBUG,
1153 "%s: invalid group cipher 0x%x (%08x)",
1154 __func__, data->group_cipher,
1155 WPA_GET_BE32(pos));
6fc6879b
JM
1156 return -1;
1157 }
6fc6879b
JM
1158 pos += RSN_SELECTOR_LEN;
1159 left -= RSN_SELECTOR_LEN;
1160 } else if (left > 0) {
1161 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
1162 __func__, left);
1163 return -3;
1164 }
1165
1166 if (left >= 2) {
1167 data->pairwise_cipher = 0;
1168 count = WPA_GET_LE16(pos);
1169 pos += 2;
1170 left -= 2;
649c0a69 1171 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
6fc6879b
JM
1172 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
1173 "count %u left %u", __func__, count, left);
1174 return -4;
1175 }
1176 for (i = 0; i < count; i++) {
1177 data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
1178 pos += RSN_SELECTOR_LEN;
1179 left -= RSN_SELECTOR_LEN;
1180 }
1181#ifdef CONFIG_IEEE80211W
1182 if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
1183 wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
1184 "pairwise cipher", __func__);
1185 return -1;
1186 }
1187#endif /* CONFIG_IEEE80211W */
1188 } else if (left == 1) {
1189 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
1190 __func__);
1191 return -5;
1192 }
1193
1194 if (left >= 2) {
1195 data->key_mgmt = 0;
1196 count = WPA_GET_LE16(pos);
1197 pos += 2;
1198 left -= 2;
649c0a69 1199 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
6fc6879b
JM
1200 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
1201 "count %u left %u", __func__, count, left);
1202 return -6;
1203 }
1204 for (i = 0; i < count; i++) {
1205 data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
1206 pos += RSN_SELECTOR_LEN;
1207 left -= RSN_SELECTOR_LEN;
1208 }
1209 } else if (left == 1) {
1210 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
1211 __func__);
1212 return -7;
1213 }
1214
1215 if (left >= 2) {
1216 data->capabilities = WPA_GET_LE16(pos);
1217 pos += 2;
1218 left -= 2;
1219 }
1220
1221 if (left >= 2) {
46a03525 1222 u16 num_pmkid = WPA_GET_LE16(pos);
6fc6879b
JM
1223 pos += 2;
1224 left -= 2;
46a03525 1225 if (num_pmkid > (unsigned int) left / PMKID_LEN) {
6fc6879b 1226 wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
46a03525
JM
1227 "(num_pmkid=%u left=%d)",
1228 __func__, num_pmkid, left);
6fc6879b
JM
1229 data->num_pmkid = 0;
1230 return -9;
1231 } else {
46a03525 1232 data->num_pmkid = num_pmkid;
6fc6879b
JM
1233 data->pmkid = pos;
1234 pos += data->num_pmkid * PMKID_LEN;
1235 left -= data->num_pmkid * PMKID_LEN;
1236 }
1237 }
1238
1239#ifdef CONFIG_IEEE80211W
1240 if (left >= 4) {
1241 data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
8dd9f9cd 1242 if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
b0ecbd3a
JM
1243 wpa_printf(MSG_DEBUG,
1244 "%s: Unsupported management group cipher 0x%x (%08x)",
1245 __func__, data->mgmt_group_cipher,
1246 WPA_GET_BE32(pos));
6fc6879b
JM
1247 return -10;
1248 }
1249 pos += RSN_SELECTOR_LEN;
1250 left -= RSN_SELECTOR_LEN;
1251 }
1252#endif /* CONFIG_IEEE80211W */
1253
1254 if (left > 0) {
749fa140
JM
1255 wpa_hexdump(MSG_DEBUG,
1256 "wpa_parse_wpa_ie_rsn: ignore trailing bytes",
1257 pos, left);
6fc6879b
JM
1258 }
1259
1260 return 0;
6fc6879b
JM
1261}
1262
1263
f3b87561
JM
1264static int wpa_selector_to_bitfield(const u8 *s)
1265{
1266 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
1267 return WPA_CIPHER_NONE;
f3b87561
JM
1268 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
1269 return WPA_CIPHER_TKIP;
1270 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
1271 return WPA_CIPHER_CCMP;
f3b87561
JM
1272 return 0;
1273}
1274
1275
1276static int wpa_key_mgmt_to_bitfield(const u8 *s)
1277{
1278 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
1279 return WPA_KEY_MGMT_IEEE8021X;
1280 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
1281 return WPA_KEY_MGMT_PSK;
1282 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
1283 return WPA_KEY_MGMT_WPA_NONE;
1284 return 0;
1285}
1286
1287
1288int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
1289 struct wpa_ie_data *data)
1290{
1291 const struct wpa_ie_hdr *hdr;
1292 const u8 *pos;
1293 int left;
1294 int i, count;
1295
1296 os_memset(data, 0, sizeof(*data));
1297 data->proto = WPA_PROTO_WPA;
1298 data->pairwise_cipher = WPA_CIPHER_TKIP;
1299 data->group_cipher = WPA_CIPHER_TKIP;
1300 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1301 data->capabilities = 0;
1302 data->pmkid = NULL;
1303 data->num_pmkid = 0;
1304 data->mgmt_group_cipher = 0;
1305
f3b87561
JM
1306 if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
1307 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
1308 __func__, (unsigned long) wpa_ie_len);
1309 return -1;
1310 }
1311
1312 hdr = (const struct wpa_ie_hdr *) wpa_ie;
1313
1314 if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
1315 hdr->len != wpa_ie_len - 2 ||
1316 RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
1317 WPA_GET_LE16(hdr->version) != WPA_VERSION) {
1318 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
1319 __func__);
1320 return -2;
1321 }
1322
1323 pos = (const u8 *) (hdr + 1);
1324 left = wpa_ie_len - sizeof(*hdr);
1325
1326 if (left >= WPA_SELECTOR_LEN) {
1327 data->group_cipher = wpa_selector_to_bitfield(pos);
1328 pos += WPA_SELECTOR_LEN;
1329 left -= WPA_SELECTOR_LEN;
1330 } else if (left > 0) {
1331 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
1332 __func__, left);
1333 return -3;
1334 }
1335
1336 if (left >= 2) {
1337 data->pairwise_cipher = 0;
1338 count = WPA_GET_LE16(pos);
1339 pos += 2;
1340 left -= 2;
649c0a69 1341 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
f3b87561
JM
1342 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
1343 "count %u left %u", __func__, count, left);
1344 return -4;
1345 }
1346 for (i = 0; i < count; i++) {
1347 data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
1348 pos += WPA_SELECTOR_LEN;
1349 left -= WPA_SELECTOR_LEN;
1350 }
1351 } else if (left == 1) {
1352 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
1353 __func__);
1354 return -5;
1355 }
1356
1357 if (left >= 2) {
1358 data->key_mgmt = 0;
1359 count = WPA_GET_LE16(pos);
1360 pos += 2;
1361 left -= 2;
649c0a69 1362 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
f3b87561
JM
1363 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
1364 "count %u left %u", __func__, count, left);
1365 return -6;
1366 }
1367 for (i = 0; i < count; i++) {
1368 data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
1369 pos += WPA_SELECTOR_LEN;
1370 left -= WPA_SELECTOR_LEN;
1371 }
1372 } else if (left == 1) {
1373 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
1374 __func__);
1375 return -7;
1376 }
1377
1378 if (left >= 2) {
1379 data->capabilities = WPA_GET_LE16(pos);
1380 pos += 2;
1381 left -= 2;
1382 }
1383
1384 if (left > 0) {
749fa140
JM
1385 wpa_hexdump(MSG_DEBUG,
1386 "wpa_parse_wpa_ie_wpa: ignore trailing bytes",
1387 pos, left);
f3b87561
JM
1388 }
1389
1390 return 0;
1391}
1392
1393
6fc6879b
JM
1394#ifdef CONFIG_IEEE80211R
1395
1396/**
1397 * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
1398 *
c1e033b0 1399 * IEEE Std 802.11r-2008 - 8.5.1.5.3
6fc6879b 1400 */
364c064a
JM
1401int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
1402 const u8 *ssid, size_t ssid_len,
1403 const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
1404 const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
6fc6879b 1405{
6fb761c6 1406 u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
6fc6879b
JM
1407 FT_R0KH_ID_MAX_LEN + ETH_ALEN];
1408 u8 *pos, r0_key_data[48], hash[32];
1409 const u8 *addr[2];
1410 size_t len[2];
1411
1412 /*
1413 * R0-Key-Data = KDF-384(XXKey, "FT-R0",
1414 * SSIDlength || SSID || MDID || R0KHlength ||
1415 * R0KH-ID || S0KH-ID)
1416 * XXKey is either the second 256 bits of MSK or PSK.
1417 * PMK-R0 = L(R0-Key-Data, 0, 256)
1418 * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
1419 */
6fb761c6 1420 if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
364c064a 1421 return -1;
6fc6879b
JM
1422 pos = buf;
1423 *pos++ = ssid_len;
1424 os_memcpy(pos, ssid, ssid_len);
1425 pos += ssid_len;
1426 os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
1427 pos += MOBILITY_DOMAIN_ID_LEN;
1428 *pos++ = r0kh_id_len;
1429 os_memcpy(pos, r0kh_id, r0kh_id_len);
1430 pos += r0kh_id_len;
1431 os_memcpy(pos, s0kh_id, ETH_ALEN);
1432 pos += ETH_ALEN;
1433
364c064a
JM
1434 if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
1435 r0_key_data, sizeof(r0_key_data)) < 0)
1436 return -1;
6fc6879b
JM
1437 os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
1438
1439 /*
1440 * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
1441 */
1442 addr[0] = (const u8 *) "FT-R0N";
1443 len[0] = 6;
1444 addr[1] = r0_key_data + PMK_LEN;
1445 len[1] = 16;
1446
364c064a
JM
1447 if (sha256_vector(2, addr, len, hash) < 0)
1448 return -1;
6fc6879b 1449 os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
364c064a 1450 return 0;
6fc6879b
JM
1451}
1452
1453
1454/**
1455 * wpa_derive_pmk_r1_name - Derive PMKR1Name
1456 *
c1e033b0 1457 * IEEE Std 802.11r-2008 - 8.5.1.5.4
6fc6879b 1458 */
364c064a
JM
1459int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
1460 const u8 *s1kh_id, u8 *pmk_r1_name)
6fc6879b
JM
1461{
1462 u8 hash[32];
1463 const u8 *addr[4];
1464 size_t len[4];
1465
1466 /*
1467 * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
1468 * R1KH-ID || S1KH-ID))
1469 */
1470 addr[0] = (const u8 *) "FT-R1N";
1471 len[0] = 6;
1472 addr[1] = pmk_r0_name;
1473 len[1] = WPA_PMK_NAME_LEN;
1474 addr[2] = r1kh_id;
1475 len[2] = FT_R1KH_ID_LEN;
1476 addr[3] = s1kh_id;
1477 len[3] = ETH_ALEN;
1478
364c064a
JM
1479 if (sha256_vector(4, addr, len, hash) < 0)
1480 return -1;
6fc6879b 1481 os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
364c064a 1482 return 0;
6fc6879b
JM
1483}
1484
1485
1486/**
1487 * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
1488 *
c1e033b0 1489 * IEEE Std 802.11r-2008 - 8.5.1.5.4
6fc6879b 1490 */
a3e18dbb
JM
1491int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len,
1492 const u8 *pmk_r0_name,
364c064a
JM
1493 const u8 *r1kh_id, const u8 *s1kh_id,
1494 u8 *pmk_r1, u8 *pmk_r1_name)
6fc6879b
JM
1495{
1496 u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
1497 u8 *pos;
1498
1499 /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
1500 pos = buf;
1501 os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
1502 pos += FT_R1KH_ID_LEN;
1503 os_memcpy(pos, s1kh_id, ETH_ALEN);
1504 pos += ETH_ALEN;
1505
364c064a
JM
1506 if (sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf,
1507 pmk_r1, PMK_LEN) < 0)
1508 return -1;
6fc6879b 1509
364c064a
JM
1510 return wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id,
1511 pmk_r1_name);
6fc6879b
JM
1512}
1513
1514
1515/**
1516 * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
1517 *
c1e033b0 1518 * IEEE Std 802.11r-2008 - 8.5.1.5.5
6fc6879b 1519 */
a3e18dbb
JM
1520int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len,
1521 const u8 *snonce, const u8 *anonce,
98cd3d1c
JM
1522 const u8 *sta_addr, const u8 *bssid,
1523 const u8 *pmk_r1_name,
1524 struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher)
6fc6879b
JM
1525{
1526 u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
1527 u8 *pos, hash[32];
1528 const u8 *addr[6];
1529 size_t len[6];
2f373878
JM
1530 u8 tmp[2 * WPA_KCK_MAX_LEN + 2 * WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
1531 size_t ptk_len, offset;
6fc6879b
JM
1532
1533 /*
1534 * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
1535 * BSSID || STA-ADDR)
1536 */
1537 pos = buf;
1538 os_memcpy(pos, snonce, WPA_NONCE_LEN);
1539 pos += WPA_NONCE_LEN;
1540 os_memcpy(pos, anonce, WPA_NONCE_LEN);
1541 pos += WPA_NONCE_LEN;
1542 os_memcpy(pos, bssid, ETH_ALEN);
1543 pos += ETH_ALEN;
1544 os_memcpy(pos, sta_addr, ETH_ALEN);
1545 pos += ETH_ALEN;
1546
567da5bb 1547 ptk->kck_len = wpa_kck_len(akmp, PMK_LEN);
2f373878 1548 ptk->kck2_len = wpa_kck2_len(akmp);
567da5bb 1549 ptk->kek_len = wpa_kek_len(akmp, PMK_LEN);
2f373878 1550 ptk->kek2_len = wpa_kek2_len(akmp);
98cd3d1c 1551 ptk->tk_len = wpa_cipher_key_len(cipher);
2f373878
JM
1552 ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len +
1553 ptk->kck2_len + ptk->kek2_len;
98cd3d1c 1554
364c064a
JM
1555 if (sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf,
1556 tmp, ptk_len) < 0)
1557 return -1;
6fc6879b
JM
1558
1559 /*
1560 * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
1561 * ANonce || BSSID || STA-ADDR))
1562 */
1563 addr[0] = pmk_r1_name;
1564 len[0] = WPA_PMK_NAME_LEN;
1565 addr[1] = (const u8 *) "FT-PTKN";
1566 len[1] = 7;
1567 addr[2] = snonce;
1568 len[2] = WPA_NONCE_LEN;
1569 addr[3] = anonce;
1570 len[3] = WPA_NONCE_LEN;
1571 addr[4] = bssid;
1572 len[4] = ETH_ALEN;
1573 addr[5] = sta_addr;
1574 len[5] = ETH_ALEN;
1575
364c064a
JM
1576 if (sha256_vector(6, addr, len, hash) < 0)
1577 return -1;
6fc6879b 1578 os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
98cd3d1c
JM
1579
1580 os_memcpy(ptk->kck, tmp, ptk->kck_len);
2f373878
JM
1581 offset = ptk->kck_len;
1582 os_memcpy(ptk->kek, tmp + offset, ptk->kek_len);
1583 offset += ptk->kek_len;
1584 os_memcpy(ptk->tk, tmp + offset, ptk->tk_len);
1585 offset += ptk->tk_len;
1586 os_memcpy(ptk->kck2, tmp + offset, ptk->kck2_len);
1587 offset = ptk->kck2_len;
1588 os_memcpy(ptk->kek2, tmp + offset, ptk->kek2_len);
98cd3d1c
JM
1589
1590 wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len);
1591 wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len);
2f373878
JM
1592 if (ptk->kck2_len)
1593 wpa_hexdump_key(MSG_DEBUG, "FT: KCK2",
1594 ptk->kck2, ptk->kck2_len);
1595 if (ptk->kek2_len)
1596 wpa_hexdump_key(MSG_DEBUG, "FT: KEK2",
1597 ptk->kek2, ptk->kek2_len);
98cd3d1c
JM
1598 wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len);
1599 wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
1600
1601 os_memset(tmp, 0, sizeof(tmp));
1602
1603 return 0;
6fc6879b
JM
1604}
1605
1606#endif /* CONFIG_IEEE80211R */
13268290
JM
1607
1608
1609/**
1610 * rsn_pmkid - Calculate PMK identifier
1611 * @pmk: Pairwise master key
1612 * @pmk_len: Length of pmk in bytes
1613 * @aa: Authenticator address
1614 * @spa: Supplicant address
1615 * @pmkid: Buffer for PMKID
41b81914 1616 * @akmp: Negotiated key management protocol
13268290 1617 *
41b81914
JM
1618 * IEEE Std 802.11-2016 - 12.7.1.3 Pairwise key hierarchy
1619 * AKM: 00-0F-AC:5, 00-0F-AC:6, 00-0F-AC:14, 00-0F-AC:16
1620 * PMKID = Truncate-128(HMAC-SHA-256(PMK, "PMK Name" || AA || SPA))
1621 * AKM: 00-0F-AC:11
1622 * See rsn_pmkid_suite_b()
1623 * AKM: 00-0F-AC:12
1624 * See rsn_pmkid_suite_b_192()
1625 * AKM: 00-0F-AC:15, 00-0F-AC:17
1626 * PMKID = Truncate-128(HMAC-SHA-384(PMK, "PMK Name" || AA || SPA))
1627 * Otherwise:
1628 * PMKID = Truncate-128(HMAC-SHA-1(PMK, "PMK Name" || AA || SPA))
13268290
JM
1629 */
1630void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
41b81914 1631 u8 *pmkid, int akmp)
13268290
JM
1632{
1633 char *title = "PMK Name";
1634 const u8 *addr[3];
1635 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
41b81914 1636 unsigned char hash[SHA384_MAC_LEN];
13268290
JM
1637
1638 addr[0] = (u8 *) title;
1639 addr[1] = aa;
1640 addr[2] = spa;
1641
41b81914
JM
1642 if (0) {
1643#ifdef CONFIG_FILS
1644 } else if (wpa_key_mgmt_sha384(akmp)) {
1645 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-384");
1646 hmac_sha384_vector(pmk, pmk_len, 3, addr, len, hash);
1647#endif /* CONFIG_FILS */
1648#if defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS)
1649 } else if (wpa_key_mgmt_sha256(akmp)) {
1650 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-256");
13268290 1651 hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
41b81914
JM
1652#endif /* CONFIG_IEEE80211W || CONFIG_FILS */
1653 } else {
1654 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-1");
13268290 1655 hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
41b81914
JM
1656 }
1657 wpa_hexdump(MSG_DEBUG, "RSN: Derived PMKID", hash, PMKID_LEN);
13268290
JM
1658 os_memcpy(pmkid, hash, PMKID_LEN);
1659}
43fb5297
JM
1660
1661
087a1f4e
JM
1662#ifdef CONFIG_SUITEB
1663/**
1664 * rsn_pmkid_suite_b - Calculate PMK identifier for Suite B AKM
1665 * @kck: Key confirmation key
1666 * @kck_len: Length of kck in bytes
1667 * @aa: Authenticator address
1668 * @spa: Supplicant address
1669 * @pmkid: Buffer for PMKID
1670 * Returns: 0 on success, -1 on failure
1671 *
1672 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1673 * PMKID = Truncate(HMAC-SHA-256(KCK, "PMK Name" || AA || SPA))
1674 */
1675int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
1676 const u8 *spa, u8 *pmkid)
1677{
1678 char *title = "PMK Name";
1679 const u8 *addr[3];
1680 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1681 unsigned char hash[SHA256_MAC_LEN];
1682
1683 addr[0] = (u8 *) title;
1684 addr[1] = aa;
1685 addr[2] = spa;
1686
1687 if (hmac_sha256_vector(kck, kck_len, 3, addr, len, hash) < 0)
1688 return -1;
1689 os_memcpy(pmkid, hash, PMKID_LEN);
1690 return 0;
1691}
1692#endif /* CONFIG_SUITEB */
1693
1694
5e3b5197
JM
1695#ifdef CONFIG_SUITEB192
1696/**
1697 * rsn_pmkid_suite_b_192 - Calculate PMK identifier for Suite B AKM
1698 * @kck: Key confirmation key
1699 * @kck_len: Length of kck in bytes
1700 * @aa: Authenticator address
1701 * @spa: Supplicant address
1702 * @pmkid: Buffer for PMKID
1703 * Returns: 0 on success, -1 on failure
1704 *
1705 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1706 * PMKID = Truncate(HMAC-SHA-384(KCK, "PMK Name" || AA || SPA))
1707 */
1708int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa,
1709 const u8 *spa, u8 *pmkid)
1710{
1711 char *title = "PMK Name";
1712 const u8 *addr[3];
1713 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1714 unsigned char hash[SHA384_MAC_LEN];
1715
1716 addr[0] = (u8 *) title;
1717 addr[1] = aa;
1718 addr[2] = spa;
1719
1720 if (hmac_sha384_vector(kck, kck_len, 3, addr, len, hash) < 0)
1721 return -1;
1722 os_memcpy(pmkid, hash, PMKID_LEN);
1723 return 0;
1724}
1725#endif /* CONFIG_SUITEB192 */
1726
1727
43fb5297
JM
1728/**
1729 * wpa_cipher_txt - Convert cipher suite to a text string
1730 * @cipher: Cipher suite (WPA_CIPHER_* enum)
1731 * Returns: Pointer to a text string of the cipher suite name
1732 */
1733const char * wpa_cipher_txt(int cipher)
1734{
1735 switch (cipher) {
1736 case WPA_CIPHER_NONE:
1737 return "NONE";
1738 case WPA_CIPHER_WEP40:
1739 return "WEP-40";
1740 case WPA_CIPHER_WEP104:
1741 return "WEP-104";
1742 case WPA_CIPHER_TKIP:
1743 return "TKIP";
1744 case WPA_CIPHER_CCMP:
1745 return "CCMP";
1746 case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
1747 return "CCMP+TKIP";
eb7719ff
JM
1748 case WPA_CIPHER_GCMP:
1749 return "GCMP";
30675c34
JM
1750 case WPA_CIPHER_GCMP_256:
1751 return "GCMP-256";
1752 case WPA_CIPHER_CCMP_256:
1753 return "CCMP-256";
3a5954ef
JM
1754 case WPA_CIPHER_AES_128_CMAC:
1755 return "BIP";
1756 case WPA_CIPHER_BIP_GMAC_128:
1757 return "BIP-GMAC-128";
1758 case WPA_CIPHER_BIP_GMAC_256:
1759 return "BIP-GMAC-256";
1760 case WPA_CIPHER_BIP_CMAC_256:
1761 return "BIP-CMAC-256";
dff1e285
JM
1762 case WPA_CIPHER_GTK_NOT_USED:
1763 return "GTK_NOT_USED";
43fb5297
JM
1764 default:
1765 return "UNKNOWN";
1766 }
1767}
1768
1769
1770/**
1771 * wpa_key_mgmt_txt - Convert key management suite to a text string
1772 * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
1773 * @proto: WPA/WPA2 version (WPA_PROTO_*)
1774 * Returns: Pointer to a text string of the key management suite name
1775 */
1776const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
1777{
1778 switch (key_mgmt) {
1779 case WPA_KEY_MGMT_IEEE8021X:
1780 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1781 return "WPA2+WPA/IEEE 802.1X/EAP";
1782 return proto == WPA_PROTO_RSN ?
1783 "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
1784 case WPA_KEY_MGMT_PSK:
1785 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1786 return "WPA2-PSK+WPA-PSK";
1787 return proto == WPA_PROTO_RSN ?
1788 "WPA2-PSK" : "WPA-PSK";
1789 case WPA_KEY_MGMT_NONE:
1790 return "NONE";
4ac5f2f8
SB
1791 case WPA_KEY_MGMT_WPA_NONE:
1792 return "WPA-NONE";
43fb5297
JM
1793 case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
1794 return "IEEE 802.1X (no WPA)";
1795#ifdef CONFIG_IEEE80211R
1796 case WPA_KEY_MGMT_FT_IEEE8021X:
1797 return "FT-EAP";
c22bb5bb
JM
1798 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
1799 return "FT-EAP-SHA384";
43fb5297
JM
1800 case WPA_KEY_MGMT_FT_PSK:
1801 return "FT-PSK";
1802#endif /* CONFIG_IEEE80211R */
1803#ifdef CONFIG_IEEE80211W
1804 case WPA_KEY_MGMT_IEEE8021X_SHA256:
1805 return "WPA2-EAP-SHA256";
1806 case WPA_KEY_MGMT_PSK_SHA256:
1807 return "WPA2-PSK-SHA256";
1808#endif /* CONFIG_IEEE80211W */
72c5c289
JM
1809 case WPA_KEY_MGMT_WPS:
1810 return "WPS";
1811 case WPA_KEY_MGMT_SAE:
1812 return "SAE";
1813 case WPA_KEY_MGMT_FT_SAE:
1814 return "FT-SAE";
1815 case WPA_KEY_MGMT_OSEN:
1816 return "OSEN";
666497c8
JM
1817 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
1818 return "WPA2-EAP-SUITE-B";
5e3b5197
JM
1819 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
1820 return "WPA2-EAP-SUITE-B-192";
94318a0d
JM
1821 case WPA_KEY_MGMT_FILS_SHA256:
1822 return "FILS-SHA256";
1823 case WPA_KEY_MGMT_FILS_SHA384:
1824 return "FILS-SHA384";
1825 case WPA_KEY_MGMT_FT_FILS_SHA256:
1826 return "FT-FILS-SHA256";
1827 case WPA_KEY_MGMT_FT_FILS_SHA384:
1828 return "FT-FILS-SHA384";
88850232
JM
1829 case WPA_KEY_MGMT_OWE:
1830 return "OWE";
1831 case WPA_KEY_MGMT_DPP:
1832 return "DPP";
43fb5297
JM
1833 default:
1834 return "UNKNOWN";
1835 }
1836}
26e23750
JM
1837
1838
6c460eaf
JM
1839u32 wpa_akm_to_suite(int akm)
1840{
c22bb5bb
JM
1841 if (akm & WPA_KEY_MGMT_FT_IEEE8021X_SHA384)
1842 return RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384;
6c460eaf 1843 if (akm & WPA_KEY_MGMT_FT_IEEE8021X)
bf9f8a05 1844 return RSN_AUTH_KEY_MGMT_FT_802_1X;
6c460eaf 1845 if (akm & WPA_KEY_MGMT_FT_PSK)
bf9f8a05 1846 return RSN_AUTH_KEY_MGMT_FT_PSK;
6c460eaf 1847 if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256)
bf9f8a05 1848 return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
6c460eaf 1849 if (akm & WPA_KEY_MGMT_IEEE8021X)
bf9f8a05 1850 return RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
6c460eaf 1851 if (akm & WPA_KEY_MGMT_PSK_SHA256)
bf9f8a05 1852 return RSN_AUTH_KEY_MGMT_PSK_SHA256;
6c460eaf 1853 if (akm & WPA_KEY_MGMT_PSK)
bf9f8a05 1854 return RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
6c460eaf 1855 if (akm & WPA_KEY_MGMT_CCKM)
bf9f8a05 1856 return RSN_AUTH_KEY_MGMT_CCKM;
6c460eaf 1857 if (akm & WPA_KEY_MGMT_OSEN)
bf9f8a05 1858 return RSN_AUTH_KEY_MGMT_OSEN;
666497c8 1859 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
bf9f8a05 1860 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
5e3b5197 1861 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
bf9f8a05 1862 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
94318a0d 1863 if (akm & WPA_KEY_MGMT_FILS_SHA256)
bf9f8a05 1864 return RSN_AUTH_KEY_MGMT_FILS_SHA256;
94318a0d 1865 if (akm & WPA_KEY_MGMT_FILS_SHA384)
bf9f8a05 1866 return RSN_AUTH_KEY_MGMT_FILS_SHA384;
94318a0d 1867 if (akm & WPA_KEY_MGMT_FT_FILS_SHA256)
bf9f8a05 1868 return RSN_AUTH_KEY_MGMT_FT_FILS_SHA256;
94318a0d 1869 if (akm & WPA_KEY_MGMT_FT_FILS_SHA384)
bf9f8a05 1870 return RSN_AUTH_KEY_MGMT_FT_FILS_SHA384;
6c460eaf
JM
1871 return 0;
1872}
1873
1874
26e23750
JM
1875int wpa_compare_rsn_ie(int ft_initial_assoc,
1876 const u8 *ie1, size_t ie1len,
1877 const u8 *ie2, size_t ie2len)
1878{
d3ccead3
JM
1879 if (ie1 == NULL || ie2 == NULL)
1880 return -1;
1881
26e23750
JM
1882 if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
1883 return 0; /* identical IEs */
1884
1885#ifdef CONFIG_IEEE80211R
1886 if (ft_initial_assoc) {
1887 struct wpa_ie_data ie1d, ie2d;
1888 /*
1889 * The PMKID-List in RSN IE is different between Beacon/Probe
1890 * Response/(Re)Association Request frames and EAPOL-Key
1891 * messages in FT initial mobility domain association. Allow
1892 * for this, but verify that other parts of the RSN IEs are
1893 * identical.
1894 */
1895 if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
1896 wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
1897 return -1;
1898 if (ie1d.proto == ie2d.proto &&
1899 ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
1900 ie1d.group_cipher == ie2d.group_cipher &&
1901 ie1d.key_mgmt == ie2d.key_mgmt &&
1902 ie1d.capabilities == ie2d.capabilities &&
1903 ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
1904 return 0;
1905 }
1906#endif /* CONFIG_IEEE80211R */
1907
1908 return -1;
1909}
1910
1911
14de9e31 1912#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
59e78c24 1913int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
26e23750
JM
1914{
1915 u8 *start, *end, *rpos, *rend;
1916 int added = 0;
1917
1918 start = ies;
59e78c24 1919 end = ies + *ies_len;
26e23750
JM
1920
1921 while (start < end) {
1922 if (*start == WLAN_EID_RSN)
1923 break;
1924 start += 2 + start[1];
1925 }
1926 if (start >= end) {
1927 wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
1928 "IEs data");
1929 return -1;
1930 }
1931 wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
1932 start, 2 + start[1]);
1933
1934 /* Find start of PMKID-Count */
1935 rpos = start + 2;
1936 rend = rpos + start[1];
1937
1938 /* Skip Version and Group Data Cipher Suite */
1939 rpos += 2 + 4;
1940 /* Skip Pairwise Cipher Suite Count and List */
1941 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1942 /* Skip AKM Suite Count and List */
1943 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1944
1945 if (rpos == rend) {
1946 /* Add RSN Capabilities */
1947 os_memmove(rpos + 2, rpos, end - rpos);
1948 *rpos++ = 0;
1949 *rpos++ = 0;
3bc25adb
JM
1950 added += 2;
1951 start[1] += 2;
1952 rend = rpos;
26e23750
JM
1953 } else {
1954 /* Skip RSN Capabilities */
1955 rpos += 2;
1956 if (rpos > rend) {
1957 wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
1958 "IEs data");
1959 return -1;
1960 }
1961 }
1962
1963 if (rpos == rend) {
1964 /* No PMKID-Count field included; add it */
3bc25adb 1965 os_memmove(rpos + 2 + PMKID_LEN, rpos, end + added - rpos);
26e23750
JM
1966 WPA_PUT_LE16(rpos, 1);
1967 rpos += 2;
1968 os_memcpy(rpos, pmkid, PMKID_LEN);
1969 added += 2 + PMKID_LEN;
1970 start[1] += 2 + PMKID_LEN;
1971 } else {
59e78c24
JM
1972 u16 num_pmkid;
1973
1974 if (rend - rpos < 2)
26e23750 1975 return -1;
59e78c24
JM
1976 num_pmkid = WPA_GET_LE16(rpos);
1977 /* PMKID-Count was included; use it */
1978 if (num_pmkid != 0) {
1979 u8 *after;
1980
1981 if (num_pmkid * PMKID_LEN > rend - rpos - 2)
1982 return -1;
1983 /*
1984 * PMKID may have been included in RSN IE in
1985 * (Re)Association Request frame, so remove the old
1986 * PMKID(s) first before adding the new one.
1987 */
1988 wpa_printf(MSG_DEBUG,
1989 "FT: Remove %u old PMKID(s) from RSN IE",
1990 num_pmkid);
1991 after = rpos + 2 + num_pmkid * PMKID_LEN;
1992 os_memmove(rpos + 2, after, rend - after);
1993 start[1] -= num_pmkid * PMKID_LEN;
1994 added -= num_pmkid * PMKID_LEN;
26e23750
JM
1995 }
1996 WPA_PUT_LE16(rpos, 1);
1997 rpos += 2;
3bc25adb 1998 os_memmove(rpos + PMKID_LEN, rpos, end + added - rpos);
26e23750
JM
1999 os_memcpy(rpos, pmkid, PMKID_LEN);
2000 added += PMKID_LEN;
2001 start[1] += PMKID_LEN;
2002 }
2003
2004 wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
2005 "(PMKID inserted)", start, 2 + start[1]);
2006
59e78c24
JM
2007 *ies_len += added;
2008
2009 return 0;
26e23750 2010}
14de9e31 2011#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
c3550295
JM
2012
2013
2014int wpa_cipher_key_len(int cipher)
2015{
2016 switch (cipher) {
30675c34
JM
2017 case WPA_CIPHER_CCMP_256:
2018 case WPA_CIPHER_GCMP_256:
8dd9f9cd
JM
2019 case WPA_CIPHER_BIP_GMAC_256:
2020 case WPA_CIPHER_BIP_CMAC_256:
30675c34 2021 return 32;
c3550295
JM
2022 case WPA_CIPHER_CCMP:
2023 case WPA_CIPHER_GCMP:
8dd9f9cd
JM
2024 case WPA_CIPHER_AES_128_CMAC:
2025 case WPA_CIPHER_BIP_GMAC_128:
c3550295
JM
2026 return 16;
2027 case WPA_CIPHER_TKIP:
2028 return 32;
c3550295
JM
2029 }
2030
2031 return 0;
2032}
2033
2034
2035int wpa_cipher_rsc_len(int cipher)
2036{
2037 switch (cipher) {
30675c34
JM
2038 case WPA_CIPHER_CCMP_256:
2039 case WPA_CIPHER_GCMP_256:
c3550295
JM
2040 case WPA_CIPHER_CCMP:
2041 case WPA_CIPHER_GCMP:
2042 case WPA_CIPHER_TKIP:
2043 return 6;
c3550295
JM
2044 }
2045
2046 return 0;
2047}
2048
2049
04f02faa 2050enum wpa_alg wpa_cipher_to_alg(int cipher)
c3550295
JM
2051{
2052 switch (cipher) {
30675c34
JM
2053 case WPA_CIPHER_CCMP_256:
2054 return WPA_ALG_CCMP_256;
2055 case WPA_CIPHER_GCMP_256:
2056 return WPA_ALG_GCMP_256;
c3550295
JM
2057 case WPA_CIPHER_CCMP:
2058 return WPA_ALG_CCMP;
2059 case WPA_CIPHER_GCMP:
2060 return WPA_ALG_GCMP;
2061 case WPA_CIPHER_TKIP:
2062 return WPA_ALG_TKIP;
8dd9f9cd
JM
2063 case WPA_CIPHER_AES_128_CMAC:
2064 return WPA_ALG_IGTK;
2065 case WPA_CIPHER_BIP_GMAC_128:
2066 return WPA_ALG_BIP_GMAC_128;
2067 case WPA_CIPHER_BIP_GMAC_256:
2068 return WPA_ALG_BIP_GMAC_256;
2069 case WPA_CIPHER_BIP_CMAC_256:
2070 return WPA_ALG_BIP_CMAC_256;
c3550295
JM
2071 }
2072 return WPA_ALG_NONE;
2073}
2074
2075
2076int wpa_cipher_valid_pairwise(int cipher)
2077{
30675c34
JM
2078 return cipher == WPA_CIPHER_CCMP_256 ||
2079 cipher == WPA_CIPHER_GCMP_256 ||
2080 cipher == WPA_CIPHER_CCMP ||
c3550295
JM
2081 cipher == WPA_CIPHER_GCMP ||
2082 cipher == WPA_CIPHER_TKIP;
2083}
2084
2085
2086u32 wpa_cipher_to_suite(int proto, int cipher)
2087{
30675c34
JM
2088 if (cipher & WPA_CIPHER_CCMP_256)
2089 return RSN_CIPHER_SUITE_CCMP_256;
2090 if (cipher & WPA_CIPHER_GCMP_256)
2091 return RSN_CIPHER_SUITE_GCMP_256;
c3550295
JM
2092 if (cipher & WPA_CIPHER_CCMP)
2093 return (proto == WPA_PROTO_RSN ?
2094 RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
2095 if (cipher & WPA_CIPHER_GCMP)
2096 return RSN_CIPHER_SUITE_GCMP;
2097 if (cipher & WPA_CIPHER_TKIP)
2098 return (proto == WPA_PROTO_RSN ?
2099 RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
c3550295
JM
2100 if (cipher & WPA_CIPHER_NONE)
2101 return (proto == WPA_PROTO_RSN ?
2102 RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
dff1e285
JM
2103 if (cipher & WPA_CIPHER_GTK_NOT_USED)
2104 return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
8dd9f9cd
JM
2105 if (cipher & WPA_CIPHER_AES_128_CMAC)
2106 return RSN_CIPHER_SUITE_AES_128_CMAC;
2107 if (cipher & WPA_CIPHER_BIP_GMAC_128)
2108 return RSN_CIPHER_SUITE_BIP_GMAC_128;
2109 if (cipher & WPA_CIPHER_BIP_GMAC_256)
2110 return RSN_CIPHER_SUITE_BIP_GMAC_256;
2111 if (cipher & WPA_CIPHER_BIP_CMAC_256)
2112 return RSN_CIPHER_SUITE_BIP_CMAC_256;
c3550295
JM
2113 return 0;
2114}
2115
2116
8a4ce280 2117int rsn_cipher_put_suites(u8 *start, int ciphers)
c3550295 2118{
8a4ce280 2119 u8 *pos = start;
c3550295 2120
30675c34
JM
2121 if (ciphers & WPA_CIPHER_CCMP_256) {
2122 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256);
2123 pos += RSN_SELECTOR_LEN;
30675c34
JM
2124 }
2125 if (ciphers & WPA_CIPHER_GCMP_256) {
2126 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256);
2127 pos += RSN_SELECTOR_LEN;
30675c34 2128 }
c3550295
JM
2129 if (ciphers & WPA_CIPHER_CCMP) {
2130 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
2131 pos += RSN_SELECTOR_LEN;
c3550295
JM
2132 }
2133 if (ciphers & WPA_CIPHER_GCMP) {
2134 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP);
2135 pos += RSN_SELECTOR_LEN;
c3550295
JM
2136 }
2137 if (ciphers & WPA_CIPHER_TKIP) {
2138 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
2139 pos += RSN_SELECTOR_LEN;
c3550295
JM
2140 }
2141 if (ciphers & WPA_CIPHER_NONE) {
2142 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
2143 pos += RSN_SELECTOR_LEN;
c3550295
JM
2144 }
2145
8a4ce280 2146 return (pos - start) / RSN_SELECTOR_LEN;
c3550295
JM
2147}
2148
2149
8a4ce280 2150int wpa_cipher_put_suites(u8 *start, int ciphers)
c3550295 2151{
8a4ce280 2152 u8 *pos = start;
c3550295
JM
2153
2154 if (ciphers & WPA_CIPHER_CCMP) {
2155 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
2156 pos += WPA_SELECTOR_LEN;
c3550295
JM
2157 }
2158 if (ciphers & WPA_CIPHER_TKIP) {
2159 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
2160 pos += WPA_SELECTOR_LEN;
c3550295
JM
2161 }
2162 if (ciphers & WPA_CIPHER_NONE) {
2163 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
2164 pos += WPA_SELECTOR_LEN;
c3550295
JM
2165 }
2166
8a4ce280 2167 return (pos - start) / RSN_SELECTOR_LEN;
c3550295 2168}
edbd2a19
JM
2169
2170
2171int wpa_pick_pairwise_cipher(int ciphers, int none_allowed)
2172{
30675c34
JM
2173 if (ciphers & WPA_CIPHER_CCMP_256)
2174 return WPA_CIPHER_CCMP_256;
2175 if (ciphers & WPA_CIPHER_GCMP_256)
2176 return WPA_CIPHER_GCMP_256;
edbd2a19
JM
2177 if (ciphers & WPA_CIPHER_CCMP)
2178 return WPA_CIPHER_CCMP;
2179 if (ciphers & WPA_CIPHER_GCMP)
2180 return WPA_CIPHER_GCMP;
2181 if (ciphers & WPA_CIPHER_TKIP)
2182 return WPA_CIPHER_TKIP;
2183 if (none_allowed && (ciphers & WPA_CIPHER_NONE))
2184 return WPA_CIPHER_NONE;
2185 return -1;
2186}
2187
2188
2189int wpa_pick_group_cipher(int ciphers)
2190{
30675c34
JM
2191 if (ciphers & WPA_CIPHER_CCMP_256)
2192 return WPA_CIPHER_CCMP_256;
2193 if (ciphers & WPA_CIPHER_GCMP_256)
2194 return WPA_CIPHER_GCMP_256;
edbd2a19
JM
2195 if (ciphers & WPA_CIPHER_CCMP)
2196 return WPA_CIPHER_CCMP;
2197 if (ciphers & WPA_CIPHER_GCMP)
2198 return WPA_CIPHER_GCMP;
dff1e285
JM
2199 if (ciphers & WPA_CIPHER_GTK_NOT_USED)
2200 return WPA_CIPHER_GTK_NOT_USED;
edbd2a19
JM
2201 if (ciphers & WPA_CIPHER_TKIP)
2202 return WPA_CIPHER_TKIP;
edbd2a19
JM
2203 return -1;
2204}
a39c78be
JM
2205
2206
2207int wpa_parse_cipher(const char *value)
2208{
2209 int val = 0, last;
2210 char *start, *end, *buf;
2211
2212 buf = os_strdup(value);
2213 if (buf == NULL)
2214 return -1;
2215 start = buf;
2216
2217 while (*start != '\0') {
2218 while (*start == ' ' || *start == '\t')
2219 start++;
2220 if (*start == '\0')
2221 break;
2222 end = start;
2223 while (*end != ' ' && *end != '\t' && *end != '\0')
2224 end++;
2225 last = *end == '\0';
2226 *end = '\0';
30675c34
JM
2227 if (os_strcmp(start, "CCMP-256") == 0)
2228 val |= WPA_CIPHER_CCMP_256;
2229 else if (os_strcmp(start, "GCMP-256") == 0)
2230 val |= WPA_CIPHER_GCMP_256;
2231 else if (os_strcmp(start, "CCMP") == 0)
a39c78be
JM
2232 val |= WPA_CIPHER_CCMP;
2233 else if (os_strcmp(start, "GCMP") == 0)
2234 val |= WPA_CIPHER_GCMP;
2235 else if (os_strcmp(start, "TKIP") == 0)
2236 val |= WPA_CIPHER_TKIP;
2237 else if (os_strcmp(start, "WEP104") == 0)
2238 val |= WPA_CIPHER_WEP104;
2239 else if (os_strcmp(start, "WEP40") == 0)
2240 val |= WPA_CIPHER_WEP40;
2241 else if (os_strcmp(start, "NONE") == 0)
2242 val |= WPA_CIPHER_NONE;
dff1e285
JM
2243 else if (os_strcmp(start, "GTK_NOT_USED") == 0)
2244 val |= WPA_CIPHER_GTK_NOT_USED;
61a56c14
JM
2245 else if (os_strcmp(start, "AES-128-CMAC") == 0)
2246 val |= WPA_CIPHER_AES_128_CMAC;
2247 else if (os_strcmp(start, "BIP-GMAC-128") == 0)
2248 val |= WPA_CIPHER_BIP_GMAC_128;
2249 else if (os_strcmp(start, "BIP-GMAC-256") == 0)
2250 val |= WPA_CIPHER_BIP_GMAC_256;
2251 else if (os_strcmp(start, "BIP-CMAC-256") == 0)
2252 val |= WPA_CIPHER_BIP_CMAC_256;
a39c78be
JM
2253 else {
2254 os_free(buf);
2255 return -1;
2256 }
2257
2258 if (last)
2259 break;
2260 start = end + 1;
2261 }
2262 os_free(buf);
2263
2264 return val;
2265}
0282a8c4
JM
2266
2267
2268int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
2269{
2270 char *pos = start;
2271 int ret;
2272
30675c34
JM
2273 if (ciphers & WPA_CIPHER_CCMP_256) {
2274 ret = os_snprintf(pos, end - pos, "%sCCMP-256",
2275 pos == start ? "" : delim);
d85e1fc8 2276 if (os_snprintf_error(end - pos, ret))
30675c34
JM
2277 return -1;
2278 pos += ret;
2279 }
2280 if (ciphers & WPA_CIPHER_GCMP_256) {
2281 ret = os_snprintf(pos, end - pos, "%sGCMP-256",
2282 pos == start ? "" : delim);
d85e1fc8 2283 if (os_snprintf_error(end - pos, ret))
30675c34
JM
2284 return -1;
2285 pos += ret;
2286 }
0282a8c4
JM
2287 if (ciphers & WPA_CIPHER_CCMP) {
2288 ret = os_snprintf(pos, end - pos, "%sCCMP",
2289 pos == start ? "" : delim);
d85e1fc8 2290 if (os_snprintf_error(end - pos, ret))
0282a8c4
JM
2291 return -1;
2292 pos += ret;
2293 }
2294 if (ciphers & WPA_CIPHER_GCMP) {
2295 ret = os_snprintf(pos, end - pos, "%sGCMP",
2296 pos == start ? "" : delim);
d85e1fc8 2297 if (os_snprintf_error(end - pos, ret))
0282a8c4
JM
2298 return -1;
2299 pos += ret;
2300 }
2301 if (ciphers & WPA_CIPHER_TKIP) {
2302 ret = os_snprintf(pos, end - pos, "%sTKIP",
2303 pos == start ? "" : delim);
d85e1fc8 2304 if (os_snprintf_error(end - pos, ret))
0282a8c4
JM
2305 return -1;
2306 pos += ret;
2307 }
61a56c14
JM
2308 if (ciphers & WPA_CIPHER_AES_128_CMAC) {
2309 ret = os_snprintf(pos, end - pos, "%sAES-128-CMAC",
2310 pos == start ? "" : delim);
2311 if (os_snprintf_error(end - pos, ret))
2312 return -1;
2313 pos += ret;
2314 }
2315 if (ciphers & WPA_CIPHER_BIP_GMAC_128) {
2316 ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-128",
2317 pos == start ? "" : delim);
2318 if (os_snprintf_error(end - pos, ret))
2319 return -1;
2320 pos += ret;
2321 }
2322 if (ciphers & WPA_CIPHER_BIP_GMAC_256) {
2323 ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-256",
2324 pos == start ? "" : delim);
2325 if (os_snprintf_error(end - pos, ret))
2326 return -1;
2327 pos += ret;
2328 }
2329 if (ciphers & WPA_CIPHER_BIP_CMAC_256) {
2330 ret = os_snprintf(pos, end - pos, "%sBIP-CMAC-256",
2331 pos == start ? "" : delim);
2332 if (os_snprintf_error(end - pos, ret))
2333 return -1;
2334 pos += ret;
2335 }
0282a8c4
JM
2336 if (ciphers & WPA_CIPHER_NONE) {
2337 ret = os_snprintf(pos, end - pos, "%sNONE",
2338 pos == start ? "" : delim);
d85e1fc8 2339 if (os_snprintf_error(end - pos, ret))
0282a8c4
JM
2340 return -1;
2341 pos += ret;
2342 }
2343
2344 return pos - start;
2345}
cf830c1c
JM
2346
2347
2348int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
2349{
2350 int pairwise = 0;
2351
2352 /* Select group cipher based on the enabled pairwise cipher suites */
2353 if (wpa & 1)
2354 pairwise |= wpa_pairwise;
2355 if (wpa & 2)
2356 pairwise |= rsn_pairwise;
2357
2358 if (pairwise & WPA_CIPHER_TKIP)
2359 return WPA_CIPHER_TKIP;
2360 if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP)
2361 return WPA_CIPHER_GCMP;
30675c34
JM
2362 if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP |
2363 WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256)
2364 return WPA_CIPHER_GCMP_256;
2365 if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
2366 WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256)
2367 return WPA_CIPHER_CCMP_256;
cf830c1c
JM
2368 return WPA_CIPHER_CCMP;
2369}
94f66e8a
JM
2370
2371
2372#ifdef CONFIG_FILS
42b847ac 2373int fils_domain_name_hash(const char *domain, u8 *hash)
94f66e8a
JM
2374{
2375 char buf[255], *wpos = buf;
2376 const char *pos = domain;
2377 size_t len;
42b847ac
JM
2378 const u8 *addr[1];
2379 u8 mac[SHA256_MAC_LEN];
94f66e8a
JM
2380
2381 for (len = 0; len < sizeof(buf) && *pos; len++) {
2382 if (isalpha(*pos) && isupper(*pos))
2383 *wpos++ = tolower(*pos);
2384 else
2385 *wpos++ = *pos;
2386 pos++;
2387 }
2388
42b847ac
JM
2389 addr[0] = (const u8 *) buf;
2390 if (sha256_vector(1, addr, &len, mac) < 0)
2391 return -1;
2392 os_memcpy(hash, mac, 2);
2393 return 0;
94f66e8a
JM
2394}
2395#endif /* CONFIG_FILS */