diff --git a/contrib/wpa/src/drivers/driver_bsd.c b/contrib/wpa/src/drivers/driver_bsd.c index 14c19eb1246c..342f6618d9a0 100644 --- a/contrib/wpa/src/drivers/driver_bsd.c +++ b/contrib/wpa/src/drivers/driver_bsd.c @@ -378,6 +378,9 @@ bsd_set_key(void *priv, struct wpa_driver_set_key_params *params) case WPA_ALG_CCMP: wk.ik_type = IEEE80211_CIPHER_AES_CCM; break; + case WPA_ALG_BIP_CMAC_128: + wk.ik_type = IEEE80211_CIPHER_BIP_CMAC_128; + break; default: wpa_printf(MSG_ERROR, "%s: unknown alg=%d", __func__, alg); return -1; @@ -449,6 +452,9 @@ bsd_configure_wpa(void *priv, struct wpa_bss_params *params) case WPA_CIPHER_CCMP: v = IEEE80211_CIPHER_AES_CCM; break; + case WPA_CIPHER_BIP_CMAC_128: + v = IEEE80211_CIPHER_BIP_CMAC_128; + break; case WPA_CIPHER_TKIP: v = IEEE80211_CIPHER_TKIP; break; @@ -485,6 +491,8 @@ bsd_configure_wpa(void *priv, struct wpa_bss_params *params) } v = 0; + if (params->wpa_pairwise & WPA_CIPHER_BIP_CMAC_128) + v |= 1<wpa_pairwise & WPA_CIPHER_CCMP) v |= 1<wpa_pairwise & WPA_CIPHER_TKIP) @@ -1267,6 +1275,7 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params) u32 mode; int ret = 0; const u8 *wpa_ie, *rsn_ie; + int value = 0; wpa_printf(MSG_DEBUG, "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u" @@ -1316,6 +1325,26 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params) if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0) ret = -1; + /* XXX TODO: only if IEEE80211_IOC_MFP is defined? */ + + switch (params->mgmt_frame_protection) { + case NO_MGMT_FRAME_PROTECTION: + value = 0; // XXX + break; + case MGMT_FRAME_PROTECTION_OPTIONAL: + value = 1; // XXX + break; + case MGMT_FRAME_PROTECTION_REQUIRED: + value = 2; // XXX + break; + } + + if (set80211param(priv, IEEE80211_IOC_MFP, value)) { + wpa_printf(MSG_INFO, + "Unable to set MFP configuration to %d", value); + // TODO: XXX not perm failure + } + if (params->wpa_ie_len) { rsn_ie = get_ie(params->wpa_ie, params->wpa_ie_len, WLAN_EID_RSN); diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c index c6875785f8f5..646a33881d6c 100644 --- a/sbin/ifconfig/ifieee80211.c +++ b/sbin/ifconfig/ifieee80211.c @@ -126,6 +126,7 @@ #define IEEE80211_NODE_VHT 0x100000 /* VHT enabled */ #define IEEE80211_NODE_LDPC 0x200000 /* LDPC enabled */ #define IEEE80211_NODE_UAPSD 0x400000 /* UAPSD enabled */ +#define IEEE80211_NODE_MFP 0x800000 /* MFP enabled */ #endif /* XXX should also figure out where to put these for k/u-space sharing. */ @@ -2693,6 +2694,8 @@ getflags(int flags) *cp++ = 'U'; if (flags & IEEE80211_NODE_LDPC) *cp++ = 'L'; + if (flags & IEEE80211_NODE_MFP) + *cp++ = 'F'; *cp = '\0'; return flagstring; } @@ -4985,6 +4988,20 @@ ieee80211_status(if_ctx *ctx) } } + if (get80211val(ctx, IEEE80211_IOC_MFP, &val) != -1) { + switch (val) { + case 0: + LINE_CHECK("mfp DISABLED"); + break; + case 1: + LINE_CHECK("mfp OPTIONAL"); + break; + case 2: + LINE_CHECK("mfp REQUIRED"); + break; + } + } + if (wpa || verbose) { if (get80211val(ctx, IEEE80211_IOC_WPS, &val) != -1) { if (val) diff --git a/sys/conf/files b/sys/conf/files index 875021aaa357..87d7fd533732 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -4208,6 +4208,8 @@ net80211/ieee80211_adhoc.c optional wlan \ compile-with "${NORMAL_C} -Wno-unused-function" net80211/ieee80211_ageq.c optional wlan net80211/ieee80211_amrr.c optional wlan | wlan_amrr +net80211/ieee80211_crypto_bip_cmac.c optional wlan wlan_bip_cmac +net80211/ieee80211_crypto_bip_gmac.c optional wlan wlan_bip_gmac net80211/ieee80211_crypto.c optional wlan \ compile-with "${NORMAL_C} -Wno-unused-function" net80211/ieee80211_crypto_ccmp.c optional wlan wlan_ccmp diff --git a/sys/dev/ath/if_ath_keycache.c b/sys/dev/ath/if_ath_keycache.c index a58625ad2803..192af2d9e642 100644 --- a/sys/dev/ath/if_ath_keycache.c +++ b/sys/dev/ath/if_ath_keycache.c @@ -440,6 +440,9 @@ ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, "%s: bogus group key\n", __func__); return 0; } + + /* TODO: bogus BIP key */ + if (vap->iv_opmode != IEEE80211_M_HOSTAP || !(k->wk_flags & IEEE80211_KEY_GROUP) || !sc->sc_mcastkey) { @@ -502,6 +505,10 @@ ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && sc->sc_splitmic) ath_hal_keyreset(ah, keyix+32); /* RX key */ if (keyix >= IEEE80211_WEP_NKID) { + if ((keyix == 4 || keyix == 5) && (k->wk_flags & (IEEE80211_KEY_GROUP | IEEE80211_KEY_IGTK))) { + device_printf(sc->sc_dev, "%s: called: GROUP: keyix=%d, flags=0x%08x\n", + __func__, k->wk_keyix, k->wk_flags); + } /* * Don't touch keymap entries for global keys so * they are never considered for dynamic allocation. diff --git a/sys/dev/rtwn/if_rtwn_cam.c b/sys/dev/rtwn/if_rtwn_cam.c index d142cd0476e4..9421d2627437 100644 --- a/sys/dev/rtwn/if_rtwn_cam.c +++ b/sys/dev/rtwn/if_rtwn_cam.c @@ -185,11 +185,32 @@ rtwn_key_set_cb0(struct rtwn_softc *sc, const struct ieee80211_key *k) uint8_t algo, keyid; int i, error; + /* + * TODO: what about IGTK keys (4, 5) ? Would they allocated + * as "real" keycache entries? + */ + + /* + * TODO: I likely need to clean up by introducing + * "are these WEP group keys" and "are these IGTK group keys" + * inline functions and use them here, not the wk_keyix thing). + */ + if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL && - k->wk_keyix < IEEE80211_WEP_NKID) + k->wk_keyix < IEEE80211_WEP_NKID) { + keyid = k->wk_keyix; + } else if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL && + k->wk_flags & IEEE80211_KEY_GROUP) { keyid = k->wk_keyix; - else + } else if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL && + (k->wk_flags & (IEEE80211_KEY_GROUP | IEEE80211_KEY_IGTK)) && + (k->wk_keyix == 4 || k->wk_keyix == 5)) { + device_printf(sc->sc_dev, "%s: got group key idx 4/5? (%d) (flags=0x%08x)\n", + __func__, k->wk_keyix, k->wk_flags); keyid = 0; + } else { + keyid = 0; + } /* Map net80211 cipher to HW crypto algorithm. */ switch (k->wk_cipher->ic_cipher) { diff --git a/sys/modules/Makefile b/sys/modules/Makefile index d3ef4c63a41c..1c18e6198f0d 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -418,6 +418,8 @@ SUBDIR= \ wlan \ wlan_acl \ wlan_amrr \ + wlan_bip_cmac \ + wlan_bip_gmac \ wlan_ccmp \ wlan_rssadapt \ wlan_tkip \ diff --git a/sys/net80211/_ieee80211.h b/sys/net80211/_ieee80211.h index 5c7e6110026d..49de8b78c886 100644 --- a/sys/net80211/_ieee80211.h +++ b/sys/net80211/_ieee80211.h @@ -487,7 +487,7 @@ struct ieee80211_mimo_info { #define IEEE80211_C_SWSLEEP 0x00080000 /* CAPABILITY: do sleep here */ #define IEEE80211_C_SWAMSDUTX 0x00100000 /* CAPABILITY: software A-MSDU TX */ #define IEEE80211_C_UAPSD 0x00200000 /* CAPABILITY: U-APSD */ -/* 0x7c0000 available */ +#define IEEE80211_C_MFP 0x00400000 /* CAPABILITY: MFP */ #define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ #define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ #define IEEE80211_C_WPA 0x01800000 /* CAPABILITY: WPA1+WPA2 avail*/ diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index 20834614de8f..52665debe708 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -592,6 +592,9 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, vap->iv_opmode = opmode; vap->iv_caps |= ieee80211_opcap[opmode]; + + vap->iv_mfp_cfg = 0; // XXX + IEEE80211_ADDR_COPY(vap->iv_myaddr, ic->ic_macaddr); switch (opmode) { case IEEE80211_M_WDS: diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h index fe2a0a7f3b64..e471569fa3c2 100644 --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -1469,7 +1469,10 @@ enum { #define IEEE80211_WEP_TOTLEN (IEEE80211_WEP_IVLEN + \ IEEE80211_WEP_KIDLEN + \ IEEE80211_WEP_CRCLEN) -#define IEEE80211_WEP_NKID 4 /* number of key ids */ + +#define IEEE80211_WEP_NKID 4 /* number of WEP/global key ids */ +#define IEEE80211_MAX_NKID 6 /* number of WEP/global/iGTK key ids */ +#define IEEE80211_IGTK_NKID 2 /* number of iGTK key IDs */ /* * 802.11i defines an extended IV for use with non-WEP ciphers. diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c index 12ab81960b23..0b8ba02e317d 100644 --- a/sys/net80211/ieee80211_crypto.c +++ b/sys/net80211/ieee80211_crypto.c @@ -231,9 +231,11 @@ ieee80211_crypto_vattach(struct ieee80211vap *vap) /* NB: we assume everything is pre-zero'd */ vap->iv_max_keyix = IEEE80211_WEP_NKID; vap->iv_def_txkey = IEEE80211_KEYIX_NONE; - for (i = 0; i < IEEE80211_WEP_NKID; i++) + + for (i = 0; i < IEEE80211_MAX_NKID; i++) ieee80211_crypto_resetkey(vap, &vap->iv_nw_keys[i], IEEE80211_KEYIX_NONE); + /* * Initialize the driver key support routines to noop entries. * This is useful especially for the cipher test modules. @@ -546,7 +548,7 @@ ieee80211_crypto_delglobalkeys(struct ieee80211vap *vap) int i; ieee80211_key_update_begin(vap); - for (i = 0; i < IEEE80211_WEP_NKID; i++) + for (i = 0; i < IEEE80211_MAX_NKID; i++) (void) _ieee80211_crypto_delkey(vap, &vap->iv_nw_keys[i]); ieee80211_key_update_end(vap); } @@ -857,11 +859,16 @@ ieee80211_crypto_reload_keys(struct ieee80211com *ic) TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { if (vap->iv_state != IEEE80211_S_RUN) continue; + + /* Global/WEP keys */ for (i = 0; i < IEEE80211_WEP_NKID; i++) { const struct ieee80211_key *k = &vap->iv_nw_keys[i]; if (k->wk_flags & IEEE80211_KEY_DEVKEY) dev_key_set(vap, k); } + + /* TODO: do the two iGTK keys too if the driver supports it? */ + /* (The drivers will need to be made aware of the other two KIDs and ignore them if needed..) */ } /* * Unicast keys. diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h index d8ca6e49f4c7..1f74df372b96 100644 --- a/sys/net80211/ieee80211_crypto.h +++ b/sys/net80211/ieee80211_crypto.h @@ -91,6 +91,7 @@ struct ieee80211_key { #define IEEE80211_KEY_NOIVMGT 0x00008000 /* don't insert IV/MIC for mgmt */ #define IEEE80211_KEY_NOMIC 0x00010000 /* don't insert MIC for !mgmt */ #define IEEE80211_KEY_NOMICMGT 0x00020000 /* don't insert MIC for mgmt */ +#define IEEE80211_KEY_IGTK 0x00040000 /* key is used for IGTK */ ieee80211_keyix wk_keyix; /* h/w key index */ ieee80211_keyix wk_rxkeyix; /* optional h/w rx key index */ @@ -106,7 +107,7 @@ struct ieee80211_key { }; #define IEEE80211_KEY_COMMON /* common flags passed in by apps */\ (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV | IEEE80211_KEY_GROUP | \ - IEEE80211_KEY_NOREPLAY) + IEEE80211_KEY_NOREPLAY | IEEE80211_KEY_IGTK) #define IEEE80211_KEY_SWCRYPT \ (IEEE80211_KEY_SWENCRYPT | IEEE80211_KEY_SWDECRYPT) diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c index eca893fa6810..b37620f41e34 100644 --- a/sys/net80211/ieee80211_ddb.c +++ b/sys/net80211/ieee80211_ddb.c @@ -604,7 +604,7 @@ _db_show_vap(const struct ieee80211vap *vap, int showmesh, int showprocs) db_printf("\tmax_keyix %u", vap->iv_max_keyix); db_printf(" def_txkey %d", vap->iv_def_txkey); db_printf("\n"); - for (i = 0; i < IEEE80211_WEP_NKID; i++) + for (i = 0; i < IEEE80211_MAX_NKID; i++) _db_show_key("\tnw_keys[%u]", i, &vap->iv_nw_keys[i]); db_printf("\tauth %p(%s)", vap->iv_auth, vap->iv_auth->ia_name); diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index c1687cd8bfc8..d4e4a78f95fd 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -93,7 +93,7 @@ ieee80211_ioctl_getkey(u_long cmd, struct ieee80211vap *vap, return ENOENT; wk = &ni->ni_ucastkey; } else { - if (kid >= IEEE80211_WEP_NKID) + if (kid >= IEEE80211_MAX_NKID) return EINVAL; wk = &vap->iv_nw_keys[kid]; IEEE80211_ADDR_COPY(&ik.ik_macaddr, vap->iv_bss->ni_macaddr); @@ -1166,6 +1166,11 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, if (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD) ireq->i_val = 1; break; + case IEEE80211_IOC_MFP: + /* TODO: IEEE80211_C_MFP check */ + if_printf(vap->iv_ifp, "%s: MFP: get: %d\n", __func__, vap->iv_mfp_cfg); + ireq->i_val = vap->iv_mfp_cfg; + break; case IEEE80211_IOC_VHTCONF: ireq->i_val = vap->iv_vht_flags & IEEE80211_FVHT_MASK; break; @@ -1214,7 +1219,7 @@ ieee80211_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq) } wk = &ni->ni_ucastkey; } else { - if (kid >= IEEE80211_WEP_NKID) + if (kid >= IEEE80211_MAX_NKID) return EINVAL; wk = &vap->iv_nw_keys[kid]; /* @@ -3509,6 +3514,12 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r else return EINVAL; break; + case IEEE80211_IOC_MFP: + /* TODO: IEEE80211_C_MFP check */ + if_printf(vap->iv_ifp, "%s: MFP: set %d\n", __func__, ireq->i_val); + /* XXX magic value; no validity checking */ + vap->iv_mfp_cfg = ireq->i_val; + break; /* VHT */ case IEEE80211_IOC_VHTCONF: diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h index 7d11d708f4b8..b462b8baa8d7 100644 --- a/sys/net80211/ieee80211_ioctl.h +++ b/sys/net80211/ieee80211_ioctl.h @@ -715,6 +715,7 @@ struct ieee80211req { #define IEEE80211_IOC_LDPC 114 /* LDPC Tx/RX (on, off) */ #define IEEE80211_IOC_UAPSD 115 /* UAPSD (on, off) */ #define IEEE80211_IOC_UAPSD_INFO 116 /* UAPSD (SP, per-AC enable) */ +#define IEEE80211_IOC_MFP 117 /* MFP (off, optional, required) */ /* VHT */ #define IEEE80211_IOC_VHTCONF 130 /* VHT config (off, on; widths) */ diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index 954e8e03563f..e577dc0440c1 100644 --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -145,6 +145,7 @@ struct ieee80211_node { #define IEEE80211_NODE_VHT 0x100000 /* VHT enabled */ #define IEEE80211_NODE_LDPC 0x200000 /* LDPC enabled */ #define IEEE80211_NODE_UAPSD 0x400000 /* U-APSD power save enabled */ +#define IEEE80211_NODE_MFP 0x800000 /* MFP enabled */ uint16_t ni_associd; /* association ID */ uint16_t ni_vlan; /* vlan tag */ uint16_t ni_txpower; /* current transmit power */ diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index cc65252c9eb9..dc8629f42bfc 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -509,7 +509,7 @@ struct ieee80211vap { /* Key management */ uint16_t iv_max_keyix; /* max h/w key index */ ieee80211_keyix iv_def_txkey; /* default/group tx key index */ - struct ieee80211_key iv_nw_keys[IEEE80211_WEP_NKID]; + struct ieee80211_key iv_nw_keys[IEEE80211_MAX_NKID]; int (*iv_key_alloc)(struct ieee80211vap *, struct ieee80211_key *, ieee80211_keyix *, ieee80211_keyix *); @@ -611,6 +611,9 @@ struct ieee80211vap { /* per-vap U-APSD state */ uint8_t iv_uapsdinfo; /* sta mode QoS Info flags */ + /* per-VAP MFP configuration */ + int iv_mfp_cfg; + /* Optional transmit/receive histogram statistics */ struct ieee80211_rx_histogram *rx_histogram; struct ieee80211_tx_histogram *tx_histogram;