1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include <mp.h>
5 #include <libsec.h>
6 #include <auth.h>
7
8 enum {
9 PMKlen = 256/8,
10 PTKlen = 512/8,
11 GTKlen = 256/8,
12
13 MIClen = 16,
14
15 Noncelen = 32,
16 Eaddrlen = 6,
17 };
18
19 enum {
20 Fptk = 1<<3,
21 Fins = 1<<6,
22 Fack = 1<<7,
23 Fmic = 1<<8,
24 Fsec = 1<<9,
25 Ferr = 1<<10,
26 Freq = 1<<11,
27 Fenc = 1<<12,
28
29 Keydescrlen = 1+2+2+8+32+16+8+8+16+2,
30 };
31
32 typedef struct Keydescr Keydescr;
33 struct Keydescr
34 {
35 uchar type[1];
36 uchar flags[2];
37 uchar keylen[2];
38 uchar repc[8];
39 uchar nonce[32];
40 uchar eapoliv[16];
41 uchar rsc[8];
42 uchar id[8];
43 uchar mic[16];
44 uchar datalen[2];
45 uchar data[];
46 };
47
48 typedef struct Cipher Cipher;
49 struct Cipher
50 {
51 char *name;
52 int keylen;
53 };
54
55 typedef struct Eapconn Eapconn;
56 typedef struct TLStunn TLStunn;
57
58 struct Eapconn
59 {
60 int fd;
61 int version;
62
63 uchar type;
64 uchar smac[Eaddrlen];
65 uchar amac[Eaddrlen];
66
67 TLStunn *tunn;
68
69 void (*write)(Eapconn*, uchar *data, int datalen);
70 };
71
72 struct TLStunn
73 {
74 int fd;
75
76 int clientpid;
77 int readerpid;
78
79 uchar id;
80 uchar tp;
81 };
82
83 Cipher tkip = { "tkip", 32 };
84 Cipher ccmp = { "ccmp", 16 };
85
86 Cipher *peercipher;
87 Cipher *groupcipher;
88
89 int forked;
90 int prompt;
91 int debug;
92 int fd, cfd;
93 char *dev;
94 enum {
95 AuthNone,
96 AuthPSK,
97 AuthWPA,
98 };
99 int authtype;
100 char devdir[40];
101 uchar ptk[PTKlen];
102 char essid[32+1];
103 uvlong lastrepc;
104
105 uchar rsntkipoui[4] = {0x00, 0x0F, 0xAC, 0x02};
106 uchar rsnccmpoui[4] = {0x00, 0x0F, 0xAC, 0x04};
107 uchar rsnapskoui[4] = {0x00, 0x0F, 0xAC, 0x02};
108 uchar rsnawpaoui[4] = {0x00, 0x0F, 0xAC, 0x01};
109
110 uchar rsnie[] = {
111 0x30, /* RSN */
112 0x14, /* length */
113 0x01, 0x00, /* version 1 */
114 0x00, 0x0F, 0xAC, 0x04, /* group cipher suite CCMP */
115 0x01, 0x00, /* pairwise cipher suite count 1 */
116 0x00, 0x0F, 0xAC, 0x04, /* pairwise cipher suite CCMP */
117 0x01, 0x00, /* authentication suite count 1 */
118 0x00, 0x0F, 0xAC, 0x02, /* authentication suite PSK */
119 0x00, 0x00, /* capabilities */
120 };
121
122 uchar wpa1oui[4] = {0x00, 0x50, 0xF2, 0x01};
123 uchar wpatkipoui[4] = {0x00, 0x50, 0xF2, 0x02};
124 uchar wpaapskoui[4] = {0x00, 0x50, 0xF2, 0x02};
125 uchar wpaawpaoui[4] = {0x00, 0x50, 0xF2, 0x01};
126
127 uchar wpaie[] = {
128 0xdd, /* vendor specific */
129 0x16, /* length */
130 0x00, 0x50, 0xf2, 0x01, /* WPAIE type 1 */
131 0x01, 0x00, /* version 1 */
132 0x00, 0x50, 0xf2, 0x02, /* group cipher suite TKIP */
133 0x01, 0x00, /* pairwise cipher suite count 1 */
134 0x00, 0x50, 0xf2, 0x02, /* pairwise cipher suite TKIP */
135 0x01, 0x00, /* authentication suite count 1 */
136 0x00, 0x50, 0xf2, 0x02, /* authentication suite PSK */
137 };
138
139 void*
emalloc(int len)140 emalloc(int len)
141 {
142 void *v;
143
144 if((v = mallocz(len, 1)) == nil)
145 sysfatal("malloc: %r");
146 return v;
147 }
148
149 int
hextob(char * s,char ** sp,uchar * b,int n)150 hextob(char *s, char **sp, uchar *b, int n)
151 {
152 int r;
153
154 n <<= 1;
155 for(r = 0; r < n && *s; s++){
156 *b <<= 4;
157 if(*s >= '0' && *s <= '9')
158 *b |= (*s - '0');
159 else if(*s >= 'a' && *s <= 'f')
160 *b |= 10+(*s - 'a');
161 else if(*s >= 'A' && *s <= 'F')
162 *b |= 10+(*s - 'A');
163 else break;
164 if((++r & 1) == 0)
165 b++;
166 }
167 if(sp != nil)
168 *sp = s;
169 return r >> 1;
170 }
171
172 char*
getifstats(char * key,char * val,int nval)173 getifstats(char *key, char *val, int nval)
174 {
175 char buf[8*1024], *f[2], *p, *e;
176 int fd, n;
177
178 snprint(buf, sizeof(buf), "%s/ifstats", devdir);
179 if((fd = open(buf, OREAD)) < 0)
180 return nil;
181 n = readn(fd, buf, sizeof(buf)-1);
182 close(fd);
183 if(n <= 0)
184 return nil;
185 buf[n] = 0;
186 for(p = buf; (e = strchr(p, '\n')) != nil; p = e){
187 *e++ = 0;
188 if(gettokens(p, f, 2, "\t\r\n ") != 2)
189 continue;
190 if(strcmp(f[0], key) != 0)
191 continue;
192 strncpy(val, f[1], nval);
193 val[nval-1] = 0;
194 return val;
195 }
196 return nil;
197 }
198
199 char*
getessid(void)200 getessid(void)
201 {
202 return getifstats("essid:", essid, sizeof(essid));
203 }
204
205 int
getbssid(uchar mac[Eaddrlen])206 getbssid(uchar mac[Eaddrlen])
207 {
208 char buf[64];
209
210 if(getifstats("bssid:", buf, sizeof(buf)) != nil)
211 return parseether(mac, buf);
212 return -1;
213 }
214
215 int
connected(void)216 connected(void)
217 {
218 char status[1024];
219
220 if(getifstats("status:", status, sizeof(status)) == nil)
221 return 0;
222 if(strcmp(status, "connecting") == 0)
223 return 0;
224 if(strcmp(status, "unauthenticated") == 0)
225 return 0;
226 if(debug)
227 fprint(2, "status: %s\n", status);
228 return 1;
229 }
230
231 int
buildrsne(uchar rsne[258])232 buildrsne(uchar rsne[258])
233 {
234 char buf[1024];
235 uchar brsne[258];
236 int brsnelen;
237 uchar *p, *w, *e;
238 int i, n;
239
240 if(getifstats("brsne:", buf, sizeof(buf)) == nil)
241 return 0; /* not an error, might be old kernel */
242
243 brsnelen = hextob(buf, nil, brsne, sizeof(brsne));
244 if(brsnelen <= 4){
245 trunc: sysfatal("invalid or truncated RSNE; brsne: %s", buf);
246 return 0;
247 }
248
249 w = rsne;
250 p = brsne;
251 e = p + brsnelen;
252 if(p[0] == 0x30){
253 p += 2;
254
255 /* RSN */
256 *w++ = 0x30;
257 *w++ = 0; /* length */
258 } else if(p[0] == 0xDD){
259 p += 2;
260 if((e - p) < 4 || memcmp(p, wpa1oui, 4) != 0){
261 sysfatal("unrecognized WPAIE type; brsne: %s", buf);
262 return 0;
263 }
264
265 /* WPA */
266 *w++ = 0xDD;
267 *w++ = 0; /* length */
268
269 memmove(w, wpa1oui, 4);
270 w += 4;
271 p += 4;
272 } else {
273 sysfatal("unrecognized RSNE type; brsne: %s", buf);
274 return 0;
275 }
276
277 if((e - p) < 6)
278 goto trunc;
279
280 *w++ = *p++; /* version */
281 *w++ = *p++;
282
283 if(rsne[0] == 0x30){
284 if(memcmp(p, rsnccmpoui, 4) == 0)
285 groupcipher = &ccmp;
286 else if(memcmp(p, rsntkipoui, 4) == 0)
287 groupcipher = &tkip;
288 else {
289 sysfatal("unrecognized RSN group cipher; brsne: %s", buf);
290 return 0;
291 }
292 } else {
293 if(memcmp(p, wpatkipoui, 4) != 0){
294 sysfatal("unrecognized WPA group cipher; brsne: %s", buf);
295 return 0;
296 }
297 groupcipher = &tkip;
298 }
299
300 memmove(w, p, 4); /* group cipher */
301 w += 4;
302 p += 4;
303
304 if((e - p) < 6)
305 goto trunc;
306
307 *w++ = 0x01; /* # of peer ciphers */
308 *w++ = 0x00;
309 n = *p++;
310 n |= *p++ << 8;
311
312 if(n <= 0)
313 goto trunc;
314
315 peercipher = &tkip;
316 for(i=0; i<n; i++){
317 if((e - p) < 4)
318 goto trunc;
319
320 if(rsne[0] == 0x30 && memcmp(p, rsnccmpoui, 4) == 0 && peercipher == &tkip)
321 peercipher = &ccmp;
322 p += 4;
323 }
324 if(peercipher == &ccmp)
325 memmove(w, rsnccmpoui, 4);
326 else if(rsne[0] == 0x30)
327 memmove(w, rsntkipoui, 4);
328 else
329 memmove(w, wpatkipoui, 4);
330 w += 4;
331
332 if((e - p) < 6)
333 goto trunc;
334
335 *w++ = 0x01; /* # of auth suites */
336 *w++ = 0x00;
337 n = *p++;
338 n |= *p++ << 8;
339
340 if(n <= 0)
341 goto trunc;
342
343 for(i=0; i<n; i++){
344 if((e - p) < 4)
345 goto trunc;
346
347 if(rsne[0] == 0x30){
348 /* look for PSK oui */
349 if(memcmp(p, rsnapskoui, 4) == 0)
350 break;
351 /* look for WPA oui */
352 if(memcmp(p, rsnawpaoui, 4) == 0){
353 authtype = AuthWPA;
354 break;
355 }
356 } else {
357 /* look for PSK oui */
358 if(memcmp(p, wpaapskoui, 4) == 0)
359 break;
360 /* look for WPA oui */
361 if(memcmp(p, wpaawpaoui, 4) == 0){
362 authtype = AuthWPA;
363 break;
364 }
365 }
366 p += 4;
367 }
368 if(i >= n){
369 sysfatal("auth suite is not PSK or WPA; brsne: %s", buf);
370 return 0;
371 }
372
373 memmove(w, p, 4);
374 w += 4;
375
376 if(rsne[0] == 0x30){
377 /* RSN caps */
378 *w++ = 0x00;
379 *w++ = 0x00;
380 }
381
382 rsne[1] = (w - rsne) - 2;
383 return w - rsne;
384 }
385
386 char*
factotumattr(char * attr,char * fmt,...)387 factotumattr(char *attr, char *fmt, ...)
388 {
389 char buf[1024];
390 va_list list;
391 AuthRpc *rpc;
392 char *val;
393 Attr *a;
394 int afd;
395
396 if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
397 return nil;
398 if((rpc = auth_allocrpc(afd)) == nil){
399 close(afd);
400 return nil;
401 }
402 va_start(list, fmt);
403 vsnprint(buf, sizeof(buf), fmt, list);
404 va_end(list);
405 val = nil;
406 if(auth_rpc(rpc, "start", buf, strlen(buf)) == 0){
407 if((a = auth_attr(rpc)) != nil){
408 if((val = _strfindattr(a, attr)) != nil)
409 val = strdup(val);
410 _freeattr(a);
411 }
412 }
413 auth_freerpc(rpc);
414 close(afd);
415
416 return val;
417 }
418
419 void
freeup(UserPasswd * up)420 freeup(UserPasswd *up)
421 {
422 memset(up->user, 0, strlen(up->user));
423 memset(up->passwd, 0, strlen(up->passwd));
424 free(up);
425 }
426
427 char*
getidentity(void)428 getidentity(void)
429 {
430 static char *identity;
431 char *s;
432
433 s = nil;
434 for(;;){
435 if(getessid() == nil)
436 break;
437 if((s = factotumattr("user", "proto=pass service=wpa essid=%q", essid)) != nil)
438 break;
439 if((s = factotumattr("user", "proto=mschapv2 role=client service=wpa essid=%q", essid)) != nil)
440 break;
441 break;
442 }
443 if(s != nil){
444 free(identity);
445 identity = s;
446 } else if(identity == nil)
447 identity = strdup("anonymous");
448 if(debug)
449 fprint(2, "identity: %s\n", identity);
450 return identity;
451 }
452
453 int
factotumctl(char * fmt,...)454 factotumctl(char *fmt, ...)
455 {
456 va_list list;
457 int fd, r, n;
458 char *s;
459
460 r = -1;
461 if((fd = open("/mnt/factotum/ctl", OWRITE)) >= 0){
462 va_start(list, fmt);
463 s = vsmprint(fmt, list);
464 va_end(list);
465 if(s != nil){
466 n = strlen(s);
467 r = write(fd, s, n);
468 memset(s, 0, n);
469 free(s);
470 }
471 close(fd);
472 }
473 return r;
474 }
475
476 int
setpmk(uchar pmk[PMKlen])477 setpmk(uchar pmk[PMKlen])
478 {
479 if(getessid() == nil)
480 return -1;
481 return factotumctl("key proto=wpapsk role=client essid=%q !password=%.*H\n", essid, PMKlen, pmk);
482 }
483
484 int
getptk(AuthGetkey * getkey,uchar smac[Eaddrlen],uchar amac[Eaddrlen],uchar snonce[Noncelen],uchar anonce[Noncelen],uchar ptk[PTKlen])485 getptk(AuthGetkey *getkey,
486 uchar smac[Eaddrlen], uchar amac[Eaddrlen],
487 uchar snonce[Noncelen], uchar anonce[Noncelen],
488 uchar ptk[PTKlen])
489 {
490 uchar buf[2*Eaddrlen + 2*Noncelen], *p;
491 AuthRpc *rpc;
492 int afd, ret;
493 char *s;
494
495 ret = -1;
496 s = nil;
497 rpc = nil;
498 if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
499 goto out;
500 if((rpc = auth_allocrpc(afd)) == nil)
501 goto out;
502 if((s = getessid()) == nil)
503 goto out;
504 if((s = smprint("proto=wpapsk role=client essid=%q", s)) == nil)
505 goto out;
506 if((ret = auth_rpc(rpc, "start", s, strlen(s))) != ARok)
507 goto out;
508 p = buf;
509 memmove(p, smac, Eaddrlen); p += Eaddrlen;
510 memmove(p, amac, Eaddrlen); p += Eaddrlen;
511 memmove(p, snonce, Noncelen); p += Noncelen;
512 memmove(p, anonce, Noncelen); p += Noncelen;
513 if((ret = auth_rpc(rpc, "write", buf, p - buf)) != ARok)
514 goto out;
515 if((ret = auth_rpc(rpc, "read", nil, 0)) != ARok)
516 goto out;
517 if(rpc->narg != PTKlen){
518 ret = -1;
519 goto out;
520 }
521 memmove(ptk, rpc->arg, PTKlen);
522 ret = 0;
523 out:
524 if(getkey != nil){
525 switch(ret){
526 case ARneedkey:
527 case ARbadkey:
528 (*getkey)(rpc->arg);
529 break;
530 }
531 }
532 free(s);
533 if(afd >= 0) close(afd);
534 if(rpc != nil) auth_freerpc(rpc);
535 return ret;
536 }
537
538 void
dumpkeydescr(Keydescr * kd)539 dumpkeydescr(Keydescr *kd)
540 {
541 static struct {
542 int flag;
543 char *name;
544 } flags[] = {
545 Fptk, "ptk",
546 Fins, "ins",
547 Fack, "ack",
548 Fmic, "mic",
549 Fsec, "sec",
550 Ferr, "err",
551 Freq, "req",
552 Fenc, "enc",
553 };
554 int i, f;
555
556 f = kd->flags[0]<<8 | kd->flags[1];
557 fprint(2, "type=%.*H vers=%d flags=%.*H ( ",
558 sizeof(kd->type), kd->type, kd->flags[1] & 7,
559 sizeof(kd->flags), kd->flags);
560 for(i=0; i<nelem(flags); i++)
561 if(flags[i].flag & f)
562 fprint(2, "%s ", flags[i].name);
563 fprint(2, ") len=%.*H\nrepc=%.*H nonce=%.*H\neapoliv=%.*H rsc=%.*H id=%.*H mic=%.*H\n",
564 sizeof(kd->keylen), kd->keylen,
565 sizeof(kd->repc), kd->repc,
566 sizeof(kd->nonce), kd->nonce,
567 sizeof(kd->eapoliv), kd->eapoliv,
568 sizeof(kd->rsc), kd->rsc,
569 sizeof(kd->id), kd->id,
570 sizeof(kd->mic), kd->mic);
571 i = kd->datalen[0]<<8 | kd->datalen[1];
572 fprint(2, "data[%.4x]=%.*H\n", i, i, kd->data);
573 }
574
575 int
rc4unwrap(uchar key[16],uchar iv[16],uchar * data,int len)576 rc4unwrap(uchar key[16], uchar iv[16], uchar *data, int len)
577 {
578 uchar seed[32];
579 RC4state rs;
580
581 memmove(seed, iv, 16);
582 memmove(seed+16, key, 16);
583 setupRC4state(&rs, seed, sizeof(seed));
584 rc4skip(&rs, 256);
585 rc4(&rs, data, len);
586 return len;
587 }
588
589 int
aesunwrap(uchar * key,int nkey,uchar * data,int len)590 aesunwrap(uchar *key, int nkey, uchar *data, int len)
591 {
592 static uchar IV[8] = { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, };
593 uchar B[16], *R;
594 AESstate s;
595 uint t;
596 int n;
597
598 len -= 8;
599 if(len < 16 || (len % 8) != 0)
600 return -1;
601 n = len/8;
602 t = n*6;
603 setupAESstate(&s, key, nkey, 0);
604 memmove(B, data, 8);
605 memmove(data, data+8, n*8);
606 do {
607 for(R = data + (n - 1)*8; R >= data; t--, R -= 8){
608 memmove(B+8, R, 8);
609 B[7] ^= (t >> 0);
610 B[6] ^= (t >> 8);
611 B[5] ^= (t >> 16);
612 B[4] ^= (t >> 24);
613 aes_decrypt(s.dkey, s.rounds, B, B);
614 memmove(R, B+8, 8);
615 }
616 } while(t > 0);
617 if(memcmp(B, IV, 8) != 0)
618 return -1;
619 return n*8;
620 }
621
622 int
calcmic(Keydescr * kd,uchar * msg,int msglen)623 calcmic(Keydescr *kd, uchar *msg, int msglen)
624 {
625 int vers;
626
627 vers = kd->flags[1] & 7;
628 memset(kd->mic, 0, MIClen);
629 if(vers == 1){
630 uchar digest[MD5dlen];
631
632 hmac_md5(msg, msglen, ptk, 16, digest, nil);
633 memmove(kd->mic, digest, MIClen);
634 return 0;
635 }
636 if(vers == 2){
637 uchar digest[SHA1dlen];
638
639 hmac_sha1(msg, msglen, ptk, 16, digest, nil);
640 memmove(kd->mic, digest, MIClen);
641 return 0;
642 }
643 return -1;
644 }
645
646 int
checkmic(Keydescr * kd,uchar * msg,int msglen)647 checkmic(Keydescr *kd, uchar *msg, int msglen)
648 {
649 uchar tmp[MIClen];
650
651 memmove(tmp, kd->mic, MIClen);
652 if(calcmic(kd, msg, msglen) != 0)
653 return -1;
654 return memcmp(tmp, kd->mic, MIClen) != 0;
655 }
656
657 void
fdwrite(Eapconn * conn,uchar * data,int len)658 fdwrite(Eapconn *conn, uchar *data, int len)
659 {
660 if(write(conn->fd, data, len) != len)
661 sysfatal("write: %r");
662 }
663
664 void
etherwrite(Eapconn * conn,uchar * data,int len)665 etherwrite(Eapconn *conn, uchar *data, int len)
666 {
667 uchar *buf, *p;
668 int n;
669
670 if(debug)
671 fprint(2, "\nreply(v%d,t%d) %E -> %E: ", conn->version, conn->type, conn->smac, conn->amac);
672 n = 2*Eaddrlen + 2 + len;
673 if(n < 60) n = 60; /* ETHERMINTU */
674 p = buf = emalloc(n);
675 /* ethernet header */
676 memmove(p, conn->amac, Eaddrlen); p += Eaddrlen;
677 memmove(p, conn->smac, Eaddrlen); p += Eaddrlen;
678 *p++ = 0x88;
679 *p++ = 0x8e;
680 /* eapol data */
681 memmove(p, data, len);
682 fdwrite(conn, buf, n);
683 free(buf);
684 }
685
686 void
eapwrite(Eapconn * conn,uchar * data,int len)687 eapwrite(Eapconn *conn, uchar *data, int len)
688 {
689 uchar *buf, *p;
690
691 p = buf = emalloc(len + 4);
692 /* eapol header */
693 *p++ = conn->version;
694 *p++ = conn->type;
695 *p++ = len >> 8;
696 *p++ = len;
697 /* eap data */
698 memmove(p, data, len); p += len;
699 etherwrite(conn, buf, p - buf);
700 free(buf);
701 }
702
703 void
replykey(Eapconn * conn,int flags,Keydescr * kd,uchar * data,int datalen)704 replykey(Eapconn *conn, int flags, Keydescr *kd, uchar *data, int datalen)
705 {
706 uchar buf[4096], *p = buf;
707
708 /* eapol hader */
709 *p++ = conn->version;
710 *p++ = conn->type;
711 datalen += Keydescrlen;
712 *p++ = datalen >> 8;
713 *p++ = datalen;
714 datalen -= Keydescrlen;
715 /* key header */
716 memmove(p, kd, Keydescrlen);
717 kd = (Keydescr*)p;
718 kd->flags[0] = flags >> 8;
719 kd->flags[1] = flags;
720 kd->datalen[0] = datalen >> 8;
721 kd->datalen[1] = datalen;
722 /* key data */
723 p = kd->data;
724 memmove(p, data, datalen);
725 p += datalen;
726 /* mic */
727 memset(kd->mic, 0, MIClen);
728 if(flags & Fmic)
729 calcmic(kd, buf, p - buf);
730 etherwrite(conn, buf, p - buf);
731 if(debug)
732 dumpkeydescr(kd);
733 }
734
735 void
eapresp(Eapconn * conn,int code,int id,uchar * data,int len)736 eapresp(Eapconn *conn, int code, int id, uchar *data, int len)
737 {
738 uchar *buf, *p;
739
740 len += 4;
741 p = buf = emalloc(len);
742 /* eap header */
743 *p++ = code;
744 *p++ = id;
745 *p++ = len >> 8;
746 *p++ = len;
747 memmove(p, data, len-4);
748 (*conn->write)(conn, buf, len);
749 free(buf);
750
751 if(debug)
752 fprint(2, "eapresp(code=%d, id=%d, data=%.*H)\n", code, id, len-4, data);
753 }
754
755 void
tlsreader(TLStunn * tunn,Eapconn * conn)756 tlsreader(TLStunn *tunn, Eapconn *conn)
757 {
758 enum {
759 Tlshdrsz = 5,
760 TLStunnhdrsz = 6,
761 };
762 uchar *rec, *w, *p;
763 int fd, n, css;
764
765 fd = tunn->fd;
766 rec = nil;
767 css = 0;
768 Reset:
769 w = rec;
770 w += TLStunnhdrsz;
771 for(;;w += n){
772 if((p = realloc(rec, (w - rec) + Tlshdrsz)) == nil)
773 break;
774 w = p + (w - rec), rec = p;
775 if(readn(fd, w, Tlshdrsz) != Tlshdrsz)
776 break;
777 n = w[3]<<8 | w[4];
778 if(n < 1)
779 break;
780 if((p = realloc(rec, (w - rec) + Tlshdrsz+n)) == nil)
781 break;
782 w = p + (w - rec), rec = p;
783 if(readn(fd, w+Tlshdrsz, n) != n)
784 break;
785 n += Tlshdrsz;
786
787 /* batch records that need to be send together */
788 if(!css){
789 /* Client Certificate */
790 if(w[0] == 22 && w[5] == 11)
791 continue;
792 /* Client Key Exchange */
793 if(w[0] == 22 && w[5] == 16)
794 continue;
795 /* Change Cipher Spec */
796 if(w[0] == 20){
797 css = 1;
798 continue;
799 }
800 }
801
802 /* do not forward alert, close connection */
803 if(w[0] == 21)
804 break;
805
806 /* check if we'r still the tunnel for this connection */
807 if(conn->tunn != tunn)
808 break;
809
810 /* flush records in encapsulation */
811 p = rec + TLStunnhdrsz;
812 w += n;
813 n = w - p;
814 *(--p) = n;
815 *(--p) = n >> 8;
816 *(--p) = n >> 16;
817 *(--p) = n >> 24;
818 *(--p) = 0x80; /* flags: Length included */
819 *(--p) = tunn->tp;
820
821 eapresp(conn, 2, tunn->id, p, w - p);
822 goto Reset;
823 }
824 free(rec);
825 }
826
827 void ttlsclient(int);
828 void peapclient(int);
829
830 void
eapreset(Eapconn * conn)831 eapreset(Eapconn *conn)
832 {
833 TLStunn *tunn;
834
835 tunn = conn->tunn;
836 if(tunn == nil)
837 return;
838 if(debug)
839 fprint(2, "eapreset: kill client %d\n", tunn->clientpid);
840 conn->tunn = nil;
841 postnote(PNPROC, tunn->clientpid, "kill");
842 }
843
844 int
tlswrap(int fd,char * label)845 tlswrap(int fd, char *label)
846 {
847 TLSconn *tls;
848
849 tls = emalloc(sizeof(TLSconn));
850 if(debug)
851 tls->trace = print;
852 if(label != nil){
853 /* tls client computes the 1024 bit MSK for us */
854 tls->sessionType = "ttls";
855 tls->sessionConst = label;
856 tls->sessionKeylen = 128;
857 tls->sessionKey = emalloc(tls->sessionKeylen);
858 }
859 fd = tlsClient(fd, tls);
860 if(fd < 0)
861 sysfatal("tlsClient: %r");
862 if(label != nil && tls->sessionKey != nil){
863 /*
864 * PMK is derived from MSK by taking the first 256 bits.
865 * we store the PMK into factotum with setpmk() associated
866 * with the current essid.
867 */
868 if(setpmk(tls->sessionKey) < 0)
869 sysfatal("setpmk: %r");
870
871 /* destroy session key */
872 memset(tls->sessionKey, 0, tls->sessionKeylen);
873 }
874 free(tls->cert); /* TODO: check cert */
875 free(tls->sessionID);
876 free(tls->sessionKey);
877 free(tls);
878 return fd;
879 }
880
881 void
eapreq(Eapconn * conn,int code,int id,uchar * data,int datalen)882 eapreq(Eapconn *conn, int code, int id, uchar *data, int datalen)
883 {
884 TLStunn *tunn;
885 int tp, frag;
886 char *user;
887
888 if(debug)
889 fprint(2, "eapreq(code=%d, id=%d, data=%.*H)\n", code, id, datalen, data);
890
891 switch(code){
892 case 1: /* Request */
893 break;
894 case 4: /* NAK */
895 case 3: /* Success */
896 eapreset(conn);
897 if(code == 4 || debug)
898 fprint(2, "%s: eap code %s\n", argv0, code == 3 ? "Success" : "NAK");
899 return;
900 default:
901 unhandled:
902 if(debug)
903 fprint(2, "unhandled: %.*H\n", datalen < 0 ? 0 : datalen, data);
904 return;
905 }
906 if(datalen < 1)
907 goto unhandled;
908
909 tp = data[0];
910 switch(tp){
911 case 1: /* Identity */
912 user = getidentity();
913 datalen = 1+strlen(user);
914 memmove(data+1, user, datalen-1);
915 eapresp(conn, 2, id, data, datalen);
916 return;
917 case 2:
918 fprint(2, "%s: eap error: %.*s\n",
919 argv0, utfnlen((char*)data+1, datalen-1), (char*)data+1);
920 return;
921 case 33: /* EAP Extensions (AVP) */
922 if(debug)
923 fprint(2, "eap extension: %.*H\n", datalen, data);
924 eapresp(conn, 2, id, data, datalen);
925 return;
926 case 26: /* MS-CHAP-V2 */
927 data++;
928 datalen--;
929 if(datalen < 1)
930 break;
931
932 /* OpCode */
933 switch(data[0]){
934 case 1: /* Challenge */
935 if(datalen > 4) {
936 uchar cid, chal[16], resp[48];
937 char user[256+1];
938 int len;
939
940 cid = data[1];
941 len = data[2]<<8 | data[3];
942 if(data[4] != sizeof(chal))
943 break;
944 if(len > datalen || (5 + data[4]) > len)
945 break;
946 memmove(chal, data+5, sizeof(chal));
947 memset(user, 0, sizeof(user));
948 memset(resp, 0, sizeof(resp));
949 if(auth_respond(chal, sizeof(chal), user, sizeof(user), resp, sizeof(resp), nil,
950 "proto=mschapv2 role=client service=wpa essid=%q", essid) < 0){
951 fprint(2, "%s: eap mschapv2: auth_respond: %r\n", argv0);
952 break;
953 }
954 len = 5 + sizeof(resp) + 1 + strlen(user);
955 data[0] = 2; /* OpCode - Response */
956 data[1] = cid; /* Identifier */
957 data[2] = len >> 8;
958 data[3] = len;
959 data[4] = sizeof(resp)+1; /* ValueSize */
960 memmove(data+5, resp, sizeof(resp));
961 data[5 + sizeof(resp)] = 0; /* flags */
962 strcpy((char*)&data[5 + sizeof(resp) + 1], user);
963
964 *(--data) = tp, len++;
965 eapresp(conn, 2, id, data, len);
966 return;
967 }
968 break;
969
970 case 3: /* Success */
971 case 4: /* Failure */
972 if(debug || data[0] == 4)
973 fprint(2, "%s: eap mschapv2 %s: %.*s\n", argv0,
974 data[0] == 3 ? "Success" : "Failure",
975 datalen < 4 ? 0 : utfnlen((char*)data+4, datalen-4), (char*)data+4);
976 *(--data) = tp;
977 eapresp(conn, 2, id, data, 2);
978 return;
979 }
980 break;
981
982 case 21: /* EAP-TTLS */
983 case 25: /* PEAP */
984 if(datalen < 2)
985 break;
986 datalen -= 2;
987 data++;
988 tunn = conn->tunn;
989 if(*data & 0x20){ /* flags: start */
990 int p[2], pid;
991
992 if(tunn != nil){
993 if(tunn->id == id && tunn->tp == tp)
994 break; /* is retransmit, ignore */
995 eapreset(conn);
996 }
997 if(pipe(p) < 0)
998 sysfatal("pipe: %r");
999 if((pid = fork()) == -1)
1000 sysfatal("fork: %r");
1001 if(pid == 0){
1002 close(p[0]);
1003 switch(tp){
1004 case 21:
1005 ttlsclient(p[1]);
1006 break;
1007 case 25:
1008 peapclient(p[1]);
1009 break;
1010 }
1011 exits(nil);
1012 }
1013 close(p[1]);
1014 tunn = emalloc(sizeof(TLStunn));
1015 tunn->tp = tp;
1016 tunn->id = id;
1017 tunn->fd = p[0];
1018 tunn->clientpid = pid;
1019 conn->tunn = tunn;
1020 if((pid = rfork(RFPROC|RFMEM)) == -1)
1021 sysfatal("fork: %r");
1022 if(pid == 0){
1023 tunn->readerpid = getpid();
1024 tlsreader(tunn, conn);
1025 if(conn->tunn == tunn)
1026 conn->tunn = nil;
1027 close(tunn->fd);
1028 free(tunn);
1029 exits(nil);
1030 }
1031 return;
1032 }
1033 if(tunn == nil)
1034 break;
1035 if(id <= tunn->id || tunn->tp != tp)
1036 break;
1037 tunn->id = id;
1038 frag = *data & 0x40; /* flags: more fragments */
1039 if(*data & 0x80){ /* flags: length included */
1040 datalen -= 4;
1041 data += 4;
1042 }
1043 data++;
1044 if(datalen > 0)
1045 write(tunn->fd, data, datalen);
1046 if(frag || (tp == 25 && data[0] == 20)){ /* ack change cipher spec */
1047 data -= 2;
1048 data[0] = tp;
1049 data[1] = 0;
1050 eapresp(conn, 2, id, data, 2);
1051 }
1052 return;
1053 }
1054 goto unhandled;
1055 }
1056
1057 int
avp(uchar * p,int n,int code,void * val,int len,int pad)1058 avp(uchar *p, int n, int code, void *val, int len, int pad)
1059 {
1060 pad = 8 + ((len + pad) & ~pad); /* header + data + data pad */
1061 assert(((pad + 3) & ~3) <= n);
1062 p[0] = code >> 24;
1063 p[1] = code >> 16;
1064 p[2] = code >> 8;
1065 p[3] = code;
1066 p[4] = 2;
1067 p[5] = pad >> 16;
1068 p[6] = pad >> 8;
1069 p[7] = pad;
1070 memmove(p+8, val, len);
1071 len += 8;
1072 pad = (pad + 3) & ~3; /* packet padding */
1073 memset(p+len, 0, pad - len);
1074 return pad;
1075 }
1076
1077 enum {
1078 /* Avp Code */
1079 AvpUserName = 1,
1080 AvpUserPass = 2,
1081 AvpChapPass = 3,
1082 AvpChapChal = 60,
1083 };
1084
1085 void
ttlsclient(int fd)1086 ttlsclient(int fd)
1087 {
1088 uchar buf[4096];
1089 UserPasswd *up;
1090 int n;
1091
1092 fd = tlswrap(fd, "ttls keying material");
1093 if((up = auth_getuserpasswd(nil, "proto=pass service=wpa essid=%q", essid)) == nil)
1094 sysfatal("auth_getuserpasswd: %r");
1095 n = avp(buf, sizeof(buf), AvpUserName, up->user, strlen(up->user), 0);
1096 n += avp(buf+n, sizeof(buf)-n, AvpUserPass, up->passwd, strlen(up->passwd), 15);
1097 freeup(up);
1098 write(fd, buf, n);
1099 memset(buf, 0, n);
1100 }
1101
1102 void
peapwrite(Eapconn * conn,uchar * data,int len)1103 peapwrite(Eapconn *conn, uchar *data, int len)
1104 {
1105 assert(len >= 4);
1106 fdwrite(conn, data + 4, len - 4);
1107 }
1108
1109 void
peapclient(int fd)1110 peapclient(int fd)
1111 {
1112 static Eapconn conn;
1113 uchar buf[4096], *p;
1114 int n, id, code;
1115
1116 conn.fd = fd = tlswrap(fd, "client EAP encryption");
1117 while((n = read(fd, p = buf, sizeof(buf))) > 0){
1118 if(n > 4 && (p[2] << 8 | p[3]) == n && p[4] == 33){
1119 code = p[0];
1120 id = p[1];
1121 p += 4, n -= 4;
1122 conn.write = fdwrite;
1123 } else {
1124 code = 1;
1125 id = 0;
1126 conn.write = peapwrite;
1127 }
1128 eapreq(&conn, code, id, p, n);
1129 }
1130 }
1131
1132 void
usage(void)1133 usage(void)
1134 {
1135 fprint(2, "%s: [-dp12] [-s essid] dev\n", argv0);
1136 exits("usage");
1137 }
1138
1139 void
background(void)1140 background(void)
1141 {
1142 if(forked || debug)
1143 return;
1144 switch(rfork(RFNOTEG|RFREND|RFPROC|RFNOWAIT)){
1145 default:
1146 exits(nil);
1147 case -1:
1148 sysfatal("fork: %r");
1149 return;
1150 case 0:
1151 break;
1152 }
1153 forked = 1;
1154 }
1155
1156 void
main(int argc,char * argv[])1157 main(int argc, char *argv[])
1158 {
1159 uchar mac[Eaddrlen], buf[4096], snonce[Noncelen], anonce[Noncelen];
1160 static uchar brsne[258];
1161 static Eapconn conn;
1162 char addr[128];
1163 uchar *rsne;
1164 int newptk; /* gate key reinstallation */
1165 int rsnelen;
1166 int n, try;
1167
1168 quotefmtinstall();
1169 fmtinstall('H', encodefmt);
1170 fmtinstall('E', eipfmt);
1171
1172 rsne = nil;
1173 rsnelen = -1;
1174 peercipher = nil;
1175 groupcipher = nil;
1176
1177 ARGBEGIN {
1178 case 'd':
1179 debug = 1;
1180 break;
1181 case 'p':
1182 prompt = 1;
1183 break;
1184 case 's':
1185 strncpy(essid, EARGF(usage()), 32);
1186 break;
1187 case '1':
1188 rsne = wpaie;
1189 rsnelen = sizeof(wpaie);
1190 peercipher = &tkip;
1191 groupcipher = &tkip;
1192 break;
1193 case '2':
1194 rsne = rsnie;
1195 rsnelen = sizeof(rsnie);
1196 peercipher = &ccmp;
1197 groupcipher = &ccmp;
1198 break;
1199 default:
1200 usage();
1201 } ARGEND;
1202
1203 if(*argv != nil)
1204 dev = *argv++;
1205
1206 if(*argv != nil || dev == nil)
1207 usage();
1208
1209 if(myetheraddr(mac, dev) < 0)
1210 sysfatal("can't get mac address: %r");
1211
1212 snprint(addr, sizeof(addr), "%s!0x888e", dev);
1213 if((fd = dial(addr, nil, devdir, &cfd)) < 0)
1214 sysfatal("dial: %r");
1215
1216 if(essid[0] != 0){
1217 if(fprint(cfd, "essid %q", essid) < 0)
1218 sysfatal("write essid: %r");
1219 } else if(prompt) {
1220 getessid();
1221 if(essid[0] == 0)
1222 sysfatal("no essid set");
1223 }
1224 if(!prompt)
1225 background();
1226
1227 Connect:
1228 /* bss scan might not be complete yet, so check for 10 seconds. */
1229 for(try = 100; (forked || try >= 0) && !connected(); try--)
1230 sleep(100);
1231
1232 authtype = AuthPSK;
1233 if(rsnelen <= 0 || rsne == brsne){
1234 rsne = brsne;
1235 rsnelen = buildrsne(rsne);
1236 }
1237 if(rsnelen > 0){
1238 if(debug)
1239 fprint(2, "rsne: %.*H\n", rsnelen, rsne);
1240 /*
1241 * we use write() instead of fprint so the message gets written
1242 * at once and not chunked up on fprint buffer.
1243 */
1244 n = sprint((char*)buf, "auth %.*H", rsnelen, rsne);
1245 if(write(cfd, buf, n) != n)
1246 sysfatal("write auth: %r");
1247 } else {
1248 authtype = AuthNone;
1249 }
1250
1251 conn.fd = fd;
1252 conn.write = eapwrite;
1253 conn.type = 1; /* Start */
1254 conn.version = 1;
1255 memmove(conn.smac, mac, Eaddrlen);
1256 getbssid(conn.amac);
1257
1258 if(prompt){
1259 UserPasswd *up;
1260 prompt = 0;
1261 switch(authtype){
1262 case AuthNone:
1263 print("no authentication required\n");
1264 break;
1265 case AuthPSK:
1266 /* dummy to for factotum keyprompt */
1267 genrandom(anonce, sizeof(anonce));
1268 genrandom(snonce, sizeof(snonce));
1269 getptk(auth_getkey, conn.smac, conn.amac, snonce, anonce, ptk);
1270 break;
1271 case AuthWPA:
1272 up = auth_getuserpasswd(auth_getkey, "proto=pass service=wpa essid=%q", essid);
1273 if(up != nil){
1274 factotumctl("key proto=mschapv2 role=client service=wpa"
1275 " essid=%q user=%q !password=%q\n",
1276 essid, up->user, up->passwd);
1277 freeup(up);
1278 }
1279 break;
1280 }
1281 background();
1282 }
1283
1284 genrandom(ptk, sizeof(ptk));
1285 newptk = 0;
1286
1287 lastrepc = 0ULL;
1288 for(;;){
1289 uchar *p, *e, *m;
1290 int proto, flags, vers, datalen;
1291 uvlong repc, rsc, tsc;
1292 Keydescr *kd;
1293
1294 if((n = read(fd, buf, sizeof(buf))) < 0)
1295 sysfatal("read: %r");
1296
1297 if(n == 0){
1298 if(debug)
1299 fprint(2, "got deassociation\n");
1300 eapreset(&conn);
1301 goto Connect;
1302 }
1303
1304 p = buf;
1305 e = buf+n;
1306 if(n < 2*Eaddrlen + 2)
1307 continue;
1308
1309 memmove(conn.smac, p, Eaddrlen); p += Eaddrlen;
1310 memmove(conn.amac, p, Eaddrlen); p += Eaddrlen;
1311 proto = p[0]<<8 | p[1]; p += 2;
1312
1313 if(proto != 0x888e || memcmp(conn.smac, mac, Eaddrlen) != 0)
1314 continue;
1315
1316 m = p;
1317 n = e - p;
1318 if(n < 4)
1319 continue;
1320
1321 conn.version = p[0];
1322 if(conn.version != 0x01 && conn.version != 0x02)
1323 continue;
1324 conn.type = p[1];
1325 n = p[2]<<8 | p[3];
1326 p += 4;
1327 if(p+n > e)
1328 continue;
1329 e = p + n;
1330
1331 if(debug)
1332 fprint(2, "\nrecv(v%d,t%d) %E <- %E: ", conn.version, conn.type, conn.smac, conn.amac);
1333
1334 if(authtype == AuthNone)
1335 continue;
1336
1337 if(conn.type == 0x00 && authtype == AuthWPA){
1338 uchar code, id;
1339
1340 if(n < 4)
1341 continue;
1342 code = p[0];
1343 id = p[1];
1344 n = p[3] | p[2]<<8;
1345 if(n < 4 || p + n > e)
1346 continue;
1347 p += 4, n -= 4;
1348 eapreq(&conn, code, id, p, n);
1349 continue;
1350 }
1351
1352 if(conn.type != 0x03)
1353 continue;
1354
1355 if(n < Keydescrlen){
1356 if(debug)
1357 fprint(2, "bad kd size\n");
1358 continue;
1359 }
1360 kd = (Keydescr*)p;
1361 if(debug)
1362 dumpkeydescr(kd);
1363
1364 if(kd->type[0] != 0xFE && kd->type[0] != 0x02)
1365 continue;
1366
1367 vers = kd->flags[1] & 7;
1368 flags = kd->flags[0]<<8 | kd->flags[1];
1369 datalen = kd->datalen[0]<<8 | kd->datalen[1];
1370 if(kd->data + datalen > e)
1371 continue;
1372
1373 if((flags & Fmic) == 0){
1374 if((flags & (Fptk|Fack)) != (Fptk|Fack))
1375 continue;
1376
1377 memmove(anonce, kd->nonce, sizeof(anonce));
1378 genrandom(snonce, sizeof(snonce));
1379 if(getptk(nil, conn.smac, conn.amac, snonce, anonce, ptk) != 0){
1380 if(debug)
1381 fprint(2, "getptk: %r\n");
1382 continue;
1383 }
1384 /* allow installation of new keys */
1385 newptk = 1;
1386
1387 /* ack key exchange with mic */
1388 memset(kd->rsc, 0, sizeof(kd->rsc));
1389 memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
1390 memmove(kd->nonce, snonce, sizeof(kd->nonce));
1391 replykey(&conn, (flags & ~(Fack|Fins)) | Fmic, kd, rsne, rsnelen);
1392 } else {
1393 uchar gtk[GTKlen];
1394 int gtklen, gtkkid;
1395
1396 if(checkmic(kd, m, e - m) != 0){
1397 if(debug)
1398 fprint(2, "bad mic\n");
1399 continue;
1400 }
1401
1402 repc = (uvlong)kd->repc[7] |
1403 (uvlong)kd->repc[6]<<8 |
1404 (uvlong)kd->repc[5]<<16 |
1405 (uvlong)kd->repc[4]<<24 |
1406 (uvlong)kd->repc[3]<<32 |
1407 (uvlong)kd->repc[2]<<40 |
1408 (uvlong)kd->repc[1]<<48 |
1409 (uvlong)kd->repc[0]<<56;
1410 if(repc <= lastrepc){
1411 if(debug)
1412 fprint(2, "bad repc: %llux <= %llux\n", repc, lastrepc);
1413 continue;
1414 }
1415 lastrepc = repc;
1416
1417 rsc = (uvlong)kd->rsc[0] |
1418 (uvlong)kd->rsc[1]<<8 |
1419 (uvlong)kd->rsc[2]<<16 |
1420 (uvlong)kd->rsc[3]<<24 |
1421 (uvlong)kd->rsc[4]<<32 |
1422 (uvlong)kd->rsc[5]<<40;
1423
1424 if(datalen > 0 && (flags & Fenc) != 0){
1425 if(vers == 1)
1426 datalen = rc4unwrap(ptk+16, kd->eapoliv, kd->data, datalen);
1427 else
1428 datalen = aesunwrap(ptk+16, 16, kd->data, datalen);
1429 if(datalen <= 0){
1430 if(debug)
1431 fprint(2, "bad keywrap\n");
1432 continue;
1433 }
1434 if(debug)
1435 fprint(2, "unwraped keydata[%.4x]=%.*H\n", datalen, datalen, kd->data);
1436 }
1437
1438 gtklen = 0;
1439 gtkkid = -1;
1440
1441 if(kd->type[0] != 0xFE || (flags & (Fptk|Fack)) == (Fptk|Fack)){
1442 uchar *p, *x, *e;
1443
1444 p = kd->data;
1445 e = p + datalen;
1446 for(; p+2 <= e; p = x){
1447 if((x = p+2+p[1]) > e)
1448 break;
1449 if(debug)
1450 fprint(2, "ie=%.2x data[%.2x]=%.*H\n", p[0], p[1], p[1], p+2);
1451 if(p[0] == 0x30){ /* RSN */
1452 }
1453 if(p[0] == 0xDD){ /* WPA */
1454 static uchar oui[] = { 0x00, 0x0f, 0xac, 0x01, };
1455
1456 if(p+2+sizeof(oui) > x || memcmp(p+2, oui, sizeof(oui)) != 0)
1457 continue;
1458 if((flags & Fenc) == 0)
1459 continue; /* ignore gorup key if unencrypted */
1460 gtklen = x - (p + 8);
1461 if(gtklen <= 0)
1462 continue;
1463 if(gtklen > sizeof(gtk))
1464 gtklen = sizeof(gtk);
1465 memmove(gtk, p + 8, gtklen);
1466 gtkkid = p[6] & 3;
1467 }
1468 }
1469 }
1470
1471 if((flags & (Fptk|Fack)) == (Fptk|Fack)){
1472 if(!newptk) /* a retransmit, already installed PTK */
1473 continue;
1474 if(vers != 1) /* in WPA2, RSC is for group key only */
1475 tsc = 0LL;
1476 else {
1477 tsc = rsc;
1478 rsc = 0LL;
1479 }
1480 /* install pairwise receive key (PTK) */
1481 if(fprint(cfd, "rxkey %E %s:%.*H@%llux", conn.amac,
1482 peercipher->name, peercipher->keylen, ptk+32, tsc) < 0)
1483 sysfatal("write rxkey: %r");
1484
1485 memset(kd->rsc, 0, sizeof(kd->rsc));
1486 memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
1487 memset(kd->nonce, 0, sizeof(kd->nonce));
1488 replykey(&conn, flags & ~(Fack|Fenc|Fins), kd, nil, 0);
1489 sleep(100);
1490
1491 tsc = 0LL;
1492 /* install pairwise transmit key (PTK) */
1493 if(fprint(cfd, "txkey %E %s:%.*H@%llux", conn.amac,
1494 peercipher->name, peercipher->keylen, ptk+32, tsc) < 0)
1495 sysfatal("write txkey: %r");
1496 newptk = 0; /* prevent PTK re-installation on (replayed) retransmits */
1497 } else
1498 if((flags & (Fptk|Fsec|Fack)) == (Fsec|Fack)){
1499 if(kd->type[0] == 0xFE){
1500 /* WPA always RC4 encrypts the GTK, even tho the flag isnt set */
1501 if((flags & Fenc) == 0)
1502 datalen = rc4unwrap(ptk+16, kd->eapoliv, kd->data, datalen);
1503 gtklen = datalen;
1504 if(gtklen > sizeof(gtk))
1505 gtklen = sizeof(gtk);
1506 memmove(gtk, kd->data, gtklen);
1507 gtkkid = (flags >> 4) & 3;
1508 }
1509 memset(kd->rsc, 0, sizeof(kd->rsc));
1510 memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
1511 memset(kd->nonce, 0, sizeof(kd->nonce));
1512 replykey(&conn, flags & ~(Fenc|Fack), kd, nil, 0);
1513 } else
1514 continue;
1515 /* install group key (GTK) */
1516 if(gtklen >= groupcipher->keylen && gtkkid != -1)
1517 if(fprint(cfd, "rxkey%d %E %s:%.*H@%llux",
1518 gtkkid, conn.amac,
1519 groupcipher->name, groupcipher->keylen, gtk, rsc) < 0)
1520 sysfatal("write rxkey%d: %r", gtkkid);
1521 }
1522 }
1523 }
1524