2 #include "../port/lib.h"
9 #include "../port/error.h"
10 #include "../port/netif.h"
17 typedef struct SNAP SNAP;
28 WIFIHDRSIZE = 2+2+3*6+2,
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 */
40 static Block* wifidecrypt(Wifi *, Wnode *, Block *);
41 static Block* wifiencrypt(Wifi *, Wnode *, Block *);
46 if((w->fc[1] & 3) == 0x02)
54 if((w->fc[1] & 3) == 0x01)
61 wifihdrlen(Wifipkt *w)
66 if((w->fc[0] & 0x0c) == 0x08)
67 if((w->fc[0] & 0xf0) == 0x80){ /* QOS */
76 wifiiq(Wifi *wifi, Block *b)
82 if(BLEN(b) < WIFIHDRSIZE)
90 switch(w->fc[0] & 0x0c){
91 case 0x00: /* management */
92 if((w->fc[1] & 3) != 0x00) /* STA->STA */
96 case 0x04: /* control */
99 if((w->fc[1] & 3) == 0x03) /* AP->AP */
101 b->rp += wifihdrlen(w);
102 switch(w->fc[0] & 0xf0){
109 if(BLEN(b) < SNAPHDRSIZE)
111 memmove(&s, b->rp, SNAPHDRSIZE);
112 if(s.dsap != 0xAA || s.ssap != 0xAA || s.control != 3)
114 if(s.orgcode[0] != 0 || s.orgcode[1] != 0 || s.orgcode[2] != 0)
116 b->rp += SNAPHDRSIZE-ETHERHDRSIZE;
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);
130 wifitx(Wifi *wifi, Wnode *wn, Block *b)
135 seq = incref(&wifi->txseq);
144 if((w->fc[0] & 0x0c) != 0x00)
145 b = wifiencrypt(wifi, wn, b);
148 (*wifi->transmit)(wifi, wn, b);
152 nodelookup(Wifi *wifi, uchar *bssid, int new)
156 if(memcmp(bssid, wifi->ether->bcast, Eaddrlen) == 0)
158 if((wn = wifi->bss) != nil){
159 if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){
160 wn->lastseen = MACHP(0)->ticks;
164 if((nn = wifi->node) == wn)
166 for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){
169 if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){
170 wn->lastseen = MACHP(0)->ticks;
173 if(wn->lastseen < nn->lastseen)
178 memset(nn, 0, sizeof(Wnode));
179 memmove(nn->bssid, bssid, Eaddrlen);
180 nn->lastseen = MACHP(0)->ticks;
185 sendauth(Wifi *wifi, Wnode *bss)
191 b = allocb(WIFIHDRSIZE + 3*2);
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;
204 *p++ = 0; /* status */
207 wifitx(wifi, bss, b);
211 sendassoc(Wifi *wifi, Wnode *bss)
218 b = allocb(WIFIHDRSIZE + 512);
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;
227 *p++ = 1; /* capinfo */
229 *p++ = 16; /* interval */
233 *p = strlen(bss->ssid);
234 memmove(p+1, bss->ssid, *p);
237 *p++ = 1; /* RATES (BUG: these are all lies!) */
246 memmove(p, bss->rsne, n);
251 wifitx(wifi, bss, b);
255 recvassoc(Wifi *wifi, Wnode *wn, uchar *d, int len)
267 wn->aid = d[0] | d[1]<<8;
269 wifi->status = Sblocked;
271 wifi->status = Sassoc;
275 wifi->status = Sunassoc;
281 recvbeacon(Wifi *, Wnode *wn, uchar *d, int len)
289 d += 8; /* timestamp */
290 wn->ival = d[0] | d[1]<<8;
292 wn->cap = d[0] | d[1]<<8;
295 memset(m, 0, sizeof(m));
296 for(e = d + len; d+2 <= e; d = x){
301 /* skip double entries */
302 if(m[t/8] & 1<<(t%8))
309 while(len < Essidlen && d+len < x && d[len] != 0)
313 if(len != strlen(wn->ssid) || strncmp(wn->ssid, (char*)d, len) != 0){
314 strncpy(wn->ssid, (char*)d, len);
318 case 3: /* DSPARAMS */
339 if((b = qbread(wifi->iq, 100000)) == nil)
344 if((wn = nodelookup(wifi, w->a2, 1)) == nil)
346 if((b = wifidecrypt(wifi, wn, b)) != nil){
356 if((w->fc[0] & 0x0c) != 0x00)
358 switch(w->fc[0] & 0xf0){
359 case 0x50: /* probe response */
360 case 0x80: /* beacon */
361 if((wn = nodelookup(wifi, w->a3, 1)) == nil)
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){
367 wifi->status = Sconn;
372 if(memcmp(w->a1, wifi->ether->ea, Eaddrlen))
374 if((wn = nodelookup(wifi, w->a3, 0)) == nil)
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));
384 case 0xb0: /* auth */
385 wifi->status = Sauth;
388 case 0xc0: /* deauth */
389 wifi->status = Sunauth;
390 memset(wn->rxkey, 0, sizeof(wn->rxkey));
391 memset(wn->txkey, 0, sizeof(wn->txkey));
397 pexit("wifi in queue closed", 0);
401 wifietheroq(Wifi *wifi, Block *b)
408 if(BLEN(b) < ETHERHDRSIZE)
410 if((wn = wifi->bss) == nil)
413 memmove(&e, b->rp, ETHERHDRSIZE);
414 b->rp += ETHERHDRSIZE;
416 if(wifi->status == Sblocked){
417 /* only pass EAPOL frames when port is blocked */
418 if((e.type[0]<<8 | e.type[1]) != 0x888e)
420 } else if(wifi->status != Sassoc)
423 b = padblock(b, WIFIHDRSIZE + SNAPHDRSIZE);
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);
432 s = (SNAP*)(b->rp + WIFIHDRSIZE);
433 s->dsap = s->ssap = 0xAA;
438 memmove(s->type, e.type, 2);
455 while((b = qbread(ether->oq, 1000000)) != nil)
456 wifietheroq(wifi, b);
457 pexit("ether out queue closed", 0);
461 wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*))
466 wifi = malloc(sizeof(Wifi));
468 wifi->iq = qopen(8*1024, 0, 0, 0);
469 wifi->transmit = transmit;
470 wifi->status = Snone;
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);
481 hextob(char *s, char **sp, uchar *b, int n)
486 for(r = 0; r < n && *s; s++){
488 if(*s >= '0' && *s <= '9')
490 else if(*s >= 'a' && *s <= 'f')
492 else if(*s >= 'A' && *s <= 'F')
503 static char *ciphers[] = {
510 parsekey(Wkey *k, char *s)
515 strncpy(buf, s, sizeof(buf)-1);
516 buf[sizeof(buf)-1] = 0;
517 if((p = strchr(buf, ':')) != nil)
521 for(i=0; i<nelem(ciphers); i++){
522 if(ciphers[i] == nil)
524 if(strcmp(ciphers[i], buf) == 0)
527 if(i >= nelem(ciphers))
529 memset(k, 0, sizeof(Wkey));
530 k->len = hextob(p, &p, k->key, sizeof(k->key));
532 k->tsc = strtoull(++p, nil, 16);
550 static Cmdtab wifictlmsg[] =
555 CMrxkey0, "rxkey0", 0, /* group keys */
556 CMrxkey1, "rxkey1", 0,
557 CMrxkey2, "rxkey2", 0,
558 CMrxkey3, "rxkey3", 0,
560 CMrxkey4, "rxkey", 0, /* peerwise keys */
561 CMtxkey0, "txkey", 0,
563 CMtxkey0, "txkey0", 0,
567 wifictl(Wifi *wifi, void *buf, long n)
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];
586 if(parseether(addr, cb->f[1]) == 0){
589 wn = nodelookup(wifi, addr, 0);
593 error("missing node");
600 wifi->status = Snone;
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){
606 wifi->status = Sconn;
613 wifi->status = Sauth;
614 memset(wn->rxkey, 0, sizeof(wn->rxkey));
615 memset(wn->txkey, 0, sizeof(wn->txkey));
619 wn->rsnelen = hextob(cb->f[1], nil, wn->rsne, sizeof(wn->rsne));
622 case CMrxkey0: case CMrxkey1: case CMrxkey2: case CMrxkey3: case CMrxkey4:
624 if(ct->index < CMtxkey0)
625 k = &wn->rxkey[ct->index - CMrxkey0];
627 k = &wn->txkey[ct->index - CMtxkey0];
628 if(cb->f[1] == nil || parsekey(k, cb->f[1]) != 0)
630 if(ct->index >= CMtxkey0 && wifi->status == Sblocked && wifi->bss == wn)
631 wifi->status = Sassoc;
640 wifistat(Wifi *wifi, void *buf, long n, ulong off)
642 static uchar zeros[Eaddrlen];
647 p = s = smalloc(4096);
650 p = seprint(p, e, "status: %s\n", wifi->status);
651 p = seprint(p, e, "essid: %s\n", wifi->essid);
653 p = seprint(p, e, "bssid: %E\n", wn != nil ? wn->bssid : zeros);
655 now = MACHP(0)->ticks;
656 for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){
657 if(wn->lastseen == 0)
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);
662 n = readstr(off, buf, n, s);
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);
673 wifiencrypt(Wifi *, Wnode *wn, Block *b)
685 n = wifihdrlen((Wifipkt*)b->rp);
688 b = padblock(b, -(8+4));
691 memmove(w, b->rp+8, n);
699 b->rp[1] = (b->rp[0] | 0x20) & 0x7f;
701 b->rp[3] = kid<<6 | 0x20;
709 tkipencrypt(k, w, b, tsc);
715 b->rp[3] = kid<<6 | 0x20;
723 ccmpencrypt(k, w, b, tsc);
737 wifidecrypt(Wifi *, Wnode *wn, Block *b)
745 if(BLEN(b) < WIFIHDRSIZE)
754 if((b->rp[3] & 0x20) == 0)
756 if((dstaddr(w)[0] & 1) == 0)
757 kid = 4; /* use peerwise key for non-unicast */
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 |
769 if(tsc <= k->tsc || k->len != 32)
771 if(tkipdecrypt(k, w, b, tsc) != 0)
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 |
782 if(tsc <= k->tsc || k->len != 16)
784 if(ccmpdecrypt(k, w, b, tsc) != 0)
795 memmove(b->rp, w, n);
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
837 tkipk2tk(uchar key[16], u16int tk[8])
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];
850 tkipphase1(u32int tscu, uchar ta[Eaddrlen], u16int tk[8], u16int p1k[5])
852 u16int *k, i, x0, x1, x2;
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];
865 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
869 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
873 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
877 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
881 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
889 tkipphase2(u16int tscl, u16int p1k[5], u16int tk[8], uchar rc4key[16])
891 u16int ppk[6], x0, x1, x2;
898 ppk[5] = p1k[4] + tscl;
902 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
906 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
910 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
914 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
918 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
922 x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8));
926 ppk[0] += (x2 >> 1) | (x2 << 15);
928 ppk[1] += (x2 >> 1) | (x2 << 15);
931 ppk[2] += (x2 >> 1) | (x2 << 15);
933 ppk[3] += (x2 >> 1) | (x2 << 15);
935 ppk[4] += (x2 >> 1) | (x2 << 15);
937 ppk[5] += (x2 >> 1) | (x2 << 15);
939 rc4key[0] = tscl >> 8;
940 rc4key[1] = (rc4key[0] | 0x20) & 0x7F;
942 rc4key[3] = (ppk[5] ^ tk[0]) >> 1;
944 rc4key[5] = ppk[0] >> 8;
946 rc4key[7] = ppk[1] >> 8;
948 rc4key[9] = ppk[2] >> 8;
950 rc4key[11] = ppk[3] >> 8;
952 rc4key[13] = ppk[4] >> 8;
954 rc4key[15] = ppk[5] >> 8;
957 typedef struct MICstate MICstate;
967 micsetup(MICstate *s, uchar key[8])
969 s->l = (u32int)key[0] |
973 s->r = (u32int)key[4] |
982 micupdate(MICstate *s, uchar *data, ulong len)
984 u32int l, r, m, n, e;
993 m |= (u32int)*data++ << 24;
997 r ^= (l << 17) | (l >> 15);
999 r ^= ((l & 0x00FF00FFUL)<<8) | ((l & 0xFF00FF00UL)>>8);
1001 r ^= (l << 3) | (l >> 29);
1003 r ^= (l >> 2) | (l << 30);
1013 micfinish(MICstate *s, uchar mic[8])
1015 static uchar pad[8] = { 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
1017 micupdate(s, pad, sizeof(pad));
1029 static uchar pad4[4] = { 0x00, 0x00, 0x00, 0x00, };
1032 tkipencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1034 u16int tk[8], p1k[5];
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);
1048 crc = ethercrc(b->rp, BLEN(b));
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));
1064 tkipdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1066 uchar seed[16], mic[8];
1067 u16int tk[8], p1k[5];
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));
1082 crc = (ulong)b->wp[0] |
1083 (ulong)b->wp[1]<<8 |
1084 (ulong)b->wp[2]<<16 |
1085 (ulong)b->wp[3]<<24;
1087 if(ethercrc(b->rp, BLEN(b)) != crc)
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);
1098 return memcmp(b->wp, mic, 8) != 0;
1102 putbe(uchar *p, int L, uint v)
1105 *p++ = (v >> L*8) & 0xFF;
1110 xblock(int L, int M, uchar *N, uchar *a, int la, int lm, uchar t[16], AESstate *s)
1112 uchar l[8], *p, *x, *e;
1114 assert(M >= 4 && M <= 16);
1115 assert(L >= 2 && L <= 4);
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);
1123 assert(la < 0xFF00);
1124 for(p = l, e = putbe(l, 2, la), x = t; p < e; x++, p++)
1126 for(e = a + la; a < e; x = t){
1127 for(; a < e && x < &t[16]; x++, a++)
1129 aes_encrypt(s->ekey, s->rounds, t, t);
1135 sblock(int L, uchar *N, uint i, uchar b[16], AESstate *s)
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);
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,
1150 uchar t[16], b[16], *p, *x;
1153 xblock(L, M, N, a, la, lm, t, s);
1155 for(i = 1; lm >= 16; i++, m += 16, lm -= 16){
1156 sblock(L, N, i, b, s);
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]);
1167 aes_encrypt(s->ekey, s->rounds, t, t);
1170 for(p = sblock(L, N, i, b, s), x = t; p < &b[lm]; x++, m++, p++){
1174 aes_encrypt(s->ekey, s->rounds, t, t);
1177 for(p = sblock(L, N, 0, b, s), x = t; p < &b[M]; x++, p++)
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,
1189 uchar t[16], b[16], *p, *x;
1192 xblock(L, M, N, a, la, lm, t, s);
1194 for(i = 1; lm >= 16; i++, m += 16, lm -= 16){
1195 sblock(L, N, i, b, s);
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]);
1206 aes_encrypt(s->ekey, s->rounds, t, t);
1209 for(p = sblock(L, N, i, b, s), x = t; p < &b[lm]; x++, m++, p++){
1213 aes_encrypt(s->ekey, s->rounds, t, t);
1216 for(p = sblock(L, N, 0, b, s), x = t; p < &b[M]; x++, p++)
1219 return memcmp(m, t, M) != 0;
1223 setupCCMP(Wkey *k, Wifipkt *w, uvlong tsc, uchar nonce[13], uchar auth[32], AESstate *as)
1227 setupAESstate(as, k->key, k->len, nil);
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;
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;
1251 ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1253 uchar auth[32], nonce[13];
1256 aesCCMencrypt(2, 8, nonce, auth,
1257 setupCCMP(k, w, tsc, nonce, auth, &as),
1258 b->rp, BLEN(b), &as);
1263 ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
1265 uchar auth[32], nonce[13];
1272 return aesCCMdecrypt(2, 8, nonce, auth,
1273 setupCCMP(k, w, tsc, nonce, auth, &as),
1274 b->rp, BLEN(b), &as);