changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: aux/wpa: prevent PTK re-installation attack by replaying AP retransmits

changeset 6187: 94d052c01881
parent 6186: a956f47ced84
child 6188: fff962c96ca6
author: cinap_lenrek@felloff.net
date: Tue, 17 Oct 2017 20:15:48 +0200
files: sys/src/cmd/aux/wpa.c
description: 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
     1.1--- a/sys/src/cmd/aux/wpa.c
     1.2+++ b/sys/src/cmd/aux/wpa.c
     1.3@@ -629,7 +629,7 @@ aesunwrap(uchar *key, int nkey, uchar *d
     1.4 			memmove(R, B+8, 8);
     1.5 		}
     1.6 	} while(t > 0);
     1.7-	if(memcmp(B, IV, 8) != 0)
     1.8+	if(tsmemcmp(B, IV, 8) != 0)
     1.9 		return -1;
    1.10 	return n*8;
    1.11 }
    1.12@@ -666,7 +666,7 @@ checkmic(Keydescr *kd, uchar *msg, int m
    1.13 	memmove(tmp, kd->mic, MIClen);
    1.14 	if(calcmic(kd, msg, msglen) != 0)
    1.15 		return -1;
    1.16-	return memcmp(tmp, kd->mic, MIClen) != 0;
    1.17+	return tsmemcmp(tmp, kd->mic, MIClen) != 0;
    1.18 }
    1.19 
    1.20 void
    1.21@@ -1175,6 +1175,7 @@ main(int argc, char *argv[])
    1.22 	static Eapconn conn;
    1.23 	char addr[128];
    1.24 	uchar *rsne;
    1.25+	int newptk; /* gate key reinstallation */
    1.26 	int rsnelen;
    1.27 	int n, try;
    1.28 
    1.29@@ -1294,6 +1295,9 @@ Connect:
    1.30 		background();
    1.31 	}
    1.32 
    1.33+	genrandom(ptk, sizeof(ptk));
    1.34+	newptk = 0;
    1.35+
    1.36 	lastrepc = 0ULL;
    1.37 	for(;;){
    1.38 		uchar *p, *e, *m;
    1.39@@ -1391,6 +1395,8 @@ Connect:
    1.40 					fprint(2, "getptk: %r\n");
    1.41 				continue;
    1.42 			}
    1.43+			/* allow installation of new keys */	
    1.44+			newptk = 1;
    1.45 
    1.46 			/* ack key exchange with mic */
    1.47 			memset(kd->rsc, 0, sizeof(kd->rsc));
    1.48@@ -1477,28 +1483,31 @@ Connect:
    1.49 			}
    1.50 
    1.51 			if((flags & (Fptk|Fack)) == (Fptk|Fack)){
    1.52+				if(!newptk)	/* a retransmit, already installed PTK */
    1.53+					continue;
    1.54 				if(vers != 1)	/* in WPA2, RSC is for group key only */
    1.55 					tsc = 0LL;
    1.56 				else {
    1.57 					tsc = rsc;
    1.58 					rsc = 0LL;
    1.59 				}
    1.60-				/* install pairwise receive key */
    1.61+				/* install pairwise receive key (PTK) */
    1.62 				if(fprint(cfd, "rxkey %.*H %s:%.*H@%llux", Eaddrlen, conn.amac,
    1.63 					peercipher->name, peercipher->keylen, ptk+32, tsc) < 0)
    1.64 					sysfatal("write rxkey: %r");
    1.65 
    1.66-				tsc = 0LL;
    1.67 				memset(kd->rsc, 0, sizeof(kd->rsc));
    1.68 				memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
    1.69 				memset(kd->nonce, 0, sizeof(kd->nonce));
    1.70 				replykey(&conn, flags & ~(Fack|Fenc|Fins), kd, nil, 0);
    1.71 				sleep(100);
    1.72 
    1.73-				/* install pairwise transmit key */ 
    1.74+				tsc = 0LL;
    1.75+				/* install pairwise transmit key (PTK) */ 
    1.76 				if(fprint(cfd, "txkey %.*H %s:%.*H@%llux", Eaddrlen, conn.amac,
    1.77 					peercipher->name, peercipher->keylen, ptk+32, tsc) < 0)
    1.78 					sysfatal("write txkey: %r");
    1.79+				newptk = 0; /* prevent PTK re-installation on (replayed) retransmits */
    1.80 			} else
    1.81 			if((flags & (Fptk|Fsec|Fack)) == (Fsec|Fack)){
    1.82 				if(kd->type[0] == 0xFE){
    1.83@@ -1511,21 +1520,18 @@ Connect:
    1.84 					memmove(gtk, kd->data, gtklen);
    1.85 					gtkkid = (flags >> 4) & 3;
    1.86 				}
    1.87-
    1.88 				memset(kd->rsc, 0, sizeof(kd->rsc));
    1.89 				memset(kd->eapoliv, 0, sizeof(kd->eapoliv));
    1.90 				memset(kd->nonce, 0, sizeof(kd->nonce));
    1.91 				replykey(&conn, flags & ~(Fenc|Fack), kd, nil, 0);
    1.92 			} else
    1.93 				continue;
    1.94-
    1.95-			if(gtklen >= groupcipher->keylen && gtkkid != -1){
    1.96-				/* install group key */
    1.97+			/* install group key (GTK) */
    1.98+			if(gtklen >= groupcipher->keylen && gtkkid != -1)
    1.99 				if(fprint(cfd, "rxkey%d %.*H %s:%.*H@%llux",
   1.100 					gtkkid, Eaddrlen, conn.amac, 
   1.101 					groupcipher->name, groupcipher->keylen, gtk, rsc) < 0)
   1.102 					sysfatal("write rxkey%d: %r", gtkkid);
   1.103-			}
   1.104 		}
   1.105 	}
   1.106 }