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; }
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; }
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; }
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); }
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); }
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; }
/* 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); }
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; }
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); }
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); }
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; }
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); }