1/* 2 * hostapd / EAP-EKE (RFC 6124) server 3 * Copyright (c) 2013, 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 "crypto/random.h" 13#include "eap_server/eap_i.h" 14#include "eap_common/eap_eke_common.h" 15 16 17struct eap_eke_data { 18 enum { 19 IDENTITY, COMMIT, CONFIRM, FAILURE_REPORT, SUCCESS, FAILURE 20 } state; 21 u8 msk[EAP_MSK_LEN]; 22 u8 emsk[EAP_EMSK_LEN]; 23 u8 *peerid; 24 size_t peerid_len; 25 u8 peerid_type; 26 u8 serverid_type; 27 u8 dh_priv[EAP_EKE_MAX_DH_LEN]; 28 u8 key[EAP_EKE_MAX_KEY_LEN]; 29 struct eap_eke_session sess; 30 u8 nonce_p[EAP_EKE_MAX_NONCE_LEN]; 31 u8 nonce_s[EAP_EKE_MAX_NONCE_LEN]; 32 struct wpabuf *msgs; 33 int phase2; 34 u32 failure_code; 35}; 36 37 38static const char * eap_eke_state_txt(int state) 39{ 40 switch (state) { 41 case IDENTITY: 42 return "IDENTITY"; 43 case COMMIT: 44 return "COMMIT"; 45 case CONFIRM: 46 return "CONFIRM"; 47 case FAILURE_REPORT: 48 return "FAILURE_REPORT"; 49 case SUCCESS: 50 return "SUCCESS"; 51 case FAILURE: 52 return "FAILURE"; 53 default: 54 return "?"; 55 } 56} 57 58 59static void eap_eke_state(struct eap_eke_data *data, int state) 60{ 61 wpa_printf(MSG_DEBUG, "EAP-EKE: %s -> %s", 62 eap_eke_state_txt(data->state), 63 eap_eke_state_txt(state)); 64 data->state = state; 65} 66 67 68static void eap_eke_fail(struct eap_eke_data *data, u32 code) 69{ 70 wpa_printf(MSG_DEBUG, "EAP-EKE: Failure - code 0x%x", code); 71 data->failure_code = code; 72 eap_eke_state(data, FAILURE_REPORT); 73} 74 75 76static void * eap_eke_init(struct eap_sm *sm) 77{ 78 struct eap_eke_data *data; 79 size_t i; 80 81 data = os_zalloc(sizeof(*data)); 82 if (data == NULL) 83 return NULL; 84 eap_eke_state(data, IDENTITY); 85 86 data->serverid_type = EAP_EKE_ID_OPAQUE; 87 for (i = 0; i < sm->server_id_len; i++) { 88 if (sm->server_id[i] == '.' && 89 data->serverid_type == EAP_EKE_ID_OPAQUE) 90 data->serverid_type = EAP_EKE_ID_FQDN; 91 if (sm->server_id[i] == '@') 92 data->serverid_type = EAP_EKE_ID_NAI; 93 } 94 95 data->phase2 = sm->init_phase2; 96 97 return data; 98} 99 100 101static void eap_eke_reset(struct eap_sm *sm, void *priv) 102{ 103 struct eap_eke_data *data = priv; 104 eap_eke_session_clean(&data->sess); 105 os_free(data->peerid); 106 wpabuf_free(data->msgs); 107 os_free(data); 108} 109 110 111static struct wpabuf * eap_eke_build_msg(struct eap_eke_data *data, 112 u8 id, size_t length, u8 eke_exch) 113{ 114 struct wpabuf *msg; 115 size_t plen; 116 117 plen = 1 + length; 118 119 msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EKE, plen, 120 EAP_CODE_REQUEST, id); 121 if (msg == NULL) { 122 wpa_printf(MSG_ERROR, "EAP-EKE: Failed to allocate memory"); 123 return NULL; 124 } 125 126 wpabuf_put_u8(msg, eke_exch); 127 128 return msg; 129} 130 131 132static int supported_proposal(const u8 *pos) 133{ 134 if (pos[0] == EAP_EKE_DHGROUP_EKE_16 && 135 pos[1] == EAP_EKE_ENCR_AES128_CBC && 136 pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 && 137 pos[3] == EAP_EKE_MAC_HMAC_SHA2_256) 138 return 1; 139 140 if (pos[0] == EAP_EKE_DHGROUP_EKE_15 && 141 pos[1] == EAP_EKE_ENCR_AES128_CBC && 142 pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 && 143 pos[3] == EAP_EKE_MAC_HMAC_SHA2_256) 144 return 1; 145 146 if (pos[0] == EAP_EKE_DHGROUP_EKE_14 && 147 pos[1] == EAP_EKE_ENCR_AES128_CBC && 148 pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 && 149 pos[3] == EAP_EKE_MAC_HMAC_SHA2_256) 150 return 1; 151 152 if (pos[0] == EAP_EKE_DHGROUP_EKE_14 && 153 pos[1] == EAP_EKE_ENCR_AES128_CBC && 154 pos[2] == EAP_EKE_PRF_HMAC_SHA1 && 155 pos[3] == EAP_EKE_MAC_HMAC_SHA1) 156 return 1; 157 158 return 0; 159} 160 161 162static struct wpabuf * eap_eke_build_failure(struct eap_eke_data *data, u8 id) 163{ 164 struct wpabuf *msg; 165 166 wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Failure: Failure-Code=0x%x", 167 data->failure_code); 168 169 msg = eap_eke_build_msg(data, id, 4, EAP_EKE_FAILURE); 170 if (msg == NULL) { 171 eap_eke_state(data, FAILURE); 172 return NULL; 173 } 174 wpabuf_put_be32(msg, data->failure_code); 175 176 return msg; 177} 178 179 180static struct wpabuf * eap_eke_build_identity(struct eap_sm *sm, 181 struct eap_eke_data *data, 182 u8 id) 183{ 184 struct wpabuf *msg; 185 size_t plen; 186 187 wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Identity"); 188 189 plen = 2 + 4 * 4 + 1 + sm->server_id_len; 190 msg = eap_eke_build_msg(data, id, plen, EAP_EKE_ID); 191 if (msg == NULL) 192 return NULL; 193 194 wpabuf_put_u8(msg, 4); /* NumProposals */ 195 wpabuf_put_u8(msg, 0); /* Reserved */ 196 197 /* Proposal - DH Group 16 with AES128-CBC and SHA256 */ 198 wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_16); /* Group Description */ 199 wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ 200 wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */ 201 wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */ 202 203 /* Proposal - DH Group 15 with AES128-CBC and SHA256 */ 204 wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_15); /* Group Description */ 205 wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ 206 wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */ 207 wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */ 208 209 /* Proposal - DH Group 14 with AES128-CBC and SHA256 */ 210 wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */ 211 wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ 212 wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */ 213 wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */ 214 215 /* 216 * Proposal - DH Group 14 with AES128-CBC and SHA1 217 * (mandatory to implement algorithms) 218 */ 219 wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */ 220 wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ 221 wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA1); /* PRF */ 222 wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA1); /* MAC */ 223 224 /* Server IDType + Identity */ 225 wpabuf_put_u8(msg, data->serverid_type); 226 wpabuf_put_data(msg, sm->server_id, sm->server_id_len); 227 228 wpabuf_free(data->msgs); 229 data->msgs = wpabuf_dup(msg); 230 if (data->msgs == NULL) { 231 wpabuf_free(msg); 232 return NULL; 233 } 234 235 return msg; 236} 237 238 239static struct wpabuf * eap_eke_build_commit(struct eap_sm *sm, 240 struct eap_eke_data *data, u8 id) 241{ 242 struct wpabuf *msg; 243 u8 pub[EAP_EKE_MAX_DH_LEN]; 244 245 wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Commit"); 246 247 if (sm->user == NULL || sm->user->password == NULL) { 248 wpa_printf(MSG_INFO, "EAP-EKE: Password with not configured"); 249 eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); 250 return eap_eke_build_failure(data, id); 251 } 252 253 if (eap_eke_derive_key(&data->sess, sm->user->password, 254 sm->user->password_len, 255 sm->server_id, sm->server_id_len, 256 data->peerid, data->peerid_len, data->key) < 0) { 257 wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive key"); 258 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 259 return eap_eke_build_failure(data, id); 260 } 261 262 msg = eap_eke_build_msg(data, id, data->sess.dhcomp_len, 263 EAP_EKE_COMMIT); 264 if (msg == NULL) { 265 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 266 return eap_eke_build_failure(data, id); 267 } 268 269 /* 270 * y_s = g ^ x_s (mod p) 271 * x_s = random number 2 .. p-1 272 * temp = prf(0+, password) 273 * key = prf+(temp, ID_S | ID_P) 274 * DHComponent_S = Encr(key, y_s) 275 */ 276 277 if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) { 278 wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH"); 279 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 280 return eap_eke_build_failure(data, id); 281 } 282 283 if (eap_eke_dhcomp(&data->sess, data->key, pub, 284 wpabuf_put(msg, data->sess.dhcomp_len)) 285 < 0) { 286 wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_S"); 287 wpabuf_free(msg); 288 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 289 return eap_eke_build_failure(data, id); 290 } 291 292 if (wpabuf_resize(&data->msgs, wpabuf_len(msg)) < 0) { 293 wpabuf_free(msg); 294 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 295 return eap_eke_build_failure(data, id); 296 } 297 wpabuf_put_buf(data->msgs, msg); 298 299 return msg; 300} 301 302 303static struct wpabuf * eap_eke_build_confirm(struct eap_sm *sm, 304 struct eap_eke_data *data, u8 id) 305{ 306 struct wpabuf *msg; 307 size_t plen, prot_len; 308 u8 nonces[2 * EAP_EKE_MAX_NONCE_LEN]; 309 u8 *auth; 310 311 wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Confirm"); 312 313 plen = data->sess.pnonce_ps_len + data->sess.prf_len; 314 msg = eap_eke_build_msg(data, id, plen, EAP_EKE_CONFIRM); 315 if (msg == NULL) { 316 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 317 return eap_eke_build_failure(data, id); 318 } 319 320 if (random_get_bytes(data->nonce_s, data->sess.nonce_len)) { 321 wpabuf_free(msg); 322 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 323 return eap_eke_build_failure(data, id); 324 } 325 wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S", 326 data->nonce_s, data->sess.nonce_len); 327 328 os_memcpy(nonces, data->nonce_p, data->sess.nonce_len); 329 os_memcpy(nonces + data->sess.nonce_len, data->nonce_s, 330 data->sess.nonce_len); 331 prot_len = wpabuf_tailroom(msg); 332 if (eap_eke_prot(&data->sess, nonces, 2 * data->sess.nonce_len, 333 wpabuf_put(msg, 0), &prot_len) < 0) { 334 wpabuf_free(msg); 335 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 336 return eap_eke_build_failure(data, id); 337 } 338 wpabuf_put(msg, prot_len); 339 340 if (eap_eke_derive_ka(&data->sess, 341 sm->server_id, sm->server_id_len, 342 data->peerid, data->peerid_len, 343 data->nonce_p, data->nonce_s) < 0) { 344 wpabuf_free(msg); 345 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 346 return eap_eke_build_failure(data, id); 347 } 348 349 auth = wpabuf_put(msg, data->sess.prf_len); 350 if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth) < 0) { 351 wpabuf_free(msg); 352 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 353 return eap_eke_build_failure(data, id); 354 } 355 wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth, data->sess.prf_len); 356 357 return msg; 358} 359 360 361static struct wpabuf * eap_eke_buildReq(struct eap_sm *sm, void *priv, u8 id) 362{ 363 struct eap_eke_data *data = priv; 364 365 switch (data->state) { 366 case IDENTITY: 367 return eap_eke_build_identity(sm, data, id); 368 case COMMIT: 369 return eap_eke_build_commit(sm, data, id); 370 case CONFIRM: 371 return eap_eke_build_confirm(sm, data, id); 372 case FAILURE_REPORT: 373 return eap_eke_build_failure(data, id); 374 default: 375 wpa_printf(MSG_DEBUG, "EAP-EKE: Unknown state %d in buildReq", 376 data->state); 377 break; 378 } 379 return NULL; 380} 381 382 383static Boolean eap_eke_check(struct eap_sm *sm, void *priv, 384 struct wpabuf *respData) 385{ 386 struct eap_eke_data *data = priv; 387 size_t len; 388 const u8 *pos; 389 u8 eke_exch; 390 391 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len); 392 if (pos == NULL || len < 1) { 393 wpa_printf(MSG_INFO, "EAP-EKE: Invalid frame"); 394 return TRUE; 395 } 396 397 eke_exch = *pos; 398 wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: EKE-Exch=%d", eke_exch); 399 400 if (data->state == IDENTITY && eke_exch == EAP_EKE_ID) 401 return FALSE; 402 403 if (data->state == COMMIT && eke_exch == EAP_EKE_COMMIT) 404 return FALSE; 405 406 if (data->state == CONFIRM && eke_exch == EAP_EKE_CONFIRM) 407 return FALSE; 408 409 if (eke_exch == EAP_EKE_FAILURE) 410 return FALSE; 411 412 wpa_printf(MSG_INFO, "EAP-EKE: Unexpected EKE-Exch=%d in state=%d", 413 eke_exch, data->state); 414 415 return TRUE; 416} 417 418 419static void eap_eke_process_identity(struct eap_sm *sm, 420 struct eap_eke_data *data, 421 const struct wpabuf *respData, 422 const u8 *payload, size_t payloadlen) 423{ 424 const u8 *pos, *end; 425 int i; 426 427 wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Identity"); 428 429 if (data->state != IDENTITY) { 430 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 431 return; 432 } 433 434 pos = payload; 435 end = payload + payloadlen; 436 437 if (pos + 2 + 4 + 1 > end) { 438 wpa_printf(MSG_INFO, "EAP-EKE: Too short EAP-EKE-ID payload"); 439 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 440 return; 441 } 442 443 if (*pos != 1) { 444 wpa_printf(MSG_INFO, "EAP-EKE: Unexpected NumProposals %d (expected 1)", 445 *pos); 446 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 447 return; 448 } 449 450 pos += 2; 451 452 if (!supported_proposal(pos)) { 453 wpa_printf(MSG_INFO, "EAP-EKE: Unexpected Proposal (%u:%u:%u:%u)", 454 pos[0], pos[1], pos[2], pos[3]); 455 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 456 return; 457 } 458 459 wpa_printf(MSG_DEBUG, "EAP-EKE: Selected Proposal (%u:%u:%u:%u)", 460 pos[0], pos[1], pos[2], pos[3]); 461 if (eap_eke_session_init(&data->sess, pos[0], pos[1], pos[2], pos[3]) < 462 0) { 463 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 464 return; 465 } 466 pos += 4; 467 468 data->peerid_type = *pos++; 469 os_free(data->peerid); 470 data->peerid = os_malloc(end - pos); 471 if (data->peerid == NULL) { 472 wpa_printf(MSG_INFO, "EAP-EKE: Failed to allocate memory for peerid"); 473 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 474 return; 475 } 476 os_memcpy(data->peerid, pos, end - pos); 477 data->peerid_len = end - pos; 478 wpa_printf(MSG_DEBUG, "EAP-EKE: Peer IDType %u", data->peerid_type); 479 wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Peer Identity", 480 data->peerid, data->peerid_len); 481 482 if (eap_user_get(sm, data->peerid, data->peerid_len, data->phase2)) { 483 wpa_printf(MSG_INFO, "EAP-EKE: Peer Identity not found from user database"); 484 eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); 485 return; 486 } 487 488 for (i = 0; i < EAP_MAX_METHODS; i++) { 489 if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && 490 sm->user->methods[i].method == EAP_TYPE_EKE) 491 break; 492 } 493 if (i == EAP_MAX_METHODS) { 494 wpa_printf(MSG_INFO, "EAP-EKE: Matching user entry does not allow EAP-EKE"); 495 eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); 496 return; 497 } 498 499 if (sm->user->password == NULL || sm->user->password_len == 0) { 500 wpa_printf(MSG_INFO, "EAP-EKE: No password configured for peer"); 501 eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); 502 return; 503 } 504 505 if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) { 506 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 507 return; 508 } 509 wpabuf_put_buf(data->msgs, respData); 510 511 eap_eke_state(data, COMMIT); 512} 513 514 515static void eap_eke_process_commit(struct eap_sm *sm, 516 struct eap_eke_data *data, 517 const struct wpabuf *respData, 518 const u8 *payload, size_t payloadlen) 519{ 520 const u8 *pos, *end, *dhcomp, *pnonce; 521 size_t decrypt_len; 522 523 wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Commit"); 524 525 if (data->state != COMMIT) { 526 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 527 return; 528 } 529 530 pos = payload; 531 end = payload + payloadlen; 532 533 if (pos + data->sess.dhcomp_len + data->sess.pnonce_len > end) { 534 wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit"); 535 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 536 return; 537 } 538 539 wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_P", 540 pos, data->sess.dhcomp_len); 541 dhcomp = pos; 542 pos += data->sess.dhcomp_len; 543 wpa_hexdump(MSG_DEBUG, "EAP-EKE: PNonce_P", pos, data->sess.pnonce_len); 544 pnonce = pos; 545 pos += data->sess.pnonce_len; 546 wpa_hexdump(MSG_DEBUG, "EAP-EKE: CBValue", pos, end - pos); 547 548 if (eap_eke_shared_secret(&data->sess, data->key, data->dh_priv, dhcomp) 549 < 0) { 550 wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret"); 551 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 552 return; 553 } 554 555 if (eap_eke_derive_ke_ki(&data->sess, 556 sm->server_id, sm->server_id_len, 557 data->peerid, data->peerid_len) < 0) { 558 wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki"); 559 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 560 return; 561 } 562 563 decrypt_len = sizeof(data->nonce_p); 564 if (eap_eke_decrypt_prot(&data->sess, pnonce, data->sess.pnonce_len, 565 data->nonce_p, &decrypt_len) < 0) { 566 wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_P"); 567 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 568 return; 569 } 570 if (decrypt_len < (size_t) data->sess.nonce_len) { 571 wpa_printf(MSG_INFO, "EAP-EKE: PNonce_P protected data too short to include Nonce_P"); 572 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 573 return; 574 } 575 wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_P", 576 data->nonce_p, data->sess.nonce_len); 577 578 if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) { 579 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 580 return; 581 } 582 wpabuf_put_buf(data->msgs, respData); 583 584 eap_eke_state(data, CONFIRM); 585} 586 587 588static void eap_eke_process_confirm(struct eap_sm *sm, 589 struct eap_eke_data *data, 590 const struct wpabuf *respData, 591 const u8 *payload, size_t payloadlen) 592{ 593 size_t decrypt_len; 594 u8 nonce[EAP_EKE_MAX_NONCE_LEN]; 595 u8 auth_p[EAP_EKE_MAX_HASH_LEN]; 596 597 wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm"); 598 599 if (data->state != CONFIRM) { 600 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 601 return; 602 } 603 604 wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm"); 605 606 if (payloadlen < (size_t) data->sess.pnonce_len + data->sess.prf_len) { 607 wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm"); 608 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 609 return; 610 } 611 612 decrypt_len = sizeof(nonce); 613 if (eap_eke_decrypt_prot(&data->sess, payload, data->sess.pnonce_len, 614 nonce, &decrypt_len) < 0) { 615 wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_S"); 616 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 617 return; 618 } 619 if (decrypt_len < (size_t) data->sess.nonce_len) { 620 wpa_printf(MSG_INFO, "EAP-EKE: PNonce_S protected data too short to include Nonce_S"); 621 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 622 return; 623 } 624 wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_S", 625 nonce, data->sess.nonce_len); 626 if (os_memcmp(nonce, data->nonce_s, data->sess.nonce_len) != 0) { 627 wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_S does not match previously sent Nonce_S"); 628 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 629 return; 630 } 631 632 if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth_p) < 0) { 633 wpa_printf(MSG_INFO, "EAP-EKE: Could not derive Auth_P"); 634 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 635 return; 636 } 637 wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth_p, data->sess.prf_len); 638 if (os_memcmp(auth_p, payload + data->sess.pnonce_len, 639 data->sess.prf_len) != 0) { 640 wpa_printf(MSG_INFO, "EAP-EKE: Auth_P does not match"); 641 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 642 return; 643 } 644 645 if (eap_eke_derive_msk(&data->sess, sm->server_id, sm->server_id_len, 646 data->peerid, data->peerid_len, 647 data->nonce_s, data->nonce_p, 648 data->msk, data->emsk) < 0) { 649 wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK"); 650 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 651 return; 652 } 653 654 os_memset(data->dh_priv, 0, sizeof(data->dh_priv)); 655 os_memset(data->key, 0, sizeof(data->key)); 656 eap_eke_session_clean(&data->sess); 657 658 eap_eke_state(data, SUCCESS); 659} 660 661 662static void eap_eke_process_failure(struct eap_sm *sm, 663 struct eap_eke_data *data, 664 const struct wpabuf *respData, 665 const u8 *payload, size_t payloadlen) 666{ 667 u32 code; 668 669 wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Failure"); 670 671 if (payloadlen < 4) { 672 wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Failure"); 673 eap_eke_state(data, FAILURE); 674 return; 675 } 676 677 code = WPA_GET_BE32(payload); 678 wpa_printf(MSG_DEBUG, "EAP-EKE: Peer reported failure code 0x%x", code); 679 680 eap_eke_state(data, FAILURE); 681} 682 683 684static void eap_eke_process(struct eap_sm *sm, void *priv, 685 struct wpabuf *respData) 686{ 687 struct eap_eke_data *data = priv; 688 u8 eke_exch; 689 size_t len; 690 const u8 *pos, *end; 691 692 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len); 693 if (pos == NULL || len < 1) 694 return; 695 696 eke_exch = *pos; 697 end = pos + len; 698 pos++; 699 700 wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received payload", pos, end - pos); 701 702 switch (eke_exch) { 703 case EAP_EKE_ID: 704 eap_eke_process_identity(sm, data, respData, pos, end - pos); 705 break; 706 case EAP_EKE_COMMIT: 707 eap_eke_process_commit(sm, data, respData, pos, end - pos); 708 break; 709 case EAP_EKE_CONFIRM: 710 eap_eke_process_confirm(sm, data, respData, pos, end - pos); 711 break; 712 case EAP_EKE_FAILURE: 713 eap_eke_process_failure(sm, data, respData, pos, end - pos); 714 break; 715 } 716} 717 718 719static Boolean eap_eke_isDone(struct eap_sm *sm, void *priv) 720{ 721 struct eap_eke_data *data = priv; 722 return data->state == SUCCESS || data->state == FAILURE; 723} 724 725 726static u8 * eap_eke_getKey(struct eap_sm *sm, void *priv, size_t *len) 727{ 728 struct eap_eke_data *data = priv; 729 u8 *key; 730 731 if (data->state != SUCCESS) 732 return NULL; 733 734 key = os_malloc(EAP_MSK_LEN); 735 if (key == NULL) 736 return NULL; 737 os_memcpy(key, data->msk, EAP_MSK_LEN); 738 *len = EAP_MSK_LEN; 739 740 return key; 741} 742 743 744static u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 745{ 746 struct eap_eke_data *data = priv; 747 u8 *key; 748 749 if (data->state != SUCCESS) 750 return NULL; 751 752 key = os_malloc(EAP_EMSK_LEN); 753 if (key == NULL) 754 return NULL; 755 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 756 *len = EAP_EMSK_LEN; 757 758 return key; 759} 760 761 762static Boolean eap_eke_isSuccess(struct eap_sm *sm, void *priv) 763{ 764 struct eap_eke_data *data = priv; 765 return data->state == SUCCESS; 766} 767 768 769int eap_server_eke_register(void) 770{ 771 struct eap_method *eap; 772 int ret; 773 774 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 775 EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE"); 776 if (eap == NULL) 777 return -1; 778 779 eap->init = eap_eke_init; 780 eap->reset = eap_eke_reset; 781 eap->buildReq = eap_eke_buildReq; 782 eap->check = eap_eke_check; 783 eap->process = eap_eke_process; 784 eap->isDone = eap_eke_isDone; 785 eap->getKey = eap_eke_getKey; 786 eap->isSuccess = eap_eke_isSuccess; 787 eap->get_emsk = eap_eke_get_emsk; 788 789 ret = eap_server_method_register(eap); 790 if (ret) 791 eap_server_method_free(eap); 792 return ret; 793} 794