1 /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
4 * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
5 * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
6 * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include <sys/cdefs.h>
22 __FBSDID("$FreeBSD$");
26 #include <sys/param.h>
28 #include <sys/mutex.h>
30 #include <sys/kernel.h>
31 #include <sys/socket.h>
32 #include <sys/systm.h>
33 #include <sys/malloc.h>
34 #include <sys/queue.h>
35 #include <sys/taskqueue.h>
37 #include <sys/endian.h>
40 #include <net/ethernet.h>
41 #include <net/if_media.h>
43 #include <net80211/ieee80211_var.h>
44 #include <net80211/ieee80211_radiotap.h>
46 #include <dev/rtwn/if_rtwnreg.h>
47 #include <dev/rtwn/if_rtwnvar.h>
49 #include <dev/rtwn/if_rtwn_cam.h>
50 #include <dev/rtwn/if_rtwn_debug.h>
51 #include <dev/rtwn/if_rtwn_task.h>
53 #include <dev/rtwn/rtl8192c/r92c_reg.h>
57 rtwn_init_cam(struct rtwn_softc *sc)
59 /* Invalidate all CAM entries. */
60 rtwn_write_4(sc, R92C_CAMCMD,
61 R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR);
65 rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data)
69 error = rtwn_write_4(sc, R92C_CAMWRITE, data);
72 error = rtwn_write_4(sc, R92C_CAMCMD,
73 R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE |
74 SM(R92C_CAMCMD_ADDR, addr));
80 rtwn_init_seccfg(struct rtwn_softc *sc)
84 /* Select decryption / encryption flags. */
86 switch (sc->sc_hwcrypto) {
88 break; /* nothing to do */
89 case RTWN_CRYPTO_PAIR:
90 /* NB: TXUCKEY_DEF / RXUCKEY_DEF are required for RTL8192C */
91 seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF |
92 R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA |
93 R92C_SECCFG_MC_SRCH_DIS;
95 case RTWN_CRYPTO_FULL:
96 seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF |
97 R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA |
98 R92C_SECCFG_TXBCKEY_DEF | R92C_SECCFG_RXBCKEY_DEF;
101 KASSERT(0, ("%s: case %d was not handled\n", __func__,
106 RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, "%s: seccfg %04X, hwcrypto %d\n",
107 __func__, seccfg, sc->sc_hwcrypto);
109 rtwn_write_2(sc, R92C_SECCFG, seccfg);
113 rtwn_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
114 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
116 struct rtwn_softc *sc = vap->iv_ic->ic_softc;
119 if (&vap->iv_nw_keys[0] <= k &&
120 k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
121 #if __FreeBSD_version > 1200018
122 *keyix = ieee80211_crypto_get_key_wepidx(vap, k);
124 *keyix = k - vap->iv_nw_keys;
126 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
127 k->wk_flags |= IEEE80211_KEY_SWCRYPT;
130 if (isset(sc->keys_bmap, *keyix)) {
131 device_printf(sc->sc_dev,
132 "%s: group key slot %d is already used!\n",
139 setbit(sc->keys_bmap, *keyix);
146 start = sc->cam_entry_limit;
147 switch (sc->sc_hwcrypto) {
149 k->wk_flags |= IEEE80211_KEY_SWCRYPT;
152 case RTWN_CRYPTO_PAIR:
153 /* all slots for pairwise keys. */
156 if (sc->sc_flags & RTWN_FLAG_CAM_FIXED)
160 case RTWN_CRYPTO_FULL:
161 /* first 4 - for group keys, others for pairwise. */
165 KASSERT(0, ("%s: case %d was not handled!\n",
166 __func__, sc->sc_hwcrypto));
171 for (i = start; i < sc->cam_entry_limit; i++) {
172 if (isclr(sc->keys_bmap, i)) {
173 setbit(sc->keys_bmap, i);
179 if (i == sc->cam_entry_limit) {
180 #if __FreeBSD_version > 1200008
181 /* XXX check and remove keys with the same MAC address */
182 k->wk_flags |= IEEE80211_KEY_SWCRYPT;
185 device_printf(sc->sc_dev,
186 "%s: no free space in the key table\n", __func__);
197 rtwn_key_set_cb0(struct rtwn_softc *sc, const struct ieee80211_key *k)
202 if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL &&
203 k->wk_keyix < IEEE80211_WEP_NKID)
208 /* Map net80211 cipher to HW crypto algorithm. */
209 switch (k->wk_cipher->ic_cipher) {
210 case IEEE80211_CIPHER_WEP:
211 if (k->wk_keylen < 8)
212 algo = R92C_CAM_ALGO_WEP40;
214 algo = R92C_CAM_ALGO_WEP104;
216 case IEEE80211_CIPHER_TKIP:
217 algo = R92C_CAM_ALGO_TKIP;
219 case IEEE80211_CIPHER_AES_CCM:
220 algo = R92C_CAM_ALGO_AES;
223 device_printf(sc->sc_dev, "%s: unknown cipher %u\n",
224 __func__, k->wk_cipher->ic_cipher);
228 RTWN_DPRINTF(sc, RTWN_DEBUG_KEY,
229 "%s: keyix %u, keyid %u, algo %u/%u, flags %04X, len %u, "
230 "macaddr %s\n", __func__, k->wk_keyix, keyid,
231 k->wk_cipher->ic_cipher, algo, k->wk_flags, k->wk_keylen,
232 ether_sprintf(k->wk_macaddr));
234 /* Clear high bits. */
235 rtwn_cam_write(sc, R92C_CAM_CTL6(k->wk_keyix), 0);
236 rtwn_cam_write(sc, R92C_CAM_CTL7(k->wk_keyix), 0);
239 for (i = 0; i < 4; i++) {
240 error = rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i),
241 le32dec(&k->wk_key[i * 4]));
246 /* Write CTL0 last since that will validate the CAM entry. */
247 error = rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix),
248 le32dec(&k->wk_macaddr[2]));
251 error = rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix),
252 SM(R92C_CAM_ALGO, algo) |
253 SM(R92C_CAM_KEYID, keyid) |
254 SM(R92C_CAM_MACLO, le16dec(&k->wk_macaddr[0])) |
262 device_printf(sc->sc_dev, "%s fails, error %d\n", __func__, error);
267 rtwn_key_set_cb(struct rtwn_softc *sc, union sec_param *data)
269 const struct ieee80211_key *k = &data->key;
271 (void) rtwn_key_set_cb0(sc, k);
275 rtwn_init_static_keys(struct rtwn_softc *sc, struct rtwn_vap *rvp)
279 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
280 return (0); /* nothing to do */
282 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
283 const struct ieee80211_key *k = rvp->keys[i];
285 error = rtwn_key_set_cb0(sc, k);
295 rtwn_key_del_cb(struct rtwn_softc *sc, union sec_param *data)
297 struct ieee80211_key *k = &data->key;
300 RTWN_DPRINTF(sc, RTWN_DEBUG_KEY,
301 "%s: keyix %u, flags %04X, macaddr %s\n", __func__,
302 k->wk_keyix, k->wk_flags, ether_sprintf(k->wk_macaddr));
304 rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 0);
305 rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 0);
308 for (i = 0; i < 4; i++)
309 rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 0);
310 clrbit(sc->keys_bmap, k->wk_keyix);
314 rtwn_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k,
317 struct rtwn_softc *sc = vap->iv_ic->ic_softc;
319 if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
324 if (&vap->iv_nw_keys[0] <= k &&
325 k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
326 #if __FreeBSD_version <= 1200008
327 struct ieee80211_key *k1 = &vap->iv_nw_keys[k->wk_keyix];
329 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) {
330 k1->wk_flags |= IEEE80211_KEY_SWCRYPT;
331 return (k->wk_cipher->ic_setkey(k1));
334 if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL) {
336 struct rtwn_vap *rvp = RTWN_VAP(vap);
339 rvp->keys[k->wk_keyix] = (set ? k : NULL);
340 if ((sc->sc_flags & RTWN_RUNNING) == 0) {
342 clrbit(sc->keys_bmap, k->wk_keyix);
350 return (!rtwn_cmd_sleepable(sc, k, sizeof(*k),
351 set ? rtwn_key_set_cb : rtwn_key_del_cb));
355 rtwn_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
357 return (rtwn_process_key(vap, k, 1));
361 rtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
363 return (rtwn_process_key(vap, k, 0));