2 #include "../port/lib.h"
8 #include "../port/error.h"
9 #include "../port/netif.h"
16 typedef struct SNAP SNAP;
27 WIFIHDRSIZE = 2+2+3*6+2,
31 static char Sconn[] = "connecting";
32 static char Sauth[] = "authenticated";
33 static char Sneedauth[] = "need authentication";
34 static char Sunauth[] = "unauthenticated";
36 static char Sassoc[] = "associated";
37 static char Sunassoc[] = "unassociated";
38 static char Sblocked[] = "blocked"; /* no keys negotiated. only pass EAPOL frames */
40 static uchar basicrates[] = {
41 0x80 | 2, /* 1.0 Mb/s */
42 0x80 | 4, /* 2.0 Mb/s */
43 0x80 | 11, /* 5.5 Mb/s */
44 0x80 | 22, /* 11.0 Mb/s */
49 static Block* wifidecrypt(Wifi *, Wnode *, Block *);
50 static Block* wifiencrypt(Wifi *, Wnode *, Block *);
55 if((w->fc[1] & 0x02) == 0)
57 if((w->fc[1] & 0x01) == 0)
64 if((w->fc[1] & 0x01) != 0)
70 wifihdrlen(Wifipkt *w)
75 if((w->fc[0] & 0x0c) == 0x08)
76 if((w->fc[0] & 0xf0) == 0x80){ /* QOS */
81 if((w->fc[1] & 3) == 0x03)
87 wifiiq(Wifi *wifi, Block *b)
94 if(BLEN(b) < WIFIHDRSIZE)
97 hdrlen = wifihdrlen(w);
105 switch(w->fc[0] & 0x0c){
106 case 0x00: /* management */
107 if((w->fc[1] & 3) != 0x00) /* STA->STA */
111 case 0x04: /* control */
113 case 0x08: /* data */
115 switch(w->fc[0] & 0xf0){
122 if(BLEN(b) < SNAPHDRSIZE)
124 memmove(&s, b->rp, SNAPHDRSIZE);
125 if(s.dsap != 0xAA || s.ssap != 0xAA || s.control != 3)
127 if(s.orgcode[0] != 0 || s.orgcode[1] != 0 || s.orgcode[2] != 0)
129 b->rp += SNAPHDRSIZE-ETHERHDRSIZE;
131 e = (Etherpkt*)b->rp;
132 memmove(e->d, dstaddr(&h), Eaddrlen);
133 memmove(e->s, srcaddr(&h), Eaddrlen);
134 memmove(e->type, s.type, 2);
135 etheriq(wifi->ether, b, 1);
143 wifitx(Wifi *wifi, Wnode *wn, Block *b)
148 wn->lastsend = MACHP(0)->ticks;
150 seq = incref(&wifi->txseq);
159 if((w->fc[0] & 0x0c) != 0x00)
160 b = wifiencrypt(wifi, wn, b);
163 (*wifi->transmit)(wifi, wn, b);
167 nodelookup(Wifi *wifi, uchar *bssid, int new)
171 if(memcmp(bssid, wifi->ether->bcast, Eaddrlen) == 0)
173 if((wn = wifi->bss) != nil){
174 if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){
175 wn->lastseen = MACHP(0)->ticks;
179 if((nn = wifi->node) == wn)
181 for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){
184 if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){
185 wn->lastseen = MACHP(0)->ticks;
188 if((long)(wn->lastseen - nn->lastseen) < 0)
193 memset(nn, 0, sizeof(Wnode));
194 memmove(nn->bssid, bssid, Eaddrlen);
195 nn->lastseen = MACHP(0)->ticks;
200 putrates(uchar *p, uchar *rates)
204 n = m = strlen((char*)rates);
207 /* supported rates */
210 memmove(p, rates, n);
213 /* extended supported rates */
216 memmove(p, rates, m);
223 wifiprobe(Wifi *wifi, Wnode *wn)
230 n = strlen(wifi->essid);
232 /* no specific essid, just tell driver to tune channel */
233 (*wifi->transmit)(wifi, wn, nil);
237 b = allocb(WIFIHDRSIZE + 512);
239 w->fc[0] = 0x40; /* probe request */
240 w->fc[1] = 0x00; /* STA->STA */
241 memmove(w->a1, wifi->ether->bcast, Eaddrlen); /* ??? */
242 memmove(w->a2, wifi->ether->ea, Eaddrlen);
243 memmove(w->a3, wifi->ether->bcast, Eaddrlen);
244 b->wp += WIFIHDRSIZE;
249 memmove(p, wifi->essid, n);
252 p = putrates(p, wifi->rates);
254 *p++ = 3; /* ds parameter set */
263 sendauth(Wifi *wifi, Wnode *bss)
269 b = allocb(WIFIHDRSIZE + 3*2);
271 w->fc[0] = 0xB0; /* auth request */
272 w->fc[1] = 0x00; /* STA->STA */
273 memmove(w->a1, bss->bssid, Eaddrlen); /* ??? */
274 memmove(w->a2, wifi->ether->ea, Eaddrlen);
275 memmove(w->a3, bss->bssid, Eaddrlen);
276 b->wp += WIFIHDRSIZE;
282 *p++ = 0; /* status */
288 wifitx(wifi, bss, b);
292 sendassoc(Wifi *wifi, Wnode *bss)
299 b = allocb(WIFIHDRSIZE + 512);
301 w->fc[0] = 0x00; /* assoc request */
302 w->fc[1] = 0x00; /* STA->STA */
303 memmove(w->a1, bss->bssid, Eaddrlen); /* ??? */
304 memmove(w->a2, wifi->ether->ea, Eaddrlen);
305 memmove(w->a3, bss->bssid, Eaddrlen);
306 b->wp += WIFIHDRSIZE;
308 *p++ = 1; /* capinfo */
310 *p++ = 16; /* interval */
313 n = strlen(bss->ssid);
316 memmove(p, bss->ssid, n);
319 p = putrates(p, wifi->rates);
323 memmove(p, bss->rsne, n);
328 wifitx(wifi, bss, b);
332 setstatus(Wifi *wifi, Wnode *wn, char *new)
338 if(wifi->debug && new != old)
339 print("#l%d: status %E: %s -> %s (from pc=%#p)\n",
347 recvassoc(Wifi *wifi, Wnode *wn, uchar *d, int len)
359 wn->aid = d[0] | d[1]<<8;
361 setstatus(wifi, wn, Sblocked);
363 setstatus(wifi, wn, Sassoc);
367 setstatus(wifi, wn, Sunassoc);
372 recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len)
374 static uchar wpa1oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
381 d += 8; /* timestamp */
382 wn->ival = d[0] | d[1]<<8;
384 wn->cap = d[0] | d[1]<<8;
387 memset(m, 0, sizeof(m));
388 for(e = d + len; d+2 <= e; d = x){
393 /* skip double entries */
394 if(m[t/8] & 1<<(t%8))
401 while(len < Essidlen && d+len < x && d[len] != 0)
405 if(len != strlen(wn->ssid) || strncmp(wn->ssid, (char*)d, len) != 0){
406 strncpy(wn->ssid, (char*)d, len);
410 case 1: /* supported rates */
411 case 50: /* extended rates */
412 if(wn->minrate != nil || wn->maxrate != nil || wifi->rates == nil)
413 break; /* already set */
416 for(p = wifi->rates; *p != 0; p++){
417 if((*p & 0x7f) == t){
418 if(wn->minrate == nil || t < (*wn->minrate & 0x7f))
420 if(wn->maxrate == nil || t > (*wn->maxrate & 0x7f))
427 case 3: /* DSPARAMS */
431 case 221: /* vendor specific */
433 if(len < sizeof(wpa1oui) || memcmp(d, wpa1oui, sizeof(wpa1oui)) != 0)
436 case 48: /* RSN information */
438 memmove(wn->brsne, &d[-2], len);
446 wifideauth(Wifi *wifi, Wnode *wn)
452 /* deassociate node, clear keys */
453 setstatus(wifi, wn, Sunauth);
454 memset(wn->rxkey, 0, sizeof(wn->rxkey));
455 memset(wn->txkey, 0, sizeof(wn->txkey));
459 /* notify driver about node aid association */
460 (*wifi->transmit)(wifi, wn, nil);
462 /* notify aux/wpa with a zero length write that we got deassociated from the ap */
464 for(i=0; i<ether->nfile; i++){
466 if(f == nil || f->in == nil || f->inuse == 0 || f->type != 0x888e)
473 /* check if a node qualifies as our bss matching bssid and essid */
475 goodbss(Wifi *wifi, Wnode *wn)
477 if(memcmp(wifi->bssid, wifi->ether->bcast, Eaddrlen) != 0){
478 if(memcmp(wifi->bssid, wn->bssid, Eaddrlen) != 0)
479 return 0; /* bssid doesnt match */
480 } else if(wifi->essid[0] == 0)
481 return 0; /* both bssid and essid unspecified */
482 if(wifi->essid[0] != 0 && strcmp(wifi->essid, wn->ssid) != 0)
483 return 0; /* essid doesnt match */
505 if((b = qbread(wifi->iq, 100000)) == nil)
510 if((wn = nodelookup(wifi, w->a2, 0)) == nil)
512 if((b = wifidecrypt(wifi, wn, b)) != nil){
522 if((w->fc[0] & 0x0c) != 0x00)
525 switch(w->fc[0] & 0xf0){
526 case 0x50: /* probe response */
528 print("#l%d: got probe from %E\n", wifi->ether->ctlrno, w->a3);
530 case 0x80: /* beacon */
531 if((wn = nodelookup(wifi, w->a3, 1)) == nil)
533 b->rp += wifihdrlen(w);
534 recvbeacon(wifi, wn, b->rp, BLEN(b));
537 && TK2MS(MACHP(0)->ticks - wn->lastsend) > 1000
538 && goodbss(wifi, wn)){
539 setstatus(wifi, wn, Sconn);
545 if(memcmp(w->a1, wifi->ether->ea, Eaddrlen))
547 if((wn = nodelookup(wifi, w->a3, 0)) == nil)
549 switch(w->fc[0] & 0xf0){
550 case 0x10: /* assoc response */
551 case 0x30: /* reassoc response */
552 b->rp += wifihdrlen(w);
553 recvassoc(wifi, wn, b->rp, BLEN(b));
554 /* notify driver about node aid association */
556 (*wifi->transmit)(wifi, wn, nil);
558 case 0xb0: /* auth */
560 print("#l%d: got auth from %E\n", wifi->ether->ctlrno, wn->bssid);
561 if(wn->brsnelen > 0 && wn->rsnelen == 0)
562 setstatus(wifi, wn, Sneedauth);
564 setstatus(wifi, wn, Sauth);
565 if(wifi->bss == nil && goodbss(wifi, wn)){
567 if(wn->status == Sauth)
571 case 0xc0: /* deauth */
573 print("#l%d: got deauth from %E\n", wifi->ether->ctlrno, wn->bssid);
574 wifideauth(wifi, wn);
578 pexit("wifi in queue closed", 1);
582 wifietheroq(Wifi *wifi, Block *b)
590 if(BLEN(b) < ETHERHDRSIZE)
592 if((wn = wifi->bss) == nil)
595 memmove(&e, b->rp, ETHERHDRSIZE);
596 b->rp += ETHERHDRSIZE;
598 if(wn->status == Sblocked){
599 /* only pass EAPOL frames when port is blocked */
600 if((e.type[0]<<8 | e.type[1]) != 0x888e)
602 } else if(wn->status != Sassoc)
605 h.fc[0] = 0x08; /* data */
606 memmove(h.a1, wn->bssid, Eaddrlen);
607 if(memcmp(e.s, wifi->ether->ea, Eaddrlen) == 0) {
608 h.fc[1] = 0x01; /* STA->AP */
610 h.fc[1] = 0x03; /* AP->AP (WDS) */
611 memmove(h.a2, wifi->ether->ea, Eaddrlen);
613 memmove(dstaddr(&h), e.d, Eaddrlen);
614 memmove(srcaddr(&h), e.s, Eaddrlen);
616 hdrlen = wifihdrlen(&h);
617 b = padblock(b, hdrlen + SNAPHDRSIZE);
618 memmove(b->rp, &h, hdrlen);
619 s = (SNAP*)(b->rp + hdrlen);
620 s->dsap = s->ssap = 0xAA;
625 memmove(s->type, e.type, 2);
644 while((b = qbread(ether->oq, 1000000)) != nil)
645 wifietheroq(wifi, b);
646 pexit("ether out queue closed", 1);
663 memset(wn, 0, sizeof(*wn));
664 memmove(wn->bssid, ether->bcast, Eaddrlen);
669 /* scan for access point */
670 while(wifi->bss == nil){
672 wnscan.channel = 1 + wnscan.channel % 11;
673 wifiprobe(wifi, &wnscan);
674 tsleep(&up->sleep, return0, 0, 1000);
677 /* maintain access point */
679 while((wn = wifi->bss) != nil){
680 ether->link = (wn->status == Sassoc) || (wn->status == Sblocked);
681 if(ether->link && (rate = wn->maxrate) != nil)
682 ether->mbps = ((*rate & 0x7f)+1)/2;
683 now = MACHP(0)->ticks;
684 if(wn->status != Sneedauth && TK2SEC(now - wn->lastseen) > 60 || goodbss(wifi, wn) == 0){
685 wifideauth(wifi, wn);
689 if(TK2MS(now - wn->lastsend) > 1000){
690 if(wn->status == Sauth && (++tmout & 7) == 0)
691 wifideauth(wifi, wn); /* stuck in auth, start over */
692 if(wn->status == Sconn || wn->status == Sunauth)
694 if(wn->status == Sauth)
697 tsleep(&up->sleep, return0, 0, 500);
703 wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*))
708 wifi = malloc(sizeof(Wifi));
711 wifi->iq = qopen(ether->limit, 0, 0, 0);
717 wifi->transmit = transmit;
719 wifi->rates = basicrates;
722 memmove(wifi->bssid, ether->bcast, Eaddrlen);
724 snprint(name, sizeof(name), "#l%dwifi", ether->ctlrno);
725 kproc(name, wifiproc, wifi);
726 snprint(name, sizeof(name), "#l%dwifo", ether->ctlrno);
727 kproc(name, wifoproc, wifi);
728 snprint(name, sizeof(name), "#l%dwifs", ether->ctlrno);
729 kproc(name, wifsproc, wifi);
735 hextob(char *s, char **sp, uchar *b, int n)
740 for(r = 0; r < n && *s; s++){
742 if(*s >= '0' && *s <= '9')
744 else if(*s >= 'a' && *s <= 'f')
746 else if(*s >= 'A' && *s <= 'F')
757 static char *ciphers[] = {
764 parsekey(Wkey *k, char *s)
769 strncpy(buf, s, sizeof(buf)-1);
770 buf[sizeof(buf)-1] = 0;
771 if((p = strchr(buf, ':')) != nil)
775 for(i=0; i<nelem(ciphers); i++){
776 if(ciphers[i] == nil)
778 if(strcmp(ciphers[i], buf) == 0)
781 if(i >= nelem(ciphers))
783 memset(k, 0, sizeof(Wkey));
784 k->len = hextob(p, &p, k->key, sizeof(k->key));
786 k->tsc = strtoull(++p, nil, 16);
804 static Cmdtab wifictlmsg[] =
811 CMrxkey0, "rxkey0", 0, /* group keys */
812 CMrxkey1, "rxkey1", 0,
813 CMrxkey2, "rxkey2", 0,
814 CMrxkey3, "rxkey3", 0,
816 CMrxkey4, "rxkey", 0, /* peerwise keys */
817 CMtxkey0, "txkey", 0,
819 CMtxkey0, "txkey0", 0,
823 wifictl(Wifi *wifi, void *buf, long n)
825 uchar addr[Eaddrlen];
837 print("#l%d: wifictl: %.*s\n", wifi->ether->ctlrno, (int)n, buf);
838 memmove(addr, wifi->ether->bcast, Eaddrlen);
840 cb = parsecmd(buf, n);
841 ct = lookupcmd(cb, wifictlmsg, nelem(wifictlmsg));
842 if(ct->index >= CMauth){
843 if(cb->nf > 1 && (ct->index == CMbssid || ct->index >= CMrxkey0)){
844 if(parseether(addr, cb->f[1]) == 0){
847 wn = nodelookup(wifi, addr, 0);
850 if(wn == nil && ct->index != CMbssid)
851 error("missing node");
856 wifi->debug = atoi(cb->f[1]);
859 print("#l%d: debug: %d\n", wifi->ether->ctlrno, wifi->debug);
863 strncpy(wifi->essid, cb->f[1], Essidlen);
869 if(goodbss(wifi, wn))
871 wifideauth(wifi, wn);
874 if(wifi->essid[0] == 0 && memcmp(wifi->bssid, wifi->ether->bcast, Eaddrlen) == 0)
876 for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++)
877 if(goodbss(wifi, wn)){
878 setstatus(wifi, wn, Sconn);
883 memmove(wifi->bssid, addr, Eaddrlen);
886 memset(wn->rxkey, 0, sizeof(wn->rxkey));
887 memset(wn->txkey, 0, sizeof(wn->txkey));
891 wn->rsnelen = hextob(cb->f[1], nil, wn->rsne, sizeof(wn->rsne));
893 setstatus(wifi, wn, Sconn);
896 setstatus(wifi, wn, Sauth);
900 case CMrxkey0: case CMrxkey1: case CMrxkey2: case CMrxkey3: case CMrxkey4:
902 if(ct->index < CMtxkey0)
903 k = &wn->rxkey[ct->index - CMrxkey0];
905 k = &wn->txkey[ct->index - CMtxkey0];
906 if(cb->f[1] == nil || parsekey(k, cb->f[1]) != 0)
908 if(ct->index >= CMtxkey0 && wn->status == Sblocked)
909 setstatus(wifi, wn, Sassoc);
918 wifistat(Wifi *wifi, void *buf, long n, ulong off)
920 static uchar zeros[Eaddrlen];
926 p = s = smalloc(4096);
931 p = seprint(p, e, "essid: %s\n", wn->ssid);
932 p = seprint(p, e, "bssid: %E\n", wn->bssid);
933 p = seprint(p, e, "status: %s\n", wn->status);
934 p = seprint(p, e, "channel: %.2d\n", wn->channel);
936 /* only print key ciphers and key length */
937 for(i = 0; i<nelem(wn->rxkey); i++)
938 p = seprint(p, e, "rxkey%d: %s:[%d]\n", i,
939 ciphers[wn->rxkey[i].cipher], wn->rxkey[i].len);
940 for(i = 0; i<nelem(wn->txkey); i++)
941 p = seprint(p, e, "txkey%d: %s:[%d]\n", i,
942 ciphers[wn->txkey[i].cipher], wn->txkey[i].len);
944 if(wn->brsnelen > 0){
945 p = seprint(p, e, "brsne: ");
946 for(i=0; i<wn->brsnelen; i++)
947 p = seprint(p, e, "%.2X", wn->brsne[i]);
948 p = seprint(p, e, "\n");
951 p = seprint(p, e, "essid: %s\n", wifi->essid);
952 p = seprint(p, e, "bssid: %E\n", wifi->bssid);
955 now = MACHP(0)->ticks;
956 for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){
957 if(wn->lastseen == 0)
959 p = seprint(p, e, "node: %E %.4x %-11ld %.2d %s\n",
960 wn->bssid, wn->cap, TK2MS(now - wn->lastseen), wn->channel, wn->ssid);
962 n = readstr(off, buf, n, s);
967 static void tkipencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
968 static int tkipdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
969 static void ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
970 static int ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
973 wifiencrypt(Wifi *, Wnode *wn, Block *b)
985 n = wifihdrlen((Wifipkt*)b->rp);
988 b = padblock(b, -(8+4));
991 memmove(w, b->rp+8, n);
999 b->rp[1] = (b->rp[0] | 0x20) & 0x7f;
1001 b->rp[3] = kid<<6 | 0x20;
1009 tkipencrypt(k, w, b, tsc);
1015 b->rp[3] = kid<<6 | 0x20;
1023 ccmpencrypt(k, w, b, tsc);
1037 wifidecrypt(Wifi *, Wnode *wn, Block *b)
1044 w = (Wifipkt*)b->rp;
1051 if((b->rp[3] & 0x20) == 0)
1053 if((w->a1[0] & 1) == 0)
1054 kid = 4; /* use peerwise key for non-unicast */
1056 k = &wn->rxkey[kid];
1059 tsc = (uvlong)b->rp[7]<<40 |
1060 (uvlong)b->rp[6]<<32 |
1061 (uvlong)b->rp[5]<<24 |
1062 (uvlong)b->rp[4]<<16 |
1063 (uvlong)b->rp[0]<<8 |
1066 if(tsc <= k->tsc || k->len != 32)
1068 if(tkipdecrypt(k, w, b, tsc) != 0)
1072 tsc = (uvlong)b->rp[7]<<40 |
1073 (uvlong)b->rp[6]<<32 |
1074 (uvlong)b->rp[5]<<24 |
1075 (uvlong)b->rp[4]<<16 |
1076 (uvlong)b->rp[1]<<8 |
1079 if(tsc <= k->tsc || k->len != 16)
1081 if(ccmpdecrypt(k, w, b, tsc) != 0)
1092 memmove(b->rp, w, n);
1093 w = (Wifipkt*)b->rp;
1098 static u16int Sbox[256] = {
1099 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
1100 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
1101 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
1102 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
1103 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
1104 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
1105 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
1106 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
1107 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
1108 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
1109 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
1110 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
1111 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
1112 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
1113 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
1114 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
1115 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
1116 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
1117 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
1118 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
1119 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
1120 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
1121 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
1122 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
1123 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
1124 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
1125 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
1126 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
1127 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
1128 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
1129 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
1130 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A
1134 tkipk2tk(uchar key[16], u16int tk[8])
1136 tk[0] = (u16int)key[1]<<8 | key[0];
1137 tk[1] = (u16int)key[3]<<8 | key[2];
1138 tk[2] = (u16int)key[5]<<8 | key[4];
1139 tk[3] = (u16int)key[7]<<8 | key[6];
1140 tk[4] = (u16int)key[9]<<8 | key[8];
1141 tk[5] = (u16int)key[11]<<8 | key[10];
1142 tk[6] = (u16int)key[13]<<8 | key[12];
1143 tk[7] = (u16int)key[15]<<8 | key[14];
1147 tkipphase1(u32int tscu, uchar ta[Eaddrlen], u16int tk[8], u16int p1k[5])
1149 u16int *k, i, x0, x1, x2;
1153 p1k[2] = (u16int)ta[1]<<8 | ta[0];
1154 p1k[3] = (u16int)ta[3]<<8 | ta[2];
1155 p1k[4] = (u16int)ta[5]<<8 | ta[4];
1162 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
1166 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
1170 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
1174 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
1178 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
1186 tkipphase2(u16int tscl, u16int p1k[5], u16int tk[8], uchar rc4key[16])
1188 u16int ppk[6], x0, x1, x2;
1195 ppk[5] = p1k[4] + tscl;
1197 x0 = ppk[5] ^ tk[0];
1199 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
1201 x0 = ppk[0] ^ tk[1];
1203 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
1205 x0 = ppk[1] ^ tk[2];
1207 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
1209 x0 = ppk[2] ^ tk[3];
1211 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
1213 x0 = ppk[3] ^ tk[4];
1215 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
1217 x0 = ppk[4] ^ tk[5];
1219 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
1222 x2 = ppk[5] ^ tk[6];
1223 ppk[0] += (x2 >> 1) | (x2 << 15);
1224 x2 = ppk[0] ^ tk[7];
1225 ppk[1] += (x2 >> 1) | (x2 << 15);
1228 ppk[2] += (x2 >> 1) | (x2 << 15);
1230 ppk[3] += (x2 >> 1) | (x2 << 15);
1232 ppk[4] += (x2 >> 1) | (x2 << 15);
1234 ppk[5] += (x2 >> 1) | (x2 << 15);
1236 rc4key[0] = tscl >> 8;
1237 rc4key[1] = (rc4key[0] | 0x20) & 0x7F;
1239 rc4key[3] = (ppk[5] ^ tk[0]) >> 1;
1241 rc4key[5] = ppk[0] >> 8;
1243 rc4key[7] = ppk[1] >> 8;
1245 rc4key[9] = ppk[2] >> 8;
1246 rc4key[10] = ppk[3];
1247 rc4key[11] = ppk[3] >> 8;
1248 rc4key[12] = ppk[4];
1249 rc4key[13] = ppk[4] >> 8;
1250 rc4key[14] = ppk[5];
1251 rc4key[15] = ppk[5] >> 8;
1254 typedef struct MICstate MICstate;
1264 micsetup(MICstate *s, uchar key[8])
1266 s->l = (u32int)key[0] |
1268 (u32int)key[2]<<16 |
1270 s->r = (u32int)key[4] |
1272 (u32int)key[6]<<16 |
1279 micupdate(MICstate *s, uchar *data, ulong len)
1281 u32int l, r, m, n, e;
1290 m |= (u32int)*data++ << 24;
1294 r ^= (l << 17) | (l >> 15);
1296 r ^= ((l & 0x00FF00FFUL)<<8) | ((l & 0xFF00FF00UL)>>8);
1298 r ^= (l << 3) | (l >> 29);
1300 r ^= (l >> 2) | (l << 30);
1310 micfinish(MICstate *s, uchar mic[8])
1312 static uchar pad[8] = { 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
1314 micupdate(s, pad, sizeof(pad));
1326 static uchar pad4[4] = { 0x00, 0x00, 0x00, 0x00, };
1329 tkipencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1331 u16int tk[8], p1k[5];
1337 micsetup(&ms, k->key+24);
1338 micupdate(&ms, dstaddr(w), Eaddrlen);
1339 micupdate(&ms, srcaddr(w), Eaddrlen);
1340 micupdate(&ms, pad4, 4);
1341 micupdate(&ms, b->rp, BLEN(b));
1342 micfinish(&ms, b->wp);
1345 crc = ethercrc(b->rp, BLEN(b));
1353 tkipk2tk(k->key, tk);
1354 tkipphase1(tsc >> 16, w->a2, tk, p1k);
1355 tkipphase2(tsc & 0xFFFF, p1k, tk, seed);
1356 setupRC4state(&rs, seed, sizeof(seed));
1357 rc4(&rs, b->rp, BLEN(b));
1361 tkipdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1363 uchar seed[16], mic[8];
1364 u16int tk[8], p1k[5];
1372 tkipk2tk(k->key, tk);
1373 tkipphase1(tsc >> 16, w->a2, tk, p1k);
1374 tkipphase2(tsc & 0xFFFF, p1k, tk, seed);
1375 setupRC4state(&rs, seed, sizeof(seed));
1376 rc4(&rs, b->rp, BLEN(b));
1379 crc = (ulong)b->wp[0] |
1380 (ulong)b->wp[1]<<8 |
1381 (ulong)b->wp[2]<<16 |
1382 (ulong)b->wp[3]<<24;
1384 if(ethercrc(b->rp, BLEN(b)) != crc)
1388 micsetup(&ms, k->key+16);
1389 micupdate(&ms, dstaddr(w), Eaddrlen);
1390 micupdate(&ms, srcaddr(w), Eaddrlen);
1391 micupdate(&ms, pad4, 4);
1392 micupdate(&ms, b->rp, BLEN(b));
1393 micfinish(&ms, mic);
1395 return memcmp(b->wp, mic, 8) != 0;
1399 putbe(uchar *p, int L, uint v)
1402 *p++ = (v >> L*8) & 0xFF;
1407 xblock(int L, int M, uchar *N, uchar *a, int la, int lm, uchar t[16], AESstate *s)
1409 uchar l[8], *p, *x, *e;
1411 assert(M >= 4 && M <= 16);
1412 assert(L >= 2 && L <= 4);
1414 t[0] = ((la > 0)<<6) | ((M-2)/2)<<3 | (L-1); /* flags */
1415 memmove(&t[1], N, 15-L);
1416 putbe(&t[16-L], L, lm);
1417 aes_encrypt(s->ekey, s->rounds, t, t);
1420 assert(la < 0xFF00);
1421 for(p = l, e = putbe(l, 2, la), x = t; p < e; x++, p++)
1423 for(e = a + la; a < e; x = t){
1424 for(; a < e && x < &t[16]; x++, a++)
1426 aes_encrypt(s->ekey, s->rounds, t, t);
1432 sblock(int L, uchar *N, uint i, uchar b[16], AESstate *s)
1434 b[0] = L-1; /* flags */
1435 memmove(&b[1], N, 15-L);
1436 putbe(&b[16-L], L, i);
1437 aes_encrypt(s->ekey, s->rounds, b, b);
1442 aesCCMencrypt(int L, int M, uchar *N /* N[15-L] */,
1443 uchar *a /* a[la] */, int la,
1444 uchar *m /* m[lm+M] */, int lm,
1447 uchar t[16], b[16], *p, *x;
1450 xblock(L, M, N, a, la, lm, t, s);
1452 for(i = 1; lm >= 16; i++, m += 16, lm -= 16){
1453 sblock(L, N, i, b, s);
1455 *((u32int*)&t[0]) ^= *((u32int*)&m[0]);
1456 *((u32int*)&m[0]) ^= *((u32int*)&b[0]);
1457 *((u32int*)&t[4]) ^= *((u32int*)&m[4]);
1458 *((u32int*)&m[4]) ^= *((u32int*)&b[4]);
1459 *((u32int*)&t[8]) ^= *((u32int*)&m[8]);
1460 *((u32int*)&m[8]) ^= *((u32int*)&b[8]);
1461 *((u32int*)&t[12]) ^= *((u32int*)&m[12]);
1462 *((u32int*)&m[12]) ^= *((u32int*)&b[12]);
1464 aes_encrypt(s->ekey, s->rounds, t, t);
1467 for(p = sblock(L, N, i, b, s), x = t; p < &b[lm]; x++, m++, p++){
1471 aes_encrypt(s->ekey, s->rounds, t, t);
1474 for(p = sblock(L, N, 0, b, s), x = t; p < &b[M]; x++, p++)
1481 aesCCMdecrypt(int L, int M, uchar *N /* N[15-L] */,
1482 uchar *a /* a[la] */, int la,
1483 uchar *m /* m[lm+M] */, int lm,
1486 uchar t[16], b[16], *p, *x;
1489 xblock(L, M, N, a, la, lm, t, s);
1491 for(i = 1; lm >= 16; i++, m += 16, lm -= 16){
1492 sblock(L, N, i, b, s);
1494 *((u32int*)&m[0]) ^= *((u32int*)&b[0]);
1495 *((u32int*)&t[0]) ^= *((u32int*)&m[0]);
1496 *((u32int*)&m[4]) ^= *((u32int*)&b[4]);
1497 *((u32int*)&t[4]) ^= *((u32int*)&m[4]);
1498 *((u32int*)&m[8]) ^= *((u32int*)&b[8]);
1499 *((u32int*)&t[8]) ^= *((u32int*)&m[8]);
1500 *((u32int*)&m[12]) ^= *((u32int*)&b[12]);
1501 *((u32int*)&t[12]) ^= *((u32int*)&m[12]);
1503 aes_encrypt(s->ekey, s->rounds, t, t);
1506 for(p = sblock(L, N, i, b, s), x = t; p < &b[lm]; x++, m++, p++){
1510 aes_encrypt(s->ekey, s->rounds, t, t);
1513 for(p = sblock(L, N, 0, b, s), x = t; p < &b[M]; x++, p++)
1516 return memcmp(m, t, M) != 0;
1520 setupCCMP(Wkey *k, Wifipkt *w, uvlong tsc, uchar nonce[13], uchar auth[32], AESstate *as)
1524 setupAESstate(as, k->key, k->len, nil);
1526 nonce[0] = ((w->fc[0] & 0x0c) == 0x00) << 4;
1527 memmove(&nonce[1], w->a2, Eaddrlen);
1528 nonce[7] = tsc >> 40;
1529 nonce[8] = tsc >> 32;
1530 nonce[9] = tsc >> 24;
1531 nonce[10] = tsc >> 16;
1532 nonce[11] = tsc >> 8;
1536 *p++ = (w->fc[0] & (((w->fc[0] & 0x0c) == 0x08) ? 0x0f : 0xff));
1537 *p++ = (w->fc[1] & ~0x38) | 0x40;
1538 memmove(p, w->a1, Eaddrlen); p += Eaddrlen;
1539 memmove(p, w->a2, Eaddrlen); p += Eaddrlen;
1540 memmove(p, w->a3, Eaddrlen); p += Eaddrlen;
1541 *p++ = w->seq[0] & 0x0f;
1543 if((w->fc[1] & 3) == 0x03) {
1544 memmove(p, w->a4, Eaddrlen);
1552 ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1554 uchar auth[32], nonce[13];
1557 aesCCMencrypt(2, 8, nonce, auth,
1558 setupCCMP(k, w, tsc, nonce, auth, &as),
1559 b->rp, BLEN(b), &as);
1564 ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1566 uchar auth[32], nonce[13];
1573 return aesCCMdecrypt(2, 8, nonce, auth,
1574 setupCCMP(k, w, tsc, nonce, auth, &as),
1575 b->rp, BLEN(b), &as);