コード例 #1
1
int main(int argc, char const *argv[])
{
	PKCS7 *p7;
	FILE *fp = NULL;
	PKCS7_SIGNER_INFO *si;
	STACK_OF(PKCS7_SIGNER_INFO) *sk;
	X509_STORE_CTX cert_ctx;
	X509_STORE *cert_store;
	BIO *mybio;
	int ret, len, i;
	unsigned char *errordesc;
	unsigned long errorno;

	unsigned char data[2028], *p, *buf;
	OpenSSL_add_all_algorithms();

	fp = fopen("p7signed.cer", "rb");
	if(fp == NULL)
		return 0;
	len = fread(data, 1, 2048, fp);
	fclose(fp);
	p = data;
	p7 = d2i_PKCS7(NULL, (const unsigned char **)&p, len);

	mybio = PKCS7_dataInit(p7, NULL);
	sk = PKCS7_get_signer_info(p7);
	if(sk == NULL)
	{
		printf("no signer in p7\n");
		return 0;
	}

cert_store=X509_STORE_new(); 
X509_STORE_set_verify_cb_func(cert_store,verify_callback);//必须要有回调设置 
for(i = 0; i < sk_PKCS7_SIGNER_INFO_num(sk); i++) 
{ 
si = sk_PKCS7_SIGNER_INFO_value(sk, i); 
ret = PKCS7_dataVerify(cert_store, &cert_ctx, mybio, p7, si); 
if(ret == 1) 
printf("succ in pkcs7 signed data verify\n"); 
else 
printf("fail in pkcs7 signed data verify\n"); 
} 

X509_STORE_free(cert_store); 
PKCS7_free(p7); 
return 1; 
} 
コード例 #2
0
ファイル: smime-vfy.c プロジェクト: gitpan/smime
long  /* return serial on success, -1 on failure */
smime_get_signer_info(const char* signed_entity,
		      int info_ix,     /* 0 = first signer */
		      char** issuer)   /* DN of the issuer */
{
  int serial = -1;
  PKCS7* p7 = NULL;
  STACK_OF(PKCS7_SIGNER_INFO)* sigs = NULL;
  PKCS7_SIGNER_INFO* si;
  
  if (!signed_entity || !issuer) GOTO_ERR("NULL arg(s)");
  *issuer = NULL;
  
  if (!(p7 = get_pkcs7_from_pem(signed_entity))) goto err;
  if (!(sigs=PKCS7_get_signer_info(p7)))
    GOTO_ERR("13 no sigs? (PKCS7_get_signer_info)");

  if (info_ix >= sk_PKCS7_SIGNER_INFO_num(sigs))
    GOTO_ERR("No more signers. info_ix too large.");

  if (!(si=sk_PKCS7_SIGNER_INFO_value(sigs,info_ix)))
    GOTO_ERR("NULL signer info");
  
  *issuer = X509_NAME_oneline(si->issuer_and_serial->issuer, NULL,0);
  serial = ASN1_INTEGER_get(si->issuer_and_serial->serial);
  
err:
  if (p7) PKCS7_free(p7);
  return serial;
}
コード例 #3
0
ファイル: ossl_pkcs7.c プロジェクト: AndreMeira/rubinius
static VALUE
ossl_pkcs7_get_signer(VALUE self)
{
    PKCS7 *pkcs7;
    STACK_OF(PKCS7_SIGNER_INFO) *sk;
    PKCS7_SIGNER_INFO *si;
    int num, i;
    VALUE ary;
    
    GetPKCS7(self, pkcs7);
    if (!(sk = PKCS7_get_signer_info(pkcs7))) {
	OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!");
	return rb_ary_new();
    }
    if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) {
	ossl_raise(ePKCS7Error, "Negative number of signers!");
    }
    ary = rb_ary_new2(num);
    for (i=0; i<num; i++) {
	si = sk_PKCS7_SIGNER_INFO_value(sk, i);
	rb_ary_push(ary, ossl_pkcs7si_new(si));
    }

    return ary;
}
コード例 #4
0
ファイル: pki_x509_pkcs7.c プロジェクト: Brenhilt/libpki
PKCS7_SIGNER_INFO * PKI_X509_PKCS7_get_signer_info ( PKI_X509_PKCS7 *p7, 
								int idx ) {

	int type = 0;
	int cnt = 0;
	STACK_OF(PKCS7_SIGNER_INFO) *sk = NULL;
	PKCS7_SIGNER_INFO *ret = NULL;

	PKI_X509_PKCS7_VALUE *value = NULL;

	if ( !p7 || !p7->value ) return ( NULL );

	type = PKI_X509_PKCS7_get_type ( p7 );

	value = p7->value;

	if( type == PKI_X509_PKCS7_TYPE_SIGNED ) {
		sk = value->d.sign->signer_info;
	} else if ( type == PKI_X509_PKCS7_TYPE_SIGNEDANDENCRYPTED ) {
		sk = value->d.signed_and_enveloped->signer_info;
	} else {
		return NULL;
	}

	//PKI_log_debug( "PKI_X509_PKCS7_get_signer_info()::"
	//					"Elements in stack [%d]", cnt );
	//PKI_log_debug( "PKI_X509_PKCS7_get_signer_info()::"
	//					"Requested Element [%d]", idx );

	if((cnt = sk_PKCS7_SIGNER_INFO_num ( sk )) <= 0 ) {
		return ( NULL );
	}

	if (idx > cnt ) return NULL;

	if( idx >= 0 ) {
		ret = sk_PKCS7_SIGNER_INFO_value( sk, idx );
	} else {
		// PKI_log_debug( "_get_signer_info()::Return Last Element");
		ret = sk_PKCS7_SIGNER_INFO_value( sk, cnt-1 );
	}
	
	return (ret);
}
コード例 #5
0
ファイル: pk7_doit.c プロジェクト: 4872866/node
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
{
    int ret = 0;
    int i, j;
    BIO *btmp;
    PKCS7_SIGNER_INFO *si;
    EVP_MD_CTX *mdc, ctx_tmp;
    STACK_OF(X509_ATTRIBUTE) *sk;
    STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
    ASN1_OCTET_STRING *os = NULL;

    if (p7 == NULL) {
        PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER);
        return 0;
    }

    if (p7->d.ptr == NULL) {
        PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT);
        return 0;
    }

    EVP_MD_CTX_init(&ctx_tmp);
    i = OBJ_obj2nid(p7->type);
    p7->state = PKCS7_S_HEADER;

    switch (i) {
    case NID_pkcs7_data:
        os = p7->d.data;
        break;
    case NID_pkcs7_signedAndEnveloped:
        /* XXXXXXXXXXXXXXXX */
        si_sk = p7->d.signed_and_enveloped->signer_info;
        os = p7->d.signed_and_enveloped->enc_data->enc_data;
        if (!os) {
            os = M_ASN1_OCTET_STRING_new();
            if (!os) {
                PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            p7->d.signed_and_enveloped->enc_data->enc_data = os;
        }
        break;
    case NID_pkcs7_enveloped:
        /* XXXXXXXXXXXXXXXX */
        os = p7->d.enveloped->enc_data->enc_data;
        if (!os) {
            os = M_ASN1_OCTET_STRING_new();
            if (!os) {
                PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            p7->d.enveloped->enc_data->enc_data = os;
        }
        break;
    case NID_pkcs7_signed:
        si_sk = p7->d.sign->signer_info;
        os = PKCS7_get_octet_string(p7->d.sign->contents);
        /* If detached data then the content is excluded */
        if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
            M_ASN1_OCTET_STRING_free(os);
            os = NULL;
            p7->d.sign->contents->d.data = NULL;
        }
        break;

    case NID_pkcs7_digest:
        os = PKCS7_get_octet_string(p7->d.digest->contents);
        /* If detached data then the content is excluded */
        if (PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) {
            M_ASN1_OCTET_STRING_free(os);
            os = NULL;
            p7->d.digest->contents->d.data = NULL;
        }
        break;

    default:
        PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
        goto err;
    }

    if (si_sk != NULL) {
        for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) {
            si = sk_PKCS7_SIGNER_INFO_value(si_sk, i);
            if (si->pkey == NULL)
                continue;

            j = OBJ_obj2nid(si->digest_alg->algorithm);

            btmp = bio;

            btmp = PKCS7_find_digest(&mdc, btmp, j);

            if (btmp == NULL)
                goto err;

            /*
             * We now have the EVP_MD_CTX, lets do the signing.
             */
            if (!EVP_MD_CTX_copy_ex(&ctx_tmp, mdc))
                goto err;

            sk = si->auth_attr;

            /*
             * If there are attributes, we add the digest attribute and only
             * sign the attributes
             */
            if (sk_X509_ATTRIBUTE_num(sk) > 0) {
                if (!do_pkcs7_signed_attrib(si, &ctx_tmp))
                    goto err;
            } else {
                unsigned char *abuf = NULL;
                unsigned int abuflen;
                abuflen = EVP_PKEY_size(si->pkey);
                abuf = OPENSSL_malloc(abuflen);
                if (!abuf)
                    goto err;

                if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen, si->pkey)) {
                    PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB);
                    goto err;
                }
                ASN1_STRING_set0(si->enc_digest, abuf, abuflen);
            }
        }
    } else if (i == NID_pkcs7_digest) {
        unsigned char md_data[EVP_MAX_MD_SIZE];
        unsigned int md_len;
        if (!PKCS7_find_digest(&mdc, bio,
                               OBJ_obj2nid(p7->d.digest->md->algorithm)))
            goto err;
        if (!EVP_DigestFinal_ex(mdc, md_data, &md_len))
            goto err;
        M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
    }

    if (!PKCS7_is_detached(p7)) {
        /*
         * NOTE(emilia): I think we only reach os == NULL here because detached
         * digested data support is broken.
         */
        if (os == NULL)
            goto err;
        if (!(os->flags & ASN1_STRING_FLAG_NDEF)) {
            char *cont;
            long contlen;
            btmp = BIO_find_type(bio, BIO_TYPE_MEM);
            if (btmp == NULL) {
                PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
                goto err;
            }
            contlen = BIO_get_mem_data(btmp, &cont);
            /*
             * Mark the BIO read only then we can use its copy of the data
             * instead of making an extra copy.
             */
            BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
            BIO_set_mem_eof_return(btmp, 0);
            ASN1_STRING_set0(os, (unsigned char *)cont, contlen);
        }
    }
    ret = 1;
 err:
    EVP_MD_CTX_cleanup(&ctx_tmp);
    return (ret);
}
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
	{
	int ret=0;
	int i,j;
	BIO *btmp;
	BUF_MEM *buf_mem=NULL;
	BUF_MEM *buf=NULL;
	PKCS7_SIGNER_INFO *si;
	EVP_MD_CTX *mdc,ctx_tmp;
	STACK_OF(X509_ATTRIBUTE) *sk;
	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
	ASN1_OCTET_STRING *os=NULL;

	EVP_MD_CTX_init(&ctx_tmp);
	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signedAndEnveloped:
		/* XXXXXXXXXXXXXXXX */
		si_sk=p7->d.signed_and_enveloped->signer_info;
		if (!(os=M_ASN1_OCTET_STRING_new()))
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		p7->d.signed_and_enveloped->enc_data->enc_data=os;
		break;
	case NID_pkcs7_enveloped:
		/* XXXXXXXXXXXXXXXX */
		if (!(os=M_ASN1_OCTET_STRING_new()))
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		p7->d.enveloped->enc_data->enc_data=os;
		break;
	case NID_pkcs7_signed:
		si_sk=p7->d.sign->signer_info;
		os=PKCS7_get_octet_string(p7->d.sign->contents);
		/* If detached data then the content is excluded */
		if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
			M_ASN1_OCTET_STRING_free(os);
			p7->d.sign->contents->d.data = NULL;
		}
		break;

	case NID_pkcs7_digest:
		os=PKCS7_get_octet_string(p7->d.digest->contents);
		/* If detached data then the content is excluded */
		if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
			{
			M_ASN1_OCTET_STRING_free(os);
			p7->d.digest->contents->d.data = NULL;
			}
		break;

		}

	if (si_sk != NULL)
		{
		if ((buf=BUF_MEM_new()) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
			goto err;
			}
		for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++)
			{
			si=sk_PKCS7_SIGNER_INFO_value(si_sk,i);
			if (si->pkey == NULL) continue;

			j=OBJ_obj2nid(si->digest_alg->algorithm);

			btmp=bio;

			btmp = PKCS7_find_digest(&mdc, btmp, j);

			if (btmp == NULL)
				goto err;

			/* We now have the EVP_MD_CTX, lets do the
			 * signing. */
			EVP_MD_CTX_copy_ex(&ctx_tmp,mdc);
			if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey)))
				{
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
				goto err;
				}

			sk=si->auth_attr;

			/* If there are attributes, we add the digest
			 * attribute and only sign the attributes */
			if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
				{
				unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL;
				unsigned int md_len, alen;
				ASN1_OCTET_STRING *digest;
				ASN1_UTCTIME *sign_time;
				const EVP_MD *md_tmp;

				/* Add signing time if not already present */
				if (!PKCS7_get_signed_attribute(si,
							NID_pkcs9_signingTime))
					{
					if (!(sign_time=X509_gmtime_adj(NULL,0)))
						{
						PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
							ERR_R_MALLOC_FAILURE);
						goto err;
						}
					PKCS7_add_signed_attribute(si,
						NID_pkcs9_signingTime,
						V_ASN1_UTCTIME,sign_time);
					}

				/* Add digest */
				md_tmp=EVP_MD_CTX_md(&ctx_tmp);
				EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len);
				if (!(digest=M_ASN1_OCTET_STRING_new()))
					{
					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
						ERR_R_MALLOC_FAILURE);
					goto err;
					}
				if (!M_ASN1_OCTET_STRING_set(digest,md_data,
								md_len))
					{
					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
						ERR_R_MALLOC_FAILURE);
					goto err;
					}
				PKCS7_add_signed_attribute(si,
					NID_pkcs9_messageDigest,
					V_ASN1_OCTET_STRING,digest);

				/* Now sign the attributes */
				EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL);
				alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf,
							ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
				if(!abuf) goto err;
				EVP_SignUpdate(&ctx_tmp,abuf,alen);
				OPENSSL_free(abuf);
				}

#ifndef OPENSSL_NO_DSA
			if (si->pkey->type == EVP_PKEY_DSA)
				ctx_tmp.digest=EVP_dss1();
#endif
#ifndef OPENSSL_NO_ECDSA
 			if (si->pkey->type == EVP_PKEY_EC)
 				ctx_tmp.digest=EVP_ecdsa();
#endif

			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
				(unsigned int *)&buf->length,si->pkey))
				{
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_EVP_LIB);
				goto err;
				}
			if (!ASN1_STRING_set(si->enc_digest,
				(unsigned char *)buf->data,buf->length))
				{
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_ASN1_LIB);
				goto err;
				}
			}
		}
	else if (i == NID_pkcs7_digest)
		{
		unsigned char md_data[EVP_MAX_MD_SIZE];
		unsigned int md_len;
		if (!PKCS7_find_digest(&mdc, bio,
				OBJ_obj2nid(p7->d.digest->md->algorithm)))
			goto err;
		EVP_DigestFinal_ex(mdc,md_data,&md_len);
		M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
		}

	if (!PKCS7_is_detached(p7))
		{
		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
		if (btmp == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
			goto err;
			}
		BIO_get_mem_ptr(btmp,&buf_mem);
		/* Mark the BIO read only then we can use its copy of the data
		 * instead of making an extra copy.
		 */
		BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
		BIO_set_mem_eof_return(btmp, 0);
		os->data = (unsigned char *)buf_mem->data;
		os->length = buf_mem->length;
#if 0
		M_ASN1_OCTET_STRING_set(os,
			(unsigned char *)buf_mem->data,buf_mem->length);
#endif
		}
	ret=1;
err:
	EVP_MD_CTX_cleanup(&ctx_tmp);
	if (buf != NULL) BUF_MEM_free(buf);
	return(ret);
	}
コード例 #7
0
ファイル: pdf-pkcs7.c プロジェクト: n1tehawk/mupdf
static int pk7_verify(X509_STORE *cert_store, PKCS7 *p7, BIO *detached, char *ebuf, int ebufsize)
{
	PKCS7_SIGNER_INFO *si;
	verify_context vctx;
	BIO *p7bio=NULL;
	char readbuf[1024*4];
	int res = 1;
	int i;
	STACK_OF(PKCS7_SIGNER_INFO) *sk;

	vctx.err = X509_V_OK;
	ebuf[0] = 0;

	OpenSSL_add_all_algorithms();

	EVP_add_digest(EVP_md5());
	EVP_add_digest(EVP_sha1());

	ERR_load_crypto_strings();

	ERR_clear_error();

	X509_VERIFY_PARAM_set_flags(cert_store->param, X509_V_FLAG_CB_ISSUER_CHECK);
	X509_STORE_set_verify_cb_func(cert_store, verify_callback);

	p7bio = PKCS7_dataInit(p7, detached);

	/* We now have to 'read' from p7bio to calculate digests etc. */
	while (BIO_read(p7bio, readbuf, sizeof(readbuf)) > 0)
		;

	/* We can now verify signatures */
	sk = PKCS7_get_signer_info(p7);
	if (sk == NULL)
	{
		/* there are no signatures on this data */
		res = 0;
		fz_strlcpy(ebuf, "No signatures", ebufsize);
		goto exit;
	}

	for (i=0; i<sk_PKCS7_SIGNER_INFO_num(sk); i++)
	{
		int rc;
		si = sk_PKCS7_SIGNER_INFO_value(sk, i);
		rc = PKCS7_dataVerify(cert_store, &vctx.x509_ctx, p7bio,p7, si);
		if (rc <= 0 || vctx.err != X509_V_OK)
		{
			char tbuf[120];

			if (rc <= 0)
			{
				fz_strlcpy(ebuf, ERR_error_string(ERR_get_error(), tbuf), ebufsize);
			}
			else
			{
				/* Error while checking the certificate chain */
				snprintf(ebuf, ebufsize, "%s(%d): %s", X509_verify_cert_error_string(vctx.err), vctx.err, vctx.certdesc);
			}

			res = 0;
			goto exit;
		}
	}

exit:
	X509_STORE_CTX_cleanup(&vctx.x509_ctx);
	ERR_free_strings();

	return res;
}
コード例 #8
0
/* Load a DER formatted file into internal SCEP_MSG structure */
SCEP_MSG *d2i_SCEP_MSG_bio (BIO *inbio) {

	BIO *outbio = NULL;
	BIO *p7bio = NULL;
	PKCS7 *p7 = NULL;
	// BIO *bio_err = NULL;

	SCEP_MSG *msg = NULL;

	int bytes, length, fd, used;
	int nMessageType = -1, nPkiStatus = -1;

	PKCS7_SIGNER_INFO *si = NULL;
	PKCS7_RECIP_INFO *ri = NULL;

	STACK_OF(X509_ATTRIBUTE) *sig_attribs = NULL;
	PKCS7 *p7env = NULL;

	SCEP_RECIP_INFO *rinfo = NULL;

	char buffer[1024];
	char *data = NULL;
	char *tmp_string = NULL;

	int debug = 0;
	int i;

        // if ((bio_err=BIO_new(BIO_s_file())) != NULL)
	// 	BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);

	msg = (SCEP_MSG *) OPENSSL_malloc ( sizeof(SCEP_MSG));
	if( msg == NULL ) return (NULL);

	/* decode the data */
	p7 = d2i_PKCS7_bio(inbio, NULL);
	if (p7 == NULL) goto err;

	/* make sure this is a signed data PKCS#7			*/
	// if (!PKCS7_type_is_signed(p7)) {
	// 	BIO_printf(bio_err, "%s:%d: supplied PKCS#7 is not signed "
	// 		"data\n", __FILE__, __LINE__);
	// 	goto err;
	// }

	/* create BIOs to read signed content data from			*/
	p7bio = PKCS7_dataInit(p7, NULL);
	if (p7bio == NULL) goto err;

	/* Use an outbio and fill it with data from the p7 */
	outbio = BIO_new(BIO_s_mem());
	used = 0;
	for (;;) {
		bytes = BIO_read(p7bio, buffer, sizeof(buffer));
		used += bytes;
		if (bytes <= 0) break;
		BIO_write(outbio, buffer, bytes);
	}
	BIO_flush(outbio);

	/* there should be exactly one signer info			*/
	msg->sk_signer_info = PKCS7_get_signer_info(p7);
	if (msg->sk_signer_info == NULL) {
		goto err;
	}
	if (sk_PKCS7_SIGNER_INFO_num(msg->sk_signer_info) != 1) {
		goto err;
	}

	si = sk_PKCS7_SIGNER_INFO_value(msg->sk_signer_info, 0);
	msg->signer_ias = si->issuer_and_serial;
	msg->signer_cert = PKCS7_cert_from_signer_info( p7, si );

	/* If msg->signer_cert == NULL there is no signer certificate,
	 * otherwise the certificate is included into the PKCS#7 envelope
	 * this certificate may be self signed, but for the PKCS7_
	 * signatureVerify method, this does not matter */

	/* verify the PKCS#7 using the store just constructed		*/
	if (PKCS7_signatureVerify(p7bio, p7, si, 
				msg->signer_cert) <= 0) {
		// BIO_printf(bio_err, "%s:%d: verification failed\n", __FILE__,
		// 	__LINE__);
		goto err;
	}

	/* extract the signed attributes				*/
	msg->attrs = PKCS7_get_signed_attributes(si);
	if ((msg->attrs == NULL) || (sk_X509_ATTRIBUTE_num(msg->attrs) == 0)){
		goto err;
	}

	tmp_string = (char *) 
		SCEP_get_string_attr_by_name(msg->attrs, "messageType");

	if( tmp_string != NULL ) {
		msg->messageType = atoi( tmp_string );
		free( tmp_string );
		tmp_string = NULL;
	} else {
		msg->messageType = -1;
	}

	/* unpack the internal PKCS#7					*/
	p7env = d2i_PKCS7_bio(outbio, NULL);
	if (p7env == NULL) return msg;

	i=OBJ_obj2nid(p7env->type);
	msg->env_data.NID_p7data = i;
	msg->env_data.p7env = p7env;

	/* use a commodity variable */
	rinfo = &(msg->env_data.recip_info);

	switch(i) {
		case NID_pkcs7_signed:
			break;
		case NID_pkcs7_signedAndEnveloped:
			rinfo->sk_recip_info =
				p7env->d.signed_and_enveloped->recipientinfo;
			break;
		case  NID_pkcs7_enveloped:
			rinfo->sk_recip_info =
				p7env->d.enveloped->recipientinfo;
			break;
		default:
			// BIO_printf( bio_err, "%s:%d: unknown PKCS7 structure\n",
			// 		__FILE__, __LINE__);
			break;
	}

	/* Lets do the pub key stuff :-) */
	// FIXME: usaly only 1, but pix has 4 in structure - to be clarified...
	// so currently set to 4 to get it working with cisco-pix
	if( sk_PKCS7_RECIP_INFO_num(rinfo->sk_recip_info) > 4 ) {
		goto err;
	}

	/* Let's get the recipient info at stack num 0, the first and
	 * hopefully, the only one */
	ri = sk_PKCS7_RECIP_INFO_value( rinfo->sk_recip_info, 0);

	/* Usually certificates are not present, but in case the standard
	 * will be updated... */
	// if (debug && ri->cert == NULL) {
	// 	BIO_printf( bio_err, 
	// 		"%s:%d: Recipient info cert %d missing\n",
	// 		__FILE__, __LINE__, 0);
	// }

	rinfo->ias = ri->issuer_and_serial;
	/*
	if( rinfo->ias != NULL ) {
		BIO_printf(bio_err, "%s:%d: Recip cert issued by ",
			__FILE__, __LINE__);
                X509_NAME_print_ex (bio_err, rinfo->ias->issuer,  
                                    0, XN_FLAG_RFC2253&(~ASN1_STRFLGS_ESC_MSB));
		BIO_printf(bio_err, "\n%s:%d: Recip cert serial: %s\n",
			__FILE__, __LINE__,
			BN_bn2hex(ASN1_INTEGER_to_BN(rinfo->ias->serial,
			NULL)));
	};
	*/

	if( ri->cert ) {
		/* Usually this does not happen to be included in
		 * the pkcs7env data, but in case we just get it */
		sk_X509_push( rinfo->sk_recip_certs, ri->cert );
        /*
		if ( debug ) {
                        BIO_printf(bio_err, "%s:%d: Recipient cert for ",
                              __FILE__, __LINE__);
                        X509_NAME_print_ex (bio_err, X509_get_subject_name(ri->cert),
                                0, XN_FLAG_RFC2253&(~ASN1_STRFLGS_ESC_MSB));	
                        BIO_printf(bio_err, "\n");
		}
        */
	}

	/* perform some consistency checks				*/

	/* UniCert 3.1.2 seems to out the message type, so fudge 	*/
	/* the value of 3 (CertRep) if it is missing (problem pointed	*/
	/* out by Peter Onion						*/
	/*
	if (NULL == req->messageType) {
		BIO_printf(bio_err, "%s:%d: no message type (setting to 3)\n",
			__FILE__, __LINE__);
		req->messageType = "3";	// XXX should we strdup here?
	}
	*/

	/* UniCert doesn't seem to bother to put in a senderNonce,	*/
	/* so don't get upset if it is missing.				*/
	/*
	if (NULL == scep->senderNonce) {
		BIO_printf(bio_err, "%s:%d: senderNonce missing\n",
			__FILE__, __LINE__);
	}

	*/

	/* perform some type/status dependent checks			*/
	/*
	if ((used == 0) && (nMessageType != 3)) {
		BIO_printf(bio_err, "%s:%d: only CertRep message may be "
			"empty\n", __FILE__, __LINE__);
		goto err;
	}
	if ((used == 0) && (nMessageType == 3) && (nPkiStatus == 0)) {
		BIO_printf(bio_err, "%s:%d: CertRep may only be empty for "
			"failure or pending\n", __FILE__, __LINE__);
		goto err;
	}
	*/

	/* no content is only allowed if the message is a CertRep with	*/
	/* a pkiStatus of failure or pending				*/
	/*
	if (used == 0) {
		BIO_printf(bio_err, "%s:%d: empty PKCSReq, must be failure or "
			"pending\n", __FILE__, __LINE__);
		goto signedonly;
	}
	if (debug)
		BIO_printf(bio_err, "%s:%d: working on inner pkcs#7\n",
			__FILE__, __LINE__);

	*/

	BIO_free(outbio);
signedonly:

	/* we were successfull in extracting the telescoping PKCS#7's	*/
	return(msg);
err:
	// if( debug ) ERR_print_errors(bio_err);
	return(NULL);
}
コード例 #9
0
ファイル: pkcs7.c プロジェクト: chk-jxcn/lua-openssl
static LUA_FUNCTION(openssl_pkcs7_parse)
{
  PKCS7 * p7 = CHECK_OBJECT(1, PKCS7, "openssl.pkcs7");
  STACK_OF(X509) *certs = NULL;
  STACK_OF(X509_CRL) *crls = NULL;
  int i = OBJ_obj2nid(p7->type);

  lua_newtable(L);
  AUXILIAR_SET(L, -1, "type", OBJ_nid2ln(i), string);
  switch (i)
  {
  case NID_pkcs7_signed:
  {
    PKCS7_SIGNED *sign = p7->d.sign;
    certs = sign->cert ? sign->cert : NULL;
    crls = sign->crl ? sign->crl : NULL;

    AUXILIAR_SET(L, -1, "version", ASN1_INTEGER_get(sign->version), integer);
    AUXILIAR_SET(L, -1, "detached", PKCS7_is_detached(p7), boolean);
    lua_pushstring(L, "md_algs");
    openssl_sk_x509_algor_totable(L, sign->md_algs);
    lua_rawset(L, -3);

    if (sign->signer_info)
    {
      int j, n;
      n = sk_PKCS7_SIGNER_INFO_num(sign->signer_info);
      lua_pushstring(L, "signer_info");
      lua_newtable(L);
      for (j = 0; j < n; j++)
      {
        PKCS7_SIGNER_INFO *info = sk_PKCS7_SIGNER_INFO_value(sign->signer_info, j);
        lua_pushinteger(L, j + 1);
        openssl_push_pkcs7_signer_info(L, info);
        lua_rawset(L, -3);
      }
      lua_rawset(L, -3);
    }

    if (!PKCS7_is_detached(p7))
    {
      PKCS7* c = sign->contents;
      c = PKCS7_dup(c);
      AUXILIAR_SETOBJECT(L, c, "openssl.pkcs7", -1, "contents");
    }
  }
  break;
  case NID_pkcs7_signedAndEnveloped:
    certs = p7->d.signed_and_enveloped->cert;
    crls = p7->d.signed_and_enveloped->crl;
    break;
  case NID_pkcs7_enveloped:
  {
    /*
    BIO * mem = BIO_new(BIO_s_mem());
    BIO * v_p7bio = PKCS7_dataDecode(p7,pkey,NULL,NULL);
    BUF_MEM *bptr = NULL;
    unsigned char src[4096];
    int len;

    while((len = BIO_read(v_p7bio,src,4096))>0){
     BIO_write(mem, src, len);
    }
    BIO_free(v_p7bio);
    BIO_get_mem_ptr(mem, &bptr);
    if((int)*puiDataLen < bptr->length)
    {
     *puiDataLen = bptr->length;
     ret = SAR_MemoryErr;
    }else{
     *puiDataLen =  bptr->length;
     memcpy(pucData,bptr->data, bptr->length);
    }
    */
  }
  break;
  case NID_pkcs7_digest:
  {
    PKCS7_DIGEST* d = p7->d.digest;

    ASN1_OCTET_STRING *as = ASN1_STRING_dup(d->digest);
    PUSH_OBJECT(as, "openssl.asn1_string");
    lua_setfield(L, -2, "digest");
  }
  break;
  case NID_pkcs7_data:
  {
    ASN1_OCTET_STRING *as = ASN1_STRING_dup(p7->d.data);
    PUSH_OBJECT(as, "openssl.asn1_string");
    lua_setfield(L, -2, "data");
  }
  break;
  default:
    break;
  }

  /* NID_pkcs7_signed or NID_pkcs7_signedAndEnveloped */
  if (certs != NULL)
  {
    lua_pushstring(L, "certs");
    openssl_sk_x509_totable(L, certs);
    lua_rawset(L, -3);
  }
  if (crls != NULL)
  {
    lua_pushstring(L, "crls");
    openssl_sk_x509_crl_totable(L, crls);
    lua_rawset(L, -3);
  }
  return 1;
}
コード例 #10
0
ファイル: pkcs7.c プロジェクト: chk-jxcn/lua-openssl
static LUA_FUNCTION(openssl_pkcs7_verify_digest)
{
  PKCS7 *p7 = CHECK_OBJECT(1, PKCS7, "openssl.pkcs7");
  STACK_OF(X509) *certs = lua_isnoneornil(L, 2) ? NULL : openssl_sk_x509_fromtable(L, 2);
  X509_STORE *store = lua_isnoneornil(L, 3) ? NULL : CHECK_OBJECT(3, X509_STORE, "openssl.x509_store");
  size_t len;
  const char* data = luaL_checklstring(L, 4, &len);
  long flags = luaL_optint(L, 5, 0);
  int hash = lua_isnoneornil(L, 6) ? 0 : lua_toboolean(L, 6);

  STACK_OF(X509) *signers;
  X509 *signer;
  STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
  PKCS7_SIGNER_INFO *si;
  X509_STORE_CTX cert_ctx;

  int i, j = 0, k, ret = 0;

  if (!PKCS7_type_is_signed(p7))
  {
    luaL_error(L, "pkcs7 must be signedData");
  }

  /* Check for no data and no content: no data to verify signature */
  if (!PKCS7_get_detached(p7))
  {
    luaL_error(L, "pkcs7 must be detached signedData");
  }


  sinfos = PKCS7_get_signer_info(p7);
  if (!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos))
  {
    luaL_error(L, "pkcs7 signedData without signature");
  }

  signers = PKCS7_get0_signers(p7, certs, flags);
  if (!signers)
  {
    luaL_error(L, "pkcs7 signedData without signers");
  }

  if (!store)
    flags |= PKCS7_NOVERIFY;

  /* Now verify the certificates */
  if (!(flags & PKCS7_NOVERIFY))
    for (k = 0; k < sk_X509_num(signers); k++)
    {
      signer = sk_X509_value(signers, k);
      if (!(flags & PKCS7_NOCHAIN))
      {
        if (!X509_STORE_CTX_init(&cert_ctx, store, signer,
                                 p7->d.sign->cert))
        {
          PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB);
          goto err;
        }
        X509_STORE_CTX_set_default(&cert_ctx, "smime_sign");
      }
      else if (!X509_STORE_CTX_init(&cert_ctx, store, signer, NULL))
      {
        PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB);
        goto err;
      }
      if (!(flags & PKCS7_NOCRL))
        X509_STORE_CTX_set0_crls(&cert_ctx, p7->d.sign->crl);
      i = X509_verify_cert(&cert_ctx);
      if (i <= 0)
        j = X509_STORE_CTX_get_error(&cert_ctx);
      X509_STORE_CTX_cleanup(&cert_ctx);
      if (i <= 0)
      {
        PKCS7err(PKCS7_F_PKCS7_VERIFY,
                 PKCS7_R_CERTIFICATE_VERIFY_ERROR);
        ERR_add_error_data(2, "Verify error:",
                           X509_verify_cert_error_string(j));
        goto err;
      }
      /* Check for revocation status here */
    }

  /* Now Verify All Signatures */
  if (!(flags & PKCS7_NOSIGS))
    for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
    {
      si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
      signer = sk_X509_value(signers, i);
      j = PKCS7_signatureVerify_digest(p7, si, signer,
                                       (const unsigned char*) data, len, hash);
      if (j <= 0)
      {
        PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_SIGNATURE_FAILURE);
        goto err;
      }
    }
  ret = 1;

err:
  if (certs)
    sk_X509_pop_free(certs, X509_free);
  sk_X509_free(signers);
  return openssl_pushresult(L, ret);
}
コード例 #11
0
ファイル: pkcs7.c プロジェクト: chk-jxcn/lua-openssl
static LUA_FUNCTION(openssl_pkcs7_sign_digest)
{
  PKCS7 *p7 = CHECK_OBJECT(1, PKCS7, "openssl.pkcs7");
  size_t l;
  const char* data = luaL_checklstring(L, 2, &l);
  long flags = luaL_optint(L, 3, 0);
  int hash = lua_isnoneornil(L, 4) ? 0 : lua_toboolean(L, 4);

  int ret = 0;
  int i, j;

  const EVP_MD* md;
  PKCS7_SIGNER_INFO *si;
  EVP_MD_CTX mdc;
  STACK_OF(X509_ATTRIBUTE) *sk;
  STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
  ASN1_OCTET_STRING *os = NULL;

  if (p7->d.ptr == NULL)
  {
    luaL_error(L, "pkcs7 without content");
    return 0;
  }

  flags |= PKCS7_DETACHED;
  PKCS7_set_detached(p7, 1);

  EVP_MD_CTX_init(&mdc);
  i = OBJ_obj2nid(p7->type);
  p7->state = PKCS7_S_HEADER;

  switch (i)
  {
  case NID_pkcs7_data:
    os = p7->d.data;
    break;
  case NID_pkcs7_signedAndEnveloped:
    /* XXXXXXXXXXXXXXXX */
    si_sk = p7->d.signed_and_enveloped->signer_info;
    os = p7->d.signed_and_enveloped->enc_data->enc_data;
    if (!os)
    {
      os = M_ASN1_OCTET_STRING_new();
      if (!os)
      {
        PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE);
        goto err;
      }
      p7->d.signed_and_enveloped->enc_data->enc_data = os;
    }
    break;
  case NID_pkcs7_enveloped:
    /* XXXXXXXXXXXXXXXX */
    os = p7->d.enveloped->enc_data->enc_data;
    if (!os)
    {
      os = M_ASN1_OCTET_STRING_new();
      if (!os)
      {
        PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE);
        goto err;
      }
      p7->d.enveloped->enc_data->enc_data = os;
    }
    break;
  case NID_pkcs7_signed:
    si_sk = p7->d.sign->signer_info;
    os = PKCS7_get_octet_string(p7->d.sign->contents);
    /* If detached data then the content is excluded */
    if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached)
    {
      M_ASN1_OCTET_STRING_free(os);
      os = NULL;
      p7->d.sign->contents->d.data = NULL;
    }
    break;

  case NID_pkcs7_digest:
    os = PKCS7_get_octet_string(p7->d.digest->contents);
    /* If detached data then the content is excluded */
    if (PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
    {
      M_ASN1_OCTET_STRING_free(os);
      os = NULL;
      p7->d.digest->contents->d.data = NULL;
    }
    break;

  default:
    PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
    goto err;
  }

  if (si_sk != NULL)
  {
    for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++)
    {
      si = sk_PKCS7_SIGNER_INFO_value(si_sk, i);
      if (si->pkey == NULL)
        continue;
      j = OBJ_obj2nid(si->digest_alg->algorithm);
      md = EVP_get_digestbynid(j);
      EVP_DigestInit_ex(&mdc, md, NULL);

      if (hash)
      {
        if (l == (size_t) mdc.digest->ctx_size)
        {
          memcpy(mdc.md_data, data, l);
        }
        else
        {
          EVP_MD_CTX_cleanup(&mdc);
          luaL_argerror(L, 2, "data with wrong length");
        }
      }
      else
        EVP_DigestUpdate(&mdc, data, l);

      sk = si->auth_attr;

      /*
      * If there are attributes, we add the digest attribute and only
      * sign the attributes
      */
      if (sk_X509_ATTRIBUTE_num(sk) > 0)
      {
        if (!do_pkcs7_signed_attrib(si, &mdc))
          goto err;
      }
      else
      {
        unsigned char *abuf = NULL;
        unsigned int abuflen;
        abuflen = EVP_PKEY_size(si->pkey);
        abuf = OPENSSL_malloc(abuflen);
        if (!abuf)
          goto err;

        if (!EVP_SignFinal(&mdc, abuf, &abuflen, si->pkey))
        {
          PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB);
          goto err;
        }
        ASN1_STRING_set0(si->enc_digest, abuf, abuflen);
      }
    }
  }
  else if (i == NID_pkcs7_digest)
  {
    unsigned char md_data[EVP_MAX_MD_SIZE];
    unsigned int md_len;
    md = EVP_get_digestbynid(OBJ_obj2nid(p7->d.digest->md->algorithm));
    EVP_DigestInit_ex(&mdc, md, NULL);
    if (l == (size_t) mdc.digest->ctx_size)
    {
      memcpy(mdc.md_data, data, l);
    }
    else
    {
      EVP_MD_CTX_cleanup(&mdc);
      luaL_error(L, "data with wrong data");
    }
    if (!EVP_DigestFinal_ex(&mdc, md_data, &md_len))
      goto err;
    M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
  }

  if (!PKCS7_is_detached(p7))
  {
    /*
    * NOTE(emilia): I think we only reach os == NULL here because detached
    * digested data support is broken.
    */
    if (os == NULL)
      goto err;
    if (!(os->flags & ASN1_STRING_FLAG_NDEF))
    {
      char *cont = memdup(data, l);
      long contlen = l;
      ASN1_STRING_set0(os, (unsigned char *) cont, contlen);
    }
  }

  ret = 1;
err:
  EVP_MD_CTX_cleanup(&mdc);
  return openssl_pushresult(L, ret);
}
コード例 #12
0
ファイル: smime-vfy.c プロジェクト: gitpan/smime
char* /* returns contents of the signed message, NULL if error */
smime_verify_signature(const char* pubkey,
		       const char* sig_entity,     /* signed entity
						      or just the sigature */
		       const char* detached_data,  /* possibly NULL */
		       int detached_data_len)
{
  X509*  x509 = NULL;
  PKCS7* p7 = NULL;
  STACK_OF(PKCS7_SIGNER_INFO)* sigs = NULL;
  X509_STORE* certs=NULL;
  BIO*   detached = NULL;
  BIO*   p7bio = NULL;
  BIO*   wbio = NULL;
  char*  data = NULL;
  char   buf[4096];
  int    i,x;
  
  if (!sig_entity || !pubkey) GOTO_ERR("NULL arg(s)");
  if (!(p7 = get_pkcs7_from_pem(sig_entity))) goto err;

  /* Hmm, if its clear signed, we already provided the detached sig, but
   * if its one sig blob, may be PKCS7_get_detached() provides BIO connected
   * to the detached part. Go figure.
   */

  if (detached_data && detached_data_len) {
    if (!(detached = set_read_BIO_from_buf(detached_data, detached_data_len)))
      goto err;
  } else {
    if (!PKCS7_get_detached(p7))
      GOTO_ERR("15 cant extract signed data from signed entity (PKCS7_get_detached)");
  }
  if (!(p7bio=PKCS7_dataInit(p7,detached))) GOTO_ERR("PKCS7_dataInit");
  
  if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
  
  /* We now have to 'read' from p7bio to calculate message digest(s).
   * I also take the opportunity to save the signed data. */
  for (;;) {
    i = BIO_read(p7bio,buf,sizeof(buf));
    if (i <= 0) break;
    BIO_write(wbio, buf, i);
  }
  
  if (get_written_BIO_data(wbio, &data)==-1) goto err;
  BIO_free_all(wbio);
  wbio = NULL;
  
  /* We can now verify signatures */
  if (!(sigs=PKCS7_get_signer_info(p7)))
    GOTO_ERR("13 no sigs? (PKCS7_get_signer_info)");
  
  /* Ok, first we need to, for each subject entry, see if we can verify */
  for (i=0; i<sk_PKCS7_SIGNER_INFO_num(sigs); i++) {
    X509_STORE_CTX cert_ctx;
    PKCS7_SIGNER_INFO *si;
    ASN1_UTCTIME *tm;
    char *str1,*str2;
    
    si=sk_PKCS7_SIGNER_INFO_value(sigs,i);
    
    /* The bio is needed here only to lookup the message digest context
     * which presumably now contains the message digest. It will not be
     * read, and hence its good for any number of iterations. This is so
     * because MD bios pass the data right thru so they can be stacked
     * to calculate multiple message digests simultaneously. Clever, eh?
     */

#if 0
    /* *** this is currently broken and thus disabled. --Sampo */
    /* verifies by looking up the certificate from certs database,
     * verifying the validity of the certificate, and finally
     * validity of the signature */

    x=PKCS7_dataVerify(certs, &cert_ctx, p7bio, p7, si);
#else
    /* just verify the signature, given that we already have certificate
     * candidate (see crypto/pk7_doit.c around line 675) */

    if (!(x509 = extract_certificate(pubkey))) goto err;
    x=PKCS7_signatureVerify(p7bio, p7, si, x509);
#endif
    if (x <= 0) GOTO_ERR("14 sig verify failed");
    
#if 0
    if ((tm=get_signed_time(si)) != NULL) {
      //fprintf(stderr,"Signed time:");
      //ASN1_UTCTIME_print(bio_out,tm);
      ASN1_UTCTIME_free(tm);
      //BIO_printf(bio_out,"\n");
    }
#endif
#if 0
    if (get_signed_seq2string(si,&str1,&str2)) {
      fprintf(stderr,"String 1 is %s\n",str1);
      fprintf(stderr,"String 2 is %s\n",str2);
    }
#endif
  }
  
  BIO_free_all(p7bio);
  PKCS7_free(p7);
  X509_STORE_free(certs);
  return data;    /* return the signed plain text */

err:
  if (wbio) BIO_free_all(wbio);
  if (p7bio) BIO_free_all(p7bio);
  if (p7) PKCS7_free(p7);
  if (certs) X509_STORE_free(certs);
  if (data) Free(data);
  return NULL;
}
コード例 #13
0
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
	{
	int ret=0;
	int i,j;
	BIO *btmp;
	BUF_MEM *buf_mem=NULL;
	BUF_MEM *buf=NULL;
	PKCS7_SIGNER_INFO *si;
	EVP_MD_CTX *mdc,ctx_tmp;
	STACK_OF(X509_ATTRIBUTE) *sk;
	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
	unsigned char *p,*pp=NULL;
	int x;
	ASN1_OCTET_STRING *os=NULL;

	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signedAndEnveloped:
		/* XXXXXXXXXXXXXXXX */
		si_sk=p7->d.signed_and_enveloped->signer_info;
		os=M_ASN1_OCTET_STRING_new();
		p7->d.signed_and_enveloped->enc_data->enc_data=os;
		break;
	case NID_pkcs7_enveloped:
		/* XXXXXXXXXXXXXXXX */
		os=M_ASN1_OCTET_STRING_new();
		p7->d.enveloped->enc_data->enc_data=os;
		break;
	case NID_pkcs7_signed:
		si_sk=p7->d.sign->signer_info;
		os=p7->d.sign->contents->d.data;
		/* If detached data then the content is excluded */
		if(p7->detached) {
			M_ASN1_OCTET_STRING_free(os);
			p7->d.sign->contents->d.data = NULL;
		}
		break;
		}

	if (si_sk != NULL)
		{
		if ((buf=BUF_MEM_new()) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
			goto err;
			}
		for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++)
			{
			si=sk_PKCS7_SIGNER_INFO_value(si_sk,i);
			if (si->pkey == NULL) continue;

			j=OBJ_obj2nid(si->digest_alg->algorithm);

			btmp=bio;
			for (;;)
				{
				if ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) 
					== NULL)
					{
					PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
					goto err;
					}
				BIO_get_md_ctx(btmp,&mdc);
				if (mdc == NULL)
					{
					PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_INTERNAL_ERROR);
					goto err;
					}
				if (EVP_MD_CTX_type(mdc) == j)
					break;
				else
					btmp=BIO_next(btmp);
				}
			
			/* We now have the EVP_MD_CTX, lets do the
			 * signing. */
			memcpy(&ctx_tmp,mdc,sizeof(ctx_tmp));
			if (!BUF_MEM_grow(buf,EVP_PKEY_size(si->pkey)))
				{
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
				goto err;
				}

			sk=si->auth_attr;

			/* If there are attributes, we add the digest
			 * attribute and only sign the attributes */
			if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
				{
				unsigned char md_data[EVP_MAX_MD_SIZE];
				unsigned int md_len;
				ASN1_OCTET_STRING *digest;
				ASN1_UTCTIME *sign_time;
				const EVP_MD *md_tmp;

				/* Add signing time */
				sign_time=X509_gmtime_adj(NULL,0);
				PKCS7_add_signed_attribute(si,
					NID_pkcs9_signingTime,
					V_ASN1_UTCTIME,sign_time);

				/* Add digest */
				md_tmp=EVP_MD_CTX_md(&ctx_tmp);
				EVP_DigestFinal(&ctx_tmp,md_data,&md_len);
				digest=M_ASN1_OCTET_STRING_new();
				M_ASN1_OCTET_STRING_set(digest,md_data,md_len);
				PKCS7_add_signed_attribute(si,
					NID_pkcs9_messageDigest,
					V_ASN1_OCTET_STRING,digest);

				/* Now sign the mess */
				EVP_SignInit(&ctx_tmp,md_tmp);
				x=i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,NULL,
					   i2d_X509_ATTRIBUTE,
					   V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET);
				pp=(unsigned char *)OPENSSL_malloc(x);
				p=pp;
				i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,&p,
				           i2d_X509_ATTRIBUTE,
					   V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET);
				EVP_SignUpdate(&ctx_tmp,pp,x);
				OPENSSL_free(pp);
				pp=NULL;
				}

#ifndef NO_DSA
			if (si->pkey->type == EVP_PKEY_DSA)
				ctx_tmp.digest=EVP_dss1();
#endif

			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
				(unsigned int *)&buf->length,si->pkey))
				{
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB);
				goto err;
				}
			if (!ASN1_STRING_set(si->enc_digest,
				(unsigned char *)buf->data,buf->length))
				{
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB);
				goto err;
				}
			}
		}

	if (!p7->detached)
		{
		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
		if (btmp == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
			goto err;
			}
		BIO_get_mem_ptr(btmp,&buf_mem);
		/* Mark the BIO read only then we can use its copy of the data
		 * instead of making an extra copy.
		 */
		BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
		BIO_set_mem_eof_return(btmp, 0);
		os->data = (unsigned char *)buf_mem->data;
		os->length = buf_mem->length;
#if 0
		M_ASN1_OCTET_STRING_set(os,
			(unsigned char *)buf_mem->data,buf_mem->length);
#endif
		}
	if (pp != NULL) OPENSSL_free(pp);
	pp=NULL;

	ret=1;
err:
	if (buf != NULL) BUF_MEM_free(buf);
	return(ret);
	}