]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/wifi.c
merge
[plan9front.git] / sys / src / 9 / pc / wifi.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "pool.h"
8 #include "ureg.h"
9 #include "../port/error.h"
10 #include "../port/netif.h"
11
12 #include "etherif.h"
13 #include "wifi.h"
14
15 #include <libsec.h>
16
17 typedef struct SNAP SNAP;
18 struct SNAP
19 {
20         uchar   dsap;
21         uchar   ssap;
22         uchar   control;
23         uchar   orgcode[3];
24         uchar   type[2];
25 };
26
27 enum {
28         WIFIHDRSIZE = 2+2+3*6+2,
29         SNAPHDRSIZE = 8,
30 };
31
32 static char Snone[] = "new";
33 static char Sconn[] = "connecting";
34 static char Sauth[] = "authenticated";
35 static char Sunauth[] = "unauthentictaed";
36 static char Sassoc[] = "associated";
37 static char Sunassoc[] = "unassociated";
38 static char Sblocked[] = "blocked";     /* no keys negotiated. only pass EAPOL frames */
39
40 static Block* wifidecrypt(Wifi *, Wnode *, Block *);
41 static Block* wifiencrypt(Wifi *, Wnode *, Block *);
42
43 static uchar*
44 srcaddr(Wifipkt *w)
45 {
46         if((w->fc[1] & 3) == 0x02)
47                 return w->a3;
48         else
49                 return w->a2;
50 }
51 static uchar*
52 dstaddr(Wifipkt *w)
53 {
54         if((w->fc[1] & 3) == 0x01)
55                 return w->a3;
56         else
57                 return w->a1;
58 }
59
60 static int
61 wifihdrlen(Wifipkt *w)
62 {
63         int n;
64
65         n = WIFIHDRSIZE;
66         if((w->fc[0] & 0x0c) == 0x08)
67                 if((w->fc[0] & 0xf0) == 0x80){  /* QOS */
68                         n += 2;
69                         if(w->fc[1] & 0x80)
70                                 n += 4;
71                 }
72         return n;
73 }
74
75 void
76 wifiiq(Wifi *wifi, Block *b)
77 {
78         SNAP s;
79         Wifipkt h, *w;
80         Etherpkt *e;
81
82         if(BLEN(b) < WIFIHDRSIZE)
83                 goto drop;
84         w = (Wifipkt*)b->rp;
85         if(w->fc[1] & 0x40){
86                 /* encrypted */
87                 qpass(wifi->iq, b);
88                 return;
89         }
90         switch(w->fc[0] & 0x0c){
91         case 0x00:      /* management */
92                 if((w->fc[1] & 3) != 0x00)      /* STA->STA */
93                         break;
94                 qpass(wifi->iq, b);
95                 return;
96         case 0x04:      /* control */
97                 break;
98         case 0x08:      /* data */
99                 if((w->fc[1] & 3) == 0x03)      /* AP->AP */
100                         break;
101                 b->rp += wifihdrlen(w);
102                 switch(w->fc[0] & 0xf0){
103                 default:
104                         goto drop;
105                 case 0x80:      /* QOS */
106                 case 0x00:
107                         break;
108                 }
109                 if(BLEN(b) < SNAPHDRSIZE)
110                         break;
111                 memmove(&s, b->rp, SNAPHDRSIZE);
112                 if(s.dsap != 0xAA || s.ssap != 0xAA || s.control != 3)
113                         break;
114                 if(s.orgcode[0] != 0 || s.orgcode[1] != 0 || s.orgcode[2] != 0)
115                         break;
116                 b->rp += SNAPHDRSIZE-ETHERHDRSIZE;
117                 h = *w;
118                 e = (Etherpkt*)b->rp;
119                 memmove(e->d, dstaddr(&h), Eaddrlen);
120                 memmove(e->s, srcaddr(&h), Eaddrlen);
121                 memmove(e->type, s.type, 2);
122                 etheriq(wifi->ether, b, 1);
123                 return;
124         }
125 drop:
126         freeb(b);
127 }
128
129 static void
130 wifitx(Wifi *wifi, Wnode *wn, Block *b)
131 {
132         Wifipkt *w;
133         uint seq;
134
135         seq = incref(&wifi->txseq);
136         seq <<= 4;
137
138         w = (Wifipkt*)b->rp;
139         w->dur[0] = 0;
140         w->dur[1] = 0;
141         w->seq[0] = seq;
142         w->seq[1] = seq>>8;
143
144         if((w->fc[0] & 0x0c) != 0x00)
145                 b = wifiencrypt(wifi, wn, b);
146
147         if(b != nil)
148                 (*wifi->transmit)(wifi, wn, b);
149 }
150
151 static Wnode*
152 nodelookup(Wifi *wifi, uchar *bssid, int new)
153 {
154         Wnode *wn, *nn;
155
156         if(memcmp(bssid, wifi->ether->bcast, Eaddrlen) == 0)
157                 return nil;
158         if((wn = wifi->bss) != nil){
159                 if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){
160                         wn->lastseen = MACHP(0)->ticks;
161                         return wn;
162                 }
163         }
164         if((nn = wifi->node) == wn)
165                 nn++;
166         for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){
167                 if(wn == wifi->bss)
168                         continue;
169                 if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){
170                         wn->lastseen = MACHP(0)->ticks;
171                         return wn;
172                 }
173                 if(wn->lastseen < nn->lastseen)
174                         nn = wn;
175         }
176         if(!new)
177                 return nil;
178         memset(nn, 0, sizeof(Wnode));
179         memmove(nn->bssid, bssid, Eaddrlen);
180         nn->lastseen = MACHP(0)->ticks;
181         return nn;
182 }
183
184 static void
185 sendauth(Wifi *wifi, Wnode *bss)
186 {
187         Wifipkt *w;
188         Block *b;
189         uchar *p;
190
191         b = allocb(WIFIHDRSIZE + 3*2);
192         w = (Wifipkt*)b->wp;
193         w->fc[0] = 0xB0;        /* auth request */
194         w->fc[1] = 0x00;        /* STA->STA */
195         memmove(w->a1, bss->bssid, Eaddrlen);   /* ??? */
196         memmove(w->a2, wifi->ether->ea, Eaddrlen);
197         memmove(w->a3, bss->bssid, Eaddrlen);
198         b->wp += WIFIHDRSIZE;
199         p = b->wp;
200         *p++ = 0;       /* alg */
201         *p++ = 0;
202         *p++ = 1;       /* seq */
203         *p++ = 0;
204         *p++ = 0;       /* status */
205         *p++ = 0;
206         b->wp = p;
207         wifitx(wifi, bss, b);
208 }
209
210 static void
211 sendassoc(Wifi *wifi, Wnode *bss)
212 {
213         Wifipkt *w;
214         Block *b;
215         uchar *p;
216         int n;
217
218         b = allocb(WIFIHDRSIZE + 512);
219         w = (Wifipkt*)b->wp;
220         w->fc[0] = 0x00;        /* assoc request */
221         w->fc[1] = 0x00;        /* STA->STA */
222         memmove(w->a1, bss->bssid, Eaddrlen);   /* ??? */
223         memmove(w->a2, wifi->ether->ea, Eaddrlen);
224         memmove(w->a3, bss->bssid, Eaddrlen);
225         b->wp += WIFIHDRSIZE;
226         p = b->wp;
227         *p++ = 1;       /* capinfo */
228         *p++ = 0;
229         *p++ = 16;      /* interval */
230         *p++ = 16>>8;
231
232         *p++ = 0;       /* SSID */
233         *p = strlen(bss->ssid);
234         memmove(p+1, bss->ssid, *p);
235         p += 1+*p;
236
237         *p++ = 1;       /* RATES (BUG: these are all lies!) */
238         *p++ = 4;
239         *p++ = 0x82;
240         *p++ = 0x84;
241         *p++ = 0x8b;
242         *p++ = 0x96;
243
244         n = bss->rsnelen;
245         if(n > 0){
246                 memmove(p, bss->rsne, n);
247                 p += n;
248         }
249
250         b->wp = p;
251         wifitx(wifi, bss, b);
252 }
253
254 static void
255 recvassoc(Wifi *wifi, Wnode *wn, uchar *d, int len)
256 {
257         uint s;
258
259         if(len < 2+2+2)
260                 return;
261
262         d += 2; /* caps */
263         s = d[0] | d[1]<<8;
264         d += 2;
265         switch(s){
266         case 0x00:
267                 wn->aid = d[0] | d[1]<<8;
268                 if(wn->rsnelen > 0)
269                         wifi->status = Sblocked;
270                 else
271                         wifi->status = Sassoc;
272                 break;
273         default:
274                 wn->aid = 0;
275                 wifi->status = Sunassoc;
276                 return;
277         }
278 }
279
280 static void
281 recvbeacon(Wifi *, Wnode *wn, uchar *d, int len)
282 {
283         uchar *e, *x;
284         uchar t, m[256/8];
285
286         if(len < 8+2+2)
287                 return;
288
289         d += 8; /* timestamp */
290         wn->ival = d[0] | d[1]<<8;
291         d += 2;
292         wn->cap = d[0] | d[1]<<8;
293         d += 2;
294
295         memset(m, 0, sizeof(m));
296         for(e = d + len; d+2 <= e; d = x){
297                 d += 2;
298                 x = d + d[-1];
299                 t = d[-2];
300
301                 /* skip double entries */
302                 if(m[t/8] & 1<<(t%8))
303                         continue;
304                 m[t/8] |= 1<<(t%8);
305
306                 switch(t){
307                 case 0: /* SSID */
308                         len = 0;
309                         while(len < Essidlen && d+len < x && d[len] != 0)
310                                 len++;
311                         if(len == 0)
312                                 continue;
313                         if(len != strlen(wn->ssid) || strncmp(wn->ssid, (char*)d, len) != 0){
314                                 strncpy(wn->ssid, (char*)d, len);
315                                 wn->ssid[len] = 0;
316                         }
317                         break;
318                 case 3: /* DSPARAMS */
319                         if(d != x)
320                                 wn->channel = d[0];
321                         break;
322                 }
323         }
324 }
325
326 static void
327 wifiproc(void *arg)
328 {
329         Wifi *wifi;
330         Wifipkt *w;
331         Wnode *wn;
332         Block *b;
333
334         b = nil;
335         wifi = arg;
336         for(;;){
337                 if(b != nil)
338                         freeb(b);
339                 if((b = qbread(wifi->iq, 100000)) == nil)
340                         break;
341                 w = (Wifipkt*)b->rp;
342                 if(w->fc[1] & 0x40){
343                         /* encrypted */
344                         if((wn = nodelookup(wifi, w->a2, 1)) == nil)
345                                 continue;
346                         if((b = wifidecrypt(wifi, wn, b)) != nil){
347                                 w = (Wifipkt*)b->rp;
348                                 if(w->fc[1] & 0x40)
349                                         continue;
350                                 wifiiq(wifi, b);
351                                 b = nil;
352                         }
353                         continue;
354                 }
355                 /* management */
356                 if((w->fc[0] & 0x0c) != 0x00)
357                         continue;
358                 switch(w->fc[0] & 0xf0){
359                 case 0x50:      /* probe response */
360                 case 0x80:      /* beacon */
361                         if((wn = nodelookup(wifi, w->a3, 1)) == nil)
362                                 continue;
363                         b->rp += wifihdrlen(w);
364                         recvbeacon(wifi, wn, b->rp, BLEN(b));
365                         if(wifi->bss == nil && wifi->essid[0] != 0 && strcmp(wifi->essid, wn->ssid) == 0){
366                                 wifi->bss = wn;
367                                 wifi->status = Sconn;
368                                 sendauth(wifi, wn);
369                         }
370                         continue;
371                 }
372                 if(memcmp(w->a1, wifi->ether->ea, Eaddrlen))
373                         continue;
374                 if((wn = nodelookup(wifi, w->a3, 0)) == nil)
375                         continue;
376                 if(wn != wifi->bss)
377                         continue;
378                 switch(w->fc[0] & 0xf0){
379                 case 0x10:      /* assoc response */
380                 case 0x30:      /* reassoc response */
381                         b->rp += wifihdrlen(w);
382                         recvassoc(wifi, wn, b->rp, BLEN(b));
383                         break;
384                 case 0xb0:      /* auth */
385                         wifi->status = Sauth;
386                         sendassoc(wifi, wn);
387                         break;
388                 case 0xc0:      /* deauth */
389                         wifi->status = Sunauth;
390                         memset(wn->rxkey, 0, sizeof(wn->rxkey));
391                         memset(wn->txkey, 0, sizeof(wn->txkey));
392                         wn->aid = 0;
393                         sendauth(wifi, wn);
394                         break;
395                 }
396         }
397         pexit("wifi in queue closed", 0);
398 }
399
400 static void
401 wifietheroq(Wifi *wifi, Block *b)
402 {
403         Etherpkt e;
404         Wifipkt *w;
405         Wnode *wn;
406         SNAP *s;
407
408         if(BLEN(b) < ETHERHDRSIZE)
409                 goto drop;
410         if((wn = wifi->bss) == nil)
411                 goto drop;
412
413         memmove(&e, b->rp, ETHERHDRSIZE);
414         b->rp += ETHERHDRSIZE;
415
416         if(wifi->status == Sblocked){
417                 /* only pass EAPOL frames when port is blocked */
418                 if((e.type[0]<<8 | e.type[1]) != 0x888e)
419                         goto drop;
420         } else if(wifi->status != Sassoc)
421                 goto drop;
422
423         b = padblock(b, WIFIHDRSIZE + SNAPHDRSIZE);
424
425         w = (Wifipkt*)b->rp;
426         w->fc[0] = 0x08;        /* data */
427         w->fc[1] = 0x01;        /* STA->AP */
428         memmove(w->a1, wn->bssid, Eaddrlen);
429         memmove(w->a2, e.s, Eaddrlen);
430         memmove(w->a3, e.d, Eaddrlen);
431
432         s = (SNAP*)(b->rp + WIFIHDRSIZE);
433         s->dsap = s->ssap = 0xAA;
434         s->control = 0x03;
435         s->orgcode[0] = 0;
436         s->orgcode[1] = 0;
437         s->orgcode[2] = 0;
438         memmove(s->type, e.type, 2);
439
440         wifitx(wifi, wn, b);
441         return;
442 drop:
443         freeb(b);
444 }
445
446 static void
447 wifoproc(void *arg)
448 {
449         Ether *ether;
450         Wifi *wifi;
451         Block *b;
452
453         wifi = arg;
454         ether = wifi->ether;
455         while((b = qbread(ether->oq, 1000000)) != nil)
456                 wifietheroq(wifi, b);
457         pexit("ether out queue closed", 0);
458 }
459
460 Wifi*
461 wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*))
462 {
463         char name[32];
464         Wifi *wifi;
465
466         wifi = malloc(sizeof(Wifi));
467         wifi->ether = ether;
468         wifi->iq = qopen(8*1024, 0, 0, 0);
469         wifi->transmit = transmit;
470         wifi->status = Snone;
471
472         snprint(name, sizeof(name), "#l%dwifi", ether->ctlrno);
473         kproc(name, wifiproc, wifi);
474         snprint(name, sizeof(name), "#l%dwifo", ether->ctlrno);
475         kproc(name, wifoproc, wifi);
476
477         return wifi;
478 }
479
480 static int
481 hextob(char *s, char **sp, uchar *b, int n)
482 {
483         int r;
484
485         n <<= 1;
486         for(r = 0; r < n && *s; s++){
487                 *b <<= 4;
488                 if(*s >= '0' && *s <= '9')
489                         *b |= (*s - '0');
490                 else if(*s >= 'a' && *s <= 'f')
491                         *b |= 10+(*s - 'a');
492                 else if(*s >= 'A' && *s <= 'F')
493                         *b |= 10+(*s - 'A');
494                 else break;
495                 if((++r & 1) == 0)
496                         b++;
497         }
498         if(sp != nil)
499                 *sp = s;
500         return r >> 1;
501 }
502
503 static char *ciphers[] = {
504         [0]     "clear",
505         [TKIP]  "tkip",
506         [CCMP]  "ccmp",
507 };
508
509 static int
510 parsekey(Wkey *k, char *s)
511 {
512         char buf[256], *p;
513         int i;
514
515         strncpy(buf, s, sizeof(buf)-1);
516         buf[sizeof(buf)-1] = 0;
517         if((p = strchr(buf, ':')) != nil)
518                 *p++ = 0;
519         else
520                 p = buf;
521         for(i=0; i<nelem(ciphers); i++){
522                 if(ciphers[i] == nil)
523                         continue;
524                 if(strcmp(ciphers[i], buf) == 0)
525                         break;
526         }
527         if(i >= nelem(ciphers))
528                 return -1;
529         memset(k, 0, sizeof(Wkey));
530         k->len = hextob(p, &p, k->key, sizeof(k->key));
531         if(*p == '@')
532                 k->tsc = strtoull(++p, nil, 16);
533         k->cipher = i;
534         return 0;
535 }
536
537 enum {
538         CMessid,
539         CMauth,
540         CMunblock,
541
542         CMrxkey0,
543         CMrxkey1,
544         CMrxkey2,
545         CMrxkey3,
546         CMrxkey4,
547         CMtxkey0,
548 };
549
550 static Cmdtab wifictlmsg[] =
551 {
552         CMessid,        "essid",        0,
553         CMauth,         "auth",         0,
554
555         CMrxkey0,       "rxkey0",       0,      /* group keys */
556         CMrxkey1,       "rxkey1",       0,
557         CMrxkey2,       "rxkey2",       0,
558         CMrxkey3,       "rxkey3",       0,
559
560         CMrxkey4,       "rxkey",        0,      /* peerwise keys */
561         CMtxkey0,       "txkey",        0,
562
563         CMtxkey0,       "txkey0",       0,
564 };
565
566 long
567 wifictl(Wifi *wifi, void *buf, long n)
568 {
569         Cmdbuf *cb;
570         Cmdtab *ct;
571         Wnode *wn;
572         Wkey *k;
573
574         cb = nil;
575         if(waserror()){
576                 free(cb);
577                 nexterror();
578         }
579         wn = wifi->bss;
580         cb = parsecmd(buf, n);
581         ct = lookupcmd(cb, wifictlmsg, nelem(wifictlmsg));
582         if(ct->index != CMessid){
583                 if(ct->index >= CMrxkey0 && cb->nf > 1){
584                         uchar addr[Eaddrlen];
585
586                         if(parseether(addr, cb->f[1]) == 0){
587                                 cb->f++;
588                                 cb->nf--;
589                                 wn = nodelookup(wifi, addr, 0);
590                         }
591                 }
592                 if(wn == nil)
593                         error("missing node");
594         }
595         switch(ct->index){
596         case CMessid:
597                 if(cb->f[1] == nil){
598                         wifi->essid[0] = 0;
599                         wifi->bss = nil;
600                         wifi->status = Snone;
601                 } else {
602                         strncpy(wifi->essid, cb->f[1], Essidlen);
603                         for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++)
604                                 if(strcmp(wifi->essid, wn->ssid) == 0){
605                                         wifi->bss = wn;
606                                         wifi->status = Sconn;
607                                         sendauth(wifi, wn);
608                                         break;
609                                 }
610                 }
611                 break;
612         case CMauth:
613                 wifi->status = Sauth;
614                 memset(wn->rxkey, 0, sizeof(wn->rxkey));
615                 memset(wn->txkey, 0, sizeof(wn->txkey));
616                 if(cb->f[1] == nil)
617                         wn->rsnelen = 0;
618                 else
619                         wn->rsnelen = hextob(cb->f[1], nil, wn->rsne, sizeof(wn->rsne));
620                 sendassoc(wifi, wn);
621                 break;
622         case CMrxkey0: case CMrxkey1: case CMrxkey2: case CMrxkey3: case CMrxkey4:
623         case CMtxkey0:
624                 if(ct->index < CMtxkey0)
625                         k = &wn->rxkey[ct->index - CMrxkey0];
626                 else
627                         k = &wn->txkey[ct->index - CMtxkey0];
628                 if(cb->f[1] == nil || parsekey(k, cb->f[1]) != 0)
629                         error("bad key");
630                 if(ct->index >= CMtxkey0 && wifi->status == Sblocked && wifi->bss == wn)
631                         wifi->status = Sassoc;
632                 break;
633         }
634         poperror();
635         free(cb);
636         return n;
637 }
638
639 long
640 wifistat(Wifi *wifi, void *buf, long n, ulong off)
641 {
642         static uchar zeros[Eaddrlen];
643         char *s, *p, *e;
644         Wnode *wn;
645         long now;
646
647         p = s = smalloc(4096);
648         e = s + 4096;
649
650         p = seprint(p, e, "status: %s\n", wifi->status);
651         p = seprint(p, e, "essid: %s\n", wifi->essid);
652         wn = wifi->bss;
653         p = seprint(p, e, "bssid: %E\n", wn != nil ? wn->bssid : zeros);
654
655         now = MACHP(0)->ticks;
656         for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){
657                 if(wn->lastseen == 0)
658                         continue;
659                 p = seprint(p, e, "node: %E %.4x %-11ld %.2d %s\n",
660                         wn->bssid, wn->cap, TK2MS(now - wn->lastseen), wn->channel, wn->ssid);
661         }
662         n = readstr(off, buf, n, s);
663         free(s);
664         return n;
665 }
666
667 static void tkipencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
668 static int tkipdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
669 static void ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
670 static int ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
671
672 static Block*
673 wifiencrypt(Wifi *, Wnode *wn, Block *b)
674 {
675         uvlong tsc;
676         int n, kid;
677         Wifipkt *w;
678         Wkey *k;
679
680         kid = 0;
681         k = &wn->txkey[kid];
682         if(k->cipher == 0)
683                 return b;
684
685         n = wifihdrlen((Wifipkt*)b->rp);
686
687         b = padblock(b, 8);
688         b = padblock(b, -(8+4));
689
690         w = (Wifipkt*)b->rp;
691         memmove(w, b->rp+8, n);
692         b->rp += n;
693
694         tsc = ++k->tsc;
695
696         switch(k->cipher){
697         case TKIP:
698                 b->rp[0] = tsc>>8;
699                 b->rp[1] = (b->rp[0] | 0x20) & 0x7f;
700                 b->rp[2] = tsc;
701                 b->rp[3] = kid<<6 | 0x20;
702                 b->rp[4] = tsc>>16;
703                 b->rp[5] = tsc>>24;
704                 b->rp[6] = tsc>>32;
705                 b->rp[7] = tsc>>40;
706                 b->rp += 8;
707                 if(k->len != 32)
708                         goto drop;
709                 tkipencrypt(k, w, b, tsc);
710                 break;
711         case CCMP:
712                 b->rp[0] = tsc;
713                 b->rp[1] = tsc>>8;
714                 b->rp[2] = 0;
715                 b->rp[3] = kid<<6 | 0x20;
716                 b->rp[4] = tsc>>16;
717                 b->rp[5] = tsc>>24;
718                 b->rp[6] = tsc>>32;
719                 b->rp[7] = tsc>>40;
720                 b->rp += 8;
721                 if(k->len != 16)
722                         goto drop;
723                 ccmpencrypt(k, w, b, tsc);
724                 break;
725         default:
726         drop:
727                 free(b);
728                 return nil;
729         }
730
731         b->rp = (uchar*)w;
732         w->fc[1] |= 0x40;
733         return b;
734 }
735
736 static Block*
737 wifidecrypt(Wifi *, Wnode *wn, Block *b)
738 {
739         uvlong tsc;
740         int n, kid;
741         Wifipkt *w;
742         Wkey *k;
743
744         w = (Wifipkt*)b->rp;
745         if(BLEN(b) < WIFIHDRSIZE)
746                 goto drop;
747
748         n = wifihdrlen(w);
749         b->rp += n;
750         if(BLEN(b) < 8+8)
751                 goto drop;
752
753         kid = b->rp[3]>>6;
754         if((b->rp[3] & 0x20) == 0)
755                 goto drop;
756         if((dstaddr(w)[0] & 1) == 0)
757                 kid = 4;        /* use peerwise key for non-unicast */
758
759         k = &wn->rxkey[kid];
760         switch(k->cipher){
761         case TKIP:
762                 tsc =   (uvlong)b->rp[7]<<40 |
763                         (uvlong)b->rp[6]<<32 |
764                         (uvlong)b->rp[5]<<24 |
765                         (uvlong)b->rp[4]<<16 |
766                         (uvlong)b->rp[0]<<8 |
767                         (uvlong)b->rp[2];
768                 b->rp += 8;
769                 if(tsc <= k->tsc || k->len != 32)
770                         goto drop;
771                 if(tkipdecrypt(k, w, b, tsc) != 0)
772                         goto drop;
773                 break;
774         case CCMP:
775                 tsc =   (uvlong)b->rp[7]<<40 |
776                         (uvlong)b->rp[6]<<32 |
777                         (uvlong)b->rp[5]<<24 |
778                         (uvlong)b->rp[4]<<16 |
779                         (uvlong)b->rp[1]<<8 |
780                         (uvlong)b->rp[0];
781                 b->rp += 8;
782                 if(tsc <= k->tsc || k->len != 16)
783                         goto drop;
784                 if(ccmpdecrypt(k, w, b, tsc) != 0)
785                         goto drop;
786                 break;
787         default:
788         drop:
789                 freeb(b);
790                 return nil;
791         }
792
793         k->tsc = tsc;
794         b->rp -= n;
795         memmove(b->rp, w, n);
796         w = (Wifipkt*)b->rp;
797         w->fc[1] &= ~0x40;
798         return b;
799 }
800
801 static u16int Sbox[256] = {
802         0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
803         0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
804         0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
805         0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
806         0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
807         0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
808         0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
809         0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
810         0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
811         0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
812         0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
813         0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
814         0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
815         0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
816         0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
817         0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
818         0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
819         0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
820         0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
821         0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
822         0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
823         0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
824         0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
825         0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
826         0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
827         0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
828         0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
829         0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
830         0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
831         0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
832         0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
833         0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A
834 };
835
836 static void
837 tkipk2tk(uchar key[16], u16int tk[8])
838 {
839         tk[0] = (u16int)key[1]<<8 | key[0];
840         tk[1] = (u16int)key[3]<<8 | key[2];
841         tk[2] = (u16int)key[5]<<8 | key[4];
842         tk[3] = (u16int)key[7]<<8 | key[6];
843         tk[4] = (u16int)key[9]<<8 | key[8];
844         tk[5] = (u16int)key[11]<<8 | key[10];
845         tk[6] = (u16int)key[13]<<8 | key[12];
846         tk[7] = (u16int)key[15]<<8 | key[14];
847 }
848
849 static void
850 tkipphase1(u32int tscu, uchar ta[Eaddrlen], u16int tk[8], u16int p1k[5])
851 {
852         u16int *k, i, x0, x1, x2;
853
854         p1k[0] = tscu;
855         p1k[1] = tscu>>16;
856         p1k[2] = (u16int)ta[1]<<8 | ta[0];
857         p1k[3] = (u16int)ta[3]<<8 | ta[2];
858         p1k[4] = (u16int)ta[5]<<8 | ta[4];
859
860         for(i=0; i<8; i++){
861                 k = &tk[i & 1];
862
863                 x0 = p1k[4] ^ k[0];
864                 x1 = Sbox[x0 >> 8];
865                 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
866                 p1k[0] += x2;
867                 x0 = p1k[0] ^ k[2];
868                 x1 = Sbox[x0 >> 8];
869                 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
870                 p1k[1] += x2;
871                 x0 = p1k[1] ^ k[4];
872                 x1 = Sbox[x0 >> 8];
873                 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
874                 p1k[2] += x2;
875                 x0 = p1k[2] ^ k[6];
876                 x1 = Sbox[x0 >> 8];
877                 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
878                 p1k[3] += x2;
879                 x0 = p1k[3] ^ k[0];
880                 x1 = Sbox[x0 >> 8];
881                 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
882                 p1k[4] += x2;
883
884                 p1k[4] += i;
885         }
886 }
887
888 static void
889 tkipphase2(u16int tscl, u16int p1k[5], u16int tk[8], uchar rc4key[16])
890 {
891         u16int ppk[6], x0, x1, x2;
892
893         ppk[0] = p1k[0];
894         ppk[1] = p1k[1];
895         ppk[2] = p1k[2];
896         ppk[3] = p1k[3];
897         ppk[4] = p1k[4];
898         ppk[5] = p1k[4] + tscl;
899
900         x0 = ppk[5] ^ tk[0];
901         x1 = Sbox[x0 >> 8];
902         x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
903         ppk[0] += x2;
904         x0 = ppk[0] ^ tk[1];
905         x1 = Sbox[x0 >> 8];
906         x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
907         ppk[1] += x2;
908         x0 = ppk[1] ^ tk[2];
909         x1 = Sbox[x0 >> 8];
910         x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
911         ppk[2] += x2;
912         x0 = ppk[2] ^ tk[3];
913         x1 = Sbox[x0 >> 8];
914         x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
915         ppk[3] += x2;
916         x0 = ppk[3] ^ tk[4];
917         x1 = Sbox[x0 >> 8];
918         x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
919         ppk[4] += x2;
920         x0 = ppk[4] ^ tk[5];
921         x1 = Sbox[x0 >> 8];
922         x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
923         ppk[5] += x2;
924
925         x2 = ppk[5] ^ tk[6];
926         ppk[0] += (x2 >> 1) | (x2 << 15);
927         x2 = ppk[0] ^ tk[7];
928         ppk[1] += (x2 >> 1) | (x2 << 15);
929
930         x2 = ppk[1];
931         ppk[2] += (x2 >> 1) | (x2 << 15);
932         x2 = ppk[2];
933         ppk[3] += (x2 >> 1) | (x2 << 15);
934         x2 = ppk[3];
935         ppk[4] += (x2 >> 1) | (x2 << 15);
936         x2 = ppk[4];
937         ppk[5] += (x2 >> 1) | (x2 << 15);
938
939         rc4key[0] = tscl >> 8;
940         rc4key[1] = (rc4key[0] | 0x20) & 0x7F;
941         rc4key[2] = tscl;
942         rc4key[3] = (ppk[5] ^ tk[0]) >> 1;
943         rc4key[4]  = ppk[0];
944         rc4key[5]  = ppk[0] >> 8;
945         rc4key[6]  = ppk[1];
946         rc4key[7]  = ppk[1] >> 8;
947         rc4key[8]  = ppk[2];
948         rc4key[9]  = ppk[2] >> 8;
949         rc4key[10] = ppk[3];
950         rc4key[11] = ppk[3] >> 8;
951         rc4key[12] = ppk[4];
952         rc4key[13] = ppk[4] >> 8;
953         rc4key[14] = ppk[5];
954         rc4key[15] = ppk[5] >> 8;
955 }
956
957 typedef struct MICstate MICstate;
958 struct MICstate
959 {
960         u32int  l;
961         u32int  r;
962         u32int  m;
963         u32int  n;
964 };
965
966 static void
967 micsetup(MICstate *s, uchar key[8])
968 {
969         s->l =  (u32int)key[0] |
970                 (u32int)key[1]<<8 |
971                 (u32int)key[2]<<16 |
972                 (u32int)key[3]<<24;
973         s->r =  (u32int)key[4] |
974                 (u32int)key[5]<<8 |
975                 (u32int)key[6]<<16 |
976                 (u32int)key[7]<<24;
977         s->m = 0;
978         s->n = 0;
979 }
980
981 static void
982 micupdate(MICstate *s, uchar *data, ulong len)
983 {
984         u32int l, r, m, n, e;
985
986         l = s->l;
987         r = s->r;
988         m = s->m;
989         n = s->n;
990         e = n + len;
991         while(n != e){
992                 m >>= 8;
993                 m |= (u32int)*data++ << 24;
994                 if(++n & 3)
995                         continue;
996                 l ^= m;
997                 r ^= (l << 17) | (l >> 15);
998                 l += r;
999                 r ^= ((l & 0x00FF00FFUL)<<8) | ((l & 0xFF00FF00UL)>>8);
1000                 l += r;
1001                 r ^= (l << 3) | (l >> 29);
1002                 l += r;
1003                 r ^= (l >> 2) | (l << 30);
1004                 l += r;
1005         }
1006         s->l = l;
1007         s->r = r;
1008         s->m = m;
1009         s->n = n;
1010 }
1011
1012 static void
1013 micfinish(MICstate *s, uchar mic[8])
1014 {
1015         static uchar pad[8] = { 0x5a, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, };
1016
1017         micupdate(s, pad, sizeof(pad));
1018
1019         mic[0] = s->l;
1020         mic[1] = s->l>>8;
1021         mic[2] = s->l>>16;
1022         mic[3] = s->l>>24;
1023         mic[4] = s->r;
1024         mic[5] = s->r>>8;
1025         mic[6] = s->r>>16;
1026         mic[7] = s->r>>24;
1027 }
1028
1029 static uchar pad4[4] = { 0x00, 0x00, 0x00, 0x00, };
1030
1031 static void
1032 tkipencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1033 {
1034         u16int tk[8], p1k[5];
1035         uchar seed[16];
1036         RC4state rs;
1037         MICstate ms;
1038         ulong crc;
1039
1040         micsetup(&ms, k->key+24);
1041         micupdate(&ms, dstaddr(w), Eaddrlen);
1042         micupdate(&ms, srcaddr(w), Eaddrlen);
1043         micupdate(&ms, pad4, 4);
1044         micupdate(&ms, b->rp, BLEN(b));
1045         micfinish(&ms, b->wp);
1046         b->wp += 8;
1047
1048         crc = ethercrc(b->rp, BLEN(b));
1049         crc = ~crc;
1050         b->wp[0] = crc;
1051         b->wp[1] = crc>>8;
1052         b->wp[2] = crc>>16;
1053         b->wp[3] = crc>>24;
1054         b->wp += 4;
1055
1056         tkipk2tk(k->key, tk);
1057         tkipphase1(tsc >> 16, w->a2, tk, p1k);
1058         tkipphase2(tsc & 0xFFFF, p1k, tk, seed);
1059         setupRC4state(&rs, seed, sizeof(seed));
1060         rc4(&rs, b->rp, BLEN(b));
1061 }
1062
1063 static int
1064 tkipdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1065 {
1066         uchar seed[16], mic[8];
1067         u16int tk[8], p1k[5];
1068         RC4state rs;
1069         MICstate ms;
1070         ulong crc;
1071
1072         if(BLEN(b) < 8+4)
1073                 return -1;
1074
1075         tkipk2tk(k->key, tk);
1076         tkipphase1(tsc >> 16, w->a2, tk, p1k);
1077         tkipphase2(tsc & 0xFFFF, p1k, tk, seed);
1078         setupRC4state(&rs, seed, sizeof(seed));
1079         rc4(&rs, b->rp, BLEN(b));
1080
1081         b->wp -= 4;
1082         crc =   (ulong)b->wp[0] |
1083                 (ulong)b->wp[1]<<8 |
1084                 (ulong)b->wp[2]<<16 |
1085                 (ulong)b->wp[3]<<24;
1086         crc = ~crc;
1087         if(ethercrc(b->rp, BLEN(b)) != crc)
1088                 return -1;
1089
1090         b->wp -= 8;
1091         micsetup(&ms, k->key+16);
1092         micupdate(&ms, dstaddr(w), Eaddrlen);
1093         micupdate(&ms, srcaddr(w), Eaddrlen);
1094         micupdate(&ms, pad4, 4);
1095         micupdate(&ms, b->rp, BLEN(b));
1096         micfinish(&ms, mic);
1097
1098         return memcmp(b->wp, mic, 8) != 0;
1099 }
1100
1101 static uchar*
1102 putbe(uchar *p, int L, uint v)
1103 {
1104         while(--L >= 0)
1105                 *p++ = (v >> L*8) & 0xFF;
1106         return p;
1107 }
1108
1109 static void
1110 xblock(int L, int M, uchar *N, uchar *a, int la, int lm, uchar t[16], AESstate *s)
1111 {
1112         uchar l[8], *p, *x, *e;
1113
1114         assert(M >= 4 && M <= 16);
1115         assert(L >= 2 && L <= 4);
1116
1117         t[0] = ((la > 0)<<6) | ((M-2)/2)<<3 | (L-1);    /* flags */
1118         memmove(&t[1], N, 15-L);
1119         putbe(&t[16-L], L, lm);
1120         aes_encrypt(s->ekey, s->rounds, t, t);
1121         
1122         if(la > 0){
1123                 assert(la < 0xFF00);
1124                 for(p = l, e = putbe(l, 2, la), x = t; p < e; x++, p++)
1125                         *x ^= *p;
1126                 for(e = a + la; a < e; x = t){
1127                         for(; a < e && x < &t[16]; x++, a++)
1128                                 *x ^= *a;
1129                         aes_encrypt(s->ekey, s->rounds, t, t);
1130                 }
1131         }
1132 }
1133
1134 static uchar*
1135 sblock(int L, uchar *N, uint i, uchar b[16], AESstate *s)
1136 {
1137         b[0] = L-1;     /* flags */
1138         memmove(&b[1], N, 15-L);
1139         putbe(&b[16-L], L, i);
1140         aes_encrypt(s->ekey, s->rounds, b, b);
1141         return b;
1142 };
1143
1144 static void
1145 aesCCMencrypt(int L, int M, uchar *N /* N[15-L] */,
1146         uchar *a /* a[la] */, int la,
1147         uchar *m /* m[lm+M] */, int lm,
1148         AESstate *s)
1149 {
1150         uchar t[16], b[16], *p, *x;
1151         uint i;
1152
1153         xblock(L, M, N, a, la, lm, t, s);
1154
1155         for(i = 1; lm >= 16; i++, m += 16, lm -= 16){
1156                 sblock(L, N, i, b, s);
1157
1158                 *((u32int*)&t[0]) ^= *((u32int*)&m[0]);
1159                 *((u32int*)&m[0]) ^= *((u32int*)&b[0]);
1160                 *((u32int*)&t[4]) ^= *((u32int*)&m[4]);
1161                 *((u32int*)&m[4]) ^= *((u32int*)&b[4]);
1162                 *((u32int*)&t[8]) ^= *((u32int*)&m[8]);
1163                 *((u32int*)&m[8]) ^= *((u32int*)&b[8]);
1164                 *((u32int*)&t[12]) ^= *((u32int*)&m[12]);
1165                 *((u32int*)&m[12]) ^= *((u32int*)&b[12]);
1166
1167                 aes_encrypt(s->ekey, s->rounds, t, t);
1168         }
1169         if(lm > 0){
1170                 for(p = sblock(L, N, i, b, s), x = t; p < &b[lm]; x++, m++, p++){
1171                         *x ^= *m;
1172                         *m ^= *p;
1173                 }
1174                 aes_encrypt(s->ekey, s->rounds, t, t);
1175         }
1176
1177         for(p = sblock(L, N, 0, b, s), x = t; p < &b[M]; x++, p++)
1178                 *x ^= *p;
1179
1180         memmove(m, t, M);
1181 }
1182
1183 static int
1184 aesCCMdecrypt(int L, int M, uchar *N /* N[15-L] */,
1185         uchar *a /* a[la] */, int la,
1186         uchar *m /* m[lm+M] */, int lm,
1187         AESstate *s)
1188 {
1189         uchar t[16], b[16], *p, *x;
1190         uint i;
1191
1192         xblock(L, M, N, a, la, lm, t, s);
1193
1194         for(i = 1; lm >= 16; i++, m += 16, lm -= 16){
1195                 sblock(L, N, i, b, s);
1196
1197                 *((u32int*)&m[0]) ^= *((u32int*)&b[0]);
1198                 *((u32int*)&t[0]) ^= *((u32int*)&m[0]);
1199                 *((u32int*)&m[4]) ^= *((u32int*)&b[4]);
1200                 *((u32int*)&t[4]) ^= *((u32int*)&m[4]);
1201                 *((u32int*)&m[8]) ^= *((u32int*)&b[8]);
1202                 *((u32int*)&t[8]) ^= *((u32int*)&m[8]);
1203                 *((u32int*)&m[12]) ^= *((u32int*)&b[12]);
1204                 *((u32int*)&t[12]) ^= *((u32int*)&m[12]);
1205
1206                 aes_encrypt(s->ekey, s->rounds, t, t);
1207         }
1208         if(lm > 0){
1209                 for(p = sblock(L, N, i, b, s), x = t; p < &b[lm]; x++, m++, p++){
1210                         *m ^= *p;
1211                         *x ^= *m;
1212                 }
1213                 aes_encrypt(s->ekey, s->rounds, t, t);
1214         }
1215
1216         for(p = sblock(L, N, 0, b, s), x = t; p < &b[M]; x++, p++)
1217                 *x ^= *p;
1218
1219         return memcmp(m, t, M) != 0;
1220 }
1221
1222 static int
1223 setupCCMP(Wkey *k, Wifipkt *w, uvlong tsc, uchar nonce[13], uchar auth[32], AESstate *as)
1224 {
1225         uchar *p;
1226
1227         setupAESstate(as, k->key, k->len, nil);
1228
1229         nonce[0] = ((w->fc[0] & 0x0c) == 0x00) << 4;
1230         memmove(&nonce[1], w->a2, Eaddrlen);
1231         nonce[7]  = tsc >> 40;
1232         nonce[8]  = tsc >> 32;
1233         nonce[9]  = tsc >> 24;
1234         nonce[10] = tsc >> 16;
1235         nonce[11] = tsc >> 8;
1236         nonce[12] = tsc;
1237
1238         p = auth;
1239         *p++ = (w->fc[0] & (((w->fc[0] & 0x0c) == 0x08) ? 0x0f : 0xff));
1240         *p++ = (w->fc[1] & ~0x38) | 0x40;
1241         memmove(p, w->a1, Eaddrlen); p += Eaddrlen;
1242         memmove(p, w->a2, Eaddrlen); p += Eaddrlen;
1243         memmove(p, w->a3, Eaddrlen); p += Eaddrlen;
1244         *p++ = w->seq[0] & 0x0f;
1245         *p++ = 0;
1246
1247         return p - auth;
1248 }
1249
1250 static void
1251 ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1252 {
1253         uchar auth[32], nonce[13];
1254         AESstate as;
1255
1256         aesCCMencrypt(2, 8, nonce, auth,
1257                 setupCCMP(k, w, tsc, nonce, auth, &as),
1258                 b->rp, BLEN(b), &as);
1259         b->wp += 8;
1260 }
1261
1262 static int
1263 ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1264 {
1265         uchar auth[32], nonce[13];
1266         AESstate as;
1267
1268         if(BLEN(b) < 8)
1269                 return -1;
1270
1271         b->wp -= 8;
1272         return aesCCMdecrypt(2, 8, nonce, auth,
1273                 setupCCMP(k, w, tsc, nonce, auth, &as),
1274                 b->rp, BLEN(b), &as);
1275 }