ASN1_ITEM versions of sign, verify, pack and unpack.

The old function pointer versions will eventually go
away.
diff --git a/CHANGES b/CHANGES
index 193e9ad..d83e08a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,10 @@
 
  Changes between 0.9.6 and 0.9.7  [xx XXX 2000]
 
+  *) New ASN1 functions to handle sign, verify, digest, pack and
+     unpack operations in terms of ASN1_ITEM.
+     [Steve Henson]
+
   *) New extension functions for OCSP structures, these follow the
      same conventions as certificates and CRLs.
      [Steve Henson]
diff --git a/crypto/asn1/a_digest.c b/crypto/asn1/a_digest.c
index 8257b86..fb4686f 100644
--- a/crypto/asn1/a_digest.c
+++ b/crypto/asn1/a_digest.c
@@ -88,3 +88,21 @@
 	return(1);
 	}
 
+
+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);
+	OPENSSL_free(str);
+	return(1);
+	}
+
diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c
index 4c65170..5be077d 100644
--- a/crypto/asn1/a_sign.c
+++ b/crypto/asn1/a_sign.c
@@ -146,3 +146,76 @@
 		{ memset((char *)buf_out,0,outll); OPENSSL_free(buf_out); }
 	return(outl);
 	}
+
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+	     ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey,
+	     const EVP_MD *type)
+	{
+	EVP_MD_CTX ctx;
+	unsigned char *buf_in=NULL,*buf_out=NULL;
+	int i,inl=0,outl=0,outll=0;
+	X509_ALGOR *a;
+
+	for (i=0; i<2; i++)
+		{
+		if (i == 0)
+			a=algor1;
+		else
+			a=algor2;
+		if (a == NULL) continue;
+		if (	(a->parameter == NULL) || 
+			(a->parameter->type != V_ASN1_NULL))
+			{
+			ASN1_TYPE_free(a->parameter);
+			if ((a->parameter=ASN1_TYPE_new()) == NULL) goto err;
+			a->parameter->type=V_ASN1_NULL;
+			}
+		ASN1_OBJECT_free(a->algorithm);
+		a->algorithm=OBJ_nid2obj(type->pkey_type);
+		if (a->algorithm == NULL)
+			{
+			ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_UNKNOWN_OBJECT_TYPE);
+			goto err;
+			}
+		if (a->algorithm->length == 0)
+			{
+			ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
+			goto err;
+			}
+		}
+	inl=ASN1_item_i2d(asn,&buf_in, it);
+	outll=outl=EVP_PKEY_size(pkey);
+	buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl);
+	if ((buf_in == NULL) || (buf_out == NULL))
+		{
+		outl=0;
+		ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	EVP_SignInit(&ctx,type);
+	EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl);
+	if (!EVP_SignFinal(&ctx,(unsigned char *)buf_out,
+			(unsigned int *)&outl,pkey))
+		{
+		outl=0;
+		ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB);
+		goto err;
+		}
+	if (signature->data != NULL) OPENSSL_free(signature->data);
+	signature->data=buf_out;
+	buf_out=NULL;
+	signature->length=outl;
+	/* In the interests of compatibility, I'll make sure that
+	 * the bit string has a 'not-used bits' value of 0
+	 */
+	signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+	signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
+err:
+	memset(&ctx,0,sizeof(ctx));
+	if (buf_in != NULL)
+		{ memset((char *)buf_in,0,(unsigned int)inl); OPENSSL_free(buf_in); }
+	if (buf_out != NULL)
+		{ memset((char *)buf_out,0,outll); OPENSSL_free(buf_out); }
+	return(outl);
+	}
diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c
index 2a11927..be5a27e 100644
--- a/crypto/asn1/a_verify.c
+++ b/crypto/asn1/a_verify.c
@@ -117,3 +117,51 @@
 err:
 	return(ret);
 	}
+
+
+int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signature,
+	     void *asn, EVP_PKEY *pkey)
+	{
+	EVP_MD_CTX ctx;
+	const EVP_MD *type;
+	unsigned char *buf_in=NULL;
+	int ret= -1,i,inl;
+
+	i=OBJ_obj2nid(a->algorithm);
+	type=EVP_get_digestbyname(OBJ_nid2sn(i));
+	if (type == NULL)
+		{
+		ASN1err(ASN1_F_ASN1_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+		goto err;
+		}
+
+	inl = ASN1_item_i2d(asn, &buf_in, it);
+	
+	if (buf_in == NULL)
+		{
+		ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	EVP_VerifyInit(&ctx,type);
+	EVP_VerifyUpdate(&ctx,(unsigned char *)buf_in,inl);
+
+	memset(buf_in,0,(unsigned int)inl);
+	OPENSSL_free(buf_in);
+
+	if (EVP_VerifyFinal(&ctx,(unsigned char *)signature->data,
+			(unsigned int)signature->length,pkey) <= 0)
+		{
+		ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_EVP_LIB);
+		ret=0;
+		goto err;
+		}
+	/* we don't need to zero the 'ctx' because we just checked
+	 * public information */
+	/* memset(&ctx,0,sizeof(ctx)); */
+	ret=1;
+err:
+	return(ret);
+	}
+
+
diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h
index 080bf71..902aebb 100644
--- a/crypto/asn1/asn1.h
+++ b/crypto/asn1/asn1.h
@@ -852,7 +852,9 @@
 unsigned char *ASN1_seq_pack(STACK *safes, int (*i2d)(), unsigned char **buf,
 			     int *len );
 void *ASN1_unpack_string(ASN1_STRING *oct, char *(*d2i)());
+void *ASN1_unpack_item(ASN1_STRING *oct, const ASN1_ITEM *it);
 ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct);
+ASN1_STRING *ASN1_pack_item(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct);
 
 void ASN1_STRING_set_default_mask(unsigned long mask);
 int ASN1_STRING_set_default_mask_asc(char *p);
diff --git a/crypto/asn1/asn_pack.c b/crypto/asn1/asn_pack.c
index bdf5f13..0b9ed69 100644
--- a/crypto/asn1/asn_pack.c
+++ b/crypto/asn1/asn_pack.c
@@ -117,7 +117,7 @@
 
 /* Pack an ASN1 object into an ASN1_STRING */
 
-ASN1_STRING *ASN1_pack_string (void *obj, int (*i2d)(), ASN1_STRING **oct)
+ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_STRING **oct)
 {
 	unsigned char *p;
 	ASN1_STRING *octmp;
@@ -143,3 +143,45 @@
 	return octmp;
 }
 
+/* ASN1_ITEM versions of the above */
+
+ASN1_STRING *ASN1_pack_item(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
+{
+	ASN1_STRING *octmp;
+
+	if (!oct || !*oct) {
+		if (!(octmp = ASN1_STRING_new ())) {
+			ASN1err(ASN1_F_ASN1_PACK_STRING,ERR_R_MALLOC_FAILURE);
+			return NULL;
+		}
+		if (oct) *oct = octmp;
+	} else octmp = *oct;
+
+	if(octmp->data) {
+		OPENSSL_free(octmp->data);
+		octmp->data = NULL;
+	}
+		
+	if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
+		ASN1err(ASN1_F_ASN1_PACK_STRING,ASN1_R_ENCODE_ERROR);
+		return NULL;
+	}
+	if (!octmp->data) {
+		ASN1err(ASN1_F_ASN1_PACK_STRING,ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	return octmp;
+}
+
+/* Extract an ASN1 object from an ASN1_STRING */
+
+void *ASN1_unpack_item(ASN1_STRING *oct, const ASN1_ITEM *it)
+{
+	unsigned char *p;
+	void *ret;
+
+	p = oct->data;
+	if(!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
+		ASN1err(ASN1_F_ASN1_UNPACK_STRING,ASN1_R_DECODE_ERROR);
+	return ret;
+}
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index 24ba861..332cad5 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -913,6 +913,16 @@
 int ASN1_sign(int (*i2d)(), X509_ALGOR *algor1, X509_ALGOR *algor2,
 	ASN1_BIT_STRING *signature,
 	char *data,EVP_PKEY *pkey, const EVP_MD *type);
+
+int ASN1_item_digest(const ASN1_ITEM *it,const EVP_MD *type,void *data,
+	unsigned char *md,unsigned int *len);
+
+int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1,
+	ASN1_BIT_STRING *signature,void *data,EVP_PKEY *pkey);
+
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+	ASN1_BIT_STRING *signature,
+	void *data, EVP_PKEY *pkey, const EVP_MD *type);
 #endif
 
 int 		X509_set_version(X509 *x,long version);