source: rtems-libbsd/freebsd/contrib/wpa/src/wps/wps_attr_build.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: 12.7 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Wi-Fi Protected Setup - attribute building
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/aes_wrap.h"
15#include "crypto/crypto.h"
16#include "crypto/dh_group5.h"
17#include "crypto/sha256.h"
18#include "crypto/random.h"
19#include "common/ieee802_11_defs.h"
20#include "wps_i.h"
21
22
23int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
24{
25        struct wpabuf *pubkey;
26
27        wpa_printf(MSG_DEBUG, "WPS:  * Public Key");
28        wpabuf_free(wps->dh_privkey);
29        wps->dh_privkey = NULL;
30        if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey &&
31            wps->wps->dh_ctx) {
32                wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys");
33                if (wps->wps->dh_pubkey == NULL) {
34                        wpa_printf(MSG_DEBUG,
35                                   "WPS: wps->wps->dh_pubkey == NULL");
36                        return -1;
37                }
38                wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey);
39                wps->dh_ctx = wps->wps->dh_ctx;
40                wps->wps->dh_ctx = NULL;
41                pubkey = wpabuf_dup(wps->wps->dh_pubkey);
42#ifdef CONFIG_WPS_NFC
43        } else if ((wps->dev_pw_id >= 0x10 ||
44                    wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) &&
45                   (wps->wps->ap ||
46                    (wps->wps->ap_nfc_dh_pubkey &&
47                     wps->wps->ap_nfc_dev_pw_id ==
48                     DEV_PW_NFC_CONNECTION_HANDOVER &&
49                     wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)) &&
50                   (wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id ||
51                    wps->wps->ap_nfc_dh_pubkey)) {
52                wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys");
53                if (wps->wps->ap_nfc_dh_privkey == NULL) {
54                        wpa_printf(MSG_DEBUG,
55                                   "WPS: wps->wps->ap_nfc_dh_privkey == NULL");
56                        return -1;
57                }
58                if (wps->wps->ap_nfc_dh_pubkey == NULL) {
59                        wpa_printf(MSG_DEBUG,
60                                   "WPS: wps->wps->ap_nfc_dh_pubkey == NULL");
61                        return -1;
62                }
63                wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey);
64                pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey);
65                wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey);
66#endif /* CONFIG_WPS_NFC */
67        } else {
68                wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys");
69                dh5_free(wps->dh_ctx);
70                wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey);
71                pubkey = wpabuf_zeropad(pubkey, 192);
72        }
73        if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) {
74                wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
75                           "Diffie-Hellman handshake");
76                wpabuf_free(pubkey);
77                return -1;
78        }
79        wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey);
80        wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey);
81
82        wpabuf_put_be16(msg, ATTR_PUBLIC_KEY);
83        wpabuf_put_be16(msg, wpabuf_len(pubkey));
84        wpabuf_put_buf(msg, pubkey);
85
86        if (wps->registrar) {
87                wpabuf_free(wps->dh_pubkey_r);
88                wps->dh_pubkey_r = pubkey;
89        } else {
90                wpabuf_free(wps->dh_pubkey_e);
91                wps->dh_pubkey_e = pubkey;
92        }
93
94        return 0;
95}
96
97
98int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type)
99{
100        wpa_printf(MSG_DEBUG, "WPS:  * Request Type");
101        wpabuf_put_be16(msg, ATTR_REQUEST_TYPE);
102        wpabuf_put_be16(msg, 1);
103        wpabuf_put_u8(msg, type);
104        return 0;
105}
106
107
108int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type)
109{
110        wpa_printf(MSG_DEBUG, "WPS:  * Response Type (%d)", type);
111        wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE);
112        wpabuf_put_be16(msg, 1);
113        wpabuf_put_u8(msg, type);
114        return 0;
115}
116
117
118int wps_build_config_methods(struct wpabuf *msg, u16 methods)
119{
120        wpa_printf(MSG_DEBUG, "WPS:  * Config Methods (%x)", methods);
121        wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
122        wpabuf_put_be16(msg, 2);
123        wpabuf_put_be16(msg, methods);
124        return 0;
125}
126
127
128int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid)
129{
130        if (wpabuf_tailroom(msg) < 4 + WPS_UUID_LEN)
131                return -1;
132        wpa_printf(MSG_DEBUG, "WPS:  * UUID-E");
133        wpabuf_put_be16(msg, ATTR_UUID_E);
134        wpabuf_put_be16(msg, WPS_UUID_LEN);
135        wpabuf_put_data(msg, uuid, WPS_UUID_LEN);
136        return 0;
137}
138
139
140int wps_build_dev_password_id(struct wpabuf *msg, u16 id)
141{
142        wpa_printf(MSG_DEBUG, "WPS:  * Device Password ID (%d)", id);
143        wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
144        wpabuf_put_be16(msg, 2);
145        wpabuf_put_be16(msg, id);
146        return 0;
147}
148
149
150int wps_build_config_error(struct wpabuf *msg, u16 err)
151{
152        wpa_printf(MSG_DEBUG, "WPS:  * Configuration Error (%d)", err);
153        wpabuf_put_be16(msg, ATTR_CONFIG_ERROR);
154        wpabuf_put_be16(msg, 2);
155        wpabuf_put_be16(msg, err);
156        return 0;
157}
158
159
160int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg)
161{
162        u8 hash[SHA256_MAC_LEN];
163        const u8 *addr[2];
164        size_t len[2];
165
166        if (wps->last_msg == NULL) {
167                wpa_printf(MSG_DEBUG, "WPS: Last message not available for "
168                           "building authenticator");
169                return -1;
170        }
171
172        /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*)
173         * (M_curr* is M_curr without the Authenticator attribute)
174         */
175        addr[0] = wpabuf_head(wps->last_msg);
176        len[0] = wpabuf_len(wps->last_msg);
177        addr[1] = wpabuf_head(msg);
178        len[1] = wpabuf_len(msg);
179        hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
180
181        wpa_printf(MSG_DEBUG, "WPS:  * Authenticator");
182        wpabuf_put_be16(msg, ATTR_AUTHENTICATOR);
183        wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN);
184        wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN);
185
186        return 0;
187}
188
189
190int wps_build_version(struct wpabuf *msg)
191{
192        /*
193         * Note: This attribute is deprecated and set to hardcoded 0x10 for
194         * backwards compatibility reasons. The real version negotiation is
195         * done with Version2.
196         */
197        if (wpabuf_tailroom(msg) < 5)
198                return -1;
199        wpa_printf(MSG_DEBUG, "WPS:  * Version (hardcoded 0x10)");
200        wpabuf_put_be16(msg, ATTR_VERSION);
201        wpabuf_put_be16(msg, 1);
202        wpabuf_put_u8(msg, 0x10);
203        return 0;
204}
205
206
207int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
208                      const u8 *auth_macs, size_t auth_macs_count)
209{
210        u8 *len;
211
212#ifdef CONFIG_WPS_TESTING
213        if (WPS_VERSION == 0x10)
214                return 0;
215#endif /* CONFIG_WPS_TESTING */
216
217        if (wpabuf_tailroom(msg) <
218            7 + 3 + (req_to_enroll ? 3 : 0) +
219            (auth_macs ? 2 + auth_macs_count * ETH_ALEN : 0))
220                return -1;
221        wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
222        len = wpabuf_put(msg, 2); /* to be filled */
223        wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA);
224
225        wpa_printf(MSG_DEBUG, "WPS:  * Version2 (0x%x)", WPS_VERSION);
226        wpabuf_put_u8(msg, WFA_ELEM_VERSION2);
227        wpabuf_put_u8(msg, 1);
228        wpabuf_put_u8(msg, WPS_VERSION);
229
230        if (req_to_enroll) {
231                wpa_printf(MSG_DEBUG, "WPS:  * Request to Enroll (1)");
232                wpabuf_put_u8(msg, WFA_ELEM_REQUEST_TO_ENROLL);
233                wpabuf_put_u8(msg, 1);
234                wpabuf_put_u8(msg, 1);
235        }
236
237        if (auth_macs && auth_macs_count) {
238                size_t i;
239                wpa_printf(MSG_DEBUG, "WPS:  * AuthorizedMACs (count=%d)",
240                           (int) auth_macs_count);
241                wpabuf_put_u8(msg, WFA_ELEM_AUTHORIZEDMACS);
242                wpabuf_put_u8(msg, auth_macs_count * ETH_ALEN);
243                wpabuf_put_data(msg, auth_macs, auth_macs_count * ETH_ALEN);
244                for (i = 0; i < auth_macs_count; i++)
245                        wpa_printf(MSG_DEBUG, "WPS:    AuthorizedMAC: " MACSTR,
246                                   MAC2STR(&auth_macs[i * ETH_ALEN]));
247        }
248
249        WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2);
250
251#ifdef CONFIG_WPS_TESTING
252        if (WPS_VERSION > 0x20) {
253                if (wpabuf_tailroom(msg) < 5)
254                        return -1;
255                wpa_printf(MSG_DEBUG, "WPS:  * Extensibility Testing - extra "
256                           "attribute");
257                wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST);
258                wpabuf_put_be16(msg, 1);
259                wpabuf_put_u8(msg, 42);
260        }
261#endif /* CONFIG_WPS_TESTING */
262        return 0;
263}
264
265
266int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type)
267{
268        wpa_printf(MSG_DEBUG, "WPS:  * Message Type (%d)", msg_type);
269        wpabuf_put_be16(msg, ATTR_MSG_TYPE);
270        wpabuf_put_be16(msg, 1);
271        wpabuf_put_u8(msg, msg_type);
272        return 0;
273}
274
275
276int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg)
277{
278        wpa_printf(MSG_DEBUG, "WPS:  * Enrollee Nonce");
279        wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE);
280        wpabuf_put_be16(msg, WPS_NONCE_LEN);
281        wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN);
282        return 0;
283}
284
285
286int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg)
287{
288        wpa_printf(MSG_DEBUG, "WPS:  * Registrar Nonce");
289        wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
290        wpabuf_put_be16(msg, WPS_NONCE_LEN);
291        wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN);
292        return 0;
293}
294
295
296int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg)
297{
298        u16 auth_types = WPS_AUTH_TYPES;
299        /* WPA/WPA2-Enterprise enrollment not supported through WPS */
300        auth_types &= ~WPS_AUTH_WPA;
301        auth_types &= ~WPS_AUTH_WPA2;
302        auth_types &= ~WPS_AUTH_SHARED;
303        wpa_printf(MSG_DEBUG, "WPS:  * Authentication Type Flags");
304        wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS);
305        wpabuf_put_be16(msg, 2);
306        wpabuf_put_be16(msg, auth_types);
307        return 0;
308}
309
310
311int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg)
312{
313        u16 encr_types = WPS_ENCR_TYPES;
314        encr_types &= ~WPS_ENCR_WEP;
315        wpa_printf(MSG_DEBUG, "WPS:  * Encryption Type Flags");
316        wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS);
317        wpabuf_put_be16(msg, 2);
318        wpabuf_put_be16(msg, encr_types);
319        return 0;
320}
321
322
323int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg)
324{
325        wpa_printf(MSG_DEBUG, "WPS:  * Connection Type Flags");
326        wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS);
327        wpabuf_put_be16(msg, 1);
328        wpabuf_put_u8(msg, WPS_CONN_ESS);
329        return 0;
330}
331
332
333int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg)
334{
335        wpa_printf(MSG_DEBUG, "WPS:  * Association State");
336        wpabuf_put_be16(msg, ATTR_ASSOC_STATE);
337        wpabuf_put_be16(msg, 2);
338        wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC);
339        return 0;
340}
341
342
343int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg)
344{
345        u8 hash[SHA256_MAC_LEN];
346
347        wpa_printf(MSG_DEBUG, "WPS:  * Key Wrap Authenticator");
348        hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg),
349                    wpabuf_len(msg), hash);
350
351        wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH);
352        wpabuf_put_be16(msg, WPS_KWA_LEN);
353        wpabuf_put_data(msg, hash, WPS_KWA_LEN);
354        return 0;
355}
356
357
358int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
359                            struct wpabuf *plain)
360{
361        size_t pad_len;
362        const size_t block_size = 16;
363        u8 *iv, *data;
364
365        wpa_printf(MSG_DEBUG, "WPS:  * Encrypted Settings");
366
367        /* PKCS#5 v2.0 pad */
368        pad_len = block_size - wpabuf_len(plain) % block_size;
369        os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len);
370
371        wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS);
372        wpabuf_put_be16(msg, block_size + wpabuf_len(plain));
373
374        iv = wpabuf_put(msg, block_size);
375        if (random_get_bytes(iv, block_size) < 0)
376                return -1;
377
378        data = wpabuf_put(msg, 0);
379        wpabuf_put_buf(msg, plain);
380        if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain)))
381                return -1;
382
383        return 0;
384}
385
386
387#ifdef CONFIG_WPS_OOB
388int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id,
389                         const struct wpabuf *pubkey, const u8 *dev_pw,
390                         size_t dev_pw_len)
391{
392        size_t hash_len;
393        const u8 *addr[1];
394        u8 pubkey_hash[WPS_HASH_LEN];
395
396        wpa_printf(MSG_DEBUG, "WPS:  * OOB Device Password (dev_pw_id=%u)",
397                   dev_pw_id);
398        addr[0] = wpabuf_head(pubkey);
399        hash_len = wpabuf_len(pubkey);
400        sha256_vector(1, addr, &hash_len, pubkey_hash);
401#ifdef CONFIG_WPS_TESTING
402        if (wps_corrupt_pkhash) {
403                wpa_hexdump(MSG_DEBUG, "WPS: Real Public Key Hash",
404                            pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
405                wpa_printf(MSG_INFO, "WPS: Testing - corrupt public key hash");
406                pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN - 2]++;
407        }
408#endif /* CONFIG_WPS_TESTING */
409
410        wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD);
411        wpabuf_put_be16(msg, WPS_OOB_PUBKEY_HASH_LEN + 2 + dev_pw_len);
412        wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash",
413                    pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
414        wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
415        wpabuf_put_be16(msg, dev_pw_id);
416        if (dev_pw) {
417                wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password",
418                                dev_pw, dev_pw_len);
419                wpabuf_put_data(msg, dev_pw, dev_pw_len);
420        }
421
422        return 0;
423}
424#endif /* CONFIG_WPS_OOB */
425
426
427/* Encapsulate WPS IE data with one (or more, if needed) IE headers */
428struct wpabuf * wps_ie_encapsulate(struct wpabuf *data)
429{
430        struct wpabuf *ie;
431        const u8 *pos, *end;
432
433        ie = wpabuf_alloc(wpabuf_len(data) + 100);
434        if (ie == NULL) {
435                wpabuf_free(data);
436                return NULL;
437        }
438
439        pos = wpabuf_head(data);
440        end = pos + wpabuf_len(data);
441
442        while (end > pos) {
443                size_t frag_len = end - pos;
444                if (frag_len > 251)
445                        frag_len = 251;
446                wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
447                wpabuf_put_u8(ie, 4 + frag_len);
448                wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
449                wpabuf_put_data(ie, pos, frag_len);
450                pos += frag_len;
451        }
452
453        wpabuf_free(data);
454
455        return ie;
456}
457
458
459int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr)
460{
461        wpa_printf(MSG_DEBUG, "WPS:  * MAC Address (" MACSTR ")",
462                   MAC2STR(addr));
463        wpabuf_put_be16(msg, ATTR_MAC_ADDR);
464        wpabuf_put_be16(msg, ETH_ALEN);
465        wpabuf_put_data(msg, addr, ETH_ALEN);
466        return 0;
467}
468
469
470int wps_build_rf_bands_attr(struct wpabuf *msg, u8 rf_bands)
471{
472        wpa_printf(MSG_DEBUG, "WPS:  * RF Bands (%x)", rf_bands);
473        wpabuf_put_be16(msg, ATTR_RF_BANDS);
474        wpabuf_put_be16(msg, 1);
475        wpabuf_put_u8(msg, rf_bands);
476        return 0;
477}
478
479
480int wps_build_ap_channel(struct wpabuf *msg, u16 ap_channel)
481{
482        wpa_printf(MSG_DEBUG, "WPS:  * AP Channel (%u)", ap_channel);
483        wpabuf_put_be16(msg, ATTR_AP_CHANNEL);
484        wpabuf_put_be16(msg, 2);
485        wpabuf_put_be16(msg, ap_channel);
486        return 0;
487}
Note: See TracBrowser for help on using the repository browser.