OPENSSL_free(pp);
alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, &PKCS7_ATTR_VERIFY_it); EVP_VerifyUpdate(&mdc_tmp, abuf, alen);  OPENSSL_free(abuf);
int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,								X509 *x509)	{	ASN1_OCTET_STRING *os;	EVP_MD_CTX mdc_tmp,*mdc;	unsigned char *pp,*p;	int ret=0,i;	int md_type;	STACK_OF(X509_ATTRIBUTE) *sk;	BIO *btmp;	EVP_PKEY *pkey;	if (!PKCS7_type_is_signed(p7) && 				!PKCS7_type_is_signedAndEnveloped(p7)) {		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,						PKCS7_R_WRONG_PKCS7_TYPE);		goto err;	}	md_type=OBJ_obj2nid(si->digest_alg->algorithm);	btmp=bio;	for (;;)		{		if ((btmp == NULL) ||			((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))			{			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);			goto err;			}		BIO_get_md_ctx(btmp,&mdc);		if (mdc == NULL)			{			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,							PKCS7_R_INTERNAL_ERROR);			goto err;			}		if (EVP_MD_CTX_type(mdc) == md_type)			break;		btmp=BIO_next(btmp);		}	/* mdc is the digest ctx that we want, unless there are attributes,	 * in which case the digest is the signed attributes */	memcpy(&mdc_tmp,mdc,sizeof(mdc_tmp));	sk=si->auth_attr;	if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))		{		unsigned char md_dat[EVP_MAX_MD_SIZE];                unsigned int md_len;		ASN1_OCTET_STRING *message_digest;		EVP_DigestFinal(&mdc_tmp,md_dat,&md_len);		message_digest=PKCS7_digest_from_attributes(sk);		if (!message_digest)			{			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);			goto err;			}		if ((message_digest->length != (int)md_len) ||			(memcmp(message_digest->data,md_dat,md_len)))			{#if 0{int ii;for (ii=0; ii<message_digest->length; ii++)	printf("%02X",message_digest->data[ii]); printf(" sent\n");for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n");}#endif			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,							PKCS7_R_DIGEST_FAILURE);			ret= -1;			goto err;			}		EVP_VerifyInit(&mdc_tmp,EVP_get_digestbynid(md_type));		/* Note: when forming the encoding of the attributes we		 * shouldn't reorder them or this will break the signature.		 * This is done by using the IS_SEQUENCE flag.		 */		i=i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,NULL,i2d_X509_ATTRIBUTE,			V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE);		pp=OPENSSL_malloc(i);		p=pp;		i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,&p,i2d_X509_ATTRIBUTE,			V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE);		EVP_VerifyUpdate(&mdc_tmp,pp,i);		OPENSSL_free(pp);		}	os=si->enc_digest;	pkey = X509_get_pubkey(x509);	if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1();	i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);	EVP_PKEY_free(pkey);	if (i <= 0)		{		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,						PKCS7_R_SIGNATURE_FAILURE);		ret= -1;		goto err;		}	else		ret=1;err:	return(ret);	}