eap_peap.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_tlv_common.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_peap_common.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_tls_common.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_config.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tncc.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Maximum supported PEAP version 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_PEAP_VERSION 1 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_deinit(struct eap_sm *sm, void *priv); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_peap_data { 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data ssl; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int peap_version, force_peap_version, force_new_label; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_method *phase2_method; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *phase2_priv; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int phase2_success; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int phase2_eap_success; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int phase2_eap_started; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_type phase2_type; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_type *phase2_types; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_phase2_types; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-Success 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1 = reply with tunneled EAP-Success to inner 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-Success and expect AS to send outer 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (unencrypted) EAP-Success after this 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2 = reply with PEAP/TLS ACK to inner 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-Success and expect AS to send outer 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (unencrypted) EAP-Success after this */ 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int resuming; /* starting a resumed session */ 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reauth; /* reauthentication */ 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key_data; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *pending_phase2_req; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int crypto_binding_used; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 binding_nonce[32]; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ipmk[40]; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 cmk[20]; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP) 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is enabled. */ 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peap_parse_phase1(struct eap_peap_data *data, 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *phase1) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pos; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(phase1, "peapver="); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) { 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->force_peap_version = atoi(pos + 8); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version = data->force_peap_version; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version %d", 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->force_peap_version); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(phase1, "peaplabel=1")) { 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->force_new_label = 1; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for key " 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "derivation"); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(phase1, "peap_outer_success=0")) { 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_outer_success = 0; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate authentication on " 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "tunneled EAP-Success"); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strstr(phase1, "peap_outer_success=1")) { 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_outer_success = 1; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled EAP-Success " 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "after receiving tunneled EAP-Success"); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strstr(phase1, "peap_outer_success=2")) { 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_outer_success = 2; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK after " 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "receiving tunneled EAP-Success"); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(phase1, "crypto_binding=0")) { 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->crypto_binding = NO_BINDING; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Do not use cryptobinding"); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strstr(phase1, "crypto_binding=1")) { 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->crypto_binding = OPTIONAL_BINDING; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Optional cryptobinding"); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strstr(phase1, "crypto_binding=2")) { 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->crypto_binding = REQUIRE_BINDING; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding"); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(phase1, "tnc=soh2")) { 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->soh = 2; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled"); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strstr(phase1, "tnc=soh1")) { 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->soh = 1; 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 1 enabled"); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strstr(phase1, "tnc=soh")) { 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->soh = 2; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled"); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_peap_init(struct eap_sm *sm) 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peap_done = FALSE; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version = EAP_PEAP_VERSION; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->force_peap_version = -1; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_outer_success = 2; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->crypto_binding = OPTIONAL_BINDING; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config && config->phase1 && 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_parse_phase1(data, config->phase1) < 0) { 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_deinit(sm, data); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peer_select_phase2_methods(config, "auth=", 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->phase2_types, 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->num_phase2_types) < 0) { 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_deinit(sm, data); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type.vendor = EAP_VENDOR_IETF; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type.method = EAP_TYPE_NONE; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) { 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peap_deinit(sm, data); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_deinit(struct eap_sm *sm, void *priv) 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv && data->phase2_method) 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->deinit(sm, data->phase2_priv); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->phase2_types); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_ssl_deinit(sm, &data->ssl); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->key_data); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_req); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_tlv_build_nak - Build EAP-TLV NAK message 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the header 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nak_type: TLV type (EAP_TLV_*) 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This function builds an EAP-TLV NAK message. The caller is responsible for 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * freeing the returned buffer. 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type) 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10, 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, id); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, 0x80); /* Mandatory */ 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, EAP_TLV_NAK_TLV); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 6); /* Length */ 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be32(msg, 0); /* Vendor-Id */ 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, nak_type); /* NAK-Type */ 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data, 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *isk, size_t isk_len) 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t key_len; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(isk, 0, isk_len); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_method == NULL || data->phase2_priv == NULL || 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->isKeyAvailable == NULL || 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->getKey == NULL) 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) || 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key = data->phase2_method->getKey(sm, data->phase2_priv, 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &key_len)) == NULL) { 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not get key material " 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from Phase 2"); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_len > isk_len) 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = isk_len; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(isk, key, key_len); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(key); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *tk; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 isk[32], imck[60]; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Tunnel key (TK) is the first 60 octets of the key generated by 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * phase 1 of PEAP (based on TLS). 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tk = data->key_data; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tk == NULL) 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth && 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Fast-connect: IPMK|CMK = TK */ 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->ipmk, tk, 40); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK", 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ipmk, 40); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->cmk, tk + 40, 20); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK", 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->cmk, 20); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peap_get_isk(sm, data, isk, sizeof(isk)) < 0) 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk)); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IPMK Seed = "Inner Methods Compound Keys" | ISK 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TempKey = First 40 octets of TK 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60) 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in the end of the label just before ISK; is that just a typo?) 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); 2881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (peap_prfplus(data->peap_version, tk, 40, 2891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Inner Methods Compound Keys", 2901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt isk, sizeof(isk), imck, sizeof(imck)) < 0) 2911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt imck, sizeof(imck)); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->ipmk, imck, 40); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->cmk, imck + 40, 20); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tlv_add_cryptobinding(struct eap_sm *sm, 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf) 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mac; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 eap_type = EAP_TYPE_PEAP; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[2]; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 tlv_type; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = wpabuf_put(buf, 0); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = 60; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = &eap_type; 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 1; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version >= 2) 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_type |= EAP_TLV_TYPE_MANDATORY; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(buf, tlv_type); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(buf, 56); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, 0); /* Reserved */ 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, data->peap_version); /* Version */ 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, data->peap_version); /* RecvVersion */ 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, 1); /* SubType: 0 = Request, 1 = Response */ 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mac = wpabuf_put(buf, 20); /* Compound_MAC */ 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0], len[0]); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1], len[1]); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->crypto_binding_used = 1; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_tlv_build_result - Build EAP-TLV Result message 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the header 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE) 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This function builds an EAP-TLV Result message. The caller is responsible 3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * for freeing the returned buffer. 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_tlv_build_result(struct eap_sm *sm, 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int crypto_tlv_used, 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int id, u16 status) 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->crypto_binding == NO_BINDING) 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_tlv_used = 0; 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = 6; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_tlv_used) 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += 60; /* Cryptobinding TLV */ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len, 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, id); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, 0x80); /* Mandatory */ 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 2); /* Length */ 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, status); /* Status */ 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) { 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tlv_validate_cryptobinding(struct eap_sm *sm, 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *crypto_tlv, 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t crypto_tlv_len) 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[61], mac[SHA1_MAC_LEN]; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peap_derive_cmk(sm, data) < 0) { 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK"); 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_tlv_len != 4 + 56) { 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length %d", (int) crypto_tlv_len); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = crypto_tlv; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; /* TLV header */ 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[1] != data->peap_version) { 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "mismatch (was %d; expected %d)", 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos[1], data->peap_version); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[3] != 0) { 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SubType %d", pos[3]); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->binding_nonce, pos, 32); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 32; /* Nonce */ 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, crypto_tlv, 60); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[60] = EAP_TYPE_PEAP; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Compound_MAC data", 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, sizeof(buf)); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) { 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "cryptobinding TLV"); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received MAC", 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, SHA1_MAC_LEN); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Expected MAC", 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mac, SHA1_MAC_LEN); 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_tlv_process - Process a received EAP-TLV message and generate a response 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ret: Return values from EAP request validation and processing 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @req: EAP-TLV request to be processed. The caller must have validated that 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the buffer is large enough to contain full request (hdr->length bytes) and 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that the EAP type is EAP_TYPE_TLV. 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @resp: Buffer to return a pointer to the allocated response message. This 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * field should be initialized to %NULL before the call. The value will be 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * updated if a response message is generated. The caller is responsible for 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * freeing the allocated message. 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @force_failure: Force negotiation to fail 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data, 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *req, struct wpabuf **resp, 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int force_failure) 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left, tlv_len; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *result_tlv = NULL, *crypto_tlv = NULL; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t result_tlv_len = 0, crypto_tlv_len = 0; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tlv_type, mandatory; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Parse TLVs */ 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left >= 4) { 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mandatory = !!(pos[0] & 0x80); 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_type = WPA_GET_BE16(pos) & 0x3fff; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_len = WPA_GET_BE16(pos); 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 4; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlv_len > left) { 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun " 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(tlv_len=%lu left=%lu)", 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) tlv_len, 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) left); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (tlv_type) { 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TLV_RESULT_TLV: 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt result_tlv = pos; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt result_tlv_len = tlv_len; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TLV_CRYPTO_BINDING_TLV: 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_tlv = pos; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_tlv_len = tlv_len; 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type " 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d%s", tlv_type, 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mandatory ? " (mandatory)" : ""); 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mandatory) { 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* NAK TLV and ignore all TLVs in this packet. 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = eap_tlv_build_nak(eap_get_id(req), 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv_type); 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return *resp == NULL ? -1 : 0; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Ignore this TLV, but process other TLVs */ 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += tlv_len; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= tlv_len; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left) { 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in " 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Request (left=%lu)", (unsigned long) left); 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process supported TLVs */ 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_tlv && data->crypto_binding != NO_BINDING) { 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_tlv, crypto_tlv_len); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_tlv_len + 4) < 0) { 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (result_tlv == NULL) 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt force_failure = 1; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_tlv = NULL; /* do not include Cryptobinding TLV 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in response, if the received 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cryptobinding was invalid. */ 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!crypto_tlv && data->crypto_binding == REQUIRE_BINDING) { 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (result_tlv) { 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int status, resp_status; 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV", 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt result_tlv, result_tlv_len); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (result_tlv_len < 2) { 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV " 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(len=%lu)", 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) result_tlv_len); 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WPA_GET_BE16(result_tlv); 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status == EAP_TLV_RESULT_SUCCESS) { 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success " 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- EAP-TLV/Phase2 Completed"); 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (force_failure) { 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure" 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " - force failed Phase 2"); 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp_status = EAP_TLV_RESULT_FAILURE; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp_status = EAP_TLV_RESULT_SUCCESS; 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_UNCOND_SUCC; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (status == EAP_TLV_RESULT_FAILURE) { 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure"); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp_status = EAP_TLV_RESULT_FAILURE; 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result " 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Status %d", status); 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp_status = EAP_TLV_RESULT_FAILURE; 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = eap_tlv_build_result(sm, data, crypto_tlv != NULL, 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_get_id(req), resp_status); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf) 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *e; 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_tlv_hdr *tlv; 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Encapsulate EAP packet in EAP-Payload TLV */ 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV"); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf)); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (e == NULL) { 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory " 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for TLV encapsulation"); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv = wpabuf_put(e, sizeof(*tlv)); 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TLV_EAP_PAYLOAD_TLV); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv->length = host_to_be16(wpabuf_len(buf)); 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(e, buf); 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return e; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peap_phase2_request(struct eap_sm *sm, 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data, 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req, 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **resp) 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr = wpabuf_mhead(req); 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = be_to_host16(hdr->length); 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret iret; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len <= sizeof(struct eap_hdr)) { 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: too short " 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 request (len=%lu)", (unsigned long) len); 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos); 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (*pos) { 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TYPE_IDENTITY: 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TYPE_TLV: 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iret, 0, sizeof(iret)); 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_tlv_process(sm, data, &iret, req, resp, 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_started && 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !data->phase2_eap_success)) { 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iret.methodState == METHOD_DONE || 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iret.methodState == METHOD_MAY_CONT) { 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = iret.methodState; 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = iret.decision; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success = 1; 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TYPE_EXPANDED: 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->soh) { 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *epos; 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t eleft; 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt epos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req, &eleft); 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (epos) { 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-PEAP: SoH EAP Extensions"); 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = tncc_process_soh_request(data->soh, 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt epos, eleft); 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf) { 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = eap_msg_alloc( 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_MICROSOFT, 0x21, 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(buf), 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->identifier); 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*resp == NULL) { 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(*resp, buf); 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* fall through */ 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_type.vendor == EAP_VENDOR_IETF && 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type.method == EAP_TYPE_NONE) { 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < data->num_phase2_types; i++) { 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_types[i].vendor != 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF || 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_types[i].method != *pos) 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type.vendor = 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_types[i].vendor; 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type.method = 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_types[i].method; 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected " 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP vendor %d method %d", 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type.vendor, 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type.method); 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos != data->phase2_type.method || 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos == EAP_TYPE_NONE) { 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peer_tls_phase2_nak(data->phase2_types, 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_phase2_types, 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr, resp)) 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv == NULL) { 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method = eap_peer_get_eap_method( 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type.vendor, 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type.method); 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_method) { 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->init_phase2 = 1; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_priv = 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->init(sm); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->init_phase2 = 0; 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv == NULL || data->phase2_method == NULL) { 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize " 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP method %d", *pos); 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_started = 1; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iret, 0, sizeof(iret)); 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = data->phase2_method->process(sm, data->phase2_priv, 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &iret, req); 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((iret.methodState == METHOD_DONE || 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iret.methodState == METHOD_MAY_CONT) && 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (iret.decision == DECISION_UNCOND_SUCC || 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iret.decision == DECISION_COND_SUCC)) { 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_success = 1; 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success = 1; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*resp == NULL && 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (config->pending_req_identity || config->pending_req_password || 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->pending_req_otp || config->pending_req_new_password)) { 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_req); 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data, 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_hdr *req, 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_decrypted = NULL; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res, skip_change = 0; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr, *rhdr; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp = NULL; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Phase 2", (unsigned long) wpabuf_len(in_data)); 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->pending_phase2_req) { 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - " 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "skip decryption and use old data"); 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Clear TLS reassembly state. */ 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(&data->ssl); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted = data->pending_phase2_req; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_req = NULL; 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt skip_change = 1; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto continue_req; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(in_data) == 0 && sm->workaround && 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success) { 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Cisco ACS seems to be using TLS ACK to terminate 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-PEAPv0/GTC. Try to reply with TLS ACK. 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but " 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "expected data - acknowledge with TLS ACK since " 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 has been completed"); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_COND_SUCC; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wpabuf_len(in_data) == 0) { 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Received TLS ACK - requesting more fragments */ 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version, 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->identifier, NULL, out_data); 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtcontinue_req: 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = wpabuf_mhead(in_decrypted); 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(in_decrypted) == 5 && hdr->code == EAP_CODE_REQUEST && 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be_to_host16(hdr->length) == 5 && 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_get_type(in_decrypted) == EAP_TYPE_IDENTITY) { 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* At least FreeRADIUS seems to send full EAP header with 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP Request Identity */ 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt skip_change = 1; 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(in_decrypted) >= 5 && hdr->code == EAP_CODE_REQUEST && 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_get_type(in_decrypted) == EAP_TYPE_TLV) { 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt skip_change = 1; 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version == 0 && !skip_change) { 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *nhdr; 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) + 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(in_decrypted)); 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nmsg == NULL) { 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nhdr = wpabuf_put(nmsg, sizeof(*nhdr)); 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(nmsg, in_decrypted); 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nhdr->code = req->code; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nhdr->identifier = req->identifier; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nhdr->length = host_to_be16(sizeof(struct eap_hdr) + 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(in_decrypted)); 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted = nmsg; 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version >= 2) { 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_tlv_hdr *tlv; 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *nmsg; 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) { 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 " 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP TLV"); 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlv = wpabuf_mhead(in_decrypted); 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((be_to_host16(tlv->tlv_type) & 0x3fff) != 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TLV_EAP_PAYLOAD_TLV) { 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV"); 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sizeof(*tlv) + be_to_host16(tlv->length) > 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(in_decrypted)) { 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV " 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length"); 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct eap_hdr *) (tlv + 1); 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) { 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full " 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP packet in EAP TLV"); 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nmsg = wpabuf_alloc(be_to_host16(hdr->length)); 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nmsg == NULL) { 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length)); 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted = nmsg; 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = wpabuf_mhead(in_decrypted); 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(in_decrypted) < sizeof(*hdr)) { 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP frame (len=%lu)", 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(in_decrypted)); 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = be_to_host16(hdr->length); 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > wpabuf_len(in_decrypted)) { 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP frame (len=%lu hdr->length=%lu)", 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(in_decrypted), 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len); 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < wpabuf_len(in_decrypted)) { 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has " 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "shorter length than full decrypted data " 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%lu < %lu)", 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(in_decrypted)); 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "identifier=%d length=%lu", hdr->code, hdr->identifier, 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len); 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->code) { 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_REQUEST: 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peap_phase2_request(sm, data, ret, in_decrypted, 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &resp)) { 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request " 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "processing failed"); 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_SUCCESS: 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version == 1) { 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* EAP-Success within TLS tunnel is used to indicate 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * shutdown of the TLS channel. The authentication has 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * been completed. */ 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_eap_started && 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !data->phase2_eap_success) { 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 " 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Success used to indicate success, " 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "but Phase 2 EAP was not yet " 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "completed successfully"); 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - " 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-Success within TLS tunnel - " 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication completed"); 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_UNCOND_SUCC; 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success = 1; 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_outer_success == 2) { 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK " 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "to finish authentication"); 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (data->peap_outer_success == 1) { 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Reply with EAP-Success within the TLS 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * channel to complete the authentication. */ 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = wpabuf_alloc(sizeof(struct eap_hdr)); 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp) { 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr = wpabuf_put(resp, sizeof(*rhdr)); 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr->code = EAP_CODE_SUCCESS; 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr->identifier = hdr->identifier; 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr->length = 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt host_to_be16(sizeof(*rhdr)); 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No EAP-Success expected for Phase 1 (outer, 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * unencrypted auth), so force EAP state 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * machine to SUCCESS state. */ 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peap_done = TRUE; 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: ? */ 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_FAILURE: 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Reply with EAP-Failure within the TLS channel to complete 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * failure reporting. */ 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = wpabuf_alloc(sizeof(struct eap_hdr)); 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp) { 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr = wpabuf_put(resp, sizeof(*rhdr)); 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr->code = EAP_CODE_FAILURE; 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr->identifier = hdr->identifier; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr->length = host_to_be16(sizeof(*rhdr)); 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP header", hdr->code); 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp) { 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int skip_change2 = 0; 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *rmsg, buf; 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-PEAP: Encrypting Phase 2 data", resp); 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PEAP version changes */ 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version >= 2) { 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_peapv2_tlv_eap_payload(resp); 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(resp) >= 5 && 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE && 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_get_type(resp) == EAP_TYPE_TLV) 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt skip_change2 = 1; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rmsg = resp; 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version == 0 && !skip_change2) { 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&buf, wpabuf_head_u8(resp) + 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct eap_hdr), 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(resp) - sizeof(struct eap_hdr)); 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rmsg = &buf; 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version, req->identifier, 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rmsg, out_data)) { 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt " 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "a Phase 2 frame"); 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_hdr *req; 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags, id; 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret, 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reqData, &left, &flags); 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = wpabuf_head(reqData); 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id = req->identifier; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & EAP_TLS_FLAGS_START) { 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own " 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ver=%d)", flags & EAP_TLS_VERSION_MASK, 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version); 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((flags & EAP_TLS_VERSION_MASK) < data->peap_version) 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version = flags & EAP_TLS_VERSION_MASK; 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->force_peap_version >= 0 && 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->force_peap_version != data->peap_version) { 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select " 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "forced PEAP version %d", 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->force_peap_version); 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d", 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version); 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = 0; /* make sure that this frame is empty, even though it 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * should always be, anyway */ 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = NULL; 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !data->resuming) { 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf msg; 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&msg, pos, left); 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_peer_tls_process_helper(sm, &data->ssl, 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TYPE_PEAP, 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version, id, pos, 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left, &resp); 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *label; 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-PEAP: TLS done, proceed to Phase 2"); 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->key_data); 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* draft-josefsson-ppext-eap-tls-eap-05.txt 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * specifies that PEAPv1 would use "client PEAP 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encryption" as the label. However, most existing 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PEAPv1 implementations seem to be using the old 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * label, "client EAP encryption", instead. Use the old 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * label by default, but allow it to be configured with 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * phase1 parameter peaplabel=1. */ 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peap_version > 1 || data->force_new_label) 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt label = "client PEAP encryption"; 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt label = "client EAP encryption"; 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in " 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key derivation", label); 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_data = 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_derive_key(sm, &data->ssl, label, 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TLS_KEY_LEN); 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->key_data) { 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-PEAP: Derived key", 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_data, 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TLS_KEY_LEN); 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to " 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "derive key"); 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->workaround && data->resuming) { 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * At least few RADIUS servers (Aegis v1.1.6; 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * but not v1.1.4; and Cisco ACS) seem to be 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ACS) session resumption with outer 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-Success. This does not seem to follow 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * draft-josefsson-pppext-eap-tls-eap-05.txt 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * section 4.2, so only allow this if EAP 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * workarounds are enabled. 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - " 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "allow outer EAP-Success to " 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "terminate PEAP resumption"); 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_COND_SUCC; 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success = 1; 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->resuming = 0; 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 2) { 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf msg; 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Application data included in the handshake message. 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_req); 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_req = resp; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = NULL; 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&msg, pos, left); 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_peap_decrypt(sm, data, ret, req, &msg, 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &resp); 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret->methodState == METHOD_DONE) { 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 1) { 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP, 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version); 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success; 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv) 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_req); 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_req = NULL; 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->crypto_binding_used = 0; 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv) 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->key_data); 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_data = NULL; 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peer_tls_reauth_init(sm, &data->ssl)) { 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv && data->phase2_method && 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->init_for_reauth) 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->init_for_reauth(sm, data->phase2_priv); 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success = 0; 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_success = 0; 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_started = 0; 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->resuming = 1; 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = 1; 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peap_done = FALSE; 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf, 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen, int verbose) 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len, ret; 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_method) { 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-PEAPv%d Phase2 method=%s\n", 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peap_version, 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->name); 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv) 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->key_data != NULL && data->phase2_success; 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peap_data *data = priv; 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->key_data == NULL || !data->phase2_success) 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_TLS_KEY_LEN); 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_TLS_KEY_LEN; 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->crypto_binding_used) { 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 csk[128]; 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: It looks like Microsoft implementation requires null 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * termination for this label while the one used for deriving 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IPMK|CMK did not use null termination. 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (peap_prfplus(data->peap_version, data->ipmk, 40, 12531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Session Key Generating Function", 12541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (u8 *) "\00", 1, csk, sizeof(csk)) < 0) { 12551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(key); 12561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 12571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, csk, EAP_TLS_KEY_LEN); 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key, EAP_TLS_KEY_LEN); 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_peap_register(void) 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_peap_init; 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_peap_deinit; 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_peap_process; 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isKeyAvailable = eap_peap_isKeyAvailable; 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_peap_getKey; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_status = eap_peap_get_status; 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->has_reauth_data = eap_peap_has_reauth_data; 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit_for_reauth = eap_peap_deinit_for_reauth; 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init_for_reauth = eap_peap_init_for_reauth; 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_peer_method_register(eap); 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_method_free(eap); 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1294