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 void 56 rtwn_init_cam(struct rtwn_softc *sc) 57 { 58 /* Invalidate all CAM entries. */ 59 rtwn_write_4(sc, R92C_CAMCMD, 60 R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR); 61 } 62 63 static int 64 rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data) 65 { 66 int error; 67 68 error = rtwn_write_4(sc, R92C_CAMWRITE, data); 69 if (error != 0) 70 return (error); 71 error = rtwn_write_4(sc, R92C_CAMCMD, 72 R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE | 73 SM(R92C_CAMCMD_ADDR, addr)); 74 75 return (error); 76 } 77 78 void 79 rtwn_init_seccfg(struct rtwn_softc *sc) 80 { 81 uint16_t seccfg; 82 83 /* Select decryption / encryption flags. */ 84 seccfg = 0; 85 switch (sc->sc_hwcrypto) { 86 case RTWN_CRYPTO_SW: 87 break; /* nothing to do */ 88 case RTWN_CRYPTO_PAIR: 89 /* NB: TXUCKEY_DEF / RXUCKEY_DEF are required for RTL8192C */ 90 seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF | 91 R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA | 92 R92C_SECCFG_MC_SRCH_DIS; 93 break; 94 case RTWN_CRYPTO_FULL: 95 seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF | 96 R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA | 97 R92C_SECCFG_TXBCKEY_DEF | R92C_SECCFG_RXBCKEY_DEF; 98 break; 99 default: 100 KASSERT(0, ("%s: case %d was not handled\n", __func__, 101 sc->sc_hwcrypto)); 102 break; 103 } 104 105 RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, "%s: seccfg %04X, hwcrypto %d\n", 106 __func__, seccfg, sc->sc_hwcrypto); 107 108 rtwn_write_2(sc, R92C_SECCFG, seccfg); 109 } 110 111 int 112 rtwn_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, 113 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 114 { 115 struct rtwn_softc *sc = vap->iv_ic->ic_softc; 116 int i, start; 117 118 if (&vap->iv_nw_keys[0] <= k && 119 k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) { 120 #if __FreeBSD_version > 1200018 121 *keyix = ieee80211_crypto_get_key_wepidx(vap, k); 122 #else 123 *keyix = k - vap->iv_nw_keys; 124 #endif 125 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) 126 k->wk_flags |= IEEE80211_KEY_SWCRYPT; 127 else { 128 RTWN_LOCK(sc); 129 if (isset(sc->keys_bmap, *keyix)) { 130 device_printf(sc->sc_dev, 131 "%s: group key slot %d is already used!\n", 132 __func__, *keyix); 133 /* XXX recover? */ 134 RTWN_UNLOCK(sc); 135 return (0); 136 } 137 138 setbit(sc->keys_bmap, *keyix); 139 RTWN_UNLOCK(sc); 140 } 141 142 goto end; 143 } 144 145 start = sc->cam_entry_limit; 146 switch (sc->sc_hwcrypto) { 147 case RTWN_CRYPTO_SW: 148 k->wk_flags |= IEEE80211_KEY_SWCRYPT; 149 *keyix = 0; 150 goto end; 151 case RTWN_CRYPTO_PAIR: 152 /* all slots for pairwise keys. */ 153 start = 0; 154 RTWN_LOCK(sc); 155 if (sc->sc_flags & RTWN_FLAG_CAM_FIXED) 156 start = 4; 157 RTWN_UNLOCK(sc); 158 break; 159 case RTWN_CRYPTO_FULL: 160 /* first 4 - for group keys, others for pairwise. */ 161 start = 4; 162 break; 163 default: 164 KASSERT(0, ("%s: case %d was not handled!\n", 165 __func__, sc->sc_hwcrypto)); 166 break; 167 } 168 169 RTWN_LOCK(sc); 170 for (i = start; i < sc->cam_entry_limit; i++) { 171 if (isclr(sc->keys_bmap, i)) { 172 setbit(sc->keys_bmap, i); 173 *keyix = i; 174 break; 175 } 176 } 177 RTWN_UNLOCK(sc); 178 if (i == sc->cam_entry_limit) { 179 #if __FreeBSD_version > 1200008 180 /* XXX check and remove keys with the same MAC address */ 181 k->wk_flags |= IEEE80211_KEY_SWCRYPT; 182 *keyix = 0; 183 #else 184 device_printf(sc->sc_dev, 185 "%s: no free space in the key table\n", __func__); 186 return (0); 187 #endif 188 } 189 190 end: 191 *rxkeyix = *keyix; 192 return (1); 193 } 194 195 static int 196 rtwn_key_set_cb0(struct rtwn_softc *sc, const struct ieee80211_key *k) 197 { 198 uint8_t algo, keyid; 199 int i, error; 200 201 if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL && 202 k->wk_keyix < IEEE80211_WEP_NKID) 203 keyid = k->wk_keyix; 204 else 205 keyid = 0; 206 207 /* Map net80211 cipher to HW crypto algorithm. */ 208 switch (k->wk_cipher->ic_cipher) { 209 case IEEE80211_CIPHER_WEP: 210 if (k->wk_keylen < 8) 211 algo = R92C_CAM_ALGO_WEP40; 212 else 213 algo = R92C_CAM_ALGO_WEP104; 214 break; 215 case IEEE80211_CIPHER_TKIP: 216 algo = R92C_CAM_ALGO_TKIP; 217 break; 218 case IEEE80211_CIPHER_AES_CCM: 219 algo = R92C_CAM_ALGO_AES; 220 break; 221 default: 222 device_printf(sc->sc_dev, "%s: unknown cipher %u\n", 223 __func__, k->wk_cipher->ic_cipher); 224 return (EINVAL); 225 } 226 227 RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, 228 "%s: keyix %u, keyid %u, algo %u/%u, flags %04X, len %u, " 229 "macaddr %s\n", __func__, k->wk_keyix, keyid, 230 k->wk_cipher->ic_cipher, algo, k->wk_flags, k->wk_keylen, 231 ether_sprintf(k->wk_macaddr)); 232 233 /* Clear high bits. */ 234 rtwn_cam_write(sc, R92C_CAM_CTL6(k->wk_keyix), 0); 235 rtwn_cam_write(sc, R92C_CAM_CTL7(k->wk_keyix), 0); 236 237 /* Write key. */ 238 for (i = 0; i < 4; i++) { 239 error = rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 240 le32dec(&k->wk_key[i * 4])); 241 if (error != 0) 242 goto fail; 243 } 244 245 /* Write CTL0 last since that will validate the CAM entry. */ 246 error = rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 247 le32dec(&k->wk_macaddr[2])); 248 if (error != 0) 249 goto fail; 250 error = rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 251 SM(R92C_CAM_ALGO, algo) | 252 SM(R92C_CAM_KEYID, keyid) | 253 SM(R92C_CAM_MACLO, le16dec(&k->wk_macaddr[0])) | 254 R92C_CAM_VALID); 255 if (error != 0) 256 goto fail; 257 258 return (0); 259 260 fail: 261 device_printf(sc->sc_dev, "%s fails, error %d\n", __func__, error); 262 return (error); 263 } 264 265 static void 266 rtwn_key_set_cb(struct rtwn_softc *sc, union sec_param *data) 267 { 268 const struct ieee80211_key *k = &data->key; 269 270 (void) rtwn_key_set_cb0(sc, k); 271 } 272 273 int 274 rtwn_init_static_keys(struct rtwn_softc *sc, struct rtwn_vap *rvp) 275 { 276 int i, error; 277 278 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) 279 return (0); /* nothing to do */ 280 281 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 282 const struct ieee80211_key *k = rvp->keys[i]; 283 if (k != NULL) { 284 error = rtwn_key_set_cb0(sc, k); 285 if (error != 0) 286 return (error); 287 } 288 } 289 290 return (0); 291 } 292 293 static void 294 rtwn_key_del_cb(struct rtwn_softc *sc, union sec_param *data) 295 { 296 struct ieee80211_key *k = &data->key; 297 int i; 298 299 RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, 300 "%s: keyix %u, flags %04X, macaddr %s\n", __func__, 301 k->wk_keyix, k->wk_flags, ether_sprintf(k->wk_macaddr)); 302 303 rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 0); 304 rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 0); 305 306 /* Clear key. */ 307 for (i = 0; i < 4; i++) 308 rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 0); 309 clrbit(sc->keys_bmap, k->wk_keyix); 310 } 311 312 static int 313 rtwn_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k, 314 int set) 315 { 316 struct rtwn_softc *sc = vap->iv_ic->ic_softc; 317 318 if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { 319 /* Not for us. */ 320 return (1); 321 } 322 323 if (&vap->iv_nw_keys[0] <= k && 324 k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) { 325 #if __FreeBSD_version <= 1200008 326 struct ieee80211_key *k1 = &vap->iv_nw_keys[k->wk_keyix]; 327 328 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) { 329 k1->wk_flags |= IEEE80211_KEY_SWCRYPT; 330 return (k->wk_cipher->ic_setkey(k1)); 331 } else { 332 #else 333 if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL) { 334 #endif 335 struct rtwn_vap *rvp = RTWN_VAP(vap); 336 337 RTWN_LOCK(sc); 338 rvp->keys[k->wk_keyix] = (set ? k : NULL); 339 if ((sc->sc_flags & RTWN_RUNNING) == 0) { 340 if (!set) 341 clrbit(sc->keys_bmap, k->wk_keyix); 342 RTWN_UNLOCK(sc); 343 return (1); 344 } 345 RTWN_UNLOCK(sc); 346 } 347 } 348 349 return (!rtwn_cmd_sleepable(sc, k, sizeof(*k), 350 set ? rtwn_key_set_cb : rtwn_key_del_cb)); 351 } 352 353 int 354 rtwn_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) 355 { 356 return (rtwn_process_key(vap, k, 1)); 357 } 358 359 int 360 rtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) 361 { 362 return (rtwn_process_key(vap, k, 0)); 363 } 364