Various function for commmon operations.
diff --git a/CHANGES b/CHANGES
index a19f241..8ccb3b9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,12 @@
 
  Changes between 0.9.6 and 0.9.7  [xx XXX 2000]
 
+  *) Various new functions. EVP_Digest() combines EVP_Digest{Init,Update,Final}()
+     in a single operation. X509_get0_pubkey_bitstr() extracts the public_key
+     structure from a certificate. X509_pubkey_digest() digests tha public_key
+     contents: this is used in various key identifiers. 
+     [Steve Henson]
+
   *) Tolerate nonRepudiation as being valid for S/MIME signing and certSign
      keyUsage if basicConstraints absent for a CA.
      [Steve Henson]
diff --git a/apps/ocsp.c b/apps/ocsp.c
index eaba15f..cec2f2b 100644
--- a/apps/ocsp.c
+++ b/apps/ocsp.c
@@ -525,7 +525,7 @@
 	if(!*req) *req = OCSP_REQUEST_new();
 	if(!*req) goto err;
 	iname = X509_get_subject_name(issuer);
-	ikey = issuer->cert_info->key->public_key;
+	ikey = X509_get0_pubkey_bitstr(issuer);
 	sno = s2i_ASN1_INTEGER(NULL, serial);
 	if(!sno)
 		{
diff --git a/crypto/asn1/a_digest.c b/crypto/asn1/a_digest.c
index 6c12249..3243bea 100644
--- a/crypto/asn1/a_digest.c
+++ b/crypto/asn1/a_digest.c
@@ -74,7 +74,6 @@
 int ASN1_digest(int (*i2d)(), const EVP_MD *type, char *data,
 		unsigned char *md, unsigned int *len)
 	{
-	EVP_MD_CTX ctx;
 	int i;
 	unsigned char *str,*p;
 
@@ -83,9 +82,7 @@
 	p=str;
 	i2d(data,&p);
 
-	EVP_DigestInit(&ctx,type);
-	EVP_DigestUpdate(&ctx,str,i);
-	EVP_DigestFinal(&ctx,md,len);
+	EVP_Digest(str, i, md, len, type);
 	OPENSSL_free(str);
 	return(1);
 	}
@@ -96,16 +93,13 @@
 int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
 		unsigned char *md, unsigned int *len)
 	{
-	EVP_MD_CTX ctx;
 	int i;
 	unsigned char *str = NULL;
 
 	i=ASN1_item_i2d(asn,&str, it);
 	if (!str) return(0);
 
-	EVP_DigestInit(&ctx,type);
-	EVP_DigestUpdate(&ctx,str,i);
-	EVP_DigestFinal(&ctx,md,len);
+	EVP_Digest(str, i, md, len, type);
 	OPENSSL_free(str);
 	return(1);
 	}
diff --git a/crypto/asn1/n_pkey.c b/crypto/asn1/n_pkey.c
index 82a6212..c7b92e3 100644
--- a/crypto/asn1/n_pkey.c
+++ b/crypto/asn1/n_pkey.c
@@ -196,14 +196,11 @@
 	i = strlen((char *)buf);
 	/* If the key is used for SGC the algorithm is modified a little. */
 	if(sgckey) {
-		EVP_MD_CTX mctx;
-		EVP_DigestInit(&mctx, EVP_md5());
-		EVP_DigestUpdate(&mctx, buf, i);
-		EVP_DigestFinal(&mctx, buf, NULL);
+		EVP_Digest(buf, i, buf, NULL, EVP_md5());
 		memcpy(buf + 16, "SGCKEYSALT", 10);
 		i = 26;
 	}
-		
+
 	EVP_BytesToKey(EVP_rc4(),EVP_md5(),NULL,buf,i,1,key,NULL);
 	memset(buf,0,256);
 
@@ -287,10 +284,7 @@
 
 	i = strlen((char *)buf);
 	if(sgckey){
-		EVP_MD_CTX mctx;
-		EVP_DigestInit(&mctx, EVP_md5());
-		EVP_DigestUpdate(&mctx, buf, i);
-		EVP_DigestFinal(&mctx, buf, NULL);
+		EVP_Digest(buf, i, buf, NULL, EVP_md5());
 		memcpy(buf + 16, "SGCKEYSALT", 10);
 		i = 26;
 	}
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index c560733..5c75a34 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -89,4 +89,14 @@
     }
     memcpy((char *)out,(char *)in,in->digest->ctx_size);
     return 1;
-}    
+}
+
+int EVP_Digest(void *data, unsigned int count,
+		unsigned char *md, unsigned int *size, const EVP_MD *type)
+{
+	EVP_MD_CTX ctx;
+	EVP_DigestInit(&ctx, type);
+	EVP_DigestUpdate(&ctx, data, count);
+	EVP_DigestFinal(&ctx, md, size);
+	return 1;
+}
diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
index 17a0f30..60578f9 100644
--- a/crypto/evp/evp.h
+++ b/crypto/evp/evp.h
@@ -559,6 +559,8 @@
 void	EVP_DigestUpdate(EVP_MD_CTX *ctx,const void *d,
 			 unsigned int cnt);
 void	EVP_DigestFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s);
+int	EVP_Digest(void *data, unsigned int count,
+		unsigned char *md, unsigned int *size, const EVP_MD *type);
 
 int	EVP_read_pw_string(char *buf,int length,const char *prompt,int verify);
 void	EVP_set_pw_prompt(char *prompt);
diff --git a/crypto/ocsp/ocsp_lib.c b/crypto/ocsp/ocsp_lib.c
index bdd4cfc..825d023 100644
--- a/crypto/ocsp/ocsp_lib.c
+++ b/crypto/ocsp/ocsp_lib.c
@@ -82,7 +82,7 @@
 #endif
 	iname = X509_get_issuer_name(subject);
 	serial = X509_get_serialNumber(subject);
-	ikey = issuer->cert_info->key->public_key;
+	ikey = X509_get0_pubkey_bitstr(issuer);
 	return OCSP_cert_id_new(dgst, iname, ikey, serial);
 }
 
@@ -97,7 +97,6 @@
 	X509_ALGOR *alg;
 	OCSP_CERTID *cid = NULL;
 	unsigned char md[EVP_MAX_MD_SIZE];
-	EVP_MD_CTX ctx;
 
 	if (!(cid = OCSP_CERTID_new())) goto err;
 
@@ -116,9 +115,7 @@
 	if (!(ASN1_OCTET_STRING_set(cid->issuerNameHash, md, i))) goto err;
 
 	/* Calculate the issuerKey hash, excluding tag and length */
-	EVP_DigestInit(&ctx,dgst);
-	EVP_DigestUpdate(&ctx,issuerKey->data, issuerKey->length);
-	EVP_DigestFinal(&ctx,md,&i);
+	EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst);
 
 	if (!(ASN1_OCTET_STRING_set(cid->issuerKeyHash, md, i))) goto err;
 	
@@ -186,7 +183,6 @@
         {
 	time_t t;
 	OCSP_RESPID *rid;
-        ASN1_BIT_STRING *bs;
 	OCSP_BASICRESP *rsp = NULL;
 	unsigned char md[SHA_DIGEST_LENGTH];
 	
@@ -205,9 +201,7 @@
 			/* SHA-1 hash of responder's public key
                          * (excluding the tag and length fields)
 			 */
-		        bs = cert->cert_info->key->public_key;
-		        SHA1(ASN1_STRING_data((ASN1_STRING*)bs), 
-			     ASN1_STRING_length((ASN1_STRING*)bs), md);
+			X509_pubkey_digest(cert, EVP_sha1(), md, NULL);
 			if (!(rid->value.byKey = ASN1_OCTET_STRING_new()))
 				goto err;
 			if (!(ASN1_OCTET_STRING_set(rid->value.byKey,
diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c
index 7470f1c..4ac7e82 100644
--- a/crypto/ocsp/ocsp_vfy.c
+++ b/crypto/ocsp/ocsp_vfy.c
@@ -177,8 +177,6 @@
 	{
 	int i;
 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
-	ASN1_BIT_STRING *key;
-	EVP_MD_CTX ctx;
 	X509 *x;
 
 	/* Easy if lookup by name */
@@ -194,10 +192,7 @@
 	for (i = 0; i < sk_X509_num(certs); i++)
 		{
 		x = sk_X509_value(certs, i);
-		key = x->cert_info->key->public_key;
-		EVP_DigestInit(&ctx,EVP_sha1());
-		EVP_DigestUpdate(&ctx,key->data, key->length);
-		EVP_DigestFinal(&ctx,tmphash,NULL);
+		X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
 		if(!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
 			return x;
 		}
@@ -294,9 +289,7 @@
 	if(cid)
 		{
 		const EVP_MD *dgst;
-		EVP_MD_CTX ctx;
 		X509_NAME *iname;
-		ASN1_BIT_STRING *ikey;
 		int mdlen;
 		unsigned char md[EVP_MAX_MD_SIZE];
 		if (!(dgst = EVP_get_digestbyobj(cid->hashAlgorithm->algorithm)))
@@ -314,11 +307,7 @@
 			return -1;
 		if (memcmp(md, cid->issuerNameHash->data, mdlen))
 			return 0;
-		ikey = cert->cert_info->key->public_key;
-
-		EVP_DigestInit(&ctx,dgst);
-		EVP_DigestUpdate(&ctx,ikey->data, ikey->length);
-		EVP_DigestFinal(&ctx,md,NULL);
+		X509_pubkey_digest(cert, EVP_sha1(), md, NULL);
 		if (memcmp(md, cid->issuerKeyHash->data, mdlen))
 			return 0;
 
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index 4b19572..c3ec6bf 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -719,6 +719,8 @@
 int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md);
 int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md);
 
+int X509_pubkey_digest(const X509 *data,const EVP_MD *type,
+		unsigned char *md, unsigned int *len);
 int X509_digest(const X509 *data,const EVP_MD *type,
 		unsigned char *md, unsigned int *len);
 int X509_CRL_digest(const X509_CRL *data,const EVP_MD *type,
@@ -937,6 +939,7 @@
 int 		X509_set_notAfter(X509 *x, ASN1_TIME *tm);
 int 		X509_set_pubkey(X509 *x, EVP_PKEY *pkey);
 EVP_PKEY *	X509_get_pubkey(X509 *x);
+ASN1_BIT_STRING * X509_get0_pubkey_bitstr(const X509 *x);
 int		X509_certificate_type(X509 *x,EVP_PKEY *pubkey /* optional */);
 
 int		X509_REQ_set_version(X509_REQ *x,long version);
diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c
index b147d57..7927155 100644
--- a/crypto/x509/x509_cmp.c
+++ b/crypto/x509/x509_cmp.c
@@ -264,6 +264,12 @@
 	return(X509_PUBKEY_get(x->cert_info->key));
 	}
 
+ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
+	{
+	if(!x) return NULL;
+	return x->cert_info->key->public_key;
+	}
+
 int X509_check_private_key(X509 *x, EVP_PKEY *k)
 	{
 	EVP_PKEY *xk=NULL;
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index 7095a28..de53e67 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -379,6 +379,15 @@
 	return ASN1_item_dup(&X509_NAME_ENTRY_it, ne);
 	}
 
+int X509_pubkey_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
+	     unsigned int *len)
+	{
+	ASN1_BIT_STRING *key;
+	key = X509_get0_pubkey_bitstr(data);
+	if(!key) return 0;
+	return EVP_Digest(key->data, key->length, md, len, type);
+	}
+
 int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
 	     unsigned int *len)
 	{
diff --git a/crypto/x509v3/v3_skey.c b/crypto/x509v3/v3_skey.c
index 58da456..3e1eb05 100644
--- a/crypto/x509v3/v3_skey.c
+++ b/crypto/x509v3/v3_skey.c
@@ -104,7 +104,6 @@
 	ASN1_OCTET_STRING *oct;
 	ASN1_BIT_STRING *pk;
 	unsigned char pkey_dig[EVP_MAX_MD_SIZE];
-	EVP_MD_CTX md;
 	unsigned int diglen;
 
 	if(strcmp(str, "hash")) return s2i_ASN1_OCTET_STRING(method, ctx, str);
@@ -130,9 +129,7 @@
 		goto err;
 	}
 
-	EVP_DigestInit(&md, EVP_sha1());
-	EVP_DigestUpdate(&md, pk->data, pk->length);
-	EVP_DigestFinal(&md, pkey_dig, &diglen);
+	EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1());
 
 	if(!M_ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) {
 		X509V3err(X509V3_F_S2I_S2I_SKEY_ID,ERR_R_MALLOC_FAILURE);