1 /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ 2 3 /*- 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> 7 * 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. 11 * 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. 19 */ 20 21 #include <sys/cdefs.h> 22 __FBSDID("$FreeBSD$"); 23 24 #include "opt_wlan.h" 25 26 #include <sys/param.h> 27 #include <sys/lock.h> 28 #include <sys/mutex.h> 29 #include <sys/mbuf.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> 36 #include <sys/bus.h> 37 #include <sys/endian.h> 38 39 #include <net/if.h> 40 #include <net/ethernet.h> 41 #include <net/if_media.h> 42 43 #include <net80211/ieee80211_var.h> 44 #include <net80211/ieee80211_radiotap.h> 45 46 #include <dev/rtwn/if_rtwnreg.h> 47 #include <dev/rtwn/if_rtwnvar.h> 48 49 #include <dev/rtwn/if_rtwn_cam.h> 50 #include <dev/rtwn/if_rtwn_debug.h> 51 #include <dev/rtwn/if_rtwn_task.h> 52 53 #include <dev/rtwn/rtl8192c/r92c_reg.h> 54 55 56 void 57 rtwn_init_cam(struct rtwn_softc *sc) 58 { 59 /* Invalidate all CAM entries. */ 60 rtwn_write_4(sc, R92C_CAMCMD, 61 R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR); 62 } 63 64 static int 65 rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data) 66 { 67 int error; 68 69 error = rtwn_write_4(sc, R92C_CAMWRITE, data); 70 if (error != 0) 71 return (error); 72 error = rtwn_write_4(sc, R92C_CAMCMD, 73 R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE | 74 SM(R92C_CAMCMD_ADDR, addr)); 75 76 return (error); 77 } 78 79 void 80 rtwn_init_seccfg(struct rtwn_softc *sc) 81 { 82 uint16_t seccfg; 83 84 /* Select decryption / encryption flags. */ 85 seccfg = 0; 86 switch (sc->sc_hwcrypto) { 87 case RTWN_CRYPTO_SW: 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; 94 break; 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; 99 break; 100 default: 101 KASSERT(0, ("%s: case %d was not handled\n", __func__, 102 sc->sc_hwcrypto)); 103 break; 104 } 105 106 RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, "%s: seccfg %04X, hwcrypto %d\n", 107 __func__, seccfg, sc->sc_hwcrypto); 108 109 rtwn_write_2(sc, R92C_SECCFG, seccfg); 110 } 111 112 int 113 rtwn_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, 114 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 115 { 116 struct rtwn_softc *sc = vap->iv_ic->ic_softc; 117 int i, start; 118 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); 123 #else 124 *keyix = k - vap->iv_nw_keys; 125 #endif 126 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) 127 k->wk_flags |= IEEE80211_KEY_SWCRYPT; 128 else { 129 RTWN_LOCK(sc); 130 if (isset(sc->keys_bmap, *keyix)) { 131 device_printf(sc->sc_dev, 132 "%s: group key slot %d is already used!\n", 133 __func__, *keyix); 134 /* XXX recover? */ 135 RTWN_UNLOCK(sc); 136 return (0); 137 } 138 139 setbit(sc->keys_bmap, *keyix); 140 RTWN_UNLOCK(sc); 141 } 142 143 goto end; 144 } 145 146 start = sc->cam_entry_limit; 147 switch (sc->sc_hwcrypto) { 148 case RTWN_CRYPTO_SW: 149 k->wk_flags |= IEEE80211_KEY_SWCRYPT; 150 *keyix = 0; 151 goto end; 152 case RTWN_CRYPTO_PAIR: 153 /* all slots for pairwise keys. */ 154 start = 0; 155 RTWN_LOCK(sc); 156 if (sc->sc_flags & RTWN_FLAG_CAM_FIXED) 157 start = 4; 158 RTWN_UNLOCK(sc); 159 break; 160 case RTWN_CRYPTO_FULL: 161 /* first 4 - for group keys, others for pairwise. */ 162 start = 4; 163 break; 164 default: 165 KASSERT(0, ("%s: case %d was not handled!\n", 166 __func__, sc->sc_hwcrypto)); 167 break; 168 } 169 170 RTWN_LOCK(sc); 171 for (i = start; i < sc->cam_entry_limit; i++) { 172 if (isclr(sc->keys_bmap, i)) { 173 setbit(sc->keys_bmap, i); 174 *keyix = i; 175 break; 176 } 177 } 178 RTWN_UNLOCK(sc); 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; 183 *keyix = 0; 184 #else 185 device_printf(sc->sc_dev, 186 "%s: no free space in the key table\n", __func__); 187 return (0); 188 #endif 189 } 190 191 end: 192 *rxkeyix = *keyix; 193 return (1); 194 } 195 196 static int 197 rtwn_key_set_cb0(struct rtwn_softc *sc, const struct ieee80211_key *k) 198 { 199 uint8_t algo, keyid; 200 int i, error; 201 202 if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL && 203 k->wk_keyix < IEEE80211_WEP_NKID) 204 keyid = k->wk_keyix; 205 else 206 keyid = 0; 207 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; 213 else 214 algo = R92C_CAM_ALGO_WEP104; 215 break; 216 case IEEE80211_CIPHER_TKIP: 217 algo = R92C_CAM_ALGO_TKIP; 218 break; 219 case IEEE80211_CIPHER_AES_CCM: 220 algo = R92C_CAM_ALGO_AES; 221 break; 222 default: 223 device_printf(sc->sc_dev, "%s: unknown cipher %u\n", 224 __func__, k->wk_cipher->ic_cipher); 225 return (EINVAL); 226 } 227 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)); 233 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); 237 238 /* Write key. */ 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])); 242 if (error != 0) 243 goto fail; 244 } 245 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])); 249 if (error != 0) 250 goto fail; 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])) | 255 R92C_CAM_VALID); 256 if (error != 0) 257 goto fail; 258 259 return (0); 260 261 fail: 262 device_printf(sc->sc_dev, "%s fails, error %d\n", __func__, error); 263 return (error); 264 } 265 266 static void 267 rtwn_key_set_cb(struct rtwn_softc *sc, union sec_param *data) 268 { 269 const struct ieee80211_key *k = &data->key; 270 271 (void) rtwn_key_set_cb0(sc, k); 272 } 273 274 int 275 rtwn_init_static_keys(struct rtwn_softc *sc, struct rtwn_vap *rvp) 276 { 277 int i, error; 278 279 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) 280 return (0); /* nothing to do */ 281 282 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 283 const struct ieee80211_key *k = rvp->keys[i]; 284 if (k != NULL) { 285 error = rtwn_key_set_cb0(sc, k); 286 if (error != 0) 287 return (error); 288 } 289 } 290 291 return (0); 292 } 293 294 static void 295 rtwn_key_del_cb(struct rtwn_softc *sc, union sec_param *data) 296 { 297 struct ieee80211_key *k = &data->key; 298 int i; 299 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)); 303 304 rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 0); 305 rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 0); 306 307 /* Clear key. */ 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); 311 } 312 313 static int 314 rtwn_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k, 315 int set) 316 { 317 struct rtwn_softc *sc = vap->iv_ic->ic_softc; 318 319 if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { 320 /* Not for us. */ 321 return (1); 322 } 323 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]; 328 329 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) { 330 k1->wk_flags |= IEEE80211_KEY_SWCRYPT; 331 return (k->wk_cipher->ic_setkey(k1)); 332 } else { 333 #else 334 if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL) { 335 #endif 336 struct rtwn_vap *rvp = RTWN_VAP(vap); 337 338 RTWN_LOCK(sc); 339 rvp->keys[k->wk_keyix] = (set ? k : NULL); 340 if ((sc->sc_flags & RTWN_RUNNING) == 0) { 341 if (!set) 342 clrbit(sc->keys_bmap, k->wk_keyix); 343 RTWN_UNLOCK(sc); 344 return (1); 345 } 346 RTWN_UNLOCK(sc); 347 } 348 } 349 350 return (!rtwn_cmd_sleepable(sc, k, sizeof(*k), 351 set ? rtwn_key_set_cb : rtwn_key_del_cb)); 352 } 353 354 int 355 rtwn_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) 356 { 357 return (rtwn_process_key(vap, k, 1)); 358 } 359 360 int 361 rtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) 362 { 363 return (rtwn_process_key(vap, k, 0)); 364 } 365