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