eap_server_ikev2.c revision 214734
1/*
2 * EAP-IKEv2 server (RFC 5106)
3 * Copyright (c) 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
15#include "includes.h"
16
17#include "common.h"
18#include "eap_i.h"
19#include "eap_common/eap_ikev2_common.h"
20#include "ikev2.h"
21
22
23struct eap_ikev2_data {
24	struct ikev2_initiator_data ikev2;
25	enum { MSG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state;
26	struct wpabuf *in_buf;
27	struct wpabuf *out_buf;
28	size_t out_used;
29	size_t fragment_size;
30	int keys_ready;
31	u8 keymat[EAP_MSK_LEN + EAP_EMSK_LEN];
32	int keymat_ok;
33};
34
35
36static const u8 * eap_ikev2_get_shared_secret(void *ctx, const u8 *IDr,
37					      size_t IDr_len,
38					      size_t *secret_len)
39{
40	struct eap_sm *sm = ctx;
41
42	if (IDr == NULL) {
43		wpa_printf(MSG_DEBUG, "EAP-IKEV2: No IDr received - default "
44			   "to user identity from EAP-Identity");
45		IDr = sm->identity;
46		IDr_len = sm->identity_len;
47	}
48
49	if (eap_user_get(sm, IDr, IDr_len, 0) < 0 || sm->user == NULL ||
50	    sm->user->password == NULL) {
51		wpa_printf(MSG_DEBUG, "EAP-IKEV2: No user entry found");
52		return NULL;
53	}
54
55	*secret_len = sm->user->password_len;
56	return sm->user->password;
57}
58
59
60static const char * eap_ikev2_state_txt(int state)
61{
62	switch (state) {
63	case MSG:
64		return "MSG";
65	case FRAG_ACK:
66		return "FRAG_ACK";
67	case WAIT_FRAG_ACK:
68		return "WAIT_FRAG_ACK";
69	case DONE:
70		return "DONE";
71	case FAIL:
72		return "FAIL";
73	default:
74		return "?";
75	}
76}
77
78
79static void eap_ikev2_state(struct eap_ikev2_data *data, int state)
80{
81	wpa_printf(MSG_DEBUG, "EAP-IKEV2: %s -> %s",
82		   eap_ikev2_state_txt(data->state),
83		   eap_ikev2_state_txt(state));
84	data->state = state;
85}
86
87
88static void * eap_ikev2_init(struct eap_sm *sm)
89{
90	struct eap_ikev2_data *data;
91
92	data = os_zalloc(sizeof(*data));
93	if (data == NULL)
94		return NULL;
95	data->state = MSG;
96	data->fragment_size = IKEV2_FRAGMENT_SIZE;
97	data->ikev2.state = SA_INIT;
98	data->ikev2.peer_auth = PEER_AUTH_SECRET;
99	data->ikev2.key_pad = (u8 *) os_strdup("Key Pad for EAP-IKEv2");
100	if (data->ikev2.key_pad == NULL)
101		goto failed;
102	data->ikev2.key_pad_len = 21;
103
104	/* TODO: make proposals configurable */
105	data->ikev2.proposal.proposal_num = 1;
106	data->ikev2.proposal.integ = AUTH_HMAC_SHA1_96;
107	data->ikev2.proposal.prf = PRF_HMAC_SHA1;
108	data->ikev2.proposal.encr = ENCR_AES_CBC;
109	data->ikev2.proposal.dh = DH_GROUP2_1024BIT_MODP;
110
111	data->ikev2.IDi = (u8 *) os_strdup("hostapd");
112	data->ikev2.IDi_len = 7;
113
114	data->ikev2.get_shared_secret = eap_ikev2_get_shared_secret;
115	data->ikev2.cb_ctx = sm;
116
117	return data;
118
119failed:
120	ikev2_initiator_deinit(&data->ikev2);
121	os_free(data);
122	return NULL;
123}
124
125
126static void eap_ikev2_reset(struct eap_sm *sm, void *priv)
127{
128	struct eap_ikev2_data *data = priv;
129	wpabuf_free(data->in_buf);
130	wpabuf_free(data->out_buf);
131	ikev2_initiator_deinit(&data->ikev2);
132	os_free(data);
133}
134
135
136static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, u8 id)
137{
138	struct wpabuf *req;
139	u8 flags;
140	size_t send_len, plen, icv_len = 0;
141
142	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Request");
143
144	flags = 0;
145	send_len = wpabuf_len(data->out_buf) - data->out_used;
146	if (1 + send_len > data->fragment_size) {
147		send_len = data->fragment_size - 1;
148		flags |= IKEV2_FLAGS_MORE_FRAGMENTS;
149		if (data->out_used == 0) {
150			flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
151			send_len -= 4;
152		}
153	}
154
155	plen = 1 + send_len;
156	if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
157		plen += 4;
158	if (data->keys_ready) {
159		const struct ikev2_integ_alg *integ;
160		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum "
161			   "Data");
162		flags |= IKEV2_FLAGS_ICV_INCLUDED;
163		integ = ikev2_get_integ(data->ikev2.proposal.integ);
164		if (integ == NULL) {
165			wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
166				   "transform / cannot generate ICV");
167			return NULL;
168		}
169		icv_len = integ->hash_len;
170
171		plen += icv_len;
172	}
173	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen,
174			    EAP_CODE_REQUEST, id);
175	if (req == NULL)
176		return NULL;
177
178	wpabuf_put_u8(req, flags); /* Flags */
179	if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
180		wpabuf_put_be32(req, wpabuf_len(data->out_buf));
181
182	wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used,
183			send_len);
184	data->out_used += send_len;
185
186	if (flags & IKEV2_FLAGS_ICV_INCLUDED) {
187		const u8 *msg = wpabuf_head(req);
188		size_t len = wpabuf_len(req);
189		ikev2_integ_hash(data->ikev2.proposal.integ,
190				 data->ikev2.keys.SK_ai,
191				 data->ikev2.keys.SK_integ_len,
192				 msg, len, wpabuf_put(req, icv_len));
193	}
194
195	if (data->out_used == wpabuf_len(data->out_buf)) {
196		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
197			   "(message sent completely)",
198			   (unsigned long) send_len);
199		wpabuf_free(data->out_buf);
200		data->out_buf = NULL;
201		data->out_used = 0;
202	} else {
203		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
204			   "(%lu more to send)", (unsigned long) send_len,
205			   (unsigned long) wpabuf_len(data->out_buf) -
206			   data->out_used);
207		eap_ikev2_state(data, WAIT_FRAG_ACK);
208	}
209
210	return req;
211}
212
213
214static struct wpabuf * eap_ikev2_buildReq(struct eap_sm *sm, void *priv, u8 id)
215{
216	struct eap_ikev2_data *data = priv;
217
218	switch (data->state) {
219	case MSG:
220		if (data->out_buf == NULL) {
221			data->out_buf = ikev2_initiator_build(&data->ikev2);
222			if (data->out_buf == NULL) {
223				wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to "
224					   "generate IKEv2 message");
225				return NULL;
226			}
227			data->out_used = 0;
228		}
229		/* pass through */
230	case WAIT_FRAG_ACK:
231		return eap_ikev2_build_msg(data, id);
232	case FRAG_ACK:
233		return eap_ikev2_build_frag_ack(id, EAP_CODE_REQUEST);
234	default:
235		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected state %d in "
236			   "buildReq", data->state);
237		return NULL;
238	}
239}
240
241
242static Boolean eap_ikev2_check(struct eap_sm *sm, void *priv,
243			       struct wpabuf *respData)
244{
245	const u8 *pos;
246	size_t len;
247
248	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, respData,
249			       &len);
250	if (pos == NULL) {
251		wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid frame");
252		return TRUE;
253	}
254
255	return FALSE;
256}
257
258
259static int eap_ikev2_process_icv(struct eap_ikev2_data *data,
260				 const struct wpabuf *respData,
261				 u8 flags, const u8 *pos, const u8 **end)
262{
263	if (flags & IKEV2_FLAGS_ICV_INCLUDED) {
264		int icv_len = eap_ikev2_validate_icv(
265			data->ikev2.proposal.integ, &data->ikev2.keys, 0,
266			respData, pos, *end);
267		if (icv_len < 0)
268			return -1;
269		/* Hide Integrity Checksum Data from further processing */
270		*end -= icv_len;
271	} else if (data->keys_ready) {
272		wpa_printf(MSG_INFO, "EAP-IKEV2: The message should have "
273			   "included integrity checksum");
274		return -1;
275	}
276
277	return 0;
278}
279
280
281static int eap_ikev2_process_cont(struct eap_ikev2_data *data,
282				  const u8 *buf, size_t len)
283{
284	/* Process continuation of a pending message */
285	if (len > wpabuf_tailroom(data->in_buf)) {
286		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment overflow");
287		eap_ikev2_state(data, FAIL);
288		return -1;
289	}
290
291	wpabuf_put_data(data->in_buf, buf, len);
292	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes, waiting for %lu "
293		   "bytes more", (unsigned long) len,
294		   (unsigned long) wpabuf_tailroom(data->in_buf));
295
296	return 0;
297}
298
299
300static int eap_ikev2_process_fragment(struct eap_ikev2_data *data,
301				      u8 flags, u32 message_length,
302				      const u8 *buf, size_t len)
303{
304	/* Process a fragment that is not the last one of the message */
305	if (data->in_buf == NULL && !(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) {
306		wpa_printf(MSG_DEBUG, "EAP-IKEV2: No Message Length field in "
307			   "a fragmented packet");
308		return -1;
309	}
310
311	if (data->in_buf == NULL) {
312		/* First fragment of the message */
313		data->in_buf = wpabuf_alloc(message_length);
314		if (data->in_buf == NULL) {
315			wpa_printf(MSG_DEBUG, "EAP-IKEV2: No memory for "
316				   "message");
317			return -1;
318		}
319		wpabuf_put_data(data->in_buf, buf, len);
320		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes in first "
321			   "fragment, waiting for %lu bytes more",
322			   (unsigned long) len,
323			   (unsigned long) wpabuf_tailroom(data->in_buf));
324	}
325
326	return 0;
327}
328
329
330static int eap_ikev2_server_keymat(struct eap_ikev2_data *data)
331{
332	if (eap_ikev2_derive_keymat(
333		    data->ikev2.proposal.prf, &data->ikev2.keys,
334		    data->ikev2.i_nonce, data->ikev2.i_nonce_len,
335		    data->ikev2.r_nonce, data->ikev2.r_nonce_len,
336		    data->keymat) < 0) {
337		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to derive "
338			   "key material");
339		return -1;
340	}
341	data->keymat_ok = 1;
342	return 0;
343}
344
345
346static void eap_ikev2_process(struct eap_sm *sm, void *priv,
347			      struct wpabuf *respData)
348{
349	struct eap_ikev2_data *data = priv;
350	const u8 *start, *pos, *end;
351	size_t len;
352	u8 flags;
353	u32 message_length = 0;
354	struct wpabuf tmpbuf;
355
356	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, respData,
357			       &len);
358	if (pos == NULL)
359		return; /* Should not happen; message already verified */
360
361	start = pos;
362	end = start + len;
363
364	if (len == 0) {
365		/* fragment ack */
366		flags = 0;
367	} else
368		flags = *pos++;
369
370	if (eap_ikev2_process_icv(data, respData, flags, pos, &end) < 0) {
371		eap_ikev2_state(data, FAIL);
372		return;
373	}
374
375	if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) {
376		if (end - pos < 4) {
377			wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow");
378			eap_ikev2_state(data, FAIL);
379			return;
380		}
381		message_length = WPA_GET_BE32(pos);
382		pos += 4;
383
384		if (message_length < (u32) (end - pos)) {
385			wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message "
386				   "Length (%d; %ld remaining in this msg)",
387				   message_length, (long) (end - pos));
388			eap_ikev2_state(data, FAIL);
389			return;
390		}
391	}
392	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received packet: Flags 0x%x "
393		   "Message Length %u", flags, message_length);
394
395	if (data->state == WAIT_FRAG_ACK) {
396		if (len != 0) {
397			wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload "
398				   "in WAIT_FRAG_ACK state");
399			eap_ikev2_state(data, FAIL);
400			return;
401		}
402		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged");
403		eap_ikev2_state(data, MSG);
404		return;
405	}
406
407	if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) {
408		eap_ikev2_state(data, FAIL);
409		return;
410	}
411
412	if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) {
413		if (eap_ikev2_process_fragment(data, flags, message_length,
414					       pos, end - pos) < 0)
415			eap_ikev2_state(data, FAIL);
416		else
417			eap_ikev2_state(data, FRAG_ACK);
418		return;
419	} else if (data->state == FRAG_ACK) {
420		wpa_printf(MSG_DEBUG, "EAP-TNC: All fragments received");
421		data->state = MSG;
422	}
423
424	if (data->in_buf == NULL) {
425		/* Wrap unfragmented messages as wpabuf without extra copy */
426		wpabuf_set(&tmpbuf, pos, end - pos);
427		data->in_buf = &tmpbuf;
428	}
429
430	if (ikev2_initiator_process(&data->ikev2, data->in_buf) < 0) {
431		if (data->in_buf == &tmpbuf)
432			data->in_buf = NULL;
433		eap_ikev2_state(data, FAIL);
434		return;
435	}
436
437	switch (data->ikev2.state) {
438	case SA_AUTH:
439		/* SA_INIT was sent out, so message have to be
440		 * integrity protected from now on. */
441		data->keys_ready = 1;
442		break;
443	case IKEV2_DONE:
444		if (data->state == FAIL)
445			break;
446		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication completed "
447			   "successfully");
448		if (eap_ikev2_server_keymat(data))
449			break;
450		eap_ikev2_state(data, DONE);
451		break;
452	default:
453		break;
454	}
455
456	if (data->in_buf != &tmpbuf)
457		wpabuf_free(data->in_buf);
458	data->in_buf = NULL;
459}
460
461
462static Boolean eap_ikev2_isDone(struct eap_sm *sm, void *priv)
463{
464	struct eap_ikev2_data *data = priv;
465	return data->state == DONE || data->state == FAIL;
466}
467
468
469static Boolean eap_ikev2_isSuccess(struct eap_sm *sm, void *priv)
470{
471	struct eap_ikev2_data *data = priv;
472	return data->state == DONE && data->ikev2.state == IKEV2_DONE &&
473		data->keymat_ok;
474}
475
476
477static u8 * eap_ikev2_getKey(struct eap_sm *sm, void *priv, size_t *len)
478{
479	struct eap_ikev2_data *data = priv;
480	u8 *key;
481
482	if (data->state != DONE || !data->keymat_ok)
483		return NULL;
484
485	key = os_malloc(EAP_MSK_LEN);
486	if (key) {
487		os_memcpy(key, data->keymat, EAP_MSK_LEN);
488		*len = EAP_MSK_LEN;
489	}
490
491	return key;
492}
493
494
495static u8 * eap_ikev2_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
496{
497	struct eap_ikev2_data *data = priv;
498	u8 *key;
499
500	if (data->state != DONE || !data->keymat_ok)
501		return NULL;
502
503	key = os_malloc(EAP_EMSK_LEN);
504	if (key) {
505		os_memcpy(key, data->keymat + EAP_MSK_LEN, EAP_EMSK_LEN);
506		*len = EAP_EMSK_LEN;
507	}
508
509	return key;
510}
511
512
513int eap_server_ikev2_register(void)
514{
515	struct eap_method *eap;
516	int ret;
517
518	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
519				      EAP_VENDOR_IETF, EAP_TYPE_IKEV2,
520				      "IKEV2");
521	if (eap == NULL)
522		return -1;
523
524	eap->init = eap_ikev2_init;
525	eap->reset = eap_ikev2_reset;
526	eap->buildReq = eap_ikev2_buildReq;
527	eap->check = eap_ikev2_check;
528	eap->process = eap_ikev2_process;
529	eap->isDone = eap_ikev2_isDone;
530	eap->getKey = eap_ikev2_getKey;
531	eap->isSuccess = eap_ikev2_isSuccess;
532	eap->get_emsk = eap_ikev2_get_emsk;
533
534	ret = eap_server_method_register(eap);
535	if (ret)
536		eap_server_method_free(eap);
537	return ret;
538}
539