]> git.ipfire.org Git - thirdparty/hostap.git/blob - src/wps/wps.c
WPS: Parse Request Type from WPS IE in (Re)AssocReq and derive mgmt keys
[thirdparty/hostap.git] / src / wps / wps.c
1 /*
2 * Wi-Fi Protected Setup
3 * Copyright (c) 2007-2008, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "wps_i.h"
19 #include "wps_dev_attr.h"
20
21
22 struct wps_data * wps_init(const struct wps_config *cfg)
23 {
24 struct wps_data *data = os_zalloc(sizeof(*data));
25 if (data == NULL)
26 return NULL;
27 data->authenticator = cfg->authenticator;
28 data->wps = cfg->wps;
29 data->registrar = cfg->registrar;
30 if (cfg->enrollee_mac_addr)
31 os_memcpy(data->mac_addr_e, cfg->enrollee_mac_addr, ETH_ALEN);
32 if (cfg->uuid) {
33 os_memcpy(cfg->registrar ? data->uuid_r : data->uuid_e,
34 cfg->uuid, WPS_UUID_LEN);
35 }
36 if (cfg->pin) {
37 data->dev_pw_id = DEV_PW_DEFAULT;
38 data->dev_password = os_malloc(cfg->pin_len);
39 if (data->dev_password == NULL) {
40 os_free(data);
41 return NULL;
42 }
43 os_memcpy(data->dev_password, cfg->pin, cfg->pin_len);
44 data->dev_password_len = cfg->pin_len;
45 }
46
47 data->pbc = cfg->pbc;
48 if (cfg->pbc) {
49 /* Use special PIN '00000000' for PBC */
50 data->dev_pw_id = DEV_PW_PUSHBUTTON;
51 os_free(data->dev_password);
52 data->dev_password = os_malloc(8);
53 if (data->dev_password == NULL) {
54 os_free(data);
55 return NULL;
56 }
57 os_memset(data->dev_password, '0', 8);
58 data->dev_password_len = 8;
59 }
60
61 data->state = data->registrar ? RECV_M1 : SEND_M1;
62
63 if (cfg->assoc_wps_ie) {
64 struct wps_parse_attr attr;
65 wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq",
66 cfg->assoc_wps_ie);
67 if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) {
68 wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE "
69 "from (Re)AssocReq");
70 } else if (attr.request_type == NULL) {
71 wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute "
72 "in (Re)AssocReq WPS IE");
73 } else {
74 wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE "
75 "in (Re)AssocReq WPS IE): %d",
76 *attr.request_type);
77 data->request_type = *attr.request_type;
78 }
79 }
80
81 return data;
82 }
83
84
85 void wps_deinit(struct wps_data *data)
86 {
87 if (data->wps_pin_revealed) {
88 wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and "
89 "negotiation failed");
90 if (data->registrar)
91 wps_registrar_invalidate_pin(data->registrar,
92 data->uuid_e);
93 } else if (data->registrar)
94 wps_registrar_unlock_pin(data->registrar, data->uuid_e);
95
96 wpabuf_free(data->dh_privkey);
97 wpabuf_free(data->dh_pubkey_e);
98 wpabuf_free(data->dh_pubkey_r);
99 wpabuf_free(data->last_msg);
100 os_free(data->dev_password);
101 os_free(data->new_psk);
102 wps_device_data_free(&data->peer_dev);
103 os_free(data);
104 }
105
106
107 enum wps_process_res wps_process_msg(struct wps_data *wps, u8 op_code,
108 const struct wpabuf *msg)
109 {
110 if (wps->registrar)
111 return wps_registrar_process_msg(wps, op_code, msg);
112 else
113 return wps_enrollee_process_msg(wps, op_code, msg);
114 }
115
116
117 struct wpabuf * wps_get_msg(struct wps_data *wps, u8 *op_code)
118 {
119 if (wps->registrar)
120 return wps_registrar_get_msg(wps, op_code);
121 else
122 return wps_enrollee_get_msg(wps, op_code);
123 }
124
125
126 int wps_is_selected_pbc_registrar(const u8 *buf, size_t len)
127 {
128 struct wps_parse_attr attr;
129 struct wpabuf msg;
130
131 wpabuf_set(&msg, buf, len);
132 if (wps_parse_msg(&msg, &attr) < 0 ||
133 !attr.selected_registrar || *attr.selected_registrar == 0 ||
134 !attr.sel_reg_config_methods ||
135 !(WPA_GET_BE16(attr.sel_reg_config_methods) &
136 WPS_CONFIG_PUSHBUTTON) ||
137 !attr.dev_password_id ||
138 WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON)
139 return 0;
140
141 return 1;
142 }
143
144
145 int wps_is_selected_pin_registrar(const u8 *buf, size_t len)
146 {
147 struct wps_parse_attr attr;
148 struct wpabuf msg;
149
150 wpabuf_set(&msg, buf, len);
151 if (wps_parse_msg(&msg, &attr) < 0 ||
152 !attr.selected_registrar || *attr.selected_registrar == 0 ||
153 !attr.sel_reg_config_methods ||
154 !(WPA_GET_BE16(attr.sel_reg_config_methods) &
155 (WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD)) ||
156 !attr.dev_password_id ||
157 WPA_GET_BE16(attr.dev_password_id) == DEV_PW_PUSHBUTTON)
158 return 0;
159
160 return 1;
161 }
162
163
164 const u8 * wps_get_uuid_e(const u8 *buf, size_t len)
165 {
166 struct wps_parse_attr attr;
167 struct wpabuf msg;
168
169 wpabuf_set(&msg, buf, len);
170 if (wps_parse_msg(&msg, &attr) < 0)
171 return NULL;
172 return attr.uuid_e;
173 }