WPS: Use separate list of NFC Password Tokens in the Registrar

This adds a cleaner mechanism for handling NFC Password Tokens in the
WPS Registrar. There could be more than one active NFC Password Token in
use and as such, a list of tokens needs to be maintained. The old
WPS_OOB interface is still using the old mechanism that supports only a
single active NFC Password Token.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2012-06-27 22:15:55 +03:00
parent bb45b6d79a
commit 0e3c16546b
4 changed files with 150 additions and 9 deletions

View file

@ -118,6 +118,12 @@ struct wps_data * wps_init(const struct wps_config *cfg)
*/ */
void wps_deinit(struct wps_data *data) void wps_deinit(struct wps_data *data)
{ {
#ifdef CONFIG_WPS_NFC
if (data->registrar && data->nfc_pw_token)
wps_registrar_remove_nfc_pw_token(data->wps->registrar,
data->nfc_pw_token);
#endif /* CONFIG_WPS_NFC */
if (data->wps_pin_revealed) { if (data->wps_pin_revealed) {
wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and " wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and "
"negotiation failed"); "negotiation failed");
@ -136,6 +142,7 @@ void wps_deinit(struct wps_data *data)
wps_device_data_free(&data->peer_dev); wps_device_data_free(&data->peer_dev);
os_free(data->new_ap_settings); os_free(data->new_ap_settings);
dh5_free(data->dh_ctx); dh5_free(data->dh_ctx);
os_free(data->nfc_pw_token);
os_free(data); os_free(data);
} }

View file

@ -797,6 +797,9 @@ int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr,
char *buf, size_t buflen); char *buf, size_t buflen);
int wps_registrar_config_ap(struct wps_registrar *reg, int wps_registrar_config_ap(struct wps_registrar *reg,
struct wps_credential *cred); struct wps_credential *cred);
int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
const u8 *pubkey_hash, u16 pw_id,
const u8 *dev_pw, size_t dev_pw_len);
int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
const u8 *oob_dev_pw, const u8 *oob_dev_pw,
size_t oob_dev_pw_len); size_t oob_dev_pw_len);

View file

@ -1,6 +1,6 @@
/* /*
* Wi-Fi Protected Setup - internal definitions * Wi-Fi Protected Setup - internal definitions
* 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. * This software may be distributed under the terms of the BSD license.
* See README for more details. * See README for more details.
@ -12,6 +12,8 @@
#include "wps.h" #include "wps.h"
#include "wps_attr_parse.h" #include "wps_attr_parse.h"
struct wps_nfc_pw_token;
/** /**
* struct wps_data - WPS registration protocol data * struct wps_data - WPS registration protocol data
* *
@ -115,6 +117,8 @@ struct wps_data {
u8 p2p_dev_addr[ETH_ALEN]; /* P2P Device Address of the client or u8 p2p_dev_addr[ETH_ALEN]; /* P2P Device Address of the client or
* 00:00:00:00:00:00 if not a P2p client */ * 00:00:00:00:00:00 if not a P2p client */
int pbc_in_m1; int pbc_in_m1;
struct wps_nfc_pw_token *nfc_pw_token;
}; };
@ -198,5 +202,7 @@ void wps_registrar_selected_registrar_changed(struct wps_registrar *reg);
const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count); const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count);
int wps_registrar_pbc_overlap(struct wps_registrar *reg, int wps_registrar_pbc_overlap(struct wps_registrar *reg,
const u8 *addr, const u8 *uuid_e); const u8 *addr, const u8 *uuid_e);
void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg,
struct wps_nfc_pw_token *token);
#endif /* WPS_I_H */ #endif /* WPS_I_H */

View file

@ -26,6 +26,53 @@
#define WPS_WORKAROUNDS #define WPS_WORKAROUNDS
#endif /* CONFIG_WPS_STRICT */ #endif /* CONFIG_WPS_STRICT */
#ifdef CONFIG_WPS_NFC
struct wps_nfc_pw_token {
struct dl_list list;
u8 pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN];
u16 pw_id;
u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN];
size_t dev_pw_len;
};
static void wps_remove_nfc_pw_token(struct wps_nfc_pw_token *token)
{
dl_list_del(&token->list);
os_free(token);
}
static void wps_free_nfc_pw_tokens(struct dl_list *tokens, u16 pw_id)
{
struct wps_nfc_pw_token *token, *prev;
dl_list_for_each_safe(token, prev, tokens, struct wps_nfc_pw_token,
list) {
if (pw_id == 0 || pw_id == token->pw_id)
wps_remove_nfc_pw_token(token);
}
}
static struct wps_nfc_pw_token * wps_get_nfc_pw_token(struct dl_list *tokens,
u16 pw_id)
{
struct wps_nfc_pw_token *token;
dl_list_for_each(token, tokens, struct wps_nfc_pw_token, list) {
if (pw_id == token->pw_id)
return token;
}
return NULL;
}
#else /* CONFIG_WPS_NFC */
#define wps_free_nfc_pw_tokens(t, p) do { } while (0)
#endif /* CONFIG_WPS_NFC */
struct wps_uuid_pin { struct wps_uuid_pin {
struct dl_list list; struct dl_list list;
u8 uuid[WPS_UUID_LEN]; u8 uuid[WPS_UUID_LEN];
@ -113,6 +160,7 @@ struct wps_registrar {
void *cb_ctx; void *cb_ctx;
struct dl_list pins; struct dl_list pins;
struct dl_list nfc_pw_tokens;
struct wps_pbc_session *pbc_sessions; struct wps_pbc_session *pbc_sessions;
int skip_cred_build; int skip_cred_build;
@ -591,6 +639,7 @@ wps_registrar_init(struct wps_context *wps,
return NULL; return NULL;
dl_list_init(&reg->pins); dl_list_init(&reg->pins);
dl_list_init(&reg->nfc_pw_tokens);
reg->wps = wps; reg->wps = wps;
reg->new_psk_cb = cfg->new_psk_cb; reg->new_psk_cb = cfg->new_psk_cb;
reg->set_ie_cb = cfg->set_ie_cb; reg->set_ie_cb = cfg->set_ie_cb;
@ -634,6 +683,7 @@ void wps_registrar_deinit(struct wps_registrar *reg)
eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
wps_free_pins(&reg->pins); wps_free_pins(&reg->pins);
wps_free_nfc_pw_tokens(&reg->nfc_pw_tokens, 0);
wps_free_pbc_sessions(reg->pbc_sessions); wps_free_pbc_sessions(reg->pbc_sessions);
wpabuf_free(reg->extra_cred); wpabuf_free(reg->extra_cred);
wps_free_devices(reg->devices); wps_free_devices(reg->devices);
@ -1255,6 +1305,13 @@ static int wps_get_dev_password(struct wps_data *wps)
wpa_printf(MSG_DEBUG, "WPS: Use default PIN for PBC"); wpa_printf(MSG_DEBUG, "WPS: Use default PIN for PBC");
pin = (const u8 *) "00000000"; pin = (const u8 *) "00000000";
pin_len = 8; pin_len = 8;
#ifdef CONFIG_WPS_NFC
} else if (wps->nfc_pw_token) {
wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from NFC "
"Password Token");
pin = wps->nfc_pw_token->dev_pw;
pin_len = wps->nfc_pw_token->dev_pw_len;
#endif /* CONFIG_WPS_NFC */
} else { } else {
pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e, pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e,
&pin_len); &pin_len);
@ -2441,8 +2498,34 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
return WPS_CONTINUE; return WPS_CONTINUE;
} }
#ifdef CONFIG_WPS_NFC
if (wps->dev_pw_id >= 0x10) {
struct wps_nfc_pw_token *token;
const u8 *addr[1];
u8 hash[WPS_HASH_LEN];
token = wps_get_nfc_pw_token(
&wps->wps->registrar->nfc_pw_tokens, wps->dev_pw_id);
if (token) {
wpa_printf(MSG_DEBUG, "WPS: Found matching NFC "
"Password Token");
dl_list_del(&token->list);
wps->nfc_pw_token = token;
addr[0] = attr->public_key;
sha256_vector(1, addr, &attr->public_key_len, hash);
if (os_memcmp(hash, wps->nfc_pw_token->pubkey_hash,
WPS_OOB_PUBKEY_HASH_LEN) != 0) {
wpa_printf(MSG_ERROR, "WPS: Public Key hash "
"mismatch");
return WPS_FAILURE;
}
}
}
#endif /* CONFIG_WPS_NFC */
#ifdef CONFIG_WPS_OOB #ifdef CONFIG_WPS_OOB
if (wps->dev_pw_id >= 0x10 && if (wps->dev_pw_id >= 0x10 && wps->nfc_pw_token == NULL &&
wps->dev_pw_id != wps->wps->oob_dev_pw_id) { wps->dev_pw_id != wps->wps->oob_dev_pw_id) {
wpa_printf(MSG_DEBUG, "WPS: OOB Device Password ID " wpa_printf(MSG_DEBUG, "WPS: OOB Device Password ID "
"%d mismatch", wps->dev_pw_id); "%d mismatch", wps->dev_pw_id);
@ -3369,6 +3452,43 @@ int wps_registrar_config_ap(struct wps_registrar *reg,
#ifdef CONFIG_WPS_NFC #ifdef CONFIG_WPS_NFC
int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
const u8 *pubkey_hash, u16 pw_id,
const u8 *dev_pw, size_t dev_pw_len)
{
struct wps_nfc_pw_token *token;
if (dev_pw_len > WPS_OOB_DEVICE_PASSWORD_LEN)
return -1;
wps_free_nfc_pw_tokens(&reg->nfc_pw_tokens, pw_id);
token = os_zalloc(sizeof(*token));
if (token == NULL)
return -1;
os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
token->pw_id = pw_id;
os_memcpy(token->dev_pw, dev_pw, dev_pw_len);
token->dev_pw_len = dev_pw_len;
dl_list_add(&reg->nfc_pw_tokens, &token->list);
reg->selected_registrar = 1;
reg->pbc = 0;
wps_registrar_add_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
wps_registrar_selected_registrar_changed(reg);
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
wps_registrar_set_selected_timeout,
reg, NULL);
return 0;
}
int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
const u8 *oob_dev_pw, const u8 *oob_dev_pw,
size_t oob_dev_pw_len) size_t oob_dev_pw_len)
@ -3396,12 +3516,17 @@ int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
hash, WPS_OOB_PUBKEY_HASH_LEN); hash, WPS_OOB_PUBKEY_HASH_LEN);
wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", dev_pw, dev_pw_len); wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", dev_pw, dev_pw_len);
reg->wps->oob_dev_pw_id = id; return wps_registrar_add_nfc_pw_token(reg, hash, id, dev_pw,
wpabuf_free(reg->wps->oob_conf.pubkey_hash); dev_pw_len);
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);
} }
void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg,
struct wps_nfc_pw_token *token)
{
wps_registrar_remove_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
wps_registrar_selected_registrar_changed(reg);
}
#endif /* CONFIG_WPS_NFC */ #endif /* CONFIG_WPS_NFC */