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]; 2534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *id_p; 2634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t id_p_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 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_psk_reset(struct eap_sm *sm, void *priv) 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_p); 50c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt bin_clear_free(data, sizeof(*data)); 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_psk_build_1(struct eap_sm *sm, 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data, u8 id) 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_hdr_1 *psk; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-1 (sending)"); 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->rand_s, EAP_PSK_RAND_LEN)) { 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_S (server rand)", 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_s, EAP_PSK_RAND_LEN); 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, 7134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sizeof(*psk) + sm->server_id_len, 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_REQUEST, id); 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request"); 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt psk = wpabuf_put(req, sizeof(*psk)); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt psk->flags = EAP_PSK_FLAGS_SET_T(0); /* T=0 */ 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN); 8334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_data(req, sm->server_id, sm->server_id_len); 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return req; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_psk_build_3(struct eap_sm *sm, 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data, u8 id) 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_hdr_3 *psk; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pchannel, nonce[16]; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-3 (sending)"); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*psk) + 4 + 16 + 1, EAP_CODE_REQUEST, id); 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request"); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt psk = wpabuf_put(req, sizeof(*psk)); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt psk->flags = EAP_PSK_FLAGS_SET_T(2); /* T=2 */ 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ 11334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt buflen = sm->server_id_len + EAP_PSK_RAND_LEN; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(buflen); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(buf, sm->server_id, sm->server_id_len); 11934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(buf + sm->server_id_len, data->rand_p, EAP_PSK_RAND_LEN); 1201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s)) { 1211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(buf); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk, 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->emsk)) 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(nonce, 0, sizeof(nonce)); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel = wpabuf_put(req, 4 + 16 + 1); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pchannel, nonce + 12, 4); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(pchannel + 4, 0, 16); /* Tag */ 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (plaintext)", 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel, 4 + 16 + 1); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(req), 22, 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel + 4 + 16, 1, pchannel + 4)) 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (encrypted)", 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel, 4 + 16 + 1); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return req; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(req); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_psk_buildReq(struct eap_sm *sm, void *priv, u8 id) 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PSK_1: 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_psk_build_1(sm, data, id); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PSK_3: 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_psk_build_3(sm, data, id); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Unknown state %d in buildReq", 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_psk_check(struct eap_sm *sm, void *priv, 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 t; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 1) { 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t = EAP_PSK_FLAGS_GET_T(*pos); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: received frame: T=%d", t); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == PSK_1 && t != 1) { 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-2 - " 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignore T=%d", t); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == PSK_3 && t != 3) { 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-4 - " 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignore T=%d", t); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((t == 1 && len < sizeof(struct eap_psk_hdr_2)) || 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (t == 3 && len < sizeof(struct eap_psk_hdr_4))) { 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Too short frame"); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_psk_process_2(struct eap_sm *sm, 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data, 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_psk_hdr_2 *resp; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, mac[EAP_PSK_MAC_LEN], *buf; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left, buflen; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *cpos; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PSK_1) 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-2"); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &left); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cpos == NULL || left < sizeof(*resp)) { 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = (const struct eap_psk_hdr_2 *) cpos; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos = (const u8 *) (resp + 1); 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= sizeof(*resp); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_p); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p = os_malloc(left); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_p == NULL) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Failed to allocate memory for " 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ID_P"); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->id_p, cpos, left); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p_len = left; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PSK: ID_P", 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p, data->id_p_len); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user_get(sm, data->id_p, data->id_p_len, 0) < 0) { 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: unknown ID_P", 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p, data->id_p_len); 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i < EAP_MAX_METHODS && 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->user->methods[i].vendor != EAP_VENDOR_IETF || 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].method != EAP_TYPE_NONE); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i++) { 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].method == EAP_TYPE_PSK) 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i >= EAP_MAX_METHODS || 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].vendor != EAP_VENDOR_IETF || 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].method != EAP_TYPE_PSK) { 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-PSK: EAP-PSK not enabled for ID_P", 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p, data->id_p_len); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->password == NULL || 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password_len != EAP_PSK_PSK_LEN) { 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: invalid password in " 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "user database for ID_P", 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p, data->id_p_len); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_psk_key_setup(sm->user->password, data->ak, data->kdk)) { 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_P (client rand)", 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp->rand_p, EAP_PSK_RAND_LEN); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->rand_p, resp->rand_p, EAP_PSK_RAND_LEN); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ 29734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt buflen = data->id_p_len + sm->server_id_len + 2 * EAP_PSK_RAND_LEN; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(buflen); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, data->id_p, data->id_p_len); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf + data->id_p_len; 30534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(pos, sm->server_id, sm->server_id_len); 30634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos += sm->server_id_len; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_PSK_RAND_LEN; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (omac1_aes_128(data->ak, buf, buflen, mac)) { 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN); 317c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) { 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid MAC_P"); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Expected MAC_P", 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mac, EAP_PSK_MAC_LEN); 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PSK_3; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_psk_process_4(struct eap_sm *sm, 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data, 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_psk_hdr_4 *resp; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *decrypted, nonce[16]; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *tag; 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PSK_3) 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-4"); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &left); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || left < sizeof(*resp)) { 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = (const struct eap_psk_hdr_4 *) pos; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (resp + 1); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= sizeof(*resp); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Encrypted PCHANNEL", pos, left); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < 4 + 16 + 1) { 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PSK-4 (len=%lu, expected 21)", 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) left); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == 0 && pos[1] == 0 && pos[2] == 0 && pos[3] == 0) { 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Nonce did not increase"); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(nonce, 0, 12); 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(nonce + 12, pos, 4); 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 4; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tag = pos; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 16; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 16; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = os_malloc(left); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(decrypted, pos, left); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(respData), 22, decrypted, left, 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tag)) { 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted, left); 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Verify R flag */ 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (decrypted[0] >> 6) { 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PSK_R_FLAG_CONT: 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PSK_R_FLAG_DONE_SUCCESS: 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = SUCCESS; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PSK_R_FLAG_DONE_FAILURE: 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_psk_process(struct eap_sm *sm, void *priv, 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user == NULL || sm->user->password == NULL) { 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Plaintext password not " 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "configured"); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 1) 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (EAP_PSK_FLAGS_GET_T(*pos)) { 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 1: 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_psk_process_2(sm, data, respData); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 3: 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_psk_process_4(sm, data, respData); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_psk_isDone(struct eap_sm *sm, void *priv) 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_MSK_LEN); 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_MSK_LEN); 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_MSK_LEN; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_psk_isSuccess(struct eap_sm *sm, void *priv) 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidtstatic u8 * eap_psk_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 489fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt{ 490fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt struct eap_psk_data *data = priv; 491fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt u8 *id; 492fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 493fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (data->state != SUCCESS) 494fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return NULL; 495fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 496fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt *len = 1 + 2 * EAP_PSK_RAND_LEN; 497fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt id = os_malloc(*len); 498fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (id == NULL) 499fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return NULL; 500fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 501fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt id[0] = EAP_TYPE_PSK; 502fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt os_memcpy(id + 1, data->rand_p, EAP_PSK_RAND_LEN); 503fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt os_memcpy(id + 1 + EAP_PSK_RAND_LEN, data->rand_s, EAP_PSK_RAND_LEN); 504fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: Derived Session-Id", id, *len); 505fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 506fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return id; 507fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt} 508fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 509fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_psk_register(void) 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_psk_init; 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_psk_reset; 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_psk_buildReq; 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_psk_check; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_psk_process; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_psk_isDone; 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_psk_getKey; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_psk_isSuccess; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_psk_get_emsk; 529fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt eap->getSessionId = eap_psk_get_session_id; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 536