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