Add support for default public key digest type ctrl.
diff --git a/CHANGES b/CHANGES
index 1d536cd..991e4b0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,16 @@
 
  Changes between 0.9.8a and 0.9.9  [xx XXX xxxx]
 
+  *) Add a ctrl to asn1 method to allow a public key algorithm to express
+     a default digest type to use. In most cases this will be SHA1 but some
+     algorithms (such as GOST) need to specify an alternative digest. The
+     return value indicates how strong the prefernce is 1 means optional and
+     2 is mandatory (that is it is the only supported type). Modify
+     ASN1_item_sign() to accept a NULL digest argument to indicate it should
+     use the default md. Update openssl utilities to use the default digest
+     type for signing if it is not explicitly indicated.
+     [Steve Henson]
+
   *) Use OID cross reference table in ASN1_sign() and ASN1_verify(). New 
      EVP_MD flag EVP_MD_FLAG_PKEY_METHOD_SIGNATURE. This uses the relevant
      signing method from the key type. This effectively removes the link
diff --git a/apps/ca.c b/apps/ca.c
index f7532d2..9fde400 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -1016,6 +1016,17 @@
 		goto err;
 		}
 
+	if (!strcmp(md, "default"))
+		{
+		int def_nid;
+		if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0)
+			{
+			BIO_puts(bio_err,"no default digest\n");
+			goto err;
+			}
+		md = (char *)OBJ_nid2sn(def_nid);
+		}
+
 	if ((dgst=EVP_get_digestbyname(md)) == NULL)
 		{
 		BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
@@ -1412,17 +1423,6 @@
 
 		/* we now have a CRL */
 		if (verbose) BIO_printf(bio_err,"signing CRL\n");
-#if 0
-#ifndef OPENSSL_NO_DSA
-		if (pkey->type == EVP_PKEY_DSA) 
-			dgst=EVP_dss1();
-		else
-#endif
-#ifndef OPENSSL_NO_ECDSA
-		if (pkey->type == EVP_PKEY_EC)
-			dgst=EVP_ecdsa();
-#endif
-#endif
 
 		/* Add any extensions asked for */
 
@@ -2101,25 +2101,11 @@
 			}
 		}
 
-
-#ifndef OPENSSL_NO_DSA
-	if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
 	pktmp=X509_get_pubkey(ret);
 	if (EVP_PKEY_missing_parameters(pktmp) &&
 		!EVP_PKEY_missing_parameters(pkey))
 		EVP_PKEY_copy_parameters(pktmp,pkey);
 	EVP_PKEY_free(pktmp);
-#endif
-#ifndef OPENSSL_NO_ECDSA
-	if (pkey->type == EVP_PKEY_EC)
-		dgst = EVP_ecdsa();
-	pktmp = X509_get_pubkey(ret);
-	if (EVP_PKEY_missing_parameters(pktmp) &&
-		!EVP_PKEY_missing_parameters(pkey))
-		EVP_PKEY_copy_parameters(pktmp, pkey);
-	EVP_PKEY_free(pktmp);
-#endif
-
 
 	if (!X509_sign(ret,pkey,dgst))
 		goto err;
diff --git a/apps/openssl.cnf b/apps/openssl.cnf
index a620b98..2995800 100644
--- a/apps/openssl.cnf
+++ b/apps/openssl.cnf
@@ -72,7 +72,7 @@
 
 default_days	= 365			# how long to certify for
 default_crl_days= 30			# how long before next CRL
-default_md	= sha1			# which md to use.
+default_md	= default		# use public key default MD
 preserve	= no			# keep passed DN ordering
 
 # A few difference way of specifying how similar the request should look
diff --git a/apps/req.c b/apps/req.c
index b9a3852..4c95bb9 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -193,7 +193,7 @@
 	char *p;
 	char *subj = NULL;
 	int multirdn = 0;
-	const EVP_MD *md_alg=NULL,*digest=EVP_sha1();
+	const EVP_MD *md_alg=NULL,*digest=NULL;
 	unsigned long chtype = MBSTRING_ASC;
 #ifndef MONOLITH
 	char *to_free;
@@ -894,16 +894,7 @@
 			BIO_printf(bio_err,"you need to specify a private key\n");
 			goto end;
 			}
-#if 0
-#ifndef OPENSSL_NO_DSA
-		if (pkey->type == EVP_PKEY_DSA)
-			digest=EVP_dss1();
-#endif
-#ifndef OPENSSL_NO_ECDSA
-		if (pkey->type == EVP_PKEY_EC)
-			digest=EVP_ecdsa();
-#endif
-#endif
+
 		if (req == NULL)
 			{
 			req=X509_REQ_new();
diff --git a/apps/x509.c b/apps/x509.c
index e3a9738..dfe41a6 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -188,7 +188,7 @@
 	X509_REQ *rq=NULL;
 	int fingerprint=0;
 	char buf[256];
-	const EVP_MD *md_alg,*digest=EVP_sha1();
+	const EVP_MD *md_alg,*digest=NULL;
 	CONF *extconf = NULL;
 	char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
 	int need_rand = 0;
@@ -885,14 +885,18 @@
 				int j;
 				unsigned int n;
 				unsigned char md[EVP_MAX_MD_SIZE];
+				const EVP_MD *fdig = digest;
 
-				if (!X509_digest(x,digest,md,&n))
+				if (!fdig)
+					fdig = EVP_sha1();
+
+				if (!X509_digest(x,fdig,md,&n))
 					{
 					BIO_printf(bio_err,"out of memory\n");
 					goto end;
 					}
 				BIO_printf(STDout,"%s Fingerprint=",
-						OBJ_nid2sn(EVP_MD_type(digest)));
+						OBJ_nid2sn(EVP_MD_type(fdig)));
 				for (j=0; j<(int)n; j++)
 					{
 					BIO_printf(STDout,"%02X%c",md[j],
@@ -912,16 +916,6 @@
 						passin, e, "Private key");
 					if (Upkey == NULL) goto end;
 					}
-#if 0
-#ifndef OPENSSL_NO_DSA
-		                if (Upkey->type == EVP_PKEY_DSA)
-		                        digest=EVP_dss1();
-#endif
-#ifndef OPENSSL_NO_ECDSA
-				if (Upkey->type == EVP_PKEY_EC)
-					digest=EVP_ecdsa();
-#endif
-#endif
 
 				assert(need_rand);
 				if (!sign(x,Upkey,days,clrext,digest,
@@ -938,14 +932,6 @@
 						"CA Private Key");
 					if (CApkey == NULL) goto end;
 					}
-#ifndef OPENSSL_NO_DSA
-		                if (CApkey->type == EVP_PKEY_DSA)
-		                        digest=EVP_dss1();
-#endif
-#ifndef OPENSSL_NO_ECDSA
-				if (CApkey->type == EVP_PKEY_EC)
-					digest = EVP_ecdsa();
-#endif
 				
 				assert(need_rand);
 				if (!x509_certify(ctx,CAfile,digest,x,xca,
@@ -973,15 +959,6 @@
 
 				BIO_printf(bio_err,"Generating certificate request\n");
 
-#ifndef OPENSSL_NO_DSA
-		                if (pk->type == EVP_PKEY_DSA)
-		                        digest=EVP_dss1();
-#endif
-#ifndef OPENSSL_NO_ECDSA
-				if (pk->type == EVP_PKEY_EC)
-					digest=EVP_ecdsa();
-#endif
-
 				rq=X509_to_X509_REQ(x,pk,digest);
 				EVP_PKEY_free(pk);
 				if (rq == NULL)
diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c
index c98dc7c..ff63bfc 100644
--- a/crypto/asn1/a_sign.c
+++ b/crypto/asn1/a_sign.c
@@ -222,6 +222,19 @@
 	int inl=0,outl=0,outll=0;
 	int signid, paramtype;
 
+	if (type == NULL)
+		{
+		int def_nid;
+		if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0)
+			type = EVP_get_digestbynid(def_nid);
+		}
+
+	if (type == NULL)
+		{
+		ASN1err(ASN1_F_ASN1_ITEM_SIGN, ASN1_R_NO_DEFAULT_DIGEST);
+		return 0;
+		}
+
 	if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE)
 		{
 		if (!pkey->ameth ||
diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h
index ea57f77..912619e 100644
--- a/crypto/asn1/asn1.h
+++ b/crypto/asn1/asn1.h
@@ -1228,6 +1228,7 @@
 #define ASN1_R_NON_HEX_CHARACTERS			 141
 #define ASN1_R_NOT_ASCII_FORMAT				 190
 #define ASN1_R_NOT_ENOUGH_DATA				 142
+#define ASN1_R_NO_DEFAULT_DIGEST			 201
 #define ASN1_R_NO_MATCHING_CHOICE_TYPE			 143
 #define ASN1_R_NULL_IS_WRONG_LENGTH			 144
 #define ASN1_R_OBJECT_NOT_ASCII_FORMAT			 191
diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c
index 8b1a651..148455c 100644
--- a/crypto/asn1/asn1_err.c
+++ b/crypto/asn1/asn1_err.c
@@ -248,6 +248,7 @@
 {ERR_REASON(ASN1_R_NON_HEX_CHARACTERS)   ,"non hex characters"},
 {ERR_REASON(ASN1_R_NOT_ASCII_FORMAT)     ,"not ascii format"},
 {ERR_REASON(ASN1_R_NOT_ENOUGH_DATA)      ,"not enough data"},
+{ERR_REASON(ASN1_R_NO_DEFAULT_DIGEST)    ,"no default digest"},
 {ERR_REASON(ASN1_R_NO_MATCHING_CHOICE_TYPE),"no matching choice type"},
 {ERR_REASON(ASN1_R_NULL_IS_WRONG_LENGTH) ,"null is wrong length"},
 {ERR_REASON(ASN1_R_OBJECT_NOT_ASCII_FORMAT),"object not ascii format"},
diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c
index 3178bac..e221fad 100644
--- a/crypto/dsa/dsa_ameth.c
+++ b/crypto/dsa/dsa_ameth.c
@@ -544,6 +544,10 @@
 			}
 		return 1;
 
+		case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
+		*(int *)arg2 = NID_sha1;
+		return 2;
+
 		default:
 		return -2;
 
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
index 12b85b6..ba61164 100644
--- a/crypto/ec/ec_ameth.c
+++ b/crypto/ec/ec_ameth.c
@@ -586,6 +586,10 @@
 			}
 		return 1;
 
+		case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
+		*(int *)arg2 = NID_sha1;
+		return 2;
+
 		default:
 		return -2;
 
diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
index 83bf805..ff95a34 100644
--- a/crypto/evp/evp.h
+++ b/crypto/evp/evp.h
@@ -770,6 +770,8 @@
 int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
 				int indent, ASN1_PCTX *pctx);
 
+int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid);
+
 int EVP_CIPHER_type(const EVP_CIPHER *ctx);
 
 /* calls methods */
@@ -805,6 +807,7 @@
 
 #define ASN1_PKEY_CTRL_PKCS7_SIGN	0x1
 #define ASN1_PKEY_CTRL_PKCS7_ENCRYPT	0x2
+#define ASN1_PKEY_CTRL_DEFAULT_MD_NID	0x3
 
 int EVP_PKEY_asn1_get_count(void);
 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 19644ab..730520f 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -361,3 +361,12 @@
 		return pkey->ameth->param_print(out, pkey, indent, pctx);
 	return unsup_alg(out, pkey, indent, "Parameters");
 	}
+
+int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid)
+	{
+	if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
+		return -2;
+	return pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID,
+						0, pnid);
+	}
+
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 917b376..0378549 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -287,6 +287,10 @@
 			}
 		return 1;
 
+		case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
+		*(int *)arg2 = NID_sha1;
+		return 1;
+
 		default:
 		return -2;