eap_server_peap.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
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 if (peap_prfplus(data->peap_version, tk, 40, 355 "Inner Methods Compound Keys", 356 isk, sizeof(isk), imck, sizeof(imck)) < 0) { 357 os_free(tk); 358 return -1; 359 } 360 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", 361 imck, sizeof(imck)); 362 363 os_free(tk); 364 365 /* TODO: fast-connect: IPMK|CMK = TK */ 366 os_memcpy(data->ipmk, imck, 40); 367 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40); 368 os_memcpy(data->cmk, imck + 40, 20); 369 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20); 370 371 return 0; 372} 373 374 375static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm, 376 struct eap_peap_data *data, 377 u8 id) 378{ 379 struct wpabuf *buf, *encr_req; 380 size_t mlen; 381 382 mlen = 6; /* Result TLV */ 383 if (data->crypto_binding != NO_BINDING) 384 mlen += 60; /* Cryptobinding TLV */ 385#ifdef EAP_SERVER_TNC 386 if (data->soh_response) 387 mlen += wpabuf_len(data->soh_response); 388#endif /* EAP_SERVER_TNC */ 389 390 buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, mlen, 391 EAP_CODE_REQUEST, id); 392 if (buf == NULL) 393 return NULL; 394 395 wpabuf_put_u8(buf, 0x80); /* Mandatory */ 396 wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV); 397 /* Length */ 398 wpabuf_put_be16(buf, 2); 399 /* Status */ 400 wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ? 401 EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE); 402 403 if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS && 404 data->crypto_binding != NO_BINDING) { 405 u8 *mac; 406 u8 eap_type = EAP_TYPE_PEAP; 407 const u8 *addr[2]; 408 size_t len[2]; 409 u16 tlv_type; 410 411#ifdef EAP_SERVER_TNC 412 if (data->soh_response) { 413 wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH " 414 "Response TLV"); 415 wpabuf_put_buf(buf, data->soh_response); 416 wpabuf_free(data->soh_response); 417 data->soh_response = NULL; 418 } 419#endif /* EAP_SERVER_TNC */ 420 421 if (eap_peap_derive_cmk(sm, data) < 0 || 422 random_get_bytes(data->binding_nonce, 32)) { 423 wpabuf_free(buf); 424 return NULL; 425 } 426 427 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 428 addr[0] = wpabuf_put(buf, 0); 429 len[0] = 60; 430 addr[1] = &eap_type; 431 len[1] = 1; 432 433 tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; 434 if (data->peap_version >= 2) 435 tlv_type |= EAP_TLV_TYPE_MANDATORY; 436 wpabuf_put_be16(buf, tlv_type); 437 wpabuf_put_be16(buf, 56); 438 439 wpabuf_put_u8(buf, 0); /* Reserved */ 440 wpabuf_put_u8(buf, data->peap_version); /* Version */ 441 wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */ 442 wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */ 443 wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ 444 mac = wpabuf_put(buf, 20); /* Compound_MAC */ 445 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", 446 data->cmk, 20); 447 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", 448 addr[0], len[0]); 449 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", 450 addr[1], len[1]); 451 hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); 452 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", 453 mac, SHA1_MAC_LEN); 454 data->crypto_binding_sent = 1; 455 } 456 457 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data", 458 buf); 459 460 encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf); 461 wpabuf_free(buf); 462 463 return encr_req; 464} 465 466 467static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm, 468 struct eap_peap_data *data, 469 u8 id, int success) 470{ 471 struct wpabuf *encr_req, msgbuf; 472 size_t req_len; 473 struct eap_hdr *hdr; 474 475 req_len = sizeof(*hdr); 476 hdr = os_zalloc(req_len); 477 if (hdr == NULL) 478 return NULL; 479 480 hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; 481 hdr->identifier = id; 482 hdr->length = host_to_be16(req_len); 483 484 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", 485 (u8 *) hdr, req_len); 486 487 wpabuf_set(&msgbuf, hdr, req_len); 488 encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); 489 os_free(hdr); 490 491 return encr_req; 492} 493 494 495static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id) 496{ 497 struct eap_peap_data *data = priv; 498 499 if (data->ssl.state == FRAG_ACK) { 500 return eap_server_tls_build_ack(id, EAP_TYPE_PEAP, 501 data->peap_version); 502 } 503 504 if (data->ssl.state == WAIT_FRAG_ACK) { 505 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, 506 data->peap_version, id); 507 } 508 509 switch (data->state) { 510 case START: 511 return eap_peap_build_start(sm, data, id); 512 case PHASE1: 513 case PHASE1_ID2: 514 if (data->peap_version < 2 && 515 tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 516 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, " 517 "starting Phase2"); 518 eap_peap_state(data, PHASE2_START); 519 } 520 break; 521 case PHASE2_ID: 522 case PHASE2_METHOD: 523 wpabuf_free(data->ssl.tls_out); 524 data->ssl.tls_out_pos = 0; 525 data->ssl.tls_out = eap_peap_build_phase2_req(sm, data, id); 526 break; 527#ifdef EAP_SERVER_TNC 528 case PHASE2_SOH: 529 wpabuf_free(data->ssl.tls_out); 530 data->ssl.tls_out_pos = 0; 531 data->ssl.tls_out = eap_peap_build_phase2_soh(sm, data, id); 532 break; 533#endif /* EAP_SERVER_TNC */ 534 case PHASE2_TLV: 535 wpabuf_free(data->ssl.tls_out); 536 data->ssl.tls_out_pos = 0; 537 data->ssl.tls_out = eap_peap_build_phase2_tlv(sm, data, id); 538 break; 539 case SUCCESS_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 1); 544 break; 545 case FAILURE_REQ: 546 wpabuf_free(data->ssl.tls_out); 547 data->ssl.tls_out_pos = 0; 548 data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id, 549 0); 550 break; 551 default: 552 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", 553 __func__, data->state); 554 return NULL; 555 } 556 557 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, 558 data->peap_version, id); 559} 560 561 562static Boolean eap_peap_check(struct eap_sm *sm, void *priv, 563 struct wpabuf *respData) 564{ 565 const u8 *pos; 566 size_t len; 567 568 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len); 569 if (pos == NULL || len < 1) { 570 wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame"); 571 return TRUE; 572 } 573 574 return FALSE; 575} 576 577 578static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data, 579 EapType eap_type) 580{ 581 if (data->phase2_priv && data->phase2_method) { 582 data->phase2_method->reset(sm, data->phase2_priv); 583 data->phase2_method = NULL; 584 data->phase2_priv = NULL; 585 } 586 data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF, 587 eap_type); 588 if (!data->phase2_method) 589 return -1; 590 591 sm->init_phase2 = 1; 592 data->phase2_priv = data->phase2_method->init(sm); 593 sm->init_phase2 = 0; 594 return 0; 595} 596 597 598static int eap_tlv_validate_cryptobinding(struct eap_sm *sm, 599 struct eap_peap_data *data, 600 const u8 *crypto_tlv, 601 size_t crypto_tlv_len) 602{ 603 u8 buf[61], mac[SHA1_MAC_LEN]; 604 const u8 *pos; 605 606 if (crypto_tlv_len != 4 + 56) { 607 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " 608 "length %d", (int) crypto_tlv_len); 609 return -1; 610 } 611 612 pos = crypto_tlv; 613 pos += 4; /* TLV header */ 614 if (pos[1] != data->peap_version) { 615 wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " 616 "mismatch (was %d; expected %d)", 617 pos[1], data->peap_version); 618 return -1; 619 } 620 621 if (pos[3] != 1) { 622 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " 623 "SubType %d", pos[3]); 624 return -1; 625 } 626 pos += 4; 627 pos += 32; /* Nonce */ 628 629 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 630 os_memcpy(buf, crypto_tlv, 60); 631 os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ 632 buf[60] = EAP_TYPE_PEAP; 633 hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); 634 635 if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) { 636 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " 637 "cryptobinding TLV"); 638 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20); 639 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data", 640 buf, 61); 641 return -1; 642 } 643 644 wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); 645 646 return 0; 647} 648 649 650static void eap_peap_process_phase2_tlv(struct eap_sm *sm, 651 struct eap_peap_data *data, 652 struct wpabuf *in_data) 653{ 654 const u8 *pos; 655 size_t left; 656 const u8 *result_tlv = NULL, *crypto_tlv = NULL; 657 size_t result_tlv_len = 0, crypto_tlv_len = 0; 658 int tlv_type, mandatory, tlv_len; 659 660 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left); 661 if (pos == NULL) { 662 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header"); 663 return; 664 } 665 666 /* Parse TLVs */ 667 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left); 668 while (left >= 4) { 669 mandatory = !!(pos[0] & 0x80); 670 tlv_type = pos[0] & 0x3f; 671 tlv_type = (tlv_type << 8) | pos[1]; 672 tlv_len = ((int) pos[2] << 8) | pos[3]; 673 pos += 4; 674 left -= 4; 675 if ((size_t) tlv_len > left) { 676 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " 677 "(tlv_len=%d left=%lu)", tlv_len, 678 (unsigned long) left); 679 eap_peap_state(data, FAILURE); 680 return; 681 } 682 switch (tlv_type) { 683 case EAP_TLV_RESULT_TLV: 684 result_tlv = pos; 685 result_tlv_len = tlv_len; 686 break; 687 case EAP_TLV_CRYPTO_BINDING_TLV: 688 crypto_tlv = pos; 689 crypto_tlv_len = tlv_len; 690 break; 691 default: 692 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " 693 "%d%s", tlv_type, 694 mandatory ? " (mandatory)" : ""); 695 if (mandatory) { 696 eap_peap_state(data, FAILURE); 697 return; 698 } 699 /* Ignore this TLV, but process other TLVs */ 700 break; 701 } 702 703 pos += tlv_len; 704 left -= tlv_len; 705 } 706 if (left) { 707 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " 708 "Request (left=%lu)", (unsigned long) left); 709 eap_peap_state(data, FAILURE); 710 return; 711 } 712 713 /* Process supported TLVs */ 714 if (crypto_tlv && data->crypto_binding_sent) { 715 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", 716 crypto_tlv, crypto_tlv_len); 717 if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, 718 crypto_tlv_len + 4) < 0) { 719 eap_peap_state(data, FAILURE); 720 return; 721 } 722 data->crypto_binding_used = 1; 723 } else if (!crypto_tlv && data->crypto_binding_sent && 724 data->crypto_binding == REQUIRE_BINDING) { 725 wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); 726 eap_peap_state(data, FAILURE); 727 return; 728 } 729 730 if (result_tlv) { 731 int status; 732 const char *requested; 733 734 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV", 735 result_tlv, result_tlv_len); 736 if (result_tlv_len < 2) { 737 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV " 738 "(len=%lu)", 739 (unsigned long) result_tlv_len); 740 eap_peap_state(data, FAILURE); 741 return; 742 } 743 requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" : 744 "Failure"; 745 status = WPA_GET_BE16(result_tlv); 746 if (status == EAP_TLV_RESULT_SUCCESS) { 747 wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success " 748 "- requested %s", requested); 749 if (data->tlv_request == TLV_REQ_SUCCESS) 750 eap_peap_state(data, SUCCESS); 751 else 752 eap_peap_state(data, FAILURE); 753 754 } else if (status == EAP_TLV_RESULT_FAILURE) { 755 wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure " 756 "- requested %s", requested); 757 eap_peap_state(data, FAILURE); 758 } else { 759 wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result " 760 "Status %d", status); 761 eap_peap_state(data, FAILURE); 762 } 763 } 764} 765 766 767#ifdef EAP_SERVER_TNC 768static void eap_peap_process_phase2_soh(struct eap_sm *sm, 769 struct eap_peap_data *data, 770 struct wpabuf *in_data) 771{ 772 const u8 *pos, *vpos; 773 size_t left; 774 const u8 *soh_tlv = NULL; 775 size_t soh_tlv_len = 0; 776 int tlv_type, mandatory, tlv_len, vtlv_len; 777 u8 next_type; 778 u32 vendor_id; 779 780 pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left); 781 if (pos == NULL) { 782 wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP " 783 "Extensions Method header - skip TNC"); 784 goto auth_method; 785 } 786 787 /* Parse TLVs */ 788 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left); 789 while (left >= 4) { 790 mandatory = !!(pos[0] & 0x80); 791 tlv_type = pos[0] & 0x3f; 792 tlv_type = (tlv_type << 8) | pos[1]; 793 tlv_len = ((int) pos[2] << 8) | pos[3]; 794 pos += 4; 795 left -= 4; 796 if ((size_t) tlv_len > left) { 797 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " 798 "(tlv_len=%d left=%lu)", tlv_len, 799 (unsigned long) left); 800 eap_peap_state(data, FAILURE); 801 return; 802 } 803 switch (tlv_type) { 804 case EAP_TLV_VENDOR_SPECIFIC_TLV: 805 if (tlv_len < 4) { 806 wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short " 807 "vendor specific TLV (len=%d)", 808 (int) tlv_len); 809 eap_peap_state(data, FAILURE); 810 return; 811 } 812 813 vendor_id = WPA_GET_BE32(pos); 814 if (vendor_id != EAP_VENDOR_MICROSOFT) { 815 if (mandatory) { 816 eap_peap_state(data, FAILURE); 817 return; 818 } 819 break; 820 } 821 822 vpos = pos + 4; 823 mandatory = !!(vpos[0] & 0x80); 824 tlv_type = vpos[0] & 0x3f; 825 tlv_type = (tlv_type << 8) | vpos[1]; 826 vtlv_len = ((int) vpos[2] << 8) | vpos[3]; 827 vpos += 4; 828 if (vpos + vtlv_len > pos + left) { 829 wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV " 830 "underrun"); 831 eap_peap_state(data, FAILURE); 832 return; 833 } 834 835 if (tlv_type == 1) { 836 soh_tlv = vpos; 837 soh_tlv_len = vtlv_len; 838 break; 839 } 840 841 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV " 842 "Type %d%s", tlv_type, 843 mandatory ? " (mandatory)" : ""); 844 if (mandatory) { 845 eap_peap_state(data, FAILURE); 846 return; 847 } 848 /* Ignore this TLV, but process other TLVs */ 849 break; 850 default: 851 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " 852 "%d%s", tlv_type, 853 mandatory ? " (mandatory)" : ""); 854 if (mandatory) { 855 eap_peap_state(data, FAILURE); 856 return; 857 } 858 /* Ignore this TLV, but process other TLVs */ 859 break; 860 } 861 862 pos += tlv_len; 863 left -= tlv_len; 864 } 865 if (left) { 866 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " 867 "Request (left=%lu)", (unsigned long) left); 868 eap_peap_state(data, FAILURE); 869 return; 870 } 871 872 /* Process supported TLVs */ 873 if (soh_tlv) { 874 int failure = 0; 875 wpabuf_free(data->soh_response); 876 data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len, 877 &failure); 878 if (failure) { 879 eap_peap_state(data, FAILURE); 880 return; 881 } 882 } else { 883 wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received"); 884 eap_peap_state(data, FAILURE); 885 return; 886 } 887 888auth_method: 889 eap_peap_state(data, PHASE2_METHOD); 890 next_type = sm->user->methods[0].method; 891 sm->user_eap_method_index = 1; 892 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type); 893 eap_peap_phase2_init(sm, data, next_type); 894} 895#endif /* EAP_SERVER_TNC */ 896 897 898static void eap_peap_process_phase2_response(struct eap_sm *sm, 899 struct eap_peap_data *data, 900 struct wpabuf *in_data) 901{ 902 u8 next_type = EAP_TYPE_NONE; 903 const struct eap_hdr *hdr; 904 const u8 *pos; 905 size_t left; 906 907 if (data->state == PHASE2_TLV) { 908 eap_peap_process_phase2_tlv(sm, data, in_data); 909 return; 910 } 911 912#ifdef EAP_SERVER_TNC 913 if (data->state == PHASE2_SOH) { 914 eap_peap_process_phase2_soh(sm, data, in_data); 915 return; 916 } 917#endif /* EAP_SERVER_TNC */ 918 919 if (data->phase2_priv == NULL) { 920 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not " 921 "initialized?!", __func__); 922 return; 923 } 924 925 hdr = wpabuf_head(in_data); 926 pos = (const u8 *) (hdr + 1); 927 928 if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { 929 left = wpabuf_len(in_data) - sizeof(*hdr); 930 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; " 931 "allowed types", pos + 1, left - 1); 932 eap_sm_process_nak(sm, pos + 1, left - 1); 933 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && 934 sm->user->methods[sm->user_eap_method_index].method != 935 EAP_TYPE_NONE) { 936 next_type = sm->user->methods[ 937 sm->user_eap_method_index++].method; 938 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", 939 next_type); 940 } else { 941 eap_peap_req_failure(sm, data); 942 next_type = EAP_TYPE_NONE; 943 } 944 eap_peap_phase2_init(sm, data, next_type); 945 return; 946 } 947 948 if (data->phase2_method->check(sm, data->phase2_priv, in_data)) { 949 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to " 950 "ignore the packet"); 951 return; 952 } 953 954 data->phase2_method->process(sm, data->phase2_priv, in_data); 955 956 if (sm->method_pending == METHOD_PENDING_WAIT) { 957 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in " 958 "pending wait state - save decrypted response"); 959 wpabuf_free(data->pending_phase2_resp); 960 data->pending_phase2_resp = wpabuf_dup(in_data); 961 } 962 963 if (!data->phase2_method->isDone(sm, data->phase2_priv)) 964 return; 965 966 if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) { 967 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed"); 968 eap_peap_req_failure(sm, data); 969 next_type = EAP_TYPE_NONE; 970 eap_peap_phase2_init(sm, data, next_type); 971 return; 972 } 973 974 os_free(data->phase2_key); 975 if (data->phase2_method->getKey) { 976 data->phase2_key = data->phase2_method->getKey( 977 sm, data->phase2_priv, &data->phase2_key_len); 978 if (data->phase2_key == NULL) { 979 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey " 980 "failed"); 981 eap_peap_req_failure(sm, data); 982 eap_peap_phase2_init(sm, data, EAP_TYPE_NONE); 983 return; 984 } 985 } 986 987 switch (data->state) { 988 case PHASE1_ID2: 989 case PHASE2_ID: 990 case PHASE2_SOH: 991 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { 992 wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 " 993 "Identity not found in the user " 994 "database", 995 sm->identity, sm->identity_len); 996 eap_peap_req_failure(sm, data); 997 next_type = EAP_TYPE_NONE; 998 break; 999 } 1000 1001#ifdef EAP_SERVER_TNC 1002 if (data->state != PHASE2_SOH && sm->tnc && 1003 data->peap_version == 0) { 1004 eap_peap_state(data, PHASE2_SOH); 1005 wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize " 1006 "TNC (NAP SOH)"); 1007 next_type = EAP_TYPE_NONE; 1008 break; 1009 } 1010#endif /* EAP_SERVER_TNC */ 1011 1012 eap_peap_state(data, PHASE2_METHOD); 1013 next_type = sm->user->methods[0].method; 1014 sm->user_eap_method_index = 1; 1015 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type); 1016 break; 1017 case PHASE2_METHOD: 1018 eap_peap_req_success(sm, data); 1019 next_type = EAP_TYPE_NONE; 1020 break; 1021 case FAILURE: 1022 break; 1023 default: 1024 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", 1025 __func__, data->state); 1026 break; 1027 } 1028 1029 eap_peap_phase2_init(sm, data, next_type); 1030} 1031 1032 1033static void eap_peap_process_phase2(struct eap_sm *sm, 1034 struct eap_peap_data *data, 1035 const struct wpabuf *respData, 1036 struct wpabuf *in_buf) 1037{ 1038 struct wpabuf *in_decrypted; 1039 const struct eap_hdr *hdr; 1040 size_t len; 1041 1042 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" 1043 " Phase 2", (unsigned long) wpabuf_len(in_buf)); 1044 1045 if (data->pending_phase2_resp) { 1046 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - " 1047 "skip decryption and use old data"); 1048 eap_peap_process_phase2_response(sm, data, 1049 data->pending_phase2_resp); 1050 wpabuf_free(data->pending_phase2_resp); 1051 data->pending_phase2_resp = NULL; 1052 return; 1053 } 1054 1055 in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, 1056 in_buf); 1057 if (in_decrypted == NULL) { 1058 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 " 1059 "data"); 1060 eap_peap_state(data, FAILURE); 1061 return; 1062 } 1063 1064 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", 1065 in_decrypted); 1066 1067 if (data->peap_version == 0 && data->state != PHASE2_TLV) { 1068 const struct eap_hdr *resp; 1069 struct eap_hdr *nhdr; 1070 struct wpabuf *nbuf = 1071 wpabuf_alloc(sizeof(struct eap_hdr) + 1072 wpabuf_len(in_decrypted)); 1073 if (nbuf == NULL) { 1074 wpabuf_free(in_decrypted); 1075 return; 1076 } 1077 1078 resp = wpabuf_head(respData); 1079 nhdr = wpabuf_put(nbuf, sizeof(*nhdr)); 1080 nhdr->code = resp->code; 1081 nhdr->identifier = resp->identifier; 1082 nhdr->length = host_to_be16(sizeof(struct eap_hdr) + 1083 wpabuf_len(in_decrypted)); 1084 wpabuf_put_buf(nbuf, in_decrypted); 1085 wpabuf_free(in_decrypted); 1086 1087 in_decrypted = nbuf; 1088 } else if (data->peap_version >= 2) { 1089 struct eap_tlv_hdr *tlv; 1090 struct wpabuf *nmsg; 1091 1092 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) { 1093 wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 " 1094 "EAP TLV"); 1095 wpabuf_free(in_decrypted); 1096 return; 1097 } 1098 tlv = wpabuf_mhead(in_decrypted); 1099 if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) != 1100 EAP_TLV_EAP_PAYLOAD_TLV) { 1101 wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV"); 1102 wpabuf_free(in_decrypted); 1103 return; 1104 } 1105 if (sizeof(*tlv) + be_to_host16(tlv->length) > 1106 wpabuf_len(in_decrypted)) { 1107 wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV " 1108 "length"); 1109 wpabuf_free(in_decrypted); 1110 return; 1111 } 1112 hdr = (struct eap_hdr *) (tlv + 1); 1113 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) { 1114 wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full " 1115 "EAP packet in EAP TLV"); 1116 wpabuf_free(in_decrypted); 1117 return; 1118 } 1119 1120 nmsg = wpabuf_alloc(be_to_host16(hdr->length)); 1121 if (nmsg == NULL) { 1122 wpabuf_free(in_decrypted); 1123 return; 1124 } 1125 1126 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length)); 1127 wpabuf_free(in_decrypted); 1128 in_decrypted = nmsg; 1129 } 1130 1131 hdr = wpabuf_head(in_decrypted); 1132 if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) { 1133 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " 1134 "EAP frame (len=%lu)", 1135 (unsigned long) wpabuf_len(in_decrypted)); 1136 wpabuf_free(in_decrypted); 1137 eap_peap_req_failure(sm, data); 1138 return; 1139 } 1140 len = be_to_host16(hdr->length); 1141 if (len > wpabuf_len(in_decrypted)) { 1142 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " 1143 "Phase 2 EAP frame (len=%lu hdr->length=%lu)", 1144 (unsigned long) wpabuf_len(in_decrypted), 1145 (unsigned long) len); 1146 wpabuf_free(in_decrypted); 1147 eap_peap_req_failure(sm, data); 1148 return; 1149 } 1150 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " 1151 "identifier=%d length=%lu", hdr->code, hdr->identifier, 1152 (unsigned long) len); 1153 switch (hdr->code) { 1154 case EAP_CODE_RESPONSE: 1155 eap_peap_process_phase2_response(sm, data, in_decrypted); 1156 break; 1157 case EAP_CODE_SUCCESS: 1158 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); 1159 if (data->state == SUCCESS_REQ) { 1160 eap_peap_state(data, SUCCESS); 1161 } 1162 break; 1163 case EAP_CODE_FAILURE: 1164 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); 1165 eap_peap_state(data, FAILURE); 1166 break; 1167 default: 1168 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " 1169 "Phase 2 EAP header", hdr->code); 1170 break; 1171 } 1172 1173 wpabuf_free(in_decrypted); 1174} 1175 1176 1177static int eap_peapv2_start_phase2(struct eap_sm *sm, 1178 struct eap_peap_data *data) 1179{ 1180 struct wpabuf *buf, *buf2; 1181 1182 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 " 1183 "payload in the same message"); 1184 eap_peap_state(data, PHASE1_ID2); 1185 if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY)) 1186 return -1; 1187 1188 /* TODO: which Id to use here? */ 1189 buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6); 1190 if (buf == NULL) 1191 return -1; 1192 1193 buf2 = eap_peapv2_tlv_eap_payload(buf); 1194 if (buf2 == NULL) 1195 return -1; 1196 1197 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2); 1198 1199 buf = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, 1200 buf2); 1201 wpabuf_free(buf2); 1202 1203 if (buf == NULL) { 1204 wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 " 1205 "data"); 1206 return -1; 1207 } 1208 1209 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request", 1210 buf); 1211 1212 /* Append TLS data into the pending buffer after the Server Finished */ 1213 if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(buf)) < 0) { 1214 wpabuf_free(buf); 1215 return -1; 1216 } 1217 wpabuf_put_buf(data->ssl.tls_out, buf); 1218 wpabuf_free(buf); 1219 1220 return 0; 1221} 1222 1223 1224static int eap_peap_process_version(struct eap_sm *sm, void *priv, 1225 int peer_version) 1226{ 1227 struct eap_peap_data *data = priv; 1228 1229 data->recv_version = peer_version; 1230 if (data->force_version >= 0 && peer_version != data->force_version) { 1231 wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced" 1232 " version (forced=%d peer=%d) - reject", 1233 data->force_version, peer_version); 1234 return -1; 1235 } 1236 if (peer_version < data->peap_version) { 1237 wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; " 1238 "use version %d", 1239 peer_version, data->peap_version, peer_version); 1240 data->peap_version = peer_version; 1241 } 1242 1243 return 0; 1244} 1245 1246 1247static void eap_peap_process_msg(struct eap_sm *sm, void *priv, 1248 const struct wpabuf *respData) 1249{ 1250 struct eap_peap_data *data = priv; 1251 1252 switch (data->state) { 1253 case PHASE1: 1254 if (eap_server_tls_phase1(sm, &data->ssl) < 0) { 1255 eap_peap_state(data, FAILURE); 1256 break; 1257 } 1258 1259 if (data->peap_version >= 2 && 1260 tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 1261 if (eap_peapv2_start_phase2(sm, data)) { 1262 eap_peap_state(data, FAILURE); 1263 break; 1264 } 1265 } 1266 break; 1267 case PHASE2_START: 1268 eap_peap_state(data, PHASE2_ID); 1269 eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY); 1270 break; 1271 case PHASE1_ID2: 1272 case PHASE2_ID: 1273 case PHASE2_METHOD: 1274 case PHASE2_SOH: 1275 case PHASE2_TLV: 1276 eap_peap_process_phase2(sm, data, respData, data->ssl.tls_in); 1277 break; 1278 case SUCCESS_REQ: 1279 eap_peap_state(data, SUCCESS); 1280 break; 1281 case FAILURE_REQ: 1282 eap_peap_state(data, FAILURE); 1283 break; 1284 default: 1285 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s", 1286 data->state, __func__); 1287 break; 1288 } 1289} 1290 1291 1292static void eap_peap_process(struct eap_sm *sm, void *priv, 1293 struct wpabuf *respData) 1294{ 1295 struct eap_peap_data *data = priv; 1296 if (eap_server_tls_process(sm, &data->ssl, respData, data, 1297 EAP_TYPE_PEAP, eap_peap_process_version, 1298 eap_peap_process_msg) < 0) 1299 eap_peap_state(data, FAILURE); 1300} 1301 1302 1303static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv) 1304{ 1305 struct eap_peap_data *data = priv; 1306 return data->state == SUCCESS || data->state == FAILURE; 1307} 1308 1309 1310static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) 1311{ 1312 struct eap_peap_data *data = priv; 1313 u8 *eapKeyData; 1314 1315 if (data->state != SUCCESS) 1316 return NULL; 1317 1318 if (data->crypto_binding_used) { 1319 u8 csk[128]; 1320 /* 1321 * Note: It looks like Microsoft implementation requires null 1322 * termination for this label while the one used for deriving 1323 * IPMK|CMK did not use null termination. 1324 */ 1325 if (peap_prfplus(data->peap_version, data->ipmk, 40, 1326 "Session Key Generating Function", 1327 (u8 *) "\00", 1, csk, sizeof(csk)) < 0) 1328 return NULL; 1329 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); 1330 eapKeyData = os_malloc(EAP_TLS_KEY_LEN); 1331 if (eapKeyData) { 1332 os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN); 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 " 1338 "key"); 1339 } 1340 1341 return eapKeyData; 1342 } 1343 1344 /* TODO: PEAPv1 - different label in some cases */ 1345 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, 1346 "client EAP encryption", 1347 EAP_TLS_KEY_LEN); 1348 if (eapKeyData) { 1349 *len = EAP_TLS_KEY_LEN; 1350 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", 1351 eapKeyData, EAP_TLS_KEY_LEN); 1352 } else { 1353 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key"); 1354 } 1355 1356 return eapKeyData; 1357} 1358 1359 1360static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv) 1361{ 1362 struct eap_peap_data *data = priv; 1363 return data->state == SUCCESS; 1364} 1365 1366 1367int eap_server_peap_register(void) 1368{ 1369 struct eap_method *eap; 1370 int ret; 1371 1372 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 1373 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); 1374 if (eap == NULL) 1375 return -1; 1376 1377 eap->init = eap_peap_init; 1378 eap->reset = eap_peap_reset; 1379 eap->buildReq = eap_peap_buildReq; 1380 eap->check = eap_peap_check; 1381 eap->process = eap_peap_process; 1382 eap->isDone = eap_peap_isDone; 1383 eap->getKey = eap_peap_getKey; 1384 eap->isSuccess = eap_peap_isSuccess; 1385 1386 ret = eap_server_method_register(eap); 1387 if (ret) 1388 eap_server_method_free(eap); 1389 return ret; 1390} 1391