29 Keydescrlen = 1+2+2+8+32+16+8+8+16+2,
32 typedef struct Keydescr Keydescr;
48 typedef struct Cipher Cipher;
55 typedef struct Eapconn Eapconn;
56 typedef struct TLStunn TLStunn;
69 void (*write)(Eapconn*, uchar *data, int datalen);
83 Cipher tkip = { "tkip", 32 };
84 Cipher ccmp = { "ccmp", 16 };
100 uchar rsntkipoui[4] = {0x00, 0x0F, 0xAC, 0x02};
101 uchar rsnccmpoui[4] = {0x00, 0x0F, 0xAC, 0x04};
102 uchar rsnapskoui[4] = {0x00, 0x0F, 0xAC, 0x02};
103 uchar rsnawpaoui[4] = {0x00, 0x0F, 0xAC, 0x01};
108 0x01, 0x00, /* version 1 */
109 0x00, 0x0F, 0xAC, 0x04, /* group cipher suite CCMP */
110 0x01, 0x00, /* pairwise cipher suite count 1 */
111 0x00, 0x0F, 0xAC, 0x04, /* pairwise cipher suite CCMP */
112 0x01, 0x00, /* authentication suite count 1 */
113 0x00, 0x0F, 0xAC, 0x02, /* authentication suite PSK */
114 0x00, 0x00, /* capabilities */
117 uchar wpa1oui[4] = {0x00, 0x50, 0xF2, 0x01};
118 uchar wpatkipoui[4] = {0x00, 0x50, 0xF2, 0x02};
119 uchar wpaapskoui[4] = {0x00, 0x50, 0xF2, 0x02};
120 uchar wpaawpaoui[4] = {0x00, 0x50, 0xF2, 0x01};
123 0xdd, /* vendor specific */
125 0x00, 0x50, 0xf2, 0x01, /* WPAIE type 1 */
126 0x01, 0x00, /* version 1 */
127 0x00, 0x50, 0xf2, 0x02, /* group cipher suite TKIP */
128 0x01, 0x00, /* pairwise cipher suite count 1 */
129 0x00, 0x50, 0xf2, 0x02, /* pairwise cipher suite TKIP */
130 0x01, 0x00, /* authentication suite count 1 */
131 0x00, 0x50, 0xf2, 0x02, /* authentication suite PSK */
139 if((v = mallocz(len, 1)) == nil)
140 sysfatal("malloc: %r");
145 hextob(char *s, char **sp, uchar *b, int n)
150 for(r = 0; r < n && *s; s++){
152 if(*s >= '0' && *s <= '9')
154 else if(*s >= 'a' && *s <= 'f')
156 else if(*s >= 'A' && *s <= 'F')
168 getifstats(char *key, char *val, int nval)
170 char buf[8*1024], *f[2], *p, *e;
173 snprint(buf, sizeof(buf), "%s/ifstats", devdir);
174 if((fd = open(buf, OREAD)) < 0)
176 n = readn(fd, buf, sizeof(buf)-1);
181 for(p = buf; (e = strchr(p, '\n')) != nil; p = e){
183 if(gettokens(p, f, 2, "\t\r\n ") != 2)
185 if(strcmp(f[0], key) != 0)
187 strncpy(val, f[1], nval);
197 return getifstats("essid:", essid, sizeof(essid));
201 getbssid(uchar mac[Eaddrlen])
205 if(getifstats("bssid:", buf, sizeof(buf)) != nil)
206 return parseether(mac, buf);
215 if(getifstats("status:", status, sizeof(status)) == nil)
217 if(strcmp(status, "connecting") == 0)
219 if(strcmp(status, "unauthenticated") == 0)
222 if(strcmp(status, "blocked") != 0 && strcmp(status, "associated") != 0)
226 fprint(2, "status: %s\n", status);
231 buildrsne(uchar rsne[258])
239 if(getifstats("brsne:", buf, sizeof(buf)) == nil)
240 return 0; /* not an error, might be old kernel */
242 brsnelen = hextob(buf, nil, brsne, sizeof(brsne));
244 trunc: sysfatal("invalid or truncated RSNE; brsne: %s", buf);
256 *w++ = 0; /* length */
257 } else if(p[0] == 0xDD){
259 if((e - p) < 4 || memcmp(p, wpa1oui, 4) != 0){
260 sysfatal("unrecognized WPAIE type; brsne: %s", buf);
266 *w++ = 0; /* length */
268 memmove(w, wpa1oui, 4);
272 sysfatal("unrecognized RSNE type; brsne: %s", buf);
279 *w++ = *p++; /* version */
283 if(memcmp(p, rsnccmpoui, 4) == 0)
285 else if(memcmp(p, rsntkipoui, 4) == 0)
288 sysfatal("unrecognized RSN group cipher; brsne: %s", buf);
292 if(memcmp(p, wpatkipoui, 4) != 0){
293 sysfatal("unrecognized WPA group cipher; brsne: %s", buf);
299 memmove(w, p, 4); /* group cipher */
306 *w++ = 0x01; /* # of peer ciphers */
319 if(rsne[0] == 0x30 && memcmp(p, rsnccmpoui, 4) == 0 && peercipher == &tkip)
323 if(peercipher == &ccmp)
324 memmove(w, rsnccmpoui, 4);
325 else if(rsne[0] == 0x30)
326 memmove(w, rsntkipoui, 4);
328 memmove(w, wpatkipoui, 4);
334 *w++ = 0x01; /* # of auth suites */
347 /* look for PSK oui */
348 if(memcmp(p, rsnapskoui, 4) == 0)
350 /* look for WPA oui */
351 if(memcmp(p, rsnawpaoui, 4) == 0){
356 /* look for PSK oui */
357 if(memcmp(p, wpaapskoui, 4) == 0)
359 /* look for WPA oui */
360 if(memcmp(p, wpaawpaoui, 4) == 0){
368 sysfatal("auth suite is not PSK or WPA; brsne: %s", buf);
381 rsne[1] = (w - rsne) - 2;
386 factotumattr(char *attr, char *fmt, ...)
395 if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
397 if((rpc = auth_allocrpc(afd)) == nil){
402 vsnprint(buf, sizeof(buf), fmt, list);
405 if(auth_rpc(rpc, "start", buf, strlen(buf)) == 0){
406 if((a = auth_attr(rpc)) != nil){
407 if((val = _strfindattr(a, attr)) != nil)
419 freeup(UserPasswd *up)
421 memset(up->user, 0, strlen(up->user));
422 memset(up->passwd, 0, strlen(up->passwd));
429 static char *identity;
434 if(getessid() == nil)
436 if((s = factotumattr("user", "proto=pass service=wpa essid=%q", essid)) != nil)
438 if((s = factotumattr("user", "proto=mschapv2 role=client service=wpa essid=%q", essid)) != nil)
445 } else if(identity == nil)
446 identity = strdup("anonymous");
448 fprint(2, "identity: %s\n", identity);
453 factotumctl(char *fmt, ...)
460 if((fd = open("/mnt/factotum/ctl", OWRITE)) >= 0){
462 s = vsmprint(fmt, list);
476 setpmk(uchar pmk[PMKlen])
478 if(getessid() == nil)
480 return factotumctl("key proto=wpapsk role=client essid=%q !password=%.*H\n", essid, PMKlen, pmk);
484 getptk( uchar smac[Eaddrlen], uchar amac[Eaddrlen],
485 uchar snonce[Noncelen], uchar anonce[Noncelen],
488 uchar buf[2*Eaddrlen + 2*Noncelen], *p;
496 if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
498 if((rpc = auth_allocrpc(afd)) == nil)
500 if((s = getessid()) == nil)
502 if((s = smprint("proto=wpapsk role=client essid=%q", s)) == nil)
504 if((ret = auth_rpc(rpc, "start", s, strlen(s))) != ARok)
507 memmove(p, smac, Eaddrlen); p += Eaddrlen;
508 memmove(p, amac, Eaddrlen); p += Eaddrlen;
509 memmove(p, snonce, Noncelen); p += Noncelen;
510 memmove(p, anonce, Noncelen); p += Noncelen;
511 if((ret = auth_rpc(rpc, "write", buf, p - buf)) != ARok)
513 if((ret = auth_rpc(rpc, "read", nil, 0)) != ARok)
515 if(rpc->narg != PTKlen){
519 memmove(ptk, rpc->arg, PTKlen);
523 if(afd >= 0) close(afd);
524 if(rpc != nil) auth_freerpc(rpc);
533 p = va_arg(f->args, uchar*);
538 if(fmtprint(f, "%.2x", *p) < 0)
544 dumpkeydescr(Keydescr *kd)
561 f = kd->flags[0]<<8 | kd->flags[1];
562 fprint(2, "type=%.*H vers=%d flags=%.*H ( ",
563 sizeof(kd->type), kd->type, kd->flags[1] & 7,
564 sizeof(kd->flags), kd->flags);
565 for(i=0; i<nelem(flags); i++)
566 if(flags[i].flag & f)
567 fprint(2, "%s ", flags[i].name);
568 fprint(2, ") len=%.*H\nrepc=%.*H nonce=%.*H\neapoliv=%.*H rsc=%.*H id=%.*H mic=%.*H\n",
569 sizeof(kd->keylen), kd->keylen,
570 sizeof(kd->repc), kd->repc,
571 sizeof(kd->nonce), kd->nonce,
572 sizeof(kd->eapoliv), kd->eapoliv,
573 sizeof(kd->rsc), kd->rsc,
574 sizeof(kd->id), kd->id,
575 sizeof(kd->mic), kd->mic);
576 i = kd->datalen[0]<<8 | kd->datalen[1];
577 fprint(2, "data[%.4x]=%.*H\n", i, i, kd->data);
581 rc4unwrap(uchar key[16], uchar iv[16], uchar *data, int len)
586 memmove(seed, iv, 16);
587 memmove(seed+16, key, 16);
588 setupRC4state(&rs, seed, sizeof(seed));
595 aesunwrap(uchar *key, int nkey, uchar *data, int len)
597 static uchar IV[8] = { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, };
604 if(len < 16 || (len % 8) != 0)
608 setupAESstate(&s, key, nkey, 0);
610 memmove(data, data+8, n*8);
612 for(R = data + (n - 1)*8; R >= data; t--, R -= 8){
618 aes_decrypt(s.dkey, s.rounds, B, B);
622 if(memcmp(B, IV, 8) != 0)
628 calcmic(Keydescr *kd, uchar *msg, int msglen)
632 vers = kd->flags[1] & 7;
633 memset(kd->mic, 0, MIClen);
635 uchar digest[MD5dlen];
637 hmac_md5(msg, msglen, ptk, 16, digest, nil);
638 memmove(kd->mic, digest, MIClen);
642 uchar digest[SHA1dlen];
644 hmac_sha1(msg, msglen, ptk, 16, digest, nil);
645 memmove(kd->mic, digest, MIClen);
652 checkmic(Keydescr *kd, uchar *msg, int msglen)
656 memmove(tmp, kd->mic, MIClen);
657 if(calcmic(kd, msg, msglen) != 0)
659 return memcmp(tmp, kd->mic, MIClen) != 0;
663 fdwrite(Eapconn *conn, uchar *data, int len)
665 if(write(conn->fd, data, len) != len)
666 sysfatal("write: %r");
670 etherwrite(Eapconn *conn, uchar *data, int len)
676 fprint(2, "\nreply(v%d,t%d) %E -> %E: ", conn->version, conn->type, conn->smac, conn->amac);
677 n = 2*Eaddrlen + 2 + len;
678 if(n < 60) n = 60; /* ETHERMINTU */
679 p = buf = emalloc(n);
680 /* ethernet header */
681 memmove(p, conn->amac, Eaddrlen); p += Eaddrlen;
682 memmove(p, conn->smac, Eaddrlen); p += Eaddrlen;
686 memmove(p, data, len);
687 fdwrite(conn, buf, n);
692 eapwrite(Eapconn *conn, uchar *data, int len)
696 p = buf = emalloc(len + 4);
698 *p++ = conn->version;
703 memmove(p, data, len); p += len;
704 etherwrite(conn, buf, p - buf);
709 replykey(Eapconn *conn, int flags, Keydescr *kd, uchar *data, int datalen)
711 uchar buf[4096], *p = buf;
714 *p++ = conn->version;
716 datalen += Keydescrlen;
719 datalen -= Keydescrlen;
721 memmove(p, kd, Keydescrlen);
723 kd->flags[0] = flags >> 8;
724 kd->flags[1] = flags;
725 kd->datalen[0] = datalen >> 8;
726 kd->datalen[1] = datalen;
729 memmove(p, data, datalen);
732 memset(kd->mic, 0, MIClen);
734 calcmic(kd, buf, p - buf);
735 etherwrite(conn, buf, p - buf);
741 eapresp(Eapconn *conn, int code, int id, uchar *data, int len)
746 p = buf = emalloc(len);
752 memmove(p, data, len-4);
753 (*conn->write)(conn, buf, len);
757 fprint(2, "eapresp(code=%d, id=%d, data=%.*H)\n", code, id, len-4, data);
761 tlsreader(TLStunn *tunn, Eapconn *conn)
777 if((p = realloc(rec, (w - rec) + Tlshdrsz)) == nil)
779 w = p + (w - rec), rec = p;
780 if(readn(fd, w, Tlshdrsz) != Tlshdrsz)
785 if((p = realloc(rec, (w - rec) + Tlshdrsz+n)) == nil)
787 w = p + (w - rec), rec = p;
788 if(readn(fd, w+Tlshdrsz, n) != n)
792 /* batch records that need to be send together */
794 /* Client Certificate */
795 if(w[0] == 22 && w[5] == 11)
797 /* Client Key Exchange */
798 if(w[0] == 22 && w[5] == 16)
800 /* Change Cipher Spec */
807 /* do not forward alert, close connection */
811 /* check if we'r still the tunnel for this connection */
812 if(conn->tunn != tunn)
815 /* flush records in encapsulation */
816 p = rec + TLStunnhdrsz;
823 *(--p) = 0x80; /* flags: Length included */
826 eapresp(conn, 2, tunn->id, p, w - p);
832 void ttlsclient(int);
833 void peapclient(int);
836 eapreset(Eapconn *conn)
844 fprint(2, "eapreset: kill client %d\n", tunn->clientpid);
846 postnote(PNPROC, tunn->clientpid, "kill");
850 tlswrap(int fd, char *label)
854 tls = emalloc(sizeof(TLSconn));
858 /* tls client computes the 1024 bit MSK for us */
859 tls->sessionType = "ttls";
860 tls->sessionConst = label;
861 tls->sessionKeylen = 128;
862 tls->sessionKey = emalloc(tls->sessionKeylen);
864 fd = tlsClient(fd, tls);
866 sysfatal("tlsClient: %r");
867 if(label != nil && tls->sessionKey != nil){
869 * PMK is derived from MSK by taking the first 256 bits.
870 * we store the PMK into factotum with setpmk() associated
871 * with the current essid.
873 if(setpmk(tls->sessionKey) < 0)
874 sysfatal("setpmk: %r");
876 /* destroy session key */
877 memset(tls->sessionKey, 0, tls->sessionKeylen);
879 free(tls->cert); /* TODO: check cert */
880 free(tls->sessionID);
881 free(tls->sessionKey);
887 eapreq(Eapconn *conn, int code, int id, uchar *data, int datalen)
894 fprint(2, "eapreq(code=%d, id=%d, data=%.*H)\n", code, id, datalen, data);
897 case 1: /* Request */
900 case 3: /* Success */
902 if(code == 4 || debug)
903 fprint(2, "%s: eap code %s\n", argv0, code == 3 ? "Success" : "NAK");
908 fprint(2, "unhandled: %.*H\n", datalen < 0 ? 0 : datalen, data);
916 case 1: /* Identity */
917 user = getidentity();
918 datalen = 1+strlen(user);
919 memmove(data+1, user, datalen-1);
920 eapresp(conn, 2, id, data, datalen);
923 fprint(2, "%s: eap error: %.*s\n", argv0, datalen-1, (char*)data+1);
925 case 33: /* EAP Extensions (AVP) */
927 fprint(2, "eap extension: %.*H\n", datalen, data);
928 eapresp(conn, 2, id, data, datalen);
930 case 26: /* MS-CHAP-V2 */
938 case 1: /* Challenge */
940 uchar cid, chal[16], resp[48];
945 len = data[2]<<8 | data[3];
946 if(data[4] != sizeof(chal))
948 if(len > datalen || (5 + data[4]) > len)
950 memmove(chal, data+5, sizeof(chal));
951 memset(user, 0, sizeof(user));
952 memset(resp, 0, sizeof(resp));
953 if(auth_respond(chal, sizeof(chal), user, sizeof(user), resp, sizeof(resp), nil,
954 "proto=mschapv2 role=client service=wpa essid=%q", essid) < 0){
955 fprint(2, "%s: eap mschapv2: auth_respond: %r\n", argv0);
958 len = 5 + sizeof(resp) + 1 + strlen(user);
959 data[0] = 2; /* OpCode - Response */
960 data[1] = cid; /* Identifier */
963 data[4] = sizeof(resp)+1; /* ValueSize */
964 memmove(data+5, resp, sizeof(resp));
965 data[5 + sizeof(resp)] = 0; /* flags */
966 strcpy((char*)&data[5 + sizeof(resp) + 1], user);
968 *(--data) = tp, len++;
969 eapresp(conn, 2, id, data, len);
974 case 3: /* Success */
975 case 4: /* Failure */
976 if(debug || data[0] == 4)
977 fprint(2, "%s: eap mschapv2 %s: %.*s\n", argv0,
978 data[0] == 3 ? "Success" : "Failure",
979 datalen < 4 ? 0 : datalen-4, (char*)data+4);
981 eapresp(conn, 2, id, data, 2);
986 case 21: /* EAP-TTLS */
993 if(*data & 0x20){ /* flags: start */
997 if(tunn->id == id && tunn->tp == tp)
998 break; /* is retransmit, ignore */
1002 sysfatal("pipe: %r");
1003 if((pid = fork()) == -1)
1004 sysfatal("fork: %r");
1018 tunn = emalloc(sizeof(TLStunn));
1022 tunn->clientpid = pid;
1024 if((pid = rfork(RFPROC|RFMEM)) == -1)
1025 sysfatal("fork: %r");
1027 tunn->readerpid = getpid();
1028 tlsreader(tunn, conn);
1029 if(conn->tunn == tunn)
1039 if(id <= tunn->id || tunn->tp != tp)
1042 frag = *data & 0x40; /* flags: more fragments */
1043 if(*data & 0x80){ /* flags: length included */
1049 write(tunn->fd, data, datalen);
1050 if(frag || (tp == 25 && data[0] == 20)){ /* ack change cipher spec */
1054 eapresp(conn, 2, id, data, 2);
1062 avp(uchar *p, int n, int code, void *val, int len, int pad)
1064 pad = 8 + ((len + pad) & ~pad); /* header + data + data pad */
1065 assert(((pad + 3) & ~3) <= n);
1074 memmove(p+8, val, len);
1076 pad = (pad + 3) & ~3; /* packet padding */
1077 memset(p+len, 0, pad - len);
1096 fd = tlswrap(fd, "ttls keying material");
1097 if((up = auth_getuserpasswd(nil, "proto=pass service=wpa essid=%q", essid)) == nil)
1098 sysfatal("auth_getuserpasswd: %r");
1099 n = avp(buf, sizeof(buf), AvpUserName, up->user, strlen(up->user), 0);
1100 n += avp(buf+n, sizeof(buf)-n, AvpUserPass, up->passwd, strlen(up->passwd), 15);
1107 peapwrite(Eapconn *conn, uchar *data, int len)
1110 fdwrite(conn, data + 4, len - 4);
1116 static Eapconn conn;
1117 uchar buf[4096], *p;
1120 conn.fd = fd = tlswrap(fd, "client EAP encryption");
1121 while((n = read(fd, p = buf, sizeof(buf))) > 0){
1122 if(n > 4 && (p[2] << 8 | p[3]) == n && p[4] == 33){
1126 conn.write = fdwrite;
1130 conn.write = peapwrite;
1132 eapreq(&conn, code, id, p, n);
1139 fprint(2, "%s: [-dp12] [-s essid] dev\n", argv0);
1144 main(int argc, char *argv[])
1146 uchar mac[Eaddrlen], buf[4096];
1147 static uchar brsne[258];
1148 static Eapconn conn;
1155 fmtinstall('H', Hfmt);
1156 fmtinstall('E', eipfmt);
1171 strncpy(essid, EARGF(usage()), 32);
1175 rsnelen = sizeof(wpaie);
1177 groupcipher = &tkip;
1181 rsnelen = sizeof(rsnie);
1183 groupcipher = &ccmp;
1192 if(*argv != nil || dev == nil)
1195 if(myetheraddr(mac, dev) < 0)
1196 sysfatal("can't get mac address: %r");
1198 snprint(addr, sizeof(addr), "%s!0x888e", dev);
1199 if((fd = dial(addr, nil, devdir, &cfd)) < 0)
1200 sysfatal("dial: %r");
1203 if(fprint(cfd, "essid %q", essid) < 0)
1204 sysfatal("write essid: %r");
1208 sysfatal("no essid set");
1212 /* bss scan might not be complete yet, so check for 10 seconds. */
1213 for(try = 10; (background || try >= 0) && !connected(0); try--)
1217 if(rsnelen <= 0 || rsne == brsne){
1219 rsnelen = buildrsne(rsne);
1223 /* default is WPA */
1225 rsnelen = sizeof(wpaie);
1227 groupcipher = &tkip;
1231 fprint(2, "rsne: %.*H\n", rsnelen, rsne);
1234 * we use write() instead of fprint so the message gets written
1235 * at once and not chunked up on fprint buffer.
1237 n = sprint((char*)buf, "auth %.*H", rsnelen, rsne);
1238 if(write(cfd, buf, n) != n)
1239 sysfatal("write auth: %r");
1244 s = smprint("proto=wpapsk essid=%q !password?", essid);
1250 s = smprint("proto=pass service=wpa essid=%q user? !password?", essid);
1254 if((up = auth_getuserpasswd(nil, "proto=pass service=wpa essid=%q", essid)) != nil){
1255 factotumctl("key proto=mschapv2 role=client service=wpa essid=%q user=%q !password=%q\n",
1256 essid, up->user, up->passwd);
1265 switch(rfork(RFNOTEG|RFREND|RFPROC|RFNOWAIT)){
1269 sysfatal("fork: %r");
1277 /* wait for getting associated before sending start message */
1278 for(try = 10; (background || try >= 0) && !connected(1); try--)
1282 conn.write = eapwrite;
1283 conn.type = 1; /* Start */
1285 memmove(conn.smac, mac, Eaddrlen);
1286 if(getbssid(conn.amac) == 0)
1287 eapwrite(&conn, nil, 0);
1291 uchar snonce[Noncelen], anonce[Noncelen], *p, *e, *m;
1292 int proto, flags, vers, datalen;
1293 uvlong repc, rsc, tsc;
1296 if((n = read(fd, buf, sizeof(buf))) < 0)
1297 sysfatal("read: %r");
1301 fprint(2, "got deassociation\n");
1308 if(n < 2*Eaddrlen + 2)
1311 memmove(conn.smac, p, Eaddrlen); p += Eaddrlen;
1312 memmove(conn.amac, p, Eaddrlen); p += Eaddrlen;
1313 proto = p[0]<<8 | p[1]; p += 2;
1315 if(proto != 0x888e || memcmp(conn.smac, mac, Eaddrlen) != 0)
1323 conn.version = p[0];
1324 if(conn.version != 0x01 && conn.version != 0x02)
1334 fprint(2, "\nrecv(v%d,t%d) %E <- %E: ", conn.version, conn.type, conn.smac, conn.amac);
1336 if(conn.type == 0x00 && !ispsk){
1344 if(n < 4 || p + n > e)
1347 eapreq(&conn, code, id, p, n);
1351 if(conn.type != 0x03)
1354 if(n < Keydescrlen){
1356 fprint(2, "bad kd size\n");
1363 if(kd->type[0] != 0xFE && kd->type[0] != 0x02)
1366 vers = kd->flags[1] & 7;
1367 flags = kd->flags[0]<<8 | kd->flags[1];
1368 datalen = kd->datalen[0]<<8 | kd->datalen[1];
1369 if(kd->data + datalen > e)
1372 if((flags & Fmic) == 0){
1373 if((flags & (Fptk|Fack)) != (Fptk|Fack))
1376 memmove(anonce, kd->nonce, sizeof(anonce));
1377 genrandom(snonce, sizeof(snonce));
1378 if(getptk(conn.smac, conn.amac, snonce, anonce, ptk) != 0){
1380 fprint(2, "getptk: %r\n");
1384 /* ack key exchange with mic */
1385 memset(kd->rsc, 0, sizeof(kd->rsc));
1386 memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
1387 memmove(kd->nonce, snonce, sizeof(kd->nonce));
1388 replykey(&conn, (flags & ~(Fack|Fins)) | Fmic, kd, rsne, rsnelen);
1393 if(checkmic(kd, m, e - m) != 0){
1395 fprint(2, "bad mic\n");
1399 repc = (uvlong)kd->repc[7] |
1400 (uvlong)kd->repc[6]<<8 |
1401 (uvlong)kd->repc[5]<<16 |
1402 (uvlong)kd->repc[4]<<24 |
1403 (uvlong)kd->repc[3]<<32 |
1404 (uvlong)kd->repc[2]<<40 |
1405 (uvlong)kd->repc[1]<<48 |
1406 (uvlong)kd->repc[0]<<56;
1407 if(repc <= lastrepc){
1409 fprint(2, "bad repc: %llux <= %llux\n", repc, lastrepc);
1414 rsc = (uvlong)kd->rsc[0] |
1415 (uvlong)kd->rsc[1]<<8 |
1416 (uvlong)kd->rsc[2]<<16 |
1417 (uvlong)kd->rsc[3]<<24 |
1418 (uvlong)kd->rsc[4]<<32 |
1419 (uvlong)kd->rsc[5]<<40;
1421 if(datalen > 0 && (flags & Fenc) != 0){
1423 datalen = rc4unwrap(ptk+16, kd->eapoliv, kd->data, datalen);
1425 datalen = aesunwrap(ptk+16, 16, kd->data, datalen);
1428 fprint(2, "bad keywrap\n");
1432 fprint(2, "unwraped keydata[%.4x]=%.*H\n", datalen, datalen, kd->data);
1438 if(kd->type[0] != 0xFE || (flags & (Fptk|Fack)) == (Fptk|Fack)){
1443 for(; p+2 <= e; p = x){
1444 if((x = p+2+p[1]) > e)
1447 fprint(2, "ie=%.2x data[%.2x]=%.*H\n", p[0], p[1], p[1], p+2);
1448 if(p[0] == 0x30){ /* RSN */
1450 if(p[0] == 0xDD){ /* WPA */
1451 static uchar oui[] = { 0x00, 0x0f, 0xac, 0x01, };
1453 if(p+2+sizeof(oui) > x || memcmp(p+2, oui, sizeof(oui)) != 0)
1455 if((flags & Fenc) == 0)
1456 continue; /* ignore gorup key if unencrypted */
1457 gtklen = x - (p + 8);
1460 if(gtklen > sizeof(gtk))
1461 gtklen = sizeof(gtk);
1462 memmove(gtk, p + 8, gtklen);
1468 if((flags & (Fptk|Fack)) == (Fptk|Fack)){
1469 if(vers != 1) /* in WPA2, RSC is for group key only */
1475 /* install pairwise receive key */
1476 if(fprint(cfd, "rxkey %.*H %s:%.*H@%llux", Eaddrlen, conn.amac,
1477 peercipher->name, peercipher->keylen, ptk+32, tsc) < 0)
1478 sysfatal("write rxkey: %r");
1481 memset(kd->rsc, 0, sizeof(kd->rsc));
1482 memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
1483 memset(kd->nonce, 0, sizeof(kd->nonce));
1484 replykey(&conn, flags & ~(Fack|Fenc|Fins), kd, nil, 0);
1487 /* install pairwise transmit key */
1488 if(fprint(cfd, "txkey %.*H %s:%.*H@%llux", Eaddrlen, conn.amac,
1489 peercipher->name, peercipher->keylen, ptk+32, tsc) < 0)
1490 sysfatal("write txkey: %r");
1492 if((flags & (Fptk|Fsec|Fack)) == (Fsec|Fack)){
1493 if(kd->type[0] == 0xFE){
1494 /* WPA always RC4 encrypts the GTK, even tho the flag isnt set */
1495 if((flags & Fenc) == 0)
1496 datalen = rc4unwrap(ptk+16, kd->eapoliv, kd->data, datalen);
1498 if(gtklen > sizeof(gtk))
1499 gtklen = sizeof(gtk);
1500 memmove(gtk, kd->data, gtklen);
1501 gtkkid = (flags >> 4) & 3;
1504 memset(kd->rsc, 0, sizeof(kd->rsc));
1505 memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
1506 memset(kd->nonce, 0, sizeof(kd->nonce));
1507 replykey(&conn, flags & ~(Fenc|Fack), kd, nil, 0);
1511 if(gtklen >= groupcipher->keylen && gtkkid != -1){
1512 /* install group key */
1513 if(fprint(cfd, "rxkey%d %.*H %s:%.*H@%llux",
1514 gtkkid, Eaddrlen, conn.amac,
1515 groupcipher->name, groupcipher->keylen, gtk, rsc) < 0)
1516 sysfatal("write rxkey%d: %r", gtkkid);