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 17 struct 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 38 static 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 59 static 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 68 static 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 76 static 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->cfg->server_id_len; i++) { 88 if (sm->cfg->server_id[i] == '.' && 89 data->serverid_type == EAP_EKE_ID_OPAQUE) 90 data->serverid_type = EAP_EKE_ID_FQDN; 91 if (sm->cfg->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 101 static 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 bin_clear_free(data, sizeof(*data)); 108 } 109 110 111 static 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 132 static 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 162 static 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 180 static 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->cfg->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->cfg->server_id, sm->cfg->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 239 static 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->cfg->server_id, sm->cfg->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 303 static 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->cfg->server_id, sm->cfg->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 361 static 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 383 static bool 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 419 static 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_memdup(pos, 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 data->peerid_len = end - pos; 477 wpa_printf(MSG_DEBUG, "EAP-EKE: Peer IDType %u", data->peerid_type); 478 wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Peer Identity", 479 data->peerid, data->peerid_len); 480 481 if (eap_user_get(sm, data->peerid, data->peerid_len, data->phase2)) { 482 wpa_printf(MSG_INFO, "EAP-EKE: Peer Identity not found from user database"); 483 eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); 484 return; 485 } 486 487 for (i = 0; i < EAP_MAX_METHODS; i++) { 488 if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && 489 sm->user->methods[i].method == EAP_TYPE_EKE) 490 break; 491 } 492 if (i == EAP_MAX_METHODS) { 493 wpa_printf(MSG_INFO, "EAP-EKE: Matching user entry does not allow EAP-EKE"); 494 eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); 495 return; 496 } 497 498 if (sm->user->password == NULL || sm->user->password_len == 0) { 499 wpa_printf(MSG_INFO, "EAP-EKE: No password configured for peer"); 500 eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); 501 return; 502 } 503 504 if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) { 505 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 506 return; 507 } 508 wpabuf_put_buf(data->msgs, respData); 509 510 eap_eke_state(data, COMMIT); 511 } 512 513 514 static void eap_eke_process_commit(struct eap_sm *sm, 515 struct eap_eke_data *data, 516 const struct wpabuf *respData, 517 const u8 *payload, size_t payloadlen) 518 { 519 const u8 *pos, *end, *dhcomp, *pnonce; 520 size_t decrypt_len; 521 522 wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Commit"); 523 524 if (data->state != COMMIT) { 525 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 526 return; 527 } 528 529 pos = payload; 530 end = payload + payloadlen; 531 532 if (pos + data->sess.dhcomp_len + data->sess.pnonce_len > end) { 533 wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit"); 534 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 535 return; 536 } 537 538 wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_P", 539 pos, data->sess.dhcomp_len); 540 dhcomp = pos; 541 pos += data->sess.dhcomp_len; 542 wpa_hexdump(MSG_DEBUG, "EAP-EKE: PNonce_P", pos, data->sess.pnonce_len); 543 pnonce = pos; 544 pos += data->sess.pnonce_len; 545 wpa_hexdump(MSG_DEBUG, "EAP-EKE: CBValue", pos, end - pos); 546 547 if (eap_eke_shared_secret(&data->sess, data->key, data->dh_priv, dhcomp) 548 < 0) { 549 wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret"); 550 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 551 return; 552 } 553 554 if (eap_eke_derive_ke_ki(&data->sess, 555 sm->cfg->server_id, sm->cfg->server_id_len, 556 data->peerid, data->peerid_len) < 0) { 557 wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki"); 558 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 559 return; 560 } 561 562 decrypt_len = sizeof(data->nonce_p); 563 if (eap_eke_decrypt_prot(&data->sess, pnonce, data->sess.pnonce_len, 564 data->nonce_p, &decrypt_len) < 0) { 565 wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_P"); 566 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 567 return; 568 } 569 if (decrypt_len < (size_t) data->sess.nonce_len) { 570 wpa_printf(MSG_INFO, "EAP-EKE: PNonce_P protected data too short to include Nonce_P"); 571 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 572 return; 573 } 574 wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_P", 575 data->nonce_p, data->sess.nonce_len); 576 577 if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) { 578 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 579 return; 580 } 581 wpabuf_put_buf(data->msgs, respData); 582 583 eap_eke_state(data, CONFIRM); 584 } 585 586 587 static void eap_eke_process_confirm(struct eap_sm *sm, 588 struct eap_eke_data *data, 589 const struct wpabuf *respData, 590 const u8 *payload, size_t payloadlen) 591 { 592 size_t decrypt_len; 593 u8 nonce[EAP_EKE_MAX_NONCE_LEN]; 594 u8 auth_p[EAP_EKE_MAX_HASH_LEN]; 595 596 wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm"); 597 598 if (data->state != CONFIRM) { 599 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 600 return; 601 } 602 603 wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm"); 604 605 if (payloadlen < (size_t) data->sess.pnonce_len + data->sess.prf_len) { 606 wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm"); 607 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 608 return; 609 } 610 611 decrypt_len = sizeof(nonce); 612 if (eap_eke_decrypt_prot(&data->sess, payload, data->sess.pnonce_len, 613 nonce, &decrypt_len) < 0) { 614 wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_S"); 615 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 616 return; 617 } 618 if (decrypt_len < (size_t) data->sess.nonce_len) { 619 wpa_printf(MSG_INFO, "EAP-EKE: PNonce_S protected data too short to include Nonce_S"); 620 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 621 return; 622 } 623 wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_S", 624 nonce, data->sess.nonce_len); 625 if (os_memcmp(nonce, data->nonce_s, data->sess.nonce_len) != 0) { 626 wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_S does not match previously sent Nonce_S"); 627 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 628 return; 629 } 630 631 if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth_p) < 0) { 632 wpa_printf(MSG_INFO, "EAP-EKE: Could not derive Auth_P"); 633 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 634 return; 635 } 636 wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth_p, data->sess.prf_len); 637 if (os_memcmp_const(auth_p, payload + data->sess.pnonce_len, 638 data->sess.prf_len) != 0) { 639 wpa_printf(MSG_INFO, "EAP-EKE: Auth_P does not match"); 640 eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 641 return; 642 } 643 644 if (eap_eke_derive_msk(&data->sess, sm->cfg->server_id, 645 sm->cfg->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 662 static 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 684 static 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 719 static bool 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 726 static 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_memdup(data->msk, EAP_MSK_LEN); 735 if (key == NULL) 736 return NULL; 737 *len = EAP_MSK_LEN; 738 739 return key; 740 } 741 742 743 static u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 744 { 745 struct eap_eke_data *data = priv; 746 u8 *key; 747 748 if (data->state != SUCCESS) 749 return NULL; 750 751 key = os_memdup(data->emsk, EAP_EMSK_LEN); 752 if (key == NULL) 753 return NULL; 754 *len = EAP_EMSK_LEN; 755 756 return key; 757 } 758 759 760 static bool eap_eke_isSuccess(struct eap_sm *sm, void *priv) 761 { 762 struct eap_eke_data *data = priv; 763 return data->state == SUCCESS; 764 } 765 766 767 static u8 * eap_eke_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 768 { 769 struct eap_eke_data *data = priv; 770 u8 *sid; 771 size_t sid_len; 772 773 if (data->state != SUCCESS) 774 return NULL; 775 776 sid_len = 1 + 2 * data->sess.nonce_len; 777 sid = os_malloc(sid_len); 778 if (sid == NULL) 779 return NULL; 780 sid[0] = EAP_TYPE_EKE; 781 os_memcpy(sid + 1, data->nonce_p, data->sess.nonce_len); 782 os_memcpy(sid + 1 + data->sess.nonce_len, data->nonce_s, 783 data->sess.nonce_len); 784 *len = sid_len; 785 786 return sid; 787 } 788 789 790 int eap_server_eke_register(void) 791 { 792 struct eap_method *eap; 793 794 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 795 EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE"); 796 if (eap == NULL) 797 return -1; 798 799 eap->init = eap_eke_init; 800 eap->reset = eap_eke_reset; 801 eap->buildReq = eap_eke_buildReq; 802 eap->check = eap_eke_check; 803 eap->process = eap_eke_process; 804 eap->isDone = eap_eke_isDone; 805 eap->getKey = eap_eke_getKey; 806 eap->isSuccess = eap_eke_isSuccess; 807 eap->get_emsk = eap_eke_get_emsk; 808 eap->getSessionId = eap_eke_get_session_id; 809 810 return eap_server_method_register(eap); 811 } 812