transparently handle X9.42 DH parameters
diff --git a/CHANGES b/CHANGES
index 4a0ce55..ddf9059 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
 
  Changes between 1.0.1 and 1.1.0  [xx XXX xxxx]
 
+  *) Transparently support X9.42 DH parameters when calling
+     PEM_read_bio_DHparameters. This means existing applications can handle
+     the new parameter format automatically.
+     [Steve Henson]
+
   *) Initial experimental support for X9.42 DH parameter format: mainly
      to support use of 'q' parameter for RFC5114 parameters.
      [Steve Henson]
diff --git a/apps/dhparam.c b/apps/dhparam.c
index b47097c..79c0d64 100644
--- a/apps/dhparam.c
+++ b/apps/dhparam.c
@@ -513,7 +513,12 @@
 		if 	(outformat == FORMAT_ASN1)
 			i=i2d_DHparams_bio(out,dh);
 		else if (outformat == FORMAT_PEM)
-			i=PEM_write_bio_DHparams(out,dh);
+			{
+			if (dh->q)
+				i=PEM_write_bio_DHxparams(out,dh);
+			else
+				i=PEM_write_bio_DHparams(out,dh);
+			}
 		else	{
 			BIO_printf(bio_err,"bad output format specified for outfile\n");
 			goto end;
diff --git a/crypto/pem/pem.h b/crypto/pem/pem.h
index e09ce80..01dcde7 100644
--- a/crypto/pem/pem.h
+++ b/crypto/pem/pem.h
@@ -594,8 +594,10 @@
 #define PEM_F_PEM_PK8PKEY				 119
 #define PEM_F_PEM_READ					 108
 #define PEM_F_PEM_READ_BIO				 109
+#define PEM_F_PEM_READ_BIO_DHPARAMS			 141
 #define PEM_F_PEM_READ_BIO_PARAMETERS			 140
 #define PEM_F_PEM_READ_BIO_PRIVATEKEY			 123
+#define PEM_F_PEM_READ_DHPARAMS				 142
 #define PEM_F_PEM_READ_PRIVATEKEY			 124
 #define PEM_F_PEM_SEALFINAL				 110
 #define PEM_F_PEM_SEALINIT				 111
diff --git a/crypto/pem/pem_all.c b/crypto/pem/pem_all.c
index e09b24a..5c8c6f4 100644
--- a/crypto/pem/pem_all.c
+++ b/crypto/pem/pem_all.c
@@ -289,7 +289,7 @@
 
 #ifndef OPENSSL_NO_DH
 
-IMPLEMENT_PEM_rw_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
+IMPLEMENT_PEM_write_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
 IMPLEMENT_PEM_write_const(DHxparams, DH, PEM_STRING_DHXPARAMS, DHxparams)
 
 #endif
diff --git a/crypto/pem/pem_err.c b/crypto/pem/pem_err.c
index d644aee..9690224 100644
--- a/crypto/pem/pem_err.c
+++ b/crypto/pem/pem_err.c
@@ -1,6 +1,6 @@
 /* crypto/pem/pem_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -98,8 +98,10 @@
 {ERR_FUNC(PEM_F_PEM_PK8PKEY),	"PEM_PK8PKEY"},
 {ERR_FUNC(PEM_F_PEM_READ),	"PEM_read"},
 {ERR_FUNC(PEM_F_PEM_READ_BIO),	"PEM_read_bio"},
+{ERR_FUNC(PEM_F_PEM_READ_BIO_DHPARAMS),	"PEM_READ_BIO_DHPARAMS"},
 {ERR_FUNC(PEM_F_PEM_READ_BIO_PARAMETERS),	"PEM_read_bio_Parameters"},
 {ERR_FUNC(PEM_F_PEM_READ_BIO_PRIVATEKEY),	"PEM_READ_BIO_PRIVATEKEY"},
+{ERR_FUNC(PEM_F_PEM_READ_DHPARAMS),	"PEM_READ_DHPARAMS"},
 {ERR_FUNC(PEM_F_PEM_READ_PRIVATEKEY),	"PEM_READ_PRIVATEKEY"},
 {ERR_FUNC(PEM_F_PEM_SEALFINAL),	"PEM_SealFinal"},
 {ERR_FUNC(PEM_F_PEM_SEALINIT),	"PEM_SealInit"},
diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c
index 5a421fc..9e551d1 100644
--- a/crypto/pem/pem_lib.c
+++ b/crypto/pem/pem_lib.c
@@ -236,6 +236,9 @@
 			}
 		return 0;
 		}
+	/* If reading DH parameters handle X9.42 DH format too */
+	if(!strcmp(nm,PEM_STRING_DHXPARAMS) &&
+		!strcmp(name,PEM_STRING_DHPARAMS)) return 1;
 
 	/* Permit older strings */
 
diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c
index 8ecf249..e9e41dd 100644
--- a/crypto/pem/pem_pkey.c
+++ b/crypto/pem/pem_pkey.c
@@ -68,6 +68,9 @@
 #ifndef OPENSSL_NO_ENGINE
 #include <openssl/engine.h>
 #endif
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
 #include "asn1_locl.h"
 
 int pem_check_suffix(const char *pem_str, const char *suffix);
@@ -240,3 +243,52 @@
 	}
 
 #endif
+
+#ifndef OPENSSL_NO_DH
+
+/* Transparently read in PKCS#3 or X9.42 DH parameters */
+
+DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u)
+	{
+	char *nm=NULL;
+	const unsigned char *p=NULL;
+	unsigned char *data=NULL;
+	long len;
+	DH *ret=NULL;
+
+	if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS,
+								bp, cb, u))
+		return NULL;
+	p = data;
+
+	if (!strcmp(nm, PEM_STRING_DHXPARAMS))
+		ret = d2i_DHxparams(x, &p, len);
+	else
+		ret = d2i_DHparams(x, &p, len);
+
+	if (ret == NULL)
+		PEMerr(PEM_F_PEM_READ_BIO_DHPARAMS,ERR_R_ASN1_LIB);
+	OPENSSL_free(nm);
+	OPENSSL_free(data);
+	return ret;
+	}
+
+#ifndef OPENSSL_NO_FP_API
+DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u)
+	{
+        BIO *b;
+        DH *ret;
+
+        if ((b=BIO_new(BIO_s_file())) == NULL)
+		{
+		PEMerr(PEM_F_PEM_READ_DHPARAMS,ERR_R_BUF_LIB);
+                return(0);
+		}
+        BIO_set_fp(b,fp,BIO_NOCLOSE);
+        ret=PEM_read_bio_DHparams(b,x,cb,u);
+        BIO_free(b);
+        return(ret);
+	}
+#endif
+
+#endif