18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / EAP-PSK (RFC 4764) server 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: EAP-PSK is an EAP authentication method and as such, completely 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * different from WPA-PSK. This file is not needed for WPA-PSK functionality. 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_psk_common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_i.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_psk_data { 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { PSK_1, PSK_3, SUCCESS, FAILURE } state; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rand_s[EAP_PSK_RAND_LEN]; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rand_p[EAP_PSK_RAND_LEN]; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *id_p, *id_s; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t id_p_len, id_s_len; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN]; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 msk[EAP_MSK_LEN]; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 emsk[EAP_EMSK_LEN]; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_psk_init(struct eap_sm *sm) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PSK_1; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_s = (u8 *) "hostapd"; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_s_len = 7; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_psk_reset(struct eap_sm *sm, void *priv) 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_p); 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_psk_build_1(struct eap_sm *sm, 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data, u8 id) 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_hdr_1 *psk; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-1 (sending)"); 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->rand_s, EAP_PSK_RAND_LEN)) { 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_S (server rand)", 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_s, EAP_PSK_RAND_LEN); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*psk) + data->id_s_len, 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_REQUEST, id); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request"); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt psk = wpabuf_put(req, sizeof(*psk)); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt psk->flags = EAP_PSK_FLAGS_SET_T(0); /* T=0 */ 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(req, data->id_s, data->id_s_len); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return req; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_psk_build_3(struct eap_sm *sm, 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data, u8 id) 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_hdr_3 *psk; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pchannel, nonce[16]; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-3 (sending)"); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*psk) + 4 + 16 + 1, EAP_CODE_REQUEST, id); 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request"); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt psk = wpabuf_put(req, sizeof(*psk)); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt psk->flags = EAP_PSK_FLAGS_SET_T(2); /* T=2 */ 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buflen = data->id_s_len + EAP_PSK_RAND_LEN; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(buflen); 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, data->id_s, data->id_s_len); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); 1221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s)) { 1231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(buf); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk, 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->emsk)) 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(nonce, 0, sizeof(nonce)); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel = wpabuf_put(req, 4 + 16 + 1); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pchannel, nonce + 12, 4); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(pchannel + 4, 0, 16); /* Tag */ 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (plaintext)", 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel, 4 + 16 + 1); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(req), 22, 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel + 4 + 16, 1, pchannel + 4)) 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (encrypted)", 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel, 4 + 16 + 1); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return req; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(req); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_psk_buildReq(struct eap_sm *sm, void *priv, u8 id) 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PSK_1: 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_psk_build_1(sm, data, id); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PSK_3: 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_psk_build_3(sm, data, id); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Unknown state %d in buildReq", 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_psk_check(struct eap_sm *sm, void *priv, 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 t; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 1) { 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t = EAP_PSK_FLAGS_GET_T(*pos); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: received frame: T=%d", t); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == PSK_1 && t != 1) { 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-2 - " 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignore T=%d", t); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == PSK_3 && t != 3) { 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-4 - " 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignore T=%d", t); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((t == 1 && len < sizeof(struct eap_psk_hdr_2)) || 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (t == 3 && len < sizeof(struct eap_psk_hdr_4))) { 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Too short frame"); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_psk_process_2(struct eap_sm *sm, 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data, 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_psk_hdr_2 *resp; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, mac[EAP_PSK_MAC_LEN], *buf; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left, buflen; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *cpos; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PSK_1) 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-2"); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &left); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cpos == NULL || left < sizeof(*resp)) { 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = (const struct eap_psk_hdr_2 *) cpos; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos = (const u8 *) (resp + 1); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= sizeof(*resp); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_p); 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p = os_malloc(left); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_p == NULL) { 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Failed to allocate memory for " 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ID_P"); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->id_p, cpos, left); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p_len = left; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PSK: ID_P", 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p, data->id_p_len); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user_get(sm, data->id_p, data->id_p_len, 0) < 0) { 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: unknown ID_P", 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p, data->id_p_len); 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i < EAP_MAX_METHODS && 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->user->methods[i].vendor != EAP_VENDOR_IETF || 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].method != EAP_TYPE_NONE); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i++) { 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].method == EAP_TYPE_PSK) 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i >= EAP_MAX_METHODS || 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].vendor != EAP_VENDOR_IETF || 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].method != EAP_TYPE_PSK) { 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-PSK: EAP-PSK not enabled for ID_P", 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p, data->id_p_len); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->password == NULL || 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password_len != EAP_PSK_PSK_LEN) { 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: invalid password in " 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "user database for ID_P", 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p, data->id_p_len); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_psk_key_setup(sm->user->password, data->ak, data->kdk)) { 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_P (client rand)", 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp->rand_p, EAP_PSK_RAND_LEN); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->rand_p, resp->rand_p, EAP_PSK_RAND_LEN); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(buflen); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, data->id_p, data->id_p_len); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf + data->id_p_len; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->id_s, data->id_s_len); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += data->id_s_len; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_PSK_RAND_LEN; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (omac1_aes_128(data->ak, buf, buflen, mac)) { 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) { 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid MAC_P"); 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Expected MAC_P", 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mac, EAP_PSK_MAC_LEN); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PSK_3; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_psk_process_4(struct eap_sm *sm, 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data, 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_psk_hdr_4 *resp; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *decrypted, nonce[16]; 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *tag; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PSK_3) 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-4"); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &left); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || left < sizeof(*resp)) { 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = (const struct eap_psk_hdr_4 *) pos; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (resp + 1); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= sizeof(*resp); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Encrypted PCHANNEL", pos, left); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < 4 + 16 + 1) { 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PSK-4 (len=%lu, expected 21)", 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) left); 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == 0 && pos[1] == 0 && pos[2] == 0 && pos[3] == 0) { 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Nonce did not increase"); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(nonce, 0, 12); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(nonce + 12, pos, 4); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 4; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tag = pos; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 16; 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 16; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = os_malloc(left); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(decrypted, pos, left); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(respData), 22, decrypted, left, 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tag)) { 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted, left); 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Verify R flag */ 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (decrypted[0] >> 6) { 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PSK_R_FLAG_CONT: 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PSK_R_FLAG_DONE_SUCCESS: 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = SUCCESS; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PSK_R_FLAG_DONE_FAILURE: 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_psk_process(struct eap_sm *sm, void *priv, 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user == NULL || sm->user->password == NULL) { 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Plaintext password not " 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "configured"); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 1) 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (EAP_PSK_FLAGS_GET_T(*pos)) { 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 1: 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_psk_process_2(sm, data, respData); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 3: 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_psk_process_4(sm, data, respData); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_psk_isDone(struct eap_sm *sm, void *priv) 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_MSK_LEN); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_MSK_LEN); 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_MSK_LEN; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_psk_isSuccess(struct eap_sm *sm, void *priv) 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_psk_register(void) 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_psk_init; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_psk_reset; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_psk_buildReq; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_psk_check; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_psk_process; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_psk_isDone; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_psk_getKey; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_psk_isSuccess; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_psk_get_emsk; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 515