1/*
2 * hostapd - PeerKey for Direct Link Setup (DLS)
3 * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "utils/includes.h"
16
17#include "utils/common.h"
18#include "utils/eloop.h"
19#include "crypto/sha1.h"
20#include "crypto/sha256.h"
21#include "wpa_auth.h"
22#include "wpa_auth_i.h"
23#include "wpa_auth_ie.h"
24
25#ifdef CONFIG_PEERKEY
26
27static void wpa_stsl_step(void *eloop_ctx, void *timeout_ctx)
28{
29#if 0
30	struct wpa_authenticator *wpa_auth = eloop_ctx;
31	struct wpa_stsl_negotiation *neg = timeout_ctx;
32#endif
33
34	/* TODO: ? */
35}
36
37
38struct wpa_stsl_search {
39	const u8 *addr;
40	struct wpa_state_machine *sm;
41};
42
43
44static int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx)
45{
46	struct wpa_stsl_search *search = ctx;
47	if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) {
48		search->sm = sm;
49		return 1;
50	}
51	return 0;
52}
53
54
55static void wpa_smk_send_error(struct wpa_authenticator *wpa_auth,
56			       struct wpa_state_machine *sm, const u8 *peer,
57			       u16 mui, u16 error_type)
58{
59	u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN +
60	       2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)];
61	u8 *pos;
62	struct rsn_error_kde error;
63
64	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
65			"Sending SMK Error");
66
67	pos = kde;
68
69	if (peer) {
70		pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN,
71				  NULL, 0);
72	}
73
74	error.mui = host_to_be16(mui);
75	error.error_type = host_to_be16(error_type);
76	pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR,
77			  (u8 *) &error, sizeof(error), NULL, 0);
78
79	__wpa_send_eapol(wpa_auth, sm,
80			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
81			 WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR,
82			 NULL, NULL, kde, pos - kde, 0, 0, 0);
83}
84
85
86void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
87		struct wpa_state_machine *sm, struct wpa_eapol_key *key)
88{
89	struct wpa_eapol_ie_parse kde;
90	struct wpa_stsl_search search;
91	u8 *buf, *pos;
92	size_t buf_len;
93
94	if (wpa_parse_kde_ies((const u8 *) (key + 1),
95			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
96		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1");
97		return;
98	}
99
100	if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
101	    kde.mac_addr_len < ETH_ALEN) {
102		wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
103			   "SMK M1");
104		return;
105	}
106
107	/* Initiator = sm->addr; Peer = kde.mac_addr */
108
109	search.addr = kde.mac_addr;
110	search.sm = NULL;
111	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
112	    0 || search.sm == NULL) {
113		wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
114			   " aborted - STA not associated anymore",
115			   MAC2STR(kde.mac_addr));
116		wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
117				   STK_ERR_STA_NR);
118		/* FIX: wpa_stsl_remove(wpa_auth, neg); */
119		return;
120	}
121
122	buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
123	buf = os_malloc(buf_len);
124	if (buf == NULL)
125		return;
126	/* Initiator RSN IE */
127	os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len);
128	pos = buf + kde.rsn_ie_len;
129	/* Initiator MAC Address */
130	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN,
131			  NULL, 0);
132
133	/* SMK M2:
134	 * EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
135	 *           MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE)
136	 */
137
138	wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG,
139			"Sending SMK M2");
140
141	__wpa_send_eapol(wpa_auth, search.sm,
142			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
143			 WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE,
144			 NULL, key->key_nonce, buf, pos - buf, 0, 0, 0);
145
146	os_free(buf);
147}
148
149
150static void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth,
151			    struct wpa_state_machine *sm,
152			    struct wpa_eapol_key *key,
153			    struct wpa_eapol_ie_parse *kde,
154			    const u8 *smk)
155{
156	u8 *buf, *pos;
157	size_t buf_len;
158	u32 lifetime;
159
160	/* SMK M4:
161	 * EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce,
162	 *           MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE,
163	 *           Lifetime KDE)
164	 */
165
166	buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN +
167		2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
168		2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
169		2 + RSN_SELECTOR_LEN + sizeof(lifetime);
170	pos = buf = os_malloc(buf_len);
171	if (buf == NULL)
172		return;
173
174	/* Initiator MAC Address */
175	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN,
176			  NULL, 0);
177
178	/* Initiator Nonce */
179	pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN,
180			  NULL, 0);
181
182	/* SMK with PNonce */
183	pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
184			  key->key_nonce, WPA_NONCE_LEN);
185
186	/* Lifetime */
187	lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
188	pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
189			  (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
190
191	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
192			"Sending SMK M4");
193
194	__wpa_send_eapol(wpa_auth, sm,
195			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
196			 WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE,
197			 NULL, key->key_nonce, buf, pos - buf, 0, 1, 0);
198
199	os_free(buf);
200}
201
202
203static void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth,
204			    struct wpa_state_machine *sm,
205			    struct wpa_eapol_key *key,
206			    struct wpa_eapol_ie_parse *kde,
207			    const u8 *smk, const u8 *peer)
208{
209	u8 *buf, *pos;
210	size_t buf_len;
211	u32 lifetime;
212
213	/* SMK M5:
214	 * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
215	 *           MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE,
216	 *                             Lifetime KDE))
217	 */
218
219	buf_len = kde->rsn_ie_len +
220		2 + RSN_SELECTOR_LEN + ETH_ALEN +
221		2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
222		2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
223		2 + RSN_SELECTOR_LEN + sizeof(lifetime);
224	pos = buf = os_malloc(buf_len);
225	if (buf == NULL)
226		return;
227
228	/* Peer RSN IE */
229	os_memcpy(buf, kde->rsn_ie, kde->rsn_ie_len);
230	pos = buf + kde->rsn_ie_len;
231
232	/* Peer MAC Address */
233	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0);
234
235	/* PNonce */
236	pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce,
237			  WPA_NONCE_LEN, NULL, 0);
238
239	/* SMK and INonce */
240	pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
241			  kde->nonce, WPA_NONCE_LEN);
242
243	/* Lifetime */
244	lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
245	pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
246			  (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
247
248	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
249			"Sending SMK M5");
250
251	__wpa_send_eapol(wpa_auth, sm,
252			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
253			 WPA_KEY_INFO_SMK_MESSAGE,
254			 NULL, kde->nonce, buf, pos - buf, 0, 1, 0);
255
256	os_free(buf);
257}
258
259
260void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
261		struct wpa_state_machine *sm, struct wpa_eapol_key *key)
262{
263	struct wpa_eapol_ie_parse kde;
264	struct wpa_stsl_search search;
265	u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos;
266
267	if (wpa_parse_kde_ies((const u8 *) (key + 1),
268			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
269		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3");
270		return;
271	}
272
273	if (kde.rsn_ie == NULL ||
274	    kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
275	    kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) {
276		wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or "
277			   "Nonce KDE in SMK M3");
278		return;
279	}
280
281	/* Peer = sm->addr; Initiator = kde.mac_addr;
282	 * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */
283
284	search.addr = kde.mac_addr;
285	search.sm = NULL;
286	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
287	    0 || search.sm == NULL) {
288		wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
289			   " aborted - STA not associated anymore",
290			   MAC2STR(kde.mac_addr));
291		wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
292				   STK_ERR_STA_NR);
293		/* FIX: wpa_stsl_remove(wpa_auth, neg); */
294		return;
295	}
296
297	if (os_get_random(smk, PMK_LEN)) {
298		wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
299		return;
300	}
301
302	/* SMK = PRF-256(Random number, "SMK Derivation",
303	 *               AA || Time || INonce || PNonce)
304	 */
305	os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
306	pos = buf + ETH_ALEN;
307	wpa_get_ntp_timestamp(pos);
308	pos += 8;
309	os_memcpy(pos, kde.nonce, WPA_NONCE_LEN);
310	pos += WPA_NONCE_LEN;
311	os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN);
312#ifdef CONFIG_IEEE80211W
313	sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
314		   smk, PMK_LEN);
315#else /* CONFIG_IEEE80211W */
316	sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
317		 smk, PMK_LEN);
318#endif /* CONFIG_IEEE80211W */
319
320	wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN);
321
322	wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk);
323	wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr);
324
325	/* Authenticator does not need SMK anymore and it is required to forget
326	 * it. */
327	os_memset(smk, 0, sizeof(*smk));
328}
329
330
331void wpa_smk_error(struct wpa_authenticator *wpa_auth,
332		   struct wpa_state_machine *sm, struct wpa_eapol_key *key)
333{
334	struct wpa_eapol_ie_parse kde;
335	struct wpa_stsl_search search;
336	struct rsn_error_kde error;
337	u16 mui, error_type;
338
339	if (wpa_parse_kde_ies((const u8 *) (key + 1),
340			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
341		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
342		return;
343	}
344
345	if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
346	    kde.error == NULL || kde.error_len < sizeof(error)) {
347		wpa_printf(MSG_INFO, "RSN: No MAC address or Error KDE in "
348			   "SMK Error");
349		return;
350	}
351
352	search.addr = kde.mac_addr;
353	search.sm = NULL;
354	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
355	    0 || search.sm == NULL) {
356		wpa_printf(MSG_DEBUG, "RSN: Peer STA " MACSTR " not "
357			   "associated for SMK Error message from " MACSTR,
358			   MAC2STR(kde.mac_addr), MAC2STR(sm->addr));
359		return;
360	}
361
362	os_memcpy(&error, kde.error, sizeof(error));
363	mui = be_to_host16(error.mui);
364	error_type = be_to_host16(error.error_type);
365	wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
366			 "STA reported SMK Error: Peer " MACSTR
367			 " MUI %d Error Type %d",
368			 MAC2STR(kde.mac_addr), mui, error_type);
369
370	wpa_smk_send_error(wpa_auth, search.sm, sm->addr, mui, error_type);
371}
372
373
374int wpa_stsl_remove(struct wpa_authenticator *wpa_auth,
375		    struct wpa_stsl_negotiation *neg)
376{
377	struct wpa_stsl_negotiation *pos, *prev;
378
379	if (wpa_auth == NULL)
380		return -1;
381	pos = wpa_auth->stsl_negotiations;
382	prev = NULL;
383	while (pos) {
384		if (pos == neg) {
385			if (prev)
386				prev->next = pos->next;
387			else
388				wpa_auth->stsl_negotiations = pos->next;
389
390			eloop_cancel_timeout(wpa_stsl_step, wpa_auth, pos);
391			os_free(pos);
392			return 0;
393		}
394		prev = pos;
395		pos = pos->next;
396	}
397
398	return -1;
399}
400
401#endif /* CONFIG_PEERKEY */
402