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