changes from plan 9.  some clean-up.
diff --git a/src/libsec/port/decodepem.c b/src/libsec/port/decodepem.c
index 194a455..a0b0094 100644
--- a/src/libsec/port/decodepem.c
+++ b/src/libsec/port/decodepem.c
@@ -6,7 +6,7 @@
 #define STRLEN(s)	(sizeof(s)-1)
 
 uchar*
-decodepem(char *s, char *type, int *len)
+decodepem(char *s, char *type, int *len, char **news)
 {
 	uchar *d;
 	char *t, *e, *tt;
@@ -44,6 +44,8 @@
 		return nil;
 	}
 
+	if(news)
+		*news = tt+1;
 	n = ((tt - t) * 6 + 7) / 8;
 	d = malloc(n);
 	if(d == nil){
@@ -59,3 +61,29 @@
 	*len = n;
 	return d;
 }
+
+PEMChain*
+decodepemchain(char *s, char *type)
+{
+	PEMChain *first = nil, *last = nil, *chp;
+	uchar *d;
+	char *e;
+	int n;
+
+	e = strchr(s, '\0');
+	while (s < e) {
+		d = decodepem(s, type, &n, &s);
+		if(d == nil)
+			break;
+		chp = malloc(sizeof(PEMChain));
+		chp->next = nil;
+		chp->pem = d;
+		chp->pemlen = n;
+		if (first == nil)
+			first = chp;
+		else
+			last->next = chp;
+		last = chp;
+	}
+	return first;
+}
diff --git a/src/libsec/port/md5pickle.c b/src/libsec/port/md5pickle.c
index 5b353b5..012489a 100644
--- a/src/libsec/port/md5pickle.c
+++ b/src/libsec/port/md5pickle.c
@@ -7,11 +7,12 @@
 	char *p;
 	int m, n;
 
-	m = 4*9+4*((s->blen+3)/3);
+	m = 17+4*9+4*((s->blen+3)/3);
 	p = malloc(m);
 	if(p == nil)
 		return p;
-	n = sprint(p, "%8.8ux %8.8ux %8.8ux %8.8ux ",
+	n = sprint(p, "%16.16llux %8.8ux %8.8ux %8.8ux %8.8ux ",
+		s->len,
 		s->state[0], s->state[1], s->state[2],
 		s->state[3]);
 	enc64(p+n, m-n, s->buf, s->blen);
@@ -26,6 +27,7 @@
 	s = malloc(sizeof(*s));
 	if(s == nil)
 		return nil;
+	s->len = strtoull(p, &p, 16);
 	s->state[0] = strtoul(p, &p, 16);
 	s->state[1] = strtoul(p, &p, 16);
 	s->state[2] = strtoul(p, &p, 16);
diff --git a/src/libsec/port/readcert.c b/src/libsec/port/readcert.c
index 9ba801f..b8ddf6d 100644
--- a/src/libsec/port/readcert.c
+++ b/src/libsec/port/readcert.c
@@ -40,7 +40,7 @@
 		werrstr("can't read %s", filename);
 		return nil;
 	}
-	binary = decodepem(pem, "CERTIFICATE", pcertlen);
+	binary = decodepem(pem, "CERTIFICATE", pcertlen, nil);
 	free(pem);
 	if(binary == nil){
 		werrstr("can't parse %s", filename);
@@ -49,3 +49,19 @@
 	return binary;
 }
 
+
+PEMChain *
+readcertchain(char *filename)
+{
+	char *chfile;
+	PEMChain *chp;
+
+	chfile = readfile(filename);
+	if (chfile == nil) {
+		werrstr("can't read %s", filename);
+		return nil;
+	}
+	chp = decodepemchain(chfile, "CERTIFICATE");
+	return chp;
+}
+
diff --git a/src/libsec/port/tlshand.c b/src/libsec/port/tlshand.c
index 68c9808..47d0f80 100644
--- a/src/libsec/port/tlshand.c
+++ b/src/libsec/port/tlshand.c
@@ -248,7 +248,7 @@
 	CompressionNull,
 };
 
-static TlsConnection *tlsServer2(int ctl, int hand, uchar *cert, int ncert, int (*trace)(char*fmt, ...));
+static TlsConnection *tlsServer2(int ctl, int hand, uchar *cert, int ncert, int (*trace)(char*fmt, ...), PEMChain *chain);
 static TlsConnection *tlsClient2(int ctl, int hand, uchar *csid, int ncsid, int (*trace)(char*fmt, ...));
 
 static void	msgClear(Msg *m);
@@ -273,7 +273,7 @@
 static int	tlsSecSecretc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers, uchar **epm, int *nepm, uchar *kd, int nkd);
 static int	tlsSecFinished(TlsSec *sec, MD5state md5, SHAstate sha1, uchar *fin, int nfin, int isclient);
 static void	tlsSecOk(TlsSec *sec);
-static void	tlsSecKill(TlsSec *sec);
+/* static void	tlsSecKill(TlsSec *sec); */
 static void	tlsSecClose(TlsSec *sec);
 static void	setMasterSecret(TlsSec *sec, Bytes *pm);
 static void	serverMasterSecret(TlsSec *sec, uchar *epm, int nepm);
@@ -296,14 +296,14 @@
 static void put32(uchar *p, u32int);
 static void put24(uchar *p, int);
 static void put16(uchar *p, int);
-static u32int get32(uchar *p);
+/* static u32int get32(uchar *p); */
 static int get24(uchar *p);
 static int get16(uchar *p);
 static Bytes* newbytes(int len);
 static Bytes* makebytes(uchar* buf, int len);
 static void freebytes(Bytes* b);
 static Ints* newints(int len);
-static Ints* makeints(int* buf, int len);
+/* static Ints* makeints(int* buf, int len); */
 static void freeints(Ints* b);
 
 //================= client/server ========================
@@ -337,7 +337,7 @@
 		return -1;
 	}
 	fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
-	tls = tlsServer2(ctl, hand, conn->cert, conn->certlen, conn->trace);
+	tls = tlsServer2(ctl, hand, conn->cert, conn->certlen, conn->trace, conn->chain);
 	sprint(dname, "#a/tls/%s/data", buf);
 	data = open(dname, ORDWR);
 	close(fd);
@@ -412,15 +412,27 @@
 	return data;
 }
 
+static int
+countchain(PEMChain *p)
+{
+	int i = 0;
+
+	while (p) {
+		i++;
+		p = p->next;
+	}
+	return i;
+}
+
 static TlsConnection *
-tlsServer2(int ctl, int hand, uchar *cert, int ncert, int (*trace)(char*fmt, ...))
+tlsServer2(int ctl, int hand, uchar *cert, int ncert, int (*trace)(char*fmt, ...), PEMChain *chp)
 {
 	TlsConnection *c;
 	Msg m;
 	Bytes *csid;
 	uchar sid[SidSize], kd[MaxKeyData];
 	char *secrets;
-	int cipher, compressor, nsid, rv;
+	int cipher, compressor, nsid, rv, numcerts, i;
 
 	if(trace)
 		trace("tlsServer2\n");
@@ -498,9 +510,12 @@
 	msgClear(&m);
 
 	m.tag = HCertificate;
-	m.u.certificate.ncert = 1;
+	numcerts = countchain(chp);
+	m.u.certificate.ncert = 1 + numcerts;
 	m.u.certificate.certs = emalloc(m.u.certificate.ncert * sizeof(Bytes));
 	m.u.certificate.certs[0] = makebytes(cert, ncert);
+	for (i = 0; i < numcerts && chp; i++, chp = chp->next)
+		m.u.certificate.certs[i+1] = makebytes(chp->pem, chp->pemlen);
 	if(!msgSend(c, &m, AQueue))
 		goto Err;
 	msgClear(&m);
@@ -1824,6 +1839,7 @@
 		sec->ok = 1;
 }
 
+/*
 static void
 tlsSecKill(TlsSec *sec)
 {
@@ -1832,6 +1848,7 @@
 	factotum_rsa_close(sec->rpc);
 	sec->ok = -1;
 }
+*/
 
 static void
 tlsSecClose(TlsSec *sec)
@@ -2205,11 +2222,13 @@
 	p[1] = x;
 }
 
+/*
 static u32int
 get32(uchar *p)
 {
 	return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
 }
+*/
 
 static int
 get24(uchar *p)
@@ -2272,6 +2291,7 @@
 	return ans;
 }
 
+/*
 static Ints*
 makeints(int* buf, int len)
 {
@@ -2282,6 +2302,7 @@
 		memmove(ans->data, buf, len*sizeof(int));
 	return ans;
 }
+*/
 
 static void
 freeints(Ints* b)
diff --git a/src/libsec/port/x509.c b/src/libsec/port/x509.c
index 838c8b4..a37b64a 100644
--- a/src/libsec/port/x509.c
+++ b/src/libsec/port/x509.c
@@ -134,8 +134,10 @@
 static int	is_string(Elem* pe, char** pstring);
 static int	is_time(Elem* pe, char** ptime);
 static int	decode(uchar* a, int alen, Elem* pelem);
+/*
 static int	decode_seq(uchar* a, int alen, Elist** pelist);
 static int	decode_value(uchar* a, int alen, int kind, int isconstr, Value* pval);
+*/
 static int	encode(Elem e, Bytes** pbytes);
 static int	oid_lookup(Ints* o, Ints** tab);
 static void	freevalfields(Value* v);
@@ -206,7 +208,7 @@
 /*
  * Like decode, but continue decoding after first element
  * of array ends.
- */
+ *
 static int
 decode_seq(uchar* a, int alen, Elist** pelist)
 {
@@ -214,6 +216,7 @@
 
 	return seq_decode(&p, &a[alen], -1, 1, pelist);
 }
+*/
 
 /*
  * Decode the whole array as a BER encoding of an ASN1 value,
@@ -223,7 +226,7 @@
  * If there's an error, the return string will contain the error.
  * Depending on the error, the returned value may or may not
  * be nil.
- */
+ *
 static int
 decode_value(uchar* a, int alen, int kind, int isconstr, Value* pval)
 {
@@ -231,6 +234,7 @@
 
 	return value_decode(&p, &a[alen], alen, kind, isconstr, pval);
 }
+*/
 
 /*
  * All of the following decoding routines take arguments:
@@ -1585,12 +1589,12 @@
 static Ints7 oid_sha1WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 5 };
 static Ints7 oid_md5 ={6, 1, 2, 840, 113549, 2, 5, 0 };
 static Ints *alg_oid_tab[NUMALGS+1] = {
-	(Ints*)&oid_rsaEncryption,
-	(Ints*)&oid_md2WithRSAEncryption,
-	(Ints*)&oid_md4WithRSAEncryption,
-	(Ints*)&oid_md5WithRSAEncryption,
-	(Ints*)&oid_sha1WithRSAEncryption,
-	(Ints*)&oid_md5,
+	(Ints*)(void*)&oid_rsaEncryption,
+	(Ints*)(void*)&oid_md2WithRSAEncryption,
+	(Ints*)(void*)&oid_md4WithRSAEncryption,
+	(Ints*)(void*)&oid_md5WithRSAEncryption,
+	(Ints*)(void*)&oid_sha1WithRSAEncryption,
+	(Ints*)(void*)&oid_md5,
 	nil
 };
 static DigestFun digestalg[NUMALGS+1] = { md5, md5, md5, md5, sha1, md5, 0 };