Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F167335603
D58384.id184301.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D58384.id184301.diff
View Options
diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h
--- a/sys/net80211/ieee80211_ioctl.h
+++ b/sys/net80211/ieee80211_ioctl.h
@@ -279,8 +279,12 @@
* Otherwise a unicast/pairwise key is specified by the bssid
* (on a station) or mac address (on an ap). They key length
* must include any MIC key data; otherwise it should be no
- * more than IEEE80211_KEYBUF_SIZE.
+ * more than IEEE80211_IOCTL_KEYBUF_SIZE.
*/
+#define IEEE80211_IOCTL_KEYBUF_SIZE 16
+#define IEEE80211_IOCTL_MICBUF_SIZE (8+8)
+#define IEEE80211_IOCTL_TX_MICBUF_SIZE 8
+#define IEEE80211_IOCTL_RX_MICBUF_SIZE 8
struct ieee80211req_key {
uint8_t ik_type; /* key/cipher type */
uint8_t ik_pad;
@@ -292,7 +296,7 @@
uint8_t ik_macaddr[IEEE80211_ADDR_LEN];
uint64_t ik_keyrsc; /* key receive sequence counter */
uint64_t ik_keytsc; /* key transmit sequence counter */
- uint8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
+ uint8_t ik_keydata[IEEE80211_IOCTL_KEYBUF_SIZE+IEEE80211_IOCTL_MICBUF_SIZE];
};
/*
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
@@ -101,7 +101,7 @@
}
cip = wk->wk_cipher;
ik.ik_type = cip->ic_cipher;
- ik.ik_keylen = wk->wk_keylen;
+ ik.ik_keylen = ieee80211_crypto_get_key_len(wk);
ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV);
if (wk->wk_keyix == vap->iv_def_txkey)
ik.ik_flags |= IEEE80211_KEY_DEFAULT;
@@ -109,12 +109,39 @@
/* NB: only root can read key data */
ik.ik_keyrsc = wk->wk_keyrsc[IEEE80211_NONQOS_TID];
ik.ik_keytsc = wk->wk_keytsc;
- memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen);
+
+ if (ieee80211_crypto_copy_key_data(wk, ik.ik_keydata,
+ IEEE80211_IOCTL_KEYBUF_SIZE) == false)
+ return (EINVAL);
+
if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) {
- memcpy(ik.ik_keydata+wk->wk_keylen,
- wk->wk_key + IEEE80211_KEYBUF_SIZE,
- IEEE80211_MICBUF_SIZE);
- ik.ik_keylen += IEEE80211_MICBUF_SIZE;
+ /*
+ * Note: assume that we've copied up to
+ * IEEE80211_IOCTL_KEYBUF_SIZE size, and we
+ * have space for the TX/RX MIC. The API
+ * is actually asking for "how big is the
+ * buffer" and the assumption here is
+ * that since it's currently a static sized
+ * buffer in ieee80211req_key, we know
+ * that there's IEEE80211_IOCTL_TX_MICBUF_SIZE
+ * bytes available after IEEE80211_IOCTL_KEYBUF_SIZE.
+ */
+ if (ieee80211_crypto_copy_txmic_data(wk,
+ ik.ik_keydata + wk->wk_keylen,
+ IEEE80211_IOCTL_TX_MICBUF_SIZE) == false)
+ return (EINVAL);
+
+ /*
+ * Similar assumptions here about static buffer
+ * sizing and available space.
+ */
+ if (ieee80211_crypto_copy_rxmic_data(wk,
+ ik.ik_keydata + wk->wk_keylen +
+ IEEE80211_IOCTL_TX_MICBUF_SIZE,
+ IEEE80211_IOCTL_RX_MICBUF_SIZE) == false)
+ return (EINVAL);
+
+ ik.ik_keylen += IEEE80211_IOCTL_MICBUF_SIZE;
}
} else {
ik.ik_keyrsc = 0;
@@ -780,7 +807,7 @@
{
struct ieee80211com *ic = vap->iv_ic;
u_int kid, len;
- uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
+ uint8_t tmpkey[IEEE80211_IOCTL_KEYBUF_SIZE];
char tmpssid[IEEE80211_NWID_LEN];
int error = 0;
@@ -821,12 +848,27 @@
kid = (u_int) ireq->i_val;
if (kid >= IEEE80211_WEP_NKID)
return EINVAL;
- len = (u_int) vap->iv_nw_keys[kid].wk_keylen;
+
+ /*
+ * Bounds-check the key length before potentially reading
+ * the key data - reading the key data can only happen with
+ * sufficient privileges.
+ */
+ if (ieee80211_crypto_get_key_len(&vap->iv_nw_keys[kid]) >
+ sizeof(tmpkey))
+ return EINVAL;
+ len = (u_int) MIN(
+ ieee80211_crypto_get_key_len(&vap->iv_nw_keys[kid]),
+ sizeof(tmpkey));
+ bzero(tmpkey, sizeof(tmpkey));
/* NB: only root can read WEP keys */
if (ieee80211_priv_check_vap_getkey(cmd, vap, NULL) == 0) {
- bcopy(vap->iv_nw_keys[kid].wk_key, tmpkey, len);
- } else {
- bzero(tmpkey, len);
+ if (ieee80211_crypto_copy_key_data(
+ &vap->iv_nw_keys[kid], tmpkey,
+ IEEE80211_IOCTL_KEYBUF_SIZE) == false) {
+ error = EINVAL;
+ break;
+ }
}
ireq->i_len = len;
error = copyout(tmpkey, ireq->i_data, len);
@@ -1219,15 +1261,72 @@
error = 0;
ieee80211_key_update_begin(vap);
if (ieee80211_crypto_newkey(vap, ik.ik_type, ik.ik_flags, wk)) {
- wk->wk_keylen = ik.ik_keylen;
- /* NB: MIC presence is implied by cipher type */
- if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE)
- wk->wk_keylen = IEEE80211_KEYBUF_SIZE;
+ uint32_t key_len;
+
for (i = 0; i < IEEE80211_TID_SIZE; i++)
wk->wk_keyrsc[i] = ik.ik_keyrsc;
wk->wk_keytsc = 0; /* new key, reset */
+
+ /* TODO: methodize */
memset(wk->wk_key, 0, sizeof(wk->wk_key));
- memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen);
+
+ /*
+ * Set the key using the provided key contents.
+ *
+ * TKIP is special cased in this API because it lumps key and
+ * MIC together with the key length spanning both.
+ *
+ * However the net80211 crypto key API only expects the key
+ * length to be without the MIC.
+ *
+ * So, cap key_len to 128 bits here regardless of key type,
+ * and then assume the next 128 bits are the MIC.
+ *
+ * When the net80211 key storage is bumped to include 256/384
+ * bit keys this API should continue to be supported - it
+ * copies the data from the same location and into the right
+ * place in ieee80211_key via key/MIC set methods.
+ */
+ key_len = ik.ik_keylen;
+ switch (ik.ik_type) {
+ case IEEE80211_CIPHER_TKIP:
+ /*
+ * This API requires that there's enough key data
+ * for a 128 bit TKIP key and 128 bit MIC. So, enforce
+ * that here before we do math on the key_len.
+ */
+ if (key_len < (IEEE80211_IOCTL_KEYBUF_SIZE +
+ IEEE80211_IOCTL_MICBUF_SIZE)) {
+ error = EINVAL;
+ goto finish;
+ }
+
+ /* Subtract the 128 bit TX/RX MIC. */
+ key_len -= IEEE80211_IOCTL_MICBUF_SIZE;
+
+ /* Set the key with the adjusted key length. */
+ ieee80211_crypto_set_key_data(wk, ik.ik_keydata,
+ key_len);
+
+ /* The TX and RX MIC follow the key data. */
+ ieee80211_crypto_set_key_txmic_data(wk,
+ ik.ik_keydata + key_len,
+ IEEE80211_IOCTL_TX_MICBUF_SIZE);
+ ieee80211_crypto_set_key_rxmic_data(wk,
+ ik.ik_keydata + key_len +
+ IEEE80211_IOCTL_TX_MICBUF_SIZE,
+ IEEE80211_IOCTL_RX_MICBUF_SIZE);
+ break;
+ default:
+ /*
+ * Non-TKIP keys don't need the special case around
+ * key length; just use what was supplied.
+ */
+ ieee80211_crypto_set_key_data(wk, ik.ik_keydata,
+ key_len);
+ break;
+ }
+
IEEE80211_ADDR_COPY(wk->wk_macaddr,
ni != NULL ? ni->ni_macaddr : ik.ik_macaddr);
if (!ieee80211_crypto_setkey(vap, wk))
@@ -1244,6 +1343,7 @@
ieee80211_crypto_set_deftxkey(vap, kid);
} else
error = ENXIO;
+finish:
ieee80211_key_update_end(vap);
if (ni != NULL)
ieee80211_free_node(ni);
@@ -2772,7 +2872,7 @@
struct ieee80211com *ic = vap->iv_ic;
int error;
const struct ieee80211_authenticator *auth;
- uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
+ uint8_t tmpkey[IEEE80211_IOCTL_KEYBUF_SIZE];
char tmpssid[IEEE80211_NWID_LEN];
uint8_t tmpbssid[IEEE80211_ADDR_LEN];
struct ieee80211_key *k;
@@ -2831,13 +2931,20 @@
k->wk_keyix = kid; /* NB: force fixed key id */
if (ieee80211_crypto_newkey(vap, IEEE80211_CIPHER_WEP,
IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
- k->wk_keylen = ireq->i_len;
- memcpy(k->wk_key, tmpkey, sizeof(tmpkey));
+ if (ieee80211_crypto_set_key_data(k, tmpkey,
+ ireq->i_len) == false) {
+ error = EINVAL;
+ goto skip;
+ }
IEEE80211_ADDR_COPY(k->wk_macaddr, vap->iv_myaddr);
- if (!ieee80211_crypto_setkey(vap, k))
+ if (!ieee80211_crypto_setkey(vap, k)) {
error = EINVAL;
- } else
+ goto skip;
+ }
+ } else {
error = EINVAL;
+ }
+skip:
ieee80211_key_update_end(vap);
break;
case IEEE80211_IOC_WEPTXKEY:
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Aug 22, 12:29 AM (17 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36845431
Default Alt Text
D58384.id184301.diff (7 KB)
Attached To
Mode
D58384: net80211: migrate the ioctl API to a 128 bit specific API + use key API
Attached
Detach File
Event Timeline
Log In to Comment