2 * Wi-Fi Protected Setup - Enrollee
3 * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
19 #include "ieee802_11_defs.h"
23 static int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type)
25 wpa_printf(MSG_DEBUG, "WPS: * Request Type");
26 wpabuf_put_be16(msg, ATTR_REQUEST_TYPE);
27 wpabuf_put_be16(msg, 1);
28 wpabuf_put_u8(msg, type);
33 static int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid)
35 wpa_printf(MSG_DEBUG, "WPS: * UUID-E");
36 wpabuf_put_be16(msg, ATTR_UUID_E);
37 wpabuf_put_be16(msg, WPS_UUID_LEN);
38 wpabuf_put_data(msg, uuid, WPS_UUID_LEN);
43 static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg)
45 wpa_printf(MSG_DEBUG, "WPS: * MAC Address");
46 wpabuf_put_be16(msg, ATTR_MAC_ADDR);
47 wpabuf_put_be16(msg, ETH_ALEN);
48 wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN);
53 static int wps_build_config_methods(struct wpabuf *msg, u16 methods)
55 wpa_printf(MSG_DEBUG, "WPS: * Config Methods");
56 wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
57 wpabuf_put_be16(msg, 2);
58 wpabuf_put_be16(msg, methods);
63 static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg)
65 wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State");
66 wpabuf_put_be16(msg, ATTR_WPS_STATE);
67 wpabuf_put_be16(msg, 1);
68 wpabuf_put_u8(msg, WPS_STATE_CONFIGURED);
73 static int wps_build_manufacturer(struct wps_data *wps, struct wpabuf *msg)
75 wpa_printf(MSG_DEBUG, "WPS: * Manufacturer");
76 wpabuf_put_be16(msg, ATTR_MANUFACTURER);
77 wpabuf_put_be16(msg, 5);
78 wpabuf_put_data(msg, "manuf", 5); /* FIX */
83 static int wps_build_model_name(struct wps_data *wps, struct wpabuf *msg)
85 wpa_printf(MSG_DEBUG, "WPS: * Model Name");
86 wpabuf_put_be16(msg, ATTR_MODEL_NAME);
87 wpabuf_put_be16(msg, 10);
88 wpabuf_put_data(msg, "model name", 10); /* FIX */
93 static int wps_build_model_number(struct wps_data *wps, struct wpabuf *msg)
95 wpa_printf(MSG_DEBUG, "WPS: * Model Number");
96 wpabuf_put_be16(msg, ATTR_MODEL_NUMBER);
97 wpabuf_put_be16(msg, 12);
98 wpabuf_put_data(msg, "model number", 12); /* FIX */
103 static int wps_build_serial_number(struct wps_data *wps, struct wpabuf *msg)
105 wpa_printf(MSG_DEBUG, "WPS: * Serial Number");
106 wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER);
107 wpabuf_put_be16(msg, 5);
108 wpabuf_put_data(msg, "12345", 5); /* FIX */
113 static int wps_build_primary_dev_type(struct wps_data *wps, struct wpabuf *msg)
115 struct wps_dev_type *dev;
116 wpa_printf(MSG_DEBUG, "WPS: * Primary Device Type");
117 wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE);
118 wpabuf_put_be16(msg, sizeof(*dev));
119 dev = wpabuf_put(msg, sizeof(*dev));
120 WPA_PUT_BE16(dev->categ_id, WPS_DEV_COMPUTER);
121 WPA_PUT_BE32(dev->oui, WPS_DEV_OUI_WFA);
122 WPA_PUT_BE16(dev->sub_categ_id, WPS_DEV_COMPUTER_PC);
127 static int wps_build_dev_name(struct wps_data *wps, struct wpabuf *msg)
129 wpa_printf(MSG_DEBUG, "WPS: * Device Name");
130 wpabuf_put_be16(msg, ATTR_DEV_NAME);
131 wpabuf_put_be16(msg, 8);
132 wpabuf_put_data(msg, "dev name", 8); /* FIX */
137 static int wps_build_rf_bands(struct wps_data *wps, struct wpabuf *msg)
139 wpa_printf(MSG_DEBUG, "WPS: * RF Bands");
140 wpabuf_put_be16(msg, ATTR_RF_BANDS);
141 wpabuf_put_be16(msg, 1);
142 wpabuf_put_u8(msg, WPS_RF_24GHZ | WPS_RF_50GHZ);
147 static int wps_build_dev_password_id(struct wpabuf *msg, u16 id)
149 wpa_printf(MSG_DEBUG, "WPS: * Device Password ID");
150 wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
151 wpabuf_put_be16(msg, 2);
152 wpabuf_put_be16(msg, id);
157 static int wps_build_config_error(struct wps_data *wps, struct wpabuf *msg)
159 u16 err = WPS_CFG_NO_ERROR;
160 wpabuf_put_be16(msg, ATTR_CONFIG_ERROR);
161 wpabuf_put_be16(msg, 2);
162 if (wps && wps->authenticator && wps->wps->ap_setup_locked)
163 err = WPS_CFG_SETUP_LOCKED;
164 wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err);
165 wpabuf_put_be16(msg, err);
170 static int wps_build_os_version(struct wps_data *wps, struct wpabuf *msg)
172 wpa_printf(MSG_DEBUG, "WPS: * OS Version");
173 wpabuf_put_be16(msg, ATTR_OS_VERSION);
174 wpabuf_put_be16(msg, 4);
175 wpabuf_put_be32(msg, 0x80000000); /* FIX */
180 static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg)
186 if (os_get_random(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0)
188 wpa_hexdump(MSG_DEBUG, "WPS: E-S1", wps->snonce, WPS_SECRET_NONCE_LEN);
189 wpa_hexdump(MSG_DEBUG, "WPS: E-S2",
190 wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN);
192 if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) {
193 wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for "
194 "E-Hash derivation");
198 wpa_printf(MSG_DEBUG, "WPS: * E-Hash1");
199 wpabuf_put_be16(msg, ATTR_E_HASH1);
200 wpabuf_put_be16(msg, SHA256_MAC_LEN);
201 hash = wpabuf_put(msg, SHA256_MAC_LEN);
202 /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */
203 addr[0] = wps->snonce;
204 len[0] = WPS_SECRET_NONCE_LEN;
206 len[1] = WPS_PSK_LEN;
207 addr[2] = wpabuf_head(wps->dh_pubkey_e);
208 len[2] = wpabuf_len(wps->dh_pubkey_e);
209 addr[3] = wpabuf_head(wps->dh_pubkey_r);
210 len[3] = wpabuf_len(wps->dh_pubkey_r);
211 hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
212 wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", hash, SHA256_MAC_LEN);
214 wpa_printf(MSG_DEBUG, "WPS: * E-Hash2");
215 wpabuf_put_be16(msg, ATTR_E_HASH2);
216 wpabuf_put_be16(msg, SHA256_MAC_LEN);
217 hash = wpabuf_put(msg, SHA256_MAC_LEN);
218 /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */
219 addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN;
221 hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
222 wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", hash, SHA256_MAC_LEN);
228 static int wps_build_e_snonce1(struct wps_data *wps, struct wpabuf *msg)
230 wpa_printf(MSG_DEBUG, "WPS: * E-SNonce1");
231 wpabuf_put_be16(msg, ATTR_E_SNONCE1);
232 wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
233 wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN);
238 static int wps_build_e_snonce2(struct wps_data *wps, struct wpabuf *msg)
240 wpa_printf(MSG_DEBUG, "WPS: * E-SNonce2");
241 wpabuf_put_be16(msg, ATTR_E_SNONCE2);
242 wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
243 wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN,
244 WPS_SECRET_NONCE_LEN);
249 static struct wpabuf * wps_build_m1(struct wps_data *wps)
254 if (os_get_random(wps->nonce_e, WPS_NONCE_LEN) < 0)
256 wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce",
257 wps->nonce_e, WPS_NONCE_LEN);
259 wpa_printf(MSG_DEBUG, "WPS: Building Message M1");
260 msg = wpabuf_alloc(1000);
264 methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
266 methods |= WPS_CONFIG_PUSHBUTTON;
268 if (wps_build_version(msg) ||
269 wps_build_msg_type(msg, WPS_M1) ||
270 wps_build_uuid_e(msg, wps->uuid_e) ||
271 wps_build_mac_addr(wps, msg) ||
272 wps_build_enrollee_nonce(wps, msg) ||
273 wps_build_public_key(wps, msg) ||
274 wps_build_auth_type_flags(wps, msg) ||
275 wps_build_encr_type_flags(wps, msg) ||
276 wps_build_conn_type_flags(wps, msg) ||
277 wps_build_config_methods(msg, methods) ||
278 wps_build_wps_state(wps, msg) ||
279 wps_build_manufacturer(wps, msg) ||
280 wps_build_model_name(wps, msg) ||
281 wps_build_model_number(wps, msg) ||
282 wps_build_serial_number(wps, msg) ||
283 wps_build_primary_dev_type(wps, msg) ||
284 wps_build_dev_name(wps, msg) ||
285 wps_build_rf_bands(wps, msg) ||
286 wps_build_assoc_state(wps, msg) ||
287 wps_build_dev_password_id(msg, wps->dev_pw_id) ||
288 wps_build_config_error(wps, msg) ||
289 wps_build_os_version(wps, msg)) {
294 wps->state = RECV_M2;
299 static struct wpabuf * wps_build_m3(struct wps_data *wps)
303 wpa_printf(MSG_DEBUG, "WPS: Building Message M3");
305 if (wps->dev_password == NULL) {
306 wpa_printf(MSG_DEBUG, "WPS: No Device Password available");
309 wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
311 msg = wpabuf_alloc(1000);
315 if (wps_build_version(msg) ||
316 wps_build_msg_type(msg, WPS_M3) ||
317 wps_build_registrar_nonce(wps, msg) ||
318 wps_build_e_hash(wps, msg) ||
319 wps_build_authenticator(wps, msg)) {
324 wps->state = RECV_M4;
329 static struct wpabuf * wps_build_m5(struct wps_data *wps)
331 struct wpabuf *msg, *plain;
333 wpa_printf(MSG_DEBUG, "WPS: Building Message M5");
335 plain = wpabuf_alloc(200);
339 msg = wpabuf_alloc(1000);
345 if (wps_build_version(msg) ||
346 wps_build_msg_type(msg, WPS_M5) ||
347 wps_build_registrar_nonce(wps, msg) ||
348 wps_build_e_snonce1(wps, plain) ||
349 wps_build_key_wrap_auth(wps, plain) ||
350 wps_build_encr_settings(wps, msg, plain) ||
351 wps_build_authenticator(wps, msg)) {
358 wps->state = RECV_M6;
363 static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg)
365 wpa_printf(MSG_DEBUG, "WPS: * SSID");
366 wpabuf_put_be16(msg, ATTR_SSID);
367 wpabuf_put_be16(msg, wps->wps->ssid_len);
368 wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len);
373 static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg)
375 wpa_printf(MSG_DEBUG, "WPS: * Authentication Type");
376 wpabuf_put_be16(msg, ATTR_AUTH_TYPE);
377 wpabuf_put_be16(msg, 2);
378 wpabuf_put_be16(msg, wps->wps->auth_types);
383 static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg)
385 wpa_printf(MSG_DEBUG, "WPS: * Encryption Type");
386 wpabuf_put_be16(msg, ATTR_ENCR_TYPE);
387 wpabuf_put_be16(msg, 2);
388 wpabuf_put_be16(msg, wps->wps->encr_types);
393 static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg)
395 wpa_printf(MSG_DEBUG, "WPS: * Network Key");
396 wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
397 wpabuf_put_be16(msg, wps->wps->network_key_len);
398 wpabuf_put_data(msg, wps->wps->network_key, wps->wps->network_key_len);
403 static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg)
405 wpa_printf(MSG_DEBUG, "WPS: * MAC Address (AP BSSID)");
406 wpabuf_put_be16(msg, ATTR_MAC_ADDR);
407 wpabuf_put_be16(msg, ETH_ALEN);
408 wpabuf_put_data(msg, wps->wps->dev.mac_addr, ETH_ALEN);
413 static struct wpabuf * wps_build_m7(struct wps_data *wps)
415 struct wpabuf *msg, *plain;
417 wpa_printf(MSG_DEBUG, "WPS: Building Message M7");
419 plain = wpabuf_alloc(500);
423 msg = wpabuf_alloc(1000);
429 if (wps_build_version(msg) ||
430 wps_build_msg_type(msg, WPS_M7) ||
431 wps_build_registrar_nonce(wps, msg) ||
432 wps_build_e_snonce2(wps, plain) ||
433 (wps->authenticator &&
434 (wps_build_cred_ssid(wps, plain) ||
435 wps_build_cred_mac_addr(wps, plain) ||
436 wps_build_cred_auth_type(wps, plain) ||
437 wps_build_cred_encr_type(wps, plain) ||
438 wps_build_cred_network_key(wps, plain))) ||
439 wps_build_key_wrap_auth(wps, plain) ||
440 wps_build_encr_settings(wps, msg, plain) ||
441 wps_build_authenticator(wps, msg)) {
448 wps->state = RECV_M8;
453 static struct wpabuf * wps_build_wsc_done(struct wps_data *wps)
457 wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done");
459 msg = wpabuf_alloc(1000);
463 if (wps_build_version(msg) ||
464 wps_build_msg_type(msg, WPS_WSC_DONE) ||
465 wps_build_enrollee_nonce(wps, msg) ||
466 wps_build_registrar_nonce(wps, msg)) {
471 wps->state = wps->authenticator ? RECV_ACK : WPS_FINISHED;
476 static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps)
480 wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK");
482 msg = wpabuf_alloc(1000);
486 if (wps_build_version(msg) ||
487 wps_build_msg_type(msg, WPS_WSC_ACK) ||
488 wps_build_enrollee_nonce(wps, msg) ||
489 wps_build_registrar_nonce(wps, msg)) {
498 static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
502 wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK");
504 msg = wpabuf_alloc(1000);
508 if (wps_build_version(msg) ||
509 wps_build_msg_type(msg, WPS_WSC_NACK) ||
510 wps_build_enrollee_nonce(wps, msg) ||
511 wps_build_registrar_nonce(wps, msg) ||
512 wps_build_config_error(wps, msg)) {
521 struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, u8 *op_code)
525 switch (wps->state) {
527 msg = wps_build_m1(wps);
531 msg = wps_build_m3(wps);
535 msg = wps_build_m5(wps);
539 msg = wps_build_m7(wps);
543 msg = wps_build_wsc_ack(wps);
546 /* Another M2/M2D may be received */
547 wps->state = RECV_M2;
551 msg = wps_build_wsc_nack(wps);
555 msg = wps_build_wsc_done(wps);
559 wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building "
560 "a message", wps->state);
565 if (*op_code == WSC_MSG && msg) {
566 /* Save a copy of the last message for Authenticator derivation
568 wpabuf_free(wps->last_msg);
569 wps->last_msg = wpabuf_dup(msg);
576 static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce)
578 if (r_nonce == NULL) {
579 wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received");
583 os_memcpy(wps->nonce_r, r_nonce, WPS_NONCE_LEN);
584 wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce",
585 wps->nonce_r, WPS_NONCE_LEN);
591 static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce)
593 if (e_nonce == NULL) {
594 wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received");
598 if (os_memcmp(wps->nonce_e, e_nonce, WPS_NONCE_LEN) != 0) {
599 wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce received");
607 static int wps_process_uuid_r(struct wps_data *wps, const u8 *uuid_r)
609 if (uuid_r == NULL) {
610 wpa_printf(MSG_DEBUG, "WPS: No UUID-R received");
614 os_memcpy(wps->uuid_r, uuid_r, WPS_UUID_LEN);
615 wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN);
621 static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
624 if (pk == NULL || pk_len == 0) {
625 wpa_printf(MSG_DEBUG, "WPS: No Public Key received");
629 wpabuf_free(wps->dh_pubkey_r);
630 wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len);
631 if (wps->dh_pubkey_r == NULL)
634 return wps_derive_keys(wps);
638 static int wps_process_r_hash1(struct wps_data *wps, const u8 *r_hash1)
640 if (r_hash1 == NULL) {
641 wpa_printf(MSG_DEBUG, "WPS: No R-Hash1 received");
645 os_memcpy(wps->peer_hash1, r_hash1, WPS_HASH_LEN);
646 wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", wps->peer_hash1, WPS_HASH_LEN);
652 static int wps_process_r_hash2(struct wps_data *wps, const u8 *r_hash2)
654 if (r_hash2 == NULL) {
655 wpa_printf(MSG_DEBUG, "WPS: No R-Hash2 received");
659 os_memcpy(wps->peer_hash2, r_hash2, WPS_HASH_LEN);
660 wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", wps->peer_hash2, WPS_HASH_LEN);
666 static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1)
668 u8 hash[SHA256_MAC_LEN];
672 if (r_snonce1 == NULL) {
673 wpa_printf(MSG_DEBUG, "WPS: No R-SNonce1 received");
677 wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce1", r_snonce1,
678 WPS_SECRET_NONCE_LEN);
680 /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */
682 len[0] = WPS_SECRET_NONCE_LEN;
684 len[1] = WPS_PSK_LEN;
685 addr[2] = wpabuf_head(wps->dh_pubkey_e);
686 len[2] = wpabuf_len(wps->dh_pubkey_e);
687 addr[3] = wpabuf_head(wps->dh_pubkey_r);
688 len[3] = wpabuf_len(wps->dh_pubkey_r);
689 hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
691 if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
692 wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does "
693 "not match with the pre-committed value");
697 wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the first "
698 "half of the device password");
704 static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2)
706 u8 hash[SHA256_MAC_LEN];
710 if (r_snonce2 == NULL) {
711 wpa_printf(MSG_DEBUG, "WPS: No R-SNonce2 received");
715 wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce2", r_snonce2,
716 WPS_SECRET_NONCE_LEN);
718 /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */
720 len[0] = WPS_SECRET_NONCE_LEN;
722 len[1] = WPS_PSK_LEN;
723 addr[2] = wpabuf_head(wps->dh_pubkey_e);
724 len[2] = wpabuf_len(wps->dh_pubkey_e);
725 addr[3] = wpabuf_head(wps->dh_pubkey_r);
726 len[3] = wpabuf_len(wps->dh_pubkey_r);
727 hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
729 if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
730 wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does "
731 "not match with the pre-committed value");
735 wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the second "
736 "half of the device password");
742 static int wps_process_cred_network_idx(struct wps_credential *cred,
746 wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
751 wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx);
757 static int wps_process_cred_ssid(struct wps_credential *cred, const u8 *ssid,
761 wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID");
765 /* Remove zero-padding since some Registrar implementations seem to use
766 * hardcoded 32-octet length for this attribute */
767 while (ssid_len > 0 && ssid[ssid_len - 1] == 0)
770 wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", ssid, ssid_len);
771 if (ssid_len <= sizeof(cred->ssid)) {
772 os_memcpy(cred->ssid, ssid, ssid_len);
773 cred->ssid_len = ssid_len;
780 static int wps_process_cred_auth_type(struct wps_credential *cred,
783 if (auth_type == NULL) {
784 wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
785 "Authentication Type");
789 cred->auth_type = WPA_GET_BE16(auth_type);
790 wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x",
797 static int wps_process_cred_encr_type(struct wps_credential *cred,
800 if (encr_type == NULL) {
801 wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
806 cred->encr_type = WPA_GET_BE16(encr_type);
807 wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x",
814 static int wps_process_cred_network_key_idx(struct wps_credential *cred,
818 return 0; /* optional attribute */
820 wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx);
821 cred->key_idx = *key_idx;
827 static int wps_process_cred_network_key(struct wps_credential *cred,
828 const u8 *key, size_t key_len)
831 wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
836 wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", key, key_len);
837 if (key_len <= sizeof(cred->key)) {
838 os_memcpy(cred->key, key, key_len);
839 cred->key_len = key_len;
846 static int wps_process_cred_mac_addr(struct wps_credential *cred,
849 if (mac_addr == NULL) {
850 wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
855 wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr));
856 os_memcpy(cred->mac_addr, mac_addr, ETH_ALEN);
862 static int wps_process_cred_eap_type(struct wps_credential *cred,
863 const u8 *eap_type, size_t eap_type_len)
865 if (eap_type == NULL)
866 return 0; /* optional attribute */
868 wpa_hexdump(MSG_DEBUG, "WPS: EAP Type", eap_type, eap_type_len);
874 static int wps_process_cred_eap_identity(struct wps_credential *cred,
878 if (identity == NULL)
879 return 0; /* optional attribute */
881 wpa_hexdump_ascii(MSG_DEBUG, "WPS: EAP Identity",
882 identity, identity_len);
888 static int wps_process_cred_key_prov_auto(struct wps_credential *cred,
889 const u8 *key_prov_auto)
891 if (key_prov_auto == NULL)
892 return 0; /* optional attribute */
894 wpa_printf(MSG_DEBUG, "WPS: Key Provided Automatically: %d",
901 static int wps_process_cred_802_1x_enabled(struct wps_credential *cred,
902 const u8 *dot1x_enabled)
904 if (dot1x_enabled == NULL)
905 return 0; /* optional attribute */
907 wpa_printf(MSG_DEBUG, "WPS: 802.1X Enabled: %d", *dot1x_enabled);
913 static int wps_process_cred(struct wps_data *wps, const u8 *cred,
916 struct wps_parse_attr attr;
919 wpa_printf(MSG_DEBUG, "WPS: Received Credential");
920 os_memset(&wps->cred, 0, sizeof(wps->cred));
921 wpabuf_set(&msg, cred, cred_len);
922 /* TODO: support multiple Network Keys */
923 if (wps_parse_msg(&msg, &attr) < 0 ||
924 wps_process_cred_network_idx(&wps->cred, attr.network_idx) ||
925 wps_process_cred_ssid(&wps->cred, attr.ssid, attr.ssid_len) ||
926 wps_process_cred_auth_type(&wps->cred, attr.auth_type) ||
927 wps_process_cred_encr_type(&wps->cred, attr.encr_type) ||
928 wps_process_cred_network_key_idx(&wps->cred, attr.network_key_idx)
930 wps_process_cred_network_key(&wps->cred, attr.network_key,
931 attr.network_key_len) ||
932 wps_process_cred_mac_addr(&wps->cred, attr.mac_addr) ||
933 wps_process_cred_eap_type(&wps->cred, attr.eap_type,
934 attr.eap_type_len) ||
935 wps_process_cred_eap_identity(&wps->cred, attr.eap_identity,
936 attr.eap_identity_len) ||
937 wps_process_cred_key_prov_auto(&wps->cred, attr.key_prov_auto) ||
938 wps_process_cred_802_1x_enabled(&wps->cred, attr.dot1x_enabled))
941 if (wps->wps_cred_cb)
942 wps->wps_cred_cb(wps->cb_ctx, &wps->cred);
948 static int wps_process_creds(struct wps_data *wps, const u8 *cred[],
949 size_t cred_len[], size_t num_cred)
953 if (wps->authenticator)
957 wpa_printf(MSG_DEBUG, "WPS: No Credential attributes "
962 for (i = 0; i < num_cred; i++) {
963 if (wps_process_cred(wps, cred[i], cred_len[i]))
971 static int wps_process_ap_settings(struct wps_data *wps,
972 struct wps_parse_attr *attr)
974 struct wps_credential cred;
976 if (!wps->authenticator)
979 wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings");
980 os_memset(&cred, 0, sizeof(cred));
981 /* TODO: optional attributes New Password and Device Password ID */
982 if (wps_process_cred_ssid(&cred, attr->ssid, attr->ssid_len) ||
983 wps_process_cred_auth_type(&cred, attr->auth_type) ||
984 wps_process_cred_encr_type(&cred, attr->encr_type) ||
985 wps_process_cred_network_key_idx(&cred, attr->network_key_idx) ||
986 wps_process_cred_network_key(&cred, attr->network_key,
987 attr->network_key_len) ||
988 wps_process_cred_mac_addr(&cred, attr->mac_addr))
991 wpa_printf(MSG_INFO, "WPS: Received new AP configuration from "
994 if (wps->wps->cred_cb)
995 wps->wps->cred_cb(wps->wps->cb_ctx, &cred);
1001 static enum wps_process_res wps_process_m2(struct wps_data *wps,
1002 const struct wpabuf *msg,
1003 struct wps_parse_attr *attr)
1005 wpa_printf(MSG_DEBUG, "WPS: Received M2");
1007 if (wps->state != RECV_M2) {
1008 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
1009 "receiving M2", wps->state);
1013 if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
1014 wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
1015 wps_process_uuid_r(wps, attr->uuid_r) ||
1016 wps_process_pubkey(wps, attr->public_key, attr->public_key_len) ||
1017 wps_process_authenticator(wps, attr->authenticator, msg))
1020 if (wps->authenticator && wps->wps->ap_setup_locked) {
1021 wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse "
1022 "registration of a new Registrar");
1023 wps->state = SEND_WSC_NACK;
1024 return WPS_CONTINUE;
1027 wps->state = SEND_M3;
1028 return WPS_CONTINUE;
1032 static enum wps_process_res wps_process_m2d(struct wps_data *wps,
1033 struct wps_parse_attr *attr)
1035 wpa_printf(MSG_DEBUG, "WPS: Received M2D");
1037 if (wps->state != RECV_M2) {
1038 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
1039 "receiving M2D", wps->state);
1043 wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer",
1044 attr->manufacturer, attr->manufacturer_len);
1045 wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name",
1046 attr->model_name, attr->model_name_len);
1047 wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number",
1048 attr->model_number, attr->model_number_len);
1049 wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number",
1050 attr->serial_number, attr->serial_number_len);
1051 wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name",
1052 attr->dev_name, attr->dev_name_len);
1055 * TODO: notify monitor programs (cli/gui/etc.) of the M2D and provide
1056 * user information about the registrar properties.
1059 wps->state = RECEIVED_M2D;
1064 static enum wps_process_res wps_process_m4(struct wps_data *wps,
1065 const struct wpabuf *msg,
1066 struct wps_parse_attr *attr)
1068 struct wpabuf *decrypted;
1069 struct wps_parse_attr eattr;
1071 wpa_printf(MSG_DEBUG, "WPS: Received M4");
1073 if (wps->state != RECV_M4) {
1074 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
1075 "receiving M4", wps->state);
1079 if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
1080 wps_process_authenticator(wps, attr->authenticator, msg) ||
1081 wps_process_r_hash1(wps, attr->r_hash1) ||
1082 wps_process_r_hash2(wps, attr->r_hash2))
1085 decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
1086 attr->encr_settings_len);
1087 if (decrypted == NULL) {
1088 wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
1089 "Settings attribute");
1093 wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
1095 if (wps_parse_msg(decrypted, &eattr) < 0 ||
1096 wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
1097 wps_process_r_snonce1(wps, eattr.r_snonce1)) {
1098 wpabuf_free(decrypted);
1101 wpabuf_free(decrypted);
1103 wps->state = SEND_M5;
1104 return WPS_CONTINUE;
1108 static enum wps_process_res wps_process_m6(struct wps_data *wps,
1109 const struct wpabuf *msg,
1110 struct wps_parse_attr *attr)
1112 struct wpabuf *decrypted;
1113 struct wps_parse_attr eattr;
1115 wpa_printf(MSG_DEBUG, "WPS: Received M6");
1117 if (wps->state != RECV_M6) {
1118 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
1119 "receiving M6", wps->state);
1123 if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
1124 wps_process_authenticator(wps, attr->authenticator, msg))
1127 decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
1128 attr->encr_settings_len);
1129 if (decrypted == NULL) {
1130 wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
1131 "Settings attribute");
1135 wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
1137 if (wps_parse_msg(decrypted, &eattr) < 0 ||
1138 wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
1139 wps_process_r_snonce2(wps, eattr.r_snonce2)) {
1140 wpabuf_free(decrypted);
1143 wpabuf_free(decrypted);
1145 wps->state = SEND_M7;
1146 return WPS_CONTINUE;
1150 static enum wps_process_res wps_process_m8(struct wps_data *wps,
1151 const struct wpabuf *msg,
1152 struct wps_parse_attr *attr)
1154 struct wpabuf *decrypted;
1155 struct wps_parse_attr eattr;
1157 wpa_printf(MSG_DEBUG, "WPS: Received M8");
1159 if (wps->state != RECV_M8) {
1160 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
1161 "receiving M8", wps->state);
1165 if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
1166 wps_process_authenticator(wps, attr->authenticator, msg))
1169 decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
1170 attr->encr_settings_len);
1171 if (decrypted == NULL) {
1172 wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
1173 "Settings attribute");
1177 wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
1179 if (wps_parse_msg(decrypted, &eattr) < 0 ||
1180 wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
1181 wps_process_creds(wps, eattr.cred, eattr.cred_len,
1183 wps_process_ap_settings(wps, &eattr)) {
1184 wpabuf_free(decrypted);
1187 wpabuf_free(decrypted);
1189 wps->state = WPS_MSG_DONE;
1190 return WPS_CONTINUE;
1194 static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
1195 const struct wpabuf *msg)
1197 struct wps_parse_attr attr;
1198 enum wps_process_res ret = WPS_CONTINUE;
1200 wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG");
1202 if (wps_parse_msg(msg, &attr) < 0)
1205 if (attr.version == NULL || *attr.version != WPS_VERSION) {
1206 wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
1207 attr.version ? *attr.version : 0);
1211 if (attr.enrollee_nonce == NULL ||
1212 os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) {
1213 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
1217 if (attr.msg_type == NULL) {
1218 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
1222 switch (*attr.msg_type) {
1224 ret = wps_process_m2(wps, msg, &attr);
1227 ret = wps_process_m2d(wps, &attr);
1230 ret = wps_process_m4(wps, msg, &attr);
1233 ret = wps_process_m6(wps, msg, &attr);
1236 ret = wps_process_m8(wps, msg, &attr);
1239 wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d",
1244 if (ret == WPS_CONTINUE) {
1245 /* Save a copy of the last message for Authenticator derivation
1247 wpabuf_free(wps->last_msg);
1248 wps->last_msg = wpabuf_dup(msg);
1255 static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
1256 const struct wpabuf *msg)
1258 struct wps_parse_attr attr;
1260 wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK");
1262 if (wps_parse_msg(msg, &attr) < 0)
1265 if (attr.version == NULL || *attr.version != WPS_VERSION) {
1266 wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
1267 attr.version ? *attr.version : 0);
1271 if (attr.msg_type == NULL) {
1272 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
1276 if (*attr.msg_type != WPS_WSC_ACK) {
1277 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
1282 if (attr.registrar_nonce == NULL ||
1283 os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0))
1285 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
1289 if (attr.enrollee_nonce == NULL ||
1290 os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) {
1291 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
1295 if (wps->state == RECV_ACK && wps->authenticator) {
1296 wpa_printf(MSG_DEBUG, "WPS: External Registrar registration "
1297 "completed successfully");
1298 wps->state = WPS_FINISHED;
1306 static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps,
1307 const struct wpabuf *msg)
1309 struct wps_parse_attr attr;
1311 wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK");
1313 if (wps_parse_msg(msg, &attr) < 0)
1316 if (attr.version == NULL || *attr.version != WPS_VERSION) {
1317 wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
1318 attr.version ? *attr.version : 0);
1322 if (attr.msg_type == NULL) {
1323 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
1327 if (*attr.msg_type != WPS_WSC_NACK) {
1328 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
1333 if (attr.registrar_nonce == NULL ||
1334 os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0))
1336 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
1337 wpa_hexdump(MSG_DEBUG, "WPS: Received Registrar Nonce",
1338 attr.registrar_nonce, WPS_NONCE_LEN);
1339 wpa_hexdump(MSG_DEBUG, "WPS: Expected Registrar Nonce",
1340 wps->nonce_r, WPS_NONCE_LEN);
1344 if (attr.enrollee_nonce == NULL ||
1345 os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) {
1346 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
1347 wpa_hexdump(MSG_DEBUG, "WPS: Received Enrollee Nonce",
1348 attr.enrollee_nonce, WPS_NONCE_LEN);
1349 wpa_hexdump(MSG_DEBUG, "WPS: Expected Enrollee Nonce",
1350 wps->nonce_e, WPS_NONCE_LEN);
1354 if (attr.config_error == NULL) {
1355 wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute "
1360 wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with "
1361 "Configuration Error %d", WPA_GET_BE16(attr.config_error));
1367 enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, u8 op_code,
1368 const struct wpabuf *msg)
1371 wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu "
1373 (unsigned long) wpabuf_len(msg), op_code);
1377 return wps_process_wsc_msg(wps, msg);
1379 return wps_process_wsc_ack(wps, msg);
1381 return wps_process_wsc_nack(wps, msg);
1383 wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code);
1389 struct wpabuf * wps_enrollee_build_assoc_req_ie(void)
1394 wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association "
1396 ie = wpabuf_alloc(100);
1400 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
1401 len = wpabuf_put(ie, 1);
1402 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
1404 if (wps_build_version(ie) ||
1405 wps_build_req_type(ie, WPS_REQ_ENROLLEE)) {
1410 *len = wpabuf_len(ie) - 2;
1416 struct wpabuf * wps_enrollee_build_probe_req_ie(int pbc, const u8 *uuid)
1422 wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request");
1423 ie = wpabuf_alloc(200);
1427 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
1428 len = wpabuf_put(ie, 1);
1429 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
1432 methods = WPS_CONFIG_PUSHBUTTON;
1434 methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY |
1437 if (wps_build_version(ie) ||
1438 wps_build_req_type(ie, WPS_REQ_ENROLLEE) ||
1439 wps_build_config_methods(ie, methods) ||
1440 wps_build_uuid_e(ie, uuid) ||
1441 wps_build_primary_dev_type(NULL, ie) ||
1442 wps_build_rf_bands(NULL, ie) ||
1443 wps_build_assoc_state(NULL, ie) ||
1444 wps_build_config_error(NULL, ie) ||
1445 wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON :
1451 *len = wpabuf_len(ie) - 2;