wpa_supplicant previously hard-coded the destination MAC address for EAPOL packets to 01:80:c2:00:00:03 (the "PAE Group Address"). The PAE Group Address continues to be the default value for the newly introduced wpa_supplicant per-network eapol_dest_addr configuration setting, but alternative multicast addresses (e.g. 01:80:c2:00:00:1f - the "EDE-CC PEP Address") can now be specified so that outgoing packets can reach the desired destination station(s) in a wider variety of operating environments. For example third party ISP switches providing layer 2 forwarding services to a customer should filter or terminate packets which use the PAE Group Address according to 802.1D ("Ethernet MAC bridges"). This will effectively prevent a customer creating their own secure 802.1X + MACsec links atop the ISP-provided layer 2 network. The same ISP switches should instead forward packets which use the ECE-CC PEP Address (or a variety of other multicast addresses which may be better suited to the particular usage scenario). --- src/ap/ap_config.h | 1 + src/ap/wpa_auth_kay.c | 1 + src/common/ieee802_1x_defs.h | 8 ++++++ src/pae/ieee802_1x_kay.c | 12 ++++----- src/pae/ieee802_1x_kay.h | 5 +++- wpa_supplicant/config.c | 51 ++++++++++++++++++++++++++++++++++++ wpa_supplicant/config_ssid.h | 11 ++++++++ wpa_supplicant/wpas_kay.c | 1 + 8 files changed, 83 insertions(+), 7 deletions(-) diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index d42076785d..57e38c8be7 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -301,6 +301,7 @@ struct hostapd_bss_config { int eapol_version; int eap_server; /* Use internal EAP server instead of external * RADIUS server */ + u8 eapol_dest_addr[ETH_ALEN]; struct hostapd_eap_user *eap_user; char *eap_user_sqlite; char *eap_sim_db; diff --git a/src/ap/wpa_auth_kay.c b/src/ap/wpa_auth_kay.c index 625f405127..107924fa90 100644 --- a/src/ap/wpa_auth_kay.c +++ b/src/ap/wpa_auth_kay.c @@ -331,6 +331,7 @@ int ieee802_1x_alloc_kay_sm_hapd(struct hostapd_data *hapd, hapd->conf->macsec_port, hapd->conf->mka_priority, hapd->conf->macsec_csindex, + hapd->conf->eapol_dest_addr, hapd->conf->iface, hapd->own_addr); /* ieee802_1x_kay_init() frees kay_ctx on failure */ diff --git a/src/common/ieee802_1x_defs.h b/src/common/ieee802_1x_defs.h index e7acff108e..b193472a76 100644 --- a/src/common/ieee802_1x_defs.h +++ b/src/common/ieee802_1x_defs.h @@ -83,4 +83,12 @@ enum confidentiality_offset { #define DEFAULT_PRIO_GROUP_CA_MEMBER 0x70 #define DEFAULT_PRIO_NOT_KEY_SERVER 0xFF +/* + * Nearest non-TPMR (non Two Port MAC Relay) Bridge group address, + * also referred to as IEEE Std 802.1X PAE address + * IEEE Std 802.1X-2020 - Table 11-1 + */ + +#define PAE_GROUP_ADDRESS { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 } + #endif /* IEEE802_1X_DEFS_H */ diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c index 230c69d197..c76f7501f0 100644 --- a/src/pae/ieee802_1x_kay.c +++ b/src/pae/ieee802_1x_kay.c @@ -2451,10 +2451,6 @@ ieee802_1x_kay_decide_macsec_use( return 0; } -static const u8 pae_group_addr[ETH_ALEN] = { - 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 -}; - /** * ieee802_1x_kay_encode_mkpdu - @@ -2468,7 +2464,8 @@ ieee802_1x_kay_encode_mkpdu(struct ieee802_1x_mka_participant *participant, struct ieee802_1x_hdr *eapol_hdr; ether_hdr = wpabuf_put(pbuf, sizeof(*ether_hdr)); - os_memcpy(ether_hdr->dest, pae_group_addr, sizeof(ether_hdr->dest)); + os_memcpy(ether_hdr->dest, participant->kay->eapol_dest_addr, + sizeof(ether_hdr->dest)); os_memcpy(ether_hdr->src, participant->kay->actor_sci.addr, sizeof(ether_hdr->dest)); ether_hdr->ethertype = host_to_be16(ETH_P_EAPOL); @@ -3495,7 +3492,8 @@ struct ieee802_1x_kay * ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, bool macsec_replay_protect, u32 macsec_replay_window, u8 macsec_offload, u16 port, u8 priority, - u32 macsec_csindex, const char *ifname, const u8 *addr) + u32 macsec_csindex, + const u8 *eapol_dest_addr, const char *ifname, const u8 *addr) { struct ieee802_1x_kay *kay; @@ -3536,6 +3534,8 @@ ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, kay->mka_algindex = DEFAULT_MKA_ALG_INDEX; kay->mka_version = MKA_VERSION_ID; + os_memcpy(kay->eapol_dest_addr, eapol_dest_addr, ETH_ALEN); + os_memcpy(kay->algo_agility, mka_algo_agility, sizeof(kay->algo_agility)); diff --git a/src/pae/ieee802_1x_kay.h b/src/pae/ieee802_1x_kay.h index 11464f7fc6..fd16db3a07 100644 --- a/src/pae/ieee802_1x_kay.h +++ b/src/pae/ieee802_1x_kay.h @@ -234,6 +234,8 @@ struct ieee802_1x_kay { enum validate_frames vf; enum confidentiality_offset co; + + u8 eapol_dest_addr[ETH_ALEN]; }; @@ -243,7 +245,8 @@ struct ieee802_1x_kay * ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, bool macsec_replay_protect, u32 macsec_replay_window, u8 macsec_offload, u16 port, u8 priority, - u32 macsec_csindex, const char *ifname, const u8 *addr); + u32 macsec_csindex, + const u8 *eapol_dest_addr, const char *ifname, const u8 *addr); void ieee802_1x_kay_deinit(struct ieee802_1x_kay *kay); struct ieee802_1x_mka_participant * diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 13043afe94..3c097476a2 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -21,6 +21,9 @@ #include "config.h" +static const u8 pae_group_addr[ETH_ALEN] = PAE_GROUP_ADDRESS; + + #if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE) #define NO_CONFIG_WRITE #endif @@ -1663,6 +1666,30 @@ static int wpa_config_parse_eap(const struct parse_data *data, } +static int wpa_config_parse_eapol_dest_addr(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + wpa_printf(MSG_DEBUG, "value: '%s'", value); + + if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 || + os_strcmp(value, "default") == 0) { + os_memcpy(ssid->eapol_dest_addr, pae_group_addr, ETH_ALEN); + wpa_printf(MSG_DEBUG, "EAPOL using PAE (default) destination MAC address" MACSTR, + MAC2STR(ssid->eapol_dest_addr)); + return 0; + } + if (hwaddr_aton2(value, ssid->eapol_dest_addr) == -1) { + wpa_printf(MSG_ERROR, "Line %d: Invalid EAPOL destination MAC address '%s'.", + line, value); + return -1; + } + wpa_printf(MSG_DEBUG, "EAPOL destination MAC address " MACSTR, + MAC2STR(ssid->eapol_dest_addr)); + return 0; +} + + #ifndef NO_CONFIG_WRITE static char * wpa_config_write_eap(const struct parse_data *data, struct wpa_ssid *ssid) @@ -1697,6 +1724,28 @@ static char * wpa_config_write_eap(const struct parse_data *data, return buf; } + + +static char * wpa_config_write_eapol_dest_addr(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + char *value; + int res; + + if (is_zero_ether_addr(ssid->eapol_dest_addr)) + return NULL; + + value = os_malloc(20); + if (value == NULL) + return NULL; + res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->eapol_dest_addr)); + if (os_snprintf_error(20, res)) { + os_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} #endif /* NO_CONFIG_WRITE */ @@ -2549,6 +2598,7 @@ static const struct parse_data ssid_fields[] = { { INT(vht_center_freq2) }, #ifdef IEEE8021X_EAPOL { FUNC(eap) }, + { FUNC(eapol_dest_addr) }, { STR_LENe(identity, identity) }, { STR_LENe(anonymous_identity, anonymous_identity) }, { STR_LENe(imsi_identity, imsi_identity) }, @@ -3236,6 +3286,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE; ssid->eap.sim_num = DEFAULT_USER_SELECTED_SIM; + os_memcpy(ssid->eapol_dest_addr, pae_group_addr, ETH_ALEN); #endif /* IEEE8021X_EAPOL */ #ifdef CONFIG_MESH ssid->dot11MeshMaxRetries = DEFAULT_MESH_MAX_RETRIES; diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index d64c305082..1909a718d6 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -418,6 +418,17 @@ struct wpa_ssid { */ unsigned int eap_workaround; + /** + * eapol_dest_addr - mac addr for EAPOL packets (802.11AE-2018+ etc.) + * EAPOL packets may have their destination MAC address set to any + * non-individual (i.g. multi-cast) address, including the ethernet + * broadcast address (ff:ff:ff:ff:ff:ff). Choice of destination + * address is dictated by which types of entity (should) filter them + * out vs. act on their contents vs. relay them. + * See 802.11X-2020 Table 11-1 + */ + u8 eapol_dest_addr[ETH_ALEN]; + #endif /* IEEE8021X_EAPOL */ /** diff --git a/wpa_supplicant/wpas_kay.c b/wpa_supplicant/wpas_kay.c index 600b3bc545..4712bcb221 100644 --- a/wpa_supplicant/wpas_kay.c +++ b/wpa_supplicant/wpas_kay.c @@ -249,6 +249,7 @@ int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) ssid->macsec_replay_window, ssid->macsec_offload, ssid->macsec_port, ssid->mka_priority, ssid->macsec_csindex, + ssid->eapol_dest_addr, wpa_s->ifname, wpa_s->own_addr); /* ieee802_1x_kay_init() frees kay_ctx on failure */ if (res == NULL) -- 2.39.5 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap