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