WPS 2.0: Add new attributes and update version negotiation

This adds definitions and parsing of the new attributes that were added
in WPS 2.0. In addition, the version negotiation is updated to use the
new mechanism, i.e., accept everything received and use the new Version2
attribute in transmitted messages.
This commit is contained in:
Jouni Malinen 2009-12-11 18:00:10 +02:00 committed by Jouni Malinen
parent 266c828e54
commit f439079e93
11 changed files with 124 additions and 75 deletions

View file

@ -307,7 +307,8 @@ struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type)
wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
if (wps_build_version(ie) ||
wps_build_req_type(ie, req_type)) {
wps_build_req_type(ie, req_type) ||
wps_build_version2(ie)) {
wpabuf_free(ie);
return NULL;
}
@ -340,7 +341,8 @@ struct wpabuf * wps_build_assoc_resp_ie(void)
wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
if (wps_build_version(ie) ||
wps_build_resp_type(ie, WPS_RESP_AP)) {
wps_build_resp_type(ie, WPS_RESP_AP) ||
wps_build_version2(ie)) {
wpabuf_free(ie);
return NULL;
}
@ -401,7 +403,8 @@ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev,
wps_build_assoc_state(NULL, ie) ||
wps_build_config_error(ie, WPS_CFG_NO_ERROR) ||
wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON :
DEV_PW_DEFAULT)) {
DEV_PW_DEFAULT) ||
wps_build_version2(ie)) {
wpabuf_free(ie);
return NULL;
}

View file

@ -158,9 +158,24 @@ int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg)
int wps_build_version(struct wpabuf *msg)
{
wpa_printf(MSG_DEBUG, "WPS: * Version");
/*
* Note: This attribute is deprecated and set to hardcoded 0x10 for
* backwards compatibility reasons. The real version negotiation is
* done with Version2.
*/
wpa_printf(MSG_DEBUG, "WPS: * Version (hardcoded 0x10)");
wpabuf_put_be16(msg, ATTR_VERSION);
wpabuf_put_be16(msg, 1);
wpabuf_put_u8(msg, 0x10);
return 0;
}
int wps_build_version2(struct wpabuf *msg)
{
wpa_printf(MSG_DEBUG, "WPS: * Version2 (0x%x)", WPS_VERSION);
wpabuf_put_be16(msg, ATTR_VERSION2);
wpabuf_put_be16(msg, 1);
wpabuf_put_u8(msg, WPS_VERSION);
return 0;
}

View file

@ -32,6 +32,14 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
}
attr->version = pos;
break;
case ATTR_VERSION2:
if (len != 1) {
wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length "
"%u", len);
return -1;
}
attr->version2 = pos;
break;
case ATTR_MSG_TYPE:
if (len != 1) {
wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
@ -399,6 +407,49 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
}
attr->ap_setup_locked = pos;
break;
case ATTR_SETTINGS_DELAY_TIME:
if (len != 1) {
wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay "
"Time length %u", len);
return -1;
}
attr->settings_delay_time = pos;
break;
case ATTR_NETWORK_KEY_SHAREABLE:
if (len != 1) {
wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key "
"Shareable length %u", len);
return -1;
}
attr->network_key_shareable = pos;
break;
case ATTR_REQUEST_TO_ENROLL:
if (len != 1) {
wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll "
"length %u", len);
return -1;
}
attr->request_to_enroll = pos;
break;
case ATTR_AUTHORIZED_MACS:
attr->authorized_macs = pos;
attr->authorized_macs_len = len;
break;
case ATTR_REQUESTED_DEV_TYPE:
if (len != WPS_DEV_TYPE_LEN) {
wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device "
"Type length %u", len);
return -1;
}
if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) {
wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device "
"Type attribute (max %u types)",
MAX_REQ_DEV_TYPE_COUNT);
break;
}
attr->req_dev_type[attr->num_req_dev_type] = pos;
attr->num_req_dev_type++;
break;
default:
wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
"len=%u", type, len);

View file

@ -327,7 +327,9 @@ static struct wpabuf * wps_get_oob_cred(struct wps_context *wps)
data.wps = wps;
data.auth_type = wps->auth_types;
data.encr_type = wps->encr_types;
if (wps_build_version(plain) || wps_build_cred(&data, plain)) {
if (wps_build_version(plain) ||
wps_build_cred(&data, plain) ||
wps_build_version2(plain)) {
wpabuf_free(plain);
return NULL;
}
@ -358,7 +360,8 @@ static struct wpabuf * wps_get_oob_dev_pwd(struct wps_context *wps)
}
if (wps_build_version(data) ||
wps_build_oob_dev_password(data, wps)) {
wps_build_oob_dev_password(data, wps) ||
wps_build_version2(data)) {
wpa_printf(MSG_ERROR, "WPS: Build OOB device password "
"attribute error");
wpabuf_free(data);

View file

@ -15,7 +15,7 @@
#ifndef WPS_DEFS_H
#define WPS_DEFS_H
#define WPS_VERSION 0x10
#define WPS_VERSION 0x20
/* Diffie-Hellman 1536-bit MODP Group; RFC 3526, Group 5 */
#define WPS_DH_GROUP 5
@ -124,7 +124,13 @@ enum wps_attribute {
ATTR_KEY_PROVIDED_AUTO = 0x1061,
ATTR_802_1X_ENABLED = 0x1062,
ATTR_APPSESSIONKEY = 0x1063,
ATTR_WEPTRANSMITKEY = 0x1064
ATTR_WEPTRANSMITKEY = 0x1064,
ATTR_SETTINGS_DELAY_TIME = 0x1065,
ATTR_NETWORK_KEY_SHAREABLE = 0x1066,
ATTR_VERSION2 = 0x1067,
ATTR_REQUEST_TO_ENROLL = 0x1068,
ATTR_AUTHORIZED_MACS = 0x1069,
ATTR_REQUESTED_DEV_TYPE = 0x106a
};
/* Device Password ID */

View file

@ -146,7 +146,8 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps)
wps_build_assoc_state(wps, msg) ||
wps_build_dev_password_id(msg, wps->dev_pw_id) ||
wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
wps_build_os_version(&wps->wps->dev, msg)) {
wps_build_os_version(&wps->wps->dev, msg) ||
wps_build_version2(msg)) {
wpabuf_free(msg);
return NULL;
}
@ -176,6 +177,7 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps)
wps_build_msg_type(msg, WPS_M3) ||
wps_build_registrar_nonce(wps, msg) ||
wps_build_e_hash(wps, msg) ||
wps_build_version2(msg) ||
wps_build_authenticator(wps, msg)) {
wpabuf_free(msg);
return NULL;
@ -208,6 +210,7 @@ static struct wpabuf * wps_build_m5(struct wps_data *wps)
wps_build_e_snonce1(wps, plain) ||
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain) ||
wps_build_version2(msg) ||
wps_build_authenticator(wps, msg)) {
wpabuf_free(plain);
wpabuf_free(msg);
@ -310,6 +313,7 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps)
(wps->wps->ap && wps_build_ap_settings(wps, plain)) ||
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain) ||
wps_build_version2(msg) ||
wps_build_authenticator(wps, msg)) {
wpabuf_free(plain);
wpabuf_free(msg);
@ -345,7 +349,8 @@ static struct wpabuf * wps_build_wsc_done(struct wps_data *wps)
if (wps_build_version(msg) ||
wps_build_msg_type(msg, WPS_WSC_DONE) ||
wps_build_enrollee_nonce(wps, msg) ||
wps_build_registrar_nonce(wps, msg)) {
wps_build_registrar_nonce(wps, msg) ||
wps_build_version2(msg)) {
wpabuf_free(msg);
return NULL;
}
@ -373,7 +378,8 @@ static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps)
if (wps_build_version(msg) ||
wps_build_msg_type(msg, WPS_WSC_ACK) ||
wps_build_enrollee_nonce(wps, msg) ||
wps_build_registrar_nonce(wps, msg)) {
wps_build_registrar_nonce(wps, msg) ||
wps_build_version2(msg)) {
wpabuf_free(msg);
return NULL;
}
@ -396,7 +402,8 @@ static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
wps_build_msg_type(msg, WPS_WSC_NACK) ||
wps_build_enrollee_nonce(wps, msg) ||
wps_build_registrar_nonce(wps, msg) ||
wps_build_config_error(msg, wps->config_error)) {
wps_build_config_error(msg, wps->config_error) ||
wps_build_version2(msg)) {
wpabuf_free(msg);
return NULL;
}
@ -1011,12 +1018,6 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
if (wps_parse_msg(msg, &attr) < 0)
return WPS_FAILURE;
if (!wps_version_supported(attr.version)) {
wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
attr.version ? *attr.version : 0);
return WPS_FAILURE;
}
if (attr.enrollee_nonce == NULL ||
os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) {
wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
@ -1084,12 +1085,6 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
if (wps_parse_msg(msg, &attr) < 0)
return WPS_FAILURE;
if (!wps_version_supported(attr.version)) {
wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
attr.version ? *attr.version : 0);
return WPS_FAILURE;
}
if (attr.msg_type == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
return WPS_FAILURE;
@ -1136,12 +1131,6 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps,
if (wps_parse_msg(msg, &attr) < 0)
return WPS_FAILURE;
if (!wps_version_supported(attr.version)) {
wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
attr.version ? *attr.version : 0);
return WPS_FAILURE;
}
if (attr.msg_type == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
return WPS_FAILURE;

View file

@ -1362,7 +1362,8 @@ void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
if (wps_build_version(msg) ||
wps_er_build_selected_registrar(msg, sel_reg) ||
wps_er_build_dev_password_id(msg, dev_passwd_id) ||
wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods)) {
wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods) ||
wps_build_version2(msg)) {
wpabuf_free(msg);
return;
}

View file

@ -122,6 +122,7 @@ struct wps_data {
struct wps_parse_attr {
/* fixed length fields */
const u8 *version; /* 1 octet */
const u8 *version2; /* 1 octet */
const u8 *msg_type; /* 1 octet */
const u8 *enrollee_nonce; /* WPS_NONCE_LEN (16) octets */
const u8 *registrar_nonce; /* WPS_NONCE_LEN (16) octets */
@ -162,6 +163,9 @@ struct wps_parse_attr {
const u8 *request_type; /* 1 octet */
const u8 *response_type; /* 1 octet */
const u8 *ap_setup_locked; /* 1 octet */
const u8 *settings_delay_time; /* 1 octet */
const u8 *network_key_shareable; /* 1 octet (Bool) */
const u8 *request_to_enroll; /* 1 octet (Bool) */
/* variable length fields */
const u8 *manufacturer;
@ -186,12 +190,18 @@ struct wps_parse_attr {
size_t eap_type_len;
const u8 *eap_identity; /* <= 64 octets */
size_t eap_identity_len;
const u8 *authorized_macs; /* <= 30 octets */
size_t authorized_macs_len;
/* attributes that can occur multiple times */
#define MAX_CRED_COUNT 10
const u8 *cred[MAX_CRED_COUNT];
size_t cred_len[MAX_CRED_COUNT];
size_t num_cred;
#define MAX_REQ_DEV_TYPE_COUNT 10
const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT];
size_t num_req_dev_type;
};
/* wps_common.c */
@ -228,6 +238,7 @@ 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);
int wps_build_version(struct wpabuf *msg);
int wps_build_version2(struct wpabuf *msg);
int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type);
int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg);
int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg);
@ -269,10 +280,4 @@ void wps_registrar_selected_registrar_changed(struct wps_registrar *reg);
struct wpabuf * ndef_parse_wifi(struct wpabuf *buf);
struct wpabuf * ndef_build_wifi(struct wpabuf *buf);
static inline int wps_version_supported(const u8 *version)
{
/* Require major version match, but allow minor version differences */
return version && (*version & 0xf0) == (WPS_VERSION & 0xf0);
}
#endif /* WPS_I_H */

View file

@ -755,11 +755,6 @@ void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr,
if (wps_parse_msg(wps_data, &attr) < 0)
return;
if (!wps_version_supported(attr.version)) {
wpa_printf(MSG_DEBUG, "WPS: Unsupported ProbeReq WPS IE "
"version 0x%x", attr.version ? *attr.version : 0);
return;
}
if (attr.config_methods == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No Config Methods attribute in "
@ -923,6 +918,7 @@ static int wps_set_ie(struct wps_registrar *reg)
wps_build_selected_registrar(reg, beacon) ||
wps_build_sel_reg_dev_password_id(reg, beacon) ||
wps_build_sel_reg_config_methods(reg, beacon) ||
wps_build_version2(beacon) ||
wps_build_version(probe) ||
wps_build_wps_state(reg->wps, probe) ||
wps_build_ap_setup_locked(reg->wps, probe) ||
@ -934,7 +930,8 @@ static int wps_set_ie(struct wps_registrar *reg)
wps_build_uuid_e(probe, reg->wps->uuid) ||
wps_build_device_attrs(&reg->wps->dev, probe) ||
wps_build_probe_config_methods(reg, probe) ||
wps_build_rf_bands(&reg->wps->dev, probe)) {
wps_build_rf_bands(&reg->wps->dev, probe) ||
wps_build_version2(probe)) {
wpabuf_free(beacon);
wpabuf_free(probe);
return -1;
@ -1350,6 +1347,7 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps)
wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
wps_build_dev_password_id(msg, wps->dev_pw_id) ||
wps_build_os_version(&wps->wps->dev, msg) ||
wps_build_version2(msg) ||
wps_build_authenticator(wps, msg)) {
wpabuf_free(msg);
return NULL;
@ -1388,7 +1386,8 @@ static struct wpabuf * wps_build_m2d(struct wps_data *wps)
wps_build_rf_bands(&wps->wps->dev, msg) ||
wps_build_assoc_state(wps, msg) ||
wps_build_config_error(msg, err) ||
wps_build_os_version(&wps->wps->dev, msg)) {
wps_build_os_version(&wps->wps->dev, msg) ||
wps_build_version2(msg)) {
wpabuf_free(msg);
return NULL;
}
@ -1423,6 +1422,7 @@ static struct wpabuf * wps_build_m4(struct wps_data *wps)
wps_build_r_snonce1(wps, plain) ||
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain) ||
wps_build_version2(msg) ||
wps_build_authenticator(wps, msg)) {
wpabuf_free(plain);
wpabuf_free(msg);
@ -1457,6 +1457,7 @@ static struct wpabuf * wps_build_m6(struct wps_data *wps)
wps_build_r_snonce2(wps, plain) ||
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain) ||
wps_build_version2(msg) ||
wps_build_authenticator(wps, msg)) {
wpabuf_free(plain);
wpabuf_free(msg);
@ -1493,6 +1494,7 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps)
(!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) ||
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain) ||
wps_build_version2(msg) ||
wps_build_authenticator(wps, msg)) {
wpabuf_free(plain);
wpabuf_free(msg);
@ -1518,7 +1520,8 @@ static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps)
if (wps_build_version(msg) ||
wps_build_msg_type(msg, WPS_WSC_ACK) ||
wps_build_enrollee_nonce(wps, msg) ||
wps_build_registrar_nonce(wps, msg)) {
wps_build_registrar_nonce(wps, msg) ||
wps_build_version2(msg)) {
wpabuf_free(msg);
return NULL;
}
@ -1541,7 +1544,8 @@ static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
wps_build_msg_type(msg, WPS_WSC_NACK) ||
wps_build_enrollee_nonce(wps, msg) ||
wps_build_registrar_nonce(wps, msg) ||
wps_build_config_error(msg, wps->config_error)) {
wps_build_config_error(msg, wps->config_error) ||
wps_build_version2(msg)) {
wpabuf_free(msg);
return NULL;
}
@ -2362,12 +2366,6 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
if (wps_parse_msg(msg, &attr) < 0)
return WPS_FAILURE;
if (!wps_version_supported(attr.version)) {
wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
attr.version ? *attr.version : 0);
return WPS_FAILURE;
}
if (attr.msg_type == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
return WPS_FAILURE;
@ -2438,12 +2436,6 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
if (wps_parse_msg(msg, &attr) < 0)
return WPS_FAILURE;
if (!wps_version_supported(attr.version)) {
wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
attr.version ? *attr.version : 0);
return WPS_FAILURE;
}
if (attr.msg_type == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
return WPS_FAILURE;
@ -2515,12 +2507,6 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps,
if (wps_parse_msg(msg, &attr) < 0)
return WPS_FAILURE;
if (!wps_version_supported(attr.version)) {
wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
attr.version ? *attr.version : 0);
return WPS_FAILURE;
}
if (attr.msg_type == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
return WPS_FAILURE;
@ -2600,12 +2586,6 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps,
if (wps_parse_msg(msg, &attr) < 0)
return WPS_FAILURE;
if (!wps_version_supported(attr.version)) {
wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
attr.version ? *attr.version : 0);
return WPS_FAILURE;
}
if (attr.msg_type == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
return WPS_FAILURE;

View file

@ -578,6 +578,7 @@ static struct wpabuf * build_fake_wsc_ack(void)
wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
wpabuf_put_be16(msg, WPS_NONCE_LEN);
wpabuf_put(msg, WPS_NONCE_LEN);
wps_build_version2(msg);
return msg;
}

View file

@ -42,11 +42,6 @@ int upnp_er_set_selected_registrar(struct wps_registrar *reg,
if (wps_parse_msg(msg, &attr) < 0)
return -1;
if (!wps_version_supported(attr.version)) {
wpa_printf(MSG_DEBUG, "WPS: Unsupported SetSelectedRegistrar "
"version 0x%x", attr.version ? *attr.version : 0);
return -1;
}
s->reg = reg;
eloop_cancel_timeout(upnp_er_set_selected_timeout, s, NULL);