1 /*
2  * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "utils/common.h"
8 
9 #include "rsn_supp/wpa.h"
10 #include "common/eapol_common.h"
11 #include "utils/wpa_debug.h"
12 #include "common/ieee802_11_defs.h"
13 #include "wps/wps_i.h"
14 #include "wps/wps_dev_attr.h"
15 #include "eap_peer/eap_defs.h"
16 #include "eap_peer/eap_common.h"
17 #include "esp_wifi_driver.h"
18 #include "esp_event.h"
19 #include "esp_wifi.h"
20 #include "esp_err.h"
21 #include "esp_private/wifi.h"
22 #include "esp_wps.h"
23 #include "esp_wps_i.h"
24 #include "eap_common/eap_wsc_common.h"
25 #include "esp_wpas_glue.h"
26 #include "ap/hostapd.h"
27 #include "ap/ap_config.h"
28 #include "ap/wps_hostapd.h"
29 #include "utils/eloop.h"
30 
31 extern struct wps_sm *gWpsSm;
32 extern void *s_wps_api_lock;
33 extern void *s_wps_api_sem;
34 extern bool s_wps_enabled;
35 
36 static int wps_reg_eloop_post_block(uint32_t sig, void *arg);
37 
wifi_ap_wps_init(const esp_wps_config_t * config)38 static int wifi_ap_wps_init(const esp_wps_config_t *config)
39 {
40     struct wps_sm *sm = NULL;
41     uint8_t mac[ETH_ALEN];
42     struct wps_config cfg = {0};
43     struct hostapd_data *hapd = hostapd_get_hapd_data();
44 
45     if (!hapd || gWpsSm) {
46         goto _out;
47     }
48 
49     wpa_printf(MSG_DEBUG, "wifi wps init");
50 
51     gWpsSm = os_zalloc(sizeof(struct wps_sm));   /* alloc Wps_sm */
52     if (!gWpsSm) {
53         goto _out;
54     }
55 
56     sm = gWpsSm;
57 
58     esp_wifi_get_macaddr_internal(WIFI_IF_AP, mac);
59     os_memcpy(sm->ownaddr, mac, ETH_ALEN);
60 
61     sm->identity_len = WSC_ID_REGISTRAR_LEN;
62     os_memcpy(sm->identity, WSC_ID_REGISTRAR, sm->identity_len);
63 
64     sm->wps_ctx = os_zalloc(sizeof(struct wps_context)); /* alloc wps_ctx */
65     if (!sm->wps_ctx) {
66         goto _err;
67     }
68 
69     if (wps_dev_init() != 0) {
70         goto _err;
71     }
72 
73     cfg.registrar = 1;
74     cfg.wps = sm->wps_ctx;
75 
76     os_memcpy((void *)cfg.pin, config->pin, 8);
77     wps_init_cfg_pin(&cfg);
78     os_memcpy(cfg.wps->uuid, sm->uuid, WPS_UUID_LEN);
79     if ((sm->wps = wps_init(&cfg)) == NULL) {         /* alloc wps_data */
80         goto _err;
81     }
82 
83     hostapd_init_wps(hapd, sm->wps, sm->wps_ctx);
84 
85     /* Report PIN */
86     if (wps_get_type() == WPS_TYPE_PIN) {
87         wifi_event_sta_wps_er_pin_t evt;
88         os_memcpy(evt.pin_code, sm->wps->dev_password, 8);
89         esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_PIN, &evt, sizeof(evt), OS_BLOCK);
90     }
91 
92     return ESP_OK;
93 
94 _err:
95     if (sm->dev) {
96         wps_dev_deinit(sm->dev);
97         sm->dev = NULL;
98     }
99     if (sm->wps_ctx) {
100         os_free(sm->wps_ctx);
101         sm->wps_ctx = NULL;
102     }
103     if (sm->wps) {
104         wps_deinit(sm->wps);
105         sm->wps = NULL;
106     }
107     os_free(gWpsSm);
108     gWpsSm = NULL;
109     return ESP_FAIL;
110 _out:
111     return ESP_FAIL;
112 }
113 
wifi_ap_wps_deinit(void)114 int wifi_ap_wps_deinit(void)
115 {
116     struct wps_sm *sm = gWpsSm;
117 
118     if (gWpsSm == NULL) {
119         return ESP_FAIL;
120     }
121 
122     hostapd_deinit_wps(hostapd_get_hapd_data());
123     if (sm->wps) {
124         sm->wps->registrar = 0;
125         wps_deinit(sm->wps);
126         sm->wps = NULL;
127     }
128     if (sm->dev) {
129         wps_dev_deinit(sm->dev);
130         sm->dev = NULL;
131     }
132 
133     if (sm->wps_ctx) {
134         os_free(sm->wps_ctx);
135         sm->wps_ctx = NULL;
136     }
137 
138     os_free(gWpsSm);
139     gWpsSm = NULL;
140 
141     return ESP_OK;
142 }
143 
wifi_ap_wps_enable_internal(const esp_wps_config_t * config)144 static int wifi_ap_wps_enable_internal(const esp_wps_config_t *config)
145 {
146     struct wps_sm *sm = gWpsSm;
147     wifi_mode_t mode = WIFI_MODE_NULL;
148 
149     if (esp_wifi_get_user_init_flag_internal() == 0) {
150         wpa_printf(MSG_ERROR, "wps enable: wifi not started cannot enable wpsreg");
151         return ESP_ERR_WIFI_STATE;
152     }
153 
154     if (esp_wifi_get_mode(&mode) != ESP_OK) {
155         wpa_printf(MSG_ERROR, "wps enable: unable to get current wifi mode");
156         return ESP_FAIL;
157     }
158 
159     if (mode != WIFI_MODE_AP && mode != ESP32_WIFI_MODE_APSTA) {
160         wpa_printf(MSG_ERROR, "wps enable: mode=%d does not include AP", mode);
161         return ESP_ERR_WIFI_MODE;
162     }
163 
164     if (esp_wifi_ap_get_prof_authmode_internal() == WIFI_AUTH_OPEN) {
165         wpa_printf(MSG_ERROR, "wps enable: wpsreg not supported when authmode is open");
166         return ESP_ERR_WIFI_MODE;
167     }
168 
169     if (s_wps_enabled) {
170         if (sm && os_memcmp(sm->identity, WSC_ID_ENROLLEE, sm->identity_len) == 0) {
171             wpa_printf(MSG_ERROR, "wps enable: wps enrollee already enabled cannot enable wpsreg");
172             return ESP_ERR_WIFI_MODE;
173         } else {
174             wpa_printf(MSG_DEBUG, "wps enable: already enabled");
175             return ESP_OK;
176         }
177     }
178 
179     if (config->wps_type == WPS_TYPE_DISABLE) {
180         wpa_printf(MSG_ERROR, "wps enable: invalid wps type");
181         return ESP_ERR_WIFI_WPS_TYPE;
182     }
183 
184     wpa_printf(MSG_DEBUG, "Set factory information.");
185     if (wps_set_factory_info(config) != ESP_OK) {
186         return ESP_FAIL;
187     }
188 
189 
190     if (wps_set_type(config->wps_type) != ESP_OK) {
191         goto _err;
192     }
193 
194     if (wps_set_status(WPS_STATUS_DISABLE) != ESP_OK) {
195         goto _err;
196     }
197 
198     if (wifi_ap_wps_init(config) != ESP_OK) {
199         goto _err;
200     }
201 
202     wpa_printf(MSG_INFO, "wifi_wps_enable");
203     s_wps_enabled = true;
204     return ESP_OK;
205 
206 _err:
207     wpa_printf(MSG_ERROR, "failure in wifi_wps_enable");
208     wps_set_type(WPS_TYPE_DISABLE);
209     wps_set_status(WPS_STATUS_DISABLE);
210 
211     return ESP_FAIL;
212 }
213 
esp_wifi_ap_wps_enable(const esp_wps_config_t * config)214 int esp_wifi_ap_wps_enable(const esp_wps_config_t *config)
215 {
216     int ret = ESP_OK;
217 
218     API_MUTEX_TAKE();
219     ret = wps_reg_eloop_post_block(SIG_WPS_REG_ENABLE, (void *) config);
220     API_MUTEX_GIVE();
221     return ret;
222 }
223 
wifi_ap_wps_disable_internal(void)224 int wifi_ap_wps_disable_internal(void)
225 {
226     struct wps_sm *sm = gWpsSm;
227 
228     if (sm && os_memcmp(sm->identity, WSC_ID_ENROLLEE, sm->identity_len) == 0) {
229         return ESP_ERR_WIFI_MODE;
230     }
231 
232     if (!s_wps_enabled) {
233         wpa_printf(MSG_DEBUG, "wps disable: already disabled");
234         return ESP_OK;
235     }
236 
237     wpa_printf(MSG_INFO, "wifi_wps_disable");
238     if (wps_set_type(WPS_TYPE_DISABLE) != ESP_OK) {
239         goto _err;
240     }
241 
242     if (wps_set_status(WPS_STATUS_DISABLE) != ESP_OK) {
243         goto _err;
244     }
245 
246     if (wifi_ap_wps_deinit() != ESP_OK) {
247         goto _err;
248     }
249 
250 
251     s_wps_enabled = false;
252     return ESP_OK;
253 
254 _err:
255     wpa_printf(MSG_ERROR, "wps disable: failed to disable wps");
256     return ESP_FAIL;
257 }
258 
esp_wifi_ap_wps_disable(void)259 int esp_wifi_ap_wps_disable(void)
260 {
261     int ret = ESP_FAIL;
262     API_MUTEX_TAKE();
263     ret = wps_reg_eloop_post_block(SIG_WPS_REG_DISABLE, NULL);
264     API_MUTEX_GIVE();
265     return ret;
266 }
267 
wifi_ap_wps_start_internal(const unsigned char * pin)268 static int wifi_ap_wps_start_internal(const unsigned char *pin)
269 {
270     wifi_mode_t mode = WIFI_MODE_NULL;
271 
272     esp_wifi_get_mode(&mode);
273     if (mode != WIFI_MODE_AP && mode != ESP32_WIFI_MODE_APSTA) {
274         wpa_printf(MSG_ERROR, "wps start: mode=%d does not include AP", mode);
275         return ESP_ERR_WIFI_MODE;
276     }
277 
278 
279     if (!s_wps_enabled) {
280         wpa_printf(MSG_ERROR, "wps start: wps not enabled");
281         API_MUTEX_GIVE();
282         return ESP_ERR_WIFI_WPS_SM;
283     }
284 
285     if (wps_get_type() == WPS_TYPE_DISABLE ||
286             (wps_get_status() != WPS_STATUS_DISABLE &&
287              wps_get_status() != WPS_STATUS_SCANNING)) {
288         wpa_printf(MSG_ERROR, "wps start: wps_get_type=%d wps_get_status=%d",
289                 wps_get_type(), wps_get_status());
290         return ESP_ERR_WIFI_WPS_TYPE;
291     }
292 
293     if (esp_wifi_get_user_init_flag_internal() == 0) {
294         wpa_printf(MSG_ERROR, "wps start: esp_wifi_get_user_init_flag_internal=%d",
295                 esp_wifi_get_user_init_flag_internal());
296         return ESP_ERR_WIFI_STATE;
297     }
298 
299     if (!pin) {
300         pin = gWpsSm->wps->dev_password;
301     }
302 
303     /* TODO ideally SoftAP mode should also do a single scan in PBC mode
304      * however softAP scanning is not available at the moment */
305     if (wps_set_status(WPS_STATUS_PENDING) != ESP_OK) {
306         return ESP_FAIL;
307     }
308     if (wps_get_type() == WPS_TYPE_PBC) {
309         if (hostapd_wps_button_pushed(hostapd_get_hapd_data(), NULL) != ESP_OK) {
310             return ESP_FAIL;
311         }
312     } else if (wps_get_type() == WPS_TYPE_PIN) {
313         if (hostapd_wps_add_pin(hostapd_get_hapd_data(), pin) != ESP_OK) {
314             return ESP_FAIL;
315         }
316     }
317     return ESP_OK;
318 }
319 
esp_wifi_ap_wps_start(const unsigned char * pin)320 int esp_wifi_ap_wps_start(const unsigned char *pin)
321 {
322     int ret = ESP_FAIL;
323     API_MUTEX_TAKE();
324     ret = wps_reg_eloop_post_block(SIG_WPS_REG_START, (void *)pin);
325     API_MUTEX_GIVE();
326     return ret;
327 }
328 
wps_reg_eloop_handler(void * eloop_ctx,void * user_ctx)329 static void wps_reg_eloop_handler(void *eloop_ctx, void *user_ctx)
330 {
331     int ret = ESP_FAIL;
332     enum wps_reg_sig_type *sig = (enum wps_reg_sig_type *) eloop_ctx;
333     wps_ioctl_param_t *param = (wps_ioctl_param_t *) user_ctx;
334 
335     switch(*sig) {
336     case SIG_WPS_REG_ENABLE:
337         esp_wps_config_t *config = (esp_wps_config_t *)param->arg;
338         ret = wifi_ap_wps_enable_internal(config);
339         break;
340     case SIG_WPS_REG_START:
341         unsigned char *pin = (unsigned char *)param->arg;
342         ret = wifi_ap_wps_start_internal((const unsigned char *)pin);
343         break;
344     case SIG_WPS_REG_DISABLE:
345         ret = wifi_ap_wps_disable_internal();
346         break;
347     default:
348         wpa_printf(MSG_WARNING, "%s(): invalid signal type=%d", __func__, *sig);
349         ret = ESP_FAIL;
350         break;
351     }
352 
353     param->ret = ret;
354     os_semphr_give(s_wps_api_sem);
355 }
356 
wps_reg_eloop_post_block(uint32_t sig,void * arg)357 static int wps_reg_eloop_post_block(uint32_t sig, void *arg)
358 {
359     int ret = ESP_FAIL;
360     wps_ioctl_param_t param;
361     param.ret = ESP_FAIL;
362     param.arg = arg;
363 
364     if (s_wps_api_sem == NULL) {
365         s_wps_api_sem = os_semphr_create(1, 0);
366         if (s_wps_api_sem == NULL) {
367             wpa_printf(MSG_ERROR, "%s(): failed to create WPA API semaphore", __func__);
368             return ESP_ERR_NO_MEM;
369         }
370     }
371 
372     eloop_register_timeout(0, 0, wps_reg_eloop_handler, (void *)&sig, (void *)&param);
373 
374     if (TRUE == os_semphr_take(s_wps_api_sem, OS_BLOCK)) {
375         ret = param.ret;
376     } else {
377         ret = ESP_FAIL;
378     }
379 
380     return ret;
381 }
382