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