Page MenuHomeFreeBSD

D57551.diff
No OneTemporary

D57551.diff

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

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)

Event Timeline