WPS NFC: Validate peer public key hash on Enrollee
Since the Enrollee can now get the public key hash from the Registrar, there is need to validate this during the WPS protocol run. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
ff40cd6dd1
commit
5f4545573f
8 changed files with 92 additions and 16 deletions
|
@ -144,12 +144,13 @@ static void * eap_wsc_init(struct eap_sm *sm)
|
||||||
size_t identity_len;
|
size_t identity_len;
|
||||||
int registrar;
|
int registrar;
|
||||||
struct wps_config cfg;
|
struct wps_config cfg;
|
||||||
const char *pos;
|
const char *pos, *end;
|
||||||
const char *phase1;
|
const char *phase1;
|
||||||
struct wps_context *wps;
|
struct wps_context *wps;
|
||||||
struct wps_credential new_ap_settings;
|
struct wps_credential new_ap_settings;
|
||||||
int res;
|
int res;
|
||||||
int nfc = 0;
|
int nfc = 0;
|
||||||
|
u8 pkhash[WPS_OOB_PUBKEY_HASH_LEN];
|
||||||
|
|
||||||
wps = sm->wps;
|
wps = sm->wps;
|
||||||
if (wps == NULL) {
|
if (wps == NULL) {
|
||||||
|
@ -220,6 +221,24 @@ static void * eap_wsc_init(struct eap_sm *sm)
|
||||||
if (pos && cfg.pin)
|
if (pos && cfg.pin)
|
||||||
cfg.dev_pw_id = atoi(pos + 10);
|
cfg.dev_pw_id = atoi(pos + 10);
|
||||||
|
|
||||||
|
pos = os_strstr(phase1, " pkhash=");
|
||||||
|
if (pos) {
|
||||||
|
size_t len;
|
||||||
|
pos += 8;
|
||||||
|
end = os_strchr(pos, ' ');
|
||||||
|
if (end)
|
||||||
|
len = end - pos;
|
||||||
|
else
|
||||||
|
len = os_strlen(pos);
|
||||||
|
if (len != 2 * WPS_OOB_PUBKEY_HASH_LEN ||
|
||||||
|
hexstr2bin(pos, pkhash, WPS_OOB_PUBKEY_HASH_LEN)) {
|
||||||
|
wpa_printf(MSG_INFO, "EAP-WSC: Invalid pkhash");
|
||||||
|
os_free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
cfg.peer_pubkey_hash = pkhash;
|
||||||
|
}
|
||||||
|
|
||||||
res = eap_wsc_new_ap_settings(&new_ap_settings, phase1);
|
res = eap_wsc_new_ap_settings(&new_ap_settings, phase1);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
os_free(data);
|
os_free(data);
|
||||||
|
|
|
@ -133,6 +133,12 @@ struct wps_data * wps_init(const struct wps_config *cfg)
|
||||||
data->use_psk_key = cfg->use_psk_key;
|
data->use_psk_key = cfg->use_psk_key;
|
||||||
data->pbc_in_m1 = cfg->pbc_in_m1;
|
data->pbc_in_m1 = cfg->pbc_in_m1;
|
||||||
|
|
||||||
|
if (cfg->peer_pubkey_hash) {
|
||||||
|
os_memcpy(data->peer_pubkey_hash, cfg->peer_pubkey_hash,
|
||||||
|
WPS_OOB_PUBKEY_HASH_LEN);
|
||||||
|
data->peer_pubkey_hash_set = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,11 @@ struct wps_config {
|
||||||
* PBC with the AP.
|
* PBC with the AP.
|
||||||
*/
|
*/
|
||||||
int pbc_in_m1;
|
int pbc_in_m1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* peer_pubkey_hash - Peer public key hash or %NULL if not known
|
||||||
|
*/
|
||||||
|
const u8 *peer_pubkey_hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wps_data * wps_init(const struct wps_config *cfg);
|
struct wps_data * wps_init(const struct wps_config *cfg);
|
||||||
|
|
|
@ -514,6 +514,23 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wps->peer_pubkey_hash_set) {
|
||||||
|
u8 hash[WPS_HASH_LEN];
|
||||||
|
sha256_vector(1, &pk, &pk_len, hash);
|
||||||
|
if (os_memcmp(hash, wps->peer_pubkey_hash,
|
||||||
|
WPS_OOB_PUBKEY_HASH_LEN) != 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "WPS: Public Key hash mismatch");
|
||||||
|
wpa_hexdump(MSG_DEBUG, "WPS: Received public key",
|
||||||
|
pk, pk_len);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "WPS: Calculated public key "
|
||||||
|
"hash", hash, WPS_OOB_PUBKEY_HASH_LEN);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "WPS: Expected public key hash",
|
||||||
|
wps->peer_pubkey_hash,
|
||||||
|
WPS_OOB_PUBKEY_HASH_LEN);
|
||||||
|
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)
|
||||||
|
|
|
@ -75,6 +75,9 @@ struct wps_data {
|
||||||
size_t alt_dev_password_len;
|
size_t alt_dev_password_len;
|
||||||
u16 alt_dev_pw_id;
|
u16 alt_dev_pw_id;
|
||||||
|
|
||||||
|
u8 peer_pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN];
|
||||||
|
int peer_pubkey_hash_set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* request_type - Request Type attribute from (Re)AssocReq
|
* request_type - Request Type attribute from (Re)AssocReq
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -813,7 +813,7 @@ static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
|
||||||
else if (hwaddr_aton(cmd, bssid))
|
else if (hwaddr_aton(cmd, bssid))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return wpas_wps_start_nfc(wpa_s, _bssid);
|
return wpas_wps_start_nfc(wpa_s, _bssid, NULL, 0, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1072,12 +1072,14 @@ 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,
|
static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
const char *pin, int p2p_group, u16 dev_pw_id)
|
const char *pin, int p2p_group, u16 dev_pw_id,
|
||||||
|
const u8 *peer_pubkey_hash)
|
||||||
{
|
{
|
||||||
struct wpa_ssid *ssid;
|
struct wpa_ssid *ssid;
|
||||||
char val[128];
|
char val[128 + 2 * WPS_OOB_PUBKEY_HASH_LEN];
|
||||||
unsigned int rpin = 0;
|
unsigned int rpin = 0;
|
||||||
|
char hash[2 * WPS_OOB_PUBKEY_HASH_LEN + 10];
|
||||||
|
|
||||||
wpas_clear_wps(wpa_s);
|
wpas_clear_wps(wpa_s);
|
||||||
ssid = wpas_wps_add_network(wpa_s, 0, bssid);
|
ssid = wpas_wps_add_network(wpa_s, 0, bssid);
|
||||||
|
@ -1085,6 +1087,14 @@ int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
return -1;
|
return -1;
|
||||||
ssid->temporary = 1;
|
ssid->temporary = 1;
|
||||||
ssid->p2p_group = p2p_group;
|
ssid->p2p_group = p2p_group;
|
||||||
|
if (peer_pubkey_hash) {
|
||||||
|
os_memcpy(hash, " pkhash=", 8);
|
||||||
|
wpa_snprintf_hex_uppercase(hash + 8, sizeof(hash) - 8,
|
||||||
|
peer_pubkey_hash,
|
||||||
|
WPS_OOB_PUBKEY_HASH_LEN);
|
||||||
|
} else {
|
||||||
|
hash[0] = '\0';
|
||||||
|
}
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
|
if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
|
||||||
ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
|
ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
|
||||||
|
@ -1098,12 +1108,12 @@ int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
if (pin)
|
if (pin)
|
||||||
os_snprintf(val, sizeof(val), "\"pin=%s dev_pw_id=%u\"",
|
os_snprintf(val, sizeof(val), "\"pin=%s dev_pw_id=%u%s\"",
|
||||||
pin, dev_pw_id);
|
pin, dev_pw_id, hash);
|
||||||
else {
|
else {
|
||||||
rpin = wps_generate_pin();
|
rpin = wps_generate_pin();
|
||||||
os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u\"",
|
os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u%s\"",
|
||||||
rpin, dev_pw_id);
|
rpin, dev_pw_id, hash);
|
||||||
}
|
}
|
||||||
if (wpa_config_set(ssid, "phase1", val, 0) < 0)
|
if (wpa_config_set(ssid, "phase1", val, 0) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1117,6 +1127,14 @@ 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, int p2p_group, u16 dev_pw_id)
|
||||||
|
{
|
||||||
|
return wpas_wps_start_dev_pw(wpa_s, bssid, pin, p2p_group, dev_pw_id,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Cancel the wps pbc/pin requests */
|
/* Cancel the wps pbc/pin requests */
|
||||||
int wpas_wps_cancel(struct wpa_supplicant *wpa_s)
|
int wpas_wps_cancel(struct wpa_supplicant *wpa_s)
|
||||||
{
|
{
|
||||||
|
@ -2070,14 +2088,21 @@ struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid)
|
int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
|
const struct wpabuf *dev_pw, u16 dev_pw_id,
|
||||||
|
int p2p_group, const u8 *peer_pubkey_hash)
|
||||||
{
|
{
|
||||||
struct wps_context *wps = wpa_s->wps;
|
struct wps_context *wps = wpa_s->wps;
|
||||||
char pw[32 * 2 + 1];
|
char pw[32 * 2 + 1];
|
||||||
|
|
||||||
|
if (dev_pw == NULL) {
|
||||||
|
dev_pw = wpa_s->conf->wps_nfc_dev_pw;
|
||||||
|
dev_pw_id = wpa_s->conf->wps_nfc_dev_pw_id;
|
||||||
|
}
|
||||||
|
|
||||||
if (wpa_s->conf->wps_nfc_dh_pubkey == NULL ||
|
if (wpa_s->conf->wps_nfc_dh_pubkey == NULL ||
|
||||||
wpa_s->conf->wps_nfc_dh_privkey == NULL ||
|
wpa_s->conf->wps_nfc_dh_privkey == NULL ||
|
||||||
wpa_s->conf->wps_nfc_dev_pw == NULL)
|
dev_pw == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
dh5_free(wps->dh_ctx);
|
dh5_free(wps->dh_ctx);
|
||||||
|
@ -2103,10 +2128,9 @@ int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid)
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_snprintf_hex_uppercase(pw, sizeof(pw),
|
wpa_snprintf_hex_uppercase(pw, sizeof(pw),
|
||||||
wpabuf_head(wpa_s->conf->wps_nfc_dev_pw),
|
wpabuf_head(dev_pw), wpabuf_len(dev_pw));
|
||||||
wpabuf_len(wpa_s->conf->wps_nfc_dev_pw));
|
return wpas_wps_start_dev_pw(wpa_s, bssid, pw, p2p_group, dev_pw_id,
|
||||||
return wpas_wps_start_pin(wpa_s, bssid, pw, 0,
|
peer_pubkey_hash);
|
||||||
wpa_s->conf->wps_nfc_dev_pw_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,9 @@ void wpas_wps_update_config(struct wpa_supplicant *wpa_s);
|
||||||
struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
|
struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
|
||||||
int ndef, const char *id_str);
|
int ndef, const char *id_str);
|
||||||
struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef);
|
struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef);
|
||||||
int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid);
|
int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
|
const struct wpabuf *dev_pw, u16 dev_pw_id,
|
||||||
|
int p2p_group, const u8 *peer_pubkey_hash);
|
||||||
int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s,
|
int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s,
|
||||||
const struct wpabuf *data);
|
const struct wpabuf *data);
|
||||||
struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr);
|
struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr);
|
||||||
|
|
Loading…
Reference in a new issue