WPS: Add new mechanism for communicating NFC tag read events

hostapd ctrl_iface can now be used to deliver payload from read
operation of an NFC tag. This allows operations without having to have
low-level NFC code within hostapd. For now, the new wps_nfc_tag_read
command can be used with NFC password tokens for the case where the AP
has an NFC device that is used to read an NFC tag from the station
Enrollee.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2012-06-27 20:54:56 +03:00
parent 3f2c8ba6d3
commit bb45b6d79a
6 changed files with 206 additions and 6 deletions

View file

@ -1,6 +1,6 @@
/*
* hostapd / UNIX domain socket -based control interface
* Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -274,6 +274,35 @@ static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
#endif /* CONFIG_WPS_OOB */
#ifdef CONFIG_WPS_NFC
static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
char *pos)
{
size_t len;
struct wpabuf *buf;
int ret;
len = os_strlen(pos);
if (len & 0x01)
return -1;
len /= 2;
buf = wpabuf_alloc(len);
if (buf == NULL)
return -1;
if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
wpabuf_free(buf);
return -1;
}
ret = hostapd_wps_nfc_tag_read(hapd, buf);
wpabuf_free(buf);
return ret;
}
#endif /* CONFIG_WPS_NFC */
static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
char *buf, size_t buflen)
{
@ -769,6 +798,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
reply_len = -1;
#ifdef CONFIG_WPS_NFC
} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
reply_len = -1;
#endif /* CONFIG_WPS_NFC */
#endif /* CONFIG_WPS */
} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))

View file

@ -1,6 +1,6 @@
/*
* hostapd - command line interface for hostapd daemon
* Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -74,6 +74,9 @@ static const char *commands_help =
#ifdef CONFIG_WPS_OOB
" wps_oob <type> <path> <method> use WPS with out-of-band (UFD)\n"
#endif /* CONFIG_WPS_OOB */
#ifdef CONFIG_WPS_NFC
" wps_nfc_tag_read <hexdump> report read NFC tag with WPS data\n"
#endif /* CONFIG_WPS_NFC */
" wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
" wps_config <SSID> <auth> <encr> <key> configure AP\n"
#endif /* CONFIG_WPS */
@ -433,6 +436,34 @@ static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
#endif /* CONFIG_WPS_OOB */
#ifdef CONFIG_WPS_NFC
static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
int ret;
char *buf;
size_t buflen;
if (argc != 1) {
printf("Invalid 'wps_nfc_tag_read' command - one argument "
"is required.\n");
return -1;
}
buflen = 18 + os_strlen(argv[0]);
buf = os_malloc(buflen);
if (buf == NULL)
return -1;
os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
ret = wpa_ctrl_command(ctrl, buf);
os_free(buf);
return ret;
}
#endif /* CONFIG_WPS_NFC */
static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@ -730,6 +761,9 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
#ifdef CONFIG_WPS_OOB
{ "wps_oob", hostapd_cli_cmd_wps_oob },
#endif /* CONFIG_WPS_OOB */
#ifdef CONFIG_WPS_NFC
{ "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
#endif /* CONFIG_WPS_NFC */
{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
{ "wps_config", hostapd_cli_cmd_wps_config },
#endif /* CONFIG_WPS */

View file

@ -1,6 +1,6 @@
/*
* hostapd / WPS integration
* Copyright (c) 2008-2010, Jouni Malinen <j@w1.fi>
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -20,6 +20,7 @@
#include "wps/wps.h"
#include "wps/wps_defs.h"
#include "wps/wps_dev_attr.h"
#include "wps/wps_attr_parse.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
@ -1497,3 +1498,90 @@ int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
return wps_registrar_config_ap(hapd->wps->registrar, &cred);
}
#ifdef CONFIG_WPS_NFC
struct wps_nfc_password_token_data {
const u8 *oob_dev_pw;
size_t oob_dev_pw_len;
int added;
};
static int wps_add_nfc_password_token(struct hostapd_data *hapd, void *ctx)
{
struct wps_nfc_password_token_data *data = ctx;
int ret;
if (hapd->wps == NULL)
return 0;
ret = wps_registrar_add_nfc_password_token(hapd->wps->registrar,
data->oob_dev_pw,
data->oob_dev_pw_len);
if (ret == 0)
data->added++;
return ret;
}
static int hostapd_wps_add_nfc_password_token(struct hostapd_data *hapd,
struct wps_parse_attr *attr)
{
struct wps_nfc_password_token_data data;
data.oob_dev_pw = attr->oob_dev_password;
data.oob_dev_pw_len = attr->oob_dev_password_len;
data.added = 0;
if (hostapd_wps_for_each(hapd, wps_add_nfc_password_token, &data) < 0)
return -1;
return data.added ? 0 : -1;
}
static int hostapd_wps_nfc_tag_process(struct hostapd_data *hapd,
const struct wpabuf *wps)
{
struct wps_parse_attr attr;
wpa_hexdump_buf(MSG_DEBUG, "WPS: Received NFC tag payload", wps);
if (wps_parse_msg(wps, &attr)) {
wpa_printf(MSG_DEBUG, "WPS: Ignore invalid data from NFC tag");
return -1;
}
if (attr.oob_dev_password)
return hostapd_wps_add_nfc_password_token(hapd, &attr);
wpa_printf(MSG_DEBUG, "WPS: Ignore unrecognized NFC tag");
return -1;
}
int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
const struct wpabuf *data)
{
const struct wpabuf *wps = data;
struct wpabuf *tmp = NULL;
int ret;
if (wpabuf_len(data) < 4)
return -1;
if (*wpabuf_head_u8(data) != 0x10) {
/* Assume this contains full NDEF record */
tmp = ndef_parse_wifi(data);
if (tmp == NULL) {
wpa_printf(MSG_DEBUG, "WPS: Could not parse NDEF");
return -1;
}
wps = tmp;
}
ret = hostapd_wps_nfc_tag_process(hapd, wps);
wpabuf_free(tmp);
return ret;
}
#endif /* CONFIG_WPS_NFC */

View file

@ -1,6 +1,6 @@
/*
* hostapd / WPS integration
* Copyright (c) 2008-2010, Jouni Malinen <j@w1.fi>
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -33,6 +33,8 @@ int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
void hostapd_wps_update_ie(struct hostapd_data *hapd);
int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
const char *auth, const char *encr, const char *key);
int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
const struct wpabuf *data);
#else /* CONFIG_WPS */

View file

@ -1,6 +1,6 @@
/*
* Wi-Fi Protected Setup
* Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2007-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -797,6 +797,9 @@ int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr,
char *buf, size_t buflen);
int wps_registrar_config_ap(struct wps_registrar *reg,
struct wps_credential *cred);
int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
const u8 *oob_dev_pw,
size_t oob_dev_pw_len);
int wps_build_credential_wrap(struct wpabuf *msg,
const struct wps_credential *cred);

View file

@ -1,6 +1,6 @@
/*
* Wi-Fi Protected Setup - Registrar
* Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -3366,3 +3366,42 @@ int wps_registrar_config_ap(struct wps_registrar *reg,
return -1;
}
#ifdef CONFIG_WPS_NFC
int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
const u8 *oob_dev_pw,
size_t oob_dev_pw_len)
{
const u8 *pos, *hash, *dev_pw;
u16 id;
size_t dev_pw_len;
if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
WPS_OOB_DEVICE_PASSWORD_MIN_LEN ||
oob_dev_pw_len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
WPS_OOB_DEVICE_PASSWORD_LEN)
return -1;
hash = oob_dev_pw;
pos = oob_dev_pw + WPS_OOB_PUBKEY_HASH_LEN;
id = WPA_GET_BE16(pos);
dev_pw = pos + 2;
dev_pw_len = oob_dev_pw + oob_dev_pw_len - dev_pw;
wpa_printf(MSG_DEBUG, "WPS: Add NFC Password Token for Password ID %u",
id);
wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash",
hash, WPS_OOB_PUBKEY_HASH_LEN);
wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", dev_pw, dev_pw_len);
reg->wps->oob_dev_pw_id = id;
wpabuf_free(reg->wps->oob_conf.pubkey_hash);
reg->wps->oob_conf.pubkey_hash = wpabuf_alloc_copy(
hash, WPS_OOB_PUBKEY_HASH_LEN);
if (reg->wps->oob_conf.pubkey_hash == NULL)
return -1;
return wps_registrar_add_pin(reg, NULL, NULL, dev_pw, dev_pw_len, 300);
}
#endif /* CONFIG_WPS_NFC */