00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "includes.h"
00016
00017 #include "common.h"
00018 #include "crypto/sha1.h"
00019 #include "crypto/tls.h"
00020 #include "eap_common/eap_tlv_common.h"
00021 #include "eap_common/eap_peap_common.h"
00022 #include "eap_i.h"
00023 #include "eap_tls_common.h"
00024 #include "eap_config.h"
00025 #include "tncc.h"
00026
00027
00028
00029
00030
00031
00032
00033 #define EAP_PEAP_VERSION 1
00034
00035
00036 static void eap_peap_deinit(struct eap_sm *sm, void *priv);
00037
00038
00039 struct eap_peap_data {
00040 struct eap_ssl_data ssl;
00041
00042 int peap_version, force_peap_version, force_new_label;
00043
00044 const struct eap_method *phase2_method;
00045 void *phase2_priv;
00046 int phase2_success;
00047 int phase2_eap_success;
00048 int phase2_eap_started;
00049
00050 struct eap_method_type phase2_type;
00051 struct eap_method_type *phase2_types;
00052 size_t num_phase2_types;
00053
00054 int peap_outer_success;
00055
00056
00057
00058
00059
00060
00061
00062 int resuming;
00063 int reauth;
00064 u8 *key_data;
00065
00066 struct wpabuf *pending_phase2_req;
00067 enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
00068 int crypto_binding_used;
00069 u8 binding_nonce[32];
00070 u8 ipmk[40];
00071 u8 cmk[20];
00072 int soh;
00073
00074 };
00075
00076
00077 static int eap_peap_parse_phase1(struct eap_peap_data *data,
00078 const char *phase1)
00079 {
00080 const char *pos;
00081
00082 pos = os_strstr(phase1, "peapver=");
00083 if (pos) {
00084 data->force_peap_version = atoi(pos + 8);
00085 data->peap_version = data->force_peap_version;
00086 wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version %d",
00087 data->force_peap_version);
00088 }
00089
00090 if (os_strstr(phase1, "peaplabel=1")) {
00091 data->force_new_label = 1;
00092 wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for key "
00093 "derivation");
00094 }
00095
00096 if (os_strstr(phase1, "peap_outer_success=0")) {
00097 data->peap_outer_success = 0;
00098 wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate authentication on "
00099 "tunneled EAP-Success");
00100 } else if (os_strstr(phase1, "peap_outer_success=1")) {
00101 data->peap_outer_success = 1;
00102 wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled EAP-Success "
00103 "after receiving tunneled EAP-Success");
00104 } else if (os_strstr(phase1, "peap_outer_success=2")) {
00105 data->peap_outer_success = 2;
00106 wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK after "
00107 "receiving tunneled EAP-Success");
00108 }
00109
00110 if (os_strstr(phase1, "crypto_binding=0")) {
00111 data->crypto_binding = NO_BINDING;
00112 wpa_printf(MSG_DEBUG, "EAP-PEAP: Do not use cryptobinding");
00113 } else if (os_strstr(phase1, "crypto_binding=1")) {
00114 data->crypto_binding = OPTIONAL_BINDING;
00115 wpa_printf(MSG_DEBUG, "EAP-PEAP: Optional cryptobinding");
00116 } else if (os_strstr(phase1, "crypto_binding=2")) {
00117 data->crypto_binding = REQUIRE_BINDING;
00118 wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding");
00119 }
00120
00121 #ifdef EAP_TNC
00122 if (os_strstr(phase1, "tnc=soh2")) {
00123 data->soh = 2;
00124 wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled");
00125 } else if (os_strstr(phase1, "tnc=soh1")) {
00126 data->soh = 1;
00127 wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 1 enabled");
00128 } else if (os_strstr(phase1, "tnc=soh")) {
00129 data->soh = 2;
00130 wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled");
00131 }
00132 #endif
00133
00134 return 0;
00135 }
00136
00137
00138 static void * eap_peap_init(struct eap_sm *sm)
00139 {
00140 struct eap_peap_data *data;
00141 struct eap_peer_config *config = eap_get_config(sm);
00142
00143 data = os_zalloc(sizeof(*data));
00144 if (data == NULL)
00145 return NULL;
00146 sm->peap_done = FALSE;
00147 data->peap_version = EAP_PEAP_VERSION;
00148 data->force_peap_version = -1;
00149 data->peap_outer_success = 2;
00150 data->crypto_binding = OPTIONAL_BINDING;
00151
00152 if (config && config->phase1 &&
00153 eap_peap_parse_phase1(data, config->phase1) < 0) {
00154 eap_peap_deinit(sm, data);
00155 return NULL;
00156 }
00157
00158 if (eap_peer_select_phase2_methods(config, "auth=",
00159 &data->phase2_types,
00160 &data->num_phase2_types) < 0) {
00161 eap_peap_deinit(sm, data);
00162 return NULL;
00163 }
00164
00165 data->phase2_type.vendor = EAP_VENDOR_IETF;
00166 data->phase2_type.method = EAP_TYPE_NONE;
00167
00168 if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
00169 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
00170 eap_peap_deinit(sm, data);
00171 return NULL;
00172 }
00173
00174 return data;
00175 }
00176
00177
00178 static void eap_peap_deinit(struct eap_sm *sm, void *priv)
00179 {
00180 struct eap_peap_data *data = priv;
00181 if (data == NULL)
00182 return;
00183 if (data->phase2_priv && data->phase2_method)
00184 data->phase2_method->deinit(sm, data->phase2_priv);
00185 os_free(data->phase2_types);
00186 eap_peer_tls_ssl_deinit(sm, &data->ssl);
00187 os_free(data->key_data);
00188 wpabuf_free(data->pending_phase2_req);
00189 os_free(data);
00190 }
00191
00192
00202 static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type)
00203 {
00204 struct wpabuf *msg;
00205
00206 msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10,
00207 EAP_CODE_RESPONSE, id);
00208 if (msg == NULL)
00209 return NULL;
00210
00211 wpabuf_put_u8(msg, 0x80);
00212 wpabuf_put_u8(msg, EAP_TLV_NAK_TLV);
00213 wpabuf_put_be16(msg, 6);
00214 wpabuf_put_be32(msg, 0);
00215 wpabuf_put_be16(msg, nak_type);
00216
00217 return msg;
00218 }
00219
00220
00221 static int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data,
00222 u8 *isk, size_t isk_len)
00223 {
00224 u8 *key;
00225 size_t key_len;
00226
00227 os_memset(isk, 0, isk_len);
00228 if (data->phase2_method == NULL || data->phase2_priv == NULL ||
00229 data->phase2_method->isKeyAvailable == NULL ||
00230 data->phase2_method->getKey == NULL)
00231 return 0;
00232
00233 if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) ||
00234 (key = data->phase2_method->getKey(sm, data->phase2_priv,
00235 &key_len)) == NULL) {
00236 wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not get key material "
00237 "from Phase 2");
00238 return -1;
00239 }
00240
00241 if (key_len > isk_len)
00242 key_len = isk_len;
00243 os_memcpy(isk, key, key_len);
00244 os_free(key);
00245
00246 return 0;
00247 }
00248
00249
00250 static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
00251 {
00252 u8 *tk;
00253 u8 isk[32], imck[60];
00254
00255
00256
00257
00258
00259 tk = data->key_data;
00260 if (tk == NULL)
00261 return -1;
00262 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
00263
00264 if (data->reauth &&
00265 tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
00266
00267 os_memcpy(data->ipmk, tk, 40);
00268 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK",
00269 data->ipmk, 40);
00270 os_memcpy(data->cmk, tk + 40, 20);
00271 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK",
00272 data->cmk, 20);
00273 return 0;
00274 }
00275
00276 if (eap_peap_get_isk(sm, data, isk, sizeof(isk)) < 0)
00277 return -1;
00278 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
00279
00280
00281
00282
00283
00284
00285
00286
00287 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
00288 peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys",
00289 isk, sizeof(isk), imck, sizeof(imck));
00290 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
00291 imck, sizeof(imck));
00292
00293 os_memcpy(data->ipmk, imck, 40);
00294 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
00295 os_memcpy(data->cmk, imck + 40, 20);
00296 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
00297
00298 return 0;
00299 }
00300
00301
00302 static int eap_tlv_add_cryptobinding(struct eap_sm *sm,
00303 struct eap_peap_data *data,
00304 struct wpabuf *buf)
00305 {
00306 u8 *mac;
00307 u8 eap_type = EAP_TYPE_PEAP;
00308 const u8 *addr[2];
00309 size_t len[2];
00310 u16 tlv_type;
00311
00312
00313 addr[0] = wpabuf_put(buf, 0);
00314 len[0] = 60;
00315 addr[1] = &eap_type;
00316 len[1] = 1;
00317
00318 tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
00319 if (data->peap_version >= 2)
00320 tlv_type |= EAP_TLV_TYPE_MANDATORY;
00321 wpabuf_put_be16(buf, tlv_type);
00322 wpabuf_put_be16(buf, 56);
00323
00324 wpabuf_put_u8(buf, 0);
00325 wpabuf_put_u8(buf, data->peap_version);
00326 wpabuf_put_u8(buf, data->peap_version);
00327 wpabuf_put_u8(buf, 1);
00328 wpabuf_put_data(buf, data->binding_nonce, 32);
00329 mac = wpabuf_put(buf, 20);
00330 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20);
00331 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
00332 addr[0], len[0]);
00333 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
00334 addr[1], len[1]);
00335 hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
00336 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN);
00337 data->crypto_binding_used = 1;
00338
00339 return 0;
00340 }
00341
00342
00352 static struct wpabuf * eap_tlv_build_result(struct eap_sm *sm,
00353 struct eap_peap_data *data,
00354 int crypto_tlv_used,
00355 int id, u16 status)
00356 {
00357 struct wpabuf *msg;
00358 size_t len;
00359
00360 if (data->crypto_binding == NO_BINDING)
00361 crypto_tlv_used = 0;
00362
00363 len = 6;
00364 if (crypto_tlv_used)
00365 len += 60;
00366 msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len,
00367 EAP_CODE_RESPONSE, id);
00368 if (msg == NULL)
00369 return NULL;
00370
00371 wpabuf_put_u8(msg, 0x80);
00372 wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV);
00373 wpabuf_put_be16(msg, 2);
00374 wpabuf_put_be16(msg, status);
00375
00376 if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) {
00377 wpabuf_free(msg);
00378 return NULL;
00379 }
00380
00381 return msg;
00382 }
00383
00384
00385 static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
00386 struct eap_peap_data *data,
00387 const u8 *crypto_tlv,
00388 size_t crypto_tlv_len)
00389 {
00390 u8 buf[61], mac[SHA1_MAC_LEN];
00391 const u8 *pos;
00392
00393 if (eap_peap_derive_cmk(sm, data) < 0) {
00394 wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK");
00395 return -1;
00396 }
00397
00398 if (crypto_tlv_len != 4 + 56) {
00399 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
00400 "length %d", (int) crypto_tlv_len);
00401 return -1;
00402 }
00403
00404 pos = crypto_tlv;
00405 pos += 4;
00406 if (pos[1] != data->peap_version) {
00407 wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
00408 "mismatch (was %d; expected %d)",
00409 pos[1], data->peap_version);
00410 return -1;
00411 }
00412
00413 if (pos[3] != 0) {
00414 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
00415 "SubType %d", pos[3]);
00416 return -1;
00417 }
00418 pos += 4;
00419 os_memcpy(data->binding_nonce, pos, 32);
00420 pos += 32;
00421
00422
00423 os_memcpy(buf, crypto_tlv, 60);
00424 os_memset(buf + 4 + 4 + 32, 0, 20);
00425 buf[60] = EAP_TYPE_PEAP;
00426 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Compound_MAC data",
00427 buf, sizeof(buf));
00428 hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
00429
00430 if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) {
00431 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
00432 "cryptobinding TLV");
00433 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received MAC",
00434 pos, SHA1_MAC_LEN);
00435 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Expected MAC",
00436 mac, SHA1_MAC_LEN);
00437 return -1;
00438 }
00439
00440 wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
00441
00442 return 0;
00443 }
00444
00445
00460 static int eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data,
00461 struct eap_method_ret *ret,
00462 const struct wpabuf *req, struct wpabuf **resp,
00463 int force_failure)
00464 {
00465 size_t left, tlv_len;
00466 const u8 *pos;
00467 const u8 *result_tlv = NULL, *crypto_tlv = NULL;
00468 size_t result_tlv_len = 0, crypto_tlv_len = 0;
00469 int tlv_type, mandatory;
00470
00471
00472 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left);
00473 if (pos == NULL)
00474 return -1;
00475 wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left);
00476 while (left >= 4) {
00477 mandatory = !!(pos[0] & 0x80);
00478 tlv_type = WPA_GET_BE16(pos) & 0x3fff;
00479 pos += 2;
00480 tlv_len = WPA_GET_BE16(pos);
00481 pos += 2;
00482 left -= 4;
00483 if (tlv_len > left) {
00484 wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun "
00485 "(tlv_len=%lu left=%lu)",
00486 (unsigned long) tlv_len,
00487 (unsigned long) left);
00488 return -1;
00489 }
00490 switch (tlv_type) {
00491 case EAP_TLV_RESULT_TLV:
00492 result_tlv = pos;
00493 result_tlv_len = tlv_len;
00494 break;
00495 case EAP_TLV_CRYPTO_BINDING_TLV:
00496 crypto_tlv = pos;
00497 crypto_tlv_len = tlv_len;
00498 break;
00499 default:
00500 wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type "
00501 "%d%s", tlv_type,
00502 mandatory ? " (mandatory)" : "");
00503 if (mandatory) {
00504
00505
00506 *resp = eap_tlv_build_nak(eap_get_id(req),
00507 tlv_type);
00508 return *resp == NULL ? -1 : 0;
00509 }
00510
00511 break;
00512 }
00513
00514 pos += tlv_len;
00515 left -= tlv_len;
00516 }
00517 if (left) {
00518 wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in "
00519 "Request (left=%lu)", (unsigned long) left);
00520 return -1;
00521 }
00522
00523
00524 if (crypto_tlv && data->crypto_binding != NO_BINDING) {
00525 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
00526 crypto_tlv, crypto_tlv_len);
00527 if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
00528 crypto_tlv_len + 4) < 0) {
00529 if (result_tlv == NULL)
00530 return -1;
00531 force_failure = 1;
00532 crypto_tlv = NULL;
00533
00534
00535 }
00536 } else if (!crypto_tlv && data->crypto_binding == REQUIRE_BINDING) {
00537 wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
00538 return -1;
00539 }
00540
00541 if (result_tlv) {
00542 int status, resp_status;
00543 wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV",
00544 result_tlv, result_tlv_len);
00545 if (result_tlv_len < 2) {
00546 wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV "
00547 "(len=%lu)",
00548 (unsigned long) result_tlv_len);
00549 return -1;
00550 }
00551 status = WPA_GET_BE16(result_tlv);
00552 if (status == EAP_TLV_RESULT_SUCCESS) {
00553 wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success "
00554 "- EAP-TLV/Phase2 Completed");
00555 if (force_failure) {
00556 wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure"
00557 " - force failed Phase 2");
00558 resp_status = EAP_TLV_RESULT_FAILURE;
00559 ret->decision = DECISION_FAIL;
00560 } else {
00561 resp_status = EAP_TLV_RESULT_SUCCESS;
00562 ret->decision = DECISION_UNCOND_SUCC;
00563 }
00564 } else if (status == EAP_TLV_RESULT_FAILURE) {
00565 wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure");
00566 resp_status = EAP_TLV_RESULT_FAILURE;
00567 ret->decision = DECISION_FAIL;
00568 } else {
00569 wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result "
00570 "Status %d", status);
00571 resp_status = EAP_TLV_RESULT_FAILURE;
00572 ret->decision = DECISION_FAIL;
00573 }
00574 ret->methodState = METHOD_DONE;
00575
00576 *resp = eap_tlv_build_result(sm, data, crypto_tlv != NULL,
00577 eap_get_id(req), resp_status);
00578 }
00579
00580 return 0;
00581 }
00582
00583
00584 static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
00585 {
00586 struct wpabuf *e;
00587 struct eap_tlv_hdr *tlv;
00588
00589 if (buf == NULL)
00590 return NULL;
00591
00592
00593 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
00594 e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
00595 if (e == NULL) {
00596 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
00597 "for TLV encapsulation");
00598 wpabuf_free(buf);
00599 return NULL;
00600 }
00601 tlv = wpabuf_put(e, sizeof(*tlv));
00602 tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
00603 EAP_TLV_EAP_PAYLOAD_TLV);
00604 tlv->length = host_to_be16(wpabuf_len(buf));
00605 wpabuf_put_buf(e, buf);
00606 wpabuf_free(buf);
00607 return e;
00608 }
00609
00610
00611 static int eap_peap_phase2_request(struct eap_sm *sm,
00612 struct eap_peap_data *data,
00613 struct eap_method_ret *ret,
00614 struct wpabuf *req,
00615 struct wpabuf **resp)
00616 {
00617 struct eap_hdr *hdr = wpabuf_mhead(req);
00618 size_t len = be_to_host16(hdr->length);
00619 u8 *pos;
00620 struct eap_method_ret iret;
00621 struct eap_peer_config *config = eap_get_config(sm);
00622
00623 if (len <= sizeof(struct eap_hdr)) {
00624 wpa_printf(MSG_INFO, "EAP-PEAP: too short "
00625 "Phase 2 request (len=%lu)", (unsigned long) len);
00626 return -1;
00627 }
00628 pos = (u8 *) (hdr + 1);
00629 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos);
00630 switch (*pos) {
00631 case EAP_TYPE_IDENTITY:
00632 *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
00633 break;
00634 case EAP_TYPE_TLV:
00635 os_memset(&iret, 0, sizeof(iret));
00636 if (eap_tlv_process(sm, data, &iret, req, resp,
00637 data->phase2_eap_started &&
00638 !data->phase2_eap_success)) {
00639 ret->methodState = METHOD_DONE;
00640 ret->decision = DECISION_FAIL;
00641 return -1;
00642 }
00643 if (iret.methodState == METHOD_DONE ||
00644 iret.methodState == METHOD_MAY_CONT) {
00645 ret->methodState = iret.methodState;
00646 ret->decision = iret.decision;
00647 data->phase2_success = 1;
00648 }
00649 break;
00650 case EAP_TYPE_EXPANDED:
00651 #ifdef EAP_TNC
00652 if (data->soh) {
00653 const u8 *epos;
00654 size_t eleft;
00655
00656 epos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21,
00657 req, &eleft);
00658 if (epos) {
00659 struct wpabuf *buf;
00660 wpa_printf(MSG_DEBUG,
00661 "EAP-PEAP: SoH EAP Extensions");
00662 buf = tncc_process_soh_request(data->soh,
00663 epos, eleft);
00664 if (buf) {
00665 *resp = eap_msg_alloc(
00666 EAP_VENDOR_MICROSOFT, 0x21,
00667 wpabuf_len(buf),
00668 EAP_CODE_RESPONSE,
00669 hdr->identifier);
00670 if (*resp == NULL) {
00671 ret->methodState = METHOD_DONE;
00672 ret->decision = DECISION_FAIL;
00673 return -1;
00674 }
00675 wpabuf_put_buf(*resp, buf);
00676 wpabuf_free(buf);
00677 break;
00678 }
00679 }
00680 }
00681 #endif
00682
00683 default:
00684 if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
00685 data->phase2_type.method == EAP_TYPE_NONE) {
00686 size_t i;
00687 for (i = 0; i < data->num_phase2_types; i++) {
00688 if (data->phase2_types[i].vendor !=
00689 EAP_VENDOR_IETF ||
00690 data->phase2_types[i].method != *pos)
00691 continue;
00692
00693 data->phase2_type.vendor =
00694 data->phase2_types[i].vendor;
00695 data->phase2_type.method =
00696 data->phase2_types[i].method;
00697 wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected "
00698 "Phase 2 EAP vendor %d method %d",
00699 data->phase2_type.vendor,
00700 data->phase2_type.method);
00701 break;
00702 }
00703 }
00704 if (*pos != data->phase2_type.method ||
00705 *pos == EAP_TYPE_NONE) {
00706 if (eap_peer_tls_phase2_nak(data->phase2_types,
00707 data->num_phase2_types,
00708 hdr, resp))
00709 return -1;
00710 return 0;
00711 }
00712
00713 if (data->phase2_priv == NULL) {
00714 data->phase2_method = eap_peer_get_eap_method(
00715 data->phase2_type.vendor,
00716 data->phase2_type.method);
00717 if (data->phase2_method) {
00718 sm->init_phase2 = 1;
00719 data->phase2_priv =
00720 data->phase2_method->init(sm);
00721 sm->init_phase2 = 0;
00722 }
00723 }
00724 if (data->phase2_priv == NULL || data->phase2_method == NULL) {
00725 wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize "
00726 "Phase 2 EAP method %d", *pos);
00727 ret->methodState = METHOD_DONE;
00728 ret->decision = DECISION_FAIL;
00729 return -1;
00730 }
00731 data->phase2_eap_started = 1;
00732 os_memset(&iret, 0, sizeof(iret));
00733 *resp = data->phase2_method->process(sm, data->phase2_priv,
00734 &iret, req);
00735 if ((iret.methodState == METHOD_DONE ||
00736 iret.methodState == METHOD_MAY_CONT) &&
00737 (iret.decision == DECISION_UNCOND_SUCC ||
00738 iret.decision == DECISION_COND_SUCC)) {
00739 data->phase2_eap_success = 1;
00740 data->phase2_success = 1;
00741 }
00742 break;
00743 }
00744
00745 if (*resp == NULL &&
00746 (config->pending_req_identity || config->pending_req_password ||
00747 config->pending_req_otp || config->pending_req_new_password)) {
00748 wpabuf_free(data->pending_phase2_req);
00749 data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
00750 }
00751
00752 return 0;
00753 }
00754
00755
00756 static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data,
00757 struct eap_method_ret *ret,
00758 const struct eap_hdr *req,
00759 const struct wpabuf *in_data,
00760 struct wpabuf **out_data)
00761 {
00762 struct wpabuf *in_decrypted = NULL;
00763 int res, skip_change = 0;
00764 struct eap_hdr *hdr, *rhdr;
00765 struct wpabuf *resp = NULL;
00766 size_t len;
00767
00768 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
00769 " Phase 2", (unsigned long) wpabuf_len(in_data));
00770
00771 if (data->pending_phase2_req) {
00772 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - "
00773 "skip decryption and use old data");
00774
00775 eap_peer_tls_reset_input(&data->ssl);
00776 in_decrypted = data->pending_phase2_req;
00777 data->pending_phase2_req = NULL;
00778 skip_change = 1;
00779 goto continue_req;
00780 }
00781
00782 if (wpabuf_len(in_data) == 0 && sm->workaround &&
00783 data->phase2_success) {
00784
00785
00786
00787
00788 wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but "
00789 "expected data - acknowledge with TLS ACK since "
00790 "Phase 2 has been completed");
00791 ret->decision = DECISION_COND_SUCC;
00792 ret->methodState = METHOD_DONE;
00793 return 1;
00794 } else if (wpabuf_len(in_data) == 0) {
00795
00796 return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP,
00797 data->peap_version,
00798 req->identifier, NULL, out_data);
00799 }
00800
00801 res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
00802 if (res)
00803 return res;
00804
00805 continue_req:
00806 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
00807 in_decrypted);
00808
00809 hdr = wpabuf_mhead(in_decrypted);
00810 if (wpabuf_len(in_decrypted) == 5 && hdr->code == EAP_CODE_REQUEST &&
00811 be_to_host16(hdr->length) == 5 &&
00812 eap_get_type(in_decrypted) == EAP_TYPE_IDENTITY) {
00813
00814
00815 skip_change = 1;
00816 }
00817 if (wpabuf_len(in_decrypted) >= 5 && hdr->code == EAP_CODE_REQUEST &&
00818 eap_get_type(in_decrypted) == EAP_TYPE_TLV) {
00819 skip_change = 1;
00820 }
00821
00822 if (data->peap_version == 0 && !skip_change) {
00823 struct eap_hdr *nhdr;
00824 struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) +
00825 wpabuf_len(in_decrypted));
00826 if (nmsg == NULL) {
00827 wpabuf_free(in_decrypted);
00828 return 0;
00829 }
00830 nhdr = wpabuf_put(nmsg, sizeof(*nhdr));
00831 wpabuf_put_buf(nmsg, in_decrypted);
00832 nhdr->code = req->code;
00833 nhdr->identifier = req->identifier;
00834 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
00835 wpabuf_len(in_decrypted));
00836
00837 wpabuf_free(in_decrypted);
00838 in_decrypted = nmsg;
00839 }
00840
00841 if (data->peap_version >= 2) {
00842 struct eap_tlv_hdr *tlv;
00843 struct wpabuf *nmsg;
00844
00845 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
00846 wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
00847 "EAP TLV");
00848 wpabuf_free(in_decrypted);
00849 return 0;
00850 }
00851 tlv = wpabuf_mhead(in_decrypted);
00852 if ((be_to_host16(tlv->tlv_type) & 0x3fff) !=
00853 EAP_TLV_EAP_PAYLOAD_TLV) {
00854 wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
00855 wpabuf_free(in_decrypted);
00856 return 0;
00857 }
00858 if (sizeof(*tlv) + be_to_host16(tlv->length) >
00859 wpabuf_len(in_decrypted)) {
00860 wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
00861 "length");
00862 wpabuf_free(in_decrypted);
00863 return 0;
00864 }
00865 hdr = (struct eap_hdr *) (tlv + 1);
00866 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
00867 wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
00868 "EAP packet in EAP TLV");
00869 wpabuf_free(in_decrypted);
00870 return 0;
00871 }
00872
00873 nmsg = wpabuf_alloc(be_to_host16(hdr->length));
00874 if (nmsg == NULL) {
00875 wpabuf_free(in_decrypted);
00876 return 0;
00877 }
00878
00879 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
00880 wpabuf_free(in_decrypted);
00881 in_decrypted = nmsg;
00882 }
00883
00884 hdr = wpabuf_mhead(in_decrypted);
00885 if (wpabuf_len(in_decrypted) < sizeof(*hdr)) {
00886 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
00887 "EAP frame (len=%lu)",
00888 (unsigned long) wpabuf_len(in_decrypted));
00889 wpabuf_free(in_decrypted);
00890 return 0;
00891 }
00892 len = be_to_host16(hdr->length);
00893 if (len > wpabuf_len(in_decrypted)) {
00894 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
00895 "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
00896 (unsigned long) wpabuf_len(in_decrypted),
00897 (unsigned long) len);
00898 wpabuf_free(in_decrypted);
00899 return 0;
00900 }
00901 if (len < wpabuf_len(in_decrypted)) {
00902 wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has "
00903 "shorter length than full decrypted data "
00904 "(%lu < %lu)",
00905 (unsigned long) len,
00906 (unsigned long) wpabuf_len(in_decrypted));
00907 }
00908 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
00909 "identifier=%d length=%lu", hdr->code, hdr->identifier,
00910 (unsigned long) len);
00911 switch (hdr->code) {
00912 case EAP_CODE_REQUEST:
00913 if (eap_peap_phase2_request(sm, data, ret, in_decrypted,
00914 &resp)) {
00915 wpabuf_free(in_decrypted);
00916 wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request "
00917 "processing failed");
00918 return 0;
00919 }
00920 break;
00921 case EAP_CODE_SUCCESS:
00922 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
00923 if (data->peap_version == 1) {
00924
00925
00926
00927 if (data->phase2_eap_started &&
00928 !data->phase2_eap_success) {
00929 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 "
00930 "Success used to indicate success, "
00931 "but Phase 2 EAP was not yet "
00932 "completed successfully");
00933 ret->methodState = METHOD_DONE;
00934 ret->decision = DECISION_FAIL;
00935 wpabuf_free(in_decrypted);
00936 return 0;
00937 }
00938 wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
00939 "EAP-Success within TLS tunnel - "
00940 "authentication completed");
00941 ret->decision = DECISION_UNCOND_SUCC;
00942 ret->methodState = METHOD_DONE;
00943 data->phase2_success = 1;
00944 if (data->peap_outer_success == 2) {
00945 wpabuf_free(in_decrypted);
00946 wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
00947 "to finish authentication");
00948 return 1;
00949 } else if (data->peap_outer_success == 1) {
00950
00951
00952 resp = wpabuf_alloc(sizeof(struct eap_hdr));
00953 if (resp) {
00954 rhdr = wpabuf_put(resp, sizeof(*rhdr));
00955 rhdr->code = EAP_CODE_SUCCESS;
00956 rhdr->identifier = hdr->identifier;
00957 rhdr->length =
00958 host_to_be16(sizeof(*rhdr));
00959 }
00960 } else {
00961
00962
00963
00964 sm->peap_done = TRUE;
00965 }
00966 } else {
00967
00968 }
00969 break;
00970 case EAP_CODE_FAILURE:
00971 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
00972 ret->decision = DECISION_FAIL;
00973 ret->methodState = METHOD_MAY_CONT;
00974 ret->allowNotifications = FALSE;
00975
00976
00977 resp = wpabuf_alloc(sizeof(struct eap_hdr));
00978 if (resp) {
00979 rhdr = wpabuf_put(resp, sizeof(*rhdr));
00980 rhdr->code = EAP_CODE_FAILURE;
00981 rhdr->identifier = hdr->identifier;
00982 rhdr->length = host_to_be16(sizeof(*rhdr));
00983 }
00984 break;
00985 default:
00986 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
00987 "Phase 2 EAP header", hdr->code);
00988 break;
00989 }
00990
00991 wpabuf_free(in_decrypted);
00992
00993 if (resp) {
00994 int skip_change2 = 0;
00995 struct wpabuf *rmsg, buf;
00996
00997 wpa_hexdump_buf_key(MSG_DEBUG,
00998 "EAP-PEAP: Encrypting Phase 2 data", resp);
00999
01000 if (data->peap_version >= 2) {
01001 resp = eap_peapv2_tlv_eap_payload(resp);
01002 if (resp == NULL)
01003 return -1;
01004 }
01005 if (wpabuf_len(resp) >= 5 &&
01006 wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE &&
01007 eap_get_type(resp) == EAP_TYPE_TLV)
01008 skip_change2 = 1;
01009 rmsg = resp;
01010 if (data->peap_version == 0 && !skip_change2) {
01011 wpabuf_set(&buf, wpabuf_head_u8(resp) +
01012 sizeof(struct eap_hdr),
01013 wpabuf_len(resp) - sizeof(struct eap_hdr));
01014 rmsg = &buf;
01015 }
01016
01017 if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP,
01018 data->peap_version, req->identifier,
01019 rmsg, out_data)) {
01020 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
01021 "a Phase 2 frame");
01022 }
01023 wpabuf_free(resp);
01024 }
01025
01026 return 0;
01027 }
01028
01029
01030 static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
01031 struct eap_method_ret *ret,
01032 const struct wpabuf *reqData)
01033 {
01034 const struct eap_hdr *req;
01035 size_t left;
01036 int res;
01037 u8 flags, id;
01038 struct wpabuf *resp;
01039 const u8 *pos;
01040 struct eap_peap_data *data = priv;
01041
01042 pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret,
01043 reqData, &left, &flags);
01044 if (pos == NULL)
01045 return NULL;
01046 req = wpabuf_head(reqData);
01047 id = req->identifier;
01048
01049 if (flags & EAP_TLS_FLAGS_START) {
01050 wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own "
01051 "ver=%d)", flags & EAP_TLS_VERSION_MASK,
01052 data->peap_version);
01053 if ((flags & EAP_TLS_VERSION_MASK) < data->peap_version)
01054 data->peap_version = flags & EAP_TLS_VERSION_MASK;
01055 if (data->force_peap_version >= 0 &&
01056 data->force_peap_version != data->peap_version) {
01057 wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select "
01058 "forced PEAP version %d",
01059 data->force_peap_version);
01060 ret->methodState = METHOD_DONE;
01061 ret->decision = DECISION_FAIL;
01062 ret->allowNotifications = FALSE;
01063 return NULL;
01064 }
01065 wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d",
01066 data->peap_version);
01067 left = 0;
01068
01069 }
01070
01071 resp = NULL;
01072 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
01073 !data->resuming) {
01074 struct wpabuf msg;
01075 wpabuf_set(&msg, pos, left);
01076 res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp);
01077 } else {
01078 res = eap_peer_tls_process_helper(sm, &data->ssl,
01079 EAP_TYPE_PEAP,
01080 data->peap_version, id, pos,
01081 left, &resp);
01082
01083 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
01084 char *label;
01085 wpa_printf(MSG_DEBUG,
01086 "EAP-PEAP: TLS done, proceed to Phase 2");
01087 os_free(data->key_data);
01088
01089
01090
01091
01092
01093
01094
01095 if (data->peap_version > 1 || data->force_new_label)
01096 label = "client PEAP encryption";
01097 else
01098 label = "client EAP encryption";
01099 wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in "
01100 "key derivation", label);
01101 data->key_data =
01102 eap_peer_tls_derive_key(sm, &data->ssl, label,
01103 EAP_TLS_KEY_LEN);
01104 if (data->key_data) {
01105 wpa_hexdump_key(MSG_DEBUG,
01106 "EAP-PEAP: Derived key",
01107 data->key_data,
01108 EAP_TLS_KEY_LEN);
01109 } else {
01110 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "
01111 "derive key");
01112 }
01113
01114 if (sm->workaround && data->resuming) {
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125 wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - "
01126 "allow outer EAP-Success to "
01127 "terminate PEAP resumption");
01128 ret->decision = DECISION_COND_SUCC;
01129 data->phase2_success = 1;
01130 }
01131
01132 data->resuming = 0;
01133 }
01134
01135 if (res == 2) {
01136 struct wpabuf msg;
01137
01138
01139
01140 wpabuf_free(data->pending_phase2_req);
01141 data->pending_phase2_req = resp;
01142 resp = NULL;
01143 wpabuf_set(&msg, pos, left);
01144 res = eap_peap_decrypt(sm, data, ret, req, &msg,
01145 &resp);
01146 }
01147 }
01148
01149 if (ret->methodState == METHOD_DONE) {
01150 ret->allowNotifications = FALSE;
01151 }
01152
01153 if (res == 1) {
01154 wpabuf_free(resp);
01155 return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP,
01156 data->peap_version);
01157 }
01158
01159 return resp;
01160 }
01161
01162
01163 static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv)
01164 {
01165 struct eap_peap_data *data = priv;
01166 return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
01167 data->phase2_success;
01168 }
01169
01170
01171 static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
01172 {
01173 struct eap_peap_data *data = priv;
01174 wpabuf_free(data->pending_phase2_req);
01175 data->pending_phase2_req = NULL;
01176 data->crypto_binding_used = 0;
01177 }
01178
01179
01180 static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
01181 {
01182 struct eap_peap_data *data = priv;
01183 os_free(data->key_data);
01184 data->key_data = NULL;
01185 if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
01186 os_free(data);
01187 return NULL;
01188 }
01189 if (data->phase2_priv && data->phase2_method &&
01190 data->phase2_method->init_for_reauth)
01191 data->phase2_method->init_for_reauth(sm, data->phase2_priv);
01192 data->phase2_success = 0;
01193 data->phase2_eap_success = 0;
01194 data->phase2_eap_started = 0;
01195 data->resuming = 1;
01196 data->reauth = 1;
01197 sm->peap_done = FALSE;
01198 return priv;
01199 }
01200
01201
01202 static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf,
01203 size_t buflen, int verbose)
01204 {
01205 struct eap_peap_data *data = priv;
01206 int len, ret;
01207
01208 len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
01209 if (data->phase2_method) {
01210 ret = os_snprintf(buf + len, buflen - len,
01211 "EAP-PEAPv%d Phase2 method=%s\n",
01212 data->peap_version,
01213 data->phase2_method->name);
01214 if (ret < 0 || (size_t) ret >= buflen - len)
01215 return len;
01216 len += ret;
01217 }
01218 return len;
01219 }
01220
01221
01222 static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv)
01223 {
01224 struct eap_peap_data *data = priv;
01225 return data->key_data != NULL && data->phase2_success;
01226 }
01227
01228
01229 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
01230 {
01231 struct eap_peap_data *data = priv;
01232 u8 *key;
01233
01234 if (data->key_data == NULL || !data->phase2_success)
01235 return NULL;
01236
01237 key = os_malloc(EAP_TLS_KEY_LEN);
01238 if (key == NULL)
01239 return NULL;
01240
01241 *len = EAP_TLS_KEY_LEN;
01242
01243 if (data->crypto_binding_used) {
01244 u8 csk[128];
01245
01246
01247
01248
01249
01250 peap_prfplus(data->peap_version, data->ipmk, 40,
01251 "Session Key Generating Function",
01252 (u8 *) "\00", 1, csk, sizeof(csk));
01253 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
01254 os_memcpy(key, csk, EAP_TLS_KEY_LEN);
01255 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
01256 key, EAP_TLS_KEY_LEN);
01257 } else
01258 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
01259
01260 return key;
01261 }
01262
01263
01264 int eap_peer_peap_register(void)
01265 {
01266 struct eap_method *eap;
01267 int ret;
01268
01269 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
01270 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
01271 if (eap == NULL)
01272 return -1;
01273
01274 eap->init = eap_peap_init;
01275 eap->deinit = eap_peap_deinit;
01276 eap->process = eap_peap_process;
01277 eap->isKeyAvailable = eap_peap_isKeyAvailable;
01278 eap->getKey = eap_peap_getKey;
01279 eap->get_status = eap_peap_get_status;
01280 eap->has_reauth_data = eap_peap_has_reauth_data;
01281 eap->deinit_for_reauth = eap_peap_deinit_for_reauth;
01282 eap->init_for_reauth = eap_peap_init_for_reauth;
01283
01284 ret = eap_peer_method_register(eap);
01285 if (ret)
01286 eap_peer_method_free(eap);
01287 return ret;
01288 }