• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
wpa_stsl_step(void * eloop_ctx,void * timeout_ctx)28 static 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 
39 struct wpa_stsl_search {
40 	const u8 *addr;
41 	struct wpa_state_machine *sm;
42 };
43 
44 
wpa_stsl_select_sta(struct wpa_state_machine * sm,void * ctx)45 static 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 
wpa_smk_send_error(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,const u8 * peer,u16 mui,u16 error_type)56 static 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 
wpa_smk_m1(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key)87 void 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 
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)151 static 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 
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)204 static 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 
wpa_smk_m3(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key)261 void 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 
wpa_smk_error(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key)332 void 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 
wpa_stsl_remove(struct wpa_authenticator * wpa_auth,struct wpa_stsl_negotiation * neg)375 int 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