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