int BIO_ssl_copy_session_id(BIO *t, BIO *f) { t=BIO_find_type(t,BIO_TYPE_SSL); f=BIO_find_type(f,BIO_TYPE_SSL); if ((t == NULL) || (f == NULL)) return(0); if ( (((BIO_SSL *)t->ptr)->ssl == NULL) || (((BIO_SSL *)f->ptr)->ssl == NULL)) return(0); SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl,((BIO_SSL *)f->ptr)->ssl); return(1); }
int BIO_ssl_copy_session_id(BIO *t, BIO *f) { BIO_SSL *tdata, *fdata; t = BIO_find_type(t, BIO_TYPE_SSL); f = BIO_find_type(f, BIO_TYPE_SSL); if ((t == NULL) || (f == NULL)) return 0; tdata = BIO_get_data(t); fdata = BIO_get_data(f); if ((tdata->ssl == NULL) || (fdata->ssl == NULL)) return 0; if (!SSL_copy_session_id(tdata->ssl, (fdata->ssl))) return 0; return 1; }
int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, X509_ALGOR *mdalg) { int nid; ASN1_OBJECT *mdoid; X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); nid = OBJ_obj2nid(mdoid); /* Look for digest type to match signature */ for (;;) { EVP_MD_CTX *mtmp; chain = BIO_find_type(chain, BIO_TYPE_MD); if (chain == NULL) { CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, CMS_R_NO_MATCHING_DIGEST); return 0; } BIO_get_md_ctx(chain, &mtmp); if (EVP_MD_CTX_type(mtmp) == nid /* * Workaround for broken implementations that use signature * algorithm OID instead of digest. */ || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) return EVP_MD_CTX_copy_ex(mctx, mtmp); chain = BIO_next(chain); } }
int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) { ASN1_OCTET_STRING **pos = CMS_get0_content(cms); if (!pos) return 0; /* If ebmedded content find memory BIO and set content */ if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) { BIO *mbio; unsigned char *cont; long contlen; mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); if (!mbio) { CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND); return 0; } contlen = BIO_get_mem_data(mbio, &cont); /* Set bio as read only so its content can't be clobbered */ BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); BIO_set_mem_eof_return(mbio, 0); ASN1_STRING_set0(*pos, cont, contlen); (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; } switch (OBJ_obj2nid(cms->contentType)) { case NID_pkcs7_data: case NID_pkcs7_enveloped: case NID_pkcs7_encrypted: case NID_id_smime_ct_compressedData: /* Nothing to do */ return 1; case NID_pkcs7_signed: return cms_SignedData_final(cms, cmsbio); case NID_pkcs7_digest: return cms_DigestedData_do_final(cms, cmsbio, 0); default: CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE); return 0; } }
static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) { for (;;) { bio = BIO_find_type(bio, BIO_TYPE_MD); if (bio == NULL) { PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); return NULL; } BIO_get_md_ctx(bio, pmd); if (*pmd == NULL) { PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, ERR_R_INTERNAL_ERROR); return NULL; } if (EVP_MD_CTX_type(*pmd) == nid) return bio; bio = BIO_next(bio); } return NULL; }
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_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, X509 *x509) { ASN1_OCTET_STRING *os; EVP_MD_CTX mdc_tmp, *mdc; int ret = 0, i; int md_type; STACK_OF(X509_ATTRIBUTE) *sk; BIO *btmp; EVP_PKEY *pkey; EVP_MD_CTX_init(&mdc_tmp); if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); goto err; } md_type = OBJ_obj2nid(si->digest_alg->algorithm); btmp = bio; for (;;) { if ((btmp == NULL) || ((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } BIO_get_md_ctx(btmp, &mdc); if (mdc == NULL) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_INTERNAL_ERROR); goto err; } if (EVP_MD_CTX_type(mdc) == md_type) break; /* * Workaround for some broken clients that put the signature OID * instead of the digest OID in digest_alg->algorithm */ if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) break; btmp = BIO_next(btmp); } /* * mdc is the digest ctx that we want, unless there are attributes, in * which case the digest is the signed attributes */ if (!EVP_MD_CTX_copy_ex(&mdc_tmp, mdc)) goto err; sk = si->auth_attr; if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; unsigned int md_len; int alen; ASN1_OCTET_STRING *message_digest; if (!EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len)) goto err; message_digest = PKCS7_digest_from_attributes(sk); if (!message_digest) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } if ((message_digest->length != (int)md_len) || (memcmp(message_digest->data, md_dat, md_len))) { #if 0 { int ii; for (ii = 0; ii < message_digest->length; ii++) printf("%02X", message_digest->data[ii]); printf(" sent\n"); for (ii = 0; ii < md_len; ii++) printf("%02X", md_dat[ii]); printf(" calc\n"); } #endif PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); ret = -1; goto err; } if (!EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL)) goto err; alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); if (alen <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_ASN1_LIB); ret = -1; goto err; } if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen)) goto err; OPENSSL_free(abuf); } os = si->enc_digest; pkey = X509_get_pubkey(x509); if (!pkey) { ret = -1; goto err; } i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); EVP_PKEY_free(pkey); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); ret = -1; goto err; } else ret = 1; err: EVP_MD_CTX_cleanup(&mdc_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); }
int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, X509 *x509) { ASN1_OCTET_STRING *os; EVP_MD_CTX mdc_tmp,*mdc; unsigned char *pp,*p; int ret=0,i; int md_type; STACK_OF(X509_ATTRIBUTE) *sk; BIO *btmp; EVP_PKEY *pkey; if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); goto err; } md_type=OBJ_obj2nid(si->digest_alg->algorithm); btmp=bio; for (;;) { if ((btmp == NULL) || ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } BIO_get_md_ctx(btmp,&mdc); if (mdc == NULL) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_INTERNAL_ERROR); goto err; } if (EVP_MD_CTX_type(mdc) == md_type) break; btmp=BIO_next(btmp); } /* mdc is the digest ctx that we want, unless there are attributes, * in which case the digest is the signed attributes */ memcpy(&mdc_tmp,mdc,sizeof(mdc_tmp)); sk=si->auth_attr; if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_dat[EVP_MAX_MD_SIZE]; unsigned int md_len; ASN1_OCTET_STRING *message_digest; EVP_DigestFinal(&mdc_tmp,md_dat,&md_len); message_digest=PKCS7_digest_from_attributes(sk); if (!message_digest) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } if ((message_digest->length != (int)md_len) || (memcmp(message_digest->data,md_dat,md_len))) { #if 0 { int ii; for (ii=0; ii<message_digest->length; ii++) printf("%02X",message_digest->data[ii]); printf(" sent\n"); for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n"); } #endif PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); ret= -1; goto err; } EVP_VerifyInit(&mdc_tmp,EVP_get_digestbynid(md_type)); /* Note: when forming the encoding of the attributes we * shouldn't reorder them or this will break the signature. * This is done by using the IS_SEQUENCE flag. */ i=i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,NULL,i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE); pp=OPENSSL_malloc(i); p=pp; i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,&p,i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE); EVP_VerifyUpdate(&mdc_tmp,pp,i); OPENSSL_free(pp); } os=si->enc_digest; pkey = X509_get_pubkey(x509); if (!pkey) { ret = -1; goto err; } #ifndef NO_DSA if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1(); #endif i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey); EVP_PKEY_free(pkey); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); ret= -1; goto err; } else ret=1; err: return(ret); }
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); }