blob: 14c5769b08170cefe9ec5570482bbacdf81920c7 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA/RSN - Shared functions for supplicant and authenticator
Roshan Pius3a1667e2018-07-03 15:17:14 -07003 * Copyright (c) 2002-2018, 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:
Roshan Pius3a1667e2018-07-03 15:17:14 -070028 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
Dmitry Shmidt807291d2015-01-27 13:40:23 -080029 return 24;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080030 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;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070035 case WPA_KEY_MGMT_DPP:
36 return pmk_len / 2;
37 case WPA_KEY_MGMT_OWE:
38 return pmk_len / 2;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080039 default:
40 return 16;
41 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -080042}
43
44
Roshan Pius3a1667e2018-07-03 15:17:14 -070045#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
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070060static unsigned int wpa_kek_len(int akmp, size_t pmk_len)
Dmitry Shmidt807291d2015-01-27 13:40:23 -080061{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080062 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:
Roshan Pius3a1667e2018-07-03 15:17:14 -070069 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
Dmitry Shmidt807291d2015-01-27 13:40:23 -080070 return 32;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070071 case WPA_KEY_MGMT_DPP:
72 return pmk_len <= 32 ? 16 : 32;
73 case WPA_KEY_MGMT_OWE:
74 return pmk_len <= 32 ? 16 : 32;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080075 default:
76 return 16;
77 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -080078}
79
80
Roshan Pius3a1667e2018-07-03 15:17:14 -070081#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
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070096unsigned int wpa_mic_len(int akmp, size_t pmk_len)
Dmitry Shmidt807291d2015-01-27 13:40:23 -080097{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080098 switch (akmp) {
99 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700100 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800101 return 24;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800102 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;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700107 case WPA_KEY_MGMT_DPP:
108 return pmk_len / 2;
109 case WPA_KEY_MGMT_OWE:
110 return pmk_len / 2;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800111 default:
112 return 16;
113 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800114}
115
116
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700117/**
Roshan Pius3a1667e2018-07-03 15:17:14 -0700118 * 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 ||
127 akmp == WPA_KEY_MGMT_FT_IEEE8021X_SHA384 ||
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
172/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700173 * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
174 * @key: EAPOL-Key Key Confirmation Key (KCK)
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800175 * @key_len: KCK length in octets
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800176 * @akmp: WPA_KEY_MGMT_* used in key derivation
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700177 * @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 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800192int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
193 const u8 *buf, size_t len, u8 *mic)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700194{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700195 u8 hash[SHA512_MAC_LEN];
196
197 if (key_len == 0) {
198 wpa_printf(MSG_DEBUG,
199 "WPA: KCK not set - cannot calculate MIC");
200 return -1;
201 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700202
203 switch (ver) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700204#ifndef CONFIG_FIPS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700205 case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700206 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-MD5");
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800207 return hmac_md5(key, key_len, buf, len, mic);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700208#endif /* CONFIG_FIPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700209 case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700210 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-SHA1");
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800211 if (hmac_sha1(key, key_len, buf, len, hash))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700212 return -1;
213 os_memcpy(mic, hash, MD5_MAC_LEN);
214 break;
215#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
216 case WPA_KEY_INFO_TYPE_AES_128_CMAC:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700217 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using AES-CMAC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700218 return omac1_aes_128(key, buf, len, mic);
219#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800220 case WPA_KEY_INFO_TYPE_AKM_DEFINED:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800221 switch (akmp) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700222#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 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800229#ifdef CONFIG_HS20
230 case WPA_KEY_MGMT_OSEN:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700231 wpa_printf(MSG_DEBUG,
232 "WPA: EAPOL-Key MIC using AES-CMAC (AKM-defined - OSEN)");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800233 return omac1_aes_128(key, buf, len, mic);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800234#endif /* CONFIG_HS20 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800235#ifdef CONFIG_SUITEB
236 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700237 wpa_printf(MSG_DEBUG,
238 "WPA: EAPOL-Key MIC using HMAC-SHA256 (AKM-defined - Suite B)");
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800239 if (hmac_sha256(key, key_len, buf, len, hash))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800240 return -1;
241 os_memcpy(mic, hash, MD5_MAC_LEN);
242 break;
243#endif /* CONFIG_SUITEB */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800244#ifdef CONFIG_SUITEB192
245 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700246 wpa_printf(MSG_DEBUG,
247 "WPA: EAPOL-Key MIC using HMAC-SHA384 (AKM-defined - Suite B 192-bit)");
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800248 if (hmac_sha384(key, key_len, buf, len, hash))
249 return -1;
250 os_memcpy(mic, hash, 24);
251 break;
252#endif /* CONFIG_SUITEB192 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700253#ifdef CONFIG_OWE
254 case WPA_KEY_MGMT_OWE:
255 wpa_printf(MSG_DEBUG,
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);
271 return -1;
272 }
273 os_memcpy(mic, hash, key_len);
274 break;
275#endif /* CONFIG_OWE */
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) {
288 if (hmac_sha512(key, key_len, buf, len, hash))
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 }
296 os_memcpy(mic, hash, key_len);
297 break;
298#endif /* CONFIG_DPP */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700299#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 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800308 default:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700309 wpa_printf(MSG_DEBUG,
310 "WPA: EAPOL-Key MIC algorithm not known (AKM-defined - akmp=0x%x)",
311 akmp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800312 return -1;
313 }
314 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700315 default:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700316 wpa_printf(MSG_DEBUG,
317 "WPA: EAPOL-Key MIC algorithm not known (ver=%d)",
318 ver);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700319 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
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800336 * @akmp: Negotiated AKM
337 * @cipher: Negotiated pairwise cipher
338 * Returns: 0 on success, -1 on failure
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700339 *
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))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700344 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800345int 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)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700349{
350 u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800351 u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
352 size_t ptk_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700353
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700354 if (pmk_len == 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700355 wpa_printf(MSG_ERROR, "WPA: No PMK set for PTK derivation");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700356 return -1;
357 }
358
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700359 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
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700377 ptk->kck_len = wpa_kck_len(akmp, pmk_len);
378 ptk->kek_len = wpa_kek_len(akmp, pmk_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800379 ptk->tk_len = wpa_cipher_key_len(cipher);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700380 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 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800386 ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
387
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700388 if (wpa_key_mgmt_sha384(akmp)) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800389#if defined(CONFIG_SUITEB192) || defined(CONFIG_FILS)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700390 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;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800396#endif /* CONFIG_SUITEB192 || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700397 } else if (wpa_key_mgmt_sha256(akmp) || akmp == WPA_KEY_MGMT_OWE) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700398#if defined(CONFIG_IEEE80211W) || defined(CONFIG_SAE) || defined(CONFIG_FILS)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700399 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;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700403#else /* CONFIG_IEEE80211W or CONFIG_SAE or CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700404 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700405#endif /* CONFIG_IEEE80211W or CONFIG_SAE or CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700406#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 */
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 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700433
434 wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
435 MAC2STR(addr1), MAC2STR(addr2));
436 wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
437 wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN);
438 wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800439 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
Roshan Pius3a1667e2018-07-03 15:17:14 -0700450 ptk->kek2_len = 0;
451 ptk->kck2_len = 0;
452
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800453 os_memset(tmp, 0, sizeof(tmp));
454 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700455}
456
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800457#ifdef CONFIG_FILS
458
Paul Stewart092955c2017-02-06 09:13:09 -0800459int 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);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700502 else
503 *pmk_len = 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800504 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
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800533int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700534 const u8 *snonce, const u8 *anonce, const u8 *dhss,
535 size_t dhss_len, struct wpa_ptk *ptk,
536 u8 *ick, size_t *ick_len, int akmp, int cipher,
537 u8 *fils_ft, size_t *fils_ft_len)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800538{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700539 u8 *data, *pos;
540 size_t data_len;
541 u8 tmp[FILS_ICK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN +
542 FILS_FT_MAX_LEN];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800543 size_t key_data_len;
544 const char *label = "FILS PTK Derivation";
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700545 int ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800546
547 /*
548 * FILS-Key-Data = PRF-X(PMK, "FILS PTK Derivation",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700549 * SPA || AA || SNonce || ANonce [ || DHss ])
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800550 * 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 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700557 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);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800572
573 ptk->kck_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700574 ptk->kek_len = wpa_kek_len(akmp, pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800575 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
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700581 goto err;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800582 key_data_len = *ick_len + ptk->kek_len + ptk->tk_len;
583
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700584 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
596 if (wpa_key_mgmt_sha384(akmp)) {
597 wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA384)");
598 if (sha384_prf(pmk, pmk_len, label, data, data_len,
599 tmp, key_data_len) < 0)
600 goto err;
601 } else {
602 wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA256)");
603 if (sha256_prf(pmk, pmk_len, label, data, data_len,
604 tmp, key_data_len) < 0)
605 goto err;
606 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800607
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);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700612 if (dhss)
613 wpa_hexdump_key(MSG_DEBUG, "FILS: DHss", dhss, dhss_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800614 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
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700626 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 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800632
Roshan Pius3a1667e2018-07-03 15:17:14 -0700633 ptk->kek2_len = 0;
634 ptk->kck2_len = 0;
635
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800636 os_memset(tmp, 0, sizeof(tmp));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700637 ret = 0;
638err:
639 bin_clear_free(data, data_len);
640 return ret;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800641}
642
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
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700656 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
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800664 /*
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
732#endif /* CONFIG_FILS */
733
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700734
735#ifdef CONFIG_IEEE80211R
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800736int 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,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700739 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{
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700743 const u8 *addr[9];
744 size_t len[9];
745 size_t i, num_elem = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700746 u8 zero_mic[24];
747 size_t mic_len, fte_fixed_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700748
Roshan Pius3a1667e2018-07-03 15:17:14 -0700749 if (kck_len == 16) {
750 mic_len = 16;
751#ifdef CONFIG_SHA384
752 } else if (kck_len == 24) {
753 mic_len = 24;
754#endif /* CONFIG_SHA384 */
755 } else {
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800756 wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u",
757 (unsigned int) kck_len);
758 return -1;
759 }
760
Roshan Pius3a1667e2018-07-03 15:17:14 -0700761 fte_fixed_len = sizeof(struct rsn_ftie) - 16 + mic_len;
762
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700763 addr[num_elem] = sta_addr;
764 len[num_elem] = ETH_ALEN;
765 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700767 addr[num_elem] = ap_addr;
768 len[num_elem] = ETH_ALEN;
769 num_elem++;
770
771 addr[num_elem] = &transaction_seqnum;
772 len[num_elem] = 1;
773 num_elem++;
774
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700775 if (rsnie) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700776 addr[num_elem] = rsnie;
777 len[num_elem] = rsnie_len;
778 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700779 }
780 if (mdie) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700781 addr[num_elem] = mdie;
782 len[num_elem] = mdie_len;
783 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700784 }
785 if (ftie) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700786 if (ftie_len < 2 + fte_fixed_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700787 return -1;
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700788
789 /* IE hdr and mic_control */
790 addr[num_elem] = ftie;
791 len[num_elem] = 2 + 2;
792 num_elem++;
793
794 /* MIC field with all zeros */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700795 os_memset(zero_mic, 0, mic_len);
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700796 addr[num_elem] = zero_mic;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700797 len[num_elem] = mic_len;
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700798 num_elem++;
799
800 /* Rest of FTIE */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700801 addr[num_elem] = ftie + 2 + 2 + mic_len;
802 len[num_elem] = ftie_len - (2 + 2 + mic_len);
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700803 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700804 }
805 if (ric) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700806 addr[num_elem] = ric;
807 len[num_elem] = ric_len;
808 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700809 }
810
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700811 for (i = 0; i < num_elem; i++)
812 wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", addr[i], len[i]);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700813#ifdef CONFIG_SHA384
814 if (kck_len == 24) {
815 u8 hash[SHA384_MAC_LEN];
816
817 if (hmac_sha384_vector(kck, kck_len, num_elem, addr, len, hash))
818 return -1;
819 os_memcpy(mic, hash, 24);
820 }
821#endif /* CONFIG_SHA384 */
822 if (kck_len == 16 &&
823 omac1_aes_128_vector(kck, num_elem, addr, len, mic))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700824 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700825
826 return 0;
827}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800828
829
830static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700831 struct wpa_ft_ies *parse, int use_sha384)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800832{
833 const u8 *end, *pos;
834
835 parse->ftie = ie;
836 parse->ftie_len = ie_len;
837
Roshan Pius3a1667e2018-07-03 15:17:14 -0700838 pos = ie + (use_sha384 ? sizeof(struct rsn_ftie_sha384) :
839 sizeof(struct rsn_ftie));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800840 end = ie + ie_len;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700841 wpa_hexdump(MSG_DEBUG, "FT: Parse FTE subelements", pos, end - pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800842
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800843 while (end - pos >= 2) {
844 u8 id, len;
845
846 id = *pos++;
847 len = *pos++;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700848 if (len > end - pos) {
849 wpa_printf(MSG_DEBUG, "FT: Truncated subelement");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800850 break;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700851 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800852
853 switch (id) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800854 case FTIE_SUBELEM_R1KH_ID:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800855 if (len != FT_R1KH_ID_LEN) {
856 wpa_printf(MSG_DEBUG,
857 "FT: Invalid R1KH-ID length in FTIE: %d",
858 len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800859 return -1;
860 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800861 parse->r1kh_id = pos;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800862 break;
863 case FTIE_SUBELEM_GTK:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800864 parse->gtk = pos;
865 parse->gtk_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800866 break;
867 case FTIE_SUBELEM_R0KH_ID:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800868 if (len < 1 || len > FT_R0KH_ID_MAX_LEN) {
869 wpa_printf(MSG_DEBUG,
870 "FT: Invalid R0KH-ID length in FTIE: %d",
871 len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800872 return -1;
873 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800874 parse->r0kh_id = pos;
875 parse->r0kh_id_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800876 break;
877#ifdef CONFIG_IEEE80211W
878 case FTIE_SUBELEM_IGTK:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800879 parse->igtk = pos;
880 parse->igtk_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800881 break;
882#endif /* CONFIG_IEEE80211W */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700883 default:
884 wpa_printf(MSG_DEBUG, "FT: Unknown subelem id %u", id);
885 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800886 }
887
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800888 pos += len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800889 }
890
891 return 0;
892}
893
894
895int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700896 struct wpa_ft_ies *parse, int use_sha384)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800897{
898 const u8 *end, *pos;
899 struct wpa_ie_data data;
900 int ret;
901 const struct rsn_ftie *ftie;
902 int prot_ie_count = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700903 int update_use_sha384 = 0;
904
905 if (use_sha384 < 0) {
906 use_sha384 = 0;
907 update_use_sha384 = 1;
908 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800909
910 os_memset(parse, 0, sizeof(*parse));
911 if (ies == NULL)
912 return 0;
913
914 pos = ies;
915 end = ies + ies_len;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800916 while (end - pos >= 2) {
917 u8 id, len;
918
919 id = *pos++;
920 len = *pos++;
921 if (len > end - pos)
922 break;
923
924 switch (id) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800925 case WLAN_EID_RSN:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700926 wpa_hexdump(MSG_DEBUG, "FT: RSNE", pos, len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800927 parse->rsn = pos;
928 parse->rsn_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800929 ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
930 parse->rsn_len + 2,
931 &data);
932 if (ret < 0) {
933 wpa_printf(MSG_DEBUG, "FT: Failed to parse "
934 "RSN IE: %d", ret);
935 return -1;
936 }
937 if (data.num_pmkid == 1 && data.pmkid)
938 parse->rsn_pmkid = data.pmkid;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800939 parse->key_mgmt = data.key_mgmt;
940 parse->pairwise_cipher = data.pairwise_cipher;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700941 if (update_use_sha384) {
942 use_sha384 =
943 wpa_key_mgmt_sha384(parse->key_mgmt);
944 update_use_sha384 = 0;
945 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800946 break;
947 case WLAN_EID_MOBILITY_DOMAIN:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700948 wpa_hexdump(MSG_DEBUG, "FT: MDE", pos, len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800949 if (len < sizeof(struct rsn_mdie))
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700950 return -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800951 parse->mdie = pos;
952 parse->mdie_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800953 break;
954 case WLAN_EID_FAST_BSS_TRANSITION:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700955 wpa_hexdump(MSG_DEBUG, "FT: FTE", pos, len);
956 if (use_sha384) {
957 const struct rsn_ftie_sha384 *ftie_sha384;
958
959 if (len < sizeof(*ftie_sha384))
960 return -1;
961 ftie_sha384 =
962 (const struct rsn_ftie_sha384 *) pos;
963 wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control",
964 ftie_sha384->mic_control, 2);
965 wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC",
966 ftie_sha384->mic,
967 sizeof(ftie_sha384->mic));
968 wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce",
969 ftie_sha384->anonce,
970 WPA_NONCE_LEN);
971 wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce",
972 ftie_sha384->snonce,
973 WPA_NONCE_LEN);
974 prot_ie_count = ftie_sha384->mic_control[1];
975 if (wpa_ft_parse_ftie(pos, len, parse, 1) < 0)
976 return -1;
977 break;
978 }
979
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800980 if (len < sizeof(*ftie))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800981 return -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800982 ftie = (const struct rsn_ftie *) pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700983 wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control",
984 ftie->mic_control, 2);
985 wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC",
986 ftie->mic, sizeof(ftie->mic));
987 wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce",
988 ftie->anonce, WPA_NONCE_LEN);
989 wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce",
990 ftie->snonce, WPA_NONCE_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800991 prot_ie_count = ftie->mic_control[1];
Roshan Pius3a1667e2018-07-03 15:17:14 -0700992 if (wpa_ft_parse_ftie(pos, len, parse, 0) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800993 return -1;
994 break;
995 case WLAN_EID_TIMEOUT_INTERVAL:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700996 wpa_hexdump(MSG_DEBUG, "FT: Timeout Interval",
997 pos, len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800998 if (len != 5)
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700999 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001000 parse->tie = pos;
1001 parse->tie_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001002 break;
1003 case WLAN_EID_RIC_DATA:
1004 if (parse->ric == NULL)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001005 parse->ric = pos - 2;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001006 break;
1007 }
1008
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001009 pos += len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001010 }
1011
1012 if (prot_ie_count == 0)
1013 return 0; /* no MIC */
1014
1015 /*
1016 * Check that the protected IE count matches with IEs included in the
1017 * frame.
1018 */
1019 if (parse->rsn)
1020 prot_ie_count--;
1021 if (parse->mdie)
1022 prot_ie_count--;
1023 if (parse->ftie)
1024 prot_ie_count--;
1025 if (prot_ie_count < 0) {
1026 wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
1027 "the protected IE count");
1028 return -1;
1029 }
1030
1031 if (prot_ie_count == 0 && parse->ric) {
1032 wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
1033 "included in protected IE count");
1034 return -1;
1035 }
1036
1037 /* Determine the end of the RIC IE(s) */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001038 if (parse->ric) {
1039 pos = parse->ric;
1040 while (end - pos >= 2 && 2 + pos[1] <= end - pos &&
1041 prot_ie_count) {
1042 prot_ie_count--;
1043 pos += 2 + pos[1];
1044 }
1045 parse->ric_len = pos - parse->ric;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001046 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001047 if (prot_ie_count) {
1048 wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
1049 "frame", (int) prot_ie_count);
1050 return -1;
1051 }
1052
1053 return 0;
1054}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001055#endif /* CONFIG_IEEE80211R */
1056
1057
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001058static int rsn_selector_to_bitfield(const u8 *s)
1059{
1060 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
1061 return WPA_CIPHER_NONE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001062 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
1063 return WPA_CIPHER_TKIP;
1064 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
1065 return WPA_CIPHER_CCMP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001066#ifdef CONFIG_IEEE80211W
1067 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
1068 return WPA_CIPHER_AES_128_CMAC;
1069#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001070 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
1071 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001072 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256)
1073 return WPA_CIPHER_CCMP_256;
1074 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256)
1075 return WPA_CIPHER_GCMP_256;
1076 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128)
1077 return WPA_CIPHER_BIP_GMAC_128;
1078 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256)
1079 return WPA_CIPHER_BIP_GMAC_256;
1080 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256)
1081 return WPA_CIPHER_BIP_CMAC_256;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001082 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED)
1083 return WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001084 return 0;
1085}
1086
1087
1088static int rsn_key_mgmt_to_bitfield(const u8 *s)
1089{
1090 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
1091 return WPA_KEY_MGMT_IEEE8021X;
1092 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
1093 return WPA_KEY_MGMT_PSK;
1094#ifdef CONFIG_IEEE80211R
1095 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
1096 return WPA_KEY_MGMT_FT_IEEE8021X;
1097 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
1098 return WPA_KEY_MGMT_FT_PSK;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001099#ifdef CONFIG_SHA384
1100 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384)
1101 return WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1102#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001103#endif /* CONFIG_IEEE80211R */
1104#ifdef CONFIG_IEEE80211W
1105 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
1106 return WPA_KEY_MGMT_IEEE8021X_SHA256;
1107 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
1108 return WPA_KEY_MGMT_PSK_SHA256;
1109#endif /* CONFIG_IEEE80211W */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001110#ifdef CONFIG_SAE
1111 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
1112 return WPA_KEY_MGMT_SAE;
1113 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
1114 return WPA_KEY_MGMT_FT_SAE;
1115#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001116 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B)
1117 return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001118 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
1119 return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001120 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA256)
1121 return WPA_KEY_MGMT_FILS_SHA256;
1122 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA384)
1123 return WPA_KEY_MGMT_FILS_SHA384;
1124 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA256)
1125 return WPA_KEY_MGMT_FT_FILS_SHA256;
1126 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA384)
1127 return WPA_KEY_MGMT_FT_FILS_SHA384;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001128#ifdef CONFIG_OWE
1129 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE)
1130 return WPA_KEY_MGMT_OWE;
1131#endif /* CONFIG_OWE */
1132#ifdef CONFIG_DPP
1133 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_DPP)
1134 return WPA_KEY_MGMT_DPP;
1135#endif /* CONFIG_DPP */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001136 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN)
1137 return WPA_KEY_MGMT_OSEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001138 return 0;
1139}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001140
1141
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001142int wpa_cipher_valid_group(int cipher)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001143{
1144 return wpa_cipher_valid_pairwise(cipher) ||
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001145 cipher == WPA_CIPHER_GTK_NOT_USED;
1146}
1147
1148
1149#ifdef CONFIG_IEEE80211W
1150int wpa_cipher_valid_mgmt_group(int cipher)
1151{
1152 return cipher == WPA_CIPHER_AES_128_CMAC ||
1153 cipher == WPA_CIPHER_BIP_GMAC_128 ||
1154 cipher == WPA_CIPHER_BIP_GMAC_256 ||
1155 cipher == WPA_CIPHER_BIP_CMAC_256;
1156}
1157#endif /* CONFIG_IEEE80211W */
1158
1159
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001160/**
1161 * wpa_parse_wpa_ie_rsn - Parse RSN IE
1162 * @rsn_ie: Buffer containing RSN IE
1163 * @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
1164 * @data: Pointer to structure that will be filled in with parsed data
1165 * Returns: 0 on success, <0 on failure
1166 */
1167int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
1168 struct wpa_ie_data *data)
1169{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001170 const u8 *pos;
1171 int left;
1172 int i, count;
1173
1174 os_memset(data, 0, sizeof(*data));
1175 data->proto = WPA_PROTO_RSN;
1176 data->pairwise_cipher = WPA_CIPHER_CCMP;
1177 data->group_cipher = WPA_CIPHER_CCMP;
1178 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1179 data->capabilities = 0;
1180 data->pmkid = NULL;
1181 data->num_pmkid = 0;
1182#ifdef CONFIG_IEEE80211W
1183 data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1184#else /* CONFIG_IEEE80211W */
1185 data->mgmt_group_cipher = 0;
1186#endif /* CONFIG_IEEE80211W */
1187
1188 if (rsn_ie_len == 0) {
1189 /* No RSN IE - fail silently */
1190 return -1;
1191 }
1192
1193 if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
1194 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
1195 __func__, (unsigned long) rsn_ie_len);
1196 return -1;
1197 }
1198
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001199 if (rsn_ie_len >= 6 && rsn_ie[1] >= 4 &&
1200 rsn_ie[1] == rsn_ie_len - 2 &&
1201 WPA_GET_BE32(&rsn_ie[2]) == OSEN_IE_VENDOR_TYPE) {
1202 pos = rsn_ie + 6;
1203 left = rsn_ie_len - 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001204
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001205 data->proto = WPA_PROTO_OSEN;
1206 } else {
1207 const struct rsn_ie_hdr *hdr;
1208
1209 hdr = (const struct rsn_ie_hdr *) rsn_ie;
1210
1211 if (hdr->elem_id != WLAN_EID_RSN ||
1212 hdr->len != rsn_ie_len - 2 ||
1213 WPA_GET_LE16(hdr->version) != RSN_VERSION) {
1214 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
1215 __func__);
1216 return -2;
1217 }
1218
1219 pos = (const u8 *) (hdr + 1);
1220 left = rsn_ie_len - sizeof(*hdr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001221 }
1222
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001223 if (left >= RSN_SELECTOR_LEN) {
1224 data->group_cipher = rsn_selector_to_bitfield(pos);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001225 if (!wpa_cipher_valid_group(data->group_cipher)) {
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08001226 wpa_printf(MSG_DEBUG,
1227 "%s: invalid group cipher 0x%x (%08x)",
1228 __func__, data->group_cipher,
1229 WPA_GET_BE32(pos));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001230 return -1;
1231 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001232 pos += RSN_SELECTOR_LEN;
1233 left -= RSN_SELECTOR_LEN;
1234 } else if (left > 0) {
1235 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
1236 __func__, left);
1237 return -3;
1238 }
1239
1240 if (left >= 2) {
1241 data->pairwise_cipher = 0;
1242 count = WPA_GET_LE16(pos);
1243 pos += 2;
1244 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001245 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001246 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
1247 "count %u left %u", __func__, count, left);
1248 return -4;
1249 }
1250 for (i = 0; i < count; i++) {
1251 data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
1252 pos += RSN_SELECTOR_LEN;
1253 left -= RSN_SELECTOR_LEN;
1254 }
1255#ifdef CONFIG_IEEE80211W
1256 if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
1257 wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
1258 "pairwise cipher", __func__);
1259 return -1;
1260 }
1261#endif /* CONFIG_IEEE80211W */
1262 } else if (left == 1) {
1263 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
1264 __func__);
1265 return -5;
1266 }
1267
1268 if (left >= 2) {
1269 data->key_mgmt = 0;
1270 count = WPA_GET_LE16(pos);
1271 pos += 2;
1272 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001273 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
1275 "count %u left %u", __func__, count, left);
1276 return -6;
1277 }
1278 for (i = 0; i < count; i++) {
1279 data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
1280 pos += RSN_SELECTOR_LEN;
1281 left -= RSN_SELECTOR_LEN;
1282 }
1283 } else if (left == 1) {
1284 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
1285 __func__);
1286 return -7;
1287 }
1288
1289 if (left >= 2) {
1290 data->capabilities = WPA_GET_LE16(pos);
1291 pos += 2;
1292 left -= 2;
1293 }
1294
1295 if (left >= 2) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001296 u16 num_pmkid = WPA_GET_LE16(pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001297 pos += 2;
1298 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001299 if (num_pmkid > (unsigned int) left / PMKID_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001300 wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001301 "(num_pmkid=%u left=%d)",
1302 __func__, num_pmkid, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001303 data->num_pmkid = 0;
1304 return -9;
1305 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001306 data->num_pmkid = num_pmkid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001307 data->pmkid = pos;
1308 pos += data->num_pmkid * PMKID_LEN;
1309 left -= data->num_pmkid * PMKID_LEN;
1310 }
1311 }
1312
1313#ifdef CONFIG_IEEE80211W
1314 if (left >= 4) {
1315 data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001316 if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001317 wpa_printf(MSG_DEBUG,
1318 "%s: Unsupported management group cipher 0x%x (%08x)",
1319 __func__, data->mgmt_group_cipher,
1320 WPA_GET_BE32(pos));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001321 return -10;
1322 }
1323 pos += RSN_SELECTOR_LEN;
1324 left -= RSN_SELECTOR_LEN;
1325 }
1326#endif /* CONFIG_IEEE80211W */
1327
1328 if (left > 0) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001329 wpa_hexdump(MSG_DEBUG,
1330 "wpa_parse_wpa_ie_rsn: ignore trailing bytes",
1331 pos, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001332 }
1333
1334 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001335}
1336
1337
1338static int wpa_selector_to_bitfield(const u8 *s)
1339{
1340 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
1341 return WPA_CIPHER_NONE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001342 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
1343 return WPA_CIPHER_TKIP;
1344 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
1345 return WPA_CIPHER_CCMP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001346 return 0;
1347}
1348
1349
1350static int wpa_key_mgmt_to_bitfield(const u8 *s)
1351{
1352 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
1353 return WPA_KEY_MGMT_IEEE8021X;
1354 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
1355 return WPA_KEY_MGMT_PSK;
1356 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
1357 return WPA_KEY_MGMT_WPA_NONE;
1358 return 0;
1359}
1360
1361
1362int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
1363 struct wpa_ie_data *data)
1364{
1365 const struct wpa_ie_hdr *hdr;
1366 const u8 *pos;
1367 int left;
1368 int i, count;
1369
1370 os_memset(data, 0, sizeof(*data));
1371 data->proto = WPA_PROTO_WPA;
1372 data->pairwise_cipher = WPA_CIPHER_TKIP;
1373 data->group_cipher = WPA_CIPHER_TKIP;
1374 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1375 data->capabilities = 0;
1376 data->pmkid = NULL;
1377 data->num_pmkid = 0;
1378 data->mgmt_group_cipher = 0;
1379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001380 if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
1381 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
1382 __func__, (unsigned long) wpa_ie_len);
1383 return -1;
1384 }
1385
1386 hdr = (const struct wpa_ie_hdr *) wpa_ie;
1387
1388 if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
1389 hdr->len != wpa_ie_len - 2 ||
1390 RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
1391 WPA_GET_LE16(hdr->version) != WPA_VERSION) {
1392 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
1393 __func__);
1394 return -2;
1395 }
1396
1397 pos = (const u8 *) (hdr + 1);
1398 left = wpa_ie_len - sizeof(*hdr);
1399
1400 if (left >= WPA_SELECTOR_LEN) {
1401 data->group_cipher = wpa_selector_to_bitfield(pos);
1402 pos += WPA_SELECTOR_LEN;
1403 left -= WPA_SELECTOR_LEN;
1404 } else if (left > 0) {
1405 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
1406 __func__, left);
1407 return -3;
1408 }
1409
1410 if (left >= 2) {
1411 data->pairwise_cipher = 0;
1412 count = WPA_GET_LE16(pos);
1413 pos += 2;
1414 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001415 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001416 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
1417 "count %u left %u", __func__, count, left);
1418 return -4;
1419 }
1420 for (i = 0; i < count; i++) {
1421 data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
1422 pos += WPA_SELECTOR_LEN;
1423 left -= WPA_SELECTOR_LEN;
1424 }
1425 } else if (left == 1) {
1426 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
1427 __func__);
1428 return -5;
1429 }
1430
1431 if (left >= 2) {
1432 data->key_mgmt = 0;
1433 count = WPA_GET_LE16(pos);
1434 pos += 2;
1435 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001436 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001437 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
1438 "count %u left %u", __func__, count, left);
1439 return -6;
1440 }
1441 for (i = 0; i < count; i++) {
1442 data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
1443 pos += WPA_SELECTOR_LEN;
1444 left -= WPA_SELECTOR_LEN;
1445 }
1446 } else if (left == 1) {
1447 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
1448 __func__);
1449 return -7;
1450 }
1451
1452 if (left >= 2) {
1453 data->capabilities = WPA_GET_LE16(pos);
1454 pos += 2;
1455 left -= 2;
1456 }
1457
1458 if (left > 0) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001459 wpa_hexdump(MSG_DEBUG,
1460 "wpa_parse_wpa_ie_wpa: ignore trailing bytes",
1461 pos, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001462 }
1463
1464 return 0;
1465}
1466
1467
1468#ifdef CONFIG_IEEE80211R
1469
1470/**
1471 * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
1472 *
1473 * IEEE Std 802.11r-2008 - 8.5.1.5.3
1474 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001475int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
1476 const u8 *ssid, size_t ssid_len,
1477 const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001478 const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name,
1479 int use_sha384)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001480{
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001481 u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001482 FT_R0KH_ID_MAX_LEN + ETH_ALEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07001483 u8 *pos, r0_key_data[64], hash[48];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001484 const u8 *addr[2];
1485 size_t len[2];
Roshan Pius3a1667e2018-07-03 15:17:14 -07001486 size_t q = use_sha384 ? 48 : 32;
1487 size_t r0_key_data_len = q + 16;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001488
1489 /*
1490 * R0-Key-Data = KDF-384(XXKey, "FT-R0",
1491 * SSIDlength || SSID || MDID || R0KHlength ||
1492 * R0KH-ID || S0KH-ID)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001493 * XXKey is either the second 256 bits of MSK or PSK; or the first
1494 * 384 bits of MSK for FT-EAP-SHA384.
1495 * PMK-R0 = L(R0-Key-Data, 0, Q)
1496 * PMK-R0Name-Salt = L(R0-Key-Data, Q, 128)
1497 * Q = 384 for FT-EAP-SHA384; otherwise, 256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001498 */
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001499 if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001500 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001501 wpa_printf(MSG_DEBUG, "FT: Derive PMK-R0 using KDF-%s",
1502 use_sha384 ? "SHA384" : "SHA256");
1503 wpa_hexdump_key(MSG_DEBUG, "FT: XXKey", xxkey, xxkey_len);
1504 wpa_hexdump_ascii(MSG_DEBUG, "FT: SSID", ssid, ssid_len);
1505 wpa_hexdump(MSG_DEBUG, "FT: MDID", mdid, MOBILITY_DOMAIN_ID_LEN);
1506 wpa_hexdump_ascii(MSG_DEBUG, "FT: R0KH-ID", r0kh_id, r0kh_id_len);
1507 wpa_printf(MSG_DEBUG, "FT: S0KH-ID: " MACSTR, MAC2STR(s0kh_id));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001508 pos = buf;
1509 *pos++ = ssid_len;
1510 os_memcpy(pos, ssid, ssid_len);
1511 pos += ssid_len;
1512 os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
1513 pos += MOBILITY_DOMAIN_ID_LEN;
1514 *pos++ = r0kh_id_len;
1515 os_memcpy(pos, r0kh_id, r0kh_id_len);
1516 pos += r0kh_id_len;
1517 os_memcpy(pos, s0kh_id, ETH_ALEN);
1518 pos += ETH_ALEN;
1519
Roshan Pius3a1667e2018-07-03 15:17:14 -07001520#ifdef CONFIG_SHA384
1521 if (use_sha384) {
1522 if (xxkey_len != SHA384_MAC_LEN) {
1523 wpa_printf(MSG_ERROR,
1524 "FT: Unexpected XXKey length %d (expected %d)",
1525 (int) xxkey_len, SHA384_MAC_LEN);
1526 return -1;
1527 }
1528 if (sha384_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
1529 r0_key_data, r0_key_data_len) < 0)
1530 return -1;
1531 }
1532#endif /* CONFIG_SHA384 */
1533 if (!use_sha384) {
1534 if (xxkey_len != PMK_LEN) {
1535 wpa_printf(MSG_ERROR,
1536 "FT: Unexpected XXKey length %d (expected %d)",
1537 (int) xxkey_len, PMK_LEN);
1538 return -1;
1539 }
1540 if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
1541 r0_key_data, r0_key_data_len) < 0)
1542 return -1;
1543 }
1544 os_memcpy(pmk_r0, r0_key_data, q);
1545 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, q);
1546 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0Name-Salt", &r0_key_data[q], 16);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001547
1548 /*
Roshan Pius3a1667e2018-07-03 15:17:14 -07001549 * PMKR0Name = Truncate-128(Hash("FT-R0N" || PMK-R0Name-Salt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001550 */
1551 addr[0] = (const u8 *) "FT-R0N";
1552 len[0] = 6;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001553 addr[1] = &r0_key_data[q];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001554 len[1] = 16;
1555
Roshan Pius3a1667e2018-07-03 15:17:14 -07001556#ifdef CONFIG_SHA384
1557 if (use_sha384 && sha384_vector(2, addr, len, hash) < 0)
1558 return -1;
1559#endif /* CONFIG_SHA384 */
1560 if (!use_sha384 && sha256_vector(2, addr, len, hash) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001561 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001562 os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001563 os_memset(r0_key_data, 0, sizeof(r0_key_data));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001564 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001565}
1566
1567
1568/**
1569 * wpa_derive_pmk_r1_name - Derive PMKR1Name
1570 *
1571 * IEEE Std 802.11r-2008 - 8.5.1.5.4
1572 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001573int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001574 const u8 *s1kh_id, u8 *pmk_r1_name, int use_sha384)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001575{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001576 u8 hash[48];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001577 const u8 *addr[4];
1578 size_t len[4];
1579
1580 /*
Roshan Pius3a1667e2018-07-03 15:17:14 -07001581 * PMKR1Name = Truncate-128(Hash("FT-R1N" || PMKR0Name ||
1582 * R1KH-ID || S1KH-ID))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001583 */
1584 addr[0] = (const u8 *) "FT-R1N";
1585 len[0] = 6;
1586 addr[1] = pmk_r0_name;
1587 len[1] = WPA_PMK_NAME_LEN;
1588 addr[2] = r1kh_id;
1589 len[2] = FT_R1KH_ID_LEN;
1590 addr[3] = s1kh_id;
1591 len[3] = ETH_ALEN;
1592
Roshan Pius3a1667e2018-07-03 15:17:14 -07001593#ifdef CONFIG_SHA384
1594 if (use_sha384 && sha384_vector(4, addr, len, hash) < 0)
1595 return -1;
1596#endif /* CONFIG_SHA384 */
1597 if (!use_sha384 && sha256_vector(4, addr, len, hash) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001598 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001599 os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001600 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001601}
1602
1603
1604/**
1605 * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
1606 *
1607 * IEEE Std 802.11r-2008 - 8.5.1.5.4
1608 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001609int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len,
1610 const u8 *pmk_r0_name,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001611 const u8 *r1kh_id, const u8 *s1kh_id,
1612 u8 *pmk_r1, u8 *pmk_r1_name)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001613{
1614 u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
1615 u8 *pos;
1616
1617 /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001618 wpa_printf(MSG_DEBUG, "FT: Derive PMK-R1 using KDF-%s",
1619 pmk_r0_len == SHA384_MAC_LEN ? "SHA384" : "SHA256");
1620 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len);
1621 wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", r1kh_id, FT_R1KH_ID_LEN);
1622 wpa_printf(MSG_DEBUG, "FT: S1KH-ID: " MACSTR, MAC2STR(s1kh_id));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001623 pos = buf;
1624 os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
1625 pos += FT_R1KH_ID_LEN;
1626 os_memcpy(pos, s1kh_id, ETH_ALEN);
1627 pos += ETH_ALEN;
1628
Roshan Pius3a1667e2018-07-03 15:17:14 -07001629#ifdef CONFIG_SHA384
1630 if (pmk_r0_len == SHA384_MAC_LEN &&
1631 sha384_prf(pmk_r0, pmk_r0_len, "FT-R1",
1632 buf, pos - buf, pmk_r1, pmk_r0_len) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001633 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001634#endif /* CONFIG_SHA384 */
1635 if (pmk_r0_len == PMK_LEN &&
1636 sha256_prf(pmk_r0, pmk_r0_len, "FT-R1",
1637 buf, pos - buf, pmk_r1, pmk_r0_len) < 0)
1638 return -1;
1639 if (pmk_r0_len != SHA384_MAC_LEN && pmk_r0_len != PMK_LEN) {
1640 wpa_printf(MSG_ERROR, "FT: Unexpected PMK-R0 length %d",
1641 (int) pmk_r0_len);
1642 return -1;
1643 }
1644 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r0_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001645
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001646 return wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001647 pmk_r1_name,
1648 pmk_r0_len == SHA384_MAC_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001649}
1650
1651
1652/**
1653 * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
1654 *
1655 * IEEE Std 802.11r-2008 - 8.5.1.5.5
1656 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001657int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len,
1658 const u8 *snonce, const u8 *anonce,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001659 const u8 *sta_addr, const u8 *bssid,
1660 const u8 *pmk_r1_name,
1661 struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001662{
1663 u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
1664 u8 *pos, hash[32];
1665 const u8 *addr[6];
1666 size_t len[6];
Roshan Pius3a1667e2018-07-03 15:17:14 -07001667 u8 tmp[2 * WPA_KCK_MAX_LEN + 2 * WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
1668 size_t ptk_len, offset;
1669 int use_sha384 = wpa_key_mgmt_sha384(akmp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001670
1671 /*
1672 * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
1673 * BSSID || STA-ADDR)
1674 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001675 wpa_printf(MSG_DEBUG, "FT: Derive PTK using KDF-%s",
1676 use_sha384 ? "SHA384" : "SHA256");
1677 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len);
1678 wpa_hexdump(MSG_DEBUG, "FT: SNonce", snonce, WPA_NONCE_LEN);
1679 wpa_hexdump(MSG_DEBUG, "FT: ANonce", anonce, WPA_NONCE_LEN);
1680 wpa_printf(MSG_DEBUG, "FT: BSSID=" MACSTR " STA-ADDR=" MACSTR,
1681 MAC2STR(bssid), MAC2STR(sta_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001682 pos = buf;
1683 os_memcpy(pos, snonce, WPA_NONCE_LEN);
1684 pos += WPA_NONCE_LEN;
1685 os_memcpy(pos, anonce, WPA_NONCE_LEN);
1686 pos += WPA_NONCE_LEN;
1687 os_memcpy(pos, bssid, ETH_ALEN);
1688 pos += ETH_ALEN;
1689 os_memcpy(pos, sta_addr, ETH_ALEN);
1690 pos += ETH_ALEN;
1691
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001692 ptk->kck_len = wpa_kck_len(akmp, PMK_LEN);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001693 ptk->kck2_len = wpa_kck2_len(akmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001694 ptk->kek_len = wpa_kek_len(akmp, PMK_LEN);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001695 ptk->kek2_len = wpa_kek2_len(akmp);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001696 ptk->tk_len = wpa_cipher_key_len(cipher);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001697 ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len +
1698 ptk->kck2_len + ptk->kek2_len;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001699
Roshan Pius3a1667e2018-07-03 15:17:14 -07001700#ifdef CONFIG_SHA384
1701 if (use_sha384) {
1702 if (pmk_r1_len != SHA384_MAC_LEN) {
1703 wpa_printf(MSG_ERROR,
1704 "FT: Unexpected PMK-R1 length %d (expected %d)",
1705 (int) pmk_r1_len, SHA384_MAC_LEN);
1706 return -1;
1707 }
1708 if (sha384_prf(pmk_r1, pmk_r1_len, "FT-PTK",
1709 buf, pos - buf, tmp, ptk_len) < 0)
1710 return -1;
1711 }
1712#endif /* CONFIG_SHA384 */
1713 if (!use_sha384) {
1714 if (pmk_r1_len != PMK_LEN) {
1715 wpa_printf(MSG_ERROR,
1716 "FT: Unexpected PMK-R1 length %d (expected %d)",
1717 (int) pmk_r1_len, PMK_LEN);
1718 return -1;
1719 }
1720 if (sha256_prf(pmk_r1, pmk_r1_len, "FT-PTK",
1721 buf, pos - buf, tmp, ptk_len) < 0)
1722 return -1;
1723 }
1724 wpa_hexdump_key(MSG_DEBUG, "FT: PTK", tmp, ptk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725
1726 /*
1727 * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
1728 * ANonce || BSSID || STA-ADDR))
1729 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001730 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001731 addr[0] = pmk_r1_name;
1732 len[0] = WPA_PMK_NAME_LEN;
1733 addr[1] = (const u8 *) "FT-PTKN";
1734 len[1] = 7;
1735 addr[2] = snonce;
1736 len[2] = WPA_NONCE_LEN;
1737 addr[3] = anonce;
1738 len[3] = WPA_NONCE_LEN;
1739 addr[4] = bssid;
1740 len[4] = ETH_ALEN;
1741 addr[5] = sta_addr;
1742 len[5] = ETH_ALEN;
1743
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001744 if (sha256_vector(6, addr, len, hash) < 0)
1745 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746 os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001747
1748 os_memcpy(ptk->kck, tmp, ptk->kck_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001749 offset = ptk->kck_len;
1750 os_memcpy(ptk->kek, tmp + offset, ptk->kek_len);
1751 offset += ptk->kek_len;
1752 os_memcpy(ptk->tk, tmp + offset, ptk->tk_len);
1753 offset += ptk->tk_len;
1754 os_memcpy(ptk->kck2, tmp + offset, ptk->kck2_len);
1755 offset = ptk->kck2_len;
1756 os_memcpy(ptk->kek2, tmp + offset, ptk->kek2_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001757
1758 wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len);
1759 wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001760 if (ptk->kck2_len)
1761 wpa_hexdump_key(MSG_DEBUG, "FT: KCK2",
1762 ptk->kck2, ptk->kck2_len);
1763 if (ptk->kek2_len)
1764 wpa_hexdump_key(MSG_DEBUG, "FT: KEK2",
1765 ptk->kek2, ptk->kek2_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001766 wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len);
1767 wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
1768
1769 os_memset(tmp, 0, sizeof(tmp));
1770
1771 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001772}
1773
1774#endif /* CONFIG_IEEE80211R */
1775
1776
1777/**
1778 * rsn_pmkid - Calculate PMK identifier
1779 * @pmk: Pairwise master key
1780 * @pmk_len: Length of pmk in bytes
1781 * @aa: Authenticator address
1782 * @spa: Supplicant address
1783 * @pmkid: Buffer for PMKID
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001784 * @akmp: Negotiated key management protocol
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001785 *
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001786 * IEEE Std 802.11-2016 - 12.7.1.3 Pairwise key hierarchy
1787 * AKM: 00-0F-AC:5, 00-0F-AC:6, 00-0F-AC:14, 00-0F-AC:16
1788 * PMKID = Truncate-128(HMAC-SHA-256(PMK, "PMK Name" || AA || SPA))
1789 * AKM: 00-0F-AC:11
1790 * See rsn_pmkid_suite_b()
1791 * AKM: 00-0F-AC:12
1792 * See rsn_pmkid_suite_b_192()
Roshan Pius3a1667e2018-07-03 15:17:14 -07001793 * AKM: 00-0F-AC:13, 00-0F-AC:15, 00-0F-AC:17
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001794 * PMKID = Truncate-128(HMAC-SHA-384(PMK, "PMK Name" || AA || SPA))
1795 * Otherwise:
1796 * PMKID = Truncate-128(HMAC-SHA-1(PMK, "PMK Name" || AA || SPA))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797 */
1798void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001799 u8 *pmkid, int akmp)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001800{
1801 char *title = "PMK Name";
1802 const u8 *addr[3];
1803 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001804 unsigned char hash[SHA384_MAC_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805
1806 addr[0] = (u8 *) title;
1807 addr[1] = aa;
1808 addr[2] = spa;
1809
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001810 if (0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001811#if defined(CONFIG_FILS) || defined(CONFIG_SHA384)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001812 } else if (wpa_key_mgmt_sha384(akmp)) {
1813 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-384");
1814 hmac_sha384_vector(pmk, pmk_len, 3, addr, len, hash);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001815#endif /* CONFIG_FILS || CONFIG_SHA384 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001816#if defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS)
1817 } else if (wpa_key_mgmt_sha256(akmp)) {
1818 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001819 hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001820#endif /* CONFIG_IEEE80211W || CONFIG_FILS */
1821 } else {
1822 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-1");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823 hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001824 }
1825 wpa_hexdump(MSG_DEBUG, "RSN: Derived PMKID", hash, PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001826 os_memcpy(pmkid, hash, PMKID_LEN);
1827}
1828
1829
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001830#ifdef CONFIG_SUITEB
1831/**
1832 * rsn_pmkid_suite_b - Calculate PMK identifier for Suite B AKM
1833 * @kck: Key confirmation key
1834 * @kck_len: Length of kck in bytes
1835 * @aa: Authenticator address
1836 * @spa: Supplicant address
1837 * @pmkid: Buffer for PMKID
1838 * Returns: 0 on success, -1 on failure
1839 *
1840 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1841 * PMKID = Truncate(HMAC-SHA-256(KCK, "PMK Name" || AA || SPA))
1842 */
1843int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
1844 const u8 *spa, u8 *pmkid)
1845{
1846 char *title = "PMK Name";
1847 const u8 *addr[3];
1848 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1849 unsigned char hash[SHA256_MAC_LEN];
1850
1851 addr[0] = (u8 *) title;
1852 addr[1] = aa;
1853 addr[2] = spa;
1854
1855 if (hmac_sha256_vector(kck, kck_len, 3, addr, len, hash) < 0)
1856 return -1;
1857 os_memcpy(pmkid, hash, PMKID_LEN);
1858 return 0;
1859}
1860#endif /* CONFIG_SUITEB */
1861
1862
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001863#ifdef CONFIG_SUITEB192
1864/**
1865 * rsn_pmkid_suite_b_192 - Calculate PMK identifier for Suite B AKM
1866 * @kck: Key confirmation key
1867 * @kck_len: Length of kck in bytes
1868 * @aa: Authenticator address
1869 * @spa: Supplicant address
1870 * @pmkid: Buffer for PMKID
1871 * Returns: 0 on success, -1 on failure
1872 *
1873 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1874 * PMKID = Truncate(HMAC-SHA-384(KCK, "PMK Name" || AA || SPA))
1875 */
1876int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa,
1877 const u8 *spa, u8 *pmkid)
1878{
1879 char *title = "PMK Name";
1880 const u8 *addr[3];
1881 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1882 unsigned char hash[SHA384_MAC_LEN];
1883
1884 addr[0] = (u8 *) title;
1885 addr[1] = aa;
1886 addr[2] = spa;
1887
1888 if (hmac_sha384_vector(kck, kck_len, 3, addr, len, hash) < 0)
1889 return -1;
1890 os_memcpy(pmkid, hash, PMKID_LEN);
1891 return 0;
1892}
1893#endif /* CONFIG_SUITEB192 */
1894
1895
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001896/**
1897 * wpa_cipher_txt - Convert cipher suite to a text string
1898 * @cipher: Cipher suite (WPA_CIPHER_* enum)
1899 * Returns: Pointer to a text string of the cipher suite name
1900 */
1901const char * wpa_cipher_txt(int cipher)
1902{
1903 switch (cipher) {
1904 case WPA_CIPHER_NONE:
1905 return "NONE";
1906 case WPA_CIPHER_WEP40:
1907 return "WEP-40";
1908 case WPA_CIPHER_WEP104:
1909 return "WEP-104";
1910 case WPA_CIPHER_TKIP:
1911 return "TKIP";
1912 case WPA_CIPHER_CCMP:
1913 return "CCMP";
1914 case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
1915 return "CCMP+TKIP";
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001916 case WPA_CIPHER_GCMP:
1917 return "GCMP";
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001918 case WPA_CIPHER_GCMP_256:
1919 return "GCMP-256";
1920 case WPA_CIPHER_CCMP_256:
1921 return "CCMP-256";
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001922 case WPA_CIPHER_AES_128_CMAC:
1923 return "BIP";
1924 case WPA_CIPHER_BIP_GMAC_128:
1925 return "BIP-GMAC-128";
1926 case WPA_CIPHER_BIP_GMAC_256:
1927 return "BIP-GMAC-256";
1928 case WPA_CIPHER_BIP_CMAC_256:
1929 return "BIP-CMAC-256";
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001930 case WPA_CIPHER_GTK_NOT_USED:
1931 return "GTK_NOT_USED";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001932 default:
1933 return "UNKNOWN";
1934 }
1935}
1936
1937
1938/**
1939 * wpa_key_mgmt_txt - Convert key management suite to a text string
1940 * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
1941 * @proto: WPA/WPA2 version (WPA_PROTO_*)
1942 * Returns: Pointer to a text string of the key management suite name
1943 */
1944const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
1945{
1946 switch (key_mgmt) {
1947 case WPA_KEY_MGMT_IEEE8021X:
1948 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1949 return "WPA2+WPA/IEEE 802.1X/EAP";
1950 return proto == WPA_PROTO_RSN ?
1951 "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
1952 case WPA_KEY_MGMT_PSK:
1953 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1954 return "WPA2-PSK+WPA-PSK";
1955 return proto == WPA_PROTO_RSN ?
1956 "WPA2-PSK" : "WPA-PSK";
1957 case WPA_KEY_MGMT_NONE:
1958 return "NONE";
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001959 case WPA_KEY_MGMT_WPA_NONE:
1960 return "WPA-NONE";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001961 case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
1962 return "IEEE 802.1X (no WPA)";
1963#ifdef CONFIG_IEEE80211R
1964 case WPA_KEY_MGMT_FT_IEEE8021X:
1965 return "FT-EAP";
Roshan Pius3a1667e2018-07-03 15:17:14 -07001966 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
1967 return "FT-EAP-SHA384";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968 case WPA_KEY_MGMT_FT_PSK:
1969 return "FT-PSK";
1970#endif /* CONFIG_IEEE80211R */
1971#ifdef CONFIG_IEEE80211W
1972 case WPA_KEY_MGMT_IEEE8021X_SHA256:
1973 return "WPA2-EAP-SHA256";
1974 case WPA_KEY_MGMT_PSK_SHA256:
1975 return "WPA2-PSK-SHA256";
1976#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001977 case WPA_KEY_MGMT_WPS:
1978 return "WPS";
1979 case WPA_KEY_MGMT_SAE:
1980 return "SAE";
1981 case WPA_KEY_MGMT_FT_SAE:
1982 return "FT-SAE";
1983 case WPA_KEY_MGMT_OSEN:
1984 return "OSEN";
1985 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
1986 return "WPA2-EAP-SUITE-B";
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001987 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
1988 return "WPA2-EAP-SUITE-B-192";
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001989 case WPA_KEY_MGMT_FILS_SHA256:
1990 return "FILS-SHA256";
1991 case WPA_KEY_MGMT_FILS_SHA384:
1992 return "FILS-SHA384";
1993 case WPA_KEY_MGMT_FT_FILS_SHA256:
1994 return "FT-FILS-SHA256";
1995 case WPA_KEY_MGMT_FT_FILS_SHA384:
1996 return "FT-FILS-SHA384";
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001997 case WPA_KEY_MGMT_OWE:
1998 return "OWE";
1999 case WPA_KEY_MGMT_DPP:
2000 return "DPP";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002001 default:
2002 return "UNKNOWN";
2003 }
2004}
2005
2006
Dmitry Shmidt03658832014-08-13 11:03:49 -07002007u32 wpa_akm_to_suite(int akm)
2008{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002009 if (akm & WPA_KEY_MGMT_FT_IEEE8021X_SHA384)
2010 return RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002011 if (akm & WPA_KEY_MGMT_FT_IEEE8021X)
Paul Stewart092955c2017-02-06 09:13:09 -08002012 return RSN_AUTH_KEY_MGMT_FT_802_1X;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002013 if (akm & WPA_KEY_MGMT_FT_PSK)
Paul Stewart092955c2017-02-06 09:13:09 -08002014 return RSN_AUTH_KEY_MGMT_FT_PSK;
Rebecca Silberstein055a67c2017-02-01 23:05:56 +00002015 if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08002016 return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
Rebecca Silberstein055a67c2017-02-01 23:05:56 +00002017 if (akm & WPA_KEY_MGMT_IEEE8021X)
Paul Stewart092955c2017-02-06 09:13:09 -08002018 return RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002019 if (akm & WPA_KEY_MGMT_PSK_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08002020 return RSN_AUTH_KEY_MGMT_PSK_SHA256;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002021 if (akm & WPA_KEY_MGMT_PSK)
Paul Stewart092955c2017-02-06 09:13:09 -08002022 return RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002023 if (akm & WPA_KEY_MGMT_CCKM)
Paul Stewart092955c2017-02-06 09:13:09 -08002024 return RSN_AUTH_KEY_MGMT_CCKM;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002025 if (akm & WPA_KEY_MGMT_OSEN)
Paul Stewart092955c2017-02-06 09:13:09 -08002026 return RSN_AUTH_KEY_MGMT_OSEN;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002027 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
Paul Stewart092955c2017-02-06 09:13:09 -08002028 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002029 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Paul Stewart092955c2017-02-06 09:13:09 -08002030 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002031 if (akm & WPA_KEY_MGMT_FILS_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08002032 return RSN_AUTH_KEY_MGMT_FILS_SHA256;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002033 if (akm & WPA_KEY_MGMT_FILS_SHA384)
Paul Stewart092955c2017-02-06 09:13:09 -08002034 return RSN_AUTH_KEY_MGMT_FILS_SHA384;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002035 if (akm & WPA_KEY_MGMT_FT_FILS_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08002036 return RSN_AUTH_KEY_MGMT_FT_FILS_SHA256;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002037 if (akm & WPA_KEY_MGMT_FT_FILS_SHA384)
Paul Stewart092955c2017-02-06 09:13:09 -08002038 return RSN_AUTH_KEY_MGMT_FT_FILS_SHA384;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002039 return 0;
2040}
2041
2042
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002043int wpa_compare_rsn_ie(int ft_initial_assoc,
2044 const u8 *ie1, size_t ie1len,
2045 const u8 *ie2, size_t ie2len)
2046{
2047 if (ie1 == NULL || ie2 == NULL)
2048 return -1;
2049
2050 if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
2051 return 0; /* identical IEs */
2052
2053#ifdef CONFIG_IEEE80211R
2054 if (ft_initial_assoc) {
2055 struct wpa_ie_data ie1d, ie2d;
2056 /*
2057 * The PMKID-List in RSN IE is different between Beacon/Probe
2058 * Response/(Re)Association Request frames and EAPOL-Key
2059 * messages in FT initial mobility domain association. Allow
2060 * for this, but verify that other parts of the RSN IEs are
2061 * identical.
2062 */
2063 if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
2064 wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
2065 return -1;
2066 if (ie1d.proto == ie2d.proto &&
2067 ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
2068 ie1d.group_cipher == ie2d.group_cipher &&
2069 ie1d.key_mgmt == ie2d.key_mgmt &&
2070 ie1d.capabilities == ie2d.capabilities &&
2071 ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
2072 return 0;
2073 }
2074#endif /* CONFIG_IEEE80211R */
2075
2076 return -1;
2077}
2078
2079
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002080#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002081int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002082{
2083 u8 *start, *end, *rpos, *rend;
2084 int added = 0;
2085
2086 start = ies;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002087 end = ies + *ies_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002088
2089 while (start < end) {
2090 if (*start == WLAN_EID_RSN)
2091 break;
2092 start += 2 + start[1];
2093 }
2094 if (start >= end) {
2095 wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
2096 "IEs data");
2097 return -1;
2098 }
2099 wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
2100 start, 2 + start[1]);
2101
2102 /* Find start of PMKID-Count */
2103 rpos = start + 2;
2104 rend = rpos + start[1];
2105
2106 /* Skip Version and Group Data Cipher Suite */
2107 rpos += 2 + 4;
2108 /* Skip Pairwise Cipher Suite Count and List */
2109 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
2110 /* Skip AKM Suite Count and List */
2111 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
2112
2113 if (rpos == rend) {
2114 /* Add RSN Capabilities */
2115 os_memmove(rpos + 2, rpos, end - rpos);
2116 *rpos++ = 0;
2117 *rpos++ = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002118 added += 2;
2119 start[1] += 2;
2120 rend = rpos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002121 } else {
2122 /* Skip RSN Capabilities */
2123 rpos += 2;
2124 if (rpos > rend) {
2125 wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
2126 "IEs data");
2127 return -1;
2128 }
2129 }
2130
2131 if (rpos == rend) {
2132 /* No PMKID-Count field included; add it */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002133 os_memmove(rpos + 2 + PMKID_LEN, rpos, end + added - rpos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002134 WPA_PUT_LE16(rpos, 1);
2135 rpos += 2;
2136 os_memcpy(rpos, pmkid, PMKID_LEN);
2137 added += 2 + PMKID_LEN;
2138 start[1] += 2 + PMKID_LEN;
2139 } else {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002140 u16 num_pmkid;
2141
2142 if (rend - rpos < 2)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002143 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002144 num_pmkid = WPA_GET_LE16(rpos);
2145 /* PMKID-Count was included; use it */
2146 if (num_pmkid != 0) {
2147 u8 *after;
2148
2149 if (num_pmkid * PMKID_LEN > rend - rpos - 2)
2150 return -1;
2151 /*
2152 * PMKID may have been included in RSN IE in
2153 * (Re)Association Request frame, so remove the old
2154 * PMKID(s) first before adding the new one.
2155 */
2156 wpa_printf(MSG_DEBUG,
2157 "FT: Remove %u old PMKID(s) from RSN IE",
2158 num_pmkid);
2159 after = rpos + 2 + num_pmkid * PMKID_LEN;
2160 os_memmove(rpos + 2, after, rend - after);
2161 start[1] -= num_pmkid * PMKID_LEN;
2162 added -= num_pmkid * PMKID_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002163 }
2164 WPA_PUT_LE16(rpos, 1);
2165 rpos += 2;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002166 os_memmove(rpos + PMKID_LEN, rpos, end + added - rpos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002167 os_memcpy(rpos, pmkid, PMKID_LEN);
2168 added += PMKID_LEN;
2169 start[1] += PMKID_LEN;
2170 }
2171
2172 wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
2173 "(PMKID inserted)", start, 2 + start[1]);
2174
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002175 *ies_len += added;
2176
2177 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002178}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002179#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002180
2181
2182int wpa_cipher_key_len(int cipher)
2183{
2184 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002185 case WPA_CIPHER_CCMP_256:
2186 case WPA_CIPHER_GCMP_256:
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002187 case WPA_CIPHER_BIP_GMAC_256:
2188 case WPA_CIPHER_BIP_CMAC_256:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002189 return 32;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002190 case WPA_CIPHER_CCMP:
2191 case WPA_CIPHER_GCMP:
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002192 case WPA_CIPHER_AES_128_CMAC:
2193 case WPA_CIPHER_BIP_GMAC_128:
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002194 return 16;
2195 case WPA_CIPHER_TKIP:
2196 return 32;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002197 }
2198
2199 return 0;
2200}
2201
2202
2203int wpa_cipher_rsc_len(int cipher)
2204{
2205 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002206 case WPA_CIPHER_CCMP_256:
2207 case WPA_CIPHER_GCMP_256:
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002208 case WPA_CIPHER_CCMP:
2209 case WPA_CIPHER_GCMP:
2210 case WPA_CIPHER_TKIP:
2211 return 6;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002212 }
2213
2214 return 0;
2215}
2216
2217
Dmitry Shmidt29333592017-01-09 12:27:11 -08002218enum wpa_alg wpa_cipher_to_alg(int cipher)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002219{
2220 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002221 case WPA_CIPHER_CCMP_256:
2222 return WPA_ALG_CCMP_256;
2223 case WPA_CIPHER_GCMP_256:
2224 return WPA_ALG_GCMP_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002225 case WPA_CIPHER_CCMP:
2226 return WPA_ALG_CCMP;
2227 case WPA_CIPHER_GCMP:
2228 return WPA_ALG_GCMP;
2229 case WPA_CIPHER_TKIP:
2230 return WPA_ALG_TKIP;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002231 case WPA_CIPHER_AES_128_CMAC:
2232 return WPA_ALG_IGTK;
2233 case WPA_CIPHER_BIP_GMAC_128:
2234 return WPA_ALG_BIP_GMAC_128;
2235 case WPA_CIPHER_BIP_GMAC_256:
2236 return WPA_ALG_BIP_GMAC_256;
2237 case WPA_CIPHER_BIP_CMAC_256:
2238 return WPA_ALG_BIP_CMAC_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002239 }
2240 return WPA_ALG_NONE;
2241}
2242
2243
2244int wpa_cipher_valid_pairwise(int cipher)
2245{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002246 return cipher == WPA_CIPHER_CCMP_256 ||
2247 cipher == WPA_CIPHER_GCMP_256 ||
2248 cipher == WPA_CIPHER_CCMP ||
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002249 cipher == WPA_CIPHER_GCMP ||
2250 cipher == WPA_CIPHER_TKIP;
2251}
2252
2253
2254u32 wpa_cipher_to_suite(int proto, int cipher)
2255{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002256 if (cipher & WPA_CIPHER_CCMP_256)
2257 return RSN_CIPHER_SUITE_CCMP_256;
2258 if (cipher & WPA_CIPHER_GCMP_256)
2259 return RSN_CIPHER_SUITE_GCMP_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002260 if (cipher & WPA_CIPHER_CCMP)
2261 return (proto == WPA_PROTO_RSN ?
2262 RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
2263 if (cipher & WPA_CIPHER_GCMP)
2264 return RSN_CIPHER_SUITE_GCMP;
2265 if (cipher & WPA_CIPHER_TKIP)
2266 return (proto == WPA_PROTO_RSN ?
2267 RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002268 if (cipher & WPA_CIPHER_NONE)
2269 return (proto == WPA_PROTO_RSN ?
2270 RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002271 if (cipher & WPA_CIPHER_GTK_NOT_USED)
2272 return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002273 if (cipher & WPA_CIPHER_AES_128_CMAC)
2274 return RSN_CIPHER_SUITE_AES_128_CMAC;
2275 if (cipher & WPA_CIPHER_BIP_GMAC_128)
2276 return RSN_CIPHER_SUITE_BIP_GMAC_128;
2277 if (cipher & WPA_CIPHER_BIP_GMAC_256)
2278 return RSN_CIPHER_SUITE_BIP_GMAC_256;
2279 if (cipher & WPA_CIPHER_BIP_CMAC_256)
2280 return RSN_CIPHER_SUITE_BIP_CMAC_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002281 return 0;
2282}
2283
2284
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002285int rsn_cipher_put_suites(u8 *start, int ciphers)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002286{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002287 u8 *pos = start;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002288
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002289 if (ciphers & WPA_CIPHER_CCMP_256) {
2290 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256);
2291 pos += RSN_SELECTOR_LEN;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002292 }
2293 if (ciphers & WPA_CIPHER_GCMP_256) {
2294 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256);
2295 pos += RSN_SELECTOR_LEN;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002296 }
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002297 if (ciphers & WPA_CIPHER_CCMP) {
2298 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
2299 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002300 }
2301 if (ciphers & WPA_CIPHER_GCMP) {
2302 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP);
2303 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002304 }
2305 if (ciphers & WPA_CIPHER_TKIP) {
2306 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
2307 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002308 }
2309 if (ciphers & WPA_CIPHER_NONE) {
2310 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
2311 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002312 }
2313
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002314 return (pos - start) / RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002315}
2316
2317
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002318int wpa_cipher_put_suites(u8 *start, int ciphers)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002319{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002320 u8 *pos = start;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002321
2322 if (ciphers & WPA_CIPHER_CCMP) {
2323 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
2324 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002325 }
2326 if (ciphers & WPA_CIPHER_TKIP) {
2327 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
2328 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002329 }
2330 if (ciphers & WPA_CIPHER_NONE) {
2331 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
2332 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002333 }
2334
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002335 return (pos - start) / RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002336}
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002337
2338
2339int wpa_pick_pairwise_cipher(int ciphers, int none_allowed)
2340{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002341 if (ciphers & WPA_CIPHER_CCMP_256)
2342 return WPA_CIPHER_CCMP_256;
2343 if (ciphers & WPA_CIPHER_GCMP_256)
2344 return WPA_CIPHER_GCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002345 if (ciphers & WPA_CIPHER_CCMP)
2346 return WPA_CIPHER_CCMP;
2347 if (ciphers & WPA_CIPHER_GCMP)
2348 return WPA_CIPHER_GCMP;
2349 if (ciphers & WPA_CIPHER_TKIP)
2350 return WPA_CIPHER_TKIP;
2351 if (none_allowed && (ciphers & WPA_CIPHER_NONE))
2352 return WPA_CIPHER_NONE;
2353 return -1;
2354}
2355
2356
2357int wpa_pick_group_cipher(int ciphers)
2358{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002359 if (ciphers & WPA_CIPHER_CCMP_256)
2360 return WPA_CIPHER_CCMP_256;
2361 if (ciphers & WPA_CIPHER_GCMP_256)
2362 return WPA_CIPHER_GCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002363 if (ciphers & WPA_CIPHER_CCMP)
2364 return WPA_CIPHER_CCMP;
2365 if (ciphers & WPA_CIPHER_GCMP)
2366 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002367 if (ciphers & WPA_CIPHER_GTK_NOT_USED)
2368 return WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002369 if (ciphers & WPA_CIPHER_TKIP)
2370 return WPA_CIPHER_TKIP;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002371 return -1;
2372}
2373
2374
2375int wpa_parse_cipher(const char *value)
2376{
2377 int val = 0, last;
2378 char *start, *end, *buf;
2379
2380 buf = os_strdup(value);
2381 if (buf == NULL)
2382 return -1;
2383 start = buf;
2384
2385 while (*start != '\0') {
2386 while (*start == ' ' || *start == '\t')
2387 start++;
2388 if (*start == '\0')
2389 break;
2390 end = start;
2391 while (*end != ' ' && *end != '\t' && *end != '\0')
2392 end++;
2393 last = *end == '\0';
2394 *end = '\0';
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002395 if (os_strcmp(start, "CCMP-256") == 0)
2396 val |= WPA_CIPHER_CCMP_256;
2397 else if (os_strcmp(start, "GCMP-256") == 0)
2398 val |= WPA_CIPHER_GCMP_256;
2399 else if (os_strcmp(start, "CCMP") == 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002400 val |= WPA_CIPHER_CCMP;
2401 else if (os_strcmp(start, "GCMP") == 0)
2402 val |= WPA_CIPHER_GCMP;
2403 else if (os_strcmp(start, "TKIP") == 0)
2404 val |= WPA_CIPHER_TKIP;
2405 else if (os_strcmp(start, "WEP104") == 0)
2406 val |= WPA_CIPHER_WEP104;
2407 else if (os_strcmp(start, "WEP40") == 0)
2408 val |= WPA_CIPHER_WEP40;
2409 else if (os_strcmp(start, "NONE") == 0)
2410 val |= WPA_CIPHER_NONE;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002411 else if (os_strcmp(start, "GTK_NOT_USED") == 0)
2412 val |= WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002413 else if (os_strcmp(start, "AES-128-CMAC") == 0)
2414 val |= WPA_CIPHER_AES_128_CMAC;
2415 else if (os_strcmp(start, "BIP-GMAC-128") == 0)
2416 val |= WPA_CIPHER_BIP_GMAC_128;
2417 else if (os_strcmp(start, "BIP-GMAC-256") == 0)
2418 val |= WPA_CIPHER_BIP_GMAC_256;
2419 else if (os_strcmp(start, "BIP-CMAC-256") == 0)
2420 val |= WPA_CIPHER_BIP_CMAC_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002421 else {
2422 os_free(buf);
2423 return -1;
2424 }
2425
2426 if (last)
2427 break;
2428 start = end + 1;
2429 }
2430 os_free(buf);
2431
2432 return val;
2433}
2434
2435
2436int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
2437{
2438 char *pos = start;
2439 int ret;
2440
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002441 if (ciphers & WPA_CIPHER_CCMP_256) {
2442 ret = os_snprintf(pos, end - pos, "%sCCMP-256",
2443 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002444 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002445 return -1;
2446 pos += ret;
2447 }
2448 if (ciphers & WPA_CIPHER_GCMP_256) {
2449 ret = os_snprintf(pos, end - pos, "%sGCMP-256",
2450 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002451 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002452 return -1;
2453 pos += ret;
2454 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002455 if (ciphers & WPA_CIPHER_CCMP) {
2456 ret = os_snprintf(pos, end - pos, "%sCCMP",
2457 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002458 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002459 return -1;
2460 pos += ret;
2461 }
2462 if (ciphers & WPA_CIPHER_GCMP) {
2463 ret = os_snprintf(pos, end - pos, "%sGCMP",
2464 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002465 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002466 return -1;
2467 pos += ret;
2468 }
2469 if (ciphers & WPA_CIPHER_TKIP) {
2470 ret = os_snprintf(pos, end - pos, "%sTKIP",
2471 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002472 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002473 return -1;
2474 pos += ret;
2475 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002476 if (ciphers & WPA_CIPHER_AES_128_CMAC) {
2477 ret = os_snprintf(pos, end - pos, "%sAES-128-CMAC",
2478 pos == start ? "" : delim);
2479 if (os_snprintf_error(end - pos, ret))
2480 return -1;
2481 pos += ret;
2482 }
2483 if (ciphers & WPA_CIPHER_BIP_GMAC_128) {
2484 ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-128",
2485 pos == start ? "" : delim);
2486 if (os_snprintf_error(end - pos, ret))
2487 return -1;
2488 pos += ret;
2489 }
2490 if (ciphers & WPA_CIPHER_BIP_GMAC_256) {
2491 ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-256",
2492 pos == start ? "" : delim);
2493 if (os_snprintf_error(end - pos, ret))
2494 return -1;
2495 pos += ret;
2496 }
2497 if (ciphers & WPA_CIPHER_BIP_CMAC_256) {
2498 ret = os_snprintf(pos, end - pos, "%sBIP-CMAC-256",
2499 pos == start ? "" : delim);
2500 if (os_snprintf_error(end - pos, ret))
2501 return -1;
2502 pos += ret;
2503 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002504 if (ciphers & WPA_CIPHER_NONE) {
2505 ret = os_snprintf(pos, end - pos, "%sNONE",
2506 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002507 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002508 return -1;
2509 pos += ret;
2510 }
2511
2512 return pos - start;
2513}
2514
2515
2516int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
2517{
2518 int pairwise = 0;
2519
2520 /* Select group cipher based on the enabled pairwise cipher suites */
2521 if (wpa & 1)
2522 pairwise |= wpa_pairwise;
2523 if (wpa & 2)
2524 pairwise |= rsn_pairwise;
2525
2526 if (pairwise & WPA_CIPHER_TKIP)
2527 return WPA_CIPHER_TKIP;
2528 if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP)
2529 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002530 if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP |
2531 WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256)
2532 return WPA_CIPHER_GCMP_256;
2533 if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
2534 WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256)
2535 return WPA_CIPHER_CCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002536 return WPA_CIPHER_CCMP;
2537}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002538
2539
2540#ifdef CONFIG_FILS
Dmitry Shmidt29333592017-01-09 12:27:11 -08002541int fils_domain_name_hash(const char *domain, u8 *hash)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002542{
2543 char buf[255], *wpos = buf;
2544 const char *pos = domain;
2545 size_t len;
Dmitry Shmidt29333592017-01-09 12:27:11 -08002546 const u8 *addr[1];
2547 u8 mac[SHA256_MAC_LEN];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002548
2549 for (len = 0; len < sizeof(buf) && *pos; len++) {
2550 if (isalpha(*pos) && isupper(*pos))
2551 *wpos++ = tolower(*pos);
2552 else
2553 *wpos++ = *pos;
2554 pos++;
2555 }
2556
Dmitry Shmidt29333592017-01-09 12:27:11 -08002557 addr[0] = (const u8 *) buf;
2558 if (sha256_vector(1, addr, &len, mac) < 0)
2559 return -1;
2560 os_memcpy(hash, mac, 2);
2561 return 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002562}
2563#endif /* CONFIG_FILS */