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