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