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