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