Branch data Line data Source code
1 : : /*
2 : : * Wi-Fi Protected Setup - Registrar
3 : : * Copyright (c) 2008-2013, Jouni Malinen <j@w1.fi>
4 : : *
5 : : * This software may be distributed under the terms of the BSD license.
6 : : * See README for more details.
7 : : */
8 : :
9 : : #include "utils/includes.h"
10 : :
11 : : #include "utils/common.h"
12 : : #include "utils/base64.h"
13 : : #include "utils/eloop.h"
14 : : #include "utils/uuid.h"
15 : : #include "utils/list.h"
16 : : #include "crypto/crypto.h"
17 : : #include "crypto/sha256.h"
18 : : #include "crypto/random.h"
19 : : #include "common/ieee802_11_defs.h"
20 : : #include "wps_i.h"
21 : : #include "wps_dev_attr.h"
22 : : #include "wps_upnp.h"
23 : : #include "wps_upnp_i.h"
24 : :
25 : : #ifndef CONFIG_WPS_STRICT
26 : : #define WPS_WORKAROUNDS
27 : : #endif /* CONFIG_WPS_STRICT */
28 : :
29 : : #ifdef CONFIG_WPS_NFC
30 : :
31 : : struct wps_nfc_pw_token {
32 : : struct dl_list list;
33 : : u8 pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN];
34 : : unsigned int peer_pk_hash_known:1;
35 : : u16 pw_id;
36 : : u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1];
37 : : size_t dev_pw_len;
38 : : int pk_hash_provided_oob; /* whether own PK hash was provided OOB */
39 : : };
40 : :
41 : :
42 : 1 : static void wps_remove_nfc_pw_token(struct wps_nfc_pw_token *token)
43 : : {
44 : 1 : dl_list_del(&token->list);
45 : 1 : os_free(token);
46 : 1 : }
47 : :
48 : :
49 : 198 : static void wps_free_nfc_pw_tokens(struct dl_list *tokens, u16 pw_id)
50 : : {
51 : : struct wps_nfc_pw_token *token, *prev;
52 [ + + ]: 199 : dl_list_for_each_safe(token, prev, tokens, struct wps_nfc_pw_token,
53 : : list) {
54 [ - + ][ # # ]: 1 : if (pw_id == 0 || pw_id == token->pw_id)
55 : 1 : wps_remove_nfc_pw_token(token);
56 : : }
57 : 198 : }
58 : :
59 : :
60 : 29 : static struct wps_nfc_pw_token * wps_get_nfc_pw_token(struct dl_list *tokens,
61 : : u16 pw_id)
62 : : {
63 : : struct wps_nfc_pw_token *token;
64 [ + + ]: 29 : dl_list_for_each(token, tokens, struct wps_nfc_pw_token, list) {
65 [ + - ]: 23 : if (pw_id == token->pw_id)
66 : 23 : return token;
67 : : }
68 : 29 : return NULL;
69 : : }
70 : :
71 : : #else /* CONFIG_WPS_NFC */
72 : :
73 : : #define wps_free_nfc_pw_tokens(t, p) do { } while (0)
74 : :
75 : : #endif /* CONFIG_WPS_NFC */
76 : :
77 : :
78 : : struct wps_uuid_pin {
79 : : struct dl_list list;
80 : : u8 uuid[WPS_UUID_LEN];
81 : : int wildcard_uuid;
82 : : u8 *pin;
83 : : size_t pin_len;
84 : : #define PIN_LOCKED BIT(0)
85 : : #define PIN_EXPIRES BIT(1)
86 : : int flags;
87 : : struct os_reltime expiration;
88 : : u8 enrollee_addr[ETH_ALEN];
89 : : };
90 : :
91 : :
92 : 106 : static void wps_free_pin(struct wps_uuid_pin *pin)
93 : : {
94 : 106 : os_free(pin->pin);
95 : 106 : os_free(pin);
96 : 106 : }
97 : :
98 : :
99 : 106 : static void wps_remove_pin(struct wps_uuid_pin *pin)
100 : : {
101 : 106 : dl_list_del(&pin->list);
102 : 106 : wps_free_pin(pin);
103 : 106 : }
104 : :
105 : :
106 : 175 : static void wps_free_pins(struct dl_list *pins)
107 : : {
108 : : struct wps_uuid_pin *pin, *prev;
109 [ + + ]: 187 : dl_list_for_each_safe(pin, prev, pins, struct wps_uuid_pin, list)
110 : 12 : wps_remove_pin(pin);
111 : 175 : }
112 : :
113 : :
114 : : struct wps_pbc_session {
115 : : struct wps_pbc_session *next;
116 : : u8 addr[ETH_ALEN];
117 : : u8 uuid_e[WPS_UUID_LEN];
118 : : struct os_reltime timestamp;
119 : : };
120 : :
121 : :
122 : 175 : static void wps_free_pbc_sessions(struct wps_pbc_session *pbc)
123 : : {
124 : : struct wps_pbc_session *prev;
125 : :
126 [ + + ]: 180 : while (pbc) {
127 : 5 : prev = pbc;
128 : 5 : pbc = pbc->next;
129 : 5 : os_free(prev);
130 : : }
131 : 175 : }
132 : :
133 : :
134 : : struct wps_registrar_device {
135 : : struct wps_registrar_device *next;
136 : : struct wps_device_data dev;
137 : : u8 uuid[WPS_UUID_LEN];
138 : : };
139 : :
140 : :
141 : : struct wps_registrar {
142 : : struct wps_context *wps;
143 : :
144 : : int pbc;
145 : : int selected_registrar;
146 : :
147 : : int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr,
148 : : const u8 *psk, size_t psk_len);
149 : : int (*set_ie_cb)(void *ctx, struct wpabuf *beacon_ie,
150 : : struct wpabuf *probe_resp_ie);
151 : : void (*pin_needed_cb)(void *ctx, const u8 *uuid_e,
152 : : const struct wps_device_data *dev);
153 : : void (*reg_success_cb)(void *ctx, const u8 *mac_addr,
154 : : const u8 *uuid_e, const u8 *dev_pw,
155 : : size_t dev_pw_len);
156 : : void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id,
157 : : u16 sel_reg_config_methods);
158 : : void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e,
159 : : const u8 *pri_dev_type, u16 config_methods,
160 : : u16 dev_password_id, u8 request_type,
161 : : const char *dev_name);
162 : : void *cb_ctx;
163 : :
164 : : struct dl_list pins;
165 : : struct dl_list nfc_pw_tokens;
166 : : struct wps_pbc_session *pbc_sessions;
167 : :
168 : : int skip_cred_build;
169 : : struct wpabuf *extra_cred;
170 : : int disable_auto_conf;
171 : : int sel_reg_union;
172 : : int sel_reg_dev_password_id_override;
173 : : int sel_reg_config_methods_override;
174 : : int static_wep_only;
175 : : int dualband;
176 : : int force_per_enrollee_psk;
177 : :
178 : : struct wps_registrar_device *devices;
179 : :
180 : : int force_pbc_overlap;
181 : :
182 : : u8 authorized_macs[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN];
183 : : u8 authorized_macs_union[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN];
184 : :
185 : : u8 p2p_dev_addr[ETH_ALEN];
186 : :
187 : : u8 pbc_ignore_uuid[WPS_UUID_LEN];
188 : : #ifdef WPS_WORKAROUNDS
189 : : struct os_reltime pbc_ignore_start;
190 : : #endif /* WPS_WORKAROUNDS */
191 : : };
192 : :
193 : :
194 : : static int wps_set_ie(struct wps_registrar *reg);
195 : : static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx);
196 : : static void wps_registrar_set_selected_timeout(void *eloop_ctx,
197 : : void *timeout_ctx);
198 : : static void wps_registrar_remove_pin(struct wps_registrar *reg,
199 : : struct wps_uuid_pin *pin);
200 : :
201 : :
202 : 150 : static void wps_registrar_add_authorized_mac(struct wps_registrar *reg,
203 : : const u8 *addr)
204 : : {
205 : : int i;
206 : 150 : wpa_printf(MSG_DEBUG, "WPS: Add authorized MAC " MACSTR,
207 : 900 : MAC2STR(addr));
208 [ + + ]: 850 : for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++)
209 [ + + ]: 710 : if (os_memcmp(reg->authorized_macs[i], addr, ETH_ALEN) == 0) {
210 : 10 : wpa_printf(MSG_DEBUG, "WPS: Authorized MAC was "
211 : : "already in the list");
212 : 150 : return; /* already in list */
213 : : }
214 [ + + ]: 700 : for (i = WPS_MAX_AUTHORIZED_MACS - 1; i > 0; i--)
215 : 560 : os_memcpy(reg->authorized_macs[i], reg->authorized_macs[i - 1],
216 : : ETH_ALEN);
217 : 140 : os_memcpy(reg->authorized_macs[0], addr, ETH_ALEN);
218 : 140 : wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs",
219 : 140 : (u8 *) reg->authorized_macs, sizeof(reg->authorized_macs));
220 : : }
221 : :
222 : :
223 : 136 : static void wps_registrar_remove_authorized_mac(struct wps_registrar *reg,
224 : : const u8 *addr)
225 : : {
226 : : int i;
227 : 136 : wpa_printf(MSG_DEBUG, "WPS: Remove authorized MAC " MACSTR,
228 : 816 : MAC2STR(addr));
229 [ + + ]: 141 : for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++) {
230 [ + + ]: 140 : if (os_memcmp(reg->authorized_macs, addr, ETH_ALEN) == 0)
231 : 135 : break;
232 : : }
233 [ + + ]: 136 : if (i == WPS_MAX_AUTHORIZED_MACS) {
234 : 1 : wpa_printf(MSG_DEBUG, "WPS: Authorized MAC was not in the "
235 : : "list");
236 : 136 : return; /* not in the list */
237 : : }
238 [ + + ]: 675 : for (; i + 1 < WPS_MAX_AUTHORIZED_MACS; i++)
239 : 540 : os_memcpy(reg->authorized_macs[i], reg->authorized_macs[i + 1],
240 : : ETH_ALEN);
241 : 135 : os_memset(reg->authorized_macs[WPS_MAX_AUTHORIZED_MACS - 1], 0,
242 : : ETH_ALEN);
243 : 135 : wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs",
244 : 135 : (u8 *) reg->authorized_macs, sizeof(reg->authorized_macs));
245 : : }
246 : :
247 : :
248 : 175 : static void wps_free_devices(struct wps_registrar_device *dev)
249 : : {
250 : : struct wps_registrar_device *prev;
251 : :
252 [ + + ]: 300 : while (dev) {
253 : 125 : prev = dev;
254 : 125 : dev = dev->next;
255 : 125 : wps_device_data_free(&prev->dev);
256 : 125 : os_free(prev);
257 : : }
258 : 175 : }
259 : :
260 : :
261 : 139 : static struct wps_registrar_device * wps_device_get(struct wps_registrar *reg,
262 : : const u8 *addr)
263 : : {
264 : : struct wps_registrar_device *dev;
265 : :
266 [ + + ]: 176 : for (dev = reg->devices; dev; dev = dev->next) {
267 [ + + ]: 48 : if (os_memcmp(dev->dev.mac_addr, addr, ETH_ALEN) == 0)
268 : 11 : return dev;
269 : : }
270 : 139 : return NULL;
271 : : }
272 : :
273 : :
274 : 135 : static void wps_device_clone_data(struct wps_device_data *dst,
275 : : struct wps_device_data *src)
276 : : {
277 : 135 : os_memcpy(dst->mac_addr, src->mac_addr, ETH_ALEN);
278 : 135 : os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN);
279 : :
280 : : #define WPS_STRDUP(n) \
281 : : os_free(dst->n); \
282 : : dst->n = src->n ? os_strdup(src->n) : NULL
283 : :
284 [ + - ]: 135 : WPS_STRDUP(device_name);
285 [ + - ]: 135 : WPS_STRDUP(manufacturer);
286 [ + - ]: 135 : WPS_STRDUP(model_name);
287 [ + - ]: 135 : WPS_STRDUP(model_number);
288 [ + - ]: 135 : WPS_STRDUP(serial_number);
289 : : #undef WPS_STRDUP
290 : 135 : }
291 : :
292 : :
293 : 135 : int wps_device_store(struct wps_registrar *reg,
294 : : struct wps_device_data *dev, const u8 *uuid)
295 : : {
296 : : struct wps_registrar_device *d;
297 : :
298 : 135 : d = wps_device_get(reg, dev->mac_addr);
299 [ + + ]: 135 : if (d == NULL) {
300 : 125 : d = os_zalloc(sizeof(*d));
301 [ - + ]: 125 : if (d == NULL)
302 : 0 : return -1;
303 : 125 : d->next = reg->devices;
304 : 125 : reg->devices = d;
305 : : }
306 : :
307 : 135 : wps_device_clone_data(&d->dev, dev);
308 : 135 : os_memcpy(d->uuid, uuid, WPS_UUID_LEN);
309 : :
310 : 135 : return 0;
311 : : }
312 : :
313 : :
314 : 38 : static void wps_registrar_add_pbc_session(struct wps_registrar *reg,
315 : : const u8 *addr, const u8 *uuid_e)
316 : : {
317 : 38 : struct wps_pbc_session *pbc, *prev = NULL;
318 : : struct os_reltime now;
319 : :
320 : 38 : os_get_reltime(&now);
321 : :
322 : 38 : pbc = reg->pbc_sessions;
323 [ + + ]: 39 : while (pbc) {
324 [ + + ][ + - ]: 18 : if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 &&
325 : 17 : os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) {
326 [ - + ]: 17 : if (prev)
327 : 0 : prev->next = pbc->next;
328 : : else
329 : 17 : reg->pbc_sessions = pbc->next;
330 : 17 : break;
331 : : }
332 : 1 : prev = pbc;
333 : 1 : pbc = pbc->next;
334 : : }
335 : :
336 [ + + ]: 38 : if (!pbc) {
337 : 21 : pbc = os_zalloc(sizeof(*pbc));
338 [ - + ]: 21 : if (pbc == NULL)
339 : 38 : return;
340 : 21 : os_memcpy(pbc->addr, addr, ETH_ALEN);
341 [ + - ]: 21 : if (uuid_e)
342 : 21 : os_memcpy(pbc->uuid_e, uuid_e, WPS_UUID_LEN);
343 : : }
344 : :
345 : 38 : pbc->next = reg->pbc_sessions;
346 : 38 : reg->pbc_sessions = pbc;
347 : 38 : pbc->timestamp = now;
348 : :
349 : : /* remove entries that have timed out */
350 : 38 : prev = pbc;
351 : 38 : pbc = pbc->next;
352 : :
353 [ + + ]: 39 : while (pbc) {
354 [ - + ]: 1 : if (os_reltime_expired(&now, &pbc->timestamp,
355 : : WPS_PBC_WALK_TIME)) {
356 : 0 : prev->next = NULL;
357 : 0 : wps_free_pbc_sessions(pbc);
358 : 0 : break;
359 : : }
360 : 1 : prev = pbc;
361 : 1 : pbc = pbc->next;
362 : : }
363 : : }
364 : :
365 : :
366 : 16 : static void wps_registrar_remove_pbc_session(struct wps_registrar *reg,
367 : : const u8 *uuid_e,
368 : : const u8 *p2p_dev_addr)
369 : : {
370 : 16 : struct wps_pbc_session *pbc, *prev = NULL, *tmp;
371 : :
372 : 16 : pbc = reg->pbc_sessions;
373 [ + + ]: 32 : while (pbc) {
374 [ - + ][ # # ]: 16 : if (os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0 ||
375 [ # # ][ # # ]: 0 : (p2p_dev_addr && !is_zero_ether_addr(reg->p2p_dev_addr) &&
376 : 0 : os_memcmp(reg->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) ==
377 : : 0)) {
378 [ - + ]: 16 : if (prev)
379 : 0 : prev->next = pbc->next;
380 : : else
381 : 16 : reg->pbc_sessions = pbc->next;
382 : 16 : tmp = pbc;
383 : 16 : pbc = pbc->next;
384 : 16 : wpa_printf(MSG_DEBUG, "WPS: Removing PBC session for "
385 : 96 : "addr=" MACSTR, MAC2STR(tmp->addr));
386 : 16 : wpa_hexdump(MSG_DEBUG, "WPS: Removed UUID-E",
387 : 16 : tmp->uuid_e, WPS_UUID_LEN);
388 : 16 : os_free(tmp);
389 : 16 : continue;
390 : : }
391 : 0 : prev = pbc;
392 : 0 : pbc = pbc->next;
393 : : }
394 : 16 : }
395 : :
396 : :
397 : 58 : int wps_registrar_pbc_overlap(struct wps_registrar *reg,
398 : : const u8 *addr, const u8 *uuid_e)
399 : : {
400 : 58 : int count = 0;
401 : : struct wps_pbc_session *pbc;
402 : 58 : struct wps_pbc_session *first = NULL;
403 : : struct os_reltime now;
404 : :
405 : 58 : os_get_reltime(&now);
406 : :
407 : 58 : wpa_printf(MSG_DEBUG, "WPS: Checking active PBC sessions for overlap");
408 : :
409 [ + + ]: 58 : if (uuid_e) {
410 : 38 : wpa_printf(MSG_DEBUG, "WPS: Add one for the requested UUID");
411 : 38 : wpa_hexdump(MSG_DEBUG, "WPS: Requested UUID",
412 : : uuid_e, WPS_UUID_LEN);
413 : 38 : count++;
414 : : }
415 : :
416 [ + + ]: 101 : for (pbc = reg->pbc_sessions; pbc; pbc = pbc->next) {
417 : 43 : wpa_printf(MSG_DEBUG, "WPS: Consider PBC session with " MACSTR,
418 : 258 : MAC2STR(pbc->addr));
419 : 43 : wpa_hexdump(MSG_DEBUG, "WPS: UUID-E",
420 : 43 : pbc->uuid_e, WPS_UUID_LEN);
421 [ - + ]: 43 : if (os_reltime_expired(&now, &pbc->timestamp,
422 : : WPS_PBC_WALK_TIME)) {
423 : 0 : wpa_printf(MSG_DEBUG, "WPS: PBC walk time has expired");
424 : 0 : break;
425 : : }
426 [ + + ][ - + ]: 43 : if (first &&
427 : 2 : os_memcmp(pbc->uuid_e, first->uuid_e, WPS_UUID_LEN) == 0) {
428 : 0 : wpa_printf(MSG_DEBUG, "WPS: Same Enrollee");
429 : 0 : continue; /* same Enrollee */
430 : : }
431 [ + + ][ + + ]: 43 : if (uuid_e == NULL ||
432 : 39 : os_memcmp(uuid_e, pbc->uuid_e, WPS_UUID_LEN)) {
433 : 5 : wpa_printf(MSG_DEBUG, "WPS: New Enrollee");
434 : 5 : count++;
435 : : }
436 [ + + ]: 43 : if (first == NULL)
437 : 41 : first = pbc;
438 : : }
439 : :
440 : 58 : wpa_printf(MSG_DEBUG, "WPS: %u active PBC session(s) found", count);
441 : :
442 : 58 : return count > 1 ? 1 : 0;
443 : : }
444 : :
445 : :
446 : 978 : static int wps_build_wps_state(struct wps_context *wps, struct wpabuf *msg)
447 : : {
448 : 978 : wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)",
449 : 978 : wps->wps_state);
450 : 978 : wpabuf_put_be16(msg, ATTR_WPS_STATE);
451 : 978 : wpabuf_put_be16(msg, 1);
452 : 978 : wpabuf_put_u8(msg, wps->wps_state);
453 : 978 : return 0;
454 : : }
455 : :
456 : :
457 : : #ifdef CONFIG_WPS_UPNP
458 : 50 : static void wps_registrar_free_pending_m2(struct wps_context *wps)
459 : : {
460 : 50 : struct upnp_pending_message *p, *p2, *prev = NULL;
461 : 50 : p = wps->upnp_msgs;
462 [ + + ]: 80 : while (p) {
463 [ + - ][ - + ]: 30 : if (p->type == WPS_M2 || p->type == WPS_M2D) {
464 [ # # ]: 0 : if (prev == NULL)
465 : 0 : wps->upnp_msgs = p->next;
466 : : else
467 : 0 : prev->next = p->next;
468 : 0 : wpa_printf(MSG_DEBUG, "WPS UPnP: Drop pending M2/M2D");
469 : 0 : p2 = p;
470 : 0 : p = p->next;
471 : 0 : wpabuf_free(p2->msg);
472 : 0 : os_free(p2);
473 : 0 : continue;
474 : : }
475 : 30 : prev = p;
476 : 30 : p = p->next;
477 : : }
478 : 50 : }
479 : : #endif /* CONFIG_WPS_UPNP */
480 : :
481 : :
482 : 978 : static int wps_build_ap_setup_locked(struct wps_context *wps,
483 : : struct wpabuf *msg)
484 : : {
485 [ + + ][ + + ]: 978 : if (wps->ap_setup_locked && wps->ap_setup_locked != 2) {
486 : 10 : wpa_printf(MSG_DEBUG, "WPS: * AP Setup Locked");
487 : 10 : wpabuf_put_be16(msg, ATTR_AP_SETUP_LOCKED);
488 : 10 : wpabuf_put_be16(msg, 1);
489 : 10 : wpabuf_put_u8(msg, 1);
490 : : }
491 : 978 : return 0;
492 : : }
493 : :
494 : :
495 : 978 : static int wps_build_selected_registrar(struct wps_registrar *reg,
496 : : struct wpabuf *msg)
497 : : {
498 [ + + ]: 978 : if (!reg->sel_reg_union)
499 : 590 : return 0;
500 : 388 : wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar");
501 : 388 : wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR);
502 : 388 : wpabuf_put_be16(msg, 1);
503 : 388 : wpabuf_put_u8(msg, 1);
504 : 978 : return 0;
505 : : }
506 : :
507 : :
508 : 978 : static int wps_build_sel_reg_dev_password_id(struct wps_registrar *reg,
509 : : struct wpabuf *msg)
510 : : {
511 [ + + ]: 978 : u16 id = reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT;
512 [ + + ]: 978 : if (!reg->sel_reg_union)
513 : 590 : return 0;
514 [ + + ]: 388 : if (reg->sel_reg_dev_password_id_override >= 0)
515 : 100 : id = reg->sel_reg_dev_password_id_override;
516 : 388 : wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id);
517 : 388 : wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
518 : 388 : wpabuf_put_be16(msg, 2);
519 : 388 : wpabuf_put_be16(msg, id);
520 : 978 : return 0;
521 : : }
522 : :
523 : :
524 : 489 : static int wps_build_sel_pbc_reg_uuid_e(struct wps_registrar *reg,
525 : : struct wpabuf *msg)
526 : : {
527 [ + + ]: 489 : u16 id = reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT;
528 [ + + ]: 489 : if (!reg->sel_reg_union)
529 : 295 : return 0;
530 [ + + ]: 194 : if (reg->sel_reg_dev_password_id_override >= 0)
531 : 50 : id = reg->sel_reg_dev_password_id_override;
532 [ + + ][ + + ]: 194 : if (id != DEV_PW_PUSHBUTTON || !reg->dualband)
533 : 192 : return 0;
534 : 489 : return wps_build_uuid_e(msg, reg->wps->uuid);
535 : : }
536 : :
537 : :
538 : 62 : static void wps_set_pushbutton(u16 *methods, u16 conf_methods)
539 : : {
540 : 62 : *methods |= WPS_CONFIG_PUSHBUTTON;
541 : : #ifdef CONFIG_WPS2
542 [ - + ]: 62 : if ((conf_methods & WPS_CONFIG_VIRT_PUSHBUTTON) ==
543 : : WPS_CONFIG_VIRT_PUSHBUTTON)
544 : 0 : *methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
545 [ - + ]: 62 : if ((conf_methods & WPS_CONFIG_PHY_PUSHBUTTON) ==
546 : : WPS_CONFIG_PHY_PUSHBUTTON)
547 : 0 : *methods |= WPS_CONFIG_PHY_PUSHBUTTON;
548 [ + - ]: 62 : if ((*methods & WPS_CONFIG_VIRT_PUSHBUTTON) !=
549 [ + - ]: 62 : WPS_CONFIG_VIRT_PUSHBUTTON &&
550 : 62 : (*methods & WPS_CONFIG_PHY_PUSHBUTTON) !=
551 : : WPS_CONFIG_PHY_PUSHBUTTON) {
552 : : /*
553 : : * Required to include virtual/physical flag, but we were not
554 : : * configured with push button type, so have to default to one
555 : : * of them.
556 : : */
557 : 62 : *methods |= WPS_CONFIG_PHY_PUSHBUTTON;
558 : : }
559 : : #endif /* CONFIG_WPS2 */
560 : 62 : }
561 : :
562 : :
563 : 978 : static int wps_build_sel_reg_config_methods(struct wps_registrar *reg,
564 : : struct wpabuf *msg)
565 : : {
566 : : u16 methods;
567 [ + + ]: 978 : if (!reg->sel_reg_union)
568 : 590 : return 0;
569 : 388 : methods = reg->wps->config_methods;
570 : 388 : methods &= ~WPS_CONFIG_PUSHBUTTON;
571 : : #ifdef CONFIG_WPS2
572 : 388 : methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
573 : : WPS_CONFIG_PHY_PUSHBUTTON);
574 : : #endif /* CONFIG_WPS2 */
575 [ + + ]: 388 : if (reg->pbc)
576 : 40 : wps_set_pushbutton(&methods, reg->wps->config_methods);
577 [ + - ]: 388 : if (reg->sel_reg_config_methods_override >= 0)
578 : 388 : methods = reg->sel_reg_config_methods_override;
579 : 388 : wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar Config Methods (%x)",
580 : : methods);
581 : 388 : wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS);
582 : 388 : wpabuf_put_be16(msg, 2);
583 : 388 : wpabuf_put_be16(msg, methods);
584 : 978 : return 0;
585 : : }
586 : :
587 : :
588 : 489 : static int wps_build_probe_config_methods(struct wps_registrar *reg,
589 : : struct wpabuf *msg)
590 : : {
591 : : u16 methods;
592 : : /*
593 : : * These are the methods that the AP supports as an Enrollee for adding
594 : : * external Registrars.
595 : : */
596 : 489 : methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
597 : : #ifdef CONFIG_WPS2
598 : 489 : methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
599 : : WPS_CONFIG_PHY_PUSHBUTTON);
600 : : #endif /* CONFIG_WPS2 */
601 : 489 : wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods);
602 : 489 : wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
603 : 489 : wpabuf_put_be16(msg, 2);
604 : 489 : wpabuf_put_be16(msg, methods);
605 : 489 : return 0;
606 : : }
607 : :
608 : :
609 : 154 : static int wps_build_config_methods_r(struct wps_registrar *reg,
610 : : struct wpabuf *msg)
611 : : {
612 : 154 : return wps_build_config_methods(msg, reg->wps->config_methods);
613 : : }
614 : :
615 : :
616 : 515 : const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count)
617 : : {
618 : 515 : *count = 0;
619 : :
620 : : #ifdef CONFIG_WPS2
621 [ + - ]: 667 : while (*count < WPS_MAX_AUTHORIZED_MACS) {
622 [ + + ]: 667 : if (is_zero_ether_addr(reg->authorized_macs_union[*count]))
623 : 515 : break;
624 : 152 : (*count)++;
625 : : }
626 : : #endif /* CONFIG_WPS2 */
627 : :
628 : 515 : return (const u8 *) reg->authorized_macs_union;
629 : : }
630 : :
631 : :
632 : : /**
633 : : * wps_registrar_init - Initialize WPS Registrar data
634 : : * @wps: Pointer to longterm WPS context
635 : : * @cfg: Registrar configuration
636 : : * Returns: Pointer to allocated Registrar data or %NULL on failure
637 : : *
638 : : * This function is used to initialize WPS Registrar functionality. It can be
639 : : * used for a single Registrar run (e.g., when run in a supplicant) or multiple
640 : : * runs (e.g., when run as an internal Registrar in an AP). Caller is
641 : : * responsible for freeing the returned data with wps_registrar_deinit() when
642 : : * Registrar functionality is not needed anymore.
643 : : */
644 : : struct wps_registrar *
645 : 175 : wps_registrar_init(struct wps_context *wps,
646 : : const struct wps_registrar_config *cfg)
647 : : {
648 : 175 : struct wps_registrar *reg = os_zalloc(sizeof(*reg));
649 [ - + ]: 175 : if (reg == NULL)
650 : 0 : return NULL;
651 : :
652 : 175 : dl_list_init(®->pins);
653 : 175 : dl_list_init(®->nfc_pw_tokens);
654 : 175 : reg->wps = wps;
655 : 175 : reg->new_psk_cb = cfg->new_psk_cb;
656 : 175 : reg->set_ie_cb = cfg->set_ie_cb;
657 : 175 : reg->pin_needed_cb = cfg->pin_needed_cb;
658 : 175 : reg->reg_success_cb = cfg->reg_success_cb;
659 : 175 : reg->set_sel_reg_cb = cfg->set_sel_reg_cb;
660 : 175 : reg->enrollee_seen_cb = cfg->enrollee_seen_cb;
661 : 175 : reg->cb_ctx = cfg->cb_ctx;
662 : 175 : reg->skip_cred_build = cfg->skip_cred_build;
663 [ - + ]: 175 : if (cfg->extra_cred) {
664 : 0 : reg->extra_cred = wpabuf_alloc_copy(cfg->extra_cred,
665 : : cfg->extra_cred_len);
666 [ # # ]: 0 : if (reg->extra_cred == NULL) {
667 : 0 : os_free(reg);
668 : 0 : return NULL;
669 : : }
670 : : }
671 : 175 : reg->disable_auto_conf = cfg->disable_auto_conf;
672 : 175 : reg->sel_reg_dev_password_id_override = -1;
673 : 175 : reg->sel_reg_config_methods_override = -1;
674 : 175 : reg->static_wep_only = cfg->static_wep_only;
675 : 175 : reg->dualband = cfg->dualband;
676 : 175 : reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk;
677 : :
678 [ - + ]: 175 : if (wps_set_ie(reg)) {
679 : 0 : wps_registrar_deinit(reg);
680 : 0 : return NULL;
681 : : }
682 : :
683 : 175 : return reg;
684 : : }
685 : :
686 : :
687 : : /**
688 : : * wps_registrar_deinit - Deinitialize WPS Registrar data
689 : : * @reg: Registrar data from wps_registrar_init()
690 : : */
691 : 175 : void wps_registrar_deinit(struct wps_registrar *reg)
692 : : {
693 [ - + ]: 175 : if (reg == NULL)
694 : 175 : return;
695 : 175 : eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
696 : 175 : eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
697 : 175 : wps_free_pins(®->pins);
698 : 175 : wps_free_nfc_pw_tokens(®->nfc_pw_tokens, 0);
699 : 175 : wps_free_pbc_sessions(reg->pbc_sessions);
700 : 175 : wpabuf_free(reg->extra_cred);
701 : 175 : wps_free_devices(reg->devices);
702 : 175 : os_free(reg);
703 : : }
704 : :
705 : :
706 : 101 : static void wps_registrar_invalidate_unused(struct wps_registrar *reg)
707 : : {
708 : : struct wps_uuid_pin *pin;
709 : :
710 [ + + ]: 129 : dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) {
711 [ + + ][ + - ]: 29 : if (pin->wildcard_uuid == 1 && !(pin->flags & PIN_LOCKED)) {
712 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalidate previously "
713 : : "configured wildcard PIN");
714 : 1 : wps_registrar_remove_pin(reg, pin);
715 : 1 : break;
716 : : }
717 : : }
718 : 101 : }
719 : :
720 : :
721 : : /**
722 : : * wps_registrar_add_pin - Configure a new PIN for Registrar
723 : : * @reg: Registrar data from wps_registrar_init()
724 : : * @addr: Enrollee MAC address or %NULL if not known
725 : : * @uuid: UUID-E or %NULL for wildcard (any UUID)
726 : : * @pin: PIN (Device Password)
727 : : * @pin_len: Length of pin in octets
728 : : * @timeout: Time (in seconds) when the PIN will be invalidated; 0 = no timeout
729 : : * Returns: 0 on success, -1 on failure
730 : : */
731 : 106 : int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr,
732 : : const u8 *uuid, const u8 *pin, size_t pin_len,
733 : : int timeout)
734 : : {
735 : : struct wps_uuid_pin *p;
736 : :
737 : 106 : p = os_zalloc(sizeof(*p));
738 [ - + ]: 106 : if (p == NULL)
739 : 0 : return -1;
740 [ + + ]: 106 : if (addr)
741 : 40 : os_memcpy(p->enrollee_addr, addr, ETH_ALEN);
742 [ + + ]: 106 : if (uuid == NULL)
743 : 101 : p->wildcard_uuid = 1;
744 : : else
745 : 5 : os_memcpy(p->uuid, uuid, WPS_UUID_LEN);
746 : 106 : p->pin = os_malloc(pin_len);
747 [ - + ]: 106 : if (p->pin == NULL) {
748 : 0 : os_free(p);
749 : 0 : return -1;
750 : : }
751 : 106 : os_memcpy(p->pin, pin, pin_len);
752 : 106 : p->pin_len = pin_len;
753 : :
754 [ + + ]: 106 : if (timeout) {
755 : 4 : p->flags |= PIN_EXPIRES;
756 : 4 : os_get_reltime(&p->expiration);
757 : 4 : p->expiration.sec += timeout;
758 : : }
759 : :
760 [ + + ]: 106 : if (p->wildcard_uuid)
761 : 101 : wps_registrar_invalidate_unused(reg);
762 : :
763 : 106 : dl_list_add(®->pins, &p->list);
764 : :
765 : 106 : wpa_printf(MSG_DEBUG, "WPS: A new PIN configured (timeout=%d)",
766 : : timeout);
767 : 106 : wpa_hexdump(MSG_DEBUG, "WPS: UUID", uuid, WPS_UUID_LEN);
768 : 106 : wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: PIN", pin, pin_len);
769 : 106 : reg->selected_registrar = 1;
770 : 106 : reg->pbc = 0;
771 [ + + ]: 106 : if (addr)
772 : 40 : wps_registrar_add_authorized_mac(reg, addr);
773 : : else
774 : 66 : wps_registrar_add_authorized_mac(
775 : : reg, (u8 *) "\xff\xff\xff\xff\xff\xff");
776 : 106 : wps_registrar_selected_registrar_changed(reg, 0);
777 : 106 : eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
778 : 106 : eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
779 : : wps_registrar_set_selected_timeout,
780 : : reg, NULL);
781 : :
782 : 106 : return 0;
783 : : }
784 : :
785 : :
786 : 94 : static void wps_registrar_remove_pin(struct wps_registrar *reg,
787 : : struct wps_uuid_pin *pin)
788 : : {
789 : : u8 *addr;
790 : 94 : u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
791 : :
792 [ + + ]: 94 : if (is_zero_ether_addr(pin->enrollee_addr))
793 : 55 : addr = bcast;
794 : : else
795 : 39 : addr = pin->enrollee_addr;
796 : 94 : wps_registrar_remove_authorized_mac(reg, addr);
797 : 94 : wps_remove_pin(pin);
798 : 94 : wps_registrar_selected_registrar_changed(reg, 0);
799 : 94 : }
800 : :
801 : :
802 : 111 : static void wps_registrar_expire_pins(struct wps_registrar *reg)
803 : : {
804 : : struct wps_uuid_pin *pin, *prev;
805 : : struct os_reltime now;
806 : :
807 : 111 : os_get_reltime(&now);
808 [ + + ]: 244 : dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list)
809 : : {
810 [ + + - + ]: 136 : if ((pin->flags & PIN_EXPIRES) &&
811 : 3 : os_reltime_before(&pin->expiration, &now)) {
812 : 0 : wpa_hexdump(MSG_DEBUG, "WPS: Expired PIN for UUID",
813 : 0 : pin->uuid, WPS_UUID_LEN);
814 : 0 : wps_registrar_remove_pin(reg, pin);
815 : : }
816 : : }
817 : 111 : }
818 : :
819 : :
820 : : /**
821 : : * wps_registrar_invalidate_wildcard_pin - Invalidate a wildcard PIN
822 : : * @reg: Registrar data from wps_registrar_init()
823 : : * @dev_pw: PIN to search for or %NULL to match any
824 : : * @dev_pw_len: Length of dev_pw in octets
825 : : * Returns: 0 on success, -1 if not wildcard PIN is enabled
826 : : */
827 : 3 : static int wps_registrar_invalidate_wildcard_pin(struct wps_registrar *reg,
828 : : const u8 *dev_pw,
829 : : size_t dev_pw_len)
830 : : {
831 : : struct wps_uuid_pin *pin, *prev;
832 : :
833 [ + + ]: 3 : dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list)
834 : : {
835 [ + + ][ + - ]: 2 : if (dev_pw && pin->pin &&
[ + - ]
836 [ - + ]: 1 : (dev_pw_len != pin->pin_len ||
837 : 1 : os_memcmp(dev_pw, pin->pin, dev_pw_len) != 0))
838 : 0 : continue; /* different PIN */
839 [ + - ]: 2 : if (pin->wildcard_uuid) {
840 : 2 : wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID",
841 : 2 : pin->uuid, WPS_UUID_LEN);
842 : 2 : wps_registrar_remove_pin(reg, pin);
843 : 2 : return 0;
844 : : }
845 : : }
846 : :
847 : 3 : return -1;
848 : : }
849 : :
850 : :
851 : : /**
852 : : * wps_registrar_invalidate_pin - Invalidate a PIN for a specific UUID-E
853 : : * @reg: Registrar data from wps_registrar_init()
854 : : * @uuid: UUID-E
855 : : * Returns: 0 on success, -1 on failure (e.g., PIN not found)
856 : : */
857 : 116 : int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid)
858 : : {
859 : : struct wps_uuid_pin *pin, *prev;
860 : :
861 [ + + ]: 117 : dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list)
862 : : {
863 [ + + ]: 92 : if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
864 : 91 : wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID",
865 : 91 : pin->uuid, WPS_UUID_LEN);
866 : 91 : wps_registrar_remove_pin(reg, pin);
867 : 91 : return 0;
868 : : }
869 : : }
870 : :
871 : 116 : return -1;
872 : : }
873 : :
874 : :
875 : 111 : static const u8 * wps_registrar_get_pin(struct wps_registrar *reg,
876 : : const u8 *uuid, size_t *pin_len)
877 : : {
878 : 111 : struct wps_uuid_pin *pin, *found = NULL;
879 : :
880 : 111 : wps_registrar_expire_pins(reg);
881 : :
882 [ + + ]: 238 : dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) {
883 [ + + ][ + + ]: 132 : if (!pin->wildcard_uuid &&
884 : 6 : os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
885 : 5 : found = pin;
886 : 5 : break;
887 : : }
888 : : }
889 : :
890 [ + + ]: 111 : if (!found) {
891 : : /* Check for wildcard UUIDs since none of the UUID-specific
892 : : * PINs matched */
893 [ + + ]: 106 : dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) {
894 [ - + ][ # # ]: 98 : if (pin->wildcard_uuid == 1 ||
895 : 0 : pin->wildcard_uuid == 2) {
896 : 98 : wpa_printf(MSG_DEBUG, "WPS: Found a wildcard "
897 : : "PIN. Assigned it for this UUID-E");
898 : 98 : pin->wildcard_uuid++;
899 : 98 : os_memcpy(pin->uuid, uuid, WPS_UUID_LEN);
900 : 98 : found = pin;
901 : 98 : break;
902 : : }
903 : : }
904 : : }
905 : :
906 [ + + ]: 111 : if (!found)
907 : 8 : return NULL;
908 : :
909 : : /*
910 : : * Lock the PIN to avoid attacks based on concurrent re-use of the PIN
911 : : * that could otherwise avoid PIN invalidations.
912 : : */
913 [ - + ]: 103 : if (found->flags & PIN_LOCKED) {
914 : 0 : wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not "
915 : : "allow concurrent re-use");
916 : 0 : return NULL;
917 : : }
918 : 103 : *pin_len = found->pin_len;
919 : 103 : found->flags |= PIN_LOCKED;
920 : 111 : return found->pin;
921 : : }
922 : :
923 : :
924 : : /**
925 : : * wps_registrar_unlock_pin - Unlock a PIN for a specific UUID-E
926 : : * @reg: Registrar data from wps_registrar_init()
927 : : * @uuid: UUID-E
928 : : * Returns: 0 on success, -1 on failure
929 : : *
930 : : * PINs are locked to enforce only one concurrent use. This function unlocks a
931 : : * PIN to allow it to be used again. If the specified PIN was configured using
932 : : * a wildcard UUID, it will be removed instead of allowing multiple uses.
933 : : */
934 : 264 : int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid)
935 : : {
936 : : struct wps_uuid_pin *pin;
937 : :
938 [ + + ]: 270 : dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) {
939 [ + + ]: 108 : if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
940 [ - + ]: 102 : if (pin->wildcard_uuid == 3) {
941 : 0 : wpa_printf(MSG_DEBUG, "WPS: Invalidating used "
942 : : "wildcard PIN");
943 : 0 : return wps_registrar_invalidate_pin(reg, uuid);
944 : : }
945 : 102 : pin->flags &= ~PIN_LOCKED;
946 : 102 : return 0;
947 : : }
948 : : }
949 : :
950 : 264 : return -1;
951 : : }
952 : :
953 : :
954 : 19 : static void wps_registrar_stop_pbc(struct wps_registrar *reg)
955 : : {
956 : 19 : reg->selected_registrar = 0;
957 : 19 : reg->pbc = 0;
958 : 19 : os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
959 : 19 : wps_registrar_remove_authorized_mac(reg,
960 : : (u8 *) "\xff\xff\xff\xff\xff\xff");
961 : 19 : wps_registrar_selected_registrar_changed(reg, 0);
962 : 19 : }
963 : :
964 : :
965 : 3 : static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx)
966 : : {
967 : 3 : struct wps_registrar *reg = eloop_ctx;
968 : :
969 : 3 : wpa_printf(MSG_DEBUG, "WPS: PBC timed out - disable PBC mode");
970 : 3 : wps_pbc_timeout_event(reg->wps);
971 : 3 : wps_registrar_stop_pbc(reg);
972 : 3 : }
973 : :
974 : :
975 : : /**
976 : : * wps_registrar_button_pushed - Notify Registrar that AP button was pushed
977 : : * @reg: Registrar data from wps_registrar_init()
978 : : * @p2p_dev_addr: Limit allowed PBC devices to the specified P2P device, %NULL
979 : : * indicates no such filtering
980 : : * Returns: 0 on success, -1 on failure, -2 on session overlap
981 : : *
982 : : * This function is called on an AP when a push button is pushed to activate
983 : : * PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout
984 : : * or when a PBC registration is completed. If more than one Enrollee in active
985 : : * PBC mode has been detected during the monitor time (previous 2 minutes), the
986 : : * PBC mode is not activated and -2 is returned to indicate session overlap.
987 : : * This is skipped if a specific Enrollee is selected.
988 : : */
989 : 22 : int wps_registrar_button_pushed(struct wps_registrar *reg,
990 : : const u8 *p2p_dev_addr)
991 : : {
992 [ + + + + ]: 41 : if (p2p_dev_addr == NULL &&
993 : 19 : wps_registrar_pbc_overlap(reg, NULL, NULL)) {
994 : 1 : wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC "
995 : : "mode");
996 : 1 : wps_pbc_overlap_event(reg->wps);
997 : 1 : return -2;
998 : : }
999 : 21 : wpa_printf(MSG_DEBUG, "WPS: Button pushed - PBC mode started");
1000 : 21 : reg->force_pbc_overlap = 0;
1001 : 21 : reg->selected_registrar = 1;
1002 : 21 : reg->pbc = 1;
1003 [ + + ]: 21 : if (p2p_dev_addr)
1004 : 3 : os_memcpy(reg->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
1005 : : else
1006 : 18 : os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
1007 : 21 : wps_registrar_add_authorized_mac(reg,
1008 : : (u8 *) "\xff\xff\xff\xff\xff\xff");
1009 : 21 : wps_registrar_selected_registrar_changed(reg, 0);
1010 : :
1011 : 21 : wps_pbc_active_event(reg->wps);
1012 : 21 : eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
1013 : 21 : eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
1014 : 21 : eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_pbc_timeout,
1015 : : reg, NULL);
1016 : 22 : return 0;
1017 : : }
1018 : :
1019 : :
1020 : 16 : static void wps_registrar_pbc_completed(struct wps_registrar *reg)
1021 : : {
1022 : 16 : wpa_printf(MSG_DEBUG, "WPS: PBC completed - stopping PBC mode");
1023 : 16 : eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
1024 : 16 : wps_registrar_stop_pbc(reg);
1025 : 16 : wps_pbc_disable_event(reg->wps);
1026 : 16 : }
1027 : :
1028 : :
1029 : 110 : static void wps_registrar_pin_completed(struct wps_registrar *reg)
1030 : : {
1031 : 110 : wpa_printf(MSG_DEBUG, "WPS: PIN completed using internal Registrar");
1032 : 110 : eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
1033 : 110 : reg->selected_registrar = 0;
1034 : 110 : wps_registrar_selected_registrar_changed(reg, 0);
1035 : 110 : }
1036 : :
1037 : :
1038 : 2 : void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e,
1039 : : const u8 *dev_pw, size_t dev_pw_len)
1040 : : {
1041 [ + + ]: 2 : if (registrar->pbc) {
1042 : 1 : wps_registrar_remove_pbc_session(registrar,
1043 : : uuid_e, NULL);
1044 : 1 : wps_registrar_pbc_completed(registrar);
1045 : : #ifdef WPS_WORKAROUNDS
1046 : 1 : os_get_reltime(®istrar->pbc_ignore_start);
1047 : : #endif /* WPS_WORKAROUNDS */
1048 : 1 : os_memcpy(registrar->pbc_ignore_uuid, uuid_e, WPS_UUID_LEN);
1049 : : } else {
1050 : 1 : wps_registrar_pin_completed(registrar);
1051 : : }
1052 : :
1053 [ + - + + ]: 4 : if (dev_pw &&
1054 : 2 : wps_registrar_invalidate_wildcard_pin(registrar, dev_pw,
1055 : : dev_pw_len) == 0) {
1056 : 1 : wpa_hexdump_key(MSG_DEBUG, "WPS: Invalidated wildcard PIN",
1057 : : dev_pw, dev_pw_len);
1058 : : }
1059 : 2 : }
1060 : :
1061 : :
1062 : 8 : int wps_registrar_wps_cancel(struct wps_registrar *reg)
1063 : : {
1064 [ + + ]: 8 : if (reg->pbc) {
1065 : 3 : wpa_printf(MSG_DEBUG, "WPS: PBC is set - cancelling it");
1066 : 3 : wps_registrar_pbc_timeout(reg, NULL);
1067 : 3 : eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
1068 : 3 : return 1;
1069 [ + + ]: 5 : } else if (reg->selected_registrar) {
1070 : : /* PIN Method */
1071 : 1 : wpa_printf(MSG_DEBUG, "WPS: PIN is set - cancelling it");
1072 : 1 : wps_registrar_pin_completed(reg);
1073 : 1 : wps_registrar_invalidate_wildcard_pin(reg, NULL, 0);
1074 : 1 : return 1;
1075 : : }
1076 : 8 : return 0;
1077 : : }
1078 : :
1079 : :
1080 : : /**
1081 : : * wps_registrar_probe_req_rx - Notify Registrar of Probe Request
1082 : : * @reg: Registrar data from wps_registrar_init()
1083 : : * @addr: MAC address of the Probe Request sender
1084 : : * @wps_data: WPS IE contents
1085 : : *
1086 : : * This function is called on an AP when a Probe Request with WPS IE is
1087 : : * received. This is used to track PBC mode use and to detect possible overlap
1088 : : * situation with other WPS APs.
1089 : : */
1090 : 254 : void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr,
1091 : : const struct wpabuf *wps_data,
1092 : : int p2p_wildcard)
1093 : : {
1094 : : struct wps_parse_attr attr;
1095 : 254 : int skip_add = 0;
1096 : :
1097 : 254 : wpa_hexdump_buf(MSG_MSGDUMP,
1098 : : "WPS: Probe Request with WPS data received",
1099 : : wps_data);
1100 : :
1101 [ - + ]: 254 : if (wps_parse_msg(wps_data, &attr) < 0)
1102 : 0 : return;
1103 : :
1104 [ - + ]: 254 : if (attr.config_methods == NULL) {
1105 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Config Methods attribute in "
1106 : : "Probe Request");
1107 : 0 : return;
1108 : : }
1109 : :
1110 [ - + ]: 254 : if (attr.dev_password_id == NULL) {
1111 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Device Password Id attribute "
1112 : : "in Probe Request");
1113 : 0 : return;
1114 : : }
1115 : :
1116 [ + + ][ + - ]: 254 : if (reg->enrollee_seen_cb && attr.uuid_e &&
[ + - ]
1117 [ + - ][ + - ]: 229 : attr.primary_dev_type && attr.request_type && !p2p_wildcard) {
1118 : 229 : char *dev_name = NULL;
1119 [ + - ]: 229 : if (attr.dev_name) {
1120 : 229 : dev_name = os_zalloc(attr.dev_name_len + 1);
1121 [ + - ]: 229 : if (dev_name) {
1122 : 229 : os_memcpy(dev_name, attr.dev_name,
1123 : : attr.dev_name_len);
1124 : : }
1125 : : }
1126 : 229 : reg->enrollee_seen_cb(reg->cb_ctx, addr, attr.uuid_e,
1127 : : attr.primary_dev_type,
1128 : 229 : WPA_GET_BE16(attr.config_methods),
1129 : 229 : WPA_GET_BE16(attr.dev_password_id),
1130 : 229 : *attr.request_type, dev_name);
1131 : 229 : os_free(dev_name);
1132 : : }
1133 : :
1134 [ + + ]: 254 : if (WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON)
1135 : 231 : return; /* Not PBC */
1136 : :
1137 : 23 : wpa_printf(MSG_DEBUG, "WPS: Probe Request for PBC received from "
1138 : 138 : MACSTR, MAC2STR(addr));
1139 [ - + ]: 23 : if (attr.uuid_e == NULL) {
1140 : 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Probe Request WPS IE: No "
1141 : : "UUID-E included");
1142 : 0 : return;
1143 : : }
1144 : 23 : wpa_hexdump(MSG_DEBUG, "WPS: UUID-E from Probe Request", attr.uuid_e,
1145 : : WPS_UUID_LEN);
1146 : :
1147 : : #ifdef WPS_WORKAROUNDS
1148 [ # # ][ - + ]: 23 : if (reg->pbc_ignore_start.sec &&
1149 : 0 : os_memcmp(attr.uuid_e, reg->pbc_ignore_uuid, WPS_UUID_LEN) == 0) {
1150 : : struct os_reltime now, dur;
1151 : 0 : os_get_reltime(&now);
1152 : 0 : os_reltime_sub(&now, ®->pbc_ignore_start, &dur);
1153 [ # # ][ # # ]: 0 : if (dur.sec >= 0 && dur.sec < 5) {
1154 : 0 : wpa_printf(MSG_DEBUG, "WPS: Ignore PBC activation "
1155 : : "based on Probe Request from the Enrollee "
1156 : : "that just completed PBC provisioning");
1157 : 0 : skip_add = 1;
1158 : : } else
1159 : 0 : reg->pbc_ignore_start.sec = 0;
1160 : : }
1161 : : #endif /* WPS_WORKAROUNDS */
1162 : :
1163 [ + - ]: 23 : if (!skip_add)
1164 : 23 : wps_registrar_add_pbc_session(reg, addr, attr.uuid_e);
1165 [ + + ]: 23 : if (wps_registrar_pbc_overlap(reg, addr, attr.uuid_e)) {
1166 : 1 : wpa_printf(MSG_DEBUG, "WPS: PBC session overlap detected");
1167 : 1 : reg->force_pbc_overlap = 1;
1168 : 254 : wps_pbc_overlap_event(reg->wps);
1169 : : }
1170 : : }
1171 : :
1172 : :
1173 : 8 : static int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr,
1174 : : const u8 *p2p_dev_addr, const u8 *psk, size_t psk_len)
1175 : : {
1176 [ - + ]: 8 : if (reg->new_psk_cb == NULL)
1177 : 0 : return 0;
1178 : :
1179 : 8 : return reg->new_psk_cb(reg->cb_ctx, mac_addr, p2p_dev_addr, psk,
1180 : : psk_len);
1181 : : }
1182 : :
1183 : :
1184 : 8 : static void wps_cb_pin_needed(struct wps_registrar *reg, const u8 *uuid_e,
1185 : : const struct wps_device_data *dev)
1186 : : {
1187 [ - + ]: 8 : if (reg->pin_needed_cb == NULL)
1188 : 8 : return;
1189 : :
1190 : 8 : reg->pin_needed_cb(reg->cb_ctx, uuid_e, dev);
1191 : : }
1192 : :
1193 : :
1194 : 111 : static void wps_cb_reg_success(struct wps_registrar *reg, const u8 *mac_addr,
1195 : : const u8 *uuid_e, const u8 *dev_pw,
1196 : : size_t dev_pw_len)
1197 : : {
1198 [ + + ]: 111 : if (reg->reg_success_cb == NULL)
1199 : 111 : return;
1200 : :
1201 : 100 : reg->reg_success_cb(reg->cb_ctx, mac_addr, uuid_e, dev_pw, dev_pw_len);
1202 : : }
1203 : :
1204 : :
1205 : 489 : static int wps_cb_set_ie(struct wps_registrar *reg, struct wpabuf *beacon_ie,
1206 : : struct wpabuf *probe_resp_ie)
1207 : : {
1208 : 489 : return reg->set_ie_cb(reg->cb_ctx, beacon_ie, probe_resp_ie);
1209 : : }
1210 : :
1211 : :
1212 : 428 : static void wps_cb_set_sel_reg(struct wps_registrar *reg)
1213 : : {
1214 : 428 : u16 methods = 0;
1215 [ + + ]: 428 : if (reg->set_sel_reg_cb == NULL)
1216 : 428 : return;
1217 : :
1218 [ + + ]: 93 : if (reg->selected_registrar) {
1219 : 64 : methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
1220 : : #ifdef CONFIG_WPS2
1221 : 64 : methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
1222 : : WPS_CONFIG_PHY_PUSHBUTTON);
1223 : : #endif /* CONFIG_WPS2 */
1224 [ + + ]: 64 : if (reg->pbc)
1225 : 1 : wps_set_pushbutton(&methods, reg->wps->config_methods);
1226 : : }
1227 : :
1228 : 93 : wpa_printf(MSG_DEBUG, "WPS: wps_cb_set_sel_reg: sel_reg=%d "
1229 : : "config_methods=0x%x pbc=%d methods=0x%x",
1230 : 93 : reg->selected_registrar, reg->wps->config_methods,
1231 : : reg->pbc, methods);
1232 : :
1233 [ + + ]: 93 : reg->set_sel_reg_cb(reg->cb_ctx, reg->selected_registrar,
1234 : 93 : reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT,
1235 : : methods);
1236 : : }
1237 : :
1238 : :
1239 : 621 : static int wps_set_ie(struct wps_registrar *reg)
1240 : : {
1241 : : struct wpabuf *beacon;
1242 : : struct wpabuf *probe;
1243 : : const u8 *auth_macs;
1244 : : size_t count;
1245 : 621 : size_t vendor_len = 0;
1246 : : int i;
1247 : :
1248 [ + + ]: 621 : if (reg->set_ie_cb == NULL)
1249 : 132 : return 0;
1250 : :
1251 [ + + ]: 5379 : for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
1252 [ - + ]: 4890 : if (reg->wps->dev.vendor_ext[i]) {
1253 : 0 : vendor_len += 2 + 2;
1254 : 0 : vendor_len += wpabuf_len(reg->wps->dev.vendor_ext[i]);
1255 : : }
1256 : : }
1257 : :
1258 : 489 : beacon = wpabuf_alloc(400 + vendor_len);
1259 [ - + ]: 489 : if (beacon == NULL)
1260 : 0 : return -1;
1261 : 489 : probe = wpabuf_alloc(500 + vendor_len);
1262 [ - + ]: 489 : if (probe == NULL) {
1263 : 0 : wpabuf_free(beacon);
1264 : 0 : return -1;
1265 : : }
1266 : :
1267 : 489 : auth_macs = wps_authorized_macs(reg, &count);
1268 : :
1269 : 489 : wpa_printf(MSG_DEBUG, "WPS: Build Beacon IEs");
1270 : :
1271 [ + - + - ]: 978 : if (wps_build_version(beacon) ||
1272 [ + - ]: 978 : wps_build_wps_state(reg->wps, beacon) ||
1273 [ + - ]: 978 : wps_build_ap_setup_locked(reg->wps, beacon) ||
1274 [ + - ]: 978 : wps_build_selected_registrar(reg, beacon) ||
1275 [ + - ]: 978 : wps_build_sel_reg_dev_password_id(reg, beacon) ||
1276 [ + - ]: 978 : wps_build_sel_reg_config_methods(reg, beacon) ||
1277 [ + + ]: 978 : wps_build_sel_pbc_reg_uuid_e(reg, beacon) ||
1278 [ + - + - ]: 500 : (reg->dualband && wps_build_rf_bands(®->wps->dev, beacon, 0)) ||
1279 [ - + ]: 978 : wps_build_wfa_ext(beacon, 0, auth_macs, count) ||
1280 : 489 : wps_build_vendor_ext(®->wps->dev, beacon)) {
1281 : 0 : wpabuf_free(beacon);
1282 : 0 : wpabuf_free(probe);
1283 : 0 : return -1;
1284 : : }
1285 : :
1286 : : #ifdef CONFIG_P2P
1287 [ + - - + ]: 646 : if (wps_build_dev_name(®->wps->dev, beacon) ||
1288 : 323 : wps_build_primary_dev_type(®->wps->dev, beacon)) {
1289 : 0 : wpabuf_free(beacon);
1290 : 0 : wpabuf_free(probe);
1291 : 0 : return -1;
1292 : : }
1293 : : #endif /* CONFIG_P2P */
1294 : :
1295 : 489 : wpa_printf(MSG_DEBUG, "WPS: Build Probe Response IEs");
1296 : :
1297 [ + - + - ]: 978 : if (wps_build_version(probe) ||
1298 [ + - ]: 978 : wps_build_wps_state(reg->wps, probe) ||
1299 [ + - ]: 978 : wps_build_ap_setup_locked(reg->wps, probe) ||
1300 [ + - ]: 978 : wps_build_selected_registrar(reg, probe) ||
1301 [ + - ]: 978 : wps_build_sel_reg_dev_password_id(reg, probe) ||
1302 [ + - ]: 978 : wps_build_sel_reg_config_methods(reg, probe) ||
1303 [ + - ]: 489 : wps_build_resp_type(probe, reg->wps->ap ? WPS_RESP_AP :
1304 [ + - ]: 489 : WPS_RESP_REGISTRAR) ||
1305 [ + - ]: 978 : wps_build_uuid_e(probe, reg->wps->uuid) ||
1306 [ + - ]: 978 : wps_build_device_attrs(®->wps->dev, probe) ||
1307 [ + + ]: 978 : wps_build_probe_config_methods(reg, probe) ||
1308 [ + - + - ]: 500 : (reg->dualband && wps_build_rf_bands(®->wps->dev, probe, 0)) ||
1309 [ - + ]: 978 : wps_build_wfa_ext(probe, 0, auth_macs, count) ||
1310 : 489 : wps_build_vendor_ext(®->wps->dev, probe)) {
1311 : 0 : wpabuf_free(beacon);
1312 : 0 : wpabuf_free(probe);
1313 : 0 : return -1;
1314 : : }
1315 : :
1316 : 489 : beacon = wps_ie_encapsulate(beacon);
1317 : 489 : probe = wps_ie_encapsulate(probe);
1318 : :
1319 [ - + ][ + - ]: 489 : if (!beacon || !probe) {
1320 : 0 : wpabuf_free(beacon);
1321 : 0 : wpabuf_free(probe);
1322 : 0 : return -1;
1323 : : }
1324 : :
1325 [ - + ]: 489 : if (reg->static_wep_only) {
1326 : : /*
1327 : : * Windows XP and Vista clients can get confused about
1328 : : * EAP-Identity/Request when they probe the network with
1329 : : * EAPOL-Start. In such a case, they may assume the network is
1330 : : * using IEEE 802.1X and prompt user for a certificate while
1331 : : * the correct (non-WPS) behavior would be to ask for the
1332 : : * static WEP key. As a workaround, use Microsoft Provisioning
1333 : : * IE to advertise that legacy 802.1X is not supported.
1334 : : */
1335 : 0 : const u8 ms_wps[7] = {
1336 : : WLAN_EID_VENDOR_SPECIFIC, 5,
1337 : : /* Microsoft Provisioning IE (00:50:f2:5) */
1338 : : 0x00, 0x50, 0xf2, 5,
1339 : : 0x00 /* no legacy 802.1X or MS WPS */
1340 : : };
1341 : 0 : wpa_printf(MSG_DEBUG, "WPS: Add Microsoft Provisioning IE "
1342 : : "into Beacon/Probe Response frames");
1343 : 0 : wpabuf_put_data(beacon, ms_wps, sizeof(ms_wps));
1344 : 0 : wpabuf_put_data(probe, ms_wps, sizeof(ms_wps));
1345 : : }
1346 : :
1347 : 621 : return wps_cb_set_ie(reg, beacon, probe);
1348 : : }
1349 : :
1350 : :
1351 : 149 : static int wps_get_dev_password(struct wps_data *wps)
1352 : : {
1353 : : const u8 *pin;
1354 : 149 : size_t pin_len = 0;
1355 : :
1356 : 149 : os_free(wps->dev_password);
1357 : 149 : wps->dev_password = NULL;
1358 : :
1359 [ + + ]: 149 : if (wps->pbc) {
1360 : 15 : wpa_printf(MSG_DEBUG, "WPS: Use default PIN for PBC");
1361 : 15 : pin = (const u8 *) "00000000";
1362 : 15 : pin_len = 8;
1363 : : #ifdef CONFIG_WPS_NFC
1364 [ + + ]: 134 : } else if (wps->nfc_pw_token) {
1365 [ + + ]: 21 : if (wps->nfc_pw_token->pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)
1366 : : {
1367 : 13 : wpa_printf(MSG_DEBUG, "WPS: Using NFC connection "
1368 : : "handover and abbreviated WPS handshake "
1369 : : "without Device Password");
1370 : 13 : return 0;
1371 : : }
1372 : 8 : wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from NFC "
1373 : : "Password Token");
1374 : 8 : pin = wps->nfc_pw_token->dev_pw;
1375 : 8 : pin_len = wps->nfc_pw_token->dev_pw_len;
1376 [ + + ][ + + ]: 113 : } else if (wps->dev_pw_id >= 0x10 &&
1377 [ + - ]: 2 : wps->wps->ap_nfc_dev_pw_id == wps->dev_pw_id &&
1378 : 2 : wps->wps->ap_nfc_dev_pw) {
1379 : 2 : wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from own NFC Password Token");
1380 : 2 : pin = wpabuf_head(wps->wps->ap_nfc_dev_pw);
1381 : 2 : pin_len = wpabuf_len(wps->wps->ap_nfc_dev_pw);
1382 : : #endif /* CONFIG_WPS_NFC */
1383 : : } else {
1384 : 111 : pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e,
1385 : : &pin_len);
1386 [ - + ][ + + ]: 111 : if (pin && wps->dev_pw_id >= 0x10) {
1387 : 0 : wpa_printf(MSG_DEBUG, "WPS: No match for OOB Device "
1388 : : "Password ID, but PIN found");
1389 : : /*
1390 : : * See whether Enrollee is willing to use PIN instead.
1391 : : */
1392 : 0 : wps->dev_pw_id = DEV_PW_DEFAULT;
1393 : : }
1394 : : }
1395 [ + + ]: 136 : if (pin == NULL) {
1396 : 8 : wpa_printf(MSG_DEBUG, "WPS: No Device Password available for "
1397 : : "the Enrollee (context %p registrar %p)",
1398 : 8 : wps->wps, wps->wps->registrar);
1399 : 8 : wps_cb_pin_needed(wps->wps->registrar, wps->uuid_e,
1400 : 8 : &wps->peer_dev);
1401 : 8 : return -1;
1402 : : }
1403 : :
1404 : 128 : wps->dev_password = os_malloc(pin_len);
1405 [ - + ]: 128 : if (wps->dev_password == NULL)
1406 : 0 : return -1;
1407 : 128 : os_memcpy(wps->dev_password, pin, pin_len);
1408 : 128 : wps->dev_password_len = pin_len;
1409 : :
1410 : 149 : return 0;
1411 : : }
1412 : :
1413 : :
1414 : 154 : static int wps_build_uuid_r(struct wps_data *wps, struct wpabuf *msg)
1415 : : {
1416 : 154 : wpa_printf(MSG_DEBUG, "WPS: * UUID-R");
1417 : 154 : wpabuf_put_be16(msg, ATTR_UUID_R);
1418 : 154 : wpabuf_put_be16(msg, WPS_UUID_LEN);
1419 : 154 : wpabuf_put_data(msg, wps->uuid_r, WPS_UUID_LEN);
1420 : 154 : return 0;
1421 : : }
1422 : :
1423 : :
1424 : 122 : static int wps_build_r_hash(struct wps_data *wps, struct wpabuf *msg)
1425 : : {
1426 : : u8 *hash;
1427 : : const u8 *addr[4];
1428 : : size_t len[4];
1429 : :
1430 [ - + ]: 122 : if (random_get_bytes(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0)
1431 : 0 : return -1;
1432 : 122 : wpa_hexdump(MSG_DEBUG, "WPS: R-S1", wps->snonce, WPS_SECRET_NONCE_LEN);
1433 : 122 : wpa_hexdump(MSG_DEBUG, "WPS: R-S2",
1434 : : wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN);
1435 : :
1436 [ - + ][ + - ]: 122 : if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) {
1437 : 0 : wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for "
1438 : : "R-Hash derivation");
1439 : 0 : return -1;
1440 : : }
1441 : :
1442 : 122 : wpa_printf(MSG_DEBUG, "WPS: * R-Hash1");
1443 : 122 : wpabuf_put_be16(msg, ATTR_R_HASH1);
1444 : 122 : wpabuf_put_be16(msg, SHA256_MAC_LEN);
1445 : 122 : hash = wpabuf_put(msg, SHA256_MAC_LEN);
1446 : : /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */
1447 : 122 : addr[0] = wps->snonce;
1448 : 122 : len[0] = WPS_SECRET_NONCE_LEN;
1449 : 122 : addr[1] = wps->psk1;
1450 : 122 : len[1] = WPS_PSK_LEN;
1451 : 122 : addr[2] = wpabuf_head(wps->dh_pubkey_e);
1452 : 122 : len[2] = wpabuf_len(wps->dh_pubkey_e);
1453 : 122 : addr[3] = wpabuf_head(wps->dh_pubkey_r);
1454 : 122 : len[3] = wpabuf_len(wps->dh_pubkey_r);
1455 : 122 : hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
1456 : 122 : wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", hash, SHA256_MAC_LEN);
1457 : :
1458 : 122 : wpa_printf(MSG_DEBUG, "WPS: * R-Hash2");
1459 : 122 : wpabuf_put_be16(msg, ATTR_R_HASH2);
1460 : 122 : wpabuf_put_be16(msg, SHA256_MAC_LEN);
1461 : 122 : hash = wpabuf_put(msg, SHA256_MAC_LEN);
1462 : : /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */
1463 : 122 : addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN;
1464 : 122 : addr[1] = wps->psk2;
1465 : 122 : hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
1466 : 122 : wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", hash, SHA256_MAC_LEN);
1467 : :
1468 : 122 : return 0;
1469 : : }
1470 : :
1471 : :
1472 : 122 : static int wps_build_r_snonce1(struct wps_data *wps, struct wpabuf *msg)
1473 : : {
1474 : 122 : wpa_printf(MSG_DEBUG, "WPS: * R-SNonce1");
1475 : 122 : wpabuf_put_be16(msg, ATTR_R_SNONCE1);
1476 : 122 : wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
1477 : 122 : wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN);
1478 : 122 : return 0;
1479 : : }
1480 : :
1481 : :
1482 : 116 : static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg)
1483 : : {
1484 : 116 : wpa_printf(MSG_DEBUG, "WPS: * R-SNonce2");
1485 : 116 : wpabuf_put_be16(msg, ATTR_R_SNONCE2);
1486 : 116 : wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
1487 : 116 : wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN,
1488 : : WPS_SECRET_NONCE_LEN);
1489 : 116 : return 0;
1490 : : }
1491 : :
1492 : :
1493 : 130 : static int wps_build_cred_network_idx(struct wpabuf *msg,
1494 : : const struct wps_credential *cred)
1495 : : {
1496 : 130 : wpa_printf(MSG_DEBUG, "WPS: * Network Index (1)");
1497 : 130 : wpabuf_put_be16(msg, ATTR_NETWORK_INDEX);
1498 : 130 : wpabuf_put_be16(msg, 1);
1499 : 130 : wpabuf_put_u8(msg, 1);
1500 : 130 : return 0;
1501 : : }
1502 : :
1503 : :
1504 : 130 : static int wps_build_cred_ssid(struct wpabuf *msg,
1505 : : const struct wps_credential *cred)
1506 : : {
1507 : 130 : wpa_printf(MSG_DEBUG, "WPS: * SSID");
1508 : 130 : wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID for Credential",
1509 : 130 : cred->ssid, cred->ssid_len);
1510 : 130 : wpabuf_put_be16(msg, ATTR_SSID);
1511 : 130 : wpabuf_put_be16(msg, cred->ssid_len);
1512 : 130 : wpabuf_put_data(msg, cred->ssid, cred->ssid_len);
1513 : 130 : return 0;
1514 : : }
1515 : :
1516 : :
1517 : 130 : static int wps_build_cred_auth_type(struct wpabuf *msg,
1518 : : const struct wps_credential *cred)
1519 : : {
1520 : 130 : wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)",
1521 : 130 : cred->auth_type);
1522 : 130 : wpabuf_put_be16(msg, ATTR_AUTH_TYPE);
1523 : 130 : wpabuf_put_be16(msg, 2);
1524 : 130 : wpabuf_put_be16(msg, cred->auth_type);
1525 : 130 : return 0;
1526 : : }
1527 : :
1528 : :
1529 : 130 : static int wps_build_cred_encr_type(struct wpabuf *msg,
1530 : : const struct wps_credential *cred)
1531 : : {
1532 : 130 : wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)",
1533 : 130 : cred->encr_type);
1534 : 130 : wpabuf_put_be16(msg, ATTR_ENCR_TYPE);
1535 : 130 : wpabuf_put_be16(msg, 2);
1536 : 130 : wpabuf_put_be16(msg, cred->encr_type);
1537 : 130 : return 0;
1538 : : }
1539 : :
1540 : :
1541 : 130 : static int wps_build_cred_network_key(struct wpabuf *msg,
1542 : : const struct wps_credential *cred)
1543 : : {
1544 : 130 : wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%d)",
1545 : 130 : (int) cred->key_len);
1546 : 130 : wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key",
1547 : 130 : cred->key, cred->key_len);
1548 : 130 : wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
1549 : 130 : wpabuf_put_be16(msg, cred->key_len);
1550 : 130 : wpabuf_put_data(msg, cred->key, cred->key_len);
1551 : 130 : return 0;
1552 : : }
1553 : :
1554 : :
1555 : 130 : static int wps_build_credential(struct wpabuf *msg,
1556 : : const struct wps_credential *cred)
1557 : : {
1558 [ + - + - ]: 260 : if (wps_build_cred_network_idx(msg, cred) ||
1559 [ + - ]: 260 : wps_build_cred_ssid(msg, cred) ||
1560 [ + - ]: 260 : wps_build_cred_auth_type(msg, cred) ||
1561 [ + - ]: 260 : wps_build_cred_encr_type(msg, cred) ||
1562 [ - + ]: 260 : wps_build_cred_network_key(msg, cred) ||
1563 : 130 : wps_build_mac_addr(msg, cred->mac_addr))
1564 : 0 : return -1;
1565 : 130 : return 0;
1566 : : }
1567 : :
1568 : :
1569 : 0 : int wps_build_credential_wrap(struct wpabuf *msg,
1570 : : const struct wps_credential *cred)
1571 : : {
1572 : : struct wpabuf *wbuf;
1573 : 0 : wbuf = wpabuf_alloc(200);
1574 [ # # ]: 0 : if (wbuf == NULL)
1575 : 0 : return -1;
1576 [ # # ]: 0 : if (wps_build_credential(wbuf, cred)) {
1577 : 0 : wpabuf_free(wbuf);
1578 : 0 : return -1;
1579 : : }
1580 : 0 : wpabuf_put_be16(msg, ATTR_CRED);
1581 : 0 : wpabuf_put_be16(msg, wpabuf_len(wbuf));
1582 : 0 : wpabuf_put_buf(msg, wbuf);
1583 : 0 : wpabuf_free(wbuf);
1584 : 0 : return 0;
1585 : : }
1586 : :
1587 : :
1588 : 112 : int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
1589 : : {
1590 : : struct wpabuf *cred;
1591 : :
1592 [ - + ]: 112 : if (wps->wps->registrar->skip_cred_build)
1593 : 0 : goto skip_cred_build;
1594 : :
1595 : 112 : wpa_printf(MSG_DEBUG, "WPS: * Credential");
1596 [ + + ]: 112 : if (wps->use_cred) {
1597 : 8 : os_memcpy(&wps->cred, wps->use_cred, sizeof(wps->cred));
1598 : 8 : goto use_provided;
1599 : : }
1600 : 104 : os_memset(&wps->cred, 0, sizeof(wps->cred));
1601 : :
1602 : 104 : os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
1603 : 104 : wps->cred.ssid_len = wps->wps->ssid_len;
1604 : :
1605 : : /* Select the best authentication and encryption type */
1606 [ + - ]: 104 : if (wps->auth_type & WPS_AUTH_WPA2PSK)
1607 : 104 : wps->auth_type = WPS_AUTH_WPA2PSK;
1608 [ # # ]: 0 : else if (wps->auth_type & WPS_AUTH_WPAPSK)
1609 : 0 : wps->auth_type = WPS_AUTH_WPAPSK;
1610 [ # # ]: 0 : else if (wps->auth_type & WPS_AUTH_OPEN)
1611 : 0 : wps->auth_type = WPS_AUTH_OPEN;
1612 [ # # ]: 0 : else if (wps->auth_type & WPS_AUTH_SHARED)
1613 : 0 : wps->auth_type = WPS_AUTH_SHARED;
1614 : : else {
1615 : 0 : wpa_printf(MSG_DEBUG, "WPS: Unsupported auth_type 0x%x",
1616 : 0 : wps->auth_type);
1617 : 0 : return -1;
1618 : : }
1619 : 104 : wps->cred.auth_type = wps->auth_type;
1620 : :
1621 [ - + ][ # # ]: 104 : if (wps->auth_type == WPS_AUTH_WPA2PSK ||
1622 : 0 : wps->auth_type == WPS_AUTH_WPAPSK) {
1623 [ + - ]: 208 : if (wps->encr_type & WPS_ENCR_AES)
1624 : 104 : wps->encr_type = WPS_ENCR_AES;
1625 [ # # ]: 0 : else if (wps->encr_type & WPS_ENCR_TKIP)
1626 : 0 : wps->encr_type = WPS_ENCR_TKIP;
1627 : : else {
1628 : 0 : wpa_printf(MSG_DEBUG, "WPS: No suitable encryption "
1629 : : "type for WPA/WPA2");
1630 : 0 : return -1;
1631 : : }
1632 : : } else {
1633 [ # # ]: 0 : if (wps->encr_type & WPS_ENCR_WEP)
1634 : 0 : wps->encr_type = WPS_ENCR_WEP;
1635 [ # # ]: 0 : else if (wps->encr_type & WPS_ENCR_NONE)
1636 : 0 : wps->encr_type = WPS_ENCR_NONE;
1637 : : else {
1638 : 0 : wpa_printf(MSG_DEBUG, "WPS: No suitable encryption "
1639 : : "type for non-WPA/WPA2 mode");
1640 : 0 : return -1;
1641 : : }
1642 : : }
1643 : 104 : wps->cred.encr_type = wps->encr_type;
1644 : : /*
1645 : : * Set MAC address in the Credential to be the Enrollee's MAC address
1646 : : */
1647 : 104 : os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN);
1648 : :
1649 [ + + ][ + - ]: 104 : if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap &&
[ + - ]
1650 : 6 : !wps->wps->registrar->disable_auto_conf) {
1651 : : u8 r[16];
1652 : : /* Generate a random passphrase */
1653 [ - + ]: 6 : if (random_get_bytes(r, sizeof(r)) < 0)
1654 : 0 : return -1;
1655 : 6 : os_free(wps->new_psk);
1656 : 6 : wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len);
1657 [ - + ]: 6 : if (wps->new_psk == NULL)
1658 : 0 : return -1;
1659 : 6 : wps->new_psk_len--; /* remove newline */
1660 [ + - ][ + + ]: 18 : while (wps->new_psk_len &&
1661 : 18 : wps->new_psk[wps->new_psk_len - 1] == '=')
1662 : 12 : wps->new_psk_len--;
1663 : 6 : wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase",
1664 : 6 : wps->new_psk, wps->new_psk_len);
1665 : 6 : os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len);
1666 : 6 : wps->cred.key_len = wps->new_psk_len;
1667 [ + + ][ + + ]: 98 : } else if (!wps->wps->registrar->force_per_enrollee_psk &&
1668 [ + - ]: 140 : wps->use_psk_key && wps->wps->psk_set) {
1669 : : char hex[65];
1670 : 70 : wpa_printf(MSG_DEBUG, "WPS: Use PSK format for Network Key");
1671 : 70 : wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, 32);
1672 : 70 : os_memcpy(wps->cred.key, hex, 32 * 2);
1673 : 70 : wps->cred.key_len = 32 * 2;
1674 [ + + ][ + - ]: 28 : } else if (!wps->wps->registrar->force_per_enrollee_psk &&
1675 : 20 : wps->wps->network_key) {
1676 : 20 : os_memcpy(wps->cred.key, wps->wps->network_key,
1677 : : wps->wps->network_key_len);
1678 : 20 : wps->cred.key_len = wps->wps->network_key_len;
1679 [ + - ]: 8 : } else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
1680 : : char hex[65];
1681 : : /* Generate a random per-device PSK */
1682 : 8 : os_free(wps->new_psk);
1683 : 8 : wps->new_psk_len = 32;
1684 : 8 : wps->new_psk = os_malloc(wps->new_psk_len);
1685 [ - + ]: 8 : if (wps->new_psk == NULL)
1686 : 0 : return -1;
1687 [ - + ]: 8 : if (random_get_bytes(wps->new_psk, wps->new_psk_len) < 0) {
1688 : 0 : os_free(wps->new_psk);
1689 : 0 : wps->new_psk = NULL;
1690 : 0 : return -1;
1691 : : }
1692 : 8 : wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK",
1693 : 8 : wps->new_psk, wps->new_psk_len);
1694 : 8 : wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk,
1695 : : wps->new_psk_len);
1696 : 8 : os_memcpy(wps->cred.key, hex, wps->new_psk_len * 2);
1697 : 8 : wps->cred.key_len = wps->new_psk_len * 2;
1698 : : }
1699 : :
1700 : : use_provided:
1701 : : #ifdef CONFIG_WPS_TESTING
1702 [ - + ]: 112 : if (wps_testing_dummy_cred)
1703 : 0 : cred = wpabuf_alloc(200);
1704 : : else
1705 : 112 : cred = NULL;
1706 [ - + ]: 112 : if (cred) {
1707 : : struct wps_credential dummy;
1708 : 0 : wpa_printf(MSG_DEBUG, "WPS: Add dummy credential");
1709 : 0 : os_memset(&dummy, 0, sizeof(dummy));
1710 : 0 : os_memcpy(dummy.ssid, "dummy", 5);
1711 : 0 : dummy.ssid_len = 5;
1712 : 0 : dummy.auth_type = WPS_AUTH_WPA2PSK;
1713 : 0 : dummy.encr_type = WPS_ENCR_AES;
1714 : 0 : os_memcpy(dummy.key, "dummy psk", 9);
1715 : 0 : dummy.key_len = 9;
1716 : 0 : os_memcpy(dummy.mac_addr, wps->mac_addr_e, ETH_ALEN);
1717 : 0 : wps_build_credential(cred, &dummy);
1718 : 0 : wpa_hexdump_buf(MSG_DEBUG, "WPS: Dummy Credential", cred);
1719 : :
1720 : 0 : wpabuf_put_be16(msg, ATTR_CRED);
1721 : 0 : wpabuf_put_be16(msg, wpabuf_len(cred));
1722 : 0 : wpabuf_put_buf(msg, cred);
1723 : :
1724 : 0 : wpabuf_free(cred);
1725 : : }
1726 : : #endif /* CONFIG_WPS_TESTING */
1727 : :
1728 : 112 : cred = wpabuf_alloc(200);
1729 [ - + ]: 112 : if (cred == NULL)
1730 : 0 : return -1;
1731 : :
1732 [ - + ]: 112 : if (wps_build_credential(cred, &wps->cred)) {
1733 : 0 : wpabuf_free(cred);
1734 : 0 : return -1;
1735 : : }
1736 : :
1737 : 112 : wpabuf_put_be16(msg, ATTR_CRED);
1738 : 112 : wpabuf_put_be16(msg, wpabuf_len(cred));
1739 : 112 : wpabuf_put_buf(msg, cred);
1740 : 112 : wpabuf_free(cred);
1741 : :
1742 : : skip_cred_build:
1743 [ - + ]: 112 : if (wps->wps->registrar->extra_cred) {
1744 : 0 : wpa_printf(MSG_DEBUG, "WPS: * Credential (pre-configured)");
1745 : 0 : wpabuf_put_buf(msg, wps->wps->registrar->extra_cred);
1746 : : }
1747 : :
1748 : 112 : return 0;
1749 : : }
1750 : :
1751 : :
1752 : 18 : static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *msg)
1753 : : {
1754 : 18 : wpa_printf(MSG_DEBUG, "WPS: * AP Settings");
1755 : :
1756 [ - + ]: 18 : if (wps_build_credential(msg, &wps->cred))
1757 : 0 : return -1;
1758 : :
1759 : 18 : return 0;
1760 : : }
1761 : :
1762 : :
1763 : 12 : static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
1764 : : {
1765 : : struct wpabuf *msg, *plain;
1766 : :
1767 : 12 : msg = wpabuf_alloc(1000);
1768 [ - + ]: 12 : if (msg == NULL)
1769 : 0 : return NULL;
1770 : :
1771 : 12 : plain = wpabuf_alloc(200);
1772 [ - + ]: 12 : if (plain == NULL) {
1773 : 0 : wpabuf_free(msg);
1774 : 0 : return NULL;
1775 : : }
1776 : :
1777 [ - + ]: 12 : if (wps_build_ap_settings(wps, plain)) {
1778 : 0 : wpabuf_free(plain);
1779 : 0 : wpabuf_free(msg);
1780 : 0 : return NULL;
1781 : : }
1782 : :
1783 : 12 : wpabuf_put_be16(msg, ATTR_CRED);
1784 : 12 : wpabuf_put_be16(msg, wpabuf_len(plain));
1785 : 12 : wpabuf_put_buf(msg, plain);
1786 : 12 : wpabuf_free(plain);
1787 : :
1788 : 12 : return msg;
1789 : : }
1790 : :
1791 : :
1792 : 141 : static struct wpabuf * wps_build_m2(struct wps_data *wps)
1793 : : {
1794 : : struct wpabuf *msg;
1795 : 141 : int config_in_m2 = 0;
1796 : :
1797 [ - + ]: 141 : if (random_get_bytes(wps->nonce_r, WPS_NONCE_LEN) < 0)
1798 : 0 : return NULL;
1799 : 141 : wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce",
1800 : 141 : wps->nonce_r, WPS_NONCE_LEN);
1801 : 141 : wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN);
1802 : :
1803 : 141 : wpa_printf(MSG_DEBUG, "WPS: Building Message M2");
1804 : 141 : msg = wpabuf_alloc(1000);
1805 [ - + ]: 141 : if (msg == NULL)
1806 : 0 : return NULL;
1807 : :
1808 [ + - + - ]: 282 : if (wps_build_version(msg) ||
1809 [ + - ]: 282 : wps_build_msg_type(msg, WPS_M2) ||
1810 [ + - ]: 282 : wps_build_enrollee_nonce(wps, msg) ||
1811 [ + - ]: 282 : wps_build_registrar_nonce(wps, msg) ||
1812 [ + - ]: 282 : wps_build_uuid_r(wps, msg) ||
1813 [ + - ]: 282 : wps_build_public_key(wps, msg) ||
1814 [ + - ]: 282 : wps_derive_keys(wps) ||
1815 [ + - ]: 282 : wps_build_auth_type_flags(wps, msg) ||
1816 [ + - ]: 282 : wps_build_encr_type_flags(wps, msg) ||
1817 [ + - ]: 282 : wps_build_conn_type_flags(wps, msg) ||
1818 [ + - ]: 282 : wps_build_config_methods_r(wps->wps->registrar, msg) ||
1819 [ + - ]: 282 : wps_build_device_attrs(&wps->wps->dev, msg) ||
1820 : 141 : wps_build_rf_bands(&wps->wps->dev, msg,
1821 [ + - ]: 282 : wps->wps->rf_band_cb(wps->wps->cb_ctx)) ||
1822 [ + - ]: 282 : wps_build_assoc_state(wps, msg) ||
1823 [ + - ]: 282 : wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
1824 [ + - ]: 282 : wps_build_dev_password_id(msg, wps->dev_pw_id) ||
1825 [ - + ]: 282 : wps_build_os_version(&wps->wps->dev, msg) ||
1826 : 141 : wps_build_wfa_ext(msg, 0, NULL, 0)) {
1827 : 0 : wpabuf_free(msg);
1828 : 0 : return NULL;
1829 : : }
1830 : :
1831 : : #ifdef CONFIG_WPS_NFC
1832 [ + + ][ + + ]: 141 : if (wps->nfc_pw_token && wps->nfc_pw_token->pk_hash_provided_oob &&
[ + + ]
1833 : 17 : wps->nfc_pw_token->pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) {
1834 : : /*
1835 : : * Use abbreviated handshake since public key hash allowed
1836 : : * Enrollee to validate our public key similarly to how Enrollee
1837 : : * public key was validated. There is no need to validate Device
1838 : : * Password in this case.
1839 : : */
1840 : 13 : struct wpabuf *plain = wpabuf_alloc(500);
1841 [ + - + - ]: 26 : if (plain == NULL ||
1842 [ + - ]: 26 : wps_build_cred(wps, plain) ||
1843 [ - + ]: 26 : wps_build_key_wrap_auth(wps, plain) ||
1844 : 13 : wps_build_encr_settings(wps, msg, plain)) {
1845 : 0 : wpabuf_free(msg);
1846 : 0 : wpabuf_free(plain);
1847 : 0 : return NULL;
1848 : : }
1849 : 13 : wpabuf_free(plain);
1850 : 13 : config_in_m2 = 1;
1851 : : }
1852 : : #endif /* CONFIG_WPS_NFC */
1853 : :
1854 [ - + ]: 141 : if (wps_build_authenticator(wps, msg)) {
1855 : 0 : wpabuf_free(msg);
1856 : 0 : return NULL;
1857 : : }
1858 : :
1859 : 141 : wps->int_reg = 1;
1860 [ + + ]: 141 : wps->state = config_in_m2 ? RECV_DONE : RECV_M3;
1861 : 141 : return msg;
1862 : : }
1863 : :
1864 : :
1865 : 13 : static struct wpabuf * wps_build_m2d(struct wps_data *wps)
1866 : : {
1867 : : struct wpabuf *msg;
1868 : 13 : u16 err = wps->config_error;
1869 : :
1870 : 13 : wpa_printf(MSG_DEBUG, "WPS: Building Message M2D");
1871 : 13 : msg = wpabuf_alloc(1000);
1872 [ - + ]: 13 : if (msg == NULL)
1873 : 0 : return NULL;
1874 : :
1875 [ + + ][ - + ]: 13 : if (wps->wps->ap && wps->wps->ap_setup_locked &&
[ # # ]
1876 : : err == WPS_CFG_NO_ERROR)
1877 : 0 : err = WPS_CFG_SETUP_LOCKED;
1878 : :
1879 [ + - + - ]: 26 : if (wps_build_version(msg) ||
1880 [ + - ]: 26 : wps_build_msg_type(msg, WPS_M2D) ||
1881 [ + - ]: 26 : wps_build_enrollee_nonce(wps, msg) ||
1882 [ + - ]: 26 : wps_build_registrar_nonce(wps, msg) ||
1883 [ + - ]: 26 : wps_build_uuid_r(wps, msg) ||
1884 [ + - ]: 26 : wps_build_auth_type_flags(wps, msg) ||
1885 [ + - ]: 26 : wps_build_encr_type_flags(wps, msg) ||
1886 [ + - ]: 26 : wps_build_conn_type_flags(wps, msg) ||
1887 [ + - ]: 26 : wps_build_config_methods_r(wps->wps->registrar, msg) ||
1888 [ + - ]: 26 : wps_build_device_attrs(&wps->wps->dev, msg) ||
1889 : 13 : wps_build_rf_bands(&wps->wps->dev, msg,
1890 [ + - ]: 26 : wps->wps->rf_band_cb(wps->wps->cb_ctx)) ||
1891 [ + - ]: 26 : wps_build_assoc_state(wps, msg) ||
1892 [ + - ]: 26 : wps_build_config_error(msg, err) ||
1893 [ - + ]: 26 : wps_build_os_version(&wps->wps->dev, msg) ||
1894 : 13 : wps_build_wfa_ext(msg, 0, NULL, 0)) {
1895 : 0 : wpabuf_free(msg);
1896 : 0 : return NULL;
1897 : : }
1898 : :
1899 : 13 : wps->state = RECV_M2D_ACK;
1900 : 13 : return msg;
1901 : : }
1902 : :
1903 : :
1904 : 122 : static struct wpabuf * wps_build_m4(struct wps_data *wps)
1905 : : {
1906 : : struct wpabuf *msg, *plain;
1907 : :
1908 : 122 : wpa_printf(MSG_DEBUG, "WPS: Building Message M4");
1909 : :
1910 : 122 : wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
1911 : :
1912 : 122 : plain = wpabuf_alloc(200);
1913 [ - + ]: 122 : if (plain == NULL)
1914 : 0 : return NULL;
1915 : :
1916 : 122 : msg = wpabuf_alloc(1000);
1917 [ - + ]: 122 : if (msg == NULL) {
1918 : 0 : wpabuf_free(plain);
1919 : 0 : return NULL;
1920 : : }
1921 : :
1922 [ + - + - ]: 244 : if (wps_build_version(msg) ||
1923 [ + - ]: 244 : wps_build_msg_type(msg, WPS_M4) ||
1924 [ + - ]: 244 : wps_build_enrollee_nonce(wps, msg) ||
1925 [ + - ]: 244 : wps_build_r_hash(wps, msg) ||
1926 [ + - ]: 244 : wps_build_r_snonce1(wps, plain) ||
1927 [ + - ]: 244 : wps_build_key_wrap_auth(wps, plain) ||
1928 [ + - ]: 244 : wps_build_encr_settings(wps, msg, plain) ||
1929 [ - + ]: 244 : wps_build_wfa_ext(msg, 0, NULL, 0) ||
1930 : 122 : wps_build_authenticator(wps, msg)) {
1931 : 0 : wpabuf_free(plain);
1932 : 0 : wpabuf_free(msg);
1933 : 0 : return NULL;
1934 : : }
1935 : 122 : wpabuf_free(plain);
1936 : :
1937 : 122 : wps->state = RECV_M5;
1938 : 122 : return msg;
1939 : : }
1940 : :
1941 : :
1942 : 116 : static struct wpabuf * wps_build_m6(struct wps_data *wps)
1943 : : {
1944 : : struct wpabuf *msg, *plain;
1945 : :
1946 : 116 : wpa_printf(MSG_DEBUG, "WPS: Building Message M6");
1947 : :
1948 : 116 : plain = wpabuf_alloc(200);
1949 [ - + ]: 116 : if (plain == NULL)
1950 : 0 : return NULL;
1951 : :
1952 : 116 : msg = wpabuf_alloc(1000);
1953 [ - + ]: 116 : if (msg == NULL) {
1954 : 0 : wpabuf_free(plain);
1955 : 0 : return NULL;
1956 : : }
1957 : :
1958 [ + - + - ]: 232 : if (wps_build_version(msg) ||
1959 [ + - ]: 232 : wps_build_msg_type(msg, WPS_M6) ||
1960 [ + - ]: 232 : wps_build_enrollee_nonce(wps, msg) ||
1961 [ + - ]: 232 : wps_build_r_snonce2(wps, plain) ||
1962 [ + - ]: 232 : wps_build_key_wrap_auth(wps, plain) ||
1963 [ + - ]: 232 : wps_build_encr_settings(wps, msg, plain) ||
1964 [ - + ]: 232 : wps_build_wfa_ext(msg, 0, NULL, 0) ||
1965 : 116 : wps_build_authenticator(wps, msg)) {
1966 : 0 : wpabuf_free(plain);
1967 : 0 : wpabuf_free(msg);
1968 : 0 : return NULL;
1969 : : }
1970 : 116 : wpabuf_free(plain);
1971 : :
1972 : 116 : wps->wps_pin_revealed = 1;
1973 : 116 : wps->state = RECV_M7;
1974 : 116 : return msg;
1975 : : }
1976 : :
1977 : :
1978 : 101 : static struct wpabuf * wps_build_m8(struct wps_data *wps)
1979 : : {
1980 : : struct wpabuf *msg, *plain;
1981 : :
1982 : 101 : wpa_printf(MSG_DEBUG, "WPS: Building Message M8");
1983 : :
1984 : 101 : plain = wpabuf_alloc(500);
1985 [ - + ]: 101 : if (plain == NULL)
1986 : 0 : return NULL;
1987 : :
1988 : 101 : msg = wpabuf_alloc(1000);
1989 [ - + ]: 101 : if (msg == NULL) {
1990 : 0 : wpabuf_free(plain);
1991 : 0 : return NULL;
1992 : : }
1993 : :
1994 [ + - + - ]: 202 : if (wps_build_version(msg) ||
1995 [ + - ]: 202 : wps_build_msg_type(msg, WPS_M8) ||
1996 [ + + ]: 202 : wps_build_enrollee_nonce(wps, msg) ||
1997 [ + + ][ + - ]: 101 : ((wps->wps->ap || wps->er) && wps_build_cred(wps, plain)) ||
[ + + ]
1998 [ + + ]: 112 : (!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) ||
[ + - + - ]
1999 [ + - ]: 202 : wps_build_key_wrap_auth(wps, plain) ||
2000 [ + - ]: 202 : wps_build_encr_settings(wps, msg, plain) ||
2001 [ - + ]: 202 : wps_build_wfa_ext(msg, 0, NULL, 0) ||
2002 : 101 : wps_build_authenticator(wps, msg)) {
2003 : 0 : wpabuf_free(plain);
2004 : 0 : wpabuf_free(msg);
2005 : 0 : return NULL;
2006 : : }
2007 : 101 : wpabuf_free(plain);
2008 : :
2009 : 101 : wps->state = RECV_DONE;
2010 : 101 : return msg;
2011 : : }
2012 : :
2013 : :
2014 : 545 : struct wpabuf * wps_registrar_get_msg(struct wps_data *wps,
2015 : : enum wsc_op_code *op_code)
2016 : : {
2017 : : struct wpabuf *msg;
2018 : :
2019 : : #ifdef CONFIG_WPS_UPNP
2020 [ + + ][ + + ]: 545 : if (!wps->int_reg && wps->wps->wps_upnp) {
2021 : 31 : struct upnp_pending_message *p, *prev = NULL;
2022 [ + + ]: 31 : if (wps->ext_reg > 1)
2023 : 15 : wps_registrar_free_pending_m2(wps->wps);
2024 : 31 : p = wps->wps->upnp_msgs;
2025 : : /* TODO: check pending message MAC address */
2026 [ + + ][ - + ]: 31 : while (p && p->next) {
2027 : 0 : prev = p;
2028 : 0 : p = p->next;
2029 : : }
2030 [ + + ]: 31 : if (p) {
2031 : 23 : wpa_printf(MSG_DEBUG, "WPS: Use pending message from "
2032 : : "UPnP");
2033 [ - + ]: 23 : if (prev)
2034 : 0 : prev->next = NULL;
2035 : : else
2036 : 23 : wps->wps->upnp_msgs = NULL;
2037 : 23 : msg = p->msg;
2038 [ - - + ]: 23 : switch (p->type) {
2039 : : case WPS_WSC_ACK:
2040 : 0 : *op_code = WSC_ACK;
2041 : 0 : break;
2042 : : case WPS_WSC_NACK:
2043 : 0 : *op_code = WSC_NACK;
2044 : 0 : break;
2045 : : default:
2046 : 23 : *op_code = WSC_MSG;
2047 : 23 : break;
2048 : : }
2049 : 23 : os_free(p);
2050 [ - + ]: 23 : if (wps->ext_reg == 0)
2051 : 0 : wps->ext_reg = 1;
2052 : 23 : return msg;
2053 : : }
2054 : : }
2055 [ - + ]: 522 : if (wps->ext_reg) {
2056 : 0 : wpa_printf(MSG_DEBUG, "WPS: Using external Registrar, but no "
2057 : : "pending message available");
2058 : 0 : return NULL;
2059 : : }
2060 : : #endif /* CONFIG_WPS_UPNP */
2061 : :
2062 [ + + + + : 522 : switch (wps->state) {
+ + + - ]
2063 : : case SEND_M2:
2064 [ + + ]: 149 : if (wps_get_dev_password(wps) < 0)
2065 : 8 : msg = wps_build_m2d(wps);
2066 : : else
2067 : 141 : msg = wps_build_m2(wps);
2068 : 149 : *op_code = WSC_MSG;
2069 : 149 : break;
2070 : : case SEND_M2D:
2071 : 5 : msg = wps_build_m2d(wps);
2072 : 5 : *op_code = WSC_MSG;
2073 : 5 : break;
2074 : : case SEND_M4:
2075 : 122 : msg = wps_build_m4(wps);
2076 : 122 : *op_code = WSC_MSG;
2077 : 122 : break;
2078 : : case SEND_M6:
2079 : 116 : msg = wps_build_m6(wps);
2080 : 116 : *op_code = WSC_MSG;
2081 : 116 : break;
2082 : : case SEND_M8:
2083 : 101 : msg = wps_build_m8(wps);
2084 : 101 : *op_code = WSC_MSG;
2085 : 101 : break;
2086 : : case RECV_DONE:
2087 : 4 : msg = wps_build_wsc_ack(wps);
2088 : 4 : *op_code = WSC_ACK;
2089 : 4 : break;
2090 : : case SEND_WSC_NACK:
2091 : 25 : msg = wps_build_wsc_nack(wps);
2092 : 25 : *op_code = WSC_NACK;
2093 : 25 : break;
2094 : : default:
2095 : 0 : wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building "
2096 : 0 : "a message", wps->state);
2097 : 0 : msg = NULL;
2098 : 0 : break;
2099 : : }
2100 : :
2101 [ + + ][ + - ]: 522 : if (*op_code == WSC_MSG && msg) {
2102 : : /* Save a copy of the last message for Authenticator derivation
2103 : : */
2104 : 493 : wpabuf_free(wps->last_msg);
2105 : 493 : wps->last_msg = wpabuf_dup(msg);
2106 : : }
2107 : :
2108 : 545 : return msg;
2109 : : }
2110 : :
2111 : :
2112 : 154 : static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce)
2113 : : {
2114 [ - + ]: 154 : if (e_nonce == NULL) {
2115 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received");
2116 : 0 : return -1;
2117 : : }
2118 : :
2119 : 154 : os_memcpy(wps->nonce_e, e_nonce, WPS_NONCE_LEN);
2120 : 154 : wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce",
2121 : 154 : wps->nonce_e, WPS_NONCE_LEN);
2122 : :
2123 : 154 : return 0;
2124 : : }
2125 : :
2126 : :
2127 : 351 : static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce)
2128 : : {
2129 [ - + ]: 351 : if (r_nonce == NULL) {
2130 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received");
2131 : 0 : return -1;
2132 : : }
2133 : :
2134 [ - + ]: 351 : if (os_memcmp(wps->nonce_r, r_nonce, WPS_NONCE_LEN) != 0) {
2135 : 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce received");
2136 : 0 : return -1;
2137 : : }
2138 : :
2139 : 351 : return 0;
2140 : : }
2141 : :
2142 : :
2143 : 154 : static int wps_process_uuid_e(struct wps_data *wps, const u8 *uuid_e)
2144 : : {
2145 [ - + ]: 154 : if (uuid_e == NULL) {
2146 : 0 : wpa_printf(MSG_DEBUG, "WPS: No UUID-E received");
2147 : 0 : return -1;
2148 : : }
2149 : :
2150 : 154 : os_memcpy(wps->uuid_e, uuid_e, WPS_UUID_LEN);
2151 : 154 : wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", wps->uuid_e, WPS_UUID_LEN);
2152 : :
2153 : 154 : return 0;
2154 : : }
2155 : :
2156 : :
2157 : 154 : static int wps_process_dev_password_id(struct wps_data *wps, const u8 *pw_id)
2158 : : {
2159 [ - + ]: 154 : if (pw_id == NULL) {
2160 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Device Password ID received");
2161 : 0 : return -1;
2162 : : }
2163 : :
2164 : 154 : wps->dev_pw_id = WPA_GET_BE16(pw_id);
2165 : 154 : wpa_printf(MSG_DEBUG, "WPS: Device Password ID %d", wps->dev_pw_id);
2166 : :
2167 : 154 : return 0;
2168 : : }
2169 : :
2170 : :
2171 : 122 : static int wps_process_e_hash1(struct wps_data *wps, const u8 *e_hash1)
2172 : : {
2173 [ - + ]: 122 : if (e_hash1 == NULL) {
2174 : 0 : wpa_printf(MSG_DEBUG, "WPS: No E-Hash1 received");
2175 : 0 : return -1;
2176 : : }
2177 : :
2178 : 122 : os_memcpy(wps->peer_hash1, e_hash1, WPS_HASH_LEN);
2179 : 122 : wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", wps->peer_hash1, WPS_HASH_LEN);
2180 : :
2181 : 122 : return 0;
2182 : : }
2183 : :
2184 : :
2185 : 122 : static int wps_process_e_hash2(struct wps_data *wps, const u8 *e_hash2)
2186 : : {
2187 [ - + ]: 122 : if (e_hash2 == NULL) {
2188 : 0 : wpa_printf(MSG_DEBUG, "WPS: No E-Hash2 received");
2189 : 0 : return -1;
2190 : : }
2191 : :
2192 : 122 : os_memcpy(wps->peer_hash2, e_hash2, WPS_HASH_LEN);
2193 : 122 : wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", wps->peer_hash2, WPS_HASH_LEN);
2194 : :
2195 : 122 : return 0;
2196 : : }
2197 : :
2198 : :
2199 : 116 : static int wps_process_e_snonce1(struct wps_data *wps, const u8 *e_snonce1)
2200 : : {
2201 : : u8 hash[SHA256_MAC_LEN];
2202 : : const u8 *addr[4];
2203 : : size_t len[4];
2204 : :
2205 [ - + ]: 116 : if (e_snonce1 == NULL) {
2206 : 0 : wpa_printf(MSG_DEBUG, "WPS: No E-SNonce1 received");
2207 : 0 : return -1;
2208 : : }
2209 : :
2210 : 116 : wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce1", e_snonce1,
2211 : : WPS_SECRET_NONCE_LEN);
2212 : :
2213 : : /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */
2214 : 116 : addr[0] = e_snonce1;
2215 : 116 : len[0] = WPS_SECRET_NONCE_LEN;
2216 : 116 : addr[1] = wps->psk1;
2217 : 116 : len[1] = WPS_PSK_LEN;
2218 : 116 : addr[2] = wpabuf_head(wps->dh_pubkey_e);
2219 : 116 : len[2] = wpabuf_len(wps->dh_pubkey_e);
2220 : 116 : addr[3] = wpabuf_head(wps->dh_pubkey_r);
2221 : 116 : len[3] = wpabuf_len(wps->dh_pubkey_r);
2222 : 116 : hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
2223 : :
2224 [ - + ]: 116 : if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
2225 : 0 : wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does "
2226 : : "not match with the pre-committed value");
2227 : 0 : wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
2228 : 0 : wps_pwd_auth_fail_event(wps->wps, 0, 1, wps->mac_addr_e);
2229 : 0 : return -1;
2230 : : }
2231 : :
2232 : 116 : wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the first "
2233 : : "half of the device password");
2234 : :
2235 : 116 : return 0;
2236 : : }
2237 : :
2238 : :
2239 : 113 : static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2)
2240 : : {
2241 : : u8 hash[SHA256_MAC_LEN];
2242 : : const u8 *addr[4];
2243 : : size_t len[4];
2244 : :
2245 [ - + ]: 113 : if (e_snonce2 == NULL) {
2246 : 0 : wpa_printf(MSG_DEBUG, "WPS: No E-SNonce2 received");
2247 : 0 : return -1;
2248 : : }
2249 : :
2250 : 113 : wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce2", e_snonce2,
2251 : : WPS_SECRET_NONCE_LEN);
2252 : :
2253 : : /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */
2254 : 113 : addr[0] = e_snonce2;
2255 : 113 : len[0] = WPS_SECRET_NONCE_LEN;
2256 : 113 : addr[1] = wps->psk2;
2257 : 113 : len[1] = WPS_PSK_LEN;
2258 : 113 : addr[2] = wpabuf_head(wps->dh_pubkey_e);
2259 : 113 : len[2] = wpabuf_len(wps->dh_pubkey_e);
2260 : 113 : addr[3] = wpabuf_head(wps->dh_pubkey_r);
2261 : 113 : len[3] = wpabuf_len(wps->dh_pubkey_r);
2262 : 113 : hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
2263 : :
2264 [ - + ]: 113 : if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
2265 : 0 : wpa_printf(MSG_DEBUG, "WPS: E-Hash2 derived from E-S2 does "
2266 : : "not match with the pre-committed value");
2267 : 0 : wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e);
2268 : 0 : wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
2269 : 0 : wps_pwd_auth_fail_event(wps->wps, 0, 2, wps->mac_addr_e);
2270 : 0 : return -1;
2271 : : }
2272 : :
2273 : 113 : wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the second "
2274 : : "half of the device password");
2275 : 113 : wps->wps_pin_revealed = 0;
2276 : 113 : wps_registrar_unlock_pin(wps->wps->registrar, wps->uuid_e);
2277 : :
2278 : : /*
2279 : : * In case wildcard PIN is used and WPS handshake succeeds in the first
2280 : : * attempt, wps_registrar_unlock_pin() would not free the PIN, so make
2281 : : * sure the PIN gets invalidated here.
2282 : : */
2283 : 113 : wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e);
2284 : :
2285 : 113 : return 0;
2286 : : }
2287 : :
2288 : :
2289 : 154 : static int wps_process_mac_addr(struct wps_data *wps, const u8 *mac_addr)
2290 : : {
2291 [ - + ]: 154 : if (mac_addr == NULL) {
2292 : 0 : wpa_printf(MSG_DEBUG, "WPS: No MAC Address received");
2293 : 0 : return -1;
2294 : : }
2295 : :
2296 : 154 : wpa_printf(MSG_DEBUG, "WPS: Enrollee MAC Address " MACSTR,
2297 : 924 : MAC2STR(mac_addr));
2298 : 154 : os_memcpy(wps->mac_addr_e, mac_addr, ETH_ALEN);
2299 : 154 : os_memcpy(wps->peer_dev.mac_addr, mac_addr, ETH_ALEN);
2300 : :
2301 : 154 : return 0;
2302 : : }
2303 : :
2304 : :
2305 : 154 : static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
2306 : : size_t pk_len)
2307 : : {
2308 [ + - ][ - + ]: 154 : if (pk == NULL || pk_len == 0) {
2309 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Public Key received");
2310 : 0 : return -1;
2311 : : }
2312 : :
2313 : 154 : wpabuf_free(wps->dh_pubkey_e);
2314 : 154 : wps->dh_pubkey_e = wpabuf_alloc_copy(pk, pk_len);
2315 [ - + ]: 154 : if (wps->dh_pubkey_e == NULL)
2316 : 0 : return -1;
2317 : :
2318 : 154 : return 0;
2319 : : }
2320 : :
2321 : :
2322 : 154 : static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth)
2323 : : {
2324 : : u16 auth_types;
2325 : :
2326 [ - + ]: 154 : if (auth == NULL) {
2327 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Authentication Type flags "
2328 : : "received");
2329 : 0 : return -1;
2330 : : }
2331 : :
2332 : 154 : auth_types = WPA_GET_BE16(auth);
2333 : :
2334 : 154 : wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x",
2335 : : auth_types);
2336 : 154 : wps->auth_type = wps->wps->auth_types & auth_types;
2337 [ - + ]: 154 : if (wps->auth_type == 0) {
2338 : 0 : wpa_printf(MSG_DEBUG, "WPS: No match in supported "
2339 : : "authentication types (own 0x%x Enrollee 0x%x)",
2340 : 0 : wps->wps->auth_types, auth_types);
2341 : : #ifdef WPS_WORKAROUNDS
2342 : : /*
2343 : : * Some deployed implementations seem to advertise incorrect
2344 : : * information in this attribute. For example, Linksys WRT350N
2345 : : * seems to have a byteorder bug that breaks this negotiation.
2346 : : * In order to interoperate with existing implementations,
2347 : : * assume that the Enrollee supports everything we do.
2348 : : */
2349 : 0 : wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee "
2350 : : "does not advertise supported authentication types "
2351 : : "correctly");
2352 : 0 : wps->auth_type = wps->wps->auth_types;
2353 : : #else /* WPS_WORKAROUNDS */
2354 : : return -1;
2355 : : #endif /* WPS_WORKAROUNDS */
2356 : : }
2357 : :
2358 : 154 : return 0;
2359 : : }
2360 : :
2361 : :
2362 : 154 : static int wps_process_encr_type_flags(struct wps_data *wps, const u8 *encr)
2363 : : {
2364 : : u16 encr_types;
2365 : :
2366 [ - + ]: 154 : if (encr == NULL) {
2367 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Encryption Type flags "
2368 : : "received");
2369 : 0 : return -1;
2370 : : }
2371 : :
2372 : 154 : encr_types = WPA_GET_BE16(encr);
2373 : :
2374 : 154 : wpa_printf(MSG_DEBUG, "WPS: Enrollee Encryption Type flags 0x%x",
2375 : : encr_types);
2376 : 154 : wps->encr_type = wps->wps->encr_types & encr_types;
2377 [ - + ]: 154 : if (wps->encr_type == 0) {
2378 : 0 : wpa_printf(MSG_DEBUG, "WPS: No match in supported "
2379 : : "encryption types (own 0x%x Enrollee 0x%x)",
2380 : 0 : wps->wps->encr_types, encr_types);
2381 : : #ifdef WPS_WORKAROUNDS
2382 : : /*
2383 : : * Some deployed implementations seem to advertise incorrect
2384 : : * information in this attribute. For example, Linksys WRT350N
2385 : : * seems to have a byteorder bug that breaks this negotiation.
2386 : : * In order to interoperate with existing implementations,
2387 : : * assume that the Enrollee supports everything we do.
2388 : : */
2389 : 0 : wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee "
2390 : : "does not advertise supported encryption types "
2391 : : "correctly");
2392 : 0 : wps->encr_type = wps->wps->encr_types;
2393 : : #else /* WPS_WORKAROUNDS */
2394 : : return -1;
2395 : : #endif /* WPS_WORKAROUNDS */
2396 : : }
2397 : :
2398 : 154 : return 0;
2399 : : }
2400 : :
2401 : :
2402 : 154 : static int wps_process_conn_type_flags(struct wps_data *wps, const u8 *conn)
2403 : : {
2404 [ - + ]: 154 : if (conn == NULL) {
2405 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Connection Type flags "
2406 : : "received");
2407 : 0 : return -1;
2408 : : }
2409 : :
2410 : 154 : wpa_printf(MSG_DEBUG, "WPS: Enrollee Connection Type flags 0x%x",
2411 : 154 : *conn);
2412 : :
2413 : 154 : return 0;
2414 : : }
2415 : :
2416 : :
2417 : 154 : static int wps_process_config_methods(struct wps_data *wps, const u8 *methods)
2418 : : {
2419 : : u16 m;
2420 : :
2421 [ - + ]: 154 : if (methods == NULL) {
2422 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Config Methods received");
2423 : 0 : return -1;
2424 : : }
2425 : :
2426 : 154 : m = WPA_GET_BE16(methods);
2427 : :
2428 [ + + ][ + + ]: 154 : wpa_printf(MSG_DEBUG, "WPS: Enrollee Config Methods 0x%x"
[ - + ][ - + ]
[ + + ][ + + ]
[ - + ][ - + ]
[ + + ]
2429 : : "%s%s%s%s%s%s%s%s%s", m,
2430 : 154 : m & WPS_CONFIG_USBA ? " [USBA]" : "",
2431 : 154 : m & WPS_CONFIG_ETHERNET ? " [Ethernet]" : "",
2432 : 154 : m & WPS_CONFIG_LABEL ? " [Label]" : "",
2433 : 154 : m & WPS_CONFIG_DISPLAY ? " [Display]" : "",
2434 : 154 : m & WPS_CONFIG_EXT_NFC_TOKEN ? " [Ext NFC Token]" : "",
2435 : 154 : m & WPS_CONFIG_INT_NFC_TOKEN ? " [Int NFC Token]" : "",
2436 : 154 : m & WPS_CONFIG_NFC_INTERFACE ? " [NFC]" : "",
2437 : 154 : m & WPS_CONFIG_PUSHBUTTON ? " [PBC]" : "",
2438 : 154 : m & WPS_CONFIG_KEYPAD ? " [Keypad]" : "");
2439 : :
2440 [ + - ][ + + ]: 154 : if (!(m & WPS_CONFIG_DISPLAY) && !wps->use_psk_key) {
2441 : : /*
2442 : : * The Enrollee does not have a display so it is unlikely to be
2443 : : * able to show the passphrase to a user and as such, could
2444 : : * benefit from receiving PSK to reduce key derivation time.
2445 : : */
2446 : 15 : wpa_printf(MSG_DEBUG, "WPS: Prefer PSK format key due to "
2447 : : "Enrollee not supporting display");
2448 : 15 : wps->use_psk_key = 1;
2449 : : }
2450 : :
2451 : 154 : return 0;
2452 : : }
2453 : :
2454 : :
2455 : 154 : static int wps_process_wps_state(struct wps_data *wps, const u8 *state)
2456 : : {
2457 [ - + ]: 154 : if (state == NULL) {
2458 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Wi-Fi Protected Setup State "
2459 : : "received");
2460 : 0 : return -1;
2461 : : }
2462 : :
2463 : 154 : wpa_printf(MSG_DEBUG, "WPS: Enrollee Wi-Fi Protected Setup State %d",
2464 : 154 : *state);
2465 : :
2466 : 154 : return 0;
2467 : : }
2468 : :
2469 : :
2470 : 154 : static int wps_process_assoc_state(struct wps_data *wps, const u8 *assoc)
2471 : : {
2472 : : u16 a;
2473 : :
2474 [ - + ]: 154 : if (assoc == NULL) {
2475 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Association State received");
2476 : 0 : return -1;
2477 : : }
2478 : :
2479 : 154 : a = WPA_GET_BE16(assoc);
2480 : 154 : wpa_printf(MSG_DEBUG, "WPS: Enrollee Association State %d", a);
2481 : :
2482 : 154 : return 0;
2483 : : }
2484 : :
2485 : :
2486 : 154 : static int wps_process_config_error(struct wps_data *wps, const u8 *err)
2487 : : {
2488 : : u16 e;
2489 : :
2490 [ - + ]: 154 : if (err == NULL) {
2491 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Configuration Error received");
2492 : 0 : return -1;
2493 : : }
2494 : :
2495 : 154 : e = WPA_GET_BE16(err);
2496 : 154 : wpa_printf(MSG_DEBUG, "WPS: Enrollee Configuration Error %d", e);
2497 : :
2498 : 154 : return 0;
2499 : : }
2500 : :
2501 : :
2502 : 15 : static int wps_registrar_p2p_dev_addr_match(struct wps_data *wps)
2503 : : {
2504 : : #ifdef CONFIG_P2P
2505 : 6 : struct wps_registrar *reg = wps->wps->registrar;
2506 : :
2507 [ + + ]: 6 : if (is_zero_ether_addr(reg->p2p_dev_addr))
2508 : 3 : return 1; /* no filtering in use */
2509 : :
2510 [ - + ]: 3 : if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) != 0) {
2511 : 0 : wpa_printf(MSG_DEBUG, "WPS: No match on P2P Device Address "
2512 : : "filtering for PBC: expected " MACSTR " was "
2513 : : MACSTR " - indicate PBC session overlap",
2514 : 0 : MAC2STR(reg->p2p_dev_addr),
2515 : 0 : MAC2STR(wps->p2p_dev_addr));
2516 : 0 : return 0;
2517 : : }
2518 : : #endif /* CONFIG_P2P */
2519 : 15 : return 1;
2520 : : }
2521 : :
2522 : :
2523 : 2 : static int wps_registrar_skip_overlap(struct wps_data *wps)
2524 : : {
2525 : : #ifdef CONFIG_P2P
2526 : 0 : struct wps_registrar *reg = wps->wps->registrar;
2527 : :
2528 [ # # ]: 0 : if (is_zero_ether_addr(reg->p2p_dev_addr))
2529 : 0 : return 0; /* no specific Enrollee selected */
2530 : :
2531 [ # # ]: 0 : if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) == 0) {
2532 : 0 : wpa_printf(MSG_DEBUG, "WPS: Skip PBC overlap due to selected "
2533 : : "Enrollee match");
2534 : 0 : return 1;
2535 : : }
2536 : : #endif /* CONFIG_P2P */
2537 : 2 : return 0;
2538 : : }
2539 : :
2540 : :
2541 : 154 : static enum wps_process_res wps_process_m1(struct wps_data *wps,
2542 : : struct wps_parse_attr *attr)
2543 : : {
2544 : 154 : wpa_printf(MSG_DEBUG, "WPS: Received M1");
2545 : :
2546 [ - + ]: 154 : if (wps->state != RECV_M1) {
2547 : 0 : wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
2548 : 0 : "receiving M1", wps->state);
2549 : 0 : return WPS_FAILURE;
2550 : : }
2551 : :
2552 [ + - + - ]: 308 : if (wps_process_uuid_e(wps, attr->uuid_e) ||
2553 [ + - ]: 308 : wps_process_mac_addr(wps, attr->mac_addr) ||
2554 [ + - ]: 308 : wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
2555 [ + - ]: 308 : wps_process_pubkey(wps, attr->public_key, attr->public_key_len) ||
2556 [ + - ]: 308 : wps_process_auth_type_flags(wps, attr->auth_type_flags) ||
2557 [ + - ]: 308 : wps_process_encr_type_flags(wps, attr->encr_type_flags) ||
2558 [ + - ]: 308 : wps_process_conn_type_flags(wps, attr->conn_type_flags) ||
2559 [ + - ]: 308 : wps_process_config_methods(wps, attr->config_methods) ||
2560 [ + - ]: 308 : wps_process_wps_state(wps, attr->wps_state) ||
2561 [ + - ]: 308 : wps_process_device_attrs(&wps->peer_dev, attr) ||
2562 [ + - ]: 308 : wps_process_rf_bands(&wps->peer_dev, attr->rf_bands) ||
2563 [ + - ]: 308 : wps_process_assoc_state(wps, attr->assoc_state) ||
2564 [ + - ]: 308 : wps_process_dev_password_id(wps, attr->dev_password_id) ||
2565 [ - + ]: 308 : wps_process_config_error(wps, attr->config_error) ||
2566 : 154 : wps_process_os_version(&wps->peer_dev, attr->os_version))
2567 : 0 : return WPS_FAILURE;
2568 : :
2569 [ + + ][ + + ]: 154 : if (wps->dev_pw_id < 0x10 &&
2570 [ + - ]: 72 : wps->dev_pw_id != DEV_PW_DEFAULT &&
2571 [ + - ]: 72 : wps->dev_pw_id != DEV_PW_USER_SPECIFIED &&
2572 [ + + ]: 72 : wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED &&
2573 [ + + ]: 36 : wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED &&
2574 : : #ifdef CONFIG_WPS_NFC
2575 [ + - ]: 18 : wps->dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER &&
2576 : : #endif /* CONFIG_WPS_NFC */
2577 [ + + ]: 18 : (wps->dev_pw_id != DEV_PW_PUSHBUTTON ||
2578 : 18 : !wps->wps->registrar->pbc)) {
2579 : 1 : wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d",
2580 : 1 : wps->dev_pw_id);
2581 : 1 : wps->state = SEND_M2D;
2582 : 1 : return WPS_CONTINUE;
2583 : : }
2584 : :
2585 : : #ifdef CONFIG_WPS_NFC
2586 [ + + ][ + + ]: 153 : if (wps->dev_pw_id >= 0x10 ||
2587 : 142 : wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) {
2588 : : struct wps_nfc_pw_token *token;
2589 : : const u8 *addr[1];
2590 : : u8 hash[WPS_HASH_LEN];
2591 : :
2592 : 29 : wpa_printf(MSG_DEBUG, "WPS: Searching for NFC token match for id=%d (ctx %p registrar %p)",
2593 : 58 : wps->dev_pw_id, wps->wps, wps->wps->registrar);
2594 : 29 : token = wps_get_nfc_pw_token(
2595 : 58 : &wps->wps->registrar->nfc_pw_tokens, wps->dev_pw_id);
2596 [ + + ][ + + ]: 29 : if (token && token->peer_pk_hash_known) {
2597 : 22 : wpa_printf(MSG_DEBUG, "WPS: Found matching NFC "
2598 : : "Password Token");
2599 : 22 : dl_list_del(&token->list);
2600 : 22 : wps->nfc_pw_token = token;
2601 : :
2602 : 22 : addr[0] = attr->public_key;
2603 : 22 : sha256_vector(1, addr, &attr->public_key_len, hash);
2604 [ + + ]: 22 : if (os_memcmp(hash, wps->nfc_pw_token->pubkey_hash,
2605 : : WPS_OOB_PUBKEY_HASH_LEN) != 0) {
2606 : 2 : wpa_printf(MSG_ERROR, "WPS: Public Key hash "
2607 : : "mismatch");
2608 : 2 : wps->state = SEND_M2D;
2609 : 2 : wps->config_error =
2610 : : WPS_CFG_PUBLIC_KEY_HASH_MISMATCH;
2611 : 2 : return WPS_CONTINUE;
2612 : : }
2613 [ + + ]: 7 : } else if (token) {
2614 : 1 : wpa_printf(MSG_DEBUG, "WPS: Found matching NFC "
2615 : : "Password Token (no peer PK hash)");
2616 : 1 : wps->nfc_pw_token = token;
2617 [ + + ][ + + ]: 6 : } else if (wps->dev_pw_id >= 0x10 &&
2618 [ + - ]: 2 : wps->wps->ap_nfc_dev_pw_id == wps->dev_pw_id &&
2619 : 2 : wps->wps->ap_nfc_dev_pw) {
2620 : 2 : wpa_printf(MSG_DEBUG, "WPS: Found match with own NFC Password Token");
2621 : : }
2622 : : }
2623 : : #endif /* CONFIG_WPS_NFC */
2624 : :
2625 [ + + ]: 151 : if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) {
2626 [ + + + - ]: 32 : if ((wps->wps->registrar->force_pbc_overlap ||
2627 : 15 : wps_registrar_pbc_overlap(wps->wps->registrar,
2628 [ - + ]: 15 : wps->mac_addr_e, wps->uuid_e) ||
2629 [ + - ]: 17 : !wps_registrar_p2p_dev_addr_match(wps)) &&
2630 : 2 : !wps_registrar_skip_overlap(wps)) {
2631 : 2 : wpa_printf(MSG_DEBUG, "WPS: PBC overlap - deny PBC "
2632 : : "negotiation");
2633 : 2 : wps->state = SEND_M2D;
2634 : 2 : wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED;
2635 : 2 : wps_pbc_overlap_event(wps->wps);
2636 : 2 : wps_fail_event(wps->wps, WPS_M1,
2637 : : WPS_CFG_MULTIPLE_PBC_DETECTED,
2638 : 2 : WPS_EI_NO_ERROR, wps->mac_addr_e);
2639 : 2 : wps->wps->registrar->force_pbc_overlap = 1;
2640 : 2 : return WPS_CONTINUE;
2641 : : }
2642 : 15 : wps_registrar_add_pbc_session(wps->wps->registrar,
2643 : 15 : wps->mac_addr_e, wps->uuid_e);
2644 : 15 : wps->pbc = 1;
2645 : : }
2646 : :
2647 : : #ifdef WPS_WORKAROUNDS
2648 : : /*
2649 : : * It looks like Mac OS X 10.6.3 and 10.6.4 do not like Network Key in
2650 : : * passphrase format. To avoid interop issues, force PSK format to be
2651 : : * used.
2652 : : */
2653 [ + + ][ + - ]: 149 : if (!wps->use_psk_key &&
2654 [ - + ]: 55 : wps->peer_dev.manufacturer &&
2655 [ # # ]: 0 : os_strncmp(wps->peer_dev.manufacturer, "Apple ", 6) == 0 &&
2656 [ # # ]: 0 : wps->peer_dev.model_name &&
2657 : 0 : os_strcmp(wps->peer_dev.model_name, "AirPort") == 0) {
2658 : 0 : wpa_printf(MSG_DEBUG, "WPS: Workaround - Force Network Key in "
2659 : : "PSK format");
2660 : 0 : wps->use_psk_key = 1;
2661 : : }
2662 : : #endif /* WPS_WORKAROUNDS */
2663 : :
2664 : 149 : wps->state = SEND_M2;
2665 : 154 : return WPS_CONTINUE;
2666 : : }
2667 : :
2668 : :
2669 : 122 : static enum wps_process_res wps_process_m3(struct wps_data *wps,
2670 : : const struct wpabuf *msg,
2671 : : struct wps_parse_attr *attr)
2672 : : {
2673 : 122 : wpa_printf(MSG_DEBUG, "WPS: Received M3");
2674 : :
2675 [ - + ]: 122 : if (wps->state != RECV_M3) {
2676 : 0 : wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
2677 : 0 : "receiving M3", wps->state);
2678 : 0 : wps->state = SEND_WSC_NACK;
2679 : 0 : return WPS_CONTINUE;
2680 : : }
2681 : :
2682 [ + + ]: 122 : if (wps->pbc && wps->wps->registrar->force_pbc_overlap &&
[ - + # # ]
2683 : 0 : !wps_registrar_skip_overlap(wps)) {
2684 : 0 : wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC "
2685 : : "session overlap");
2686 : 0 : wps->state = SEND_WSC_NACK;
2687 : 0 : wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED;
2688 : 0 : return WPS_CONTINUE;
2689 : : }
2690 : :
2691 [ + - + - ]: 244 : if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
2692 [ + - ]: 244 : wps_process_authenticator(wps, attr->authenticator, msg) ||
2693 [ - + ]: 244 : wps_process_e_hash1(wps, attr->e_hash1) ||
2694 : 122 : wps_process_e_hash2(wps, attr->e_hash2)) {
2695 : 0 : wps->state = SEND_WSC_NACK;
2696 : 0 : return WPS_CONTINUE;
2697 : : }
2698 : :
2699 : 122 : wps->state = SEND_M4;
2700 : 122 : return WPS_CONTINUE;
2701 : : }
2702 : :
2703 : :
2704 : 116 : static enum wps_process_res wps_process_m5(struct wps_data *wps,
2705 : : const struct wpabuf *msg,
2706 : : struct wps_parse_attr *attr)
2707 : : {
2708 : : struct wpabuf *decrypted;
2709 : : struct wps_parse_attr eattr;
2710 : :
2711 : 116 : wpa_printf(MSG_DEBUG, "WPS: Received M5");
2712 : :
2713 [ - + ]: 116 : if (wps->state != RECV_M5) {
2714 : 0 : wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
2715 : 0 : "receiving M5", wps->state);
2716 : 0 : wps->state = SEND_WSC_NACK;
2717 : 0 : return WPS_CONTINUE;
2718 : : }
2719 : :
2720 [ + + ]: 116 : if (wps->pbc && wps->wps->registrar->force_pbc_overlap &&
[ - + # # ]
2721 : 0 : !wps_registrar_skip_overlap(wps)) {
2722 : 0 : wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC "
2723 : : "session overlap");
2724 : 0 : wps->state = SEND_WSC_NACK;
2725 : 0 : wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED;
2726 : 0 : return WPS_CONTINUE;
2727 : : }
2728 : :
2729 [ + - - + ]: 232 : if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
2730 : 116 : wps_process_authenticator(wps, attr->authenticator, msg)) {
2731 : 0 : wps->state = SEND_WSC_NACK;
2732 : 0 : return WPS_CONTINUE;
2733 : : }
2734 : :
2735 : 116 : decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
2736 : : attr->encr_settings_len);
2737 [ - + ]: 116 : if (decrypted == NULL) {
2738 : 0 : wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
2739 : : "Settings attribute");
2740 : 0 : wps->state = SEND_WSC_NACK;
2741 : 0 : return WPS_CONTINUE;
2742 : : }
2743 : :
2744 [ - + ]: 116 : if (wps_validate_m5_encr(decrypted, attr->version2 != NULL) < 0) {
2745 : 0 : wpabuf_free(decrypted);
2746 : 0 : wps->state = SEND_WSC_NACK;
2747 : 0 : return WPS_CONTINUE;
2748 : : }
2749 : :
2750 : 116 : wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
2751 : : "attribute");
2752 [ + - + - ]: 232 : if (wps_parse_msg(decrypted, &eattr) < 0 ||
2753 [ - + ]: 232 : wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
2754 : 116 : wps_process_e_snonce1(wps, eattr.e_snonce1)) {
2755 : 0 : wpabuf_free(decrypted);
2756 : 0 : wps->state = SEND_WSC_NACK;
2757 : 0 : return WPS_CONTINUE;
2758 : : }
2759 : 116 : wpabuf_free(decrypted);
2760 : :
2761 : 116 : wps->state = SEND_M6;
2762 : 116 : return WPS_CONTINUE;
2763 : : }
2764 : :
2765 : :
2766 : 16 : static void wps_sta_cred_cb(struct wps_data *wps)
2767 : : {
2768 : : /*
2769 : : * Update credential to only include a single authentication and
2770 : : * encryption type in case the AP configuration includes more than one
2771 : : * option.
2772 : : */
2773 [ + + ]: 16 : if (wps->cred.auth_type & WPS_AUTH_WPA2PSK)
2774 : 15 : wps->cred.auth_type = WPS_AUTH_WPA2PSK;
2775 [ + - ]: 1 : else if (wps->cred.auth_type & WPS_AUTH_WPAPSK)
2776 : 1 : wps->cred.auth_type = WPS_AUTH_WPAPSK;
2777 [ + + ]: 16 : if (wps->cred.encr_type & WPS_ENCR_AES)
2778 : 15 : wps->cred.encr_type = WPS_ENCR_AES;
2779 [ + - ]: 1 : else if (wps->cred.encr_type & WPS_ENCR_TKIP)
2780 : 1 : wps->cred.encr_type = WPS_ENCR_TKIP;
2781 : 16 : wpa_printf(MSG_DEBUG, "WPS: Update local configuration based on the "
2782 : : "AP configuration");
2783 [ + - ]: 16 : if (wps->wps->cred_cb)
2784 : 16 : wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred);
2785 : 16 : }
2786 : :
2787 : :
2788 : 6 : static void wps_cred_update(struct wps_credential *dst,
2789 : : struct wps_credential *src)
2790 : : {
2791 : 6 : os_memcpy(dst->ssid, src->ssid, sizeof(dst->ssid));
2792 : 6 : dst->ssid_len = src->ssid_len;
2793 : 6 : dst->auth_type = src->auth_type;
2794 : 6 : dst->encr_type = src->encr_type;
2795 : 6 : dst->key_idx = src->key_idx;
2796 : 6 : os_memcpy(dst->key, src->key, sizeof(dst->key));
2797 : 6 : dst->key_len = src->key_len;
2798 : 6 : }
2799 : :
2800 : :
2801 : 113 : static int wps_process_ap_settings_r(struct wps_data *wps,
2802 : : struct wps_parse_attr *attr)
2803 : : {
2804 : : struct wpabuf *msg;
2805 : :
2806 [ + + ][ + + ]: 113 : if (wps->wps->ap || wps->er)
2807 : 95 : return 0;
2808 : :
2809 : : /* AP Settings Attributes in M7 when Enrollee is an AP */
2810 [ - + ]: 18 : if (wps_process_ap_settings(attr, &wps->cred) < 0)
2811 : 0 : return -1;
2812 : :
2813 : 18 : wpa_printf(MSG_INFO, "WPS: Received old AP configuration from AP");
2814 : :
2815 [ + + ]: 18 : if (wps->new_ap_settings) {
2816 : 6 : wpa_printf(MSG_INFO, "WPS: Update AP configuration based on "
2817 : : "new settings");
2818 : 6 : wps_cred_update(&wps->cred, wps->new_ap_settings);
2819 : 6 : return 0;
2820 : : } else {
2821 : : /*
2822 : : * Use the AP PIN only to receive the current AP settings, not
2823 : : * to reconfigure the AP.
2824 : : */
2825 : :
2826 : : /*
2827 : : * Clear selected registrar here since we do not get to
2828 : : * WSC_Done in this protocol run.
2829 : : */
2830 : 12 : wps_registrar_pin_completed(wps->wps->registrar);
2831 : :
2832 : 12 : msg = wps_build_ap_cred(wps);
2833 [ - + ]: 12 : if (msg == NULL)
2834 : 0 : return -1;
2835 : 12 : wps->cred.cred_attr = wpabuf_head(msg);
2836 : 12 : wps->cred.cred_attr_len = wpabuf_len(msg);
2837 : :
2838 [ + + ]: 12 : if (wps->ap_settings_cb) {
2839 : 1 : wps->ap_settings_cb(wps->ap_settings_cb_ctx,
2840 : 1 : &wps->cred);
2841 : 1 : wpabuf_free(msg);
2842 : 1 : return 1;
2843 : : }
2844 : 11 : wps_sta_cred_cb(wps);
2845 : :
2846 : 11 : wps->cred.cred_attr = NULL;
2847 : 11 : wps->cred.cred_attr_len = 0;
2848 : 11 : wpabuf_free(msg);
2849 : :
2850 : 113 : return 1;
2851 : : }
2852 : : }
2853 : :
2854 : :
2855 : 113 : static enum wps_process_res wps_process_m7(struct wps_data *wps,
2856 : : const struct wpabuf *msg,
2857 : : struct wps_parse_attr *attr)
2858 : : {
2859 : : struct wpabuf *decrypted;
2860 : : struct wps_parse_attr eattr;
2861 : :
2862 : 113 : wpa_printf(MSG_DEBUG, "WPS: Received M7");
2863 : :
2864 [ - + ]: 113 : if (wps->state != RECV_M7) {
2865 : 0 : wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
2866 : 0 : "receiving M7", wps->state);
2867 : 0 : wps->state = SEND_WSC_NACK;
2868 : 0 : return WPS_CONTINUE;
2869 : : }
2870 : :
2871 [ + + ]: 113 : if (wps->pbc && wps->wps->registrar->force_pbc_overlap &&
[ - + # # ]
2872 : 0 : !wps_registrar_skip_overlap(wps)) {
2873 : 0 : wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC "
2874 : : "session overlap");
2875 : 0 : wps->state = SEND_WSC_NACK;
2876 : 0 : wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED;
2877 : 0 : return WPS_CONTINUE;
2878 : : }
2879 : :
2880 [ + - - + ]: 226 : if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
2881 : 113 : wps_process_authenticator(wps, attr->authenticator, msg)) {
2882 : 0 : wps->state = SEND_WSC_NACK;
2883 : 0 : return WPS_CONTINUE;
2884 : : }
2885 : :
2886 : 113 : decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
2887 : : attr->encr_settings_len);
2888 [ - + ]: 113 : if (decrypted == NULL) {
2889 : 0 : wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt Encrypted "
2890 : : "Settings attribute");
2891 : 0 : wps->state = SEND_WSC_NACK;
2892 : 0 : return WPS_CONTINUE;
2893 : : }
2894 : :
2895 [ + + ][ + + ]: 113 : if (wps_validate_m7_encr(decrypted, wps->wps->ap || wps->er,
[ - + ]
2896 : 113 : attr->version2 != NULL) < 0) {
2897 : 0 : wpabuf_free(decrypted);
2898 : 0 : wps->state = SEND_WSC_NACK;
2899 : 0 : return WPS_CONTINUE;
2900 : : }
2901 : :
2902 : 113 : wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
2903 : : "attribute");
2904 [ + - + - ]: 226 : if (wps_parse_msg(decrypted, &eattr) < 0 ||
2905 [ + - ]: 226 : wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
2906 [ + + ]: 226 : wps_process_e_snonce2(wps, eattr.e_snonce2) ||
2907 : 113 : wps_process_ap_settings_r(wps, &eattr)) {
2908 : 12 : wpabuf_free(decrypted);
2909 : 12 : wps->state = SEND_WSC_NACK;
2910 : 12 : return WPS_CONTINUE;
2911 : : }
2912 : :
2913 : 101 : wpabuf_free(decrypted);
2914 : :
2915 : 101 : wps->state = SEND_M8;
2916 : 113 : return WPS_CONTINUE;
2917 : : }
2918 : :
2919 : :
2920 : 505 : static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
2921 : : const struct wpabuf *msg)
2922 : : {
2923 : : struct wps_parse_attr attr;
2924 : 505 : enum wps_process_res ret = WPS_CONTINUE;
2925 : :
2926 : 505 : wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG");
2927 : :
2928 [ - + ]: 505 : if (wps_parse_msg(msg, &attr) < 0)
2929 : 0 : return WPS_FAILURE;
2930 : :
2931 [ - + ]: 505 : if (attr.msg_type == NULL) {
2932 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
2933 : 0 : wps->state = SEND_WSC_NACK;
2934 : 0 : return WPS_CONTINUE;
2935 : : }
2936 : :
2937 [ + + ][ + - ]: 505 : if (*attr.msg_type != WPS_M1 &&
2938 [ - + ]: 351 : (attr.registrar_nonce == NULL ||
2939 : 351 : os_memcmp(wps->nonce_r, attr.registrar_nonce,
2940 : : WPS_NONCE_LEN) != 0)) {
2941 : 0 : wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
2942 : 0 : return WPS_FAILURE;
2943 : : }
2944 : :
2945 [ + + + + : 505 : switch (*attr.msg_type) {
- ]
2946 : : case WPS_M1:
2947 [ - + ]: 154 : if (wps_validate_m1(msg) < 0)
2948 : 0 : return WPS_FAILURE;
2949 : : #ifdef CONFIG_WPS_UPNP
2950 [ + + ][ + - ]: 154 : if (wps->wps->wps_upnp && attr.mac_addr) {
2951 : : /* Remove old pending messages when starting new run */
2952 : 8 : wps_free_pending_msgs(wps->wps->upnp_msgs);
2953 : 8 : wps->wps->upnp_msgs = NULL;
2954 : :
2955 : 8 : upnp_wps_device_send_wlan_event(
2956 : 8 : wps->wps->wps_upnp, attr.mac_addr,
2957 : : UPNP_WPS_WLANEVENT_TYPE_EAP, msg);
2958 : : }
2959 : : #endif /* CONFIG_WPS_UPNP */
2960 : 154 : ret = wps_process_m1(wps, &attr);
2961 : 154 : break;
2962 : : case WPS_M3:
2963 [ - + ]: 122 : if (wps_validate_m3(msg) < 0)
2964 : 0 : return WPS_FAILURE;
2965 : 122 : ret = wps_process_m3(wps, msg, &attr);
2966 [ - + ][ + - ]: 122 : if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
2967 : 0 : wps_fail_event(wps->wps, WPS_M3, wps->config_error,
2968 : 0 : wps->error_indication, wps->mac_addr_e);
2969 : 122 : break;
2970 : : case WPS_M5:
2971 [ - + ]: 116 : if (wps_validate_m5(msg) < 0)
2972 : 0 : return WPS_FAILURE;
2973 : 116 : ret = wps_process_m5(wps, msg, &attr);
2974 [ - + ][ + - ]: 116 : if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
2975 : 0 : wps_fail_event(wps->wps, WPS_M5, wps->config_error,
2976 : 0 : wps->error_indication, wps->mac_addr_e);
2977 : 116 : break;
2978 : : case WPS_M7:
2979 [ - + ]: 113 : if (wps_validate_m7(msg) < 0)
2980 : 0 : return WPS_FAILURE;
2981 : 113 : ret = wps_process_m7(wps, msg, &attr);
2982 [ + + ][ + - ]: 113 : if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
2983 : 12 : wps_fail_event(wps->wps, WPS_M7, wps->config_error,
2984 : 12 : wps->error_indication, wps->mac_addr_e);
2985 : 113 : break;
2986 : : default:
2987 : 0 : wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d",
2988 : 0 : *attr.msg_type);
2989 : 0 : return WPS_FAILURE;
2990 : : }
2991 : :
2992 [ + - ]: 505 : if (ret == WPS_CONTINUE) {
2993 : : /* Save a copy of the last message for Authenticator derivation
2994 : : */
2995 : 505 : wpabuf_free(wps->last_msg);
2996 : 505 : wps->last_msg = wpabuf_dup(msg);
2997 : : }
2998 : :
2999 : 505 : return ret;
3000 : : }
3001 : :
3002 : :
3003 : 21 : static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
3004 : : const struct wpabuf *msg)
3005 : : {
3006 : : struct wps_parse_attr attr;
3007 : :
3008 : 21 : wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK");
3009 : :
3010 [ - + ]: 21 : if (wps_parse_msg(msg, &attr) < 0)
3011 : 0 : return WPS_FAILURE;
3012 : :
3013 [ - + ]: 21 : if (attr.msg_type == NULL) {
3014 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
3015 : 0 : return WPS_FAILURE;
3016 : : }
3017 : :
3018 [ - + ]: 21 : if (*attr.msg_type != WPS_WSC_ACK) {
3019 : 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
3020 : 0 : *attr.msg_type);
3021 : 0 : return WPS_FAILURE;
3022 : : }
3023 : :
3024 : : #ifdef CONFIG_WPS_UPNP
3025 [ + + ][ + + ]: 30 : if (wps->wps->wps_upnp && wps->ext_reg && wps->state == RECV_M2D_ACK &&
[ + - + - ]
3026 : 9 : upnp_wps_subscribers(wps->wps->wps_upnp)) {
3027 [ + + ]: 9 : if (wps->wps->upnp_msgs)
3028 : 8 : return WPS_CONTINUE;
3029 : 1 : wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
3030 : : "external Registrar");
3031 : 1 : return WPS_PENDING;
3032 : : }
3033 : : #endif /* CONFIG_WPS_UPNP */
3034 : :
3035 [ + - ][ - + ]: 12 : if (attr.registrar_nonce == NULL ||
3036 : 12 : os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0)
3037 : : {
3038 : 0 : wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
3039 : 0 : return WPS_FAILURE;
3040 : : }
3041 : :
3042 [ + - ][ - + ]: 12 : if (attr.enrollee_nonce == NULL ||
3043 : 12 : os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) {
3044 : 0 : wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
3045 : 0 : return WPS_FAILURE;
3046 : : }
3047 : :
3048 [ + - ]: 12 : if (wps->state == RECV_M2D_ACK) {
3049 : : #ifdef CONFIG_WPS_UPNP
3050 [ + + + - ]: 20 : if (wps->wps->wps_upnp &&
3051 : 8 : upnp_wps_subscribers(wps->wps->wps_upnp)) {
3052 [ - + ]: 8 : if (wps->wps->upnp_msgs)
3053 : 0 : return WPS_CONTINUE;
3054 [ + - ]: 8 : if (wps->ext_reg == 0)
3055 : 8 : wps->ext_reg = 1;
3056 : 8 : wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
3057 : : "external Registrar");
3058 : 8 : return WPS_PENDING;
3059 : : }
3060 : : #endif /* CONFIG_WPS_UPNP */
3061 : :
3062 : 4 : wpa_printf(MSG_DEBUG, "WPS: No more registrars available - "
3063 : : "terminate negotiation");
3064 : : }
3065 : :
3066 : 21 : return WPS_FAILURE;
3067 : : }
3068 : :
3069 : :
3070 : 19 : static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps,
3071 : : const struct wpabuf *msg)
3072 : : {
3073 : : struct wps_parse_attr attr;
3074 : : int old_state;
3075 : : u16 config_error;
3076 : :
3077 : 19 : wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK");
3078 : :
3079 : 19 : old_state = wps->state;
3080 : 19 : wps->state = SEND_WSC_NACK;
3081 : :
3082 [ - + ]: 19 : if (wps_parse_msg(msg, &attr) < 0)
3083 : 0 : return WPS_FAILURE;
3084 : :
3085 [ - + ]: 19 : if (attr.msg_type == NULL) {
3086 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
3087 : 0 : return WPS_FAILURE;
3088 : : }
3089 : :
3090 [ - + ]: 19 : if (*attr.msg_type != WPS_WSC_NACK) {
3091 : 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
3092 : 0 : *attr.msg_type);
3093 : 0 : return WPS_FAILURE;
3094 : : }
3095 : :
3096 : : #ifdef CONFIG_WPS_UPNP
3097 [ + + ][ + - ]: 19 : if (wps->wps->wps_upnp && wps->ext_reg) {
3098 : 1 : wpa_printf(MSG_DEBUG, "WPS: Negotiation using external "
3099 : : "Registrar terminated by the Enrollee");
3100 : 1 : return WPS_FAILURE;
3101 : : }
3102 : : #endif /* CONFIG_WPS_UPNP */
3103 : :
3104 [ + - ][ - + ]: 18 : if (attr.registrar_nonce == NULL ||
3105 : 18 : os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0)
3106 : : {
3107 : 0 : wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
3108 : 0 : return WPS_FAILURE;
3109 : : }
3110 : :
3111 [ + - ][ - + ]: 18 : if (attr.enrollee_nonce == NULL ||
3112 : 18 : os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) {
3113 : 0 : wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
3114 : 0 : return WPS_FAILURE;
3115 : : }
3116 : :
3117 [ - + ]: 18 : if (attr.config_error == NULL) {
3118 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute "
3119 : : "in WSC_NACK");
3120 : 0 : return WPS_FAILURE;
3121 : : }
3122 : :
3123 : 18 : config_error = WPA_GET_BE16(attr.config_error);
3124 : 18 : wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with "
3125 : : "Configuration Error %d", config_error);
3126 : :
3127 [ + + + + : 18 : switch (old_state) {
- ]
3128 : : case RECV_M3:
3129 : 6 : wps_fail_event(wps->wps, WPS_M2, config_error,
3130 : 6 : wps->error_indication, wps->mac_addr_e);
3131 : 6 : break;
3132 : : case RECV_M5:
3133 : 6 : wps_fail_event(wps->wps, WPS_M4, config_error,
3134 : 6 : wps->error_indication, wps->mac_addr_e);
3135 : 6 : break;
3136 : : case RECV_M7:
3137 : 3 : wps_fail_event(wps->wps, WPS_M6, config_error,
3138 : 3 : wps->error_indication, wps->mac_addr_e);
3139 : 3 : break;
3140 : : case RECV_DONE:
3141 : 3 : wps_fail_event(wps->wps, WPS_M8, config_error,
3142 : 3 : wps->error_indication, wps->mac_addr_e);
3143 : 3 : break;
3144 : : default:
3145 : 0 : break;
3146 : : }
3147 : :
3148 : 19 : return WPS_FAILURE;
3149 : : }
3150 : :
3151 : :
3152 : 117 : static enum wps_process_res wps_process_wsc_done(struct wps_data *wps,
3153 : : const struct wpabuf *msg)
3154 : : {
3155 : : struct wps_parse_attr attr;
3156 : :
3157 : 117 : wpa_printf(MSG_DEBUG, "WPS: Received WSC_Done");
3158 : :
3159 [ + - ][ + + ]: 117 : if (wps->state != RECV_DONE &&
3160 [ - + ]: 6 : (!wps->wps->wps_upnp || !wps->ext_reg)) {
3161 : 0 : wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
3162 : 0 : "receiving WSC_Done", wps->state);
3163 : 0 : return WPS_FAILURE;
3164 : : }
3165 : :
3166 [ - + ]: 117 : if (wps_parse_msg(msg, &attr) < 0)
3167 : 0 : return WPS_FAILURE;
3168 : :
3169 [ - + ]: 117 : if (attr.msg_type == NULL) {
3170 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
3171 : 0 : return WPS_FAILURE;
3172 : : }
3173 : :
3174 [ - + ]: 117 : if (*attr.msg_type != WPS_WSC_DONE) {
3175 : 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
3176 : 0 : *attr.msg_type);
3177 : 0 : return WPS_FAILURE;
3178 : : }
3179 : :
3180 : : #ifdef CONFIG_WPS_UPNP
3181 [ + + ][ + - ]: 117 : if (wps->wps->wps_upnp && wps->ext_reg) {
3182 : 6 : wpa_printf(MSG_DEBUG, "WPS: Negotiation using external "
3183 : : "Registrar completed successfully");
3184 : 6 : wps_device_store(wps->wps->registrar, &wps->peer_dev,
3185 : 6 : wps->uuid_e);
3186 : 6 : return WPS_DONE;
3187 : : }
3188 : : #endif /* CONFIG_WPS_UPNP */
3189 : :
3190 [ + - ][ - + ]: 111 : if (attr.registrar_nonce == NULL ||
3191 : 111 : os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0)
3192 : : {
3193 : 0 : wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
3194 : 0 : return WPS_FAILURE;
3195 : : }
3196 : :
3197 [ + - ][ - + ]: 111 : if (attr.enrollee_nonce == NULL ||
3198 : 111 : os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) {
3199 : 0 : wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
3200 : 0 : return WPS_FAILURE;
3201 : : }
3202 : :
3203 : 111 : wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully");
3204 : 111 : wps_device_store(wps->wps->registrar, &wps->peer_dev,
3205 : 111 : wps->uuid_e);
3206 : :
3207 [ + - ][ + - ]: 111 : if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk &&
[ + + ]
3208 [ + - ]: 5 : wps->wps->ap && !wps->wps->registrar->disable_auto_conf) {
3209 : : struct wps_credential cred;
3210 : :
3211 : 5 : wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based "
3212 : : "on first Enrollee connection");
3213 : :
3214 : 5 : os_memset(&cred, 0, sizeof(cred));
3215 : 5 : os_memcpy(cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
3216 : 5 : cred.ssid_len = wps->wps->ssid_len;
3217 : 5 : cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK;
3218 : 5 : cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES;
3219 : 5 : os_memcpy(cred.key, wps->new_psk, wps->new_psk_len);
3220 : 5 : cred.key_len = wps->new_psk_len;
3221 : :
3222 : 5 : wps->wps->wps_state = WPS_STATE_CONFIGURED;
3223 : 5 : wpa_hexdump_ascii_key(MSG_DEBUG,
3224 : : "WPS: Generated random passphrase",
3225 : 5 : wps->new_psk, wps->new_psk_len);
3226 [ + - ]: 5 : if (wps->wps->cred_cb)
3227 : 5 : wps->wps->cred_cb(wps->wps->cb_ctx, &cred);
3228 : :
3229 : 5 : os_free(wps->new_psk);
3230 : 5 : wps->new_psk = NULL;
3231 : : }
3232 : :
3233 [ + + ][ + + ]: 111 : if (!wps->wps->ap && !wps->er)
3234 : 5 : wps_sta_cred_cb(wps);
3235 : :
3236 [ + + ]: 111 : if (wps->new_psk) {
3237 [ - + ]: 8 : if (wps_cb_new_psk(wps->wps->registrar, wps->mac_addr_e,
3238 : 8 : wps->p2p_dev_addr, wps->new_psk,
3239 : : wps->new_psk_len)) {
3240 : 0 : wpa_printf(MSG_DEBUG, "WPS: Failed to configure the "
3241 : : "new PSK");
3242 : : }
3243 : 8 : os_free(wps->new_psk);
3244 : 8 : wps->new_psk = NULL;
3245 : : }
3246 : :
3247 : 111 : wps_cb_reg_success(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e,
3248 : 111 : wps->dev_password, wps->dev_password_len);
3249 : :
3250 [ + + ]: 111 : if (wps->pbc) {
3251 : 15 : wps_registrar_remove_pbc_session(wps->wps->registrar,
3252 : 15 : wps->uuid_e,
3253 : 15 : wps->p2p_dev_addr);
3254 : 15 : wps_registrar_pbc_completed(wps->wps->registrar);
3255 : : #ifdef WPS_WORKAROUNDS
3256 : 15 : os_get_reltime(&wps->wps->registrar->pbc_ignore_start);
3257 : : #endif /* WPS_WORKAROUNDS */
3258 : 15 : os_memcpy(wps->wps->registrar->pbc_ignore_uuid, wps->uuid_e,
3259 : : WPS_UUID_LEN);
3260 : : } else {
3261 : 96 : wps_registrar_pin_completed(wps->wps->registrar);
3262 : : }
3263 : : /* TODO: maintain AuthorizedMACs somewhere separately for each ER and
3264 : : * merge them into APs own list.. */
3265 : :
3266 : 111 : wps_success_event(wps->wps, wps->mac_addr_e);
3267 : :
3268 : 117 : return WPS_DONE;
3269 : : }
3270 : :
3271 : :
3272 : 692 : enum wps_process_res wps_registrar_process_msg(struct wps_data *wps,
3273 : : enum wsc_op_code op_code,
3274 : : const struct wpabuf *msg)
3275 : : {
3276 : : enum wps_process_res ret;
3277 : :
3278 : 692 : wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu "
3279 : : "op_code=%d)",
3280 : : (unsigned long) wpabuf_len(msg), op_code);
3281 : :
3282 : : #ifdef CONFIG_WPS_UPNP
3283 [ + + ][ + + ]: 692 : if (wps->wps->wps_upnp && op_code == WSC_MSG && wps->ext_reg == 1) {
[ + + ]
3284 : : struct wps_parse_attr attr;
3285 [ + - ][ + - ]: 5 : if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type &&
[ + - ]
3286 : 5 : *attr.msg_type == WPS_M3)
3287 : 5 : wps->ext_reg = 2; /* past M2/M2D phase */
3288 : : }
3289 [ + + ]: 692 : if (wps->ext_reg > 1)
3290 : 35 : wps_registrar_free_pending_m2(wps->wps);
3291 [ + + ][ + + ]: 692 : if (wps->wps->wps_upnp && wps->ext_reg &&
[ + + ]
3292 [ + + ]: 23 : wps->wps->upnp_msgs == NULL &&
3293 [ + + ][ + + ]: 8 : (op_code == WSC_MSG || op_code == WSC_Done || op_code == WSC_NACK))
3294 : 7 : {
3295 : : struct wps_parse_attr attr;
3296 : : int type;
3297 [ + - ][ - + ]: 22 : if (wps_parse_msg(msg, &attr) < 0 || attr.msg_type == NULL)
3298 : 0 : type = -1;
3299 : : else
3300 : 22 : type = *attr.msg_type;
3301 : 22 : wpa_printf(MSG_DEBUG, "WPS: Sending received message (type %d)"
3302 : : " to external Registrar for processing", type);
3303 : 22 : upnp_wps_device_send_wlan_event(wps->wps->wps_upnp,
3304 : 22 : wps->mac_addr_e,
3305 : : UPNP_WPS_WLANEVENT_TYPE_EAP,
3306 : : msg);
3307 [ + + ]: 22 : if (op_code == WSC_MSG)
3308 : 15 : return WPS_PENDING;
3309 [ + + ][ + + ]: 670 : } else if (wps->wps->wps_upnp && wps->ext_reg && op_code == WSC_MSG) {
[ + + ]
3310 : 15 : wpa_printf(MSG_DEBUG, "WPS: Skip internal processing - using "
3311 : : "external Registrar");
3312 : 15 : return WPS_CONTINUE;
3313 : : }
3314 : : #endif /* CONFIG_WPS_UPNP */
3315 : :
3316 [ + + + + : 662 : switch (op_code) {
- ]
3317 : : case WSC_MSG:
3318 : 505 : return wps_process_wsc_msg(wps, msg);
3319 : : case WSC_ACK:
3320 [ - + ]: 21 : if (wps_validate_wsc_ack(msg) < 0)
3321 : 0 : return WPS_FAILURE;
3322 : 21 : return wps_process_wsc_ack(wps, msg);
3323 : : case WSC_NACK:
3324 [ - + ]: 19 : if (wps_validate_wsc_nack(msg) < 0)
3325 : 0 : return WPS_FAILURE;
3326 : 19 : return wps_process_wsc_nack(wps, msg);
3327 : : case WSC_Done:
3328 [ - + ]: 117 : if (wps_validate_wsc_done(msg) < 0)
3329 : 0 : return WPS_FAILURE;
3330 : 117 : ret = wps_process_wsc_done(wps, msg);
3331 [ - + ]: 117 : if (ret == WPS_FAILURE) {
3332 : 0 : wps->state = SEND_WSC_NACK;
3333 : 0 : wps_fail_event(wps->wps, WPS_WSC_DONE,
3334 : 0 : wps->config_error,
3335 : 0 : wps->error_indication, wps->mac_addr_e);
3336 : : }
3337 : 117 : return ret;
3338 : : default:
3339 : 0 : wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code);
3340 : 692 : return WPS_FAILURE;
3341 : : }
3342 : : }
3343 : :
3344 : :
3345 : 18 : int wps_registrar_update_ie(struct wps_registrar *reg)
3346 : : {
3347 : 18 : return wps_set_ie(reg);
3348 : : }
3349 : :
3350 : :
3351 : 3 : static void wps_registrar_set_selected_timeout(void *eloop_ctx,
3352 : : void *timeout_ctx)
3353 : : {
3354 : 3 : struct wps_registrar *reg = eloop_ctx;
3355 : :
3356 : 3 : wpa_printf(MSG_DEBUG, "WPS: Selected Registrar timeout - "
3357 : : "unselect internal Registrar");
3358 : 3 : reg->selected_registrar = 0;
3359 : 3 : reg->pbc = 0;
3360 : 3 : wps_registrar_selected_registrar_changed(reg, 0);
3361 : 3 : }
3362 : :
3363 : :
3364 : : #ifdef CONFIG_WPS_UPNP
3365 : 12 : static void wps_registrar_sel_reg_add(struct wps_registrar *reg,
3366 : : struct subscription *s)
3367 : : {
3368 : : int i, j;
3369 : 12 : wpa_printf(MSG_DEBUG, "WPS: External Registrar selected (dev_pw_id=%d "
3370 : : "config_methods=0x%x)",
3371 : 24 : s->dev_password_id, s->config_methods);
3372 : 12 : reg->sel_reg_union = 1;
3373 [ + - ]: 12 : if (reg->sel_reg_dev_password_id_override != DEV_PW_PUSHBUTTON)
3374 : 12 : reg->sel_reg_dev_password_id_override = s->dev_password_id;
3375 [ + - ]: 12 : if (reg->sel_reg_config_methods_override == -1)
3376 : 12 : reg->sel_reg_config_methods_override = 0;
3377 : 12 : reg->sel_reg_config_methods_override |= s->config_methods;
3378 [ + - ]: 12 : for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++)
3379 [ + - ]: 12 : if (is_zero_ether_addr(reg->authorized_macs_union[i]))
3380 : 12 : break;
3381 [ + - ][ + - ]: 24 : for (j = 0; i < WPS_MAX_AUTHORIZED_MACS && j < WPS_MAX_AUTHORIZED_MACS;
3382 : 12 : j++) {
3383 [ + + ]: 24 : if (is_zero_ether_addr(s->authorized_macs[j]))
3384 : 12 : break;
3385 : 12 : wpa_printf(MSG_DEBUG, "WPS: Add authorized MAC into union: "
3386 : 72 : MACSTR, MAC2STR(s->authorized_macs[j]));
3387 : 12 : os_memcpy(reg->authorized_macs_union[i],
3388 : : s->authorized_macs[j], ETH_ALEN);
3389 : 12 : i++;
3390 : : }
3391 : 12 : wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs union",
3392 : 12 : (u8 *) reg->authorized_macs_union,
3393 : : sizeof(reg->authorized_macs_union));
3394 : 12 : }
3395 : : #endif /* CONFIG_WPS_UPNP */
3396 : :
3397 : :
3398 : 428 : static void wps_registrar_sel_reg_union(struct wps_registrar *reg)
3399 : : {
3400 : : #ifdef CONFIG_WPS_UPNP
3401 : : struct subscription *s;
3402 : :
3403 [ + + ]: 428 : if (reg->wps->wps_upnp == NULL)
3404 : 428 : return;
3405 : :
3406 [ + + ]: 47 : dl_list_for_each(s, ®->wps->wps_upnp->subscriptions,
3407 : : struct subscription, list) {
3408 : : struct subscr_addr *sa;
3409 [ + - ]: 18 : sa = dl_list_first(&s->addr_list, struct subscr_addr, list);
3410 [ + - ]: 18 : if (sa) {
3411 : 18 : wpa_printf(MSG_DEBUG, "WPS: External Registrar %s:%d",
3412 : : inet_ntoa(sa->saddr.sin_addr),
3413 : 18 : ntohs(sa->saddr.sin_port));
3414 : : }
3415 [ + + ]: 18 : if (s->selected_registrar)
3416 : 12 : wps_registrar_sel_reg_add(reg, s);
3417 : : else
3418 : 6 : wpa_printf(MSG_DEBUG, "WPS: External Registrar not "
3419 : : "selected");
3420 : : }
3421 : : #endif /* CONFIG_WPS_UPNP */
3422 : : }
3423 : :
3424 : :
3425 : : /**
3426 : : * wps_registrar_selected_registrar_changed - SetSelectedRegistrar change
3427 : : * @reg: Registrar data from wps_registrar_init()
3428 : : *
3429 : : * This function is called when selected registrar state changes, e.g., when an
3430 : : * AP receives a SetSelectedRegistrar UPnP message.
3431 : : */
3432 : 428 : void wps_registrar_selected_registrar_changed(struct wps_registrar *reg,
3433 : : u16 dev_pw_id)
3434 : : {
3435 : 428 : wpa_printf(MSG_DEBUG, "WPS: Selected registrar information changed");
3436 : :
3437 : 428 : reg->sel_reg_union = reg->selected_registrar;
3438 : 428 : reg->sel_reg_dev_password_id_override = -1;
3439 : 428 : reg->sel_reg_config_methods_override = -1;
3440 : 428 : os_memcpy(reg->authorized_macs_union, reg->authorized_macs,
3441 : : WPS_MAX_AUTHORIZED_MACS * ETH_ALEN);
3442 : 428 : wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs union (start with own)",
3443 : 428 : (u8 *) reg->authorized_macs_union,
3444 : : sizeof(reg->authorized_macs_union));
3445 [ + + ]: 428 : if (reg->selected_registrar) {
3446 : : u16 methods;
3447 : :
3448 : 246 : methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
3449 : : #ifdef CONFIG_WPS2
3450 : 246 : methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
3451 : : WPS_CONFIG_PHY_PUSHBUTTON);
3452 : : #endif /* CONFIG_WPS2 */
3453 [ + + ]: 246 : if (reg->pbc) {
3454 : 21 : reg->sel_reg_dev_password_id_override =
3455 : : DEV_PW_PUSHBUTTON;
3456 : 21 : wps_set_pushbutton(&methods, reg->wps->config_methods);
3457 [ + + ]: 225 : } else if (dev_pw_id)
3458 : 23 : reg->sel_reg_dev_password_id_override = dev_pw_id;
3459 : 246 : wpa_printf(MSG_DEBUG, "WPS: Internal Registrar selected "
3460 : : "(pbc=%d)", reg->pbc);
3461 : 246 : reg->sel_reg_config_methods_override = methods;
3462 : : } else
3463 : 182 : wpa_printf(MSG_DEBUG, "WPS: Internal Registrar not selected");
3464 : :
3465 : 428 : wps_registrar_sel_reg_union(reg);
3466 : :
3467 : 428 : wps_set_ie(reg);
3468 : 428 : wps_cb_set_sel_reg(reg);
3469 : 428 : }
3470 : :
3471 : :
3472 : 4 : int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr,
3473 : : char *buf, size_t buflen)
3474 : : {
3475 : : struct wps_registrar_device *d;
3476 : 4 : int len = 0, ret;
3477 : : char uuid[40];
3478 : : char devtype[WPS_DEV_TYPE_BUFSIZE];
3479 : :
3480 : 4 : d = wps_device_get(reg, addr);
3481 [ + + ]: 4 : if (d == NULL)
3482 : 3 : return 0;
3483 [ - + ]: 1 : if (uuid_bin2str(d->uuid, uuid, sizeof(uuid)))
3484 : 0 : return 0;
3485 : :
3486 [ + - ][ + - ]: 1 : ret = os_snprintf(buf + len, buflen - len,
[ + - ][ + - ]
[ + - ]
3487 : : "wpsUuid=%s\n"
3488 : : "wpsPrimaryDeviceType=%s\n"
3489 : : "wpsDeviceName=%s\n"
3490 : : "wpsManufacturer=%s\n"
3491 : : "wpsModelName=%s\n"
3492 : : "wpsModelNumber=%s\n"
3493 : : "wpsSerialNumber=%s\n",
3494 : : uuid,
3495 : 1 : wps_dev_type_bin2str(d->dev.pri_dev_type, devtype,
3496 : : sizeof(devtype)),
3497 : 1 : d->dev.device_name ? d->dev.device_name : "",
3498 : 1 : d->dev.manufacturer ? d->dev.manufacturer : "",
3499 : 1 : d->dev.model_name ? d->dev.model_name : "",
3500 : 1 : d->dev.model_number ? d->dev.model_number : "",
3501 : 1 : d->dev.serial_number ? d->dev.serial_number : "");
3502 [ - + ][ + - ]: 1 : if (ret < 0 || (size_t) ret >= buflen - len)
3503 : 0 : return len;
3504 : 1 : len += ret;
3505 : :
3506 : 4 : return len;
3507 : : }
3508 : :
3509 : :
3510 : 1 : int wps_registrar_config_ap(struct wps_registrar *reg,
3511 : : struct wps_credential *cred)
3512 : : {
3513 : : #ifdef CONFIG_WPS2
3514 : 1 : wpa_printf(MSG_DEBUG, "WPS: encr_type=0x%x", cred->encr_type);
3515 [ - + ]: 1 : if (!(cred->encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP |
3516 : : WPS_ENCR_AES))) {
3517 [ # # ]: 0 : if (cred->encr_type & WPS_ENCR_WEP) {
3518 : 0 : wpa_printf(MSG_INFO, "WPS: Reject new AP settings "
3519 : : "due to WEP configuration");
3520 : 0 : return -1;
3521 : : }
3522 : :
3523 : 0 : wpa_printf(MSG_INFO, "WPS: Reject new AP settings due to "
3524 : 0 : "invalid encr_type 0x%x", cred->encr_type);
3525 : 0 : return -1;
3526 : : }
3527 : :
3528 [ - + ]: 1 : if ((cred->encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) ==
3529 : : WPS_ENCR_TKIP) {
3530 : 0 : wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> "
3531 : : "TKIP+AES");
3532 : 0 : cred->encr_type |= WPS_ENCR_AES;
3533 : : }
3534 : :
3535 [ - + ]: 1 : if ((cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) ==
3536 : : WPS_AUTH_WPAPSK) {
3537 : 0 : wpa_printf(MSG_DEBUG, "WPS: Upgrade auth_type WPAPSK -> "
3538 : : "WPAPSK+WPA2PSK");
3539 : 0 : cred->auth_type |= WPS_AUTH_WPA2PSK;
3540 : : }
3541 : : #endif /* CONFIG_WPS2 */
3542 : :
3543 [ + - ]: 1 : if (reg->wps->cred_cb)
3544 : 1 : return reg->wps->cred_cb(reg->wps->cb_ctx, cred);
3545 : :
3546 : 1 : return -1;
3547 : : }
3548 : :
3549 : :
3550 : : #ifdef CONFIG_WPS_NFC
3551 : :
3552 : 23 : int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
3553 : : const u8 *pubkey_hash, u16 pw_id,
3554 : : const u8 *dev_pw, size_t dev_pw_len,
3555 : : int pk_hash_provided_oob)
3556 : : {
3557 : : struct wps_nfc_pw_token *token;
3558 : :
3559 [ - + ]: 23 : if (dev_pw_len > WPS_OOB_DEVICE_PASSWORD_LEN)
3560 : 0 : return -1;
3561 : :
3562 [ + + ][ + - ]: 23 : if (pw_id == DEV_PW_NFC_CONNECTION_HANDOVER &&
3563 [ - + ]: 15 : (pubkey_hash == NULL || !pk_hash_provided_oob)) {
3564 : 0 : wpa_printf(MSG_DEBUG, "WPS: Unexpected NFC Password Token "
3565 : : "addition - missing public key hash");
3566 : 0 : return -1;
3567 : : }
3568 : :
3569 : 23 : wps_free_nfc_pw_tokens(®->nfc_pw_tokens, pw_id);
3570 : :
3571 : 23 : token = os_zalloc(sizeof(*token));
3572 [ - + ]: 23 : if (token == NULL)
3573 : 0 : return -1;
3574 : :
3575 : 23 : token->peer_pk_hash_known = pubkey_hash != NULL;
3576 [ + + ]: 23 : if (pubkey_hash)
3577 : 22 : os_memcpy(token->pubkey_hash, pubkey_hash,
3578 : : WPS_OOB_PUBKEY_HASH_LEN);
3579 : 23 : token->pw_id = pw_id;
3580 : 23 : token->pk_hash_provided_oob = pk_hash_provided_oob;
3581 [ + + ]: 23 : if (dev_pw) {
3582 : 8 : wpa_snprintf_hex_uppercase((char *) token->dev_pw,
3583 : : sizeof(token->dev_pw),
3584 : : dev_pw, dev_pw_len);
3585 : 8 : token->dev_pw_len = dev_pw_len * 2;
3586 : : }
3587 : :
3588 : 23 : dl_list_add(®->nfc_pw_tokens, &token->list);
3589 : :
3590 : 23 : reg->selected_registrar = 1;
3591 : 23 : reg->pbc = 0;
3592 : 23 : wps_registrar_add_authorized_mac(reg,
3593 : : (u8 *) "\xff\xff\xff\xff\xff\xff");
3594 : 23 : wps_registrar_selected_registrar_changed(reg, pw_id);
3595 : 23 : eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
3596 : 23 : eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
3597 : : wps_registrar_set_selected_timeout,
3598 : : reg, NULL);
3599 : :
3600 : 23 : wpa_printf(MSG_DEBUG, "WPS: Added NFC Device Password %u to Registrar",
3601 : : pw_id);
3602 : :
3603 : 23 : return 0;
3604 : : }
3605 : :
3606 : :
3607 : 4 : int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
3608 : : const u8 *oob_dev_pw,
3609 : : size_t oob_dev_pw_len)
3610 : : {
3611 : : const u8 *pos, *hash, *dev_pw;
3612 : : u16 id;
3613 : : size_t dev_pw_len;
3614 : :
3615 [ + - ][ - + ]: 4 : if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
3616 : : oob_dev_pw_len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
3617 : : WPS_OOB_DEVICE_PASSWORD_LEN)
3618 : 0 : return -1;
3619 : :
3620 : 4 : hash = oob_dev_pw;
3621 : 4 : pos = oob_dev_pw + WPS_OOB_PUBKEY_HASH_LEN;
3622 : 4 : id = WPA_GET_BE16(pos);
3623 : 4 : dev_pw = pos + 2;
3624 : 4 : dev_pw_len = oob_dev_pw + oob_dev_pw_len - dev_pw;
3625 : :
3626 : 4 : wpa_printf(MSG_DEBUG, "WPS: Add NFC Password Token for Password ID %u",
3627 : : id);
3628 : :
3629 : 4 : wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash",
3630 : : hash, WPS_OOB_PUBKEY_HASH_LEN);
3631 : 4 : wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", dev_pw, dev_pw_len);
3632 : :
3633 : 4 : return wps_registrar_add_nfc_pw_token(reg, hash, id, dev_pw,
3634 : : dev_pw_len, 0);
3635 : : }
3636 : :
3637 : :
3638 : 23 : void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg,
3639 : : struct wps_nfc_pw_token *token)
3640 : : {
3641 : 23 : wps_registrar_remove_authorized_mac(reg,
3642 : : (u8 *) "\xff\xff\xff\xff\xff\xff");
3643 : 23 : wps_registrar_selected_registrar_changed(reg, 0);
3644 : :
3645 : : /*
3646 : : * Free the NFC password token if it was used only for a single protocol
3647 : : * run. The static handover case uses the same password token multiple
3648 : : * times, so do not free that case here.
3649 : : */
3650 [ + + ]: 23 : if (token->peer_pk_hash_known)
3651 : 22 : os_free(token);
3652 : 23 : }
3653 : :
3654 : : #endif /* CONFIG_WPS_NFC */
|