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
rtwn_init_cam(struct rtwn_softc * sc)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
rtwn_cam_write(struct rtwn_softc * sc,uint32_t addr,uint32_t data)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
rtwn_init_seccfg(struct rtwn_softc * sc)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
rtwn_key_alloc(struct ieee80211vap * vap,struct ieee80211_key * k,ieee80211_keyix * keyix,ieee80211_keyix * rxkeyix)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 (&vap->iv_nw_keys[0] <= k &&
117 k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
118 *keyix = ieee80211_crypto_get_key_wepidx(vap, k);
119 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
120 k->wk_flags |= IEEE80211_KEY_SWCRYPT;
121 else {
122 RTWN_LOCK(sc);
123 if (isset(sc->keys_bmap, *keyix)) {
124 device_printf(sc->sc_dev,
125 "%s: group key slot %d is already used!\n",
126 __func__, *keyix);
127 /* XXX recover? */
128 RTWN_UNLOCK(sc);
129 return (0);
130 }
131
132 setbit(sc->keys_bmap, *keyix);
133 RTWN_UNLOCK(sc);
134 }
135
136 goto end;
137 }
138
139 start = sc->cam_entry_limit;
140 switch (sc->sc_hwcrypto) {
141 case RTWN_CRYPTO_SW:
142 k->wk_flags |= IEEE80211_KEY_SWCRYPT;
143 *keyix = 0;
144 goto end;
145 case RTWN_CRYPTO_PAIR:
146 /* all slots for pairwise keys. */
147 start = 0;
148 RTWN_LOCK(sc);
149 if (sc->sc_flags & RTWN_FLAG_CAM_FIXED)
150 start = 4;
151 RTWN_UNLOCK(sc);
152 break;
153 case RTWN_CRYPTO_FULL:
154 /* first 4 - for group keys, others for pairwise. */
155 start = 4;
156 break;
157 default:
158 KASSERT(0, ("%s: case %d was not handled!\n",
159 __func__, sc->sc_hwcrypto));
160 break;
161 }
162
163 RTWN_LOCK(sc);
164 for (i = start; i < sc->cam_entry_limit; i++) {
165 if (isclr(sc->keys_bmap, i)) {
166 setbit(sc->keys_bmap, i);
167 *keyix = i;
168 break;
169 }
170 }
171 RTWN_UNLOCK(sc);
172 if (i == sc->cam_entry_limit) {
173 /* XXX check and remove keys with the same MAC address */
174 k->wk_flags |= IEEE80211_KEY_SWCRYPT;
175 *keyix = 0;
176 }
177
178 end:
179 *rxkeyix = *keyix;
180 return (1);
181 }
182
183 static int
rtwn_key_set_cb0(struct rtwn_softc * sc,const struct ieee80211_key * k)184 rtwn_key_set_cb0(struct rtwn_softc *sc, const struct ieee80211_key *k)
185 {
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 (k->wk_keylen < 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 RTWN_DPRINTF(sc, RTWN_DEBUG_KEY,
216 "%s: keyix %u, keyid %u, algo %u/%u, flags %04X, len %u, "
217 "macaddr %s\n", __func__, k->wk_keyix, keyid,
218 k->wk_cipher->ic_cipher, algo, k->wk_flags, k->wk_keylen,
219 ether_sprintf(k->wk_macaddr));
220
221 /* Clear high bits. */
222 rtwn_cam_write(sc, R92C_CAM_CTL6(k->wk_keyix), 0);
223 rtwn_cam_write(sc, R92C_CAM_CTL7(k->wk_keyix), 0);
224
225 /* Write key. */
226 for (i = 0; i < 4; i++) {
227 error = rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i),
228 le32dec(&k->wk_key[i * 4]));
229 if (error != 0)
230 goto fail;
231 }
232
233 /* Write CTL0 last since that will validate the CAM entry. */
234 error = rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix),
235 le32dec(&k->wk_macaddr[2]));
236 if (error != 0)
237 goto fail;
238 error = rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix),
239 SM(R92C_CAM_ALGO, algo) |
240 SM(R92C_CAM_KEYID, keyid) |
241 SM(R92C_CAM_MACLO, le16dec(&k->wk_macaddr[0])) |
242 R92C_CAM_VALID);
243 if (error != 0)
244 goto fail;
245
246 return (0);
247
248 fail:
249 device_printf(sc->sc_dev, "%s fails, error %d\n", __func__, error);
250 return (error);
251 }
252
253 static void
rtwn_key_set_cb(struct rtwn_softc * sc,union sec_param * data)254 rtwn_key_set_cb(struct rtwn_softc *sc, union sec_param *data)
255 {
256 const struct ieee80211_key *k = &data->key;
257
258 (void) rtwn_key_set_cb0(sc, k);
259 }
260
261 int
rtwn_init_static_keys(struct rtwn_softc * sc,struct rtwn_vap * rvp)262 rtwn_init_static_keys(struct rtwn_softc *sc, struct rtwn_vap *rvp)
263 {
264 int i, error;
265
266 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
267 return (0); /* nothing to do */
268
269 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
270 const struct ieee80211_key *k = rvp->keys[i];
271 if (k != NULL) {
272 error = rtwn_key_set_cb0(sc, k);
273 if (error != 0)
274 return (error);
275 }
276 }
277
278 return (0);
279 }
280
281 static void
rtwn_key_del_cb(struct rtwn_softc * sc,union sec_param * data)282 rtwn_key_del_cb(struct rtwn_softc *sc, union sec_param *data)
283 {
284 struct ieee80211_key *k = &data->key;
285 int i;
286
287 RTWN_DPRINTF(sc, RTWN_DEBUG_KEY,
288 "%s: keyix %u, flags %04X, macaddr %s\n", __func__,
289 k->wk_keyix, k->wk_flags, ether_sprintf(k->wk_macaddr));
290
291 rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 0);
292 rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 0);
293
294 /* Clear key. */
295 for (i = 0; i < 4; i++)
296 rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 0);
297 clrbit(sc->keys_bmap, k->wk_keyix);
298 }
299
300 static int
rtwn_process_key(struct ieee80211vap * vap,const struct ieee80211_key * k,int set)301 rtwn_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k,
302 int set)
303 {
304 struct rtwn_softc *sc = vap->iv_ic->ic_softc;
305
306 if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
307 /* Not for us. */
308 return (1);
309 }
310
311 if (&vap->iv_nw_keys[0] <= k &&
312 k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
313 if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL) {
314 struct rtwn_vap *rvp = RTWN_VAP(vap);
315
316 RTWN_LOCK(sc);
317 rvp->keys[k->wk_keyix] = (set ? k : NULL);
318 if ((sc->sc_flags & RTWN_RUNNING) == 0) {
319 if (!set)
320 clrbit(sc->keys_bmap, k->wk_keyix);
321 RTWN_UNLOCK(sc);
322 return (1);
323 }
324 RTWN_UNLOCK(sc);
325 }
326 }
327
328 return (!rtwn_cmd_sleepable(sc, k, sizeof(*k),
329 set ? rtwn_key_set_cb : rtwn_key_del_cb));
330 }
331
332 int
rtwn_key_set(struct ieee80211vap * vap,const struct ieee80211_key * k)333 rtwn_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
334 {
335 return (rtwn_process_key(vap, k, 1));
336 }
337
338 int
rtwn_key_delete(struct ieee80211vap * vap,const struct ieee80211_key * k)339 rtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
340 {
341 return (rtwn_process_key(vap, k, 0));
342 }
343