18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_tls_common.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_tlv_common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_peap_common.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tncs.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Maximum supported PEAP version 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_PEAP_VERSION 1 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_reset(struct eap_sm *sm, void *priv); 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_peap_data { 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data ssl; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID, 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PHASE2_METHOD, PHASE2_SOH, 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } state; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int peap_version; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int recv_version; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_method *phase2_method; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *phase2_priv; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int force_version; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *pending_phase2_resp; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int crypto_binding_sent; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int crypto_binding_used; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 binding_nonce[32]; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ipmk[40]; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 cmk[20]; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *phase2_key; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t phase2_key_len; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *soh_response; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_peap_state_txt(int state) 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "START"; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE1: 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PHASE1"; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE1_ID2: 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PHASE1_ID2"; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_START: 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PHASE2_START"; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_ID: 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PHASE2_ID"; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_METHOD: 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PHASE2_METHOD"; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_SOH: 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PHASE2_SOH"; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_TLV: 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PHASE2_TLV"; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS_REQ: 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "SUCCESS_REQ"; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE_REQ: 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAILURE_REQ"; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS: 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "SUCCESS"; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAILURE"; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Unknown?!"; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_state(struct eap_peap_data *data, int state) 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s", 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state_txt(data->state), 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state_txt(state)); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 98d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (state == FAILURE || state == FAILURE_REQ) 99d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt tls_connection_remove_session(data->ssl.conn); 100d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt} 101d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 102d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 103d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void eap_peap_valid_session(struct eap_sm *sm, 104d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct eap_peap_data *data) 105d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{ 106d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct wpabuf *buf; 107d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 108d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (!sm->tls_session_lifetime || 109d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) 110d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 111d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 112d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt buf = wpabuf_alloc(1 + 1 + sm->identity_len); 113d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (!buf) 114d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 115d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpabuf_put_u8(buf, EAP_TYPE_PEAP); 116d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (sm->identity) { 117d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt u8 id_len; 118d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 119d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (sm->identity_len <= 255) 120d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt id_len = sm->identity_len; 121d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt else 122d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt id_len = 255; 123d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpabuf_put_u8(buf, id_len); 124d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpabuf_put_data(buf, sm->identity, id_len); 125d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } else { 126d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpabuf_put_u8(buf, 0); 127d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 128d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt tls_connection_set_success_data(data->ssl.conn, buf); 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_req_success(struct eap_sm *sm, 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data) 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == FAILURE || data->state == FAILURE_REQ) { 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version == 0) { 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tlv_request = TLV_REQ_SUCCESS; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, PHASE2_TLV); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, SUCCESS_REQ); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_req_failure(struct eap_sm *sm, 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data) 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == FAILURE || data->state == FAILURE_REQ || 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state == SUCCESS_REQ || data->tlv_request != TLV_REQ_NONE) { 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version == 0) { 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tlv_request = TLV_REQ_FAILURE; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, PHASE2_TLV); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE_REQ); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_peap_init(struct eap_sm *sm) 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version = EAP_PEAP_VERSION; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->force_version = -1; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user && sm->user->force_version >= 0) { 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->force_version = sm->user->force_version; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d", 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->force_version); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version = data->force_version; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = START; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->crypto_binding = OPTIONAL_BINDING; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 185d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_TYPE_PEAP)) { 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_reset(sm, data); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_reset(struct eap_sm *sm, void *priv) 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv && data->phase2_method) 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->reset(sm, data->phase2_priv); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_tls_ssl_deinit(sm, &data->ssl); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_resp); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->phase2_key); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->soh_response); 206c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt bin_clear_free(data, sizeof(*data)); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_peap_build_start(struct eap_sm *sm, 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, u8 id) 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1, 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_REQUEST, id); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for" 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " request"); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, PHASE1); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return req; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm, 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf, *encr_req, msgbuf; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *req; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t req_len; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_method == NULL || data->phase2_priv == NULL) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 method not ready"); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = data->phase2_method->buildReq(sm, data->phase2_priv, id); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = wpabuf_head(buf); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req_len = wpabuf_len(buf); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req, req_len); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version == 0 && 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->method != EAP_TYPE_TLV) { 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req += sizeof(struct eap_hdr); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req_len -= sizeof(struct eap_hdr); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&msgbuf, req, req_len); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return encr_req; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm, 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf1, *buf, *encr_req, msgbuf; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *req; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t req_len; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf1 = tncs_build_soh_request(); 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf1 == NULL) 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = eap_msg_alloc(EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf1), 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_REQUEST, id); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf1); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(buf, buf1); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf1); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = wpabuf_head(buf); 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req_len = wpabuf_len(buf); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 SOH data", 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req, req_len); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req += sizeof(struct eap_hdr); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req_len -= sizeof(struct eap_hdr); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&msgbuf, req, req_len); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return encr_req; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */ 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_get_isk(struct eap_peap_data *data, 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *isk, size_t isk_len) 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t key_len; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(isk, 0, isk_len); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_key == NULL) 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = data->phase2_key_len; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_len > isk_len) 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = isk_len; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(isk, data->phase2_key, key_len); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *tk; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 isk[32], imck[60]; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Tunnel key (TK) is the first 60 octets of the key generated by 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * phase 1 of PEAP (based on TLS). 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption", 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TLS_KEY_LEN); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tk == NULL) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3387d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { 3397d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt /* Fast-connect: IPMK|CMK = TK */ 3407d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt os_memcpy(data->ipmk, tk, 40); 3417d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK", 3427d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt data->ipmk, 40); 3437d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt os_memcpy(data->cmk, tk + 40, 20); 3447d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK", 3457d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt data->cmk, 20); 3467d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt os_free(tk); 3477d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt return 0; 3487d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt } 3497d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_get_isk(data, isk, sizeof(isk)); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk)); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IPMK Seed = "Inner Methods Compound Keys" | ISK 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TempKey = First 40 octets of TK 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60) 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in the end of the label just before ISK; is that just a typo?) 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); 3611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (peap_prfplus(data->peap_version, tk, 40, 3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Inner Methods Compound Keys", 3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt isk, sizeof(isk), imck, sizeof(imck)) < 0) { 3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(tk); 3651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt imck, sizeof(imck)); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(tk); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->ipmk, imck, 40); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40); 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->cmk, imck + 40, 20); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm, 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf, *encr_req; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mlen; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlen = 6; /* Result TLV */ 389216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS && 390216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt data->crypto_binding != NO_BINDING) { 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlen += 60; /* Cryptobinding TLV */ 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC 393216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (data->soh_response) 394216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt mlen += wpabuf_len(data->soh_response); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */ 396216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, mlen, 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_REQUEST, id); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, 0x80); /* Mandatory */ 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Length */ 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(buf, 2); 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Status */ 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ? 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE); 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS && 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->crypto_binding != NO_BINDING) { 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mac; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 eap_type = EAP_TYPE_PEAP; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[2]; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 tlv_type; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->soh_response) { 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH " 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Response TLV"); 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(buf, data->soh_response); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->soh_response); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->soh_response = NULL; 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */ 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peap_derive_cmk(sm, data) < 0 || 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_get_bytes(data->binding_nonce, 32)) { 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = wpabuf_put(buf, 0); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = 60; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = &eap_type; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 1; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(buf, tlv_type); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(buf, 56); 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, 0); /* Reserved */ 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, data->peap_version); /* Version */ 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */ 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */ 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mac = wpabuf_put(buf, 20); /* Compound_MAC */ 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->cmk, 20); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0], len[0]); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1], len[1]); 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mac, SHA1_MAC_LEN); 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->crypto_binding_sent = 1; 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data", 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf); 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return encr_req; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm, 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, int success) 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *encr_req, msgbuf; 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t req_len; 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req_len = sizeof(*hdr); 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = os_zalloc(req_len); 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr == NULL) 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->identifier = id; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->length = host_to_be16(req_len); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) hdr, req_len); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&msgbuf, hdr, req_len); 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return encr_req; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id) 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->ssl.state == FRAG_ACK) { 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_server_tls_build_ack(id, EAP_TYPE_PEAP, 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version); 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->ssl.state == WAIT_FRAG_ACK) { 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version, id); 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_peap_build_start(sm, data, id); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE1: 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE1_ID2: 520fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, " 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "starting Phase2"); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, PHASE2_START); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_ID: 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_METHOD: 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->ssl.tls_out); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out_pos = 0; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out = eap_peap_build_phase2_req(sm, data, id); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_SOH: 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->ssl.tls_out); 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out_pos = 0; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out = eap_peap_build_phase2_soh(sm, data, id); 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */ 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_TLV: 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->ssl.tls_out); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out_pos = 0; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out = eap_peap_build_phase2_tlv(sm, data, id); 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS_REQ: 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->ssl.tls_out); 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out_pos = 0; 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id, 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE_REQ: 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->ssl.tls_out); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out_pos = 0; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id, 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, data->state); 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version, id); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_peap_check(struct eap_sm *sm, void *priv, 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 1) { 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame"); 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data, 584af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt int vendor, EapType eap_type) 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv && data->phase2_method) { 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->reset(sm, data->phase2_priv); 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method = NULL; 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_priv = NULL; 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 591af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt data->phase2_method = eap_server_get_eap_method(vendor, eap_type); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->phase2_method) 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->init_phase2 = 1; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_priv = data->phase2_method->init(sm); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->init_phase2 = 0; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tlv_validate_cryptobinding(struct eap_sm *sm, 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *crypto_tlv, 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t crypto_tlv_len) 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[61], mac[SHA1_MAC_LEN]; 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_tlv_len != 4 + 56) { 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length %d", (int) crypto_tlv_len); 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = crypto_tlv; 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; /* TLV header */ 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[1] != data->peap_version) { 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "mismatch (was %d; expected %d)", 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos[1], data->peap_version); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[3] != 1) { 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SubType %d", pos[3]); 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 32; /* Nonce */ 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, crypto_tlv, 60); 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[60] = EAP_TYPE_PEAP; 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 639c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(mac, pos, SHA1_MAC_LEN) != 0) { 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "cryptobinding TLV"); 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20); 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data", 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, 61); 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_process_phase2_tlv(struct eap_sm *sm, 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_data) 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *result_tlv = NULL, *crypto_tlv = NULL; 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t result_tlv_len = 0, crypto_tlv_len = 0; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tlv_type, mandatory, tlv_len; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left); 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) { 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header"); 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Parse TLVs */ 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left); 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left >= 4) { 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mandatory = !!(pos[0] & 0x80); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_type = pos[0] & 0x3f; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_type = (tlv_type << 8) | pos[1]; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_len = ((int) pos[2] << 8) | pos[3]; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 4; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((size_t) tlv_len > left) { 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(tlv_len=%d left=%lu)", tlv_len, 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) left); 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (tlv_type) { 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TLV_RESULT_TLV: 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt result_tlv = pos; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt result_tlv_len = tlv_len; 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TLV_CRYPTO_BINDING_TLV: 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_tlv = pos; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_tlv_len = tlv_len; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d%s", tlv_type, 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mandatory ? " (mandatory)" : ""); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mandatory) { 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Ignore this TLV, but process other TLVs */ 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += tlv_len; 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= tlv_len; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left) { 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Request (left=%lu)", (unsigned long) left); 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process supported TLVs */ 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_tlv && data->crypto_binding_sent) { 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_tlv, crypto_tlv_len); 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_tlv_len + 4) < 0) { 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->crypto_binding_used = 1; 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!crypto_tlv && data->crypto_binding_sent && 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->crypto_binding == REQUIRE_BINDING) { 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (result_tlv) { 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int status; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *requested; 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV", 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt result_tlv, result_tlv_len); 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (result_tlv_len < 2) { 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV " 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(len=%lu)", 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) result_tlv_len); 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" : 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Failure"; 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WPA_GET_BE16(result_tlv); 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status == EAP_TLV_RESULT_SUCCESS) { 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success " 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- requested %s", requested); 753d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (data->tlv_request == TLV_REQ_SUCCESS) { 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, SUCCESS); 755d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eap_peap_valid_session(sm, data); 756d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } else { 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 758d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (status == EAP_TLV_RESULT_FAILURE) { 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure " 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- requested %s", requested); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result " 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Status %d", status); 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_process_phase2_soh(struct eap_sm *sm, 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_data) 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *vpos; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *soh_tlv = NULL; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t soh_tlv_len = 0; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tlv_type, mandatory, tlv_len, vtlv_len; 783af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt u32 next_type; 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 vendor_id; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left); 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) { 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP " 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Extensions Method header - skip TNC"); 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto auth_method; 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Parse TLVs */ 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left); 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left >= 4) { 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mandatory = !!(pos[0] & 0x80); 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_type = pos[0] & 0x3f; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_type = (tlv_type << 8) | pos[1]; 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_len = ((int) pos[2] << 8) | pos[3]; 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 4; 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((size_t) tlv_len > left) { 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(tlv_len=%d left=%lu)", tlv_len, 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) left); 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (tlv_type) { 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TLV_VENDOR_SPECIFIC_TLV: 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlv_len < 4) { 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short " 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "vendor specific TLV (len=%d)", 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) tlv_len); 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor_id = WPA_GET_BE32(pos); 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vendor_id != EAP_VENDOR_MICROSOFT) { 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mandatory) { 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vpos = pos + 4; 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mandatory = !!(vpos[0] & 0x80); 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_type = vpos[0] & 0x3f; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_type = (tlv_type << 8) | vpos[1]; 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vtlv_len = ((int) vpos[2] << 8) | vpos[3]; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vpos += 4; 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vpos + vtlv_len > pos + left) { 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV " 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "underrun"); 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlv_type == 1) { 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt soh_tlv = vpos; 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt soh_tlv_len = vtlv_len; 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV " 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Type %d%s", tlv_type, 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mandatory ? " (mandatory)" : ""); 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mandatory) { 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Ignore this TLV, but process other TLVs */ 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d%s", tlv_type, 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mandatory ? " (mandatory)" : ""); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mandatory) { 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Ignore this TLV, but process other TLVs */ 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += tlv_len; 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= tlv_len; 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left) { 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Request (left=%lu)", (unsigned long) left); 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process supported TLVs */ 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (soh_tlv) { 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int failure = 0; 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->soh_response); 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len, 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &failure); 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (failure) { 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received"); 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtauth_method: 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, PHASE2_METHOD); 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = sm->user->methods[0].method; 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user_eap_method_index = 1; 898af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type %d", 899af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt sm->user->methods[0].vendor, next_type); 900af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt eap_peap_phase2_init(sm, data, sm->user->methods[0].vendor, next_type); 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */ 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_process_phase2_response(struct eap_sm *sm, 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_data) 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 909af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt int next_vendor = EAP_VENDOR_IETF; 910af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt u32 next_type = EAP_TYPE_NONE; 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_hdr *hdr; 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == PHASE2_TLV) { 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_process_phase2_tlv(sm, data, in_data); 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == PHASE2_SOH) { 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_process_phase2_soh(sm, data, in_data); 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */ 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv == NULL) { 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not " 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialized?!", __func__); 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = wpabuf_head(in_data); 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (hdr + 1); 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = wpabuf_len(in_data) - sizeof(*hdr); 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; " 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "allowed types", pos + 1, left - 1); 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_process_nak(sm, pos + 1, left - 1); 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && 942af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt (sm->user->methods[sm->user_eap_method_index].vendor != 943af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt EAP_VENDOR_IETF || 944af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt sm->user->methods[sm->user_eap_method_index].method != 945af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt EAP_TYPE_NONE)) { 946af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt next_vendor = sm->user->methods[ 947af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt sm->user_eap_method_index].vendor; 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = sm->user->methods[ 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user_eap_method_index++].method; 950af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt wpa_printf(MSG_DEBUG, 951af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt "EAP-PEAP: try EAP vendor %d type 0x%x", 952af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt next_vendor, next_type); 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_req_failure(sm, data); 955af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt next_vendor = EAP_VENDOR_IETF; 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = EAP_TYPE_NONE; 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 958af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt eap_peap_phase2_init(sm, data, next_vendor, next_type); 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_method->check(sm, data->phase2_priv, in_data)) { 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to " 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignore the packet"); 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->process(sm, data->phase2_priv, in_data); 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->method_pending == METHOD_PENDING_WAIT) { 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in " 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pending wait state - save decrypted response"); 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_resp); 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_resp = wpabuf_dup(in_data); 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->phase2_method->isDone(sm, data->phase2_priv)) 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) { 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed"); 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_req_failure(sm, data); 983af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt next_vendor = EAP_VENDOR_IETF; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = EAP_TYPE_NONE; 985af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt eap_peap_phase2_init(sm, data, next_vendor, next_type); 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->phase2_key); 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_method->getKey) { 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_key = data->phase2_method->getKey( 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, data->phase2_priv, &data->phase2_key_len); 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_key == NULL) { 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey " 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed"); 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_req_failure(sm, data); 997af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF, 998af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt EAP_TYPE_NONE); 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE1_ID2: 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_ID: 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_SOH: 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 " 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Identity not found in the user " 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "database", 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, sm->identity_len); 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_req_failure(sm, data); 1013af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt next_vendor = EAP_VENDOR_IETF; 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = EAP_TYPE_NONE; 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PHASE2_SOH && sm->tnc && 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version == 0) { 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, PHASE2_SOH); 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize " 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TNC (NAP SOH)"); 1024af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt next_vendor = EAP_VENDOR_IETF; 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = EAP_TYPE_NONE; 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */ 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, PHASE2_METHOD); 1031af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt next_vendor = sm->user->methods[0].vendor; 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = sm->user->methods[0].method; 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user_eap_method_index = 1; 1034af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type 0x%x", 1035af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt next_vendor, next_type); 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_METHOD: 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_req_success(sm, data); 1039af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt next_vendor = EAP_VENDOR_IETF; 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = EAP_TYPE_NONE; 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, data->state); 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1050af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt eap_peap_phase2_init(sm, data, next_vendor, next_type); 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_process_phase2(struct eap_sm *sm, 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *respData, 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_buf) 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_decrypted; 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_hdr *hdr; 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Phase 2", (unsigned long) wpabuf_len(in_buf)); 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->pending_phase2_resp) { 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - " 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "skip decryption and use old data"); 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_process_phase2_response(sm, data, 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_resp); 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_resp); 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_resp = NULL; 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_buf); 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_decrypted == NULL) { 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 " 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data"); 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted); 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version == 0 && data->state != PHASE2_TLV) { 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_hdr *resp; 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *nhdr; 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *nbuf = 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_alloc(sizeof(struct eap_hdr) + 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(in_decrypted)); 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nbuf == NULL) { 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = wpabuf_head(respData); 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nhdr = wpabuf_put(nbuf, sizeof(*nhdr)); 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nhdr->code = resp->code; 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nhdr->identifier = resp->identifier; 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nhdr->length = host_to_be16(sizeof(struct eap_hdr) + 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(in_decrypted)); 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(nbuf, in_decrypted); 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted = nbuf; 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = wpabuf_head(in_decrypted); 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) { 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP frame (len=%lu)", 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(in_decrypted)); 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_req_failure(sm, data); 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = be_to_host16(hdr->length); 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > wpabuf_len(in_decrypted)) { 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP frame (len=%lu hdr->length=%lu)", 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(in_decrypted), 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len); 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_req_failure(sm, data); 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "identifier=%d length=%lu", hdr->code, hdr->identifier, 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len); 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->code) { 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_RESPONSE: 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_process_phase2_response(sm, data, in_decrypted); 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_SUCCESS: 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == SUCCESS_REQ) { 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, SUCCESS); 1141d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eap_peap_valid_session(sm, data); 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_FAILURE: 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP header", hdr->code); 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peap_process_version(struct eap_sm *sm, void *priv, 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int peer_version) 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->recv_version = peer_version; 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->force_version >= 0 && peer_version != data->force_version) { 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced" 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " version (forced=%d peer=%d) - reject", 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->force_version, peer_version); 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer_version < data->peap_version) { 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; " 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "use version %d", 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_version, data->peap_version, peer_version); 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version = peer_version; 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_process_msg(struct eap_sm *sm, void *priv, 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *respData) 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE1: 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_server_tls_phase1(sm, &data->ssl) < 0) { 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_START: 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, PHASE2_ID); 1195af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF, 1196af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt EAP_TYPE_IDENTITY); 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE1_ID2: 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_ID: 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_METHOD: 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_SOH: 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_TLV: 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_process_phase2(sm, data, respData, data->ssl.tls_in); 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS_REQ: 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, SUCCESS); 1207d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eap_peap_valid_session(sm, data); 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE_REQ: 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s", 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state, __func__); 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_process(struct eap_sm *sm, void *priv, 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 1224d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt const struct wpabuf *buf; 1225d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt const u8 *pos; 1226d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt u8 id_len; 1227d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_server_tls_process(sm, &data->ssl, respData, data, 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TYPE_PEAP, eap_peap_process_version, 1230d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eap_peap_process_msg) < 0) { 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_state(data, FAILURE); 1232d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 1233d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1234d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1235d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (data->state == SUCCESS || 1236d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt !tls_connection_established(sm->ssl_ctx, data->ssl.conn) || 1237d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) 1238d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 1239d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1240d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt buf = tls_connection_get_success_data(data->ssl.conn); 1241d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (!buf || wpabuf_len(buf) < 2) { 1242d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1243d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "EAP-PEAP: No success data in resumed session - reject attempt"); 1244d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eap_peap_state(data, FAILURE); 1245d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 1246d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1247d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1248d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pos = wpabuf_head(buf); 1249d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (*pos != EAP_TYPE_PEAP) { 1250d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1251d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "EAP-PEAP: Resumed session for another EAP type (%u) - reject attempt", 1252d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt *pos); 1253d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eap_peap_state(data, FAILURE); 1254d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 1255d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1256d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1257d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pos++; 1258d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt id_len = *pos++; 1259d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Identity from cached session", 1260d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pos, id_len); 1261d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt os_free(sm->identity); 1262d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt sm->identity = os_malloc(id_len ? id_len : 1); 1263d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (!sm->identity) { 1264d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt sm->identity_len = 0; 1265d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eap_peap_state(data, FAILURE); 1266d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 1267d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1268d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1269d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt os_memcpy(sm->identity, pos, id_len); 1270d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt sm->identity_len = id_len; 1271d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1272d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { 1273d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Phase2 Identity not found in the user database", 1274d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt sm->identity, sm->identity_len); 1275d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eap_peap_state(data, FAILURE); 1276d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 1277d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1278d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1279d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1280d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "EAP-PEAP: Resuming previous session - skip Phase2"); 12817d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt eap_peap_req_success(sm, data); 12827d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (data->state == SUCCESS_REQ) 12837d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt tls_connection_set_success_data_resumed(data->ssl.conn); 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_peap_isDone(struct eap_sm *sm, void *priv) 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *eapKeyData; 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->crypto_binding_used) { 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 csk[128]; 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: It looks like Microsoft implementation requires null 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * termination for this label while the one used for deriving 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IPMK|CMK did not use null termination. 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (peap_prfplus(data->peap_version, data->ipmk, 40, 13101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Session Key Generating Function", 13111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (u8 *) "\00", 1, csk, sizeof(csk)) < 0) 13121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapKeyData = os_malloc(EAP_TLS_KEY_LEN); 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapKeyData) { 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN); 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_TLS_KEY_LEN; 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapKeyData, EAP_TLS_KEY_LEN); 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive " 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key"); 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eapKeyData; 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: PEAPv1 - different label in some cases */ 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "client EAP encryption", 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TLS_KEY_LEN); 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapKeyData) { 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_TLS_KEY_LEN; 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapKeyData, EAP_TLS_KEY_LEN); 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key"); 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eapKeyData; 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv) 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 13526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 13536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct eap_peap_data *data = priv; 13546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 13556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (data->state != SUCCESS) 13566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 13576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 13586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return eap_server_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_PEAP, 13596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt len); 13606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 13616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 13626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_peap_register(void) 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_peap_init; 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_peap_reset; 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_peap_buildReq; 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_peap_check; 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_peap_process; 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_peap_isDone; 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_peap_getKey; 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_peap_isSuccess; 13806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eap->getSessionId = eap_peap_get_session_id; 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13821d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt return eap_server_method_register(eap); 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1384