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