shithub: riscv

Download patch

ref: 17a67eeb652ebc76f6fc9f7f7bbed501187d24e1
parent: 7b3334775edcfe43fc6ff44955b09dc294d96974
author: cinap_lenrek <[email protected]>
date: Thu Apr 21 22:33:29 EDT 2016

libsec: implement server side SCSV preventing silly client fallbacks

silly clients (web*) reconnect when the handshake failed with a lower
protocol version, which allows downgrade attacks (POODLE). but instead
of stopping this madness, they invented a new magic TLSID to indicate
to the server that this connection attempt is a retry, and rely on the
server to notice and stop them from sabotaging themselfs.

--- a/sys/src/libsec/port/tlshand.c
+++ b/sys/src/libsec/port/tlshand.c
@@ -211,6 +211,7 @@
 	EProtocolVersion = 70,
 	EInsufficientSecurity = 71,
 	EInternalError = 80,
+	EInappropriateFallback = 86,
 	EUserCanceled = 90,
 	ENoRenegotiation = 100,
 	EUnknownPSKidentity = 115,
@@ -295,6 +296,8 @@
 	TLS_PSK_WITH_CHACHA20_POLY1305		= 0xCCAB,
 	TLS_PSK_WITH_AES_128_CBC_SHA256		= 0x00AE,
 	TLS_PSK_WITH_AES_128_CBC_SHA		= 0x008C,
+
+	TLS_FALLBACK_SCSV = 0x5600,
 };
 
 // compression methods
@@ -446,6 +449,7 @@
 static void freebytes(Bytes* b);
 static Ints* newints(int len);
 static void freeints(Ints* b);
+static int lookupid(Ints* b, int id);
 
 /* x509.c */
 extern mpint*	pkcs1padbuf(uchar *buf, int len, mpint *modulus);
@@ -708,7 +712,11 @@
 		tlsError(c, EIllegalParameter, "incompatible version");
 		goto Err;
 	}
-
+	if(c->version < ProtocolVersion
+	&& lookupid(m.u.clientHello.ciphers, TLS_FALLBACK_SCSV) >= 0){
+		tlsError(c, EInappropriateFallback, "inappropriate fallback");
+		goto Err;
+	}
 	cipher = okCipher(m.u.clientHello.ciphers, psklen > 0);
 	if(cipher < 0 || !setAlgs(c, cipher)) {
 		tlsError(c, EHandshakeFailure, "no matching cipher suite");
@@ -2019,10 +2027,10 @@
 	va_end(arg);
 	if(c->trace)
 		c->trace("tlsError: %s\n", msg);
-	else if(c->erred)
+	if(c->erred)
 		fprint(2, "double error: %r, %s", msg);
 	else
-		werrstr("tls: local %s", msg);
+		errstr(msg, sizeof(msg));
 	c->erred = 1;
 	fprint(c->ctl, "alert %d", err);
 }
@@ -2163,15 +2171,14 @@
 static int
 okCipher(Ints *cv, int ispsk)
 {
-	int i, j, c;
+	int i, c;
 
 	for(i = 0; i < nelem(cipherAlgs); i++) {
 		c = cipherAlgs[i].tlsid;
 		if(!cipherAlgs[i].ok || isECDSA(c) || isDHE(c) || isPSK(c) != ispsk)
 			continue;
-		for(j = 0; j < cv->len; j++)
-			if(cv->data[j] == c)
-				return c;
+		if(lookupid(cv, c) >= 0)
+			return c;
 	}
 	return -1;
 }
@@ -2179,13 +2186,12 @@
 static int
 okCompression(Bytes *cv)
 {
-	int i, j, c;
+	int i, c;
 
 	for(i = 0; i < nelem(compressors); i++) {
 		c = compressors[i];
-		for(j = 0; j < cv->len; j++)
-			if(cv->data[j] == c)
-				return c;
+		if(memchr(cv->data, c, cv->len) != nil)
+			return c;
 	}
 	return -1;
 }
@@ -3096,4 +3102,15 @@
 freeints(Ints* b)
 {
 	free(b);
+}
+
+static int
+lookupid(Ints* b, int id)
+{
+	int i;
+
+	for(i=0; i<b->len; i++)
+		if(b->data[i] == id)
+			return i;
+	return -1;
 }