18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-GPSK (RFC 5433) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2006-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 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_peer/eap_i.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_gpsk_common.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_gpsk_data { 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state; 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rand_server[EAP_GPSK_RAND_LEN]; 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rand_peer[EAP_GPSK_RAND_LEN]; 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 msk[EAP_MSK_LEN]; 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 emsk[EAP_EMSK_LEN]; 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 sk[EAP_GPSK_MAX_SK_LEN]; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t sk_len; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 pk[EAP_GPSK_MAX_PK_LEN]; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t pk_len; 26f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt u8 session_id[128]; 27f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt size_t id_len; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *id_peer; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t id_peer_len; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *id_server; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t id_server_len; 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vendor; /* CSuite/Specifier */ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int specifier; /* CSuite/Specifier */ 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *psk; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t psk_len; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier, 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *csuite_list, 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t csuite_list_len); 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier); 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_gpsk_state_txt(int state) 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GPSK_1: 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "GPSK-1"; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GPSK_3: 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "GPSK-3"; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS: 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "SUCCESS"; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAILURE"; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "?"; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */ 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_gpsk_state(struct eap_gpsk_data *data, int state) 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s", 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state_txt(data->state), 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state_txt(state)); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_gpsk_deinit(struct eap_sm *sm, void *priv); 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_gpsk_init(struct eap_sm *sm) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *password; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, password_len; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password(sm, &password_len); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (password == NULL) { 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-GPSK: No key (password) configured"); 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = GPSK_1; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity) { 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_peer = os_malloc(identity_len); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_peer == NULL) { 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_deinit(sm, data); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->id_peer, identity, identity_len); 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_peer_len = identity_len; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->psk = os_malloc(password_len); 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->psk == NULL) { 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_deinit(sm, data); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->psk, password, password_len); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->psk_len = password_len; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_gpsk_deinit(struct eap_sm *sm, void *priv) 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data = priv; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_server); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_peer); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->psk); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_process_id_server(struct eap_gpsk_data *data, 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 alen; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < 2) { 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alen = WPA_GET_BE16(pos); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < alen) { 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server overflow"); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_server); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server = os_malloc(alen); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_server == NULL) { 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: No memory for ID_Server"); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->id_server, pos, alen); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server_len = alen; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server", 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server, data->id_server_len); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += alen; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_process_rand_server(struct eap_gpsk_data *data, 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < EAP_GPSK_RAND_LEN) { 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server overflow"); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->rand_server, pos, EAP_GPSK_RAND_LEN); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server", 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_server, EAP_GPSK_RAND_LEN); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_GPSK_RAND_LEN; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_gpsk_select_csuite(struct eap_sm *sm, 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data, 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *csuite_list, 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t csuite_list_len) 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_csuite *csuite; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, count; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = csuite_list_len / sizeof(struct eap_gpsk_csuite); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->vendor = EAP_GPSK_VENDOR_IETF; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier = EAP_GPSK_CIPHER_RESERVED; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt csuite = (struct eap_gpsk_csuite *) csuite_list; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vendor, specifier; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor = WPA_GET_BE32(csuite->vendor); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt specifier = WPA_GET_BE16(csuite->specifier); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite[%d]: %d:%d", 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i, vendor, specifier); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->vendor == EAP_GPSK_VENDOR_IETF && 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier == EAP_GPSK_CIPHER_RESERVED && 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_supported_ciphersuite(vendor, specifier)) { 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->vendor = vendor; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier = specifier; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt csuite++; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->vendor == EAP_GPSK_VENDOR_IETF && 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier == EAP_GPSK_CIPHER_RESERVED) { 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->msg_ctx, MSG_INFO, "EAP-GPSK: No supported " 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ciphersuite found"); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Selected ciphersuite %d:%d", 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->vendor, data->specifier); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm, 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data, 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 **list, 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *list_len, 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < 2) { 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *list_len = WPA_GET_BE16(pos); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) *list_len) { 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow"); 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*list_len == 0 || (*list_len % sizeof(struct eap_gpsk_csuite))) { 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %lu", 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) *list_len); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *list = pos; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += *list_len; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_gpsk_select_csuite(sm, data, *list, *list_len) < 0) 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_process_gpsk_1(struct eap_sm *sm, 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data, 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *payload, 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t payload_len) 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t csuite_list_len; 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *csuite_list, *pos, *end; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != GPSK_1) { 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-1"); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = payload + payload_len; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_process_id_server(data, payload, end); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_process_rand_server(data, pos, end); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_process_csuite_list(sm, data, &csuite_list, 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &csuite_list_len, pos, end); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) { 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_gpsk_send_gpsk_2(data, eap_get_id(reqData), 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt csuite_list, csuite_list_len); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, GPSK_3); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier, 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *csuite_list, 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t csuite_list_len) 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, miclen; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rpos, *start; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_csuite *csuite; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2"); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = 1 + 2 + data->id_peer_len + 2 + data->id_server_len + 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len + 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct eap_gpsk_csuite) + 2 + miclen; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, identifier); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_2); 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = wpabuf_put(resp, 0); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_peer, data->id_peer_len); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, data->id_peer_len); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, data->id_peer, data->id_peer_len); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, data->id_server_len); 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, data->id_server, data->id_server_len); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->rand_peer, EAP_GPSK_RAND_LEN)) { 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data " 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for RAND_Peer"); 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_peer, EAP_GPSK_RAND_LEN); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, data->rand_peer, EAP_GPSK_RAND_LEN); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, data->rand_server, EAP_GPSK_RAND_LEN); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, csuite_list_len); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, csuite_list, csuite_list_len); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt csuite = wpabuf_put(resp, sizeof(*csuite)); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(csuite->vendor, data->vendor); 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(csuite->specifier, data->specifier); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_gpsk_derive_keys(data->psk, data->psk_len, 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->vendor, data->specifier, 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_peer, data->rand_server, 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_peer, data->id_peer_len, 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server, data->id_server_len, 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk, 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->sk, &data->sk_len, 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pk, &data->pk_len) < 0) { 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys"); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 357f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (eap_gpsk_derive_session_id(data->psk, data->psk_len, 358f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->vendor, data->specifier, 359f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->rand_peer, data->rand_server, 360f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->id_peer, data->id_peer_len, 361f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->id_server, data->id_server_len, 362f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt EAP_TYPE_GPSK, 363f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->session_id, &data->id_len) < 0) { 364f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive Session-Id"); 365f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt eap_gpsk_state(data, FAILURE); 366f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpabuf_free(resp); 367f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 368f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 369f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Derived Session-Id", 370f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->session_id, data->id_len); 371f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No PD_Payload_1 */ 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, 0); 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos = wpabuf_put(resp, miclen); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier, start, rpos - start, rpos) < 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_validate_rand(struct eap_gpsk_data *data, 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < EAP_GPSK_RAND_LEN) { 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RAND_Peer"); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(pos, data->rand_peer, EAP_GPSK_RAND_LEN) != 0) { 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2 and " 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GPSK-3 did not match"); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2", 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_peer, EAP_GPSK_RAND_LEN); 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-3", 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, EAP_GPSK_RAND_LEN); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_GPSK_RAND_LEN; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < EAP_GPSK_RAND_LEN) { 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RAND_Server"); 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(pos, data->rand_server, EAP_GPSK_RAND_LEN) != 0) { 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and " 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GPSK-3 did not match"); 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1", 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_server, EAP_GPSK_RAND_LEN); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-3", 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, EAP_GPSK_RAND_LEN); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_GPSK_RAND_LEN; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_validate_id_server(struct eap_gpsk_data *data, 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) 2) { 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length(ID_Server)"); 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = WPA_GET_BE16(pos); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) len) { 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ID_Server"); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len != data->id_server_len || 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(pos, data->id_server, len) != 0) { 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-GPSK: ID_Server did not match with " 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the one used in GPSK-1"); 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1", 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server, data->id_server_len); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-3", 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, len); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += len; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_validate_csuite(struct eap_gpsk_data *data, 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vendor, specifier; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_gpsk_csuite *csuite; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) sizeof(*csuite)) { 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "CSuite_Sel"); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt csuite = (const struct eap_gpsk_csuite *) pos; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor = WPA_GET_BE32(csuite->vendor); 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt specifier = WPA_GET_BE16(csuite->specifier); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(*csuite); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vendor != data->vendor || specifier != data->specifier) { 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not " 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one sent in GPSK-2 (%d:%d)", 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor, specifier, data->vendor, data->specifier); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_validate_pd_payload_2(struct eap_gpsk_data *data, 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 alen; 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < 2) { 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PD_Payload_2 length"); 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alen = WPA_GET_BE16(pos); 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < alen) { 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d-octet PD_Payload_2", alen); 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_2", pos, alen); 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += alen; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data, 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *payload, 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t miclen; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[EAP_GPSK_MAX_MIC_LEN]; 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) miclen) { 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(left=%lu miclen=%lu)", 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) (end - pos), 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) miclen); 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier, payload, pos - payload, mic) 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) { 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mic, pos, miclen) != 0) { 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3"); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += miclen; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm, 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data, 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *payload, 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t payload_len) 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != GPSK_3) { 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3"); 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = payload + payload_len; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_validate_rand(data, payload, end); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_validate_id_server(data, pos, end); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_validate_csuite(data, pos, end); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_validate_pd_payload_2(data, pos, end); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_validate_gpsk_3_mic(data, payload, pos, end); 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) { 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos != end) { 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data in the end of GPSK-2", 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) (end - pos)); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_gpsk_send_gpsk_4(data, eap_get_id(reqData)); 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, SUCCESS); 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_UNCOND_SUCC; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier) 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rpos, *start; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mlen; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4"); 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlen = eap_gpsk_mic_len(data->vendor, data->specifier); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, 1 + 2 + mlen, 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, identifier); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_4); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = wpabuf_put(resp, 0); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No PD_Payload_3 */ 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, 0); 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos = wpabuf_put(resp, mlen); 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier, start, rpos - start, rpos) < 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data = priv; 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, reqData, &len); 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 1) { 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", *pos); 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (*pos) { 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_GPSK_OPCODE_GPSK_1: 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_gpsk_process_gpsk_1(sm, data, ret, reqData, 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos + 1, len - 1); 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_GPSK_OPCODE_GPSK_3: 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData, 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos + 1, len - 1); 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with " 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unknown opcode %d", *pos); 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv) 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data = priv; 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len) 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data = priv; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_MSK_LEN); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_MSK_LEN); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_MSK_LEN; 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data = priv; 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 726f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic u8 * eap_gpsk_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 727f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 728f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct eap_gpsk_data *data = priv; 729f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt u8 *sid; 730f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 731f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (data->state != SUCCESS) 732f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 733f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 734f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt sid = os_malloc(data->id_len); 735f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (sid == NULL) 736f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 737f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_memcpy(sid, data->session_id, data->id_len); 738f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt *len = data->id_len; 739f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 740f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return sid; 741f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 742f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 743f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_gpsk_register(void) 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_gpsk_init; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_gpsk_deinit; 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_gpsk_process; 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isKeyAvailable = eap_gpsk_isKeyAvailable; 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_gpsk_getKey; 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_gpsk_get_emsk; 760f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt eap->getSessionId = eap_gpsk_get_session_id; 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_peer_method_register(eap); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_method_free(eap); 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 767