summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2008-08-29 11:15:33 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2008-08-29 11:15:33 +0000
commit05ec9e5948c1b5ef23e066521d27864000bf26a2 (patch)
tree87606a4fa4fb02c8a7cca60622fcff85703993d3 /sys
parent77ece86375374475f67cd30654a2946326c3df69 (diff)
add support for software crypto to allow WPA/WPA2/RSN. it is disabled
for now because it needs more testing, but basic WPA/WPA2 and WEP seems to work. to enable it, set the compiled-in ath_softcrypto variable to 1. this is based on a previous diff from damien@ with some changes to disable the hardware crypto engine if softcrypto is enabled and to keeps the hardware crypto code in place to allow later work on hardware WPA/WPA2.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/ath.c73
-rw-r--r--sys/dev/ic/athvar.h4
2 files changed, 55 insertions, 22 deletions
diff --git a/sys/dev/ic/ath.c b/sys/dev/ic/ath.c
index 565f0790ba1..3192be78c75 100644
--- a/sys/dev/ic/ath.c
+++ b/sys/dev/ic/ath.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ath.c,v 1.76 2008/08/27 10:01:18 damien Exp $ */
+/* $OpenBSD: ath.c,v 1.77 2008/08/29 11:15:32 reyk Exp $ */
/* $NetBSD: ath.c,v 1.37 2004/08/18 21:59:39 dyoung Exp $ */
/*-
@@ -78,6 +78,7 @@
#include <dev/pci/pcidevs.h>
#include <dev/gpio/gpiovar.h>
+
#include <dev/ic/athvar.h>
int ath_init(struct ifnet *);
@@ -157,6 +158,7 @@ int ath_dwelltime = 200; /* 5 channels/second */
int ath_calinterval = 30; /* calibrate every 30 secs */
int ath_outdoor = AH_TRUE; /* outdoor operation */
int ath_xchanmode = AH_TRUE; /* enable extended channels */
+int ath_softcrypto = 0; /* 1=enable software crypto */
struct cfdriver ath_cd = {
NULL, "ath", DV_IFNET
@@ -370,6 +372,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
| IEEE80211_C_MONITOR /* monitor mode */
| IEEE80211_C_SHSLOT /* short slot time supported */
| IEEE80211_C_SHPREAMBLE; /* short preamble supported */
+ if (ath_softcrypto)
+ ic->ic_caps |= IEEE80211_C_RSN; /* wpa/rsn supported */
/*
* Not all chips have the VEOL support we want to use with
@@ -751,20 +755,13 @@ ath_init1(struct ath_softc *sc)
goto done;
}
ath_set_slot_time(sc);
- /*
- * Setup the hardware after reset: the key cache
- * is filled as needed and the receive engine is
- * set going. Frame transmit is handled entirely
- * in the frame output path; there's nothing to do
- * here except setup the interrupt mask.
- */
- if (ic->ic_flags & IEEE80211_F_WEPON) {
- if ((error = ath_initkeytable(sc)) != 0) {
- printf("%s: unable to initialize the key cache\n",
- ifp->if_xname);
- goto done;
- }
+
+ if ((error = ath_initkeytable(sc)) != 0) {
+ printf("%s: unable to reset the key cache\n",
+ ifp->if_xname);
+ goto done;
}
+
if ((error = ath_startrecv(sc)) != 0) {
printf("%s: unable to start recv logic\n", ifp->if_xname);
goto done;
@@ -1156,6 +1153,29 @@ ath_initkeytable(struct ath_softc *sc)
struct ath_hal *ah = sc->sc_ah;
int i;
+ if (ath_softcrypto) {
+ /*
+ * Disable the hardware crypto engine and reset the key cache
+ * to allow software crypto operation for WEP/RSN/WPA2
+ */
+ if (ic->ic_flags & (IEEE80211_F_WEPON|IEEE80211_F_RSNON))
+ (void)ath_hal_softcrypto(ah, AH_TRUE);
+ else
+ (void)ath_hal_softcrypto(ah, AH_FALSE);
+ return (0);
+ }
+
+ /* WEP is disabled, we only support WEP in hardware yet */
+ if ((ic->ic_flags & IEEE80211_F_WEPON) == 0)
+ return (0);
+
+ /*
+ * Setup the hardware after reset: the key cache is filled as
+ * needed and the receive engine is set going. Frame transmit
+ * is handled entirely in the frame output path; there's nothing
+ * to do here except setup the interrupt mask.
+ */
+
/* XXX maybe should reset all keys when !WEPON */
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
struct ieee80211_key *k = &ic->ic_nw_keys[i];
@@ -1907,7 +1927,8 @@ ath_rx_proc(void *arg, int npending)
struct ath_hal *ah = sc->sc_ah;
struct ath_desc *ds;
struct mbuf *m;
- struct ieee80211_frame *wh, whbuf;
+ struct ieee80211_frame *wh;
+ struct ieee80211_frame whbuf;
struct ieee80211_rxinfo rxi;
struct ieee80211_node *ni;
struct ath_node *an;
@@ -2045,7 +2066,7 @@ ath_rx_proc(void *arg, int npending)
m_adj(m, -IEEE80211_CRC_LEN);
wh = mtod(m, struct ieee80211_frame *);
rxi.rxi_flags = 0;
- if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
+ if (!ath_softcrypto && (wh->i_fc[1] & IEEE80211_FC1_WEP)) {
/*
* WEP is decrypted by hardware. Clear WEP bit
* and trim WEP header for ieee80211_input().
@@ -2129,6 +2150,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
struct ath_desc *ds;
struct mbuf *m;
struct ieee80211_frame *wh;
+ struct ieee80211_key *k;
u_int32_t iv;
u_int8_t *ivp;
u_int8_t hdrbuf[sizeof(struct ieee80211_frame) +
@@ -2141,11 +2163,19 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
u_int8_t hwqueue = HAL_TX_QUEUE_ID_DATA_MIN;
wh = mtod(m0, struct ieee80211_frame *);
- iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
+ iswep = wh->i_fc[1] & IEEE80211_FC1_PROTECTED;
hdrlen = sizeof(struct ieee80211_frame);
pktlen = m0->m_pkthdr.len;
- if (iswep) {
+ if (ath_softcrypto && iswep) {
+ k = ieee80211_get_txkey(ic, wh, ni);
+ if ((m0 = ieee80211_encrypt(ic, m0, k)) == NULL)
+ return ENOMEM;
+ wh = mtod(m0, struct ieee80211_frame *);
+
+ /* reset len in case we got a new mbuf */
+ pktlen = m0->m_pkthdr.len;
+ } else if (!ath_softcrypto && iswep) {
bcopy(mtod(m0, caddr_t), hdrbuf, hdrlen);
m_adj(m0, hdrlen);
M_PREPEND(m0, sizeof(hdrbuf), M_DONTWAIT);
@@ -2417,7 +2447,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
sc->sc_txtap.wt_flags = 0;
if (shortPreamble)
sc->sc_txtap.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
- if (iswep)
+ if (!ath_softcrypto && iswep)
sc->sc_txtap.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
sc->sc_txtap.wt_rate = ni->ni_rates.rs_rates[ni->ni_txrate] &
IEEE80211_RATE_VAL;
@@ -2908,7 +2938,8 @@ ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
struct ath_hal *ah = sc->sc_ah;
struct ieee80211_node *ni;
const u_int8_t *bssid;
- int i, error;
+ int error, i;
+
u_int32_t rfilt;
DPRINTF(ATH_DEBUG_ANY, ("%s: %s -> %s\n", __func__,
@@ -2946,7 +2977,7 @@ ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
ath_hal_set_associd(ah, bssid, 0);
}
- if (ic->ic_flags & IEEE80211_F_WEPON) {
+ if (!ath_softcrypto && (ic->ic_flags & IEEE80211_F_WEPON)) {
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
if (ath_hal_is_key_valid(ah, i))
ath_hal_set_key_lladdr(ah, i, bssid);
diff --git a/sys/dev/ic/athvar.h b/sys/dev/ic/athvar.h
index ebaabbe4241..05db2d96aec 100644
--- a/sys/dev/ic/athvar.h
+++ b/sys/dev/ic/athvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: athvar.h,v 1.24 2008/07/29 00:18:25 reyk Exp $ */
+/* $OpenBSD: athvar.h,v 1.25 2008/08/29 11:15:32 reyk Exp $ */
/* $NetBSD: athvar.h,v 1.10 2004/08/10 01:03:53 dyoung Exp $ */
/*-
@@ -449,6 +449,8 @@ int ath_enable(struct ath_softc *);
(((*(_ah)->ah_is_key_valid)((_ah), (_ix))))
#define ath_hal_set_key_lladdr(_ah, _ix, _mac) \
((*(_ah)->ah_set_key_lladdr)((_ah), (_ix), (_mac)))
+#define ath_hal_softcrypto(_ah, _val ) \
+ ((*(_ah)->ah_softcrypto)((_ah), (_val)))
#define ath_hal_get_rx_filter(_ah) \
((*(_ah)->ah_get_rx_filter)((_ah)))
#define ath_hal_set_rx_filter(_ah, _filter) \