Пример #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; 
} 
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;
}
Пример #3
0
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;
}
Пример #4
0
/*******************************************************************************
函数名称: cert_pkcs7_unwrap
功能描述: 解析从服务器收到的信息,包括验证签名以及解密。
输入参数: struct scep *s, SCEP操作的结构体指针。

输出参数: 无
返 回 值: 1,成功;-1,失败
--------------------------------------------------------------------------------
最近一次修改记录:
修改作者:王朝
修改目的:添加新函数
修改日期:2009年12月28日
*********************************************************************************/
s32 cert_pkcs7_unwrap(struct scep *s)
{
	BIO	*memorybio = NULL;
	BIO	*outbio = NULL;
	BIO	*pkcs7bio = NULL;
	s32	bytes, used, retval = -1;
	STACK_OF(PKCS7_SIGNER_INFO)	*sk = NULL;
	PKCS7 *p7enc = NULL;
	PKCS7_SIGNER_INFO *si = NULL;
	STACK_OF(X509_ATTRIBUTE) *attribs = NULL;
	s8 *p = NULL;
	u8 buffer[1024];
	X509 *recipientcert = NULL;
	EVP_PKEY *recipientkey = NULL;


	/* Create new memory BIO for outer PKCS#7 */
	memorybio = BIO_new(BIO_s_mem());

	/* Read in data */
	if ((BIO_write(memorybio, s->reply_payload, s->reply_len)) <= 0)
    {
        goto end;
	}

	BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY);
	s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL);

    BIO_free(memorybio);
    memorybio = NULL;

	 /* Make sure this is a signed PKCS#7 */
    if (!PKCS7_type_is_signed(s->reply_p7))
    {
        goto end;
    }

	/* Create BIO for content data */
	pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL);
	if (pkcs7bio == NULL)
    {
        goto end;
	}

	/* */
	outbio = BIO_new(BIO_s_mem());
	used = 0;
	for (;;)
    {
		bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer));
		used += bytes;
		if (bytes <= 0) break;
		BIO_write(outbio, buffer, bytes);
	}
	(void)BIO_flush(outbio);

	/* Get signer */
	sk = PKCS7_get_signer_info(s->reply_p7);
	if (sk == NULL)
    {
        goto end;
	}

	/* Verify signature */
	si = sk_PKCS7_SIGNER_INFO_value(sk, 0);

	if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, cert_cacert) <= 0)
    {
        goto end;
	}

	/* Get signed attributes */
	attribs = PKCS7_get_signed_attributes(si);
	if (attribs == NULL)
    {
        goto end;
	}

	/* Transaction id */
	if (1 != cert_get_signed_attribute(attribs, nid_transId,	V_ASN1_PRINTABLESTRING, &p))
    {
        goto end;
	}

	if (strncmp(s->transaction_id, p, strlen(p)))
    {
        goto end;
	}
	/* Message type, should be of type CertRep */
	if (1 != cert_get_signed_attribute(attribs, nid_messageType,	V_ASN1_PRINTABLESTRING, &p))
    {
        goto end;
	}
	if (atoi(p) != 3)
    {
        goto end;
	}

	/* Sender and recipient nonces: */
	if (1 == cert_get_signed_attribute(attribs, nid_senderNonce,	V_ASN1_OCTET_STRING, &p))
    {
		s->reply_sender_nonce = (u8 *)p;
	}
    else
    {
	    s->reply_sender_nonce = NULL;
    }
    
	if ( 1 != cert_get_signed_attribute(attribs, nid_recipientNonce,V_ASN1_OCTET_STRING, &p))
    {
		goto end;
	}
	s->reply_recipient_nonce = (u8 *)p;

	/* Get pkiStatus */
	if (1 != cert_get_signed_attribute(attribs, nid_pkiStatus,V_ASN1_PRINTABLESTRING, &p))
    {
		goto end;
	}
	switch (atoi(p))
    {
		case SCEP_PKISTATUS_SUCCESS:
			s->pki_status = SCEP_PKISTATUS_SUCCESS;
			break;
		case SCEP_PKISTATUS_FAILURE:
			s->pki_status = SCEP_PKISTATUS_FAILURE;
			break;
		case SCEP_PKISTATUS_PENDING:
			s->pki_status = SCEP_PKISTATUS_PENDING;
			break;
		default:
			goto end;
	}

	/* Get failInfo */
	if (s->pki_status == SCEP_PKISTATUS_FAILURE)
    {
		if (1 != cert_get_signed_attribute(attribs, nid_failInfo,V_ASN1_PRINTABLESTRING, &p)) 
        {
            goto end;
		}
		switch (atoi(p))
        {
			case SCEP_FAILINFO_BADALG:
				s->fail_info = SCEP_FAILINFO_BADALG;
				break;
			case SCEP_FAILINFO_BADMSGCHK:
				s->fail_info = SCEP_FAILINFO_BADMSGCHK;
				break;
			case SCEP_FAILINFO_BADREQ:
				s->fail_info = SCEP_FAILINFO_BADREQ;
				break;
			case SCEP_FAILINFO_BADTIME:
				s->fail_info = SCEP_FAILINFO_BADTIME;
				break;
			case SCEP_FAILINFO_BADCERTID:
				s->fail_info = SCEP_FAILINFO_BADCERTID;
				break;
			default:
				goto end;
		}
	}
	/* If FAILURE or PENDING, we can return */
	if (s->pki_status != SCEP_PKISTATUS_SUCCESS)
    {
		/* There shouldn't be any more data... */
		retval = 1;
        goto end;
	}
	/* We got success and expect data */
	if (used == 0)
    {
		goto end;
	}

	/* Decrypt the inner PKCS#7 */
	if ((s->request_type == SCEP_REQUEST_PKCSREQ) || (s->request_type == SCEP_REQUEST_GETCERTINIT))
    {
		recipientcert = s->signercert;
		recipientkey = s->signerkey;
	}
	else
    {
		recipientcert = cert_localcert;
		recipientkey = cert_rsa;
	}

	p7enc = d2i_PKCS7_bio(outbio, NULL);
	if (p7enc == NULL)
    {
		goto end;
	}

    BIO_free(outbio);
    outbio = NULL;

	/* Decrypt the data  */
	outbio = BIO_new(BIO_s_mem());
	if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0)
    {
		goto end;
	}
	(void)BIO_flush(outbio);

	/* Write decrypted data */
	s->reply_len = BIO_get_mem_data(outbio, &s->reply_payload);

	BIO_set_flags(outbio, BIO_FLAGS_MEM_RDONLY);
	s->reply_p7 = d2i_PKCS7_bio(outbio, NULL);

    retval = 1;
end:
    if(NULL != outbio)
    {
        BIO_free(outbio);
    }

    if(NULL != memorybio)
    {
        BIO_free(memorybio);
    }

    if(NULL != pkcs7bio)
    {
        BIO_free(pkcs7bio);
    }

    if(NULL != p7enc)
    {
        PKCS7_free(p7enc);
    }

    return retval;
}
Пример #5
0
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;
}
Пример #6
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);
}
Пример #7
0
/*
 * Unwrap PKCS#7 data and decrypt if necessary
 */
int pkcs7_unwrap(struct scep *s, struct sscep_ctx *ctx, struct sscep_operation_info *op_info, char* data, int datalen)
{
    BIO *memorybio = NULL;
    BIO *outbio = NULL;
    BIO *pkcs7bio = NULL;
    int i, bytes, used;
    STACK_OF(PKCS7_SIGNER_INFO) *sk;
    PKCS7 *p7enc = NULL;
    PKCS7_SIGNER_INFO *si;
    STACK_OF(X509_ATTRIBUTE) *attribs;
    char *p = NULL;
    unsigned char buffer[1024];
    X509 *recipientcert;
    EVP_PKEY *recipientkey;
    int ret = SCEP_PKISTATUS_P7;

    /* Create new memory BIO for outer PKCS#7 */
    memorybio = BIO_new(BIO_s_mem());

    /* Read in data */
    if (ctx->verbose){
        qeo_log_i("reading outer PKCS#7");
    }
    if (BIO_write(memorybio, data, datalen) <= 0) {
        qeo_log_e("error reading PKCS#7 data");
        goto error;
    }
    if (ctx->verbose){
        qeo_log_i("PKCS#7 payload size: %d bytes", datalen);
    }
    s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL );
    if (s->reply_p7 == NULL ) {
        qeo_log_e("error retrieving PKCS#7 data");
        goto error;
    }
    if (ctx->debug) {
        qeo_log_i("printing PEM fomatted PKCS#7");
        PEM_write_PKCS7(stdout, s->reply_p7);
    }

    /* Make sure this is a signed PKCS#7 */
    if (!PKCS7_type_is_signed(s->reply_p7)) {
        qeo_log_e("PKCS#7 is not signed!");
        goto error;
    }

    /* Create BIO for content data */
    pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL );
    if (pkcs7bio == NULL ) {
        qeo_log_e("cannot get PKCS#7 data");
        goto error;
    }

    /* Copy enveloped data from PKCS#7 */
    outbio = BIO_new(BIO_s_mem());
    used = 0;
    for (;;) {
        bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer));
        used += bytes;
        if (bytes <= 0)
            break;
        BIO_write(outbio, buffer, bytes);
    }
    (void)BIO_flush(outbio);
    if (ctx->verbose){
        qeo_log_i("PKCS#7 contains %d bytes of enveloped data", used);
    }

    /* Get signer */
    sk = PKCS7_get_signer_info(s->reply_p7);
    if (sk == NULL ) {
        qeo_log_e("cannot get signer info!");
        goto error;
    }

    /* Verify signature */
    if (ctx->verbose){
        qeo_log_i("verifying signature");
    }
    si = sk_PKCS7_SIGNER_INFO_value(sk, 0);
    if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, op_info->racert) <= 0) {
        qeo_log_e("error verifying signature");
        goto error;
    }
    if (ctx->verbose){
        qeo_log_i("signature ok");
    }

    /* Get signed attributes */
    if (ctx->verbose){
        qeo_log_i("finding signed attributes");
    }
    attribs = PKCS7_get_signed_attributes(si);
    if (attribs == NULL ) {
        qeo_log_e("no attributes found");
        goto error;
    }

    /* Transaction id */
    if ((get_signed_attribute(attribs, ctx->nid_transId, V_ASN1_PRINTABLESTRING, &p, ctx)) == 1) {
        qeo_log_e("cannot find transId");
        goto error;
    }
    if (ctx->verbose){
        qeo_log_i("reply transaction id: %s", p);
    }
    if (strncmp(s->transaction_id, p, strlen(p))) {
        qeo_log_e("transaction id mismatch");
        goto error;
    }
    free(p);
    p=NULL;
    /* Message type, should be of type CertRep */
    if (get_signed_attribute(attribs, ctx->nid_messageType, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) {
        qeo_log_e("cannot find messageType");
        goto error;
    }
    if (atoi(p) != 3) {
        qeo_log_e("wrong message type in reply");
        goto error;
    }
    if (ctx->verbose){
        qeo_log_i("reply message type is good");
    }

    free(p);
    p=NULL;
    /* Recipient nonces: */
    if (get_signed_attribute(attribs, ctx->nid_recipientNonce, V_ASN1_OCTET_STRING, &p, ctx) == 1) {
        qeo_log_e("cannot find recipientNonce");
        goto error;
    }
    s->reply_recipient_nonce = p;
    p = NULL;
    if (ctx->verbose) {
        qeo_log_i("recipientNonce in reply");
    }
    /*
     * Compare recipient nonce to original sender nonce
     * The draft says nothing about this, but it makes sense to me..
     * XXXXXXXXXXXXXX check
     */
    for (i = 0; i < 16; i++) {
        if (s->sender_nonce[i] != s->reply_recipient_nonce[i]) {
            if (ctx->verbose)
                qeo_log_e("corrupted nonce received");
            /* Instead of exit, break out */
            break;
        }
    }
    /* Get pkiStatus */
    if (get_signed_attribute(attribs, ctx->nid_pkiStatus, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) {
        qeo_log_e("cannot find pkiStatus");
        /* This is a mandatory attribute.. */
        goto error;
    }
    switch (atoi(p)) {
        case SCEP_PKISTATUS_SUCCESS:
            qeo_log_i("pkistatus: SUCCESS");
            s->pki_status = SCEP_PKISTATUS_SUCCESS;
            break;
        case SCEP_PKISTATUS_FAILURE:
            qeo_log_i("pkistatus: FAILURE");
            s->pki_status = SCEP_PKISTATUS_FAILURE;
            break;
        case SCEP_PKISTATUS_PENDING:
            qeo_log_i("pkistatus: PENDING");
            s->pki_status = SCEP_PKISTATUS_PENDING;
            break;
        default:
            qeo_log_e("wrong pkistatus in reply");
            goto error;
    }
    free(p);
    p=NULL;

    /* Get failInfo */
    if (s->pki_status == SCEP_PKISTATUS_FAILURE) {
        if (get_signed_attribute(attribs, ctx->nid_failInfo, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) {
            qeo_log_e("cannot find failInfo");
            goto error;
        }
        switch (atoi(p)) {
            case SCEP_FAILINFO_BADALG:
                s->fail_info = SCEP_FAILINFO_BADALG;
                qeo_log_i("reason: %s", SCEP_FAILINFO_BADALG_STR);
                break;
            case SCEP_FAILINFO_BADMSGCHK:
                s->fail_info = SCEP_FAILINFO_BADMSGCHK;
                qeo_log_i("reason: %s", SCEP_FAILINFO_BADMSGCHK_STR);
                break;
            case SCEP_FAILINFO_BADREQ:
                s->fail_info = SCEP_FAILINFO_BADREQ;
                qeo_log_i("reason: %s", SCEP_FAILINFO_BADREQ_STR);
                break;
            case SCEP_FAILINFO_BADTIME:
                s->fail_info = SCEP_FAILINFO_BADTIME;
                qeo_log_i("reason: %s", SCEP_FAILINFO_BADTIME_STR);
                break;
            case SCEP_FAILINFO_BADCERTID:
                s->fail_info = SCEP_FAILINFO_BADCERTID;
                qeo_log_i("reason: %s", SCEP_FAILINFO_BADCERTID_STR);
                break;
            default:
                qeo_log_e("wrong failInfo in " "reply");
                goto error;
        }
        free(p);
        p=NULL;
    }
    /* If FAILURE or PENDING, we can return */
    if (s->pki_status != SCEP_PKISTATUS_SUCCESS) {
        /* There shouldn't be any more data... */
        if (ctx->verbose && (used != 0)) {
            qeo_log_e("illegal size of payload");
        }
        return (0);
    }
    /* We got success and expect data */
    if (used == 0) {
        qeo_log_e("illegal size of payload");
        goto error;
    }

    /* Decrypt the inner PKCS#7 */
    recipientcert = s->signercert;
    recipientkey = s->signerkey;

    if (ctx->verbose){
        qeo_log_i("reading inner PKCS#7");
    }
    p7enc = d2i_PKCS7_bio(outbio, NULL );
    if (p7enc == NULL ) {
        qeo_log_e("cannot read inner PKCS#7");
        goto error;
    }
    BIO_free(outbio);/* No longer need it */
    outbio = NULL;
    if (ctx->debug) {
        qeo_log_i("printing PEM fomatted PKCS#7");
        PEM_write_PKCS7(stdout, p7enc);
    }

    /* Decrypt the data  */

    outbio = BIO_new(BIO_s_mem());
    if (ctx->verbose){
        qeo_log_i("decrypting inner PKCS#7");
    }
    if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) {
        qeo_log_e("error decrypting inner PKCS#7");
        goto error;
    }
    (void)BIO_flush(outbio);

    /* Write decrypted data */
    PKCS7_free(s->reply_p7);
    s->reply_p7 = d2i_PKCS7_bio(outbio, NULL );
    ret = 0;
error:
    free(p);
    BIO_free(outbio);
    BIO_free_all(pkcs7bio);
    BIO_free(memorybio);
    PKCS7_free(p7enc);
    return ret;
}
Пример #8
0
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);
}
Пример #9
0
/*
 * Unwrap PKCS#7 data and decrypt if necessary
 */
int pkcs7_unwrap(struct scep *s) {
	BIO				*memorybio;
	BIO				*outbio;
	BIO				*pkcs7bio;
	int				i, len, bytes, used;
	STACK_OF(PKCS7_SIGNER_INFO)	*sk;
	PKCS7				*p7enc;
	PKCS7_SIGNER_INFO		*si;
	STACK_OF(X509_ATTRIBUTE)	*attribs;
	char				*p;
	unsigned char			buffer[1024];
	X509				*recipientcert;
	EVP_PKEY			*recipientkey;

	/* Create new memory BIO for outer PKCS#7 */
	memorybio = BIO_new(BIO_s_mem());

	/* Read in data */
	if (v_flag)
		printf("%s: reading outer PKCS#7\n",pname);
	if ((len = BIO_write(memorybio, s->reply_payload, s->reply_len)) <= 0) {
		fprintf(stderr, "%s: error reading PKCS#7 data\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	if (v_flag)
		printf("%s: PKCS#7 payload size: %d bytes\n", pname, len);
	BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY); 
	s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL);
	if (d_flag) {
		printf("%s: printing PEM fomatted PKCS#7\n", pname);
		PEM_write_PKCS7(stdout, s->reply_p7);
	}

	 /* Make sure this is a signed PKCS#7 */
        if (!PKCS7_type_is_signed(s->reply_p7)) {
		fprintf(stderr, "%s: PKCS#7 is not signed!\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
        }

	/* Create BIO for content data */
	pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL);
	if (pkcs7bio == NULL) {
		fprintf(stderr, "%s: cannot get PKCS#7 data\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}

	/* Copy enveloped data from PKCS#7 */
	outbio = BIO_new(BIO_s_mem());
	used = 0;
	for (;;) {
		bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer));
		used += bytes;
		if (bytes <= 0) break;
		BIO_write(outbio, buffer, bytes);
	}
	BIO_flush(outbio);
	if (v_flag)
		printf("%s: PKCS#7 contains %d bytes of enveloped data\n",
			pname, used);

	/* Get signer */
	sk = PKCS7_get_signer_info(s->reply_p7);
	if (sk == NULL) {
		fprintf(stderr, "%s: cannot get signer info!\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}

	/* Verify signature */
	if (v_flag)
		printf("%s: verifying signature\n", pname);
	si = sk_PKCS7_SIGNER_INFO_value(sk, 0);
	if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, cacert) <= 0) {
		fprintf(stderr, "%s: error verifying signature\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	if (v_flag)
		printf("%s: signature ok\n", pname);

	/* Get signed attributes */
	if (v_flag)
		printf("%s: finding signed attributes\n", pname);
	attribs = PKCS7_get_signed_attributes(si);
	if (attribs == NULL) {
		fprintf(stderr, "%s: no attributes found\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}

	/* Transaction id */
	if ((get_signed_attribute(attribs, nid_transId,
			V_ASN1_PRINTABLESTRING, &p)) == 1) {
		fprintf(stderr, "%s: cannot find transId\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}
	if (v_flag)
		printf("%s: reply transaction id: %s\n", pname, p);
	if (strncmp(s->transaction_id, p, strlen(p))) {
		fprintf(stderr, "%s: transaction id mismatch\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}
	/* Message type, should be of type CertRep */
	if ((i = get_signed_attribute(attribs, nid_messageType,
			V_ASN1_PRINTABLESTRING, &p)) == 1) {
		fprintf(stderr, "%s: cannot find messageType\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}
	if (atoi(p) != 3) {
		fprintf(stderr, "%s: wrong message type in reply\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}
	if (v_flag)
		printf("%s: reply message type is good\n", pname);

	/* Sender and recipient nonces: */
	if ((i = get_signed_attribute(attribs, nid_senderNonce,
			V_ASN1_OCTET_STRING, &p)) == 1) {
		if (v_flag)
			fprintf(stderr, "%s: cannot find senderNonce\n", pname);
		/* Some implementations don't put in on reply */
		/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
		exit (SCEP_PKISTATUS_P7); */
	}
	s->reply_sender_nonce = p;
	if (v_flag) {
		printf("%s: senderNonce in reply: ", pname);
		for (i = 0; i < 16; i++) {
			printf("%02X", s->reply_sender_nonce[i]);
		}
		printf("\n");
	}
	if (( i = get_signed_attribute(attribs, nid_recipientNonce,
			V_ASN1_OCTET_STRING, &p)) == 1) {
		fprintf(stderr, "%s: cannot find recipientNonce\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}
	s->reply_recipient_nonce = p;
	if (v_flag) {
		printf("%s: recipientNonce in reply: ", pname);
		for (i = 0; i < 16; i++) {
			printf("%02X", s->reply_recipient_nonce[i]);
		}
		printf("\n");
	}
	/*
	 * Compare recipient nonce to original sender nonce 
	 * The draft says nothing about this, but it makes sense to me..
	 * XXXXXXXXXXXXXX check
	 */
	for (i = 0; i < 16; i++) {
		if (s->sender_nonce[i] != s->reply_recipient_nonce[i]) {
			if (v_flag)
				fprintf(stderr, "%s: corrupted nonce "
					"received\n", pname);
			/* Instead of exit, break out */
			break;
		}
	}
	/* Get pkiStatus */
	if ((i = get_signed_attribute(attribs, nid_pkiStatus,
			V_ASN1_PRINTABLESTRING, &p)) == 1) {
		fprintf(stderr, "%s: cannot find pkiStatus\n", pname);
		/* This is a mandatory attribute.. */
		exit (SCEP_PKISTATUS_P7);
	}
	switch (atoi(p)) {
		case SCEP_PKISTATUS_SUCCESS:
			printf("%s: pkistatus: SUCCESS\n",pname);
			s->pki_status = SCEP_PKISTATUS_SUCCESS;
			break;
		case SCEP_PKISTATUS_FAILURE:
			printf("%s: pkistatus: FAILURE\n",pname);
			s->pki_status = SCEP_PKISTATUS_FAILURE;
			break;
		case SCEP_PKISTATUS_PENDING:
			printf("%s: pkistatus: PENDING\n",pname);
			s->pki_status = SCEP_PKISTATUS_PENDING;
			break;
		default:
			fprintf(stderr, "%s: wrong pkistatus in reply\n",pname);
			exit (SCEP_PKISTATUS_P7);
	}

	/* Get failInfo */
	if (s->pki_status == SCEP_PKISTATUS_FAILURE) {
		if ((i = get_signed_attribute(attribs, nid_failInfo,
			V_ASN1_PRINTABLESTRING, &p)) == 1) {
				fprintf(stderr, "%s: cannot find failInfo\n",
						pname);
				exit (SCEP_PKISTATUS_P7);
		}
		switch (atoi(p)) {
			case SCEP_FAILINFO_BADALG:
				s->fail_info = SCEP_FAILINFO_BADALG;
				printf("%s: reason: %s\n", pname,
					SCEP_FAILINFO_BADALG_STR);
				break;
			case SCEP_FAILINFO_BADMSGCHK:
				s->fail_info = SCEP_FAILINFO_BADMSGCHK;
				printf("%s: reason: %s\n", pname,
					SCEP_FAILINFO_BADMSGCHK_STR);
				break;
			case SCEP_FAILINFO_BADREQ:
				s->fail_info = SCEP_FAILINFO_BADREQ;
				printf("%s: reason: %s\n", pname,
					SCEP_FAILINFO_BADREQ_STR);
				break;
			case SCEP_FAILINFO_BADTIME:
				s->fail_info = SCEP_FAILINFO_BADTIME;
				printf("%s: reason: %s\n", pname,
					SCEP_FAILINFO_BADTIME_STR);
				break;
			case SCEP_FAILINFO_BADCERTID:		
				s->fail_info = SCEP_FAILINFO_BADCERTID;
				printf("%s: reason: %s\n", pname,
					SCEP_FAILINFO_BADCERTID_STR);
				break;
			default:
				fprintf(stderr, "%s: wrong failInfo in "							"reply\n",pname);
				exit (SCEP_PKISTATUS_P7);
		}
	}
	/* If FAILURE or PENDING, we can return */
	if (s->pki_status != SCEP_PKISTATUS_SUCCESS) {
		/* There shouldn't be any more data... */
		if (v_flag && (used != 0)) {
			fprintf(stderr, "%s: illegal size of payload\n", pname);
		}
		return (0);
	}
	/* We got success and expect data */
	if (used == 0) {
		fprintf(stderr, "%s: illegal size of payload\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}

	/* Decrypt the inner PKCS#7 */
	if ((s->request_type == SCEP_REQUEST_PKCSREQ) ||
	    (s->request_type == SCEP_REQUEST_GETCERTINIT)) {
		recipientcert = s->signercert;
		recipientkey = s->signerkey;
	}
	else {
		recipientcert = localcert;
		recipientkey = rsa;
	}
	if (v_flag)
		printf("%s: reading inner PKCS#7\n",pname);
	p7enc = d2i_PKCS7_bio(outbio, NULL);
	if (p7enc == NULL) {
		fprintf(stderr, "%s: cannot read inner PKCS#7\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	if (d_flag) {
		printf("%s: printing PEM fomatted PKCS#7\n", pname);
		PEM_write_PKCS7(stdout, p7enc);
	}

	/* Decrypt the data  */
	outbio = BIO_new(BIO_s_mem());
	if (v_flag)
		printf("%s: decrypting inner PKCS#7\n",pname);
	if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) {
		fprintf(stderr, "%s: error decrypting inner PKCS#7\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	BIO_flush(outbio);

	/* Write decrypted data */
	s->reply_len = BIO_get_mem_data(outbio, &s->reply_payload);
	if (v_flag)
		printf("%s: PKCS#7 payload size: %d bytes\n", pname,
			s->reply_len);
	BIO_set_flags(outbio, BIO_FLAGS_MEM_RDONLY); 
	s->reply_p7 = d2i_PKCS7_bio(outbio, NULL);

	return (0);

}
Пример #10
0
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;
}