blob: b47f632e50c5683672b9a2d14fc6ea85247e3644 [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 */
Hai Shalom74f70d42019-02-11 14:42:39 -0800883#ifdef CONFIG_OCV
884 case FTIE_SUBELEM_OCI:
885 parse->oci = pos;
886 parse->oci_len = len;
887 break;
888#endif /* CONFIG_OCV */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700889 default:
890 wpa_printf(MSG_DEBUG, "FT: Unknown subelem id %u", id);
891 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800892 }
893
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800894 pos += len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800895 }
896
897 return 0;
898}
899
900
901int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700902 struct wpa_ft_ies *parse, int use_sha384)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800903{
904 const u8 *end, *pos;
905 struct wpa_ie_data data;
906 int ret;
907 const struct rsn_ftie *ftie;
908 int prot_ie_count = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700909 int update_use_sha384 = 0;
910
911 if (use_sha384 < 0) {
912 use_sha384 = 0;
913 update_use_sha384 = 1;
914 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800915
916 os_memset(parse, 0, sizeof(*parse));
917 if (ies == NULL)
918 return 0;
919
920 pos = ies;
921 end = ies + ies_len;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800922 while (end - pos >= 2) {
923 u8 id, len;
924
925 id = *pos++;
926 len = *pos++;
927 if (len > end - pos)
928 break;
929
930 switch (id) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800931 case WLAN_EID_RSN:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700932 wpa_hexdump(MSG_DEBUG, "FT: RSNE", pos, len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800933 parse->rsn = pos;
934 parse->rsn_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800935 ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
936 parse->rsn_len + 2,
937 &data);
938 if (ret < 0) {
939 wpa_printf(MSG_DEBUG, "FT: Failed to parse "
940 "RSN IE: %d", ret);
941 return -1;
942 }
943 if (data.num_pmkid == 1 && data.pmkid)
944 parse->rsn_pmkid = data.pmkid;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800945 parse->key_mgmt = data.key_mgmt;
946 parse->pairwise_cipher = data.pairwise_cipher;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700947 if (update_use_sha384) {
948 use_sha384 =
949 wpa_key_mgmt_sha384(parse->key_mgmt);
950 update_use_sha384 = 0;
951 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800952 break;
953 case WLAN_EID_MOBILITY_DOMAIN:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700954 wpa_hexdump(MSG_DEBUG, "FT: MDE", pos, len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800955 if (len < sizeof(struct rsn_mdie))
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700956 return -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800957 parse->mdie = pos;
958 parse->mdie_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800959 break;
960 case WLAN_EID_FAST_BSS_TRANSITION:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700961 wpa_hexdump(MSG_DEBUG, "FT: FTE", pos, len);
962 if (use_sha384) {
963 const struct rsn_ftie_sha384 *ftie_sha384;
964
965 if (len < sizeof(*ftie_sha384))
966 return -1;
967 ftie_sha384 =
968 (const struct rsn_ftie_sha384 *) pos;
969 wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control",
970 ftie_sha384->mic_control, 2);
971 wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC",
972 ftie_sha384->mic,
973 sizeof(ftie_sha384->mic));
974 wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce",
975 ftie_sha384->anonce,
976 WPA_NONCE_LEN);
977 wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce",
978 ftie_sha384->snonce,
979 WPA_NONCE_LEN);
980 prot_ie_count = ftie_sha384->mic_control[1];
981 if (wpa_ft_parse_ftie(pos, len, parse, 1) < 0)
982 return -1;
983 break;
984 }
985
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800986 if (len < sizeof(*ftie))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800987 return -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800988 ftie = (const struct rsn_ftie *) pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700989 wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control",
990 ftie->mic_control, 2);
991 wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC",
992 ftie->mic, sizeof(ftie->mic));
993 wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce",
994 ftie->anonce, WPA_NONCE_LEN);
995 wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce",
996 ftie->snonce, WPA_NONCE_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800997 prot_ie_count = ftie->mic_control[1];
Roshan Pius3a1667e2018-07-03 15:17:14 -0700998 if (wpa_ft_parse_ftie(pos, len, parse, 0) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800999 return -1;
1000 break;
1001 case WLAN_EID_TIMEOUT_INTERVAL:
Roshan Pius3a1667e2018-07-03 15:17:14 -07001002 wpa_hexdump(MSG_DEBUG, "FT: Timeout Interval",
1003 pos, len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001004 if (len != 5)
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001005 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001006 parse->tie = pos;
1007 parse->tie_len = len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001008 break;
1009 case WLAN_EID_RIC_DATA:
1010 if (parse->ric == NULL)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001011 parse->ric = pos - 2;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001012 break;
1013 }
1014
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001015 pos += len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001016 }
1017
1018 if (prot_ie_count == 0)
1019 return 0; /* no MIC */
1020
1021 /*
1022 * Check that the protected IE count matches with IEs included in the
1023 * frame.
1024 */
1025 if (parse->rsn)
1026 prot_ie_count--;
1027 if (parse->mdie)
1028 prot_ie_count--;
1029 if (parse->ftie)
1030 prot_ie_count--;
1031 if (prot_ie_count < 0) {
1032 wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
1033 "the protected IE count");
1034 return -1;
1035 }
1036
1037 if (prot_ie_count == 0 && parse->ric) {
1038 wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
1039 "included in protected IE count");
1040 return -1;
1041 }
1042
1043 /* Determine the end of the RIC IE(s) */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001044 if (parse->ric) {
1045 pos = parse->ric;
1046 while (end - pos >= 2 && 2 + pos[1] <= end - pos &&
1047 prot_ie_count) {
1048 prot_ie_count--;
1049 pos += 2 + pos[1];
1050 }
1051 parse->ric_len = pos - parse->ric;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001052 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001053 if (prot_ie_count) {
1054 wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
1055 "frame", (int) prot_ie_count);
1056 return -1;
1057 }
1058
1059 return 0;
1060}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001061#endif /* CONFIG_IEEE80211R */
1062
1063
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001064static int rsn_selector_to_bitfield(const u8 *s)
1065{
1066 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
1067 return WPA_CIPHER_NONE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001068 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
1069 return WPA_CIPHER_TKIP;
1070 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
1071 return WPA_CIPHER_CCMP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001072#ifdef CONFIG_IEEE80211W
1073 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
1074 return WPA_CIPHER_AES_128_CMAC;
1075#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001076 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
1077 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001078 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256)
1079 return WPA_CIPHER_CCMP_256;
1080 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256)
1081 return WPA_CIPHER_GCMP_256;
1082 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128)
1083 return WPA_CIPHER_BIP_GMAC_128;
1084 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256)
1085 return WPA_CIPHER_BIP_GMAC_256;
1086 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256)
1087 return WPA_CIPHER_BIP_CMAC_256;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001088 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED)
1089 return WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001090 return 0;
1091}
1092
1093
1094static int rsn_key_mgmt_to_bitfield(const u8 *s)
1095{
1096 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
1097 return WPA_KEY_MGMT_IEEE8021X;
1098 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
1099 return WPA_KEY_MGMT_PSK;
1100#ifdef CONFIG_IEEE80211R
1101 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
1102 return WPA_KEY_MGMT_FT_IEEE8021X;
1103 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
1104 return WPA_KEY_MGMT_FT_PSK;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001105#ifdef CONFIG_SHA384
1106 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384)
1107 return WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1108#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001109#endif /* CONFIG_IEEE80211R */
1110#ifdef CONFIG_IEEE80211W
1111 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
1112 return WPA_KEY_MGMT_IEEE8021X_SHA256;
1113 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
1114 return WPA_KEY_MGMT_PSK_SHA256;
1115#endif /* CONFIG_IEEE80211W */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001116#ifdef CONFIG_SAE
1117 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
1118 return WPA_KEY_MGMT_SAE;
1119 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
1120 return WPA_KEY_MGMT_FT_SAE;
1121#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001122 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B)
1123 return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001124 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
1125 return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001126 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA256)
1127 return WPA_KEY_MGMT_FILS_SHA256;
1128 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA384)
1129 return WPA_KEY_MGMT_FILS_SHA384;
1130 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA256)
1131 return WPA_KEY_MGMT_FT_FILS_SHA256;
1132 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA384)
1133 return WPA_KEY_MGMT_FT_FILS_SHA384;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001134#ifdef CONFIG_OWE
1135 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE)
1136 return WPA_KEY_MGMT_OWE;
1137#endif /* CONFIG_OWE */
1138#ifdef CONFIG_DPP
1139 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_DPP)
1140 return WPA_KEY_MGMT_DPP;
1141#endif /* CONFIG_DPP */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001142 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN)
1143 return WPA_KEY_MGMT_OSEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001144 return 0;
1145}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001146
1147
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001148int wpa_cipher_valid_group(int cipher)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001149{
1150 return wpa_cipher_valid_pairwise(cipher) ||
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001151 cipher == WPA_CIPHER_GTK_NOT_USED;
1152}
1153
1154
1155#ifdef CONFIG_IEEE80211W
1156int wpa_cipher_valid_mgmt_group(int cipher)
1157{
1158 return cipher == WPA_CIPHER_AES_128_CMAC ||
1159 cipher == WPA_CIPHER_BIP_GMAC_128 ||
1160 cipher == WPA_CIPHER_BIP_GMAC_256 ||
1161 cipher == WPA_CIPHER_BIP_CMAC_256;
1162}
1163#endif /* CONFIG_IEEE80211W */
1164
1165
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001166/**
1167 * wpa_parse_wpa_ie_rsn - Parse RSN IE
1168 * @rsn_ie: Buffer containing RSN IE
1169 * @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
1170 * @data: Pointer to structure that will be filled in with parsed data
1171 * Returns: 0 on success, <0 on failure
1172 */
1173int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
1174 struct wpa_ie_data *data)
1175{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001176 const u8 *pos;
1177 int left;
1178 int i, count;
1179
1180 os_memset(data, 0, sizeof(*data));
1181 data->proto = WPA_PROTO_RSN;
1182 data->pairwise_cipher = WPA_CIPHER_CCMP;
1183 data->group_cipher = WPA_CIPHER_CCMP;
1184 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1185 data->capabilities = 0;
1186 data->pmkid = NULL;
1187 data->num_pmkid = 0;
1188#ifdef CONFIG_IEEE80211W
1189 data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1190#else /* CONFIG_IEEE80211W */
1191 data->mgmt_group_cipher = 0;
1192#endif /* CONFIG_IEEE80211W */
1193
1194 if (rsn_ie_len == 0) {
1195 /* No RSN IE - fail silently */
1196 return -1;
1197 }
1198
1199 if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
1200 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
1201 __func__, (unsigned long) rsn_ie_len);
1202 return -1;
1203 }
1204
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001205 if (rsn_ie_len >= 6 && rsn_ie[1] >= 4 &&
1206 rsn_ie[1] == rsn_ie_len - 2 &&
1207 WPA_GET_BE32(&rsn_ie[2]) == OSEN_IE_VENDOR_TYPE) {
1208 pos = rsn_ie + 6;
1209 left = rsn_ie_len - 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001210
Hai Shalom74f70d42019-02-11 14:42:39 -08001211 data->group_cipher = WPA_CIPHER_GTK_NOT_USED;
1212 data->key_mgmt = WPA_KEY_MGMT_OSEN;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001213 data->proto = WPA_PROTO_OSEN;
1214 } else {
1215 const struct rsn_ie_hdr *hdr;
1216
1217 hdr = (const struct rsn_ie_hdr *) rsn_ie;
1218
1219 if (hdr->elem_id != WLAN_EID_RSN ||
1220 hdr->len != rsn_ie_len - 2 ||
1221 WPA_GET_LE16(hdr->version) != RSN_VERSION) {
1222 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
1223 __func__);
1224 return -2;
1225 }
1226
1227 pos = (const u8 *) (hdr + 1);
1228 left = rsn_ie_len - sizeof(*hdr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001229 }
1230
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001231 if (left >= RSN_SELECTOR_LEN) {
1232 data->group_cipher = rsn_selector_to_bitfield(pos);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001233 if (!wpa_cipher_valid_group(data->group_cipher)) {
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08001234 wpa_printf(MSG_DEBUG,
1235 "%s: invalid group cipher 0x%x (%08x)",
1236 __func__, data->group_cipher,
1237 WPA_GET_BE32(pos));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001238 return -1;
1239 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001240 pos += RSN_SELECTOR_LEN;
1241 left -= RSN_SELECTOR_LEN;
1242 } else if (left > 0) {
1243 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
1244 __func__, left);
1245 return -3;
1246 }
1247
1248 if (left >= 2) {
1249 data->pairwise_cipher = 0;
1250 count = WPA_GET_LE16(pos);
1251 pos += 2;
1252 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001253 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001254 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
1255 "count %u left %u", __func__, count, left);
1256 return -4;
1257 }
1258 for (i = 0; i < count; i++) {
1259 data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
1260 pos += RSN_SELECTOR_LEN;
1261 left -= RSN_SELECTOR_LEN;
1262 }
1263#ifdef CONFIG_IEEE80211W
1264 if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
1265 wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
1266 "pairwise cipher", __func__);
1267 return -1;
1268 }
1269#endif /* CONFIG_IEEE80211W */
1270 } else if (left == 1) {
1271 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
1272 __func__);
1273 return -5;
1274 }
1275
1276 if (left >= 2) {
1277 data->key_mgmt = 0;
1278 count = WPA_GET_LE16(pos);
1279 pos += 2;
1280 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001281 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001282 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
1283 "count %u left %u", __func__, count, left);
1284 return -6;
1285 }
1286 for (i = 0; i < count; i++) {
1287 data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
1288 pos += RSN_SELECTOR_LEN;
1289 left -= RSN_SELECTOR_LEN;
1290 }
1291 } else if (left == 1) {
1292 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
1293 __func__);
1294 return -7;
1295 }
1296
1297 if (left >= 2) {
1298 data->capabilities = WPA_GET_LE16(pos);
1299 pos += 2;
1300 left -= 2;
1301 }
1302
1303 if (left >= 2) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001304 u16 num_pmkid = WPA_GET_LE16(pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001305 pos += 2;
1306 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001307 if (num_pmkid > (unsigned int) left / PMKID_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001308 wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001309 "(num_pmkid=%u left=%d)",
1310 __func__, num_pmkid, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001311 data->num_pmkid = 0;
1312 return -9;
1313 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001314 data->num_pmkid = num_pmkid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001315 data->pmkid = pos;
1316 pos += data->num_pmkid * PMKID_LEN;
1317 left -= data->num_pmkid * PMKID_LEN;
1318 }
1319 }
1320
1321#ifdef CONFIG_IEEE80211W
1322 if (left >= 4) {
1323 data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001324 if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001325 wpa_printf(MSG_DEBUG,
1326 "%s: Unsupported management group cipher 0x%x (%08x)",
1327 __func__, data->mgmt_group_cipher,
1328 WPA_GET_BE32(pos));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001329 return -10;
1330 }
1331 pos += RSN_SELECTOR_LEN;
1332 left -= RSN_SELECTOR_LEN;
1333 }
1334#endif /* CONFIG_IEEE80211W */
1335
1336 if (left > 0) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001337 wpa_hexdump(MSG_DEBUG,
1338 "wpa_parse_wpa_ie_rsn: ignore trailing bytes",
1339 pos, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001340 }
1341
1342 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001343}
1344
1345
1346static int wpa_selector_to_bitfield(const u8 *s)
1347{
1348 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
1349 return WPA_CIPHER_NONE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001350 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
1351 return WPA_CIPHER_TKIP;
1352 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
1353 return WPA_CIPHER_CCMP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001354 return 0;
1355}
1356
1357
1358static int wpa_key_mgmt_to_bitfield(const u8 *s)
1359{
1360 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
1361 return WPA_KEY_MGMT_IEEE8021X;
1362 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
1363 return WPA_KEY_MGMT_PSK;
1364 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
1365 return WPA_KEY_MGMT_WPA_NONE;
1366 return 0;
1367}
1368
1369
1370int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
1371 struct wpa_ie_data *data)
1372{
1373 const struct wpa_ie_hdr *hdr;
1374 const u8 *pos;
1375 int left;
1376 int i, count;
1377
1378 os_memset(data, 0, sizeof(*data));
1379 data->proto = WPA_PROTO_WPA;
1380 data->pairwise_cipher = WPA_CIPHER_TKIP;
1381 data->group_cipher = WPA_CIPHER_TKIP;
1382 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1383 data->capabilities = 0;
1384 data->pmkid = NULL;
1385 data->num_pmkid = 0;
1386 data->mgmt_group_cipher = 0;
1387
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001388 if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
1389 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
1390 __func__, (unsigned long) wpa_ie_len);
1391 return -1;
1392 }
1393
1394 hdr = (const struct wpa_ie_hdr *) wpa_ie;
1395
1396 if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
1397 hdr->len != wpa_ie_len - 2 ||
1398 RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
1399 WPA_GET_LE16(hdr->version) != WPA_VERSION) {
1400 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
1401 __func__);
1402 return -2;
1403 }
1404
1405 pos = (const u8 *) (hdr + 1);
1406 left = wpa_ie_len - sizeof(*hdr);
1407
1408 if (left >= WPA_SELECTOR_LEN) {
1409 data->group_cipher = wpa_selector_to_bitfield(pos);
1410 pos += WPA_SELECTOR_LEN;
1411 left -= WPA_SELECTOR_LEN;
1412 } else if (left > 0) {
1413 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
1414 __func__, left);
1415 return -3;
1416 }
1417
1418 if (left >= 2) {
1419 data->pairwise_cipher = 0;
1420 count = WPA_GET_LE16(pos);
1421 pos += 2;
1422 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001423 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001424 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
1425 "count %u left %u", __func__, count, left);
1426 return -4;
1427 }
1428 for (i = 0; i < count; i++) {
1429 data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
1430 pos += WPA_SELECTOR_LEN;
1431 left -= WPA_SELECTOR_LEN;
1432 }
1433 } else if (left == 1) {
1434 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
1435 __func__);
1436 return -5;
1437 }
1438
1439 if (left >= 2) {
1440 data->key_mgmt = 0;
1441 count = WPA_GET_LE16(pos);
1442 pos += 2;
1443 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001444 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001445 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
1446 "count %u left %u", __func__, count, left);
1447 return -6;
1448 }
1449 for (i = 0; i < count; i++) {
1450 data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
1451 pos += WPA_SELECTOR_LEN;
1452 left -= WPA_SELECTOR_LEN;
1453 }
1454 } else if (left == 1) {
1455 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
1456 __func__);
1457 return -7;
1458 }
1459
1460 if (left >= 2) {
1461 data->capabilities = WPA_GET_LE16(pos);
1462 pos += 2;
1463 left -= 2;
1464 }
1465
1466 if (left > 0) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001467 wpa_hexdump(MSG_DEBUG,
1468 "wpa_parse_wpa_ie_wpa: ignore trailing bytes",
1469 pos, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001470 }
1471
1472 return 0;
1473}
1474
1475
1476#ifdef CONFIG_IEEE80211R
1477
1478/**
1479 * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
1480 *
1481 * IEEE Std 802.11r-2008 - 8.5.1.5.3
1482 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001483int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
1484 const u8 *ssid, size_t ssid_len,
1485 const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001486 const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name,
1487 int use_sha384)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001488{
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001489 u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001490 FT_R0KH_ID_MAX_LEN + ETH_ALEN];
Roshan Pius3a1667e2018-07-03 15:17:14 -07001491 u8 *pos, r0_key_data[64], hash[48];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001492 const u8 *addr[2];
1493 size_t len[2];
Roshan Pius3a1667e2018-07-03 15:17:14 -07001494 size_t q = use_sha384 ? 48 : 32;
1495 size_t r0_key_data_len = q + 16;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001496
1497 /*
1498 * R0-Key-Data = KDF-384(XXKey, "FT-R0",
1499 * SSIDlength || SSID || MDID || R0KHlength ||
1500 * R0KH-ID || S0KH-ID)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001501 * XXKey is either the second 256 bits of MSK or PSK; or the first
1502 * 384 bits of MSK for FT-EAP-SHA384.
1503 * PMK-R0 = L(R0-Key-Data, 0, Q)
1504 * PMK-R0Name-Salt = L(R0-Key-Data, Q, 128)
1505 * Q = 384 for FT-EAP-SHA384; otherwise, 256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001506 */
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001507 if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001508 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001509 wpa_printf(MSG_DEBUG, "FT: Derive PMK-R0 using KDF-%s",
1510 use_sha384 ? "SHA384" : "SHA256");
1511 wpa_hexdump_key(MSG_DEBUG, "FT: XXKey", xxkey, xxkey_len);
1512 wpa_hexdump_ascii(MSG_DEBUG, "FT: SSID", ssid, ssid_len);
1513 wpa_hexdump(MSG_DEBUG, "FT: MDID", mdid, MOBILITY_DOMAIN_ID_LEN);
1514 wpa_hexdump_ascii(MSG_DEBUG, "FT: R0KH-ID", r0kh_id, r0kh_id_len);
1515 wpa_printf(MSG_DEBUG, "FT: S0KH-ID: " MACSTR, MAC2STR(s0kh_id));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001516 pos = buf;
1517 *pos++ = ssid_len;
1518 os_memcpy(pos, ssid, ssid_len);
1519 pos += ssid_len;
1520 os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
1521 pos += MOBILITY_DOMAIN_ID_LEN;
1522 *pos++ = r0kh_id_len;
1523 os_memcpy(pos, r0kh_id, r0kh_id_len);
1524 pos += r0kh_id_len;
1525 os_memcpy(pos, s0kh_id, ETH_ALEN);
1526 pos += ETH_ALEN;
1527
Roshan Pius3a1667e2018-07-03 15:17:14 -07001528#ifdef CONFIG_SHA384
1529 if (use_sha384) {
1530 if (xxkey_len != SHA384_MAC_LEN) {
1531 wpa_printf(MSG_ERROR,
1532 "FT: Unexpected XXKey length %d (expected %d)",
1533 (int) xxkey_len, SHA384_MAC_LEN);
1534 return -1;
1535 }
1536 if (sha384_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
1537 r0_key_data, r0_key_data_len) < 0)
1538 return -1;
1539 }
1540#endif /* CONFIG_SHA384 */
1541 if (!use_sha384) {
1542 if (xxkey_len != PMK_LEN) {
1543 wpa_printf(MSG_ERROR,
1544 "FT: Unexpected XXKey length %d (expected %d)",
1545 (int) xxkey_len, PMK_LEN);
1546 return -1;
1547 }
1548 if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
1549 r0_key_data, r0_key_data_len) < 0)
1550 return -1;
1551 }
1552 os_memcpy(pmk_r0, r0_key_data, q);
1553 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, q);
1554 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0Name-Salt", &r0_key_data[q], 16);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555
1556 /*
Roshan Pius3a1667e2018-07-03 15:17:14 -07001557 * PMKR0Name = Truncate-128(Hash("FT-R0N" || PMK-R0Name-Salt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001558 */
1559 addr[0] = (const u8 *) "FT-R0N";
1560 len[0] = 6;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001561 addr[1] = &r0_key_data[q];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001562 len[1] = 16;
1563
Roshan Pius3a1667e2018-07-03 15:17:14 -07001564#ifdef CONFIG_SHA384
1565 if (use_sha384 && sha384_vector(2, addr, len, hash) < 0)
1566 return -1;
1567#endif /* CONFIG_SHA384 */
1568 if (!use_sha384 && sha256_vector(2, addr, len, hash) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001569 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001570 os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001571 os_memset(r0_key_data, 0, sizeof(r0_key_data));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001572 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001573}
1574
1575
1576/**
1577 * wpa_derive_pmk_r1_name - Derive PMKR1Name
1578 *
1579 * IEEE Std 802.11r-2008 - 8.5.1.5.4
1580 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001581int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001582 const u8 *s1kh_id, u8 *pmk_r1_name, int use_sha384)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001583{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001584 u8 hash[48];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001585 const u8 *addr[4];
1586 size_t len[4];
1587
1588 /*
Roshan Pius3a1667e2018-07-03 15:17:14 -07001589 * PMKR1Name = Truncate-128(Hash("FT-R1N" || PMKR0Name ||
1590 * R1KH-ID || S1KH-ID))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001591 */
1592 addr[0] = (const u8 *) "FT-R1N";
1593 len[0] = 6;
1594 addr[1] = pmk_r0_name;
1595 len[1] = WPA_PMK_NAME_LEN;
1596 addr[2] = r1kh_id;
1597 len[2] = FT_R1KH_ID_LEN;
1598 addr[3] = s1kh_id;
1599 len[3] = ETH_ALEN;
1600
Roshan Pius3a1667e2018-07-03 15:17:14 -07001601#ifdef CONFIG_SHA384
1602 if (use_sha384 && sha384_vector(4, addr, len, hash) < 0)
1603 return -1;
1604#endif /* CONFIG_SHA384 */
1605 if (!use_sha384 && sha256_vector(4, addr, len, hash) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001606 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001607 os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001608 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001609}
1610
1611
1612/**
1613 * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
1614 *
1615 * IEEE Std 802.11r-2008 - 8.5.1.5.4
1616 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001617int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len,
1618 const u8 *pmk_r0_name,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001619 const u8 *r1kh_id, const u8 *s1kh_id,
1620 u8 *pmk_r1, u8 *pmk_r1_name)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001621{
1622 u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
1623 u8 *pos;
1624
1625 /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001626 wpa_printf(MSG_DEBUG, "FT: Derive PMK-R1 using KDF-%s",
1627 pmk_r0_len == SHA384_MAC_LEN ? "SHA384" : "SHA256");
1628 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len);
1629 wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", r1kh_id, FT_R1KH_ID_LEN);
1630 wpa_printf(MSG_DEBUG, "FT: S1KH-ID: " MACSTR, MAC2STR(s1kh_id));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001631 pos = buf;
1632 os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
1633 pos += FT_R1KH_ID_LEN;
1634 os_memcpy(pos, s1kh_id, ETH_ALEN);
1635 pos += ETH_ALEN;
1636
Roshan Pius3a1667e2018-07-03 15:17:14 -07001637#ifdef CONFIG_SHA384
1638 if (pmk_r0_len == SHA384_MAC_LEN &&
1639 sha384_prf(pmk_r0, pmk_r0_len, "FT-R1",
1640 buf, pos - buf, pmk_r1, pmk_r0_len) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001641 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001642#endif /* CONFIG_SHA384 */
1643 if (pmk_r0_len == PMK_LEN &&
1644 sha256_prf(pmk_r0, pmk_r0_len, "FT-R1",
1645 buf, pos - buf, pmk_r1, pmk_r0_len) < 0)
1646 return -1;
1647 if (pmk_r0_len != SHA384_MAC_LEN && pmk_r0_len != PMK_LEN) {
1648 wpa_printf(MSG_ERROR, "FT: Unexpected PMK-R0 length %d",
1649 (int) pmk_r0_len);
1650 return -1;
1651 }
1652 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r0_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001653
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001654 return wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001655 pmk_r1_name,
1656 pmk_r0_len == SHA384_MAC_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001657}
1658
1659
1660/**
1661 * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
1662 *
1663 * IEEE Std 802.11r-2008 - 8.5.1.5.5
1664 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001665int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len,
1666 const u8 *snonce, const u8 *anonce,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001667 const u8 *sta_addr, const u8 *bssid,
1668 const u8 *pmk_r1_name,
1669 struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001670{
1671 u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
1672 u8 *pos, hash[32];
1673 const u8 *addr[6];
1674 size_t len[6];
Roshan Pius3a1667e2018-07-03 15:17:14 -07001675 u8 tmp[2 * WPA_KCK_MAX_LEN + 2 * WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
1676 size_t ptk_len, offset;
1677 int use_sha384 = wpa_key_mgmt_sha384(akmp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001678
1679 /*
1680 * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
1681 * BSSID || STA-ADDR)
1682 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001683 wpa_printf(MSG_DEBUG, "FT: Derive PTK using KDF-%s",
1684 use_sha384 ? "SHA384" : "SHA256");
1685 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len);
1686 wpa_hexdump(MSG_DEBUG, "FT: SNonce", snonce, WPA_NONCE_LEN);
1687 wpa_hexdump(MSG_DEBUG, "FT: ANonce", anonce, WPA_NONCE_LEN);
1688 wpa_printf(MSG_DEBUG, "FT: BSSID=" MACSTR " STA-ADDR=" MACSTR,
1689 MAC2STR(bssid), MAC2STR(sta_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001690 pos = buf;
1691 os_memcpy(pos, snonce, WPA_NONCE_LEN);
1692 pos += WPA_NONCE_LEN;
1693 os_memcpy(pos, anonce, WPA_NONCE_LEN);
1694 pos += WPA_NONCE_LEN;
1695 os_memcpy(pos, bssid, ETH_ALEN);
1696 pos += ETH_ALEN;
1697 os_memcpy(pos, sta_addr, ETH_ALEN);
1698 pos += ETH_ALEN;
1699
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001700 ptk->kck_len = wpa_kck_len(akmp, PMK_LEN);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001701 ptk->kck2_len = wpa_kck2_len(akmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001702 ptk->kek_len = wpa_kek_len(akmp, PMK_LEN);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001703 ptk->kek2_len = wpa_kek2_len(akmp);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001704 ptk->tk_len = wpa_cipher_key_len(cipher);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001705 ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len +
1706 ptk->kck2_len + ptk->kek2_len;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001707
Roshan Pius3a1667e2018-07-03 15:17:14 -07001708#ifdef CONFIG_SHA384
1709 if (use_sha384) {
1710 if (pmk_r1_len != SHA384_MAC_LEN) {
1711 wpa_printf(MSG_ERROR,
1712 "FT: Unexpected PMK-R1 length %d (expected %d)",
1713 (int) pmk_r1_len, SHA384_MAC_LEN);
1714 return -1;
1715 }
1716 if (sha384_prf(pmk_r1, pmk_r1_len, "FT-PTK",
1717 buf, pos - buf, tmp, ptk_len) < 0)
1718 return -1;
1719 }
1720#endif /* CONFIG_SHA384 */
1721 if (!use_sha384) {
1722 if (pmk_r1_len != PMK_LEN) {
1723 wpa_printf(MSG_ERROR,
1724 "FT: Unexpected PMK-R1 length %d (expected %d)",
1725 (int) pmk_r1_len, PMK_LEN);
1726 return -1;
1727 }
1728 if (sha256_prf(pmk_r1, pmk_r1_len, "FT-PTK",
1729 buf, pos - buf, tmp, ptk_len) < 0)
1730 return -1;
1731 }
1732 wpa_hexdump_key(MSG_DEBUG, "FT: PTK", tmp, ptk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001733
1734 /*
1735 * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
1736 * ANonce || BSSID || STA-ADDR))
1737 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001738 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001739 addr[0] = pmk_r1_name;
1740 len[0] = WPA_PMK_NAME_LEN;
1741 addr[1] = (const u8 *) "FT-PTKN";
1742 len[1] = 7;
1743 addr[2] = snonce;
1744 len[2] = WPA_NONCE_LEN;
1745 addr[3] = anonce;
1746 len[3] = WPA_NONCE_LEN;
1747 addr[4] = bssid;
1748 len[4] = ETH_ALEN;
1749 addr[5] = sta_addr;
1750 len[5] = ETH_ALEN;
1751
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001752 if (sha256_vector(6, addr, len, hash) < 0)
1753 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001754 os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001755
1756 os_memcpy(ptk->kck, tmp, ptk->kck_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001757 offset = ptk->kck_len;
1758 os_memcpy(ptk->kek, tmp + offset, ptk->kek_len);
1759 offset += ptk->kek_len;
1760 os_memcpy(ptk->tk, tmp + offset, ptk->tk_len);
1761 offset += ptk->tk_len;
1762 os_memcpy(ptk->kck2, tmp + offset, ptk->kck2_len);
1763 offset = ptk->kck2_len;
1764 os_memcpy(ptk->kek2, tmp + offset, ptk->kek2_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001765
1766 wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len);
1767 wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001768 if (ptk->kck2_len)
1769 wpa_hexdump_key(MSG_DEBUG, "FT: KCK2",
1770 ptk->kck2, ptk->kck2_len);
1771 if (ptk->kek2_len)
1772 wpa_hexdump_key(MSG_DEBUG, "FT: KEK2",
1773 ptk->kek2, ptk->kek2_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001774 wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len);
1775 wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
1776
1777 os_memset(tmp, 0, sizeof(tmp));
1778
1779 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780}
1781
1782#endif /* CONFIG_IEEE80211R */
1783
1784
1785/**
1786 * rsn_pmkid - Calculate PMK identifier
1787 * @pmk: Pairwise master key
1788 * @pmk_len: Length of pmk in bytes
1789 * @aa: Authenticator address
1790 * @spa: Supplicant address
1791 * @pmkid: Buffer for PMKID
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001792 * @akmp: Negotiated key management protocol
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001793 *
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001794 * IEEE Std 802.11-2016 - 12.7.1.3 Pairwise key hierarchy
1795 * AKM: 00-0F-AC:5, 00-0F-AC:6, 00-0F-AC:14, 00-0F-AC:16
1796 * PMKID = Truncate-128(HMAC-SHA-256(PMK, "PMK Name" || AA || SPA))
1797 * AKM: 00-0F-AC:11
1798 * See rsn_pmkid_suite_b()
1799 * AKM: 00-0F-AC:12
1800 * See rsn_pmkid_suite_b_192()
Roshan Pius3a1667e2018-07-03 15:17:14 -07001801 * AKM: 00-0F-AC:13, 00-0F-AC:15, 00-0F-AC:17
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001802 * PMKID = Truncate-128(HMAC-SHA-384(PMK, "PMK Name" || AA || SPA))
1803 * Otherwise:
1804 * PMKID = Truncate-128(HMAC-SHA-1(PMK, "PMK Name" || AA || SPA))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805 */
1806void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001807 u8 *pmkid, int akmp)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001808{
1809 char *title = "PMK Name";
1810 const u8 *addr[3];
1811 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001812 unsigned char hash[SHA384_MAC_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001813
1814 addr[0] = (u8 *) title;
1815 addr[1] = aa;
1816 addr[2] = spa;
1817
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001818 if (0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001819#if defined(CONFIG_FILS) || defined(CONFIG_SHA384)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001820 } else if (wpa_key_mgmt_sha384(akmp)) {
1821 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-384");
1822 hmac_sha384_vector(pmk, pmk_len, 3, addr, len, hash);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001823#endif /* CONFIG_FILS || CONFIG_SHA384 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001824#if defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS)
1825 } else if (wpa_key_mgmt_sha256(akmp)) {
1826 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001827 hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001828#endif /* CONFIG_IEEE80211W || CONFIG_FILS */
1829 } else {
1830 wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-1");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001831 hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001832 }
1833 wpa_hexdump(MSG_DEBUG, "RSN: Derived PMKID", hash, PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834 os_memcpy(pmkid, hash, PMKID_LEN);
1835}
1836
1837
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001838#ifdef CONFIG_SUITEB
1839/**
1840 * rsn_pmkid_suite_b - Calculate PMK identifier for Suite B AKM
1841 * @kck: Key confirmation key
1842 * @kck_len: Length of kck in bytes
1843 * @aa: Authenticator address
1844 * @spa: Supplicant address
1845 * @pmkid: Buffer for PMKID
1846 * Returns: 0 on success, -1 on failure
1847 *
1848 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1849 * PMKID = Truncate(HMAC-SHA-256(KCK, "PMK Name" || AA || SPA))
1850 */
1851int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
1852 const u8 *spa, u8 *pmkid)
1853{
1854 char *title = "PMK Name";
1855 const u8 *addr[3];
1856 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1857 unsigned char hash[SHA256_MAC_LEN];
1858
1859 addr[0] = (u8 *) title;
1860 addr[1] = aa;
1861 addr[2] = spa;
1862
1863 if (hmac_sha256_vector(kck, kck_len, 3, addr, len, hash) < 0)
1864 return -1;
1865 os_memcpy(pmkid, hash, PMKID_LEN);
1866 return 0;
1867}
1868#endif /* CONFIG_SUITEB */
1869
1870
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001871#ifdef CONFIG_SUITEB192
1872/**
1873 * rsn_pmkid_suite_b_192 - Calculate PMK identifier for Suite B AKM
1874 * @kck: Key confirmation key
1875 * @kck_len: Length of kck in bytes
1876 * @aa: Authenticator address
1877 * @spa: Supplicant address
1878 * @pmkid: Buffer for PMKID
1879 * Returns: 0 on success, -1 on failure
1880 *
1881 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1882 * PMKID = Truncate(HMAC-SHA-384(KCK, "PMK Name" || AA || SPA))
1883 */
1884int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa,
1885 const u8 *spa, u8 *pmkid)
1886{
1887 char *title = "PMK Name";
1888 const u8 *addr[3];
1889 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1890 unsigned char hash[SHA384_MAC_LEN];
1891
1892 addr[0] = (u8 *) title;
1893 addr[1] = aa;
1894 addr[2] = spa;
1895
1896 if (hmac_sha384_vector(kck, kck_len, 3, addr, len, hash) < 0)
1897 return -1;
1898 os_memcpy(pmkid, hash, PMKID_LEN);
1899 return 0;
1900}
1901#endif /* CONFIG_SUITEB192 */
1902
1903
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904/**
1905 * wpa_cipher_txt - Convert cipher suite to a text string
1906 * @cipher: Cipher suite (WPA_CIPHER_* enum)
1907 * Returns: Pointer to a text string of the cipher suite name
1908 */
1909const char * wpa_cipher_txt(int cipher)
1910{
1911 switch (cipher) {
1912 case WPA_CIPHER_NONE:
1913 return "NONE";
1914 case WPA_CIPHER_WEP40:
1915 return "WEP-40";
1916 case WPA_CIPHER_WEP104:
1917 return "WEP-104";
1918 case WPA_CIPHER_TKIP:
1919 return "TKIP";
1920 case WPA_CIPHER_CCMP:
1921 return "CCMP";
1922 case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
1923 return "CCMP+TKIP";
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001924 case WPA_CIPHER_GCMP:
1925 return "GCMP";
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001926 case WPA_CIPHER_GCMP_256:
1927 return "GCMP-256";
1928 case WPA_CIPHER_CCMP_256:
1929 return "CCMP-256";
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001930 case WPA_CIPHER_AES_128_CMAC:
1931 return "BIP";
1932 case WPA_CIPHER_BIP_GMAC_128:
1933 return "BIP-GMAC-128";
1934 case WPA_CIPHER_BIP_GMAC_256:
1935 return "BIP-GMAC-256";
1936 case WPA_CIPHER_BIP_CMAC_256:
1937 return "BIP-CMAC-256";
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001938 case WPA_CIPHER_GTK_NOT_USED:
1939 return "GTK_NOT_USED";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001940 default:
1941 return "UNKNOWN";
1942 }
1943}
1944
1945
1946/**
1947 * wpa_key_mgmt_txt - Convert key management suite to a text string
1948 * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
1949 * @proto: WPA/WPA2 version (WPA_PROTO_*)
1950 * Returns: Pointer to a text string of the key management suite name
1951 */
1952const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
1953{
1954 switch (key_mgmt) {
1955 case WPA_KEY_MGMT_IEEE8021X:
1956 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1957 return "WPA2+WPA/IEEE 802.1X/EAP";
1958 return proto == WPA_PROTO_RSN ?
1959 "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
1960 case WPA_KEY_MGMT_PSK:
1961 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1962 return "WPA2-PSK+WPA-PSK";
1963 return proto == WPA_PROTO_RSN ?
1964 "WPA2-PSK" : "WPA-PSK";
1965 case WPA_KEY_MGMT_NONE:
1966 return "NONE";
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001967 case WPA_KEY_MGMT_WPA_NONE:
1968 return "WPA-NONE";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001969 case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
1970 return "IEEE 802.1X (no WPA)";
1971#ifdef CONFIG_IEEE80211R
1972 case WPA_KEY_MGMT_FT_IEEE8021X:
1973 return "FT-EAP";
Roshan Pius3a1667e2018-07-03 15:17:14 -07001974 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
1975 return "FT-EAP-SHA384";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001976 case WPA_KEY_MGMT_FT_PSK:
1977 return "FT-PSK";
1978#endif /* CONFIG_IEEE80211R */
1979#ifdef CONFIG_IEEE80211W
1980 case WPA_KEY_MGMT_IEEE8021X_SHA256:
1981 return "WPA2-EAP-SHA256";
1982 case WPA_KEY_MGMT_PSK_SHA256:
1983 return "WPA2-PSK-SHA256";
1984#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001985 case WPA_KEY_MGMT_WPS:
1986 return "WPS";
1987 case WPA_KEY_MGMT_SAE:
1988 return "SAE";
1989 case WPA_KEY_MGMT_FT_SAE:
1990 return "FT-SAE";
1991 case WPA_KEY_MGMT_OSEN:
1992 return "OSEN";
1993 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
1994 return "WPA2-EAP-SUITE-B";
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001995 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
1996 return "WPA2-EAP-SUITE-B-192";
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001997 case WPA_KEY_MGMT_FILS_SHA256:
1998 return "FILS-SHA256";
1999 case WPA_KEY_MGMT_FILS_SHA384:
2000 return "FILS-SHA384";
2001 case WPA_KEY_MGMT_FT_FILS_SHA256:
2002 return "FT-FILS-SHA256";
2003 case WPA_KEY_MGMT_FT_FILS_SHA384:
2004 return "FT-FILS-SHA384";
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002005 case WPA_KEY_MGMT_OWE:
2006 return "OWE";
2007 case WPA_KEY_MGMT_DPP:
2008 return "DPP";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009 default:
2010 return "UNKNOWN";
2011 }
2012}
2013
2014
Dmitry Shmidt03658832014-08-13 11:03:49 -07002015u32 wpa_akm_to_suite(int akm)
2016{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002017 if (akm & WPA_KEY_MGMT_FT_IEEE8021X_SHA384)
2018 return RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002019 if (akm & WPA_KEY_MGMT_FT_IEEE8021X)
Paul Stewart092955c2017-02-06 09:13:09 -08002020 return RSN_AUTH_KEY_MGMT_FT_802_1X;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002021 if (akm & WPA_KEY_MGMT_FT_PSK)
Paul Stewart092955c2017-02-06 09:13:09 -08002022 return RSN_AUTH_KEY_MGMT_FT_PSK;
Rebecca Silberstein055a67c2017-02-01 23:05:56 +00002023 if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08002024 return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
Rebecca Silberstein055a67c2017-02-01 23:05:56 +00002025 if (akm & WPA_KEY_MGMT_IEEE8021X)
Paul Stewart092955c2017-02-06 09:13:09 -08002026 return RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002027 if (akm & WPA_KEY_MGMT_PSK_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08002028 return RSN_AUTH_KEY_MGMT_PSK_SHA256;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002029 if (akm & WPA_KEY_MGMT_PSK)
Paul Stewart092955c2017-02-06 09:13:09 -08002030 return RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002031 if (akm & WPA_KEY_MGMT_CCKM)
Paul Stewart092955c2017-02-06 09:13:09 -08002032 return RSN_AUTH_KEY_MGMT_CCKM;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002033 if (akm & WPA_KEY_MGMT_OSEN)
Paul Stewart092955c2017-02-06 09:13:09 -08002034 return RSN_AUTH_KEY_MGMT_OSEN;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002035 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
Paul Stewart092955c2017-02-06 09:13:09 -08002036 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002037 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Paul Stewart092955c2017-02-06 09:13:09 -08002038 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002039 if (akm & WPA_KEY_MGMT_FILS_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08002040 return RSN_AUTH_KEY_MGMT_FILS_SHA256;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002041 if (akm & WPA_KEY_MGMT_FILS_SHA384)
Paul Stewart092955c2017-02-06 09:13:09 -08002042 return RSN_AUTH_KEY_MGMT_FILS_SHA384;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002043 if (akm & WPA_KEY_MGMT_FT_FILS_SHA256)
Paul Stewart092955c2017-02-06 09:13:09 -08002044 return RSN_AUTH_KEY_MGMT_FT_FILS_SHA256;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002045 if (akm & WPA_KEY_MGMT_FT_FILS_SHA384)
Paul Stewart092955c2017-02-06 09:13:09 -08002046 return RSN_AUTH_KEY_MGMT_FT_FILS_SHA384;
Dmitry Shmidt03658832014-08-13 11:03:49 -07002047 return 0;
2048}
2049
2050
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002051int wpa_compare_rsn_ie(int ft_initial_assoc,
2052 const u8 *ie1, size_t ie1len,
2053 const u8 *ie2, size_t ie2len)
2054{
2055 if (ie1 == NULL || ie2 == NULL)
2056 return -1;
2057
2058 if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
2059 return 0; /* identical IEs */
2060
2061#ifdef CONFIG_IEEE80211R
2062 if (ft_initial_assoc) {
2063 struct wpa_ie_data ie1d, ie2d;
2064 /*
2065 * The PMKID-List in RSN IE is different between Beacon/Probe
2066 * Response/(Re)Association Request frames and EAPOL-Key
2067 * messages in FT initial mobility domain association. Allow
2068 * for this, but verify that other parts of the RSN IEs are
2069 * identical.
2070 */
2071 if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
2072 wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
2073 return -1;
2074 if (ie1d.proto == ie2d.proto &&
2075 ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
2076 ie1d.group_cipher == ie2d.group_cipher &&
2077 ie1d.key_mgmt == ie2d.key_mgmt &&
2078 ie1d.capabilities == ie2d.capabilities &&
2079 ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
2080 return 0;
2081 }
2082#endif /* CONFIG_IEEE80211R */
2083
2084 return -1;
2085}
2086
2087
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002088#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002089int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002090{
2091 u8 *start, *end, *rpos, *rend;
2092 int added = 0;
2093
2094 start = ies;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002095 end = ies + *ies_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002096
2097 while (start < end) {
2098 if (*start == WLAN_EID_RSN)
2099 break;
2100 start += 2 + start[1];
2101 }
2102 if (start >= end) {
2103 wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
2104 "IEs data");
2105 return -1;
2106 }
2107 wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
2108 start, 2 + start[1]);
2109
2110 /* Find start of PMKID-Count */
2111 rpos = start + 2;
2112 rend = rpos + start[1];
2113
2114 /* Skip Version and Group Data Cipher Suite */
2115 rpos += 2 + 4;
2116 /* Skip Pairwise Cipher Suite Count and List */
2117 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
2118 /* Skip AKM Suite Count and List */
2119 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
2120
2121 if (rpos == rend) {
2122 /* Add RSN Capabilities */
2123 os_memmove(rpos + 2, rpos, end - rpos);
2124 *rpos++ = 0;
2125 *rpos++ = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002126 added += 2;
2127 start[1] += 2;
2128 rend = rpos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002129 } else {
2130 /* Skip RSN Capabilities */
2131 rpos += 2;
2132 if (rpos > rend) {
2133 wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
2134 "IEs data");
2135 return -1;
2136 }
2137 }
2138
2139 if (rpos == rend) {
2140 /* No PMKID-Count field included; add it */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002141 os_memmove(rpos + 2 + PMKID_LEN, rpos, end + added - rpos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002142 WPA_PUT_LE16(rpos, 1);
2143 rpos += 2;
2144 os_memcpy(rpos, pmkid, PMKID_LEN);
2145 added += 2 + PMKID_LEN;
2146 start[1] += 2 + PMKID_LEN;
2147 } else {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002148 u16 num_pmkid;
2149
2150 if (rend - rpos < 2)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002151 return -1;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002152 num_pmkid = WPA_GET_LE16(rpos);
2153 /* PMKID-Count was included; use it */
2154 if (num_pmkid != 0) {
2155 u8 *after;
2156
2157 if (num_pmkid * PMKID_LEN > rend - rpos - 2)
2158 return -1;
2159 /*
2160 * PMKID may have been included in RSN IE in
2161 * (Re)Association Request frame, so remove the old
2162 * PMKID(s) first before adding the new one.
2163 */
2164 wpa_printf(MSG_DEBUG,
2165 "FT: Remove %u old PMKID(s) from RSN IE",
2166 num_pmkid);
2167 after = rpos + 2 + num_pmkid * PMKID_LEN;
2168 os_memmove(rpos + 2, after, rend - after);
2169 start[1] -= num_pmkid * PMKID_LEN;
2170 added -= num_pmkid * PMKID_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002171 }
2172 WPA_PUT_LE16(rpos, 1);
2173 rpos += 2;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002174 os_memmove(rpos + PMKID_LEN, rpos, end + added - rpos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002175 os_memcpy(rpos, pmkid, PMKID_LEN);
2176 added += PMKID_LEN;
2177 start[1] += PMKID_LEN;
2178 }
2179
2180 wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
2181 "(PMKID inserted)", start, 2 + start[1]);
2182
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002183 *ies_len += added;
2184
2185 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002186}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002187#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002188
2189
2190int wpa_cipher_key_len(int cipher)
2191{
2192 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002193 case WPA_CIPHER_CCMP_256:
2194 case WPA_CIPHER_GCMP_256:
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002195 case WPA_CIPHER_BIP_GMAC_256:
2196 case WPA_CIPHER_BIP_CMAC_256:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002197 return 32;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002198 case WPA_CIPHER_CCMP:
2199 case WPA_CIPHER_GCMP:
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002200 case WPA_CIPHER_AES_128_CMAC:
2201 case WPA_CIPHER_BIP_GMAC_128:
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002202 return 16;
2203 case WPA_CIPHER_TKIP:
2204 return 32;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002205 }
2206
2207 return 0;
2208}
2209
2210
2211int wpa_cipher_rsc_len(int cipher)
2212{
2213 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002214 case WPA_CIPHER_CCMP_256:
2215 case WPA_CIPHER_GCMP_256:
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002216 case WPA_CIPHER_CCMP:
2217 case WPA_CIPHER_GCMP:
2218 case WPA_CIPHER_TKIP:
2219 return 6;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002220 }
2221
2222 return 0;
2223}
2224
2225
Dmitry Shmidt29333592017-01-09 12:27:11 -08002226enum wpa_alg wpa_cipher_to_alg(int cipher)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002227{
2228 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002229 case WPA_CIPHER_CCMP_256:
2230 return WPA_ALG_CCMP_256;
2231 case WPA_CIPHER_GCMP_256:
2232 return WPA_ALG_GCMP_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002233 case WPA_CIPHER_CCMP:
2234 return WPA_ALG_CCMP;
2235 case WPA_CIPHER_GCMP:
2236 return WPA_ALG_GCMP;
2237 case WPA_CIPHER_TKIP:
2238 return WPA_ALG_TKIP;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002239 case WPA_CIPHER_AES_128_CMAC:
2240 return WPA_ALG_IGTK;
2241 case WPA_CIPHER_BIP_GMAC_128:
2242 return WPA_ALG_BIP_GMAC_128;
2243 case WPA_CIPHER_BIP_GMAC_256:
2244 return WPA_ALG_BIP_GMAC_256;
2245 case WPA_CIPHER_BIP_CMAC_256:
2246 return WPA_ALG_BIP_CMAC_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002247 }
2248 return WPA_ALG_NONE;
2249}
2250
2251
2252int wpa_cipher_valid_pairwise(int cipher)
2253{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002254 return cipher == WPA_CIPHER_CCMP_256 ||
2255 cipher == WPA_CIPHER_GCMP_256 ||
2256 cipher == WPA_CIPHER_CCMP ||
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002257 cipher == WPA_CIPHER_GCMP ||
2258 cipher == WPA_CIPHER_TKIP;
2259}
2260
2261
2262u32 wpa_cipher_to_suite(int proto, int cipher)
2263{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002264 if (cipher & WPA_CIPHER_CCMP_256)
2265 return RSN_CIPHER_SUITE_CCMP_256;
2266 if (cipher & WPA_CIPHER_GCMP_256)
2267 return RSN_CIPHER_SUITE_GCMP_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002268 if (cipher & WPA_CIPHER_CCMP)
2269 return (proto == WPA_PROTO_RSN ?
2270 RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
2271 if (cipher & WPA_CIPHER_GCMP)
2272 return RSN_CIPHER_SUITE_GCMP;
2273 if (cipher & WPA_CIPHER_TKIP)
2274 return (proto == WPA_PROTO_RSN ?
2275 RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002276 if (cipher & WPA_CIPHER_NONE)
2277 return (proto == WPA_PROTO_RSN ?
2278 RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002279 if (cipher & WPA_CIPHER_GTK_NOT_USED)
2280 return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002281 if (cipher & WPA_CIPHER_AES_128_CMAC)
2282 return RSN_CIPHER_SUITE_AES_128_CMAC;
2283 if (cipher & WPA_CIPHER_BIP_GMAC_128)
2284 return RSN_CIPHER_SUITE_BIP_GMAC_128;
2285 if (cipher & WPA_CIPHER_BIP_GMAC_256)
2286 return RSN_CIPHER_SUITE_BIP_GMAC_256;
2287 if (cipher & WPA_CIPHER_BIP_CMAC_256)
2288 return RSN_CIPHER_SUITE_BIP_CMAC_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002289 return 0;
2290}
2291
2292
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002293int rsn_cipher_put_suites(u8 *start, int ciphers)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002294{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002295 u8 *pos = start;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002296
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002297 if (ciphers & WPA_CIPHER_CCMP_256) {
2298 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256);
2299 pos += RSN_SELECTOR_LEN;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002300 }
2301 if (ciphers & WPA_CIPHER_GCMP_256) {
2302 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256);
2303 pos += RSN_SELECTOR_LEN;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002304 }
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002305 if (ciphers & WPA_CIPHER_CCMP) {
2306 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
2307 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002308 }
2309 if (ciphers & WPA_CIPHER_GCMP) {
2310 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP);
2311 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002312 }
2313 if (ciphers & WPA_CIPHER_TKIP) {
2314 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
2315 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002316 }
2317 if (ciphers & WPA_CIPHER_NONE) {
2318 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
2319 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002320 }
2321
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002322 return (pos - start) / RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002323}
2324
2325
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002326int wpa_cipher_put_suites(u8 *start, int ciphers)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002327{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002328 u8 *pos = start;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002329
2330 if (ciphers & WPA_CIPHER_CCMP) {
2331 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
2332 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002333 }
2334 if (ciphers & WPA_CIPHER_TKIP) {
2335 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
2336 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002337 }
2338 if (ciphers & WPA_CIPHER_NONE) {
2339 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
2340 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002341 }
2342
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08002343 return (pos - start) / RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002344}
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002345
2346
2347int wpa_pick_pairwise_cipher(int ciphers, int none_allowed)
2348{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002349 if (ciphers & WPA_CIPHER_CCMP_256)
2350 return WPA_CIPHER_CCMP_256;
2351 if (ciphers & WPA_CIPHER_GCMP_256)
2352 return WPA_CIPHER_GCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002353 if (ciphers & WPA_CIPHER_CCMP)
2354 return WPA_CIPHER_CCMP;
2355 if (ciphers & WPA_CIPHER_GCMP)
2356 return WPA_CIPHER_GCMP;
2357 if (ciphers & WPA_CIPHER_TKIP)
2358 return WPA_CIPHER_TKIP;
2359 if (none_allowed && (ciphers & WPA_CIPHER_NONE))
2360 return WPA_CIPHER_NONE;
2361 return -1;
2362}
2363
2364
2365int wpa_pick_group_cipher(int ciphers)
2366{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002367 if (ciphers & WPA_CIPHER_CCMP_256)
2368 return WPA_CIPHER_CCMP_256;
2369 if (ciphers & WPA_CIPHER_GCMP_256)
2370 return WPA_CIPHER_GCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002371 if (ciphers & WPA_CIPHER_CCMP)
2372 return WPA_CIPHER_CCMP;
2373 if (ciphers & WPA_CIPHER_GCMP)
2374 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002375 if (ciphers & WPA_CIPHER_GTK_NOT_USED)
2376 return WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002377 if (ciphers & WPA_CIPHER_TKIP)
2378 return WPA_CIPHER_TKIP;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002379 return -1;
2380}
2381
2382
2383int wpa_parse_cipher(const char *value)
2384{
2385 int val = 0, last;
2386 char *start, *end, *buf;
2387
2388 buf = os_strdup(value);
2389 if (buf == NULL)
2390 return -1;
2391 start = buf;
2392
2393 while (*start != '\0') {
2394 while (*start == ' ' || *start == '\t')
2395 start++;
2396 if (*start == '\0')
2397 break;
2398 end = start;
2399 while (*end != ' ' && *end != '\t' && *end != '\0')
2400 end++;
2401 last = *end == '\0';
2402 *end = '\0';
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002403 if (os_strcmp(start, "CCMP-256") == 0)
2404 val |= WPA_CIPHER_CCMP_256;
2405 else if (os_strcmp(start, "GCMP-256") == 0)
2406 val |= WPA_CIPHER_GCMP_256;
2407 else if (os_strcmp(start, "CCMP") == 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002408 val |= WPA_CIPHER_CCMP;
2409 else if (os_strcmp(start, "GCMP") == 0)
2410 val |= WPA_CIPHER_GCMP;
2411 else if (os_strcmp(start, "TKIP") == 0)
2412 val |= WPA_CIPHER_TKIP;
2413 else if (os_strcmp(start, "WEP104") == 0)
2414 val |= WPA_CIPHER_WEP104;
2415 else if (os_strcmp(start, "WEP40") == 0)
2416 val |= WPA_CIPHER_WEP40;
2417 else if (os_strcmp(start, "NONE") == 0)
2418 val |= WPA_CIPHER_NONE;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002419 else if (os_strcmp(start, "GTK_NOT_USED") == 0)
2420 val |= WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002421 else if (os_strcmp(start, "AES-128-CMAC") == 0)
2422 val |= WPA_CIPHER_AES_128_CMAC;
2423 else if (os_strcmp(start, "BIP-GMAC-128") == 0)
2424 val |= WPA_CIPHER_BIP_GMAC_128;
2425 else if (os_strcmp(start, "BIP-GMAC-256") == 0)
2426 val |= WPA_CIPHER_BIP_GMAC_256;
2427 else if (os_strcmp(start, "BIP-CMAC-256") == 0)
2428 val |= WPA_CIPHER_BIP_CMAC_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002429 else {
2430 os_free(buf);
2431 return -1;
2432 }
2433
2434 if (last)
2435 break;
2436 start = end + 1;
2437 }
2438 os_free(buf);
2439
2440 return val;
2441}
2442
2443
2444int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
2445{
2446 char *pos = start;
2447 int ret;
2448
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002449 if (ciphers & WPA_CIPHER_CCMP_256) {
2450 ret = os_snprintf(pos, end - pos, "%sCCMP-256",
2451 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002452 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002453 return -1;
2454 pos += ret;
2455 }
2456 if (ciphers & WPA_CIPHER_GCMP_256) {
2457 ret = os_snprintf(pos, end - pos, "%sGCMP-256",
2458 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002459 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002460 return -1;
2461 pos += ret;
2462 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002463 if (ciphers & WPA_CIPHER_CCMP) {
2464 ret = os_snprintf(pos, end - pos, "%sCCMP",
2465 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002466 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002467 return -1;
2468 pos += ret;
2469 }
2470 if (ciphers & WPA_CIPHER_GCMP) {
2471 ret = os_snprintf(pos, end - pos, "%sGCMP",
2472 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002473 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002474 return -1;
2475 pos += ret;
2476 }
2477 if (ciphers & WPA_CIPHER_TKIP) {
2478 ret = os_snprintf(pos, end - pos, "%sTKIP",
2479 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002480 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002481 return -1;
2482 pos += ret;
2483 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002484 if (ciphers & WPA_CIPHER_AES_128_CMAC) {
2485 ret = os_snprintf(pos, end - pos, "%sAES-128-CMAC",
2486 pos == start ? "" : delim);
2487 if (os_snprintf_error(end - pos, ret))
2488 return -1;
2489 pos += ret;
2490 }
2491 if (ciphers & WPA_CIPHER_BIP_GMAC_128) {
2492 ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-128",
2493 pos == start ? "" : delim);
2494 if (os_snprintf_error(end - pos, ret))
2495 return -1;
2496 pos += ret;
2497 }
2498 if (ciphers & WPA_CIPHER_BIP_GMAC_256) {
2499 ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-256",
2500 pos == start ? "" : delim);
2501 if (os_snprintf_error(end - pos, ret))
2502 return -1;
2503 pos += ret;
2504 }
2505 if (ciphers & WPA_CIPHER_BIP_CMAC_256) {
2506 ret = os_snprintf(pos, end - pos, "%sBIP-CMAC-256",
2507 pos == start ? "" : delim);
2508 if (os_snprintf_error(end - pos, ret))
2509 return -1;
2510 pos += ret;
2511 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002512 if (ciphers & WPA_CIPHER_NONE) {
2513 ret = os_snprintf(pos, end - pos, "%sNONE",
2514 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002515 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002516 return -1;
2517 pos += ret;
2518 }
2519
2520 return pos - start;
2521}
2522
2523
2524int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
2525{
2526 int pairwise = 0;
2527
2528 /* Select group cipher based on the enabled pairwise cipher suites */
2529 if (wpa & 1)
2530 pairwise |= wpa_pairwise;
2531 if (wpa & 2)
2532 pairwise |= rsn_pairwise;
2533
2534 if (pairwise & WPA_CIPHER_TKIP)
2535 return WPA_CIPHER_TKIP;
2536 if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP)
2537 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002538 if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP |
2539 WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256)
2540 return WPA_CIPHER_GCMP_256;
2541 if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
2542 WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256)
2543 return WPA_CIPHER_CCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002544 return WPA_CIPHER_CCMP;
2545}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002546
2547
2548#ifdef CONFIG_FILS
Dmitry Shmidt29333592017-01-09 12:27:11 -08002549int fils_domain_name_hash(const char *domain, u8 *hash)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002550{
2551 char buf[255], *wpos = buf;
2552 const char *pos = domain;
2553 size_t len;
Dmitry Shmidt29333592017-01-09 12:27:11 -08002554 const u8 *addr[1];
2555 u8 mac[SHA256_MAC_LEN];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002556
2557 for (len = 0; len < sizeof(buf) && *pos; len++) {
2558 if (isalpha(*pos) && isupper(*pos))
2559 *wpos++ = tolower(*pos);
2560 else
2561 *wpos++ = *pos;
2562 pos++;
2563 }
2564
Dmitry Shmidt29333592017-01-09 12:27:11 -08002565 addr[0] = (const u8 *) buf;
2566 if (sha256_vector(1, addr, &len, mac) < 0)
2567 return -1;
2568 os_memcpy(hash, mac, 2);
2569 return 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002570}
2571#endif /* CONFIG_FILS */