ref: b9214d6662c78c808f6fb788747c364028a8ff24
parent: 33d00fce10a2ffa65c80d20559e0aee74da8c8d8
author: cinap_lenrek <[email protected]>
date: Sun Mar 24 17:59:47 EDT 2013
wifi: cleanup cleanup wifiencrypt()/wifidecrypt() routines moving tkip and ccmp in separate routines so we dont use less stack space.
--- a/sys/src/9/pc/wifi.c
+++ b/sys/src/9/pc/wifi.c
@@ -664,54 +664,23 @@
return n;
}
-static void tkipk2tk(uchar key[16], u16int tk[8]);
-static void tkipphase1(u32int tscu, uchar ta[Eaddrlen], u16int tk[8], u16int p1k[5]);
-static void tkipphase2(u16int tscl, u16int p1k[5], u16int tk[8], uchar rc4key[16]);
+static void tkipencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
+static int tkipdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
+static void ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
+static int ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
-typedef struct MICstate MICstate;
-struct MICstate
-{
- u32int l;
- u32int r;
- u32int m;
- u32int n;
-};
-
-static void micsetup(MICstate *s, uchar key[8]);
-static void micupdate(MICstate *s, uchar *data, ulong len);
-static void micfinish(MICstate *s, uchar mic[8]);
-
-static uchar pad4[4] = { 0x00, 0x00, 0x00, 0x00, };
-
-static int setupCCMP(Wkey *k, Wifipkt *w, uvlong tsc, uchar nonce[13], uchar auth[30], AESstate *as);
-
-void aesCCMencrypt(int L, int M, uchar *N /* N[15-L] */,
- uchar *a /* a[la] */, int la,
- uchar *m /* m[lm+M] */, int lm,
- AESstate *s);
-int aesCCMdecrypt(int L, int M, uchar *N /* N[15-L] */,
- uchar *a /* a[la] */, int la,
- uchar *m /* m[lm+M] */, int lm,
- AESstate *s);
-
static Block*
wifiencrypt(Wifi *, Wnode *wn, Block *b)
{
- uchar auth[32], seed[16];
- u16int tk[8], p1k[5];
uvlong tsc;
- ulong crc;
- AESstate as;
- RC4state rs;
- MICstate ms;
- Wifipkt *w;
int n, kid;
+ Wifipkt *w;
Wkey *k;
kid = 0;
k = &wn->txkey[kid];
if(k->cipher == 0)
- goto pass;
+ return b;
n = wifihdrlen((Wifipkt*)b->rp);
@@ -735,30 +704,9 @@
b->rp[6] = tsc>>32;
b->rp[7] = tsc>>40;
b->rp += 8;
-
if(k->len != 32)
goto drop;
- micsetup(&ms, k->key+24);
- micupdate(&ms, dstaddr(w), Eaddrlen);
- micupdate(&ms, srcaddr(w), Eaddrlen);
- micupdate(&ms, pad4, 4);
- micupdate(&ms, b->rp, BLEN(b));
- micfinish(&ms, b->wp);
- b->wp += 8;
-
- crc = ethercrc(b->rp, BLEN(b));
- crc = ~crc;
- b->wp[0] = crc;
- b->wp[1] = crc>>8;
- b->wp[2] = crc>>16;
- b->wp[3] = crc>>24;
- b->wp += 4;
-
- tkipk2tk(k->key, tk);
- tkipphase1(tsc >> 16, w->a2, tk, p1k);
- tkipphase2(tsc & 0xFFFF, p1k, tk, seed);
- setupRC4state(&rs, seed, sizeof(seed));
- rc4(&rs, b->rp, BLEN(b));
+ tkipencrypt(k, w, b, tsc);
break;
case CCMP:
b->rp[0] = tsc;
@@ -770,39 +718,27 @@
b->rp[6] = tsc>>32;
b->rp[7] = tsc>>40;
b->rp += 8;
-
if(k->len != 16)
goto drop;
- aesCCMencrypt(2, 8, seed, auth, setupCCMP(k, w, tsc, seed, auth, &as),
- b->rp, BLEN(b), &as);
- b->wp += 8;
+ ccmpencrypt(k, w, b, tsc);
break;
default:
- goto drop;
+ drop:
+ free(b);
+ return nil;
}
b->rp = (uchar*)w;
w->fc[1] |= 0x40;
-
-pass:
return b;
-drop:
- free(b);
- return nil;
}
static Block*
wifidecrypt(Wifi *, Wnode *wn, Block *b)
{
- uchar auth[32], seed[16], mic[8];
- u16int tk[8], p1k[5];
- RC4state rs;
- AESstate as;
- MICstate ms;
uvlong tsc;
- ulong crc;
- Wifipkt *w;
int n, kid;
+ Wifipkt *w;
Wkey *k;
w = (Wifipkt*)b->rp;
@@ -830,32 +766,10 @@
(uvlong)b->rp[0]<<8 |
(uvlong)b->rp[2];
b->rp += 8;
- if(tsc <= k->tsc || BLEN(b) < 8+4 || k->len != 32)
+ if(tsc <= k->tsc || k->len != 32)
goto drop;
- tkipk2tk(k->key, tk);
- tkipphase1(tsc >> 16, w->a2, tk, p1k);
- tkipphase2(tsc & 0xFFFF, p1k, tk, seed);
- setupRC4state(&rs, seed, sizeof(seed));
- rc4(&rs, b->rp, BLEN(b));
-
- b->wp -= 4;
- crc = (ulong)b->wp[0] |
- (ulong)b->wp[1]<<8 |
- (ulong)b->wp[2]<<16 |
- (ulong)b->wp[3]<<24;
- crc = ~crc;
- if(ethercrc(b->rp, BLEN(b)) != crc)
+ if(tkipdecrypt(k, w, b, tsc) != 0)
goto drop;
-
- b->wp -= 8;
- micsetup(&ms, k->key+16);
- micupdate(&ms, dstaddr(w), Eaddrlen);
- micupdate(&ms, srcaddr(w), Eaddrlen);
- micupdate(&ms, pad4, 4);
- micupdate(&ms, b->rp, BLEN(b));
- micfinish(&ms, mic);
- if(memcmp(b->wp, mic, 8) != 0)
- goto drop;
break;
case CCMP:
tsc = (uvlong)b->rp[7]<<40 |
@@ -867,13 +781,13 @@
b->rp += 8;
if(tsc <= k->tsc || k->len != 16)
goto drop;
- b->wp -= 8;
- if(aesCCMdecrypt(2, 8, seed, auth, setupCCMP(k, w, tsc, seed, auth, &as),
- b->rp, BLEN(b), &as) != 0)
+ if(ccmpdecrypt(k, w, b, tsc) != 0)
goto drop;
break;
default:
- goto drop;
+ drop:
+ freeb(b);
+ return nil;
}
k->tsc = tsc;
@@ -882,9 +796,6 @@
w = (Wifipkt*)b->rp;
w->fc[1] &= ~0x40;
return b;
-drop:
- freeb(b);
- return nil;
}
static u16int Sbox[256] = {
@@ -1043,6 +954,14 @@
rc4key[15] = ppk[5] >> 8;
}
+typedef struct MICstate MICstate;
+struct MICstate
+{
+ u32int l;
+ u32int r;
+ u32int m;
+ u32int n;
+};
static void
micsetup(MICstate *s, uchar key[8])
@@ -1107,6 +1026,78 @@
mic[7] = s->r>>24;
}
+static uchar pad4[4] = { 0x00, 0x00, 0x00, 0x00, };
+
+static void
+tkipencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
+{
+ u16int tk[8], p1k[5];
+ uchar seed[16];
+ RC4state rs;
+ MICstate ms;
+ ulong crc;
+
+ micsetup(&ms, k->key+24);
+ micupdate(&ms, dstaddr(w), Eaddrlen);
+ micupdate(&ms, srcaddr(w), Eaddrlen);
+ micupdate(&ms, pad4, 4);
+ micupdate(&ms, b->rp, BLEN(b));
+ micfinish(&ms, b->wp);
+ b->wp += 8;
+
+ crc = ethercrc(b->rp, BLEN(b));
+ crc = ~crc;
+ b->wp[0] = crc;
+ b->wp[1] = crc>>8;
+ b->wp[2] = crc>>16;
+ b->wp[3] = crc>>24;
+ b->wp += 4;
+
+ tkipk2tk(k->key, tk);
+ tkipphase1(tsc >> 16, w->a2, tk, p1k);
+ tkipphase2(tsc & 0xFFFF, p1k, tk, seed);
+ setupRC4state(&rs, seed, sizeof(seed));
+ rc4(&rs, b->rp, BLEN(b));
+}
+
+static int
+tkipdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
+{
+ uchar seed[16], mic[8];
+ u16int tk[8], p1k[5];
+ RC4state rs;
+ MICstate ms;
+ ulong crc;
+
+ if(BLEN(b) < 8+4)
+ return -1;
+
+ tkipk2tk(k->key, tk);
+ tkipphase1(tsc >> 16, w->a2, tk, p1k);
+ tkipphase2(tsc & 0xFFFF, p1k, tk, seed);
+ setupRC4state(&rs, seed, sizeof(seed));
+ rc4(&rs, b->rp, BLEN(b));
+
+ b->wp -= 4;
+ crc = (ulong)b->wp[0] |
+ (ulong)b->wp[1]<<8 |
+ (ulong)b->wp[2]<<16 |
+ (ulong)b->wp[3]<<24;
+ crc = ~crc;
+ if(ethercrc(b->rp, BLEN(b)) != crc)
+ return -1;
+
+ b->wp -= 8;
+ micsetup(&ms, k->key+16);
+ micupdate(&ms, dstaddr(w), Eaddrlen);
+ micupdate(&ms, srcaddr(w), Eaddrlen);
+ micupdate(&ms, pad4, 4);
+ micupdate(&ms, b->rp, BLEN(b));
+ micfinish(&ms, mic);
+
+ return memcmp(b->wp, mic, 8) != 0;
+}
+
static uchar*
putbe(uchar *p, int L, uint v)
{
@@ -1150,7 +1141,7 @@
return b;
};
-void
+static void
aesCCMencrypt(int L, int M, uchar *N /* N[15-L] */,
uchar *a /* a[la] */, int la,
uchar *m /* m[lm+M] */, int lm,
@@ -1189,7 +1180,7 @@
memmove(m, t, M);
}
-int
+static int
aesCCMdecrypt(int L, int M, uchar *N /* N[15-L] */,
uchar *a /* a[la] */, int la,
uchar *m /* m[lm+M] */, int lm,
@@ -1254,4 +1245,31 @@
*p++ = 0;
return p - auth;
+}
+
+static void
+ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
+{
+ uchar auth[32], nonce[13];
+ AESstate as;
+
+ aesCCMencrypt(2, 8, nonce, auth,
+ setupCCMP(k, w, tsc, nonce, auth, &as),
+ b->rp, BLEN(b), &as);
+ b->wp += 8;
+}
+
+static int
+ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
+{
+ uchar auth[32], nonce[13];
+ AESstate as;
+
+ if(BLEN(b) < 8)
+ return -1;
+
+ b->wp -= 8;
+ return aesCCMdecrypt(2, 8, nonce, auth,
+ setupCCMP(k, w, tsc, nonce, auth, &as),
+ b->rp, BLEN(b), &as);
}