aboutsummaryrefslogtreecommitdiffstats
path: root/src/wps
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2008-11-29 11:16:26 (GMT)
committerJouni Malinen <j@w1.fi>2008-11-29 11:16:26 (GMT)
commit7d7b8e960add157b3e01b58b1a716b17975adb4a (patch)
tree21afe297e0c5077e3616476804d382626eb18458 /src/wps
parent120bd30c34bebd76bcbb3a888fbaec0cf314f7ba (diff)
downloadhostap-06-7d7b8e960add157b3e01b58b1a716b17975adb4a.zip
hostap-06-7d7b8e960add157b3e01b58b1a716b17975adb4a.tar.gz
hostap-06-7d7b8e960add157b3e01b58b1a716b17975adb4a.tar.bz2
WPS: Split wps_common.c into parts
To make it easier to find various functions, attribute functions were split into wps_attr_{build,parse,process}.c.
Diffstat (limited to 'src/wps')
-rw-r--r--src/wps/wps_attr_build.c253
-rw-r--r--src/wps/wps_attr_parse.c429
-rw-r--r--src/wps/wps_attr_process.c302
-rw-r--r--src/wps/wps_common.c926
-rw-r--r--src/wps/wps_i.h29
5 files changed, 1002 insertions, 937 deletions
diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c
new file mode 100644
index 0000000..c30e17b
--- /dev/null
+++ b/src/wps/wps_attr_build.c
@@ -0,0 +1,253 @@
+/*
+ * Wi-Fi Protected Setup - attribute building
+ * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "dh_groups.h"
+#include "sha256.h"
+#include "aes_wrap.h"
+#include "wps_i.h"
+
+
+int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
+{
+ struct wpabuf *pubkey;
+
+ wpa_printf(MSG_DEBUG, "WPS: * Public Key");
+ pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), &wps->dh_privkey);
+ if (pubkey == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
+ "Diffie-Hellman handshake");
+ return -1;
+ }
+
+ wpabuf_put_be16(msg, ATTR_PUBLIC_KEY);
+ wpabuf_put_be16(msg, wpabuf_len(pubkey));
+ wpabuf_put_buf(msg, pubkey);
+
+ if (wps->registrar) {
+ wpabuf_free(wps->dh_pubkey_r);
+ wps->dh_pubkey_r = pubkey;
+ } else {
+ wpabuf_free(wps->dh_pubkey_e);
+ wps->dh_pubkey_e = pubkey;
+ }
+
+ return 0;
+}
+
+
+int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Request Type");
+ wpabuf_put_be16(msg, ATTR_REQUEST_TYPE);
+ wpabuf_put_be16(msg, 1);
+ wpabuf_put_u8(msg, type);
+ return 0;
+}
+
+
+int wps_build_config_methods(struct wpabuf *msg, u16 methods)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods);
+ wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
+ wpabuf_put_be16(msg, 2);
+ wpabuf_put_be16(msg, methods);
+ return 0;
+}
+
+
+int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * UUID-E");
+ wpabuf_put_be16(msg, ATTR_UUID_E);
+ wpabuf_put_be16(msg, WPS_UUID_LEN);
+ wpabuf_put_data(msg, uuid, WPS_UUID_LEN);
+ return 0;
+}
+
+
+int wps_build_dev_password_id(struct wpabuf *msg, u16 id)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id);
+ wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
+ wpabuf_put_be16(msg, 2);
+ wpabuf_put_be16(msg, id);
+ return 0;
+}
+
+
+int wps_build_config_error(struct wpabuf *msg, u16 err)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err);
+ wpabuf_put_be16(msg, ATTR_CONFIG_ERROR);
+ wpabuf_put_be16(msg, 2);
+ wpabuf_put_be16(msg, err);
+ return 0;
+}
+
+
+int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg)
+{
+ u8 hash[SHA256_MAC_LEN];
+ const u8 *addr[2];
+ size_t len[2];
+
+ if (wps->last_msg == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: Last message not available for "
+ "building authenticator");
+ return -1;
+ }
+
+ /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*)
+ * (M_curr* is M_curr without the Authenticator attribute)
+ */
+ addr[0] = wpabuf_head(wps->last_msg);
+ len[0] = wpabuf_len(wps->last_msg);
+ addr[1] = wpabuf_head(msg);
+ len[1] = wpabuf_len(msg);
+ hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
+
+ wpa_printf(MSG_DEBUG, "WPS: * Authenticator");
+ wpabuf_put_be16(msg, ATTR_AUTHENTICATOR);
+ wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN);
+ wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN);
+
+ return 0;
+}
+
+
+int wps_build_version(struct wpabuf *msg)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Version");
+ wpabuf_put_be16(msg, ATTR_VERSION);
+ wpabuf_put_be16(msg, 1);
+ wpabuf_put_u8(msg, WPS_VERSION);
+ return 0;
+}
+
+
+int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type);
+ wpabuf_put_be16(msg, ATTR_MSG_TYPE);
+ wpabuf_put_be16(msg, 1);
+ wpabuf_put_u8(msg, msg_type);
+ return 0;
+}
+
+
+int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce");
+ wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE);
+ wpabuf_put_be16(msg, WPS_NONCE_LEN);
+ wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN);
+ return 0;
+}
+
+
+int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce");
+ wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
+ wpabuf_put_be16(msg, WPS_NONCE_LEN);
+ wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN);
+ return 0;
+}
+
+
+int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags");
+ wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS);
+ wpabuf_put_be16(msg, 2);
+ wpabuf_put_be16(msg, WPS_AUTH_TYPES);
+ return 0;
+}
+
+
+int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags");
+ wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS);
+ wpabuf_put_be16(msg, 2);
+ wpabuf_put_be16(msg, WPS_ENCR_TYPES);
+ return 0;
+}
+
+
+int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags");
+ wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS);
+ wpabuf_put_be16(msg, 1);
+ wpabuf_put_u8(msg, WPS_CONN_ESS);
+ return 0;
+}
+
+
+int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * Association State");
+ wpabuf_put_be16(msg, ATTR_ASSOC_STATE);
+ wpabuf_put_be16(msg, 2);
+ wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC);
+ return 0;
+}
+
+
+int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg)
+{
+ u8 hash[SHA256_MAC_LEN];
+
+ wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator");
+ hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg),
+ wpabuf_len(msg), hash);
+
+ wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH);
+ wpabuf_put_be16(msg, WPS_KWA_LEN);
+ wpabuf_put_data(msg, hash, WPS_KWA_LEN);
+ return 0;
+}
+
+
+int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
+ struct wpabuf *plain)
+{
+ size_t pad_len;
+ const size_t block_size = 16;
+ u8 *iv, *data;
+
+ wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings");
+
+ /* PKCS#5 v2.0 pad */
+ pad_len = block_size - wpabuf_len(plain) % block_size;
+ os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len);
+
+ wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS);
+ wpabuf_put_be16(msg, block_size + wpabuf_len(plain));
+
+ iv = wpabuf_put(msg, block_size);
+ if (os_get_random(iv, block_size) < 0)
+ return -1;
+
+ data = wpabuf_put(msg, 0);
+ wpabuf_put_buf(msg, plain);
+ if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain)))
+ return -1;
+
+ return 0;
+}
diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c
new file mode 100644
index 0000000..25ff251
--- /dev/null
+++ b/src/wps/wps_attr_parse.c
@@ -0,0 +1,429 @@
+/*
+ * Wi-Fi Protected Setup - attribute parsing
+ * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "wps_i.h"
+
+
+static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
+ const u8 *pos, u16 len)
+{
+ switch (type) {
+ case ATTR_VERSION:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
+ len);
+ return -1;
+ }
+ attr->version = pos;
+ break;
+ case ATTR_MSG_TYPE:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
+ "length %u", len);
+ return -1;
+ }
+ attr->msg_type = pos;
+ break;
+ case ATTR_ENROLLEE_NONCE:
+ if (len != WPS_NONCE_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
+ "length %u", len);
+ return -1;
+ }
+ attr->enrollee_nonce = pos;
+ break;
+ case ATTR_REGISTRAR_NONCE:
+ if (len != WPS_NONCE_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
+ "length %u", len);
+ return -1;
+ }
+ attr->registrar_nonce = pos;
+ break;
+ case ATTR_UUID_E:
+ if (len != WPS_UUID_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
+ len);
+ return -1;
+ }
+ attr->uuid_e = pos;
+ break;
+ case ATTR_UUID_R:
+ if (len != WPS_UUID_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
+ len);
+ return -1;
+ }
+ attr->uuid_r = pos;
+ break;
+ case ATTR_AUTH_TYPE_FLAGS:
+ if (len != 2) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
+ "Type Flags length %u", len);
+ return -1;
+ }
+ attr->auth_type_flags = pos;
+ break;
+ case ATTR_ENCR_TYPE_FLAGS:
+ if (len != 2) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
+ "Flags length %u", len);
+ return -1;
+ }
+ attr->encr_type_flags = pos;
+ break;
+ case ATTR_CONN_TYPE_FLAGS:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
+ "Flags length %u", len);
+ return -1;
+ }
+ attr->conn_type_flags = pos;
+ break;
+ case ATTR_CONFIG_METHODS:
+ if (len != 2) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
+ "length %u", len);
+ return -1;
+ }
+ attr->config_methods = pos;
+ break;
+ case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
+ if (len != 2) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
+ "Registrar Config Methods length %u", len);
+ return -1;
+ }
+ attr->sel_reg_config_methods = pos;
+ break;
+ case ATTR_PRIMARY_DEV_TYPE:
+ if (len != sizeof(struct wps_dev_type)) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
+ "Type length %u", len);
+ return -1;
+ }
+ attr->primary_dev_type = pos;
+ break;
+ case ATTR_RF_BANDS:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
+ "%u", len);
+ return -1;
+ }
+ attr->rf_bands = pos;
+ break;
+ case ATTR_ASSOC_STATE:
+ if (len != 2) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
+ "length %u", len);
+ return -1;
+ }
+ attr->assoc_state = pos;
+ break;
+ case ATTR_CONFIG_ERROR:
+ if (len != 2) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
+ "Error length %u", len);
+ return -1;
+ }
+ attr->config_error = pos;
+ break;
+ case ATTR_DEV_PASSWORD_ID:
+ if (len != 2) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
+ "ID length %u", len);
+ return -1;
+ }
+ attr->dev_password_id = pos;
+ break;
+ case ATTR_OS_VERSION:
+ if (len != 4) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
+ "%u", len);
+ return -1;
+ }
+ attr->os_version = pos;
+ break;
+ case ATTR_WPS_STATE:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
+ "Setup State length %u", len);
+ return -1;
+ }
+ attr->wps_state = pos;
+ break;
+ case ATTR_AUTHENTICATOR:
+ if (len != WPS_AUTHENTICATOR_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
+ "length %u", len);
+ return -1;
+ }
+ attr->authenticator = pos;
+ break;
+ case ATTR_R_HASH1:
+ if (len != WPS_HASH_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
+ len);
+ return -1;
+ }
+ attr->r_hash1 = pos;
+ break;
+ case ATTR_R_HASH2:
+ if (len != WPS_HASH_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
+ len);
+ return -1;
+ }
+ attr->r_hash2 = pos;
+ break;
+ case ATTR_E_HASH1:
+ if (len != WPS_HASH_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
+ len);
+ return -1;
+ }
+ attr->e_hash1 = pos;
+ break;
+ case ATTR_E_HASH2:
+ if (len != WPS_HASH_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
+ len);
+ return -1;
+ }
+ attr->e_hash2 = pos;
+ break;
+ case ATTR_R_SNONCE1:
+ if (len != WPS_SECRET_NONCE_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
+ "%u", len);
+ return -1;
+ }
+ attr->r_snonce1 = pos;
+ break;
+ case ATTR_R_SNONCE2:
+ if (len != WPS_SECRET_NONCE_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
+ "%u", len);
+ return -1;
+ }
+ attr->r_snonce2 = pos;
+ break;
+ case ATTR_E_SNONCE1:
+ if (len != WPS_SECRET_NONCE_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
+ "%u", len);
+ return -1;
+ }
+ attr->e_snonce1 = pos;
+ break;
+ case ATTR_E_SNONCE2:
+ if (len != WPS_SECRET_NONCE_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
+ "%u", len);
+ return -1;
+ }
+ attr->e_snonce2 = pos;
+ break;
+ case ATTR_KEY_WRAP_AUTH:
+ if (len != WPS_KWA_LEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
+ "Authenticator length %u", len);
+ return -1;
+ }
+ attr->key_wrap_auth = pos;
+ break;
+ case ATTR_AUTH_TYPE:
+ if (len != 2) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
+ "Type length %u", len);
+ return -1;
+ }
+ attr->auth_type = pos;
+ break;
+ case ATTR_ENCR_TYPE:
+ if (len != 2) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
+ "Type length %u", len);
+ return -1;
+ }
+ attr->encr_type = pos;
+ break;
+ case ATTR_NETWORK_INDEX:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
+ "length %u", len);
+ return -1;
+ }
+ attr->network_idx = pos;
+ break;
+ case ATTR_NETWORK_KEY_INDEX:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
+ "length %u", len);
+ return -1;
+ }
+ attr->network_key_idx = pos;
+ break;
+ case ATTR_MAC_ADDR:
+ if (len != ETH_ALEN) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
+ "length %u", len);
+ return -1;
+ }
+ attr->mac_addr = pos;
+ break;
+ case ATTR_KEY_PROVIDED_AUTO:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided "
+ "Automatically length %u", len);
+ return -1;
+ }
+ attr->key_prov_auto = pos;
+ break;
+ case ATTR_802_1X_ENABLED:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled "
+ "length %u", len);
+ return -1;
+ }
+ attr->dot1x_enabled = pos;
+ break;
+ case ATTR_SELECTED_REGISTRAR:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
+ " length %u", len);
+ return -1;
+ }
+ attr->selected_registrar = pos;
+ break;
+ case ATTR_REQUEST_TYPE:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
+ "length %u", len);
+ return -1;
+ }
+ attr->request_type = pos;
+ break;
+ case ATTR_RESPONSE_TYPE:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
+ "length %u", len);
+ return -1;
+ }
+ attr->request_type = pos;
+ break;
+ case ATTR_MANUFACTURER:
+ attr->manufacturer = pos;
+ attr->manufacturer_len = len;
+ break;
+ case ATTR_MODEL_NAME:
+ attr->model_name = pos;
+ attr->model_name_len = len;
+ break;
+ case ATTR_MODEL_NUMBER:
+ attr->model_number = pos;
+ attr->model_number_len = len;
+ break;
+ case ATTR_SERIAL_NUMBER:
+ attr->serial_number = pos;
+ attr->serial_number_len = len;
+ break;
+ case ATTR_DEV_NAME:
+ attr->dev_name = pos;
+ attr->dev_name_len = len;
+ break;
+ case ATTR_PUBLIC_KEY:
+ attr->public_key = pos;
+ attr->public_key_len = len;
+ break;
+ case ATTR_ENCR_SETTINGS:
+ attr->encr_settings = pos;
+ attr->encr_settings_len = len;
+ break;
+ case ATTR_CRED:
+ if (attr->num_cred >= MAX_CRED_COUNT) {
+ wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
+ "attribute (max %d credentials)",
+ MAX_CRED_COUNT);
+ break;
+ }
+ attr->cred[attr->num_cred] = pos;
+ attr->cred_len[attr->num_cred] = len;
+ attr->num_cred++;
+ break;
+ case ATTR_SSID:
+ attr->ssid = pos;
+ attr->ssid_len = len;
+ break;
+ case ATTR_NETWORK_KEY:
+ attr->network_key = pos;
+ attr->network_key_len = len;
+ break;
+ case ATTR_EAP_TYPE:
+ attr->eap_type = pos;
+ attr->eap_type_len = len;
+ break;
+ case ATTR_EAP_IDENTITY:
+ attr->eap_identity = pos;
+ attr->eap_identity_len = len;
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
+ "len=%u", type, len);
+ break;
+ }
+
+ return 0;
+}
+
+
+int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
+{
+ const u8 *pos, *end;
+ u16 type, len;
+
+ os_memset(attr, 0, sizeof(*attr));
+ pos = wpabuf_head(msg);
+ end = pos + wpabuf_len(msg);
+
+ while (pos < end) {
+ if (end - pos < 4) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
+ "%lu bytes remaining",
+ (unsigned long) (end - pos));
+ return -1;
+ }
+
+ type = WPA_GET_BE16(pos);
+ pos += 2;
+ len = WPA_GET_BE16(pos);
+ pos += 2;
+ wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u",
+ type, len);
+ if (len > end - pos) {
+ wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
+ return -1;
+ }
+
+ if (wps_set_attr(attr, type, pos, len) < 0)
+ return -1;
+
+ pos += len;
+ }
+
+ return 0;
+}
diff --git a/src/wps/wps_attr_process.c b/src/wps/wps_attr_process.c
new file mode 100644
index 0000000..c1b59f7
--- /dev/null
+++ b/src/wps/wps_attr_process.c
@@ -0,0 +1,302 @@
+/*
+ * Wi-Fi Protected Setup - attribute processing
+ * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "sha256.h"
+#include "wps_i.h"
+
+
+int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
+ const struct wpabuf *msg)
+{
+ u8 hash[SHA256_MAC_LEN];
+ const u8 *addr[2];
+ size_t len[2];
+
+ if (authenticator == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: No Authenticator attribute "
+ "included");
+ return -1;
+ }
+
+ if (wps->last_msg == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: Last message not available for "
+ "validating authenticator");
+ return -1;
+ }
+
+ /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*)
+ * (M_curr* is M_curr without the Authenticator attribute)
+ */
+ addr[0] = wpabuf_head(wps->last_msg);
+ len[0] = wpabuf_len(wps->last_msg);
+ addr[1] = wpabuf_head(msg);
+ len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN;
+ hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
+
+ if (os_memcmp(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) {
+ wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg,
+ const u8 *key_wrap_auth)
+{
+ u8 hash[SHA256_MAC_LEN];
+ const u8 *head;
+ size_t len;
+
+ if (key_wrap_auth == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: No KWA in decrypted attribute");
+ return -1;
+ }
+
+ head = wpabuf_head(msg);
+ len = wpabuf_len(msg) - 4 - WPS_KWA_LEN;
+ if (head + len != key_wrap_auth - 4) {
+ wpa_printf(MSG_DEBUG, "WPS: KWA not in the end of the "
+ "decrypted attribute");
+ return -1;
+ }
+
+ hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash);
+ if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid KWA");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int wps_process_cred_network_idx(struct wps_credential *cred,
+ const u8 *idx)
+{
+ if (idx == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
+ "Network Index");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx);
+
+ return 0;
+}
+
+
+static int wps_process_cred_ssid(struct wps_credential *cred, const u8 *ssid,
+ size_t ssid_len)
+{
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID");
+ return -1;
+ }
+
+ /* Remove zero-padding since some Registrar implementations seem to use
+ * hardcoded 32-octet length for this attribute */
+ while (ssid_len > 0 && ssid[ssid_len - 1] == 0)
+ ssid_len--;
+
+ wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", ssid, ssid_len);
+ if (ssid_len <= sizeof(cred->ssid)) {
+ os_memcpy(cred->ssid, ssid, ssid_len);
+ cred->ssid_len = ssid_len;
+ }
+
+ return 0;
+}
+
+
+static int wps_process_cred_auth_type(struct wps_credential *cred,
+ const u8 *auth_type)
+{
+ if (auth_type == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
+ "Authentication Type");
+ return -1;
+ }
+
+ cred->auth_type = WPA_GET_BE16(auth_type);
+ wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x",
+ cred->auth_type);
+
+ return 0;
+}
+
+
+static int wps_process_cred_encr_type(struct wps_credential *cred,
+ const u8 *encr_type)
+{
+ if (encr_type == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
+ "Encryption Type");
+ return -1;
+ }
+
+ cred->encr_type = WPA_GET_BE16(encr_type);
+ wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x",
+ cred->encr_type);
+
+ return 0;
+}
+
+
+static int wps_process_cred_network_key_idx(struct wps_credential *cred,
+ const u8 *key_idx)
+{
+ if (key_idx == NULL)
+ return 0; /* optional attribute */
+
+ wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx);
+ cred->key_idx = *key_idx;
+
+ return 0;
+}
+
+
+static int wps_process_cred_network_key(struct wps_credential *cred,
+ const u8 *key, size_t key_len)
+{
+ if (key == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
+ "Network Key");
+ return -1;
+ }
+
+ wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", key, key_len);
+ if (key_len <= sizeof(cred->key)) {
+ os_memcpy(cred->key, key, key_len);
+ cred->key_len = key_len;
+ }
+
+ return 0;
+}
+
+
+static int wps_process_cred_mac_addr(struct wps_credential *cred,
+ const u8 *mac_addr)
+{
+ if (mac_addr == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
+ "MAC Address");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr));
+ os_memcpy(cred->mac_addr, mac_addr, ETH_ALEN);
+
+ return 0;
+}
+
+
+static int wps_process_cred_eap_type(struct wps_credential *cred,
+ const u8 *eap_type, size_t eap_type_len)
+{
+ if (eap_type == NULL)
+ return 0; /* optional attribute */
+
+ wpa_hexdump(MSG_DEBUG, "WPS: EAP Type", eap_type, eap_type_len);
+
+ return 0;
+}
+
+
+static int wps_process_cred_eap_identity(struct wps_credential *cred,
+ const u8 *identity,
+ size_t identity_len)
+{
+ if (identity == NULL)
+ return 0; /* optional attribute */
+
+ wpa_hexdump_ascii(MSG_DEBUG, "WPS: EAP Identity",
+ identity, identity_len);
+
+ return 0;
+}
+
+
+static int wps_process_cred_key_prov_auto(struct wps_credential *cred,
+ const u8 *key_prov_auto)
+{
+ if (key_prov_auto == NULL)
+ return 0; /* optional attribute */
+
+ wpa_printf(MSG_DEBUG, "WPS: Key Provided Automatically: %d",
+ *key_prov_auto);
+
+ return 0;
+}
+
+
+static int wps_process_cred_802_1x_enabled(struct wps_credential *cred,
+ const u8 *dot1x_enabled)
+{
+ if (dot1x_enabled == NULL)
+ return 0; /* optional attribute */
+
+ wpa_printf(MSG_DEBUG, "WPS: 802.1X Enabled: %d", *dot1x_enabled);
+
+ return 0;
+}
+
+
+int wps_process_cred(struct wps_parse_attr *attr,
+ struct wps_credential *cred)
+{
+ wpa_printf(MSG_DEBUG, "WPS: Process Credential");
+
+ /* TODO: support multiple Network Keys */
+ if (wps_process_cred_network_idx(cred, attr->network_idx) ||
+ wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) ||
+ wps_process_cred_auth_type(cred, attr->auth_type) ||
+ wps_process_cred_encr_type(cred, attr->encr_type) ||
+ wps_process_cred_network_key_idx(cred, attr->network_key_idx) ||
+ wps_process_cred_network_key(cred, attr->network_key,
+ attr->network_key_len) ||
+ wps_process_cred_mac_addr(cred, attr->mac_addr) ||
+ wps_process_cred_eap_type(cred, attr->eap_type,
+ attr->eap_type_len) ||
+ wps_process_cred_eap_identity(cred, attr->eap_identity,
+ attr->eap_identity_len) ||
+ wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) ||
+ wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled))
+ return -1;
+
+ return 0;
+}
+
+
+int wps_process_ap_settings(struct wps_parse_attr *attr,
+ struct wps_credential *cred)
+{
+ wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings");
+ os_memset(cred, 0, sizeof(*cred));
+ /* TODO: optional attributes New Password and Device Password ID */
+ if (wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) ||
+ wps_process_cred_auth_type(cred, attr->auth_type) ||
+ wps_process_cred_encr_type(cred, attr->encr_type) ||
+ wps_process_cred_network_key_idx(cred, attr->network_key_idx) ||
+ wps_process_cred_network_key(cred, attr->network_key,
+ attr->network_key_len) ||
+ wps_process_cred_mac_addr(cred, attr->mac_addr))
+ return -1;
+
+ return 0;
+}
diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c
index 7eda594..3edb1e3 100644
--- a/src/wps/wps_common.c
+++ b/src/wps/wps_common.c
@@ -24,417 +24,6 @@
#include "wps_dev_attr.h"
-static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
- const u8 *pos, u16 len)
-{
- switch (type) {
- case ATTR_VERSION:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
- len);
- return -1;
- }
- attr->version = pos;
- break;
- case ATTR_MSG_TYPE:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
- "length %u", len);
- return -1;
- }
- attr->msg_type = pos;
- break;
- case ATTR_ENROLLEE_NONCE:
- if (len != WPS_NONCE_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
- "length %u", len);
- return -1;
- }
- attr->enrollee_nonce = pos;
- break;
- case ATTR_REGISTRAR_NONCE:
- if (len != WPS_NONCE_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
- "length %u", len);
- return -1;
- }
- attr->registrar_nonce = pos;
- break;
- case ATTR_UUID_E:
- if (len != WPS_UUID_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
- len);
- return -1;
- }
- attr->uuid_e = pos;
- break;
- case ATTR_UUID_R:
- if (len != WPS_UUID_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
- len);
- return -1;
- }
- attr->uuid_r = pos;
- break;
- case ATTR_AUTH_TYPE_FLAGS:
- if (len != 2) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
- "Type Flags length %u", len);
- return -1;
- }
- attr->auth_type_flags = pos;
- break;
- case ATTR_ENCR_TYPE_FLAGS:
- if (len != 2) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
- "Flags length %u", len);
- return -1;
- }
- attr->encr_type_flags = pos;
- break;
- case ATTR_CONN_TYPE_FLAGS:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
- "Flags length %u", len);
- return -1;
- }
- attr->conn_type_flags = pos;
- break;
- case ATTR_CONFIG_METHODS:
- if (len != 2) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
- "length %u", len);
- return -1;
- }
- attr->config_methods = pos;
- break;
- case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
- if (len != 2) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
- "Registrar Config Methods length %u", len);
- return -1;
- }
- attr->sel_reg_config_methods = pos;
- break;
- case ATTR_PRIMARY_DEV_TYPE:
- if (len != sizeof(struct wps_dev_type)) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
- "Type length %u", len);
- return -1;
- }
- attr->primary_dev_type = pos;
- break;
- case ATTR_RF_BANDS:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
- "%u", len);
- return -1;
- }
- attr->rf_bands = pos;
- break;
- case ATTR_ASSOC_STATE:
- if (len != 2) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
- "length %u", len);
- return -1;
- }
- attr->assoc_state = pos;
- break;
- case ATTR_CONFIG_ERROR:
- if (len != 2) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
- "Error length %u", len);
- return -1;
- }
- attr->config_error = pos;
- break;
- case ATTR_DEV_PASSWORD_ID:
- if (len != 2) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
- "ID length %u", len);
- return -1;
- }
- attr->dev_password_id = pos;
- break;
- case ATTR_OS_VERSION:
- if (len != 4) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
- "%u", len);
- return -1;
- }
- attr->os_version = pos;
- break;
- case ATTR_WPS_STATE:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
- "Setup State length %u", len);
- return -1;
- }
- attr->wps_state = pos;
- break;
- case ATTR_AUTHENTICATOR:
- if (len != WPS_AUTHENTICATOR_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
- "length %u", len);
- return -1;
- }
- attr->authenticator = pos;
- break;
- case ATTR_R_HASH1:
- if (len != WPS_HASH_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
- len);
- return -1;
- }
- attr->r_hash1 = pos;
- break;
- case ATTR_R_HASH2:
- if (len != WPS_HASH_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
- len);
- return -1;
- }
- attr->r_hash2 = pos;
- break;
- case ATTR_E_HASH1:
- if (len != WPS_HASH_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
- len);
- return -1;
- }
- attr->e_hash1 = pos;
- break;
- case ATTR_E_HASH2:
- if (len != WPS_HASH_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
- len);
- return -1;
- }
- attr->e_hash2 = pos;
- break;
- case ATTR_R_SNONCE1:
- if (len != WPS_SECRET_NONCE_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
- "%u", len);
- return -1;
- }
- attr->r_snonce1 = pos;
- break;
- case ATTR_R_SNONCE2:
- if (len != WPS_SECRET_NONCE_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
- "%u", len);
- return -1;
- }
- attr->r_snonce2 = pos;
- break;
- case ATTR_E_SNONCE1:
- if (len != WPS_SECRET_NONCE_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
- "%u", len);
- return -1;
- }
- attr->e_snonce1 = pos;
- break;
- case ATTR_E_SNONCE2:
- if (len != WPS_SECRET_NONCE_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
- "%u", len);
- return -1;
- }
- attr->e_snonce2 = pos;
- break;
- case ATTR_KEY_WRAP_AUTH:
- if (len != WPS_KWA_LEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
- "Authenticator length %u", len);
- return -1;
- }
- attr->key_wrap_auth = pos;
- break;
- case ATTR_AUTH_TYPE:
- if (len != 2) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
- "Type length %u", len);
- return -1;
- }
- attr->auth_type = pos;
- break;
- case ATTR_ENCR_TYPE:
- if (len != 2) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
- "Type length %u", len);
- return -1;
- }
- attr->encr_type = pos;
- break;
- case ATTR_NETWORK_INDEX:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
- "length %u", len);
- return -1;
- }
- attr->network_idx = pos;
- break;
- case ATTR_NETWORK_KEY_INDEX:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
- "length %u", len);
- return -1;
- }
- attr->network_key_idx = pos;
- break;
- case ATTR_MAC_ADDR:
- if (len != ETH_ALEN) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
- "length %u", len);
- return -1;
- }
- attr->mac_addr = pos;
- break;
- case ATTR_KEY_PROVIDED_AUTO:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided "
- "Automatically length %u", len);
- return -1;
- }
- attr->key_prov_auto = pos;
- break;
- case ATTR_802_1X_ENABLED:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled "
- "length %u", len);
- return -1;
- }
- attr->dot1x_enabled = pos;
- break;
- case ATTR_SELECTED_REGISTRAR:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
- " length %u", len);
- return -1;
- }
- attr->selected_registrar = pos;
- break;
- case ATTR_REQUEST_TYPE:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
- "length %u", len);
- return -1;
- }
- attr->request_type = pos;
- break;
- case ATTR_RESPONSE_TYPE:
- if (len != 1) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
- "length %u", len);
- return -1;
- }
- attr->request_type = pos;
- break;
- case ATTR_MANUFACTURER:
- attr->manufacturer = pos;
- attr->manufacturer_len = len;
- break;
- case ATTR_MODEL_NAME:
- attr->model_name = pos;
- attr->model_name_len = len;
- break;
- case ATTR_MODEL_NUMBER:
- attr->model_number = pos;
- attr->model_number_len = len;
- break;
- case ATTR_SERIAL_NUMBER:
- attr->serial_number = pos;
- attr->serial_number_len = len;
- break;
- case ATTR_DEV_NAME:
- attr->dev_name = pos;
- attr->dev_name_len = len;
- break;
- case ATTR_PUBLIC_KEY:
- attr->public_key = pos;
- attr->public_key_len = len;
- break;
- case ATTR_ENCR_SETTINGS:
- attr->encr_settings = pos;
- attr->encr_settings_len = len;
- break;
- case ATTR_CRED:
- if (attr->num_cred >= MAX_CRED_COUNT) {
- wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
- "attribute (max %d credentials)",
- MAX_CRED_COUNT);
- break;
- }
- attr->cred[attr->num_cred] = pos;
- attr->cred_len[attr->num_cred] = len;
- attr->num_cred++;
- break;
- case ATTR_SSID:
- attr->ssid = pos;
- attr->ssid_len = len;
- break;
- case ATTR_NETWORK_KEY:
- attr->network_key = pos;
- attr->network_key_len = len;
- break;
- case ATTR_EAP_TYPE:
- attr->eap_type = pos;
- attr->eap_type_len = len;
- break;
- case ATTR_EAP_IDENTITY:
- attr->eap_identity = pos;
- attr->eap_identity_len = len;
- break;
- default:
- wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
- "len=%u", type, len);
- break;
- }
-
- return 0;
-}
-
-
-int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
-{
- const u8 *pos, *end;
- u16 type, len;
-
- os_memset(attr, 0, sizeof(*attr));
- pos = wpabuf_head(msg);
- end = pos + wpabuf_len(msg);
-
- while (pos < end) {
- if (end - pos < 4) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
- "%lu bytes remaining",
- (unsigned long) (end - pos));
- return -1;
- }
-
- type = WPA_GET_BE16(pos);
- pos += 2;
- len = WPA_GET_BE16(pos);
- pos += 2;
- wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u",
- type, len);
- if (len > end - pos) {
- wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
- return -1;
- }
-
- if (wps_set_attr(attr, type, pos, len) < 0)
- return -1;
-
- pos += len;
- }
-
- return 0;
-}
-
-
void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
const char *label, u8 *res, size_t res_len)
{
@@ -473,84 +62,6 @@ void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
}
-int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
-{
- struct wpabuf *pubkey;
-
- wpa_printf(MSG_DEBUG, "WPS: * Public Key");
- pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), &wps->dh_privkey);
- if (pubkey == NULL) {
- wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
- "Diffie-Hellman handshake");
- return -1;
- }
-
- wpabuf_put_be16(msg, ATTR_PUBLIC_KEY);
- wpabuf_put_be16(msg, wpabuf_len(pubkey));
- wpabuf_put_buf(msg, pubkey);
-
- if (wps->registrar) {
- wpabuf_free(wps->dh_pubkey_r);
- wps->dh_pubkey_r = pubkey;
- } else {
- wpabuf_free(wps->dh_pubkey_e);
- wps->dh_pubkey_e = pubkey;
- }
-
- return 0;
-}
-
-
-static int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Request Type");
- wpabuf_put_be16(msg, ATTR_REQUEST_TYPE);
- wpabuf_put_be16(msg, 1);
- wpabuf_put_u8(msg, type);
- return 0;
-}
-
-
-int wps_build_config_methods(struct wpabuf *msg, u16 methods)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods);
- wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
- wpabuf_put_be16(msg, 2);
- wpabuf_put_be16(msg, methods);
- return 0;
-}
-
-
-int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid)
-{
- wpa_printf(MSG_DEBUG, "WPS: * UUID-E");
- wpabuf_put_be16(msg, ATTR_UUID_E);
- wpabuf_put_be16(msg, WPS_UUID_LEN);
- wpabuf_put_data(msg, uuid, WPS_UUID_LEN);
- return 0;
-}
-
-
-int wps_build_dev_password_id(struct wpabuf *msg, u16 id)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id);
- wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
- wpabuf_put_be16(msg, 2);
- wpabuf_put_be16(msg, id);
- return 0;
-}
-
-
-int wps_build_config_error(struct wpabuf *msg, u16 err)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err);
- wpabuf_put_be16(msg, ATTR_CONFIG_ERROR);
- wpabuf_put_be16(msg, 2);
- wpabuf_put_be16(msg, err);
- return 0;
-}
-
-
struct wpabuf * wps_build_assoc_req_ie(void)
{
struct wpabuf *ie;
@@ -737,73 +248,6 @@ int wps_derive_mgmt_keys(struct wps_data *wps)
}
-int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg)
-{
- u8 hash[SHA256_MAC_LEN];
- const u8 *addr[2];
- size_t len[2];
-
- if (wps->last_msg == NULL) {
- wpa_printf(MSG_DEBUG, "WPS: Last message not available for "
- "building authenticator");
- return -1;
- }
-
- /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*)
- * (M_curr* is M_curr without the Authenticator attribute)
- */
- addr[0] = wpabuf_head(wps->last_msg);
- len[0] = wpabuf_len(wps->last_msg);
- addr[1] = wpabuf_head(msg);
- len[1] = wpabuf_len(msg);
- hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
-
- wpa_printf(MSG_DEBUG, "WPS: * Authenticator");
- wpabuf_put_be16(msg, ATTR_AUTHENTICATOR);
- wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN);
- wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN);
-
- return 0;
-}
-
-
-int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
- const struct wpabuf *msg)
-{
- u8 hash[SHA256_MAC_LEN];
- const u8 *addr[2];
- size_t len[2];
-
- if (authenticator == NULL) {
- wpa_printf(MSG_DEBUG, "WPS: No Authenticator attribute "
- "included");
- return -1;
- }
-
- if (wps->last_msg == NULL) {
- wpa_printf(MSG_DEBUG, "WPS: Last message not available for "
- "validating authenticator");
- return -1;
- }
-
- /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*)
- * (M_curr* is M_curr without the Authenticator attribute)
- */
- addr[0] = wpabuf_head(wps->last_msg);
- len[0] = wpabuf_len(wps->last_msg);
- addr[1] = wpabuf_head(msg);
- len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN;
- hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
-
- if (os_memcmp(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) {
- wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator");
- return -1;
- }
-
- return 0;
-}
-
-
void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
size_t dev_passwd_len)
{
@@ -874,373 +318,3 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
return decrypted;
}
-
-
-int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg,
- const u8 *key_wrap_auth)
-{
- u8 hash[SHA256_MAC_LEN];
- const u8 *head;
- size_t len;
-
- if (key_wrap_auth == NULL) {
- wpa_printf(MSG_DEBUG, "WPS: No KWA in decrypted attribute");
- return -1;
- }
-
- head = wpabuf_head(msg);
- len = wpabuf_len(msg) - 4 - WPS_KWA_LEN;
- if (head + len != key_wrap_auth - 4) {
- wpa_printf(MSG_DEBUG, "WPS: KWA not in the end of the "
- "decrypted attribute");
- return -1;
- }
-
- hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash);
- if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) {
- wpa_printf(MSG_DEBUG, "WPS: Invalid KWA");
- return -1;
- }
-
- return 0;
-}
-
-
-int wps_build_version(struct wpabuf *msg)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Version");
- wpabuf_put_be16(msg, ATTR_VERSION);
- wpabuf_put_be16(msg, 1);
- wpabuf_put_u8(msg, WPS_VERSION);
- return 0;
-}
-
-
-int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type);
- wpabuf_put_be16(msg, ATTR_MSG_TYPE);
- wpabuf_put_be16(msg, 1);
- wpabuf_put_u8(msg, msg_type);
- return 0;
-}
-
-
-int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce");
- wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE);
- wpabuf_put_be16(msg, WPS_NONCE_LEN);
- wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN);
- return 0;
-}
-
-
-int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce");
- wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
- wpabuf_put_be16(msg, WPS_NONCE_LEN);
- wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN);
- return 0;
-}
-
-
-int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags");
- wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS);
- wpabuf_put_be16(msg, 2);
- wpabuf_put_be16(msg, WPS_AUTH_TYPES);
- return 0;
-}
-
-
-int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags");
- wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS);
- wpabuf_put_be16(msg, 2);
- wpabuf_put_be16(msg, WPS_ENCR_TYPES);
- return 0;
-}
-
-
-int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags");
- wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS);
- wpabuf_put_be16(msg, 1);
- wpabuf_put_u8(msg, WPS_CONN_ESS);
- return 0;
-}
-
-
-int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg)
-{
- wpa_printf(MSG_DEBUG, "WPS: * Association State");
- wpabuf_put_be16(msg, ATTR_ASSOC_STATE);
- wpabuf_put_be16(msg, 2);
- wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC);
- return 0;
-}
-
-
-int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg)
-{
- u8 hash[SHA256_MAC_LEN];
-
- wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator");
- hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg),
- wpabuf_len(msg), hash);
-
- wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH);
- wpabuf_put_be16(msg, WPS_KWA_LEN);
- wpabuf_put_data(msg, hash, WPS_KWA_LEN);
- return 0;
-}
-
-
-int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
- struct wpabuf *plain)
-{
- size_t pad_len;
- const size_t block_size = 16;
- u8 *iv, *data;
-
- wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings");
-
- /* PKCS#5 v2.0 pad */
- pad_len = block_size - wpabuf_len(plain) % block_size;
- os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len);
-
- wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS);
- wpabuf_put_be16(msg, block_size + wpabuf_len(plain));
-
- iv = wpabuf_put(msg, block_size);
- if (os_get_random(iv, block_size) < 0)
- return -1;
-
- data = wpabuf_put(msg, 0);
- wpabuf_put_buf(msg, plain);
- if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain)))
- return -1;
-
- return 0;
-}
-
-
-static int wps_process_cred_network_idx(struct wps_credential *cred,
- const u8 *idx)
-{
- if (idx == NULL) {
- wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
- "Network Index");
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx);
-
- return 0;
-}
-
-
-static int wps_process_cred_ssid(struct wps_credential *cred, const u8 *ssid,
- size_t ssid_len)
-{
- if (ssid == NULL) {
- wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID");
- return -1;
- }
-
- /* Remove zero-padding since some Registrar implementations seem to use
- * hardcoded 32-octet length for this attribute */
- while (ssid_len > 0 && ssid[ssid_len - 1] == 0)
- ssid_len--;
-
- wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", ssid, ssid_len);
- if (ssid_len <= sizeof(cred->ssid)) {
- os_memcpy(cred->ssid, ssid, ssid_len);
- cred->ssid_len = ssid_len;
- }
-
- return 0;
-}
-
-
-static int wps_process_cred_auth_type(struct wps_credential *cred,
- const u8 *auth_type)
-{
- if (auth_type == NULL) {
- wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
- "Authentication Type");
- return -1;
- }
-
- cred->auth_type = WPA_GET_BE16(auth_type);
- wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x",
- cred->auth_type);
-
- return 0;
-}
-
-
-static int wps_process_cred_encr_type(struct wps_credential *cred,
- const u8 *encr_type)
-{
- if (encr_type == NULL) {
- wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
- "Encryption Type");
- return -1;
- }
-
- cred->encr_type = WPA_GET_BE16(encr_type);
- wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x",
- cred->encr_type);
-
- return 0;
-}
-
-
-static int wps_process_cred_network_key_idx(struct wps_credential *cred,
- const u8 *key_idx)
-{
- if (key_idx == NULL)
- return 0; /* optional attribute */
-
- wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx);
- cred->key_idx = *key_idx;
-
- return 0;
-}
-
-
-static int wps_process_cred_network_key(struct wps_credential *cred,
- const u8 *key, size_t key_len)
-{
- if (key == NULL) {
- wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
- "Network Key");
- return -1;
- }
-
- wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", key, key_len);
- if (key_len <= sizeof(cred->key)) {
- os_memcpy(cred->key, key, key_len);
- cred->key_len = key_len;
- }
-
- return 0;
-}
-
-
-static int wps_process_cred_mac_addr(struct wps_credential *cred,
- const u8 *mac_addr)
-{
- if (mac_addr == NULL) {
- wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
- "MAC Address");
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr));
- os_memcpy(cred->mac_addr, mac_addr, ETH_ALEN);
-
- return 0;
-}
-
-
-static int wps_process_cred_eap_type(struct wps_credential *cred,
- const u8 *eap_type, size_t eap_type_len)
-{
- if (eap_type == NULL)
- return 0; /* optional attribute */
-
- wpa_hexdump(MSG_DEBUG, "WPS: EAP Type", eap_type, eap_type_len);
-
- return 0;
-}
-
-
-static int wps_process_cred_eap_identity(struct wps_credential *cred,
- const u8 *identity,
- size_t identity_len)
-{
- if (identity == NULL)
- return 0; /* optional attribute */
-
- wpa_hexdump_ascii(MSG_DEBUG, "WPS: EAP Identity",
- identity, identity_len);
-
- return 0;
-}
-
-
-static int wps_process_cred_key_prov_auto(struct wps_credential *cred,
- const u8 *key_prov_auto)
-{
- if (key_prov_auto == NULL)
- return 0; /* optional attribute */
-
- wpa_printf(MSG_DEBUG, "WPS: Key Provided Automatically: %d",
- *key_prov_auto);
-
- return 0;
-}
-
-
-static int wps_process_cred_802_1x_enabled(struct wps_credential *cred,
- const u8 *dot1x_enabled)
-{
- if (dot1x_enabled == NULL)
- return 0; /* optional attribute */
-
- wpa_printf(MSG_DEBUG, "WPS: 802.1X Enabled: %d", *dot1x_enabled);
-
- return 0;
-}
-
-
-int wps_process_cred(struct wps_parse_attr *attr,
- struct wps_credential *cred)
-{
- wpa_printf(MSG_DEBUG, "WPS: Process Credential");
-
- /* TODO: support multiple Network Keys */
- if (wps_process_cred_network_idx(cred, attr->network_idx) ||
- wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) ||
- wps_process_cred_auth_type(cred, attr->auth_type) ||
- wps_process_cred_encr_type(cred, attr->encr_type) ||
- wps_process_cred_network_key_idx(cred, attr->network_key_idx) ||
- wps_process_cred_network_key(cred, attr->network_key,
- attr->network_key_len) ||
- wps_process_cred_mac_addr(cred, attr->mac_addr) ||
- wps_process_cred_eap_type(cred, attr->eap_type,
- attr->eap_type_len) ||
- wps_process_cred_eap_identity(cred, attr->eap_identity,
- attr->eap_identity_len) ||
- wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) ||
- wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled))
- return -1;
-
- return 0;
-}
-
-
-int wps_process_ap_settings(struct wps_parse_attr *attr,
- struct wps_credential *cred)
-{
- wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings");
- os_memset(cred, 0, sizeof(*cred));
- /* TODO: optional attributes New Password and Device Password ID */
- if (wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) ||
- wps_process_cred_auth_type(cred, attr->auth_type) ||
- wps_process_cred_encr_type(cred, attr->encr_type) ||
- wps_process_cred_network_key_idx(cred, attr->network_key_idx) ||
- wps_process_cred_network_key(cred, attr->network_key,
- attr->network_key_len) ||
- wps_process_cred_mac_addr(cred, attr->mac_addr))
- return -1;
-
- return 0;
-}
diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h
index 2c2c364..693a24f 100644
--- a/src/wps/wps_i.h
+++ b/src/wps/wps_i.h
@@ -155,25 +155,26 @@ struct wps_parse_attr {
};
/* wps_common.c */
-int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
const char *label, u8 *res, size_t res_len);
-int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg);
-int wps_build_config_methods(struct wpabuf *msg, u16 methods);
-int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid);
-int wps_build_dev_password_id(struct wpabuf *msg, u16 id);
-int wps_build_config_error(struct wpabuf *msg, u16 err);
int wps_derive_keys(struct wps_data *wps);
int wps_derive_mgmt_keys(struct wps_data *wps);
-int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg);
-int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
- const struct wpabuf *msg);
void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
size_t dev_passwd_len);
struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
size_t encr_len);
-int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg,
- const u8 *key_wrap_auth);
+
+/* wps_attr_parse.c */
+int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
+
+/* wps_attr_build.c */
+int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg);
+int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type);
+int wps_build_config_methods(struct wpabuf *msg, u16 methods);
+int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid);
+int wps_build_dev_password_id(struct wpabuf *msg, u16 id);
+int wps_build_config_error(struct wpabuf *msg, u16 err);
+int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg);
int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg);
int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
struct wpabuf *plain);
@@ -185,6 +186,12 @@ int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg);
int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg);
int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg);
int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg);
+
+/* wps_attr_process.c */
+int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
+ const struct wpabuf *msg);
+int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg,
+ const u8 *key_wrap_auth);
int wps_process_cred(struct wps_parse_attr *attr,
struct wps_credential *cred);
int wps_process_ap_settings(struct wps_parse_attr *attr,