9front - general discussion about 9front
 help / color / mirror / Atom feed
From: kemal <kemalinanc8@gmail.com>
To: 9front@9front.org
Subject: Re: [9front] intent to delete: devssl, cpu, oexportfs, import
Date: Sun, 24 Oct 2021 14:46:14 +0300	[thread overview]
Message-ID: <CABO6shfizVvY3qmr+wwRrhrD493YMu3kcJ-zmXVwjovz+rbaAQ@mail.gmail.com> (raw)
In-Reply-To: <CABO6shdSD2WOr0VoG_dNP02uBrCjwqUaH32=NYKQG5AngtLp9w@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 808 bytes --]

i am sending a new diff, again. i apologise for sending 4 different
diffs for this, i definitely should have checked my diff better...

> 1. don't reject protocol versions that is higher than 0x03ff.
> this behavior is useless.

it is if it's checking the clienthello/serverhello version,
but not if we're checking the record layer version! it might
accept non-TLS data if it doesn't check `major version == 0x03`.
add that behavior back for devtls.

also, 2 more problems i saw in version negotiation code:

1. when setVersion fails, code sends a "illegal_parameter" alert
but "protocol_version" is more suitable and the standard way
for this. send "protocol_version" instead.

2. tlsClient2 should abort if the server sends a version higher
than `c->version`. fix up.

the new (and last) diff is attached.

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 31496 bytes --]

diff 5b5f69513adcb9939e4ebd93bf8adfbfdc08fcf1 uncommitted
--- a//sys/man/2/pushtls
+++ b//sys/man/2/pushtls
@@ -1,6 +1,6 @@
 .TH PUSHTLS 2
 .SH NAME
-pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS1 or SSL3 encryption to a communication channel
+pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS encryption to a communication channel
 .SH SYNOPSIS
 .B #include <u.h>
 .br
@@ -45,8 +45,6 @@
 and a handshake protocol,
 doing initial authentication and secret creation at
 user level and then starting a data channel in the record protocol.
-TLS is nearly the same as SSL 3.0, and the software should interoperate
-with implementations of either standard.
 .PP
 To use just the record layer, as described in
 .IR tls (3),
--- a//sys/man/3/tls
+++ b//sys/man/3/tls
@@ -1,6 +1,6 @@
 .TH TLS 3 
 .SH NAME
-tls \- TLS and SSL3 record layer
+tls \- TLS record layer
 .SH SYNOPSIS
 .nf
 .B bind -a #a /net
@@ -16,10 +16,9 @@
 .BI /net/tls/ n /status
 .fi
 .SH DESCRIPTION
-The TLS device implements the record layer protocols
-of Transport Layer Security version 1.0-1.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 TLS device implements the record layer protocols of Transport Layer Security
+version 1.0-1.2. It does not implement the handshake protocols, which are responsible
+for mutual authentication and key exchange.
 The
 .I tls
 device can be thought of as filters providing optional encryption and anti-tampering.
@@ -53,13 +52,11 @@
 .I vers
 format records, but incoming messages of either version are accepted.
 Valid versions are
-.B 0x300
-for SSLv3.0 and
 .BR 0x301 ,
 .B 0x302
 and
 .B 0x303
-for TLSv1.0 (which could be known as SSLv3.01), TLSv1.1 and TLSv1.2.
+for TLSv1.0, TLSv1.1 and TLSv1.2.
 This command must be issued before any other command
 and before reading or writing any messages;
 it may only be executed once.
@@ -120,10 +117,9 @@
 .TP
 .BI alert \ alertno
 Send an alert message.
-.I Alertno
-may be a valid alert code for either SSLv3.0 or TLS,
-and is mapped to an appropriate code for the protocol in use.
-If it is a fatal alert, the filter is set into an error state.
+If
+.I alertno
+is a fatal alert, the filter is set into an error state.
 .PP
 Application messages and handshake messages are communicated using
 .I data
--- a//sys/src/9/port/devtls.c
+++ b//sys/src/9/port/devtls.c
@@ -1,5 +1,5 @@
 /*
- *  devtls - record layer for transport layer security 1.2 and secure sockets layer 3.0
+ *  devtls - record layer for transport layer security 1.0-1.2
  */
 #include	"u.h"
 #include	"../port/lib.h"
@@ -24,12 +24,11 @@
 	MaxMacLen	= SHA2_256dlen,
 
 	/* protocol versions we can accept */
-	SSL3Version	= 0x0300,
 	TLS10Version	= 0x0301,
 	TLS11Version	= 0x0302,
 	TLS12Version	= 0x0303,
-	MinProtoVersion	= 0x0300,	/* limits on version we accept */
-	MaxProtoVersion	= 0x03ff,
+	MinProtoVersion	= TLS10Version,	/* limits on version we accept */
+	MaxProtoVersion	= TLS12Version,
 
 	/* connection states */
 	SHandshake	= 1 << 0,	/* doing handshake */
@@ -57,7 +56,6 @@
 	ERecordOverflow 		= 22,
 	EDecompressionFailure 	= 30,
 	EHandshakeFailure 		= 40,
-	ENoCertificate 			= 41,
 	EBadCertificate 		= 42,
 	EUnsupportedCertificate 	= 43,
 	ECertificateRevoked 		= 44,
@@ -89,7 +87,6 @@
 
 	int		(*enc)(Secret*, uchar*, int);
 	int		(*dec)(Secret*, uchar*, int);
-	int		(*unpad)(uchar*, int, int);
 	DigestState*	(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
 
 	int		block;		/* encryption block len, 0 if none */
@@ -125,12 +122,6 @@
 	int		state;
 	int		debug;
 
-	/*
-	 * function to genrate authenticated data blob for different
-	 * protocol versions
-	 */
-	int		(*packAAD)(u64int, uchar*, uchar*);
-
 	/* input side -- protected by in.io */
 	OneWay		in;
 	Block		*processed;	/* next bunch of application data */
@@ -153,37 +144,34 @@
 
 struct TlsErrs{
 	int	err;
-	int	sslerr;
-	int	tlserr;
 	int	fatal;
 	char	*msg;
 };
 
 static TlsErrs tlserrs[] = {
-	{ECloseNotify,			ECloseNotify,			ECloseNotify,			0, 	"close notify"},
-	{EUnexpectedMessage,	EUnexpectedMessage,	EUnexpectedMessage, 	1, "unexpected message"},
-	{EBadRecordMac,		EBadRecordMac,		EBadRecordMac, 		1, "bad record mac"},
-	{EDecryptionFailed,		EIllegalParameter,		EDecryptionFailed,		1, "decryption failed"},
-	{ERecordOverflow,		EIllegalParameter,		ERecordOverflow,		1, "record too long"},
-	{EDecompressionFailure,	EDecompressionFailure,	EDecompressionFailure,	1, "decompression failed"},
-	{EHandshakeFailure,		EHandshakeFailure,		EHandshakeFailure,		1, "could not negotiate acceptable security parameters"},
-	{ENoCertificate,		ENoCertificate,			ECertificateUnknown,	1, "no appropriate certificate available"},
-	{EBadCertificate,		EBadCertificate,		EBadCertificate,		1, "corrupted or invalid certificate"},
-	{EUnsupportedCertificate,	EUnsupportedCertificate,	EUnsupportedCertificate,	1, "unsupported certificate type"},
-	{ECertificateRevoked,	ECertificateRevoked,		ECertificateRevoked,		1, "revoked certificate"},
-	{ECertificateExpired,		ECertificateExpired,		ECertificateExpired,		1, "expired certificate"},
-	{ECertificateUnknown,	ECertificateUnknown,	ECertificateUnknown,	1, "unacceptable certificate"},
-	{EIllegalParameter,		EIllegalParameter,		EIllegalParameter,		1, "illegal parameter"},
-	{EUnknownCa,			EHandshakeFailure,		EUnknownCa,			1, "unknown certificate authority"},
-	{EAccessDenied,		EHandshakeFailure,		EAccessDenied,		1, "access denied"},
-	{EDecodeError,			EIllegalParameter,		EDecodeError,			1, "error decoding message"},
-	{EDecryptError,			EIllegalParameter,		EDecryptError,			1, "error decrypting message"},
-	{EExportRestriction,		EHandshakeFailure,		EExportRestriction,		1, "export restriction violated"},
-	{EProtocolVersion,		EIllegalParameter,		EProtocolVersion,		1, "protocol version not supported"},
-	{EInsufficientSecurity,	EHandshakeFailure,		EInsufficientSecurity,	1, "stronger security routines required"},
-	{EInternalError,			EHandshakeFailure,		EInternalError,			1, "internal error"},
-	{EUserCanceled,		ECloseNotify,			EUserCanceled,			0, "handshake canceled by user"},
-	{ENoRenegotiation,		EUnexpectedMessage,	ENoRenegotiation,		0, "no renegotiation"},
+	{ECloseNotify,			0, "close notify"},
+	{EUnexpectedMessage,		1, "unexpected message"},
+	{EBadRecordMac,			1, "bad record mac"},
+	{EDecryptionFailed,		1, "decryption failed"},
+	{ERecordOverflow,		1, "record too long"},
+	{EDecompressionFailure,		1, "decompression failed"},
+	{EHandshakeFailure,		1, "could not negotiate acceptable security parameters"},
+	{EBadCertificate,		1, "corrupted or invalid certificate"},
+	{EUnsupportedCertificate,	1, "unsupported certificate type"},
+	{ECertificateRevoked,		1, "revoked certificate"},
+	{ECertificateExpired,		1, "expired certificate"},
+	{ECertificateUnknown,		1, "unacceptable certificate"},
+	{EIllegalParameter,		1, "illegal parameter"},
+	{EUnknownCa,			1, "unknown certificate authority"},
+	{EAccessDenied,			1, "access denied"},
+	{EDecodeError,			1, "error decoding message"},
+	{EDecryptError,			1, "error decrypting message"},
+	{EExportRestriction,		1, "export restriction violated"},
+	{EProtocolVersion,		1, "protocol version not supported"},
+	{EInsufficientSecurity,		1, "stronger security routines required"},
+	{EInternalError,		1, "internal error"},
+	{EUserCanceled,			0, "handshake canceled by user"},
+	{ENoRenegotiation,		0, "no renegotiation"},
 };
 
 enum
@@ -227,11 +215,8 @@
 static void	alertHand(TlsRec*, char *);
 static TlsRec	*newtls(Chan *c);
 static TlsRec	*mktlsrec(void);
-static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
 static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static int	sslPackAAD(u64int, uchar*, uchar*);
-static int	tlsPackAAD(u64int, uchar*, uchar*);
+static int	packAAD(u64int, uchar*, uchar*);
 static void	packMac(Secret*, uchar*, int, uchar*, int, uchar*);
 static void	put64(uchar *p, u64int);
 static void	put32(uchar *p, u32int);
@@ -252,8 +237,7 @@
 static int	aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	noenc(Secret *sec, uchar *buf, int n);
-static int	sslunpad(uchar *buf, int n, int block);
-static int	tlsunpad(uchar *buf, int n, int block);
+static int	unpad(uchar *buf, int n, int block);
 static void	freeSec(Secret *sec);
 static char	*tlsstate(int s);
 static void	pdump(int, void*, char*);
@@ -750,7 +734,7 @@
 	nconsumed = RecHdrLen;
 
 	if((tr->handin == 0) && (header[0] & 0x80)){
-		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.
+		/* Cope with a TLS ClientHello expressed in SSL2 record format.
 			This is sent by some clients that we must interoperate
 			with, such as Java's JSSE and Microsoft's Internet Explorer. */
 		len = (get16(header) & ~0x8000) - 3;
@@ -757,13 +741,13 @@
 		type = header[2];
 		ver = get16(header + 3);
 		if(type != SSL2ClientHello || len < 22)
-			rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message");
-	}else{  /* normal SSL3 record format */
+			rcvError(tr, EUnexpectedMessage, "invalid initial SSL2-like message");
+	}else{  /* normal TLS record format */
 		type = header[0];
 		ver = get16(header+1);
 		len = get16(header+3);
 	}
-	if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion))
+	if(ver != tr->version && (tr->verset || ver>>8 != 0x03))
 		rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'",
 			tr->version, tr->verset?"/set":"", len, type, ver, (char*)header);
 	if(len > MaxCipherRecLen || len < 0)
@@ -823,7 +807,7 @@
 
 		/* update length */
 		put16(header+3, len);
-		aadlen = (*tr->packAAD)(in->seq++, header, aad);
+		aadlen = packAAD(in->seq++, header, aad);
 		if(sec->aead_dec != nil) {
 			len = (*sec->aead_dec)(sec, aad, aadlen, p - ivlen, p, unpad_len);
 			if(len < 0)
@@ -916,7 +900,7 @@
 			dechandq(tr);
 		}else{
 			unlock(&tr->hqlock);
-			if(tr->verset && tr->version != SSL3Version && !waserror()){
+			if(tr->verset && !waserror()){
 				sendAlert(tr, ENoRenegotiation);
 				poperror();
 			}
@@ -933,7 +917,7 @@
 			}
 			/* Pass the SSL2 format data, so that the handshake code can compute
 				the correct checksums.  HSSL2ClientHello = HandshakeType 9 is
-				unused in RFC2246. */
+				unused in RFC5246. */
 			b = padblock(b, 8);
 			b->rp[0] = RHandshake;
 			b->rp[1] = HSSL2ClientHello;
@@ -946,7 +930,7 @@
 			dechandq(tr);
 		}else{
 			unlock(&tr->hqlock);
-			if(tr->verset && tr->version != SSL3Version && !waserror()){
+			if(tr->verset && !waserror()){
 				sendAlert(tr, ENoRenegotiation);
 				poperror();
 			}
@@ -1314,7 +1298,7 @@
 		put16(p+3, n);
 
 		if(sec != nil){
-			aadlen = (*tr->packAAD)(out->seq++, p, aad);
+			aadlen = packAAD(out->seq++, p, aad);
 			if(sec->aead_enc != nil)
 				n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen, p + RecHdrLen + ivlen, n) + ivlen;
 			else {
@@ -1390,42 +1374,34 @@
 {
 	char	*name;
 	int	maclen;
-	void	(*initkey)(Hashalg *, int, Secret *, uchar*);
+	void	(*initkey)(Hashalg *, Secret *, uchar*);
 };
 
 static void
-initmd5key(Hashalg *ha, int version, Secret *s, uchar *p)
+initmd5key(Hashalg *ha, Secret *s, uchar *p)
 {
 	s->maclen = ha->maclen;
-	if(version == SSL3Version)
-		s->mac = sslmac_md5;
-	else
-		s->mac = hmac_md5;
+	s->mac = hmac_md5;
 	memmove(s->mackey, p, ha->maclen);
 }
 
 static void
-initclearmac(Hashalg *, int, Secret *s, uchar *)
+initclearmac(Hashalg *, Secret *s, uchar *)
 {
 	s->mac = nomac;
 }
 
 static void
-initsha1key(Hashalg *ha, int version, Secret *s, uchar *p)
+initsha1key(Hashalg *ha, Secret *s, uchar *p)
 {
 	s->maclen = ha->maclen;
-	if(version == SSL3Version)
-		s->mac = sslmac_sha1;
-	else
-		s->mac = hmac_sha1;
+	s->mac = hmac_sha1;
 	memmove(s->mackey, p, ha->maclen);
 }
 
 static void
-initsha2_256key(Hashalg *ha, int version, Secret *s, uchar *p)
+initsha2_256key(Hashalg *ha, 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);
@@ -1641,10 +1617,6 @@
 		m = strtol(cb->f[1], nil, 0);
 		if(m < MinProtoVersion || m > MaxProtoVersion)
 			error("unsupported version");
-		if(m == SSL3Version)
-			tr->packAAD = sslPackAAD;
-		else
-			tr->packAAD = tlsPackAAD;
 		tr->verset = 1;
 		tr->version = m;
 	}else if(strcmp(cb->f[0], "secret") == 0){
@@ -1685,8 +1657,8 @@
 		if(!ha->initkey || !ea->initkey)
 			error("misimplemented secret algorithm");
 
-		(*ha->initkey)(ha, tr->version, tos, &x[0]);
-		(*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]);
+		(*ha->initkey)(ha, tos, &x[0]);
+		(*ha->initkey)(ha, toc, &x[ha->maclen]);
 		(*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]);
 		(*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]);
 
@@ -1701,13 +1673,6 @@
 			tr->in.new = toc;
 			tr->out.new = tos;
 		}
-		if(tr->version == SSL3Version){
-			toc->unpad = sslunpad;
-			tos->unpad = sslunpad;
-		}else{
-			toc->unpad = tlsunpad;
-			tos->unpad = tlsunpad;
-		}
 		toc->encalg = ea->name;
 		toc->hashalg = ha->name;
 		tos->encalg = ea->name;
@@ -1879,17 +1844,12 @@
 if(tr->debug)pprint("sendAlert %d\n", err);
 	fatal = 1;
 	msg = "tls unknown alert";
-	for(i=0; i < nelem(tlserrs); i++) {
-		if(tlserrs[i].err == err) {
+	for(i=0; i < nelem(tlserrs); i++)
+		if(tlserrs[i].err == err){
 			msg = tlserrs[i].msg;
-			if(tr->version == SSL3Version)
-				err = tlserrs[i].sslerr;
-			else
-				err = tlserrs[i].tlserr;
 			fatal = tlserrs[i].fatal;
 			break;
 		}
-	}
 
 	if(!waserror()){
 		b = allocb(2);
@@ -2061,7 +2021,7 @@
 }
 
 static int
-tlsunpad(uchar *buf, int n, int block)
+unpad(uchar *buf, int n, int block)
 {
 	int pad, nn;
 
@@ -2076,18 +2036,6 @@
 }
 
 static int
-sslunpad(uchar *buf, int n, int block)
-{
-	int pad, nn;
-
-	pad = buf[n - 1];
-	nn = n - 1 - pad;
-	if(nn <= 0 || n % block)
-		return -1;
-	return nn;
-}
-
-static int
 blockpad(uchar *buf, int n, int block)
 {
 	int pad, nn;
@@ -2112,7 +2060,7 @@
 des3dec(Secret *sec, uchar *buf, int n)
 {
 	des3CBCdecrypt(buf, n, sec->enckey);
-	return (*sec->unpad)(buf, n, 8);
+	return unpad(buf, n, 8);
 }
 
 static int
@@ -2127,7 +2075,7 @@
 aesdec(Secret *sec, uchar *buf, int n)
 {
 	aesCBCdecrypt(buf, n, sec->enckey);
-	return (*sec->unpad)(buf, n, 16);
+	return unpad(buf, n, 16);
 }
 
 static void
@@ -2213,71 +2161,8 @@
 	return nil;
 }
 
-/*
- * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac.
- */
-static DigestState*
-sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
-	DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen)
-{
-	int i;
-	uchar pad[48], innerdigest[20];
-
-	if(xlen > sizeof(innerdigest)
-	|| padlen > sizeof(pad))
-		return nil;
-
-	if(klen>64)
-		return nil;
-
-	/* first time through */
-	if(s == nil){
-		for(i=0; i<padlen; i++)
-			pad[i] = 0x36;
-		s = (*x)(key, klen, nil, nil);
-		s = (*x)(pad, padlen, nil, s);
-		if(s == nil)
-			return nil;
-	}
-
-	s = (*x)(p, len, nil, s);
-	if(digest == nil)
-		return s;
-
-	/* last time through */
-	for(i=0; i<padlen; i++)
-		pad[i] = 0x5c;
-	(*x)(nil, 0, innerdigest, s);
-	s = (*x)(key, klen, nil, nil);
-	s = (*x)(pad, padlen, nil, s);
-	(*x)(innerdigest, xlen, digest, s);
-	return nil;
-}
-
-static DigestState*
-sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
-	return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40);
-}
-
-static DigestState*
-sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
-	return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
-}
-
 static int
-sslPackAAD(u64int seq, uchar *hdr, uchar *aad)
-{
-	put64(aad, seq);
-	aad[8] = hdr[0];
-	aad[9] = hdr[3];
-	aad[10] = hdr[4];
-	return 11;
-}
-
-static int
-tlsPackAAD(u64int seq, uchar *hdr, uchar *aad)
+packAAD(u64int seq, uchar *hdr, uchar *aad)
 {
 	put64(aad, seq);
 	aad[8] = hdr[0];
--- a//sys/src/libsec/port/tlshand.c
+++ b//sys/src/libsec/port/tlshand.c
@@ -8,14 +8,13 @@
 //		client/server - main handshake protocol definition
 //		message functions - formating handshake messages
 //		cipher choices - catalog of digest and encrypt algorithms
-//		security functions - PKCS#1, sslHMAC, session keygen
+//		security functions - PKCS#1, session keygen
 //		general utility functions - malloc, serialization
-// The handshake protocol builds on the TLS/SSL3 record layer protocol,
-// which is implemented in kernel device #a.  See also /lib/rfc/rfc2246.
+// The handshake protocol builds on the TLS record layer protocol,
+// which is implemented in kernel device #a.  See also /lib/rfc/rfc5246.
 
 enum {
-	TLSFinishedLen = 12,
-	SSL3FinishedLen = MD5dlen+SHA1dlen,
+	FinishedLen = 12,
 	MaxKeyData = 160,	// amount of secret we may need
 	MAXdlen = SHA2_512dlen,
 	RandomSize = 32,
@@ -47,11 +46,6 @@
 	void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
 } Namedcurve;
 
-typedef struct Finished{
-	uchar verify[SSL3FinishedLen];
-	int n;
-} Finished;
-
 typedef struct HandshakeHash {
 	MD5state	md5;
 	SHAstate	sha1;
@@ -81,7 +75,6 @@
 	// byte generation and handshake checksum
 	void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int);
 	void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int);
-	int nfin;
 };
 
 typedef struct TlsConnection{
@@ -99,7 +92,7 @@
 
 	// for finished messages
 	HandshakeHash	handhash;
-	Finished	finished;
+	uchar		finished[FinishedLen];
 
 	uchar *sendp;
 	uchar buf[1<<16];
@@ -152,19 +145,17 @@
 			int sigalg;
 			Bytes *signature;
 		} certificateVerify;		
-		Finished finished;
+		uchar finished[FinishedLen];
 	} u;
 } Msg;
 
 
 enum {
-	SSL3Version	= 0x0300,
 	TLS10Version	= 0x0301,
 	TLS11Version	= 0x0302,
 	TLS12Version	= 0x0303,
 	ProtocolVersion	= TLS12Version,	// maximum version we speak
-	MinProtoVersion	= 0x0300,	// limits on version we accept
-	MaxProtoVersion	= 0x03ff,
+	MinProtoVersion	= TLS10Version,	// limits on version we accept
 };
 
 // handshake type
@@ -192,7 +183,6 @@
 	ERecordOverflow = 22,
 	EDecompressionFailure = 30,
 	EHandshakeFailure = 40,
-	ENoCertificate = 41,
 	EBadCertificate = 42,
 	EUnsupportedCertificate = 43,
 	ECertificateRevoked = 44,
@@ -365,9 +355,8 @@
 static int	msgSend(TlsConnection *c, Msg *m, int act);
 static void	tlsError(TlsConnection *c, int err, char *msg, ...);
 #pragma	varargck argpos	tlsError 3
-static int setVersion(TlsConnection *c, int version);
+static int setVersion(TlsConnection *c, int version, int client);
 static int setSecrets(TlsConnection *c, int isclient);
-static int finishedMatch(TlsConnection *c, Finished *f);
 static void tlsConnectionFree(TlsConnection *c);
 
 static int isDHE(int tlsid);
@@ -394,7 +383,6 @@
 static Bytes*	tlsSecDHEc(TlsSec *sec, Bytes *p, Bytes *g, Bytes *Ys);
 static Bytes*	tlsSecECDHEc(TlsSec *sec, int curve, Bytes *Ys);
 static void	tlsSecVers(TlsSec *sec, int v);
-static int	tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient);
 static void	setMasterSecret(TlsSec *sec, Bytes *pm);
 static int	digestDHparams(TlsSec *sec, Bytes *par, uchar digest[MAXdlen], int sigalg);
 static char*	verifyDHparams(TlsSec *sec, Bytes *par, Bytes *cert, Bytes *sig, int sigalg);
@@ -451,7 +439,7 @@
 		return -1;
 	}
 	data = -1;
-	fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
+	fprint(ctl, "fd %d 0x%x", fd, MinProtoVersion);
 	tls = tlsServer2(ctl, hand,
 		conn->cert, conn->certlen,
 		conn->pskID, conn->psk, conn->psklen,
@@ -511,28 +499,26 @@
 	}
 
 	// Elliptic Curves (also called Supported Groups)
-	if(ProtocolVersion >= TLS10Version){
-		m = p - b;
-		b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats));
-		p = b + m;
+	m = p - b;
+	b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats));
+	p = b + m;
 
-		n = nelem(namedcurves);
-		put16(p, Extec), p += 2;	/* Type: elliptic_curves / supported_groups */
-		put16(p, (n+1)*2), p += 2;	/* Length */
-		put16(p, n*2), p += 2;		/* Elliptic Curves Length */
-		for(i=0; i < n; i++){		/* Elliptic Curves */
-			put16(p, namedcurves[i].tlsid);
-			p += 2;
-		}
-
-		n = nelem(pointformats);
-		put16(p, Extecp), p += 2;	/* Type: ec_point_formats */
-		put16(p, n+1), p += 2;		/* Length */
-		*p++ = n;			/* EC point formats Length */
-		for(i=0; i < n; i++)		/* EC point formats */
-			*p++ = pointformats[i];
+	n = nelem(namedcurves);
+	put16(p, Extec), p += 2;	/* Type: elliptic_curves / supported_groups */
+	put16(p, (n+1)*2), p += 2;	/* Length */
+	put16(p, n*2), p += 2;		/* Elliptic Curves Length */
+	for(i=0; i < n; i++){		/* Elliptic Curves */
+		put16(p, namedcurves[i].tlsid);
+		p += 2;
 	}
 
+	n = nelem(pointformats);
+	put16(p, Extecp), p += 2;	/* Type: ec_point_formats */
+	put16(p, n+1), p += 2;		/* Length */
+	*p++ = n;			/* EC point formats Length */
+	for(i=0; i < n; i++)		/* EC point formats */
+		*p++ = pointformats[i];
+
 	// signature algorithms
 	if(ProtocolVersion >= TLS12Version){
 		n = nelem(sigalgs);
@@ -591,7 +577,7 @@
 		close(ctl);
 		return -1;
 	}
-	fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
+	fprint(ctl, "fd %d 0x%x", fd, MinProtoVersion);
 	ext = tlsClientExtensions(conn, &n);
 	tls = tlsClient2(ctl, hand,
 		conn->cert, conn->certlen, 
@@ -713,8 +699,8 @@
 	}
 	if(trace)
 		trace("ClientHello version %x\n", m.u.clientHello.version);
-	if(setVersion(c, m.u.clientHello.version) < 0) {
-		tlsError(c, EIllegalParameter, "incompatible version");
+	if(setVersion(c, m.u.clientHello.version, 0) < 0){
+		tlsError(c, EProtocolVersion, "incompatible version");
 		goto Err;
 	}
 	if(c->version < ProtocolVersion
@@ -849,10 +835,7 @@
 	}
 
 	/* no CertificateVerify; skip to Finished */
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
-		tlsError(c, EInternalError, "can't set finished: %r");
-		goto Err;
-	}
+	c->sec->setFinished(c->sec, c->handhash, c->finished, 1);
 	if(!msgRecv(c, &m))
 		goto Err;
 	if(m.tag != HFinished) {
@@ -859,7 +842,7 @@
 		tlsError(c, EUnexpectedMessage, "expected a finished");
 		goto Err;
 	}
-	if(!finishedMatch(c, &m.u.finished)) {
+	if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) {
 		tlsError(c, EHandshakeFailure, "finished verification failed");
 		goto Err;
 	}
@@ -871,12 +854,9 @@
 		goto Err;
 	}
 
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
-		tlsError(c, EInternalError, "can't set finished: %r");
-		goto Err;
-	}
+	c->sec->setFinished(c->sec, c->handhash, c->finished, 0);
 	m.tag = HFinished;
-	m.u.finished = c->finished;
+	memmove(m.u.finished, c->finished, FinishedLen);
 	if(!msgSend(c, &m, AFlush))
 		goto Err;
 	if(trace)
@@ -1056,8 +1036,8 @@
 		tlsError(c, EUnexpectedMessage, "expected a server hello");
 		goto Err;
 	}
-	if(setVersion(c, m.u.serverHello.version) < 0) {
-		tlsError(c, EIllegalParameter, "incompatible version: %r");
+	if(setVersion(c, m.u.serverHello.version, 1) < 0){
+		tlsError(c, EProtocolVersion, "incompatible version: %r");
 		goto Err;
 	}
 	tlsSecVers(c->sec, c->version);
@@ -1220,21 +1200,15 @@
 
 	// Cipherchange must occur immediately before Finished to avoid
 	// potential hole;  see section 4.3 of Wagner Schneier 1996.
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
-		tlsError(c, EInternalError, "can't set finished 1: %r");
-		goto Err;
-	}
+	c->sec->setFinished(c->sec, c->handhash, c->finished, 1);
 	m.tag = HFinished;
-	m.u.finished = c->finished;
+	memmove(m.u.finished, c->finished, FinishedLen);
 	if(!msgSend(c, &m, AFlush)) {
 		tlsError(c, EInternalError, "can't flush after client Finished: %r");
 		goto Err;
 	}
 
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
-		tlsError(c, EInternalError, "can't set finished 0: %r");
-		goto Err;
-	}
+	c->sec->setFinished(c->sec, c->handhash, c->finished, 0);
 	if(!msgRecv(c, &m)) {
 		tlsError(c, EInternalError, "can't read server Finished: %r");
 		goto Err;
@@ -1244,7 +1218,7 @@
 		goto Err;
 	}
 
-	if(!finishedMatch(c, &m.u.finished)) {
+	if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) {
 		tlsError(c, EHandshakeFailure, "finished verification failed");
 		goto Err;
 	}
@@ -1418,16 +1392,16 @@
 			goto Overflow;
 		if(isECDHE(c->cipher))
 			*p++ = n;
-		else if(isDHE(c->cipher) || c->version != SSL3Version)
+		else
 			put16(p, n), p += 2;
 		memmove(p, m->u.clientKeyExchange.key->data, n);
 		p += n;
 		break;
 	case HFinished:
-		if(p+m->u.finished.n > e)
+		if(p+FinishedLen > e)
 			goto Overflow;
-		memmove(p, m->u.finished.verify, m->u.finished.n);
-		p += m->u.finished.n;
+		memmove(p, m->u.finished, FinishedLen);
+		p += FinishedLen;
 		break;
 	}
 
@@ -1496,7 +1470,7 @@
 	}
 
 	if(type == HSSL2ClientHello){
-		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.
+		/* Cope with a TLS ClientHello expressed in SSL2 record format.
 			This is sent by some clients that we must interoperate
 			with, such as Java's JSSE and Microsoft's Internet Explorer. */
 		int nsid, nrandom, nciph;
@@ -1519,7 +1493,7 @@
 		if(nsid != 0 	/* no sid's, since shouldn't restart using ssl2 header */
 		|| nrandom < 16 || nn % 3 || n - nrandom < nn)
 			goto Err;
-		/* ignore ssl2 ciphers and look for {0x00, ssl3 cipher} */
+		/* ignore ssl2 ciphers and look for {0x00, tls cipher} */
 		nciph = 0;
 		for(i = 0; i < nn; i += 3)
 			if(p[i] == 0)
@@ -1790,10 +1764,8 @@
 			goto Short;
 		if(isECDHE(c->cipher))
 			nn = *p++, n--;
-		else if(isDHE(c->cipher) || c->version != SSL3Version)
-			nn = get16(p), p += 2, n -= 2;
 		else
-			nn = n;
+			nn = get16(p), p += 2, n -= 2;
 		if(n < nn)
 			goto Short;
 		m->u.clientKeyExchange.key = makebytes(p, nn);
@@ -1800,11 +1772,10 @@
 		n -= nn;
 		break;
 	case HFinished:
-		m->u.finished.n = c->finished.n;
-		if(n < m->u.finished.n)
+		if(n < FinishedLen)
 			goto Short;
-		memmove(m->u.finished.verify, p, m->u.finished.n);
-		n -= m->u.finished.n;
+		memmove(m->u.finished, p, FinishedLen);
+		n -= FinishedLen;
 		break;
 	}
 
@@ -2000,8 +1971,8 @@
 		break;
 	case HFinished:
 		bs = seprint(bs, be, "HFinished\n");
-		for(i=0; i<m->u.finished.n; i++)
-			bs = seprint(bs, be, "%.2x", m->u.finished.verify[i]);
+		for(i=0; i<FinishedLen; i++)
+			bs = seprint(bs, be, "%.2x", m->u.finished[i]);
 		bs = seprint(bs, be, "\n");
 		break;
 	}
@@ -2030,29 +2001,20 @@
 
 // commit to specific version number
 static int
-setVersion(TlsConnection *c, int version)
+setVersion(TlsConnection *c, int version, int client)
 {
-	if(version > MaxProtoVersion || version < MinProtoVersion)
+	if(version < MinProtoVersion)
 		return -1;
-	if(version > c->version)
-		version = c->version;
-	if(version == SSL3Version) {
+	if(version > c->version){
+		if(client)
+			return -1;
+		else
+			version = c->version;
+	}else
 		c->version = version;
-		c->finished.n = SSL3FinishedLen;
-	}else {
-		c->version = version;
-		c->finished.n = TLSFinishedLen;
-	}
 	return fprint(c->ctl, "version 0x%x", version);
 }
 
-// confirm that received Finished message matches the expected value
-static int
-finishedMatch(TlsConnection *c, Finished *f)
-{
-	return tsmemcmp(f->verify, c->finished.verify, f->n) == 0;
-}
-
 // free memory associated with TlsConnection struct
 //		(but don't close the TLS channel itself)
 static void
@@ -2390,68 +2352,6 @@
 		hmac_sha2_256, SHA2_256dlen);
 }
 
-static void
-sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed, int nseed)
-{
-	uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26];
-	DigestState *s;
-	int i, n, len;
-
-	USED(label);
-	len = 1;
-	while(nbuf > 0){
-		if(len > 26)
-			return;
-		for(i = 0; i < len; i++)
-			tmp[i] = 'A' - 1 + len;
-		s = sha1(tmp, len, nil, nil);
-		s = sha1(key, nkey, nil, s);
-		sha1(seed, nseed, sha1dig, s);
-		s = md5(key, nkey, nil, nil);
-		md5(sha1dig, SHA1dlen, md5dig, s);
-		n = MD5dlen;
-		if(n > nbuf)
-			n = nbuf;
-		memmove(buf, md5dig, n);
-		buf += n;
-		nbuf -= n;
-		len++;
-	}
-}
-
-static void
-sslSetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient)
-{
-	DigestState *s;
-	uchar h0[MD5dlen], h1[SHA1dlen], pad[48];
-	char *label;
-
-	if(isclient)
-		label = "CLNT";
-	else
-		label = "SRVR";
-
-	md5((uchar*)label, 4, nil, &hsh.md5);
-	md5(sec->sec, MasterSecretSize, nil, &hsh.md5);
-	memset(pad, 0x36, 48);
-	md5(pad, 48, nil, &hsh.md5);
-	md5(nil, 0, h0, &hsh.md5);
-	memset(pad, 0x5C, 48);
-	s = md5(sec->sec, MasterSecretSize, nil, nil);
-	s = md5(pad, 48, nil, s);
-	md5(h0, MD5dlen, finished, s);
-
-	sha1((uchar*)label, 4, nil, &hsh.sha1);
-	sha1(sec->sec, MasterSecretSize, nil, &hsh.sha1);
-	memset(pad, 0x36, 40);
-	sha1(pad, 40, nil, &hsh.sha1);
-	sha1(nil, 0, h1, &hsh.sha1);
-	memset(pad, 0x5C, 40);
-	s = sha1(sec->sec, MasterSecretSize, nil, nil);
-	s = sha1(pad, 40, nil, s);
-	sha1(h1, SHA1dlen, finished + MD5dlen, s);
-}
-
 // fill "finished" arg with md5(args)^sha1(args)
 static void
 tls10SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient)
@@ -2460,6 +2360,8 @@
 	char *label;
 
 	// get current hash value, but allow further messages to be hashed in
+	hsh.md5.malloced = 0;
+	hsh.sha1.malloced = 0;
 	md5(nil, 0, h, &hsh.md5);
 	sha1(nil, 0, h+MD5dlen, &hsh.sha1);
 
@@ -2467,7 +2369,7 @@
 		label = "client finished";
 	else
 		label = "server finished";
-	tls10PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h));
+	tls10PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h));
 }
 
 static void
@@ -2477,6 +2379,7 @@
 	char *label;
 
 	// get current hash value, but allow further messages to be hashed in
+	hsh.sha2_256.malloced = 0;
 	sha2_256(nil, 0, seed, &hsh.sha2_256);
 
 	if(isclient)
@@ -2483,7 +2386,7 @@
 		label = "client finished";
 	else
 		label = "server finished";
-	tls12PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen);
+	tls12PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen);
 }
 
 static void
@@ -2630,34 +2533,14 @@
 	return epm;
 }
 
-static int
-tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient)
-{
-	if(sec->nfin != nfin){
-		werrstr("invalid finished exchange");
-		return -1;
-	}
-	hsh.md5.malloced = 0;
-	hsh.sha1.malloced = 0;
-	hsh.sha2_256.malloced = 0;
-	(*sec->setFinished)(sec, hsh, fin, isclient);
-	return 0;
-}
-
 static void
 tlsSecVers(TlsSec *sec, int v)
 {
-	if(v == SSL3Version){
-		sec->setFinished = sslSetFinished;
-		sec->nfin = SSL3FinishedLen;
-		sec->prf = sslPRF;
-	}else if(v < TLS12Version) {
+	if(v < TLS12Version){
 		sec->setFinished = tls10SetFinished;
-		sec->nfin = TLSFinishedLen;
 		sec->prf = tls10PRF;
-	}else {
+	}else{
 		sec->setFinished = tls12SetFinished;
-		sec->nfin = TLSFinishedLen;
 		sec->prf = tls12PRF;
 	}
 }

  reply	other threads:[~2021-10-24 12:01 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-22  1:48 ori
2021-10-22  1:58 ` sl
2021-10-22  2:26   ` ori
2021-10-22  2:44     ` Stanley Lieber
2021-10-22 10:19       ` Philip Silva
2021-10-22 15:32         ` ori
2021-10-22 20:26   ` Stuart Morrow
2021-12-01  2:13     ` sl
2021-12-01  2:13     ` sl
2021-10-22 11:43 ` kemal
2021-10-22 14:31   ` kemal
2021-10-22 14:36     ` kemal
2021-10-23 15:47       ` ori
2021-10-23 16:12         ` cinap_lenrek
2021-10-23 16:17           ` ori
2021-10-23 20:13         ` kemal
2021-10-24 11:46           ` kemal [this message]
2021-10-24 16:06             ` cinap_lenrek
2021-10-24 16:14             ` cinap_lenrek
2021-10-23 11:18     ` kemal
2021-12-13  2:30 ` ori
2021-12-14 19:45   ` theinicke
2021-12-15  1:49     ` ori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CABO6shfizVvY3qmr+wwRrhrD493YMu3kcJ-zmXVwjovz+rbaAQ@mail.gmail.com \
    --to=kemalinanc8@gmail.com \
    --cc=9front@9front.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).