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 wpabuf_free(msg); 280 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 281 return eap_eke_build_failure(data, id); 282 } 283 284 if (eap_eke_dhcomp(&data->sess, data->key, pub, 285 wpabuf_put(msg, data->sess.dhcomp_len)) 286 < 0) { 287 wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_S"); 288 wpabuf_free(msg); 289 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 290 return eap_eke_build_failure(data, id); 291 } 292 293 if (wpabuf_resize(&data->msgs, wpabuf_len(msg)) < 0) { 294 wpabuf_free(msg); 295 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 296 return eap_eke_build_failure(data, id); 297 } 298 wpabuf_put_buf(data->msgs, msg); 299 300 return msg; 301 } 302 303 304 static struct wpabuf * eap_eke_build_confirm(struct eap_sm *sm, 305 struct eap_eke_data *data, u8 id) 306 { 307 struct wpabuf *msg; 308 size_t plen, prot_len; 309 u8 nonces[2 * EAP_EKE_MAX_NONCE_LEN]; 310 u8 *auth; 311 312 wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Confirm"); 313 314 plen = data->sess.pnonce_ps_len + data->sess.prf_len; 315 msg = eap_eke_build_msg(data, id, plen, EAP_EKE_CONFIRM); 316 if (msg == NULL) { 317 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 318 return eap_eke_build_failure(data, id); 319 } 320 321 if (random_get_bytes(data->nonce_s, data->sess.nonce_len)) { 322 wpabuf_free(msg); 323 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 324 return eap_eke_build_failure(data, id); 325 } 326 wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S", 327 data->nonce_s, data->sess.nonce_len); 328 329 os_memcpy(nonces, data->nonce_p, data->sess.nonce_len); 330 os_memcpy(nonces + data->sess.nonce_len, data->nonce_s, 331 data->sess.nonce_len); 332 prot_len = wpabuf_tailroom(msg); 333 if (eap_eke_prot(&data->sess, nonces, 2 * data->sess.nonce_len, 334 wpabuf_put(msg, 0), &prot_len) < 0) { 335 wpabuf_free(msg); 336 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 337 return eap_eke_build_failure(data, id); 338 } 339 wpabuf_put(msg, prot_len); 340 341 if (eap_eke_derive_ka(&data->sess, 342 sm->cfg->server_id, sm->cfg->server_id_len, 343 data->peerid, data->peerid_len, 344 data->nonce_p, data->nonce_s) < 0) { 345 wpabuf_free(msg); 346 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 347 return eap_eke_build_failure(data, id); 348 } 349 350 auth = wpabuf_put(msg, data->sess.prf_len); 351 if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth) < 0) { 352 wpabuf_free(msg); 353 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 354 return eap_eke_build_failure(data, id); 355 } 356 wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth, data->sess.prf_len); 357 358 return msg; 359 } 360 361 362 static struct wpabuf * eap_eke_buildReq(struct eap_sm *sm, void *priv, u8 id) 363 { 364 struct eap_eke_data *data = priv; 365 366 switch (data->state) { 367 case IDENTITY: 368 return eap_eke_build_identity(sm, data, id); 369 case COMMIT: 370 return eap_eke_build_commit(sm, data, id); 371 case CONFIRM: 372 return eap_eke_build_confirm(sm, data, id); 373 case FAILURE_REPORT: 374 return eap_eke_build_failure(data, id); 375 default: 376 wpa_printf(MSG_DEBUG, "EAP-EKE: Unknown state %d in buildReq", 377 data->state); 378 break; 379 } 380 return NULL; 381 } 382 383 384 static bool eap_eke_check(struct eap_sm *sm, void *priv, 385 struct wpabuf *respData) 386 { 387 struct eap_eke_data *data = priv; 388 size_t len; 389 const u8 *pos; 390 u8 eke_exch; 391 392 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len); 393 if (pos == NULL || len < 1) { 394 wpa_printf(MSG_INFO, "EAP-EKE: Invalid frame"); 395 return true; 396 } 397 398 eke_exch = *pos; 399 wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: EKE-Exch=%d", eke_exch); 400 401 if (data->state == IDENTITY && eke_exch == EAP_EKE_ID) 402 return false; 403 404 if (data->state == COMMIT && eke_exch == EAP_EKE_COMMIT) 405 return false; 406 407 if (data->state == CONFIRM && eke_exch == EAP_EKE_CONFIRM) 408 return false; 409 410 if (eke_exch == EAP_EKE_FAILURE) 411 return false; 412 413 wpa_printf(MSG_INFO, "EAP-EKE: Unexpected EKE-Exch=%d in state=%d", 414 eke_exch, data->state); 415 416 return true; 417 } 418 419 420 static void eap_eke_process_identity(struct eap_sm *sm, 421 struct eap_eke_data *data, 422 const struct wpabuf *respData, 423 const u8 *payload, size_t payloadlen) 424 { 425 const u8 *pos, *end; 426 int i; 427 428 wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Identity"); 429 430 if (data->state != IDENTITY) { 431 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 432 return; 433 } 434 435 pos = payload; 436 end = payload + payloadlen; 437 438 if (pos + 2 + 4 + 1 > end) { 439 wpa_printf(MSG_INFO, "EAP-EKE: Too short EAP-EKE-ID payload"); 440 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 441 return; 442 } 443 444 if (*pos != 1) { 445 wpa_printf(MSG_INFO, "EAP-EKE: Unexpected NumProposals %d (expected 1)", 446 *pos); 447 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 448 return; 449 } 450 451 pos += 2; 452 453 if (!supported_proposal(pos)) { 454 wpa_printf(MSG_INFO, "EAP-EKE: Unexpected Proposal (%u:%u:%u:%u)", 455 pos[0], pos[1], pos[2], pos[3]); 456 eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 457 return; 458 } 459 460 wpa_printf(MSG_DEBUG, "EAP-EKE: Selected Proposal (%u:%u:%u:%u)", 461 pos[0], pos[1], pos[2], pos[3]); 462 if (eap_eke_session_init(&data->sess, pos[0], pos[1], pos[2], pos[3]) < 463 0) { 464 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 465 return; 466 } 467 pos += 4; 468 469 data->peerid_type = *pos++; 470 os_free(data->peerid); 471 data->peerid = os_memdup(pos, end - pos); 472 if (data->peerid == NULL) { 473 wpa_printf(MSG_INFO, "EAP-EKE: Failed to allocate memory for peerid"); 474 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 475 return; 476 } 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 515 static 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->cfg->server_id, sm->cfg->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 588 static 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_const(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->cfg->server_id, 646 sm->cfg->server_id_len, 647 data->peerid, data->peerid_len, 648 data->nonce_s, data->nonce_p, 649 data->msk, data->emsk) < 0) { 650 wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK"); 651 eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 652 return; 653 } 654 655 os_memset(data->dh_priv, 0, sizeof(data->dh_priv)); 656 os_memset(data->key, 0, sizeof(data->key)); 657 eap_eke_session_clean(&data->sess); 658 659 eap_eke_state(data, SUCCESS); 660 } 661 662 663 static void eap_eke_process_failure(struct eap_sm *sm, 664 struct eap_eke_data *data, 665 const struct wpabuf *respData, 666 const u8 *payload, size_t payloadlen) 667 { 668 u32 code; 669 670 wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Failure"); 671 672 if (payloadlen < 4) { 673 wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Failure"); 674 eap_eke_state(data, FAILURE); 675 return; 676 } 677 678 code = WPA_GET_BE32(payload); 679 wpa_printf(MSG_DEBUG, "EAP-EKE: Peer reported failure code 0x%x", code); 680 681 eap_eke_state(data, FAILURE); 682 } 683 684 685 static void eap_eke_process(struct eap_sm *sm, void *priv, 686 struct wpabuf *respData) 687 { 688 struct eap_eke_data *data = priv; 689 u8 eke_exch; 690 size_t len; 691 const u8 *pos, *end; 692 693 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len); 694 if (pos == NULL || len < 1) 695 return; 696 697 eke_exch = *pos; 698 end = pos + len; 699 pos++; 700 701 wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received payload", pos, end - pos); 702 703 switch (eke_exch) { 704 case EAP_EKE_ID: 705 eap_eke_process_identity(sm, data, respData, pos, end - pos); 706 break; 707 case EAP_EKE_COMMIT: 708 eap_eke_process_commit(sm, data, respData, pos, end - pos); 709 break; 710 case EAP_EKE_CONFIRM: 711 eap_eke_process_confirm(sm, data, respData, pos, end - pos); 712 break; 713 case EAP_EKE_FAILURE: 714 eap_eke_process_failure(sm, data, respData, pos, end - pos); 715 break; 716 } 717 } 718 719 720 static bool eap_eke_isDone(struct eap_sm *sm, void *priv) 721 { 722 struct eap_eke_data *data = priv; 723 return data->state == SUCCESS || data->state == FAILURE; 724 } 725 726 727 static u8 * eap_eke_getKey(struct eap_sm *sm, void *priv, size_t *len) 728 { 729 struct eap_eke_data *data = priv; 730 u8 *key; 731 732 if (data->state != SUCCESS) 733 return NULL; 734 735 key = os_memdup(data->msk, EAP_MSK_LEN); 736 if (key == NULL) 737 return NULL; 738 *len = EAP_MSK_LEN; 739 740 return key; 741 } 742 743 744 static 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_memdup(data->emsk, EAP_EMSK_LEN); 753 if (key == NULL) 754 return NULL; 755 *len = EAP_EMSK_LEN; 756 757 return key; 758 } 759 760 761 static bool eap_eke_isSuccess(struct eap_sm *sm, void *priv) 762 { 763 struct eap_eke_data *data = priv; 764 return data->state == SUCCESS; 765 } 766 767 768 static u8 * eap_eke_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 769 { 770 struct eap_eke_data *data = priv; 771 u8 *sid; 772 size_t sid_len; 773 774 if (data->state != SUCCESS) 775 return NULL; 776 777 sid_len = 1 + 2 * data->sess.nonce_len; 778 sid = os_malloc(sid_len); 779 if (sid == NULL) 780 return NULL; 781 sid[0] = EAP_TYPE_EKE; 782 os_memcpy(sid + 1, data->nonce_p, data->sess.nonce_len); 783 os_memcpy(sid + 1 + data->sess.nonce_len, data->nonce_s, 784 data->sess.nonce_len); 785 *len = sid_len; 786 787 return sid; 788 } 789 790 791 int eap_server_eke_register(void) 792 { 793 struct eap_method *eap; 794 795 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 796 EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE"); 797 if (eap == NULL) 798 return -1; 799 800 eap->init = eap_eke_init; 801 eap->reset = eap_eke_reset; 802 eap->buildReq = eap_eke_buildReq; 803 eap->check = eap_eke_check; 804 eap->process = eap_eke_process; 805 eap->isDone = eap_eke_isDone; 806 eap->getKey = eap_eke_getKey; 807 eap->isSuccess = eap_eke_isSuccess; 808 eap->get_emsk = eap_eke_get_emsk; 809 eap->getSessionId = eap_eke_get_session_id; 810 811 return eap_server_method_register(eap); 812 } 813