18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-GPSK (RFC 5433) 3fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * Copyright (c) 2006-2014, 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; 36fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt u16 forced_cipher; /* force cipher or 0 to allow all supported */ 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier, 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *csuite_list, 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t csuite_list_len); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier); 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_gpsk_state_txt(int state) 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GPSK_1: 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "GPSK-1"; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GPSK_3: 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "GPSK-3"; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS: 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "SUCCESS"; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAILURE"; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "?"; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */ 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_gpsk_state(struct eap_gpsk_data *data, int state) 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s", 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state_txt(data->state), 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state_txt(state)); 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_gpsk_deinit(struct eap_sm *sm, void *priv); 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_gpsk_init(struct eap_sm *sm) 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *password; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, password_len; 84fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt const char *phase1; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password(sm, &password_len); 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (password == NULL) { 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-GPSK: No key (password) configured"); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = GPSK_1; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity) { 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_peer = os_malloc(identity_len); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_peer == NULL) { 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_deinit(sm, data); 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->id_peer, identity, identity_len); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_peer_len = identity_len; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 108fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt phase1 = eap_get_config_phase1(sm); 109fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (phase1) { 110fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt const char *pos; 111fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 112fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos = os_strstr(phase1, "cipher="); 113fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (pos) { 114fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->forced_cipher = atoi(pos + 7); 115fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Forced cipher %u", 116fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->forced_cipher); 117fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 118fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 119fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->psk = os_malloc(password_len); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->psk == NULL) { 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_deinit(sm, data); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->psk, password, password_len); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->psk_len = password_len; 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_gpsk_deinit(struct eap_sm *sm, void *priv) 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data = priv; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_server); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_peer); 137c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (data->psk) { 138c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memset(data->psk, 0, data->psk_len); 139c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_free(data->psk); 140c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt } 141c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt bin_clear_free(data, sizeof(*data)); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_process_id_server(struct eap_gpsk_data *data, 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 alen; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < 2) { 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alen = WPA_GET_BE16(pos); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < alen) { 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server overflow"); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_server); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server = os_malloc(alen); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_server == NULL) { 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: No memory for ID_Server"); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->id_server, pos, alen); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server_len = alen; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server", 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server, data->id_server_len); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += alen; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_process_rand_server(struct eap_gpsk_data *data, 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < EAP_GPSK_RAND_LEN) { 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server overflow"); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->rand_server, pos, EAP_GPSK_RAND_LEN); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server", 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_server, EAP_GPSK_RAND_LEN); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_GPSK_RAND_LEN; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_gpsk_select_csuite(struct eap_sm *sm, 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data, 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *csuite_list, 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t csuite_list_len) 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_csuite *csuite; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, count; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = csuite_list_len / sizeof(struct eap_gpsk_csuite); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->vendor = EAP_GPSK_VENDOR_IETF; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier = EAP_GPSK_CIPHER_RESERVED; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt csuite = (struct eap_gpsk_csuite *) csuite_list; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vendor, specifier; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor = WPA_GET_BE32(csuite->vendor); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt specifier = WPA_GET_BE16(csuite->specifier); 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite[%d]: %d:%d", 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i, vendor, specifier); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->vendor == EAP_GPSK_VENDOR_IETF && 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier == EAP_GPSK_CIPHER_RESERVED && 215fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt eap_gpsk_supported_ciphersuite(vendor, specifier) && 216fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt (!data->forced_cipher || data->forced_cipher == specifier)) 217fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt { 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->vendor = vendor; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier = specifier; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt csuite++; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->vendor == EAP_GPSK_VENDOR_IETF && 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier == EAP_GPSK_CIPHER_RESERVED) { 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->msg_ctx, MSG_INFO, "EAP-GPSK: No supported " 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ciphersuite found"); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Selected ciphersuite %d:%d", 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->vendor, data->specifier); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm, 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data, 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 **list, 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *list_len, 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2420c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt size_t len; 2430c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < 2) { 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2510c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt len = WPA_GET_BE16(pos); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 2530c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt if (len > (size_t) (end - pos)) { 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow"); 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2570c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt if (len == 0 || (len % sizeof(struct eap_gpsk_csuite))) { 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %lu", 2590c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt (unsigned long) len); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2630c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt if (eap_gpsk_select_csuite(sm, data, pos, len) < 0) 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2660c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt *list = pos; 2670c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt *list_len = len; 2680c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt pos += len; 2690c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_process_gpsk_1(struct eap_sm *sm, 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data, 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *payload, 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t payload_len) 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t csuite_list_len; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *csuite_list, *pos, *end; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != GPSK_1) { 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-1"); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = payload + payload_len; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_process_id_server(data, payload, end); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_process_rand_server(data, pos, end); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_process_csuite_list(sm, data, &csuite_list, 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &csuite_list_len, pos, end); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) { 299fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ret->methodState = METHOD_DONE; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_gpsk_send_gpsk_2(data, eap_get_id(reqData), 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt csuite_list, csuite_list_len); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, GPSK_3); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier, 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *csuite_list, 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t csuite_list_len) 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, miclen; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rpos, *start; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_csuite *csuite; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2"); 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = 1 + 2 + data->id_peer_len + 2 + data->id_server_len + 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len + 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct eap_gpsk_csuite) + 2 + miclen; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, identifier); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_2); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = wpabuf_put(resp, 0); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_peer, data->id_peer_len); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, data->id_peer_len); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, data->id_peer, data->id_peer_len); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, data->id_server_len); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, data->id_server, data->id_server_len); 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->rand_peer, EAP_GPSK_RAND_LEN)) { 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data " 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for RAND_Peer"); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_peer, EAP_GPSK_RAND_LEN); 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, data->rand_peer, EAP_GPSK_RAND_LEN); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, data->rand_server, EAP_GPSK_RAND_LEN); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, csuite_list_len); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, csuite_list, csuite_list_len); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt csuite = wpabuf_put(resp, sizeof(*csuite)); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(csuite->vendor, data->vendor); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(csuite->specifier, data->specifier); 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_gpsk_derive_keys(data->psk, data->psk_len, 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->vendor, data->specifier, 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_peer, data->rand_server, 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_peer, data->id_peer_len, 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server, data->id_server_len, 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk, 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->sk, &data->sk_len, 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pk, &data->pk_len) < 0) { 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys"); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 381f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (eap_gpsk_derive_session_id(data->psk, data->psk_len, 382f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->vendor, data->specifier, 383f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->rand_peer, data->rand_server, 384f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->id_peer, data->id_peer_len, 385f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->id_server, data->id_server_len, 386f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt EAP_TYPE_GPSK, 387f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->session_id, &data->id_len) < 0) { 388f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive Session-Id"); 389f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt eap_gpsk_state(data, FAILURE); 390f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpabuf_free(resp); 391f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 392f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 393f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Derived Session-Id", 394f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data->session_id, data->id_len); 395f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No PD_Payload_1 */ 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, 0); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos = wpabuf_put(resp, miclen); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier, start, rpos - start, rpos) < 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_validate_rand(struct eap_gpsk_data *data, 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < EAP_GPSK_RAND_LEN) { 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RAND_Peer"); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(pos, data->rand_peer, EAP_GPSK_RAND_LEN) != 0) { 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2 and " 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GPSK-3 did not match"); 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2", 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_peer, EAP_GPSK_RAND_LEN); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-3", 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, EAP_GPSK_RAND_LEN); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_GPSK_RAND_LEN; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < EAP_GPSK_RAND_LEN) { 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RAND_Server"); 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(pos, data->rand_server, EAP_GPSK_RAND_LEN) != 0) { 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and " 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GPSK-3 did not match"); 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1", 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand_server, EAP_GPSK_RAND_LEN); 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-3", 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, EAP_GPSK_RAND_LEN); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_GPSK_RAND_LEN; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_validate_id_server(struct eap_gpsk_data *data, 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) 2) { 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length(ID_Server)"); 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = WPA_GET_BE16(pos); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) len) { 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ID_Server"); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len != data->id_server_len || 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(pos, data->id_server, len) != 0) { 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-GPSK: ID_Server did not match with " 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the one used in GPSK-1"); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1", 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server, data->id_server_len); 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-3", 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, len); 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += len; 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_validate_csuite(struct eap_gpsk_data *data, 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vendor, specifier; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_gpsk_csuite *csuite; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) sizeof(*csuite)) { 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "CSuite_Sel"); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt csuite = (const struct eap_gpsk_csuite *) pos; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor = WPA_GET_BE32(csuite->vendor); 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt specifier = WPA_GET_BE16(csuite->specifier); 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(*csuite); 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vendor != data->vendor || specifier != data->specifier) { 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not " 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one sent in GPSK-2 (%d:%d)", 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor, specifier, data->vendor, data->specifier); 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_validate_pd_payload_2(struct eap_gpsk_data *data, 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 alen; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < 2) { 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PD_Payload_2 length"); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alen = WPA_GET_BE16(pos); 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < alen) { 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d-octet PD_Payload_2", alen); 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_2", pos, alen); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += alen; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data, 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *payload, 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t miclen; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[EAP_GPSK_MAX_MIC_LEN]; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) miclen) { 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(left=%lu miclen=%lu)", 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) (end - pos), 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) miclen); 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier, payload, pos - payload, mic) 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) { 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 571c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(mic, pos, miclen) != 0) { 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3"); 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += miclen; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm, 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data, 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *payload, 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t payload_len) 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != GPSK_3) { 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3"); 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = payload + payload_len; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_validate_rand(data, payload, end); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_validate_id_server(data, pos, end); 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_validate_csuite(data, pos, end); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_validate_pd_payload_2(data, pos, end); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_gpsk_validate_gpsk_3_mic(data, payload, pos, end); 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) { 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos != end) { 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data in the end of GPSK-2", 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) (end - pos)); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_gpsk_send_gpsk_4(data, eap_get_id(reqData)); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, SUCCESS); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_UNCOND_SUCC; 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier) 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rpos, *start; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mlen; 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4"); 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlen = eap_gpsk_mic_len(data->vendor, data->specifier); 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, 1 + 2 + mlen, 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, identifier); 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_4); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = wpabuf_put(resp, 0); 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No PD_Payload_3 */ 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, 0); 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos = wpabuf_put(resp, mlen); 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->specifier, start, rpos - start, rpos) < 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_gpsk_state(data, FAILURE); 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data = priv; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, reqData, &len); 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 1) { 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", *pos); 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (*pos) { 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_GPSK_OPCODE_GPSK_1: 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_gpsk_process_gpsk_1(sm, data, ret, reqData, 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos + 1, len - 1); 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_GPSK_OPCODE_GPSK_3: 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData, 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos + 1, len - 1); 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with " 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unknown opcode %d", *pos); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv) 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data = priv; 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len) 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data = priv; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_MSK_LEN); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_MSK_LEN); 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_MSK_LEN; 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_gpsk_data *data = priv; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 750f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic u8 * eap_gpsk_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 751f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 752f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct eap_gpsk_data *data = priv; 753f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt u8 *sid; 754f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 755f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (data->state != SUCCESS) 756f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 757f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 758f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt sid = os_malloc(data->id_len); 759f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (sid == NULL) 760f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 761f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_memcpy(sid, data->session_id, data->id_len); 762f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt *len = data->id_len; 763f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 764f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return sid; 765f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 766f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 767f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_gpsk_register(void) 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_gpsk_init; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_gpsk_deinit; 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_gpsk_process; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isKeyAvailable = eap_gpsk_isKeyAvailable; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_gpsk_getKey; 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_gpsk_get_emsk; 784f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt eap->getSessionId = eap_gpsk_get_session_id; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_peer_method_register(eap); 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_method_free(eap); 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 791