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 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; }
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; }