shithub: riscv

Download patch

ref: ad6b99359d4bc513e9a24f865bd310743b75e259
parent: 54c49284e03e46f6e3a5d41bfc9fbc98c6f0b214
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Apr 17 03:20:54 EDT 2016

libsec: massive cleanup of tlshand.c

don't pass or generate sessionID's. this was never used nor
actually implemented and leaks the process pid.

get rid of version and random field duplications, move TlsSec
structure into TlsConnection.

make msgRecv() clear the message first, get rid of unneccesary
msgClear() calls.

--- a/sys/src/libsec/port/tlshand.c
+++ b/sys/src/libsec/port/tlshand.c
@@ -20,14 +20,11 @@
 	MaxChunk = 1<<15,
 	MAXdlen = SHA2_512dlen,
 	RandomSize = 32,
-	SidSize = 32,
 	MasterSecretSize = 48,
 	AQueue = 0,
 	AFlush = 1,
 };
 
-typedef struct TlsSec TlsSec;
-
 typedef struct Bytes{
 	int len;
 	uchar data[1];  // [len]
@@ -62,21 +59,39 @@
 	SHA2_256state	sha2_256;
 } HandshakeHash;
 
+typedef struct TlsSec TlsSec;
+struct TlsSec {
+	RSApub *rsapub;
+	AuthRpc *rpc;	// factotum for rsa private key
+	uchar *psk;	// pre-shared key
+	int psklen;
+	int clientVers;			// version in ClientHello
+	uchar sec[MasterSecretSize];	// master secret
+	uchar crandom[RandomSize];	// client random
+	uchar srandom[RandomSize];	// server random
+	// byte generation and handshake checksum
+	void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int, uchar*, int);
+	void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int);
+	int nfin;
+};
+
 typedef struct TlsConnection{
-	TlsSec *sec;	// security management goo
+	TlsSec sec[1];	// security management goo
 	int hand, ctl;	// record layer file descriptors
 	int erred;		// set when tlsError called
 	int (*trace)(char*fmt, ...); // for debugging
 	int version;	// protocol we are speaking
-	int verset;		// version has been set
-	int ver2hi;		// server got a version 2 hello
-	int isClient;	// is this the client or server?
-	Bytes *sid;		// SessionID
 	Bytes *cert;	// server certificate; only last - no chain
 
-	Lock statelk;
-	int state;		// must be set using setstate
+	int cipher;
+	int nsecret;	// amount of secret data to init keys
+	char *digest;	// name of digest algorithm to use
+	char *enc;		// name of encryption algorithm to use
 
+	// for finished messages
+	HandshakeHash	handhash;
+	Finished	finished;
+
 	// input buffer for handshake messages
 	uchar recvbuf[MaxChunk];
 	uchar *rp, *ep;
@@ -84,18 +99,6 @@
 	// output buffer
 	uchar sendbuf[MaxChunk];
 	uchar *sendp;
-
-	uchar crandom[RandomSize];	// client random
-	uchar srandom[RandomSize];	// server random
-	int clientVersion;	// version in ClientHello
-	int cipher;
-	char *digest;	// name of digest algorithm to use
-	char *enc;		// name of encryption algorithm to use
-	int nsecret;	// amount of secret data to init keys
-
-	// for finished messages
-	HandshakeHash	handhash;
-	Finished	finished;
 } TlsConnection;
 
 typedef struct Msg{
@@ -149,25 +152,7 @@
 	} u;
 } Msg;
 
-typedef struct TlsSec{
-	char *server;	// name of remote; nil for server
-	int ok;	// <0 killed; == 0 in progress; >0 reusable
-	RSApub *rsapub;
-	AuthRpc *rpc;	// factotum for rsa private key
-	uchar *psk;	// pre-shared key
-	int psklen;
-	uchar sec[MasterSecretSize];	// master secret
-	uchar crandom[RandomSize];	// client random
-	uchar srandom[RandomSize];	// server random
-	int clientVers;		// version in ClientHello
-	int vers;			// final version
-	// byte generation and handshake checksum
-	void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int, uchar*, int);
-	void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int);
-	int nfin;
-} TlsSec;
 
-
 enum {
 	SSL3Version	= 0x0300,
 	TLS10Version	= 0x0301,
@@ -386,7 +371,6 @@
 	char *pskid, uchar *psk, int psklen,
 	int (*trace)(char*fmt, ...), PEMChain *chain);
 static TlsConnection *tlsClient2(int ctl, int hand,
-	uchar *csid, int ncsid,
 	uchar *cert, int certlen,
 	char *pskid, uchar *psk, int psklen,
 	uchar *ext, int extlen, int (*trace)(char*fmt, ...));
@@ -397,6 +381,7 @@
 static void	tlsError(TlsConnection *c, int err, char *msg, ...);
 #pragma	varargck argpos	tlsError 3
 static int setVersion(TlsConnection *c, int version);
+static int setSecrets(TlsConnection *c, int isclient);
 static int finishedMatch(TlsConnection *c, Finished *f);
 static void tlsConnectionFree(TlsConnection *c);
 
@@ -406,27 +391,19 @@
 static int initCiphers(void);
 static Ints* makeciphers(int ispsk);
 
-static TlsSec*	tlsSecInits(int cvers, uchar *csid, int ncsid, uchar *crandom, uchar *ssid, int *nssid, uchar *srandom);
-static int	tlsSecRSAs(TlsSec *sec, int vers, Bytes *epm);
-static int	tlsSecPSKs(TlsSec *sec, int vers);
-static TlsSec*	tlsSecInitc(int cvers, uchar *crandom);
-static Bytes*	tlsSecRSAc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers);
-static int	tlsSecPSKc(TlsSec *sec, uchar *srandom, int vers);
-static Bytes*	tlsSecDHEc(TlsSec *sec, uchar *srandom, int vers, Bytes *p, Bytes *g, Bytes *Ys);
-static Bytes*	tlsSecECDHEc(TlsSec *sec, uchar *srandom, int vers, int curve, Bytes *Ys);
+static void	tlsSecInits(TlsSec *sec, int cvers, uchar *crandom);
+static int	tlsSecRSAs(TlsSec *sec, Bytes *epm);
+static void	tlsSecPSKs(TlsSec *sec);
+static void	tlsSecInitc(TlsSec *sec, int cvers);
+static Bytes*	tlsSecRSAc(TlsSec *sec, uchar *cert, int ncert);
+static void	tlsSecPSKc(TlsSec *sec);
+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	tlsSecOk(TlsSec *sec);
-static void	tlsSecClose(TlsSec *sec);
 static void	setMasterSecret(TlsSec *sec, Bytes *pm);
-static void	setSecrets(TlsSec *sec, uchar *kd, int nkd);
 static Bytes*	pkcs1_encrypt(Bytes* data, RSApub* key, int blocktype);
 static Bytes*	pkcs1_decrypt(TlsSec *sec, Bytes *cipher);
-static void	tls10SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isClient);
-static void	tls12SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isClient);
-static void	sslSetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isClient);
-static void	sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label,
-			uchar *seed0, int nseed0, uchar *seed1, int nseed1);
-static int setVers(TlsSec *sec, int version);
 
 static AuthRpc* factotum_rsa_open(RSApub *rsapub);
 static mpint* factotum_rsa_decrypt(AuthRpc *rpc, mpint *cipher);
@@ -482,26 +459,27 @@
 		close(ctl);
 		return -1;
 	}
+	data = -1;
 	fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
 	tls = tlsServer2(ctl, hand,
 		conn->cert, conn->certlen,
 		conn->pskID, conn->psk, conn->psklen,
 		conn->trace, conn->chain);
-	snprint(dname, sizeof(dname), "#a/tls/%s/data", buf);
-	data = open(dname, ORDWR);
+	if(tls != nil){
+		snprint(dname, sizeof(dname), "#a/tls/%s/data", buf);
+		data = open(dname, ORDWR);
+	}
 	close(hand);
 	close(ctl);
-	if(data < 0 || tls == nil){
-		if(tls != nil)
-			tlsConnectionFree(tls);
+	if(data < 0){
+		tlsConnectionFree(tls);
 		return -1;
 	}
 	free(conn->cert);
 	conn->cert = nil;  // client certificates are not yet implemented
 	conn->certlen = 0;
-	conn->sessionIDlen = tls->sid->len;
-	conn->sessionID = emalloc(conn->sessionIDlen);
-	memcpy(conn->sessionID, tls->sid->data, conn->sessionIDlen);
+	conn->sessionIDlen = 0;
+	conn->sessionID = nil;
 	if(conn->sessionKey != nil
 	&& conn->sessionType != nil
 	&& strcmp(conn->sessionType, "ttls") == 0)
@@ -624,7 +602,6 @@
 	fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
 	ext = tlsClientExtensions(conn, &n);
 	tls = tlsClient2(ctl, hand,
-		conn->sessionID, conn->sessionIDlen,
 		conn->cert, conn->certlen, 
 		conn->pskID, conn->psk, conn->psklen,
 		ext, n, conn->trace);
@@ -635,6 +612,7 @@
 		close(data);
 		return -1;
 	}
+	free(conn->cert);
 	if(tls->cert != nil){
 		conn->certlen = tls->cert->len;
 		conn->cert = emalloc(conn->certlen);
@@ -643,9 +621,8 @@
 		conn->certlen = 0;
 		conn->cert = nil;
 	}
-	conn->sessionIDlen = tls->sid->len;
-	conn->sessionID = emalloc(conn->sessionIDlen);
-	memcpy(conn->sessionID, tls->sid->data, conn->sessionIDlen);
+	conn->sessionIDlen = 0;
+	conn->sessionID = nil;
 	if(conn->sessionKey != nil
 	&& conn->sessionType != nil
 	&& strcmp(conn->sessionType, "ttls") == 0)
@@ -680,15 +657,13 @@
 {
 	TlsConnection *c;
 	Msg m;
-	Bytes *csid;
-	uchar sid[SidSize], kd[MaxKeyData];
-	char *secrets;
-	int cipher, compressor, nsid, rv, numcerts, i;
+	int cipher, compressor, numcerts, i;
 
 	if(trace)
 		trace("tlsServer2\n");
 	if(!initCiphers())
 		return nil;
+
 	c = emalloc(sizeof(TlsConnection));
 	c->ctl = ctl;
 	c->hand = hand;
@@ -705,15 +680,13 @@
 		tlsError(c, EUnexpectedMessage, "expected a client hello");
 		goto Err;
 	}
-	c->clientVersion = m.u.clientHello.version;
 	if(trace)
-		trace("ClientHello version %x\n", c->clientVersion);
-	if(setVersion(c, c->clientVersion) < 0) {
+		trace("ClientHello version %x\n", m.u.clientHello.version);
+	if(setVersion(c, m.u.clientHello.version) < 0) {
 		tlsError(c, EIllegalParameter, "incompatible version");
 		goto Err;
 	}
 
-	memmove(c->crandom, m.u.clientHello.random, RandomSize);
 	cipher = okCipher(m.u.clientHello.ciphers, psklen > 0);
 	if(cipher < 0 || !setAlgs(c, cipher)) {
 		tlsError(c, EHandshakeFailure, "no matching cipher suite");
@@ -724,11 +697,11 @@
 		tlsError(c, EHandshakeFailure, "no matching compressor");
 		goto Err;
 	}
-
-	csid = m.u.clientHello.sid;
 	if(trace)
-		trace("  cipher %x, compressor %x, csidlen %d\n", cipher, compressor, csid->len);
-	c->sec = tlsSecInits(c->clientVersion, csid->data, csid->len, c->crandom, sid, &nsid, c->srandom);
+		trace("  cipher %x, compressor %x\n", cipher, compressor);
+
+	tlsSecInits(c->sec, m.u.clientHello.version, m.u.clientHello.random);
+	tlsSecVers(c->sec, c->version);
 	if(psklen > 0){
 		c->sec->psk = psk;
 		c->sec->psklen = psklen;
@@ -750,14 +723,12 @@
 
 	m.tag = HServerHello;
 	m.u.serverHello.version = c->version;
-	memmove(m.u.serverHello.random, c->srandom, RandomSize);
+	memmove(m.u.serverHello.random, c->sec->srandom, RandomSize);
 	m.u.serverHello.cipher = cipher;
 	m.u.serverHello.compressor = compressor;
-	c->sid = makebytes(sid, nsid);
-	m.u.serverHello.sid = makebytes(c->sid->data, c->sid->len);
+	m.u.serverHello.sid = makebytes(nil, 0);
 	if(!msgSend(c, &m, AQueue))
 		goto Err;
-	msgClear(&m);
 
 	if(certlen > 0){
 		m.tag = HCertificate;
@@ -769,13 +740,11 @@
 			m.u.certificate.certs[i+1] = makebytes(chp->pem, chp->pemlen);
 		if(!msgSend(c, &m, AQueue))
 			goto Err;
-		msgClear(&m);
 	}
 
 	m.tag = HServerHelloDone;
 	if(!msgSend(c, &m, AFlush))
 		goto Err;
-	msgClear(&m);
 
 	if(!msgRecv(c, &m))
 		goto Err;
@@ -792,34 +761,23 @@
 		}
 	}
 	if(certlen > 0){
-		if(tlsSecRSAs(c->sec, c->version, m.u.clientKeyExchange.key) < 0){
-			tlsError(c, EHandshakeFailure, "couldn't set secrets: %r");
+		if(tlsSecRSAs(c->sec, m.u.clientKeyExchange.key) < 0){
+			tlsError(c, EHandshakeFailure, "couldn't set keys: %r");
 			goto Err;
 		}
 	} else if(psklen > 0){
-		if(tlsSecPSKs(c->sec, c->version) < 0){
-			tlsError(c, EHandshakeFailure, "couldn't set secrets: %r");
-			goto Err;
-		}
+		tlsSecPSKs(c->sec);
 	} else {
 		tlsError(c, EInternalError, "no psk or certificate");
 		goto Err;
 	}
 
-	setSecrets(c->sec, kd, c->nsecret);
 	if(trace)
 		trace("tls secrets\n");
-	secrets = (char*)emalloc(2*c->nsecret);
-	enc64(secrets, 2*c->nsecret, kd, c->nsecret);
-	rv = fprint(c->ctl, "secret %s %s 0 %s", c->digest, c->enc, secrets);
-	memset(secrets, 0, 2*c->nsecret);
-	free(secrets);
-	memset(kd, 0, c->nsecret);
-	if(rv < 0){
-		tlsError(c, EHandshakeFailure, "can't set keys: %r");
+	if(setSecrets(c, 0) < 0){
+		tlsError(c, EHandshakeFailure, "can't set secrets: %r");
 		goto Err;
 	}
-	msgClear(&m);
 
 	/* no CertificateVerify; skip to Finished */
 	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
@@ -852,19 +810,17 @@
 	m.u.finished = c->finished;
 	if(!msgSend(c, &m, AFlush))
 		goto Err;
-	msgClear(&m);
 	if(trace)
 		trace("tls finished\n");
 
 	if(fprint(c->ctl, "opened") < 0)
 		goto Err;
-	tlsSecOk(c->sec);
 	return c;
 
 Err:
 	msgClear(&m);
 	tlsConnectionFree(c);
-	return 0;
+	return nil;
 }
 
 static int
@@ -918,8 +874,7 @@
 }
 
 static Bytes*
-tlsSecDHEc(TlsSec *sec, uchar *srandom, int vers, 
-	Bytes *p, Bytes *g, Bytes *Ys)
+tlsSecDHEc(TlsSec *sec, Bytes *p, Bytes *g, Bytes *Ys)
 {
 	mpint *G, *P, *Y, *K;
 	Bytes *epm;
@@ -928,10 +883,6 @@
 	if(p == nil || g == nil || Ys == nil)
 		return nil;
 
-	memmove(sec->srandom, srandom, RandomSize);
-	if(setVers(sec, vers) < 0)
-		return nil;
-
 	epm = nil;
 	P = bytestomp(p);
 	G = bytestomp(g);
@@ -959,7 +910,7 @@
 }
 
 static Bytes*
-tlsSecECDHEc(TlsSec *sec, uchar *srandom, int vers, int curve, Bytes *Ys)
+tlsSecECDHEc(TlsSec *sec, int curve, Bytes *Ys)
 {
 	Namedcurve *nc, *enc;
 	Bytes *epm;
@@ -978,10 +929,6 @@
 
 	if(nc == enc)
 		return nil;
-		
-	memmove(sec->srandom, srandom, RandomSize);
-	if(setVers(sec, vers) < 0)
-		return nil;
 	
 	ecdominit(&dom, nc->init);
 	pub = ecdecodepub(&dom, Ys->data, Ys->len);
@@ -1031,7 +978,7 @@
 	char *err;
 
 	if(par == nil || par->len <= 0)
-		return "no dh parameters";
+		return "no DH parameters";
 
 	if(sig == nil || sig->len <= 0){
 		if(c->sec->psklen > 0)
@@ -1043,8 +990,8 @@
 		return "no certificate";
 
 	blob = newbytes(2*RandomSize + par->len);
-	memmove(blob->data+0*RandomSize, c->crandom, RandomSize);
-	memmove(blob->data+1*RandomSize, c->srandom, RandomSize);
+	memmove(blob->data+0*RandomSize, c->sec->crandom, RandomSize);
+	memmove(blob->data+1*RandomSize, c->sec->srandom, RandomSize);
 	memmove(blob->data+2*RandomSize, par->data, par->len);
 	if(c->version < TLS12Version){
 		digestlen = MD5dlen + SHA1dlen;
@@ -1089,7 +1036,6 @@
 
 static TlsConnection *
 tlsClient2(int ctl, int hand,
-	uchar *csid, int ncsid, 
 	uchar *cert, int certlen,
 	char *pskid, uchar *psk, int psklen,
 	uchar *ext, int extlen,
@@ -1097,25 +1043,23 @@
 {
 	TlsConnection *c;
 	Msg m;
-	uchar kd[MaxKeyData];
-	char *secrets;
-	int creq, dhx, rv, cipher;
+	int creq, dhx, cipher;
 	Bytes *epm;
 
 	if(!initCiphers())
 		return nil;
+
 	epm = nil;
+	memset(&m, 0, sizeof(m));
 	c = emalloc(sizeof(TlsConnection));
-	c->version = ProtocolVersion;
 
 	c->ctl = ctl;
 	c->hand = hand;
 	c->trace = trace;
-	c->isClient = 1;
-	c->clientVersion = c->version;
 	c->cert = nil;
 
-	c->sec = tlsSecInitc(c->clientVersion, c->crandom);
+	c->version = ProtocolVersion;
+	tlsSecInitc(c->sec, c->version);
 	if(psklen > 0){
 		c->sec->psk = psk;
 		c->sec->psklen = psklen;
@@ -1124,28 +1068,26 @@
 		/* client certificate */
 		c->sec->rsapub = X509toRSApub(cert, certlen, nil, 0);
 		if(c->sec->rsapub == nil){
-			tlsError(c, EHandshakeFailure, "invalid X509/rsa certificate");
+			tlsError(c, EInternalError, "invalid X509/rsa certificate");
 			goto Err;
 		}
 		c->sec->rpc = factotum_rsa_open(c->sec->rsapub);
 		if(c->sec->rpc == nil){
-			tlsError(c, EHandshakeFailure, "factotum_rsa_open: %r");
+			tlsError(c, EInternalError, "factotum_rsa_open: %r");
 			goto Err;
 		}
 	}
 
 	/* client hello */
-	memset(&m, 0, sizeof(m));
 	m.tag = HClientHello;
-	m.u.clientHello.version = c->clientVersion;
-	memmove(m.u.clientHello.random, c->crandom, RandomSize);
-	m.u.clientHello.sid = makebytes(csid, ncsid);
+	m.u.clientHello.version = c->version;
+	memmove(m.u.clientHello.random, c->sec->crandom, RandomSize);
+	m.u.clientHello.sid = makebytes(nil, 0);
 	m.u.clientHello.ciphers = makeciphers(psklen > 0);
 	m.u.clientHello.compressors = makebytes(compressors,sizeof(compressors));
 	m.u.clientHello.extensions = makebytes(ext, extlen);
 	if(!msgSend(c, &m, AFlush))
 		goto Err;
-	msgClear(&m);
 
 	/* server hello */
 	if(!msgRecv(c, &m))
@@ -1158,12 +1100,9 @@
 		tlsError(c, EIllegalParameter, "incompatible version: %r");
 		goto Err;
 	}
-	memmove(c->srandom, m.u.serverHello.random, RandomSize);
-	c->sid = makebytes(m.u.serverHello.sid->data, m.u.serverHello.sid->len);
-	if(c->sid->len != 0 && c->sid->len != SidSize) {
-		tlsError(c, EIllegalParameter, "invalid server session identifier");
-		goto Err;
-	}
+	tlsSecVers(c->sec, c->version);
+	memmove(c->sec->srandom, m.u.serverHello.random, RandomSize);
+
 	cipher = m.u.serverHello.cipher;
 	if((psklen > 0) != isPSK(cipher) || !setAlgs(c, cipher)) {
 		tlsError(c, EIllegalParameter, "invalid cipher suite");
@@ -1173,7 +1112,6 @@
 		tlsError(c, EIllegalParameter, "invalid compression");
 		goto Err;
 	}
-	msgClear(&m);
 
 	dhx = isDHE(cipher) || isECDHE(cipher);
 	if(!msgRecv(c, &m))
@@ -1184,7 +1122,6 @@
 			goto Err;
 		}
 		c->cert = makebytes(m.u.certificate.certs[0]->data, m.u.certificate.certs[0]->len);
-		msgClear(&m);
 		if(!msgRecv(c, &m))
 			goto Err;
 	} else if(psklen == 0) {
@@ -1198,25 +1135,26 @@
 				m.u.serverKeyExchange.dh_signature,
 				m.u.serverKeyExchange.sigalg);
 			if(err != nil){
-				tlsError(c, EBadCertificate, "can't verify dh parameters: %s", err);
+				tlsError(c, EBadCertificate, "can't verify DH parameters: %s", err);
 				goto Err;
 			}
 			if(isECDHE(cipher))
-				epm = tlsSecECDHEc(c->sec, c->srandom, c->version,
+				epm = tlsSecECDHEc(c->sec,
 					m.u.serverKeyExchange.curve,
 					m.u.serverKeyExchange.dh_Ys);
 			else
-				epm = tlsSecDHEc(c->sec, c->srandom, c->version,
+				epm = tlsSecDHEc(c->sec,
 					m.u.serverKeyExchange.dh_p, 
 					m.u.serverKeyExchange.dh_g,
 					m.u.serverKeyExchange.dh_Ys);
-			if(epm == nil)
-				goto Badcert;
+			if(epm == nil){
+				tlsError(c, EHandshakeFailure, "bad DH parameters");
+				goto Err;
+			}
 		} else if(psklen == 0){
 			tlsError(c, EUnexpectedMessage, "got an server key exchange");
 			goto Err;
 		}
-		msgClear(&m);
 		if(!msgRecv(c, &m))
 			goto Err;
 	} else if(dhx){
@@ -1228,7 +1166,6 @@
 	creq = 0;
 	if(m.tag == HCertificateRequest) {
 		creq = 1;
-		msgClear(&m);
 		if(!msgRecv(c, &m))
 			goto Err;
 	}
@@ -1241,16 +1178,13 @@
 
 	if(!dhx){
 		if(c->cert != nil){
-			epm = tlsSecRSAc(c->sec, c->sid->data, c->sid->len, c->srandom,
-				c->cert->data, c->cert->len, c->version);
+			epm = tlsSecRSAc(c->sec, c->cert->data, c->cert->len);
 			if(epm == nil){
-			Badcert:
 				tlsError(c, EBadCertificate, "bad certificate: %r");
 				goto Err;
 			}
-		} else if(psklen > 0) {
-			if(tlsSecPSKc(c->sec, c->srandom, c->version) < 0)
-				goto Badcert;
+		} else if(psklen > 0){
+			tlsSecPSKc(c->sec);
 		} else {
 			tlsError(c, EInternalError, "no psk or certificate");
 			goto Err;
@@ -1257,28 +1191,22 @@
 		}
 	}
 
-	setSecrets(c->sec, kd, c->nsecret);
-	secrets = (char*)emalloc(2*c->nsecret);
-	enc64(secrets, 2*c->nsecret, kd, c->nsecret);
-	rv = fprint(c->ctl, "secret %s %s 1 %s", c->digest, c->enc, secrets);
-	memset(secrets, 0, 2*c->nsecret);
-	free(secrets);
-	memset(kd, 0, c->nsecret);
-	if(rv < 0){
-		tlsError(c, EHandshakeFailure, "can't set keys: %r");
+	if(trace)
+		trace("tls secrets\n");
+	if(setSecrets(c, 1) < 0){
+		tlsError(c, EHandshakeFailure, "can't set secrets: %r");
 		goto Err;
 	}
 
 	if(creq) {
+		m.tag = HCertificate;
 		if(certlen > 0){
 			m.u.certificate.ncert = 1;
 			m.u.certificate.certs = emalloc(m.u.certificate.ncert * sizeof(Bytes*));
 			m.u.certificate.certs[0] = makebytes(cert, certlen);
 		}		
-		m.tag = HCertificate;
 		if(!msgSend(c, &m, AFlush))
 			goto Err;
-		msgClear(&m);
 	}
 
 	/* client key exchange */
@@ -1293,7 +1221,6 @@
 	 
 	if(!msgSend(c, &m, AFlush))
 		goto Err;
-	msgClear(&m);
 
 	/* certificate verify */
 	if(creq && certlen > 0) {
@@ -1334,7 +1261,6 @@
 		m.tag = HCertificateVerify;
 		if(!msgSend(c, &m, AFlush))
 			goto Err;
-		msgClear(&m);
 	} 
 
 	/* change cipher spec */
@@ -1355,7 +1281,6 @@
 		tlsError(c, EInternalError, "can't flush after client Finished: %r");
 		goto Err;
 	}
-	msgClear(&m);
 
 	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
 		tlsError(c, EInternalError, "can't set finished 0: %r");
@@ -1381,7 +1306,6 @@
 			trace("unable to do final open: %r\n");
 		goto Err;
 	}
-	tlsSecOk(c->sec);
 	return c;
 
 Err:
@@ -1433,13 +1357,11 @@
 
 		// sid
 		n = m->u.clientHello.sid->len;
-		assert(n < 256);
 		p[0] = n;
 		memmove(p+1, m->u.clientHello.sid->data, n);
 		p += n+1;
 
 		n = m->u.clientHello.ciphers->len;
-		assert(n > 0 && n < 200);
 		put16(p, n*2);
 		p += 2;
 		for(i=0; i<n; i++) {
@@ -1448,7 +1370,6 @@
 		}
 
 		n = m->u.clientHello.compressors->len;
-		assert(n > 0);
 		p[0] = n;
 		memmove(p+1, m->u.clientHello.compressors->data, n);
 		p += n+1;
@@ -1472,7 +1393,6 @@
 
 		// sid
 		n = m->u.serverHello.sid->len;
-		assert(n < 256);
 		p[0] = n;
 		memmove(p+1, m->u.serverHello.sid->data, n);
 		p += n+1;
@@ -1548,7 +1468,7 @@
 
 	// go back and fill in size
 	n = p - c->sendp;
-	assert(p <= c->sendbuf + sizeof(c->sendbuf));
+	assert(n <= sizeof(c->sendbuf));
 	put24(c->sendp+1, n-4);
 
 	// remember hash of Handshake messages
@@ -1599,8 +1519,9 @@
 msgRecv(TlsConnection *c, Msg *m)
 {
 	uchar *p, *s;
-	int type, n, nn, i, nsid, nrandom, nciph;
+	int type, n, nn, i;
 
+	msgClear(m);
 	for(;;) {
 		p = tlsReadN(c, 4);
 		if(p == nil)
@@ -1625,6 +1546,8 @@
 		/* Cope with an SSL3 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;
+
 		p = tlsReadN(c, n);
 		if(p == nil)
 			return 0;
@@ -1683,14 +1606,12 @@
 		if(n < 2)
 			goto Short;
 		m->u.clientHello.version = get16(p);
-		p += 2;
-		n -= 2;
+		p += 2, n -= 2;
 
 		if(n < RandomSize)
 			goto Short;
 		memmove(m->u.clientHello.random, p, RandomSize);
-		p += RandomSize;
-		n -= RandomSize;
+		p += RandomSize, n -= RandomSize;
 		if(n < 1 || n < p[0]+1)
 			goto Short;
 		m->u.clientHello.sid = makebytes(p+1, p[0]);
@@ -1700,8 +1621,7 @@
 		if(n < 2)
 			goto Short;
 		nn = get16(p);
-		p += 2;
-		n -= 2;
+		p += 2, n -= 2;
 
 		if((nn & 1) || n < nn || nn < 2)
 			goto Short;
@@ -1708,15 +1628,13 @@
 		m->u.clientHello.ciphers = newints(nn >> 1);
 		for(i = 0; i < nn; i += 2)
 			m->u.clientHello.ciphers->data[i >> 1] = get16(&p[i]);
-		p += nn;
-		n -= nn;
+		p += nn, n -= nn;
 
 		if(n < 1 || n < p[0]+1 || p[0] == 0)
 			goto Short;
 		nn = p[0];
 		m->u.clientHello.compressors = makebytes(p+1, nn);
-		p += nn + 1;
-		n -= nn + 1;
+		p += nn + 1, n -= nn + 1;
 
 		if(n < 2)
 			break;
@@ -1730,14 +1648,12 @@
 		if(n < 2)
 			goto Short;
 		m->u.serverHello.version = get16(p);
-		p += 2;
-		n -= 2;
+		p += 2, n -= 2;
 
 		if(n < RandomSize)
 			goto Short;
 		memmove(m->u.serverHello.random, p, RandomSize);
-		p += RandomSize;
-		n -= RandomSize;
+		p += RandomSize, n -= RandomSize;
 
 		if(n < 1 || n < p[0]+1)
 			goto Short;
@@ -1749,8 +1665,7 @@
 			goto Short;
 		m->u.serverHello.cipher = get16(p);
 		m->u.serverHello.compressor = p[2];
-		p += 3;
-		n -= 3;
+		p += 3, n -= 3;
 
 		if(n < 2)
 			break;
@@ -1764,8 +1679,7 @@
 		if(n < 3)
 			goto Short;
 		nn = get24(p);
-		p += 3;
-		n -= 3;
+		p += 3, n -= 3;
 		if(nn == 0 && n > 0)
 			goto Short;
 		/* certs */
@@ -1774,15 +1688,13 @@
 			if(n < 3)
 				goto Short;
 			nn = get24(p);
-			p += 3;
-			n -= 3;
+			p += 3, n -= 3;
 			if(nn > n)
 				goto Short;
 			m->u.certificate.ncert = i+1;
 			m->u.certificate.certs = erealloc(m->u.certificate.certs, (i+1)*sizeof(Bytes*));
 			m->u.certificate.certs[i] = makebytes(p, nn);
-			p += nn;
-			n -= nn;
+			p += nn, n -= nn;
 			i++;
 		}
 		break;
@@ -1790,33 +1702,28 @@
 		if(n < 1)
 			goto Short;
 		nn = p[0];
-		p += 1;
-		n -= 1;
+		p++, n--;
 		if(nn > n)
 			goto Short;
 		m->u.certificateRequest.types = makebytes(p, nn);
-		p += nn;
-		n -= nn;
+		p += nn, n -= nn;
 		if(c->version >= TLS12Version){
 			if(n < 2)
 				goto Short;
 			nn = get16(p);
-			p += 2;
-			n -= 2;
+			p += 2, n -= 2;
 			if(nn & 1)
 				goto Short;
 			m->u.certificateRequest.sigalgs = newints(nn>>1);
 			for(i = 0; i < nn; i += 2)
 				m->u.certificateRequest.sigalgs->data[i >> 1] = get16(&p[i]);
-			p += nn;
-			n -= nn;
+			p += nn, n -= nn;
 
 		}
 		if(n < 2)
 			goto Short;
 		nn = get16(p);
-		p += 2;
-		n -= 2;
+		p += 2, n -= 2;
 		/* nn == 0 can happen; yahoo's servers do it */
 		if(nn != n)
 			goto Short;
@@ -1826,8 +1733,7 @@
 			if(n < 2)
 				goto Short;
 			nn = get16(p);
-			p += 2;
-			n -= 2;
+			p += 2, n -= 2;
 			if(nn < 1 || nn > n)
 				goto Short;
 			m->u.certificateRequest.nca = i+1;
@@ -1834,8 +1740,7 @@
 			m->u.certificateRequest.cas = erealloc(
 				m->u.certificateRequest.cas, (i+1)*sizeof(Bytes*));
 			m->u.certificateRequest.cas[i] = makebytes(p, nn);
-			p += nn;
-			n -= nn;
+			p += nn, n -= nn;
 			i++;
 		}
 		break;
@@ -1940,8 +1845,7 @@
 			if(n < 2)
 				goto Short;
 			nn = get16(p);
-			p += 2;
-			n -= 2;
+			p += 2, n -= 2;
 		}
 		if(n < nn)
 			goto Short;
@@ -1980,8 +1884,6 @@
 	int i;
 
 	switch(m->tag) {
-	default:
-		sysfatal("msgClear: unknown message type: %d", m->tag);
 	case HHelloRequest:
 		break;
 	case HClientHello:
@@ -2186,7 +2088,7 @@
 static int
 setVersion(TlsConnection *c, int version)
 {
-	if(c->verset || version > MaxProtoVersion || version < MinProtoVersion)
+	if(version > MaxProtoVersion || version < MinProtoVersion)
 		return -1;
 	if(version > c->version)
 		version = c->version;
@@ -2197,7 +2099,6 @@
 		c->version = version;
 		c->finished.n = TLSFinishedLen;
 	}
-	c->verset = 1;
 	return fprint(c->ctl, "version 0x%x", version);
 }
 
@@ -2213,8 +2114,10 @@
 static void
 tlsConnectionFree(TlsConnection *c)
 {
-	tlsSecClose(c->sec);
-	freebytes(c->sid);
+	if(c == nil)
+		return;
+	factotum_rsa_close(c->sec->rpc);
+	rsapubfree(c->sec->rsapub);
 	freebytes(c->cert);
 	memset(c, 0, sizeof(*c));
 	free(c);
@@ -2528,57 +2431,129 @@
 	p_sha256(buf, nbuf, key, nkey, (uchar*)label, strlen(label), seed, nseed0+nseed1);
 }
 
-/*
- * for setting server session id's
- */
-static Lock	sidLock;
-static long	maxSid = 1;
+static void
+sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1)
+{
+	uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26];
+	DigestState *s;
+	int i, n, len;
 
-/* the keys are verified to have the same public components
- * and to function correctly with pkcs 1 encryption and decryption. */
-static TlsSec*
-tlsSecInits(int cvers, uchar *csid, int ncsid, uchar *crandom, uchar *ssid, int *nssid, uchar *srandom)
+	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);
+		s = sha1(seed0, nseed0, nil, s);
+		sha1(seed1, nseed1, 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)
 {
-	TlsSec *sec = emalloc(sizeof(*sec));
+	DigestState *s;
+	uchar h0[MD5dlen], h1[SHA1dlen], pad[48];
+	char *label;
 
-	USED(csid); USED(ncsid);  // ignore csid for now
+	if(isclient)
+		label = "CLNT";
+	else
+		label = "SRVR";
 
-	memmove(sec->crandom, crandom, RandomSize);
+	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)
+{
+	uchar h0[MD5dlen], h1[SHA1dlen];
+	char *label;
+
+	// get current hash value, but allow further messages to be hashed in
+	md5(nil, 0, h0, &hsh.md5);
+	sha1(nil, 0, h1, &hsh.sha1);
+
+	if(isclient)
+		label = "client finished";
+	else
+		label = "server finished";
+	tls10PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h0, MD5dlen, h1, SHA1dlen);
+}
+
+static void
+tls12SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient)
+{
+	uchar seed[SHA2_256dlen];
+	char *label;
+
+	// get current hash value, but allow further messages to be hashed in
+	sha2_256(nil, 0, seed, &hsh.sha2_256);
+
+	if(isclient)
+		label = "client finished";
+	else
+		label = "server finished";
+	p_sha256(finished, TLSFinishedLen, sec->sec, MasterSecretSize, (uchar*)label, strlen(label), seed, SHA2_256dlen);
+}
+
+/* the keys are verified to have the same public components
+ * and to function correctly with pkcs 1 encryption and decryption. */
+static void
+tlsSecInits(TlsSec *sec, int cvers, uchar *crandom)
+{
+	memset(sec, 0, sizeof(*sec));
 	sec->clientVers = cvers;
+	memmove(sec->crandom, crandom, RandomSize);
 
 	put32(sec->srandom, time(nil));
 	genrandom(sec->srandom+4, RandomSize-4);
-	memmove(srandom, sec->srandom, RandomSize);
-
-	/*
-	 * make up a unique sid: use our pid, and and incrementing id
-	 * can signal no sid by setting nssid to 0.
-	 */
-	memset(ssid, 0, SidSize);
-	put32(ssid, getpid());
-	lock(&sidLock);
-	put32(ssid+4, maxSid++);
-	unlock(&sidLock);
-	*nssid = SidSize;
-	return sec;
 }
 
 static int
-tlsSecRSAs(TlsSec *sec, int vers, Bytes *epm)
+tlsSecRSAs(TlsSec *sec, Bytes *epm)
 {
 	Bytes *pm;
 
-	if(setVers(sec, vers) < 0)
-		goto Err;
 	if(epm == nil){
 		werrstr("no encrypted premaster secret");
-		goto Err;
+		return -1;
 	}
 	// if the client messed up, just continue as if everything is ok,
 	// to prevent attacks to check for correctly formatted messages.
 	pm = pkcs1_decrypt(sec, epm);
-	if(sec->ok < 0 || pm == nil || pm->len != MasterSecretSize || get16(pm->data) != sec->clientVers){
-		sec->ok = -1;
+	if(pm == nil || pm->len != MasterSecretSize || get16(pm->data) != sec->clientVers){
 		freebytes(pm);
 		pm = newbytes(MasterSecretSize);
 		genrandom(pm->data, pm->len);
@@ -2585,61 +2560,39 @@
 	}
 	setMasterSecret(sec, pm);
 	return 0;
-Err:
-	sec->ok = -1;
-	return -1;
 }
 
-static int
-tlsSecPSKs(TlsSec *sec, int vers)
+static void
+tlsSecPSKs(TlsSec *sec)
 {
-	if(setVers(sec, vers) < 0){
-		sec->ok = -1;
-		return -1;
-	}
 	setMasterSecret(sec, newbytes(sec->psklen));
-	return 0;
 }
 
-static TlsSec*
-tlsSecInitc(int cvers, uchar *crandom)
+static void
+tlsSecInitc(TlsSec *sec, int cvers)
 {
-	TlsSec *sec = emalloc(sizeof(*sec));
+	memset(sec, 0, sizeof(*sec));
 	sec->clientVers = cvers;
 	put32(sec->crandom, time(nil));
 	genrandom(sec->crandom+4, RandomSize-4);
-	memmove(crandom, sec->crandom, RandomSize);
-	return sec;
 }
 
-static int
-tlsSecPSKc(TlsSec *sec, uchar *srandom, int vers)
+static void
+tlsSecPSKc(TlsSec *sec)
 {
-	memmove(sec->srandom, srandom, RandomSize);
-	if(setVers(sec, vers) < 0){
-		sec->ok = -1;
-		return -1;
-	}
 	setMasterSecret(sec, newbytes(sec->psklen));
-	return 0;
 }
 
 static Bytes*
-tlsSecRSAc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers)
+tlsSecRSAc(TlsSec *sec, uchar *cert, int ncert)
 {
 	RSApub *pub;
 	Bytes *pm, *epm;
 
-	USED(sid);
-	USED(nsid);
-	
-	memmove(sec->srandom, srandom, RandomSize);
-	if(setVers(sec, vers) < 0)
-		goto Err;
 	pub = X509toRSApub(cert, ncert, nil, 0);
 	if(pub == nil){
 		werrstr("invalid x509/rsa certificate");
-		goto Err;
+		return nil;
 	}
 	pm = newbytes(MasterSecretSize);
 	put16(pm->data, sec->clientVers);
@@ -2647,11 +2600,7 @@
 	epm = pkcs1_encrypt(pm, pub, 2);
 	setMasterSecret(sec, pm);
 	rsapubfree(pub);
-	if(epm != nil)
-		return epm;
-Err:
-	sec->ok = -1;
-	return nil;
+	return epm;
 }
 
 static int
@@ -2658,7 +2607,6 @@
 tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient)
 {
 	if(sec->nfin != nfin){
-		sec->ok = -1;
 		werrstr("invalid finished exchange");
 		return -1;
 	}
@@ -2666,30 +2614,12 @@
 	hsh.sha1.malloced = 0;
 	hsh.sha2_256.malloced = 0;
 	(*sec->setFinished)(sec, hsh, fin, isclient);
-	return 1;
+	return 0;
 }
 
 static void
-tlsSecOk(TlsSec *sec)
+tlsSecVers(TlsSec *sec, int v)
 {
-	if(sec->ok == 0)
-		sec->ok = 1;
-}
-
-static void
-tlsSecClose(TlsSec *sec)
-{
-	if(sec == nil)
-		return;
-	factotum_rsa_close(sec->rpc);
-	rsapubfree(sec->rsapub);
-	free(sec->server);
-	free(sec);
-}
-
-static int
-setVers(TlsSec *sec, int v)
-{
 	if(v == SSL3Version){
 		sec->setFinished = sslSetFinished;
 		sec->nfin = SSL3FinishedLen;
@@ -2703,22 +2633,36 @@
 		sec->nfin = TLSFinishedLen;
 		sec->prf = tls12PRF;
 	}
-	sec->vers = v;
-	return 0;
 }
 
-/*
- * generate secret keys from the master secret.
- *
- * different crypto selections will require different amounts
- * of key expansion and use of key expansion data,
- * but it's all generated using the same function.
- */
-static void
-setSecrets(TlsSec *sec, uchar *kd, int nkd)
+static int
+setSecrets(TlsConnection *c, int isclient)
 {
-	(*sec->prf)(kd, nkd, sec->sec, MasterSecretSize, "key expansion",
-			sec->srandom, RandomSize, sec->crandom, RandomSize);
+	uchar kd[MaxKeyData];
+	char *secrets;
+	int rv;
+
+	assert(c->nsecret <= sizeof(kd));
+	secrets = emalloc(2*c->nsecret);
+
+	/*
+	 * generate secret keys from the master secret.
+	 *
+	 * different cipher selections will require different amounts
+	 * of key expansion and use of key expansion data,
+	 * but it's all generated using the same function.
+	 */
+	(*c->sec->prf)(kd, c->nsecret, c->sec->sec, MasterSecretSize, "key expansion",
+			c->sec->srandom, RandomSize, c->sec->crandom, RandomSize);
+
+	enc64(secrets, 2*c->nsecret, kd, c->nsecret);
+	memset(kd, 0, c->nsecret);
+
+	rv = fprint(c->ctl, "secret %s %s %d %s", c->digest, c->enc, isclient, secrets);
+	memset(secrets, 0, 2*c->nsecret);
+	free(secrets);
+
+	return rv;
 }
 
 /*
@@ -2749,103 +2693,6 @@
 
 	memset(pm->data, 0, pm->len);	
 	freebytes(pm);
-}
-
-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)
-{
-	uchar h0[MD5dlen], h1[SHA1dlen];
-	char *label;
-
-	// get current hash value, but allow further messages to be hashed in
-	md5(nil, 0, h0, &hsh.md5);
-	sha1(nil, 0, h1, &hsh.sha1);
-
-	if(isClient)
-		label = "client finished";
-	else
-		label = "server finished";
-	tls10PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h0, MD5dlen, h1, SHA1dlen);
-}
-
-static void
-tls12SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isClient)
-{
-	uchar seed[SHA2_256dlen];
-	char *label;
-
-	// get current hash value, but allow further messages to be hashed in
-	sha2_256(nil, 0, seed, &hsh.sha2_256);
-
-	if(isClient)
-		label = "client finished";
-	else
-		label = "server finished";
-	p_sha256(finished, TLSFinishedLen, sec->sec, MasterSecretSize, (uchar*)label, strlen(label), seed, SHA2_256dlen);
-}
-
-static void
-sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1)
-{
-	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);
-		s = sha1(seed0, nseed0, nil, s);
-		sha1(seed1, nseed1, 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 mpint*