xref: /freebsd/sys/dev/rtwn/if_rtwn_cam.c (revision 333eb58deeda6cc5a5a908b92301f833ba8750fa)
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 (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
rtwn_key_set_cb0(struct rtwn_softc * sc,const struct ieee80211_key * k)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
rtwn_key_set_cb(struct rtwn_softc * sc,union sec_param * data)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
rtwn_init_static_keys(struct rtwn_softc * sc,struct rtwn_vap * rvp)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
rtwn_key_del_cb(struct rtwn_softc * sc,union sec_param * data)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
rtwn_process_key(struct ieee80211vap * vap,const struct ieee80211_key * k,int set)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
rtwn_key_set(struct ieee80211vap * vap,const struct ieee80211_key * k)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
rtwn_key_delete(struct ieee80211vap * vap,const struct ieee80211_key * k)345 rtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
346 {
347 	return (rtwn_process_key(vap, k, 0));
348 }
349