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 36 static void eap_peap_reset(struct eap_sm *sm, void *priv); 37 38 39 struct 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 66 static 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 99 static 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 108 static 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 135 static 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 152 static 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 170 static 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 198 static 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 213 static 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 235 static 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 273 static 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 312 static 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 328 static 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 375 static 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 467 static 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 495 static 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 562 static 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 578 static 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 598 static 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 650 static 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 768 static 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 888 auth_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 898 static 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 1033 static 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 hdr = wpabuf_head(in_decrypted); 1068 1069 if (data->peap_version == 0 && data->state != PHASE2_TLV) { 1070 const struct eap_hdr *resp; 1071 struct eap_hdr *nhdr; 1072 struct wpabuf *nbuf = 1073 wpabuf_alloc(sizeof(struct eap_hdr) + 1074 wpabuf_len(in_decrypted)); 1075 if (nbuf == NULL) { 1076 wpabuf_free(in_decrypted); 1077 return; 1078 } 1079 1080 resp = wpabuf_head(respData); 1081 nhdr = wpabuf_put(nbuf, sizeof(*nhdr)); 1082 nhdr->code = resp->code; 1083 nhdr->identifier = resp->identifier; 1084 nhdr->length = host_to_be16(sizeof(struct eap_hdr) + 1085 wpabuf_len(in_decrypted)); 1086 wpabuf_put_buf(nbuf, in_decrypted); 1087 wpabuf_free(in_decrypted); 1088 1089 in_decrypted = nbuf; 1090 } else if (data->peap_version >= 2) { 1091 struct eap_tlv_hdr *tlv; 1092 struct wpabuf *nmsg; 1093 1094 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) { 1095 wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 " 1096 "EAP TLV"); 1097 wpabuf_free(in_decrypted); 1098 return; 1099 } 1100 tlv = wpabuf_mhead(in_decrypted); 1101 if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) != 1102 EAP_TLV_EAP_PAYLOAD_TLV) { 1103 wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV"); 1104 wpabuf_free(in_decrypted); 1105 return; 1106 } 1107 if (sizeof(*tlv) + be_to_host16(tlv->length) > 1108 wpabuf_len(in_decrypted)) { 1109 wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV " 1110 "length"); 1111 wpabuf_free(in_decrypted); 1112 return; 1113 } 1114 hdr = (struct eap_hdr *) (tlv + 1); 1115 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) { 1116 wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full " 1117 "EAP packet in EAP TLV"); 1118 wpabuf_free(in_decrypted); 1119 return; 1120 } 1121 1122 nmsg = wpabuf_alloc(be_to_host16(hdr->length)); 1123 if (nmsg == NULL) { 1124 wpabuf_free(in_decrypted); 1125 return; 1126 } 1127 1128 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length)); 1129 wpabuf_free(in_decrypted); 1130 in_decrypted = nmsg; 1131 } 1132 1133 hdr = wpabuf_head(in_decrypted); 1134 if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) { 1135 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " 1136 "EAP frame (len=%lu)", 1137 (unsigned long) wpabuf_len(in_decrypted)); 1138 wpabuf_free(in_decrypted); 1139 eap_peap_req_failure(sm, data); 1140 return; 1141 } 1142 len = be_to_host16(hdr->length); 1143 if (len > wpabuf_len(in_decrypted)) { 1144 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " 1145 "Phase 2 EAP frame (len=%lu hdr->length=%lu)", 1146 (unsigned long) wpabuf_len(in_decrypted), 1147 (unsigned long) len); 1148 wpabuf_free(in_decrypted); 1149 eap_peap_req_failure(sm, data); 1150 return; 1151 } 1152 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " 1153 "identifier=%d length=%lu", hdr->code, hdr->identifier, 1154 (unsigned long) len); 1155 switch (hdr->code) { 1156 case EAP_CODE_RESPONSE: 1157 eap_peap_process_phase2_response(sm, data, in_decrypted); 1158 break; 1159 case EAP_CODE_SUCCESS: 1160 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); 1161 if (data->state == SUCCESS_REQ) { 1162 eap_peap_state(data, SUCCESS); 1163 } 1164 break; 1165 case EAP_CODE_FAILURE: 1166 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); 1167 eap_peap_state(data, FAILURE); 1168 break; 1169 default: 1170 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " 1171 "Phase 2 EAP header", hdr->code); 1172 break; 1173 } 1174 1175 wpabuf_free(in_decrypted); 1176 } 1177 1178 1179 static int eap_peapv2_start_phase2(struct eap_sm *sm, 1180 struct eap_peap_data *data) 1181 { 1182 struct wpabuf *buf, *buf2; 1183 1184 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 " 1185 "payload in the same message"); 1186 eap_peap_state(data, PHASE1_ID2); 1187 if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY)) 1188 return -1; 1189 1190 /* TODO: which Id to use here? */ 1191 buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6); 1192 if (buf == NULL) 1193 return -1; 1194 1195 buf2 = eap_peapv2_tlv_eap_payload(buf); 1196 if (buf2 == NULL) 1197 return -1; 1198 1199 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2); 1200 1201 buf = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, 1202 buf2); 1203 wpabuf_free(buf2); 1204 1205 if (buf == NULL) { 1206 wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 " 1207 "data"); 1208 return -1; 1209 } 1210 1211 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request", 1212 buf); 1213 1214 /* Append TLS data into the pending buffer after the Server Finished */ 1215 if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(buf)) < 0) { 1216 wpabuf_free(buf); 1217 return -1; 1218 } 1219 wpabuf_put_buf(data->ssl.tls_out, buf); 1220 wpabuf_free(buf); 1221 1222 return 0; 1223 } 1224 1225 1226 static int eap_peap_process_version(struct eap_sm *sm, void *priv, 1227 int peer_version) 1228 { 1229 struct eap_peap_data *data = priv; 1230 1231 data->recv_version = peer_version; 1232 if (data->force_version >= 0 && peer_version != data->force_version) { 1233 wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced" 1234 " version (forced=%d peer=%d) - reject", 1235 data->force_version, peer_version); 1236 return -1; 1237 } 1238 if (peer_version < data->peap_version) { 1239 wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; " 1240 "use version %d", 1241 peer_version, data->peap_version, peer_version); 1242 data->peap_version = peer_version; 1243 } 1244 1245 return 0; 1246 } 1247 1248 1249 static void eap_peap_process_msg(struct eap_sm *sm, void *priv, 1250 const struct wpabuf *respData) 1251 { 1252 struct eap_peap_data *data = priv; 1253 1254 switch (data->state) { 1255 case PHASE1: 1256 if (eap_server_tls_phase1(sm, &data->ssl) < 0) { 1257 eap_peap_state(data, FAILURE); 1258 break; 1259 } 1260 1261 if (data->peap_version >= 2 && 1262 tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 1263 if (eap_peapv2_start_phase2(sm, data)) { 1264 eap_peap_state(data, FAILURE); 1265 break; 1266 } 1267 } 1268 break; 1269 case PHASE2_START: 1270 eap_peap_state(data, PHASE2_ID); 1271 eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY); 1272 break; 1273 case PHASE1_ID2: 1274 case PHASE2_ID: 1275 case PHASE2_METHOD: 1276 case PHASE2_SOH: 1277 case PHASE2_TLV: 1278 eap_peap_process_phase2(sm, data, respData, data->ssl.tls_in); 1279 break; 1280 case SUCCESS_REQ: 1281 eap_peap_state(data, SUCCESS); 1282 break; 1283 case FAILURE_REQ: 1284 eap_peap_state(data, FAILURE); 1285 break; 1286 default: 1287 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s", 1288 data->state, __func__); 1289 break; 1290 } 1291 } 1292 1293 1294 static void eap_peap_process(struct eap_sm *sm, void *priv, 1295 struct wpabuf *respData) 1296 { 1297 struct eap_peap_data *data = priv; 1298 if (eap_server_tls_process(sm, &data->ssl, respData, data, 1299 EAP_TYPE_PEAP, eap_peap_process_version, 1300 eap_peap_process_msg) < 0) 1301 eap_peap_state(data, FAILURE); 1302 } 1303 1304 1305 static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv) 1306 { 1307 struct eap_peap_data *data = priv; 1308 return data->state == SUCCESS || data->state == FAILURE; 1309 } 1310 1311 1312 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) 1313 { 1314 struct eap_peap_data *data = priv; 1315 u8 *eapKeyData; 1316 1317 if (data->state != SUCCESS) 1318 return NULL; 1319 1320 if (data->crypto_binding_used) { 1321 u8 csk[128]; 1322 /* 1323 * Note: It looks like Microsoft implementation requires null 1324 * termination for this label while the one used for deriving 1325 * IPMK|CMK did not use null termination. 1326 */ 1327 if (peap_prfplus(data->peap_version, data->ipmk, 40, 1328 "Session Key Generating Function", 1329 (u8 *) "\00", 1, csk, sizeof(csk)) < 0) 1330 return NULL; 1331 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); 1332 eapKeyData = os_malloc(EAP_TLS_KEY_LEN); 1333 if (eapKeyData) { 1334 os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN); 1335 *len = EAP_TLS_KEY_LEN; 1336 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", 1337 eapKeyData, EAP_TLS_KEY_LEN); 1338 } else { 1339 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive " 1340 "key"); 1341 } 1342 1343 return eapKeyData; 1344 } 1345 1346 /* TODO: PEAPv1 - different label in some cases */ 1347 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, 1348 "client EAP encryption", 1349 EAP_TLS_KEY_LEN); 1350 if (eapKeyData) { 1351 *len = EAP_TLS_KEY_LEN; 1352 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", 1353 eapKeyData, EAP_TLS_KEY_LEN); 1354 } else { 1355 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key"); 1356 } 1357 1358 return eapKeyData; 1359 } 1360 1361 1362 static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv) 1363 { 1364 struct eap_peap_data *data = priv; 1365 return data->state == SUCCESS; 1366 } 1367 1368 1369 int eap_server_peap_register(void) 1370 { 1371 struct eap_method *eap; 1372 int ret; 1373 1374 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 1375 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); 1376 if (eap == NULL) 1377 return -1; 1378 1379 eap->init = eap_peap_init; 1380 eap->reset = eap_peap_reset; 1381 eap->buildReq = eap_peap_buildReq; 1382 eap->check = eap_peap_check; 1383 eap->process = eap_peap_process; 1384 eap->isDone = eap_peap_isDone; 1385 eap->getKey = eap_peap_getKey; 1386 eap->isSuccess = eap_peap_isSuccess; 1387 1388 ret = eap_server_method_register(eap); 1389 if (ret) 1390 eap_server_method_free(eap); 1391 return ret; 1392 } 1393