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 { 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { WAIT_START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, 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 FRAG_ACK: 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FRAG_ACK"; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WAIT_FRAG_ACK: 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WAIT_FRAG_ACK"; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case DONE: 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "DONE"; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAIL: 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAIL"; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "?"; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_wsc_state(struct eap_wsc_data *data, int state) 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s", 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state_txt(data->state), 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state_txt(state)); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_wsc_new_ap_settings(struct wps_credential *cred, 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *params) 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pos, *end; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cred, 0, sizeof(*cred)); 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(params, "new_ssid="); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 9; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(pos, ' '); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = os_strlen(pos); 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = end - pos; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((len & 1) || len > 2 * sizeof(cred->ssid) || 80444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt hexstr2bin(pos, cred->ssid, len / 2)) { 81444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_ssid"); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 83444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->ssid_len = len / 2; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(params, "new_auth="); 87444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (pos == NULL) { 88444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_auth"); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 90444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(pos + 9, "OPEN", 4) == 0) 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->auth_type = WPS_AUTH_OPEN; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strncmp(pos + 9, "WPAPSK", 6) == 0) 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->auth_type = WPS_AUTH_WPAPSK; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strncmp(pos + 9, "WPA2PSK", 7) == 0) 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->auth_type = WPS_AUTH_WPA2PSK; 97444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt else { 98444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_auth"); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 100444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(params, "new_encr="); 103444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (pos == NULL) { 104444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_encr"); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 106444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(pos + 9, "NONE", 4) == 0) 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->encr_type = WPS_ENCR_NONE; 10921de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strncmp(pos + 9, "WEP", 3) == 0) 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->encr_type = WPS_ENCR_WEP; 11221de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */ 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strncmp(pos + 9, "TKIP", 4) == 0) 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->encr_type = WPS_ENCR_TKIP; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strncmp(pos + 9, "CCMP", 4) == 0) 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->encr_type = WPS_ENCR_AES; 117444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt else { 118444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_encr"); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 120444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(params, "new_key="); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 8; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(pos, ' '); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = os_strlen(pos); 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = end - pos; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((len & 1) || len > 2 * sizeof(cred->key) || 132444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt hexstr2bin(pos, cred->key, len / 2)) { 133444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_key"); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 135444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cred->key_len = len / 2; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_wsc_init(struct eap_sm *sm) 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int registrar; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_config cfg; 149cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt const char *pos, *end; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *phase1; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_context *wps; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_credential new_ap_settings; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 15404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int nfc = 0; 155cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u8 pkhash[WPS_OOB_PUBKEY_HASH_LEN]; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps = sm->wps; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps == NULL) { 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-WSC: WPS context not available"); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity && identity_len == WSC_ID_REGISTRAR_LEN && 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt registrar = 1; /* Supplicant is Registrar */ 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (identity && identity_len == WSC_ID_ENROLLEE_LEN && 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt registrar = 0; /* Supplicant is Enrollee */ 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = registrar ? MESG : WAIT_START; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->registrar = registrar; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->wps_ctx = wps; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&cfg, 0, sizeof(cfg)); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.wps = wps; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.registrar = registrar; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phase1 = eap_get_config_phase1(sm); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (phase1 == NULL) { 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: phase1 configuration data not " 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "set"); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(phase1, "pin="); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) { 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pin = (const u8 *) pos; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos != '\0' && *pos != ' ') 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pin_len = pos - (const char *) cfg.pin; 203f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cfg.pin_len == 6 && 204f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_strncmp((const char *) cfg.pin, "nfc-pw", 6) == 0) { 20504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cfg.pin = NULL; 20604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cfg.pin_len = 0; 20704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt nfc = 1; 20804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(phase1, "pbc=1"); 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pbc = 1; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 215cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pos = os_strstr(phase1, "dev_pw_id="); 216cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (pos) { 217cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u16 id = atoi(pos + 10); 218cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (id == DEV_PW_NFC_CONNECTION_HANDOVER) 219cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt nfc = 1; 220cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (cfg.pin || id == DEV_PW_NFC_CONNECTION_HANDOVER) 221cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt cfg.dev_pw_id = id; 222cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 223cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 22404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cfg.pin == NULL && !cfg.pbc && !nfc) { 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 " 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "configuration data"); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 231cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pos = os_strstr(phase1, " pkhash="); 232cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (pos) { 233cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt size_t len; 234cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pos += 8; 235cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt end = os_strchr(pos, ' '); 236cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (end) 237cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt len = end - pos; 238cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt else 239cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt len = os_strlen(pos); 240cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (len != 2 * WPS_OOB_PUBKEY_HASH_LEN || 241cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt hexstr2bin(pos, pkhash, WPS_OOB_PUBKEY_HASH_LEN)) { 242cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: Invalid pkhash"); 243cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_free(data); 244cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 245cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 246cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt cfg.peer_pubkey_hash = pkhash; 247cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_wsc_new_ap_settings(&new_ap_settings, phase1); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 252444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to parse new AP " 253444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt "settings"); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 1) { 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Provide new AP settings for " 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPS"); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.new_ap_settings = &new_ap_settings; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->wps = wps_init(&cfg); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->wps == NULL) { 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 265444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: wps_init failed"); 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_get_config_fragment_size(sm); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res > 0) 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->fragment_size = res; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->fragment_size = WSC_FRAGMENT_SIZE; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment size limit %u", 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned int) data->fragment_size); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (registrar && cfg.pin) { 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_registrar_add_pin(data->wps_ctx->registrar, NULL, NULL, 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pin, cfg.pin_len, 0); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Use reduced client timeout for WPS to avoid long wait */ 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ClientTimeout > 30) 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ClientTimeout = 30; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_wsc_deinit(struct eap_sm *sm, void *priv) 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data = priv; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->in_buf); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->out_buf); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(data->wps); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->wps_ctx->network_key); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->wps_ctx->network_key = NULL; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, u8 id) 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t send_len, plen; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Generating Response"); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = 0; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = wpabuf_len(data->out_buf) - data->out_used; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (2 + send_len > data->fragment_size) { 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = data->fragment_size - 2; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= WSC_FLAGS_MF; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_used == 0) { 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= WSC_FLAGS_LF; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len -= 2; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = 2 + send_len; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_LF) 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen += 2; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen, 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, id); 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, data->out_op_code); /* Op-Code */ 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, flags); /* Flags */ 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_LF) 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, wpabuf_len(data->out_buf)); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used, 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used += send_len; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_used == wpabuf_len(data->out_buf)) { 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(message sent completely)", 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) send_len); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->out_buf); 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_buf = NULL; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used = 0; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((data->state == FAIL && data->out_op_code == WSC_ACK) || 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_op_code == WSC_NACK || 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_op_code == WSC_Done) { 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%lu more to send)", (unsigned long) send_len, 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(data->out_buf) - 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, WAIT_FRAG_ACK); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_wsc_process_cont(struct eap_wsc_data *data, 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len, u8 op_code) 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process continuation of a pending message */ 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (op_code != data->in_op_code) { 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in " 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fragment (expected %d)", 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code, data->in_op_code); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > wpabuf_tailroom(data->in_buf)) { 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow"); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting " 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for %lu bytes more", (unsigned long) len, 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_wsc_process_fragment(struct eap_wsc_data *data, 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, u8 flags, u8 op_code, 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 message_length, 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process a fragment that is not the last one of the message */ 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length field in a " 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fragmented packet"); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* First fragment of the message */ 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = wpabuf_alloc(message_length); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_op_code = op_code; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in first " 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fragment, waiting for %lu bytes more", 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_wsc_build_frag_ack(id, EAP_CODE_RESPONSE); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data = priv; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *start, *pos, *end; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 op_code, flags, id; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 message_length = 0; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_process_res res; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf tmpbuf; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *r; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, reqData, 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len); 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 2) { 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id = eap_get_id(reqData); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = pos; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = start + len; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code = *pos++; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = *pos++; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_LF) { 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < 2) { 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt message_length = WPA_GET_BE16(pos); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (message_length < end - pos) { 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Length"); 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d " 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Flags 0x%x Message Length %d", 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code, flags, message_length); 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == WAIT_FRAG_ACK) { 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (op_code != WSC_FRAG_ACK) { 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in WAIT_FRAG_ACK state", op_code); 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_wsc_build_msg(data, ret, id); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG && 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code != WSC_Done && op_code != WSC_Start) { 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == WAIT_START) { 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (op_code != WSC_Start) { 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in WAIT_START state", op_code); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received start"); 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Start message has empty payload, skip processing */ 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_msg; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (op_code == WSC_Start) { 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code); 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf && 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_MF) { 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_wsc_process_fragment(data, ret, id, flags, op_code, 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt message_length, pos, 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end - pos); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Wrap unfragmented messages as wpabuf without extra copy */ 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&tmpbuf, pos, end - pos); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = &tmpbuf; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wps_process_msg(data->wps, op_code, data->in_buf); 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (res) { 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_DONE: 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed " 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "successfully - wait for EAP failure"); 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_CONTINUE: 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_FAILURE: 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_PENDING: 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed"); 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf != &tmpbuf) 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->in_buf); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = NULL; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsend_msg: 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_buf == NULL) { 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_buf = wps_get_msg(data->wps, &data->out_op_code); 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_buf == NULL) { 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to receive " 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message from WPS"); 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used = 0; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r = eap_wsc_build_msg(data, ret, id); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == FAIL && ret->methodState == METHOD_DONE) { 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Use reduced client timeout for WPS to avoid long wait */ 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ClientTimeout > 2) 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ClientTimeout = 2; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return r; 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_wsc_register(void) 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WSC"); 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_wsc_init; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_wsc_deinit; 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_wsc_process; 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_peer_method_register(eap); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_method_free(eap); 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 596