00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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_responder_data ikev2;
00025 enum { WAIT_START, PROC_MSG, 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 char * eap_ikev2_state_txt(int state)
00037 {
00038 switch (state) {
00039 case WAIT_START:
00040 return "WAIT_START";
00041 case PROC_MSG:
00042 return "PROC_MSG";
00043 case WAIT_FRAG_ACK:
00044 return "WAIT_FRAG_ACK";
00045 case DONE:
00046 return "DONE";
00047 case FAIL:
00048 return "FAIL";
00049 default:
00050 return "?";
00051 }
00052 }
00053
00054
00055 static void eap_ikev2_state(struct eap_ikev2_data *data, int state)
00056 {
00057 wpa_printf(MSG_DEBUG, "EAP-IKEV2: %s -> %s",
00058 eap_ikev2_state_txt(data->state),
00059 eap_ikev2_state_txt(state));
00060 data->state = state;
00061 }
00062
00063
00064 static void * eap_ikev2_init(struct eap_sm *sm)
00065 {
00066 struct eap_ikev2_data *data;
00067 const u8 *identity, *password;
00068 size_t identity_len, password_len;
00069
00070 identity = eap_get_config_identity(sm, &identity_len);
00071 if (identity == NULL) {
00072 wpa_printf(MSG_INFO, "EAP-IKEV2: No identity available");
00073 return NULL;
00074 }
00075
00076 data = os_zalloc(sizeof(*data));
00077 if (data == NULL)
00078 return NULL;
00079 data->state = WAIT_START;
00080 data->fragment_size = IKEV2_FRAGMENT_SIZE;
00081 data->ikev2.state = SA_INIT;
00082 data->ikev2.peer_auth = PEER_AUTH_SECRET;
00083 data->ikev2.key_pad = (u8 *) os_strdup("Key Pad for EAP-IKEv2");
00084 if (data->ikev2.key_pad == NULL)
00085 goto failed;
00086 data->ikev2.key_pad_len = 21;
00087 data->ikev2.IDr = os_malloc(identity_len);
00088 if (data->ikev2.IDr == NULL)
00089 goto failed;
00090 os_memcpy(data->ikev2.IDr, identity, identity_len);
00091 data->ikev2.IDr_len = identity_len;
00092
00093 password = eap_get_config_password(sm, &password_len);
00094 if (password) {
00095 data->ikev2.shared_secret = os_malloc(password_len);
00096 if (data->ikev2.shared_secret == NULL)
00097 goto failed;
00098 os_memcpy(data->ikev2.shared_secret, password, password_len);
00099 data->ikev2.shared_secret_len = password_len;
00100 }
00101
00102 return data;
00103
00104 failed:
00105 ikev2_responder_deinit(&data->ikev2);
00106 os_free(data);
00107 return NULL;
00108 }
00109
00110
00111 static void eap_ikev2_deinit(struct eap_sm *sm, void *priv)
00112 {
00113 struct eap_ikev2_data *data = priv;
00114 wpabuf_free(data->in_buf);
00115 wpabuf_free(data->out_buf);
00116 ikev2_responder_deinit(&data->ikev2);
00117 os_free(data);
00118 }
00119
00120
00121 static int eap_ikev2_peer_keymat(struct eap_ikev2_data *data)
00122 {
00123 if (eap_ikev2_derive_keymat(
00124 data->ikev2.proposal.prf, &data->ikev2.keys,
00125 data->ikev2.i_nonce, data->ikev2.i_nonce_len,
00126 data->ikev2.r_nonce, data->ikev2.r_nonce_len,
00127 data->keymat) < 0) {
00128 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to "
00129 "derive key material");
00130 return -1;
00131 }
00132 data->keymat_ok = 1;
00133 return 0;
00134 }
00135
00136
00137 static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data,
00138 struct eap_method_ret *ret, u8 id)
00139 {
00140 struct wpabuf *resp;
00141 u8 flags;
00142 size_t send_len, plen, icv_len = 0;
00143
00144 ret->ignore = FALSE;
00145 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Response");
00146 ret->allowNotifications = TRUE;
00147
00148 flags = 0;
00149 send_len = wpabuf_len(data->out_buf) - data->out_used;
00150 if (1 + send_len > data->fragment_size) {
00151 send_len = data->fragment_size - 1;
00152 flags |= IKEV2_FLAGS_MORE_FRAGMENTS;
00153 if (data->out_used == 0) {
00154 flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
00155 send_len -= 4;
00156 }
00157 }
00158 #ifdef CCNS_PL
00159
00160
00161 if (!(flags & IKEV2_FLAGS_LENGTH_INCLUDED))
00162 flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
00163 #endif
00164
00165 plen = 1 + send_len;
00166 if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
00167 plen += 4;
00168 if (data->keys_ready) {
00169 const struct ikev2_integ_alg *integ;
00170 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum "
00171 "Data");
00172 flags |= IKEV2_FLAGS_ICV_INCLUDED;
00173 integ = ikev2_get_integ(data->ikev2.proposal.integ);
00174 if (integ == NULL) {
00175 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
00176 "transform / cannot generate ICV");
00177 return NULL;
00178 }
00179 icv_len = integ->hash_len;
00180
00181 plen += icv_len;
00182 }
00183 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen,
00184 EAP_CODE_RESPONSE, id);
00185 if (resp == NULL)
00186 return NULL;
00187
00188 wpabuf_put_u8(resp, flags);
00189 if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
00190 wpabuf_put_be32(resp, wpabuf_len(data->out_buf));
00191
00192 wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used,
00193 send_len);
00194 data->out_used += send_len;
00195
00196 if (flags & IKEV2_FLAGS_ICV_INCLUDED) {
00197 const u8 *msg = wpabuf_head(resp);
00198 size_t len = wpabuf_len(resp);
00199 ikev2_integ_hash(data->ikev2.proposal.integ,
00200 data->ikev2.keys.SK_ar,
00201 data->ikev2.keys.SK_integ_len,
00202 msg, len, wpabuf_put(resp, icv_len));
00203 }
00204
00205 ret->methodState = METHOD_MAY_CONT;
00206 ret->decision = DECISION_FAIL;
00207
00208 if (data->out_used == wpabuf_len(data->out_buf)) {
00209 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
00210 "(message sent completely)",
00211 (unsigned long) send_len);
00212 wpabuf_free(data->out_buf);
00213 data->out_buf = NULL;
00214 data->out_used = 0;
00215 switch (data->ikev2.state) {
00216 case SA_AUTH:
00217
00218
00219 data->keys_ready = 1;
00220 break;
00221 case IKEV2_DONE:
00222 ret->methodState = METHOD_DONE;
00223 if (data->state == FAIL)
00224 break;
00225 ret->decision = DECISION_COND_SUCC;
00226 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication "
00227 "completed successfully");
00228 if (eap_ikev2_peer_keymat(data))
00229 break;
00230 eap_ikev2_state(data, DONE);
00231 break;
00232 case IKEV2_FAILED:
00233 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication "
00234 "failed");
00235 ret->methodState = METHOD_DONE;
00236 ret->decision = DECISION_FAIL;
00237 break;
00238 default:
00239 break;
00240 }
00241 } else {
00242 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
00243 "(%lu more to send)", (unsigned long) send_len,
00244 (unsigned long) wpabuf_len(data->out_buf) -
00245 data->out_used);
00246 eap_ikev2_state(data, WAIT_FRAG_ACK);
00247 }
00248
00249 return resp;
00250 }
00251
00252
00253 static int eap_ikev2_process_icv(struct eap_ikev2_data *data,
00254 const struct wpabuf *reqData,
00255 u8 flags, const u8 *pos, const u8 **end)
00256 {
00257 if (flags & IKEV2_FLAGS_ICV_INCLUDED) {
00258 int icv_len = eap_ikev2_validate_icv(
00259 data->ikev2.proposal.integ, &data->ikev2.keys, 1,
00260 reqData, pos, *end);
00261 if (icv_len < 0)
00262 return -1;
00263
00264 *end -= icv_len;
00265 } else if (data->keys_ready) {
00266 wpa_printf(MSG_INFO, "EAP-IKEV2: The message should have "
00267 "included integrity checksum");
00268 return -1;
00269 }
00270
00271 return 0;
00272 }
00273
00274
00275 static int eap_ikev2_process_cont(struct eap_ikev2_data *data,
00276 const u8 *buf, size_t len)
00277 {
00278
00279 if (len > wpabuf_tailroom(data->in_buf)) {
00280 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment overflow");
00281 eap_ikev2_state(data, FAIL);
00282 return -1;
00283 }
00284
00285 wpabuf_put_data(data->in_buf, buf, len);
00286 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes, waiting "
00287 "for %lu bytes more", (unsigned long) len,
00288 (unsigned long) wpabuf_tailroom(data->in_buf));
00289
00290 return 0;
00291 }
00292
00293
00294 static struct wpabuf * eap_ikev2_process_fragment(struct eap_ikev2_data *data,
00295 struct eap_method_ret *ret,
00296 u8 id, u8 flags,
00297 u32 message_length,
00298 const u8 *buf, size_t len)
00299 {
00300
00301 if (data->in_buf == NULL && !(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) {
00302 wpa_printf(MSG_DEBUG, "EAP-IKEV2: No Message Length field in "
00303 "a fragmented packet");
00304 ret->ignore = TRUE;
00305 return NULL;
00306 }
00307
00308 if (data->in_buf == NULL) {
00309
00310 data->in_buf = wpabuf_alloc(message_length);
00311 if (data->in_buf == NULL) {
00312 wpa_printf(MSG_DEBUG, "EAP-IKEV2: No memory for "
00313 "message");
00314 ret->ignore = TRUE;
00315 return NULL;
00316 }
00317 wpabuf_put_data(data->in_buf, buf, len);
00318 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes in first "
00319 "fragment, waiting for %lu bytes more",
00320 (unsigned long) len,
00321 (unsigned long) wpabuf_tailroom(data->in_buf));
00322 }
00323
00324 return eap_ikev2_build_frag_ack(id, EAP_CODE_RESPONSE);
00325 }
00326
00327
00328 static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv,
00329 struct eap_method_ret *ret,
00330 const struct wpabuf *reqData)
00331 {
00332 struct eap_ikev2_data *data = priv;
00333 const u8 *start, *pos, *end;
00334 size_t len;
00335 u8 flags, id;
00336 u32 message_length = 0;
00337 struct wpabuf tmpbuf;
00338
00339 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, reqData, &len);
00340 if (pos == NULL) {
00341 ret->ignore = TRUE;
00342 return NULL;
00343 }
00344
00345 id = eap_get_id(reqData);
00346
00347 start = pos;
00348 end = start + len;
00349
00350 if (len == 0)
00351 flags = 0;
00352 else
00353 flags = *pos++;
00354
00355 if (eap_ikev2_process_icv(data, reqData, flags, pos, &end) < 0) {
00356 ret->ignore = TRUE;
00357 return NULL;
00358 }
00359
00360 if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) {
00361 if (end - pos < 4) {
00362 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow");
00363 ret->ignore = TRUE;
00364 return NULL;
00365 }
00366 message_length = WPA_GET_BE32(pos);
00367 pos += 4;
00368
00369 if (message_length < (u32) (end - pos)) {
00370 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message "
00371 "Length (%d; %ld remaining in this msg)",
00372 message_length, (long) (end - pos));
00373 ret->ignore = TRUE;
00374 return NULL;
00375 }
00376 }
00377
00378 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received packet: Flags 0x%x "
00379 "Message Length %u", flags, message_length);
00380
00381 if (data->state == WAIT_FRAG_ACK) {
00382 #ifdef CCNS_PL
00383 if (len > 1)
00384 #else
00385 if (len != 0)
00386 #endif
00387 {
00388 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload "
00389 "in WAIT_FRAG_ACK state");
00390 ret->ignore = TRUE;
00391 return NULL;
00392 }
00393 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged");
00394 eap_ikev2_state(data, PROC_MSG);
00395 return eap_ikev2_build_msg(data, ret, id);
00396 }
00397
00398 if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) {
00399 ret->ignore = TRUE;
00400 return NULL;
00401 }
00402
00403 if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) {
00404 return eap_ikev2_process_fragment(data, ret, id, flags,
00405 message_length, pos,
00406 end - pos);
00407 }
00408
00409 if (data->in_buf == NULL) {
00410
00411 wpabuf_set(&tmpbuf, pos, end - pos);
00412 data->in_buf = &tmpbuf;
00413 }
00414
00415 if (ikev2_responder_process(&data->ikev2, data->in_buf) < 0) {
00416 if (data->in_buf == &tmpbuf)
00417 data->in_buf = NULL;
00418 eap_ikev2_state(data, FAIL);
00419 return NULL;
00420 }
00421
00422 if (data->in_buf != &tmpbuf)
00423 wpabuf_free(data->in_buf);
00424 data->in_buf = NULL;
00425
00426 if (data->out_buf == NULL) {
00427 data->out_buf = ikev2_responder_build(&data->ikev2);
00428 if (data->out_buf == NULL) {
00429 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to generate "
00430 "IKEv2 message");
00431 return NULL;
00432 }
00433 data->out_used = 0;
00434 }
00435
00436 eap_ikev2_state(data, PROC_MSG);
00437 return eap_ikev2_build_msg(data, ret, id);
00438 }
00439
00440
00441 static Boolean eap_ikev2_isKeyAvailable(struct eap_sm *sm, void *priv)
00442 {
00443 struct eap_ikev2_data *data = priv;
00444 return data->state == DONE && data->keymat_ok;
00445 }
00446
00447
00448 static u8 * eap_ikev2_getKey(struct eap_sm *sm, void *priv, size_t *len)
00449 {
00450 struct eap_ikev2_data *data = priv;
00451 u8 *key;
00452
00453 if (data->state != DONE || !data->keymat_ok)
00454 return NULL;
00455
00456 key = os_malloc(EAP_MSK_LEN);
00457 if (key) {
00458 os_memcpy(key, data->keymat, EAP_MSK_LEN);
00459 *len = EAP_MSK_LEN;
00460 }
00461
00462 return key;
00463 }
00464
00465
00466 static u8 * eap_ikev2_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
00467 {
00468 struct eap_ikev2_data *data = priv;
00469 u8 *key;
00470
00471 if (data->state != DONE || !data->keymat_ok)
00472 return NULL;
00473
00474 key = os_malloc(EAP_EMSK_LEN);
00475 if (key) {
00476 os_memcpy(key, data->keymat + EAP_MSK_LEN, EAP_EMSK_LEN);
00477 *len = EAP_EMSK_LEN;
00478 }
00479
00480 return key;
00481 }
00482
00483
00484 int eap_peer_ikev2_register(void)
00485 {
00486 struct eap_method *eap;
00487 int ret;
00488
00489 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
00490 EAP_VENDOR_IETF, EAP_TYPE_IKEV2,
00491 "IKEV2");
00492 if (eap == NULL)
00493 return -1;
00494
00495 eap->init = eap_ikev2_init;
00496 eap->deinit = eap_ikev2_deinit;
00497 eap->process = eap_ikev2_process;
00498 eap->isKeyAvailable = eap_ikev2_isKeyAvailable;
00499 eap->getKey = eap_ikev2_getKey;
00500 eap->get_emsk = eap_ikev2_get_emsk;
00501
00502 ret = eap_peer_method_register(eap);
00503 if (ret)
00504 eap_peer_method_free(eap);
00505 return ret;
00506 }