WPS: Add UFD support (USBA out-of-band mechanism)
This patch is only for the following use case: - Enrollee = wpa_supplicant - Registrar = hostapd internal Registrar Following UFD methods can be used: - Enrollee PIN with UFD - Registrar PIN with UFD - unencrypted credential with UFD Encrypted credentials are not supported. Enrollee side operation: wpa_cli -i ath0 wps_oob <device type> <mount point> <oob method> oob method = pin-e/pin-r/cred wpa_cli -i ath0 wps_oob ufd /mnt/ pin-r Registrar side operation: ./hostapd_cli -i ath0 wps_oob <device type> <mount point> <oob method> oob method = pin-e/pin-r/cred hostapd_cli -i ath0 wps_oob ufd /mnt/ cred
This commit is contained in:
parent
b414900a90
commit
46bdb83acd
20 changed files with 734 additions and 10 deletions
|
@ -313,6 +313,7 @@ OBJS += ../src/wps/wps_attr_process.o
|
||||||
OBJS += ../src/wps/wps_dev_attr.o
|
OBJS += ../src/wps/wps_dev_attr.o
|
||||||
OBJS += ../src/wps/wps_enrollee.o
|
OBJS += ../src/wps/wps_enrollee.o
|
||||||
OBJS += ../src/wps/wps_registrar.o
|
OBJS += ../src/wps/wps_registrar.o
|
||||||
|
OBJS += ../src/wps/wps_ufd.o
|
||||||
NEED_DH_GROUPS=y
|
NEED_DH_GROUPS=y
|
||||||
NEED_SHA256=y
|
NEED_SHA256=y
|
||||||
NEED_CRYPTO=y
|
NEED_CRYPTO=y
|
||||||
|
|
|
@ -252,6 +252,24 @@ static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
|
||||||
*pin++ = '\0';
|
*pin++ = '\0';
|
||||||
return hostapd_wps_add_pin(hapd, txt, pin);
|
return hostapd_wps_add_pin(hapd, txt, pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
|
||||||
|
{
|
||||||
|
char *path, *method;
|
||||||
|
|
||||||
|
path = os_strchr(txt, ' ');
|
||||||
|
if (path == NULL)
|
||||||
|
return -1;
|
||||||
|
*path++ = '\0';
|
||||||
|
|
||||||
|
method = os_strchr(path, ' ');
|
||||||
|
if (method == NULL)
|
||||||
|
return -1;
|
||||||
|
*method++ = '\0';
|
||||||
|
|
||||||
|
return hostapd_wps_start_oob(hapd, txt, path, method);
|
||||||
|
}
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
|
|
||||||
|
@ -350,6 +368,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
|
||||||
} else if (os_strcmp(buf, "WPS_PBC") == 0) {
|
} else if (os_strcmp(buf, "WPS_PBC") == 0) {
|
||||||
if (hostapd_wps_button_pushed(hapd))
|
if (hostapd_wps_button_pushed(hapd))
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
|
||||||
|
if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8))
|
||||||
|
reply_len = -1;
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
} else {
|
} else {
|
||||||
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
||||||
|
|
|
@ -89,6 +89,7 @@ static const char *commands_help =
|
||||||
#ifdef CONFIG_WPS
|
#ifdef CONFIG_WPS
|
||||||
" wps_pin <uuid> <pin> add WPS Enrollee PIN (Device Password)\n"
|
" wps_pin <uuid> <pin> add WPS Enrollee PIN (Device Password)\n"
|
||||||
" wps_pbc indicate button pushed to initiate PBC\n"
|
" wps_pbc indicate button pushed to initiate PBC\n"
|
||||||
|
" wps_oob <type> <path> <method> use WPS with out-of-band (UFD)\n"
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
" help show this usage help\n"
|
" help show this usage help\n"
|
||||||
" interface [ifname] show interfaces/select interface\n"
|
" interface [ifname] show interfaces/select interface\n"
|
||||||
|
@ -275,6 +276,31 @@ static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
|
||||||
{
|
{
|
||||||
return wpa_ctrl_command(ctrl, "WPS_PBC");
|
return wpa_ctrl_command(ctrl, "WPS_PBC");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
char cmd[256];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
printf("Invalid WPS_OOB command: need three arguments:\n"
|
||||||
|
"- OOB_DEV_TYPE: use 'ufd'\n"
|
||||||
|
"- OOB_PATH: path of OOB device like '/mnt'\n"
|
||||||
|
"- OOB_METHOD: OOB method 'pin-e' or 'pin-r', "
|
||||||
|
"'cred'\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
|
||||||
|
argv[0], argv[1], argv[2]);
|
||||||
|
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||||
|
printf("Too long WPS_OOB command.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return wpa_ctrl_command(ctrl, cmd);
|
||||||
|
}
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
|
|
||||||
|
@ -432,6 +458,7 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
||||||
#ifdef CONFIG_WPS
|
#ifdef CONFIG_WPS
|
||||||
{ "wps_pin", hostapd_cli_cmd_wps_pin },
|
{ "wps_pin", hostapd_cli_cmd_wps_pin },
|
||||||
{ "wps_pbc", hostapd_cli_cmd_wps_pbc },
|
{ "wps_pbc", hostapd_cli_cmd_wps_pbc },
|
||||||
|
{ "wps_oob", hostapd_cli_cmd_wps_oob },
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
{ "help", hostapd_cli_cmd_help },
|
{ "help", hostapd_cli_cmd_help },
|
||||||
{ "interface", hostapd_cli_cmd_interface },
|
{ "interface", hostapd_cli_cmd_interface },
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "wps/wps_defs.h"
|
#include "wps/wps_defs.h"
|
||||||
#include "wps/wps_dev_attr.h"
|
#include "wps/wps_dev_attr.h"
|
||||||
#include "wps_hostapd.h"
|
#include "wps_hostapd.h"
|
||||||
|
#include "dh_groups.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_WPS_UPNP
|
#ifdef CONFIG_WPS_UPNP
|
||||||
|
@ -648,6 +649,16 @@ int hostapd_init_wps(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_WPS_UPNP */
|
#endif /* CONFIG_WPS_UPNP */
|
||||||
|
|
||||||
|
wps->dh_pubkey = dh_init(dh_groups_get(WPS_DH_GROUP),
|
||||||
|
&wps->dh_privkey);
|
||||||
|
wps->dh_pubkey = wpabuf_zeropad(wps->dh_pubkey, 192);
|
||||||
|
if (wps->dh_pubkey == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Failed to initialize "
|
||||||
|
"Diffie-Hellman handshake");
|
||||||
|
os_free(wps);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
hapd->wps = wps;
|
hapd->wps = wps;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -664,6 +675,8 @@ void hostapd_deinit_wps(struct hostapd_data *hapd)
|
||||||
wps_registrar_deinit(hapd->wps->registrar);
|
wps_registrar_deinit(hapd->wps->registrar);
|
||||||
os_free(hapd->wps->network_key);
|
os_free(hapd->wps->network_key);
|
||||||
wps_device_data_free(&hapd->wps->dev);
|
wps_device_data_free(&hapd->wps->dev);
|
||||||
|
wpabuf_free(hapd->wps->dh_pubkey);
|
||||||
|
wpabuf_free(hapd->wps->dh_privkey);
|
||||||
wps_free_pending_msgs(hapd->wps->upnp_msgs);
|
wps_free_pending_msgs(hapd->wps->upnp_msgs);
|
||||||
os_free(hapd->wps);
|
os_free(hapd->wps);
|
||||||
hapd->wps = NULL;
|
hapd->wps = NULL;
|
||||||
|
@ -696,6 +709,30 @@ int hostapd_wps_button_pushed(struct hostapd_data *hapd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
|
||||||
|
char *path, char *method)
|
||||||
|
{
|
||||||
|
struct wps_context *wps = hapd->wps;
|
||||||
|
|
||||||
|
wps->oob_dev = wps_get_oob_device(device_type);
|
||||||
|
if (wps->oob_dev == NULL)
|
||||||
|
return -1;
|
||||||
|
wps->oob_dev->device_path = path;
|
||||||
|
wps->oob_conf.oob_method = wps_get_oob_method(method);
|
||||||
|
|
||||||
|
if (wps_process_oob(wps, 1) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ||
|
||||||
|
wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) &&
|
||||||
|
hostapd_wps_add_pin(hapd, "any",
|
||||||
|
wpabuf_head(wps->oob_conf.dev_password)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr,
|
void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr,
|
||||||
const u8 *ie, size_t ie_len)
|
const u8 *ie, size_t ie_len)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,8 @@ void hostapd_deinit_wps(struct hostapd_data *hapd);
|
||||||
int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
|
int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
|
||||||
const char *pin);
|
const char *pin);
|
||||||
int hostapd_wps_button_pushed(struct hostapd_data *hapd);
|
int hostapd_wps_button_pushed(struct hostapd_data *hapd);
|
||||||
|
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
|
||||||
|
char *path, char *method);
|
||||||
void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr,
|
void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr,
|
||||||
const u8 *ie, size_t ie_len);
|
const u8 *ie, size_t ie_len);
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,8 @@ struct wps_data * wps_init(const struct wps_config *cfg)
|
||||||
os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN);
|
os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN);
|
||||||
}
|
}
|
||||||
if (cfg->pin) {
|
if (cfg->pin) {
|
||||||
data->dev_pw_id = DEV_PW_DEFAULT;
|
data->dev_pw_id = data->wps->oob_dev_pw_id == 0 ?
|
||||||
|
DEV_PW_DEFAULT : data->wps->oob_dev_pw_id;
|
||||||
data->dev_password = os_malloc(cfg->pin_len);
|
data->dev_password = os_malloc(cfg->pin_len);
|
||||||
if (data->dev_password == NULL) {
|
if (data->dev_password == NULL) {
|
||||||
os_free(data);
|
os_free(data);
|
||||||
|
@ -300,7 +301,7 @@ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev,
|
||||||
methods = WPS_CONFIG_PUSHBUTTON;
|
methods = WPS_CONFIG_PUSHBUTTON;
|
||||||
else
|
else
|
||||||
methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY |
|
methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY |
|
||||||
WPS_CONFIG_KEYPAD;
|
WPS_CONFIG_KEYPAD | WPS_CONFIG_USBA;
|
||||||
|
|
||||||
if (wps_build_version(ie) ||
|
if (wps_build_version(ie) ||
|
||||||
wps_build_req_type(ie, req_type) ||
|
wps_build_req_type(ie, req_type) ||
|
||||||
|
|
|
@ -88,6 +88,17 @@ struct wps_device_data {
|
||||||
u8 rf_bands;
|
u8 rf_bands;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct oob_conf_data {
|
||||||
|
enum {
|
||||||
|
OOB_METHOD_UNKNOWN = 0,
|
||||||
|
OOB_METHOD_DEV_PWD_E,
|
||||||
|
OOB_METHOD_DEV_PWD_R,
|
||||||
|
OOB_METHOD_CRED,
|
||||||
|
} oob_method;
|
||||||
|
struct wpabuf *dev_password;
|
||||||
|
struct wpabuf *pubkey_hash;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct wps_config - WPS configuration for a single registration protocol run
|
* struct wps_config - WPS configuration for a single registration protocol run
|
||||||
*/
|
*/
|
||||||
|
@ -397,6 +408,31 @@ struct wps_context {
|
||||||
*/
|
*/
|
||||||
struct wps_device_data dev;
|
struct wps_device_data dev;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oob_dev - OOB Device data
|
||||||
|
*/
|
||||||
|
struct oob_device_data *oob_dev;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oob_conf - OOB Config data
|
||||||
|
*/
|
||||||
|
struct oob_conf_data oob_conf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oob_dev_pw_id - OOB Device password id
|
||||||
|
*/
|
||||||
|
u16 oob_dev_pw_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dh_privkey - Diffie-Hellman private key
|
||||||
|
*/
|
||||||
|
struct wpabuf *dh_privkey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dh_pubkey_oob - Diffie-Hellman public key
|
||||||
|
*/
|
||||||
|
struct wpabuf *dh_pubkey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* config_methods - Enabled configuration methods
|
* config_methods - Enabled configuration methods
|
||||||
*
|
*
|
||||||
|
@ -494,6 +530,13 @@ struct wps_context {
|
||||||
struct upnp_pending_message *upnp_msgs;
|
struct upnp_pending_message *upnp_msgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct oob_device_data {
|
||||||
|
char *device_path;
|
||||||
|
int (*init_func)(struct wps_context *, int);
|
||||||
|
struct wpabuf * (*read_func)(void);
|
||||||
|
int (*write_func)(struct wpabuf *);
|
||||||
|
int (*deinit_func)(void);
|
||||||
|
};
|
||||||
|
|
||||||
struct wps_registrar *
|
struct wps_registrar *
|
||||||
wps_registrar_init(struct wps_context *wps,
|
wps_registrar_init(struct wps_context *wps,
|
||||||
|
@ -515,4 +558,8 @@ unsigned int wps_pin_valid(unsigned int pin);
|
||||||
unsigned int wps_generate_pin(void);
|
unsigned int wps_generate_pin(void);
|
||||||
void wps_free_pending_msgs(struct upnp_pending_message *msgs);
|
void wps_free_pending_msgs(struct upnp_pending_message *msgs);
|
||||||
|
|
||||||
|
struct oob_device_data * wps_get_oob_device(char *device_type);
|
||||||
|
int wps_get_oob_method(char *method);
|
||||||
|
int wps_process_oob(struct wps_context *wps, int registrar);
|
||||||
|
|
||||||
#endif /* WPS_H */
|
#endif /* WPS_H */
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "dh_groups.h"
|
#include "crypto.h"
|
||||||
#include "sha256.h"
|
#include "sha256.h"
|
||||||
#include "aes_wrap.h"
|
#include "aes_wrap.h"
|
||||||
#include "wps_i.h"
|
#include "wps_i.h"
|
||||||
|
@ -26,11 +26,13 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
|
||||||
struct wpabuf *pubkey;
|
struct wpabuf *pubkey;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WPS: * Public Key");
|
wpa_printf(MSG_DEBUG, "WPS: * Public Key");
|
||||||
pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), &wps->dh_privkey);
|
wpabuf_free(wps->dh_privkey);
|
||||||
pubkey = wpabuf_zeropad(pubkey, 192);
|
wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey);
|
||||||
if (pubkey == NULL) {
|
pubkey = wpabuf_dup(wps->wps->dh_pubkey);
|
||||||
|
if (wps->dh_privkey == NULL || pubkey == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
|
wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
|
||||||
"Diffie-Hellman handshake");
|
"Diffie-Hellman handshake");
|
||||||
|
wpabuf_free(pubkey);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,3 +254,45 @@ int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps)
|
||||||
|
{
|
||||||
|
size_t hash_len;
|
||||||
|
const u8 *addr[1];
|
||||||
|
u8 pubkey_hash[WPS_HASH_LEN];
|
||||||
|
u8 dev_password_bin[WPS_OOB_DEVICE_PASSWORD_LEN];
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: * OOB Device Password");
|
||||||
|
|
||||||
|
addr[0] = wpabuf_head(wps->dh_pubkey);
|
||||||
|
hash_len = wpabuf_len(wps->dh_pubkey);
|
||||||
|
sha256_vector(1, addr, &hash_len, pubkey_hash);
|
||||||
|
|
||||||
|
if (os_get_random((u8 *) &wps->oob_dev_pw_id, sizeof(u16)) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: device password id "
|
||||||
|
"generation error");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
wps->oob_dev_pw_id |= 0x0010;
|
||||||
|
|
||||||
|
if (os_get_random(dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: OOB device password "
|
||||||
|
"generation error");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD);
|
||||||
|
wpabuf_put_be16(msg, WPS_OOB_DEVICE_PASSWORD_ATTR_LEN);
|
||||||
|
wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
|
||||||
|
wpabuf_put_be16(msg, wps->oob_dev_pw_id);
|
||||||
|
wpabuf_put_data(msg, dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN);
|
||||||
|
|
||||||
|
wpa_snprintf_hex_uppercase(
|
||||||
|
wpabuf_put(wps->oob_conf.dev_password,
|
||||||
|
wpabuf_size(wps->oob_conf.dev_password)),
|
||||||
|
wpabuf_size(wps->oob_conf.dev_password),
|
||||||
|
dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -150,6 +150,14 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
|
||||||
}
|
}
|
||||||
attr->dev_password_id = pos;
|
attr->dev_password_id = pos;
|
||||||
break;
|
break;
|
||||||
|
case ATTR_OOB_DEVICE_PASSWORD:
|
||||||
|
if (len != WPS_OOB_DEVICE_PASSWORD_ATTR_LEN) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
|
||||||
|
"Password length %u", len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
attr->oob_dev_password = pos;
|
||||||
|
break;
|
||||||
case ATTR_OS_VERSION:
|
case ATTR_OS_VERSION:
|
||||||
if (len != 4) {
|
if (len != 4) {
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
|
wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
|
||||||
|
|
|
@ -335,3 +335,203 @@ void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part)
|
||||||
data.pwd_auth_fail.part = part;
|
data.pwd_auth_fail.part = part;
|
||||||
wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data);
|
wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wpabuf * wps_get_oob_cred(struct wps_context *wps)
|
||||||
|
{
|
||||||
|
struct wps_data data;
|
||||||
|
struct wpabuf *plain;
|
||||||
|
|
||||||
|
plain = wpabuf_alloc(500);
|
||||||
|
if (plain == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
|
||||||
|
"credential");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_memset(&data, 0, sizeof(data));
|
||||||
|
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)) {
|
||||||
|
wpabuf_free(plain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return plain;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wpabuf * wps_get_oob_dev_pwd(struct wps_context *wps)
|
||||||
|
{
|
||||||
|
struct wpabuf *data;
|
||||||
|
|
||||||
|
data = wpabuf_alloc(9 + WPS_OOB_DEVICE_PASSWORD_ATTR_LEN);
|
||||||
|
if (data == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
|
||||||
|
"device password attribute");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_free(wps->oob_conf.dev_password);
|
||||||
|
wps->oob_conf.dev_password =
|
||||||
|
wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1);
|
||||||
|
if (wps->oob_conf.dev_password == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
|
||||||
|
"device password");
|
||||||
|
wpabuf_free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wps_build_version(data) ||
|
||||||
|
wps_build_oob_dev_password(data, wps)) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Build OOB device password "
|
||||||
|
"attribute error");
|
||||||
|
wpabuf_free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wps_parse_oob_dev_pwd(struct wps_context *wps,
|
||||||
|
struct wpabuf *data)
|
||||||
|
{
|
||||||
|
struct oob_conf_data *oob_conf = &wps->oob_conf;
|
||||||
|
struct wps_parse_attr attr;
|
||||||
|
const u8 *pos;
|
||||||
|
|
||||||
|
if (wps_parse_msg(data, &attr) < 0 ||
|
||||||
|
attr.oob_dev_password == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: OOB device password not found");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = attr.oob_dev_password;
|
||||||
|
|
||||||
|
oob_conf->pubkey_hash =
|
||||||
|
wpabuf_alloc_copy(pos, WPS_OOB_PUBKEY_HASH_LEN);
|
||||||
|
if (oob_conf->pubkey_hash == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
|
||||||
|
"public key hash");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos += WPS_OOB_PUBKEY_HASH_LEN;
|
||||||
|
|
||||||
|
wps->oob_dev_pw_id = WPA_GET_BE16(pos);
|
||||||
|
pos += sizeof(wps->oob_dev_pw_id);
|
||||||
|
|
||||||
|
oob_conf->dev_password =
|
||||||
|
wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1);
|
||||||
|
if (oob_conf->dev_password == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
|
||||||
|
"device password");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
wpa_snprintf_hex_uppercase(wpabuf_put(oob_conf->dev_password,
|
||||||
|
wpabuf_size(oob_conf->dev_password)),
|
||||||
|
wpabuf_size(oob_conf->dev_password), pos,
|
||||||
|
WPS_OOB_DEVICE_PASSWORD_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data)
|
||||||
|
{
|
||||||
|
struct wpabuf msg;
|
||||||
|
struct wps_parse_attr attr;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: OOB credential not found");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < attr.num_cred; i++) {
|
||||||
|
struct wps_credential local_cred;
|
||||||
|
struct wps_parse_attr cattr;
|
||||||
|
|
||||||
|
os_memset(&local_cred, 0, sizeof(local_cred));
|
||||||
|
wpabuf_set(&msg, attr.cred[i], attr.cred_len[i]);
|
||||||
|
if (wps_parse_msg(&msg, &cattr) < 0 ||
|
||||||
|
wps_process_cred(&cattr, &local_cred)) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB "
|
||||||
|
"credential");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
wps->cred_cb(wps->cb_ctx, &local_cred);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wps_process_oob(struct wps_context *wps, int registrar)
|
||||||
|
{
|
||||||
|
struct oob_device_data *oob_dev = wps->oob_dev;
|
||||||
|
struct wpabuf *data;
|
||||||
|
int ret, write_f, oob_method = wps->oob_conf.oob_method;
|
||||||
|
|
||||||
|
write_f = oob_method == OOB_METHOD_DEV_PWD_E ? !registrar : registrar;
|
||||||
|
|
||||||
|
if (oob_dev->init_func(wps, registrar) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Failed to initialize OOB device");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_f) {
|
||||||
|
if (oob_method == OOB_METHOD_CRED)
|
||||||
|
data = wps_get_oob_cred(wps);
|
||||||
|
else
|
||||||
|
data = wps_get_oob_dev_pwd(wps);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
if (data == NULL || wps->oob_dev->write_func(data) < 0)
|
||||||
|
ret = -1;
|
||||||
|
} else {
|
||||||
|
data = oob_dev->read_func();
|
||||||
|
if (data == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (oob_method == OOB_METHOD_CRED)
|
||||||
|
ret = wps_parse_oob_cred(wps, data);
|
||||||
|
else
|
||||||
|
ret = wps_parse_oob_dev_pwd(wps, data);
|
||||||
|
}
|
||||||
|
wpabuf_free(data);
|
||||||
|
if (ret < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Failed to process OOB data");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oob_dev->deinit_func() < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Failed to deinitialize OOB "
|
||||||
|
"device");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct oob_device_data * wps_get_oob_device(char *device_type)
|
||||||
|
{
|
||||||
|
if (os_strstr(device_type, "ufd") != NULL)
|
||||||
|
return &oob_ufd_device_data;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wps_get_oob_method(char *method)
|
||||||
|
{
|
||||||
|
if (os_strstr(method, "pin-e") != NULL)
|
||||||
|
return OOB_METHOD_DEV_PWD_E;
|
||||||
|
if (os_strstr(method, "pin-r") != NULL)
|
||||||
|
return OOB_METHOD_DEV_PWD_R;
|
||||||
|
if (os_strstr(method, "cred") != NULL)
|
||||||
|
return OOB_METHOD_CRED;
|
||||||
|
return OOB_METHOD_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
#define WPS_MGMTAUTHKEY_LEN 32
|
#define WPS_MGMTAUTHKEY_LEN 32
|
||||||
#define WPS_MGMTENCKEY_LEN 16
|
#define WPS_MGMTENCKEY_LEN 16
|
||||||
#define WPS_MGMT_KEY_ID_LEN 16
|
#define WPS_MGMT_KEY_ID_LEN 16
|
||||||
|
#define WPS_OOB_DEVICE_PASSWORD_ATTR_LEN 54
|
||||||
|
#define WPS_OOB_DEVICE_PASSWORD_LEN 32
|
||||||
|
#define WPS_OOB_PUBKEY_HASH_LEN 20
|
||||||
|
|
||||||
/* Attribute Types */
|
/* Attribute Types */
|
||||||
enum wps_attribute {
|
enum wps_attribute {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "sha256.h"
|
#include "sha256.h"
|
||||||
#include "wps_i.h"
|
#include "wps_i.h"
|
||||||
#include "wps_dev_attr.h"
|
#include "wps_dev_attr.h"
|
||||||
|
#include "crypto.h"
|
||||||
|
|
||||||
|
|
||||||
static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg)
|
static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg)
|
||||||
|
@ -130,7 +131,8 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps)
|
||||||
if (msg == NULL)
|
if (msg == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
|
methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD |
|
||||||
|
WPS_CONFIG_USBA;
|
||||||
if (wps->pbc)
|
if (wps->pbc)
|
||||||
methods |= WPS_CONFIG_PUSHBUTTON;
|
methods |= WPS_CONFIG_PUSHBUTTON;
|
||||||
|
|
||||||
|
@ -513,6 +515,20 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wps->wps->oob_conf.pubkey_hash != NULL) {
|
||||||
|
const u8 *addr[1];
|
||||||
|
u8 hash[WPS_HASH_LEN];
|
||||||
|
|
||||||
|
addr[0] = pk;
|
||||||
|
sha256_vector(1, addr, &pk_len, hash);
|
||||||
|
if (os_memcmp(hash,
|
||||||
|
wpabuf_head(wps->wps->oob_conf.pubkey_hash),
|
||||||
|
WPS_OOB_PUBKEY_HASH_LEN) != 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Public Key hash error");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wpabuf_free(wps->dh_pubkey_r);
|
wpabuf_free(wps->dh_pubkey_r);
|
||||||
wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len);
|
wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len);
|
||||||
if (wps->dh_pubkey_r == NULL)
|
if (wps->dh_pubkey_r == NULL)
|
||||||
|
|
|
@ -124,6 +124,8 @@ struct wps_parse_attr {
|
||||||
const u8 *assoc_state; /* 2 octets */
|
const u8 *assoc_state; /* 2 octets */
|
||||||
const u8 *config_error; /* 2 octets */
|
const u8 *config_error; /* 2 octets */
|
||||||
const u8 *dev_password_id; /* 2 octets */
|
const u8 *dev_password_id; /* 2 octets */
|
||||||
|
const u8 *oob_dev_password; /* WPS_OOB_DEVICE_PASSWORD_ATTR_LEN (54)
|
||||||
|
* octets */
|
||||||
const u8 *os_version; /* 4 octets */
|
const u8 *os_version; /* 4 octets */
|
||||||
const u8 *wps_state; /* 1 octet */
|
const u8 *wps_state; /* 1 octet */
|
||||||
const u8 *authenticator; /* WPS_AUTHENTICATOR_LEN (8) octets */
|
const u8 *authenticator; /* WPS_AUTHENTICATOR_LEN (8) octets */
|
||||||
|
@ -191,6 +193,8 @@ void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg);
|
||||||
void wps_success_event(struct wps_context *wps);
|
void wps_success_event(struct wps_context *wps);
|
||||||
void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part);
|
void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part);
|
||||||
|
|
||||||
|
extern struct oob_device_data oob_ufd_device_data;
|
||||||
|
|
||||||
/* wps_attr_parse.c */
|
/* wps_attr_parse.c */
|
||||||
int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
|
int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
|
||||||
|
|
||||||
|
@ -213,6 +217,7 @@ 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_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_conn_type_flags(struct wps_data *wps, struct wpabuf *msg);
|
||||||
int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg);
|
int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg);
|
||||||
|
int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps);
|
||||||
|
|
||||||
/* wps_attr_process.c */
|
/* wps_attr_process.c */
|
||||||
int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
|
int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
|
||||||
|
@ -237,6 +242,7 @@ struct wpabuf * wps_registrar_get_msg(struct wps_data *wps,
|
||||||
enum wps_process_res wps_registrar_process_msg(struct wps_data *wps,
|
enum wps_process_res wps_registrar_process_msg(struct wps_data *wps,
|
||||||
enum wsc_op_code op_code,
|
enum wsc_op_code op_code,
|
||||||
const struct wpabuf *msg);
|
const struct wpabuf *msg);
|
||||||
|
int wps_build_cred(struct wps_data *wps, struct wpabuf *msg);
|
||||||
|
|
||||||
|
|
||||||
static inline int wps_version_supported(const u8 *version)
|
static inline int wps_version_supported(const u8 *version)
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "wps_i.h"
|
#include "wps_i.h"
|
||||||
#include "wps_dev_attr.h"
|
#include "wps_dev_attr.h"
|
||||||
#include "wps_upnp.h"
|
#include "wps_upnp.h"
|
||||||
|
#include "crypto.h"
|
||||||
|
|
||||||
|
|
||||||
struct wps_uuid_pin {
|
struct wps_uuid_pin {
|
||||||
|
@ -981,7 +982,7 @@ static int wps_build_credential(struct wpabuf *msg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
||||||
{
|
{
|
||||||
struct wpabuf *cred;
|
struct wpabuf *cred;
|
||||||
|
|
||||||
|
@ -1626,6 +1627,20 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wps->wps->oob_conf.pubkey_hash != NULL) {
|
||||||
|
const u8 *addr[1];
|
||||||
|
u8 hash[WPS_HASH_LEN];
|
||||||
|
|
||||||
|
addr[0] = pk;
|
||||||
|
sha256_vector(1, addr, &pk_len, hash);
|
||||||
|
if (os_memcmp(hash,
|
||||||
|
wpabuf_head(wps->wps->oob_conf.pubkey_hash),
|
||||||
|
WPS_OOB_PUBKEY_HASH_LEN) != 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Public Key hash error");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wpabuf_free(wps->dh_pubkey_e);
|
wpabuf_free(wps->dh_pubkey_e);
|
||||||
wps->dh_pubkey_e = wpabuf_alloc_copy(pk, pk_len);
|
wps->dh_pubkey_e = wpabuf_alloc_copy(pk, pk_len);
|
||||||
if (wps->dh_pubkey_e == NULL)
|
if (wps->dh_pubkey_e == NULL)
|
||||||
|
@ -1793,7 +1808,8 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
|
||||||
wps_process_os_version(&wps->peer_dev, attr->os_version))
|
wps_process_os_version(&wps->peer_dev, attr->os_version))
|
||||||
return WPS_FAILURE;
|
return WPS_FAILURE;
|
||||||
|
|
||||||
if (wps->dev_pw_id != DEV_PW_DEFAULT &&
|
if (wps->dev_pw_id < 0x10 &&
|
||||||
|
wps->dev_pw_id != DEV_PW_DEFAULT &&
|
||||||
wps->dev_pw_id != DEV_PW_USER_SPECIFIED &&
|
wps->dev_pw_id != DEV_PW_USER_SPECIFIED &&
|
||||||
wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED &&
|
wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED &&
|
||||||
wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED &&
|
wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED &&
|
||||||
|
@ -1805,6 +1821,14 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
|
||||||
return WPS_CONTINUE;
|
return WPS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wps->dev_pw_id >= 0x10 &&
|
||||||
|
wps->dev_pw_id != wps->wps->oob_dev_pw_id) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: OOB Device Password ID "
|
||||||
|
"%d mismatch", wps->dev_pw_id);
|
||||||
|
wps->state = SEND_M2D;
|
||||||
|
return WPS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) {
|
if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) {
|
||||||
if (wps_registrar_pbc_overlap(wps->wps->registrar,
|
if (wps_registrar_pbc_overlap(wps->wps->registrar,
|
||||||
wps->mac_addr_e, wps->uuid_e)) {
|
wps->mac_addr_e, wps->uuid_e)) {
|
||||||
|
|
193
src/wps/wps_ufd.c
Normal file
193
src/wps/wps_ufd.c
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* UFD routines for Wi-Fi Protected Setup
|
||||||
|
* Copyright (c) 2009, Masashi Honma <honma@ictec.co.jp>
|
||||||
|
*
|
||||||
|
* 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 <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#include "wps/wps.h"
|
||||||
|
|
||||||
|
static int ufd_fd = -1;
|
||||||
|
|
||||||
|
|
||||||
|
static int dev_pwd_e_file_filter(const struct dirent *entry)
|
||||||
|
{
|
||||||
|
unsigned int prefix;
|
||||||
|
char ext[5];
|
||||||
|
|
||||||
|
if (sscanf(entry->d_name, "%8x.%4s", &prefix, ext) != 2)
|
||||||
|
return 0;
|
||||||
|
if (prefix == 0)
|
||||||
|
return 0;
|
||||||
|
if (os_strcasecmp(ext, "WFA") != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wps_get_dev_pwd_e_file_name(char *path, char *file_name)
|
||||||
|
{
|
||||||
|
struct dirent **namelist;
|
||||||
|
int i, file_num;
|
||||||
|
|
||||||
|
file_num = scandir(path, &namelist, &dev_pwd_e_file_filter,
|
||||||
|
alphasort);
|
||||||
|
if (file_num <= 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: OOB file not found");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
os_strlcpy(file_name, namelist[0]->d_name, 13);
|
||||||
|
for (i = 0; i < file_num; i++)
|
||||||
|
os_free(namelist[i]);
|
||||||
|
os_free(namelist);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int get_file_name(struct wps_context *wps, int registrar,
|
||||||
|
char *file_name)
|
||||||
|
{
|
||||||
|
switch (wps->oob_conf.oob_method) {
|
||||||
|
case OOB_METHOD_CRED:
|
||||||
|
os_snprintf(file_name, 13, "00000000.WSC");
|
||||||
|
break;
|
||||||
|
case OOB_METHOD_DEV_PWD_E:
|
||||||
|
if (registrar) {
|
||||||
|
char temp[128];
|
||||||
|
|
||||||
|
os_snprintf(temp, sizeof(temp), "%s/SMRTNTKY/WFAWSC",
|
||||||
|
wps->oob_dev->device_path);
|
||||||
|
if (wps_get_dev_pwd_e_file_name(temp, file_name) < 0)
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
u8 *mac_addr = wps->dev.mac_addr;
|
||||||
|
|
||||||
|
os_snprintf(file_name, 13, "%02X%02X%02X%02X.WFA",
|
||||||
|
mac_addr[2], mac_addr[3], mac_addr[4],
|
||||||
|
mac_addr[5]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OOB_METHOD_DEV_PWD_R:
|
||||||
|
os_snprintf(file_name, 13, "00000000.WFA");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Invalid USBA OOB method");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int init_ufd(struct wps_context *wps, int registrar)
|
||||||
|
{
|
||||||
|
int write_f;
|
||||||
|
char temp[128];
|
||||||
|
char *path = wps->oob_dev->device_path;
|
||||||
|
char filename[13];
|
||||||
|
|
||||||
|
write_f = wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ?
|
||||||
|
!registrar : registrar;
|
||||||
|
|
||||||
|
if (get_file_name(wps, registrar, filename) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file name");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_f) {
|
||||||
|
os_snprintf(temp, sizeof(temp),
|
||||||
|
"mkdir -p %s/SMRTNTKY/WFAWSC", path);
|
||||||
|
if (system(temp) != 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS (UFD): Failed "
|
||||||
|
"to mkdir");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
os_snprintf(temp, sizeof(temp), "%s/SMRTNTKY/WFAWSC/%s", path,
|
||||||
|
filename);
|
||||||
|
if (write_f)
|
||||||
|
ufd_fd = open(temp, O_WRONLY | O_CREAT | O_TRUNC,
|
||||||
|
S_IRUSR | S_IWUSR);
|
||||||
|
else
|
||||||
|
ufd_fd = open(temp, O_RDONLY);
|
||||||
|
if (ufd_fd < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS (UFD): Failed to open %s: %s",
|
||||||
|
temp, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wpabuf * read_ufd(void)
|
||||||
|
{
|
||||||
|
struct wpabuf *buf;
|
||||||
|
struct stat s;
|
||||||
|
size_t file_size;
|
||||||
|
|
||||||
|
if (fstat(ufd_fd, &s) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file size");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_size = s.st_size;
|
||||||
|
buf = wpabuf_alloc(file_size);
|
||||||
|
if (buf == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS (UFD): Failed to alloc read "
|
||||||
|
"buffer");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read(ufd_fd, wpabuf_mhead(buf), file_size) != (int) file_size) {
|
||||||
|
wpabuf_free(buf);
|
||||||
|
wpa_printf(MSG_ERROR, "WPS (UFD): Failed to read");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
wpabuf_put(buf, file_size);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int write_ufd(struct wpabuf *buf)
|
||||||
|
{
|
||||||
|
if (write(ufd_fd, wpabuf_mhead(buf), wpabuf_len(buf)) !=
|
||||||
|
(int) wpabuf_len(buf)) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS (UFD): Failed to write");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int deinit_ufd(void)
|
||||||
|
{
|
||||||
|
close(ufd_fd);
|
||||||
|
ufd_fd = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct oob_device_data oob_ufd_device_data = {
|
||||||
|
.device_path = NULL,
|
||||||
|
.init_func = init_ufd,
|
||||||
|
.read_func = read_ufd,
|
||||||
|
.write_func = write_ufd,
|
||||||
|
.deinit_func = deinit_ufd,
|
||||||
|
};
|
|
@ -521,6 +521,7 @@ OBJS += ../src/wps/wps_attr_process.o
|
||||||
OBJS += ../src/wps/wps_dev_attr.o
|
OBJS += ../src/wps/wps_dev_attr.o
|
||||||
OBJS += ../src/wps/wps_enrollee.o
|
OBJS += ../src/wps/wps_enrollee.o
|
||||||
OBJS += ../src/wps/wps_registrar.o
|
OBJS += ../src/wps/wps_registrar.o
|
||||||
|
OBJS += ../src/wps/wps_ufd.o
|
||||||
OBJS_h += ../src/eap_server/eap_wsc.o
|
OBJS_h += ../src/eap_server/eap_wsc.o
|
||||||
CONFIG_IEEE8021X_EAPOL=y
|
CONFIG_IEEE8021X_EAPOL=y
|
||||||
NEED_DH_GROUPS=y
|
NEED_DH_GROUPS=y
|
||||||
|
|
|
@ -204,6 +204,25 @@ static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
|
||||||
|
char *cmd)
|
||||||
|
{
|
||||||
|
char *path, *method;
|
||||||
|
|
||||||
|
path = os_strchr(cmd, ' ');
|
||||||
|
if (path == NULL)
|
||||||
|
return -1;
|
||||||
|
*path++ = '\0';
|
||||||
|
|
||||||
|
method = os_strchr(path, ' ');
|
||||||
|
if (method == NULL)
|
||||||
|
return -1;
|
||||||
|
*method++ = '\0';
|
||||||
|
|
||||||
|
return wpas_wps_start_oob(wpa_s, cmd, path, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
|
static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
|
||||||
char *cmd)
|
char *cmd)
|
||||||
{
|
{
|
||||||
|
@ -1583,6 +1602,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
|
reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
|
||||||
reply,
|
reply,
|
||||||
reply_size);
|
reply_size);
|
||||||
|
} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
|
||||||
|
if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
|
||||||
|
reply_len = -1;
|
||||||
} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
|
} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
|
||||||
if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
|
if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
|
|
@ -446,6 +446,30 @@ static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char cmd[256];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
printf("Invalid WPS_OOB command: need three arguments:\n"
|
||||||
|
"- OOB_DEV_TYPE: use 'ufd'\n"
|
||||||
|
"- OOB_PATH: path of OOB device like '/mnt'\n"
|
||||||
|
"- OOB_METHOD: OOB method 'pin-e' or 'pin-r', "
|
||||||
|
"'cred'\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
|
||||||
|
argv[0], argv[1], argv[2]);
|
||||||
|
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||||
|
printf("Too long WPS_OOB command.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return wpa_ctrl_command(ctrl, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char cmd[256];
|
char cmd[256];
|
||||||
|
@ -1258,6 +1282,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
|
||||||
cli_cmd_flag_sensitive,
|
cli_cmd_flag_sensitive,
|
||||||
"<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
|
"<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
|
||||||
"hardcoded)" },
|
"hardcoded)" },
|
||||||
|
{ "wps_oob", wpa_cli_cmd_wps_oob,
|
||||||
|
cli_cmd_flag_sensitive,
|
||||||
|
"<OOB_DEV_TYPE> <OOB_PATH> <OOB_METHOD> = start WPS OOB" },
|
||||||
{ "wps_reg", wpa_cli_cmd_wps_reg,
|
{ "wps_reg", wpa_cli_cmd_wps_reg,
|
||||||
cli_cmd_flag_sensitive,
|
cli_cmd_flag_sensitive,
|
||||||
"<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
|
"<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "eap_common/eap_wsc_common.h"
|
#include "eap_common/eap_wsc_common.h"
|
||||||
#include "blacklist.h"
|
#include "blacklist.h"
|
||||||
#include "wps_supplicant.h"
|
#include "wps_supplicant.h"
|
||||||
|
#include "dh_groups.h"
|
||||||
|
|
||||||
#define WPS_PIN_SCAN_IGNORE_SEL_REG 3
|
#define WPS_PIN_SCAN_IGNORE_SEL_REG 3
|
||||||
|
|
||||||
|
@ -440,7 +441,7 @@ int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
const char *pin)
|
const char *pin)
|
||||||
{
|
{
|
||||||
struct wpa_ssid *ssid;
|
struct wpa_ssid *ssid;
|
||||||
char val[30];
|
char val[128];
|
||||||
unsigned int rpin = 0;
|
unsigned int rpin = 0;
|
||||||
|
|
||||||
wpas_clear_wps(wpa_s);
|
wpas_clear_wps(wpa_s);
|
||||||
|
@ -461,6 +462,33 @@ int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpas_wps_start_oob(struct wpa_supplicant *wpa_s, char *device_type,
|
||||||
|
char *path, char *method)
|
||||||
|
{
|
||||||
|
struct wps_context *wps = wpa_s->wps;
|
||||||
|
|
||||||
|
wps->oob_dev = wps_get_oob_device(device_type);
|
||||||
|
if (wps->oob_dev == NULL)
|
||||||
|
return -1;
|
||||||
|
wps->oob_dev->device_path = path;
|
||||||
|
wps->oob_conf.oob_method = wps_get_oob_method(method);
|
||||||
|
|
||||||
|
if (wps->oob_conf.oob_method == OOB_METHOD_CRED)
|
||||||
|
wpas_clear_wps(wpa_s);
|
||||||
|
|
||||||
|
if (wps_process_oob(wps, 0) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ||
|
||||||
|
wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) &&
|
||||||
|
wpas_wps_start_pin(wpa_s, NULL,
|
||||||
|
wpabuf_head(wps->oob_conf.dev_password)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
const char *pin)
|
const char *pin)
|
||||||
{
|
{
|
||||||
|
@ -584,6 +612,16 @@ int wpas_wps_init(struct wpa_supplicant *wpa_s)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wps->dh_pubkey = dh_init(dh_groups_get(WPS_DH_GROUP),
|
||||||
|
&wps->dh_privkey);
|
||||||
|
wps->dh_pubkey = wpabuf_zeropad(wps->dh_pubkey, 192);
|
||||||
|
if (wps->dh_pubkey == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Failed to initialize "
|
||||||
|
"Diffie-Hellman handshake");
|
||||||
|
os_free(wps);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_s->wps = wps;
|
wpa_s->wps = wps;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -598,6 +636,10 @@ void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wps_registrar_deinit(wpa_s->wps->registrar);
|
wps_registrar_deinit(wpa_s->wps->registrar);
|
||||||
|
wpabuf_free(wpa_s->wps->dh_pubkey);
|
||||||
|
wpabuf_free(wpa_s->wps->dh_privkey);
|
||||||
|
wpabuf_free(wpa_s->wps->oob_conf.pubkey_hash);
|
||||||
|
wpabuf_free(wpa_s->wps->oob_conf.dev_password);
|
||||||
os_free(wpa_s->wps->network_key);
|
os_free(wpa_s->wps->network_key);
|
||||||
os_free(wpa_s->wps);
|
os_free(wpa_s->wps);
|
||||||
wpa_s->wps = NULL;
|
wpa_s->wps = NULL;
|
||||||
|
|
|
@ -27,6 +27,8 @@ enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid);
|
||||||
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid);
|
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid);
|
||||||
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
const char *pin);
|
const char *pin);
|
||||||
|
int wpas_wps_start_oob(struct wpa_supplicant *wpa_s, char *device_type,
|
||||||
|
char *path, char *method);
|
||||||
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
const char *pin);
|
const char *pin);
|
||||||
int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
|
int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
|
||||||
|
|
Loading…
Reference in a new issue