Subject: wi(4) and WEP on NetBSD 4.0
To: None <tech-net@netbsd.org>
From: Quentin Garnier <cube@cubidou.net>
List: tech-net
Date: 11/26/2007 12:02:13
--W13SgbpmD6bhZUTM
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi,

I upgraded a machine from 2.0 to 4.0 this week-end.  It serves among
other things as an access point for a home 11b network, using a wi(4)
card.

I was faced with two issues related to WEP, one in the RX path, the
other in the TX path.

The RX path one is easier:  frames were dropped because of _F_DROPUNENC
which is set by default.  The reason for that is the following block in
sys/dev/ic/wi.c, in wi_rx_intr():

        if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
                /*
                 * WEP is decrypted by hardware. Clear WEP bit
                 * header for ieee80211_input().
                 */
                wh->i_fc[1] &=3D ~IEEE80211_FC1_WEP;
        }

Apparently, the net80211 subsystem has changed enough that this does the
wrong thing:  as the bit is cleared, ieee80211_input() thinks it is an
unencrypted frame, so it drops it per _F_DROPUNENC.  I believe that the
part that has changed in net80211 is that the codec for WEP is aware the
hardware is supposed to do the actual deciphering, hence it doesn't do
it.

The fix for that issue is to just comment the block shown above.

I'm told by someone that wi+WEP works for him in NetBSD 4.0.  My reading
of the code doesn't show any place where the fact that I run it in
hostap mode changes anything, so I'm rather surprised.

The TX issue is different, and I think it means a few things have to
change in net80211 so it can be fixed properly.  I don't know how the
current net80211 code in FreeBSD is different from what we have, but a
quick glance at it didn't let me see how they could have fixed it.

The bottom of the issue is that according to comments in the wi(4)
driver, the chip has a bug which means TX frames must be encoded by the
software.  However, it will still happily do the decryption for RX
frames.  The problem is that there is no way for the driver to tell the
net80211 layer to do encryption by software, but not do decryption.

My quick workaround (as in "this has to work _now_") was simply to
comment out the check for _KEY_SWCRYPT in _crypto_wep.c:wep_encap().

I started playing with the idea of adding flags or capabilities to
distinguish between encryption and decryption.  I have code, but I
haven't tested it yet.

Another solution would be to change wi so that it doesn't do decryption
in hw when it is in hostap mode.  But even in that case we have to make
sure the WEP keys structures are updated when transitioning from
infrastructure or adhoc mode to hostap, so in that regards both
solutions are rather equivalent.

Anything I would have missed on my way, before I go digging further?

Here's the mentioned untested code:

http://taryn.cubidou.net/~cube/netbsd/wi.diff

--=20
Quentin Garnier - cube@cubidou.net - cube@NetBSD.org
"See the look on my face from staying too long in one place
[...] every time the morning breaks I know I'm closer to falling"
KT Tunstall, Saving My Face, Drastic Fantastic, 2007.

--W13SgbpmD6bhZUTM
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (NetBSD)

iQEVAwUBR0qntdgoQloHrPnoAQLGvwf/TL4pNJeMoSgZy0UuFJ9rJccSIuTnK00R
wuVPHC8FFqSoGGI9O6KoU1NYq1jqvZujUz1qoDagsKxB4Mko9h0oIoKUNS60v4E8
AKvpb572k+I5K9ta2VeZg1eFavyUI7u6zaQM49ubg582cTOa9PnPPF3WCm3IR/PZ
IwYBkMlVLAWb8Hpqc6tHfaBMe4yr6VZU04uMYqzQCsJi5Is5gC6Iqbl11vx/Sbss
0rLYxgqtteTG9Z7atIMPDiAiO+5yv/QMKCmkQOBbV0/t71tk5QYHn92i4EiK2Txi
Ij777qnp28CQeX6LeQGp6w3By8TCQLSq35jHZ4nJkCa42Qt3qeJbwQ==
=SdES
-----END PGP SIGNATURE-----

--W13SgbpmD6bhZUTM--