• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * EAP peer method: EAP-PSK (RFC 4764)
3  * Copyright (c) 2004-2007, 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  * Note: EAP-PSK is an EAP authentication method and as such, completely
15  * different from WPA-PSK. This file is not needed for WPA-PSK functionality.
16  */
17 
18 #include "includes.h"
19 
20 #include "common.h"
21 #include "eap_i.h"
22 #include "config_ssid.h"
23 #include "md5.h"
24 #include "aes_wrap.h"
25 #include "eap_psk_common.h"
26 
27 
28 struct eap_psk_data {
29 	enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state;
30 	u8 rand_p[EAP_PSK_RAND_LEN];
31 	u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN];
32 	u8 *id_s, *id_p;
33 	size_t id_s_len, id_p_len;
34 	u8 msk[EAP_MSK_LEN];
35 	u8 emsk[EAP_EMSK_LEN];
36 };
37 
38 
eap_psk_init(struct eap_sm * sm)39 static void * eap_psk_init(struct eap_sm *sm)
40 {
41 	struct wpa_ssid *config = eap_get_config(sm);
42 	struct eap_psk_data *data;
43 
44 	if (config == NULL || !config->eappsk) {
45 		wpa_printf(MSG_INFO, "EAP-PSK: pre-shared key not configured");
46 		return NULL;
47 	}
48 
49 	data = os_zalloc(sizeof(*data));
50 	if (data == NULL)
51 		return NULL;
52 	eap_psk_key_setup(config->eappsk, data->ak, data->kdk);
53 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN);
54 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN);
55 	data->state = PSK_INIT;
56 
57 	if (config->nai) {
58 		data->id_p = os_malloc(config->nai_len);
59 		if (data->id_p)
60 			os_memcpy(data->id_p, config->nai, config->nai_len);
61 		data->id_p_len = config->nai_len;
62 	}
63 	if (data->id_p == NULL) {
64 		wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity");
65 		os_free(data);
66 		return NULL;
67 	}
68 
69 	return data;
70 }
71 
72 
eap_psk_deinit(struct eap_sm * sm,void * priv)73 static void eap_psk_deinit(struct eap_sm *sm, void *priv)
74 {
75 	struct eap_psk_data *data = priv;
76 	os_free(data->id_s);
77 	os_free(data->id_p);
78 	os_free(data);
79 }
80 
81 
eap_psk_process_1(struct eap_psk_data * data,struct eap_method_ret * ret,const u8 * reqData,size_t reqDataLen,size_t * respDataLen)82 static u8 * eap_psk_process_1(struct eap_psk_data *data,
83 			      struct eap_method_ret *ret,
84 			      const u8 *reqData, size_t reqDataLen,
85 			      size_t *respDataLen)
86 {
87 	const struct eap_psk_hdr_1 *hdr1;
88 	struct eap_psk_hdr_2 *hdr2;
89 	u8 *resp, *buf, *pos;
90 	size_t buflen;
91 
92 	wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state");
93 
94 	hdr1 = (const struct eap_psk_hdr_1 *) reqData;
95 	if (reqDataLen < sizeof(*hdr1) ||
96 	    be_to_host16(hdr1->length) < sizeof(*hdr1) ||
97 	    be_to_host16(hdr1->length) > reqDataLen) {
98 		wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message "
99 			   "length (%lu %d; expected %lu or more)",
100 			   (unsigned long) reqDataLen,
101 			   be_to_host16(hdr1->length),
102 			   (unsigned long) sizeof(*hdr1));
103 		ret->ignore = TRUE;
104 		return NULL;
105 	}
106 	wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags);
107 	if (EAP_PSK_FLAGS_GET_T(hdr1->flags) != 0) {
108 		wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)",
109 			   EAP_PSK_FLAGS_GET_T(hdr1->flags));
110 		ret->methodState = METHOD_DONE;
111 		ret->decision = DECISION_FAIL;
112 		return NULL;
113 	}
114 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s,
115 		    EAP_PSK_RAND_LEN);
116 	os_free(data->id_s);
117 	data->id_s_len = be_to_host16(hdr1->length) - sizeof(*hdr1);
118 	data->id_s = os_malloc(data->id_s_len);
119 	if (data->id_s == NULL) {
120 		wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for "
121 			   "ID_S (len=%lu)", (unsigned long) data->id_s_len);
122 		ret->ignore = TRUE;
123 		return NULL;
124 	}
125 	os_memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len);
126 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S",
127 			  data->id_s, data->id_s_len);
128 
129 	if (hostapd_get_rand(data->rand_p, EAP_PSK_RAND_LEN)) {
130 		wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data");
131 		ret->ignore = TRUE;
132 		return NULL;
133 	}
134 
135 	*respDataLen = sizeof(*hdr2) + data->id_p_len;
136 	resp = os_malloc(*respDataLen);
137 	if (resp == NULL)
138 		return NULL;
139 	hdr2 = (struct eap_psk_hdr_2 *) resp;
140 	hdr2->code = EAP_CODE_RESPONSE;
141 	hdr2->identifier = hdr1->identifier;
142 	hdr2->length = host_to_be16(*respDataLen);
143 	hdr2->type = EAP_TYPE_PSK;
144 	hdr2->flags = EAP_PSK_FLAGS_SET_T(1); /* T=1 */
145 	os_memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN);
146 	os_memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN);
147 	os_memcpy((u8 *) (hdr2 + 1), data->id_p, data->id_p_len);
148 	/* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */
149 	buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN;
150 	buf = os_malloc(buflen);
151 	if (buf == NULL) {
152 		os_free(resp);
153 		return NULL;
154 	}
155 	os_memcpy(buf, data->id_p, data->id_p_len);
156 	pos = buf + data->id_p_len;
157 	os_memcpy(pos, data->id_s, data->id_s_len);
158 	pos += data->id_s_len;
159 	os_memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN);
160 	pos += EAP_PSK_RAND_LEN;
161 	os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
162 	omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p);
163 	os_free(buf);
164 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p,
165 		    EAP_PSK_RAND_LEN);
166 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN);
167 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_P",
168 			  (u8 *) (hdr2 + 1), data->id_p_len);
169 
170 	data->state = PSK_MAC_SENT;
171 
172 	return resp;
173 }
174 
175 
eap_psk_process_3(struct eap_psk_data * data,struct eap_method_ret * ret,const u8 * reqData,size_t reqDataLen,size_t * respDataLen)176 static u8 * eap_psk_process_3(struct eap_psk_data *data,
177 			      struct eap_method_ret *ret,
178 			      const u8 *reqData, size_t reqDataLen,
179 			      size_t *respDataLen)
180 {
181 	const struct eap_psk_hdr_3 *hdr3;
182 	struct eap_psk_hdr_4 *hdr4;
183 	u8 *resp, *buf, *rpchannel, nonce[16], *decrypted;
184 	const u8 *pchannel, *tag, *msg;
185 	u8 mac[EAP_PSK_MAC_LEN];
186 	size_t buflen, left, data_len;
187 	int failed = 0;
188 
189 	wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state");
190 
191 	hdr3 = (const struct eap_psk_hdr_3 *) reqData;
192 	left = be_to_host16(hdr3->length);
193 	if (left < sizeof(*hdr3) || reqDataLen < left) {
194 		wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message "
195 			   "length (%lu %d; expected %lu)",
196 			   (unsigned long) reqDataLen,
197 			   be_to_host16(hdr3->length),
198 			   (unsigned long) sizeof(*hdr3));
199 		ret->ignore = TRUE;
200 		return NULL;
201 	}
202 	left -= sizeof(*hdr3);
203 	pchannel = (const u8 *) (hdr3 + 1);
204 	wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags);
205 	if (EAP_PSK_FLAGS_GET_T(hdr3->flags) != 2) {
206 		wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)",
207 			   EAP_PSK_FLAGS_GET_T(hdr3->flags));
208 		ret->methodState = METHOD_DONE;
209 		ret->decision = DECISION_FAIL;
210 		return NULL;
211 	}
212 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr3->rand_s,
213 		    EAP_PSK_RAND_LEN);
214 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_S", hdr3->mac_s, EAP_PSK_MAC_LEN);
215 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL", pchannel, left);
216 
217 	if (left < 4 + 16 + 1) {
218 		wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in "
219 			   "third message (len=%lu, expected 21)",
220 			   (unsigned long) left);
221 		ret->ignore = TRUE;
222 		return NULL;
223 	}
224 
225 	/* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
226 	buflen = data->id_s_len + EAP_PSK_RAND_LEN;
227 	buf = os_malloc(buflen);
228 	if (buf == NULL)
229 		return NULL;
230 	os_memcpy(buf, data->id_s, data->id_s_len);
231 	os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
232 	omac1_aes_128(data->ak, buf, buflen, mac);
233 	os_free(buf);
234 	if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) {
235 		wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third "
236 			   "message");
237 		ret->methodState = METHOD_DONE;
238 		ret->decision = DECISION_FAIL;
239 		return NULL;
240 	}
241 	wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully");
242 
243 	eap_psk_derive_keys(data->kdk, data->rand_p, data->tek,
244 			    data->msk, data->emsk);
245 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN);
246 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN);
247 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN);
248 
249 	os_memset(nonce, 0, 12);
250 	os_memcpy(nonce + 12, pchannel, 4);
251 	pchannel += 4;
252 	left -= 4;
253 
254 	tag = pchannel;
255 	pchannel += 16;
256 	left -= 16;
257 
258 	msg = pchannel;
259 
260 	wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - nonce",
261 		    nonce, sizeof(nonce));
262 	wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr", reqData, 5);
263 	wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left);
264 
265 	decrypted = os_malloc(left);
266 	if (decrypted == NULL) {
267 		ret->methodState = METHOD_DONE;
268 		ret->decision = DECISION_FAIL;
269 		return NULL;
270 	}
271 	os_memcpy(decrypted, msg, left);
272 
273 	if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce),
274 				reqData, 22, decrypted, left, tag)) {
275 		wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed");
276 		os_free(decrypted);
277 		return NULL;
278 	}
279 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message",
280 		    decrypted, left);
281 
282 	/* Verify R flag */
283 	switch (decrypted[0] >> 6) {
284 	case EAP_PSK_R_FLAG_CONT:
285 		wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported");
286 		failed = 1;
287 		break;
288 	case EAP_PSK_R_FLAG_DONE_SUCCESS:
289 		wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS");
290 		break;
291 	case EAP_PSK_R_FLAG_DONE_FAILURE:
292 		wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE");
293 		wpa_printf(MSG_INFO, "EAP-PSK: Authentication server rejected "
294 			   "authentication");
295 		failed = 1;
296 		break;
297 	}
298 
299 	*respDataLen = sizeof(*hdr4) + 4 + 16 + 1;
300 	resp = os_malloc(*respDataLen + 1);
301 	if (resp == NULL) {
302 		os_free(decrypted);
303 		return NULL;
304 	}
305 	hdr4 = (struct eap_psk_hdr_4 *) resp;
306 	hdr4->code = EAP_CODE_RESPONSE;
307 	hdr4->identifier = hdr3->identifier;
308 	hdr4->length = host_to_be16(*respDataLen);
309 	hdr4->type = EAP_TYPE_PSK;
310 	hdr4->flags = EAP_PSK_FLAGS_SET_T(3); /* T=3 */
311 	os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN);
312 	rpchannel = (u8 *) (hdr4 + 1);
313 
314 	/* nonce++ */
315 	inc_byte_array(nonce, sizeof(nonce));
316 	os_memcpy(rpchannel, nonce + 12, 4);
317 
318 	data_len = 1;
319 	if (decrypted[0] & EAP_PSK_E_FLAG) {
320 		wpa_printf(MSG_DEBUG, "EAP-PSK: Unsupported E (Ext) flag");
321 		failed = 1;
322 		rpchannel[4 + 16] = (EAP_PSK_R_FLAG_DONE_FAILURE << 6) |
323 			EAP_PSK_E_FLAG;
324 		if (left > 1) {
325 			/* Add empty EXT_Payload with same EXT_Type */
326 			(*respDataLen)++;
327 			hdr4->length = host_to_be16(*respDataLen);
328 			rpchannel[4 + 16 + 1] = decrypted[1];
329 			data_len++;
330 		}
331 	} else if (failed)
332 		rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_FAILURE << 6;
333 	else
334 		rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6;
335 
336 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)",
337 		    rpchannel + 4 + 16, data_len);
338 	aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), resp, 22,
339 			    rpchannel + 4 + 16, data_len, rpchannel + 4);
340 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)",
341 		    rpchannel, 4 + 16 + data_len);
342 
343 	wpa_printf(MSG_DEBUG, "EAP-PSK: Completed %ssuccessfully",
344 		   failed ? "un" : "");
345 	data->state = PSK_DONE;
346 	ret->methodState = METHOD_DONE;
347 	ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC;
348 
349 	os_free(decrypted);
350 
351 	return resp;
352 }
353 
354 
eap_psk_process(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const u8 * reqData,size_t reqDataLen,size_t * respDataLen)355 static u8 * eap_psk_process(struct eap_sm *sm, void *priv,
356 			    struct eap_method_ret *ret,
357 			    const u8 *reqData, size_t reqDataLen,
358 			    size_t *respDataLen)
359 {
360 	struct eap_psk_data *data = priv;
361 	const u8 *pos;
362 	u8 *resp = NULL;
363 	size_t len;
364 
365 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK,
366 			       reqData, reqDataLen, &len);
367 	if (pos == NULL) {
368 		ret->ignore = TRUE;
369 		return NULL;
370 	}
371 	len += sizeof(struct eap_hdr) + 1;
372 
373 	ret->ignore = FALSE;
374 	ret->methodState = METHOD_MAY_CONT;
375 	ret->decision = DECISION_FAIL;
376 	ret->allowNotifications = TRUE;
377 
378 	switch (data->state) {
379 	case PSK_INIT:
380 		resp = eap_psk_process_1(data, ret, reqData, len,
381 					 respDataLen);
382 		break;
383 	case PSK_MAC_SENT:
384 		resp = eap_psk_process_3(data, ret, reqData, len,
385 					 respDataLen);
386 		break;
387 	case PSK_DONE:
388 		wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore "
389 			   "unexpected message");
390 		ret->ignore = TRUE;
391 		return NULL;
392 	}
393 
394 	if (ret->methodState == METHOD_DONE) {
395 		ret->allowNotifications = FALSE;
396 	}
397 
398 	return resp;
399 }
400 
401 
eap_psk_isKeyAvailable(struct eap_sm * sm,void * priv)402 static Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv)
403 {
404 	struct eap_psk_data *data = priv;
405 	return data->state == PSK_DONE;
406 }
407 
408 
eap_psk_getKey(struct eap_sm * sm,void * priv,size_t * len)409 static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len)
410 {
411 	struct eap_psk_data *data = priv;
412 	u8 *key;
413 
414 	if (data->state != PSK_DONE)
415 		return NULL;
416 
417 	key = os_malloc(EAP_MSK_LEN);
418 	if (key == NULL)
419 		return NULL;
420 
421 	*len = EAP_MSK_LEN;
422 	os_memcpy(key, data->msk, EAP_MSK_LEN);
423 
424 	return key;
425 }
426 
427 
eap_psk_get_emsk(struct eap_sm * sm,void * priv,size_t * len)428 static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
429 {
430 	struct eap_psk_data *data = priv;
431 	u8 *key;
432 
433 	if (data->state != PSK_DONE)
434 		return NULL;
435 
436 	key = os_malloc(EAP_EMSK_LEN);
437 	if (key == NULL)
438 		return NULL;
439 
440 	*len = EAP_EMSK_LEN;
441 	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
442 
443 	return key;
444 }
445 
446 
eap_peer_psk_register(void)447 int eap_peer_psk_register(void)
448 {
449 	struct eap_method *eap;
450 	int ret;
451 
452 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
453 				    EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK");
454 	if (eap == NULL)
455 		return -1;
456 
457 	eap->init = eap_psk_init;
458 	eap->deinit = eap_psk_deinit;
459 	eap->process = eap_psk_process;
460 	eap->isKeyAvailable = eap_psk_isKeyAvailable;
461 	eap->getKey = eap_psk_getKey;
462 	eap->get_emsk = eap_psk_get_emsk;
463 
464 	ret = eap_peer_method_register(eap);
465 	if (ret)
466 		eap_peer_method_free(eap);
467 	return ret;
468 }
469