blob: 4bab6b9c159a17f5f80f6ff53bdbba84cfef3a8e [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA/RSN - Shared functions for supplicant and authenticator
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003 * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "crypto/md5.h"
13#include "crypto/sha1.h"
14#include "crypto/sha256.h"
Dmitry Shmidt807291d2015-01-27 13:40:23 -080015#include "crypto/sha384.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070016#include "crypto/sha512.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070017#include "crypto/aes_wrap.h"
18#include "crypto/crypto.h"
19#include "ieee802_11_defs.h"
20#include "defs.h"
21#include "wpa_common.h"
22
23
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070024static unsigned int wpa_kck_len(int akmp, size_t pmk_len)
Dmitry Shmidt807291d2015-01-27 13:40:23 -080025{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080026 switch (akmp) {
27 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
Dmitry Shmidt807291d2015-01-27 13:40:23 -080028 return 24;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080029 case WPA_KEY_MGMT_FILS_SHA256:
30 case WPA_KEY_MGMT_FT_FILS_SHA256:
31 case WPA_KEY_MGMT_FILS_SHA384:
32 case WPA_KEY_MGMT_FT_FILS_SHA384:
33 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070034 case WPA_KEY_MGMT_DPP:
35 return pmk_len / 2;
36 case WPA_KEY_MGMT_OWE:
37 return pmk_len / 2;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080038 default:
39 return 16;
40 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -080041}
42
43
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070044static unsigned int wpa_kek_len(int akmp, size_t pmk_len)
Dmitry Shmidt807291d2015-01-27 13:40:23 -080045{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080046 switch (akmp) {
47 case WPA_KEY_MGMT_FILS_SHA384:
48 case WPA_KEY_MGMT_FT_FILS_SHA384:
49 return 64;
50 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
51 case WPA_KEY_MGMT_FILS_SHA256:
52 case WPA_KEY_MGMT_FT_FILS_SHA256:
Dmitry Shmidt807291d2015-01-27 13:40:23 -080053 return 32;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070054 case WPA_KEY_MGMT_DPP:
55 return pmk_len <= 32 ? 16 : 32;
56 case WPA_KEY_MGMT_OWE:
57 return pmk_len <= 32 ? 16 : 32;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080058 default:
59 return 16;
60 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -080061}
62
63
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070064unsigned int wpa_mic_len(int akmp, size_t pmk_len)
Dmitry Shmidt807291d2015-01-27 13:40:23 -080065{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080066 switch (akmp) {
67 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
Dmitry Shmidt807291d2015-01-27 13:40:23 -080068 return 24;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080069 case WPA_KEY_MGMT_FILS_SHA256:
70 case WPA_KEY_MGMT_FILS_SHA384:
71 case WPA_KEY_MGMT_FT_FILS_SHA256:
72 case WPA_KEY_MGMT_FT_FILS_SHA384:
73 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070074 case WPA_KEY_MGMT_DPP:
75 return pmk_len / 2;
76 case WPA_KEY_MGMT_OWE:
77 return pmk_len / 2;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080078 default:
79 return 16;
80 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -080081}
82
83
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070084/**
85 * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
86 * @key: EAPOL-Key Key Confirmation Key (KCK)
Dmitry Shmidt807291d2015-01-27 13:40:23 -080087 * @key_len: KCK length in octets
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080088 * @akmp: WPA_KEY_MGMT_* used in key derivation
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070089 * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
90 * @buf: Pointer to the beginning of the EAPOL header (version field)
91 * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
92 * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written
93 * Returns: 0 on success, -1 on failure
94 *
95 * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has
96 * to be cleared (all zeroes) when calling this function.
97 *
98 * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the
99 * description of the Key MIC calculation. It includes packet data from the
100 * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change
101 * happened during final editing of the standard and the correct behavior is
102 * defined in the last draft (IEEE 802.11i/D10).
103 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800104int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
105 const u8 *buf, size_t len, u8 *mic)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700106{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700107 u8 hash[SHA512_MAC_LEN];
108
109 if (key_len == 0) {
110 wpa_printf(MSG_DEBUG,
111 "WPA: KCK not set - cannot calculate MIC");
112 return -1;
113 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700114
115 switch (ver) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700116#ifndef CONFIG_FIPS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700117 case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700118 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-MD5");
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800119 return hmac_md5(key, key_len, buf, len, mic);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700120#endif /* CONFIG_FIPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700121 case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700122 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-SHA1");
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800123 if (hmac_sha1(key, key_len, buf, len, hash))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700124 return -1;
125 os_memcpy(mic, hash, MD5_MAC_LEN);
126 break;
127#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
128 case WPA_KEY_INFO_TYPE_AES_128_CMAC:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700129 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using AES-CMAC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700130 return omac1_aes_128(key, buf, len, mic);
131#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800132 case WPA_KEY_INFO_TYPE_AKM_DEFINED:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800133 switch (akmp) {
134#ifdef CONFIG_HS20
135 case WPA_KEY_MGMT_OSEN:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700136 wpa_printf(MSG_DEBUG,
137 "WPA: EAPOL-Key MIC using AES-CMAC (AKM-defined - OSEN)");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800138 return omac1_aes_128(key, buf, len, mic);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800139#endif /* CONFIG_HS20 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800140#ifdef CONFIG_SUITEB
141 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700142 wpa_printf(MSG_DEBUG,
143 "WPA: EAPOL-Key MIC using HMAC-SHA256 (AKM-defined - Suite B)");
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800144 if (hmac_sha256(key, key_len, buf, len, hash))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800145 return -1;
146 os_memcpy(mic, hash, MD5_MAC_LEN);
147 break;
148#endif /* CONFIG_SUITEB */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800149#ifdef CONFIG_SUITEB192
150 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700151 wpa_printf(MSG_DEBUG,
152 "WPA: EAPOL-Key MIC using HMAC-SHA384 (AKM-defined - Suite B 192-bit)");
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800153 if (hmac_sha384(key, key_len, buf, len, hash))
154 return -1;
155 os_memcpy(mic, hash, 24);
156 break;
157#endif /* CONFIG_SUITEB192 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700158#ifdef CONFIG_OWE
159 case WPA_KEY_MGMT_OWE:
160 wpa_printf(MSG_DEBUG,
161 "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - OWE)",
162 (unsigned int) key_len * 8 * 2);
163 if (key_len == 128 / 8) {
164 if (hmac_sha256(key, key_len, buf, len, hash))
165 return -1;
166 } else if (key_len == 192 / 8) {
167 if (hmac_sha384(key, key_len, buf, len, hash))
168 return -1;
169 } else if (key_len == 256 / 8) {
170 if (hmac_sha512(key, key_len, buf, len, hash))
171 return -1;
172 } else {
173 wpa_printf(MSG_INFO,
174 "OWE: Unsupported KCK length: %u",
175 (unsigned int) key_len);
176 return -1;
177 }
178 os_memcpy(mic, hash, key_len);
179 break;
180#endif /* CONFIG_OWE */
181#ifdef CONFIG_DPP
182 case WPA_KEY_MGMT_DPP:
183 wpa_printf(MSG_DEBUG,
184 "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - DPP)",
185 (unsigned int) key_len * 8 * 2);
186 if (key_len == 128 / 8) {
187 if (hmac_sha256(key, key_len, buf, len, hash))
188 return -1;
189 } else if (key_len == 192 / 8) {
190 if (hmac_sha384(key, key_len, buf, len, hash))
191 return -1;
192 } else if (key_len == 256 / 8) {
193 if (hmac_sha512(key, key_len, buf, len, hash))
194 return -1;
195 } else {
196 wpa_printf(MSG_INFO,
197 "DPP: Unsupported KCK length: %u",
198 (unsigned int) key_len);
199 return -1;
200 }
201 os_memcpy(mic, hash, key_len);
202 break;
203#endif /* CONFIG_DPP */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800204 default:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700205 wpa_printf(MSG_DEBUG,
206 "WPA: EAPOL-Key MIC algorithm not known (AKM-defined - akmp=0x%x)",
207 akmp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800208 return -1;
209 }
210 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700211 default:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700212 wpa_printf(MSG_DEBUG,
213 "WPA: EAPOL-Key MIC algorithm not known (ver=%d)",
214 ver);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700215 return -1;
216 }
217
218 return 0;
219}
220
221
222/**
223 * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces
224 * @pmk: Pairwise master key
225 * @pmk_len: Length of PMK
226 * @label: Label to use in derivation
227 * @addr1: AA or SA
228 * @addr2: SA or AA
229 * @nonce1: ANonce or SNonce
230 * @nonce2: SNonce or ANonce
231 * @ptk: Buffer for pairwise transient key
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800232 * @akmp: Negotiated AKM
233 * @cipher: Negotiated pairwise cipher
234 * Returns: 0 on success, -1 on failure
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700235 *
236 * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
237 * PTK = PRF-X(PMK, "Pairwise key expansion",
238 * Min(AA, SA) || Max(AA, SA) ||
239 * Min(ANonce, SNonce) || Max(ANonce, SNonce))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700240 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800241int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
242 const u8 *addr1, const u8 *addr2,
243 const u8 *nonce1, const u8 *nonce2,
244 struct wpa_ptk *ptk, int akmp, int cipher)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700245{
246 u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800247 u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
248 size_t ptk_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700249
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700250 if (pmk_len == 0) {
251 wpa_printf(MSG_ERROR, "WPA: No PMK set for PT derivation");
252 return -1;
253 }
254
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700255 if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
256 os_memcpy(data, addr1, ETH_ALEN);
257 os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
258 } else {
259 os_memcpy(data, addr2, ETH_ALEN);
260 os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
261 }
262
263 if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) {
264 os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);
265 os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,
266 WPA_NONCE_LEN);
267 } else {
268 os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);
269 os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,
270 WPA_NONCE_LEN);
271 }
272
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700273 ptk->kck_len = wpa_kck_len(akmp, pmk_len);
274 ptk->kek_len = wpa_kek_len(akmp, pmk_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800275 ptk->tk_len = wpa_cipher_key_len(cipher);
276 ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
277
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700278 if (wpa_key_mgmt_sha384(akmp)) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800279#if defined(CONFIG_SUITEB192) || defined(CONFIG_FILS)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700280 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)");
281 if (sha384_prf(pmk, pmk_len, label, data, sizeof(data),
282 tmp, ptk_len) < 0)
283 return -1;
284#else /* CONFIG_SUITEB192 || CONFIG_FILS */
285 return -1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800286#endif /* CONFIG_SUITEB192 || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700287 } else if (wpa_key_mgmt_sha256(akmp) || akmp == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700288#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700289 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)");
290 if (sha256_prf(pmk, pmk_len, label, data, sizeof(data),
291 tmp, ptk_len) < 0)
292 return -1;
293#else /* CONFIG_IEEE80211W */
294 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700295#endif /* CONFIG_IEEE80211W */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700296#ifdef CONFIG_DPP
297 } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 32) {
298 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)");
299 if (sha256_prf(pmk, pmk_len, label, data, sizeof(data),
300 tmp, ptk_len) < 0)
301 return -1;
302 } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 48) {
303 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)");
304 if (sha384_prf(pmk, pmk_len, label, data, sizeof(data),
305 tmp, ptk_len) < 0)
306 return -1;
307 } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 64) {
308 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA512)");
309 if (sha512_prf(pmk, pmk_len, label, data, sizeof(data),
310 tmp, ptk_len) < 0)
311 return -1;
312 } else if (akmp == WPA_KEY_MGMT_DPP) {
313 wpa_printf(MSG_INFO, "DPP: Unknown PMK length %u",
314 (unsigned int) pmk_len);
315 return -1;
316#endif /* CONFIG_DPP */
317 } else {
318 wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA1)");
319 if (sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp,
320 ptk_len) < 0)
321 return -1;
322 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700323
324 wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
325 MAC2STR(addr1), MAC2STR(addr2));
326 wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
327 wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN);
328 wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800329 wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", tmp, ptk_len);
330
331 os_memcpy(ptk->kck, tmp, ptk->kck_len);
332 wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", ptk->kck, ptk->kck_len);
333
334 os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len);
335 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len);
336
337 os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len);
338 wpa_hexdump_key(MSG_DEBUG, "WPA: TK", ptk->tk, ptk->tk_len);
339
340 os_memset(tmp, 0, sizeof(tmp));
341 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700342}
343
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800344#ifdef CONFIG_FILS
345
Paul Stewart092955c2017-02-06 09:13:09 -0800346int fils_rmsk_to_pmk(int akmp, const u8 *rmsk, size_t rmsk_len,
347 const u8 *snonce, const u8 *anonce, const u8 *dh_ss,
348 size_t dh_ss_len, u8 *pmk, size_t *pmk_len)
349{
350 u8 nonces[2 * FILS_NONCE_LEN];
351 const u8 *addr[2];
352 size_t len[2];
353 size_t num_elem;
354 int res;
355
356 /* PMK = HMAC-Hash(SNonce || ANonce, rMSK [ || DHss ]) */
357 wpa_printf(MSG_DEBUG, "FILS: rMSK to PMK derivation");
358
359 if (wpa_key_mgmt_sha384(akmp))
360 *pmk_len = SHA384_MAC_LEN;
361 else if (wpa_key_mgmt_sha256(akmp))
362 *pmk_len = SHA256_MAC_LEN;
363 else
364 return -1;
365
366 wpa_hexdump_key(MSG_DEBUG, "FILS: rMSK", rmsk, rmsk_len);
367 wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN);
368 wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN);
369 wpa_hexdump(MSG_DEBUG, "FILS: DHss", dh_ss, dh_ss_len);
370
371 os_memcpy(nonces, snonce, FILS_NONCE_LEN);
372 os_memcpy(&nonces[FILS_NONCE_LEN], anonce, FILS_NONCE_LEN);
373 addr[0] = rmsk;
374 len[0] = rmsk_len;
375 num_elem = 1;
376 if (dh_ss) {
377 addr[1] = dh_ss;
378 len[1] = dh_ss_len;
379 num_elem++;
380 }
381 if (wpa_key_mgmt_sha384(akmp))
382 res = hmac_sha384_vector(nonces, 2 * FILS_NONCE_LEN, num_elem,
383 addr, len, pmk);
384 else
385 res = hmac_sha256_vector(nonces, 2 * FILS_NONCE_LEN, num_elem,
386 addr, len, pmk);
387 if (res == 0)
388 wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, *pmk_len);
389 return res;
390}
391
392
393int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len,
394 u8 *pmkid)
395{
396 const u8 *addr[1];
397 size_t len[1];
398 u8 hash[SHA384_MAC_LEN];
399 int res;
400
401 /* PMKID = Truncate-128(Hash(EAP-Initiate/Reauth)) */
402 addr[0] = reauth;
403 len[0] = reauth_len;
404 if (wpa_key_mgmt_sha384(akmp))
405 res = sha384_vector(1, addr, len, hash);
406 else if (wpa_key_mgmt_sha256(akmp))
407 res = sha256_vector(1, addr, len, hash);
408 else
409 return -1;
410 if (res)
411 return res;
412 os_memcpy(pmkid, hash, PMKID_LEN);
413 wpa_hexdump(MSG_DEBUG, "FILS: PMKID", pmkid, PMKID_LEN);
414 return 0;
415}
416
417
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800418int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700419 const u8 *snonce, const u8 *anonce, const u8 *dhss,
420 size_t dhss_len, struct wpa_ptk *ptk,
421 u8 *ick, size_t *ick_len, int akmp, int cipher,
422 u8 *fils_ft, size_t *fils_ft_len)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800423{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700424 u8 *data, *pos;
425 size_t data_len;
426 u8 tmp[FILS_ICK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN +
427 FILS_FT_MAX_LEN];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800428 size_t key_data_len;
429 const char *label = "FILS PTK Derivation";
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700430 int ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800431
432 /*
433 * FILS-Key-Data = PRF-X(PMK, "FILS PTK Derivation",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700434 * SPA || AA || SNonce || ANonce [ || DHss ])
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800435 * ICK = L(FILS-Key-Data, 0, ICK_bits)
436 * KEK = L(FILS-Key-Data, ICK_bits, KEK_bits)
437 * TK = L(FILS-Key-Data, ICK_bits + KEK_bits, TK_bits)
438 * If doing FT initial mobility domain association:
439 * FILS-FT = L(FILS-Key-Data, ICK_bits + KEK_bits + TK_bits,
440 * FILS-FT_bits)
441 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700442 data_len = 2 * ETH_ALEN + 2 * FILS_NONCE_LEN + dhss_len;
443 data = os_malloc(data_len);
444 if (!data)
445 goto err;
446 pos = data;
447 os_memcpy(pos, spa, ETH_ALEN);
448 pos += ETH_ALEN;
449 os_memcpy(pos, aa, ETH_ALEN);
450 pos += ETH_ALEN;
451 os_memcpy(pos, snonce, FILS_NONCE_LEN);
452 pos += FILS_NONCE_LEN;
453 os_memcpy(pos, anonce, FILS_NONCE_LEN);
454 pos += FILS_NONCE_LEN;
455 if (dhss)
456 os_memcpy(pos, dhss, dhss_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800457
458 ptk->kck_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700459 ptk->kek_len = wpa_kek_len(akmp, pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800460 ptk->tk_len = wpa_cipher_key_len(cipher);
461 if (wpa_key_mgmt_sha384(akmp))
462 *ick_len = 48;
463 else if (wpa_key_mgmt_sha256(akmp))
464 *ick_len = 32;
465 else
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700466 goto err;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800467 key_data_len = *ick_len + ptk->kek_len + ptk->tk_len;
468
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700469 if (fils_ft && fils_ft_len) {
470 if (akmp == WPA_KEY_MGMT_FT_FILS_SHA256) {
471 *fils_ft_len = 32;
472 } else if (akmp == WPA_KEY_MGMT_FT_FILS_SHA384) {
473 *fils_ft_len = 48;
474 } else {
475 *fils_ft_len = 0;
476 fils_ft = NULL;
477 }
478 key_data_len += *fils_ft_len;
479 }
480
481 if (wpa_key_mgmt_sha384(akmp)) {
482 wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA384)");
483 if (sha384_prf(pmk, pmk_len, label, data, data_len,
484 tmp, key_data_len) < 0)
485 goto err;
486 } else {
487 wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA256)");
488 if (sha256_prf(pmk, pmk_len, label, data, data_len,
489 tmp, key_data_len) < 0)
490 goto err;
491 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800492
493 wpa_printf(MSG_DEBUG, "FILS: PTK derivation - SPA=" MACSTR
494 " AA=" MACSTR, MAC2STR(spa), MAC2STR(aa));
495 wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN);
496 wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700497 if (dhss)
498 wpa_hexdump_key(MSG_DEBUG, "FILS: DHss", dhss, dhss_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800499 wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, pmk_len);
500 wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-Key-Data", tmp, key_data_len);
501
502 os_memcpy(ick, tmp, *ick_len);
503 wpa_hexdump_key(MSG_DEBUG, "FILS: ICK", ick, *ick_len);
504
505 os_memcpy(ptk->kek, tmp + *ick_len, ptk->kek_len);
506 wpa_hexdump_key(MSG_DEBUG, "FILS: KEK", ptk->kek, ptk->kek_len);
507
508 os_memcpy(ptk->tk, tmp + *ick_len + ptk->kek_len, ptk->tk_len);
509 wpa_hexdump_key(MSG_DEBUG, "FILS: TK", ptk->tk, ptk->tk_len);
510
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700511 if (fils_ft && fils_ft_len) {
512 os_memcpy(fils_ft, tmp + *ick_len + ptk->kek_len + ptk->tk_len,
513 *fils_ft_len);
514 wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-FT",
515 fils_ft, *fils_ft_len);
516 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800517
518 os_memset(tmp, 0, sizeof(tmp));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700519 ret = 0;
520err:
521 bin_clear_free(data, data_len);
522 return ret;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800523}
524
525
526int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce,
527 const u8 *anonce, const u8 *sta_addr, const u8 *bssid,
528 const u8 *g_sta, size_t g_sta_len,
529 const u8 *g_ap, size_t g_ap_len,
530 int akmp, u8 *key_auth_sta, u8 *key_auth_ap,
531 size_t *key_auth_len)
532{
533 const u8 *addr[6];
534 size_t len[6];
535 size_t num_elem = 4;
536 int res;
537
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700538 wpa_printf(MSG_DEBUG, "FILS: Key-Auth derivation: STA-MAC=" MACSTR
539 " AP-BSSID=" MACSTR, MAC2STR(sta_addr), MAC2STR(bssid));
540 wpa_hexdump_key(MSG_DEBUG, "FILS: ICK", ick, ick_len);
541 wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN);
542 wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN);
543 wpa_hexdump(MSG_DEBUG, "FILS: gSTA", g_sta, g_sta_len);
544 wpa_hexdump(MSG_DEBUG, "FILS: gAP", g_ap, g_ap_len);
545
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800546 /*
547 * For (Re)Association Request frame (STA->AP):
548 * Key-Auth = HMAC-Hash(ICK, SNonce || ANonce || STA-MAC || AP-BSSID
549 * [ || gSTA || gAP ])
550 */
551 addr[0] = snonce;
552 len[0] = FILS_NONCE_LEN;
553 addr[1] = anonce;
554 len[1] = FILS_NONCE_LEN;
555 addr[2] = sta_addr;
556 len[2] = ETH_ALEN;
557 addr[3] = bssid;
558 len[3] = ETH_ALEN;
559 if (g_sta && g_ap_len && g_ap && g_ap_len) {
560 addr[4] = g_sta;
561 len[4] = g_sta_len;
562 addr[5] = g_ap;
563 len[5] = g_ap_len;
564 num_elem = 6;
565 }
566
567 if (wpa_key_mgmt_sha384(akmp)) {
568 *key_auth_len = 48;
569 res = hmac_sha384_vector(ick, ick_len, num_elem, addr, len,
570 key_auth_sta);
571 } else if (wpa_key_mgmt_sha256(akmp)) {
572 *key_auth_len = 32;
573 res = hmac_sha256_vector(ick, ick_len, num_elem, addr, len,
574 key_auth_sta);
575 } else {
576 return -1;
577 }
578 if (res < 0)
579 return res;
580
581 /*
582 * For (Re)Association Response frame (AP->STA):
583 * Key-Auth = HMAC-Hash(ICK, ANonce || SNonce || AP-BSSID || STA-MAC
584 * [ || gAP || gSTA ])
585 */
586 addr[0] = anonce;
587 addr[1] = snonce;
588 addr[2] = bssid;
589 addr[3] = sta_addr;
590 if (g_sta && g_ap_len && g_ap && g_ap_len) {
591 addr[4] = g_ap;
592 len[4] = g_ap_len;
593 addr[5] = g_sta;
594 len[5] = g_sta_len;
595 }
596
597 if (wpa_key_mgmt_sha384(akmp))
598 res = hmac_sha384_vector(ick, ick_len, num_elem, addr, len,
599 key_auth_ap);
600 else if (wpa_key_mgmt_sha256(akmp))
601 res = hmac_sha256_vector(ick, ick_len, num_elem, addr, len,
602 key_auth_ap);
603 if (res < 0)
604 return res;
605
606 wpa_hexdump(MSG_DEBUG, "FILS: Key-Auth (STA)",
607 key_auth_sta, *key_auth_len);
608 wpa_hexdump(MSG_DEBUG, "FILS: Key-Auth (AP)",
609 key_auth_ap, *key_auth_len);
610
611 return 0;
612}
613
614#endif /* CONFIG_FILS */
615
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700616
617#ifdef CONFIG_IEEE80211R
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800618int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
619 const u8 *ap_addr, u8 transaction_seqnum,
620 const u8 *mdie, size_t mdie_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700621 const u8 *ftie, size_t ftie_len,
622 const u8 *rsnie, size_t rsnie_len,
623 const u8 *ric, size_t ric_len, u8 *mic)
624{
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700625 const u8 *addr[9];
626 size_t len[9];
627 size_t i, num_elem = 0;
628 u8 zero_mic[16];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700629
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800630 if (kck_len != 16) {
631 wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u",
632 (unsigned int) kck_len);
633 return -1;
634 }
635
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700636 addr[num_elem] = sta_addr;
637 len[num_elem] = ETH_ALEN;
638 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700639
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700640 addr[num_elem] = ap_addr;
641 len[num_elem] = ETH_ALEN;
642 num_elem++;
643
644 addr[num_elem] = &transaction_seqnum;
645 len[num_elem] = 1;
646 num_elem++;
647
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700648 if (rsnie) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700649 addr[num_elem] = rsnie;
650 len[num_elem] = rsnie_len;
651 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700652 }
653 if (mdie) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700654 addr[num_elem] = mdie;
655 len[num_elem] = mdie_len;
656 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700657 }
658 if (ftie) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700659 if (ftie_len < 2 + sizeof(struct rsn_ftie))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700660 return -1;
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700661
662 /* IE hdr and mic_control */
663 addr[num_elem] = ftie;
664 len[num_elem] = 2 + 2;
665 num_elem++;
666
667 /* MIC field with all zeros */
668 os_memset(zero_mic, 0, sizeof(zero_mic));
669 addr[num_elem] = zero_mic;
670 len[num_elem] = sizeof(zero_mic);
671 num_elem++;
672
673 /* Rest of FTIE */
674 addr[num_elem] = ftie + 2 + 2 + 16;
675 len[num_elem] = ftie_len - (2 + 2 + 16);
676 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700677 }
678 if (ric) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700679 addr[num_elem] = ric;
680 len[num_elem] = ric_len;
681 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700682 }
683
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700684 for (i = 0; i < num_elem; i++)
685 wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", addr[i], len[i]);
686 if (omac1_aes_128_vector(kck, num_elem, addr, len, mic))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700687 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700688
689 return 0;
690}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800691
692
693static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
694 struct wpa_ft_ies *parse)
695{
696 const u8 *end, *pos;
697
698 parse->ftie = ie;
699 parse->ftie_len = ie_len;
700
701 pos = ie + sizeof(struct rsn_ftie);
702 end = ie + ie_len;
703
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800704 while (end - pos >= 2) {
705 u8 id, len;
706
707 id = *pos++;
708 len = *pos++;
709 if (len > end - pos)
710 break;
711
712 switch (id) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800713 case FTIE_SUBELEM_R1KH_ID:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800714 if (len != FT_R1KH_ID_LEN) {
715 wpa_printf(MSG_DEBUG,
716 "FT: Invalid R1KH-ID length in FTIE: %d",
717 len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800718 return -1;
719 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800720 parse->r1kh_id = pos;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800721 break;
722 case FTIE_SUBELEM_GTK:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800723 parse->gtk = pos;
724 parse->gtk_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800725 break;
726 case FTIE_SUBELEM_R0KH_ID:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800727 if (len < 1 || len > FT_R0KH_ID_MAX_LEN) {
728 wpa_printf(MSG_DEBUG,
729 "FT: Invalid R0KH-ID length in FTIE: %d",
730 len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800731 return -1;
732 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800733 parse->r0kh_id = pos;
734 parse->r0kh_id_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800735 break;
736#ifdef CONFIG_IEEE80211W
737 case FTIE_SUBELEM_IGTK:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800738 parse->igtk = pos;
739 parse->igtk_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800740 break;
741#endif /* CONFIG_IEEE80211W */
742 }
743
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800744 pos += len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800745 }
746
747 return 0;
748}
749
750
751int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
752 struct wpa_ft_ies *parse)
753{
754 const u8 *end, *pos;
755 struct wpa_ie_data data;
756 int ret;
757 const struct rsn_ftie *ftie;
758 int prot_ie_count = 0;
759
760 os_memset(parse, 0, sizeof(*parse));
761 if (ies == NULL)
762 return 0;
763
764 pos = ies;
765 end = ies + ies_len;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800766 while (end - pos >= 2) {
767 u8 id, len;
768
769 id = *pos++;
770 len = *pos++;
771 if (len > end - pos)
772 break;
773
774 switch (id) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800775 case WLAN_EID_RSN:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800776 parse->rsn = pos;
777 parse->rsn_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800778 ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
779 parse->rsn_len + 2,
780 &data);
781 if (ret < 0) {
782 wpa_printf(MSG_DEBUG, "FT: Failed to parse "
783 "RSN IE: %d", ret);
784 return -1;
785 }
786 if (data.num_pmkid == 1 && data.pmkid)
787 parse->rsn_pmkid = data.pmkid;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800788 parse->key_mgmt = data.key_mgmt;
789 parse->pairwise_cipher = data.pairwise_cipher;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800790 break;
791 case WLAN_EID_MOBILITY_DOMAIN:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800792 if (len < sizeof(struct rsn_mdie))
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700793 return -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800794 parse->mdie = pos;
795 parse->mdie_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800796 break;
797 case WLAN_EID_FAST_BSS_TRANSITION:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800798 if (len < sizeof(*ftie))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800799 return -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800800 ftie = (const struct rsn_ftie *) pos;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800801 prot_ie_count = ftie->mic_control[1];
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800802 if (wpa_ft_parse_ftie(pos, len, parse) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800803 return -1;
804 break;
805 case WLAN_EID_TIMEOUT_INTERVAL:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800806 if (len != 5)
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700807 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800808 parse->tie = pos;
809 parse->tie_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800810 break;
811 case WLAN_EID_RIC_DATA:
812 if (parse->ric == NULL)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800813 parse->ric = pos - 2;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800814 break;
815 }
816
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800817 pos += len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800818 }
819
820 if (prot_ie_count == 0)
821 return 0; /* no MIC */
822
823 /*
824 * Check that the protected IE count matches with IEs included in the
825 * frame.
826 */
827 if (parse->rsn)
828 prot_ie_count--;
829 if (parse->mdie)
830 prot_ie_count--;
831 if (parse->ftie)
832 prot_ie_count--;
833 if (prot_ie_count < 0) {
834 wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
835 "the protected IE count");
836 return -1;
837 }
838
839 if (prot_ie_count == 0 && parse->ric) {
840 wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
841 "included in protected IE count");
842 return -1;
843 }
844
845 /* Determine the end of the RIC IE(s) */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800846 if (parse->ric) {
847 pos = parse->ric;
848 while (end - pos >= 2 && 2 + pos[1] <= end - pos &&
849 prot_ie_count) {
850 prot_ie_count--;
851 pos += 2 + pos[1];
852 }
853 parse->ric_len = pos - parse->ric;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800854 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800855 if (prot_ie_count) {
856 wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
857 "frame", (int) prot_ie_count);
858 return -1;
859 }
860
861 return 0;
862}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700863#endif /* CONFIG_IEEE80211R */
864
865
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700866static int rsn_selector_to_bitfield(const u8 *s)
867{
868 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
869 return WPA_CIPHER_NONE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700870 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
871 return WPA_CIPHER_TKIP;
872 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
873 return WPA_CIPHER_CCMP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700874#ifdef CONFIG_IEEE80211W
875 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
876 return WPA_CIPHER_AES_128_CMAC;
877#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700878 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
879 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800880 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256)
881 return WPA_CIPHER_CCMP_256;
882 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256)
883 return WPA_CIPHER_GCMP_256;
884 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128)
885 return WPA_CIPHER_BIP_GMAC_128;
886 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256)
887 return WPA_CIPHER_BIP_GMAC_256;
888 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256)
889 return WPA_CIPHER_BIP_CMAC_256;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700890 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED)
891 return WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700892 return 0;
893}
894
895
896static int rsn_key_mgmt_to_bitfield(const u8 *s)
897{
898 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
899 return WPA_KEY_MGMT_IEEE8021X;
900 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
901 return WPA_KEY_MGMT_PSK;
902#ifdef CONFIG_IEEE80211R
903 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
904 return WPA_KEY_MGMT_FT_IEEE8021X;
905 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
906 return WPA_KEY_MGMT_FT_PSK;
907#endif /* CONFIG_IEEE80211R */
908#ifdef CONFIG_IEEE80211W
909 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
910 return WPA_KEY_MGMT_IEEE8021X_SHA256;
911 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
912 return WPA_KEY_MGMT_PSK_SHA256;
913#endif /* CONFIG_IEEE80211W */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800914#ifdef CONFIG_SAE
915 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
916 return WPA_KEY_MGMT_SAE;
917 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
918 return WPA_KEY_MGMT_FT_SAE;
919#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800920 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B)
921 return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800922 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
923 return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800924 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA256)
925 return WPA_KEY_MGMT_FILS_SHA256;
926 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA384)
927 return WPA_KEY_MGMT_FILS_SHA384;
928 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA256)
929 return WPA_KEY_MGMT_FT_FILS_SHA256;
930 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA384)
931 return WPA_KEY_MGMT_FT_FILS_SHA384;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700932#ifdef CONFIG_OWE
933 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE)
934 return WPA_KEY_MGMT_OWE;
935#endif /* CONFIG_OWE */
936#ifdef CONFIG_DPP
937 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_DPP)
938 return WPA_KEY_MGMT_DPP;
939#endif /* CONFIG_DPP */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700940 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN)
941 return WPA_KEY_MGMT_OSEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700942 return 0;
943}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700944
945
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800946int wpa_cipher_valid_group(int cipher)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700947{
948 return wpa_cipher_valid_pairwise(cipher) ||
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700949 cipher == WPA_CIPHER_GTK_NOT_USED;
950}
951
952
953#ifdef CONFIG_IEEE80211W
954int wpa_cipher_valid_mgmt_group(int cipher)
955{
956 return cipher == WPA_CIPHER_AES_128_CMAC ||
957 cipher == WPA_CIPHER_BIP_GMAC_128 ||
958 cipher == WPA_CIPHER_BIP_GMAC_256 ||
959 cipher == WPA_CIPHER_BIP_CMAC_256;
960}
961#endif /* CONFIG_IEEE80211W */
962
963
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700964/**
965 * wpa_parse_wpa_ie_rsn - Parse RSN IE
966 * @rsn_ie: Buffer containing RSN IE
967 * @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
968 * @data: Pointer to structure that will be filled in with parsed data
969 * Returns: 0 on success, <0 on failure
970 */
971int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
972 struct wpa_ie_data *data)
973{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700974 const u8 *pos;
975 int left;
976 int i, count;
977
978 os_memset(data, 0, sizeof(*data));
979 data->proto = WPA_PROTO_RSN;
980 data->pairwise_cipher = WPA_CIPHER_CCMP;
981 data->group_cipher = WPA_CIPHER_CCMP;
982 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
983 data->capabilities = 0;
984 data->pmkid = NULL;
985 data->num_pmkid = 0;
986#ifdef CONFIG_IEEE80211W
987 data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
988#else /* CONFIG_IEEE80211W */
989 data->mgmt_group_cipher = 0;
990#endif /* CONFIG_IEEE80211W */
991
992 if (rsn_ie_len == 0) {
993 /* No RSN IE - fail silently */
994 return -1;
995 }
996
997 if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
998 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
999 __func__, (unsigned long) rsn_ie_len);
1000 return -1;
1001 }
1002
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001003 if (rsn_ie_len >= 6 && rsn_ie[1] >= 4 &&
1004 rsn_ie[1] == rsn_ie_len - 2 &&
1005 WPA_GET_BE32(&rsn_ie[2]) == OSEN_IE_VENDOR_TYPE) {
1006 pos = rsn_ie + 6;
1007 left = rsn_ie_len - 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001009 data->proto = WPA_PROTO_OSEN;
1010 } else {
1011 const struct rsn_ie_hdr *hdr;
1012
1013 hdr = (const struct rsn_ie_hdr *) rsn_ie;
1014
1015 if (hdr->elem_id != WLAN_EID_RSN ||
1016 hdr->len != rsn_ie_len - 2 ||
1017 WPA_GET_LE16(hdr->version) != RSN_VERSION) {
1018 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
1019 __func__);
1020 return -2;
1021 }
1022
1023 pos = (const u8 *) (hdr + 1);
1024 left = rsn_ie_len - sizeof(*hdr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025 }
1026
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001027 if (left >= RSN_SELECTOR_LEN) {
1028 data->group_cipher = rsn_selector_to_bitfield(pos);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001029 if (!wpa_cipher_valid_group(data->group_cipher)) {
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08001030 wpa_printf(MSG_DEBUG,
1031 "%s: invalid group cipher 0x%x (%08x)",
1032 __func__, data->group_cipher,
1033 WPA_GET_BE32(pos));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034 return -1;
1035 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001036 pos += RSN_SELECTOR_LEN;
1037 left -= RSN_SELECTOR_LEN;
1038 } else if (left > 0) {
1039 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
1040 __func__, left);
1041 return -3;
1042 }
1043
1044 if (left >= 2) {
1045 data->pairwise_cipher = 0;
1046 count = WPA_GET_LE16(pos);
1047 pos += 2;
1048 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001049 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001050 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
1051 "count %u left %u", __func__, count, left);
1052 return -4;
1053 }
1054 for (i = 0; i < count; i++) {
1055 data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
1056 pos += RSN_SELECTOR_LEN;
1057 left -= RSN_SELECTOR_LEN;
1058 }
1059#ifdef CONFIG_IEEE80211W
1060 if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
1061 wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
1062 "pairwise cipher", __func__);
1063 return -1;
1064 }
1065#endif /* CONFIG_IEEE80211W */
1066 } else if (left == 1) {
1067 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
1068 __func__);
1069 return -5;
1070 }
1071
1072 if (left >= 2) {
1073 data->key_mgmt = 0;
1074 count = WPA_GET_LE16(pos);
1075 pos += 2;
1076 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001077 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001078 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
1079 "count %u left %u", __func__, count, left);
1080 return -6;
1081 }
1082 for (i = 0; i < count; i++) {
1083 data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
1084 pos += RSN_SELECTOR_LEN;
1085 left -= RSN_SELECTOR_LEN;
1086 }
1087 } else if (left == 1) {
1088 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
1089 __func__);
1090 return -7;
1091 }
1092
1093 if (left >= 2) {
1094 data->capabilities = WPA_GET_LE16(pos);
1095 pos += 2;
1096 left -= 2;
1097 }
1098
1099 if (left >= 2) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001100 u16 num_pmkid = WPA_GET_LE16(pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001101 pos += 2;
1102 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001103 if (num_pmkid > (unsigned int) left / PMKID_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001104 wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001105 "(num_pmkid=%u left=%d)",
1106 __func__, num_pmkid, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001107 data->num_pmkid = 0;
1108 return -9;
1109 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001110 data->num_pmkid = num_pmkid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001111 data->pmkid = pos;
1112 pos += data->num_pmkid * PMKID_LEN;
1113 left -= data->num_pmkid * PMKID_LEN;
1114 }
1115 }
1116
1117#ifdef CONFIG_IEEE80211W
1118 if (left >= 4) {
1119 data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001120 if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001121 wpa_printf(MSG_DEBUG,
1122 "%s: Unsupported management group cipher 0x%x (%08x)",
1123 __func__, data->mgmt_group_cipher,
1124 WPA_GET_BE32(pos));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001125 return -10;
1126 }
1127 pos += RSN_SELECTOR_LEN;
1128 left -= RSN_SELECTOR_LEN;
1129 }
1130#endif /* CONFIG_IEEE80211W */
1131
1132 if (left > 0) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001133 wpa_hexdump(MSG_DEBUG,
1134 "wpa_parse_wpa_ie_rsn: ignore trailing bytes",
1135 pos, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001136 }
1137
1138 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001139}
1140
1141
1142static int wpa_selector_to_bitfield(const u8 *s)
1143{
1144 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
1145 return WPA_CIPHER_NONE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001146 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
1147 return WPA_CIPHER_TKIP;
1148 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
1149 return WPA_CIPHER_CCMP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001150 return 0;
1151}
1152
1153
1154static int wpa_key_mgmt_to_bitfield(const u8 *s)
1155{
1156 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
1157 return WPA_KEY_MGMT_IEEE8021X;
1158 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
1159 return WPA_KEY_MGMT_PSK;
1160 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
1161 return WPA_KEY_MGMT_WPA_NONE;
1162 return 0;
1163}
1164
1165
1166int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
1167 struct wpa_ie_data *data)
1168{
1169 const struct wpa_ie_hdr *hdr;
1170 const u8 *pos;
1171 int left;
1172 int i, count;
1173
1174 os_memset(data, 0, sizeof(*data));
1175 data->proto = WPA_PROTO_WPA;
1176 data->pairwise_cipher = WPA_CIPHER_TKIP;
1177 data->group_cipher = WPA_CIPHER_TKIP;
1178 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1179 data->capabilities = 0;
1180 data->pmkid = NULL;
1181 data->num_pmkid = 0;
1182 data->mgmt_group_cipher = 0;
1183
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
1185 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
1186 __func__, (unsigned long) wpa_ie_len);
1187 return -1;
1188 }
1189
1190 hdr = (const struct wpa_ie_hdr *) wpa_ie;
1191
1192 if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
1193 hdr->len != wpa_ie_len - 2 ||
1194 RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
1195 WPA_GET_LE16(hdr->version) != WPA_VERSION) {
1196 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
1197 __func__);
1198 return -2;
1199 }
1200
1201 pos = (const u8 *) (hdr + 1);
1202 left = wpa_ie_len - sizeof(*hdr);
1203
1204 if (left >= WPA_SELECTOR_LEN) {
1205 data->group_cipher = wpa_selector_to_bitfield(pos);
1206 pos += WPA_SELECTOR_LEN;
1207 left -= WPA_SELECTOR_LEN;
1208 } else if (left > 0) {
1209 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
1210 __func__, left);
1211 return -3;
1212 }
1213
1214 if (left >= 2) {
1215 data->pairwise_cipher = 0;
1216 count = WPA_GET_LE16(pos);
1217 pos += 2;
1218 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001219 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001220 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
1221 "count %u left %u", __func__, count, left);
1222 return -4;
1223 }
1224 for (i = 0; i < count; i++) {
1225 data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
1226 pos += WPA_SELECTOR_LEN;
1227 left -= WPA_SELECTOR_LEN;
1228 }
1229 } else if (left == 1) {
1230 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
1231 __func__);
1232 return -5;
1233 }
1234
1235 if (left >= 2) {
1236 data->key_mgmt = 0;
1237 count = WPA_GET_LE16(pos);
1238 pos += 2;
1239 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001240 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001241 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
1242 "count %u left %u", __func__, count, left);
1243 return -6;
1244 }
1245 for (i = 0; i < count; i++) {
1246 data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
1247 pos += WPA_SELECTOR_LEN;
1248 left -= WPA_SELECTOR_LEN;
1249 }
1250 } else if (left == 1) {
1251 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
1252 __func__);
1253 return -7;
1254 }
1255
1256 if (left >= 2) {
1257 data->capabilities = WPA_GET_LE16(pos);
1258 pos += 2;
1259 left -= 2;
1260 }
1261
1262 if (left > 0) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001263 wpa_hexdump(MSG_DEBUG,
1264 "wpa_parse_wpa_ie_wpa: ignore trailing bytes",
1265 pos, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001266 }
1267
1268 return 0;
1269}
1270
1271
1272#ifdef CONFIG_IEEE80211R
1273
1274/**
1275 * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
1276 *
1277 * IEEE Std 802.11r-2008 - 8.5.1.5.3
1278 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001279int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
1280 const u8 *ssid, size_t ssid_len,
1281 const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
1282 const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001283{
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001284 u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001285 FT_R0KH_ID_MAX_LEN + ETH_ALEN];
1286 u8 *pos, r0_key_data[48], hash[32];
1287 const u8 *addr[2];
1288 size_t len[2];
1289
1290 /*
1291 * R0-Key-Data = KDF-384(XXKey, "FT-R0",
1292 * SSIDlength || SSID || MDID || R0KHlength ||
1293 * R0KH-ID || S0KH-ID)
1294 * XXKey is either the second 256 bits of MSK or PSK.
1295 * PMK-R0 = L(R0-Key-Data, 0, 256)
1296 * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
1297 */
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001298 if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001299 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001300 pos = buf;
1301 *pos++ = ssid_len;
1302 os_memcpy(pos, ssid, ssid_len);
1303 pos += ssid_len;
1304 os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
1305 pos += MOBILITY_DOMAIN_ID_LEN;
1306 *pos++ = r0kh_id_len;
1307 os_memcpy(pos, r0kh_id, r0kh_id_len);
1308 pos += r0kh_id_len;
1309 os_memcpy(pos, s0kh_id, ETH_ALEN);
1310 pos += ETH_ALEN;
1311
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001312 if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
1313 r0_key_data, sizeof(r0_key_data)) < 0)
1314 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001315 os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
1316
1317 /*
1318 * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
1319 */
1320 addr[0] = (const u8 *) "FT-R0N";
1321 len[0] = 6;
1322 addr[1] = r0_key_data + PMK_LEN;
1323 len[1] = 16;
1324
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001325 if (sha256_vector(2, addr, len, hash) < 0)
1326 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001327 os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001328 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001329}
1330
1331
1332/**
1333 * wpa_derive_pmk_r1_name - Derive PMKR1Name
1334 *
1335 * IEEE Std 802.11r-2008 - 8.5.1.5.4
1336 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001337int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
1338 const u8 *s1kh_id, u8 *pmk_r1_name)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001339{
1340 u8 hash[32];
1341 const u8 *addr[4];
1342 size_t len[4];
1343
1344 /*
1345 * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
1346 * R1KH-ID || S1KH-ID))
1347 */
1348 addr[0] = (const u8 *) "FT-R1N";
1349 len[0] = 6;
1350 addr[1] = pmk_r0_name;
1351 len[1] = WPA_PMK_NAME_LEN;
1352 addr[2] = r1kh_id;
1353 len[2] = FT_R1KH_ID_LEN;
1354 addr[3] = s1kh_id;
1355 len[3] = ETH_ALEN;
1356
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001357 if (sha256_vector(4, addr, len, hash) < 0)
1358 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001359 os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001360 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001361}
1362
1363
1364/**
1365 * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
1366 *
1367 * IEEE Std 802.11r-2008 - 8.5.1.5.4
1368 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001369int wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
1370 const u8 *r1kh_id, const u8 *s1kh_id,
1371 u8 *pmk_r1, u8 *pmk_r1_name)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001372{
1373 u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
1374 u8 *pos;
1375
1376 /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
1377 pos = buf;
1378 os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
1379 pos += FT_R1KH_ID_LEN;
1380 os_memcpy(pos, s1kh_id, ETH_ALEN);
1381 pos += ETH_ALEN;
1382
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001383 if (sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf,
1384 pmk_r1, PMK_LEN) < 0)
1385 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001387 return wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id,
1388 pmk_r1_name);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001389}
1390
1391
1392/**
1393 * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
1394 *
1395 * IEEE Std 802.11r-2008 - 8.5.1.5.5
1396 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001397int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
1398 const u8 *sta_addr, const u8 *bssid,
1399 const u8 *pmk_r1_name,
1400 struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001401{
1402 u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
1403 u8 *pos, hash[32];
1404 const u8 *addr[6];
1405 size_t len[6];
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001406 u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
1407 size_t ptk_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001408
1409 /*
1410 * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
1411 * BSSID || STA-ADDR)
1412 */
1413 pos = buf;
1414 os_memcpy(pos, snonce, WPA_NONCE_LEN);
1415 pos += WPA_NONCE_LEN;
1416 os_memcpy(pos, anonce, WPA_NONCE_LEN);
1417 pos += WPA_NONCE_LEN;
1418 os_memcpy(pos, bssid, ETH_ALEN);
1419 pos += ETH_ALEN;
1420 os_memcpy(pos, sta_addr, ETH_ALEN);
1421 pos += ETH_ALEN;
1422
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001423 ptk->kck_len = wpa_kck_len(akmp, PMK_LEN);
1424 ptk->kek_len = wpa_kek_len(akmp, PMK_LEN);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001425 ptk->tk_len = wpa_cipher_key_len(cipher);
1426 ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
1427
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001428 if (sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf,
1429 tmp, ptk_len) < 0)
1430 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001431
1432 /*
1433 * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
1434 * ANonce || BSSID || STA-ADDR))
1435 */
1436 addr[0] = pmk_r1_name;
1437 len[0] = WPA_PMK_NAME_LEN;
1438 addr[1] = (const u8 *) "FT-PTKN";
1439 len[1] = 7;
1440 addr[2] = snonce;
1441 len[2] = WPA_NONCE_LEN;
1442 addr[3] = anonce;
1443 len[3] = WPA_NONCE_LEN;
1444 addr[4] = bssid;
1445 len[4] = ETH_ALEN;
1446 addr[5] = sta_addr;
1447 len[5] = ETH_ALEN;
1448
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001449 if (sha256_vector(6, addr, len, hash) < 0)
1450 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001451 os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001452
1453 os_memcpy(ptk->kck, tmp, ptk->kck_len);
1454 os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len);
1455 os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len);
1456
1457 wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len);
1458 wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len);
1459 wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len);
1460 wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
1461
1462 os_memset(tmp, 0, sizeof(tmp));
1463
1464 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001465}
1466
1467#endif /* CONFIG_IEEE80211R */
1468
1469
1470/**
1471 * rsn_pmkid - Calculate PMK identifier
1472 * @pmk: Pairwise master key
1473 * @pmk_len: Length of pmk in bytes
1474 * @aa: Authenticator address
1475 * @spa: Supplicant address
1476 * @pmkid: Buffer for PMKID
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001477 * @akmp: Negotiated key management protocol
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001478 *
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001479 * IEEE Std 802.11-2016 - 12.7.1.3 Pairwise key hierarchy
1480 * AKM: 00-0F-AC:5, 00-0F-AC:6, 00-0F-AC:14, 00-0F-AC:16
1481 * PMKID = Truncate-128(HMAC-SHA-256(PMK, "PMK Name" || AA || SPA))
1482 * AKM: 00-0F-AC:11
1483 * See rsn_pmkid_suite_b()
1484 * AKM: 00-0F-AC:12
1485 * See rsn_pmkid_suite_b_192()
1486 * AKM: 00-0F-AC:15, 00-0F-AC:17
1487 * PMKID = Truncate-128(HMAC-SHA-384(PMK, "PMK Name" || AA || SPA))
1488 * Otherwise:
1489 * PMKID = Truncate-128(HMAC-SHA-1(PMK, "PMK Name" || AA || SPA))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001490 */
1491void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001492 u8 *pmkid, int akmp)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001493{
1494 char *title = "PMK Name";
1495 const u8 *addr[3];
1496 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001497 unsigned char hash[SHA384_MAC_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001498
1499 addr[0] = (u8 *) title;
1500 addr[1] = aa;
1501 addr[2] = spa;
1502
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001503 if (0) {
1504#ifdef CONFIG_FILS
1505 } else if (wpa_key_mgmt_sha384(akmp)) {
1506 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-384");
1507 hmac_sha384_vector(pmk, pmk_len, 3, addr, len, hash);
1508#endif /* CONFIG_FILS */
1509#if defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS)
1510 } else if (wpa_key_mgmt_sha256(akmp)) {
1511 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001512 hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001513#endif /* CONFIG_IEEE80211W || CONFIG_FILS */
1514 } else {
1515 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-1");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001516 hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001517 }
1518 wpa_hexdump(MSG_DEBUG, "RSN: Derived PMKID", hash, PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001519 os_memcpy(pmkid, hash, PMKID_LEN);
1520}
1521
1522
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001523#ifdef CONFIG_SUITEB
1524/**
1525 * rsn_pmkid_suite_b - Calculate PMK identifier for Suite B AKM
1526 * @kck: Key confirmation key
1527 * @kck_len: Length of kck in bytes
1528 * @aa: Authenticator address
1529 * @spa: Supplicant address
1530 * @pmkid: Buffer for PMKID
1531 * Returns: 0 on success, -1 on failure
1532 *
1533 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1534 * PMKID = Truncate(HMAC-SHA-256(KCK, "PMK Name" || AA || SPA))
1535 */
1536int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
1537 const u8 *spa, u8 *pmkid)
1538{
1539 char *title = "PMK Name";
1540 const u8 *addr[3];
1541 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1542 unsigned char hash[SHA256_MAC_LEN];
1543
1544 addr[0] = (u8 *) title;
1545 addr[1] = aa;
1546 addr[2] = spa;
1547
1548 if (hmac_sha256_vector(kck, kck_len, 3, addr, len, hash) < 0)
1549 return -1;
1550 os_memcpy(pmkid, hash, PMKID_LEN);
1551 return 0;
1552}
1553#endif /* CONFIG_SUITEB */
1554
1555
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001556#ifdef CONFIG_SUITEB192
1557/**
1558 * rsn_pmkid_suite_b_192 - Calculate PMK identifier for Suite B AKM
1559 * @kck: Key confirmation key
1560 * @kck_len: Length of kck in bytes
1561 * @aa: Authenticator address
1562 * @spa: Supplicant address
1563 * @pmkid: Buffer for PMKID
1564 * Returns: 0 on success, -1 on failure
1565 *
1566 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1567 * PMKID = Truncate(HMAC-SHA-384(KCK, "PMK Name" || AA || SPA))
1568 */
1569int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa,
1570 const u8 *spa, u8 *pmkid)
1571{
1572 char *title = "PMK Name";
1573 const u8 *addr[3];
1574 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1575 unsigned char hash[SHA384_MAC_LEN];
1576
1577 addr[0] = (u8 *) title;
1578 addr[1] = aa;
1579 addr[2] = spa;
1580
1581 if (hmac_sha384_vector(kck, kck_len, 3, addr, len, hash) < 0)
1582 return -1;
1583 os_memcpy(pmkid, hash, PMKID_LEN);
1584 return 0;
1585}
1586#endif /* CONFIG_SUITEB192 */
1587
1588
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001589/**
1590 * wpa_cipher_txt - Convert cipher suite to a text string
1591 * @cipher: Cipher suite (WPA_CIPHER_* enum)
1592 * Returns: Pointer to a text string of the cipher suite name
1593 */
1594const char * wpa_cipher_txt(int cipher)
1595{
1596 switch (cipher) {
1597 case WPA_CIPHER_NONE:
1598 return "NONE";
1599 case WPA_CIPHER_WEP40:
1600 return "WEP-40";
1601 case WPA_CIPHER_WEP104:
1602 return "WEP-104";
1603 case WPA_CIPHER_TKIP:
1604 return "TKIP";
1605 case WPA_CIPHER_CCMP:
1606 return "CCMP";
1607 case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
1608 return "CCMP+TKIP";
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001609 case WPA_CIPHER_GCMP:
1610 return "GCMP";
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001611 case WPA_CIPHER_GCMP_256:
1612 return "GCMP-256";
1613 case WPA_CIPHER_CCMP_256:
1614 return "CCMP-256";
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001615 case WPA_CIPHER_AES_128_CMAC:
1616 return "BIP";
1617 case WPA_CIPHER_BIP_GMAC_128:
1618 return "BIP-GMAC-128";
1619 case WPA_CIPHER_BIP_GMAC_256:
1620 return "BIP-GMAC-256";
1621 case WPA_CIPHER_BIP_CMAC_256:
1622 return "BIP-CMAC-256";
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001623 case WPA_CIPHER_GTK_NOT_USED:
1624 return "GTK_NOT_USED";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001625 default:
1626 return "UNKNOWN";
1627 }
1628}
1629
1630
1631/**
1632 * wpa_key_mgmt_txt - Convert key management suite to a text string
1633 * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
1634 * @proto: WPA/WPA2 version (WPA_PROTO_*)
1635 * Returns: Pointer to a text string of the key management suite name
1636 */
1637const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
1638{
1639 switch (key_mgmt) {
1640 case WPA_KEY_MGMT_IEEE8021X:
1641 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1642 return "WPA2+WPA/IEEE 802.1X/EAP";
1643 return proto == WPA_PROTO_RSN ?
1644 "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
1645 case WPA_KEY_MGMT_PSK:
1646 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1647 return "WPA2-PSK+WPA-PSK";
1648 return proto == WPA_PROTO_RSN ?
1649 "WPA2-PSK" : "WPA-PSK";
1650 case WPA_KEY_MGMT_NONE:
1651 return "NONE";
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001652 case WPA_KEY_MGMT_WPA_NONE:
1653 return "WPA-NONE";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001654 case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
1655 return "IEEE 802.1X (no WPA)";
1656#ifdef CONFIG_IEEE80211R
1657 case WPA_KEY_MGMT_FT_IEEE8021X:
1658 return "FT-EAP";
1659 case WPA_KEY_MGMT_FT_PSK:
1660 return "FT-PSK";
1661#endif /* CONFIG_IEEE80211R */
1662#ifdef CONFIG_IEEE80211W
1663 case WPA_KEY_MGMT_IEEE8021X_SHA256:
1664 return "WPA2-EAP-SHA256";
1665 case WPA_KEY_MGMT_PSK_SHA256:
1666 return "WPA2-PSK-SHA256";
1667#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001668 case WPA_KEY_MGMT_WPS:
1669 return "WPS";
1670 case WPA_KEY_MGMT_SAE:
1671 return "SAE";
1672 case WPA_KEY_MGMT_FT_SAE:
1673 return "FT-SAE";
1674 case WPA_KEY_MGMT_OSEN:
1675 return "OSEN";
1676 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
1677 return "WPA2-EAP-SUITE-B";
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001678 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
1679 return "WPA2-EAP-SUITE-B-192";
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001680 case WPA_KEY_MGMT_FILS_SHA256:
1681 return "FILS-SHA256";
1682 case WPA_KEY_MGMT_FILS_SHA384:
1683 return "FILS-SHA384";
1684 case WPA_KEY_MGMT_FT_FILS_SHA256:
1685 return "FT-FILS-SHA256";
1686 case WPA_KEY_MGMT_FT_FILS_SHA384:
1687 return "FT-FILS-SHA384";
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001688 case WPA_KEY_MGMT_OWE:
1689 return "OWE";
1690 case WPA_KEY_MGMT_DPP:
1691 return "DPP";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001692 default:
1693 return "UNKNOWN";
1694 }
1695}
1696
1697
Dmitry Shmidt03658832014-08-13 11:03:49 -07001698u32 wpa_akm_to_suite(int akm)
1699{
1700 if (akm & WPA_KEY_MGMT_FT_IEEE8021X)
Paul Stewart092955c2017-02-06 09:13:09 -08001701 return RSN_AUTH_KEY_MGMT_FT_802_1X;
Dmitry Shmidt03658832014-08-13 11:03:49 -07001702 if (akm & WPA_KEY_MGMT_FT_PSK)
Paul Stewart092955c2017-02-06 09:13:09 -08001703 return RSN_AUTH_KEY_MGMT_FT_PSK;
Rebecca Silberstein055a67c2017-02-01 23:05:56 +00001704 if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08001705 return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
Rebecca Silberstein055a67c2017-02-01 23:05:56 +00001706 if (akm & WPA_KEY_MGMT_IEEE8021X)
Paul Stewart092955c2017-02-06 09:13:09 -08001707 return RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
Dmitry Shmidt03658832014-08-13 11:03:49 -07001708 if (akm & WPA_KEY_MGMT_PSK_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08001709 return RSN_AUTH_KEY_MGMT_PSK_SHA256;
Dmitry Shmidt03658832014-08-13 11:03:49 -07001710 if (akm & WPA_KEY_MGMT_PSK)
Paul Stewart092955c2017-02-06 09:13:09 -08001711 return RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
Dmitry Shmidt03658832014-08-13 11:03:49 -07001712 if (akm & WPA_KEY_MGMT_CCKM)
Paul Stewart092955c2017-02-06 09:13:09 -08001713 return RSN_AUTH_KEY_MGMT_CCKM;
Dmitry Shmidt03658832014-08-13 11:03:49 -07001714 if (akm & WPA_KEY_MGMT_OSEN)
Paul Stewart092955c2017-02-06 09:13:09 -08001715 return RSN_AUTH_KEY_MGMT_OSEN;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001716 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
Paul Stewart092955c2017-02-06 09:13:09 -08001717 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001718 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Paul Stewart092955c2017-02-06 09:13:09 -08001719 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001720 if (akm & WPA_KEY_MGMT_FILS_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08001721 return RSN_AUTH_KEY_MGMT_FILS_SHA256;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001722 if (akm & WPA_KEY_MGMT_FILS_SHA384)
Paul Stewart092955c2017-02-06 09:13:09 -08001723 return RSN_AUTH_KEY_MGMT_FILS_SHA384;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001724 if (akm & WPA_KEY_MGMT_FT_FILS_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08001725 return RSN_AUTH_KEY_MGMT_FT_FILS_SHA256;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001726 if (akm & WPA_KEY_MGMT_FT_FILS_SHA384)
Paul Stewart092955c2017-02-06 09:13:09 -08001727 return RSN_AUTH_KEY_MGMT_FT_FILS_SHA384;
Dmitry Shmidt03658832014-08-13 11:03:49 -07001728 return 0;
1729}
1730
1731
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001732int wpa_compare_rsn_ie(int ft_initial_assoc,
1733 const u8 *ie1, size_t ie1len,
1734 const u8 *ie2, size_t ie2len)
1735{
1736 if (ie1 == NULL || ie2 == NULL)
1737 return -1;
1738
1739 if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
1740 return 0; /* identical IEs */
1741
1742#ifdef CONFIG_IEEE80211R
1743 if (ft_initial_assoc) {
1744 struct wpa_ie_data ie1d, ie2d;
1745 /*
1746 * The PMKID-List in RSN IE is different between Beacon/Probe
1747 * Response/(Re)Association Request frames and EAPOL-Key
1748 * messages in FT initial mobility domain association. Allow
1749 * for this, but verify that other parts of the RSN IEs are
1750 * identical.
1751 */
1752 if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
1753 wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
1754 return -1;
1755 if (ie1d.proto == ie2d.proto &&
1756 ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
1757 ie1d.group_cipher == ie2d.group_cipher &&
1758 ie1d.key_mgmt == ie2d.key_mgmt &&
1759 ie1d.capabilities == ie2d.capabilities &&
1760 ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
1761 return 0;
1762 }
1763#endif /* CONFIG_IEEE80211R */
1764
1765 return -1;
1766}
1767
1768
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001769#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001770int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001771{
1772 u8 *start, *end, *rpos, *rend;
1773 int added = 0;
1774
1775 start = ies;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001776 end = ies + *ies_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001777
1778 while (start < end) {
1779 if (*start == WLAN_EID_RSN)
1780 break;
1781 start += 2 + start[1];
1782 }
1783 if (start >= end) {
1784 wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
1785 "IEs data");
1786 return -1;
1787 }
1788 wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
1789 start, 2 + start[1]);
1790
1791 /* Find start of PMKID-Count */
1792 rpos = start + 2;
1793 rend = rpos + start[1];
1794
1795 /* Skip Version and Group Data Cipher Suite */
1796 rpos += 2 + 4;
1797 /* Skip Pairwise Cipher Suite Count and List */
1798 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1799 /* Skip AKM Suite Count and List */
1800 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1801
1802 if (rpos == rend) {
1803 /* Add RSN Capabilities */
1804 os_memmove(rpos + 2, rpos, end - rpos);
1805 *rpos++ = 0;
1806 *rpos++ = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001807 added += 2;
1808 start[1] += 2;
1809 rend = rpos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001810 } else {
1811 /* Skip RSN Capabilities */
1812 rpos += 2;
1813 if (rpos > rend) {
1814 wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
1815 "IEs data");
1816 return -1;
1817 }
1818 }
1819
1820 if (rpos == rend) {
1821 /* No PMKID-Count field included; add it */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001822 os_memmove(rpos + 2 + PMKID_LEN, rpos, end + added - rpos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823 WPA_PUT_LE16(rpos, 1);
1824 rpos += 2;
1825 os_memcpy(rpos, pmkid, PMKID_LEN);
1826 added += 2 + PMKID_LEN;
1827 start[1] += 2 + PMKID_LEN;
1828 } else {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001829 u16 num_pmkid;
1830
1831 if (rend - rpos < 2)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001832 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001833 num_pmkid = WPA_GET_LE16(rpos);
1834 /* PMKID-Count was included; use it */
1835 if (num_pmkid != 0) {
1836 u8 *after;
1837
1838 if (num_pmkid * PMKID_LEN > rend - rpos - 2)
1839 return -1;
1840 /*
1841 * PMKID may have been included in RSN IE in
1842 * (Re)Association Request frame, so remove the old
1843 * PMKID(s) first before adding the new one.
1844 */
1845 wpa_printf(MSG_DEBUG,
1846 "FT: Remove %u old PMKID(s) from RSN IE",
1847 num_pmkid);
1848 after = rpos + 2 + num_pmkid * PMKID_LEN;
1849 os_memmove(rpos + 2, after, rend - after);
1850 start[1] -= num_pmkid * PMKID_LEN;
1851 added -= num_pmkid * PMKID_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001852 }
1853 WPA_PUT_LE16(rpos, 1);
1854 rpos += 2;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001855 os_memmove(rpos + PMKID_LEN, rpos, end + added - rpos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856 os_memcpy(rpos, pmkid, PMKID_LEN);
1857 added += PMKID_LEN;
1858 start[1] += PMKID_LEN;
1859 }
1860
1861 wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
1862 "(PMKID inserted)", start, 2 + start[1]);
1863
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001864 *ies_len += added;
1865
1866 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001867}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001868#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001869
1870
1871int wpa_cipher_key_len(int cipher)
1872{
1873 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001874 case WPA_CIPHER_CCMP_256:
1875 case WPA_CIPHER_GCMP_256:
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001876 case WPA_CIPHER_BIP_GMAC_256:
1877 case WPA_CIPHER_BIP_CMAC_256:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001878 return 32;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001879 case WPA_CIPHER_CCMP:
1880 case WPA_CIPHER_GCMP:
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001881 case WPA_CIPHER_AES_128_CMAC:
1882 case WPA_CIPHER_BIP_GMAC_128:
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001883 return 16;
1884 case WPA_CIPHER_TKIP:
1885 return 32;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001886 }
1887
1888 return 0;
1889}
1890
1891
1892int wpa_cipher_rsc_len(int cipher)
1893{
1894 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001895 case WPA_CIPHER_CCMP_256:
1896 case WPA_CIPHER_GCMP_256:
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001897 case WPA_CIPHER_CCMP:
1898 case WPA_CIPHER_GCMP:
1899 case WPA_CIPHER_TKIP:
1900 return 6;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001901 }
1902
1903 return 0;
1904}
1905
1906
Dmitry Shmidt29333592017-01-09 12:27:11 -08001907enum wpa_alg wpa_cipher_to_alg(int cipher)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001908{
1909 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001910 case WPA_CIPHER_CCMP_256:
1911 return WPA_ALG_CCMP_256;
1912 case WPA_CIPHER_GCMP_256:
1913 return WPA_ALG_GCMP_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001914 case WPA_CIPHER_CCMP:
1915 return WPA_ALG_CCMP;
1916 case WPA_CIPHER_GCMP:
1917 return WPA_ALG_GCMP;
1918 case WPA_CIPHER_TKIP:
1919 return WPA_ALG_TKIP;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001920 case WPA_CIPHER_AES_128_CMAC:
1921 return WPA_ALG_IGTK;
1922 case WPA_CIPHER_BIP_GMAC_128:
1923 return WPA_ALG_BIP_GMAC_128;
1924 case WPA_CIPHER_BIP_GMAC_256:
1925 return WPA_ALG_BIP_GMAC_256;
1926 case WPA_CIPHER_BIP_CMAC_256:
1927 return WPA_ALG_BIP_CMAC_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001928 }
1929 return WPA_ALG_NONE;
1930}
1931
1932
1933int wpa_cipher_valid_pairwise(int cipher)
1934{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001935 return cipher == WPA_CIPHER_CCMP_256 ||
1936 cipher == WPA_CIPHER_GCMP_256 ||
1937 cipher == WPA_CIPHER_CCMP ||
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001938 cipher == WPA_CIPHER_GCMP ||
1939 cipher == WPA_CIPHER_TKIP;
1940}
1941
1942
1943u32 wpa_cipher_to_suite(int proto, int cipher)
1944{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001945 if (cipher & WPA_CIPHER_CCMP_256)
1946 return RSN_CIPHER_SUITE_CCMP_256;
1947 if (cipher & WPA_CIPHER_GCMP_256)
1948 return RSN_CIPHER_SUITE_GCMP_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001949 if (cipher & WPA_CIPHER_CCMP)
1950 return (proto == WPA_PROTO_RSN ?
1951 RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
1952 if (cipher & WPA_CIPHER_GCMP)
1953 return RSN_CIPHER_SUITE_GCMP;
1954 if (cipher & WPA_CIPHER_TKIP)
1955 return (proto == WPA_PROTO_RSN ?
1956 RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001957 if (cipher & WPA_CIPHER_NONE)
1958 return (proto == WPA_PROTO_RSN ?
1959 RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001960 if (cipher & WPA_CIPHER_GTK_NOT_USED)
1961 return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001962 if (cipher & WPA_CIPHER_AES_128_CMAC)
1963 return RSN_CIPHER_SUITE_AES_128_CMAC;
1964 if (cipher & WPA_CIPHER_BIP_GMAC_128)
1965 return RSN_CIPHER_SUITE_BIP_GMAC_128;
1966 if (cipher & WPA_CIPHER_BIP_GMAC_256)
1967 return RSN_CIPHER_SUITE_BIP_GMAC_256;
1968 if (cipher & WPA_CIPHER_BIP_CMAC_256)
1969 return RSN_CIPHER_SUITE_BIP_CMAC_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001970 return 0;
1971}
1972
1973
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001974int rsn_cipher_put_suites(u8 *start, int ciphers)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001975{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001976 u8 *pos = start;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001977
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001978 if (ciphers & WPA_CIPHER_CCMP_256) {
1979 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256);
1980 pos += RSN_SELECTOR_LEN;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001981 }
1982 if (ciphers & WPA_CIPHER_GCMP_256) {
1983 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256);
1984 pos += RSN_SELECTOR_LEN;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001985 }
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001986 if (ciphers & WPA_CIPHER_CCMP) {
1987 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1988 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001989 }
1990 if (ciphers & WPA_CIPHER_GCMP) {
1991 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP);
1992 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001993 }
1994 if (ciphers & WPA_CIPHER_TKIP) {
1995 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
1996 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001997 }
1998 if (ciphers & WPA_CIPHER_NONE) {
1999 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
2000 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002001 }
2002
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002003 return (pos - start) / RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002004}
2005
2006
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002007int wpa_cipher_put_suites(u8 *start, int ciphers)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002008{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002009 u8 *pos = start;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002010
2011 if (ciphers & WPA_CIPHER_CCMP) {
2012 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
2013 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002014 }
2015 if (ciphers & WPA_CIPHER_TKIP) {
2016 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
2017 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002018 }
2019 if (ciphers & WPA_CIPHER_NONE) {
2020 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
2021 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002022 }
2023
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002024 return (pos - start) / RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002025}
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002026
2027
2028int wpa_pick_pairwise_cipher(int ciphers, int none_allowed)
2029{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002030 if (ciphers & WPA_CIPHER_CCMP_256)
2031 return WPA_CIPHER_CCMP_256;
2032 if (ciphers & WPA_CIPHER_GCMP_256)
2033 return WPA_CIPHER_GCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002034 if (ciphers & WPA_CIPHER_CCMP)
2035 return WPA_CIPHER_CCMP;
2036 if (ciphers & WPA_CIPHER_GCMP)
2037 return WPA_CIPHER_GCMP;
2038 if (ciphers & WPA_CIPHER_TKIP)
2039 return WPA_CIPHER_TKIP;
2040 if (none_allowed && (ciphers & WPA_CIPHER_NONE))
2041 return WPA_CIPHER_NONE;
2042 return -1;
2043}
2044
2045
2046int wpa_pick_group_cipher(int ciphers)
2047{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002048 if (ciphers & WPA_CIPHER_CCMP_256)
2049 return WPA_CIPHER_CCMP_256;
2050 if (ciphers & WPA_CIPHER_GCMP_256)
2051 return WPA_CIPHER_GCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002052 if (ciphers & WPA_CIPHER_CCMP)
2053 return WPA_CIPHER_CCMP;
2054 if (ciphers & WPA_CIPHER_GCMP)
2055 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002056 if (ciphers & WPA_CIPHER_GTK_NOT_USED)
2057 return WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002058 if (ciphers & WPA_CIPHER_TKIP)
2059 return WPA_CIPHER_TKIP;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002060 return -1;
2061}
2062
2063
2064int wpa_parse_cipher(const char *value)
2065{
2066 int val = 0, last;
2067 char *start, *end, *buf;
2068
2069 buf = os_strdup(value);
2070 if (buf == NULL)
2071 return -1;
2072 start = buf;
2073
2074 while (*start != '\0') {
2075 while (*start == ' ' || *start == '\t')
2076 start++;
2077 if (*start == '\0')
2078 break;
2079 end = start;
2080 while (*end != ' ' && *end != '\t' && *end != '\0')
2081 end++;
2082 last = *end == '\0';
2083 *end = '\0';
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002084 if (os_strcmp(start, "CCMP-256") == 0)
2085 val |= WPA_CIPHER_CCMP_256;
2086 else if (os_strcmp(start, "GCMP-256") == 0)
2087 val |= WPA_CIPHER_GCMP_256;
2088 else if (os_strcmp(start, "CCMP") == 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002089 val |= WPA_CIPHER_CCMP;
2090 else if (os_strcmp(start, "GCMP") == 0)
2091 val |= WPA_CIPHER_GCMP;
2092 else if (os_strcmp(start, "TKIP") == 0)
2093 val |= WPA_CIPHER_TKIP;
2094 else if (os_strcmp(start, "WEP104") == 0)
2095 val |= WPA_CIPHER_WEP104;
2096 else if (os_strcmp(start, "WEP40") == 0)
2097 val |= WPA_CIPHER_WEP40;
2098 else if (os_strcmp(start, "NONE") == 0)
2099 val |= WPA_CIPHER_NONE;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002100 else if (os_strcmp(start, "GTK_NOT_USED") == 0)
2101 val |= WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002102 else if (os_strcmp(start, "AES-128-CMAC") == 0)
2103 val |= WPA_CIPHER_AES_128_CMAC;
2104 else if (os_strcmp(start, "BIP-GMAC-128") == 0)
2105 val |= WPA_CIPHER_BIP_GMAC_128;
2106 else if (os_strcmp(start, "BIP-GMAC-256") == 0)
2107 val |= WPA_CIPHER_BIP_GMAC_256;
2108 else if (os_strcmp(start, "BIP-CMAC-256") == 0)
2109 val |= WPA_CIPHER_BIP_CMAC_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002110 else {
2111 os_free(buf);
2112 return -1;
2113 }
2114
2115 if (last)
2116 break;
2117 start = end + 1;
2118 }
2119 os_free(buf);
2120
2121 return val;
2122}
2123
2124
2125int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
2126{
2127 char *pos = start;
2128 int ret;
2129
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002130 if (ciphers & WPA_CIPHER_CCMP_256) {
2131 ret = os_snprintf(pos, end - pos, "%sCCMP-256",
2132 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002133 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002134 return -1;
2135 pos += ret;
2136 }
2137 if (ciphers & WPA_CIPHER_GCMP_256) {
2138 ret = os_snprintf(pos, end - pos, "%sGCMP-256",
2139 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002140 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002141 return -1;
2142 pos += ret;
2143 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002144 if (ciphers & WPA_CIPHER_CCMP) {
2145 ret = os_snprintf(pos, end - pos, "%sCCMP",
2146 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002147 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002148 return -1;
2149 pos += ret;
2150 }
2151 if (ciphers & WPA_CIPHER_GCMP) {
2152 ret = os_snprintf(pos, end - pos, "%sGCMP",
2153 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002154 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002155 return -1;
2156 pos += ret;
2157 }
2158 if (ciphers & WPA_CIPHER_TKIP) {
2159 ret = os_snprintf(pos, end - pos, "%sTKIP",
2160 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002161 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002162 return -1;
2163 pos += ret;
2164 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002165 if (ciphers & WPA_CIPHER_AES_128_CMAC) {
2166 ret = os_snprintf(pos, end - pos, "%sAES-128-CMAC",
2167 pos == start ? "" : delim);
2168 if (os_snprintf_error(end - pos, ret))
2169 return -1;
2170 pos += ret;
2171 }
2172 if (ciphers & WPA_CIPHER_BIP_GMAC_128) {
2173 ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-128",
2174 pos == start ? "" : delim);
2175 if (os_snprintf_error(end - pos, ret))
2176 return -1;
2177 pos += ret;
2178 }
2179 if (ciphers & WPA_CIPHER_BIP_GMAC_256) {
2180 ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-256",
2181 pos == start ? "" : delim);
2182 if (os_snprintf_error(end - pos, ret))
2183 return -1;
2184 pos += ret;
2185 }
2186 if (ciphers & WPA_CIPHER_BIP_CMAC_256) {
2187 ret = os_snprintf(pos, end - pos, "%sBIP-CMAC-256",
2188 pos == start ? "" : delim);
2189 if (os_snprintf_error(end - pos, ret))
2190 return -1;
2191 pos += ret;
2192 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002193 if (ciphers & WPA_CIPHER_NONE) {
2194 ret = os_snprintf(pos, end - pos, "%sNONE",
2195 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002196 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002197 return -1;
2198 pos += ret;
2199 }
2200
2201 return pos - start;
2202}
2203
2204
2205int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
2206{
2207 int pairwise = 0;
2208
2209 /* Select group cipher based on the enabled pairwise cipher suites */
2210 if (wpa & 1)
2211 pairwise |= wpa_pairwise;
2212 if (wpa & 2)
2213 pairwise |= rsn_pairwise;
2214
2215 if (pairwise & WPA_CIPHER_TKIP)
2216 return WPA_CIPHER_TKIP;
2217 if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP)
2218 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002219 if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP |
2220 WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256)
2221 return WPA_CIPHER_GCMP_256;
2222 if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
2223 WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256)
2224 return WPA_CIPHER_CCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002225 return WPA_CIPHER_CCMP;
2226}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002227
2228
2229#ifdef CONFIG_FILS
Dmitry Shmidt29333592017-01-09 12:27:11 -08002230int fils_domain_name_hash(const char *domain, u8 *hash)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002231{
2232 char buf[255], *wpos = buf;
2233 const char *pos = domain;
2234 size_t len;
Dmitry Shmidt29333592017-01-09 12:27:11 -08002235 const u8 *addr[1];
2236 u8 mac[SHA256_MAC_LEN];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002237
2238 for (len = 0; len < sizeof(buf) && *pos; len++) {
2239 if (isalpha(*pos) && isupper(*pos))
2240 *wpos++ = tolower(*pos);
2241 else
2242 *wpos++ = *pos;
2243 pos++;
2244 }
2245
Dmitry Shmidt29333592017-01-09 12:27:11 -08002246 addr[0] = (const u8 *) buf;
2247 if (sha256_vector(1, addr, &len, mac) < 0)
2248 return -1;
2249 os_memcpy(hash, mac, 2);
2250 return 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002251}
2252#endif /* CONFIG_FILS */