source: rtems-libbsd/freebsd/contrib/wpa/src/wps/wps_attr_process.c @ 9c9d11b

55-freebsd-126-freebsd-12
Last change on this file since 9c9d11b was 9c9d11b, checked in by Sichen Zhao <1473996754@…>, on 08/01/17 at 12:43:41

Import wpa from FreeBSD

  • Property mode set to 100644
File size: 6.9 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Wi-Fi Protected Setup - attribute processing
5 * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
6 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11#include "includes.h"
12
13#include "common.h"
14#include "crypto/sha256.h"
15#include "wps_i.h"
16
17
18int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
19                              const struct wpabuf *msg)
20{
21        u8 hash[SHA256_MAC_LEN];
22        const u8 *addr[2];
23        size_t len[2];
24
25        if (authenticator == NULL) {
26                wpa_printf(MSG_DEBUG, "WPS: No Authenticator attribute "
27                           "included");
28                return -1;
29        }
30
31        if (wps->last_msg == NULL) {
32                wpa_printf(MSG_DEBUG, "WPS: Last message not available for "
33                           "validating authenticator");
34                return -1;
35        }
36
37        /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*)
38         * (M_curr* is M_curr without the Authenticator attribute)
39         */
40        addr[0] = wpabuf_head(wps->last_msg);
41        len[0] = wpabuf_len(wps->last_msg);
42        addr[1] = wpabuf_head(msg);
43        len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN;
44        hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
45
46        if (os_memcmp_const(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) {
47                wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator");
48                return -1;
49        }
50
51        return 0;
52}
53
54
55int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg,
56                              const u8 *key_wrap_auth)
57{
58        u8 hash[SHA256_MAC_LEN];
59        const u8 *head;
60        size_t len;
61
62        if (key_wrap_auth == NULL) {
63                wpa_printf(MSG_DEBUG, "WPS: No KWA in decrypted attribute");
64                return -1;
65        }
66
67        head = wpabuf_head(msg);
68        len = wpabuf_len(msg) - 4 - WPS_KWA_LEN;
69        if (head + len != key_wrap_auth - 4) {
70                wpa_printf(MSG_DEBUG, "WPS: KWA not in the end of the "
71                           "decrypted attribute");
72                return -1;
73        }
74
75        hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash);
76        if (os_memcmp_const(hash, key_wrap_auth, WPS_KWA_LEN) != 0) {
77                wpa_printf(MSG_DEBUG, "WPS: Invalid KWA");
78                return -1;
79        }
80
81        return 0;
82}
83
84
85static int wps_process_cred_network_idx(struct wps_credential *cred,
86                                        const u8 *idx)
87{
88        if (idx == NULL) {
89                wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
90                           "Network Index");
91                return -1;
92        }
93
94        wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx);
95
96        return 0;
97}
98
99
100static int wps_process_cred_ssid(struct wps_credential *cred, const u8 *ssid,
101                                 size_t ssid_len)
102{
103        if (ssid == NULL) {
104                wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID");
105                return -1;
106        }
107
108        /* Remove zero-padding since some Registrar implementations seem to use
109         * hardcoded 32-octet length for this attribute */
110        while (ssid_len > 0 && ssid[ssid_len - 1] == 0)
111                ssid_len--;
112
113        wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", ssid, ssid_len);
114        if (ssid_len <= sizeof(cred->ssid)) {
115                os_memcpy(cred->ssid, ssid, ssid_len);
116                cred->ssid_len = ssid_len;
117        }
118
119        return 0;
120}
121
122
123static int wps_process_cred_auth_type(struct wps_credential *cred,
124                                      const u8 *auth_type)
125{
126        if (auth_type == NULL) {
127                wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
128                           "Authentication Type");
129                return -1;
130        }
131
132        cred->auth_type = WPA_GET_BE16(auth_type);
133        wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x",
134                   cred->auth_type);
135
136        return 0;
137}
138
139
140static int wps_process_cred_encr_type(struct wps_credential *cred,
141                                      const u8 *encr_type)
142{
143        if (encr_type == NULL) {
144                wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
145                           "Encryption Type");
146                return -1;
147        }
148
149        cred->encr_type = WPA_GET_BE16(encr_type);
150        wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x",
151                   cred->encr_type);
152
153        return 0;
154}
155
156
157static int wps_process_cred_network_key_idx(struct wps_credential *cred,
158                                            const u8 *key_idx)
159{
160        if (key_idx == NULL)
161                return 0; /* optional attribute */
162
163        wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx);
164        cred->key_idx = *key_idx;
165
166        return 0;
167}
168
169
170static int wps_process_cred_network_key(struct wps_credential *cred,
171                                        const u8 *key, size_t key_len)
172{
173        if (key == NULL) {
174                wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
175                           "Network Key");
176                if (cred->auth_type == WPS_AUTH_OPEN &&
177                    cred->encr_type == WPS_ENCR_NONE) {
178                        wpa_printf(MSG_DEBUG, "WPS: Workaround - Allow "
179                                   "missing mandatory Network Key attribute "
180                                   "for open network");
181                        return 0;
182                }
183                return -1;
184        }
185
186        wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", key, key_len);
187        if (key_len <= sizeof(cred->key)) {
188                os_memcpy(cred->key, key, key_len);
189                cred->key_len = key_len;
190        }
191
192        return 0;
193}
194
195
196static int wps_process_cred_mac_addr(struct wps_credential *cred,
197                                     const u8 *mac_addr)
198{
199        if (mac_addr == NULL) {
200                wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
201                           "MAC Address");
202                return -1;
203        }
204
205        wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr));
206        os_memcpy(cred->mac_addr, mac_addr, ETH_ALEN);
207
208        return 0;
209}
210
211
212static int wps_workaround_cred_key(struct wps_credential *cred)
213{
214        if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) &&
215            cred->key_len > 8 && cred->key_len < 64 &&
216            cred->key[cred->key_len - 1] == 0) {
217#ifdef CONFIG_WPS_STRICT
218                wpa_printf(MSG_INFO, "WPS: WPA/WPA2-Personal passphrase uses "
219                           "forbidden NULL termination");
220                wpa_hexdump_ascii_key(MSG_INFO, "WPS: Network Key",
221                                      cred->key, cred->key_len);
222                return -1;
223#else /* CONFIG_WPS_STRICT */
224                /*
225                 * A deployed external registrar is known to encode ASCII
226                 * passphrases incorrectly. Remove the extra NULL termination
227                 * to fix the encoding.
228                 */
229                wpa_printf(MSG_DEBUG, "WPS: Workaround - remove NULL "
230                           "termination from ASCII passphrase");
231                cred->key_len--;
232#endif /* CONFIG_WPS_STRICT */
233        }
234        return 0;
235}
236
237
238int wps_process_cred(struct wps_parse_attr *attr,
239                     struct wps_credential *cred)
240{
241        wpa_printf(MSG_DEBUG, "WPS: Process Credential");
242
243        /* TODO: support multiple Network Keys */
244        if (wps_process_cred_network_idx(cred, attr->network_idx) ||
245            wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) ||
246            wps_process_cred_auth_type(cred, attr->auth_type) ||
247            wps_process_cred_encr_type(cred, attr->encr_type) ||
248            wps_process_cred_network_key_idx(cred, attr->network_key_idx) ||
249            wps_process_cred_network_key(cred, attr->network_key,
250                                         attr->network_key_len) ||
251            wps_process_cred_mac_addr(cred, attr->mac_addr))
252                return -1;
253
254        return wps_workaround_cred_key(cred);
255}
256
257
258int wps_process_ap_settings(struct wps_parse_attr *attr,
259                            struct wps_credential *cred)
260{
261        wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings");
262        os_memset(cred, 0, sizeof(*cred));
263        /* TODO: optional attributes New Password and Device Password ID */
264        if (wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) ||
265            wps_process_cred_auth_type(cred, attr->auth_type) ||
266            wps_process_cred_encr_type(cred, attr->encr_type) ||
267            wps_process_cred_network_key_idx(cred, attr->network_key_idx) ||
268            wps_process_cred_network_key(cred, attr->network_key,
269                                         attr->network_key_len) ||
270            wps_process_cred_mac_addr(cred, attr->mac_addr))
271                return -1;
272
273        return wps_workaround_cred_key(cred);
274}
Note: See TracBrowser for help on using the repository browser.