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 *)¶m);
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