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