blob: 892eece717c6949307f87d3253c1f336b2d8be53 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - WPA state machine and EAPOL-Key processing
Roshan Pius3a1667e2018-07-03 15:17:14 -07003 * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004 * Copyright(c) 2015 Intel Deutschland GmbH
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008 */
9
10#include "includes.h"
11
12#include "common.h"
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080013#include "crypto/aes.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014#include "crypto/aes_wrap.h"
15#include "crypto/crypto.h"
16#include "crypto/random.h"
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080017#include "crypto/aes_siv.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070018#include "crypto/sha256.h"
19#include "crypto/sha384.h"
20#include "crypto/sha512.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "common/ieee802_11_defs.h"
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080022#include "common/ieee802_11_common.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080023#include "common/ocv.h"
Paul Stewart092955c2017-02-06 09:13:09 -080024#include "eap_common/eap_defs.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "eapol_supp/eapol_supp_sm.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080026#include "drivers/driver.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070027#include "wpa.h"
28#include "eloop.h"
29#include "preauth.h"
30#include "pmksa_cache.h"
31#include "wpa_i.h"
32#include "wpa_ie.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070033
34
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080035static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
36
37
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070038/**
39 * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
40 * @sm: Pointer to WPA state machine data from wpa_sm_init()
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080041 * @ptk: PTK for Key Confirmation/Encryption Key
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042 * @ver: Version field from Key Info
43 * @dest: Destination address for the frame
44 * @proto: Ethertype (usually ETH_P_EAPOL)
45 * @msg: EAPOL-Key message
46 * @msg_len: Length of message
47 * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080048 * Returns: >= 0 on success, < 0 on failure
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080050int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080051 int ver, const u8 *dest, u16 proto,
52 u8 *msg, size_t msg_len, u8 *key_mic)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070053{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080054 int ret = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070055 size_t mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -080056
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070057 wpa_printf(MSG_DEBUG, "WPA: Send EAPOL-Key frame to " MACSTR
58 " ver=%d mic_len=%d key_mgmt=0x%x",
59 MAC2STR(dest), ver, (int) mic_len, sm->key_mgmt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070060 if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
61 /*
62 * Association event was not yet received; try to fetch
63 * BSSID from the driver.
64 */
65 if (wpa_sm_get_bssid(sm, sm->bssid) < 0) {
66 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
67 "WPA: Failed to read BSSID for "
68 "EAPOL-Key destination address");
69 } else {
70 dest = sm->bssid;
71 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
72 "WPA: Use BSSID (" MACSTR
73 ") as the destination for EAPOL-Key",
74 MAC2STR(dest));
75 }
76 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080077
78 if (mic_len) {
79 if (key_mic && (!ptk || !ptk->kck_len))
80 goto out;
81
82 if (key_mic &&
83 wpa_eapol_key_mic(ptk->kck, ptk->kck_len, sm->key_mgmt, ver,
84 msg, msg_len, key_mic)) {
85 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
86 "WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC",
87 ver, sm->key_mgmt);
88 goto out;
89 }
Dmitry Shmidt29333592017-01-09 12:27:11 -080090 if (ptk)
91 wpa_hexdump_key(MSG_DEBUG, "WPA: KCK",
92 ptk->kck, ptk->kck_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080093 wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC",
94 key_mic, mic_len);
95 } else {
96#ifdef CONFIG_FILS
97 /* AEAD cipher - Key MIC field not used */
98 struct ieee802_1x_hdr *s_hdr, *hdr;
99 struct wpa_eapol_key *s_key, *key;
100 u8 *buf, *s_key_data, *key_data;
101 size_t buf_len = msg_len + AES_BLOCK_SIZE;
102 size_t key_data_len;
103 u16 eapol_len;
104 const u8 *aad[1];
105 size_t aad_len[1];
106
107 if (!ptk || !ptk->kek_len)
108 goto out;
109
110 key_data_len = msg_len - sizeof(struct ieee802_1x_hdr) -
111 sizeof(struct wpa_eapol_key) - 2;
112
113 buf = os_malloc(buf_len);
114 if (!buf)
115 goto out;
116
117 os_memcpy(buf, msg, msg_len);
118 hdr = (struct ieee802_1x_hdr *) buf;
119 key = (struct wpa_eapol_key *) (hdr + 1);
120 key_data = ((u8 *) (key + 1)) + 2;
121
122 /* Update EAPOL header to include AES-SIV overhead */
123 eapol_len = be_to_host16(hdr->length);
124 eapol_len += AES_BLOCK_SIZE;
125 hdr->length = host_to_be16(eapol_len);
126
127 /* Update Key Data Length field to include AES-SIV overhead */
128 WPA_PUT_BE16((u8 *) (key + 1), AES_BLOCK_SIZE + key_data_len);
129
130 s_hdr = (struct ieee802_1x_hdr *) msg;
131 s_key = (struct wpa_eapol_key *) (s_hdr + 1);
132 s_key_data = ((u8 *) (s_key + 1)) + 2;
133
134 wpa_hexdump_key(MSG_DEBUG, "WPA: Plaintext Key Data",
135 s_key_data, key_data_len);
136
137 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len);
138 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
139 * to Key Data (exclusive). */
140 aad[0] = buf;
141 aad_len[0] = key_data - buf;
142 if (aes_siv_encrypt(ptk->kek, ptk->kek_len,
143 s_key_data, key_data_len,
144 1, aad, aad_len, key_data) < 0) {
145 os_free(buf);
146 goto out;
147 }
148
149 wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
150 key_data, AES_BLOCK_SIZE + key_data_len);
151
152 os_free(msg);
153 msg = buf;
154 msg_len = buf_len;
155#else /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700156 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800157#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700158 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800159
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700160 wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800161 ret = wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700162 eapol_sm_notify_tx_eapol_key(sm->eapol);
163out:
164 os_free(msg);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800165 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700166}
167
168
169/**
170 * wpa_sm_key_request - Send EAPOL-Key Request
171 * @sm: Pointer to WPA state machine data from wpa_sm_init()
172 * @error: Indicate whether this is an Michael MIC error report
173 * @pairwise: 1 = error report for pairwise packet, 0 = for group packet
174 *
175 * Send an EAPOL-Key Request to the current authenticator. This function is
176 * used to request rekeying and it is usually called when a local Michael MIC
177 * failure is detected.
178 */
179void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
180{
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800181 size_t mic_len, hdrlen, rlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700182 struct wpa_eapol_key *reply;
183 int key_info, ver;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800184 u8 bssid[ETH_ALEN], *rbuf, *key_mic, *mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700185
Roshan Pius3a1667e2018-07-03 15:17:14 -0700186 if (wpa_use_akm_defined(sm->key_mgmt))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800187 ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
188 else if (wpa_key_mgmt_ft(sm->key_mgmt) ||
189 wpa_key_mgmt_sha256(sm->key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700190 ver = WPA_KEY_INFO_TYPE_AES_128_CMAC;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700191 else if (sm->pairwise_cipher != WPA_CIPHER_TKIP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700192 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
193 else
194 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
195
196 if (wpa_sm_get_bssid(sm, bssid) < 0) {
197 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
198 "Failed to read BSSID for EAPOL-Key request");
199 return;
200 }
201
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700202 mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800203 hdrlen = sizeof(*reply) + mic_len + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700204 rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800205 hdrlen, &rlen, (void *) &reply);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700206 if (rbuf == NULL)
207 return;
208
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800209 reply->type = (sm->proto == WPA_PROTO_RSN ||
210 sm->proto == WPA_PROTO_OSEN) ?
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700211 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
212 key_info = WPA_KEY_INFO_REQUEST | ver;
213 if (sm->ptk_set)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800214 key_info |= WPA_KEY_INFO_SECURE;
215 if (sm->ptk_set && mic_len)
216 key_info |= WPA_KEY_INFO_MIC;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700217 if (error)
218 key_info |= WPA_KEY_INFO_ERROR;
219 if (pairwise)
220 key_info |= WPA_KEY_INFO_KEY_TYPE;
221 WPA_PUT_BE16(reply->key_info, key_info);
222 WPA_PUT_BE16(reply->key_length, 0);
223 os_memcpy(reply->replay_counter, sm->request_counter,
224 WPA_REPLAY_COUNTER_LEN);
225 inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
226
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800227 mic = (u8 *) (reply + 1);
228 WPA_PUT_BE16(mic + mic_len, 0);
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800229 if (!(key_info & WPA_KEY_INFO_MIC))
230 key_mic = NULL;
231 else
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800232 key_mic = mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700233
234 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
235 "WPA: Sending EAPOL-Key Request (error=%d "
236 "pairwise=%d ptk_set=%d len=%lu)",
237 error, pairwise, sm->ptk_set, (unsigned long) rlen);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800238 wpa_eapol_key_send(sm, &sm->ptk, ver, bssid, ETH_P_EAPOL, rbuf, rlen,
239 key_mic);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700240}
241
242
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800243static void wpa_supplicant_key_mgmt_set_pmk(struct wpa_sm *sm)
244{
245#ifdef CONFIG_IEEE80211R
246 if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
247 if (wpa_sm_key_mgmt_set_pmk(sm, sm->xxkey, sm->xxkey_len))
248 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
249 "RSN: Cannot set low order 256 bits of MSK for key management offload");
250 } else {
251#endif /* CONFIG_IEEE80211R */
252 if (wpa_sm_key_mgmt_set_pmk(sm, sm->pmk, sm->pmk_len))
253 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
254 "RSN: Cannot set PMK for key management offload");
255#ifdef CONFIG_IEEE80211R
256 }
257#endif /* CONFIG_IEEE80211R */
258}
259
260
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700261static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
262 const unsigned char *src_addr,
263 const u8 *pmkid)
264{
265 int abort_cached = 0;
266
267 if (pmkid && !sm->cur_pmksa) {
268 /* When using drivers that generate RSN IE, wpa_supplicant may
269 * not have enough time to get the association information
270 * event before receiving this 1/4 message, so try to find a
271 * matching PMKSA cache entry here. */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800272 sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700273 NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700274 if (sm->cur_pmksa) {
275 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
276 "RSN: found matching PMKID from PMKSA cache");
277 } else {
278 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
279 "RSN: no matching PMKID found");
280 abort_cached = 1;
281 }
282 }
283
284 if (pmkid && sm->cur_pmksa &&
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700285 os_memcmp_const(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700286 wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);
287 wpa_sm_set_pmk_from_pmksa(sm);
288 wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",
289 sm->pmk, sm->pmk_len);
290 eapol_sm_notify_cached(sm->eapol);
291#ifdef CONFIG_IEEE80211R
292 sm->xxkey_len = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700293#ifdef CONFIG_SAE
294 if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE &&
295 sm->pmk_len == PMK_LEN) {
296 /* Need to allow FT key derivation to proceed with
297 * PMK from SAE being used as the XXKey in cases where
298 * the PMKID in msg 1/4 matches the PMKSA entry that was
299 * just added based on SAE authentication for the
300 * initial mobility domain association. */
301 os_memcpy(sm->xxkey, sm->pmk, sm->pmk_len);
302 sm->xxkey_len = sm->pmk_len;
303 }
304#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700305#endif /* CONFIG_IEEE80211R */
306 } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) {
307 int res, pmk_len;
Hai Shalom81f62d82019-07-22 12:10:00 -0700308#ifdef CONFIG_IEEE80211R
309 u8 buf[2 * PMK_LEN];
310#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800311
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800312 if (wpa_key_mgmt_sha384(sm->key_mgmt))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800313 pmk_len = PMK_LEN_SUITE_B_192;
314 else
315 pmk_len = PMK_LEN;
316 res = eapol_sm_get_key(sm->eapol, sm->pmk, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700317 if (res) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800318 if (pmk_len == PMK_LEN) {
319 /*
320 * EAP-LEAP is an exception from other EAP
321 * methods: it uses only 16-byte PMK.
322 */
323 res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
324 pmk_len = 16;
325 }
Hai Shalomf1c97642019-07-19 23:42:07 +0000326 }
Hai Shalom81f62d82019-07-22 12:10:00 -0700327#ifdef CONFIG_IEEE80211R
328 if (res == 0 &&
329 eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0) {
330 if (wpa_key_mgmt_sha384(sm->key_mgmt)) {
331 os_memcpy(sm->xxkey, buf, SHA384_MAC_LEN);
332 sm->xxkey_len = SHA384_MAC_LEN;
333 } else {
334 os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN);
335 sm->xxkey_len = PMK_LEN;
336 }
337 forced_memzero(buf, sizeof(buf));
338 if (sm->proto == WPA_PROTO_RSN &&
339 wpa_key_mgmt_ft(sm->key_mgmt)) {
340 struct rsn_pmksa_cache_entry *sa = NULL;
341 const u8 *fils_cache_id = NULL;
342
343#ifdef CONFIG_FILS
344 if (sm->fils_cache_id_set)
345 fils_cache_id = sm->fils_cache_id;
346#endif /* CONFIG_FILS */
347 wpa_hexdump_key(MSG_DEBUG,
348 "FT: Cache XXKey/MPMK",
349 sm->xxkey, sm->xxkey_len);
350 sa = pmksa_cache_add(sm->pmksa,
351 sm->xxkey, sm->xxkey_len,
352 NULL, NULL, 0,
353 src_addr, sm->own_addr,
354 sm->network_ctx,
355 sm->key_mgmt,
356 fils_cache_id);
357 if (!sm->cur_pmksa)
358 sm->cur_pmksa = sa;
359 }
360 }
361#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700362 if (res == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700363 struct rsn_pmksa_cache_entry *sa = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700364 const u8 *fils_cache_id = NULL;
365
366#ifdef CONFIG_FILS
367 if (sm->fils_cache_id_set)
368 fils_cache_id = sm->fils_cache_id;
369#endif /* CONFIG_FILS */
370
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700371 wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "
372 "machines", sm->pmk, pmk_len);
373 sm->pmk_len = pmk_len;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800374 wpa_supplicant_key_mgmt_set_pmk(sm);
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700375 if (sm->proto == WPA_PROTO_RSN &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800376 !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700377 !wpa_key_mgmt_ft(sm->key_mgmt)) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700378 sa = pmksa_cache_add(sm->pmksa,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800379 sm->pmk, pmk_len, NULL,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800380 NULL, 0,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700381 src_addr, sm->own_addr,
382 sm->network_ctx,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700383 sm->key_mgmt,
384 fils_cache_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700385 }
386 if (!sm->cur_pmksa && pmkid &&
Roshan Pius3a1667e2018-07-03 15:17:14 -0700387 pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL,
388 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700389 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
390 "RSN: the new PMK matches with the "
391 "PMKID");
392 abort_cached = 0;
Jouni Malinen6ec30382015-07-08 20:48:18 +0300393 } else if (sa && !sm->cur_pmksa && pmkid) {
394 /*
395 * It looks like the authentication server
396 * derived mismatching MSK. This should not
397 * really happen, but bugs happen.. There is not
398 * much we can do here without knowing what
399 * exactly caused the server to misbehave.
400 */
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -0800401 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
Jouni Malinen6ec30382015-07-08 20:48:18 +0300402 "RSN: PMKID mismatch - authentication server may have derived different MSK?!");
403 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700404 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700405
406 if (!sm->cur_pmksa)
407 sm->cur_pmksa = sa;
Hai Shalom81f62d82019-07-22 12:10:00 -0700408#ifdef CONFIG_IEEE80211R
409 } else if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->ft_protocol) {
410 wpa_printf(MSG_DEBUG,
411 "FT: Continue 4-way handshake without PMK/PMKID for association using FT protocol");
412#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700413 } else {
414 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
415 "WPA: Failed to get master session key from "
416 "EAPOL state machines - key handshake "
417 "aborted");
418 if (sm->cur_pmksa) {
419 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
420 "RSN: Cancelled PMKSA caching "
421 "attempt");
422 sm->cur_pmksa = NULL;
423 abort_cached = 1;
424 } else if (!abort_cached) {
425 return -1;
426 }
427 }
428 }
429
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700430 if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800431 !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800432 !wpa_key_mgmt_ft(sm->key_mgmt) && sm->key_mgmt != WPA_KEY_MGMT_OSEN)
433 {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700434 /* Send EAPOL-Start to trigger full EAP authentication. */
435 u8 *buf;
436 size_t buflen;
437
438 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
439 "RSN: no PMKSA entry found - trigger "
440 "full EAP authentication");
441 buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,
442 NULL, 0, &buflen, NULL);
443 if (buf) {
444 wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
445 buf, buflen);
446 os_free(buf);
447 return -2;
448 }
449
450 return -1;
451 }
452
453 return 0;
454}
455
456
457/**
458 * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake
459 * @sm: Pointer to WPA state machine data from wpa_sm_init()
460 * @dst: Destination address for the frame
461 * @key: Pointer to the EAPOL-Key frame header
462 * @ver: Version bits from EAPOL-Key Key Info
463 * @nonce: Nonce value for the EAPOL-Key frame
464 * @wpa_ie: WPA/RSN IE
465 * @wpa_ie_len: Length of the WPA/RSN IE
466 * @ptk: PTK to use for keyed hash and encryption
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800467 * Returns: >= 0 on success, < 0 on failure
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700468 */
469int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
470 const struct wpa_eapol_key *key,
471 int ver, const u8 *nonce,
472 const u8 *wpa_ie, size_t wpa_ie_len,
473 struct wpa_ptk *ptk)
474{
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800475 size_t mic_len, hdrlen, rlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700476 struct wpa_eapol_key *reply;
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800477 u8 *rbuf, *key_mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700478 u8 *rsn_ie_buf = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800479 u16 key_info;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700480
481 if (wpa_ie == NULL) {
482 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - "
483 "cannot generate msg 2/4");
484 return -1;
485 }
486
487#ifdef CONFIG_IEEE80211R
488 if (wpa_key_mgmt_ft(sm->key_mgmt)) {
489 int res;
490
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800491 wpa_hexdump(MSG_DEBUG, "WPA: WPA IE before FT processing",
492 wpa_ie, wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700493 /*
494 * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and
495 * FTIE from (Re)Association Response.
496 */
497 rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN +
498 sm->assoc_resp_ies_len);
499 if (rsn_ie_buf == NULL)
500 return -1;
501 os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -0800502 res = wpa_insert_pmkid(rsn_ie_buf, &wpa_ie_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700503 sm->pmk_r1_name);
504 if (res < 0) {
505 os_free(rsn_ie_buf);
506 return -1;
507 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800508 wpa_hexdump(MSG_DEBUG,
509 "WPA: WPA IE after PMKID[PMKR1Name] addition into RSNE",
510 rsn_ie_buf, wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700511
512 if (sm->assoc_resp_ies) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800513 wpa_hexdump(MSG_DEBUG, "WPA: Add assoc_resp_ies",
514 sm->assoc_resp_ies,
515 sm->assoc_resp_ies_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700516 os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,
517 sm->assoc_resp_ies_len);
518 wpa_ie_len += sm->assoc_resp_ies_len;
519 }
520
521 wpa_ie = rsn_ie_buf;
522 }
523#endif /* CONFIG_IEEE80211R */
524
525 wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
526
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700527 mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800528 hdrlen = sizeof(*reply) + mic_len + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700529 rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800530 NULL, hdrlen + wpa_ie_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700531 &rlen, (void *) &reply);
532 if (rbuf == NULL) {
533 os_free(rsn_ie_buf);
534 return -1;
535 }
536
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800537 reply->type = (sm->proto == WPA_PROTO_RSN ||
538 sm->proto == WPA_PROTO_OSEN) ?
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700539 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800540 key_info = ver | WPA_KEY_INFO_KEY_TYPE;
541 if (mic_len)
542 key_info |= WPA_KEY_INFO_MIC;
543 else
544 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
545 WPA_PUT_BE16(reply->key_info, key_info);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800546 if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700547 WPA_PUT_BE16(reply->key_length, 0);
548 else
549 os_memcpy(reply->key_length, key->key_length, 2);
550 os_memcpy(reply->replay_counter, key->replay_counter,
551 WPA_REPLAY_COUNTER_LEN);
552 wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter,
553 WPA_REPLAY_COUNTER_LEN);
554
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800555 key_mic = (u8 *) (reply + 1);
556 WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len); /* Key Data Length */
557 os_memcpy(key_mic + mic_len + 2, wpa_ie, wpa_ie_len); /* Key Data */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700558 os_free(rsn_ie_buf);
559
560 os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
561
Roshan Pius5e7db942018-04-12 12:27:41 -0700562 wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Sending EAPOL-Key 2/4");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800563 return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
564 key_mic);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700565}
566
567
568static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800569 const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700570{
Hai Shalom021b0b52019-04-10 11:17:58 -0700571 const u8 *z = NULL;
572 size_t z_len = 0;
573
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700574#ifdef CONFIG_IEEE80211R
575 if (wpa_key_mgmt_ft(sm->key_mgmt))
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800576 return wpa_derive_ptk_ft(sm, src_addr, key, ptk);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577#endif /* CONFIG_IEEE80211R */
578
Hai Shalom021b0b52019-04-10 11:17:58 -0700579#ifdef CONFIG_DPP2
580 if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
581 z = wpabuf_head(sm->dpp_z);
582 z_len = wpabuf_len(sm->dpp_z);
583 }
584#endif /* CONFIG_DPP2 */
585
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800586 return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
587 sm->own_addr, sm->bssid, sm->snonce,
588 key->key_nonce, ptk, sm->key_mgmt,
Hai Shalom021b0b52019-04-10 11:17:58 -0700589 sm->pairwise_cipher, z, z_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700590}
591
592
593static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
594 const unsigned char *src_addr,
595 const struct wpa_eapol_key *key,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700596 u16 ver, const u8 *key_data,
597 size_t key_data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598{
599 struct wpa_eapol_ie_parse ie;
600 struct wpa_ptk *ptk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700601 int res;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800602 u8 *kde, *kde_buf = NULL;
603 size_t kde_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700604
605 if (wpa_sm_get_network_ctx(sm) == NULL) {
606 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info "
607 "found (msg 1 of 4)");
608 return;
609 }
610
611 wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
Roshan Pius5e7db942018-04-12 12:27:41 -0700612 wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: RX message 1 of 4-Way "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700613 "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
614
615 os_memset(&ie, 0, sizeof(ie));
616
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800617 if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700618 /* RSN: msg 1/4 should contain PMKID for the selected PMK */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700619 wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data",
620 key_data, key_data_len);
621 if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800622 goto failed;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700623 if (ie.pmkid) {
624 wpa_hexdump(MSG_DEBUG, "RSN: PMKID from "
625 "Authenticator", ie.pmkid, PMKID_LEN);
626 }
627 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700628
629 res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
630 if (res == -2) {
631 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to "
632 "msg 1/4 - requesting full EAP authentication");
633 return;
634 }
635 if (res)
636 goto failed;
637
638 if (sm->renew_snonce) {
639 if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
640 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
641 "WPA: Failed to get random data for SNonce");
642 goto failed;
643 }
644 sm->renew_snonce = 0;
645 wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
646 sm->snonce, WPA_NONCE_LEN);
647 }
648
649 /* Calculate PTK which will be stored as a temporary PTK until it has
650 * been verified when processing message 3/4. */
651 ptk = &sm->tptk;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700652 if (wpa_derive_ptk(sm, src_addr, key, ptk) < 0)
653 goto failed;
Dmitry Shmidt98660862014-03-11 17:26:21 -0700654 if (sm->pairwise_cipher == WPA_CIPHER_TKIP) {
Dmitry Shmidt61593f02014-04-21 16:27:35 -0700655 u8 buf[8];
Dmitry Shmidt98660862014-03-11 17:26:21 -0700656 /* Supplicant: swap tx/rx Mic keys */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800657 os_memcpy(buf, &ptk->tk[16], 8);
658 os_memcpy(&ptk->tk[16], &ptk->tk[24], 8);
659 os_memcpy(&ptk->tk[24], buf, 8);
Hai Shalom81f62d82019-07-22 12:10:00 -0700660 forced_memzero(buf, sizeof(buf));
Dmitry Shmidt98660862014-03-11 17:26:21 -0700661 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700662 sm->tptk_set = 1;
663
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800664 kde = sm->assoc_wpa_ie;
665 kde_len = sm->assoc_wpa_ie_len;
Hai Shalomc3565922019-10-28 11:58:20 -0700666 kde_buf = os_malloc(kde_len +
667 2 + RSN_SELECTOR_LEN + 3 +
668 sm->assoc_rsnxe_len +
669 2 + RSN_SELECTOR_LEN + 1);
670 if (!kde_buf)
671 goto failed;
672 os_memcpy(kde_buf, kde, kde_len);
673 kde = kde_buf;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800674
Hai Shalom74f70d42019-02-11 14:42:39 -0800675#ifdef CONFIG_OCV
676 if (wpa_sm_ocv_enabled(sm)) {
677 struct wpa_channel_info ci;
678 u8 *pos;
679
Hai Shalomc3565922019-10-28 11:58:20 -0700680 pos = kde + kde_len;
Hai Shalom74f70d42019-02-11 14:42:39 -0800681 if (wpa_sm_channel_info(sm, &ci) != 0) {
682 wpa_printf(MSG_WARNING,
683 "Failed to get channel info for OCI element in EAPOL-Key 2/4");
684 goto failed;
685 }
686
Hai Shalom74f70d42019-02-11 14:42:39 -0800687 if (ocv_insert_oci_kde(&ci, &pos) < 0)
688 goto failed;
689 kde_len = pos - kde;
690 }
691#endif /* CONFIG_OCV */
692
Hai Shalomc3565922019-10-28 11:58:20 -0700693 if (sm->assoc_rsnxe && sm->assoc_rsnxe_len) {
694 os_memcpy(kde + kde_len, sm->assoc_rsnxe, sm->assoc_rsnxe_len);
695 kde_len += sm->assoc_rsnxe_len;
696 }
697
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800698#ifdef CONFIG_P2P
699 if (sm->p2p) {
Hai Shalomc3565922019-10-28 11:58:20 -0700700 u8 *pos;
701
702 wpa_printf(MSG_DEBUG,
703 "P2P: Add IP Address Request KDE into EAPOL-Key 2/4");
704 pos = kde + kde_len;
705 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
706 *pos++ = RSN_SELECTOR_LEN + 1;
707 RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_IP_ADDR_REQ);
708 pos += RSN_SELECTOR_LEN;
709 *pos++ = 0x01;
710 kde_len = pos - kde;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800711 }
712#endif /* CONFIG_P2P */
713
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700714 if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800715 kde, kde_len, ptk) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716 goto failed;
717
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800718 os_free(kde_buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700719 os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
720 return;
721
722failed:
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800723 os_free(kde_buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700724 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
725}
726
727
728static void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx)
729{
730 struct wpa_sm *sm = eloop_ctx;
731 rsn_preauth_candidate_process(sm);
732}
733
734
735static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
736 const u8 *addr, int secure)
737{
738 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
739 "WPA: Key negotiation completed with "
740 MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr),
741 wpa_cipher_txt(sm->pairwise_cipher),
742 wpa_cipher_txt(sm->group_cipher));
743 wpa_sm_cancel_auth_timeout(sm);
744 wpa_sm_set_state(sm, WPA_COMPLETED);
745
746 if (secure) {
747 wpa_sm_mlme_setprotection(
748 sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX,
749 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
750 eapol_sm_notify_portValid(sm->eapol, TRUE);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700751 if (wpa_key_mgmt_wpa_psk(sm->key_mgmt) ||
752 sm->key_mgmt == WPA_KEY_MGMT_DPP ||
753 sm->key_mgmt == WPA_KEY_MGMT_OWE)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700754 eapol_sm_notify_eap_success(sm->eapol, TRUE);
755 /*
756 * Start preauthentication after a short wait to avoid a
757 * possible race condition between the data receive and key
758 * configuration after the 4-Way Handshake. This increases the
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800759 * likelihood of the first preauth EAPOL-Start frame getting to
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700760 * the target AP.
761 */
Hai Shalom74f70d42019-02-11 14:42:39 -0800762 if (!dl_list_empty(&sm->pmksa_candidates))
763 eloop_register_timeout(1, 0, wpa_sm_start_preauth,
764 sm, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700765 }
766
767 if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) {
768 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
769 "RSN: Authenticator accepted "
770 "opportunistic PMKSA entry - marking it valid");
771 sm->cur_pmksa->opportunistic = 0;
772 }
773
774#ifdef CONFIG_IEEE80211R
775 if (wpa_key_mgmt_ft(sm->key_mgmt)) {
776 /* Prepare for the next transition */
777 wpa_ft_prepare_auth_request(sm, NULL);
778 }
779#endif /* CONFIG_IEEE80211R */
780}
781
782
783static void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
784{
785 struct wpa_sm *sm = eloop_ctx;
786 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Request PTK rekeying");
787 wpa_sm_key_request(sm, 0, 1);
788}
789
790
791static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
792 const struct wpa_eapol_key *key)
793{
794 int keylen, rsclen;
795 enum wpa_alg alg;
796 const u8 *key_rsc;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800797
Mathy Vanhoefc66556c2017-09-29 04:22:51 +0200798 if (sm->ptk.installed) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800799 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
800 "WPA: Do not re-install same PTK to the driver");
801 return 0;
802 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700803
804 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
805 "WPA: Installing PTK to the driver");
806
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700807 if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700808 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Pairwise Cipher "
809 "Suite: NONE - do not use pairwise keys");
810 return 0;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700811 }
812
813 if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700814 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
815 "WPA: Unsupported pairwise cipher %d",
816 sm->pairwise_cipher);
817 return -1;
818 }
819
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700820 alg = wpa_cipher_to_alg(sm->pairwise_cipher);
821 keylen = wpa_cipher_key_len(sm->pairwise_cipher);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700822 if (keylen <= 0 || (unsigned int) keylen != sm->ptk.tk_len) {
823 wpa_printf(MSG_DEBUG, "WPA: TK length mismatch: %d != %lu",
824 keylen, (long unsigned int) sm->ptk.tk_len);
825 return -1;
826 }
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700827 rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
828
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800829 if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700830 key_rsc = null_rsc;
831 } else {
832 key_rsc = key->key_rsc;
833 wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen);
834 }
835
836 if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen,
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800837 sm->ptk.tk, keylen) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700838 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
839 "WPA: Failed to set PTK to the "
840 "driver (alg=%d keylen=%d bssid=" MACSTR ")",
841 alg, keylen, MAC2STR(sm->bssid));
842 return -1;
843 }
844
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800845 /* TK is not needed anymore in supplicant */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800846 os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700847 sm->ptk.tk_len = 0;
Mathy Vanhoefc66556c2017-09-29 04:22:51 +0200848 sm->ptk.installed = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800849
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700850 if (sm->wpa_ptk_rekey) {
851 eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
852 eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk,
853 sm, NULL);
854 }
855
856 return 0;
857}
858
859
860static int wpa_supplicant_check_group_cipher(struct wpa_sm *sm,
861 int group_cipher,
862 int keylen, int maxkeylen,
863 int *key_rsc_len,
864 enum wpa_alg *alg)
865{
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700866 int klen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700867
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700868 *alg = wpa_cipher_to_alg(group_cipher);
869 if (*alg == WPA_ALG_NONE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700870 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
871 "WPA: Unsupported Group Cipher %d",
872 group_cipher);
873 return -1;
874 }
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700875 *key_rsc_len = wpa_cipher_rsc_len(group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700876
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700877 klen = wpa_cipher_key_len(group_cipher);
878 if (keylen != klen || maxkeylen < klen) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700879 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
880 "WPA: Unsupported %s Group Cipher key length %d (%d)",
881 wpa_cipher_txt(group_cipher), keylen, maxkeylen);
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700882 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700883 }
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700884 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885}
886
887
888struct wpa_gtk_data {
889 enum wpa_alg alg;
890 int tx, key_rsc_len, keyidx;
891 u8 gtk[32];
892 int gtk_len;
893};
894
895
896static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
897 const struct wpa_gtk_data *gd,
Jouni Malinen58c0e962017-10-01 12:12:24 +0300898 const u8 *key_rsc, int wnm_sleep)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700899{
900 const u8 *_gtk = gd->gtk;
901 u8 gtk_buf[32];
902
Mathy Vanhoef10bfd642017-07-12 16:03:24 +0200903 /* Detect possible key reinstallation */
Jouni Malinen58c0e962017-10-01 12:12:24 +0300904 if ((sm->gtk.gtk_len == (size_t) gd->gtk_len &&
905 os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) ||
906 (sm->gtk_wnm_sleep.gtk_len == (size_t) gd->gtk_len &&
907 os_memcmp(sm->gtk_wnm_sleep.gtk, gd->gtk,
908 sm->gtk_wnm_sleep.gtk_len) == 0)) {
Mathy Vanhoef10bfd642017-07-12 16:03:24 +0200909 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
910 "WPA: Not reinstalling already in-use GTK to the driver (keyidx=%d tx=%d len=%d)",
911 gd->keyidx, gd->tx, gd->gtk_len);
912 return 0;
913 }
914
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700915 wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len);
916 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
917 "WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)",
918 gd->keyidx, gd->tx, gd->gtk_len);
919 wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len);
920 if (sm->group_cipher == WPA_CIPHER_TKIP) {
921 /* Swap Tx/Rx keys for Michael MIC */
922 os_memcpy(gtk_buf, gd->gtk, 16);
923 os_memcpy(gtk_buf + 16, gd->gtk + 24, 8);
924 os_memcpy(gtk_buf + 24, gd->gtk + 16, 8);
925 _gtk = gtk_buf;
926 }
927 if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
928 if (wpa_sm_set_key(sm, gd->alg, NULL,
929 gd->keyidx, 1, key_rsc, gd->key_rsc_len,
930 _gtk, gd->gtk_len) < 0) {
931 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
932 "WPA: Failed to set GTK to the driver "
933 "(Group only)");
Hai Shalom81f62d82019-07-22 12:10:00 -0700934 forced_memzero(gtk_buf, sizeof(gtk_buf));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700935 return -1;
936 }
937 } else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr,
938 gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len,
939 _gtk, gd->gtk_len) < 0) {
940 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
941 "WPA: Failed to set GTK to "
942 "the driver (alg=%d keylen=%d keyidx=%d)",
943 gd->alg, gd->gtk_len, gd->keyidx);
Hai Shalom81f62d82019-07-22 12:10:00 -0700944 forced_memzero(gtk_buf, sizeof(gtk_buf));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700945 return -1;
946 }
Hai Shalom81f62d82019-07-22 12:10:00 -0700947 forced_memzero(gtk_buf, sizeof(gtk_buf));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700948
Jouni Malinen58c0e962017-10-01 12:12:24 +0300949 if (wnm_sleep) {
950 sm->gtk_wnm_sleep.gtk_len = gd->gtk_len;
951 os_memcpy(sm->gtk_wnm_sleep.gtk, gd->gtk,
952 sm->gtk_wnm_sleep.gtk_len);
953 } else {
954 sm->gtk.gtk_len = gd->gtk_len;
955 os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len);
956 }
Mathy Vanhoef10bfd642017-07-12 16:03:24 +0200957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700958 return 0;
959}
960
961
962static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm,
963 int tx)
964{
965 if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) {
966 /* Ignore Tx bit for GTK if a pairwise key is used. One AP
967 * seemed to set this bit (incorrectly, since Tx is only when
968 * doing Group Key only APs) and without this workaround, the
969 * data connection does not work because wpa_supplicant
970 * configured non-zero keyidx to be used for unicast. */
971 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
972 "WPA: Tx bit set for GTK, but pairwise "
973 "keys are used - ignore Tx bit");
974 return 0;
975 }
976 return tx;
977}
978
979
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800980static int wpa_supplicant_rsc_relaxation(const struct wpa_sm *sm,
981 const u8 *rsc)
982{
983 int rsclen;
984
985 if (!sm->wpa_rsc_relaxation)
986 return 0;
987
988 rsclen = wpa_cipher_rsc_len(sm->group_cipher);
989
990 /*
991 * Try to detect RSC (endian) corruption issue where the AP sends
992 * the RSC bytes in EAPOL-Key message in the wrong order, both if
993 * it's actually a 6-byte field (as it should be) and if it treats
994 * it as an 8-byte field.
995 * An AP model known to have this bug is the Sapido RB-1632.
996 */
997 if (rsclen == 6 && ((rsc[5] && !rsc[0]) || rsc[6] || rsc[7])) {
998 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
999 "RSC %02x%02x%02x%02x%02x%02x%02x%02x is likely bogus, using 0",
1000 rsc[0], rsc[1], rsc[2], rsc[3],
1001 rsc[4], rsc[5], rsc[6], rsc[7]);
1002
1003 return 1;
1004 }
1005
1006 return 0;
1007}
1008
1009
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001010static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
1011 const struct wpa_eapol_key *key,
1012 const u8 *gtk, size_t gtk_len,
1013 int key_info)
1014{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001015 struct wpa_gtk_data gd;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001016 const u8 *key_rsc;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001017
1018 /*
1019 * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x
1020 * GTK KDE format:
1021 * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7]
1022 * Reserved [bits 0-7]
1023 * GTK
1024 */
1025
1026 os_memset(&gd, 0, sizeof(gd));
1027 wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake",
1028 gtk, gtk_len);
1029
1030 if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk))
1031 return -1;
1032
1033 gd.keyidx = gtk[0] & 0x3;
1034 gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
1035 !!(gtk[0] & BIT(2)));
1036 gtk += 2;
1037 gtk_len -= 2;
1038
1039 os_memcpy(gd.gtk, gtk, gtk_len);
1040 gd.gtk_len = gtk_len;
1041
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001042 key_rsc = key->key_rsc;
1043 if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
1044 key_rsc = null_rsc;
1045
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001046 if (sm->group_cipher != WPA_CIPHER_GTK_NOT_USED &&
1047 (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
1048 gtk_len, gtk_len,
1049 &gd.key_rsc_len, &gd.alg) ||
Jouni Malinen58c0e962017-10-01 12:12:24 +03001050 wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001051 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1052 "RSN: Failed to install GTK");
Hai Shalom81f62d82019-07-22 12:10:00 -07001053 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001054 return -1;
1055 }
Hai Shalom81f62d82019-07-22 12:10:00 -07001056 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001057
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001058 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001059}
1060
1061
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001062static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
Jouni Malinen58c0e962017-10-01 12:12:24 +03001063 const struct wpa_igtk_kde *igtk,
1064 int wnm_sleep)
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001065{
1066 size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
1067 u16 keyidx = WPA_GET_LE16(igtk->keyid);
1068
1069 /* Detect possible key reinstallation */
Jouni Malinen58c0e962017-10-01 12:12:24 +03001070 if ((sm->igtk.igtk_len == len &&
1071 os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) ||
1072 (sm->igtk_wnm_sleep.igtk_len == len &&
1073 os_memcmp(sm->igtk_wnm_sleep.igtk, igtk->igtk,
1074 sm->igtk_wnm_sleep.igtk_len) == 0)) {
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001075 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1076 "WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)",
1077 keyidx);
1078 return 0;
1079 }
1080
1081 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001082 "WPA: IGTK keyid %d pn " COMPACT_MACSTR,
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001083 keyidx, MAC2STR(igtk->pn));
1084 wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len);
1085 if (keyidx > 4095) {
1086 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1087 "WPA: Invalid IGTK KeyID %d", keyidx);
1088 return -1;
1089 }
1090 if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
1091 broadcast_ether_addr,
1092 keyidx, 0, igtk->pn, sizeof(igtk->pn),
1093 igtk->igtk, len) < 0) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07001094 if (keyidx == 0x0400 || keyidx == 0x0500) {
1095 /* Assume the AP has broken PMF implementation since it
1096 * seems to have swapped the KeyID bytes. The AP cannot
1097 * be trusted to implement BIP correctly or provide a
1098 * valid IGTK, so do not try to configure this key with
1099 * swapped KeyID bytes. Instead, continue without
1100 * configuring the IGTK so that the driver can drop any
1101 * received group-addressed robust management frames due
1102 * to missing keys.
1103 *
1104 * Normally, this error behavior would result in us
1105 * disconnecting, but there are number of deployed APs
1106 * with this broken behavior, so as an interoperability
1107 * workaround, allow the connection to proceed. */
1108 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1109 "WPA: Ignore IGTK configuration error due to invalid IGTK KeyID byte order");
1110 } else {
1111 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1112 "WPA: Failed to configure IGTK to the driver");
1113 return -1;
1114 }
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001115 }
1116
Jouni Malinen58c0e962017-10-01 12:12:24 +03001117 if (wnm_sleep) {
1118 sm->igtk_wnm_sleep.igtk_len = len;
1119 os_memcpy(sm->igtk_wnm_sleep.igtk, igtk->igtk,
1120 sm->igtk_wnm_sleep.igtk_len);
1121 } else {
1122 sm->igtk.igtk_len = len;
1123 os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len);
1124 }
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001125
1126 return 0;
1127}
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001128
1129
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001130static int ieee80211w_set_keys(struct wpa_sm *sm,
1131 struct wpa_eapol_ie_parse *ie)
1132{
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001133 if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001134 return 0;
1135
1136 if (ie->igtk) {
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001137 size_t len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001138 const struct wpa_igtk_kde *igtk;
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001139
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001140 len = wpa_cipher_key_len(sm->mgmt_group_cipher);
1141 if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001142 return -1;
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001143
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001144 igtk = (const struct wpa_igtk_kde *) ie->igtk;
Jouni Malinen58c0e962017-10-01 12:12:24 +03001145 if (wpa_supplicant_install_igtk(sm, igtk, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001146 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001147 }
1148
1149 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001150}
1151
1152
1153static void wpa_report_ie_mismatch(struct wpa_sm *sm,
1154 const char *reason, const u8 *src_addr,
1155 const u8 *wpa_ie, size_t wpa_ie_len,
1156 const u8 *rsn_ie, size_t rsn_ie_len)
1157{
1158 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")",
1159 reason, MAC2STR(src_addr));
1160
1161 if (sm->ap_wpa_ie) {
1162 wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp",
1163 sm->ap_wpa_ie, sm->ap_wpa_ie_len);
1164 }
1165 if (wpa_ie) {
1166 if (!sm->ap_wpa_ie) {
1167 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1168 "WPA: No WPA IE in Beacon/ProbeResp");
1169 }
1170 wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg",
1171 wpa_ie, wpa_ie_len);
1172 }
1173
1174 if (sm->ap_rsn_ie) {
1175 wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp",
1176 sm->ap_rsn_ie, sm->ap_rsn_ie_len);
1177 }
1178 if (rsn_ie) {
1179 if (!sm->ap_rsn_ie) {
1180 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1181 "WPA: No RSN IE in Beacon/ProbeResp");
1182 }
1183 wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg",
1184 rsn_ie, rsn_ie_len);
1185 }
1186
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001187 wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001188}
1189
1190
1191#ifdef CONFIG_IEEE80211R
1192
1193static int ft_validate_mdie(struct wpa_sm *sm,
1194 const unsigned char *src_addr,
1195 struct wpa_eapol_ie_parse *ie,
1196 const u8 *assoc_resp_mdie)
1197{
1198 struct rsn_mdie *mdie;
1199
1200 mdie = (struct rsn_mdie *) (ie->mdie + 2);
1201 if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) ||
1202 os_memcmp(mdie->mobility_domain, sm->mobility_domain,
1203 MOBILITY_DOMAIN_ID_LEN) != 0) {
1204 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE in msg 3/4 did "
1205 "not match with the current mobility domain");
1206 return -1;
1207 }
1208
1209 if (assoc_resp_mdie &&
1210 (assoc_resp_mdie[1] != ie->mdie[1] ||
1211 os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) {
1212 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE mismatch");
1213 wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4",
1214 ie->mdie, 2 + ie->mdie[1]);
1215 wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response",
1216 assoc_resp_mdie, 2 + assoc_resp_mdie[1]);
1217 return -1;
1218 }
1219
1220 return 0;
1221}
1222
1223
1224static int ft_validate_ftie(struct wpa_sm *sm,
1225 const unsigned char *src_addr,
1226 struct wpa_eapol_ie_parse *ie,
1227 const u8 *assoc_resp_ftie)
1228{
1229 if (ie->ftie == NULL) {
1230 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1231 "FT: No FTIE in EAPOL-Key msg 3/4");
1232 return -1;
1233 }
1234
1235 if (assoc_resp_ftie == NULL)
1236 return 0;
1237
1238 if (assoc_resp_ftie[1] != ie->ftie[1] ||
1239 os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) {
1240 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: FTIE mismatch");
1241 wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4",
1242 ie->ftie, 2 + ie->ftie[1]);
1243 wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response",
1244 assoc_resp_ftie, 2 + assoc_resp_ftie[1]);
1245 return -1;
1246 }
1247
1248 return 0;
1249}
1250
1251
1252static int ft_validate_rsnie(struct wpa_sm *sm,
1253 const unsigned char *src_addr,
1254 struct wpa_eapol_ie_parse *ie)
1255{
1256 struct wpa_ie_data rsn;
1257
1258 if (!ie->rsn_ie)
1259 return 0;
1260
1261 /*
1262 * Verify that PMKR1Name from EAPOL-Key message 3/4
1263 * matches with the value we derived.
1264 */
1265 if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 ||
1266 rsn.num_pmkid != 1 || rsn.pmkid == NULL) {
1267 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No PMKR1Name in "
1268 "FT 4-way handshake message 3/4");
1269 return -1;
1270 }
1271
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001272 if (os_memcmp_const(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0)
1273 {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1275 "FT: PMKR1Name mismatch in "
1276 "FT 4-way handshake message 3/4");
1277 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator",
1278 rsn.pmkid, WPA_PMK_NAME_LEN);
1279 wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
1280 sm->pmk_r1_name, WPA_PMK_NAME_LEN);
1281 return -1;
1282 }
1283
1284 return 0;
1285}
1286
1287
1288static int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm,
1289 const unsigned char *src_addr,
1290 struct wpa_eapol_ie_parse *ie)
1291{
1292 const u8 *pos, *end, *mdie = NULL, *ftie = NULL;
1293
1294 if (sm->assoc_resp_ies) {
1295 pos = sm->assoc_resp_ies;
1296 end = pos + sm->assoc_resp_ies_len;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001297 while (end - pos > 2) {
1298 if (2 + pos[1] > end - pos)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001299 break;
1300 switch (*pos) {
1301 case WLAN_EID_MOBILITY_DOMAIN:
1302 mdie = pos;
1303 break;
1304 case WLAN_EID_FAST_BSS_TRANSITION:
1305 ftie = pos;
1306 break;
1307 }
1308 pos += 2 + pos[1];
1309 }
1310 }
1311
1312 if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 ||
1313 ft_validate_ftie(sm, src_addr, ie, ftie) < 0 ||
1314 ft_validate_rsnie(sm, src_addr, ie) < 0)
1315 return -1;
1316
1317 return 0;
1318}
1319
1320#endif /* CONFIG_IEEE80211R */
1321
1322
1323static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
1324 const unsigned char *src_addr,
1325 struct wpa_eapol_ie_parse *ie)
1326{
1327 if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) {
1328 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1329 "WPA: No WPA/RSN IE for this AP known. "
1330 "Trying to get from scan results");
1331 if (wpa_sm_get_beacon_ie(sm) < 0) {
1332 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1333 "WPA: Could not find AP from "
1334 "the scan results");
1335 } else {
1336 wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
1337 "WPA: Found the current AP from "
1338 "updated scan results");
1339 }
1340 }
1341
1342 if (ie->wpa_ie == NULL && ie->rsn_ie == NULL &&
1343 (sm->ap_wpa_ie || sm->ap_rsn_ie)) {
1344 wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
1345 "with IE in Beacon/ProbeResp (no IE?)",
1346 src_addr, ie->wpa_ie, ie->wpa_ie_len,
1347 ie->rsn_ie, ie->rsn_ie_len);
1348 return -1;
1349 }
1350
1351 if ((ie->wpa_ie && sm->ap_wpa_ie &&
1352 (ie->wpa_ie_len != sm->ap_wpa_ie_len ||
1353 os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||
1354 (ie->rsn_ie && sm->ap_rsn_ie &&
1355 wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
1356 sm->ap_rsn_ie, sm->ap_rsn_ie_len,
1357 ie->rsn_ie, ie->rsn_ie_len))) {
1358 wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
1359 "with IE in Beacon/ProbeResp",
1360 src_addr, ie->wpa_ie, ie->wpa_ie_len,
1361 ie->rsn_ie, ie->rsn_ie_len);
1362 return -1;
1363 }
1364
1365 if (sm->proto == WPA_PROTO_WPA &&
1366 ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) {
1367 wpa_report_ie_mismatch(sm, "Possible downgrade attack "
1368 "detected - RSN was enabled and RSN IE "
1369 "was in msg 3/4, but not in "
1370 "Beacon/ProbeResp",
1371 src_addr, ie->wpa_ie, ie->wpa_ie_len,
1372 ie->rsn_ie, ie->rsn_ie_len);
1373 return -1;
1374 }
1375
Hai Shalomc3565922019-10-28 11:58:20 -07001376 if ((sm->ap_rsnxe && !ie->rsnxe) ||
1377 (!sm->ap_rsnxe && ie->rsnxe) ||
1378 (sm->ap_rsnxe && ie->rsnxe &&
1379 (sm->ap_rsnxe_len != ie->rsnxe_len ||
1380 os_memcmp(sm->ap_rsnxe, ie->rsnxe, sm->ap_rsnxe_len) != 0))) {
1381 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1382 "WPA: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
1383 return -1;
1384 }
1385
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386#ifdef CONFIG_IEEE80211R
1387 if (wpa_key_mgmt_ft(sm->key_mgmt) &&
1388 wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
1389 return -1;
1390#endif /* CONFIG_IEEE80211R */
1391
1392 return 0;
1393}
1394
1395
1396/**
1397 * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake
1398 * @sm: Pointer to WPA state machine data from wpa_sm_init()
1399 * @dst: Destination address for the frame
1400 * @key: Pointer to the EAPOL-Key frame header
1401 * @ver: Version bits from EAPOL-Key Key Info
1402 * @key_info: Key Info
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001403 * @ptk: PTK to use for keyed hash and encryption
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001404 * Returns: >= 0 on success, < 0 on failure
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405 */
1406int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
1407 const struct wpa_eapol_key *key,
1408 u16 ver, u16 key_info,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001409 struct wpa_ptk *ptk)
1410{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001411 size_t mic_len, hdrlen, rlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001412 struct wpa_eapol_key *reply;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001413 u8 *rbuf, *key_mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001414
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001415 mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001416 hdrlen = sizeof(*reply) + mic_len + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001417 rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001418 hdrlen, &rlen, (void *) &reply);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001419 if (rbuf == NULL)
1420 return -1;
1421
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001422 reply->type = (sm->proto == WPA_PROTO_RSN ||
1423 sm->proto == WPA_PROTO_OSEN) ?
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001424 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1425 key_info &= WPA_KEY_INFO_SECURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001426 key_info |= ver | WPA_KEY_INFO_KEY_TYPE;
1427 if (mic_len)
1428 key_info |= WPA_KEY_INFO_MIC;
1429 else
1430 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001431 WPA_PUT_BE16(reply->key_info, key_info);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001432 if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001433 WPA_PUT_BE16(reply->key_length, 0);
1434 else
1435 os_memcpy(reply->key_length, key->key_length, 2);
1436 os_memcpy(reply->replay_counter, key->replay_counter,
1437 WPA_REPLAY_COUNTER_LEN);
1438
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001439 key_mic = (u8 *) (reply + 1);
1440 WPA_PUT_BE16(key_mic + mic_len, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001441
Roshan Pius5e7db942018-04-12 12:27:41 -07001442 wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Sending EAPOL-Key 4/4");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001443 return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
1444 key_mic);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001445}
1446
1447
1448static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
1449 const struct wpa_eapol_key *key,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001450 u16 ver, const u8 *key_data,
1451 size_t key_data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001452{
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001453 u16 key_info, keylen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001454 struct wpa_eapol_ie_parse ie;
1455
1456 wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
Roshan Pius5e7db942018-04-12 12:27:41 -07001457 wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: RX message 3 of 4-Way "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001458 "Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver);
1459
1460 key_info = WPA_GET_BE16(key->key_info);
1461
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001462 wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len);
1463 if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001464 goto failed;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001465 if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
1466 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1467 "WPA: GTK IE in unencrypted key data");
1468 goto failed;
1469 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001470 if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
1471 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1472 "WPA: IGTK KDE in unencrypted key data");
1473 goto failed;
1474 }
1475
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001476 if (ie.igtk &&
1477 wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) &&
1478 ie.igtk_len != WPA_IGTK_KDE_PREFIX_LEN +
1479 (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001480 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1481 "WPA: Invalid IGTK KDE length %lu",
1482 (unsigned long) ie.igtk_len);
1483 goto failed;
1484 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001485
1486 if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
1487 goto failed;
1488
1489 if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
1490 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1491 "WPA: ANonce from message 1 of 4-Way Handshake "
1492 "differs from 3 of 4-Way Handshake - drop packet (src="
1493 MACSTR ")", MAC2STR(sm->bssid));
1494 goto failed;
1495 }
1496
1497 keylen = WPA_GET_BE16(key->key_length);
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001498 if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) {
1499 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1500 "WPA: Invalid %s key length %d (src=" MACSTR
1501 ")", wpa_cipher_txt(sm->pairwise_cipher), keylen,
1502 MAC2STR(sm->bssid));
1503 goto failed;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001504 }
1505
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001506#ifdef CONFIG_P2P
1507 if (ie.ip_addr_alloc) {
1508 os_memcpy(sm->p2p_ip_addr, ie.ip_addr_alloc, 3 * 4);
1509 wpa_hexdump(MSG_DEBUG, "P2P: IP address info",
1510 sm->p2p_ip_addr, sizeof(sm->p2p_ip_addr));
1511 }
1512#endif /* CONFIG_P2P */
1513
Hai Shalom74f70d42019-02-11 14:42:39 -08001514#ifdef CONFIG_OCV
1515 if (wpa_sm_ocv_enabled(sm)) {
1516 struct wpa_channel_info ci;
1517
1518 if (wpa_sm_channel_info(sm, &ci) != 0) {
1519 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1520 "Failed to get channel info to validate received OCI in EAPOL-Key 3/4");
1521 return;
1522 }
1523
1524 if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci,
1525 channel_width_to_int(ci.chanwidth),
1526 ci.seg1_idx) != 0) {
1527 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "%s",
1528 ocv_errorstr);
1529 return;
1530 }
1531 }
1532#endif /* CONFIG_OCV */
1533
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001534 if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001535 &sm->ptk) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001536 goto failed;
1537 }
1538
1539 /* SNonce was successfully used in msg 3/4, so mark it to be renewed
1540 * for the next 4-Way Handshake. If msg 3 is received again, the old
1541 * SNonce will still be used to avoid changing PTK. */
1542 sm->renew_snonce = 1;
1543
1544 if (key_info & WPA_KEY_INFO_INSTALL) {
1545 if (wpa_supplicant_install_ptk(sm, key))
1546 goto failed;
1547 }
1548
1549 if (key_info & WPA_KEY_INFO_SECURE) {
1550 wpa_sm_mlme_setprotection(
1551 sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX,
1552 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
1553 eapol_sm_notify_portValid(sm->eapol, TRUE);
1554 }
1555 wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
1556
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001557 if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07001558 /* No GTK to be set to the driver */
1559 } else if (!ie.gtk && sm->proto == WPA_PROTO_RSN) {
1560 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1561 "RSN: No GTK KDE included in EAPOL-Key msg 3/4");
1562 goto failed;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001563 } else if (ie.gtk &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001564 wpa_supplicant_pairwise_gtk(sm, key,
1565 ie.gtk, ie.gtk_len, key_info) < 0) {
1566 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1567 "RSN: Failed to configure GTK");
1568 goto failed;
1569 }
1570
1571 if (ieee80211w_set_keys(sm, &ie) < 0) {
1572 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1573 "RSN: Failed to configure IGTK");
1574 goto failed;
1575 }
1576
Hai Shalom5f92bc92019-04-18 11:54:11 -07001577 if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED || ie.gtk)
1578 wpa_supplicant_key_neg_complete(sm, sm->bssid,
1579 key_info & WPA_KEY_INFO_SECURE);
1580
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001581 if (ie.gtk)
1582 wpa_sm_set_rekey_offload(sm);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001583
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001584 /* Add PMKSA cache entry for Suite B AKMs here since PMKID can be
1585 * calculated only after KCK has been derived. Though, do not replace an
1586 * existing PMKSA entry after each 4-way handshake (i.e., new KCK/PMKID)
1587 * to avoid unnecessary changes of PMKID while continuing to use the
1588 * same PMK. */
1589 if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt) &&
1590 !sm->cur_pmksa) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001591 struct rsn_pmksa_cache_entry *sa;
1592
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001593 sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001594 sm->ptk.kck, sm->ptk.kck_len,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001595 sm->bssid, sm->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001596 sm->network_ctx, sm->key_mgmt, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001597 if (!sm->cur_pmksa)
1598 sm->cur_pmksa = sa;
1599 }
1600
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07001601 sm->msg_3_of_4_ok = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001602 return;
1603
1604failed:
1605 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
1606}
1607
1608
1609static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
1610 const u8 *keydata,
1611 size_t keydatalen,
1612 u16 key_info,
1613 struct wpa_gtk_data *gd)
1614{
1615 int maxkeylen;
1616 struct wpa_eapol_ie_parse ie;
1617
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001618 wpa_hexdump_key(MSG_DEBUG, "RSN: msg 1/2 key data",
1619 keydata, keydatalen);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001620 if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0)
1621 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001622 if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
1623 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1624 "WPA: GTK IE in unencrypted key data");
1625 return -1;
1626 }
1627 if (ie.gtk == NULL) {
1628 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1629 "WPA: No GTK IE in Group Key msg 1/2");
1630 return -1;
1631 }
1632 maxkeylen = gd->gtk_len = ie.gtk_len - 2;
1633
Hai Shalom74f70d42019-02-11 14:42:39 -08001634#ifdef CONFIG_OCV
1635 if (wpa_sm_ocv_enabled(sm)) {
1636 struct wpa_channel_info ci;
1637
1638 if (wpa_sm_channel_info(sm, &ci) != 0) {
1639 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1640 "Failed to get channel info to validate received OCI in EAPOL-Key group msg 1/2");
1641 return -1;
1642 }
1643
1644 if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci,
1645 channel_width_to_int(ci.chanwidth),
1646 ci.seg1_idx) != 0) {
1647 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "%s",
1648 ocv_errorstr);
1649 return -1;
1650 }
1651 }
1652#endif /* CONFIG_OCV */
1653
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001654 if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
1655 gd->gtk_len, maxkeylen,
1656 &gd->key_rsc_len, &gd->alg))
1657 return -1;
1658
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001659 wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in group key handshake",
1660 ie.gtk, ie.gtk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001661 gd->keyidx = ie.gtk[0] & 0x3;
1662 gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
1663 !!(ie.gtk[0] & BIT(2)));
1664 if (ie.gtk_len - 2 > sizeof(gd->gtk)) {
1665 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1666 "RSN: Too long GTK in GTK IE (len=%lu)",
1667 (unsigned long) ie.gtk_len - 2);
1668 return -1;
1669 }
1670 os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2);
1671
1672 if (ieee80211w_set_keys(sm, &ie) < 0)
1673 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1674 "RSN: Failed to configure IGTK");
1675
1676 return 0;
1677}
1678
1679
1680static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
1681 const struct wpa_eapol_key *key,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001682 const u8 *key_data,
1683 size_t key_data_len, u16 key_info,
1684 u16 ver, struct wpa_gtk_data *gd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001685{
1686 size_t maxkeylen;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001687 u16 gtk_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001688
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001689 gtk_len = WPA_GET_BE16(key->key_length);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001690 maxkeylen = key_data_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001691 if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
1692 if (maxkeylen < 8) {
1693 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1694 "WPA: Too short maxkeylen (%lu)",
1695 (unsigned long) maxkeylen);
1696 return -1;
1697 }
1698 maxkeylen -= 8;
1699 }
1700
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001701 if (gtk_len > maxkeylen ||
1702 wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
1703 gtk_len, maxkeylen,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001704 &gd->key_rsc_len, &gd->alg))
1705 return -1;
1706
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001707 gd->gtk_len = gtk_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001708 gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
1709 WPA_KEY_INFO_KEY_INDEX_SHIFT;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001710 if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001711#ifdef CONFIG_NO_RC4
1712 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1713 "WPA: RC4 not supported in the build");
1714 return -1;
1715#else /* CONFIG_NO_RC4 */
Dmitry Shmidt61593f02014-04-21 16:27:35 -07001716 u8 ek[32];
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001717 if (key_data_len > sizeof(gd->gtk)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001718 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1719 "WPA: RC4 key data too long (%lu)",
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001720 (unsigned long) key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721 return -1;
1722 }
Dmitry Shmidt61593f02014-04-21 16:27:35 -07001723 os_memcpy(ek, key->key_iv, 16);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001724 os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001725 os_memcpy(gd->gtk, key_data, key_data_len);
1726 if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) {
Hai Shalom81f62d82019-07-22 12:10:00 -07001727 forced_memzero(ek, sizeof(ek));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001728 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
1729 "WPA: RC4 failed");
1730 return -1;
1731 }
Hai Shalom81f62d82019-07-22 12:10:00 -07001732 forced_memzero(ek, sizeof(ek));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001733#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001734 } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001735 if (maxkeylen % 8) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001736 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1737 "WPA: Unsupported AES-WRAP len %lu",
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001738 (unsigned long) maxkeylen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001739 return -1;
1740 }
1741 if (maxkeylen > sizeof(gd->gtk)) {
1742 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1743 "WPA: AES-WRAP key data "
1744 "too long (keydatalen=%lu maxkeylen=%lu)",
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001745 (unsigned long) key_data_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746 (unsigned long) maxkeylen);
1747 return -1;
1748 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001749 if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, maxkeylen / 8,
1750 key_data, gd->gtk)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001751 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1752 "WPA: AES unwrap failed - could not decrypt "
1753 "GTK");
1754 return -1;
1755 }
1756 } else {
1757 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1758 "WPA: Unsupported key_info type %d", ver);
1759 return -1;
1760 }
1761 gd->tx = wpa_supplicant_gtk_tx_bit_workaround(
1762 sm, !!(key_info & WPA_KEY_INFO_TXRX));
1763 return 0;
1764}
1765
1766
1767static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
1768 const struct wpa_eapol_key *key,
1769 int ver, u16 key_info)
1770{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001771 size_t mic_len, hdrlen, rlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001772 struct wpa_eapol_key *reply;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001773 u8 *rbuf, *key_mic;
Hai Shalom74f70d42019-02-11 14:42:39 -08001774 size_t kde_len = 0;
1775
1776#ifdef CONFIG_OCV
1777 if (wpa_sm_ocv_enabled(sm))
1778 kde_len = OCV_OCI_KDE_LEN;
1779#endif /* CONFIG_OCV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001781 mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001782 hdrlen = sizeof(*reply) + mic_len + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001783 rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
Hai Shalom74f70d42019-02-11 14:42:39 -08001784 hdrlen + kde_len, &rlen, (void *) &reply);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001785 if (rbuf == NULL)
1786 return -1;
1787
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001788 reply->type = (sm->proto == WPA_PROTO_RSN ||
1789 sm->proto == WPA_PROTO_OSEN) ?
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001790 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1791 key_info &= WPA_KEY_INFO_KEY_INDEX_MASK;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001792 key_info |= ver | WPA_KEY_INFO_SECURE;
1793 if (mic_len)
1794 key_info |= WPA_KEY_INFO_MIC;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001795 else
1796 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797 WPA_PUT_BE16(reply->key_info, key_info);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001798 if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001799 WPA_PUT_BE16(reply->key_length, 0);
1800 else
1801 os_memcpy(reply->key_length, key->key_length, 2);
1802 os_memcpy(reply->replay_counter, key->replay_counter,
1803 WPA_REPLAY_COUNTER_LEN);
1804
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001805 key_mic = (u8 *) (reply + 1);
Hai Shalom74f70d42019-02-11 14:42:39 -08001806 WPA_PUT_BE16(key_mic + mic_len, kde_len); /* Key Data Length */
1807
1808#ifdef CONFIG_OCV
1809 if (wpa_sm_ocv_enabled(sm)) {
1810 struct wpa_channel_info ci;
1811 u8 *pos;
1812
1813 if (wpa_sm_channel_info(sm, &ci) != 0) {
1814 wpa_printf(MSG_WARNING,
1815 "Failed to get channel info for OCI element in EAPOL-Key 2/2");
1816 os_free(rbuf);
1817 return -1;
1818 }
1819
1820 pos = key_mic + mic_len + 2; /* Key Data */
1821 if (ocv_insert_oci_kde(&ci, &pos) < 0) {
1822 os_free(rbuf);
1823 return -1;
1824 }
1825 }
1826#endif /* CONFIG_OCV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001827
1828 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001829 return wpa_eapol_key_send(sm, &sm->ptk, ver, sm->bssid, ETH_P_EAPOL,
1830 rbuf, rlen, key_mic);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001831}
1832
1833
1834static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
1835 const unsigned char *src_addr,
1836 const struct wpa_eapol_key *key,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001837 const u8 *key_data,
1838 size_t key_data_len, u16 ver)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001839{
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001840 u16 key_info;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001841 int rekey, ret;
1842 struct wpa_gtk_data gd;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001843 const u8 *key_rsc;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001844
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001845 if (!sm->msg_3_of_4_ok && !wpa_fils_is_completed(sm)) {
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07001846 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1847 "WPA: Group Key Handshake started prior to completion of 4-way handshake");
1848 goto failed;
1849 }
1850
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001851 os_memset(&gd, 0, sizeof(gd));
1852
1853 rekey = wpa_sm_get_state(sm) == WPA_COMPLETED;
1854 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of Group Key "
1855 "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
1856
1857 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001858
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001859 if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001860 ret = wpa_supplicant_process_1_of_2_rsn(sm, key_data,
1861 key_data_len, key_info,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001862 &gd);
1863 } else {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001864 ret = wpa_supplicant_process_1_of_2_wpa(sm, key, key_data,
1865 key_data_len,
1866 key_info, ver, &gd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001867 }
1868
1869 wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
1870
1871 if (ret)
1872 goto failed;
1873
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001874 key_rsc = key->key_rsc;
1875 if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
1876 key_rsc = null_rsc;
1877
Jouni Malinen58c0e962017-10-01 12:12:24 +03001878 if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0) ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001879 wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001880 goto failed;
Hai Shalom81f62d82019-07-22 12:10:00 -07001881 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001882
1883 if (rekey) {
1884 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying "
1885 "completed with " MACSTR " [GTK=%s]",
1886 MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
1887 wpa_sm_cancel_auth_timeout(sm);
1888 wpa_sm_set_state(sm, WPA_COMPLETED);
1889 } else {
1890 wpa_supplicant_key_neg_complete(sm, sm->bssid,
1891 key_info &
1892 WPA_KEY_INFO_SECURE);
1893 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001894
1895 wpa_sm_set_rekey_offload(sm);
1896
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001897 return;
1898
1899failed:
Hai Shalom81f62d82019-07-22 12:10:00 -07001900 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001901 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
1902}
1903
1904
1905static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001906 struct wpa_eapol_key *key,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001907 u16 ver,
1908 const u8 *buf, size_t len)
1909{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001910 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001911 int ok = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001912 size_t mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001913
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001914 os_memcpy(mic, key + 1, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001915 if (sm->tptk_set) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001916 os_memset(key + 1, 0, mic_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001917 if (wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len,
1918 sm->key_mgmt,
1919 ver, buf, len, (u8 *) (key + 1)) < 0 ||
1920 os_memcmp_const(mic, key + 1, mic_len) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001921 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1922 "WPA: Invalid EAPOL-Key MIC "
1923 "when using TPTK - ignoring TPTK");
Hai Shalom74f70d42019-02-11 14:42:39 -08001924#ifdef TEST_FUZZ
1925 wpa_printf(MSG_INFO,
1926 "TEST: Ignore Key MIC failure for fuzz testing");
1927 goto continue_fuzz;
1928#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001929 } else {
Hai Shalom74f70d42019-02-11 14:42:39 -08001930#ifdef TEST_FUZZ
1931 continue_fuzz:
1932#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001933 ok = 1;
1934 sm->tptk_set = 0;
1935 sm->ptk_set = 1;
1936 os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
Dmitry Shmidt61593f02014-04-21 16:27:35 -07001937 os_memset(&sm->tptk, 0, sizeof(sm->tptk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001938 /*
1939 * This assures the same TPTK in sm->tptk can never be
Roshan Pius3a1667e2018-07-03 15:17:14 -07001940 * copied twice to sm->ptk as the new PTK. In
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001941 * combination with the installed flag in the wpa_ptk
1942 * struct, this assures the same PTK is only installed
1943 * once.
1944 */
1945 sm->renew_snonce = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001946 }
1947 }
1948
1949 if (!ok && sm->ptk_set) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001950 os_memset(key + 1, 0, mic_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001951 if (wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len,
1952 sm->key_mgmt,
1953 ver, buf, len, (u8 *) (key + 1)) < 0 ||
1954 os_memcmp_const(mic, key + 1, mic_len) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001955 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1956 "WPA: Invalid EAPOL-Key MIC - "
1957 "dropping packet");
Hai Shalom74f70d42019-02-11 14:42:39 -08001958#ifdef TEST_FUZZ
1959 wpa_printf(MSG_INFO,
1960 "TEST: Ignore Key MIC failure for fuzz testing");
1961 goto continue_fuzz2;
1962#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001963 return -1;
1964 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001965#ifdef TEST_FUZZ
1966 continue_fuzz2:
1967#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968 ok = 1;
1969 }
1970
1971 if (!ok) {
1972 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1973 "WPA: Could not verify EAPOL-Key MIC - "
1974 "dropping packet");
1975 return -1;
1976 }
1977
1978 os_memcpy(sm->rx_replay_counter, key->replay_counter,
1979 WPA_REPLAY_COUNTER_LEN);
1980 sm->rx_replay_counter_set = 1;
1981 return 0;
1982}
1983
1984
1985/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
1986static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001987 struct wpa_eapol_key *key,
1988 size_t mic_len, u16 ver,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001989 u8 *key_data, size_t *key_data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001990{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001991 wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001992 key_data, *key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001993 if (!sm->ptk_set) {
1994 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1995 "WPA: PTK not available, cannot decrypt EAPOL-Key Key "
1996 "Data");
1997 return -1;
1998 }
1999
2000 /* Decrypt key data here so that this operation does not need
2001 * to be implemented separately for each message type. */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002002 if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002003#ifdef CONFIG_NO_RC4
2004 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2005 "WPA: RC4 not supported in the build");
2006 return -1;
2007#else /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002008 u8 ek[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002009
2010 wpa_printf(MSG_DEBUG, "WPA: Decrypt Key Data using RC4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002011 os_memcpy(ek, key->key_iv, 16);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002012 os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002013 if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002014 forced_memzero(ek, sizeof(ek));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002015 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
2016 "WPA: RC4 failed");
2017 return -1;
2018 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002019 forced_memzero(ek, sizeof(ek));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002020#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002021 } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002022 ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07002023 wpa_use_aes_key_wrap(sm->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002024 u8 *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002025
2026 wpa_printf(MSG_DEBUG,
2027 "WPA: Decrypt Key Data using AES-UNWRAP (KEK length %u)",
2028 (unsigned int) sm->ptk.kek_len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002029 if (*key_data_len < 8 || *key_data_len % 8) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002030 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002031 "WPA: Unsupported AES-WRAP len %u",
2032 (unsigned int) *key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002033 return -1;
2034 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002035 *key_data_len -= 8; /* AES-WRAP adds 8 bytes */
2036 buf = os_malloc(*key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002037 if (buf == NULL) {
2038 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2039 "WPA: No memory for AES-UNWRAP buffer");
2040 return -1;
2041 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002042#ifdef TEST_FUZZ
2043 os_memset(buf, 0x11, *key_data_len);
2044#endif /* TEST_FUZZ */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002045 if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002046 key_data, buf)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002047#ifdef TEST_FUZZ
2048 wpa_printf(MSG_INFO,
2049 "TEST: Ignore AES unwrap failure for fuzz testing");
2050 goto continue_fuzz;
2051#endif /* TEST_FUZZ */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002052 bin_clear_free(buf, *key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002053 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2054 "WPA: AES unwrap failed - "
2055 "could not decrypt EAPOL-Key key data");
2056 return -1;
2057 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002058#ifdef TEST_FUZZ
2059 continue_fuzz:
2060#endif /* TEST_FUZZ */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002061 os_memcpy(key_data, buf, *key_data_len);
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002062 bin_clear_free(buf, *key_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002063 WPA_PUT_BE16(((u8 *) (key + 1)) + mic_len, *key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002064 } else {
2065 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2066 "WPA: Unsupported key_info type %d", ver);
2067 return -1;
2068 }
2069 wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002070 key_data, *key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002071 return 0;
2072}
2073
2074
2075/**
2076 * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted
2077 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2078 */
2079void wpa_sm_aborted_cached(struct wpa_sm *sm)
2080{
2081 if (sm && sm->cur_pmksa) {
2082 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2083 "RSN: Cancelling PMKSA caching attempt");
2084 sm->cur_pmksa = NULL;
2085 }
2086}
2087
2088
2089static void wpa_eapol_key_dump(struct wpa_sm *sm,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002090 const struct wpa_eapol_key *key,
2091 unsigned int key_data_len,
2092 const u8 *mic, unsigned int mic_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002093{
2094#ifndef CONFIG_NO_STDOUT_DEBUG
2095 u16 key_info = WPA_GET_BE16(key->key_info);
2096
2097 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, " EAPOL-Key type=%d", key->type);
2098 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2099 " key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)",
2100 key_info, key_info & WPA_KEY_INFO_TYPE_MASK,
2101 (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
2102 WPA_KEY_INFO_KEY_INDEX_SHIFT,
2103 (key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13,
2104 key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group",
2105 key_info & WPA_KEY_INFO_INSTALL ? " Install" : "",
2106 key_info & WPA_KEY_INFO_ACK ? " Ack" : "",
2107 key_info & WPA_KEY_INFO_MIC ? " MIC" : "",
2108 key_info & WPA_KEY_INFO_SECURE ? " Secure" : "",
2109 key_info & WPA_KEY_INFO_ERROR ? " Error" : "",
2110 key_info & WPA_KEY_INFO_REQUEST ? " Request" : "",
2111 key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : "");
2112 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2113 " key_length=%u key_data_length=%u",
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002114 WPA_GET_BE16(key->key_length), key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002115 wpa_hexdump(MSG_DEBUG, " replay_counter",
2116 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
2117 wpa_hexdump(MSG_DEBUG, " key_nonce", key->key_nonce, WPA_NONCE_LEN);
2118 wpa_hexdump(MSG_DEBUG, " key_iv", key->key_iv, 16);
2119 wpa_hexdump(MSG_DEBUG, " key_rsc", key->key_rsc, 8);
2120 wpa_hexdump(MSG_DEBUG, " key_id (reserved)", key->key_id, 8);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002121 wpa_hexdump(MSG_DEBUG, " key_mic", mic, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002122#endif /* CONFIG_NO_STDOUT_DEBUG */
2123}
2124
2125
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002126#ifdef CONFIG_FILS
2127static int wpa_supp_aead_decrypt(struct wpa_sm *sm, u8 *buf, size_t buf_len,
2128 size_t *key_data_len)
2129{
2130 struct wpa_ptk *ptk;
2131 struct ieee802_1x_hdr *hdr;
2132 struct wpa_eapol_key *key;
2133 u8 *pos, *tmp;
2134 const u8 *aad[1];
2135 size_t aad_len[1];
2136
2137 if (*key_data_len < AES_BLOCK_SIZE) {
2138 wpa_printf(MSG_INFO, "No room for AES-SIV data in the frame");
2139 return -1;
2140 }
2141
2142 if (sm->tptk_set)
2143 ptk = &sm->tptk;
2144 else if (sm->ptk_set)
2145 ptk = &sm->ptk;
2146 else
2147 return -1;
2148
2149 hdr = (struct ieee802_1x_hdr *) buf;
2150 key = (struct wpa_eapol_key *) (hdr + 1);
2151 pos = (u8 *) (key + 1);
2152 pos += 2; /* Pointing at the Encrypted Key Data field */
2153
2154 tmp = os_malloc(*key_data_len);
2155 if (!tmp)
2156 return -1;
2157
2158 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
2159 * to Key Data (exclusive). */
2160 aad[0] = buf;
2161 aad_len[0] = pos - buf;
2162 if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, *key_data_len,
2163 1, aad, aad_len, tmp) < 0) {
2164 wpa_printf(MSG_INFO, "Invalid AES-SIV data in the frame");
2165 bin_clear_free(tmp, *key_data_len);
2166 return -1;
2167 }
2168
2169 /* AEAD decryption and validation completed successfully */
2170 (*key_data_len) -= AES_BLOCK_SIZE;
2171 wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
2172 tmp, *key_data_len);
2173
2174 /* Replace Key Data field with the decrypted version */
2175 os_memcpy(pos, tmp, *key_data_len);
2176 pos -= 2; /* Key Data Length field */
2177 WPA_PUT_BE16(pos, *key_data_len);
2178 bin_clear_free(tmp, *key_data_len);
2179
2180 if (sm->tptk_set) {
2181 sm->tptk_set = 0;
2182 sm->ptk_set = 1;
2183 os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
2184 os_memset(&sm->tptk, 0, sizeof(sm->tptk));
2185 }
2186
2187 os_memcpy(sm->rx_replay_counter, key->replay_counter,
2188 WPA_REPLAY_COUNTER_LEN);
2189 sm->rx_replay_counter_set = 1;
2190
2191 return 0;
2192}
2193#endif /* CONFIG_FILS */
2194
2195
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002196/**
2197 * wpa_sm_rx_eapol - Process received WPA EAPOL frames
2198 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2199 * @src_addr: Source MAC address of the EAPOL packet
2200 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
2201 * @len: Length of the EAPOL frame
2202 * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure
2203 *
2204 * This function is called for each received EAPOL frame. Other than EAPOL-Key
2205 * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is
2206 * only processing WPA and WPA2 EAPOL-Key frames.
2207 *
2208 * The received EAPOL-Key packets are validated and valid packets are replied
2209 * to. In addition, key material (PTK, GTK) is configured at the end of a
2210 * successful key handshake.
2211 */
2212int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
2213 const u8 *buf, size_t len)
2214{
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002215 size_t plen, data_len, key_data_len;
2216 const struct ieee802_1x_hdr *hdr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002217 struct wpa_eapol_key *key;
2218 u16 key_info, ver;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002219 u8 *tmp = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002220 int ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002221 u8 *mic, *key_data;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002222 size_t mic_len, keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002223
2224#ifdef CONFIG_IEEE80211R
2225 sm->ft_completed = 0;
2226#endif /* CONFIG_IEEE80211R */
2227
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002228 mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002229 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002230
2231 if (len < sizeof(*hdr) + keyhdrlen) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002232 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2233 "WPA: EAPOL frame too short to be a WPA "
2234 "EAPOL-Key (len %lu, expecting at least %lu)",
2235 (unsigned long) len,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002236 (unsigned long) sizeof(*hdr) + keyhdrlen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002237 return 0;
2238 }
2239
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002240 hdr = (const struct ieee802_1x_hdr *) buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241 plen = be_to_host16(hdr->length);
2242 data_len = plen + sizeof(*hdr);
2243 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2244 "IEEE 802.1X RX: version=%d type=%d length=%lu",
2245 hdr->version, hdr->type, (unsigned long) plen);
2246
2247 if (hdr->version < EAPOL_VERSION) {
2248 /* TODO: backwards compatibility */
2249 }
2250 if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) {
2251 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2252 "WPA: EAPOL frame (type %u) discarded, "
2253 "not a Key frame", hdr->type);
2254 ret = 0;
2255 goto out;
2256 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002257 wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", buf, len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002258 if (plen > len - sizeof(*hdr) || plen < keyhdrlen) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002259 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2260 "WPA: EAPOL frame payload size %lu "
2261 "invalid (frame size %lu)",
2262 (unsigned long) plen, (unsigned long) len);
2263 ret = 0;
2264 goto out;
2265 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002266 if (data_len < len) {
2267 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2268 "WPA: ignoring %lu bytes after the IEEE 802.1X data",
2269 (unsigned long) len - data_len);
2270 }
2271
2272 /*
2273 * Make a copy of the frame since we need to modify the buffer during
2274 * MAC validation and Key Data decryption.
2275 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002276 tmp = os_memdup(buf, data_len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002277 if (tmp == NULL)
2278 goto out;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002279 key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002280 mic = (u8 *) (key + 1);
2281 key_data = mic + mic_len + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002282
2283 if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
2284 {
2285 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2286 "WPA: EAPOL-Key type (%d) unknown, discarded",
2287 key->type);
2288 ret = 0;
2289 goto out;
2290 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002291
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002292 key_data_len = WPA_GET_BE16(mic + mic_len);
2293 wpa_eapol_key_dump(sm, key, key_data_len, mic, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002294
2295 if (key_data_len > plen - keyhdrlen) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002296 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
2297 "frame - key_data overflow (%u > %u)",
2298 (unsigned int) key_data_len,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002299 (unsigned int) (plen - keyhdrlen));
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002300 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002301 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002302
2303 eapol_sm_notify_lower_layer_success(sm->eapol, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002304 key_info = WPA_GET_BE16(key->key_info);
2305 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
2306 if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002307 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002308 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07002309 !wpa_use_akm_defined(sm->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002310 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2311 "WPA: Unsupported EAPOL-Key descriptor version %d",
2312 ver);
2313 goto out;
2314 }
2315
Roshan Pius3a1667e2018-07-03 15:17:14 -07002316 if (wpa_use_akm_defined(sm->key_mgmt) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002317 ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
2318 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2319 "RSN: Unsupported EAPOL-Key descriptor version %d (expected AKM defined = 0)",
2320 ver);
2321 goto out;
2322 }
2323
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002324#ifdef CONFIG_IEEE80211R
2325 if (wpa_key_mgmt_ft(sm->key_mgmt)) {
2326 /* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002327 if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
2328 !wpa_use_akm_defined(sm->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002329 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2330 "FT: AP did not use AES-128-CMAC");
2331 goto out;
2332 }
2333 } else
2334#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002335 if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002336 if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07002337 !wpa_use_akm_defined(sm->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002338 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2339 "WPA: AP did not use the "
2340 "negotiated AES-128-CMAC");
2341 goto out;
2342 }
Hai Shalomc3565922019-10-28 11:58:20 -07002343 } else if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
2344 !wpa_use_akm_defined(sm->key_mgmt) &&
2345 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002346 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2347 "WPA: CCMP is used, but EAPOL-Key "
2348 "descriptor version (%d) is not 2", ver);
2349 if (sm->group_cipher != WPA_CIPHER_CCMP &&
2350 !(key_info & WPA_KEY_INFO_KEY_TYPE)) {
2351 /* Earlier versions of IEEE 802.11i did not explicitly
2352 * require version 2 descriptor for all EAPOL-Key
2353 * packets, so allow group keys to use version 1 if
2354 * CCMP is not used for them. */
2355 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2356 "WPA: Backwards compatibility: allow invalid "
2357 "version for non-CCMP group keys");
Jouni Malinen658fb4a2014-11-14 20:57:05 +02002358 } else if (ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
2359 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2360 "WPA: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002361 } else
2362 goto out;
Dmitry Shmidt71757432014-06-02 13:50:35 -07002363 } else if (sm->pairwise_cipher == WPA_CIPHER_GCMP &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07002364 !wpa_use_akm_defined(sm->key_mgmt) &&
Dmitry Shmidt71757432014-06-02 13:50:35 -07002365 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002366 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2367 "WPA: GCMP is used, but EAPOL-Key "
2368 "descriptor version (%d) is not 2", ver);
2369 goto out;
2370 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002371
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002372 if (sm->rx_replay_counter_set &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002373 os_memcmp(key->replay_counter, sm->rx_replay_counter,
2374 WPA_REPLAY_COUNTER_LEN) <= 0) {
2375 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2376 "WPA: EAPOL-Key Replay Counter did not increase - "
2377 "dropping packet");
2378 goto out;
2379 }
2380
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002381 if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
2382 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2383 "WPA: Unsupported SMK bit in key_info");
2384 goto out;
2385 }
2386
2387 if (!(key_info & WPA_KEY_INFO_ACK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002388 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2389 "WPA: No Ack bit in key_info");
2390 goto out;
2391 }
2392
2393 if (key_info & WPA_KEY_INFO_REQUEST) {
2394 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2395 "WPA: EAPOL-Key with Request bit - dropped");
2396 goto out;
2397 }
2398
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002399 if ((key_info & WPA_KEY_INFO_MIC) &&
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002400 wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002401 goto out;
2402
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002403#ifdef CONFIG_FILS
2404 if (!mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
2405 if (wpa_supp_aead_decrypt(sm, tmp, data_len, &key_data_len))
2406 goto out;
2407 }
2408#endif /* CONFIG_FILS */
2409
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002410 if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002411 (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) && mic_len) {
Hai Shalomce48b4a2018-09-05 11:41:35 -07002412 /*
2413 * Only decrypt the Key Data field if the frame's authenticity
2414 * was verified. When using AES-SIV (FILS), the MIC flag is not
2415 * set, so this check should only be performed if mic_len != 0
2416 * which is the case in this code branch.
2417 */
2418 if (!(key_info & WPA_KEY_INFO_MIC)) {
2419 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2420 "WPA: Ignore EAPOL-Key with encrypted but unauthenticated data");
2421 goto out;
2422 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002423 if (wpa_supplicant_decrypt_key_data(sm, key, mic_len,
2424 ver, key_data,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002425 &key_data_len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002426 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002427 }
2428
2429 if (key_info & WPA_KEY_INFO_KEY_TYPE) {
2430 if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
2431 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2432 "WPA: Ignored EAPOL-Key (Pairwise) with "
2433 "non-zero key index");
2434 goto out;
2435 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002436 if (key_info & (WPA_KEY_INFO_MIC |
2437 WPA_KEY_INFO_ENCR_KEY_DATA)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002438 /* 3/4 4-Way Handshake */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002439 wpa_supplicant_process_3_of_4(sm, key, ver, key_data,
2440 key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002441 } else {
2442 /* 1/4 4-Way Handshake */
2443 wpa_supplicant_process_1_of_4(sm, src_addr, key,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002444 ver, key_data,
2445 key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002446 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002447 } else {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002448 if ((mic_len && (key_info & WPA_KEY_INFO_MIC)) ||
2449 (!mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002450 /* 1/2 Group Key Handshake */
2451 wpa_supplicant_process_1_of_2(sm, src_addr, key,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002452 key_data, key_data_len,
2453 ver);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002454 } else {
2455 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002456 "WPA: EAPOL-Key (Group) without Mic/Encr bit - "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002457 "dropped");
2458 }
2459 }
2460
2461 ret = 1;
2462
2463out:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002464 bin_clear_free(tmp, data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465 return ret;
2466}
2467
2468
2469#ifdef CONFIG_CTRL_IFACE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002470static u32 wpa_key_mgmt_suite(struct wpa_sm *sm)
2471{
2472 switch (sm->key_mgmt) {
2473 case WPA_KEY_MGMT_IEEE8021X:
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002474 return ((sm->proto == WPA_PROTO_RSN ||
2475 sm->proto == WPA_PROTO_OSEN) ?
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X :
2477 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
2478 case WPA_KEY_MGMT_PSK:
2479 return (sm->proto == WPA_PROTO_RSN ?
2480 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X :
2481 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
2482#ifdef CONFIG_IEEE80211R
2483 case WPA_KEY_MGMT_FT_IEEE8021X:
2484 return RSN_AUTH_KEY_MGMT_FT_802_1X;
2485 case WPA_KEY_MGMT_FT_PSK:
2486 return RSN_AUTH_KEY_MGMT_FT_PSK;
2487#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002488 case WPA_KEY_MGMT_IEEE8021X_SHA256:
2489 return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
2490 case WPA_KEY_MGMT_PSK_SHA256:
2491 return RSN_AUTH_KEY_MGMT_PSK_SHA256;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002492 case WPA_KEY_MGMT_CCKM:
2493 return (sm->proto == WPA_PROTO_RSN ?
2494 RSN_AUTH_KEY_MGMT_CCKM:
2495 WPA_AUTH_KEY_MGMT_CCKM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002496 case WPA_KEY_MGMT_WPA_NONE:
2497 return WPA_AUTH_KEY_MGMT_NONE;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002498 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
2499 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002500 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
2501 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 default:
2503 return 0;
2504 }
2505}
2506
2507
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002508#define RSN_SUITE "%02x-%02x-%02x-%d"
2509#define RSN_SUITE_ARG(s) \
2510((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
2511
2512/**
2513 * wpa_sm_get_mib - Dump text list of MIB entries
2514 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2515 * @buf: Buffer for the list
2516 * @buflen: Length of the buffer
2517 * Returns: Number of bytes written to buffer
2518 *
2519 * This function is used fetch dot11 MIB variables.
2520 */
2521int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
2522{
2523 char pmkid_txt[PMKID_LEN * 2 + 1];
2524 int rsna, ret;
2525 size_t len;
2526
2527 if (sm->cur_pmksa) {
2528 wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
2529 sm->cur_pmksa->pmkid, PMKID_LEN);
2530 } else
2531 pmkid_txt[0] = '\0';
2532
2533 if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) ||
2534 wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) &&
2535 sm->proto == WPA_PROTO_RSN)
2536 rsna = 1;
2537 else
2538 rsna = 0;
2539
2540 ret = os_snprintf(buf, buflen,
2541 "dot11RSNAOptionImplemented=TRUE\n"
2542 "dot11RSNAPreauthenticationImplemented=TRUE\n"
2543 "dot11RSNAEnabled=%s\n"
2544 "dot11RSNAPreauthenticationEnabled=%s\n"
2545 "dot11RSNAConfigVersion=%d\n"
2546 "dot11RSNAConfigPairwiseKeysSupported=5\n"
2547 "dot11RSNAConfigGroupCipherSize=%d\n"
2548 "dot11RSNAConfigPMKLifetime=%d\n"
2549 "dot11RSNAConfigPMKReauthThreshold=%d\n"
2550 "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n"
2551 "dot11RSNAConfigSATimeout=%d\n",
2552 rsna ? "TRUE" : "FALSE",
2553 rsna ? "TRUE" : "FALSE",
2554 RSN_VERSION,
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002555 wpa_cipher_key_len(sm->group_cipher) * 8,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002556 sm->dot11RSNAConfigPMKLifetime,
2557 sm->dot11RSNAConfigPMKReauthThreshold,
2558 sm->dot11RSNAConfigSATimeout);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002559 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560 return 0;
2561 len = ret;
2562
2563 ret = os_snprintf(
2564 buf + len, buflen - len,
2565 "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
2566 "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
2567 "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
2568 "dot11RSNAPMKIDUsed=%s\n"
2569 "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
2570 "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
2571 "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
2572 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n"
2573 "dot11RSNA4WayHandshakeFailures=%u\n",
2574 RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002575 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
2576 sm->pairwise_cipher)),
2577 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
2578 sm->group_cipher)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002579 pmkid_txt,
2580 RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002581 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
2582 sm->pairwise_cipher)),
2583 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
2584 sm->group_cipher)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002585 sm->dot11RSNA4WayHandshakeFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002586 if (!os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587 len += ret;
2588
2589 return (int) len;
2590}
2591#endif /* CONFIG_CTRL_IFACE */
2592
2593
2594static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002595 void *ctx, enum pmksa_free_reason reason)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002596{
2597 struct wpa_sm *sm = ctx;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002598 int deauth = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002599
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002600 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA cache entry free_cb: "
2601 MACSTR " reason=%d", MAC2STR(entry->aa), reason);
2602
2603 if (sm->cur_pmksa == entry) {
2604 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2605 "RSN: %s current PMKSA entry",
2606 reason == PMKSA_REPLACE ? "replaced" : "removed");
2607 pmksa_cache_clear_current(sm);
2608
2609 /*
2610 * If an entry is simply being replaced, there's no need to
2611 * deauthenticate because it will be immediately re-added.
2612 * This happens when EAP authentication is completed again
2613 * (reauth or failed PMKSA caching attempt).
2614 */
2615 if (reason != PMKSA_REPLACE)
2616 deauth = 1;
2617 }
2618
2619 if (reason == PMKSA_EXPIRE &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620 (sm->pmk_len == entry->pmk_len &&
2621 os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) {
2622 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002623 "RSN: deauthenticating due to expired PMK");
2624 pmksa_cache_clear_current(sm);
2625 deauth = 1;
2626 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002627
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002628 if (deauth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002629 sm->pmk_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002630 os_memset(sm->pmk, 0, sizeof(sm->pmk));
2631 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
2632 }
2633}
2634
2635
2636/**
2637 * wpa_sm_init - Initialize WPA state machine
2638 * @ctx: Context pointer for callbacks; this needs to be an allocated buffer
2639 * Returns: Pointer to the allocated WPA state machine data
2640 *
2641 * This function is used to allocate a new WPA state machine and the returned
2642 * value is passed to all WPA state machine calls.
2643 */
2644struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
2645{
2646 struct wpa_sm *sm;
2647
2648 sm = os_zalloc(sizeof(*sm));
2649 if (sm == NULL)
2650 return NULL;
2651 dl_list_init(&sm->pmksa_candidates);
2652 sm->renew_snonce = 1;
2653 sm->ctx = ctx;
2654
2655 sm->dot11RSNAConfigPMKLifetime = 43200;
2656 sm->dot11RSNAConfigPMKReauthThreshold = 70;
2657 sm->dot11RSNAConfigSATimeout = 60;
2658
2659 sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm);
2660 if (sm->pmksa == NULL) {
2661 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
2662 "RSN: PMKSA cache initialization failed");
2663 os_free(sm);
2664 return NULL;
2665 }
2666
2667 return sm;
2668}
2669
2670
2671/**
2672 * wpa_sm_deinit - Deinitialize WPA state machine
2673 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2674 */
2675void wpa_sm_deinit(struct wpa_sm *sm)
2676{
2677 if (sm == NULL)
2678 return;
2679 pmksa_cache_deinit(sm->pmksa);
2680 eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
2681 eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
2682 os_free(sm->assoc_wpa_ie);
Hai Shalomc3565922019-10-28 11:58:20 -07002683 os_free(sm->assoc_rsnxe);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002684 os_free(sm->ap_wpa_ie);
2685 os_free(sm->ap_rsn_ie);
Hai Shalomc3565922019-10-28 11:58:20 -07002686 os_free(sm->ap_rsnxe);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002687 wpa_sm_drop_sa(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002688 os_free(sm->ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002689#ifdef CONFIG_IEEE80211R
2690 os_free(sm->assoc_resp_ies);
2691#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002692#ifdef CONFIG_TESTING_OPTIONS
2693 wpabuf_free(sm->test_assoc_ie);
2694#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002695#ifdef CONFIG_FILS_SK_PFS
2696 crypto_ecdh_deinit(sm->fils_ecdh);
2697#endif /* CONFIG_FILS_SK_PFS */
2698#ifdef CONFIG_FILS
2699 wpabuf_free(sm->fils_ft_ies);
2700#endif /* CONFIG_FILS */
2701#ifdef CONFIG_OWE
2702 crypto_ecdh_deinit(sm->owe_ecdh);
2703#endif /* CONFIG_OWE */
Hai Shalom021b0b52019-04-10 11:17:58 -07002704#ifdef CONFIG_DPP2
2705 wpabuf_clear_free(sm->dpp_z);
2706#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002707 os_free(sm);
2708}
2709
2710
2711/**
2712 * wpa_sm_notify_assoc - Notify WPA state machine about association
2713 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2714 * @bssid: The BSSID of the new association
2715 *
2716 * This function is called to let WPA state machine know that the connection
2717 * was established.
2718 */
2719void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
2720{
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02002721 int clear_keys = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722
2723 if (sm == NULL)
2724 return;
2725
2726 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2727 "WPA: Association event - clear replay counter");
2728 os_memcpy(sm->bssid, bssid, ETH_ALEN);
2729 os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
2730 sm->rx_replay_counter_set = 0;
2731 sm->renew_snonce = 1;
2732 if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0)
2733 rsn_preauth_deinit(sm);
2734
2735#ifdef CONFIG_IEEE80211R
2736 if (wpa_ft_is_completed(sm)) {
2737 /*
2738 * Clear portValid to kick EAPOL state machine to re-enter
2739 * AUTHENTICATED state to get the EAPOL port Authorized.
2740 */
2741 eapol_sm_notify_portValid(sm->eapol, FALSE);
2742 wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
2743
2744 /* Prepare for the next transition */
2745 wpa_ft_prepare_auth_request(sm, NULL);
2746
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02002747 clear_keys = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07002748 sm->ft_protocol = 1;
2749 } else {
2750 sm->ft_protocol = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002751 }
2752#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002753#ifdef CONFIG_FILS
2754 if (sm->fils_completed) {
2755 /*
2756 * Clear portValid to kick EAPOL state machine to re-enter
2757 * AUTHENTICATED state to get the EAPOL port Authorized.
2758 */
2759 wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02002760 clear_keys = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002761 }
2762#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002763
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02002764 if (clear_keys) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002765 /*
2766 * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if
2767 * this is not part of a Fast BSS Transition.
2768 */
2769 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK");
2770 sm->ptk_set = 0;
Dmitry Shmidt61593f02014-04-21 16:27:35 -07002771 os_memset(&sm->ptk, 0, sizeof(sm->ptk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002772 sm->tptk_set = 0;
Dmitry Shmidt61593f02014-04-21 16:27:35 -07002773 os_memset(&sm->tptk, 0, sizeof(sm->tptk));
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02002774 os_memset(&sm->gtk, 0, sizeof(sm->gtk));
Jouni Malinen58c0e962017-10-01 12:12:24 +03002775 os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02002776 os_memset(&sm->igtk, 0, sizeof(sm->igtk));
Jouni Malinen58c0e962017-10-01 12:12:24 +03002777 os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 }
2779
2780#ifdef CONFIG_TDLS
2781 wpa_tdls_assoc(sm);
2782#endif /* CONFIG_TDLS */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002783
2784#ifdef CONFIG_P2P
2785 os_memset(sm->p2p_ip_addr, 0, sizeof(sm->p2p_ip_addr));
2786#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002787}
2788
2789
2790/**
2791 * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation
2792 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2793 *
2794 * This function is called to let WPA state machine know that the connection
2795 * was lost. This will abort any existing pre-authentication session.
2796 */
2797void wpa_sm_notify_disassoc(struct wpa_sm *sm)
2798{
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07002799 eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
2800 eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002801 rsn_preauth_deinit(sm);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002802 pmksa_cache_clear_current(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803 if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE)
2804 sm->dot11RSNA4WayHandshakeFailures++;
2805#ifdef CONFIG_TDLS
2806 wpa_tdls_disassoc(sm);
2807#endif /* CONFIG_TDLS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002808#ifdef CONFIG_FILS
2809 sm->fils_completed = 0;
2810#endif /* CONFIG_FILS */
Jouni Malinen4283f9e2017-09-22 12:06:37 +03002811#ifdef CONFIG_IEEE80211R
2812 sm->ft_reassoc_completed = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07002813 sm->ft_protocol = 0;
Jouni Malinen4283f9e2017-09-22 12:06:37 +03002814#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002815
2816 /* Keys are not needed in the WPA state machine anymore */
2817 wpa_sm_drop_sa(sm);
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07002818
2819 sm->msg_3_of_4_ok = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002820 os_memset(sm->bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002821}
2822
2823
2824/**
2825 * wpa_sm_set_pmk - Set PMK
2826 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2827 * @pmk: The new PMK
2828 * @pmk_len: The length of the new PMK in bytes
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002829 * @pmkid: Calculated PMKID
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002830 * @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002831 *
2832 * Configure the PMK for WPA state machine.
2833 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002834void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002835 const u8 *pmkid, const u8 *bssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002836{
2837 if (sm == NULL)
2838 return;
2839
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002840 wpa_hexdump_key(MSG_DEBUG, "WPA: Set PMK based on external data",
2841 pmk, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002842 sm->pmk_len = pmk_len;
2843 os_memcpy(sm->pmk, pmk, pmk_len);
2844
2845#ifdef CONFIG_IEEE80211R
2846 /* Set XXKey to be PSK for FT key derivation */
2847 sm->xxkey_len = pmk_len;
2848 os_memcpy(sm->xxkey, pmk, pmk_len);
2849#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002850
2851 if (bssid) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002852 pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002853 bssid, sm->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002854 sm->network_ctx, sm->key_mgmt, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002855 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002856}
2857
2858
2859/**
2860 * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA
2861 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2862 *
2863 * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK
2864 * will be cleared.
2865 */
2866void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm)
2867{
2868 if (sm == NULL)
2869 return;
2870
2871 if (sm->cur_pmksa) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002872 wpa_hexdump_key(MSG_DEBUG,
2873 "WPA: Set PMK based on current PMKSA",
2874 sm->cur_pmksa->pmk, sm->cur_pmksa->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002875 sm->pmk_len = sm->cur_pmksa->pmk_len;
2876 os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len);
2877 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002878 wpa_printf(MSG_DEBUG, "WPA: No current PMKSA - clear PMK");
2879 sm->pmk_len = 0;
2880 os_memset(sm->pmk, 0, PMK_LEN_MAX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002881 }
2882}
2883
2884
2885/**
2886 * wpa_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled
2887 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2888 * @fast_reauth: Whether fast reauthentication (EAP) is allowed
2889 */
2890void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth)
2891{
2892 if (sm)
2893 sm->fast_reauth = fast_reauth;
2894}
2895
2896
2897/**
2898 * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks
2899 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2900 * @scard_ctx: Context pointer for smartcard related callback functions
2901 */
2902void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx)
2903{
2904 if (sm == NULL)
2905 return;
2906 sm->scard_ctx = scard_ctx;
2907 if (sm->preauth_eapol)
2908 eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx);
2909}
2910
2911
2912/**
2913 * wpa_sm_set_config - Notification of current configration change
2914 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2915 * @config: Pointer to current network configuration
2916 *
2917 * Notify WPA state machine that configuration has changed. config will be
2918 * stored as a backpointer to network configuration. This can be %NULL to clear
2919 * the stored pointed.
2920 */
2921void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
2922{
2923 if (!sm)
2924 return;
2925
2926 if (config) {
2927 sm->network_ctx = config->network_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928 sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher;
2929 sm->proactive_key_caching = config->proactive_key_caching;
2930 sm->eap_workaround = config->eap_workaround;
2931 sm->eap_conf_ctx = config->eap_conf_ctx;
2932 if (config->ssid) {
2933 os_memcpy(sm->ssid, config->ssid, config->ssid_len);
2934 sm->ssid_len = config->ssid_len;
2935 } else
2936 sm->ssid_len = 0;
2937 sm->wpa_ptk_rekey = config->wpa_ptk_rekey;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002938 sm->p2p = config->p2p;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002939 sm->wpa_rsc_relaxation = config->wpa_rsc_relaxation;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002940#ifdef CONFIG_FILS
2941 if (config->fils_cache_id) {
2942 sm->fils_cache_id_set = 1;
2943 os_memcpy(sm->fils_cache_id, config->fils_cache_id,
2944 FILS_CACHE_ID_LEN);
2945 } else {
2946 sm->fils_cache_id_set = 0;
2947 }
2948#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002949 } else {
2950 sm->network_ctx = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002951 sm->allowed_pairwise_cipher = 0;
2952 sm->proactive_key_caching = 0;
2953 sm->eap_workaround = 0;
2954 sm->eap_conf_ctx = NULL;
2955 sm->ssid_len = 0;
2956 sm->wpa_ptk_rekey = 0;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002957 sm->p2p = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002958 sm->wpa_rsc_relaxation = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002959 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002960}
2961
2962
2963/**
2964 * wpa_sm_set_own_addr - Set own MAC address
2965 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2966 * @addr: Own MAC address
2967 */
2968void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr)
2969{
2970 if (sm)
2971 os_memcpy(sm->own_addr, addr, ETH_ALEN);
2972}
2973
2974
2975/**
2976 * wpa_sm_set_ifname - Set network interface name
2977 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2978 * @ifname: Interface name
2979 * @bridge_ifname: Optional bridge interface name (for pre-auth)
2980 */
2981void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname,
2982 const char *bridge_ifname)
2983{
2984 if (sm) {
2985 sm->ifname = ifname;
2986 sm->bridge_ifname = bridge_ifname;
2987 }
2988}
2989
2990
2991/**
2992 * wpa_sm_set_eapol - Set EAPOL state machine pointer
2993 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2994 * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init()
2995 */
2996void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol)
2997{
2998 if (sm)
2999 sm->eapol = eapol;
3000}
3001
3002
3003/**
3004 * wpa_sm_set_param - Set WPA state machine parameters
3005 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3006 * @param: Parameter field
3007 * @value: Parameter value
3008 * Returns: 0 on success, -1 on failure
3009 */
3010int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
3011 unsigned int value)
3012{
3013 int ret = 0;
3014
3015 if (sm == NULL)
3016 return -1;
3017
3018 switch (param) {
3019 case RSNA_PMK_LIFETIME:
3020 if (value > 0)
3021 sm->dot11RSNAConfigPMKLifetime = value;
3022 else
3023 ret = -1;
3024 break;
3025 case RSNA_PMK_REAUTH_THRESHOLD:
3026 if (value > 0 && value <= 100)
3027 sm->dot11RSNAConfigPMKReauthThreshold = value;
3028 else
3029 ret = -1;
3030 break;
3031 case RSNA_SA_TIMEOUT:
3032 if (value > 0)
3033 sm->dot11RSNAConfigSATimeout = value;
3034 else
3035 ret = -1;
3036 break;
3037 case WPA_PARAM_PROTO:
3038 sm->proto = value;
3039 break;
3040 case WPA_PARAM_PAIRWISE:
3041 sm->pairwise_cipher = value;
3042 break;
3043 case WPA_PARAM_GROUP:
3044 sm->group_cipher = value;
3045 break;
3046 case WPA_PARAM_KEY_MGMT:
3047 sm->key_mgmt = value;
3048 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003049 case WPA_PARAM_MGMT_GROUP:
3050 sm->mgmt_group_cipher = value;
3051 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003052 case WPA_PARAM_RSN_ENABLED:
3053 sm->rsn_enabled = value;
3054 break;
3055 case WPA_PARAM_MFP:
3056 sm->mfp = value;
3057 break;
Hai Shalom74f70d42019-02-11 14:42:39 -08003058 case WPA_PARAM_OCV:
3059 sm->ocv = value;
3060 break;
Hai Shalomc3565922019-10-28 11:58:20 -07003061 case WPA_PARAM_SAE_PWE:
3062 sm->sae_pwe = value;
3063 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003064 default:
3065 break;
3066 }
3067
3068 return ret;
3069}
3070
3071
3072/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003073 * wpa_sm_get_status - Get WPA state machine
3074 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3075 * @buf: Buffer for status information
3076 * @buflen: Maximum buffer length
3077 * @verbose: Whether to include verbose status information
3078 * Returns: Number of bytes written to buf.
3079 *
3080 * Query WPA state machine for status information. This function fills in
3081 * a text area with current status information. If the buffer (buf) is not
3082 * large enough, status information will be truncated to fit the buffer.
3083 */
3084int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
3085 int verbose)
3086{
3087 char *pos = buf, *end = buf + buflen;
3088 int ret;
3089
3090 ret = os_snprintf(pos, end - pos,
3091 "pairwise_cipher=%s\n"
3092 "group_cipher=%s\n"
3093 "key_mgmt=%s\n",
3094 wpa_cipher_txt(sm->pairwise_cipher),
3095 wpa_cipher_txt(sm->group_cipher),
3096 wpa_key_mgmt_txt(sm->key_mgmt, sm->proto));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003097 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003098 return pos - buf;
3099 pos += ret;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003100
3101 if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) {
3102 struct wpa_ie_data rsn;
3103 if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn)
3104 >= 0 &&
3105 rsn.capabilities & (WPA_CAPABILITY_MFPR |
3106 WPA_CAPABILITY_MFPC)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003107 ret = os_snprintf(pos, end - pos, "pmf=%d\n"
3108 "mgmt_group_cipher=%s\n",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003109 (rsn.capabilities &
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003110 WPA_CAPABILITY_MFPR) ? 2 : 1,
3111 wpa_cipher_txt(
3112 sm->mgmt_group_cipher));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003113 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003114 return pos - buf;
3115 pos += ret;
3116 }
3117 }
3118
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003119 return pos - buf;
3120}
3121
3122
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003123int wpa_sm_pmf_enabled(struct wpa_sm *sm)
3124{
3125 struct wpa_ie_data rsn;
3126
3127 if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie)
3128 return 0;
3129
3130 if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 &&
3131 rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC))
3132 return 1;
3133
3134 return 0;
3135}
3136
3137
Hai Shalom74f70d42019-02-11 14:42:39 -08003138int wpa_sm_ocv_enabled(struct wpa_sm *sm)
3139{
3140 struct wpa_ie_data rsn;
3141
3142 if (!sm->ocv || !sm->ap_rsn_ie)
3143 return 0;
3144
3145 return wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len,
3146 &rsn) >= 0 &&
3147 (rsn.capabilities & WPA_CAPABILITY_OCVC);
3148}
3149
3150
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003151/**
3152 * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration
3153 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3154 * @wpa_ie: Pointer to buffer for WPA/RSN IE
3155 * @wpa_ie_len: Pointer to the length of the wpa_ie buffer
3156 * Returns: 0 on success, -1 on failure
3157 */
3158int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
3159 size_t *wpa_ie_len)
3160{
3161 int res;
3162
3163 if (sm == NULL)
3164 return -1;
3165
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003166#ifdef CONFIG_TESTING_OPTIONS
3167 if (sm->test_assoc_ie) {
3168 wpa_printf(MSG_DEBUG,
3169 "TESTING: Replace association WPA/RSN IE");
3170 if (*wpa_ie_len < wpabuf_len(sm->test_assoc_ie))
3171 return -1;
3172 os_memcpy(wpa_ie, wpabuf_head(sm->test_assoc_ie),
3173 wpabuf_len(sm->test_assoc_ie));
3174 res = wpabuf_len(sm->test_assoc_ie);
3175 } else
3176#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003177 res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len);
3178 if (res < 0)
3179 return -1;
3180 *wpa_ie_len = res;
3181
3182 wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default",
3183 wpa_ie, *wpa_ie_len);
3184
3185 if (sm->assoc_wpa_ie == NULL) {
3186 /*
3187 * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets
3188 * the correct version of the IE even if PMKSA caching is
3189 * aborted (which would remove PMKID from IE generation).
3190 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003191 sm->assoc_wpa_ie = os_memdup(wpa_ie, *wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003192 if (sm->assoc_wpa_ie == NULL)
3193 return -1;
3194
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003195 sm->assoc_wpa_ie_len = *wpa_ie_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003196 } else {
3197 wpa_hexdump(MSG_DEBUG,
3198 "WPA: Leave previously set WPA IE default",
3199 sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003200 }
3201
3202 return 0;
3203}
3204
3205
3206/**
3207 * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq
3208 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3209 * @ie: Pointer to IE data (starting from id)
3210 * @len: IE length
3211 * Returns: 0 on success, -1 on failure
3212 *
3213 * Inform WPA state machine about the WPA/RSN IE used in (Re)Association
3214 * Request frame. The IE will be used to override the default value generated
3215 * with wpa_sm_set_assoc_wpa_ie_default().
3216 */
3217int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
3218{
3219 if (sm == NULL)
3220 return -1;
3221
3222 os_free(sm->assoc_wpa_ie);
3223 if (ie == NULL || len == 0) {
3224 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3225 "WPA: clearing own WPA/RSN IE");
3226 sm->assoc_wpa_ie = NULL;
3227 sm->assoc_wpa_ie_len = 0;
3228 } else {
3229 wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003230 sm->assoc_wpa_ie = os_memdup(ie, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003231 if (sm->assoc_wpa_ie == NULL)
3232 return -1;
3233
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003234 sm->assoc_wpa_ie_len = len;
3235 }
3236
3237 return 0;
3238}
3239
3240
3241/**
Hai Shalomc3565922019-10-28 11:58:20 -07003242 * wpa_sm_set_assoc_rsnxe_default - Generate own RSNXE from configuration
3243 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3244 * @rsnxe: Pointer to buffer for RSNXE
3245 * @rsnxe_len: Pointer to the length of the rsne buffer
3246 * Returns: 0 on success, -1 on failure
3247 */
3248int wpa_sm_set_assoc_rsnxe_default(struct wpa_sm *sm, u8 *rsnxe,
3249 size_t *rsnxe_len)
3250{
3251 int res;
3252
3253 if (!sm)
3254 return -1;
3255
3256 res = wpa_gen_rsnxe(sm, rsnxe, *rsnxe_len);
3257 if (res < 0)
3258 return -1;
3259 *rsnxe_len = res;
3260
3261 wpa_hexdump(MSG_DEBUG, "RSN: Set own RSNXE default", rsnxe, *rsnxe_len);
3262
3263 if (sm->assoc_rsnxe) {
3264 wpa_hexdump(MSG_DEBUG,
3265 "RSN: Leave previously set RSNXE default",
3266 sm->assoc_rsnxe, sm->assoc_rsnxe_len);
3267 } else if (*rsnxe_len > 0) {
3268 /*
3269 * Make a copy of the RSNXE so that 4-Way Handshake gets the
3270 * correct version of the IE even if it gets changed.
3271 */
3272 sm->assoc_rsnxe = os_memdup(rsnxe, *rsnxe_len);
3273 if (!sm->assoc_rsnxe)
3274 return -1;
3275
3276 sm->assoc_rsnxe_len = *rsnxe_len;
3277 }
3278
3279 return 0;
3280}
3281
3282
3283/**
3284 * wpa_sm_set_assoc_rsnxe - Set own RSNXE from (Re)AssocReq
3285 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3286 * @ie: Pointer to IE data (starting from id)
3287 * @len: IE length
3288 * Returns: 0 on success, -1 on failure
3289 *
3290 * Inform WPA state machine about the RSNXE used in (Re)Association Request
3291 * frame. The IE will be used to override the default value generated
3292 * with wpa_sm_set_assoc_rsnxe_default().
3293 */
3294int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
3295{
3296 if (!sm)
3297 return -1;
3298
3299 os_free(sm->assoc_rsnxe);
3300 if (!ie || len == 0) {
3301 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3302 "RSN: clearing own RSNXE");
3303 sm->assoc_rsnxe = NULL;
3304 sm->assoc_rsnxe_len = 0;
3305 } else {
3306 wpa_hexdump(MSG_DEBUG, "RSN: set own RSNXE", ie, len);
3307 sm->assoc_rsnxe = os_memdup(ie, len);
3308 if (!sm->assoc_rsnxe)
3309 return -1;
3310
3311 sm->assoc_rsnxe_len = len;
3312 }
3313
3314 return 0;
3315}
3316
3317
3318/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003319 * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp
3320 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3321 * @ie: Pointer to IE data (starting from id)
3322 * @len: IE length
3323 * Returns: 0 on success, -1 on failure
3324 *
3325 * Inform WPA state machine about the WPA IE used in Beacon / Probe Response
3326 * frame.
3327 */
3328int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
3329{
3330 if (sm == NULL)
3331 return -1;
3332
3333 os_free(sm->ap_wpa_ie);
3334 if (ie == NULL || len == 0) {
3335 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3336 "WPA: clearing AP WPA IE");
3337 sm->ap_wpa_ie = NULL;
3338 sm->ap_wpa_ie_len = 0;
3339 } else {
3340 wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003341 sm->ap_wpa_ie = os_memdup(ie, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003342 if (sm->ap_wpa_ie == NULL)
3343 return -1;
3344
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003345 sm->ap_wpa_ie_len = len;
3346 }
3347
3348 return 0;
3349}
3350
3351
3352/**
3353 * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp
3354 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3355 * @ie: Pointer to IE data (starting from id)
3356 * @len: IE length
3357 * Returns: 0 on success, -1 on failure
3358 *
3359 * Inform WPA state machine about the RSN IE used in Beacon / Probe Response
3360 * frame.
3361 */
3362int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
3363{
3364 if (sm == NULL)
3365 return -1;
3366
3367 os_free(sm->ap_rsn_ie);
3368 if (ie == NULL || len == 0) {
3369 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3370 "WPA: clearing AP RSN IE");
3371 sm->ap_rsn_ie = NULL;
3372 sm->ap_rsn_ie_len = 0;
3373 } else {
3374 wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003375 sm->ap_rsn_ie = os_memdup(ie, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003376 if (sm->ap_rsn_ie == NULL)
3377 return -1;
3378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003379 sm->ap_rsn_ie_len = len;
3380 }
3381
3382 return 0;
3383}
3384
3385
3386/**
Hai Shalomc3565922019-10-28 11:58:20 -07003387 * wpa_sm_set_ap_rsnxe - Set AP RSNXE from Beacon/ProbeResp
3388 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3389 * @ie: Pointer to IE data (starting from id)
3390 * @len: IE length
3391 * Returns: 0 on success, -1 on failure
3392 *
3393 * Inform WPA state machine about the RSNXE used in Beacon / Probe Response
3394 * frame.
3395 */
3396int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
3397{
3398 if (!sm)
3399 return -1;
3400
3401 os_free(sm->ap_rsnxe);
3402 if (!ie || len == 0) {
3403 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: clearing AP RSNXE");
3404 sm->ap_rsnxe = NULL;
3405 sm->ap_rsnxe_len = 0;
3406 } else {
3407 wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
3408 sm->ap_rsnxe = os_memdup(ie, len);
3409 if (!sm->ap_rsnxe)
3410 return -1;
3411
3412 sm->ap_rsnxe_len = len;
3413 }
3414
3415 return 0;
3416}
3417
3418
3419/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003420 * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
3421 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3422 * @data: Pointer to data area for parsing results
3423 * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure
3424 *
3425 * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the
3426 * parsed data into data.
3427 */
3428int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data)
3429{
3430 if (sm == NULL)
3431 return -1;
3432
3433 if (sm->assoc_wpa_ie == NULL) {
3434 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3435 "WPA: No WPA/RSN IE available from association info");
3436 return -1;
3437 }
3438 if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data))
3439 return -2;
3440 return 0;
3441}
3442
3443
3444int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
3445{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003446 return pmksa_cache_list(sm->pmksa, buf, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003447}
3448
3449
Dmitry Shmidt29333592017-01-09 12:27:11 -08003450struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_head(struct wpa_sm *sm)
3451{
3452 return pmksa_cache_head(sm->pmksa);
3453}
3454
3455
3456struct rsn_pmksa_cache_entry *
3457wpa_sm_pmksa_cache_add_entry(struct wpa_sm *sm,
3458 struct rsn_pmksa_cache_entry * entry)
3459{
3460 return pmksa_cache_add_entry(sm->pmksa, entry);
3461}
3462
3463
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003464void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
3465 const u8 *pmkid, const u8 *bssid,
3466 const u8 *fils_cache_id)
3467{
3468 sm->cur_pmksa = pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
3469 bssid, sm->own_addr, sm->network_ctx,
3470 sm->key_mgmt, fils_cache_id);
3471}
3472
3473
3474int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid,
3475 const void *network_ctx)
3476{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003477 return pmksa_cache_get(sm->pmksa, bssid, NULL, network_ctx, 0) != NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003478}
3479
3480
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003481void wpa_sm_drop_sa(struct wpa_sm *sm)
3482{
3483 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK");
3484 sm->ptk_set = 0;
3485 sm->tptk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003486 sm->pmk_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003487 os_memset(sm->pmk, 0, sizeof(sm->pmk));
3488 os_memset(&sm->ptk, 0, sizeof(sm->ptk));
3489 os_memset(&sm->tptk, 0, sizeof(sm->tptk));
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02003490 os_memset(&sm->gtk, 0, sizeof(sm->gtk));
Jouni Malinen58c0e962017-10-01 12:12:24 +03003491 os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02003492 os_memset(&sm->igtk, 0, sizeof(sm->igtk));
Jouni Malinen58c0e962017-10-01 12:12:24 +03003493 os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003494#ifdef CONFIG_IEEE80211R
3495 os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003496 sm->xxkey_len = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003497 os_memset(sm->pmk_r0, 0, sizeof(sm->pmk_r0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003498 sm->pmk_r0_len = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003499 os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003500 sm->pmk_r1_len = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003501#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003502}
3503
3504
3505int wpa_sm_has_ptk(struct wpa_sm *sm)
3506{
3507 if (sm == NULL)
3508 return 0;
3509 return sm->ptk_set;
3510}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003511
3512
3513void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr)
3514{
3515 os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN);
3516}
3517
3518
3519void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
3520{
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003521 pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003522}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003523
3524
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003525#ifdef CONFIG_WNM
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003526int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
3527{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003528 u16 keyinfo;
3529 u8 keylen; /* plaintext key len */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003530 u8 *key_rsc;
3531
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003532 if (subelem_id == WNM_SLEEP_SUBELEM_GTK) {
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003533 struct wpa_gtk_data gd;
3534
3535 os_memset(&gd, 0, sizeof(gd));
3536 keylen = wpa_cipher_key_len(sm->group_cipher);
3537 gd.key_rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
3538 gd.alg = wpa_cipher_to_alg(sm->group_cipher);
3539 if (gd.alg == WPA_ALG_NONE) {
3540 wpa_printf(MSG_DEBUG, "Unsupported group cipher suite");
3541 return -1;
3542 }
3543
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003544 key_rsc = buf + 5;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003545 keyinfo = WPA_GET_LE16(buf + 2);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003546 gd.gtk_len = keylen;
3547 if (gd.gtk_len != buf[4]) {
3548 wpa_printf(MSG_DEBUG, "GTK len mismatch len %d vs %d",
3549 gd.gtk_len, buf[4]);
3550 return -1;
3551 }
3552 gd.keyidx = keyinfo & 0x03; /* B0 - B1 */
3553 gd.tx = wpa_supplicant_gtk_tx_bit_workaround(
3554 sm, !!(keyinfo & WPA_KEY_INFO_TXRX));
3555
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003556 os_memcpy(gd.gtk, buf + 13, gd.gtk_len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003557
3558 wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
3559 gd.gtk, gd.gtk_len);
Jouni Malinen58c0e962017-10-01 12:12:24 +03003560 if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 1)) {
Hai Shalom81f62d82019-07-22 12:10:00 -07003561 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003562 wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
3563 "WNM mode");
3564 return -1;
3565 }
Hai Shalom81f62d82019-07-22 12:10:00 -07003566 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003567 } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02003568 const struct wpa_igtk_kde *igtk;
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003569
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02003570 igtk = (const struct wpa_igtk_kde *) (buf + 2);
Jouni Malinen58c0e962017-10-01 12:12:24 +03003571 if (wpa_supplicant_install_igtk(sm, igtk, 1) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003572 return -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003573 } else {
3574 wpa_printf(MSG_DEBUG, "Unknown element id");
3575 return -1;
3576 }
3577
3578 return 0;
3579}
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003580#endif /* CONFIG_WNM */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003581
3582
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003583#ifdef CONFIG_P2P
3584
3585int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf)
3586{
3587 if (sm == NULL || WPA_GET_BE32(sm->p2p_ip_addr) == 0)
3588 return -1;
3589 os_memcpy(buf, sm->p2p_ip_addr, 3 * 4);
3590 return 0;
3591}
3592
3593#endif /* CONFIG_P2P */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003594
3595
3596void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, const u8 *rx_replay_counter)
3597{
3598 if (rx_replay_counter == NULL)
3599 return;
3600
3601 os_memcpy(sm->rx_replay_counter, rx_replay_counter,
3602 WPA_REPLAY_COUNTER_LEN);
3603 sm->rx_replay_counter_set = 1;
3604 wpa_printf(MSG_DEBUG, "Updated key replay counter");
3605}
3606
3607
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003608void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm,
3609 const u8 *ptk_kck, size_t ptk_kck_len,
3610 const u8 *ptk_kek, size_t ptk_kek_len)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003611{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003612 if (ptk_kck && ptk_kck_len <= WPA_KCK_MAX_LEN) {
3613 os_memcpy(sm->ptk.kck, ptk_kck, ptk_kck_len);
3614 sm->ptk.kck_len = ptk_kck_len;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003615 wpa_printf(MSG_DEBUG, "Updated PTK KCK");
3616 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003617 if (ptk_kek && ptk_kek_len <= WPA_KEK_MAX_LEN) {
3618 os_memcpy(sm->ptk.kek, ptk_kek, ptk_kek_len);
3619 sm->ptk.kek_len = ptk_kek_len;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003620 wpa_printf(MSG_DEBUG, "Updated PTK KEK");
3621 }
3622 sm->ptk_set = 1;
3623}
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003624
3625
3626#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003627
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003628void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf)
3629{
3630 wpabuf_free(sm->test_assoc_ie);
3631 sm->test_assoc_ie = buf;
3632}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003633
3634
3635const u8 * wpa_sm_get_anonce(struct wpa_sm *sm)
3636{
3637 return sm->anonce;
3638}
3639
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003640#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003641
3642
Roshan Pius3a1667e2018-07-03 15:17:14 -07003643unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm)
3644{
3645 return sm->key_mgmt;
3646}
3647
3648
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003649#ifdef CONFIG_FILS
3650
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003651struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003652{
3653 struct wpabuf *buf = NULL;
3654 struct wpabuf *erp_msg;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003655 struct wpabuf *pub = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003656
3657 erp_msg = eapol_sm_build_erp_reauth_start(sm->eapol);
3658 if (!erp_msg && !sm->cur_pmksa) {
3659 wpa_printf(MSG_DEBUG,
3660 "FILS: Neither ERP EAP-Initiate/Re-auth nor PMKSA cache entry is available - skip FILS");
3661 goto fail;
3662 }
3663
3664 wpa_printf(MSG_DEBUG, "FILS: Try to use FILS (erp=%d pmksa_cache=%d)",
3665 erp_msg != NULL, sm->cur_pmksa != NULL);
3666
3667 sm->fils_completed = 0;
3668
3669 if (!sm->assoc_wpa_ie) {
3670 wpa_printf(MSG_INFO, "FILS: No own RSN IE set for FILS");
3671 goto fail;
3672 }
3673
3674 if (random_get_bytes(sm->fils_nonce, FILS_NONCE_LEN) < 0 ||
3675 random_get_bytes(sm->fils_session, FILS_SESSION_LEN) < 0)
3676 goto fail;
3677
3678 wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Nonce",
3679 sm->fils_nonce, FILS_NONCE_LEN);
3680 wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Session",
3681 sm->fils_session, FILS_SESSION_LEN);
3682
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003683#ifdef CONFIG_FILS_SK_PFS
3684 sm->fils_dh_group = dh_group;
3685 if (dh_group) {
3686 crypto_ecdh_deinit(sm->fils_ecdh);
3687 sm->fils_ecdh = crypto_ecdh_init(dh_group);
3688 if (!sm->fils_ecdh) {
3689 wpa_printf(MSG_INFO,
3690 "FILS: Could not initialize ECDH with group %d",
3691 dh_group);
3692 goto fail;
3693 }
3694 pub = crypto_ecdh_get_pubkey(sm->fils_ecdh, 1);
3695 if (!pub)
3696 goto fail;
3697 wpa_hexdump_buf(MSG_DEBUG, "FILS: Element (DH public key)",
3698 pub);
3699 sm->fils_dh_elem_len = wpabuf_len(pub);
3700 }
3701#endif /* CONFIG_FILS_SK_PFS */
3702
3703 buf = wpabuf_alloc(1000 + sm->assoc_wpa_ie_len +
3704 (pub ? wpabuf_len(pub) : 0));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003705 if (!buf)
3706 goto fail;
3707
3708 /* Fields following the Authentication algorithm number field */
3709
3710 /* Authentication Transaction seq# */
3711 wpabuf_put_le16(buf, 1);
3712
3713 /* Status Code */
3714 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
3715
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003716 /* TODO: FILS PK */
3717#ifdef CONFIG_FILS_SK_PFS
3718 if (dh_group) {
3719 /* Finite Cyclic Group */
3720 wpabuf_put_le16(buf, dh_group);
3721 /* Element */
3722 wpabuf_put_buf(buf, pub);
3723 }
3724#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003725
3726 /* RSNE */
3727 wpa_hexdump(MSG_DEBUG, "FILS: RSNE in FILS Authentication frame",
3728 sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
3729 wpabuf_put_data(buf, sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
3730
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003731 if (md) {
3732 /* MDE when using FILS for FT initial association */
3733 struct rsn_mdie *mdie;
3734
3735 wpabuf_put_u8(buf, WLAN_EID_MOBILITY_DOMAIN);
3736 wpabuf_put_u8(buf, sizeof(*mdie));
3737 mdie = wpabuf_put(buf, sizeof(*mdie));
3738 os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
3739 mdie->ft_capab = 0;
3740 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003741
3742 /* FILS Nonce */
3743 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
3744 wpabuf_put_u8(buf, 1 + FILS_NONCE_LEN); /* Length */
3745 /* Element ID Extension */
3746 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_NONCE);
3747 wpabuf_put_data(buf, sm->fils_nonce, FILS_NONCE_LEN);
3748
3749 /* FILS Session */
3750 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
3751 wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN); /* Length */
3752 /* Element ID Extension */
3753 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
3754 wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN);
3755
3756 /* FILS Wrapped Data */
Paul Stewart092955c2017-02-06 09:13:09 -08003757 sm->fils_erp_pmkid_set = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003758 if (erp_msg) {
3759 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
3760 wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg)); /* Length */
3761 /* Element ID Extension */
3762 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_WRAPPED_DATA);
3763 wpabuf_put_buf(buf, erp_msg);
Paul Stewart092955c2017-02-06 09:13:09 -08003764 /* Calculate pending PMKID here so that we do not need to
3765 * maintain a copy of the EAP-Initiate/Reauth message. */
3766 if (fils_pmkid_erp(sm->key_mgmt, wpabuf_head(erp_msg),
3767 wpabuf_len(erp_msg),
3768 sm->fils_erp_pmkid) == 0)
3769 sm->fils_erp_pmkid_set = 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003770 }
3771
3772 wpa_hexdump_buf(MSG_DEBUG, "RSN: FILS fields for Authentication frame",
3773 buf);
3774
3775fail:
3776 wpabuf_free(erp_msg);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003777 wpabuf_free(pub);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003778 return buf;
3779}
3780
3781
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003782int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
3783 size_t len)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003784{
3785 const u8 *pos, *end;
3786 struct ieee802_11_elems elems;
3787 struct wpa_ie_data rsn;
3788 int pmkid_match = 0;
3789 u8 ick[FILS_ICK_MAX_LEN];
3790 size_t ick_len;
3791 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003792 struct wpabuf *dh_ss = NULL;
3793 const u8 *g_sta = NULL;
3794 size_t g_sta_len = 0;
3795 const u8 *g_ap = NULL;
3796 size_t g_ap_len = 0;
3797 struct wpabuf *pub = NULL;
3798
3799 os_memcpy(sm->bssid, bssid, ETH_ALEN);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003800
3801 wpa_hexdump(MSG_DEBUG, "FILS: Authentication frame fields",
3802 data, len);
3803 pos = data;
3804 end = data + len;
3805
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003806 /* TODO: FILS PK */
3807#ifdef CONFIG_FILS_SK_PFS
3808 if (sm->fils_dh_group) {
3809 u16 group;
3810
3811 /* Using FILS PFS */
3812
3813 /* Finite Cyclic Group */
3814 if (end - pos < 2) {
3815 wpa_printf(MSG_DEBUG,
3816 "FILS: No room for Finite Cyclic Group");
3817 goto fail;
3818 }
3819 group = WPA_GET_LE16(pos);
3820 pos += 2;
3821 if (group != sm->fils_dh_group) {
3822 wpa_printf(MSG_DEBUG,
3823 "FILS: Unexpected change in Finite Cyclic Group: %u (expected %u)",
3824 group, sm->fils_dh_group);
3825 goto fail;
3826 }
3827
3828 /* Element */
3829 if ((size_t) (end - pos) < sm->fils_dh_elem_len) {
3830 wpa_printf(MSG_DEBUG, "FILS: No room for Element");
3831 goto fail;
3832 }
3833
3834 if (!sm->fils_ecdh) {
3835 wpa_printf(MSG_DEBUG, "FILS: No ECDH state available");
3836 goto fail;
3837 }
3838 dh_ss = crypto_ecdh_set_peerkey(sm->fils_ecdh, 1, pos,
3839 sm->fils_dh_elem_len);
3840 if (!dh_ss) {
3841 wpa_printf(MSG_DEBUG, "FILS: ECDH operation failed");
3842 goto fail;
3843 }
3844 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: DH_SS", dh_ss);
3845 g_ap = pos;
3846 g_ap_len = sm->fils_dh_elem_len;
3847 pos += sm->fils_dh_elem_len;
3848 }
3849#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003850
3851 wpa_hexdump(MSG_DEBUG, "FILS: Remaining IEs", pos, end - pos);
3852 if (ieee802_11_parse_elems(pos, end - pos, &elems, 1) == ParseFailed) {
3853 wpa_printf(MSG_DEBUG, "FILS: Could not parse elements");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003854 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003855 }
3856
3857 /* RSNE */
3858 wpa_hexdump(MSG_DEBUG, "FILS: RSN element", elems.rsn_ie,
3859 elems.rsn_ie_len);
3860 if (!elems.rsn_ie ||
3861 wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
3862 &rsn) < 0) {
3863 wpa_printf(MSG_DEBUG, "FILS: No RSN element");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003864 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003865 }
3866
3867 if (!elems.fils_nonce) {
3868 wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003869 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003870 }
3871 os_memcpy(sm->fils_anonce, elems.fils_nonce, FILS_NONCE_LEN);
3872 wpa_hexdump(MSG_DEBUG, "FILS: ANonce", sm->fils_anonce, FILS_NONCE_LEN);
3873
Roshan Pius3a1667e2018-07-03 15:17:14 -07003874#ifdef CONFIG_IEEE80211R
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003875 if (wpa_key_mgmt_ft(sm->key_mgmt)) {
3876 struct wpa_ft_ies parse;
3877
3878 if (!elems.mdie || !elems.ftie) {
3879 wpa_printf(MSG_DEBUG, "FILS+FT: No MDE or FTE");
3880 goto fail;
3881 }
3882
Roshan Pius3a1667e2018-07-03 15:17:14 -07003883 if (wpa_ft_parse_ies(pos, end - pos, &parse,
3884 wpa_key_mgmt_sha384(sm->key_mgmt)) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003885 wpa_printf(MSG_DEBUG, "FILS+FT: Failed to parse IEs");
3886 goto fail;
3887 }
3888
3889 if (!parse.r0kh_id) {
3890 wpa_printf(MSG_DEBUG,
3891 "FILS+FT: No R0KH-ID subelem in FTE");
3892 goto fail;
3893 }
3894 os_memcpy(sm->r0kh_id, parse.r0kh_id, parse.r0kh_id_len);
3895 sm->r0kh_id_len = parse.r0kh_id_len;
3896 wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: R0KH-ID",
3897 sm->r0kh_id, sm->r0kh_id_len);
3898
3899 if (!parse.r1kh_id) {
3900 wpa_printf(MSG_DEBUG,
3901 "FILS+FT: No R1KH-ID subelem in FTE");
3902 goto fail;
3903 }
3904 os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
3905 wpa_hexdump(MSG_DEBUG, "FILS+FT: R1KH-ID",
3906 sm->r1kh_id, FT_R1KH_ID_LEN);
3907
3908 /* TODO: Check MDE and FTE payload */
3909
3910 wpabuf_free(sm->fils_ft_ies);
3911 sm->fils_ft_ies = wpabuf_alloc(2 + elems.mdie_len +
3912 2 + elems.ftie_len);
3913 if (!sm->fils_ft_ies)
3914 goto fail;
3915 wpabuf_put_data(sm->fils_ft_ies, elems.mdie - 2,
3916 2 + elems.mdie_len);
3917 wpabuf_put_data(sm->fils_ft_ies, elems.ftie - 2,
3918 2 + elems.ftie_len);
3919 } else {
3920 wpabuf_free(sm->fils_ft_ies);
3921 sm->fils_ft_ies = NULL;
3922 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003923#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003924
3925 /* PMKID List */
3926 if (rsn.pmkid && rsn.num_pmkid > 0) {
3927 wpa_hexdump(MSG_DEBUG, "FILS: PMKID List",
3928 rsn.pmkid, rsn.num_pmkid * PMKID_LEN);
3929
3930 if (rsn.num_pmkid != 1) {
3931 wpa_printf(MSG_DEBUG, "FILS: Invalid PMKID selection");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003932 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003933 }
3934 wpa_hexdump(MSG_DEBUG, "FILS: PMKID", rsn.pmkid, PMKID_LEN);
3935 if (os_memcmp(sm->cur_pmksa->pmkid, rsn.pmkid, PMKID_LEN) != 0)
3936 {
3937 wpa_printf(MSG_DEBUG, "FILS: PMKID mismatch");
3938 wpa_hexdump(MSG_DEBUG, "FILS: Expected PMKID",
3939 sm->cur_pmksa->pmkid, PMKID_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003940 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003941 }
3942 wpa_printf(MSG_DEBUG,
3943 "FILS: Matching PMKID - continue using PMKSA caching");
3944 pmkid_match = 1;
3945 }
3946 if (!pmkid_match && sm->cur_pmksa) {
3947 wpa_printf(MSG_DEBUG,
3948 "FILS: No PMKID match - cannot use cached PMKSA entry");
3949 sm->cur_pmksa = NULL;
3950 }
3951
3952 /* FILS Session */
3953 if (!elems.fils_session) {
3954 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003955 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003956 }
3957 wpa_hexdump(MSG_DEBUG, "FILS: FILS Session", elems.fils_session,
3958 FILS_SESSION_LEN);
3959 if (os_memcmp(sm->fils_session, elems.fils_session, FILS_SESSION_LEN)
3960 != 0) {
3961 wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
3962 wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
3963 sm->fils_session, FILS_SESSION_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003964 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003965 }
3966
3967 /* FILS Wrapped Data */
3968 if (!sm->cur_pmksa && elems.fils_wrapped_data) {
Paul Stewart092955c2017-02-06 09:13:09 -08003969 u8 rmsk[ERP_MAX_KEY_LEN];
3970 size_t rmsk_len;
3971
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003972 wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
3973 elems.fils_wrapped_data,
3974 elems.fils_wrapped_data_len);
3975 eapol_sm_process_erp_finish(sm->eapol, elems.fils_wrapped_data,
3976 elems.fils_wrapped_data_len);
3977 if (eapol_sm_failed(sm->eapol))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003978 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003979
Paul Stewart092955c2017-02-06 09:13:09 -08003980 rmsk_len = ERP_MAX_KEY_LEN;
3981 res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
3982 if (res == PMK_LEN) {
3983 rmsk_len = PMK_LEN;
3984 res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
3985 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003986 if (res)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003987 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003988
Paul Stewart092955c2017-02-06 09:13:09 -08003989 res = fils_rmsk_to_pmk(sm->key_mgmt, rmsk, rmsk_len,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003990 sm->fils_nonce, sm->fils_anonce,
3991 dh_ss ? wpabuf_head(dh_ss) : NULL,
3992 dh_ss ? wpabuf_len(dh_ss) : 0,
Paul Stewart092955c2017-02-06 09:13:09 -08003993 sm->pmk, &sm->pmk_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07003994 forced_memzero(rmsk, sizeof(rmsk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003995
3996 /* Don't use DHss in PTK derivation if PMKSA caching is not
3997 * used. */
3998 wpabuf_clear_free(dh_ss);
3999 dh_ss = NULL;
4000
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004001 if (res)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004002 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08004003
4004 if (!sm->fils_erp_pmkid_set) {
4005 wpa_printf(MSG_DEBUG, "FILS: PMKID not available");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004006 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08004007 }
4008 wpa_hexdump(MSG_DEBUG, "FILS: PMKID", sm->fils_erp_pmkid,
4009 PMKID_LEN);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004010 wpa_printf(MSG_DEBUG, "FILS: ERP processing succeeded - add PMKSA cache entry for the result");
Paul Stewart092955c2017-02-06 09:13:09 -08004011 sm->cur_pmksa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len,
4012 sm->fils_erp_pmkid, NULL, 0,
4013 sm->bssid, sm->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004014 sm->network_ctx, sm->key_mgmt,
4015 NULL);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004016 }
4017
4018 if (!sm->cur_pmksa) {
4019 wpa_printf(MSG_DEBUG,
4020 "FILS: No remaining options to continue FILS authentication");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004021 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004022 }
4023
4024 if (fils_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr, sm->bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004025 sm->fils_nonce, sm->fils_anonce,
4026 dh_ss ? wpabuf_head(dh_ss) : NULL,
4027 dh_ss ? wpabuf_len(dh_ss) : 0,
4028 &sm->ptk, ick, &ick_len,
4029 sm->key_mgmt, sm->pairwise_cipher,
4030 sm->fils_ft, &sm->fils_ft_len) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004031 wpa_printf(MSG_DEBUG, "FILS: Failed to derive PTK");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004032 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004033 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004034
4035 wpabuf_clear_free(dh_ss);
4036 dh_ss = NULL;
4037
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004038 sm->ptk_set = 1;
4039 sm->tptk_set = 0;
4040 os_memset(&sm->tptk, 0, sizeof(sm->tptk));
4041
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004042#ifdef CONFIG_FILS_SK_PFS
4043 if (sm->fils_dh_group) {
4044 if (!sm->fils_ecdh) {
4045 wpa_printf(MSG_INFO, "FILS: ECDH not initialized");
4046 goto fail;
4047 }
4048 pub = crypto_ecdh_get_pubkey(sm->fils_ecdh, 1);
4049 if (!pub)
4050 goto fail;
4051 wpa_hexdump_buf(MSG_DEBUG, "FILS: gSTA", pub);
4052 g_sta = wpabuf_head(pub);
4053 g_sta_len = wpabuf_len(pub);
4054 if (!g_ap) {
4055 wpa_printf(MSG_INFO, "FILS: gAP not available");
4056 goto fail;
4057 }
4058 wpa_hexdump(MSG_DEBUG, "FILS: gAP", g_ap, g_ap_len);
4059 }
4060#endif /* CONFIG_FILS_SK_PFS */
4061
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004062 res = fils_key_auth_sk(ick, ick_len, sm->fils_nonce,
4063 sm->fils_anonce, sm->own_addr, sm->bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004064 g_sta, g_sta_len, g_ap, g_ap_len,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004065 sm->key_mgmt, sm->fils_key_auth_sta,
4066 sm->fils_key_auth_ap,
4067 &sm->fils_key_auth_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004068 wpabuf_free(pub);
Hai Shalom81f62d82019-07-22 12:10:00 -07004069 forced_memzero(ick, sizeof(ick));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004070 return res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004071fail:
4072 wpabuf_free(pub);
4073 wpabuf_clear_free(dh_ss);
4074 return -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004075}
4076
4077
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004078#ifdef CONFIG_IEEE80211R
4079static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf)
4080{
4081 struct rsn_ie_hdr *rsnie;
4082 u16 capab;
4083 u8 *pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004084 int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004085
4086 /* RSNIE[PMKR0Name/PMKR1Name] */
4087 rsnie = wpabuf_put(buf, sizeof(*rsnie));
4088 rsnie->elem_id = WLAN_EID_RSN;
4089 WPA_PUT_LE16(rsnie->version, RSN_VERSION);
4090
4091 /* Group Suite Selector */
4092 if (!wpa_cipher_valid_group(sm->group_cipher)) {
4093 wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)",
4094 sm->group_cipher);
4095 return -1;
4096 }
4097 pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
4098 RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
4099 sm->group_cipher));
4100
4101 /* Pairwise Suite Count */
4102 wpabuf_put_le16(buf, 1);
4103
4104 /* Pairwise Suite List */
4105 if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
4106 wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)",
4107 sm->pairwise_cipher);
4108 return -1;
4109 }
4110 pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
4111 RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
4112 sm->pairwise_cipher));
4113
4114 /* Authenticated Key Management Suite Count */
4115 wpabuf_put_le16(buf, 1);
4116
4117 /* Authenticated Key Management Suite List */
4118 pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
4119 if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256)
4120 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
4121 else if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384)
4122 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
4123 else {
4124 wpa_printf(MSG_WARNING,
4125 "FILS+FT: Invalid key management type (%d)",
4126 sm->key_mgmt);
4127 return -1;
4128 }
4129
4130 /* RSN Capabilities */
4131 capab = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004132 if (sm->mfp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004133 capab |= WPA_CAPABILITY_MFPC;
Hai Shalomc3565922019-10-28 11:58:20 -07004134 if (sm->mfp == 2)
4135 capab |= WPA_CAPABILITY_MFPR;
Hai Shalom74f70d42019-02-11 14:42:39 -08004136 if (sm->ocv)
4137 capab |= WPA_CAPABILITY_OCVC;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004138 wpabuf_put_le16(buf, capab);
4139
4140 /* PMKID Count */
4141 wpabuf_put_le16(buf, 1);
4142
4143 /* PMKID List [PMKR1Name] */
4144 wpa_hexdump_key(MSG_DEBUG, "FILS+FT: XXKey (FILS-FT)",
4145 sm->fils_ft, sm->fils_ft_len);
4146 wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: SSID", sm->ssid, sm->ssid_len);
4147 wpa_hexdump(MSG_DEBUG, "FILS+FT: MDID",
4148 sm->mobility_domain, MOBILITY_DOMAIN_ID_LEN);
4149 wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: R0KH-ID",
4150 sm->r0kh_id, sm->r0kh_id_len);
4151 if (wpa_derive_pmk_r0(sm->fils_ft, sm->fils_ft_len, sm->ssid,
4152 sm->ssid_len, sm->mobility_domain,
4153 sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004154 sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004155 wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMK-R0");
4156 return -1;
4157 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004158 sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
4159 wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0",
4160 sm->pmk_r0, sm->pmk_r0_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004161 wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name",
4162 sm->pmk_r0_name, WPA_PMK_NAME_LEN);
4163 wpa_printf(MSG_DEBUG, "FILS+FT: R1KH-ID: " MACSTR,
4164 MAC2STR(sm->r1kh_id));
4165 pos = wpabuf_put(buf, WPA_PMK_NAME_LEN);
4166 if (wpa_derive_pmk_r1_name(sm->pmk_r0_name, sm->r1kh_id, sm->own_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07004167 sm->pmk_r1_name, use_sha384) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004168 wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMKR1Name");
4169 return -1;
4170 }
Hai Shalom021b0b52019-04-10 11:17:58 -07004171 wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
4172 WPA_PMK_NAME_LEN);
4173 os_memcpy(pos, sm->pmk_r1_name, WPA_PMK_NAME_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004174
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004175 if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
4176 /* Management Group Cipher Suite */
4177 pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
4178 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
4179 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004180
4181 rsnie->len = ((u8 *) wpabuf_put(buf, 0) - (u8 *) rsnie) - 2;
4182 return 0;
4183}
4184#endif /* CONFIG_IEEE80211R */
4185
4186
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004187struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
4188 size_t *kek_len, const u8 **snonce,
Paul Stewart092955c2017-02-06 09:13:09 -08004189 const u8 **anonce,
4190 const struct wpabuf **hlp,
4191 unsigned int num_hlp)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004192{
4193 struct wpabuf *buf;
Paul Stewart092955c2017-02-06 09:13:09 -08004194 size_t len;
4195 unsigned int i;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004196
Paul Stewart092955c2017-02-06 09:13:09 -08004197 len = 1000;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004198#ifdef CONFIG_IEEE80211R
4199 if (sm->fils_ft_ies)
4200 len += wpabuf_len(sm->fils_ft_ies);
4201 if (wpa_key_mgmt_ft(sm->key_mgmt))
4202 len += 256;
4203#endif /* CONFIG_IEEE80211R */
Paul Stewart092955c2017-02-06 09:13:09 -08004204 for (i = 0; hlp && i < num_hlp; i++)
4205 len += 10 + wpabuf_len(hlp[i]);
4206 buf = wpabuf_alloc(len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004207 if (!buf)
4208 return NULL;
4209
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004210#ifdef CONFIG_IEEE80211R
4211 if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->fils_ft_ies) {
4212 /* MDE and FTE when using FILS+FT */
4213 wpabuf_put_buf(buf, sm->fils_ft_ies);
4214 /* RSNE with PMKR1Name in PMKID field */
4215 if (fils_ft_build_assoc_req_rsne(sm, buf) < 0) {
4216 wpabuf_free(buf);
4217 return NULL;
4218 }
4219 }
4220#endif /* CONFIG_IEEE80211R */
4221
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004222 /* FILS Session */
4223 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
4224 wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN); /* Length */
4225 /* Element ID Extension */
4226 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
4227 wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN);
4228
4229 /* Everything after FILS Session element gets encrypted in the driver
4230 * with KEK. The buffer returned from here is the plaintext version. */
4231
4232 /* TODO: FILS Public Key */
4233
4234 /* FILS Key Confirm */
4235 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
4236 wpabuf_put_u8(buf, 1 + sm->fils_key_auth_len); /* Length */
4237 /* Element ID Extension */
4238 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM);
4239 wpabuf_put_data(buf, sm->fils_key_auth_sta, sm->fils_key_auth_len);
4240
Paul Stewart092955c2017-02-06 09:13:09 -08004241 /* FILS HLP Container */
4242 for (i = 0; hlp && i < num_hlp; i++) {
4243 const u8 *pos = wpabuf_head(hlp[i]);
4244 size_t left = wpabuf_len(hlp[i]);
4245
4246 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
4247 if (left <= 254)
4248 len = 1 + left;
4249 else
4250 len = 255;
4251 wpabuf_put_u8(buf, len); /* Length */
4252 /* Element ID Extension */
4253 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_HLP_CONTAINER);
4254 /* Destination MAC Address, Source MAC Address, HLP Packet.
4255 * HLP Packet is in MSDU format (i.e., included the LLC/SNAP
4256 * header when LPD is used). */
4257 wpabuf_put_data(buf, pos, len - 1);
4258 pos += len - 1;
4259 left -= len - 1;
4260 while (left) {
4261 wpabuf_put_u8(buf, WLAN_EID_FRAGMENT);
4262 len = left > 255 ? 255 : left;
4263 wpabuf_put_u8(buf, len);
4264 wpabuf_put_data(buf, pos, len);
4265 pos += len;
4266 left -= len;
4267 }
4268 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004269
4270 /* TODO: FILS IP Address Assignment */
4271
Hai Shalom74f70d42019-02-11 14:42:39 -08004272#ifdef CONFIG_OCV
4273 if (wpa_sm_ocv_enabled(sm)) {
4274 struct wpa_channel_info ci;
4275 u8 *pos;
4276
4277 if (wpa_sm_channel_info(sm, &ci) != 0) {
4278 wpa_printf(MSG_WARNING,
4279 "FILS: Failed to get channel info for OCI element");
4280 wpabuf_free(buf);
4281 return NULL;
4282 }
4283
4284 pos = wpabuf_put(buf, OCV_OCI_EXTENDED_LEN);
4285 if (ocv_insert_extended_oci(&ci, pos) < 0) {
4286 wpabuf_free(buf);
4287 return NULL;
4288 }
4289 }
4290#endif /* CONFIG_OCV */
4291
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004292 wpa_hexdump_buf(MSG_DEBUG, "FILS: Association Request plaintext", buf);
4293
4294 *kek = sm->ptk.kek;
4295 *kek_len = sm->ptk.kek_len;
4296 wpa_hexdump_key(MSG_DEBUG, "FILS: KEK for AEAD", *kek, *kek_len);
4297 *snonce = sm->fils_nonce;
4298 wpa_hexdump(MSG_DEBUG, "FILS: SNonce for AEAD AAD",
4299 *snonce, FILS_NONCE_LEN);
4300 *anonce = sm->fils_anonce;
4301 wpa_hexdump(MSG_DEBUG, "FILS: ANonce for AEAD AAD",
4302 *anonce, FILS_NONCE_LEN);
4303
4304 return buf;
4305}
4306
4307
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004308static void fils_process_hlp_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
4309{
4310 const u8 *pos, *end;
4311
4312 wpa_hexdump(MSG_MSGDUMP, "FILS: HLP response", resp, len);
4313 if (len < 2 * ETH_ALEN)
4314 return;
4315 pos = resp + 2 * ETH_ALEN;
4316 end = resp + len;
4317 if (end - pos >= 6 &&
4318 os_memcmp(pos, "\xaa\xaa\x03\x00\x00\x00", 6) == 0)
4319 pos += 6; /* Remove SNAP/LLC header */
4320 wpa_sm_fils_hlp_rx(sm, resp, resp + ETH_ALEN, pos, end - pos);
4321}
4322
4323
4324static void fils_process_hlp_container(struct wpa_sm *sm, const u8 *pos,
4325 size_t len)
4326{
4327 const u8 *end = pos + len;
4328 u8 *tmp, *tmp_pos;
4329
4330 /* Check if there are any FILS HLP Container elements */
4331 while (end - pos >= 2) {
4332 if (2 + pos[1] > end - pos)
4333 return;
4334 if (pos[0] == WLAN_EID_EXTENSION &&
4335 pos[1] >= 1 + 2 * ETH_ALEN &&
4336 pos[2] == WLAN_EID_EXT_FILS_HLP_CONTAINER)
4337 break;
4338 pos += 2 + pos[1];
4339 }
4340 if (end - pos < 2)
4341 return; /* No FILS HLP Container elements */
4342
4343 tmp = os_malloc(end - pos);
4344 if (!tmp)
4345 return;
4346
4347 while (end - pos >= 2) {
4348 if (2 + pos[1] > end - pos ||
4349 pos[0] != WLAN_EID_EXTENSION ||
4350 pos[1] < 1 + 2 * ETH_ALEN ||
4351 pos[2] != WLAN_EID_EXT_FILS_HLP_CONTAINER)
4352 break;
4353 tmp_pos = tmp;
4354 os_memcpy(tmp_pos, pos + 3, pos[1] - 1);
4355 tmp_pos += pos[1] - 1;
4356 pos += 2 + pos[1];
4357
4358 /* Add possible fragments */
4359 while (end - pos >= 2 && pos[0] == WLAN_EID_FRAGMENT &&
4360 2 + pos[1] <= end - pos) {
4361 os_memcpy(tmp_pos, pos + 2, pos[1]);
4362 tmp_pos += pos[1];
4363 pos += 2 + pos[1];
4364 }
4365
4366 fils_process_hlp_resp(sm, tmp, tmp_pos - tmp);
4367 }
4368
4369 os_free(tmp);
4370}
4371
4372
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004373int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
4374{
4375 const struct ieee80211_mgmt *mgmt;
4376 const u8 *end, *ie_start;
4377 struct ieee802_11_elems elems;
4378 int keylen, rsclen;
4379 enum wpa_alg alg;
4380 struct wpa_gtk_data gd;
4381 int maxkeylen;
4382 struct wpa_eapol_ie_parse kde;
4383
4384 if (!sm || !sm->ptk_set) {
4385 wpa_printf(MSG_DEBUG, "FILS: No KEK available");
4386 return -1;
4387 }
4388
4389 if (!wpa_key_mgmt_fils(sm->key_mgmt)) {
4390 wpa_printf(MSG_DEBUG, "FILS: Not a FILS AKM");
4391 return -1;
4392 }
4393
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004394 if (sm->fils_completed) {
4395 wpa_printf(MSG_DEBUG,
4396 "FILS: Association has already been completed for this FILS authentication - ignore unexpected retransmission");
4397 return -1;
4398 }
4399
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004400 wpa_hexdump(MSG_DEBUG, "FILS: (Re)Association Response frame",
4401 resp, len);
4402
4403 mgmt = (const struct ieee80211_mgmt *) resp;
4404 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_resp))
4405 return -1;
4406
4407 end = resp + len;
4408 /* Same offset for Association Response and Reassociation Response */
4409 ie_start = mgmt->u.assoc_resp.variable;
4410
4411 if (ieee802_11_parse_elems(ie_start, end - ie_start, &elems, 1) ==
4412 ParseFailed) {
4413 wpa_printf(MSG_DEBUG,
4414 "FILS: Failed to parse decrypted elements");
4415 goto fail;
4416 }
4417
4418 if (!elems.fils_session) {
4419 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
4420 return -1;
4421 }
4422 if (os_memcmp(elems.fils_session, sm->fils_session,
4423 FILS_SESSION_LEN) != 0) {
4424 wpa_printf(MSG_DEBUG, "FILS: FILS Session mismatch");
4425 wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
4426 elems.fils_session, FILS_SESSION_LEN);
4427 wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
4428 sm->fils_session, FILS_SESSION_LEN);
4429 }
4430
Hai Shalom81f62d82019-07-22 12:10:00 -07004431 if (!elems.rsn_ie) {
4432 wpa_printf(MSG_DEBUG,
4433 "FILS: No RSNE in (Re)Association Response");
4434 /* As an interop workaround, allow this for now since IEEE Std
4435 * 802.11ai-2016 did not include all the needed changes to make
4436 * a FILS AP include RSNE in the frame. This workaround might
4437 * eventually be removed and replaced with rejection (goto fail)
4438 * to follow a strict interpretation of the standard. */
4439 } else if (wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
4440 sm->ap_rsn_ie, sm->ap_rsn_ie_len,
4441 elems.rsn_ie - 2, elems.rsn_ie_len + 2)) {
4442 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
4443 "FILS: RSNE mismatch between Beacon/Probe Response and (Re)Association Response");
4444 wpa_hexdump(MSG_DEBUG, "FILS: RSNE in Beacon/Probe Response",
4445 sm->ap_rsn_ie, sm->ap_rsn_ie_len);
4446 wpa_hexdump(MSG_DEBUG, "FILS: RSNE in (Re)Association Response",
4447 elems.rsn_ie, elems.rsn_ie_len);
4448 goto fail;
4449 }
4450
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004451 /* TODO: FILS Public Key */
4452
4453 if (!elems.fils_key_confirm) {
4454 wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
4455 goto fail;
4456 }
4457 if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
4458 wpa_printf(MSG_DEBUG,
4459 "FILS: Unexpected Key-Auth length %d (expected %d)",
4460 elems.fils_key_confirm_len,
4461 (int) sm->fils_key_auth_len);
4462 goto fail;
4463 }
4464 if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_ap,
4465 sm->fils_key_auth_len) != 0) {
4466 wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
4467 wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
4468 elems.fils_key_confirm,
4469 elems.fils_key_confirm_len);
4470 wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
4471 sm->fils_key_auth_ap, sm->fils_key_auth_len);
4472 goto fail;
4473 }
4474
Hai Shalom74f70d42019-02-11 14:42:39 -08004475#ifdef CONFIG_OCV
4476 if (wpa_sm_ocv_enabled(sm)) {
4477 struct wpa_channel_info ci;
4478
4479 if (wpa_sm_channel_info(sm, &ci) != 0) {
4480 wpa_printf(MSG_WARNING,
4481 "Failed to get channel info to validate received OCI in FILS (Re)Association Response frame");
4482 goto fail;
4483 }
4484
4485 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
4486 channel_width_to_int(ci.chanwidth),
4487 ci.seg1_idx) != 0) {
4488 wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr);
4489 goto fail;
4490 }
4491 }
4492#endif /* CONFIG_OCV */
4493
Hai Shalom021b0b52019-04-10 11:17:58 -07004494#ifdef CONFIG_IEEE80211R
4495 if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->fils_ft_ies) {
4496 struct wpa_ie_data rsn;
4497
4498 /* Check that PMKR1Name derived by the AP matches */
4499 if (!elems.rsn_ie ||
4500 wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
4501 &rsn) < 0 ||
4502 !rsn.pmkid || rsn.num_pmkid != 1 ||
4503 os_memcmp(rsn.pmkid, sm->pmk_r1_name,
4504 WPA_PMK_NAME_LEN) != 0) {
4505 wpa_printf(MSG_DEBUG,
4506 "FILS+FT: No RSNE[PMKR1Name] match in AssocResp");
4507 goto fail;
4508 }
4509 }
4510#endif /* CONFIG_IEEE80211R */
4511
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004512 /* Key Delivery */
4513 if (!elems.key_delivery) {
4514 wpa_printf(MSG_DEBUG, "FILS: No Key Delivery element");
4515 goto fail;
4516 }
4517
4518 /* Parse GTK and set the key to the driver */
4519 os_memset(&gd, 0, sizeof(gd));
4520 if (wpa_supplicant_parse_ies(elems.key_delivery + WPA_KEY_RSC_LEN,
4521 elems.key_delivery_len - WPA_KEY_RSC_LEN,
4522 &kde) < 0) {
4523 wpa_printf(MSG_DEBUG, "FILS: Failed to parse KDEs");
4524 goto fail;
4525 }
4526 if (!kde.gtk) {
4527 wpa_printf(MSG_DEBUG, "FILS: No GTK KDE");
4528 goto fail;
4529 }
4530 maxkeylen = gd.gtk_len = kde.gtk_len - 2;
4531 if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
4532 gd.gtk_len, maxkeylen,
4533 &gd.key_rsc_len, &gd.alg))
4534 goto fail;
4535
4536 wpa_hexdump_key(MSG_DEBUG, "FILS: Received GTK", kde.gtk, kde.gtk_len);
4537 gd.keyidx = kde.gtk[0] & 0x3;
4538 gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
4539 !!(kde.gtk[0] & BIT(2)));
4540 if (kde.gtk_len - 2 > sizeof(gd.gtk)) {
4541 wpa_printf(MSG_DEBUG, "FILS: Too long GTK in GTK KDE (len=%lu)",
4542 (unsigned long) kde.gtk_len - 2);
4543 goto fail;
4544 }
4545 os_memcpy(gd.gtk, kde.gtk + 2, kde.gtk_len - 2);
4546
4547 wpa_printf(MSG_DEBUG, "FILS: Set GTK to driver");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004548 if (wpa_supplicant_install_gtk(sm, &gd, elems.key_delivery, 0) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004549 wpa_printf(MSG_DEBUG, "FILS: Failed to set GTK");
4550 goto fail;
4551 }
4552
4553 if (ieee80211w_set_keys(sm, &kde) < 0) {
4554 wpa_printf(MSG_DEBUG, "FILS: Failed to set IGTK");
4555 goto fail;
4556 }
4557
4558 alg = wpa_cipher_to_alg(sm->pairwise_cipher);
4559 keylen = wpa_cipher_key_len(sm->pairwise_cipher);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004560 if (keylen <= 0 || (unsigned int) keylen != sm->ptk.tk_len) {
4561 wpa_printf(MSG_DEBUG, "FILS: TK length mismatch: %u != %lu",
4562 keylen, (long unsigned int) sm->ptk.tk_len);
4563 goto fail;
4564 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004565 rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
4566 wpa_hexdump_key(MSG_DEBUG, "FILS: Set TK to driver",
4567 sm->ptk.tk, keylen);
4568 if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, null_rsc, rsclen,
4569 sm->ptk.tk, keylen) < 0) {
4570 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
4571 "FILS: Failed to set PTK to the driver (alg=%d keylen=%d bssid="
4572 MACSTR ")",
4573 alg, keylen, MAC2STR(sm->bssid));
4574 goto fail;
4575 }
4576
4577 /* TODO: TK could be cleared after auth frame exchange now that driver
4578 * takes care of association frame encryption/decryption. */
4579 /* TK is not needed anymore in supplicant */
4580 os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004581 sm->ptk.tk_len = 0;
Mathy Vanhoefc66556c2017-09-29 04:22:51 +02004582 sm->ptk.installed = 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004583
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004584 /* FILS HLP Container */
4585 fils_process_hlp_container(sm, ie_start, end - ie_start);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004586
4587 /* TODO: FILS IP Address Assignment */
4588
4589 wpa_printf(MSG_DEBUG, "FILS: Auth+Assoc completed successfully");
4590 sm->fils_completed = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07004591 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004592
4593 return 0;
4594fail:
Hai Shalom81f62d82019-07-22 12:10:00 -07004595 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004596 return -1;
4597}
4598
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004599
4600void wpa_sm_set_reset_fils_completed(struct wpa_sm *sm, int set)
4601{
4602 if (sm)
4603 sm->fils_completed = !!set;
4604}
4605
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004606#endif /* CONFIG_FILS */
4607
4608
4609int wpa_fils_is_completed(struct wpa_sm *sm)
4610{
4611#ifdef CONFIG_FILS
4612 return sm && sm->fils_completed;
4613#else /* CONFIG_FILS */
4614 return 0;
4615#endif /* CONFIG_FILS */
4616}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004617
4618
4619#ifdef CONFIG_OWE
4620
4621struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm, u16 group)
4622{
4623 struct wpabuf *ie = NULL, *pub = NULL;
4624 size_t prime_len;
4625
4626 if (group == 19)
4627 prime_len = 32;
4628 else if (group == 20)
4629 prime_len = 48;
4630 else if (group == 21)
4631 prime_len = 66;
4632 else
4633 return NULL;
4634
4635 crypto_ecdh_deinit(sm->owe_ecdh);
4636 sm->owe_ecdh = crypto_ecdh_init(group);
4637 if (!sm->owe_ecdh)
4638 goto fail;
4639 sm->owe_group = group;
4640 pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
4641 pub = wpabuf_zeropad(pub, prime_len);
4642 if (!pub)
4643 goto fail;
4644
4645 ie = wpabuf_alloc(5 + wpabuf_len(pub));
4646 if (!ie)
4647 goto fail;
4648 wpabuf_put_u8(ie, WLAN_EID_EXTENSION);
4649 wpabuf_put_u8(ie, 1 + 2 + wpabuf_len(pub));
4650 wpabuf_put_u8(ie, WLAN_EID_EXT_OWE_DH_PARAM);
4651 wpabuf_put_le16(ie, group);
4652 wpabuf_put_buf(ie, pub);
4653 wpabuf_free(pub);
4654 wpa_hexdump_buf(MSG_DEBUG, "OWE: Diffie-Hellman Parameter element",
4655 ie);
4656
4657 return ie;
4658fail:
4659 wpabuf_free(pub);
4660 crypto_ecdh_deinit(sm->owe_ecdh);
4661 sm->owe_ecdh = NULL;
4662 return NULL;
4663}
4664
4665
4666int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid,
4667 const u8 *resp_ies, size_t resp_ies_len)
4668{
4669 struct ieee802_11_elems elems;
4670 u16 group;
4671 struct wpabuf *secret, *pub, *hkey;
4672 int res;
4673 u8 prk[SHA512_MAC_LEN], pmkid[SHA512_MAC_LEN];
4674 const char *info = "OWE Key Generation";
4675 const u8 *addr[2];
4676 size_t len[2];
4677 size_t hash_len, prime_len;
4678 struct wpa_ie_data data;
4679
4680 if (!resp_ies ||
4681 ieee802_11_parse_elems(resp_ies, resp_ies_len, &elems, 1) ==
4682 ParseFailed) {
4683 wpa_printf(MSG_INFO,
4684 "OWE: Could not parse Association Response frame elements");
4685 return -1;
4686 }
4687
4688 if (sm->cur_pmksa && elems.rsn_ie &&
4689 wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, 2 + elems.rsn_ie_len,
4690 &data) == 0 &&
4691 data.num_pmkid == 1 && data.pmkid &&
4692 os_memcmp(sm->cur_pmksa->pmkid, data.pmkid, PMKID_LEN) == 0) {
4693 wpa_printf(MSG_DEBUG, "OWE: Use PMKSA caching");
4694 wpa_sm_set_pmk_from_pmksa(sm);
4695 return 0;
4696 }
4697
4698 if (!elems.owe_dh) {
4699 wpa_printf(MSG_INFO,
4700 "OWE: No Diffie-Hellman Parameter element found in Association Response frame");
4701 return -1;
4702 }
4703
4704 group = WPA_GET_LE16(elems.owe_dh);
4705 if (group != sm->owe_group) {
4706 wpa_printf(MSG_INFO,
4707 "OWE: Unexpected Diffie-Hellman group in response: %u",
4708 group);
4709 return -1;
4710 }
4711
4712 if (!sm->owe_ecdh) {
4713 wpa_printf(MSG_INFO, "OWE: No ECDH state available");
4714 return -1;
4715 }
4716
4717 if (group == 19)
4718 prime_len = 32;
4719 else if (group == 20)
4720 prime_len = 48;
4721 else if (group == 21)
4722 prime_len = 66;
4723 else
4724 return -1;
4725
4726 secret = crypto_ecdh_set_peerkey(sm->owe_ecdh, 0,
4727 elems.owe_dh + 2,
4728 elems.owe_dh_len - 2);
4729 secret = wpabuf_zeropad(secret, prime_len);
4730 if (!secret) {
4731 wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key");
4732 return -1;
4733 }
4734 wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", secret);
4735
4736 /* prk = HKDF-extract(C | A | group, z) */
4737
4738 pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
4739 if (!pub) {
4740 wpabuf_clear_free(secret);
4741 return -1;
4742 }
4743
4744 /* PMKID = Truncate-128(Hash(C | A)) */
4745 addr[0] = wpabuf_head(pub);
4746 len[0] = wpabuf_len(pub);
4747 addr[1] = elems.owe_dh + 2;
4748 len[1] = elems.owe_dh_len - 2;
4749 if (group == 19) {
4750 res = sha256_vector(2, addr, len, pmkid);
4751 hash_len = SHA256_MAC_LEN;
4752 } else if (group == 20) {
4753 res = sha384_vector(2, addr, len, pmkid);
4754 hash_len = SHA384_MAC_LEN;
4755 } else if (group == 21) {
4756 res = sha512_vector(2, addr, len, pmkid);
4757 hash_len = SHA512_MAC_LEN;
4758 } else {
4759 res = -1;
4760 hash_len = 0;
4761 }
4762 pub = wpabuf_zeropad(pub, prime_len);
4763 if (res < 0 || !pub) {
4764 wpabuf_free(pub);
4765 wpabuf_clear_free(secret);
4766 return -1;
4767 }
4768
4769 hkey = wpabuf_alloc(wpabuf_len(pub) + elems.owe_dh_len - 2 + 2);
4770 if (!hkey) {
4771 wpabuf_free(pub);
4772 wpabuf_clear_free(secret);
4773 return -1;
4774 }
4775
4776 wpabuf_put_buf(hkey, pub); /* C */
4777 wpabuf_free(pub);
4778 wpabuf_put_data(hkey, elems.owe_dh + 2, elems.owe_dh_len - 2); /* A */
4779 wpabuf_put_le16(hkey, sm->owe_group); /* group */
4780 if (group == 19)
4781 res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey),
4782 wpabuf_head(secret), wpabuf_len(secret), prk);
4783 else if (group == 20)
4784 res = hmac_sha384(wpabuf_head(hkey), wpabuf_len(hkey),
4785 wpabuf_head(secret), wpabuf_len(secret), prk);
4786 else if (group == 21)
4787 res = hmac_sha512(wpabuf_head(hkey), wpabuf_len(hkey),
4788 wpabuf_head(secret), wpabuf_len(secret), prk);
4789 wpabuf_clear_free(hkey);
4790 wpabuf_clear_free(secret);
4791 if (res < 0)
4792 return -1;
4793
4794 wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len);
4795
4796 /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
4797
4798 if (group == 19)
4799 res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *) info,
4800 os_strlen(info), sm->pmk, hash_len);
4801 else if (group == 20)
4802 res = hmac_sha384_kdf(prk, hash_len, NULL, (const u8 *) info,
4803 os_strlen(info), sm->pmk, hash_len);
4804 else if (group == 21)
4805 res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info,
4806 os_strlen(info), sm->pmk, hash_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07004807 forced_memzero(prk, SHA512_MAC_LEN);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004808 if (res < 0) {
4809 sm->pmk_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004810 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004811 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004812 sm->pmk_len = hash_len;
4813
4814 wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sm->pmk, sm->pmk_len);
4815 wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
4816 pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, pmkid, NULL, 0,
4817 bssid, sm->own_addr, sm->network_ctx, sm->key_mgmt,
4818 NULL);
4819
4820 return 0;
4821}
4822
4823#endif /* CONFIG_OWE */
4824
4825
4826void wpa_sm_set_fils_cache_id(struct wpa_sm *sm, const u8 *fils_cache_id)
4827{
4828#ifdef CONFIG_FILS
4829 if (sm && fils_cache_id) {
4830 sm->fils_cache_id_set = 1;
4831 os_memcpy(sm->fils_cache_id, fils_cache_id, FILS_CACHE_ID_LEN);
4832 }
4833#endif /* CONFIG_FILS */
4834}
Hai Shalom021b0b52019-04-10 11:17:58 -07004835
4836
4837#ifdef CONFIG_DPP2
4838void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z)
4839{
4840 if (sm) {
4841 wpabuf_clear_free(sm->dpp_z);
4842 sm->dpp_z = z ? wpabuf_dup(z) : NULL;
4843 }
4844}
4845#endif /* CONFIG_DPP2 */