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 
wpa_stsl_step(void * eloop_ctx,void * timeout_ctx)27 static 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 
38 struct wpa_stsl_search {
39 	const u8 *addr;
40 	struct wpa_state_machine *sm;
41 };
42 
43 
wpa_stsl_select_sta(struct wpa_state_machine * sm,void * ctx)44 static 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 
wpa_smk_send_error(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,const u8 * peer,u16 mui,u16 error_type)55 static 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 
wpa_smk_m1(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key)86 void 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 
wpa_send_smk_m4(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key,struct wpa_eapol_ie_parse * kde,const u8 * smk)150 static 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 
wpa_send_smk_m5(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key,struct wpa_eapol_ie_parse * kde,const u8 * smk,const u8 * peer)203 static 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 
wpa_smk_m3(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key)260 void 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 
wpa_smk_error(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key)331 void 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 
wpa_stsl_remove(struct wpa_authenticator * wpa_auth,struct wpa_stsl_negotiation * neg)374 int 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