diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2002-10-27 14:46:31 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2002-10-27 14:46:31 +0000 |
commit | 8ee0bf9fa6758b817155f02b16ac2fb0caa1c977 (patch) | |
tree | 675e8e2c943807a81d2388ecc09ce1c3a194810b /sys/dev/ic/if_wi.c | |
parent | 3a2220a0e5d5efa8f7c42b3a60b919e3c1317b40 (diff) |
add a matching wi_do_hostdecrypt()
Diffstat (limited to 'sys/dev/ic/if_wi.c')
-rw-r--r-- | sys/dev/ic/if_wi.c | 77 |
1 files changed, 74 insertions, 3 deletions
diff --git a/sys/dev/ic/if_wi.c b/sys/dev/ic/if_wi.c index 8131c62dc2c..f574ec96406 100644 --- a/sys/dev/ic/if_wi.c +++ b/sys/dev/ic/if_wi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wi.c,v 1.86 2002/10/18 03:46:35 fgsch Exp $ */ +/* $OpenBSD: if_wi.c,v 1.87 2002/10/27 14:46:30 markus Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -124,7 +124,7 @@ u_int32_t widebug = WIDEBUG; #if !defined(lint) && !defined(__OpenBSD__) static const char rcsid[] = - "$OpenBSD: if_wi.c,v 1.86 2002/10/18 03:46:35 fgsch Exp $"; + "$OpenBSD: if_wi.c,v 1.87 2002/10/27 14:46:30 markus Exp $"; #endif /* lint */ #ifdef foo @@ -167,6 +167,9 @@ STATIC int wi_get_pm(struct wi_softc *, struct ieee80211_power *); STATIC int wi_get_debug(struct wi_softc *, struct wi_req *); STATIC int wi_set_debug(struct wi_softc *, struct wi_req *); +STATIC void wi_do_hostencrypt(struct wi_softc *, caddr_t, int); +STATIC int wi_do_hostdecrypt(struct wi_softc *, caddr_t, int); + /* Autoconfig definition of driver back-end */ struct cfdriver wi_cd = { NULL, "wi", DV_IFNET @@ -1909,7 +1912,7 @@ static const u_int32_t crc32_tab[] = { #define RC4SWAP(x,y) \ do { u_int8_t t = state[x]; state[x] = state[y]; state[y] = t; } while(0) -static void +STATIC void wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len) { u_int32_t i, crc, klen; @@ -1984,6 +1987,74 @@ wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len) } } +STATIC int +wi_do_hostdecrypt(struct wi_softc *sc, caddr_t buf, int len) +{ + u_int32_t i, crc, klen, kid; + u_int8_t state[RC4STATE], key[RC4KEYLEN]; + u_int8_t x, y, *dat; + + if (len < IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + + IEEE80211_WEP_CRCLEN) + return -1; + len -= (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + + IEEE80211_WEP_CRCLEN); + + dat = buf; + + bzero(key, sizeof(key)); + key[0] = dat[0]; + key[1] = dat[1]; + key[2] = dat[2]; + kid = (dat[3] >> 6) % 4; + dat += 4; + + klen = sc->wi_keys.wi_keys[kid].wi_keylen; + bcopy((char *)&sc->wi_keys.wi_keys[kid].wi_keydat, + (char *)key + IEEE80211_WEP_IVLEN, klen); + klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2; + + /* rc4 keysetup */ + x = y = 0; + for (i = 0; i < RC4STATE; i++) + state[i] = i; + for (i = 0; i < RC4STATE; i++) { + y = (key[x] + state[i] + y) % RC4STATE; + RC4SWAP(i, y); + x = (x + 1) % klen; + } + + /* compute rc4 over data, crc32 over data */ + crc = ~0; + x = y = 0; + for (i = 0; i < len; i++) { + x = (x + 1) % RC4STATE; + y = (state[x] + y) % RC4STATE; + RC4SWAP(x, y); + dat[i] ^= state[(state[x] + state[y]) % RC4STATE]; + crc = crc32_tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8); + } + crc = ~crc; + dat += len; + + /* append little-endian crc32 and encrypt */ + for (i = 0; i < IEEE80211_WEP_CRCLEN; i++) { + x = (x + 1) % RC4STATE; + y = (state[x] + y) % RC4STATE; + RC4SWAP(x, y); + dat[i] ^= state[(state[x] + state[y]) % RC4STATE]; + } + if ((dat[0] != crc) && (dat[1] != crc >> 8) && + (dat[2] != crc >> 16) && (dat[3] != crc >> 24)) { + if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG) + printf(WI_PRT_FMT ": wi_do_hostdecrypt: iv mismatch\n", + WI_PRT_ARG(sc)); + return -1; + } + + return 0; +} + STATIC void wi_start(ifp) struct ifnet *ifp; |