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