#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "mesh_mpm.h"
+#include "mesh_rsn.h"
/* TODO make configurable */
#define dot11MeshMaxRetries 10
struct hostapd_data *bss = ifmsh->bss[0];
struct mesh_conf *conf = ifmsh->mconf;
u8 supp_rates[2 + 2 + 32];
- u8 *pos;
+ u8 *pos, *cat;
u8 ie_len, add_plid = 0;
int ret;
int ampe = conf->security & MESH_CONF_SEC_AMPE;
if (!buf)
return;
+ cat = wpabuf_mhead_u8(buf);
wpabuf_put_u8(buf, WLAN_ACTION_SELF_PROTECTED);
wpabuf_put_u8(buf, type);
wpabuf_put_le16(buf, sta->peer_lid);
if (type == PLINK_CLOSE)
wpabuf_put_le16(buf, close_reason);
+ if (ampe)
+ mesh_rsn_get_pmkid(wpa_s->mesh_rsn, sta,
+ wpabuf_put(buf, PMKID_LEN));
/* TODO HT IEs */
+ if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Mesh MPM: failed to add AMPE and MIC IE");
+ goto fail;
+ }
+
ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0,
sta->addr, wpa_s->own_addr, wpa_s->own_addr,
wpabuf_head(buf), wpabuf_len(buf), 0);
wpa_msg(wpa_s, MSG_INFO,
"Mesh MPM: failed to send peering frame");
+fail:
wpabuf_free(buf);
}
* the AP code already sets this flag. */
sta->flags |= WLAN_STA_AUTH;
+ mesh_rsn_init_ampe_sta(wpa_s, sta);
+
os_memset(¶ms, 0, sizeof(params));
params.addr = sta->addr;
params.flags = WPA_STA_AUTHENTICATED | WPA_STA_AUTHORIZED;
return;
}
- mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
+ if (conf->security == MESH_CONF_SEC_NONE)
+ mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
+ else
+ mesh_rsn_auth_sae_sta(wpa_s, sta);
}
struct sta_info *sta)
{
struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+ struct mesh_conf *conf = wpa_s->ifmsh->mconf;
+ u8 seq[6] = {};
wpa_msg(wpa_s, MSG_INFO, "mesh plink with " MACSTR " established",
MAC2STR(sta->addr));
+ if (conf->security & MESH_CONF_SEC_AMPE) {
+ wpa_drv_set_key(wpa_s, WPA_ALG_CCMP, sta->addr, 0, 0,
+ seq, sizeof(seq), sta->mtk, sizeof(sta->mtk));
+ wpa_drv_set_key(wpa_s, WPA_ALG_CCMP, sta->addr, 1, 0,
+ seq, sizeof(seq),
+ sta->mgtk, sizeof(sta->mgtk));
+ wpa_drv_set_key(wpa_s, WPA_ALG_IGTK, sta->addr, 4, 0,
+ seq, sizeof(seq),
+ sta->mgtk, sizeof(sta->mgtk));
+
+ wpa_hexdump_key(MSG_DEBUG, "mtk:", sta->mtk, sizeof(sta->mtk));
+ wpa_hexdump_key(MSG_DEBUG, "mgtk:",
+ sta->mgtk, sizeof(sta->mgtk));
+ }
+
wpa_mesh_set_plink_state(wpa_s, sta, PLINK_ESTAB);
hapd->num_plinks++;
enum plink_event event)
{
struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+ struct mesh_conf *conf = wpa_s->ifmsh->mconf;
u16 reason = 0;
wpa_msg(wpa_s, MSG_DEBUG, "MPM " MACSTR " state %s event %s",
PLINK_CONFIRM, 0);
break;
case CNF_ACPT:
+ if (conf->security & MESH_CONF_SEC_AMPE)
+ mesh_rsn_derive_mtk(wpa_s, sta);
mesh_mpm_plink_estab(wpa_s, sta);
break;
default:
{
u8 action_field;
struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+ struct mesh_conf *mconf = wpa_s->ifmsh->mconf;
struct sta_info *sta;
u16 plid = 0, llid = 0;
enum plink_event event;
if (!sta)
return;
+#ifdef CONFIG_SAE
+ /* peer is in sae_accepted? */
+ if (sta->sae && sta->sae->state != SAE_ACCEPTED)
+ return;
+#endif /* CONFIG_SAE */
+
if (!sta->my_lid)
mesh_mpm_init_link(wpa_s, sta);
+ if (mconf->security & MESH_CONF_SEC_AMPE)
+ if (mesh_rsn_process_ampe(wpa_s, sta, &elems,
+ &mgmt->u.action.category,
+ ies, ie_len))
+ return;
+
if (sta->plink_state == PLINK_BLOCKED)
return;