aux/wpa: prevent PTK re-installation attack by replaying AP retransmits
this implements the mitigation suggested in section "6.5 Countermeasures" of "Key Reinstallation Attacks: Forcing Nonce Resuse in WPA2" [1]. [1] https://papers.mathyvanhoef.com/ccs2017.pdf
This commit is contained in:
parent
1d34a855fe
commit
0db4f40629
1 changed files with 16 additions and 10 deletions
|
@ -629,7 +629,7 @@ aesunwrap(uchar *key, int nkey, uchar *data, int len)
|
||||||
memmove(R, B+8, 8);
|
memmove(R, B+8, 8);
|
||||||
}
|
}
|
||||||
} while(t > 0);
|
} while(t > 0);
|
||||||
if(memcmp(B, IV, 8) != 0)
|
if(tsmemcmp(B, IV, 8) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
return n*8;
|
return n*8;
|
||||||
}
|
}
|
||||||
|
@ -666,7 +666,7 @@ checkmic(Keydescr *kd, uchar *msg, int msglen)
|
||||||
memmove(tmp, kd->mic, MIClen);
|
memmove(tmp, kd->mic, MIClen);
|
||||||
if(calcmic(kd, msg, msglen) != 0)
|
if(calcmic(kd, msg, msglen) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
return memcmp(tmp, kd->mic, MIClen) != 0;
|
return tsmemcmp(tmp, kd->mic, MIClen) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1175,6 +1175,7 @@ main(int argc, char *argv[])
|
||||||
static Eapconn conn;
|
static Eapconn conn;
|
||||||
char addr[128];
|
char addr[128];
|
||||||
uchar *rsne;
|
uchar *rsne;
|
||||||
|
int newptk; /* gate key reinstallation */
|
||||||
int rsnelen;
|
int rsnelen;
|
||||||
int n, try;
|
int n, try;
|
||||||
|
|
||||||
|
@ -1294,6 +1295,9 @@ Connect:
|
||||||
background();
|
background();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
genrandom(ptk, sizeof(ptk));
|
||||||
|
newptk = 0;
|
||||||
|
|
||||||
lastrepc = 0ULL;
|
lastrepc = 0ULL;
|
||||||
for(;;){
|
for(;;){
|
||||||
uchar *p, *e, *m;
|
uchar *p, *e, *m;
|
||||||
|
@ -1391,6 +1395,8 @@ Connect:
|
||||||
fprint(2, "getptk: %r\n");
|
fprint(2, "getptk: %r\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
/* allow installation of new keys */
|
||||||
|
newptk = 1;
|
||||||
|
|
||||||
/* ack key exchange with mic */
|
/* ack key exchange with mic */
|
||||||
memset(kd->rsc, 0, sizeof(kd->rsc));
|
memset(kd->rsc, 0, sizeof(kd->rsc));
|
||||||
|
@ -1477,28 +1483,31 @@ Connect:
|
||||||
}
|
}
|
||||||
|
|
||||||
if((flags & (Fptk|Fack)) == (Fptk|Fack)){
|
if((flags & (Fptk|Fack)) == (Fptk|Fack)){
|
||||||
|
if(!newptk) /* a retransmit, already installed PTK */
|
||||||
|
continue;
|
||||||
if(vers != 1) /* in WPA2, RSC is for group key only */
|
if(vers != 1) /* in WPA2, RSC is for group key only */
|
||||||
tsc = 0LL;
|
tsc = 0LL;
|
||||||
else {
|
else {
|
||||||
tsc = rsc;
|
tsc = rsc;
|
||||||
rsc = 0LL;
|
rsc = 0LL;
|
||||||
}
|
}
|
||||||
/* install pairwise receive key */
|
/* install pairwise receive key (PTK) */
|
||||||
if(fprint(cfd, "rxkey %.*H %s:%.*H@%llux", Eaddrlen, conn.amac,
|
if(fprint(cfd, "rxkey %.*H %s:%.*H@%llux", Eaddrlen, conn.amac,
|
||||||
peercipher->name, peercipher->keylen, ptk+32, tsc) < 0)
|
peercipher->name, peercipher->keylen, ptk+32, tsc) < 0)
|
||||||
sysfatal("write rxkey: %r");
|
sysfatal("write rxkey: %r");
|
||||||
|
|
||||||
tsc = 0LL;
|
|
||||||
memset(kd->rsc, 0, sizeof(kd->rsc));
|
memset(kd->rsc, 0, sizeof(kd->rsc));
|
||||||
memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
|
memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
|
||||||
memset(kd->nonce, 0, sizeof(kd->nonce));
|
memset(kd->nonce, 0, sizeof(kd->nonce));
|
||||||
replykey(&conn, flags & ~(Fack|Fenc|Fins), kd, nil, 0);
|
replykey(&conn, flags & ~(Fack|Fenc|Fins), kd, nil, 0);
|
||||||
sleep(100);
|
sleep(100);
|
||||||
|
|
||||||
/* install pairwise transmit key */
|
tsc = 0LL;
|
||||||
|
/* install pairwise transmit key (PTK) */
|
||||||
if(fprint(cfd, "txkey %.*H %s:%.*H@%llux", Eaddrlen, conn.amac,
|
if(fprint(cfd, "txkey %.*H %s:%.*H@%llux", Eaddrlen, conn.amac,
|
||||||
peercipher->name, peercipher->keylen, ptk+32, tsc) < 0)
|
peercipher->name, peercipher->keylen, ptk+32, tsc) < 0)
|
||||||
sysfatal("write txkey: %r");
|
sysfatal("write txkey: %r");
|
||||||
|
newptk = 0; /* prevent PTK re-installation on (replayed) retransmits */
|
||||||
} else
|
} else
|
||||||
if((flags & (Fptk|Fsec|Fack)) == (Fsec|Fack)){
|
if((flags & (Fptk|Fsec|Fack)) == (Fsec|Fack)){
|
||||||
if(kd->type[0] == 0xFE){
|
if(kd->type[0] == 0xFE){
|
||||||
|
@ -1511,21 +1520,18 @@ Connect:
|
||||||
memmove(gtk, kd->data, gtklen);
|
memmove(gtk, kd->data, gtklen);
|
||||||
gtkkid = (flags >> 4) & 3;
|
gtkkid = (flags >> 4) & 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(kd->rsc, 0, sizeof(kd->rsc));
|
memset(kd->rsc, 0, sizeof(kd->rsc));
|
||||||
memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
|
memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
|
||||||
memset(kd->nonce, 0, sizeof(kd->nonce));
|
memset(kd->nonce, 0, sizeof(kd->nonce));
|
||||||
replykey(&conn, flags & ~(Fenc|Fack), kd, nil, 0);
|
replykey(&conn, flags & ~(Fenc|Fack), kd, nil, 0);
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
|
/* install group key (GTK) */
|
||||||
if(gtklen >= groupcipher->keylen && gtkkid != -1){
|
if(gtklen >= groupcipher->keylen && gtkkid != -1)
|
||||||
/* install group key */
|
|
||||||
if(fprint(cfd, "rxkey%d %.*H %s:%.*H@%llux",
|
if(fprint(cfd, "rxkey%d %.*H %s:%.*H@%llux",
|
||||||
gtkkid, Eaddrlen, conn.amac,
|
gtkkid, Eaddrlen, conn.amac,
|
||||||
groupcipher->name, groupcipher->keylen, gtk, rsc) < 0)
|
groupcipher->name, groupcipher->keylen, gtk, rsc) < 0)
|
||||||
sysfatal("write rxkey%d: %r", gtkkid);
|
sysfatal("write rxkey%d: %r", gtkkid);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue