Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160070758
D57551.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D57551.diff
View Options
diff --git a/sys/dev/ath/if_ath_keycache.c b/sys/dev/ath/if_ath_keycache.c
--- a/sys/dev/ath/if_ath_keycache.c
+++ b/sys/dev/ath/if_ath_keycache.c
@@ -215,6 +215,16 @@
int ret;
memset(&hk, 0, sizeof(hk));
+
+ /*
+ * If it's a IGTK key then just plain ignore it;
+ * it's already marked as handled in software and we don't
+ * need a keycache entry for it.
+ */
+ if (ieee80211_is_key_igtk(vap, k)) {
+ return (1);
+ }
+
/*
* Software crypto uses a "clear key" so non-crypto
* state kept in the key cache are maintained and
@@ -435,6 +445,18 @@
{
struct ath_softc *sc = vap->iv_ic->ic_softc;
+ /*
+ * Skip IGTK keys; they're global but not used
+ * in the normal hardware keyix slots.
+ */
+ if (ieee80211_is_key_igtk(vap, k)) {
+ DPRINTF(sc, ATH_DEBUG_KEYCACHE,
+ "%s: iGTK key; skipping\n", __func__);
+ k->wk_flags |= IEEE80211_KEY_SWCRYPT;
+ *keyix = *rxkeyix = IEEE80211_KEYIX_NONE;
+ return 1;
+ }
+
/*
* Group key allocation must be handled specially for
* parts that do not support multicast key cache search
@@ -456,6 +478,9 @@
"%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) {
@@ -517,7 +542,16 @@
if (cip->ic_cipher == IEEE80211_CIPHER_TKIP &&
(k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && sc->sc_splitmic)
ath_hal_keyreset(ah, keyix+32); /* RX key */
- if (keyix >= IEEE80211_WEP_NKID) {
+
+ /*
+ * Skip BIP keys; key indexes 4 and 5 are valid non-global
+ * keycache entries
+ */
+ if (ieee80211_is_key_igtk(vap, k)) {
+ DPRINTF(sc, ATH_DEBUG_KEYCACHE,
+ "%s: keyix=%d but igtk key; skipping\n",
+ __func__, keyix);
+ } else if (keyix >= IEEE80211_WEP_NKID) {
/*
* Don't touch keymap entries for global keys so
* they are never considered for dynamic allocation.
diff --git a/sys/dev/iwx/if_iwx.c b/sys/dev/iwx/if_iwx.c
--- a/sys/dev/iwx/if_iwx.c
+++ b/sys/dev/iwx/if_iwx.c
@@ -11081,6 +11081,10 @@
*keyix = 0; /* NB: use key index 0 for ucast key */
} else if (ieee80211_is_key_global(vap, k)) {
*keyix = ieee80211_crypto_get_key_wepidx(vap, k);
+ } else if (ieee80211_is_key_igtk(vap, k)) {
+ *keyix = *rxkeyix = IEEE80211_KEYIX_NONE;
+ k->wk_flags |= IEEE80211_KEY_SWCRYPT;
+ return (1);
} else {
net80211_vap_printf(vap, "%s: invalid crypto key type\n",
__func__);
diff --git a/sys/dev/rtwn/if_rtwn_cam.c b/sys/dev/rtwn/if_rtwn_cam.c
--- a/sys/dev/rtwn/if_rtwn_cam.c
+++ b/sys/dev/rtwn/if_rtwn_cam.c
@@ -135,6 +135,15 @@
goto end;
}
+ /*
+ * IGTK encryption/decryption are handled in software.
+ */
+ if (ieee80211_is_key_igtk(vap, k)) {
+ k->wk_flags |= IEEE80211_KEY_SWCRYPT;
+ *keyix = 0;
+ goto end;
+ }
+
start = sc->cam_entry_limit;
switch (sc->sc_hwcrypto) {
case RTWN_CRYPTO_SW:
@@ -186,6 +195,11 @@
uint8_t algo, keyid;
int i, error;
+ /*
+ * If full encryption is supported and the key is a
+ * global/WEP key then use the hardware allocated key index,
+ * otherwise default to key 0 (default unicast key.)
+ */
if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL &&
k->wk_keyix < IEEE80211_WEP_NKID)
keyid = k->wk_keyix;
@@ -273,6 +287,7 @@
if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
return (0); /* nothing to do */
+ /* Note: only initialising the 4 WEP keys, no IGTK */
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
const struct ieee80211_key *k = rvp->keys[i];
if (k != NULL) {
diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c
--- a/sys/dev/usb/wlan/if_rsu.c
+++ b/sys/dev/usb/wlan/if_rsu.c
@@ -1533,7 +1533,11 @@
if (ieee80211_is_key_global(vap, k)) {
*keyix = ieee80211_crypto_get_key_wepidx(vap, k);
- } else {
+ } else if (ieee80211_is_key_igtk(vap, k)) {
+ *keyix = 0;
+ is_checked = 1;
+ k->wk_flags |= IEEE80211_KEY_SWCRYPT;
+ } else if (ieee80211_is_key_unicast(vap, k)) {
/* Note: assumes this is a pairwise key */
if (vap->iv_opmode != IEEE80211_M_STA) {
*keyix = 0;
@@ -1546,6 +1550,10 @@
* skipping over the fixed slots and _BC / _BSS.
*/
*keyix = R92S_MACID_BSS;
+ } else {
+ device_printf(sc->sc_dev, "%s: error; unknown key type\n",
+ __func__);
+ return (0);
}
if (!is_checked) {
diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c
--- a/sys/dev/usb/wlan/if_rum.c
+++ b/sys/dev/usb/wlan/if_rum.c
@@ -3027,8 +3027,16 @@
}
} else
*keyix = 0;
- } else {
+ } else if (ieee80211_is_key_igtk(vap, k)) {
+ *keyix = *rxkeyix = 0;
+ k->wk_flags |= IEEE80211_KEY_SWCRYPT;
+ return 1;
+ } else if (ieee80211_is_key_unicast(vap, k)) {
*keyix = ieee80211_crypto_get_key_wepidx(vap, k);
+ } else {
+ device_printf(sc->sc_dev, "%s: invalid key type\n",
+ __func__);
+ return 0;
}
*rxkeyix = *keyix;
return 1;
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c
--- a/sys/dev/wpi/if_wpi.c
+++ b/sys/dev/wpi/if_wpi.c
@@ -4784,6 +4784,12 @@
return 1;
}
+ /* Handle IGTK keys */
+ if (ieee80211_is_key_global(vap, k)) {
+ /* Not for us. */
+ return 1;
+ }
+
/* Handle group keys. */
if (ieee80211_is_key_global(vap, k)) {
WPI_NT_LOCK(sc);
diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h
--- a/sys/net80211/ieee80211.h
+++ b/sys/net80211/ieee80211.h
@@ -2048,7 +2048,9 @@
#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.c b/sys/net80211/ieee80211.c
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -2711,6 +2711,22 @@
key < &vap->iv_nw_keys[IEEE80211_WEP_NKID]);
}
+/**
+ * @brief Determine whether the given key in the given VAP is an iGTK key.
+ *
+ * iGTK keys are at index 4 and 5, shared between all stations on a VAP.
+ *
+ * @param vap the current vap
+ * @param key ieee80211_key to use/check
+ * @returns true if the key is an iGTK key, false otherwise
+ */
+bool
+ieee80211_is_key_igtk(const struct ieee80211vap *vap,
+ const struct ieee80211_key *key)
+{
+ return (key == &vap->iv_nw_keys[4] || key == &vap->iv_nw_keys[5]);
+}
+
/**
* @brief Determine whether the given key in the given VAP is a unicast key.
*
@@ -2738,7 +2754,8 @@
* to support multiple unicast keys, IGTK, etc) so we
* will absolutely need to fix the key flags.
*/
- return (!ieee80211_is_key_global(vap, key));
+ return (!(ieee80211_is_key_global(vap, key)
+ || ieee80211_is_key_igtk(vap, key)));
}
/**
diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h
--- a/sys/net80211/ieee80211_crypto.h
+++ b/sys/net80211/ieee80211_crypto.h
@@ -101,6 +101,7 @@
#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 */
@@ -117,7 +118,7 @@
};
#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)
@@ -248,6 +249,8 @@
int ieee80211_crypto_get_key_wepidx(const struct ieee80211vap *,
const struct ieee80211_key *k);
+int ieee80211_crypto_get_key_igtk_idx(const struct ieee80211vap *,
+ const struct ieee80211_key *k);
uint8_t ieee80211_crypto_get_keyid(struct ieee80211vap *vap,
struct ieee80211_key *k);
struct ieee80211_key *ieee80211_crypto_get_txkey(struct ieee80211_node *,
diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -63,7 +63,7 @@
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
{
- if (!ieee80211_is_key_global(vap, k)) {
+ if (ieee80211_is_key_unicast(vap, k)) {
/*
* Not in the global key table, the driver should handle this
* by allocating a slot in the h/w key table/cache. In
@@ -77,8 +77,17 @@
if (k->wk_flags & IEEE80211_KEY_GROUP)
return 0;
*keyix = 0; /* NB: use key index 0 for ucast key */
- } else {
+ } else if (ieee80211_is_key_global(vap, k)) {
+ /* global/wep keys */
*keyix = ieee80211_crypto_get_key_wepidx(vap, k);
+ } else if (ieee80211_is_key_igtk(vap, k)) {
+ /* igtk - enforce software handling */
+ *keyix = IEEE80211_KEYIX_NONE;
+ k->wk_flags |= IEEE80211_KEY_SWCRYPT;
+ } else {
+ net80211_vap_printf(vap, "%s: called on unknown key type!\n",
+ __func__);
+ return (0);
}
*rxkeyix = IEEE80211_KEYIX_NONE; /* XXX maybe *keyix? */
return 1;
@@ -229,9 +238,9 @@
int i;
/* NB: we assume everything is pre-zero'd */
- vap->iv_max_keyix = IEEE80211_WEP_NKID;
+ vap->iv_max_keyix = IEEE80211_WEP_NKID; /* Note: maximum HW key index */
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);
/*
@@ -562,7 +571,7 @@
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);
}
@@ -611,6 +620,27 @@
return dev_key_set(vap, key);
}
+/*
+ * @brief Return index if the key is an IGTK key (4..5); -1 otherwise.
+ *
+ * This is different to "get_keyid" which defaults to returning
+ * 0 for unicast keys; it assumes that it won't be used for WEP.
+ *
+ * @param vap ieee80211vap to check
+ * @param k ieee80211_key to lookup index for
+ * @returns 4 or 5, otherwise -1 if it's not an iGTK key.
+ */
+int
+ieee80211_crypto_get_key_igtk_idx(const struct ieee80211vap *vap,
+ const struct ieee80211_key *k)
+{
+ if (ieee80211_is_key_igtk(vap, k)) {
+ return (k - vap->iv_nw_keys);
+ }
+
+ return (-1);
+}
+
/**
* @brief Return index if the key is a WEP key (0..3); -1 otherwise.
*
@@ -633,17 +663,20 @@
}
/**
- * @brief Return the index of a unicast, global or IGTK key.
+ * @brief Return the index of a unicast, global or IGTK key to populate
+ * in the IV / extended IV field of a frame.
*
* Return the index of a key. For unicast keys the index is 0..1.
- * For global/WEP keys it's 0..3. For IGTK keys its 4..5.
+ * For global/WEP keys it's 0..3. Unicast protected management frames (PMF)
+ * will use the current key. Mulicast PMF ("BIP") will not be encrypted in this
+ * path and will populate the relevant IE with either the full key
+ * index (4 or 5) via a call to ieee80211_crypto_get_key_igtk_idx().
*
* TODO: support >1 unicast key
- * TODO: support IGTK keys
*
* @param vap the current VAP
* @param k ieee80211_key to check
- * @returns 0..3 for a WEP/global key, 0..1 for unicast key, 4..5 for IGTK key
+ * @returns 0..3 for a WEP/global key, 0..1 for unicast key, 0..1 for IGTK key.
*/
uint8_t
ieee80211_crypto_get_keyid(struct ieee80211vap *vap, struct ieee80211_key *k)
@@ -652,6 +685,17 @@
return (k - vap->iv_nw_keys);
}
+ /*
+ * This function shouldn't be called for an IGTK key, so just return
+ * the default unicast key (0).
+ */
+ if (ieee80211_is_key_igtk(vap, k)) {
+ net80211_printf("%s: called with an iGTK key, please check!\n",
+ __func__);
+ return (0);
+ }
+
+ /* Default to unicast key 0 */
return (0);
}
@@ -958,11 +1002,15 @@
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: iGTK keys if the driver supports it? */
}
/*
* Unicast keys.
diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c
--- a/sys/net80211/ieee80211_ddb.c
+++ b/sys/net80211/ieee80211_ddb.c
@@ -606,7 +606,7 @@
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
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -93,7 +93,7 @@
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);
@@ -1230,7 +1230,7 @@
}
wk = &ni->ni_ucastkey;
} else {
- if (kid >= IEEE80211_WEP_NKID)
+ if (kid >= IEEE80211_MAX_NKID)
return EINVAL;
wk = &vap->iv_nw_keys[kid];
/*
@@ -1365,7 +1365,7 @@
ieee80211_node_delucastkey(ni);
ieee80211_free_node(ni);
} else {
- if (kid >= IEEE80211_WEP_NKID)
+ if (kid >= IEEE80211_MAX_NKID)
return EINVAL;
/* XXX error return */
ieee80211_crypto_delkey(vap, &vap->iv_nw_keys[kid]);
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -534,7 +534,7 @@
/* 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 *);
@@ -871,6 +871,8 @@
bool ieee80211_is_key_global(const struct ieee80211vap *vap,
const struct ieee80211_key *key);
+bool ieee80211_is_key_igtk(const struct ieee80211vap *vap,
+ const struct ieee80211_key *key);
bool ieee80211_is_key_unicast(const struct ieee80211vap *vap,
const struct ieee80211_key *key);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jun 22, 3:13 AM (7 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34156731
Default Alt Text
D57551.diff (14 KB)
Attached To
Mode
D57551: net80211: add IGTK key slots needed for later MFP support
Attached
Detach File
Event Timeline
Log In to Comment