2 * Wi-Fi Protected Setup - attribute building
3 * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "crypto/aes_wrap.h"
13 #include "crypto/crypto.h"
14 #include "crypto/dh_group5.h"
15 #include "crypto/sha256.h"
16 #include "crypto/random.h"
17 #include "common/ieee802_11_defs.h"
21 int wps_build_public_key(struct wps_data
*wps
, struct wpabuf
*msg
)
23 struct wpabuf
*pubkey
;
25 wpa_printf(MSG_DEBUG
, "WPS: * Public Key");
26 wpabuf_free(wps
->dh_privkey
);
27 wps
->dh_privkey
= NULL
;
28 if (wps
->dev_pw_id
!= DEV_PW_DEFAULT
&& wps
->wps
->dh_privkey
&&
30 wpa_printf(MSG_DEBUG
, "WPS: Using pre-configured DH keys");
31 if (wps
->wps
->dh_pubkey
== NULL
) {
33 "WPS: wps->wps->dh_pubkey == NULL");
36 wps
->dh_privkey
= wpabuf_dup(wps
->wps
->dh_privkey
);
37 wps
->dh_ctx
= wps
->wps
->dh_ctx
;
38 wps
->wps
->dh_ctx
= NULL
;
39 pubkey
= wpabuf_dup(wps
->wps
->dh_pubkey
);
41 } else if ((wps
->dev_pw_id
>= 0x10 ||
42 wps
->dev_pw_id
== DEV_PW_NFC_CONNECTION_HANDOVER
) &&
44 (wps
->wps
->ap_nfc_dh_pubkey
&&
45 wps
->wps
->ap_nfc_dev_pw_id
==
46 DEV_PW_NFC_CONNECTION_HANDOVER
&&
47 wps
->dev_pw_id
== DEV_PW_NFC_CONNECTION_HANDOVER
)) &&
48 (wps
->dev_pw_id
== wps
->wps
->ap_nfc_dev_pw_id
||
49 wps
->wps
->ap_nfc_dh_pubkey
)) {
50 wpa_printf(MSG_DEBUG
, "WPS: Using NFC password token DH keys");
51 if (wps
->wps
->ap_nfc_dh_privkey
== NULL
) {
53 "WPS: wps->wps->ap_nfc_dh_privkey == NULL");
56 if (wps
->wps
->ap_nfc_dh_pubkey
== NULL
) {
58 "WPS: wps->wps->ap_nfc_dh_pubkey == NULL");
61 wps
->dh_privkey
= wpabuf_dup(wps
->wps
->ap_nfc_dh_privkey
);
62 pubkey
= wpabuf_dup(wps
->wps
->ap_nfc_dh_pubkey
);
63 wps
->dh_ctx
= dh5_init_fixed(wps
->dh_privkey
, pubkey
);
64 #endif /* CONFIG_WPS_NFC */
66 wpa_printf(MSG_DEBUG
, "WPS: Generate new DH keys");
67 dh5_free(wps
->dh_ctx
);
68 wps
->dh_ctx
= dh5_init(&wps
->dh_privkey
, &pubkey
);
69 pubkey
= wpabuf_zeropad(pubkey
, 192);
71 if (wps
->dh_ctx
== NULL
|| wps
->dh_privkey
== NULL
|| pubkey
== NULL
) {
72 wpa_printf(MSG_DEBUG
, "WPS: Failed to initialize "
73 "Diffie-Hellman handshake");
77 wpa_hexdump_buf_key(MSG_DEBUG
, "WPS: DH Private Key", wps
->dh_privkey
);
78 wpa_hexdump_buf(MSG_DEBUG
, "WPS: DH own Public Key", pubkey
);
80 wpabuf_put_be16(msg
, ATTR_PUBLIC_KEY
);
81 wpabuf_put_be16(msg
, wpabuf_len(pubkey
));
82 wpabuf_put_buf(msg
, pubkey
);
85 wpabuf_free(wps
->dh_pubkey_r
);
86 wps
->dh_pubkey_r
= pubkey
;
88 wpabuf_free(wps
->dh_pubkey_e
);
89 wps
->dh_pubkey_e
= pubkey
;
96 int wps_build_req_type(struct wpabuf
*msg
, enum wps_request_type type
)
98 wpa_printf(MSG_DEBUG
, "WPS: * Request Type");
99 wpabuf_put_be16(msg
, ATTR_REQUEST_TYPE
);
100 wpabuf_put_be16(msg
, 1);
101 wpabuf_put_u8(msg
, type
);
106 int wps_build_resp_type(struct wpabuf
*msg
, enum wps_response_type type
)
108 wpa_printf(MSG_DEBUG
, "WPS: * Response Type (%d)", type
);
109 wpabuf_put_be16(msg
, ATTR_RESPONSE_TYPE
);
110 wpabuf_put_be16(msg
, 1);
111 wpabuf_put_u8(msg
, type
);
116 int wps_build_config_methods(struct wpabuf
*msg
, u16 methods
)
118 wpa_printf(MSG_DEBUG
, "WPS: * Config Methods (%x)", methods
);
119 wpabuf_put_be16(msg
, ATTR_CONFIG_METHODS
);
120 wpabuf_put_be16(msg
, 2);
121 wpabuf_put_be16(msg
, methods
);
126 int wps_build_uuid_e(struct wpabuf
*msg
, const u8
*uuid
)
128 if (wpabuf_tailroom(msg
) < 4 + WPS_UUID_LEN
)
130 wpa_printf(MSG_DEBUG
, "WPS: * UUID-E");
131 wpabuf_put_be16(msg
, ATTR_UUID_E
);
132 wpabuf_put_be16(msg
, WPS_UUID_LEN
);
133 wpabuf_put_data(msg
, uuid
, WPS_UUID_LEN
);
138 int wps_build_dev_password_id(struct wpabuf
*msg
, u16 id
)
140 wpa_printf(MSG_DEBUG
, "WPS: * Device Password ID (%d)", id
);
141 wpabuf_put_be16(msg
, ATTR_DEV_PASSWORD_ID
);
142 wpabuf_put_be16(msg
, 2);
143 wpabuf_put_be16(msg
, id
);
148 int wps_build_config_error(struct wpabuf
*msg
, u16 err
)
150 wpa_printf(MSG_DEBUG
, "WPS: * Configuration Error (%d)", err
);
151 wpabuf_put_be16(msg
, ATTR_CONFIG_ERROR
);
152 wpabuf_put_be16(msg
, 2);
153 wpabuf_put_be16(msg
, err
);
158 int wps_build_authenticator(struct wps_data
*wps
, struct wpabuf
*msg
)
160 u8 hash
[SHA256_MAC_LEN
];
164 if (wps
->last_msg
== NULL
) {
165 wpa_printf(MSG_DEBUG
, "WPS: Last message not available for "
166 "building authenticator");
170 /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*)
171 * (M_curr* is M_curr without the Authenticator attribute)
173 addr
[0] = wpabuf_head(wps
->last_msg
);
174 len
[0] = wpabuf_len(wps
->last_msg
);
175 addr
[1] = wpabuf_head(msg
);
176 len
[1] = wpabuf_len(msg
);
177 hmac_sha256_vector(wps
->authkey
, WPS_AUTHKEY_LEN
, 2, addr
, len
, hash
);
179 wpa_printf(MSG_DEBUG
, "WPS: * Authenticator");
180 wpabuf_put_be16(msg
, ATTR_AUTHENTICATOR
);
181 wpabuf_put_be16(msg
, WPS_AUTHENTICATOR_LEN
);
182 wpabuf_put_data(msg
, hash
, WPS_AUTHENTICATOR_LEN
);
188 int wps_build_version(struct wpabuf
*msg
)
191 * Note: This attribute is deprecated and set to hardcoded 0x10 for
192 * backwards compatibility reasons. The real version negotiation is
193 * done with Version2.
195 if (wpabuf_tailroom(msg
) < 5)
197 wpa_printf(MSG_DEBUG
, "WPS: * Version (hardcoded 0x10)");
198 wpabuf_put_be16(msg
, ATTR_VERSION
);
199 wpabuf_put_be16(msg
, 1);
200 wpabuf_put_u8(msg
, 0x10);
205 int wps_build_wfa_ext(struct wpabuf
*msg
, int req_to_enroll
,
206 const u8
*auth_macs
, size_t auth_macs_count
)
210 #ifdef CONFIG_WPS_TESTING
211 if (WPS_VERSION
== 0x10)
213 #endif /* CONFIG_WPS_TESTING */
215 if (wpabuf_tailroom(msg
) <
216 7 + 3 + (req_to_enroll
? 3 : 0) +
217 (auth_macs
? 2 + auth_macs_count
* ETH_ALEN
: 0))
219 wpabuf_put_be16(msg
, ATTR_VENDOR_EXT
);
220 len
= wpabuf_put(msg
, 2); /* to be filled */
221 wpabuf_put_be24(msg
, WPS_VENDOR_ID_WFA
);
223 wpa_printf(MSG_DEBUG
, "WPS: * Version2 (0x%x)", WPS_VERSION
);
224 wpabuf_put_u8(msg
, WFA_ELEM_VERSION2
);
225 wpabuf_put_u8(msg
, 1);
226 wpabuf_put_u8(msg
, WPS_VERSION
);
229 wpa_printf(MSG_DEBUG
, "WPS: * Request to Enroll (1)");
230 wpabuf_put_u8(msg
, WFA_ELEM_REQUEST_TO_ENROLL
);
231 wpabuf_put_u8(msg
, 1);
232 wpabuf_put_u8(msg
, 1);
235 if (auth_macs
&& auth_macs_count
) {
237 wpa_printf(MSG_DEBUG
, "WPS: * AuthorizedMACs (count=%d)",
238 (int) auth_macs_count
);
239 wpabuf_put_u8(msg
, WFA_ELEM_AUTHORIZEDMACS
);
240 wpabuf_put_u8(msg
, auth_macs_count
* ETH_ALEN
);
241 wpabuf_put_data(msg
, auth_macs
, auth_macs_count
* ETH_ALEN
);
242 for (i
= 0; i
< auth_macs_count
; i
++)
243 wpa_printf(MSG_DEBUG
, "WPS: AuthorizedMAC: " MACSTR
,
244 MAC2STR(&auth_macs
[i
* ETH_ALEN
]));
247 WPA_PUT_BE16(len
, (u8
*) wpabuf_put(msg
, 0) - len
- 2);
249 #ifdef CONFIG_WPS_TESTING
250 if (WPS_VERSION
> 0x20) {
251 if (wpabuf_tailroom(msg
) < 5)
253 wpa_printf(MSG_DEBUG
, "WPS: * Extensibility Testing - extra "
255 wpabuf_put_be16(msg
, ATTR_EXTENSIBILITY_TEST
);
256 wpabuf_put_be16(msg
, 1);
257 wpabuf_put_u8(msg
, 42);
259 #endif /* CONFIG_WPS_TESTING */
264 int wps_build_msg_type(struct wpabuf
*msg
, enum wps_msg_type msg_type
)
266 wpa_printf(MSG_DEBUG
, "WPS: * Message Type (%d)", msg_type
);
267 wpabuf_put_be16(msg
, ATTR_MSG_TYPE
);
268 wpabuf_put_be16(msg
, 1);
269 wpabuf_put_u8(msg
, msg_type
);
274 int wps_build_enrollee_nonce(struct wps_data
*wps
, struct wpabuf
*msg
)
276 wpa_printf(MSG_DEBUG
, "WPS: * Enrollee Nonce");
277 wpabuf_put_be16(msg
, ATTR_ENROLLEE_NONCE
);
278 wpabuf_put_be16(msg
, WPS_NONCE_LEN
);
279 wpabuf_put_data(msg
, wps
->nonce_e
, WPS_NONCE_LEN
);
284 int wps_build_registrar_nonce(struct wps_data
*wps
, struct wpabuf
*msg
)
286 wpa_printf(MSG_DEBUG
, "WPS: * Registrar Nonce");
287 wpabuf_put_be16(msg
, ATTR_REGISTRAR_NONCE
);
288 wpabuf_put_be16(msg
, WPS_NONCE_LEN
);
289 wpabuf_put_data(msg
, wps
->nonce_r
, WPS_NONCE_LEN
);
294 int wps_build_auth_type_flags(struct wps_data
*wps
, struct wpabuf
*msg
)
296 u16 auth_types
= WPS_AUTH_TYPES
;
297 /* WPA/WPA2-Enterprise enrollment not supported through WPS */
298 auth_types
&= ~WPS_AUTH_WPA
;
299 auth_types
&= ~WPS_AUTH_WPA2
;
300 auth_types
&= ~WPS_AUTH_SHARED
;
301 wpa_printf(MSG_DEBUG
, "WPS: * Authentication Type Flags");
302 wpabuf_put_be16(msg
, ATTR_AUTH_TYPE_FLAGS
);
303 wpabuf_put_be16(msg
, 2);
304 wpabuf_put_be16(msg
, auth_types
);
309 int wps_build_encr_type_flags(struct wps_data
*wps
, struct wpabuf
*msg
)
311 u16 encr_types
= WPS_ENCR_TYPES
;
312 encr_types
&= ~WPS_ENCR_WEP
;
313 wpa_printf(MSG_DEBUG
, "WPS: * Encryption Type Flags");
314 wpabuf_put_be16(msg
, ATTR_ENCR_TYPE_FLAGS
);
315 wpabuf_put_be16(msg
, 2);
316 wpabuf_put_be16(msg
, encr_types
);
321 int wps_build_conn_type_flags(struct wps_data
*wps
, struct wpabuf
*msg
)
323 wpa_printf(MSG_DEBUG
, "WPS: * Connection Type Flags");
324 wpabuf_put_be16(msg
, ATTR_CONN_TYPE_FLAGS
);
325 wpabuf_put_be16(msg
, 1);
326 wpabuf_put_u8(msg
, WPS_CONN_ESS
);
331 int wps_build_assoc_state(struct wps_data
*wps
, struct wpabuf
*msg
)
333 wpa_printf(MSG_DEBUG
, "WPS: * Association State");
334 wpabuf_put_be16(msg
, ATTR_ASSOC_STATE
);
335 wpabuf_put_be16(msg
, 2);
336 wpabuf_put_be16(msg
, WPS_ASSOC_NOT_ASSOC
);
341 int wps_build_key_wrap_auth(struct wps_data
*wps
, struct wpabuf
*msg
)
343 u8 hash
[SHA256_MAC_LEN
];
345 wpa_printf(MSG_DEBUG
, "WPS: * Key Wrap Authenticator");
346 hmac_sha256(wps
->authkey
, WPS_AUTHKEY_LEN
, wpabuf_head(msg
),
347 wpabuf_len(msg
), hash
);
349 wpabuf_put_be16(msg
, ATTR_KEY_WRAP_AUTH
);
350 wpabuf_put_be16(msg
, WPS_KWA_LEN
);
351 wpabuf_put_data(msg
, hash
, WPS_KWA_LEN
);
356 int wps_build_encr_settings(struct wps_data
*wps
, struct wpabuf
*msg
,
357 struct wpabuf
*plain
)
360 const size_t block_size
= 16;
363 wpa_printf(MSG_DEBUG
, "WPS: * Encrypted Settings");
365 /* PKCS#5 v2.0 pad */
366 pad_len
= block_size
- wpabuf_len(plain
) % block_size
;
367 os_memset(wpabuf_put(plain
, pad_len
), pad_len
, pad_len
);
369 wpabuf_put_be16(msg
, ATTR_ENCR_SETTINGS
);
370 wpabuf_put_be16(msg
, block_size
+ wpabuf_len(plain
));
372 iv
= wpabuf_put(msg
, block_size
);
373 if (random_get_bytes(iv
, block_size
) < 0)
376 data
= wpabuf_put(msg
, 0);
377 wpabuf_put_buf(msg
, plain
);
378 if (aes_128_cbc_encrypt(wps
->keywrapkey
, iv
, data
, wpabuf_len(plain
)))
385 #ifdef CONFIG_WPS_OOB
386 int wps_build_oob_dev_pw(struct wpabuf
*msg
, u16 dev_pw_id
,
387 const struct wpabuf
*pubkey
, const u8
*dev_pw
,
392 u8 pubkey_hash
[WPS_HASH_LEN
];
394 wpa_printf(MSG_DEBUG
, "WPS: * OOB Device Password (dev_pw_id=%u)",
396 addr
[0] = wpabuf_head(pubkey
);
397 hash_len
= wpabuf_len(pubkey
);
398 sha256_vector(1, addr
, &hash_len
, pubkey_hash
);
399 #ifdef CONFIG_WPS_TESTING
400 if (wps_corrupt_pkhash
) {
401 wpa_hexdump(MSG_DEBUG
, "WPS: Real Public Key Hash",
402 pubkey_hash
, WPS_OOB_PUBKEY_HASH_LEN
);
403 wpa_printf(MSG_INFO
, "WPS: Testing - corrupt public key hash");
404 pubkey_hash
[WPS_OOB_PUBKEY_HASH_LEN
- 2]++;
406 #endif /* CONFIG_WPS_TESTING */
408 wpabuf_put_be16(msg
, ATTR_OOB_DEVICE_PASSWORD
);
409 wpabuf_put_be16(msg
, WPS_OOB_PUBKEY_HASH_LEN
+ 2 + dev_pw_len
);
410 wpa_hexdump(MSG_DEBUG
, "WPS: Public Key Hash",
411 pubkey_hash
, WPS_OOB_PUBKEY_HASH_LEN
);
412 wpabuf_put_data(msg
, pubkey_hash
, WPS_OOB_PUBKEY_HASH_LEN
);
413 wpabuf_put_be16(msg
, dev_pw_id
);
415 wpa_hexdump_key(MSG_DEBUG
, "WPS: OOB Device Password",
417 wpabuf_put_data(msg
, dev_pw
, dev_pw_len
);
422 #endif /* CONFIG_WPS_OOB */
425 /* Encapsulate WPS IE data with one (or more, if needed) IE headers */
426 struct wpabuf
* wps_ie_encapsulate(struct wpabuf
*data
)
431 ie
= wpabuf_alloc(wpabuf_len(data
) + 100);
437 pos
= wpabuf_head(data
);
438 end
= pos
+ wpabuf_len(data
);
441 size_t frag_len
= end
- pos
;
444 wpabuf_put_u8(ie
, WLAN_EID_VENDOR_SPECIFIC
);
445 wpabuf_put_u8(ie
, 4 + frag_len
);
446 wpabuf_put_be32(ie
, WPS_DEV_OUI_WFA
);
447 wpabuf_put_data(ie
, pos
, frag_len
);
457 int wps_build_mac_addr(struct wpabuf
*msg
, const u8
*addr
)
459 wpa_printf(MSG_DEBUG
, "WPS: * MAC Address (" MACSTR
")",
461 wpabuf_put_be16(msg
, ATTR_MAC_ADDR
);
462 wpabuf_put_be16(msg
, ETH_ALEN
);
463 wpabuf_put_data(msg
, addr
, ETH_ALEN
);
468 int wps_build_rf_bands_attr(struct wpabuf
*msg
, u8 rf_bands
)
470 wpa_printf(MSG_DEBUG
, "WPS: * RF Bands (%x)", rf_bands
);
471 wpabuf_put_be16(msg
, ATTR_RF_BANDS
);
472 wpabuf_put_be16(msg
, 1);
473 wpabuf_put_u8(msg
, rf_bands
);
478 int wps_build_ap_channel(struct wpabuf
*msg
, u16 ap_channel
)
480 wpa_printf(MSG_DEBUG
, "WPS: * AP Channel (%u)", ap_channel
);
481 wpabuf_put_be16(msg
, ATTR_AP_CHANNEL
);
482 wpabuf_put_be16(msg
, 2);
483 wpabuf_put_be16(msg
, ap_channel
);