From nobody Wed Aug 19 02:07:27 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hPqhc6m8Lz6pHRl for ; Wed, 19 Aug 2026 02:07:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hPqhc2Fwtz44tW for ; Wed, 19 Aug 2026 02:07:28 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787105248; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=UXilO0sIgTvPRsqtxpuLbDRGboLWUFZ025KGh9wLVGQ=; b=Ew4nz3yHkKNu6L3HwRDB2fWgNt8tSVCGEriE3lavAi6LPgVpxC4Ss+NiLKTNo+gnhCSI5p 5sIYozgM/thoV+IoD4Lsyo+TxP1pNoM3XTZhBVxImg35Z5wBBIjAUZUIQSmezDnlFR5Hbt r6kRIfmmqqGTcOzSfYcY1OF1L3zHm5b1a130T/wNEOPIMw76rCdPVtqevzHMx1ho98j342 h1AV1cByPVIG8iYYZr/AeICjvPEJhx0RP9Xz8g7uUpX4Jl55hvyECc3IbFXZgg00TttaWS 6CABl4nbRNPuy55IxfSSskWH+8mpwLgr+dveCpmkR2m5Dwmx8BPNZvRFNLeH6Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1787105248; a=rsa-sha256; cv=none; b=Dn3YqN7kXujs4QA4ZE+ZPxL/IBXadq+fxPQGmWCwoCalwbCnAr4rRIPNeoTNIMCMblX1bX CHlBYt/yd9Gh74/Tmlf+lDQmOhbfO7f8GEHp0ZfAGDbsq699jYfMXE8Bew2oATOyCX0Xpj d6/U7uvuCsHHij1mY6JZ4IHvVzW1IlWQROcYFuAECtfDa3HrrHXyWMtXUVuapUj6GDJ8Pb 51cQCHUN0i1THkRSGy2LGQv73hcPho+Cdu7M/03XaIfwDggWHJCJspT47YNR1+XA3sZ2r3 EQT387mLsEZ/kpJZt9bdkRdsQjeztjbeD3GBvOCDYcxivzC/mbjWplEiE7fOeA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787105248; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=UXilO0sIgTvPRsqtxpuLbDRGboLWUFZ025KGh9wLVGQ=; b=fXfdVw+LEAUQiPAEgkmz/SGlYzSgXs7vgj0eiNdKTIk1ZNTMejXAQz3dGzl/ort97euYLb Eg7FGZckUo41UYK0TCL6nl6qYsam0XHLQ9j7OHhOjPt9wddpl9mE4aJbjOCD5B1UlBZ8zt rKeVTHWZIzLPzjbFA1Pa+OTXFGOVz+VZl4aIZykjhiIblqeR4OPKxJGCIXN2I9c+zt2WMK GE608MEPStNw9j/wQTtWdmJnIOQGd4ny71P8au3Q7B9pmQUDIpFYp4RmZBvLei1W8nMOMk PgMmrobrR2pCQvP3zIAggMN5LLtTVi7JFhOWvbmQV9znba9Ng1thu/RmkpTQaA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hPqhb73Mdz19My for ; Wed, 19 Aug 2026 02:07:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1e04b by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 19 Aug 2026 02:07:27 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Adrian Chadd Subject: git: 99fda13f1c4a - main - net80211: migrate the ioctl API to a 128 bit specific API + use key API List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: adrian X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 99fda13f1c4a260923d3a0a173af14f730b705c9 Auto-Submitted: auto-generated Date: Wed, 19 Aug 2026 02:07:27 +0000 Message-Id: <6a850fdf.1e04b.3455d981@gitrepo.freebsd.org> The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=99fda13f1c4a260923d3a0a173af14f730b705c9 commit 99fda13f1c4a260923d3a0a173af14f730b705c9 Author: Adrian Chadd AuthorDate: 2026-08-19 02:02:05 +0000 Commit: Adrian Chadd CommitDate: 2026-08-19 02:02:05 +0000 net80211: migrate the ioctl API to a 128 bit specific API + use key API * Begin migrating the ioctl code to use the key management APIs. Not all of it has been migrated (notably the WEP API hasn't.) * Take special care to copy the TKIP MIC in and out correctly. * Note that some of the defines used as sizes are actually the ioctl sizes, they'll need to be fixed before I push this into a review. * Document this current API as a specific 128 bit key + 128 bit TKIP MIC API. The goal here is to solidify this stuff as the 128 bit ioctl API and not change it, even if net80211 will eventually grow 256 and 384 bit key support. Notably the TKIP stuff - the driver_bsd.c code puts the TKIP after the normal key contents, whereas the net80211 code puts the TKIP stuff in the /end/ of the key buffer. They happen to be equivalent when ioctl key buffer size == net80211 key buffer size, but as I learnt the last couple times I tried this, they're not always going to be equivalent. Differential Revision: https://reviews.freebsd.org/D58384 --- sys/net80211/ieee80211_ioctl.c | 149 +++++++++++++++++++++++++++++++++++------ sys/net80211/ieee80211_ioctl.h | 8 ++- 2 files changed, 134 insertions(+), 23 deletions(-) diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 09cb39cfcf6f..fc297e8bf668 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -101,7 +101,7 @@ ieee80211_ioctl_getkey(u_long cmd, struct ieee80211vap *vap, } 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 @@ ieee80211_ioctl_getkey(u_long cmd, struct ieee80211vap *vap, /* 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 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, { 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 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, 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 @@ ieee80211_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq) 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_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq) 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 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r 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 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r 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: diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h index d542d75312b9..ccb87dad995c 100644 --- a/sys/net80211/ieee80211_ioctl.h +++ b/sys/net80211/ieee80211_ioctl.h @@ -279,8 +279,12 @@ struct ieee80211_stats { * 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 @@ struct ieee80211req_key { 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]; }; /*