18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-PSK (RFC 4764) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 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_i.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_psk_data { 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rand_p[EAP_PSK_RAND_LEN]; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN]; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *id_s, *id_p; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t id_s_len, id_p_len; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 msk[EAP_MSK_LEN]; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 emsk[EAP_EMSK_LEN]; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_psk_init(struct eap_sm *sm) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *password; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, password_len; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password(sm, &password_len); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!password || password_len != 16) { 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: 16-octet pre-shared key not " 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "configured"); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_psk_key_setup(password, data->ak, data->kdk)) { 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PSK_INIT; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity) { 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p = os_malloc(identity_len); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_p) 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->id_p, identity, identity_len); 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p_len = identity_len; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_p == NULL) { 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity"); 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_psk_deinit(struct eap_sm *sm, void *priv) 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_s); 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_p); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_psk_hdr_1 *hdr1; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_hdr_2 *hdr2; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen, len; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *cpos; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state"); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr1 = (const struct eap_psk_hdr_1 *) cpos; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cpos == NULL || len < sizeof(*hdr1)) { 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message " 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length (%lu; expected %lu or more)", 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) sizeof(*hdr1)); 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (EAP_PSK_FLAGS_GET_T(hdr1->flags) != 0) { 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)", 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_PSK_FLAGS_GET_T(hdr1->flags)); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s, 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_PSK_RAND_LEN); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_s); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_s_len = len - sizeof(*hdr1); 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_s = os_malloc(data->id_s_len); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_s == NULL) { 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for " 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ID_S (len=%lu)", (unsigned long) data->id_s_len); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S", 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_s, data->id_s_len); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->rand_p, EAP_PSK_RAND_LEN)) { 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*hdr2) + data->id_p_len, EAP_CODE_RESPONSE, 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_get_id(reqData)); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr2 = wpabuf_put(resp, sizeof(*hdr2)); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr2->flags = EAP_PSK_FLAGS_SET_T(1); /* T=1 */ 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, data->id_p, data->id_p_len); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(buflen); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, data->id_p, data->id_p_len); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf + data->id_p_len; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->id_s, data->id_s_len); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += data->id_s_len; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_PSK_RAND_LEN; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p)) { 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p, 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_PSK_RAND_LEN); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_P", 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_p, data->id_p_len); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PSK_MAC_SENT; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_psk_process_3(struct eap_psk_data *data, 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_psk_hdr_3 *hdr3; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_hdr_4 *hdr4; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *rpchannel, nonce[16], *decrypted; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pchannel, *tag, *msg; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mac[EAP_PSK_MAC_LEN]; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen, left, data_len, len, plen; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int failed = 0; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state"); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reqData, &len); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr3 = (const struct eap_psk_hdr_3 *) pos; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < sizeof(*hdr3)) { 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message " 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length (%lu; expected %lu or more)", 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) sizeof(*hdr3)); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = len - sizeof(*hdr3); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel = (const u8 *) (hdr3 + 1); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (EAP_PSK_FLAGS_GET_T(hdr3->flags) != 2) { 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)", 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_PSK_FLAGS_GET_T(hdr3->flags)); 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr3->rand_s, 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_PSK_RAND_LEN); 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_S", hdr3->mac_s, EAP_PSK_MAC_LEN); 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL", pchannel, left); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < 4 + 16 + 1) { 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "third message (len=%lu, expected 21)", 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) left); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buflen = data->id_s_len + EAP_PSK_RAND_LEN; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(buflen); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, data->id_s, data->id_s_len); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (omac1_aes_128(data->ak, buf, buflen, mac)) { 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) { 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third " 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully"); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk)) { 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(nonce, 0, 12); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(nonce + 12, pchannel, 4); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel += 4; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 4; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tag = pchannel; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pchannel += 16; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 16; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = pchannel; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - nonce", 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce, sizeof(nonce)); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr", 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(reqData), 5); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = os_malloc(left); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) { 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(decrypted, msg, left); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(reqData), 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct eap_hdr) + 1 + 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*hdr3) - EAP_PSK_MAC_LEN, decrypted, 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left, tag)) { 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted, left); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Verify R flag */ 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (decrypted[0] >> 6) { 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PSK_R_FLAG_CONT: 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed = 1; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PSK_R_FLAG_DONE_SUCCESS: 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PSK_R_FLAG_DONE_FAILURE: 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Authentication server rejected " 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication"); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed = 1; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data_len = 1; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((decrypted[0] & EAP_PSK_E_FLAG) && left > 1) 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data_len++; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = sizeof(*hdr4) + 4 + 16 + data_len; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, plen, 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, eap_get_id(reqData)); 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) { 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr4 = wpabuf_put(resp, sizeof(*hdr4)); 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr4->flags = EAP_PSK_FLAGS_SET_T(3); /* T=3 */ 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpchannel = wpabuf_put(resp, 4 + 16 + data_len); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* nonce++ */ 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(nonce, sizeof(nonce)); 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rpchannel, nonce + 12, 4); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted[0] & EAP_PSK_E_FLAG) { 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Unsupported E (Ext) flag"); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed = 1; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpchannel[4 + 16] = (EAP_PSK_R_FLAG_DONE_FAILURE << 6) | 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_PSK_E_FLAG; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left > 1) { 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Add empty EXT_Payload with same EXT_Type */ 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpchannel[4 + 16 + 1] = decrypted[1]; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (failed) 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_FAILURE << 6; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)", 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpchannel + 4 + 16, data_len); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(resp), 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct eap_hdr) + 1 + sizeof(*hdr4), 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpchannel + 4 + 16, data_len, rpchannel + 4)) { 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)", 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpchannel, 4 + 16 + data_len); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Completed %ssuccessfully", 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed ? "un" : ""); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PSK_DONE; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC; 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_psk_process(struct eap_sm *sm, void *priv, 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp = NULL; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) { 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PSK_INIT: 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_psk_process_1(data, ret, reqData); 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PSK_MAC_SENT: 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_psk_process_3(data, ret, reqData); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PSK_DONE: 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore " 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected message"); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret->methodState == METHOD_DONE) { 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv) 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == PSK_DONE; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PSK_DONE) 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_MSK_LEN); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_MSK_LEN; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_MSK_LEN); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_psk_data *data = priv; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PSK_DONE) 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_psk_register(void) 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_psk_init; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_psk_deinit; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_psk_process; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isKeyAvailable = eap_psk_isKeyAvailable; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_psk_getKey; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_psk_get_emsk; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_peer_method_register(eap); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_method_free(eap); 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 478