2 * EAP-IKEv2 peer (RFC 5106)
3 * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
19 #include "eap_common/eap_ikev2_common.h"
23 struct eap_ikev2_data
{
24 struct ikev2_responder_data ikev2
;
25 enum { WAIT_START
, PROC_MSG
, WAIT_FRAG_ACK
, DONE
, FAIL
} state
;
26 struct wpabuf
*in_buf
;
27 struct wpabuf
*out_buf
;
31 u8 keymat
[EAP_MSK_LEN
+ EAP_EMSK_LEN
];
36 static const char * eap_ikev2_state_txt(int state
)
44 return "WAIT_FRAG_ACK";
55 static void eap_ikev2_state(struct eap_ikev2_data
*data
, int state
)
57 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: %s -> %s",
58 eap_ikev2_state_txt(data
->state
),
59 eap_ikev2_state_txt(state
));
64 static void * eap_ikev2_init(struct eap_sm
*sm
)
66 struct eap_ikev2_data
*data
;
67 const u8
*identity
, *password
;
68 size_t identity_len
, password_len
;
70 identity
= eap_get_config_identity(sm
, &identity_len
);
71 if (identity
== NULL
) {
72 wpa_printf(MSG_INFO
, "EAP-IKEV2: No identity available");
76 data
= os_zalloc(sizeof(*data
));
79 data
->state
= WAIT_START
;
80 data
->fragment_size
= IKEV2_FRAGMENT_SIZE
;
81 data
->ikev2
.state
= SA_INIT
;
82 data
->ikev2
.peer_auth
= PEER_AUTH_SECRET
;
83 data
->ikev2
.key_pad
= (u8
*) os_strdup("Key Pad for EAP-IKEv2");
84 if (data
->ikev2
.key_pad
== NULL
)
86 data
->ikev2
.key_pad_len
= 21;
87 data
->ikev2
.IDr
= os_malloc(identity_len
);
88 if (data
->ikev2
.IDr
== NULL
)
90 os_memcpy(data
->ikev2
.IDr
, identity
, identity_len
);
91 data
->ikev2
.IDr_len
= identity_len
;
93 password
= eap_get_config_password(sm
, &password_len
);
95 data
->ikev2
.shared_secret
= os_malloc(password_len
);
96 if (data
->ikev2
.shared_secret
== NULL
)
98 os_memcpy(data
->ikev2
.shared_secret
, password
, password_len
);
99 data
->ikev2
.shared_secret_len
= password_len
;
105 ikev2_responder_deinit(&data
->ikev2
);
111 static void eap_ikev2_deinit(struct eap_sm
*sm
, void *priv
)
113 struct eap_ikev2_data
*data
= priv
;
114 wpabuf_free(data
->in_buf
);
115 wpabuf_free(data
->out_buf
);
116 ikev2_responder_deinit(&data
->ikev2
);
121 static int eap_ikev2_peer_keymat(struct eap_ikev2_data
*data
)
123 if (eap_ikev2_derive_keymat(
124 data
->ikev2
.proposal
.prf
, &data
->ikev2
.keys
,
125 data
->ikev2
.i_nonce
, data
->ikev2
.i_nonce_len
,
126 data
->ikev2
.r_nonce
, data
->ikev2
.r_nonce_len
,
128 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Failed to "
129 "derive key material");
137 static struct wpabuf
* eap_ikev2_build_msg(struct eap_ikev2_data
*data
,
138 struct eap_method_ret
*ret
, u8 id
)
142 size_t send_len
, plen
, icv_len
= 0;
145 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Generating Response");
146 ret
->allowNotifications
= TRUE
;
149 send_len
= wpabuf_len(data
->out_buf
) - data
->out_used
;
150 if (1 + send_len
> data
->fragment_size
) {
151 send_len
= data
->fragment_size
- 1;
152 flags
|= IKEV2_FLAGS_MORE_FRAGMENTS
;
153 if (data
->out_used
== 0) {
154 flags
|= IKEV2_FLAGS_LENGTH_INCLUDED
;
159 /* Some issues figuring out the length of the message if Message Length
160 * field not included?! */
161 if (!(flags
& IKEV2_FLAGS_LENGTH_INCLUDED
))
162 flags
|= IKEV2_FLAGS_LENGTH_INCLUDED
;
166 if (flags
& IKEV2_FLAGS_LENGTH_INCLUDED
)
168 if (data
->keys_ready
) {
169 const struct ikev2_integ_alg
*integ
;
170 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Add Integrity Checksum "
172 flags
|= IKEV2_FLAGS_ICV_INCLUDED
;
173 integ
= ikev2_get_integ(data
->ikev2
.proposal
.integ
);
175 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Unknown INTEG "
176 "transform / cannot generate ICV");
179 icv_len
= integ
->hash_len
;
183 resp
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_IKEV2
, plen
,
184 EAP_CODE_RESPONSE
, id
);
188 wpabuf_put_u8(resp
, flags
); /* Flags */
189 if (flags
& IKEV2_FLAGS_LENGTH_INCLUDED
)
190 wpabuf_put_be32(resp
, wpabuf_len(data
->out_buf
));
192 wpabuf_put_data(resp
, wpabuf_head_u8(data
->out_buf
) + data
->out_used
,
194 data
->out_used
+= send_len
;
196 if (flags
& IKEV2_FLAGS_ICV_INCLUDED
) {
197 const u8
*msg
= wpabuf_head(resp
);
198 size_t len
= wpabuf_len(resp
);
199 ikev2_integ_hash(data
->ikev2
.proposal
.integ
,
200 data
->ikev2
.keys
.SK_ar
,
201 data
->ikev2
.keys
.SK_integ_len
,
202 msg
, len
, wpabuf_put(resp
, icv_len
));
205 ret
->methodState
= METHOD_MAY_CONT
;
206 ret
->decision
= DECISION_FAIL
;
208 if (data
->out_used
== wpabuf_len(data
->out_buf
)) {
209 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Sending out %lu bytes "
210 "(message sent completely)",
211 (unsigned long) send_len
);
212 wpabuf_free(data
->out_buf
);
213 data
->out_buf
= NULL
;
215 switch (data
->ikev2
.state
) {
217 /* SA_INIT was sent out, so message have to be
218 * integrity protected from now on. */
219 data
->keys_ready
= 1;
222 ret
->methodState
= METHOD_DONE
;
223 if (data
->state
== FAIL
)
225 ret
->decision
= DECISION_COND_SUCC
;
226 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Authentication "
227 "completed successfully");
228 if (eap_ikev2_peer_keymat(data
))
230 eap_ikev2_state(data
, DONE
);
233 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Authentication "
235 ret
->methodState
= METHOD_DONE
;
236 ret
->decision
= DECISION_FAIL
;
242 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Sending out %lu bytes "
243 "(%lu more to send)", (unsigned long) send_len
,
244 (unsigned long) wpabuf_len(data
->out_buf
) -
246 eap_ikev2_state(data
, WAIT_FRAG_ACK
);
253 static int eap_ikev2_process_icv(struct eap_ikev2_data
*data
,
254 const struct wpabuf
*reqData
,
255 u8 flags
, const u8
*pos
, const u8
**end
)
257 if (flags
& IKEV2_FLAGS_ICV_INCLUDED
) {
258 int icv_len
= eap_ikev2_validate_icv(
259 data
->ikev2
.proposal
.integ
, &data
->ikev2
.keys
, 1,
263 /* Hide Integrity Checksum Data from further processing */
265 } else if (data
->keys_ready
) {
266 wpa_printf(MSG_INFO
, "EAP-IKEV2: The message should have "
267 "included integrity checksum");
275 static int eap_ikev2_process_cont(struct eap_ikev2_data
*data
,
276 const u8
*buf
, size_t len
)
278 /* Process continuation of a pending message */
279 if (len
> wpabuf_tailroom(data
->in_buf
)) {
280 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Fragment overflow");
281 eap_ikev2_state(data
, FAIL
);
285 wpabuf_put_data(data
->in_buf
, buf
, len
);
286 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Received %lu bytes, waiting "
287 "for %lu bytes more", (unsigned long) len
,
288 (unsigned long) wpabuf_tailroom(data
->in_buf
));
294 static struct wpabuf
* eap_ikev2_process_fragment(struct eap_ikev2_data
*data
,
295 struct eap_method_ret
*ret
,
298 const u8
*buf
, size_t len
)
300 /* Process a fragment that is not the last one of the message */
301 if (data
->in_buf
== NULL
&& !(flags
& IKEV2_FLAGS_LENGTH_INCLUDED
)) {
302 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: No Message Length field in "
303 "a fragmented packet");
308 if (data
->in_buf
== NULL
) {
309 /* First fragment of the message */
310 data
->in_buf
= wpabuf_alloc(message_length
);
311 if (data
->in_buf
== NULL
) {
312 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: No memory for "
317 wpabuf_put_data(data
->in_buf
, buf
, len
);
318 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Received %lu bytes in first "
319 "fragment, waiting for %lu bytes more",
321 (unsigned long) wpabuf_tailroom(data
->in_buf
));
324 return eap_ikev2_build_frag_ack(id
, EAP_CODE_RESPONSE
);
328 static struct wpabuf
* eap_ikev2_process(struct eap_sm
*sm
, void *priv
,
329 struct eap_method_ret
*ret
,
330 const struct wpabuf
*reqData
)
332 struct eap_ikev2_data
*data
= priv
;
333 const u8
*start
, *pos
, *end
;
336 u32 message_length
= 0;
337 struct wpabuf tmpbuf
;
339 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_IKEV2
, reqData
, &len
);
345 id
= eap_get_id(reqData
);
351 flags
= 0; /* fragment ack */
355 if (eap_ikev2_process_icv(data
, reqData
, flags
, pos
, &end
) < 0) {
360 if (flags
& IKEV2_FLAGS_LENGTH_INCLUDED
) {
362 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Message underflow");
366 message_length
= WPA_GET_BE32(pos
);
369 if (message_length
< (u32
) (end
- pos
)) {
370 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Invalid Message "
371 "Length (%d; %ld remaining in this msg)",
372 message_length
, (long) (end
- pos
));
378 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Received packet: Flags 0x%x "
379 "Message Length %u", flags
, message_length
);
381 if (data
->state
== WAIT_FRAG_ACK
) {
383 if (len
> 1) /* Empty Flags field included in ACK */
388 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Unexpected payload "
389 "in WAIT_FRAG_ACK state");
393 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Fragment acknowledged");
394 eap_ikev2_state(data
, PROC_MSG
);
395 return eap_ikev2_build_msg(data
, ret
, id
);
398 if (data
->in_buf
&& eap_ikev2_process_cont(data
, pos
, end
- pos
) < 0) {
403 if (flags
& IKEV2_FLAGS_MORE_FRAGMENTS
) {
404 return eap_ikev2_process_fragment(data
, ret
, id
, flags
,
409 if (data
->in_buf
== NULL
) {
410 /* Wrap unfragmented messages as wpabuf without extra copy */
411 wpabuf_set(&tmpbuf
, pos
, end
- pos
);
412 data
->in_buf
= &tmpbuf
;
415 if (ikev2_responder_process(&data
->ikev2
, data
->in_buf
) < 0) {
416 if (data
->in_buf
== &tmpbuf
)
418 eap_ikev2_state(data
, FAIL
);
422 if (data
->in_buf
!= &tmpbuf
)
423 wpabuf_free(data
->in_buf
);
426 if (data
->out_buf
== NULL
) {
427 data
->out_buf
= ikev2_responder_build(&data
->ikev2
);
428 if (data
->out_buf
== NULL
) {
429 wpa_printf(MSG_DEBUG
, "EAP-IKEV2: Failed to generate "
436 eap_ikev2_state(data
, PROC_MSG
);
437 return eap_ikev2_build_msg(data
, ret
, id
);
441 static Boolean
eap_ikev2_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
443 struct eap_ikev2_data
*data
= priv
;
444 return data
->state
== DONE
&& data
->keymat_ok
;
448 static u8
* eap_ikev2_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
450 struct eap_ikev2_data
*data
= priv
;
453 if (data
->state
!= DONE
|| !data
->keymat_ok
)
456 key
= os_malloc(EAP_MSK_LEN
);
458 os_memcpy(key
, data
->keymat
, EAP_MSK_LEN
);
466 static u8
* eap_ikev2_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
468 struct eap_ikev2_data
*data
= priv
;
471 if (data
->state
!= DONE
|| !data
->keymat_ok
)
474 key
= os_malloc(EAP_EMSK_LEN
);
476 os_memcpy(key
, data
->keymat
+ EAP_MSK_LEN
, EAP_EMSK_LEN
);
484 int eap_peer_ikev2_register(void)
486 struct eap_method
*eap
;
489 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
490 EAP_VENDOR_IETF
, EAP_TYPE_IKEV2
,
495 eap
->init
= eap_ikev2_init
;
496 eap
->deinit
= eap_ikev2_deinit
;
497 eap
->process
= eap_ikev2_process
;
498 eap
->isKeyAvailable
= eap_ikev2_isKeyAvailable
;
499 eap
->getKey
= eap_ikev2_getKey
;
500 eap
->get_emsk
= eap_ikev2_get_emsk
;
502 ret
= eap_peer_method_register(eap
);
504 eap_peer_method_free(eap
);