Tidy/enhance certificate chain output code.

New function ssl_add_cert_chain which adds a certificate chain to
SSL internal BUF_MEM. Use this function in ssl3_output_cert_chain
and dtls1_output_cert_chain instead of partly duplicating code.
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index 0a84f95..ad2d1fc 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -992,70 +992,14 @@
 	return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC));
 	}
 
-static int dtls1_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
-	{
-	int n;
-	unsigned char *p;
-
-	n=i2d_X509(x,NULL);
-	if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3)))
-		{
-		SSLerr(SSL_F_DTLS1_ADD_CERT_TO_BUF,ERR_R_BUF_LIB);
-		return 0;
-		}
-	p=(unsigned char *)&(buf->data[*l]);
-	l2n3(n,p);
-	i2d_X509(x,&p);
-	*l+=n+3;
-
-	return 1;
-	}
 unsigned long dtls1_output_cert_chain(SSL *s, X509 *x)
 	{
 	unsigned char *p;
-	int i;
 	unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH;
-	BUF_MEM *buf;
+	BUF_MEM *buf=s->init_buf;
 
-	/* TLSv1 sends a chain with nothing in it, instead of an alert */
-	buf=s->init_buf;
-	if (!BUF_MEM_grow_clean(buf,10))
-		{
-		SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
-		return(0);
-		}
-	if (x != NULL)
-		{
-		X509_STORE_CTX xs_ctx;
-
-		if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL))
-  			{
-  			SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB);
-  			return(0);
-  			}
-  
-		X509_verify_cert(&xs_ctx);
-		/* Don't leave errors in the queue */
-		ERR_clear_error();
-		for (i=0; i < sk_X509_num(xs_ctx.chain); i++)
-  			{
-			x = sk_X509_value(xs_ctx.chain, i);
-
-			if (!dtls1_add_cert_to_buf(buf, &l, x))
-  				{
-				X509_STORE_CTX_cleanup(&xs_ctx);
-				return 0;
-  				}
-  			}
-  		X509_STORE_CTX_cleanup(&xs_ctx);
-  		}
-  	/* Thawte special :-) */
-	for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++)
-		{
-		x=sk_X509_value(s->ctx->extra_certs,i);
-		if (!dtls1_add_cert_to_buf(buf, &l, x))
-			return 0;
-		}
+	if (!ssl_add_cert_chain(s, x, &l))
+		return 0;
 
 	l-= (3 + DTLS1_HM_HEADER_LENGTH);
 
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index c58713f..153b2bf 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -321,84 +321,14 @@
 	return(ssl3_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC));
 	}
 
-static int ssl3_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
-	{
-	int n;
-	unsigned char *p;
-
-	n=i2d_X509(x,NULL);
-	if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3)))
-		{
-		SSLerr(SSL_F_SSL3_ADD_CERT_TO_BUF,ERR_R_BUF_LIB);
-		return(-1);
-		}
-	p=(unsigned char *)&(buf->data[*l]);
-	l2n3(n,p);
-	i2d_X509(x,&p);
-	*l+=n+3;
-
-	return(0);
-	}
-
 unsigned long ssl3_output_cert_chain(SSL *s, X509 *x)
 	{
 	unsigned char *p;
-	int i;
 	unsigned long l=7;
-	BUF_MEM *buf;
-	int no_chain;
+	BUF_MEM *buf = s->init_buf;
 
-	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs)
-		no_chain = 1;
-	else
-		no_chain = 0;
-
-	/* TLSv1 sends a chain with nothing in it, instead of an alert */
-	buf=s->init_buf;
-	if (!BUF_MEM_grow_clean(buf,10))
-		{
-		SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
-		return(0);
-		}
-	if (x != NULL)
-		{
-		if (no_chain)
-			{
-			if (ssl3_add_cert_to_buf(buf, &l, x))
-				return(0);
-			}
-		else
-			{
-			X509_STORE_CTX xs_ctx;
-
-			if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL))
-				{
-				SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB);
-				return(0);
-				}
-			X509_verify_cert(&xs_ctx);
-			/* Don't leave errors in the queue */
-			ERR_clear_error();
-			for (i=0; i < sk_X509_num(xs_ctx.chain); i++)
-				{
-				x = sk_X509_value(xs_ctx.chain, i);
-
-				if (ssl3_add_cert_to_buf(buf, &l, x))
-					{
-					X509_STORE_CTX_cleanup(&xs_ctx);
-					return 0;
-					}
-				}
-			X509_STORE_CTX_cleanup(&xs_ctx);
-			}
-		}
-	/* Thawte special :-) */
-	for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++)
-		{
-		x=sk_X509_value(s->ctx->extra_certs,i);
-		if (ssl3_add_cert_to_buf(buf, &l, x))
-			return(0);
-		}
+	if (!ssl_add_cert_chain(s, x, &l))
+		return 0;
 
 	l-=7;
 	p=(unsigned char *)&(buf->data[4]);
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 4b7397f..b9325fe 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2175,6 +2175,8 @@
 #define SSL_F_SSL3_SETUP_WRITE_BUFFER			 291
 #define SSL_F_SSL3_WRITE_BYTES				 158
 #define SSL_F_SSL3_WRITE_PENDING			 159
+#define SSL_F_SSL_ADD_CERT_CHAIN			 316
+#define SSL_F_SSL_ADD_CERT_TO_BUF			 317
 #define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT	 298
 #define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT		 277
 #define SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT		 307
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 917be31..c1e7ec1 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -851,3 +851,85 @@
 	return ret;
 	}
 
+/* Add a certificate to a BUF_MEM structure */
+
+static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
+	{
+	int n;
+	unsigned char *p;
+
+	n=i2d_X509(x,NULL);
+	if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3)))
+		{
+		SSLerr(SSL_F_SSL_ADD_CERT_TO_BUF,ERR_R_BUF_LIB);
+		return 0;
+		}
+	p=(unsigned char *)&(buf->data[*l]);
+	l2n3(n,p);
+	i2d_X509(x,&p);
+	*l+=n+3;
+
+	return 1;
+	}
+
+/* Add certificate chain to internal SSL BUF_MEM strcuture */
+int ssl_add_cert_chain(SSL *s, X509 *x, unsigned long *l)
+	{
+	BUF_MEM *buf = s->init_buf;
+	int no_chain;
+	int i;
+
+	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs)
+		no_chain = 1;
+	else
+		no_chain = 0;
+
+	/* TLSv1 sends a chain with nothing in it, instead of an alert */
+	if (!BUF_MEM_grow_clean(buf,10))
+		{
+		SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_BUF_LIB);
+		return 0;
+		}
+	if (x != NULL)
+		{
+		if (no_chain)
+			{
+			if (!ssl_add_cert_to_buf(buf, l, x))
+				return 0;
+			}
+		else
+			{
+			X509_STORE_CTX xs_ctx;
+
+			if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL))
+				{
+				SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_X509_LIB);
+				return(0);
+				}
+			X509_verify_cert(&xs_ctx);
+			/* Don't leave errors in the queue */
+			ERR_clear_error();
+			for (i=0; i < sk_X509_num(xs_ctx.chain); i++)
+				{
+				x = sk_X509_value(xs_ctx.chain, i);
+
+				if (ssl_add_cert_to_buf(buf, l, x))
+					{
+					X509_STORE_CTX_cleanup(&xs_ctx);
+					return 0;
+					}
+				}
+			X509_STORE_CTX_cleanup(&xs_ctx);
+			}
+		}
+	/* Thawte special :-) */
+	for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++)
+		{
+		x=sk_X509_value(s->ctx->extra_certs,i);
+		if (!ssl_add_cert_to_buf(buf, l, x))
+			return 0;
+		}
+
+	return 1;
+	}
+
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 4eb2e44..e94ffe0 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -180,6 +180,8 @@
 {ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER),	"SSL3_SETUP_WRITE_BUFFER"},
 {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES),	"SSL3_WRITE_BYTES"},
 {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING),	"SSL3_WRITE_PENDING"},
+{ERR_FUNC(SSL_F_SSL_ADD_CERT_CHAIN),	"SSL_ADD_CERT_CHAIN"},
+{ERR_FUNC(SSL_F_SSL_ADD_CERT_TO_BUF),	"SSL_ADD_CERT_TO_BUF"},
 {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT),	"SSL_ADD_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT),	"SSL_ADD_CLIENTHELLO_USE_SRTP_EXT"},
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 8cbaaab..25f5fd4 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -825,6 +825,7 @@
 		       const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp);
 int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md);			   
 int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);
+int ssl_add_cert_chain(SSL *s, X509 *x, unsigned long *l);
 int ssl_undefined_function(SSL *s);
 int ssl_undefined_void_function(void);
 int ssl_undefined_const_function(const SSL *s);