Plan 9 from Bell Labs’s /usr/web/sources/contrib/yk/dist/9legacy/applied/tls-devtls12.diff

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


--- /sys/src/9/port/devtls.c
+++ /sys/src/9/port/devtls.c
@@ -1,5 +1,5 @@
 /*
- *  devtls - record layer for transport layer security 1.0 and secure sockets layer 3.0
+ *  devtls - record layer for transport layer security 1.0, 1.1, 1.2 and secure sockets layer 3.0
  */
 #include	"u.h"
 #include	"../port/lib.h"
@@ -21,12 +21,13 @@ enum {
 	MaxRecLen		= 1<<14,	/* max payload length of a record layer message */
 	MaxCipherRecLen	= MaxRecLen + 2048,
 	RecHdrLen		= 5,
-	MaxMacLen		= SHA1dlen,
+	MaxMacLen		= SHA2_256dlen,
 
 	/* protocol versions we can accept */
-	TLSVersion		= 0x0301,
 	SSL3Version		= 0x0300,
-	ProtocolVersion	= 0x0301,	/* maximum version we speak */
+	TLS10Version		= 0x0301,
+	TLS11Version		= 0x0302,
+	TLS12Version		= 0x0303,
 	MinProtoVersion	= 0x0300,	/* limits on version we accept */
 	MaxProtoVersion	= 0x03ff,
 
@@ -73,6 +74,7 @@ enum {
 	EInternalError 			= 80,
 	EUserCanceled 			= 90,
 	ENoRenegotiation 		= 100,
+	EUnrecognizedName		= 112,
 
 	EMAX = 256
 };
@@ -800,6 +802,17 @@ if(tr->debug) pprint("consumed unprocessed %d\n", len);
 		/* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here
 		        should look alike, including timing of the response. */
 		unpad_len = (*in->sec->dec)(in->sec, p, len);
+
+		/* excplicit iv */
+		if(tr->version >= TLS11Version){
+			len -= in->sec->block;
+			if(len < 0)
+				rcvError(tr, EDecodeError, "runt record message");
+
+			unpad_len -= in->sec->block;
+			p += in->sec->block;
+		}
+
 		if(unpad_len >= in->sec->maclen)
 			len = unpad_len - in->sec->maclen;
 if(tr->debug) pprint("decrypted %d\n", unpad_len);
@@ -814,7 +827,8 @@ if(tr->debug) pdump(unpad_len, p, "decrypted:");
 			rcvError(tr, EBadRecordMac, "short record mac");
 		if(memcmp(hmac, p+len, in->sec->maclen) != 0)
 			rcvError(tr, EBadRecordMac, "record mac mismatch");
-		b->wp = b->rp + len;
+		b->rp = p;
+		b->wp = p+len;
 	}
 	qunlock(&in->seclock);
 	poperror();
@@ -850,18 +864,25 @@ if(tr->debug) pdump(unpad_len, p, "decrypted:");
 		/*
 		 * propate non-fatal alerts to handshaker
 		 */
-		if(p[1] == ECloseNotify) {
+		switch(p[1]){
+		case ECloseNotify:
 			tlsclosed(tr, SRClose);
 			if(tr->opened)
 				error("tls hungup");
 			error("close notify");
-		}
-		if(p[1] == ENoRenegotiation)
+			break;
+		case ENoRenegotiation:
 			alertHand(tr, "no renegotiation");
-		else if(p[1] == EUserCanceled)
+			break;
+		case EUserCanceled:
 			alertHand(tr, "handshake canceled by user");
-		else
+			break;
+		case EUnrecognizedName:
+			/* happens in response to SNI, can be ignored. */
+			break;
+		default:
 			rcvError(tr, EIllegalParameter, "invalid alert code");
+		}
 		break;
 	case RHandshake:
 		/*
@@ -1202,6 +1223,13 @@ tlsread(Chan *c, void *a, long n, vlong off)
 	return n;
 }
 
+static void
+randfill(uchar *buf, int len)
+{
+	while(len-- > 0)
+		*buf++ = nrand(256);
+}
+
 /*
  *  write a block in tls records
  */
@@ -1212,7 +1240,7 @@ tlsrecwrite(TlsRec *tr, int type, Block *b)
 	Block *nb;
 	uchar *p, seq[8];
 	OneWay *volatile out;
-	int n, maclen, pad, ok;
+	int n, ivlen, maclen, pad, ok;
 
 	out = &tr->out;
 	bb = b;
@@ -1245,21 +1273,24 @@ if(tr->debug)pdump(BLEN(b), b->rp, "sent:");
 		qlock(&out->seclock);
 		maclen = 0;
 		pad = 0;
+		ivlen = 0;
 		if(out->sec != nil){
 			maclen = out->sec->maclen;
 			pad = maclen + out->sec->block;
+			if(tr->version >= TLS11Version)
+				ivlen = out->sec->block;
 		}
 		n = BLEN(bb);
 		if(n > MaxRecLen){
 			n = MaxRecLen;
-			nb = allocb(n + pad + RecHdrLen);
-			memmove(nb->wp + RecHdrLen, bb->rp, n);
+			nb = allocb(RecHdrLen + ivlen + n + pad);
+			memmove(nb->wp + RecHdrLen + ivlen, bb->rp, n);
 			bb->rp += n;
 		}else{
 			/*
 			 * carefully reuse bb so it will get freed if we're out of memory
 			 */
-			bb = padblock(bb, RecHdrLen);
+			bb = padblock(bb, RecHdrLen + ivlen);
 			if(pad)
 				nb = padblock(bb, -pad);
 			else
@@ -1275,9 +1306,15 @@ if(tr->debug)pdump(BLEN(b), b->rp, "sent:");
 		if(out->sec != nil){
 			put64(seq, out->seq);
 			out->seq++;
-			(*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen, n, p + RecHdrLen + n);
+			(*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen + ivlen, n, p + RecHdrLen + ivlen + n);
 			n += maclen;
 
+			/* explicit iv */
+			if(ivlen > 0){
+				randfill(p + RecHdrLen, ivlen);
+				n += ivlen;
+			}
+
 			/* encrypt */
 			n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
 			nb->wp = p + RecHdrLen + n;
@@ -1380,11 +1417,22 @@ initsha1key(Hashalg *ha, int version, Secret *s, uchar *p)
 	memmove(s->mackey, p, ha->maclen);
 }
 
+static void
+initsha2_256key(Hashalg *ha, int version, Secret *s, uchar *p)
+{
+	if(version == SSL3Version)
+		error("sha256 cannot be used with SSL");
+	s->maclen = ha->maclen;
+	s->mac = hmac_sha2_256;
+	memmove(s->mackey, p, ha->maclen);
+}
+
 static Hashalg hashtab[] =
 {
 	{ "clear", 0, initclearmac, },
 	{ "md5", MD5dlen, initmd5key, },
 	{ "sha1", SHA1dlen, initsha1key, },
+	{ "sha256", SHA2_256dlen, initsha2_256key, },
 	{ 0 }
 };
 
@@ -1555,12 +1603,12 @@ tlswrite(Chan *c, void *a, long n, vlong off)
 		if(tr->verset)
 			error("version already set");
 		m = strtol(cb->f[1], nil, 0);
+		if(m < MinProtoVersion || m > MaxProtoVersion)
+			error("unsupported version");
 		if(m == SSL3Version)
 			tr->packMac = sslPackMac;
-		else if(m == TLSVersion)
-			tr->packMac = tlsPackMac;
 		else
-			error("unsupported version");
+			tr->packMac = tlsPackMac;
 		tr->verset = 1;
 		tr->version = m;
 	}else if(strcmp(cb->f[0], "secret") == 0){
--- /sys/man/3/tls
+++ /sys/man/3/tls
@@ -17,7 +17,8 @@ tls \- TLS1 and SSL3 record layer
 .fi
 .SH DESCRIPTION
 The TLS device implements the record layer protocols
-of Transport Layer Security version 1.0 and Secure Sockets Layer version 3.0.
+of Transport Layer Security versions 1.[0-2] and
+Secure Sockets Layer version 3.0.
 It does not implement the handshake protocols, which are responsible for
 mutual authentication and key exchange.
 The
@@ -54,9 +55,14 @@ Initially, outgoing messages use version
 format records, but incoming messages of either version are accepted.
 Valid versions are
 .B 0x300
-for SSLv3.0 and
+for SSLv3.0,
 .B 0x301
-for TLSv1.0 (which could be known as SSLv3.01.)
+for TLSv1.0,
+.B 0x302
+for TLSv1.1,
+and
+.B 0x303
+for TLSv1.2.
 This command must be issued before any other command
 and before reading or writing any messages;
 it may only be executed once.
@@ -265,9 +271,10 @@ Currently implemented encryption algorithms are
 and
 .BR 'aes_256_cbc' .
 Currently implemented hashing algorithms are
-.B 'md5'
+.BR "md5" ,
+.BR "sha1" ,
 and
-.BR 'sha1' .
+.BR "sha2_256" .
 .SH "SEE ALSO"
 .IR listen (8),
 .IR dial (2),

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.