18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-WSC peer for Wi-Fi Protected Setup 304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2007-2009, 2012, 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 "uuid.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_wsc_common.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_defs.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_wsc_data { 201d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt enum { WAIT_START, MESG, WAIT_FRAG_ACK, FAIL } state; 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int registrar; 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_buf; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *out_buf; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wsc_op_code in_op_code, out_op_code; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t out_used; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t fragment_size; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_data *wps; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_context *wps_ctx; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_wsc_state_txt(int state) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WAIT_START: 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WAIT_START"; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case MESG: 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "MESG"; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WAIT_FRAG_ACK: 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WAIT_FRAG_ACK"; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAIL: 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAIL"; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "?"; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_wsc_state(struct eap_wsc_data *data, int state) 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s", 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state_txt(data->state), 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state_txt(state)); 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_wsc_new_ap_settings(struct wps_credential *cred, 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *params) 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pos, *end; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cred, 0, sizeof(*cred)); 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(params, "new_ssid="); 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 9; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(pos, ' '); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = os_strlen(pos); 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = end - pos; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((len & 1) || len > 2 * sizeof(cred->ssid) || 76444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt hexstr2bin(pos, cred->ssid, len / 2)) { 77444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_ssid"); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 79444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->ssid_len = len / 2; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(params, "new_auth="); 83444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (pos == NULL) { 84444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_auth"); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 86444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(pos + 9, "OPEN", 4) == 0) 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->auth_type = WPS_AUTH_OPEN; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strncmp(pos + 9, "WPAPSK", 6) == 0) 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->auth_type = WPS_AUTH_WPAPSK; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strncmp(pos + 9, "WPA2PSK", 7) == 0) 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->auth_type = WPS_AUTH_WPA2PSK; 93444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt else { 94444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_auth"); 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 96444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(params, "new_encr="); 99444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (pos == NULL) { 100444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_encr"); 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 102444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(pos + 9, "NONE", 4) == 0) 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->encr_type = WPS_ENCR_NONE; 10521de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strncmp(pos + 9, "WEP", 3) == 0) 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->encr_type = WPS_ENCR_WEP; 10821de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */ 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strncmp(pos + 9, "TKIP", 4) == 0) 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->encr_type = WPS_ENCR_TKIP; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strncmp(pos + 9, "CCMP", 4) == 0) 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->encr_type = WPS_ENCR_AES; 113444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt else { 114444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_encr"); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 116444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(params, "new_key="); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 8; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(pos, ' '); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = os_strlen(pos); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = end - pos; 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((len & 1) || len > 2 * sizeof(cred->key) || 128444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt hexstr2bin(pos, cred->key, len / 2)) { 129444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_key"); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 131444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->key_len = len / 2; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_wsc_init(struct eap_sm *sm) 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int registrar; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_config cfg; 145cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt const char *pos, *end; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *phase1; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_context *wps; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_credential new_ap_settings; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 15004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int nfc = 0; 151cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u8 pkhash[WPS_OOB_PUBKEY_HASH_LEN]; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps = sm->wps; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps == NULL) { 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-WSC: WPS context not available"); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity && identity_len == WSC_ID_REGISTRAR_LEN && 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt registrar = 1; /* Supplicant is Registrar */ 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (identity && identity_len == WSC_ID_ENROLLEE_LEN && 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt registrar = 0; /* Supplicant is Enrollee */ 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = registrar ? MESG : WAIT_START; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->registrar = registrar; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->wps_ctx = wps; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&cfg, 0, sizeof(cfg)); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.wps = wps; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.registrar = registrar; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phase1 = eap_get_config_phase1(sm); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (phase1 == NULL) { 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: phase1 configuration data not " 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "set"); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(phase1, "pin="); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) { 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pin = (const u8 *) pos; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos != '\0' && *pos != ' ') 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pin_len = pos - (const char *) cfg.pin; 199f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cfg.pin_len == 6 && 200f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_strncmp((const char *) cfg.pin, "nfc-pw", 6) == 0) { 20104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cfg.pin = NULL; 20204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cfg.pin_len = 0; 20304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt nfc = 1; 20404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(phase1, "pbc=1"); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pbc = 1; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 211cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pos = os_strstr(phase1, "dev_pw_id="); 212cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (pos) { 213cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u16 id = atoi(pos + 10); 214cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (id == DEV_PW_NFC_CONNECTION_HANDOVER) 215cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt nfc = 1; 216cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (cfg.pin || id == DEV_PW_NFC_CONNECTION_HANDOVER) 217cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt cfg.dev_pw_id = id; 218cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 219cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 22004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cfg.pin == NULL && !cfg.pbc && !nfc) { 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 " 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "configuration data"); 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 227cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pos = os_strstr(phase1, " pkhash="); 228cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (pos) { 229cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt size_t len; 230cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pos += 8; 231cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt end = os_strchr(pos, ' '); 232cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (end) 233cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt len = end - pos; 234cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt else 235cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt len = os_strlen(pos); 236cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (len != 2 * WPS_OOB_PUBKEY_HASH_LEN || 237cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt hexstr2bin(pos, pkhash, WPS_OOB_PUBKEY_HASH_LEN)) { 238cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: Invalid pkhash"); 239cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_free(data); 240cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 241cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 242cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt cfg.peer_pubkey_hash = pkhash; 243cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_wsc_new_ap_settings(&new_ap_settings, phase1); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 248444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to parse new AP " 249444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt "settings"); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 1) { 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Provide new AP settings for " 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPS"); 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.new_ap_settings = &new_ap_settings; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->wps = wps_init(&cfg); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->wps == NULL) { 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 261444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: wps_init failed"); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_get_config_fragment_size(sm); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res > 0) 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->fragment_size = res; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->fragment_size = WSC_FRAGMENT_SIZE; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment size limit %u", 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned int) data->fragment_size); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (registrar && cfg.pin) { 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_registrar_add_pin(data->wps_ctx->registrar, NULL, NULL, 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pin, cfg.pin_len, 0); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Use reduced client timeout for WPS to avoid long wait */ 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ClientTimeout > 30) 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ClientTimeout = 30; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_wsc_deinit(struct eap_sm *sm, void *priv) 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data = priv; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->in_buf); 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->out_buf); 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(data->wps); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->wps_ctx->network_key); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->wps_ctx->network_key = NULL; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, u8 id) 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t send_len, plen; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Generating Response"); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = 0; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = wpabuf_len(data->out_buf) - data->out_used; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (2 + send_len > data->fragment_size) { 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = data->fragment_size - 2; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= WSC_FLAGS_MF; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_used == 0) { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= WSC_FLAGS_LF; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len -= 2; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = 2 + send_len; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_LF) 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen += 2; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen, 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, id); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, data->out_op_code); /* Op-Code */ 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, flags); /* Flags */ 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_LF) 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, wpabuf_len(data->out_buf)); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used, 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used += send_len; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_used == wpabuf_len(data->out_buf)) { 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(message sent completely)", 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) send_len); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->out_buf); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_buf = NULL; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used = 0; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((data->state == FAIL && data->out_op_code == WSC_ACK) || 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_op_code == WSC_NACK || 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_op_code == WSC_Done) { 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%lu more to send)", (unsigned long) send_len, 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(data->out_buf) - 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used); 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, WAIT_FRAG_ACK); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_wsc_process_cont(struct eap_wsc_data *data, 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len, u8 op_code) 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process continuation of a pending message */ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (op_code != data->in_op_code) { 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in " 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fragment (expected %d)", 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code, data->in_op_code); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > wpabuf_tailroom(data->in_buf)) { 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow"); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting " 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for %lu bytes more", (unsigned long) len, 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_wsc_process_fragment(struct eap_wsc_data *data, 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, u8 flags, u8 op_code, 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 message_length, 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process a fragment that is not the last one of the message */ 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length field in a " 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fragmented packet"); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* First fragment of the message */ 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = wpabuf_alloc(message_length); 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_op_code = op_code; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in first " 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fragment, waiting for %lu bytes more", 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_wsc_build_frag_ack(id, EAP_CODE_RESPONSE); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data = priv; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *start, *pos, *end; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 op_code, flags, id; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 message_length = 0; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_process_res res; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf tmpbuf; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *r; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, reqData, 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 2) { 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id = eap_get_id(reqData); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = pos; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = start + len; 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code = *pos++; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = *pos++; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_LF) { 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < 2) { 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt message_length = WPA_GET_BE16(pos); 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 461fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (message_length < end - pos || message_length > 50000) { 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Length"); 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d " 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Flags 0x%x Message Length %d", 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code, flags, message_length); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == WAIT_FRAG_ACK) { 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (op_code != WSC_FRAG_ACK) { 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in WAIT_FRAG_ACK state", op_code); 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_wsc_build_msg(data, ret, id); 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG && 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code != WSC_Done && op_code != WSC_Start) { 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == WAIT_START) { 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (op_code != WSC_Start) { 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in WAIT_START state", op_code); 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received start"); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Start message has empty payload, skip processing */ 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_msg; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (op_code == WSC_Start) { 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code); 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf && 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_MF) { 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_wsc_process_fragment(data, ret, id, flags, op_code, 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt message_length, pos, 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end - pos); 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Wrap unfragmented messages as wpabuf without extra copy */ 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&tmpbuf, pos, end - pos); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = &tmpbuf; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wps_process_msg(data->wps, op_code, data->in_buf); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (res) { 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_DONE: 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed " 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "successfully - wait for EAP failure"); 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_CONTINUE: 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_FAILURE: 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_PENDING: 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed"); 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf != &tmpbuf) 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->in_buf); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = NULL; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsend_msg: 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_buf == NULL) { 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_buf = wps_get_msg(data->wps, &data->out_op_code); 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_buf == NULL) { 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to receive " 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message from WPS"); 556d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eap_wsc_state(data, FAIL); 557d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ret->methodState = METHOD_DONE; 558d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ret->decision = DECISION_FAIL; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used = 0; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r = eap_wsc_build_msg(data, ret, id); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == FAIL && ret->methodState == METHOD_DONE) { 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Use reduced client timeout for WPS to avoid long wait */ 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ClientTimeout > 2) 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ClientTimeout = 2; 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return r; 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_wsc_register(void) 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WSC"); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_wsc_init; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_wsc_deinit; 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_wsc_process; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5891d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt return eap_peer_method_register(eap); 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 591