$search
00001 /* 00002 * EAP-IKEv2 server (RFC 5106) 00003 * Copyright (c) 2007, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "eap_i.h" 00019 #include "eap_common/eap_ikev2_common.h" 00020 #include "ikev2.h" 00021 00022 00023 struct eap_ikev2_data { 00024 struct ikev2_initiator_data ikev2; 00025 enum { MSG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; 00026 struct wpabuf *in_buf; 00027 struct wpabuf *out_buf; 00028 size_t out_used; 00029 size_t fragment_size; 00030 int keys_ready; 00031 u8 keymat[EAP_MSK_LEN + EAP_EMSK_LEN]; 00032 int keymat_ok; 00033 }; 00034 00035 00036 static const u8 * eap_ikev2_get_shared_secret(void *ctx, const u8 *IDr, 00037 size_t IDr_len, 00038 size_t *secret_len) 00039 { 00040 struct eap_sm *sm = ctx; 00041 00042 if (IDr == NULL) { 00043 wpa_printf(MSG_DEBUG, "EAP-IKEV2: No IDr received - default " 00044 "to user identity from EAP-Identity"); 00045 IDr = sm->identity; 00046 IDr_len = sm->identity_len; 00047 } 00048 00049 if (eap_user_get(sm, IDr, IDr_len, 0) < 0 || sm->user == NULL || 00050 sm->user->password == NULL) { 00051 wpa_printf(MSG_DEBUG, "EAP-IKEV2: No user entry found"); 00052 return NULL; 00053 } 00054 00055 *secret_len = sm->user->password_len; 00056 return sm->user->password; 00057 } 00058 00059 00060 static const char * eap_ikev2_state_txt(int state) 00061 { 00062 switch (state) { 00063 case MSG: 00064 return "MSG"; 00065 case FRAG_ACK: 00066 return "FRAG_ACK"; 00067 case WAIT_FRAG_ACK: 00068 return "WAIT_FRAG_ACK"; 00069 case DONE: 00070 return "DONE"; 00071 case FAIL: 00072 return "FAIL"; 00073 default: 00074 return "?"; 00075 } 00076 } 00077 00078 00079 static void eap_ikev2_state(struct eap_ikev2_data *data, int state) 00080 { 00081 wpa_printf(MSG_DEBUG, "EAP-IKEV2: %s -> %s", 00082 eap_ikev2_state_txt(data->state), 00083 eap_ikev2_state_txt(state)); 00084 data->state = state; 00085 } 00086 00087 00088 static void * eap_ikev2_init(struct eap_sm *sm) 00089 { 00090 struct eap_ikev2_data *data; 00091 00092 data = os_zalloc(sizeof(*data)); 00093 if (data == NULL) 00094 return NULL; 00095 data->state = MSG; 00096 data->fragment_size = IKEV2_FRAGMENT_SIZE; 00097 data->ikev2.state = SA_INIT; 00098 data->ikev2.peer_auth = PEER_AUTH_SECRET; 00099 data->ikev2.key_pad = (u8 *) os_strdup("Key Pad for EAP-IKEv2"); 00100 if (data->ikev2.key_pad == NULL) 00101 goto failed; 00102 data->ikev2.key_pad_len = 21; 00103 00104 /* TODO: make proposals configurable */ 00105 data->ikev2.proposal.proposal_num = 1; 00106 data->ikev2.proposal.integ = AUTH_HMAC_SHA1_96; 00107 data->ikev2.proposal.prf = PRF_HMAC_SHA1; 00108 data->ikev2.proposal.encr = ENCR_AES_CBC; 00109 data->ikev2.proposal.dh = DH_GROUP2_1024BIT_MODP; 00110 00111 data->ikev2.IDi = (u8 *) os_strdup("hostapd"); 00112 data->ikev2.IDi_len = 7; 00113 00114 data->ikev2.get_shared_secret = eap_ikev2_get_shared_secret; 00115 data->ikev2.cb_ctx = sm; 00116 00117 return data; 00118 00119 failed: 00120 ikev2_initiator_deinit(&data->ikev2); 00121 os_free(data); 00122 return NULL; 00123 } 00124 00125 00126 static void eap_ikev2_reset(struct eap_sm *sm, void *priv) 00127 { 00128 struct eap_ikev2_data *data = priv; 00129 wpabuf_free(data->in_buf); 00130 wpabuf_free(data->out_buf); 00131 ikev2_initiator_deinit(&data->ikev2); 00132 os_free(data); 00133 } 00134 00135 00136 static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, u8 id) 00137 { 00138 struct wpabuf *req; 00139 u8 flags; 00140 size_t send_len, plen, icv_len = 0; 00141 00142 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Request"); 00143 00144 flags = 0; 00145 send_len = wpabuf_len(data->out_buf) - data->out_used; 00146 if (1 + send_len > data->fragment_size) { 00147 send_len = data->fragment_size - 1; 00148 flags |= IKEV2_FLAGS_MORE_FRAGMENTS; 00149 if (data->out_used == 0) { 00150 flags |= IKEV2_FLAGS_LENGTH_INCLUDED; 00151 send_len -= 4; 00152 } 00153 } 00154 00155 plen = 1 + send_len; 00156 if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) 00157 plen += 4; 00158 if (data->keys_ready) { 00159 const struct ikev2_integ_alg *integ; 00160 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum " 00161 "Data"); 00162 flags |= IKEV2_FLAGS_ICV_INCLUDED; 00163 integ = ikev2_get_integ(data->ikev2.proposal.integ); 00164 if (integ == NULL) { 00165 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG " 00166 "transform / cannot generate ICV"); 00167 return NULL; 00168 } 00169 icv_len = integ->hash_len; 00170 00171 plen += icv_len; 00172 } 00173 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen, 00174 EAP_CODE_REQUEST, id); 00175 if (req == NULL) 00176 return NULL; 00177 00178 wpabuf_put_u8(req, flags); /* Flags */ 00179 if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) 00180 wpabuf_put_be32(req, wpabuf_len(data->out_buf)); 00181 00182 wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, 00183 send_len); 00184 data->out_used += send_len; 00185 00186 if (flags & IKEV2_FLAGS_ICV_INCLUDED) { 00187 const u8 *msg = wpabuf_head(req); 00188 size_t len = wpabuf_len(req); 00189 ikev2_integ_hash(data->ikev2.proposal.integ, 00190 data->ikev2.keys.SK_ai, 00191 data->ikev2.keys.SK_integ_len, 00192 msg, len, wpabuf_put(req, icv_len)); 00193 } 00194 00195 if (data->out_used == wpabuf_len(data->out_buf)) { 00196 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " 00197 "(message sent completely)", 00198 (unsigned long) send_len); 00199 wpabuf_free(data->out_buf); 00200 data->out_buf = NULL; 00201 data->out_used = 0; 00202 } else { 00203 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " 00204 "(%lu more to send)", (unsigned long) send_len, 00205 (unsigned long) wpabuf_len(data->out_buf) - 00206 data->out_used); 00207 eap_ikev2_state(data, WAIT_FRAG_ACK); 00208 } 00209 00210 return req; 00211 } 00212 00213 00214 static struct wpabuf * eap_ikev2_buildReq(struct eap_sm *sm, void *priv, u8 id) 00215 { 00216 struct eap_ikev2_data *data = priv; 00217 00218 switch (data->state) { 00219 case MSG: 00220 if (data->out_buf == NULL) { 00221 data->out_buf = ikev2_initiator_build(&data->ikev2); 00222 if (data->out_buf == NULL) { 00223 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to " 00224 "generate IKEv2 message"); 00225 return NULL; 00226 } 00227 data->out_used = 0; 00228 } 00229 /* pass through */ 00230 case WAIT_FRAG_ACK: 00231 return eap_ikev2_build_msg(data, id); 00232 case FRAG_ACK: 00233 return eap_ikev2_build_frag_ack(id, EAP_CODE_REQUEST); 00234 default: 00235 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected state %d in " 00236 "buildReq", data->state); 00237 return NULL; 00238 } 00239 } 00240 00241 00242 static Boolean eap_ikev2_check(struct eap_sm *sm, void *priv, 00243 struct wpabuf *respData) 00244 { 00245 const u8 *pos; 00246 size_t len; 00247 00248 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, respData, 00249 &len); 00250 if (pos == NULL) { 00251 wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid frame"); 00252 return TRUE; 00253 } 00254 00255 return FALSE; 00256 } 00257 00258 00259 static int eap_ikev2_process_icv(struct eap_ikev2_data *data, 00260 const struct wpabuf *respData, 00261 u8 flags, const u8 *pos, const u8 **end) 00262 { 00263 if (flags & IKEV2_FLAGS_ICV_INCLUDED) { 00264 int icv_len = eap_ikev2_validate_icv( 00265 data->ikev2.proposal.integ, &data->ikev2.keys, 0, 00266 respData, pos, *end); 00267 if (icv_len < 0) 00268 return -1; 00269 /* Hide Integrity Checksum Data from further processing */ 00270 *end -= icv_len; 00271 } else if (data->keys_ready) { 00272 wpa_printf(MSG_INFO, "EAP-IKEV2: The message should have " 00273 "included integrity checksum"); 00274 return -1; 00275 } 00276 00277 return 0; 00278 } 00279 00280 00281 static int eap_ikev2_process_cont(struct eap_ikev2_data *data, 00282 const u8 *buf, size_t len) 00283 { 00284 /* Process continuation of a pending message */ 00285 if (len > wpabuf_tailroom(data->in_buf)) { 00286 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment overflow"); 00287 eap_ikev2_state(data, FAIL); 00288 return -1; 00289 } 00290 00291 wpabuf_put_data(data->in_buf, buf, len); 00292 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes, waiting for %lu " 00293 "bytes more", (unsigned long) len, 00294 (unsigned long) wpabuf_tailroom(data->in_buf)); 00295 00296 return 0; 00297 } 00298 00299 00300 static int eap_ikev2_process_fragment(struct eap_ikev2_data *data, 00301 u8 flags, u32 message_length, 00302 const u8 *buf, size_t len) 00303 { 00304 /* Process a fragment that is not the last one of the message */ 00305 if (data->in_buf == NULL && !(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) { 00306 wpa_printf(MSG_DEBUG, "EAP-IKEV2: No Message Length field in " 00307 "a fragmented packet"); 00308 return -1; 00309 } 00310 00311 if (data->in_buf == NULL) { 00312 /* First fragment of the message */ 00313 data->in_buf = wpabuf_alloc(message_length); 00314 if (data->in_buf == NULL) { 00315 wpa_printf(MSG_DEBUG, "EAP-IKEV2: No memory for " 00316 "message"); 00317 return -1; 00318 } 00319 wpabuf_put_data(data->in_buf, buf, len); 00320 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes in first " 00321 "fragment, waiting for %lu bytes more", 00322 (unsigned long) len, 00323 (unsigned long) wpabuf_tailroom(data->in_buf)); 00324 } 00325 00326 return 0; 00327 } 00328 00329 00330 static int eap_ikev2_server_keymat(struct eap_ikev2_data *data) 00331 { 00332 if (eap_ikev2_derive_keymat( 00333 data->ikev2.proposal.prf, &data->ikev2.keys, 00334 data->ikev2.i_nonce, data->ikev2.i_nonce_len, 00335 data->ikev2.r_nonce, data->ikev2.r_nonce_len, 00336 data->keymat) < 0) { 00337 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to derive " 00338 "key material"); 00339 return -1; 00340 } 00341 data->keymat_ok = 1; 00342 return 0; 00343 } 00344 00345 00346 static void eap_ikev2_process(struct eap_sm *sm, void *priv, 00347 struct wpabuf *respData) 00348 { 00349 struct eap_ikev2_data *data = priv; 00350 const u8 *start, *pos, *end; 00351 size_t len; 00352 u8 flags; 00353 u32 message_length = 0; 00354 struct wpabuf tmpbuf; 00355 00356 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, respData, 00357 &len); 00358 if (pos == NULL) 00359 return; /* Should not happen; message already verified */ 00360 00361 start = pos; 00362 end = start + len; 00363 00364 if (len == 0) { 00365 /* fragment ack */ 00366 flags = 0; 00367 } else 00368 flags = *pos++; 00369 00370 if (eap_ikev2_process_icv(data, respData, flags, pos, &end) < 0) { 00371 eap_ikev2_state(data, FAIL); 00372 return; 00373 } 00374 00375 if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) { 00376 if (end - pos < 4) { 00377 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow"); 00378 eap_ikev2_state(data, FAIL); 00379 return; 00380 } 00381 message_length = WPA_GET_BE32(pos); 00382 pos += 4; 00383 00384 if (message_length < (u32) (end - pos)) { 00385 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message " 00386 "Length (%d; %ld remaining in this msg)", 00387 message_length, (long) (end - pos)); 00388 eap_ikev2_state(data, FAIL); 00389 return; 00390 } 00391 } 00392 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received packet: Flags 0x%x " 00393 "Message Length %u", flags, message_length); 00394 00395 if (data->state == WAIT_FRAG_ACK) { 00396 if (len != 0) { 00397 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload " 00398 "in WAIT_FRAG_ACK state"); 00399 eap_ikev2_state(data, FAIL); 00400 return; 00401 } 00402 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged"); 00403 eap_ikev2_state(data, MSG); 00404 return; 00405 } 00406 00407 if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) { 00408 eap_ikev2_state(data, FAIL); 00409 return; 00410 } 00411 00412 if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) { 00413 if (eap_ikev2_process_fragment(data, flags, message_length, 00414 pos, end - pos) < 0) 00415 eap_ikev2_state(data, FAIL); 00416 else 00417 eap_ikev2_state(data, FRAG_ACK); 00418 return; 00419 } else if (data->state == FRAG_ACK) { 00420 wpa_printf(MSG_DEBUG, "EAP-TNC: All fragments received"); 00421 data->state = MSG; 00422 } 00423 00424 if (data->in_buf == NULL) { 00425 /* Wrap unfragmented messages as wpabuf without extra copy */ 00426 wpabuf_set(&tmpbuf, pos, end - pos); 00427 data->in_buf = &tmpbuf; 00428 } 00429 00430 if (ikev2_initiator_process(&data->ikev2, data->in_buf) < 0) { 00431 if (data->in_buf == &tmpbuf) 00432 data->in_buf = NULL; 00433 eap_ikev2_state(data, FAIL); 00434 return; 00435 } 00436 00437 switch (data->ikev2.state) { 00438 case SA_AUTH: 00439 /* SA_INIT was sent out, so message have to be 00440 * integrity protected from now on. */ 00441 data->keys_ready = 1; 00442 break; 00443 case IKEV2_DONE: 00444 if (data->state == FAIL) 00445 break; 00446 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication completed " 00447 "successfully"); 00448 if (eap_ikev2_server_keymat(data)) 00449 break; 00450 eap_ikev2_state(data, DONE); 00451 break; 00452 default: 00453 break; 00454 } 00455 00456 if (data->in_buf != &tmpbuf) 00457 wpabuf_free(data->in_buf); 00458 data->in_buf = NULL; 00459 } 00460 00461 00462 static Boolean eap_ikev2_isDone(struct eap_sm *sm, void *priv) 00463 { 00464 struct eap_ikev2_data *data = priv; 00465 return data->state == DONE || data->state == FAIL; 00466 } 00467 00468 00469 static Boolean eap_ikev2_isSuccess(struct eap_sm *sm, void *priv) 00470 { 00471 struct eap_ikev2_data *data = priv; 00472 return data->state == DONE && data->ikev2.state == IKEV2_DONE && 00473 data->keymat_ok; 00474 } 00475 00476 00477 static u8 * eap_ikev2_getKey(struct eap_sm *sm, void *priv, size_t *len) 00478 { 00479 struct eap_ikev2_data *data = priv; 00480 u8 *key; 00481 00482 if (data->state != DONE || !data->keymat_ok) 00483 return NULL; 00484 00485 key = os_malloc(EAP_MSK_LEN); 00486 if (key) { 00487 os_memcpy(key, data->keymat, EAP_MSK_LEN); 00488 *len = EAP_MSK_LEN; 00489 } 00490 00491 return key; 00492 } 00493 00494 00495 static u8 * eap_ikev2_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 00496 { 00497 struct eap_ikev2_data *data = priv; 00498 u8 *key; 00499 00500 if (data->state != DONE || !data->keymat_ok) 00501 return NULL; 00502 00503 key = os_malloc(EAP_EMSK_LEN); 00504 if (key) { 00505 os_memcpy(key, data->keymat + EAP_MSK_LEN, EAP_EMSK_LEN); 00506 *len = EAP_EMSK_LEN; 00507 } 00508 00509 return key; 00510 } 00511 00512 00513 int eap_server_ikev2_register(void) 00514 { 00515 struct eap_method *eap; 00516 int ret; 00517 00518 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 00519 EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 00520 "IKEV2"); 00521 if (eap == NULL) 00522 return -1; 00523 00524 eap->init = eap_ikev2_init; 00525 eap->reset = eap_ikev2_reset; 00526 eap->buildReq = eap_ikev2_buildReq; 00527 eap->check = eap_ikev2_check; 00528 eap->process = eap_ikev2_process; 00529 eap->isDone = eap_ikev2_isDone; 00530 eap->getKey = eap_ikev2_getKey; 00531 eap->isSuccess = eap_ikev2_isSuccess; 00532 eap->get_emsk = eap_ikev2_get_emsk; 00533 00534 ret = eap_server_method_register(eap); 00535 if (ret) 00536 eap_server_method_free(eap); 00537 return ret; 00538 }