1 /* 2 * hostapd / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) 3 * Copyright (c) 2004-2008, 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/sha1.h" 13 #include "crypto/tls.h" 14 #include "crypto/random.h" 15 #include "eap_i.h" 16 #include "eap_tls_common.h" 17 #include "eap_common/eap_tlv_common.h" 18 #include "eap_common/eap_peap_common.h" 19 #include "tncs.h" 20 21 22 /* Maximum supported PEAP version 23 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt 24 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt 25 */ 26 #define EAP_PEAP_VERSION 1 27 28 29 static void eap_peap_reset(struct eap_sm *sm, void *priv); 30 31 32 struct eap_peap_data { 33 struct eap_ssl_data ssl; 34 enum { 35 START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID, 36 PHASE2_METHOD, PHASE2_SOH, 37 PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE 38 } state; 39 40 int peap_version; 41 int recv_version; 42 const struct eap_method *phase2_method; 43 void *phase2_priv; 44 int force_version; 45 struct wpabuf *pending_phase2_resp; 46 enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request; 47 int crypto_binding_sent; 48 int crypto_binding_used; 49 enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; 50 u8 binding_nonce[32]; 51 u8 ipmk[40]; 52 u8 cmk[20]; 53 u8 *phase2_key; 54 size_t phase2_key_len; 55 struct wpabuf *soh_response; 56 }; 57 58 59 static const char * eap_peap_state_txt(int state) 60 { 61 switch (state) { 62 case START: 63 return "START"; 64 case PHASE1: 65 return "PHASE1"; 66 case PHASE1_ID2: 67 return "PHASE1_ID2"; 68 case PHASE2_START: 69 return "PHASE2_START"; 70 case PHASE2_ID: 71 return "PHASE2_ID"; 72 case PHASE2_METHOD: 73 return "PHASE2_METHOD"; 74 case PHASE2_SOH: 75 return "PHASE2_SOH"; 76 case PHASE2_TLV: 77 return "PHASE2_TLV"; 78 case SUCCESS_REQ: 79 return "SUCCESS_REQ"; 80 case FAILURE_REQ: 81 return "FAILURE_REQ"; 82 case SUCCESS: 83 return "SUCCESS"; 84 case FAILURE: 85 return "FAILURE"; 86 default: 87 return "Unknown?!"; 88 } 89 } 90 91 92 static void eap_peap_state(struct eap_peap_data *data, int state) 93 { 94 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s", 95 eap_peap_state_txt(data->state), 96 eap_peap_state_txt(state)); 97 data->state = state; 98 if (state == FAILURE || state == FAILURE_REQ) 99 tls_connection_remove_session(data->ssl.conn); 100 } 101 102 103 static void eap_peap_valid_session(struct eap_sm *sm, 104 struct eap_peap_data *data) 105 { 106 struct wpabuf *buf; 107 108 if (!sm->tls_session_lifetime || 109 tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) 110 return; 111 112 buf = wpabuf_alloc(1 + 1 + sm->identity_len); 113 if (!buf) 114 return; 115 wpabuf_put_u8(buf, EAP_TYPE_PEAP); 116 if (sm->identity) { 117 u8 id_len; 118 119 if (sm->identity_len <= 255) 120 id_len = sm->identity_len; 121 else 122 id_len = 255; 123 wpabuf_put_u8(buf, id_len); 124 wpabuf_put_data(buf, sm->identity, id_len); 125 } else { 126 wpabuf_put_u8(buf, 0); 127 } 128 tls_connection_set_success_data(data->ssl.conn, buf); 129 } 130 131 132 static void eap_peap_req_success(struct eap_sm *sm, 133 struct eap_peap_data *data) 134 { 135 if (data->state == FAILURE || data->state == FAILURE_REQ) { 136 eap_peap_state(data, FAILURE); 137 return; 138 } 139 140 if (data->peap_version == 0) { 141 data->tlv_request = TLV_REQ_SUCCESS; 142 eap_peap_state(data, PHASE2_TLV); 143 } else { 144 eap_peap_state(data, SUCCESS_REQ); 145 } 146 } 147 148 149 static void eap_peap_req_failure(struct eap_sm *sm, 150 struct eap_peap_data *data) 151 { 152 if (data->state == FAILURE || data->state == FAILURE_REQ || 153 data->state == SUCCESS_REQ || data->tlv_request != TLV_REQ_NONE) { 154 eap_peap_state(data, FAILURE); 155 return; 156 } 157 158 if (data->peap_version == 0) { 159 data->tlv_request = TLV_REQ_FAILURE; 160 eap_peap_state(data, PHASE2_TLV); 161 } else { 162 eap_peap_state(data, FAILURE_REQ); 163 } 164 } 165 166 167 static void * eap_peap_init(struct eap_sm *sm) 168 { 169 struct eap_peap_data *data; 170 171 data = os_zalloc(sizeof(*data)); 172 if (data == NULL) 173 return NULL; 174 data->peap_version = EAP_PEAP_VERSION; 175 data->force_version = -1; 176 if (sm->user && sm->user->force_version >= 0) { 177 data->force_version = sm->user->force_version; 178 wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d", 179 data->force_version); 180 data->peap_version = data->force_version; 181 } 182 data->state = START; 183 data->crypto_binding = OPTIONAL_BINDING; 184 185 if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_TYPE_PEAP)) { 186 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); 187 eap_peap_reset(sm, data); 188 return NULL; 189 } 190 191 return data; 192 } 193 194 195 static void eap_peap_reset(struct eap_sm *sm, void *priv) 196 { 197 struct eap_peap_data *data = priv; 198 if (data == NULL) 199 return; 200 if (data->phase2_priv && data->phase2_method) 201 data->phase2_method->reset(sm, data->phase2_priv); 202 eap_server_tls_ssl_deinit(sm, &data->ssl); 203 wpabuf_free(data->pending_phase2_resp); 204 os_free(data->phase2_key); 205 wpabuf_free(data->soh_response); 206 bin_clear_free(data, sizeof(*data)); 207 } 208 209 210 static struct wpabuf * eap_peap_build_start(struct eap_sm *sm, 211 struct eap_peap_data *data, u8 id) 212 { 213 struct wpabuf *req; 214 215 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1, 216 EAP_CODE_REQUEST, id); 217 if (req == NULL) { 218 wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for" 219 " request"); 220 eap_peap_state(data, FAILURE); 221 return NULL; 222 } 223 224 wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version); 225 226 eap_peap_state(data, PHASE1); 227 228 return req; 229 } 230 231 232 static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm, 233 struct eap_peap_data *data, 234 u8 id) 235 { 236 struct wpabuf *buf, *encr_req, msgbuf; 237 const u8 *req; 238 size_t req_len; 239 240 if (data->phase2_method == NULL || data->phase2_priv == NULL) { 241 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 method not ready"); 242 return NULL; 243 } 244 buf = data->phase2_method->buildReq(sm, data->phase2_priv, id); 245 if (buf == NULL) 246 return NULL; 247 248 req = wpabuf_head(buf); 249 req_len = wpabuf_len(buf); 250 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", 251 req, req_len); 252 253 if (data->peap_version == 0 && 254 data->phase2_method->method != EAP_TYPE_TLV) { 255 req += sizeof(struct eap_hdr); 256 req_len -= sizeof(struct eap_hdr); 257 } 258 259 wpabuf_set(&msgbuf, req, req_len); 260 encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); 261 wpabuf_free(buf); 262 263 return encr_req; 264 } 265 266 267 #ifdef EAP_SERVER_TNC 268 static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm, 269 struct eap_peap_data *data, 270 u8 id) 271 { 272 struct wpabuf *buf1, *buf, *encr_req, msgbuf; 273 const u8 *req; 274 size_t req_len; 275 276 buf1 = tncs_build_soh_request(); 277 if (buf1 == NULL) 278 return NULL; 279 280 buf = eap_msg_alloc(EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf1), 281 EAP_CODE_REQUEST, id); 282 if (buf == NULL) { 283 wpabuf_free(buf1); 284 return NULL; 285 } 286 wpabuf_put_buf(buf, buf1); 287 wpabuf_free(buf1); 288 289 req = wpabuf_head(buf); 290 req_len = wpabuf_len(buf); 291 292 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 SOH data", 293 req, req_len); 294 295 req += sizeof(struct eap_hdr); 296 req_len -= sizeof(struct eap_hdr); 297 wpabuf_set(&msgbuf, req, req_len); 298 299 encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); 300 wpabuf_free(buf); 301 302 return encr_req; 303 } 304 #endif /* EAP_SERVER_TNC */ 305 306 307 static void eap_peap_get_isk(struct eap_peap_data *data, 308 u8 *isk, size_t isk_len) 309 { 310 size_t key_len; 311 312 os_memset(isk, 0, isk_len); 313 if (data->phase2_key == NULL) 314 return; 315 316 key_len = data->phase2_key_len; 317 if (key_len > isk_len) 318 key_len = isk_len; 319 os_memcpy(isk, data->phase2_key, key_len); 320 } 321 322 323 static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) 324 { 325 u8 *tk; 326 u8 isk[32], imck[60]; 327 328 /* 329 * Tunnel key (TK) is the first 60 octets of the key generated by 330 * phase 1 of PEAP (based on TLS). 331 */ 332 tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption", 333 EAP_TLS_KEY_LEN); 334 if (tk == NULL) 335 return -1; 336 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); 337 338 if (tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { 339 /* Fast-connect: IPMK|CMK = TK */ 340 os_memcpy(data->ipmk, tk, 40); 341 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK", 342 data->ipmk, 40); 343 os_memcpy(data->cmk, tk + 40, 20); 344 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK", 345 data->cmk, 20); 346 os_free(tk); 347 return 0; 348 } 349 350 eap_peap_get_isk(data, isk, sizeof(isk)); 351 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk)); 352 353 /* 354 * IPMK Seed = "Inner Methods Compound Keys" | ISK 355 * TempKey = First 40 octets of TK 356 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60) 357 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space 358 * in the end of the label just before ISK; is that just a typo?) 359 */ 360 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); 361 if (peap_prfplus(data->peap_version, tk, 40, 362 "Inner Methods Compound Keys", 363 isk, sizeof(isk), imck, sizeof(imck)) < 0) { 364 os_free(tk); 365 return -1; 366 } 367 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", 368 imck, sizeof(imck)); 369 370 os_free(tk); 371 372 os_memcpy(data->ipmk, imck, 40); 373 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40); 374 os_memcpy(data->cmk, imck + 40, 20); 375 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20); 376 377 return 0; 378 } 379 380 381 static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm, 382 struct eap_peap_data *data, 383 u8 id) 384 { 385 struct wpabuf *buf, *encr_req; 386 size_t mlen; 387 388 mlen = 6; /* Result TLV */ 389 if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS && 390 data->crypto_binding != NO_BINDING) { 391 mlen += 60; /* Cryptobinding TLV */ 392 #ifdef EAP_SERVER_TNC 393 if (data->soh_response) 394 mlen += wpabuf_len(data->soh_response); 395 #endif /* EAP_SERVER_TNC */ 396 } 397 398 buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, mlen, 399 EAP_CODE_REQUEST, id); 400 if (buf == NULL) 401 return NULL; 402 403 wpabuf_put_u8(buf, 0x80); /* Mandatory */ 404 wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV); 405 /* Length */ 406 wpabuf_put_be16(buf, 2); 407 /* Status */ 408 wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ? 409 EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE); 410 411 if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS && 412 data->crypto_binding != NO_BINDING) { 413 u8 *mac; 414 u8 eap_type = EAP_TYPE_PEAP; 415 const u8 *addr[2]; 416 size_t len[2]; 417 u16 tlv_type; 418 419 #ifdef EAP_SERVER_TNC 420 if (data->soh_response) { 421 wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH " 422 "Response TLV"); 423 wpabuf_put_buf(buf, data->soh_response); 424 wpabuf_free(data->soh_response); 425 data->soh_response = NULL; 426 } 427 #endif /* EAP_SERVER_TNC */ 428 429 if (eap_peap_derive_cmk(sm, data) < 0 || 430 random_get_bytes(data->binding_nonce, 32)) { 431 wpabuf_free(buf); 432 return NULL; 433 } 434 435 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 436 addr[0] = wpabuf_put(buf, 0); 437 len[0] = 60; 438 addr[1] = &eap_type; 439 len[1] = 1; 440 441 tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; 442 wpabuf_put_be16(buf, tlv_type); 443 wpabuf_put_be16(buf, 56); 444 445 wpabuf_put_u8(buf, 0); /* Reserved */ 446 wpabuf_put_u8(buf, data->peap_version); /* Version */ 447 wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */ 448 wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */ 449 wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ 450 mac = wpabuf_put(buf, 20); /* Compound_MAC */ 451 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", 452 data->cmk, 20); 453 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", 454 addr[0], len[0]); 455 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", 456 addr[1], len[1]); 457 hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); 458 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", 459 mac, SHA1_MAC_LEN); 460 data->crypto_binding_sent = 1; 461 } 462 463 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data", 464 buf); 465 466 encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf); 467 wpabuf_free(buf); 468 469 return encr_req; 470 } 471 472 473 static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm, 474 struct eap_peap_data *data, 475 u8 id, int success) 476 { 477 struct wpabuf *encr_req, msgbuf; 478 size_t req_len; 479 struct eap_hdr *hdr; 480 481 req_len = sizeof(*hdr); 482 hdr = os_zalloc(req_len); 483 if (hdr == NULL) 484 return NULL; 485 486 hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; 487 hdr->identifier = id; 488 hdr->length = host_to_be16(req_len); 489 490 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", 491 (u8 *) hdr, req_len); 492 493 wpabuf_set(&msgbuf, hdr, req_len); 494 encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); 495 os_free(hdr); 496 497 return encr_req; 498 } 499 500 501 static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id) 502 { 503 struct eap_peap_data *data = priv; 504 505 if (data->ssl.state == FRAG_ACK) { 506 return eap_server_tls_build_ack(id, EAP_TYPE_PEAP, 507 data->peap_version); 508 } 509 510 if (data->ssl.state == WAIT_FRAG_ACK) { 511 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, 512 data->peap_version, id); 513 } 514 515 switch (data->state) { 516 case START: 517 return eap_peap_build_start(sm, data, id); 518 case PHASE1: 519 case PHASE1_ID2: 520 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 521 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, " 522 "starting Phase2"); 523 eap_peap_state(data, PHASE2_START); 524 } 525 break; 526 case PHASE2_ID: 527 case PHASE2_METHOD: 528 wpabuf_free(data->ssl.tls_out); 529 data->ssl.tls_out_pos = 0; 530 data->ssl.tls_out = eap_peap_build_phase2_req(sm, data, id); 531 break; 532 #ifdef EAP_SERVER_TNC 533 case PHASE2_SOH: 534 wpabuf_free(data->ssl.tls_out); 535 data->ssl.tls_out_pos = 0; 536 data->ssl.tls_out = eap_peap_build_phase2_soh(sm, data, id); 537 break; 538 #endif /* EAP_SERVER_TNC */ 539 case PHASE2_TLV: 540 wpabuf_free(data->ssl.tls_out); 541 data->ssl.tls_out_pos = 0; 542 data->ssl.tls_out = eap_peap_build_phase2_tlv(sm, data, id); 543 break; 544 case SUCCESS_REQ: 545 wpabuf_free(data->ssl.tls_out); 546 data->ssl.tls_out_pos = 0; 547 data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id, 548 1); 549 break; 550 case FAILURE_REQ: 551 wpabuf_free(data->ssl.tls_out); 552 data->ssl.tls_out_pos = 0; 553 data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id, 554 0); 555 break; 556 default: 557 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", 558 __func__, data->state); 559 return NULL; 560 } 561 562 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, 563 data->peap_version, id); 564 } 565 566 567 static Boolean eap_peap_check(struct eap_sm *sm, void *priv, 568 struct wpabuf *respData) 569 { 570 const u8 *pos; 571 size_t len; 572 573 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len); 574 if (pos == NULL || len < 1) { 575 wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame"); 576 return TRUE; 577 } 578 579 return FALSE; 580 } 581 582 583 static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data, 584 int vendor, EapType eap_type) 585 { 586 if (data->phase2_priv && data->phase2_method) { 587 data->phase2_method->reset(sm, data->phase2_priv); 588 data->phase2_method = NULL; 589 data->phase2_priv = NULL; 590 } 591 data->phase2_method = eap_server_get_eap_method(vendor, eap_type); 592 if (!data->phase2_method) 593 return -1; 594 595 sm->init_phase2 = 1; 596 data->phase2_priv = data->phase2_method->init(sm); 597 sm->init_phase2 = 0; 598 return 0; 599 } 600 601 602 static int eap_tlv_validate_cryptobinding(struct eap_sm *sm, 603 struct eap_peap_data *data, 604 const u8 *crypto_tlv, 605 size_t crypto_tlv_len) 606 { 607 u8 buf[61], mac[SHA1_MAC_LEN]; 608 const u8 *pos; 609 610 if (crypto_tlv_len != 4 + 56) { 611 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " 612 "length %d", (int) crypto_tlv_len); 613 return -1; 614 } 615 616 pos = crypto_tlv; 617 pos += 4; /* TLV header */ 618 if (pos[1] != data->peap_version) { 619 wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " 620 "mismatch (was %d; expected %d)", 621 pos[1], data->peap_version); 622 return -1; 623 } 624 625 if (pos[3] != 1) { 626 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " 627 "SubType %d", pos[3]); 628 return -1; 629 } 630 pos += 4; 631 pos += 32; /* Nonce */ 632 633 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 634 os_memcpy(buf, crypto_tlv, 60); 635 os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ 636 buf[60] = EAP_TYPE_PEAP; 637 hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); 638 639 if (os_memcmp_const(mac, pos, SHA1_MAC_LEN) != 0) { 640 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " 641 "cryptobinding TLV"); 642 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20); 643 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data", 644 buf, 61); 645 return -1; 646 } 647 648 wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); 649 650 return 0; 651 } 652 653 654 static void eap_peap_process_phase2_tlv(struct eap_sm *sm, 655 struct eap_peap_data *data, 656 struct wpabuf *in_data) 657 { 658 const u8 *pos; 659 size_t left; 660 const u8 *result_tlv = NULL, *crypto_tlv = NULL; 661 size_t result_tlv_len = 0, crypto_tlv_len = 0; 662 int tlv_type, mandatory, tlv_len; 663 664 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left); 665 if (pos == NULL) { 666 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header"); 667 return; 668 } 669 670 /* Parse TLVs */ 671 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left); 672 while (left >= 4) { 673 mandatory = !!(pos[0] & 0x80); 674 tlv_type = pos[0] & 0x3f; 675 tlv_type = (tlv_type << 8) | pos[1]; 676 tlv_len = ((int) pos[2] << 8) | pos[3]; 677 pos += 4; 678 left -= 4; 679 if ((size_t) tlv_len > left) { 680 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " 681 "(tlv_len=%d left=%lu)", tlv_len, 682 (unsigned long) left); 683 eap_peap_state(data, FAILURE); 684 return; 685 } 686 switch (tlv_type) { 687 case EAP_TLV_RESULT_TLV: 688 result_tlv = pos; 689 result_tlv_len = tlv_len; 690 break; 691 case EAP_TLV_CRYPTO_BINDING_TLV: 692 crypto_tlv = pos; 693 crypto_tlv_len = tlv_len; 694 break; 695 default: 696 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " 697 "%d%s", tlv_type, 698 mandatory ? " (mandatory)" : ""); 699 if (mandatory) { 700 eap_peap_state(data, FAILURE); 701 return; 702 } 703 /* Ignore this TLV, but process other TLVs */ 704 break; 705 } 706 707 pos += tlv_len; 708 left -= tlv_len; 709 } 710 if (left) { 711 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " 712 "Request (left=%lu)", (unsigned long) left); 713 eap_peap_state(data, FAILURE); 714 return; 715 } 716 717 /* Process supported TLVs */ 718 if (crypto_tlv && data->crypto_binding_sent) { 719 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", 720 crypto_tlv, crypto_tlv_len); 721 if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, 722 crypto_tlv_len + 4) < 0) { 723 eap_peap_state(data, FAILURE); 724 return; 725 } 726 data->crypto_binding_used = 1; 727 } else if (!crypto_tlv && data->crypto_binding_sent && 728 data->crypto_binding == REQUIRE_BINDING) { 729 wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); 730 eap_peap_state(data, FAILURE); 731 return; 732 } 733 734 if (result_tlv) { 735 int status; 736 const char *requested; 737 738 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV", 739 result_tlv, result_tlv_len); 740 if (result_tlv_len < 2) { 741 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV " 742 "(len=%lu)", 743 (unsigned long) result_tlv_len); 744 eap_peap_state(data, FAILURE); 745 return; 746 } 747 requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" : 748 "Failure"; 749 status = WPA_GET_BE16(result_tlv); 750 if (status == EAP_TLV_RESULT_SUCCESS) { 751 wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success " 752 "- requested %s", requested); 753 if (data->tlv_request == TLV_REQ_SUCCESS) { 754 eap_peap_state(data, SUCCESS); 755 eap_peap_valid_session(sm, data); 756 } else { 757 eap_peap_state(data, FAILURE); 758 } 759 760 } else if (status == EAP_TLV_RESULT_FAILURE) { 761 wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure " 762 "- requested %s", requested); 763 eap_peap_state(data, FAILURE); 764 } else { 765 wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result " 766 "Status %d", status); 767 eap_peap_state(data, FAILURE); 768 } 769 } 770 } 771 772 773 #ifdef EAP_SERVER_TNC 774 static void eap_peap_process_phase2_soh(struct eap_sm *sm, 775 struct eap_peap_data *data, 776 struct wpabuf *in_data) 777 { 778 const u8 *pos, *vpos; 779 size_t left; 780 const u8 *soh_tlv = NULL; 781 size_t soh_tlv_len = 0; 782 int tlv_type, mandatory, tlv_len, vtlv_len; 783 u32 next_type; 784 u32 vendor_id; 785 786 pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left); 787 if (pos == NULL) { 788 wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP " 789 "Extensions Method header - skip TNC"); 790 goto auth_method; 791 } 792 793 /* Parse TLVs */ 794 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left); 795 while (left >= 4) { 796 mandatory = !!(pos[0] & 0x80); 797 tlv_type = pos[0] & 0x3f; 798 tlv_type = (tlv_type << 8) | pos[1]; 799 tlv_len = ((int) pos[2] << 8) | pos[3]; 800 pos += 4; 801 left -= 4; 802 if ((size_t) tlv_len > left) { 803 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " 804 "(tlv_len=%d left=%lu)", tlv_len, 805 (unsigned long) left); 806 eap_peap_state(data, FAILURE); 807 return; 808 } 809 switch (tlv_type) { 810 case EAP_TLV_VENDOR_SPECIFIC_TLV: 811 if (tlv_len < 4) { 812 wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short " 813 "vendor specific TLV (len=%d)", 814 (int) tlv_len); 815 eap_peap_state(data, FAILURE); 816 return; 817 } 818 819 vendor_id = WPA_GET_BE32(pos); 820 if (vendor_id != EAP_VENDOR_MICROSOFT) { 821 if (mandatory) { 822 eap_peap_state(data, FAILURE); 823 return; 824 } 825 break; 826 } 827 828 vpos = pos + 4; 829 mandatory = !!(vpos[0] & 0x80); 830 tlv_type = vpos[0] & 0x3f; 831 tlv_type = (tlv_type << 8) | vpos[1]; 832 vtlv_len = ((int) vpos[2] << 8) | vpos[3]; 833 vpos += 4; 834 if (vpos + vtlv_len > pos + left) { 835 wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV " 836 "underrun"); 837 eap_peap_state(data, FAILURE); 838 return; 839 } 840 841 if (tlv_type == 1) { 842 soh_tlv = vpos; 843 soh_tlv_len = vtlv_len; 844 break; 845 } 846 847 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV " 848 "Type %d%s", tlv_type, 849 mandatory ? " (mandatory)" : ""); 850 if (mandatory) { 851 eap_peap_state(data, FAILURE); 852 return; 853 } 854 /* Ignore this TLV, but process other TLVs */ 855 break; 856 default: 857 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " 858 "%d%s", tlv_type, 859 mandatory ? " (mandatory)" : ""); 860 if (mandatory) { 861 eap_peap_state(data, FAILURE); 862 return; 863 } 864 /* Ignore this TLV, but process other TLVs */ 865 break; 866 } 867 868 pos += tlv_len; 869 left -= tlv_len; 870 } 871 if (left) { 872 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " 873 "Request (left=%lu)", (unsigned long) left); 874 eap_peap_state(data, FAILURE); 875 return; 876 } 877 878 /* Process supported TLVs */ 879 if (soh_tlv) { 880 int failure = 0; 881 wpabuf_free(data->soh_response); 882 data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len, 883 &failure); 884 if (failure) { 885 eap_peap_state(data, FAILURE); 886 return; 887 } 888 } else { 889 wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received"); 890 eap_peap_state(data, FAILURE); 891 return; 892 } 893 894 auth_method: 895 eap_peap_state(data, PHASE2_METHOD); 896 next_type = sm->user->methods[0].method; 897 sm->user_eap_method_index = 1; 898 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type %d", 899 sm->user->methods[0].vendor, next_type); 900 eap_peap_phase2_init(sm, data, sm->user->methods[0].vendor, next_type); 901 } 902 #endif /* EAP_SERVER_TNC */ 903 904 905 static void eap_peap_process_phase2_response(struct eap_sm *sm, 906 struct eap_peap_data *data, 907 struct wpabuf *in_data) 908 { 909 int next_vendor = EAP_VENDOR_IETF; 910 u32 next_type = EAP_TYPE_NONE; 911 const struct eap_hdr *hdr; 912 const u8 *pos; 913 size_t left; 914 915 if (data->state == PHASE2_TLV) { 916 eap_peap_process_phase2_tlv(sm, data, in_data); 917 return; 918 } 919 920 #ifdef EAP_SERVER_TNC 921 if (data->state == PHASE2_SOH) { 922 eap_peap_process_phase2_soh(sm, data, in_data); 923 return; 924 } 925 #endif /* EAP_SERVER_TNC */ 926 927 if (data->phase2_priv == NULL) { 928 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not " 929 "initialized?!", __func__); 930 return; 931 } 932 933 hdr = wpabuf_head(in_data); 934 pos = (const u8 *) (hdr + 1); 935 936 if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { 937 left = wpabuf_len(in_data) - sizeof(*hdr); 938 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; " 939 "allowed types", pos + 1, left - 1); 940 eap_sm_process_nak(sm, pos + 1, left - 1); 941 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && 942 (sm->user->methods[sm->user_eap_method_index].vendor != 943 EAP_VENDOR_IETF || 944 sm->user->methods[sm->user_eap_method_index].method != 945 EAP_TYPE_NONE)) { 946 next_vendor = sm->user->methods[ 947 sm->user_eap_method_index].vendor; 948 next_type = sm->user->methods[ 949 sm->user_eap_method_index++].method; 950 wpa_printf(MSG_DEBUG, 951 "EAP-PEAP: try EAP vendor %d type 0x%x", 952 next_vendor, next_type); 953 } else { 954 eap_peap_req_failure(sm, data); 955 next_vendor = EAP_VENDOR_IETF; 956 next_type = EAP_TYPE_NONE; 957 } 958 eap_peap_phase2_init(sm, data, next_vendor, next_type); 959 return; 960 } 961 962 if (data->phase2_method->check(sm, data->phase2_priv, in_data)) { 963 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to " 964 "ignore the packet"); 965 return; 966 } 967 968 data->phase2_method->process(sm, data->phase2_priv, in_data); 969 970 if (sm->method_pending == METHOD_PENDING_WAIT) { 971 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in " 972 "pending wait state - save decrypted response"); 973 wpabuf_free(data->pending_phase2_resp); 974 data->pending_phase2_resp = wpabuf_dup(in_data); 975 } 976 977 if (!data->phase2_method->isDone(sm, data->phase2_priv)) 978 return; 979 980 if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) { 981 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed"); 982 eap_peap_req_failure(sm, data); 983 next_vendor = EAP_VENDOR_IETF; 984 next_type = EAP_TYPE_NONE; 985 eap_peap_phase2_init(sm, data, next_vendor, next_type); 986 return; 987 } 988 989 os_free(data->phase2_key); 990 if (data->phase2_method->getKey) { 991 data->phase2_key = data->phase2_method->getKey( 992 sm, data->phase2_priv, &data->phase2_key_len); 993 if (data->phase2_key == NULL) { 994 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey " 995 "failed"); 996 eap_peap_req_failure(sm, data); 997 eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF, 998 EAP_TYPE_NONE); 999 return; 1000 } 1001 } 1002 1003 switch (data->state) { 1004 case PHASE1_ID2: 1005 case PHASE2_ID: 1006 case PHASE2_SOH: 1007 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { 1008 wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 " 1009 "Identity not found in the user " 1010 "database", 1011 sm->identity, sm->identity_len); 1012 eap_peap_req_failure(sm, data); 1013 next_vendor = EAP_VENDOR_IETF; 1014 next_type = EAP_TYPE_NONE; 1015 break; 1016 } 1017 1018 #ifdef EAP_SERVER_TNC 1019 if (data->state != PHASE2_SOH && sm->tnc && 1020 data->peap_version == 0) { 1021 eap_peap_state(data, PHASE2_SOH); 1022 wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize " 1023 "TNC (NAP SOH)"); 1024 next_vendor = EAP_VENDOR_IETF; 1025 next_type = EAP_TYPE_NONE; 1026 break; 1027 } 1028 #endif /* EAP_SERVER_TNC */ 1029 1030 eap_peap_state(data, PHASE2_METHOD); 1031 next_vendor = sm->user->methods[0].vendor; 1032 next_type = sm->user->methods[0].method; 1033 sm->user_eap_method_index = 1; 1034 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type 0x%x", 1035 next_vendor, next_type); 1036 break; 1037 case PHASE2_METHOD: 1038 eap_peap_req_success(sm, data); 1039 next_vendor = EAP_VENDOR_IETF; 1040 next_type = EAP_TYPE_NONE; 1041 break; 1042 case FAILURE: 1043 break; 1044 default: 1045 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", 1046 __func__, data->state); 1047 break; 1048 } 1049 1050 eap_peap_phase2_init(sm, data, next_vendor, next_type); 1051 } 1052 1053 1054 static void eap_peap_process_phase2(struct eap_sm *sm, 1055 struct eap_peap_data *data, 1056 const struct wpabuf *respData, 1057 struct wpabuf *in_buf) 1058 { 1059 struct wpabuf *in_decrypted; 1060 const struct eap_hdr *hdr; 1061 size_t len; 1062 1063 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" 1064 " Phase 2", (unsigned long) wpabuf_len(in_buf)); 1065 1066 if (data->pending_phase2_resp) { 1067 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - " 1068 "skip decryption and use old data"); 1069 eap_peap_process_phase2_response(sm, data, 1070 data->pending_phase2_resp); 1071 wpabuf_free(data->pending_phase2_resp); 1072 data->pending_phase2_resp = NULL; 1073 return; 1074 } 1075 1076 in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, 1077 in_buf); 1078 if (in_decrypted == NULL) { 1079 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 " 1080 "data"); 1081 eap_peap_state(data, FAILURE); 1082 return; 1083 } 1084 1085 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", 1086 in_decrypted); 1087 1088 if (data->peap_version == 0 && data->state != PHASE2_TLV) { 1089 const struct eap_hdr *resp; 1090 struct eap_hdr *nhdr; 1091 struct wpabuf *nbuf = 1092 wpabuf_alloc(sizeof(struct eap_hdr) + 1093 wpabuf_len(in_decrypted)); 1094 if (nbuf == NULL) { 1095 wpabuf_free(in_decrypted); 1096 return; 1097 } 1098 1099 resp = wpabuf_head(respData); 1100 nhdr = wpabuf_put(nbuf, sizeof(*nhdr)); 1101 nhdr->code = resp->code; 1102 nhdr->identifier = resp->identifier; 1103 nhdr->length = host_to_be16(sizeof(struct eap_hdr) + 1104 wpabuf_len(in_decrypted)); 1105 wpabuf_put_buf(nbuf, in_decrypted); 1106 wpabuf_free(in_decrypted); 1107 1108 in_decrypted = nbuf; 1109 } 1110 1111 hdr = wpabuf_head(in_decrypted); 1112 if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) { 1113 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " 1114 "EAP frame (len=%lu)", 1115 (unsigned long) wpabuf_len(in_decrypted)); 1116 wpabuf_free(in_decrypted); 1117 eap_peap_req_failure(sm, data); 1118 return; 1119 } 1120 len = be_to_host16(hdr->length); 1121 if (len > wpabuf_len(in_decrypted)) { 1122 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " 1123 "Phase 2 EAP frame (len=%lu hdr->length=%lu)", 1124 (unsigned long) wpabuf_len(in_decrypted), 1125 (unsigned long) len); 1126 wpabuf_free(in_decrypted); 1127 eap_peap_req_failure(sm, data); 1128 return; 1129 } 1130 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " 1131 "identifier=%d length=%lu", hdr->code, hdr->identifier, 1132 (unsigned long) len); 1133 switch (hdr->code) { 1134 case EAP_CODE_RESPONSE: 1135 eap_peap_process_phase2_response(sm, data, in_decrypted); 1136 break; 1137 case EAP_CODE_SUCCESS: 1138 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); 1139 if (data->state == SUCCESS_REQ) { 1140 eap_peap_state(data, SUCCESS); 1141 eap_peap_valid_session(sm, data); 1142 } 1143 break; 1144 case EAP_CODE_FAILURE: 1145 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); 1146 eap_peap_state(data, FAILURE); 1147 break; 1148 default: 1149 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " 1150 "Phase 2 EAP header", hdr->code); 1151 break; 1152 } 1153 1154 wpabuf_free(in_decrypted); 1155 } 1156 1157 1158 static int eap_peap_process_version(struct eap_sm *sm, void *priv, 1159 int peer_version) 1160 { 1161 struct eap_peap_data *data = priv; 1162 1163 data->recv_version = peer_version; 1164 if (data->force_version >= 0 && peer_version != data->force_version) { 1165 wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced" 1166 " version (forced=%d peer=%d) - reject", 1167 data->force_version, peer_version); 1168 return -1; 1169 } 1170 if (peer_version < data->peap_version) { 1171 wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; " 1172 "use version %d", 1173 peer_version, data->peap_version, peer_version); 1174 data->peap_version = peer_version; 1175 } 1176 1177 return 0; 1178 } 1179 1180 1181 static void eap_peap_process_msg(struct eap_sm *sm, void *priv, 1182 const struct wpabuf *respData) 1183 { 1184 struct eap_peap_data *data = priv; 1185 1186 switch (data->state) { 1187 case PHASE1: 1188 if (eap_server_tls_phase1(sm, &data->ssl) < 0) { 1189 eap_peap_state(data, FAILURE); 1190 break; 1191 } 1192 break; 1193 case PHASE2_START: 1194 eap_peap_state(data, PHASE2_ID); 1195 eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF, 1196 EAP_TYPE_IDENTITY); 1197 break; 1198 case PHASE1_ID2: 1199 case PHASE2_ID: 1200 case PHASE2_METHOD: 1201 case PHASE2_SOH: 1202 case PHASE2_TLV: 1203 eap_peap_process_phase2(sm, data, respData, data->ssl.tls_in); 1204 break; 1205 case SUCCESS_REQ: 1206 eap_peap_state(data, SUCCESS); 1207 eap_peap_valid_session(sm, data); 1208 break; 1209 case FAILURE_REQ: 1210 eap_peap_state(data, FAILURE); 1211 break; 1212 default: 1213 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s", 1214 data->state, __func__); 1215 break; 1216 } 1217 } 1218 1219 1220 static void eap_peap_process(struct eap_sm *sm, void *priv, 1221 struct wpabuf *respData) 1222 { 1223 struct eap_peap_data *data = priv; 1224 const struct wpabuf *buf; 1225 const u8 *pos; 1226 u8 id_len; 1227 1228 if (eap_server_tls_process(sm, &data->ssl, respData, data, 1229 EAP_TYPE_PEAP, eap_peap_process_version, 1230 eap_peap_process_msg) < 0) { 1231 eap_peap_state(data, FAILURE); 1232 return; 1233 } 1234 1235 if (data->state == SUCCESS || 1236 !tls_connection_established(sm->ssl_ctx, data->ssl.conn) || 1237 !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) 1238 return; 1239 1240 buf = tls_connection_get_success_data(data->ssl.conn); 1241 if (!buf || wpabuf_len(buf) < 2) { 1242 wpa_printf(MSG_DEBUG, 1243 "EAP-PEAP: No success data in resumed session - reject attempt"); 1244 eap_peap_state(data, FAILURE); 1245 return; 1246 } 1247 1248 pos = wpabuf_head(buf); 1249 if (*pos != EAP_TYPE_PEAP) { 1250 wpa_printf(MSG_DEBUG, 1251 "EAP-PEAP: Resumed session for another EAP type (%u) - reject attempt", 1252 *pos); 1253 eap_peap_state(data, FAILURE); 1254 return; 1255 } 1256 1257 pos++; 1258 id_len = *pos++; 1259 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Identity from cached session", 1260 pos, id_len); 1261 os_free(sm->identity); 1262 sm->identity = os_malloc(id_len ? id_len : 1); 1263 if (!sm->identity) { 1264 sm->identity_len = 0; 1265 eap_peap_state(data, FAILURE); 1266 return; 1267 } 1268 1269 os_memcpy(sm->identity, pos, id_len); 1270 sm->identity_len = id_len; 1271 1272 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { 1273 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Phase2 Identity not found in the user database", 1274 sm->identity, sm->identity_len); 1275 eap_peap_state(data, FAILURE); 1276 return; 1277 } 1278 1279 wpa_printf(MSG_DEBUG, 1280 "EAP-PEAP: Resuming previous session - skip Phase2"); 1281 eap_peap_req_success(sm, data); 1282 if (data->state == SUCCESS_REQ) 1283 tls_connection_set_success_data_resumed(data->ssl.conn); 1284 } 1285 1286 1287 static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv) 1288 { 1289 struct eap_peap_data *data = priv; 1290 return data->state == SUCCESS || data->state == FAILURE; 1291 } 1292 1293 1294 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) 1295 { 1296 struct eap_peap_data *data = priv; 1297 u8 *eapKeyData; 1298 1299 if (data->state != SUCCESS) 1300 return NULL; 1301 1302 if (data->crypto_binding_used) { 1303 u8 csk[128]; 1304 /* 1305 * Note: It looks like Microsoft implementation requires null 1306 * termination for this label while the one used for deriving 1307 * IPMK|CMK did not use null termination. 1308 */ 1309 if (peap_prfplus(data->peap_version, data->ipmk, 40, 1310 "Session Key Generating Function", 1311 (u8 *) "\00", 1, csk, sizeof(csk)) < 0) 1312 return NULL; 1313 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); 1314 eapKeyData = os_malloc(EAP_TLS_KEY_LEN); 1315 if (eapKeyData) { 1316 os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN); 1317 *len = EAP_TLS_KEY_LEN; 1318 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", 1319 eapKeyData, EAP_TLS_KEY_LEN); 1320 } else { 1321 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive " 1322 "key"); 1323 } 1324 1325 return eapKeyData; 1326 } 1327 1328 /* TODO: PEAPv1 - different label in some cases */ 1329 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, 1330 "client EAP encryption", 1331 EAP_TLS_KEY_LEN); 1332 if (eapKeyData) { 1333 *len = EAP_TLS_KEY_LEN; 1334 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", 1335 eapKeyData, EAP_TLS_KEY_LEN); 1336 } else { 1337 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key"); 1338 } 1339 1340 return eapKeyData; 1341 } 1342 1343 1344 static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv) 1345 { 1346 struct eap_peap_data *data = priv; 1347 return data->state == SUCCESS; 1348 } 1349 1350 1351 static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 1352 { 1353 struct eap_peap_data *data = priv; 1354 1355 if (data->state != SUCCESS) 1356 return NULL; 1357 1358 return eap_server_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_PEAP, 1359 len); 1360 } 1361 1362 1363 int eap_server_peap_register(void) 1364 { 1365 struct eap_method *eap; 1366 1367 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 1368 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); 1369 if (eap == NULL) 1370 return -1; 1371 1372 eap->init = eap_peap_init; 1373 eap->reset = eap_peap_reset; 1374 eap->buildReq = eap_peap_buildReq; 1375 eap->check = eap_peap_check; 1376 eap->process = eap_peap_process; 1377 eap->isDone = eap_peap_isDone; 1378 eap->getKey = eap_peap_getKey; 1379 eap->isSuccess = eap_peap_isSuccess; 1380 eap->getSessionId = eap_peap_get_session_id; 1381 1382 return eap_server_method_register(eap); 1383 } 1384