+ }
+
+/* int */
+BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio,
+ X509_STORE *xs)
+ {
+ int i,j;
+ BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
+ char *tmp=NULL;
+ X509_ALGOR *xa;
+ ASN1_OCTET_STRING *data_body=NULL;
+ const EVP_MD *evp_md;
+ const EVP_CIPHER *evp_cipher=NULL;
+ EVP_CIPHER_CTX *evp_ctx=NULL;
+ X509_ALGOR *enc_alg=NULL;
+ STACK *md_sk=NULL,*rsk=NULL;
+ X509_ALGOR *xalg=NULL;
+ PKCS7_RECIP_INFO *ri=NULL;
+/* EVP_PKEY *pkey; */
+#if 0
+ X509_STORE_CTX s_ctx;
+#endif
+
+ i=OBJ_obj2nid(p7->type);
+ p7->state=PKCS7_S_HEADER;
+
+ switch (i)
+ {
+ case NID_pkcs7_signed:
+ data_body=p7->d.sign->contents->d.data;
+ md_sk=p7->d.sign->md_algs;
+ break;
+ case NID_pkcs7_signedAndEnveloped:
+ rsk=p7->d.signed_and_enveloped->recipientinfo;
+ md_sk=p7->d.signed_and_enveloped->md_algs;
+ data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
+ enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
+ evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm)));
+ if (evp_cipher == NULL)
+ {
+ PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
+ goto err;
+ }
+ xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
+ break;
+ case NID_pkcs7_enveloped:
+ rsk=p7->d.enveloped->recipientinfo;
+ enc_alg=p7->d.enveloped->enc_data->algorithm;
+ data_body=p7->d.enveloped->enc_data->enc_data;
+ evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm)));
+ if (evp_cipher == NULL)
+ {
+ PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
+ goto err;
+ }
+ xalg=p7->d.enveloped->enc_data->algorithm;
+ break;
+ default:
+ PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
+ goto err;
+ }
+
+ /* We will be checking the signature */
+ if (md_sk != NULL)
+ {
+ for (i=0; i<sk_num(md_sk); i++)
+ {
+ xa=(X509_ALGOR *)sk_value(md_sk,i);
+ if ((btmp=BIO_new(BIO_f_md())) == NULL)
+ {
+ PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_BIO_LIB);
+ goto err;
+ }
+
+ j=OBJ_obj2nid(xa->algorithm);
+ evp_md=EVP_get_digestbyname(OBJ_nid2sn(j));
+ if (evp_md == NULL)
+ {
+ PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNKNOWN_DIGEST_TYPE);
+ goto err;
+ }
+
+ BIO_set_md(btmp,evp_md);
+ if (out == NULL)
+ out=btmp;
+ else
+ BIO_push(out,btmp);
+ btmp=NULL;
+ }
+ }
+
+ if (evp_cipher != NULL)
+ {
+#if 0
+ unsigned char key[EVP_MAX_KEY_LENGTH];
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+ unsigned char *p;
+ int keylen,ivlen;
+ int max;
+ X509_OBJECT ret;
+#endif
+ int jj;
+
+ if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
+ {
+ PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_BIO_LIB);
+ goto err;
+ }
+
+ /* It was encrypted, we need to decrypt the secret key
+ * with the private key */
+
+ /* We need to find a private key for one of the people in the
+ * recipentinfo list */
+ if (rsk == NULL)
+ return(NULL);
+
+ /* FIXME: this assumes that the passed private key
+ * corresponds to the first RecipientInfo. This in
+ * general is not true
+ */
+
+ ri=(PKCS7_RECIP_INFO *)sk_value(rsk,0);
+#if 0
+ X509_STORE_CTX_init(&s_ctx,xs,NULL,NULL);
+ for (i=0; i<sk_num(rsk); i++)
+ {
+ ri=(PKCS7_RECIP_INFO *)sk_value(rsk,i);
+ uf (X509_STORE_get_by_issuer_serial(&s_ctx,
+ X509_LU_PKEY,
+ ri->issuer_and_serial->issuer,
+ ri->issuer_and_serial->serial,
+ &ret))
+ break;
+ ri=NULL;
+ }
+ if (ri == NULL) return(NULL);
+ pkey=ret.data.pkey;
+#endif
+ if (pkey == NULL)
+ {
+ return(NULL);
+ }
+
+ jj=EVP_PKEY_size(pkey);
+ tmp=Malloc(jj+10);
+ if (tmp == NULL)
+ {
+ PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ jj=EVP_PKEY_decrypt((unsigned char *)tmp,
+ ASN1_STRING_data(ri->enc_key),
+ ASN1_STRING_length(ri->enc_key),
+ pkey);
+ if (jj <= 0)
+ {
+ PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ evp_ctx=NULL;
+ BIO_get_cipher_ctx(etmp,&evp_ctx);
+ EVP_CipherInit(evp_ctx,evp_cipher,NULL,NULL,0);
+ if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
+ return(NULL);
+
+ if (jj != EVP_CIPHER_CTX_key_length(evp_ctx))
+ {
+ PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
+ goto err;
+ }
+ EVP_CipherInit(evp_ctx,NULL,(unsigned char *)tmp,NULL,0);
+
+ memset(tmp,0,jj);
+
+ if (out == NULL)
+ out=etmp;
+ else
+ BIO_push(out,etmp);
+ etmp=NULL;
+ }
+
+#if 1
+ if (p7->detached || (in_bio != NULL))
+ {
+ bio=in_bio;
+ }
+ else
+ {
+ bio=BIO_new(BIO_s_mem());
+ /* We need to set this so that when we have read all
+ * the data, the encrypt BIO, if present, will read
+ * EOF and encode the last few bytes */
+ BIO_set_mem_eof_return(bio,0);
+
+ if (data_body->length > 0)
+ BIO_write(bio,(char *)data_body->data,data_body->length);
+ }
+ BIO_push(out,bio);
+ bio=NULL;
+#endif
+ if (0)
+ {