$search
00001 /* 00002 * hostapd / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) 00003 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "crypto/sha1.h" 00019 #include "crypto/tls.h" 00020 #include "eap_i.h" 00021 #include "eap_tls_common.h" 00022 #include "eap_common/eap_tlv_common.h" 00023 #include "eap_common/eap_peap_common.h" 00024 #include "tncs.h" 00025 00026 00027 /* Maximum supported PEAP version 00028 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt 00029 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt 00030 * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt 00031 */ 00032 #define EAP_PEAP_VERSION 1 00033 00034 00035 static void eap_peap_reset(struct eap_sm *sm, void *priv); 00036 00037 00038 struct eap_peap_data { 00039 struct eap_ssl_data ssl; 00040 enum { 00041 START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID, 00042 PHASE2_METHOD, PHASE2_SOH, 00043 PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE 00044 } state; 00045 00046 int peap_version; 00047 int recv_version; 00048 const struct eap_method *phase2_method; 00049 void *phase2_priv; 00050 int force_version; 00051 struct wpabuf *pending_phase2_resp; 00052 enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request; 00053 int crypto_binding_sent; 00054 int crypto_binding_used; 00055 enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; 00056 u8 binding_nonce[32]; 00057 u8 ipmk[40]; 00058 u8 cmk[20]; 00059 u8 *phase2_key; 00060 size_t phase2_key_len; 00061 struct wpabuf *soh_response; 00062 }; 00063 00064 00065 static const char * eap_peap_state_txt(int state) 00066 { 00067 switch (state) { 00068 case START: 00069 return "START"; 00070 case PHASE1: 00071 return "PHASE1"; 00072 case PHASE1_ID2: 00073 return "PHASE1_ID2"; 00074 case PHASE2_START: 00075 return "PHASE2_START"; 00076 case PHASE2_ID: 00077 return "PHASE2_ID"; 00078 case PHASE2_METHOD: 00079 return "PHASE2_METHOD"; 00080 case PHASE2_SOH: 00081 return "PHASE2_SOH"; 00082 case PHASE2_TLV: 00083 return "PHASE2_TLV"; 00084 case SUCCESS_REQ: 00085 return "SUCCESS_REQ"; 00086 case FAILURE_REQ: 00087 return "FAILURE_REQ"; 00088 case SUCCESS: 00089 return "SUCCESS"; 00090 case FAILURE: 00091 return "FAILURE"; 00092 default: 00093 return "Unknown?!"; 00094 } 00095 } 00096 00097 00098 static void eap_peap_state(struct eap_peap_data *data, int state) 00099 { 00100 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s", 00101 eap_peap_state_txt(data->state), 00102 eap_peap_state_txt(state)); 00103 data->state = state; 00104 } 00105 00106 00107 static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf) 00108 { 00109 struct wpabuf *e; 00110 struct eap_tlv_hdr *tlv; 00111 00112 if (buf == NULL) 00113 return NULL; 00114 00115 /* Encapsulate EAP packet in EAP-Payload TLV */ 00116 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV"); 00117 e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf)); 00118 if (e == NULL) { 00119 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory " 00120 "for TLV encapsulation"); 00121 wpabuf_free(buf); 00122 return NULL; 00123 } 00124 tlv = wpabuf_put(e, sizeof(*tlv)); 00125 tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | 00126 EAP_TLV_EAP_PAYLOAD_TLV); 00127 tlv->length = host_to_be16(wpabuf_len(buf)); 00128 wpabuf_put_buf(e, buf); 00129 wpabuf_free(buf); 00130 return e; 00131 } 00132 00133 00134 static void eap_peap_req_success(struct eap_sm *sm, 00135 struct eap_peap_data *data) 00136 { 00137 if (data->state == FAILURE || data->state == FAILURE_REQ) { 00138 eap_peap_state(data, FAILURE); 00139 return; 00140 } 00141 00142 if (data->peap_version == 0) { 00143 data->tlv_request = TLV_REQ_SUCCESS; 00144 eap_peap_state(data, PHASE2_TLV); 00145 } else { 00146 eap_peap_state(data, SUCCESS_REQ); 00147 } 00148 } 00149 00150 00151 static void eap_peap_req_failure(struct eap_sm *sm, 00152 struct eap_peap_data *data) 00153 { 00154 if (data->state == FAILURE || data->state == FAILURE_REQ || 00155 data->state == SUCCESS_REQ || data->tlv_request != TLV_REQ_NONE) { 00156 eap_peap_state(data, FAILURE); 00157 return; 00158 } 00159 00160 if (data->peap_version == 0) { 00161 data->tlv_request = TLV_REQ_FAILURE; 00162 eap_peap_state(data, PHASE2_TLV); 00163 } else { 00164 eap_peap_state(data, FAILURE_REQ); 00165 } 00166 } 00167 00168 00169 static void * eap_peap_init(struct eap_sm *sm) 00170 { 00171 struct eap_peap_data *data; 00172 00173 data = os_zalloc(sizeof(*data)); 00174 if (data == NULL) 00175 return NULL; 00176 data->peap_version = EAP_PEAP_VERSION; 00177 data->force_version = -1; 00178 if (sm->user && sm->user->force_version >= 0) { 00179 data->force_version = sm->user->force_version; 00180 wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d", 00181 data->force_version); 00182 data->peap_version = data->force_version; 00183 } 00184 data->state = START; 00185 data->crypto_binding = OPTIONAL_BINDING; 00186 00187 if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) { 00188 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); 00189 eap_peap_reset(sm, data); 00190 return NULL; 00191 } 00192 00193 return data; 00194 } 00195 00196 00197 static void eap_peap_reset(struct eap_sm *sm, void *priv) 00198 { 00199 struct eap_peap_data *data = priv; 00200 if (data == NULL) 00201 return; 00202 if (data->phase2_priv && data->phase2_method) 00203 data->phase2_method->reset(sm, data->phase2_priv); 00204 eap_server_tls_ssl_deinit(sm, &data->ssl); 00205 wpabuf_free(data->pending_phase2_resp); 00206 os_free(data->phase2_key); 00207 wpabuf_free(data->soh_response); 00208 os_free(data); 00209 } 00210 00211 00212 static struct wpabuf * eap_peap_build_start(struct eap_sm *sm, 00213 struct eap_peap_data *data, u8 id) 00214 { 00215 struct wpabuf *req; 00216 00217 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1, 00218 EAP_CODE_REQUEST, id); 00219 if (req == NULL) { 00220 wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for" 00221 " request"); 00222 eap_peap_state(data, FAILURE); 00223 return NULL; 00224 } 00225 00226 wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version); 00227 00228 eap_peap_state(data, PHASE1); 00229 00230 return req; 00231 } 00232 00233 00234 static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm, 00235 struct eap_peap_data *data, 00236 u8 id) 00237 { 00238 struct wpabuf *buf, *encr_req, msgbuf; 00239 const u8 *req; 00240 size_t req_len; 00241 00242 if (data->phase2_method == NULL || data->phase2_priv == NULL) { 00243 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 method not ready"); 00244 return NULL; 00245 } 00246 buf = data->phase2_method->buildReq(sm, data->phase2_priv, id); 00247 if (data->peap_version >= 2 && buf) 00248 buf = eap_peapv2_tlv_eap_payload(buf); 00249 if (buf == NULL) 00250 return NULL; 00251 00252 req = wpabuf_head(buf); 00253 req_len = wpabuf_len(buf); 00254 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", 00255 req, req_len); 00256 00257 if (data->peap_version == 0 && 00258 data->phase2_method->method != EAP_TYPE_TLV) { 00259 req += sizeof(struct eap_hdr); 00260 req_len -= sizeof(struct eap_hdr); 00261 } 00262 00263 wpabuf_set(&msgbuf, req, req_len); 00264 encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); 00265 wpabuf_free(buf); 00266 00267 return encr_req; 00268 } 00269 00270 00271 #ifdef EAP_SERVER_TNC 00272 static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm, 00273 struct eap_peap_data *data, 00274 u8 id) 00275 { 00276 struct wpabuf *buf1, *buf, *encr_req, msgbuf; 00277 const u8 *req; 00278 size_t req_len; 00279 00280 buf1 = tncs_build_soh_request(); 00281 if (buf1 == NULL) 00282 return NULL; 00283 00284 buf = eap_msg_alloc(EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf1), 00285 EAP_CODE_REQUEST, id); 00286 if (buf == NULL) { 00287 wpabuf_free(buf1); 00288 return NULL; 00289 } 00290 wpabuf_put_buf(buf, buf1); 00291 wpabuf_free(buf1); 00292 00293 req = wpabuf_head(buf); 00294 req_len = wpabuf_len(buf); 00295 00296 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 SOH data", 00297 req, req_len); 00298 00299 req += sizeof(struct eap_hdr); 00300 req_len -= sizeof(struct eap_hdr); 00301 wpabuf_set(&msgbuf, req, req_len); 00302 00303 encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); 00304 wpabuf_free(buf); 00305 00306 return encr_req; 00307 } 00308 #endif /* EAP_SERVER_TNC */ 00309 00310 00311 static void eap_peap_get_isk(struct eap_peap_data *data, 00312 u8 *isk, size_t isk_len) 00313 { 00314 size_t key_len; 00315 00316 os_memset(isk, 0, isk_len); 00317 if (data->phase2_key == NULL) 00318 return; 00319 00320 key_len = data->phase2_key_len; 00321 if (key_len > isk_len) 00322 key_len = isk_len; 00323 os_memcpy(isk, data->phase2_key, key_len); 00324 } 00325 00326 00327 static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) 00328 { 00329 u8 *tk; 00330 u8 isk[32], imck[60]; 00331 00332 /* 00333 * Tunnel key (TK) is the first 60 octets of the key generated by 00334 * phase 1 of PEAP (based on TLS). 00335 */ 00336 tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption", 00337 EAP_TLS_KEY_LEN); 00338 if (tk == NULL) 00339 return -1; 00340 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); 00341 00342 eap_peap_get_isk(data, isk, sizeof(isk)); 00343 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk)); 00344 00345 /* 00346 * IPMK Seed = "Inner Methods Compound Keys" | ISK 00347 * TempKey = First 40 octets of TK 00348 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60) 00349 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space 00350 * in the end of the label just before ISK; is that just a typo?) 00351 */ 00352 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); 00353 peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys", 00354 isk, sizeof(isk), imck, sizeof(imck)); 00355 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", 00356 imck, sizeof(imck)); 00357 00358 os_free(tk); 00359 00360 /* TODO: fast-connect: IPMK|CMK = TK */ 00361 os_memcpy(data->ipmk, imck, 40); 00362 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40); 00363 os_memcpy(data->cmk, imck + 40, 20); 00364 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20); 00365 00366 return 0; 00367 } 00368 00369 00370 static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm, 00371 struct eap_peap_data *data, 00372 u8 id) 00373 { 00374 struct wpabuf *buf, *encr_req; 00375 size_t mlen; 00376 00377 mlen = 6; /* Result TLV */ 00378 if (data->crypto_binding != NO_BINDING) 00379 mlen += 60; /* Cryptobinding TLV */ 00380 #ifdef EAP_SERVER_TNC 00381 if (data->soh_response) 00382 mlen += wpabuf_len(data->soh_response); 00383 #endif /* EAP_SERVER_TNC */ 00384 00385 buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, mlen, 00386 EAP_CODE_REQUEST, id); 00387 if (buf == NULL) 00388 return NULL; 00389 00390 wpabuf_put_u8(buf, 0x80); /* Mandatory */ 00391 wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV); 00392 /* Length */ 00393 wpabuf_put_be16(buf, 2); 00394 /* Status */ 00395 wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ? 00396 EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE); 00397 00398 if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS && 00399 data->crypto_binding != NO_BINDING) { 00400 u8 *mac; 00401 u8 eap_type = EAP_TYPE_PEAP; 00402 const u8 *addr[2]; 00403 size_t len[2]; 00404 u16 tlv_type; 00405 00406 #ifdef EAP_SERVER_TNC 00407 if (data->soh_response) { 00408 wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH " 00409 "Response TLV"); 00410 wpabuf_put_buf(buf, data->soh_response); 00411 wpabuf_free(data->soh_response); 00412 data->soh_response = NULL; 00413 } 00414 #endif /* EAP_SERVER_TNC */ 00415 00416 if (eap_peap_derive_cmk(sm, data) < 0 || 00417 os_get_random(data->binding_nonce, 32)) { 00418 wpabuf_free(buf); 00419 return NULL; 00420 } 00421 00422 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 00423 addr[0] = wpabuf_put(buf, 0); 00424 len[0] = 60; 00425 addr[1] = &eap_type; 00426 len[1] = 1; 00427 00428 tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; 00429 if (data->peap_version >= 2) 00430 tlv_type |= EAP_TLV_TYPE_MANDATORY; 00431 wpabuf_put_be16(buf, tlv_type); 00432 wpabuf_put_be16(buf, 56); 00433 00434 wpabuf_put_u8(buf, 0); /* Reserved */ 00435 wpabuf_put_u8(buf, data->peap_version); /* Version */ 00436 wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */ 00437 wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */ 00438 wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ 00439 mac = wpabuf_put(buf, 20); /* Compound_MAC */ 00440 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", 00441 data->cmk, 20); 00442 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", 00443 addr[0], len[0]); 00444 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", 00445 addr[1], len[1]); 00446 hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); 00447 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", 00448 mac, SHA1_MAC_LEN); 00449 data->crypto_binding_sent = 1; 00450 } 00451 00452 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data", 00453 buf); 00454 00455 encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf); 00456 wpabuf_free(buf); 00457 00458 return encr_req; 00459 } 00460 00461 00462 static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm, 00463 struct eap_peap_data *data, 00464 u8 id, int success) 00465 { 00466 struct wpabuf *encr_req, msgbuf; 00467 size_t req_len; 00468 struct eap_hdr *hdr; 00469 00470 req_len = sizeof(*hdr); 00471 hdr = os_zalloc(req_len); 00472 if (hdr == NULL) 00473 return NULL; 00474 00475 hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; 00476 hdr->identifier = id; 00477 hdr->length = host_to_be16(req_len); 00478 00479 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", 00480 (u8 *) hdr, req_len); 00481 00482 wpabuf_set(&msgbuf, hdr, req_len); 00483 encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); 00484 os_free(hdr); 00485 00486 return encr_req; 00487 } 00488 00489 00490 static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id) 00491 { 00492 struct eap_peap_data *data = priv; 00493 00494 if (data->ssl.state == FRAG_ACK) { 00495 return eap_server_tls_build_ack(id, EAP_TYPE_PEAP, 00496 data->peap_version); 00497 } 00498 00499 if (data->ssl.state == WAIT_FRAG_ACK) { 00500 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, 00501 data->peap_version, id); 00502 } 00503 00504 switch (data->state) { 00505 case START: 00506 return eap_peap_build_start(sm, data, id); 00507 case PHASE1: 00508 case PHASE1_ID2: 00509 if (data->peap_version < 2 && 00510 tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 00511 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, " 00512 "starting Phase2"); 00513 eap_peap_state(data, PHASE2_START); 00514 } 00515 break; 00516 case PHASE2_ID: 00517 case PHASE2_METHOD: 00518 wpabuf_free(data->ssl.tls_out); 00519 data->ssl.tls_out_pos = 0; 00520 data->ssl.tls_out = eap_peap_build_phase2_req(sm, data, id); 00521 break; 00522 #ifdef EAP_SERVER_TNC 00523 case PHASE2_SOH: 00524 wpabuf_free(data->ssl.tls_out); 00525 data->ssl.tls_out_pos = 0; 00526 data->ssl.tls_out = eap_peap_build_phase2_soh(sm, data, id); 00527 break; 00528 #endif /* EAP_SERVER_TNC */ 00529 case PHASE2_TLV: 00530 wpabuf_free(data->ssl.tls_out); 00531 data->ssl.tls_out_pos = 0; 00532 data->ssl.tls_out = eap_peap_build_phase2_tlv(sm, data, id); 00533 break; 00534 case SUCCESS_REQ: 00535 wpabuf_free(data->ssl.tls_out); 00536 data->ssl.tls_out_pos = 0; 00537 data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id, 00538 1); 00539 break; 00540 case FAILURE_REQ: 00541 wpabuf_free(data->ssl.tls_out); 00542 data->ssl.tls_out_pos = 0; 00543 data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id, 00544 0); 00545 break; 00546 default: 00547 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", 00548 __func__, data->state); 00549 return NULL; 00550 } 00551 00552 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, 00553 data->peap_version, id); 00554 } 00555 00556 00557 static Boolean eap_peap_check(struct eap_sm *sm, void *priv, 00558 struct wpabuf *respData) 00559 { 00560 const u8 *pos; 00561 size_t len; 00562 00563 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len); 00564 if (pos == NULL || len < 1) { 00565 wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame"); 00566 return TRUE; 00567 } 00568 00569 return FALSE; 00570 } 00571 00572 00573 static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data, 00574 EapType eap_type) 00575 { 00576 if (data->phase2_priv && data->phase2_method) { 00577 data->phase2_method->reset(sm, data->phase2_priv); 00578 data->phase2_method = NULL; 00579 data->phase2_priv = NULL; 00580 } 00581 data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF, 00582 eap_type); 00583 if (!data->phase2_method) 00584 return -1; 00585 00586 sm->init_phase2 = 1; 00587 data->phase2_priv = data->phase2_method->init(sm); 00588 sm->init_phase2 = 0; 00589 return 0; 00590 } 00591 00592 00593 static int eap_tlv_validate_cryptobinding(struct eap_sm *sm, 00594 struct eap_peap_data *data, 00595 const u8 *crypto_tlv, 00596 size_t crypto_tlv_len) 00597 { 00598 u8 buf[61], mac[SHA1_MAC_LEN]; 00599 const u8 *pos; 00600 00601 if (crypto_tlv_len != 4 + 56) { 00602 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " 00603 "length %d", (int) crypto_tlv_len); 00604 return -1; 00605 } 00606 00607 pos = crypto_tlv; 00608 pos += 4; /* TLV header */ 00609 if (pos[1] != data->peap_version) { 00610 wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " 00611 "mismatch (was %d; expected %d)", 00612 pos[1], data->peap_version); 00613 return -1; 00614 } 00615 00616 if (pos[3] != 1) { 00617 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " 00618 "SubType %d", pos[3]); 00619 return -1; 00620 } 00621 pos += 4; 00622 pos += 32; /* Nonce */ 00623 00624 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 00625 os_memcpy(buf, crypto_tlv, 60); 00626 os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ 00627 buf[60] = EAP_TYPE_PEAP; 00628 hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); 00629 00630 if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) { 00631 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " 00632 "cryptobinding TLV"); 00633 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20); 00634 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data", 00635 buf, 61); 00636 return -1; 00637 } 00638 00639 wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); 00640 00641 return 0; 00642 } 00643 00644 00645 static void eap_peap_process_phase2_tlv(struct eap_sm *sm, 00646 struct eap_peap_data *data, 00647 struct wpabuf *in_data) 00648 { 00649 const u8 *pos; 00650 size_t left; 00651 const u8 *result_tlv = NULL, *crypto_tlv = NULL; 00652 size_t result_tlv_len = 0, crypto_tlv_len = 0; 00653 int tlv_type, mandatory, tlv_len; 00654 00655 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left); 00656 if (pos == NULL) { 00657 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header"); 00658 return; 00659 } 00660 00661 /* Parse TLVs */ 00662 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left); 00663 while (left >= 4) { 00664 mandatory = !!(pos[0] & 0x80); 00665 tlv_type = pos[0] & 0x3f; 00666 tlv_type = (tlv_type << 8) | pos[1]; 00667 tlv_len = ((int) pos[2] << 8) | pos[3]; 00668 pos += 4; 00669 left -= 4; 00670 if ((size_t) tlv_len > left) { 00671 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " 00672 "(tlv_len=%d left=%lu)", tlv_len, 00673 (unsigned long) left); 00674 eap_peap_state(data, FAILURE); 00675 return; 00676 } 00677 switch (tlv_type) { 00678 case EAP_TLV_RESULT_TLV: 00679 result_tlv = pos; 00680 result_tlv_len = tlv_len; 00681 break; 00682 case EAP_TLV_CRYPTO_BINDING_TLV: 00683 crypto_tlv = pos; 00684 crypto_tlv_len = tlv_len; 00685 break; 00686 default: 00687 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " 00688 "%d%s", tlv_type, 00689 mandatory ? " (mandatory)" : ""); 00690 if (mandatory) { 00691 eap_peap_state(data, FAILURE); 00692 return; 00693 } 00694 /* Ignore this TLV, but process other TLVs */ 00695 break; 00696 } 00697 00698 pos += tlv_len; 00699 left -= tlv_len; 00700 } 00701 if (left) { 00702 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " 00703 "Request (left=%lu)", (unsigned long) left); 00704 eap_peap_state(data, FAILURE); 00705 return; 00706 } 00707 00708 /* Process supported TLVs */ 00709 if (crypto_tlv && data->crypto_binding_sent) { 00710 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", 00711 crypto_tlv, crypto_tlv_len); 00712 if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, 00713 crypto_tlv_len + 4) < 0) { 00714 eap_peap_state(data, FAILURE); 00715 return; 00716 } 00717 data->crypto_binding_used = 1; 00718 } else if (!crypto_tlv && data->crypto_binding_sent && 00719 data->crypto_binding == REQUIRE_BINDING) { 00720 wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); 00721 eap_peap_state(data, FAILURE); 00722 return; 00723 } 00724 00725 if (result_tlv) { 00726 int status; 00727 const char *requested; 00728 00729 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV", 00730 result_tlv, result_tlv_len); 00731 if (result_tlv_len < 2) { 00732 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV " 00733 "(len=%lu)", 00734 (unsigned long) result_tlv_len); 00735 eap_peap_state(data, FAILURE); 00736 return; 00737 } 00738 requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" : 00739 "Failure"; 00740 status = WPA_GET_BE16(result_tlv); 00741 if (status == EAP_TLV_RESULT_SUCCESS) { 00742 wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success " 00743 "- requested %s", requested); 00744 if (data->tlv_request == TLV_REQ_SUCCESS) 00745 eap_peap_state(data, SUCCESS); 00746 else 00747 eap_peap_state(data, FAILURE); 00748 00749 } else if (status == EAP_TLV_RESULT_FAILURE) { 00750 wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure " 00751 "- requested %s", requested); 00752 eap_peap_state(data, FAILURE); 00753 } else { 00754 wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result " 00755 "Status %d", status); 00756 eap_peap_state(data, FAILURE); 00757 } 00758 } 00759 } 00760 00761 00762 #ifdef EAP_SERVER_TNC 00763 static void eap_peap_process_phase2_soh(struct eap_sm *sm, 00764 struct eap_peap_data *data, 00765 struct wpabuf *in_data) 00766 { 00767 const u8 *pos, *vpos; 00768 size_t left; 00769 const u8 *soh_tlv = NULL; 00770 size_t soh_tlv_len = 0; 00771 int tlv_type, mandatory, tlv_len, vtlv_len; 00772 u8 next_type; 00773 u32 vendor_id; 00774 00775 pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left); 00776 if (pos == NULL) { 00777 wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP " 00778 "Extensions Method header - skip TNC"); 00779 goto auth_method; 00780 } 00781 00782 /* Parse TLVs */ 00783 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left); 00784 while (left >= 4) { 00785 mandatory = !!(pos[0] & 0x80); 00786 tlv_type = pos[0] & 0x3f; 00787 tlv_type = (tlv_type << 8) | pos[1]; 00788 tlv_len = ((int) pos[2] << 8) | pos[3]; 00789 pos += 4; 00790 left -= 4; 00791 if ((size_t) tlv_len > left) { 00792 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " 00793 "(tlv_len=%d left=%lu)", tlv_len, 00794 (unsigned long) left); 00795 eap_peap_state(data, FAILURE); 00796 return; 00797 } 00798 switch (tlv_type) { 00799 case EAP_TLV_VENDOR_SPECIFIC_TLV: 00800 if (tlv_len < 4) { 00801 wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short " 00802 "vendor specific TLV (len=%d)", 00803 (int) tlv_len); 00804 eap_peap_state(data, FAILURE); 00805 return; 00806 } 00807 00808 vendor_id = WPA_GET_BE32(pos); 00809 if (vendor_id != EAP_VENDOR_MICROSOFT) { 00810 if (mandatory) { 00811 eap_peap_state(data, FAILURE); 00812 return; 00813 } 00814 break; 00815 } 00816 00817 vpos = pos + 4; 00818 mandatory = !!(vpos[0] & 0x80); 00819 tlv_type = vpos[0] & 0x3f; 00820 tlv_type = (tlv_type << 8) | vpos[1]; 00821 vtlv_len = ((int) vpos[2] << 8) | vpos[3]; 00822 vpos += 4; 00823 if (vpos + vtlv_len > pos + left) { 00824 wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV " 00825 "underrun"); 00826 eap_peap_state(data, FAILURE); 00827 return; 00828 } 00829 00830 if (tlv_type == 1) { 00831 soh_tlv = vpos; 00832 soh_tlv_len = vtlv_len; 00833 break; 00834 } 00835 00836 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV " 00837 "Type %d%s", tlv_type, 00838 mandatory ? " (mandatory)" : ""); 00839 if (mandatory) { 00840 eap_peap_state(data, FAILURE); 00841 return; 00842 } 00843 /* Ignore this TLV, but process other TLVs */ 00844 break; 00845 default: 00846 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " 00847 "%d%s", tlv_type, 00848 mandatory ? " (mandatory)" : ""); 00849 if (mandatory) { 00850 eap_peap_state(data, FAILURE); 00851 return; 00852 } 00853 /* Ignore this TLV, but process other TLVs */ 00854 break; 00855 } 00856 00857 pos += tlv_len; 00858 left -= tlv_len; 00859 } 00860 if (left) { 00861 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " 00862 "Request (left=%lu)", (unsigned long) left); 00863 eap_peap_state(data, FAILURE); 00864 return; 00865 } 00866 00867 /* Process supported TLVs */ 00868 if (soh_tlv) { 00869 int failure = 0; 00870 wpabuf_free(data->soh_response); 00871 data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len, 00872 &failure); 00873 if (failure) { 00874 eap_peap_state(data, FAILURE); 00875 return; 00876 } 00877 } else { 00878 wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received"); 00879 eap_peap_state(data, FAILURE); 00880 return; 00881 } 00882 00883 auth_method: 00884 eap_peap_state(data, PHASE2_METHOD); 00885 next_type = sm->user->methods[0].method; 00886 sm->user_eap_method_index = 1; 00887 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type); 00888 eap_peap_phase2_init(sm, data, next_type); 00889 } 00890 #endif /* EAP_SERVER_TNC */ 00891 00892 00893 static void eap_peap_process_phase2_response(struct eap_sm *sm, 00894 struct eap_peap_data *data, 00895 struct wpabuf *in_data) 00896 { 00897 u8 next_type = EAP_TYPE_NONE; 00898 const struct eap_hdr *hdr; 00899 const u8 *pos; 00900 size_t left; 00901 00902 if (data->state == PHASE2_TLV) { 00903 eap_peap_process_phase2_tlv(sm, data, in_data); 00904 return; 00905 } 00906 00907 #ifdef EAP_SERVER_TNC 00908 if (data->state == PHASE2_SOH) { 00909 eap_peap_process_phase2_soh(sm, data, in_data); 00910 return; 00911 } 00912 #endif /* EAP_SERVER_TNC */ 00913 00914 if (data->phase2_priv == NULL) { 00915 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not " 00916 "initialized?!", __func__); 00917 return; 00918 } 00919 00920 hdr = wpabuf_head(in_data); 00921 pos = (const u8 *) (hdr + 1); 00922 00923 if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { 00924 left = wpabuf_len(in_data) - sizeof(*hdr); 00925 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; " 00926 "allowed types", pos + 1, left - 1); 00927 eap_sm_process_nak(sm, pos + 1, left - 1); 00928 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && 00929 sm->user->methods[sm->user_eap_method_index].method != 00930 EAP_TYPE_NONE) { 00931 next_type = sm->user->methods[ 00932 sm->user_eap_method_index++].method; 00933 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", 00934 next_type); 00935 } else { 00936 eap_peap_req_failure(sm, data); 00937 next_type = EAP_TYPE_NONE; 00938 } 00939 eap_peap_phase2_init(sm, data, next_type); 00940 return; 00941 } 00942 00943 if (data->phase2_method->check(sm, data->phase2_priv, in_data)) { 00944 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to " 00945 "ignore the packet"); 00946 return; 00947 } 00948 00949 data->phase2_method->process(sm, data->phase2_priv, in_data); 00950 00951 if (sm->method_pending == METHOD_PENDING_WAIT) { 00952 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in " 00953 "pending wait state - save decrypted response"); 00954 wpabuf_free(data->pending_phase2_resp); 00955 data->pending_phase2_resp = wpabuf_dup(in_data); 00956 } 00957 00958 if (!data->phase2_method->isDone(sm, data->phase2_priv)) 00959 return; 00960 00961 if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) { 00962 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed"); 00963 eap_peap_req_failure(sm, data); 00964 next_type = EAP_TYPE_NONE; 00965 eap_peap_phase2_init(sm, data, next_type); 00966 return; 00967 } 00968 00969 os_free(data->phase2_key); 00970 if (data->phase2_method->getKey) { 00971 data->phase2_key = data->phase2_method->getKey( 00972 sm, data->phase2_priv, &data->phase2_key_len); 00973 if (data->phase2_key == NULL) { 00974 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey " 00975 "failed"); 00976 eap_peap_req_failure(sm, data); 00977 eap_peap_phase2_init(sm, data, EAP_TYPE_NONE); 00978 return; 00979 } 00980 } 00981 00982 switch (data->state) { 00983 case PHASE1_ID2: 00984 case PHASE2_ID: 00985 case PHASE2_SOH: 00986 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { 00987 wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 " 00988 "Identity not found in the user " 00989 "database", 00990 sm->identity, sm->identity_len); 00991 eap_peap_req_failure(sm, data); 00992 next_type = EAP_TYPE_NONE; 00993 break; 00994 } 00995 00996 #ifdef EAP_SERVER_TNC 00997 if (data->state != PHASE2_SOH && sm->tnc && 00998 data->peap_version == 0) { 00999 eap_peap_state(data, PHASE2_SOH); 01000 wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize " 01001 "TNC (NAP SOH)"); 01002 next_type = EAP_TYPE_NONE; 01003 break; 01004 } 01005 #endif /* EAP_SERVER_TNC */ 01006 01007 eap_peap_state(data, PHASE2_METHOD); 01008 next_type = sm->user->methods[0].method; 01009 sm->user_eap_method_index = 1; 01010 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type); 01011 break; 01012 case PHASE2_METHOD: 01013 eap_peap_req_success(sm, data); 01014 next_type = EAP_TYPE_NONE; 01015 break; 01016 case FAILURE: 01017 break; 01018 default: 01019 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", 01020 __func__, data->state); 01021 break; 01022 } 01023 01024 eap_peap_phase2_init(sm, data, next_type); 01025 } 01026 01027 01028 static void eap_peap_process_phase2(struct eap_sm *sm, 01029 struct eap_peap_data *data, 01030 const struct wpabuf *respData, 01031 struct wpabuf *in_buf) 01032 { 01033 struct wpabuf *in_decrypted; 01034 const struct eap_hdr *hdr; 01035 size_t len; 01036 01037 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" 01038 " Phase 2", (unsigned long) wpabuf_len(in_buf)); 01039 01040 if (data->pending_phase2_resp) { 01041 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - " 01042 "skip decryption and use old data"); 01043 eap_peap_process_phase2_response(sm, data, 01044 data->pending_phase2_resp); 01045 wpabuf_free(data->pending_phase2_resp); 01046 data->pending_phase2_resp = NULL; 01047 return; 01048 } 01049 01050 in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, 01051 in_buf); 01052 if (in_decrypted == NULL) { 01053 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 " 01054 "data"); 01055 eap_peap_state(data, FAILURE); 01056 return; 01057 } 01058 01059 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", 01060 in_decrypted); 01061 01062 hdr = wpabuf_head(in_decrypted); 01063 01064 if (data->peap_version == 0 && data->state != PHASE2_TLV) { 01065 const struct eap_hdr *resp; 01066 struct eap_hdr *nhdr; 01067 struct wpabuf *nbuf = 01068 wpabuf_alloc(sizeof(struct eap_hdr) + 01069 wpabuf_len(in_decrypted)); 01070 if (nbuf == NULL) { 01071 wpabuf_free(in_decrypted); 01072 return; 01073 } 01074 01075 resp = wpabuf_head(respData); 01076 nhdr = wpabuf_put(nbuf, sizeof(*nhdr)); 01077 nhdr->code = resp->code; 01078 nhdr->identifier = resp->identifier; 01079 nhdr->length = host_to_be16(sizeof(struct eap_hdr) + 01080 wpabuf_len(in_decrypted)); 01081 wpabuf_put_buf(nbuf, in_decrypted); 01082 wpabuf_free(in_decrypted); 01083 01084 in_decrypted = nbuf; 01085 } else if (data->peap_version >= 2) { 01086 struct eap_tlv_hdr *tlv; 01087 struct wpabuf *nmsg; 01088 01089 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) { 01090 wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 " 01091 "EAP TLV"); 01092 wpabuf_free(in_decrypted); 01093 return; 01094 } 01095 tlv = wpabuf_mhead(in_decrypted); 01096 if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) != 01097 EAP_TLV_EAP_PAYLOAD_TLV) { 01098 wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV"); 01099 wpabuf_free(in_decrypted); 01100 return; 01101 } 01102 if (sizeof(*tlv) + be_to_host16(tlv->length) > 01103 wpabuf_len(in_decrypted)) { 01104 wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV " 01105 "length"); 01106 wpabuf_free(in_decrypted); 01107 return; 01108 } 01109 hdr = (struct eap_hdr *) (tlv + 1); 01110 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) { 01111 wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full " 01112 "EAP packet in EAP TLV"); 01113 wpabuf_free(in_decrypted); 01114 return; 01115 } 01116 01117 nmsg = wpabuf_alloc(be_to_host16(hdr->length)); 01118 if (nmsg == NULL) { 01119 wpabuf_free(in_decrypted); 01120 return; 01121 } 01122 01123 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length)); 01124 wpabuf_free(in_decrypted); 01125 in_decrypted = nmsg; 01126 } 01127 01128 hdr = wpabuf_head(in_decrypted); 01129 if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) { 01130 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " 01131 "EAP frame (len=%lu)", 01132 (unsigned long) wpabuf_len(in_decrypted)); 01133 wpabuf_free(in_decrypted); 01134 eap_peap_req_failure(sm, data); 01135 return; 01136 } 01137 len = be_to_host16(hdr->length); 01138 if (len > wpabuf_len(in_decrypted)) { 01139 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " 01140 "Phase 2 EAP frame (len=%lu hdr->length=%lu)", 01141 (unsigned long) wpabuf_len(in_decrypted), 01142 (unsigned long) len); 01143 wpabuf_free(in_decrypted); 01144 eap_peap_req_failure(sm, data); 01145 return; 01146 } 01147 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " 01148 "identifier=%d length=%lu", hdr->code, hdr->identifier, 01149 (unsigned long) len); 01150 switch (hdr->code) { 01151 case EAP_CODE_RESPONSE: 01152 eap_peap_process_phase2_response(sm, data, in_decrypted); 01153 break; 01154 case EAP_CODE_SUCCESS: 01155 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); 01156 if (data->state == SUCCESS_REQ) { 01157 eap_peap_state(data, SUCCESS); 01158 } 01159 break; 01160 case EAP_CODE_FAILURE: 01161 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); 01162 eap_peap_state(data, FAILURE); 01163 break; 01164 default: 01165 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " 01166 "Phase 2 EAP header", hdr->code); 01167 break; 01168 } 01169 01170 wpabuf_free(in_decrypted); 01171 } 01172 01173 01174 static int eap_peapv2_start_phase2(struct eap_sm *sm, 01175 struct eap_peap_data *data) 01176 { 01177 struct wpabuf *buf, *buf2; 01178 01179 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 " 01180 "payload in the same message"); 01181 eap_peap_state(data, PHASE1_ID2); 01182 if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY)) 01183 return -1; 01184 01185 /* TODO: which Id to use here? */ 01186 buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6); 01187 if (buf == NULL) 01188 return -1; 01189 01190 buf2 = eap_peapv2_tlv_eap_payload(buf); 01191 if (buf2 == NULL) 01192 return -1; 01193 01194 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2); 01195 01196 buf = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, 01197 buf2); 01198 wpabuf_free(buf2); 01199 01200 if (buf == NULL) { 01201 wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 " 01202 "data"); 01203 return -1; 01204 } 01205 01206 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request", 01207 buf); 01208 01209 /* Append TLS data into the pending buffer after the Server Finished */ 01210 if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(buf)) < 0) { 01211 wpabuf_free(buf); 01212 return -1; 01213 } 01214 wpabuf_put_buf(data->ssl.tls_out, buf); 01215 wpabuf_free(buf); 01216 01217 return 0; 01218 } 01219 01220 01221 static int eap_peap_process_version(struct eap_sm *sm, void *priv, 01222 int peer_version) 01223 { 01224 struct eap_peap_data *data = priv; 01225 01226 data->recv_version = peer_version; 01227 if (data->force_version >= 0 && peer_version != data->force_version) { 01228 wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced" 01229 " version (forced=%d peer=%d) - reject", 01230 data->force_version, peer_version); 01231 return -1; 01232 } 01233 if (peer_version < data->peap_version) { 01234 wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; " 01235 "use version %d", 01236 peer_version, data->peap_version, peer_version); 01237 data->peap_version = peer_version; 01238 } 01239 01240 return 0; 01241 } 01242 01243 01244 static void eap_peap_process_msg(struct eap_sm *sm, void *priv, 01245 const struct wpabuf *respData) 01246 { 01247 struct eap_peap_data *data = priv; 01248 01249 switch (data->state) { 01250 case PHASE1: 01251 if (eap_server_tls_phase1(sm, &data->ssl) < 0) { 01252 eap_peap_state(data, FAILURE); 01253 break; 01254 } 01255 01256 if (data->peap_version >= 2 && 01257 tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 01258 if (eap_peapv2_start_phase2(sm, data)) { 01259 eap_peap_state(data, FAILURE); 01260 break; 01261 } 01262 } 01263 break; 01264 case PHASE2_START: 01265 eap_peap_state(data, PHASE2_ID); 01266 eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY); 01267 break; 01268 case PHASE1_ID2: 01269 case PHASE2_ID: 01270 case PHASE2_METHOD: 01271 case PHASE2_SOH: 01272 case PHASE2_TLV: 01273 eap_peap_process_phase2(sm, data, respData, data->ssl.tls_in); 01274 break; 01275 case SUCCESS_REQ: 01276 eap_peap_state(data, SUCCESS); 01277 break; 01278 case FAILURE_REQ: 01279 eap_peap_state(data, FAILURE); 01280 break; 01281 default: 01282 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s", 01283 data->state, __func__); 01284 break; 01285 } 01286 } 01287 01288 01289 static void eap_peap_process(struct eap_sm *sm, void *priv, 01290 struct wpabuf *respData) 01291 { 01292 struct eap_peap_data *data = priv; 01293 if (eap_server_tls_process(sm, &data->ssl, respData, data, 01294 EAP_TYPE_PEAP, eap_peap_process_version, 01295 eap_peap_process_msg) < 0) 01296 eap_peap_state(data, FAILURE); 01297 } 01298 01299 01300 static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv) 01301 { 01302 struct eap_peap_data *data = priv; 01303 return data->state == SUCCESS || data->state == FAILURE; 01304 } 01305 01306 01307 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) 01308 { 01309 struct eap_peap_data *data = priv; 01310 u8 *eapKeyData; 01311 01312 if (data->state != SUCCESS) 01313 return NULL; 01314 01315 if (data->crypto_binding_used) { 01316 u8 csk[128]; 01317 /* 01318 * Note: It looks like Microsoft implementation requires null 01319 * termination for this label while the one used for deriving 01320 * IPMK|CMK did not use null termination. 01321 */ 01322 peap_prfplus(data->peap_version, data->ipmk, 40, 01323 "Session Key Generating Function", 01324 (u8 *) "\00", 1, csk, sizeof(csk)); 01325 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); 01326 eapKeyData = os_malloc(EAP_TLS_KEY_LEN); 01327 if (eapKeyData) { 01328 os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN); 01329 *len = EAP_TLS_KEY_LEN; 01330 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", 01331 eapKeyData, EAP_TLS_KEY_LEN); 01332 } else { 01333 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive " 01334 "key"); 01335 } 01336 01337 return eapKeyData; 01338 } 01339 01340 /* TODO: PEAPv1 - different label in some cases */ 01341 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, 01342 "client EAP encryption", 01343 EAP_TLS_KEY_LEN); 01344 if (eapKeyData) { 01345 *len = EAP_TLS_KEY_LEN; 01346 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", 01347 eapKeyData, EAP_TLS_KEY_LEN); 01348 } else { 01349 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key"); 01350 } 01351 01352 return eapKeyData; 01353 } 01354 01355 01356 static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv) 01357 { 01358 struct eap_peap_data *data = priv; 01359 return data->state == SUCCESS; 01360 } 01361 01362 01363 int eap_server_peap_register(void) 01364 { 01365 struct eap_method *eap; 01366 int ret; 01367 01368 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 01369 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); 01370 if (eap == NULL) 01371 return -1; 01372 01373 eap->init = eap_peap_init; 01374 eap->reset = eap_peap_reset; 01375 eap->buildReq = eap_peap_buildReq; 01376 eap->check = eap_peap_check; 01377 eap->process = eap_peap_process; 01378 eap->isDone = eap_peap_isDone; 01379 eap->getKey = eap_peap_getKey; 01380 eap->isSuccess = eap_peap_isSuccess; 01381 01382 ret = eap_server_method_register(eap); 01383 if (ret) 01384 eap_server_method_free(eap); 01385 return ret; 01386 }