• 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 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 
wpa_stsl_step(void * eloop_ctx,void * timeout_ctx)22 static 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 
33 struct wpa_stsl_search {
34 	const u8 *addr;
35 	struct wpa_state_machine *sm;
36 };
37 
38 
wpa_stsl_select_sta(struct wpa_state_machine * sm,void * ctx)39 static 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 
wpa_smk_send_error(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,const u8 * peer,u16 mui,u16 error_type)50 static 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 
wpa_smk_m1(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key)81 void 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 
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)145 static 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 
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)198 static 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(buf, kde->rsn_ie, kde->rsn_ie_len);
225 	pos = buf + 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 
wpa_smk_m3(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key)255 void 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 
wpa_smk_error(struct wpa_authenticator * wpa_auth,struct wpa_state_machine * sm,struct wpa_eapol_key * key)326 void 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 
wpa_stsl_remove(struct wpa_authenticator * wpa_auth,struct wpa_stsl_negotiation * neg)369 int 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