1/* 2 * EAP peer method: 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 "eap_common/eap_tlv_common.h" 15#include "eap_common/eap_peap_common.h" 16#include "eap_i.h" 17#include "eap_tls_common.h" 18#include "eap_config.h" 19#include "tncc.h" 20 21 22/* Maximum supported PEAP version 23 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt 24 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt 25 * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt 26 */ 27#define EAP_PEAP_VERSION 1 28 29 30static void eap_peap_deinit(struct eap_sm *sm, void *priv); 31 32 33struct eap_peap_data { 34 struct eap_ssl_data ssl; 35 36 int peap_version, force_peap_version, force_new_label; 37 38 const struct eap_method *phase2_method; 39 void *phase2_priv; 40 int phase2_success; 41 int phase2_eap_success; 42 int phase2_eap_started; 43 44 struct eap_method_type phase2_type; 45 struct eap_method_type *phase2_types; 46 size_t num_phase2_types; 47 48 int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner 49 * EAP-Success 50 * 1 = reply with tunneled EAP-Success to inner 51 * EAP-Success and expect AS to send outer 52 * (unencrypted) EAP-Success after this 53 * 2 = reply with PEAP/TLS ACK to inner 54 * EAP-Success and expect AS to send outer 55 * (unencrypted) EAP-Success after this */ 56 int resuming; /* starting a resumed session */ 57 int reauth; /* reauthentication */ 58 u8 *key_data; 59 u8 *session_id; 60 size_t id_len; 61 62 struct wpabuf *pending_phase2_req; 63 enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; 64 int crypto_binding_used; 65 u8 binding_nonce[32]; 66 u8 ipmk[40]; 67 u8 cmk[20]; 68 int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP) 69 * is enabled. */ 70}; 71 72 73static int eap_peap_parse_phase1(struct eap_peap_data *data, 74 const char *phase1) 75{ 76 const char *pos; 77 78 pos = os_strstr(phase1, "peapver="); 79 if (pos) { 80 data->force_peap_version = atoi(pos + 8); 81 data->peap_version = data->force_peap_version; 82 wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version %d", 83 data->force_peap_version); 84 } 85 86 if (os_strstr(phase1, "peaplabel=1")) { 87 data->force_new_label = 1; 88 wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for key " 89 "derivation"); 90 } 91 92 if (os_strstr(phase1, "peap_outer_success=0")) { 93 data->peap_outer_success = 0; 94 wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate authentication on " 95 "tunneled EAP-Success"); 96 } else if (os_strstr(phase1, "peap_outer_success=1")) { 97 data->peap_outer_success = 1; 98 wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled EAP-Success " 99 "after receiving tunneled EAP-Success"); 100 } else if (os_strstr(phase1, "peap_outer_success=2")) { 101 data->peap_outer_success = 2; 102 wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK after " 103 "receiving tunneled EAP-Success"); 104 } 105 106 if (os_strstr(phase1, "crypto_binding=0")) { 107 data->crypto_binding = NO_BINDING; 108 wpa_printf(MSG_DEBUG, "EAP-PEAP: Do not use cryptobinding"); 109 } else if (os_strstr(phase1, "crypto_binding=1")) { 110 data->crypto_binding = OPTIONAL_BINDING; 111 wpa_printf(MSG_DEBUG, "EAP-PEAP: Optional cryptobinding"); 112 } else if (os_strstr(phase1, "crypto_binding=2")) { 113 data->crypto_binding = REQUIRE_BINDING; 114 wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding"); 115 } 116 117#ifdef EAP_TNC 118 if (os_strstr(phase1, "tnc=soh2")) { 119 data->soh = 2; 120 wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled"); 121 } else if (os_strstr(phase1, "tnc=soh1")) { 122 data->soh = 1; 123 wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 1 enabled"); 124 } else if (os_strstr(phase1, "tnc=soh")) { 125 data->soh = 2; 126 wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled"); 127 } 128#endif /* EAP_TNC */ 129 130 return 0; 131} 132 133 134static void * eap_peap_init(struct eap_sm *sm) 135{ 136 struct eap_peap_data *data; 137 struct eap_peer_config *config = eap_get_config(sm); 138 139 data = os_zalloc(sizeof(*data)); 140 if (data == NULL) 141 return NULL; 142 sm->peap_done = FALSE; 143 data->peap_version = EAP_PEAP_VERSION; 144 data->force_peap_version = -1; 145 data->peap_outer_success = 2; 146 data->crypto_binding = OPTIONAL_BINDING; 147 148 if (config && config->phase1 && 149 eap_peap_parse_phase1(data, config->phase1) < 0) { 150 eap_peap_deinit(sm, data); 151 return NULL; 152 } 153 154 if (eap_peer_select_phase2_methods(config, "auth=", 155 &data->phase2_types, 156 &data->num_phase2_types) < 0) { 157 eap_peap_deinit(sm, data); 158 return NULL; 159 } 160 161 data->phase2_type.vendor = EAP_VENDOR_IETF; 162 data->phase2_type.method = EAP_TYPE_NONE; 163 164 if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_PEAP)) { 165 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); 166 eap_peap_deinit(sm, data); 167 return NULL; 168 } 169 170 return data; 171} 172 173 174static void eap_peap_deinit(struct eap_sm *sm, void *priv) 175{ 176 struct eap_peap_data *data = priv; 177 if (data == NULL) 178 return; 179 if (data->phase2_priv && data->phase2_method) 180 data->phase2_method->deinit(sm, data->phase2_priv); 181 os_free(data->phase2_types); 182 eap_peer_tls_ssl_deinit(sm, &data->ssl); 183 os_free(data->key_data); 184 os_free(data->session_id); 185 wpabuf_free(data->pending_phase2_req); 186 os_free(data); 187} 188 189 190/** 191 * eap_tlv_build_nak - Build EAP-TLV NAK message 192 * @id: EAP identifier for the header 193 * @nak_type: TLV type (EAP_TLV_*) 194 * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure 195 * 196 * This function builds an EAP-TLV NAK message. The caller is responsible for 197 * freeing the returned buffer. 198 */ 199static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type) 200{ 201 struct wpabuf *msg; 202 203 msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10, 204 EAP_CODE_RESPONSE, id); 205 if (msg == NULL) 206 return NULL; 207 208 wpabuf_put_u8(msg, 0x80); /* Mandatory */ 209 wpabuf_put_u8(msg, EAP_TLV_NAK_TLV); 210 wpabuf_put_be16(msg, 6); /* Length */ 211 wpabuf_put_be32(msg, 0); /* Vendor-Id */ 212 wpabuf_put_be16(msg, nak_type); /* NAK-Type */ 213 214 return msg; 215} 216 217 218static int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data, 219 u8 *isk, size_t isk_len) 220{ 221 u8 *key; 222 size_t key_len; 223 224 os_memset(isk, 0, isk_len); 225 if (data->phase2_method == NULL || data->phase2_priv == NULL || 226 data->phase2_method->isKeyAvailable == NULL || 227 data->phase2_method->getKey == NULL) 228 return 0; 229 230 if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) || 231 (key = data->phase2_method->getKey(sm, data->phase2_priv, 232 &key_len)) == NULL) { 233 wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not get key material " 234 "from Phase 2"); 235 return -1; 236 } 237 238 if (key_len > isk_len) 239 key_len = isk_len; 240 os_memcpy(isk, key, key_len); 241 os_free(key); 242 243 return 0; 244} 245 246 247static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) 248{ 249 u8 *tk; 250 u8 isk[32], imck[60]; 251 252 /* 253 * Tunnel key (TK) is the first 60 octets of the key generated by 254 * phase 1 of PEAP (based on TLS). 255 */ 256 tk = data->key_data; 257 if (tk == NULL) 258 return -1; 259 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); 260 261 if (data->reauth && 262 tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { 263 /* Fast-connect: IPMK|CMK = TK */ 264 os_memcpy(data->ipmk, tk, 40); 265 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK", 266 data->ipmk, 40); 267 os_memcpy(data->cmk, tk + 40, 20); 268 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK", 269 data->cmk, 20); 270 return 0; 271 } 272 273 if (eap_peap_get_isk(sm, data, isk, sizeof(isk)) < 0) 274 return -1; 275 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk)); 276 277 /* 278 * IPMK Seed = "Inner Methods Compound Keys" | ISK 279 * TempKey = First 40 octets of TK 280 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60) 281 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space 282 * in the end of the label just before ISK; is that just a typo?) 283 */ 284 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); 285 if (peap_prfplus(data->peap_version, tk, 40, 286 "Inner Methods Compound Keys", 287 isk, sizeof(isk), imck, sizeof(imck)) < 0) 288 return -1; 289 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", 290 imck, sizeof(imck)); 291 292 os_memcpy(data->ipmk, imck, 40); 293 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40); 294 os_memcpy(data->cmk, imck + 40, 20); 295 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20); 296 297 return 0; 298} 299 300 301static int eap_tlv_add_cryptobinding(struct eap_sm *sm, 302 struct eap_peap_data *data, 303 struct wpabuf *buf) 304{ 305 u8 *mac; 306 u8 eap_type = EAP_TYPE_PEAP; 307 const u8 *addr[2]; 308 size_t len[2]; 309 u16 tlv_type; 310 311 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 312 addr[0] = wpabuf_put(buf, 0); 313 len[0] = 60; 314 addr[1] = &eap_type; 315 len[1] = 1; 316 317 tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; 318 if (data->peap_version >= 2) 319 tlv_type |= EAP_TLV_TYPE_MANDATORY; 320 wpabuf_put_be16(buf, tlv_type); 321 wpabuf_put_be16(buf, 56); 322 323 wpabuf_put_u8(buf, 0); /* Reserved */ 324 wpabuf_put_u8(buf, data->peap_version); /* Version */ 325 wpabuf_put_u8(buf, data->peap_version); /* RecvVersion */ 326 wpabuf_put_u8(buf, 1); /* SubType: 0 = Request, 1 = Response */ 327 wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ 328 mac = wpabuf_put(buf, 20); /* Compound_MAC */ 329 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20); 330 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", 331 addr[0], len[0]); 332 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", 333 addr[1], len[1]); 334 hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); 335 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN); 336 data->crypto_binding_used = 1; 337 338 return 0; 339} 340 341 342/** 343 * eap_tlv_build_result - Build EAP-TLV Result message 344 * @id: EAP identifier for the header 345 * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE) 346 * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure 347 * 348 * This function builds an EAP-TLV Result message. The caller is responsible 349 * for freeing the returned buffer. 350 */ 351static struct wpabuf * eap_tlv_build_result(struct eap_sm *sm, 352 struct eap_peap_data *data, 353 int crypto_tlv_used, 354 int id, u16 status) 355{ 356 struct wpabuf *msg; 357 size_t len; 358 359 if (data->crypto_binding == NO_BINDING) 360 crypto_tlv_used = 0; 361 362 len = 6; 363 if (crypto_tlv_used) 364 len += 60; /* Cryptobinding TLV */ 365 msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len, 366 EAP_CODE_RESPONSE, id); 367 if (msg == NULL) 368 return NULL; 369 370 wpabuf_put_u8(msg, 0x80); /* Mandatory */ 371 wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV); 372 wpabuf_put_be16(msg, 2); /* Length */ 373 wpabuf_put_be16(msg, status); /* Status */ 374 375 if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) { 376 wpabuf_free(msg); 377 return NULL; 378 } 379 380 return msg; 381} 382 383 384static int eap_tlv_validate_cryptobinding(struct eap_sm *sm, 385 struct eap_peap_data *data, 386 const u8 *crypto_tlv, 387 size_t crypto_tlv_len) 388{ 389 u8 buf[61], mac[SHA1_MAC_LEN]; 390 const u8 *pos; 391 392 if (eap_peap_derive_cmk(sm, data) < 0) { 393 wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK"); 394 return -1; 395 } 396 397 if (crypto_tlv_len != 4 + 56) { 398 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " 399 "length %d", (int) crypto_tlv_len); 400 return -1; 401 } 402 403 pos = crypto_tlv; 404 pos += 4; /* TLV header */ 405 if (pos[1] != data->peap_version) { 406 wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " 407 "mismatch (was %d; expected %d)", 408 pos[1], data->peap_version); 409 return -1; 410 } 411 412 if (pos[3] != 0) { 413 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " 414 "SubType %d", pos[3]); 415 return -1; 416 } 417 pos += 4; 418 os_memcpy(data->binding_nonce, pos, 32); 419 pos += 32; /* Nonce */ 420 421 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 422 os_memcpy(buf, crypto_tlv, 60); 423 os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ 424 buf[60] = EAP_TYPE_PEAP; 425 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Compound_MAC data", 426 buf, sizeof(buf)); 427 hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); 428 429 if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) { 430 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " 431 "cryptobinding TLV"); 432 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received MAC", 433 pos, SHA1_MAC_LEN); 434 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Expected MAC", 435 mac, SHA1_MAC_LEN); 436 return -1; 437 } 438 439 wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); 440 441 return 0; 442} 443 444 445/** 446 * eap_tlv_process - Process a received EAP-TLV message and generate a response 447 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 448 * @ret: Return values from EAP request validation and processing 449 * @req: EAP-TLV request to be processed. The caller must have validated that 450 * the buffer is large enough to contain full request (hdr->length bytes) and 451 * that the EAP type is EAP_TYPE_TLV. 452 * @resp: Buffer to return a pointer to the allocated response message. This 453 * field should be initialized to %NULL before the call. The value will be 454 * updated if a response message is generated. The caller is responsible for 455 * freeing the allocated message. 456 * @force_failure: Force negotiation to fail 457 * Returns: 0 on success, -1 on failure 458 */ 459static int eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data, 460 struct eap_method_ret *ret, 461 const struct wpabuf *req, struct wpabuf **resp, 462 int force_failure) 463{ 464 size_t left, tlv_len; 465 const u8 *pos; 466 const u8 *result_tlv = NULL, *crypto_tlv = NULL; 467 size_t result_tlv_len = 0, crypto_tlv_len = 0; 468 int tlv_type, mandatory; 469 470 /* Parse TLVs */ 471 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left); 472 if (pos == NULL) 473 return -1; 474 wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left); 475 while (left >= 4) { 476 mandatory = !!(pos[0] & 0x80); 477 tlv_type = WPA_GET_BE16(pos) & 0x3fff; 478 pos += 2; 479 tlv_len = WPA_GET_BE16(pos); 480 pos += 2; 481 left -= 4; 482 if (tlv_len > left) { 483 wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun " 484 "(tlv_len=%lu left=%lu)", 485 (unsigned long) tlv_len, 486 (unsigned long) left); 487 return -1; 488 } 489 switch (tlv_type) { 490 case EAP_TLV_RESULT_TLV: 491 result_tlv = pos; 492 result_tlv_len = tlv_len; 493 break; 494 case EAP_TLV_CRYPTO_BINDING_TLV: 495 crypto_tlv = pos; 496 crypto_tlv_len = tlv_len; 497 break; 498 default: 499 wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type " 500 "%d%s", tlv_type, 501 mandatory ? " (mandatory)" : ""); 502 if (mandatory) { 503 /* NAK TLV and ignore all TLVs in this packet. 504 */ 505 *resp = eap_tlv_build_nak(eap_get_id(req), 506 tlv_type); 507 return *resp == NULL ? -1 : 0; 508 } 509 /* Ignore this TLV, but process other TLVs */ 510 break; 511 } 512 513 pos += tlv_len; 514 left -= tlv_len; 515 } 516 if (left) { 517 wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in " 518 "Request (left=%lu)", (unsigned long) left); 519 return -1; 520 } 521 522 /* Process supported TLVs */ 523 if (crypto_tlv && data->crypto_binding != NO_BINDING) { 524 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", 525 crypto_tlv, crypto_tlv_len); 526 if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, 527 crypto_tlv_len + 4) < 0) { 528 if (result_tlv == NULL) 529 return -1; 530 force_failure = 1; 531 crypto_tlv = NULL; /* do not include Cryptobinding TLV 532 * in response, if the received 533 * cryptobinding was invalid. */ 534 } 535 } else if (!crypto_tlv && data->crypto_binding == REQUIRE_BINDING) { 536 wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); 537 return -1; 538 } 539 540 if (result_tlv) { 541 int status, resp_status; 542 wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV", 543 result_tlv, result_tlv_len); 544 if (result_tlv_len < 2) { 545 wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV " 546 "(len=%lu)", 547 (unsigned long) result_tlv_len); 548 return -1; 549 } 550 status = WPA_GET_BE16(result_tlv); 551 if (status == EAP_TLV_RESULT_SUCCESS) { 552 wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success " 553 "- EAP-TLV/Phase2 Completed"); 554 if (force_failure) { 555 wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure" 556 " - force failed Phase 2"); 557 resp_status = EAP_TLV_RESULT_FAILURE; 558 ret->decision = DECISION_FAIL; 559 } else { 560 resp_status = EAP_TLV_RESULT_SUCCESS; 561 ret->decision = DECISION_UNCOND_SUCC; 562 } 563 } else if (status == EAP_TLV_RESULT_FAILURE) { 564 wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure"); 565 resp_status = EAP_TLV_RESULT_FAILURE; 566 ret->decision = DECISION_FAIL; 567 } else { 568 wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result " 569 "Status %d", status); 570 resp_status = EAP_TLV_RESULT_FAILURE; 571 ret->decision = DECISION_FAIL; 572 } 573 ret->methodState = METHOD_DONE; 574 575 *resp = eap_tlv_build_result(sm, data, crypto_tlv != NULL, 576 eap_get_id(req), resp_status); 577 } 578 579 return 0; 580} 581 582 583static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf) 584{ 585 struct wpabuf *e; 586 struct eap_tlv_hdr *tlv; 587 588 if (buf == NULL) 589 return NULL; 590 591 /* Encapsulate EAP packet in EAP-Payload TLV */ 592 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV"); 593 e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf)); 594 if (e == NULL) { 595 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory " 596 "for TLV encapsulation"); 597 wpabuf_free(buf); 598 return NULL; 599 } 600 tlv = wpabuf_put(e, sizeof(*tlv)); 601 tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | 602 EAP_TLV_EAP_PAYLOAD_TLV); 603 tlv->length = host_to_be16(wpabuf_len(buf)); 604 wpabuf_put_buf(e, buf); 605 wpabuf_free(buf); 606 return e; 607} 608 609 610static int eap_peap_phase2_request(struct eap_sm *sm, 611 struct eap_peap_data *data, 612 struct eap_method_ret *ret, 613 struct wpabuf *req, 614 struct wpabuf **resp) 615{ 616 struct eap_hdr *hdr = wpabuf_mhead(req); 617 size_t len = be_to_host16(hdr->length); 618 u8 *pos; 619 struct eap_method_ret iret; 620 struct eap_peer_config *config = eap_get_config(sm); 621 622 if (len <= sizeof(struct eap_hdr)) { 623 wpa_printf(MSG_INFO, "EAP-PEAP: too short " 624 "Phase 2 request (len=%lu)", (unsigned long) len); 625 return -1; 626 } 627 pos = (u8 *) (hdr + 1); 628 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos); 629 switch (*pos) { 630 case EAP_TYPE_IDENTITY: 631 *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); 632 break; 633 case EAP_TYPE_TLV: 634 os_memset(&iret, 0, sizeof(iret)); 635 if (eap_tlv_process(sm, data, &iret, req, resp, 636 data->phase2_eap_started && 637 !data->phase2_eap_success)) { 638 ret->methodState = METHOD_DONE; 639 ret->decision = DECISION_FAIL; 640 return -1; 641 } 642 if (iret.methodState == METHOD_DONE || 643 iret.methodState == METHOD_MAY_CONT) { 644 ret->methodState = iret.methodState; 645 ret->decision = iret.decision; 646 data->phase2_success = 1; 647 } 648 break; 649 case EAP_TYPE_EXPANDED: 650#ifdef EAP_TNC 651 if (data->soh) { 652 const u8 *epos; 653 size_t eleft; 654 655 epos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, 656 req, &eleft); 657 if (epos) { 658 struct wpabuf *buf; 659 wpa_printf(MSG_DEBUG, 660 "EAP-PEAP: SoH EAP Extensions"); 661 buf = tncc_process_soh_request(data->soh, 662 epos, eleft); 663 if (buf) { 664 *resp = eap_msg_alloc( 665 EAP_VENDOR_MICROSOFT, 0x21, 666 wpabuf_len(buf), 667 EAP_CODE_RESPONSE, 668 hdr->identifier); 669 if (*resp == NULL) { 670 ret->methodState = METHOD_DONE; 671 ret->decision = DECISION_FAIL; 672 return -1; 673 } 674 wpabuf_put_buf(*resp, buf); 675 wpabuf_free(buf); 676 break; 677 } 678 } 679 } 680#endif /* EAP_TNC */ 681 /* fall through */ 682 default: 683 if (data->phase2_type.vendor == EAP_VENDOR_IETF && 684 data->phase2_type.method == EAP_TYPE_NONE) { 685 size_t i; 686 for (i = 0; i < data->num_phase2_types; i++) { 687 if (data->phase2_types[i].vendor != 688 EAP_VENDOR_IETF || 689 data->phase2_types[i].method != *pos) 690 continue; 691 692 data->phase2_type.vendor = 693 data->phase2_types[i].vendor; 694 data->phase2_type.method = 695 data->phase2_types[i].method; 696 wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected " 697 "Phase 2 EAP vendor %d method %d", 698 data->phase2_type.vendor, 699 data->phase2_type.method); 700 break; 701 } 702 } 703 if (*pos != data->phase2_type.method || 704 *pos == EAP_TYPE_NONE) { 705 if (eap_peer_tls_phase2_nak(data->phase2_types, 706 data->num_phase2_types, 707 hdr, resp)) 708 return -1; 709 return 0; 710 } 711 712 if (data->phase2_priv == NULL) { 713 data->phase2_method = eap_peer_get_eap_method( 714 data->phase2_type.vendor, 715 data->phase2_type.method); 716 if (data->phase2_method) { 717 sm->init_phase2 = 1; 718 data->phase2_priv = 719 data->phase2_method->init(sm); 720 sm->init_phase2 = 0; 721 } 722 } 723 if (data->phase2_priv == NULL || data->phase2_method == NULL) { 724 wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize " 725 "Phase 2 EAP method %d", *pos); 726 ret->methodState = METHOD_DONE; 727 ret->decision = DECISION_FAIL; 728 return -1; 729 } 730 data->phase2_eap_started = 1; 731 os_memset(&iret, 0, sizeof(iret)); 732 *resp = data->phase2_method->process(sm, data->phase2_priv, 733 &iret, req); 734 if ((iret.methodState == METHOD_DONE || 735 iret.methodState == METHOD_MAY_CONT) && 736 (iret.decision == DECISION_UNCOND_SUCC || 737 iret.decision == DECISION_COND_SUCC)) { 738 data->phase2_eap_success = 1; 739 data->phase2_success = 1; 740 } 741 break; 742 } 743 744 if (*resp == NULL && 745 (config->pending_req_identity || config->pending_req_password || 746 config->pending_req_otp || config->pending_req_new_password)) { 747 wpabuf_free(data->pending_phase2_req); 748 data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); 749 } 750 751 return 0; 752} 753 754 755static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data, 756 struct eap_method_ret *ret, 757 const struct eap_hdr *req, 758 const struct wpabuf *in_data, 759 struct wpabuf **out_data) 760{ 761 struct wpabuf *in_decrypted = NULL; 762 int res, skip_change = 0; 763 struct eap_hdr *hdr, *rhdr; 764 struct wpabuf *resp = NULL; 765 size_t len; 766 767 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" 768 " Phase 2", (unsigned long) wpabuf_len(in_data)); 769 770 if (data->pending_phase2_req) { 771 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - " 772 "skip decryption and use old data"); 773 /* Clear TLS reassembly state. */ 774 eap_peer_tls_reset_input(&data->ssl); 775 in_decrypted = data->pending_phase2_req; 776 data->pending_phase2_req = NULL; 777 skip_change = 1; 778 goto continue_req; 779 } 780 781 if (wpabuf_len(in_data) == 0 && sm->workaround && 782 data->phase2_success) { 783 /* 784 * Cisco ACS seems to be using TLS ACK to terminate 785 * EAP-PEAPv0/GTC. Try to reply with TLS ACK. 786 */ 787 wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but " 788 "expected data - acknowledge with TLS ACK since " 789 "Phase 2 has been completed"); 790 ret->decision = DECISION_COND_SUCC; 791 ret->methodState = METHOD_DONE; 792 return 1; 793 } else if (wpabuf_len(in_data) == 0) { 794 /* Received TLS ACK - requesting more fragments */ 795 return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, 796 data->peap_version, 797 req->identifier, NULL, out_data); 798 } 799 800 res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); 801 if (res) 802 return res; 803 804continue_req: 805 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", 806 in_decrypted); 807 808 hdr = wpabuf_mhead(in_decrypted); 809 if (wpabuf_len(in_decrypted) == 5 && hdr->code == EAP_CODE_REQUEST && 810 be_to_host16(hdr->length) == 5 && 811 eap_get_type(in_decrypted) == EAP_TYPE_IDENTITY) { 812 /* At least FreeRADIUS seems to send full EAP header with 813 * EAP Request Identity */ 814 skip_change = 1; 815 } 816 if (wpabuf_len(in_decrypted) >= 5 && hdr->code == EAP_CODE_REQUEST && 817 eap_get_type(in_decrypted) == EAP_TYPE_TLV) { 818 skip_change = 1; 819 } 820 821 if (data->peap_version == 0 && !skip_change) { 822 struct eap_hdr *nhdr; 823 struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) + 824 wpabuf_len(in_decrypted)); 825 if (nmsg == NULL) { 826 wpabuf_free(in_decrypted); 827 return 0; 828 } 829 nhdr = wpabuf_put(nmsg, sizeof(*nhdr)); 830 wpabuf_put_buf(nmsg, in_decrypted); 831 nhdr->code = req->code; 832 nhdr->identifier = req->identifier; 833 nhdr->length = host_to_be16(sizeof(struct eap_hdr) + 834 wpabuf_len(in_decrypted)); 835 836 wpabuf_free(in_decrypted); 837 in_decrypted = nmsg; 838 } 839 840 if (data->peap_version >= 2) { 841 struct eap_tlv_hdr *tlv; 842 struct wpabuf *nmsg; 843 844 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) { 845 wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 " 846 "EAP TLV"); 847 wpabuf_free(in_decrypted); 848 return 0; 849 } 850 tlv = wpabuf_mhead(in_decrypted); 851 if ((be_to_host16(tlv->tlv_type) & 0x3fff) != 852 EAP_TLV_EAP_PAYLOAD_TLV) { 853 wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV"); 854 wpabuf_free(in_decrypted); 855 return 0; 856 } 857 if (sizeof(*tlv) + be_to_host16(tlv->length) > 858 wpabuf_len(in_decrypted)) { 859 wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV " 860 "length"); 861 wpabuf_free(in_decrypted); 862 return 0; 863 } 864 hdr = (struct eap_hdr *) (tlv + 1); 865 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) { 866 wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full " 867 "EAP packet in EAP TLV"); 868 wpabuf_free(in_decrypted); 869 return 0; 870 } 871 872 nmsg = wpabuf_alloc(be_to_host16(hdr->length)); 873 if (nmsg == NULL) { 874 wpabuf_free(in_decrypted); 875 return 0; 876 } 877 878 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length)); 879 wpabuf_free(in_decrypted); 880 in_decrypted = nmsg; 881 } 882 883 hdr = wpabuf_mhead(in_decrypted); 884 if (wpabuf_len(in_decrypted) < sizeof(*hdr)) { 885 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " 886 "EAP frame (len=%lu)", 887 (unsigned long) wpabuf_len(in_decrypted)); 888 wpabuf_free(in_decrypted); 889 return 0; 890 } 891 len = be_to_host16(hdr->length); 892 if (len > wpabuf_len(in_decrypted)) { 893 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " 894 "Phase 2 EAP frame (len=%lu hdr->length=%lu)", 895 (unsigned long) wpabuf_len(in_decrypted), 896 (unsigned long) len); 897 wpabuf_free(in_decrypted); 898 return 0; 899 } 900 if (len < wpabuf_len(in_decrypted)) { 901 wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has " 902 "shorter length than full decrypted data " 903 "(%lu < %lu)", 904 (unsigned long) len, 905 (unsigned long) wpabuf_len(in_decrypted)); 906 } 907 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " 908 "identifier=%d length=%lu", hdr->code, hdr->identifier, 909 (unsigned long) len); 910 switch (hdr->code) { 911 case EAP_CODE_REQUEST: 912 if (eap_peap_phase2_request(sm, data, ret, in_decrypted, 913 &resp)) { 914 wpabuf_free(in_decrypted); 915 wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request " 916 "processing failed"); 917 return 0; 918 } 919 break; 920 case EAP_CODE_SUCCESS: 921 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); 922 if (data->peap_version == 1) { 923 /* EAP-Success within TLS tunnel is used to indicate 924 * shutdown of the TLS channel. The authentication has 925 * been completed. */ 926 if (data->phase2_eap_started && 927 !data->phase2_eap_success) { 928 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 " 929 "Success used to indicate success, " 930 "but Phase 2 EAP was not yet " 931 "completed successfully"); 932 ret->methodState = METHOD_DONE; 933 ret->decision = DECISION_FAIL; 934 wpabuf_free(in_decrypted); 935 return 0; 936 } 937 wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - " 938 "EAP-Success within TLS tunnel - " 939 "authentication completed"); 940 ret->decision = DECISION_UNCOND_SUCC; 941 ret->methodState = METHOD_DONE; 942 data->phase2_success = 1; 943 if (data->peap_outer_success == 2) { 944 wpabuf_free(in_decrypted); 945 wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK " 946 "to finish authentication"); 947 return 1; 948 } else if (data->peap_outer_success == 1) { 949 /* Reply with EAP-Success within the TLS 950 * channel to complete the authentication. */ 951 resp = wpabuf_alloc(sizeof(struct eap_hdr)); 952 if (resp) { 953 rhdr = wpabuf_put(resp, sizeof(*rhdr)); 954 rhdr->code = EAP_CODE_SUCCESS; 955 rhdr->identifier = hdr->identifier; 956 rhdr->length = 957 host_to_be16(sizeof(*rhdr)); 958 } 959 } else { 960 /* No EAP-Success expected for Phase 1 (outer, 961 * unencrypted auth), so force EAP state 962 * machine to SUCCESS state. */ 963 sm->peap_done = TRUE; 964 } 965 } else { 966 /* FIX: ? */ 967 } 968 break; 969 case EAP_CODE_FAILURE: 970 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); 971 ret->decision = DECISION_FAIL; 972 ret->methodState = METHOD_MAY_CONT; 973 ret->allowNotifications = FALSE; 974 /* Reply with EAP-Failure within the TLS channel to complete 975 * failure reporting. */ 976 resp = wpabuf_alloc(sizeof(struct eap_hdr)); 977 if (resp) { 978 rhdr = wpabuf_put(resp, sizeof(*rhdr)); 979 rhdr->code = EAP_CODE_FAILURE; 980 rhdr->identifier = hdr->identifier; 981 rhdr->length = host_to_be16(sizeof(*rhdr)); 982 } 983 break; 984 default: 985 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " 986 "Phase 2 EAP header", hdr->code); 987 break; 988 } 989 990 wpabuf_free(in_decrypted); 991 992 if (resp) { 993 int skip_change2 = 0; 994 struct wpabuf *rmsg, buf; 995 996 wpa_hexdump_buf_key(MSG_DEBUG, 997 "EAP-PEAP: Encrypting Phase 2 data", resp); 998 /* PEAP version changes */ 999 if (data->peap_version >= 2) { 1000 resp = eap_peapv2_tlv_eap_payload(resp); 1001 if (resp == NULL) 1002 return -1; 1003 } 1004 if (wpabuf_len(resp) >= 5 && 1005 wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE && 1006 eap_get_type(resp) == EAP_TYPE_TLV) 1007 skip_change2 = 1; 1008 rmsg = resp; 1009 if (data->peap_version == 0 && !skip_change2) { 1010 wpabuf_set(&buf, wpabuf_head_u8(resp) + 1011 sizeof(struct eap_hdr), 1012 wpabuf_len(resp) - sizeof(struct eap_hdr)); 1013 rmsg = &buf; 1014 } 1015 1016 if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, 1017 data->peap_version, req->identifier, 1018 rmsg, out_data)) { 1019 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt " 1020 "a Phase 2 frame"); 1021 } 1022 wpabuf_free(resp); 1023 } 1024 1025 return 0; 1026} 1027 1028 1029static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, 1030 struct eap_method_ret *ret, 1031 const struct wpabuf *reqData) 1032{ 1033 const struct eap_hdr *req; 1034 size_t left; 1035 int res; 1036 u8 flags, id; 1037 struct wpabuf *resp; 1038 const u8 *pos; 1039 struct eap_peap_data *data = priv; 1040 1041 pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret, 1042 reqData, &left, &flags); 1043 if (pos == NULL) 1044 return NULL; 1045 req = wpabuf_head(reqData); 1046 id = req->identifier; 1047 1048 if (flags & EAP_TLS_FLAGS_START) { 1049 wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own " 1050 "ver=%d)", flags & EAP_TLS_VERSION_MASK, 1051 data->peap_version); 1052 if ((flags & EAP_TLS_VERSION_MASK) < data->peap_version) 1053 data->peap_version = flags & EAP_TLS_VERSION_MASK; 1054 if (data->force_peap_version >= 0 && 1055 data->force_peap_version != data->peap_version) { 1056 wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select " 1057 "forced PEAP version %d", 1058 data->force_peap_version); 1059 ret->methodState = METHOD_DONE; 1060 ret->decision = DECISION_FAIL; 1061 ret->allowNotifications = FALSE; 1062 return NULL; 1063 } 1064 wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d", 1065 data->peap_version); 1066 left = 0; /* make sure that this frame is empty, even though it 1067 * should always be, anyway */ 1068 } 1069 1070 resp = NULL; 1071 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && 1072 !data->resuming) { 1073 struct wpabuf msg; 1074 wpabuf_set(&msg, pos, left); 1075 res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); 1076 } else { 1077 res = eap_peer_tls_process_helper(sm, &data->ssl, 1078 EAP_TYPE_PEAP, 1079 data->peap_version, id, pos, 1080 left, &resp); 1081 1082 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 1083 char *label; 1084 wpa_printf(MSG_DEBUG, 1085 "EAP-PEAP: TLS done, proceed to Phase 2"); 1086 os_free(data->key_data); 1087 /* draft-josefsson-ppext-eap-tls-eap-05.txt 1088 * specifies that PEAPv1 would use "client PEAP 1089 * encryption" as the label. However, most existing 1090 * PEAPv1 implementations seem to be using the old 1091 * label, "client EAP encryption", instead. Use the old 1092 * label by default, but allow it to be configured with 1093 * phase1 parameter peaplabel=1. */ 1094 if (data->peap_version > 1 || data->force_new_label) 1095 label = "client PEAP encryption"; 1096 else 1097 label = "client EAP encryption"; 1098 wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in " 1099 "key derivation", label); 1100 data->key_data = 1101 eap_peer_tls_derive_key(sm, &data->ssl, label, 1102 EAP_TLS_KEY_LEN); 1103 if (data->key_data) { 1104 wpa_hexdump_key(MSG_DEBUG, 1105 "EAP-PEAP: Derived key", 1106 data->key_data, 1107 EAP_TLS_KEY_LEN); 1108 } else { 1109 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to " 1110 "derive key"); 1111 } 1112 1113 os_free(data->session_id); 1114 data->session_id = 1115 eap_peer_tls_derive_session_id(sm, &data->ssl, 1116 EAP_TYPE_PEAP, 1117 &data->id_len); 1118 if (data->session_id) { 1119 wpa_hexdump(MSG_DEBUG, 1120 "EAP-PEAP: Derived Session-Id", 1121 data->session_id, data->id_len); 1122 } else { 1123 wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to " 1124 "derive Session-Id"); 1125 } 1126 1127 if (sm->workaround && data->resuming) { 1128 /* 1129 * At least few RADIUS servers (Aegis v1.1.6; 1130 * but not v1.1.4; and Cisco ACS) seem to be 1131 * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco 1132 * ACS) session resumption with outer 1133 * EAP-Success. This does not seem to follow 1134 * draft-josefsson-pppext-eap-tls-eap-05.txt 1135 * section 4.2, so only allow this if EAP 1136 * workarounds are enabled. 1137 */ 1138 wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - " 1139 "allow outer EAP-Success to " 1140 "terminate PEAP resumption"); 1141 ret->decision = DECISION_COND_SUCC; 1142 data->phase2_success = 1; 1143 } 1144 1145 data->resuming = 0; 1146 } 1147 1148 if (res == 2) { 1149 struct wpabuf msg; 1150 /* 1151 * Application data included in the handshake message. 1152 */ 1153 wpabuf_free(data->pending_phase2_req); 1154 data->pending_phase2_req = resp; 1155 resp = NULL; 1156 wpabuf_set(&msg, pos, left); 1157 res = eap_peap_decrypt(sm, data, ret, req, &msg, 1158 &resp); 1159 } 1160 } 1161 1162 if (ret->methodState == METHOD_DONE) { 1163 ret->allowNotifications = FALSE; 1164 } 1165 1166 if (res == 1) { 1167 wpabuf_free(resp); 1168 return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP, 1169 data->peap_version); 1170 } 1171 1172 return resp; 1173} 1174 1175 1176static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) 1177{ 1178 struct eap_peap_data *data = priv; 1179 return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && 1180 data->phase2_success; 1181} 1182 1183 1184static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv) 1185{ 1186 struct eap_peap_data *data = priv; 1187 wpabuf_free(data->pending_phase2_req); 1188 data->pending_phase2_req = NULL; 1189 data->crypto_binding_used = 0; 1190} 1191 1192 1193static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv) 1194{ 1195 struct eap_peap_data *data = priv; 1196 os_free(data->key_data); 1197 data->key_data = NULL; 1198 os_free(data->session_id); 1199 data->session_id = NULL; 1200 if (eap_peer_tls_reauth_init(sm, &data->ssl)) { 1201 os_free(data); 1202 return NULL; 1203 } 1204 if (data->phase2_priv && data->phase2_method && 1205 data->phase2_method->init_for_reauth) 1206 data->phase2_method->init_for_reauth(sm, data->phase2_priv); 1207 data->phase2_success = 0; 1208 data->phase2_eap_success = 0; 1209 data->phase2_eap_started = 0; 1210 data->resuming = 1; 1211 data->reauth = 1; 1212 sm->peap_done = FALSE; 1213 return priv; 1214} 1215 1216 1217static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf, 1218 size_t buflen, int verbose) 1219{ 1220 struct eap_peap_data *data = priv; 1221 int len, ret; 1222 1223 len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); 1224 if (data->phase2_method) { 1225 ret = os_snprintf(buf + len, buflen - len, 1226 "EAP-PEAPv%d Phase2 method=%s\n", 1227 data->peap_version, 1228 data->phase2_method->name); 1229 if (ret < 0 || (size_t) ret >= buflen - len) 1230 return len; 1231 len += ret; 1232 } 1233 return len; 1234} 1235 1236 1237static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv) 1238{ 1239 struct eap_peap_data *data = priv; 1240 return data->key_data != NULL && data->phase2_success; 1241} 1242 1243 1244static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) 1245{ 1246 struct eap_peap_data *data = priv; 1247 u8 *key; 1248 1249 if (data->key_data == NULL || !data->phase2_success) 1250 return NULL; 1251 1252 key = os_malloc(EAP_TLS_KEY_LEN); 1253 if (key == NULL) 1254 return NULL; 1255 1256 *len = EAP_TLS_KEY_LEN; 1257 1258 if (data->crypto_binding_used) { 1259 u8 csk[128]; 1260 /* 1261 * Note: It looks like Microsoft implementation requires null 1262 * termination for this label while the one used for deriving 1263 * IPMK|CMK did not use null termination. 1264 */ 1265 if (peap_prfplus(data->peap_version, data->ipmk, 40, 1266 "Session Key Generating Function", 1267 (u8 *) "\00", 1, csk, sizeof(csk)) < 0) { 1268 os_free(key); 1269 return NULL; 1270 } 1271 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); 1272 os_memcpy(key, csk, EAP_TLS_KEY_LEN); 1273 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", 1274 key, EAP_TLS_KEY_LEN); 1275 } else 1276 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); 1277 1278 return key; 1279} 1280 1281 1282static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 1283{ 1284 struct eap_peap_data *data = priv; 1285 u8 *id; 1286 1287 if (data->session_id == NULL || !data->phase2_success) 1288 return NULL; 1289 1290 id = os_malloc(data->id_len); 1291 if (id == NULL) 1292 return NULL; 1293 1294 *len = data->id_len; 1295 os_memcpy(id, data->session_id, data->id_len); 1296 1297 return id; 1298} 1299 1300 1301int eap_peer_peap_register(void) 1302{ 1303 struct eap_method *eap; 1304 int ret; 1305 1306 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 1307 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); 1308 if (eap == NULL) 1309 return -1; 1310 1311 eap->init = eap_peap_init; 1312 eap->deinit = eap_peap_deinit; 1313 eap->process = eap_peap_process; 1314 eap->isKeyAvailable = eap_peap_isKeyAvailable; 1315 eap->getKey = eap_peap_getKey; 1316 eap->get_status = eap_peap_get_status; 1317 eap->has_reauth_data = eap_peap_has_reauth_data; 1318 eap->deinit_for_reauth = eap_peap_deinit_for_reauth; 1319 eap->init_for_reauth = eap_peap_init_for_reauth; 1320 eap->getSessionId = eap_peap_get_session_id; 1321 1322 ret = eap_peer_method_register(eap); 1323 if (ret) 1324 eap_peer_method_free(eap); 1325 return ret; 1326} 1327