1c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* crypto/pkcs7/pk7_doit.c */
2c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * All rights reserved.
4c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
5c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * This package is an SSL implementation written
6c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * by Eric Young (eay@cryptsoft.com).
7c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * The implementation was written so as to conform with Netscapes SSL.
8c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
9c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * This library is free for commercial and non-commercial use as long as
10c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * the following conditions are aheared to.  The following conditions
11c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * apply to all code found in this distribution, be it the RC4, RSA,
12c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * included with this distribution is covered by the same copyright terms
14c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
16c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Copyright remains Eric Young's, and as such any Copyright notices in
17c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * the code are not to be removed.
18c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * If this package is used in a product, Eric Young should be given attribution
19c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * as the author of the parts of the library used.
20c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * This can be in the form of a textual message at program startup or
21c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * in documentation (online or textual) provided with the package.
22c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
23c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Redistribution and use in source and binary forms, with or without
24c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * modification, are permitted provided that the following conditions
25c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * are met:
26c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 1. Redistributions of source code must retain the copyright
27c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    notice, this list of conditions and the following disclaimer.
28c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
29c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    notice, this list of conditions and the following disclaimer in the
30c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    documentation and/or other materials provided with the distribution.
31c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 3. All advertising materials mentioning features or use of this software
32c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    must display the following acknowledgement:
33c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    "This product includes cryptographic software written by
34c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *     Eric Young (eay@cryptsoft.com)"
35c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    The word 'cryptographic' can be left out if the rouines from the library
36c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    being used are not cryptographic related :-).
37c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 4. If you include any Windows specific code (or a derivative thereof) from
38c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    the apps directory (application code) you must include an acknowledgement:
39c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
41c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * SUCH DAMAGE.
52c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
53c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * The licence and distribution terms for any publically available version or
54c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * derivative of this code cannot be changed.  i.e. this code cannot simply be
55c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * copied and put under another distribution licence
56c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * [including the GNU Public Licence.]
57c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
58c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
59c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <stdio.h>
60c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include "cryptlib.h"
61c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <openssl/rand.h>
62c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <openssl/objects.h>
63c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <openssl/x509.h>
64c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <openssl/x509v3.h>
65c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <openssl/err.h>
66c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
67c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
68c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 void *value);
69c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
70c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
71c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int PKCS7_type_is_other(PKCS7* p7)
72c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
73c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int isOther=1;
74c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
75c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int nid=OBJ_obj2nid(p7->type);
76c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
77c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	switch( nid )
78c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
79c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_data:
80c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_signed:
81c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_enveloped:
82c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_signedAndEnveloped:
83c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_digest:
84c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_encrypted:
85c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		isOther=0;
86c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
87c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	default:
88c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		isOther=1;
89c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
90c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
91c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return isOther;
92c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
93c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
94c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
95c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
96c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
97c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if ( PKCS7_type_is_data(p7))
98c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return p7->d.data;
99c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if ( PKCS7_type_is_other(p7) && p7->d.other
100c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		&& (p7->d.other->type == V_ASN1_OCTET_STRING))
101c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return p7->d.other->value.octet_string;
102c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return NULL;
103c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
104c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
105c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
106c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
107c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO *btmp;
108c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	const EVP_MD *md;
109c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if ((btmp=BIO_new(BIO_f_md())) == NULL)
110c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
111c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
112c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
113c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
114c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
115c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	md=EVP_get_digestbyobj(alg->algorithm);
116c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (md == NULL)
117c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
118c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,PKCS7_R_UNKNOWN_DIGEST_TYPE);
119c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
120c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
121c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
122c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_set_md(btmp,md);
123c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (*pbio == NULL)
124c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		*pbio=btmp;
125c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else if (!BIO_push(*pbio,btmp))
126c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
127c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
128c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
129c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
130c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	btmp=NULL;
131c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
132c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
133c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
134c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	err:
135c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (btmp)
136c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_free(btmp);
137c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 0;
138c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
139c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
140c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
141480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri,
142480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					unsigned char *key, int keylen)
143480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
144480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY_CTX *pctx = NULL;
145480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY *pkey = NULL;
146480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	unsigned char *ek = NULL;
147480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int ret = 0;
148480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	size_t eklen;
149480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
150480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey = X509_get_pubkey(ri->cert);
151480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
152480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!pkey)
153480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
154480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
155480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pctx = EVP_PKEY_CTX_new(pkey, NULL);
156480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!pctx)
157480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
158480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
159480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_PKEY_encrypt_init(pctx) <= 0)
160480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
161480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
162480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
163480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri) <= 0)
164480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
165480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, PKCS7_R_CTRL_ERROR);
166480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
167480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
168480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
169480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0)
170480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
171480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
172480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ek = OPENSSL_malloc(eklen);
173480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
174480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ek == NULL)
175480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
176480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, ERR_R_MALLOC_FAILURE);
177480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
178480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
179480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
180480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0)
181480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
182480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
183480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ASN1_STRING_set0(ri->enc_key, ek, eklen);
184480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ek = NULL;
185480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
186480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ret = 1;
187480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
188480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	err:
189480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (pkey)
190480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		EVP_PKEY_free(pkey);
191480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (pctx)
192480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		EVP_PKEY_CTX_free(pctx);
193480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ek)
194480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		OPENSSL_free(ek);
195480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return ret;
196480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
197480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
198480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
199480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
200480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
201480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			       PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey)
202480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
203480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY_CTX *pctx = NULL;
204480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	unsigned char *ek = NULL;
205480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	size_t eklen;
206480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
2072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int ret = -1;
208480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
209480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pctx = EVP_PKEY_CTX_new(pkey, NULL);
210480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!pctx)
2112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return -1;
212480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
213480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_PKEY_decrypt_init(pctx) <= 0)
214480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
215480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
216480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT,
217480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0)
218480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
219480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR);
220480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
221480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
222480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
223480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
224480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				ri->enc_key->data, ri->enc_key->length) <= 0)
225480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
226480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
227480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ek = OPENSSL_malloc(eklen);
228480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
229480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ek == NULL)
230480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
231480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE);
232480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
233480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
234480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
235480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_PKEY_decrypt(pctx, ek, &eklen,
236480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				ri->enc_key->data, ri->enc_key->length) <= 0)
237480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
2382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = 0;
239480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB);
240480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
241480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
242480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
243480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ret = 1;
244480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
2452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (*pek)
2462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
2472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		OPENSSL_cleanse(*pek, *peklen);
2482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		OPENSSL_free(*pek);
2492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
2502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
251480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	*pek = ek;
252480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	*peklen = eklen;
253480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
254480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	err:
255480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (pctx)
256480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		EVP_PKEY_CTX_free(pctx);
257480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!ret && ek)
258480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		OPENSSL_free(ek);
259480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
260480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return ret;
261480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
262480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
263c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgBIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
264c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
265c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i;
266c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO *out=NULL,*btmp=NULL;
267c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_ALGOR *xa = NULL;
268c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	const EVP_CIPHER *evp_cipher=NULL;
269c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(X509_ALGOR) *md_sk=NULL;
270c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
271c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_ALGOR *xalg=NULL;
272c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	PKCS7_RECIP_INFO *ri=NULL;
273c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ASN1_OCTET_STRING *os=NULL;
274c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
275c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	i=OBJ_obj2nid(p7->type);
276c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	p7->state=PKCS7_S_HEADER;
277c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
278c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	switch (i)
279c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
280c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_signed:
281c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		md_sk=p7->d.sign->md_algs;
282c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		os = PKCS7_get_octet_string(p7->d.sign->contents);
283c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
284c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_signedAndEnveloped:
285c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		rsk=p7->d.signed_and_enveloped->recipientinfo;
286c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		md_sk=p7->d.signed_and_enveloped->md_algs;
287c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
288c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
289c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (evp_cipher == NULL)
290c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
291c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
292c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						PKCS7_R_CIPHER_NOT_INITIALIZED);
293c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
294c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
295c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
296c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_enveloped:
297c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		rsk=p7->d.enveloped->recipientinfo;
298c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		xalg=p7->d.enveloped->enc_data->algorithm;
299c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		evp_cipher=p7->d.enveloped->enc_data->cipher;
300c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (evp_cipher == NULL)
301c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
302c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
303c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						PKCS7_R_CIPHER_NOT_INITIALIZED);
304c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
305c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
306c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
307c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_digest:
308c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		xa = p7->d.digest->md;
309c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		os = PKCS7_get_octet_string(p7->d.digest->contents);
310c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
311480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	case NID_pkcs7_data:
312480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
313c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	default:
314c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
315c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	        goto err;
316c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
317c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
318c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
319c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
320c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
321c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
322c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (xa && !PKCS7_bio_add_digest(&out, xa))
323c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
324c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
325c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (evp_cipher != NULL)
326c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
327c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		unsigned char key[EVP_MAX_KEY_LENGTH];
328c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		unsigned char iv[EVP_MAX_IV_LENGTH];
329c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		int keylen,ivlen;
330c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		EVP_CIPHER_CTX *ctx;
331c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
332c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
333c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
334c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
335c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
336c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
337c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_get_cipher_ctx(btmp, &ctx);
338c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		keylen=EVP_CIPHER_key_length(evp_cipher);
339c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ivlen=EVP_CIPHER_iv_length(evp_cipher);
340c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
341c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (ivlen > 0)
342c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (RAND_pseudo_bytes(iv,ivlen) <= 0)
343c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto err;
344c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
345c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
346c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
347c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
348c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
349c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
350c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
351c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (ivlen > 0) {
352c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (xalg->parameter == NULL) {
353c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				xalg->parameter = ASN1_TYPE_new();
354c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (xalg->parameter == NULL)
355c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					goto err;
356c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
357c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
358480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				goto err;
359c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
360c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
361c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Lets do the pub key stuff :-) */
362c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
363c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
364c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
365480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (pkcs7_encode_rinfo(ri, key, keylen) <= 0)
366c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto err;
367c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
368c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		OPENSSL_cleanse(key, keylen);
369c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
370c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (out == NULL)
371c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			out=btmp;
372c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
373c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_push(out,btmp);
374c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		btmp=NULL;
375c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
376c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
377c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (bio == NULL)
378c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
379c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (PKCS7_is_detached(p7))
380c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			bio=BIO_new(BIO_s_null());
381c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else if (os && os->length > 0)
382c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			bio = BIO_new_mem_buf(os->data, os->length);
383c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if(bio == NULL)
384c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
385c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			bio=BIO_new(BIO_s_mem());
386c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (bio == NULL)
387c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto err;
388c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_set_mem_eof_return(bio,0);
389c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
390c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
391480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (out)
392480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_push(out,bio);
393480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
394480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		out = bio;
395c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bio=NULL;
396c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (0)
397c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
398c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgerr:
399c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (out != NULL)
400c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_free_all(out);
401c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (btmp != NULL)
402c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_free_all(btmp);
403c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		out=NULL;
404c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
405c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(out);
406c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
407c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
408c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
409c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
410c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret;
411c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
412c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				pcert->cert_info->issuer);
413c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (ret)
414c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return ret;
415c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
416c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					ri->issuer_and_serial->serial);
417c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
418c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
419c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* int */
420c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgBIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
421c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
422c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i,j;
423c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
424c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_ALGOR *xa;
425c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ASN1_OCTET_STRING *data_body=NULL;
426c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	const EVP_MD *evp_md;
427c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	const EVP_CIPHER *evp_cipher=NULL;
428c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	EVP_CIPHER_CTX *evp_ctx=NULL;
429c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_ALGOR *enc_alg=NULL;
430c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(X509_ALGOR) *md_sk=NULL;
431c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
432c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	PKCS7_RECIP_INFO *ri=NULL;
4332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org       unsigned char *ek = NULL, *tkey = NULL;
4342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org       int eklen = 0, tkeylen = 0;
435c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
436c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	i=OBJ_obj2nid(p7->type);
437c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	p7->state=PKCS7_S_HEADER;
438c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
439c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	switch (i)
440c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
441c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_signed:
442c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
443c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		md_sk=p7->d.sign->md_algs;
444c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
445c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_signedAndEnveloped:
446c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		rsk=p7->d.signed_and_enveloped->recipientinfo;
447c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		md_sk=p7->d.signed_and_enveloped->md_algs;
448c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
449c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
450c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
451c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (evp_cipher == NULL)
452c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
453c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
454c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
455c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
456c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
457c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_enveloped:
458c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		rsk=p7->d.enveloped->recipientinfo;
459c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		enc_alg=p7->d.enveloped->enc_data->algorithm;
460c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		data_body=p7->d.enveloped->enc_data->enc_data;
461c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
462c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (evp_cipher == NULL)
463c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
464c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
465c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
466c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
467c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
468c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	default:
469c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
470c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	        goto err;
471c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
472c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
473c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* We will be checking the signature */
474c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (md_sk != NULL)
475c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
476c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
477c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
478c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			xa=sk_X509_ALGOR_value(md_sk,i);
479c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ((btmp=BIO_new(BIO_f_md())) == NULL)
480c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
481c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
482c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto err;
483c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
484c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
485c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			j=OBJ_obj2nid(xa->algorithm);
486c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			evp_md=EVP_get_digestbynid(j);
487c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (evp_md == NULL)
488c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
489c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
490c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto err;
491c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
492c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
493c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_set_md(btmp,evp_md);
494c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (out == NULL)
495c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				out=btmp;
496c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else
497c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIO_push(out,btmp);
498c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			btmp=NULL;
499c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
500c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
501c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
502c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (evp_cipher != NULL)
503c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
504c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if 0
505c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		unsigned char key[EVP_MAX_KEY_LENGTH];
506c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		unsigned char iv[EVP_MAX_IV_LENGTH];
507c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		unsigned char *p;
508c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		int keylen,ivlen;
509c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		int max;
510c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		X509_OBJECT ret;
511c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
512c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
513c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
514c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
515c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
516c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
517c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
518c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
519c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* It was encrypted, we need to decrypt the secret key
520c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * with the private key */
521c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
522c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Find the recipientInfo which matches the passed certificate
523c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * (if any)
524c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 */
525c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
526480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (pcert)
527480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
528480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
529480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
530c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
531c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (!pkcs7_cmp_ri(ri, pcert))
532c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					break;
533c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ri=NULL;
534480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
535480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (ri == NULL)
536480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
537c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
538c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				      PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
539c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto err;
540480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
541c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
542c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
543c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* If we haven't got a certificate try each ri in turn */
544c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (pcert == NULL)
545c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
5462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			/* Always attempt to decrypt all rinfo even
5472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 * after sucess as a defence against MMA timing
5482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 * attacks.
5492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 */
550c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
551c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
552c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
5532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
554480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				if (pkcs7_decrypt_rinfo(&ek, &eklen,
5552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org							ri, pkey) < 0)
5562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					goto err;
557c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ERR_clear_error();
558c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
559c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
560c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
561c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
5622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			/* Only exit on fatal errors, not decrypt failure */
5632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0)
564c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto err;
5652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ERR_clear_error();
566c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
567c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
568c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		evp_ctx=NULL;
569c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_get_cipher_ctx(etmp,&evp_ctx);
570c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
571c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
572c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
573c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
5742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Generate random key as MMA defence */
5752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx);
5762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		tkey = OPENSSL_malloc(tkeylen);
5772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (!tkey)
5782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			goto err;
5792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0)
5802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			goto err;
5812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (ek == NULL)
5822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
5832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ek = tkey;
5842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			eklen = tkeylen;
5852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			tkey = NULL;
5862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
587c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
588480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) {
589c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			/* Some S/MIME clients don't use the same key
590c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * and effective key length. The key length is
591c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * determined by the size of the decrypted RSA key.
592c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 */
593480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen))
594c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
5952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				/* Use random key as MMA defence */
5962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				OPENSSL_cleanse(ek, eklen);
5972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				OPENSSL_free(ek);
5982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				ek = tkey;
5992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				eklen = tkeylen;
6002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				tkey = NULL;
601c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
602c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
6032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Clear errors so we don't leak information useful in MMA */
6042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ERR_clear_error();
605480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,ek,NULL,0) <= 0)
606c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
607c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
608480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (ek)
609480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
610480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			OPENSSL_cleanse(ek,eklen);
611480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			OPENSSL_free(ek);
6122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                       ek = NULL;
6132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
6142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (tkey)
6152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
6162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			OPENSSL_cleanse(tkey,tkeylen);
6172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			OPENSSL_free(tkey);
6182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                       tkey = NULL;
619480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
620c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
621c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (out == NULL)
622c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			out=etmp;
623c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
624c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_push(out,etmp);
625c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		etmp=NULL;
626c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
627c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
628c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if 1
629c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (PKCS7_is_detached(p7) || (in_bio != NULL))
630c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
631c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		bio=in_bio;
632c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
633c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else
634c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
635c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if 0
636c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		bio=BIO_new(BIO_s_mem());
637c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* We need to set this so that when we have read all
638c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * the data, the encrypt BIO, if present, will read
639c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * EOF and encode the last few bytes */
640c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_set_mem_eof_return(bio,0);
641c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
642c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (data_body->length > 0)
643c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_write(bio,(char *)data_body->data,data_body->length);
644c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
645c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (data_body->length > 0)
646c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
647c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else {
648c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			bio=BIO_new(BIO_s_mem());
649c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_set_mem_eof_return(bio,0);
650c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
651c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (bio == NULL)
652c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
653c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
654c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
655c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_push(out,bio);
656c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bio=NULL;
657c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
658c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (0)
659c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
660c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgerr:
6612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org               if (ek)
6622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                       {
6632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                       OPENSSL_cleanse(ek,eklen);
6642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                       OPENSSL_free(ek);
6652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                       }
6662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org               if (tkey)
6672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                       {
6682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                       OPENSSL_cleanse(tkey,tkeylen);
6692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                       OPENSSL_free(tkey);
6702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                       }
671c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (out != NULL) BIO_free_all(out);
672c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (btmp != NULL) BIO_free_all(btmp);
673c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (etmp != NULL) BIO_free_all(etmp);
674c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (bio != NULL) BIO_free_all(bio);
675c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		out=NULL;
676c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
677c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(out);
678c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
679c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
680c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
681c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
682c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (;;)
683c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
684c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		bio=BIO_find_type(bio,BIO_TYPE_MD);
685c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (bio == NULL)
686c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
687c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
688c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return NULL;
689c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
690c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_get_md_ctx(bio,pmd);
691c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (*pmd == NULL)
692c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
693c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,ERR_R_INTERNAL_ERROR);
694c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return NULL;
695c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
696c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (EVP_MD_CTX_type(*pmd) == nid)
697c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return bio;
698c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		bio=BIO_next(bio);
699c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
700c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return NULL;
701c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
702c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
703480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx)
704480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
705480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	unsigned char md_data[EVP_MAX_MD_SIZE];
706480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	unsigned int md_len;
707480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
708480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* Add signing time if not already present */
709480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime))
710480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
711480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!PKCS7_add0_attrib_signing_time(si, NULL))
712480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
713480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB,
714480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					ERR_R_MALLOC_FAILURE);
715480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
716480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
717480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
718480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
719480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* Add digest */
7202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (!EVP_DigestFinal_ex(mctx, md_data,&md_len))
7212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
7222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_EVP_LIB);
7232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return 0;
7242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
725480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!PKCS7_add1_attrib_digest(si, md_data, md_len))
726480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
727480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE);
728480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
729480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
730480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
731480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* Now sign the attributes */
732480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!PKCS7_SIGNER_INFO_sign(si))
733480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
734480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
735480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
736480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
737480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
738480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
739c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgint PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
740c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
741c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret=0;
742c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i,j;
743c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO *btmp;
744c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	PKCS7_SIGNER_INFO *si;
745c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	EVP_MD_CTX *mdc,ctx_tmp;
746c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(X509_ATTRIBUTE) *sk;
747c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
748c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ASN1_OCTET_STRING *os=NULL;
749c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
750c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	EVP_MD_CTX_init(&ctx_tmp);
751c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	i=OBJ_obj2nid(p7->type);
752c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	p7->state=PKCS7_S_HEADER;
753c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
754c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	switch (i)
755c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
756480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	case NID_pkcs7_data:
757480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		os = p7->d.data;
758480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
759c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_signedAndEnveloped:
760c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* XXXXXXXXXXXXXXXX */
761c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		si_sk=p7->d.signed_and_enveloped->signer_info;
762480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		os = p7->d.signed_and_enveloped->enc_data->enc_data;
763480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!os)
764c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
765480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			os=M_ASN1_OCTET_STRING_new();
766480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!os)
767480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
768480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
769480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				goto err;
770480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
771480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			p7->d.signed_and_enveloped->enc_data->enc_data=os;
772c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
773c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
774c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_enveloped:
775c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* XXXXXXXXXXXXXXXX */
776480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		os = p7->d.enveloped->enc_data->enc_data;
777480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!os)
778c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
779480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			os=M_ASN1_OCTET_STRING_new();
780480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!os)
781480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
782480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
783480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				goto err;
784480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
785480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			p7->d.enveloped->enc_data->enc_data=os;
786c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
787c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
788c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_signed:
789c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		si_sk=p7->d.sign->signer_info;
790c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		os=PKCS7_get_octet_string(p7->d.sign->contents);
791c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* If detached data then the content is excluded */
792c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
793c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			M_ASN1_OCTET_STRING_free(os);
794c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			p7->d.sign->contents->d.data = NULL;
795c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
796c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
797c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
798c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs7_digest:
799c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		os=PKCS7_get_octet_string(p7->d.digest->contents);
800c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* If detached data then the content is excluded */
801c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
802c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
803c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			M_ASN1_OCTET_STRING_free(os);
804c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			p7->d.digest->contents->d.data = NULL;
805c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
806c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
807c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
808480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	default:
809480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
810480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	        goto err;
811c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
812c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
813c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (si_sk != NULL)
814c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
815c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++)
816c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
817c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			si=sk_PKCS7_SIGNER_INFO_value(si_sk,i);
818480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (si->pkey == NULL)
819480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				continue;
820c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
821480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			j = OBJ_obj2nid(si->digest_alg->algorithm);
822c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
823c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			btmp=bio;
824c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
825c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			btmp = PKCS7_find_digest(&mdc, btmp, j);
826c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
827c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (btmp == NULL)
828c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto err;
829c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
830c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			/* We now have the EVP_MD_CTX, lets do the
831c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * signing. */
8322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (!EVP_MD_CTX_copy_ex(&ctx_tmp,mdc))
8332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				goto err;
834c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
835c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			sk=si->auth_attr;
836c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
837c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			/* If there are attributes, we add the digest
838c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * attribute and only sign the attributes */
839480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (sk_X509_ATTRIBUTE_num(sk) > 0)
840c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
841480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				if (!do_pkcs7_signed_attrib(si, &ctx_tmp))
842c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					goto err;
843480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
844480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else
845480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
846480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				unsigned char *abuf = NULL;
847480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				unsigned int abuflen;
848480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				abuflen = EVP_PKEY_size(si->pkey);
849480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				abuf = OPENSSL_malloc(abuflen);
850480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				if (!abuf)
851c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					goto err;
852480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
853480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen,
854480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org							si->pkey))
855c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					{
856480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
857480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org							ERR_R_EVP_LIB);
858c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					goto err;
859c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					}
860480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				ASN1_STRING_set0(si->enc_digest, abuf, abuflen);
861c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
862c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
863c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
864c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else if (i == NID_pkcs7_digest)
865c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
866c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		unsigned char md_data[EVP_MAX_MD_SIZE];
867c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		unsigned int md_len;
868c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!PKCS7_find_digest(&mdc, bio,
869c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				OBJ_obj2nid(p7->d.digest->md->algorithm)))
870c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
8712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (!EVP_DigestFinal_ex(mdc,md_data,&md_len))
8722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			goto err;
873c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
874c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
875c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
876480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!PKCS7_is_detached(p7) && !(os->flags & ASN1_STRING_FLAG_NDEF))
877c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
878480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		char *cont;
879480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		long contlen;
880c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
881c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (btmp == NULL)
882c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
883c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
884c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
885c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
886480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		contlen = BIO_get_mem_data(btmp, &cont);
887c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Mark the BIO read only then we can use its copy of the data
888c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * instead of making an extra copy.
889c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 */
890c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
891c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_set_mem_eof_return(btmp, 0);
892480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ASN1_STRING_set0(os, (unsigned char *)cont, contlen);
893c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
894c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret=1;
895c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgerr:
896c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	EVP_MD_CTX_cleanup(&ctx_tmp);
897c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
898c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
899c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
900480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgint PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
901480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
902480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_MD_CTX mctx;
903480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY_CTX *pctx;
904480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	unsigned char *abuf = NULL;
905480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int alen;
906480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	size_t siglen;
907480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	const EVP_MD *md = NULL;
908480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
909480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	md = EVP_get_digestbyobj(si->digest_alg->algorithm);
910480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (md == NULL)
911480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
912480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
913480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_MD_CTX_init(&mctx);
914480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_DigestSignInit(&mctx, &pctx, md,NULL, si->pkey) <= 0)
915480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
916480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
917480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
918480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0)
919480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
920480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
921480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
922480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
923480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
924480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr,&abuf,
925480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
926480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(!abuf)
927480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
928480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_DigestSignUpdate(&mctx,abuf,alen) <= 0)
929480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
930480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	OPENSSL_free(abuf);
931063a4b93646788bd883fc0cb1b5eafc991ddacc4agl@chromium.org	abuf = NULL;
932480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0)
933480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
934480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	abuf = OPENSSL_malloc(siglen);
935480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(!abuf)
936480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
937480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0)
938480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
939480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
940480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
941480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0)
942480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
943480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
944480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto err;
945480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
946480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
947480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_MD_CTX_cleanup(&mctx);
948480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
949480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ASN1_STRING_set0(si->enc_digest, abuf, siglen);
950480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
951480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
952480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
953480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	err:
954480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (abuf)
955480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		OPENSSL_free(abuf);
956480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_MD_CTX_cleanup(&mctx);
957480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 0;
958480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
959480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
960480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
961c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgint PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
962c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	     PKCS7 *p7, PKCS7_SIGNER_INFO *si)
963c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
964c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	PKCS7_ISSUER_AND_SERIAL *ias;
965c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret=0,i;
966c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(X509) *cert;
967c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509 *x509;
968c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
969c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (PKCS7_type_is_signed(p7))
970c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
971c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		cert=p7->d.sign->cert;
972c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
973c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else if (PKCS7_type_is_signedAndEnveloped(p7))
974c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
975c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		cert=p7->d.signed_and_enveloped->cert;
976c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
977c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else
978c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
979c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE);
980c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
981c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
982c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* XXXXXXXXXXXXXXXXXXXXXXX */
983c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ias=si->issuer_and_serial;
984c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
985c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
986c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
987c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* were we able to find the cert in passed to us */
988c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (x509 == NULL)
989c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
990c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
991c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
992c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
993c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
994c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Lets verify */
995c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert))
996c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
997c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
998c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
999c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1000c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
1001c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	i=X509_verify_cert(ctx);
1002c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (i <= 0)
1003c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1004c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
1005c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		X509_STORE_CTX_cleanup(ctx);
1006c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
1007c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1008c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_STORE_CTX_cleanup(ctx);
1009c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1010c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return PKCS7_signatureVerify(bio, p7, si, x509);
1011c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	err:
1012c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return ret;
1013c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1014c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1015c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgint PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
1016c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org								X509 *x509)
1017c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1018c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ASN1_OCTET_STRING *os;
1019c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	EVP_MD_CTX mdc_tmp,*mdc;
1020c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret=0,i;
1021c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int md_type;
1022c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(X509_ATTRIBUTE) *sk;
1023c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO *btmp;
1024c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	EVP_PKEY *pkey;
1025c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1026c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	EVP_MD_CTX_init(&mdc_tmp);
1027c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1028c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!PKCS7_type_is_signed(p7) &&
1029c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				!PKCS7_type_is_signedAndEnveloped(p7)) {
1030c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
1031c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						PKCS7_R_WRONG_PKCS7_TYPE);
1032c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
1033c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1034c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1035c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	md_type=OBJ_obj2nid(si->digest_alg->algorithm);
1036c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1037c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	btmp=bio;
1038c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (;;)
1039c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1040c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ((btmp == NULL) ||
1041c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))
1042c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
1043c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
1044c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
1045c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
1046c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
1047c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_get_md_ctx(btmp,&mdc);
1048c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (mdc == NULL)
1049c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
1050c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
1051c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org							ERR_R_INTERNAL_ERROR);
1052c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
1053c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
1054c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (EVP_MD_CTX_type(mdc) == md_type)
1055c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
1056c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Workaround for some broken clients that put the signature
1057c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * OID instead of the digest OID in digest_alg->algorithm
1058c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 */
1059c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
1060c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
1061c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		btmp=BIO_next(btmp);
1062c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1063c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1064c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* mdc is the digest ctx that we want, unless there are attributes,
1065c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 * in which case the digest is the signed attributes */
10662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (!EVP_MD_CTX_copy_ex(&mdc_tmp,mdc))
10672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		goto err;
1068c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1069c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	sk=si->auth_attr;
1070c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
1071c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1072c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
1073480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org                unsigned int md_len;
1074480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		int alen;
1075c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ASN1_OCTET_STRING *message_digest;
1076c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
10772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (!EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len))
10782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			goto err;
1079c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		message_digest=PKCS7_digest_from_attributes(sk);
1080c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!message_digest)
1081c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
1082c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
1083c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
1084c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
1085c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
1086c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ((message_digest->length != (int)md_len) ||
1087c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			(memcmp(message_digest->data,md_dat,md_len)))
1088c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
1089c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if 0
1090c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org{
1091c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgint ii;
1092c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgfor (ii=0; ii<message_digest->length; ii++)
1093c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	printf("%02X",message_digest->data[ii]); printf(" sent\n");
1094c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgfor (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n");
1095c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org}
1096c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
1097c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
1098c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org							PKCS7_R_DIGEST_FAILURE);
1099c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret= -1;
1100c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
1101c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
1102c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
11032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (!EVP_VerifyInit_ex(&mdc_tmp,EVP_get_digestbynid(md_type), NULL))
11042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			goto err;
1105c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1106c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
1107c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
1108480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (alen <= 0)
1109480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
1110480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,ERR_R_ASN1_LIB);
1111480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ret = -1;
1112480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			goto err;
1113480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
11142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen))
11152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			goto err;
1116c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1117c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		OPENSSL_free(abuf);
1118c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1119c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1120c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	os=si->enc_digest;
1121c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	pkey = X509_get_pubkey(x509);
1122c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!pkey)
1123c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1124c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret = -1;
1125c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
1126c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1127c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1128c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);
1129c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	EVP_PKEY_free(pkey);
1130c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (i <= 0)
1131c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1132c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
1133c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						PKCS7_R_SIGNATURE_FAILURE);
1134c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret= -1;
1135c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
1136c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1137c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else
1138c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=1;
1139c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgerr:
1140c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	EVP_MD_CTX_cleanup(&mdc_tmp);
1141c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
1142c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1143c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1144c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgPKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
1145c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1146c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(PKCS7_RECIP_INFO) *rsk;
1147c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	PKCS7_RECIP_INFO *ri;
1148c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i;
1149c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1150c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	i=OBJ_obj2nid(p7->type);
1151c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (i != NID_pkcs7_signedAndEnveloped)
1152c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return NULL;
1153c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (p7->d.signed_and_enveloped == NULL)
1154c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return NULL;
1155c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	rsk=p7->d.signed_and_enveloped->recipientinfo;
1156c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (rsk == NULL)
1157c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return NULL;
1158c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ri=sk_PKCS7_RECIP_INFO_value(rsk,0);
1159c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL);
1160c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ri=sk_PKCS7_RECIP_INFO_value(rsk,idx);
1161c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ri->issuer_and_serial);
1162c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1163c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1164c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
1165c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1166c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(get_attribute(si->auth_attr,nid));
1167c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1168c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1169c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
1170c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1171c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(get_attribute(si->unauth_attr,nid));
1172c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1173c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1174c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
1175c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1176c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i;
1177c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_ATTRIBUTE *xa;
1178c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ASN1_OBJECT *o;
1179c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1180c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	o=OBJ_nid2obj(nid);
1181c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!o || !sk) return(NULL);
1182c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
1183c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1184c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		xa=sk_X509_ATTRIBUTE_value(sk,i);
1185c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (OBJ_cmp(xa->object,o) == 0)
1186c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
1187c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (!xa->single && sk_ASN1_TYPE_num(xa->value.set))
1188c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				return(sk_ASN1_TYPE_value(xa->value.set,0));
1189c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else
1190c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				return(NULL);
1191c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
1192c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1193c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(NULL);
1194c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1195c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1196c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
1197c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org{
1198c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ASN1_TYPE *astype;
1199c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL;
1200c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return astype->value.octet_string;
1201c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org}
1202c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1203c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgint PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
1204c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				STACK_OF(X509_ATTRIBUTE) *sk)
1205c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1206c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i;
1207c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1208c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (p7si->auth_attr != NULL)
1209c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free);
1210c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk);
1211c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (p7si->auth_attr == NULL)
1212c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 0;
1213c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
1214c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1215c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr,i,
1216c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
1217c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		    == NULL)
1218c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return(0);
1219c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1220c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(1);
1221c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1222c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1223c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgint PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
1224c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1225c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i;
1226c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1227c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (p7si->unauth_attr != NULL)
1228c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr,
1229c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					   X509_ATTRIBUTE_free);
1230c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk);
1231c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (p7si->unauth_attr == NULL)
1232c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 0;
1233c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
1234c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1235c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr,i,
1236c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org                        X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
1237c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		    == NULL)
1238c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return(0);
1239c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1240c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(1);
1241c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1242c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1243c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgint PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
1244c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	     void *value)
1245c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1246c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
1247c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1248c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1249c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgint PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
1250c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	     void *value)
1251c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1252c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
1253c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1254c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1255c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
1256c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 void *value)
1257c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1258c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_ATTRIBUTE *attr=NULL;
1259c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1260c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (*sk == NULL)
1261c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1262480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		*sk = sk_X509_ATTRIBUTE_new_null();
1263480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (*sk == NULL)
1264480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
1265c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgnew_attrib:
1266c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!(attr=X509_ATTRIBUTE_create(nid,atrtype,value)))
1267c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
1268c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!sk_X509_ATTRIBUTE_push(*sk,attr))
1269c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
1270c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			X509_ATTRIBUTE_free(attr);
1271c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
1272c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
1273c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1274c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else
1275c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1276c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		int i;
1277c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1278c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		for (i=0; i<sk_X509_ATTRIBUTE_num(*sk); i++)
1279c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
1280c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			attr=sk_X509_ATTRIBUTE_value(*sk,i);
1281c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (OBJ_obj2nid(attr->object) == nid)
1282c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
1283c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				X509_ATTRIBUTE_free(attr);
1284c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				attr=X509_ATTRIBUTE_create(nid,atrtype,value);
1285c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (attr == NULL)
1286c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					return 0;
1287c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (!sk_X509_ATTRIBUTE_set(*sk,i,attr))
1288c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					{
1289c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					X509_ATTRIBUTE_free(attr);
1290c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					return 0;
1291c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					}
1292c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto end;
1293c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
1294c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
1295c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto new_attrib;
1296c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1297c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgend:
1298c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(1);
1299c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1300c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1301