Copy DH key (if available) in addition to the bare parameters
in SSL_new.
If SSL_OP_SINGLE_DH_USE is set, don't waste time in SSL_[CTX_]set_tmp_dh
on computing a DH key that will be ignored anyway.

ssltest -dhe1024dsa (w/ 160-bit sub-prime) had an unfair performance
advantage over -dhe1024 (safe prime): SSL_OP_SINGLE_DH_USE was
effectively always enabled because SSL_new ignored the DH key set in
the SSL_CTX.  Now -dhe1024 takes the server only about twice as long
as -dhe1024dsa instead of three times as long (for 1024 bit RSA
with 1024 bit DH).
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index c4b49aa..892ff75 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -771,14 +771,16 @@
 	case SSL_CTRL_SET_TMP_RSA:
 		{
 			RSA *rsa = (RSA *)parg;
-			if (rsa == NULL) {
+			if (rsa == NULL)
+				{
 				SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
 				return(ret);
-			}
-			if ((rsa = RSAPrivateKey_dup(rsa)) == NULL) {
+				}
+			if ((rsa = RSAPrivateKey_dup(rsa)) == NULL)
+				{
 				SSLerr(SSL_F_SSL3_CTRL, ERR_R_RSA_LIB);
 				return(ret);
-			}
+				}
 			if (s->cert->rsa_tmp != NULL)
 				RSA_free(s->cert->rsa_tmp);
 			s->cert->rsa_tmp = rsa;
@@ -796,19 +798,25 @@
 	case SSL_CTRL_SET_TMP_DH:
 		{
 			DH *dh = (DH *)parg;
-			if (dh == NULL) {
+			if (dh == NULL)
+				{
 				SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
 				return(ret);
-			}
-			if ((dh = DHparams_dup(dh)) == NULL) {
+				}
+			if ((dh = DHparams_dup(dh)) == NULL)
+				{
 				SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
 				return(ret);
-			}
-			if (!DH_generate_key(dh)) {
-				DH_free(dh);
-				SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
-				return(ret);
-			}
+				}
+			if (!(s->options & SSL_OP_SINGLE_DH_USE))
+				{
+				if (!DH_generate_key(dh))
+					{
+					DH_free(dh);
+					SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
+					return(ret);
+					}
+				}
 			if (s->cert->dh_tmp != NULL)
 				DH_free(s->cert->dh_tmp);
 			s->cert->dh_tmp = dh;
@@ -843,7 +851,7 @@
 		0)
 		{
 		if (!ssl_cert_inst(&s->cert))
-		    	{
+			{
 			SSLerr(SSL_F_SSL3_CTRL, ERR_R_MALLOC_FAILURE);
 			return(0);
 			}
@@ -929,23 +937,26 @@
 	case SSL_CTRL_SET_TMP_DH:
 		{
 		DH *new=NULL,*dh;
-		int rret=0;
 
 		dh=(DH *)parg;
-		if (	((new=DHparams_dup(dh)) == NULL) ||
-			(!DH_generate_key(new)))
+		if ((new=DHparams_dup(dh)) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_DH_LIB);
-			if (new != NULL) DH_free(new);
+			return 0;
 			}
-		else
+		if (!(ctx->options & SSL_OP_SINGLE_DH_USE))
 			{
-			if (cert->dh_tmp != NULL)
-				DH_free(cert->dh_tmp);
-			cert->dh_tmp=new;
-			rret=1;
+			if (!DH_generate_key(new))
+				{
+				SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_DH_LIB);
+				DH_free(new);
+				return 0;
+				}
 			}
-		return(rret);
+		if (cert->dh_tmp != NULL)
+			DH_free(cert->dh_tmp);
+		cert->dh_tmp=new;
+		return 1;
 		}
 		/*break; */
 	case SSL_CTRL_SET_TMP_DH_CB:
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 48f247c..a054e0a 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -191,16 +191,33 @@
 #ifndef NO_DH
 	if (cert->dh_tmp != NULL)
 		{
-		/* DH parameters don't have a reference count (and cannot
-		 * reasonably be shared anyway, as the secret exponent may
-		 * be created just when it is needed -- earlier library
-		 * versions did not pay attention to this) */
+		/* DH parameters don't have a reference count */
 		ret->dh_tmp = DHparams_dup(cert->dh_tmp);
 		if (ret->dh_tmp == NULL)
 			{
 			SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_DH_LIB);
 			goto err;
 			}
+		if (cert->dh_tmp->priv_key)
+			{
+			BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
+			if (!b)
+				{
+				SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_BN_LIB);
+				goto err;
+				}
+			ret->dh_tmp->priv_key = b;
+			}
+		if (cert->dh_tmp->pub_key)
+			{
+			BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
+			if (!b)
+				{
+				SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_BN_LIB);
+				goto err;
+				}
+			ret->dh_tmp->pub_key = b;
+			}
 		}
 	ret->dh_tmp_cb = cert->dh_tmp_cb;
 #endif